Add auto-detect dpi method
If Xft.dpi value is not available, auto-detect value based on monitor using randr provided sizes. Disable Xinerama and enable randr by default. Also update dpi everytime the monitor changes.
This commit is contained in:
parent
cc3a08c1db
commit
4dd628ccf4
12
config.mk
12
config.mk
@ -9,8 +9,12 @@ VERSION := $(shell git describe --tags)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# Xinerama, comment if you don't want it
|
# Xinerama, comment if you don't want it
|
||||||
XINERAMALIBS = -lXinerama
|
#XINERAMALIBS = -lXinerama
|
||||||
XINERAMAFLAGS = -DXINERAMA
|
#XINERAMAFLAGS = -DXINERAMA
|
||||||
|
|
||||||
|
# RANDR, comment if you don't want it
|
||||||
|
XRANDRLIBS = -lXrandr
|
||||||
|
XRANDRFLAGS = -DXRANDR
|
||||||
|
|
||||||
# uncomment to disable parsing of dunstrc
|
# uncomment to disable parsing of dunstrc
|
||||||
# or use "CFLAGS=-DSTATIC_CONFIG make" to build
|
# or use "CFLAGS=-DSTATIC_CONFIG make" to build
|
||||||
@ -22,7 +26,7 @@ ifeq (${PKG_CONFIG}, ${EMPTY})
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# flags
|
# flags
|
||||||
CPPFLAGS += -D_DEFAULT_SOURCE -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} ${INIFLAGS}
|
CPPFLAGS += -D_DEFAULT_SOURCE -DVERSION=\"${VERSION}\" ${XRANDRFLAGS} ${XINERAMAFLAGS} ${INIFLAGS}
|
||||||
CFLAGS += -g --std=gnu99 -pedantic -Wall -Wno-overlength-strings -Os ${STATIC} ${CPPFLAGS} ${EXTRACFLAGS}
|
CFLAGS += -g --std=gnu99 -pedantic -Wall -Wno-overlength-strings -Os ${STATIC} ${CPPFLAGS} ${EXTRACFLAGS}
|
||||||
|
|
||||||
pkg_config_packs := dbus-1 x11 xscrnsaver \
|
pkg_config_packs := dbus-1 x11 xscrnsaver \
|
||||||
@ -37,7 +41,7 @@ endif
|
|||||||
# includes and libs
|
# includes and libs
|
||||||
INCS := $(shell ${PKG_CONFIG} --cflags ${pkg_config_packs})
|
INCS := $(shell ${PKG_CONFIG} --cflags ${pkg_config_packs})
|
||||||
CFLAGS += ${INCS}
|
CFLAGS += ${INCS}
|
||||||
LDFLAGS += -lm -L${X11LIB} -lXss ${XINERAMALIBS} $(shell ${PKG_CONFIG} --libs ${pkg_config_packs})
|
LDFLAGS += -lm -L${X11LIB} -lXss ${XRANDRLIBS} ${XINERAMALIBS} $(shell ${PKG_CONFIG} --libs ${pkg_config_packs})
|
||||||
|
|
||||||
# only make this an fatal error when where not cleaning
|
# only make this an fatal error when where not cleaning
|
||||||
ifneq (clean, $(MAKECMDGOALS))
|
ifneq (clean, $(MAKECMDGOALS))
|
||||||
|
138
src/x.c
138
src/x.c
@ -7,7 +7,10 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xresource.h>
|
#include <X11/Xresource.h>
|
||||||
#ifdef XINERAMA
|
#ifdef XRANDR
|
||||||
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#elif XINERAMA
|
||||||
#include <X11/extensions/Xinerama.h>
|
#include <X11/extensions/Xinerama.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#endif
|
#endif
|
||||||
@ -137,28 +140,6 @@ static color_t x_get_separator_color(colored_layout *cl, colored_layout *cl_next
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_dpi_value()
|
|
||||||
{
|
|
||||||
double dpi = 0.0;
|
|
||||||
XrmInitialize();
|
|
||||||
char * xRMS = XResourceManagerString(xctx.dpy);
|
|
||||||
|
|
||||||
if ( xRMS != NULL ) {
|
|
||||||
XrmDatabase xDB = XrmGetStringDatabase(xRMS);
|
|
||||||
char * xrmType;
|
|
||||||
XrmValue xrmValue;
|
|
||||||
|
|
||||||
if ( XrmGetResource(xDB, "Xft.dpi", NULL, &xrmType, &xrmValue))
|
|
||||||
dpi = strtod(xrmValue.addr, NULL);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dpi > 0.0) {
|
|
||||||
PangoFontMap *font_map = pango_cairo_font_map_get_default();
|
|
||||||
pango_cairo_font_map_set_resolution((PangoCairoFontMap *) font_map, dpi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void x_cairo_setup(void)
|
static void x_cairo_setup(void)
|
||||||
{
|
{
|
||||||
cairo_ctx.surface = cairo_xlib_surface_create(xctx.dpy,
|
cairo_ctx.surface = cairo_xlib_surface_create(xctx.dpy,
|
||||||
@ -166,8 +147,6 @@ static void x_cairo_setup(void)
|
|||||||
|
|
||||||
cairo_ctx.context = cairo_create(cairo_ctx.surface);
|
cairo_ctx.context = cairo_create(cairo_ctx.surface);
|
||||||
|
|
||||||
set_dpi_value();
|
|
||||||
|
|
||||||
cairo_ctx.desc = pango_font_description_from_string(settings.font);
|
cairo_ctx.desc = pango_font_description_from_string(settings.font);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -949,12 +928,80 @@ static Window get_focused_window(void)
|
|||||||
return focused;
|
return focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XINERAMA
|
static double get_xft_dpi_value()
|
||||||
|
{
|
||||||
|
double dpi = 0.0;
|
||||||
|
XrmInitialize();
|
||||||
|
char * xRMS = XResourceManagerString(xctx.dpy);
|
||||||
|
|
||||||
|
if ( xRMS != NULL ) {
|
||||||
|
XrmDatabase xDB = XrmGetStringDatabase(xRMS);
|
||||||
|
char * xrmType;
|
||||||
|
XrmValue xrmValue;
|
||||||
|
|
||||||
|
if ( XrmGetResource(xDB, "Xft.dpi", NULL, &xrmType, &xrmValue))
|
||||||
|
dpi = strtod(xrmValue.addr, NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return dpi;
|
||||||
|
}
|
||||||
|
static void set_dpi_value(screen_info * scr, double dpi)
|
||||||
|
{
|
||||||
|
if (dpi > 0.0) {
|
||||||
|
PangoFontMap *font_map = pango_cairo_font_map_get_default();
|
||||||
|
pango_cairo_font_map_set_resolution((PangoCairoFontMap *) font_map, dpi);
|
||||||
|
}
|
||||||
|
#ifdef XRANDR
|
||||||
|
//fallback to auto-detect method
|
||||||
|
else {
|
||||||
|
dpi = (double)scr->dim.h * 25.4 / (double)scr->dim.mmh;
|
||||||
|
PangoFontMap *font_map = pango_cairo_font_map_get_default();
|
||||||
|
pango_cairo_font_map_set_resolution((PangoCairoFontMap *) font_map, dpi);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XRANDR
|
||||||
|
static int lookup_active_screen(XRRMonitorInfo *info, int n, int x, int y)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
if (INRECT(x, y, info[i].x, info[i].y,
|
||||||
|
info[i].width, info[i].height)) {
|
||||||
|
ret = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
#elif XINERAMA
|
||||||
|
static int lookup_active_screen(XineramaScreenInfo * info, int n, int x, int y)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
if (INRECT(x, y, info[i].x_org, info[i].y_org,
|
||||||
|
info[i].width, info[i].height)) {
|
||||||
|
ret = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XRANDR
|
||||||
/*
|
/*
|
||||||
* Select the screen on which the Window
|
* Select the screen on which the Window
|
||||||
* should be displayed.
|
* should be displayed.
|
||||||
*/
|
*/
|
||||||
|
static int select_screen(XRRMonitorInfo *info, int n)
|
||||||
|
#elif XINERAMA
|
||||||
static int select_screen(XineramaScreenInfo * info, int info_len)
|
static int select_screen(XineramaScreenInfo * info, int info_len)
|
||||||
|
#endif
|
||||||
|
#if defined(XRANDR) || defined(XINERAMA)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
x_follow_setup_error_handler();
|
x_follow_setup_error_handler();
|
||||||
@ -996,24 +1043,20 @@ static int select_screen(XineramaScreenInfo * info, int info_len)
|
|||||||
0, 0, &x, &y, &child_return);
|
0, 0, &x, &y, &child_return);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < info_len; i++) {
|
ret = lookup_active_screen(info, n, x, y);
|
||||||
if (INRECT(x, y, info[i].x_org,
|
|
||||||
info[i].y_org,
|
if (ret > 0)
|
||||||
info[i].width, info[i].height)) {
|
|
||||||
ret = i;
|
|
||||||
goto sc_cleanup;
|
goto sc_cleanup;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* something seems to be wrong. Fallback to default */
|
/* something seems to be wrong. Fallback to default */
|
||||||
ret = settings.monitor >=
|
ret = settings.monitor >=
|
||||||
0 ? settings.monitor : XDefaultScreen(xctx.dpy);
|
0 ? settings.monitor : XDefaultScreen(xctx.dpy);
|
||||||
goto sc_cleanup;
|
goto sc_cleanup;
|
||||||
}
|
}
|
||||||
sc_cleanup:
|
sc_cleanup:
|
||||||
x_follow_tear_down_error_handler();
|
x_follow_tear_down_error_handler();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1022,7 +1065,24 @@ sc_cleanup:
|
|||||||
*/
|
*/
|
||||||
static void x_screen_info(screen_info * scr)
|
static void x_screen_info(screen_info * scr)
|
||||||
{
|
{
|
||||||
#ifdef XINERAMA
|
#ifdef XRANDR
|
||||||
|
int n;
|
||||||
|
XRRMonitorInfo *m;
|
||||||
|
|
||||||
|
m = XRRGetMonitors(xctx.dpy, RootWindow(xctx.dpy, DefaultScreen(xctx.dpy)), true, &n);
|
||||||
|
int screen = select_screen(m, n);
|
||||||
|
if (screen >= n) {
|
||||||
|
/* invalid monitor, fallback to default */
|
||||||
|
screen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
scr->dim.x = m[screen].x;
|
||||||
|
scr->dim.y = m[screen].y;
|
||||||
|
scr->dim.w = m[screen].width;
|
||||||
|
scr->dim.h = m[screen].height;
|
||||||
|
scr->dim.mmh = m[screen].mheight;
|
||||||
|
XRRFreeMonitors(m);
|
||||||
|
#elif XINERAMA
|
||||||
int n;
|
int n;
|
||||||
XineramaScreenInfo *info;
|
XineramaScreenInfo *info;
|
||||||
if ((info = XineramaQueryScreens(xctx.dpy, &n))) {
|
if ((info = XineramaQueryScreens(xctx.dpy, &n))) {
|
||||||
@ -1051,6 +1111,12 @@ static void x_screen_info(screen_info * scr)
|
|||||||
scr->dim.w = DisplayWidth(xctx.dpy, screen);
|
scr->dim.w = DisplayWidth(xctx.dpy, screen);
|
||||||
scr->dim.h = DisplayHeight(xctx.dpy, screen);
|
scr->dim.h = DisplayHeight(xctx.dpy, screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Update dpi
|
||||||
|
double dpi = 0.0;
|
||||||
|
|
||||||
|
dpi = get_xft_dpi_value();
|
||||||
|
set_dpi_value(scr, dpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void x_free(void)
|
void x_free(void)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user