1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-11-16 18:15:17 +00:00

Update DPI when changed in resource manager (#1878)

* 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 <tin.svagelj@live.com>
This commit is contained in:
Tin Švagelj 2024-05-01 14:55:05 +00:00 committed by GitHub
parent 384bbed0df
commit 7b44b2a27b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 104 additions and 53 deletions

View File

@ -49,6 +49,7 @@
#include <X11/extensions/XInput2.h>
#undef COUNT
#endif /* BUILD_XINPUT */
#include <X11/Xresource.h>
#include <cstdint>
#include <iostream>
@ -81,9 +82,7 @@ extern int need_to_update;
int get_border_total();
extern conky::range_config_setting<int> 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<float>(DisplayWidth(display, screen)) * 25.4 /
static_cast<float>(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<x_event_handler::PROPERTY_NOTIFY>(
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<float>(xft_dpi) / PIXELS_PER_INCH;
if (screen_dpi > 0) {
return static_cast<float>(screen_dpi) / PIXELS_PER_INCH;
}
#endif /* BUILD_XFT */
return 1.0;
}

View File

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

View File

@ -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];

View File

@ -90,6 +90,7 @@ extern "C" {
#include <xcb/xcb.h>
#include <xcb/xcb_errors.h>
#endif
#include <X11/Xresource.h>
}
/* 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] =

View File

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