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:
Eizen 2017-02-24 15:21:52 -03:00 committed by Nikos Tsipinakis
parent cc3a08c1db
commit 4dd628ccf4
3 changed files with 158 additions and 87 deletions

View File

@ -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
View File

@ -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)

View File

@ -16,6 +16,7 @@ typedef struct _dimension_t {
int x; int x;
int y; int y;
unsigned int h; unsigned int h;
unsigned int mmh;
unsigned int w; unsigned int w;
int mask; int mask;
int negative_width; int negative_width;