From 0a6b105f4ae19d947adb41ea88f931aadce3bbbc Mon Sep 17 00:00:00 2001 From: Nikos Tsipinakis Date: Sun, 26 Feb 2017 16:51:36 +0200 Subject: [PATCH] Move screen related code into a new file Since we are adding Xrandr support to allow for automatic dpi detection, split screen handling code into a new file as part of the effort to simplify x.c --- src/dunst.c | 1 + src/x11/screen.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++ src/x11/screen.h | 24 +++++ src/x11/x.c | 257 +------------------------------------------- src/x11/x.h | 18 +--- 5 files changed, 302 insertions(+), 271 deletions(-) create mode 100644 src/x11/screen.c create mode 100644 src/x11/screen.h diff --git a/src/dunst.c b/src/dunst.c index 9f2c0b9..ce3a8ce 100644 --- a/src/dunst.c +++ b/src/dunst.c @@ -20,6 +20,7 @@ #include "option_parser.h" #include "settings.h" #include "x11/x.h" +#include "x11/screen.h" #define LENGTH(X) (sizeof X / sizeof X[0]) diff --git a/src/x11/screen.c b/src/x11/screen.c new file mode 100644 index 0000000..b1537eb --- /dev/null +++ b/src/x11/screen.c @@ -0,0 +1,273 @@ +#include "screen.h" + +#include +#include +#include +#include +#ifdef XRANDR +#include +#include +#elif XINERAMA +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "src/settings.h" +#include "x.h" + +bool dunst_follow_errored = false; + +static void x_follow_setup_error_handler(void); +static int x_follow_tear_down_error_handler(void); +static int FollowXErrorHandler(Display *display, XErrorEvent *e); +static Window get_focused_window(void); + +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 + * should be displayed. + */ +static int select_screen(XRRMonitorInfo *info, int n) +#elif XINERAMA +static int select_screen(XineramaScreenInfo * info, int info_len) +#endif +#if defined(XRANDR) || defined(XINERAMA) +{ + int ret = 0; + x_follow_setup_error_handler(); + if (settings.f_mode == FOLLOW_NONE) { + ret = settings.monitor >= + 0 ? settings.monitor : XDefaultScreen(xctx.dpy); + goto sc_cleanup; + + } else { + int x, y; + assert(settings.f_mode == FOLLOW_MOUSE + || settings.f_mode == FOLLOW_KEYBOARD); + Window root = + RootWindow(xctx.dpy, DefaultScreen(xctx.dpy)); + + if (settings.f_mode == FOLLOW_MOUSE) { + int dummy; + unsigned int dummy_ui; + Window dummy_win; + + XQueryPointer(xctx.dpy, root, &dummy_win, + &dummy_win, &x, &y, &dummy, + &dummy, &dummy_ui); + } + + if (settings.f_mode == FOLLOW_KEYBOARD) { + + Window focused = get_focused_window(); + + if (focused == 0) { + /* something went wrong. Fallback to default */ + ret = settings.monitor >= + 0 ? settings.monitor : XDefaultScreen(xctx.dpy); + goto sc_cleanup; + } + + Window child_return; + XTranslateCoordinates(xctx.dpy, focused, root, + 0, 0, &x, &y, &child_return); + } + + ret = lookup_active_screen(info, n, x, y); + + if (ret > 0) + goto sc_cleanup; + + /* something seems to be wrong. Fallback to default */ + ret = settings.monitor >= + 0 ? settings.monitor : XDefaultScreen(xctx.dpy); + goto sc_cleanup; + } + sc_cleanup: + x_follow_tear_down_error_handler(); + return ret; + } +#endif + +/* + * Update the information about the monitor + * geometry. + */ +void x_screen_info(screen_info * scr) +{ +#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; + XineramaScreenInfo *info; + if ((info = XineramaQueryScreens(xctx.dpy, &n))) { + int screen = select_screen(info, n); + if (screen >= n) { + /* invalid monitor, fallback to default */ + screen = 0; + } + scr->dim.x = info[screen].x_org; + scr->dim.y = info[screen].y_org; + scr->dim.h = info[screen].height; + scr->dim.w = info[screen].width; + XFree(info); + } else +#endif + { + scr->dim.x = 0; + scr->dim.y = 0; + + int screen; + if (settings.monitor >= 0) + screen = settings.monitor; + else + screen = DefaultScreen(xctx.dpy); + + scr->dim.w = DisplayWidth(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); +} + +/* + * Return the window that currently has + * the keyboard focus. + */ +static Window get_focused_window(void) +{ + Window focused = 0; + Atom type; + int format; + unsigned long nitems, bytes_after; + unsigned char *prop_return = NULL; + Window root = RootWindow(xctx.dpy, DefaultScreen(xctx.dpy)); + Atom netactivewindow = + XInternAtom(xctx.dpy, "_NET_ACTIVE_WINDOW", false); + + XGetWindowProperty(xctx.dpy, root, netactivewindow, 0L, + sizeof(Window), false, XA_WINDOW, + &type, &format, &nitems, &bytes_after, &prop_return); + if (prop_return) { + focused = *(Window *) prop_return; + XFree(prop_return); + } + + return focused; +} + +static void x_follow_setup_error_handler(void) +{ + dunst_follow_errored = false; + + XFlush(xctx.dpy); + XSetErrorHandler(FollowXErrorHandler); +} + +static int x_follow_tear_down_error_handler(void) +{ + XFlush(xctx.dpy); + XSync(xctx.dpy, false); + XSetErrorHandler(NULL); + return dunst_follow_errored; +} + +static int FollowXErrorHandler(Display * display, XErrorEvent * e) +{ + dunst_follow_errored = true; + char err_buf[BUFSIZ]; + XGetErrorText(display, e->error_code, err_buf, BUFSIZ); + fputs(err_buf, stderr); + fputs("\n", stderr); + + return 0; +} diff --git a/src/x11/screen.h b/src/x11/screen.h new file mode 100644 index 0000000..b8670e7 --- /dev/null +++ b/src/x11/screen.h @@ -0,0 +1,24 @@ +/* copyright 2013 Sascha Kruse and contributors (see LICENSE for licensing information) */ +#ifndef DUNST_SCREEN_H +#define DUNST_SCREEN_H + +#define INRECT(x,y,rx,ry,rw,rh) ((x) >= (rx) && (x) < (rx)+(rw) && (y) >= (ry) && (y) < (ry)+(rh)) + +typedef struct _dimension_t { + int x; + int y; + unsigned int h; + unsigned int mmh; + unsigned int w; + int mask; + int negative_width; +} dimension_t; + +typedef struct _screen_info { + int scr; + dimension_t dim; +} screen_info; + +void x_screen_info(screen_info * scr); + +#endif diff --git a/src/x11/x.c b/src/x11/x.c index 9a2a5c8..ff36ecb 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -7,13 +7,6 @@ #include #include #include -#ifdef XRANDR -#include -#include -#elif XINERAMA -#include -#include -#endif #include #include #include @@ -31,12 +24,13 @@ #include "src/settings.h" #include "src/utils.h" +#include "screen.h" + #define WIDTH 400 #define HEIGHT 400 xctx_t xctx; bool dunst_grab_errored = false; -bool dunst_follow_errored = false; typedef struct _cairo_ctx { cairo_status_t status; @@ -59,14 +53,11 @@ typedef struct _colored_layout { cairo_ctx_t cairo_ctx; /* FIXME refactor setup teardown handlers into one setup and one teardown */ -static void x_follow_setup_error_handler(void); -static int x_follow_tear_down_error_handler(void); static void x_shortcut_setup_error_handler(void); static int x_shortcut_tear_down_error_handler(void); static void x_win_move(int width, int height); static void setopacity(Window win, unsigned long opacity); static void x_handle_click(XEvent ev); -static void x_screen_info(screen_info * scr); static void x_win_setup(void); static color_t x_color_hex_to_double(int hexValue) @@ -902,223 +893,6 @@ static void x_handle_click(XEvent ev) } } -/* - * Return the window that currently has - * the keyboard focus. - */ -static Window get_focused_window(void) -{ - Window focused = 0; - Atom type; - int format; - unsigned long nitems, bytes_after; - unsigned char *prop_return = NULL; - Window root = RootWindow(xctx.dpy, DefaultScreen(xctx.dpy)); - Atom netactivewindow = - XInternAtom(xctx.dpy, "_NET_ACTIVE_WINDOW", false); - - XGetWindowProperty(xctx.dpy, root, netactivewindow, 0L, - sizeof(Window), false, XA_WINDOW, - &type, &format, &nitems, &bytes_after, &prop_return); - if (prop_return) { - focused = *(Window *) prop_return; - XFree(prop_return); - } - - return focused; -} - -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 - * should be displayed. - */ -static int select_screen(XRRMonitorInfo *info, int n) -#elif XINERAMA -static int select_screen(XineramaScreenInfo * info, int info_len) -#endif -#if defined(XRANDR) || defined(XINERAMA) -{ - int ret = 0; - x_follow_setup_error_handler(); - if (settings.f_mode == FOLLOW_NONE) { - ret = settings.monitor >= - 0 ? settings.monitor : XDefaultScreen(xctx.dpy); - goto sc_cleanup; - - } else { - int x, y; - assert(settings.f_mode == FOLLOW_MOUSE - || settings.f_mode == FOLLOW_KEYBOARD); - Window root = - RootWindow(xctx.dpy, DefaultScreen(xctx.dpy)); - - if (settings.f_mode == FOLLOW_MOUSE) { - int dummy; - unsigned int dummy_ui; - Window dummy_win; - - XQueryPointer(xctx.dpy, root, &dummy_win, - &dummy_win, &x, &y, &dummy, - &dummy, &dummy_ui); - } - - if (settings.f_mode == FOLLOW_KEYBOARD) { - - Window focused = get_focused_window(); - - if (focused == 0) { - /* something went wrong. Fallback to default */ - ret = settings.monitor >= - 0 ? settings.monitor : XDefaultScreen(xctx.dpy); - goto sc_cleanup; - } - - Window child_return; - XTranslateCoordinates(xctx.dpy, focused, root, - 0, 0, &x, &y, &child_return); - } - - ret = lookup_active_screen(info, n, x, y); - - if (ret > 0) - goto sc_cleanup; - - /* something seems to be wrong. Fallback to default */ - ret = settings.monitor >= - 0 ? settings.monitor : XDefaultScreen(xctx.dpy); - goto sc_cleanup; - } - sc_cleanup: - x_follow_tear_down_error_handler(); - return ret; - } -#endif - -/* - * Update the information about the monitor - * geometry. - */ -static void x_screen_info(screen_info * scr) -{ -#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; - XineramaScreenInfo *info; - if ((info = XineramaQueryScreens(xctx.dpy, &n))) { - int screen = select_screen(info, n); - if (screen >= n) { - /* invalid monitor, fallback to default */ - screen = 0; - } - scr->dim.x = info[screen].x_org; - scr->dim.y = info[screen].y_org; - scr->dim.h = info[screen].height; - scr->dim.w = info[screen].width; - XFree(info); - } else -#endif - { - scr->dim.x = 0; - scr->dim.y = 0; - - int screen; - if (settings.monitor >= 0) - screen = settings.monitor; - else - screen = DefaultScreen(xctx.dpy); - - scr->dim.w = DisplayWidth(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) { cairo_surface_destroy(cairo_ctx.surface); @@ -1365,17 +1139,6 @@ static int GrabXErrorHandler(Display * display, XErrorEvent * e) return 0; } -static int FollowXErrorHandler(Display * display, XErrorEvent * e) -{ - dunst_follow_errored = true; - char err_buf[BUFSIZ]; - XGetErrorText(display, e->error_code, err_buf, BUFSIZ); - fputs(err_buf, stderr); - fputs("\n", stderr); - - return 0; -} - /* * Setup the Error handler. */ @@ -1387,14 +1150,6 @@ static void x_shortcut_setup_error_handler(void) XSetErrorHandler(GrabXErrorHandler); } -static void x_follow_setup_error_handler(void) -{ - dunst_follow_errored = false; - - XFlush(xctx.dpy); - XSetErrorHandler(FollowXErrorHandler); -} - /* * Tear down the Error handler. */ @@ -1406,14 +1161,6 @@ static int x_shortcut_tear_down_error_handler(void) return dunst_grab_errored; } -static int x_follow_tear_down_error_handler(void) -{ - XFlush(xctx.dpy); - XSync(xctx.dpy, false); - XSetErrorHandler(NULL); - return dunst_follow_errored; -} - /* * Grab the given keyboard shortcut. */ diff --git a/src/x11/x.h b/src/x11/x.h index 1459789..bb9200d 100644 --- a/src/x11/x.h +++ b/src/x11/x.h @@ -7,25 +7,11 @@ #include #include +#include "screen.h" + #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define FONT_HEIGHT_BORDER 2 #define DEFFONT "Monospace-11" -#define INRECT(x,y,rx,ry,rw,rh) ((x) >= (rx) && (x) < (rx)+(rw) && (y) >= (ry) && (y) < (ry)+(rh)) - -typedef struct _dimension_t { - int x; - int y; - unsigned int h; - unsigned int mmh; - unsigned int w; - int mask; - int negative_width; -} dimension_t; - -typedef struct _screen_info { - int scr; - dimension_t dim; -} screen_info; typedef struct _keyboard_shortcut { const char *str;