From 7b44b2a27bd0649c7c00a4f5f4ec521aa554777b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tin=20=C5=A0vagelj?= Date: Wed, 1 May 2024 14:55:05 +0000 Subject: [PATCH] Update DPI when changed in resource manager (#1878) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update xft_dpi on property change * Added fallback calculation when Xft is disabled. * Removed display_width/height and replaced it with workarea for consistency. * Make DPI work on X11 when Xft is disabled * Make find_subwindow more specific, rename it Signed-off-by: Tin Å vagelj --- src/display-x11.cc | 75 +++++++++++++++++++++++++++++++-------------- src/gui.cc | 2 -- src/gui.h | 2 -- src/x11.cc | 76 ++++++++++++++++++++++++++++++---------------- src/x11.h | 2 ++ 5 files changed, 104 insertions(+), 53 deletions(-) diff --git a/src/display-x11.cc b/src/display-x11.cc index 47105bf8..5a0d3806 100644 --- a/src/display-x11.cc +++ b/src/display-x11.cc @@ -49,6 +49,7 @@ #include #undef COUNT #endif /* BUILD_XINPUT */ +#include #include #include @@ -81,9 +82,7 @@ extern int need_to_update; int get_border_total(); extern conky::range_config_setting maximum_width; extern Colour current_color; -#ifdef BUILD_XFT -static int xft_dpi = -1; -#endif /* BUILD_XFT */ +static float screen_dpi = -1; /* for x_fonts */ struct x_font_list { @@ -147,16 +146,36 @@ struct _x11_stuff_s { #endif } x11_stuff; +void update_dpi() { + // Add XRandR support if used + // See dunst PR: https://github.com/dunst-project/dunst/pull/608 + +#ifdef BUILD_XFT + if (screen_dpi > 0) return; + if (use_xft.get(*state)) { + XrmDatabase db = XrmGetDatabase(display); + if (db != nullptr) { + char *xrmType; + XrmValue xrmValue; + if (XrmGetResource(db, "Xft.dpi", "Xft.dpi", &xrmType, &xrmValue)) { + screen_dpi = strtof(xrmValue.addr, NULL); + } + } else { + auto dpi = XGetDefault(display, "Xft", "dpi"); + if (dpi) { screen_dpi = strtof(dpi, nullptr); } + } + } +#endif /* BUILD_XFT */ + if (screen_dpi > 0) return; + screen_dpi = static_cast(DisplayWidth(display, screen)) * 25.4 / + static_cast(DisplayWidthMM(display, screen)); +} + static void X11_create_window() { if (!window.window) { return; } setup_fonts(); load_fonts(utf8_mode.get(*state)); -#ifdef BUILD_XFT - if (use_xft.get(*state)) { - auto dpi = XGetDefault(display, "Xft", "dpi"); - if (dpi) { xft_dpi = strtol(dpi, nullptr, 10); } - } -#endif /* BUILD_XFT */ + update_dpi(); update_text_area(); /* to position text/window on screen */ #ifdef OWN_WINDOW @@ -713,19 +732,31 @@ bool handle_event( get_x11_desktop_info(ev.xproperty.display, ev.xproperty.atom); } -#ifdef USE_ARGB - if (have_argb_visual) return true; -#endif + if (ev.xproperty.atom == 0) return false; - if (ev.xproperty.atom == ATOM(_XROOTPMAP_ID) || - ev.xproperty.atom == ATOM(_XROOTMAP_ID)) { - if (forced_redraw.get(*state)) { - draw_stuff(); - next_update_time = get_time(); - need_to_update = 1; + if (ev.xproperty.atom == XA_RESOURCE_MANAGER) { + update_x11_resource_db(); + update_x11_workarea(); + screen_dpi = -1; + update_dpi(); + return true; + } + + if (!have_argb_visual) { + Atom _XROOTPMAP_ID = XInternAtom(display, "_XROOTPMAP_ID", True); + Atom _XROOTMAP_ID = XInternAtom(display, "_XROOTMAP_ID", True); + if (ev.xproperty.atom == _XROOTPMAP_ID || + ev.xproperty.atom == _XROOTMAP_ID) { + if (forced_redraw.get(*state)) { + draw_stuff(); + next_update_time = get_time(); + need_to_update = 1; + } + return true; } } - return true; + + return false; } template <> @@ -947,11 +978,9 @@ void display_output_x11::move_win(int x, int y) { const float PIXELS_PER_INCH = 96.0; float display_output_x11::get_dpi_scale() { -#ifdef BUILD_XFT - if (use_xft.get(*state) && xft_dpi > 0) { - return static_cast(xft_dpi) / PIXELS_PER_INCH; + if (screen_dpi > 0) { + return static_cast(screen_dpi) / PIXELS_PER_INCH; } -#endif /* BUILD_XFT */ return 1.0; } diff --git a/src/gui.cc b/src/gui.cc index 5e6d242e..f7c1d8a0 100644 --- a/src/gui.cc +++ b/src/gui.cc @@ -45,8 +45,6 @@ #endif /* basic display attributes */ -int display_width; -int display_height; int screen; /* workarea where window / text is aligned (from _NET_WORKAREA on X11) */ diff --git a/src/gui.h b/src/gui.h index 8b68fe42..65499763 100644 --- a/src/gui.h +++ b/src/gui.h @@ -168,8 +168,6 @@ inline bool TEST_HINT(uint16_t mask, window_hints hint) { #ifdef BUILD_X11 extern Display *display; #endif /* BUILD_X11 */ -extern int display_width; -extern int display_height; extern int screen; extern int workarea[4]; diff --git a/src/x11.cc b/src/x11.cc index 778d7e69..ebf2d92d 100644 --- a/src/x11.cc +++ b/src/x11.cc @@ -90,6 +90,7 @@ extern "C" { #include #include #endif +#include } /* some basic X11 stuff */ @@ -106,9 +107,8 @@ struct conky_x11_window window; bool have_argb_visual = false; /* local prototypes */ -static void update_workarea(); static Window find_desktop_window(Window *p_root, Window *p_desktop); -static Window find_subwindow(Window win, int w, int h); +static Window find_desktop_window_impl(Window win, int w, int h); /* WARNING, this type not in Xlib spec */ static int x11_error_handler(Display *d, XErrorEvent *err) { @@ -260,13 +260,15 @@ void init_x11() { info.x11.desktop.name.clear(); screen = DefaultScreen(display); - display_width = DisplayWidth(display, screen); - display_height = DisplayHeight(display, screen); + + XSetErrorHandler(&x11_error_handler); + XSetIOErrorHandler(&x11_ioerror_handler); + + update_x11_resource_db(true); + update_x11_workarea(); get_x11_desktop_info(display, 0); - update_workarea(); - #ifdef HAVE_XCB_ERRORS auto connection = xcb_connect(NULL, NULL); if (!xcb_connection_has_error(connection)) { @@ -275,11 +277,6 @@ void init_x11() { } } #endif /* HAVE_XCB_ERRORS */ - - /* WARNING, this type not in Xlib spec */ - XSetErrorHandler(&x11_error_handler); - XSetIOErrorHandler(&x11_ioerror_handler); - DBGP("leave init_x11()"); } @@ -291,12 +288,39 @@ void deinit_x11() { } } -static void update_workarea() { +// Source: dunst +// https://github.com/bebehei/dunst/blob/1bc3237a359f37905426012c0cca90d71c4b3b18/src/x11/x.c#L463 +void update_x11_resource_db(bool first_run) { + XrmDatabase db; + XTextProperty prop; + Window root; + + XFlush(display); + + root = RootWindow(display, screen); + + XLockDisplay(display); + if (XGetTextProperty(display, root, &prop, XA_RESOURCE_MANAGER)) { + if (!first_run) { + db = XrmGetDatabase(display); + XrmDestroyDatabase(db); + } + + db = XrmGetStringDatabase((const char *)prop.value); + XrmSetDatabase(display, db); + } + XUnlockDisplay(display); + + XFlush(display); + XSync(display, false); +} + +void update_x11_workarea() { /* default work area is display */ workarea[0] = 0; workarea[1] = 0; - workarea[2] = display_width; - workarea[3] = display_height; + workarea[2] = DisplayWidth(display, screen); + workarea[3] = DisplayHeight(display, screen); #ifdef BUILD_XINERAMA /* if xinerama is being used, adjust workarea to the head's area */ @@ -344,9 +368,12 @@ static Window find_desktop_window(Window root) { Window desktop = root; /* get subwindows from root */ - desktop = find_subwindow(root, -1, -1); - update_workarea(); - desktop = find_subwindow(desktop, workarea[2], workarea[3]); + int display_width = DisplayWidth(display, screen); + int display_height = DisplayHeight(display, screen); + desktop = find_desktop_window_impl(root, display_width, display_height); + update_x11_workarea(); + desktop = find_desktop_window_impl(desktop, workarea[2] - workarea[0], + workarea[3] - workarea[1]); if (desktop != root) { NORM_ERR("desktop window (0x%lx) is subwindow of root window (0x%lx)", @@ -514,13 +541,11 @@ void x11_init_window(lua::state &l, bool own) { 0, 0}; flags |= CWBackPixel; -#ifdef BUILD_ARGB if (have_argb_visual) { attrs.colormap = window.colourmap; flags &= ~CWBackPixel; flags |= CWBorderPixel | CWColormap; } -#endif /* BUILD_ARGB */ /* Parent is desktop window (which might be a child of root) */ window.window = @@ -557,13 +582,11 @@ void x11_init_window(lua::state &l, bool own) { Atom xa; flags |= CWBackPixel; -#ifdef BUILD_ARGB if (have_argb_visual) { attrs.colormap = window.colourmap; flags &= ~CWBackPixel; flags |= CWBorderPixel | CWColormap; } -#endif /* BUILD_ARGB */ if (own_window_type.get(l) == window_type::DOCK) { window.x = window.y = 0; @@ -868,7 +891,7 @@ void x11_init_window(lua::state &l, bool own) { DBGP("leave x11_init_window()"); } -static Window find_subwindow(Window win, int w, int h) { +static Window find_desktop_window_impl(Window win, int w, int h) { unsigned int i, j; Window troot, parent, *children; unsigned int n; @@ -880,13 +903,11 @@ static Window find_subwindow(Window win, int w, int h) { for (j = 0; j < n; j++) { XWindowAttributes attrs; - if (XGetWindowAttributes(display, children[j], &attrs) != 0) { /* Window must be mapped and same size as display or * work space */ - if (attrs.map_state != 0 && - ((attrs.width == display_width && attrs.height == display_height) || - (attrs.width == w && attrs.height == h))) { + if (attrs.map_state == IsViewable && attrs.override_redirect == false && + ((attrs.width == w && attrs.height == h))) { win = children[j]; break; } @@ -1116,6 +1137,9 @@ void set_struts(alignment align) { if (strut != None) { long sizes[STRUT_COUNT] = {0}; + int display_width = workarea[2] - workarea[0]; + int display_height = workarea[3] - workarea[1]; + switch (horizontal_alignment(align)) { case axis_align::START: sizes[*x11_strut::LEFT] = diff --git a/src/x11.h b/src/x11.h index 7f983ae5..160fd21f 100644 --- a/src/x11.h +++ b/src/x11.h @@ -98,6 +98,8 @@ struct conky_x11_window { extern struct conky_x11_window window; +void update_x11_resource_db(bool first_run = false); +void update_x11_workarea(); void init_x11(); void destroy_window(void); void create_gc(void);