Skip to content

Commit 31ba7ef

Browse files
committed
x11: Refactor dpi hooks, removing GTK dependency and fixing XSettings watcher
- Removed GTK signal handler in x11settings. XSettings events are now properly dispatched to X11_XsettingsNotify. Previously events were not being passed to xsettings-client as no SDL xsettings_window was created. Now all events are filtered through xsettings_client_process_event allowing it to process the external window events that are selected. Global content scale is updated for changes to any recognized dpi settings. - X11_GetGlobalContent now reads the current RESOURCE_MANAGER prop off of the root window to ensure it sees the current value. XResourceManagerString is now only used if getting the current prop fails as it caches the current resource manager value per-display connection. - Clean up some warnings in SDL_gtk.
1 parent b139821 commit 31ba7ef

File tree

10 files changed

+85
-113
lines changed

10 files changed

+85
-113
lines changed

src/core/unix/SDL_gtk.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
ctx.sub.fn = (void *)SDL_LoadFunction(lib, #sym)
2828

2929
#define SDL_GTK_SYM2(ctx, lib, sub, fn, sym) \
30-
if (!(ctx.sub.fn = (void *)SDL_LoadFunction(lib, #sym))) { \
30+
SDL_GTK_SYM2_OPTIONAL(ctx, lib, sub, fn, sym); \
31+
if (!ctx.sub.fn) { \
3132
return SDL_SetError("Could not load GTK functions"); \
3233
}
3334

src/core/unix/SDL_gtk.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ typedef struct SDL_GtkContext
118118
extern bool SDL_Gtk_Init(void);
119119
extern void SDL_Gtk_Quit(void);
120120
extern SDL_GtkContext *SDL_Gtk_EnterContext(void);
121-
extern void SDL_Gtk_ExitContext(SDL_GtkContext *gtk);
121+
extern void SDL_Gtk_ExitContext(SDL_GtkContext *ctx);
122122
extern void SDL_UpdateGtk(void);
123123

124124
#endif // SDL_gtk_h_

src/events/SDL_events.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,6 @@ void SDL_PumpEventMaintenance(void)
14451445
}
14461446
#endif
14471447

1448-
// SDL_UpdateTrays will also pump GTK events if needed
14491448
SDL_UpdateTrays();
14501449

14511450
SDL_SendPendingSignalEvents(); // in case we had a signal handler fire, etc.

src/tray/unix/SDL_tray.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,9 @@ static void DestroySDLMenu(SDL_TrayMenu *menu)
233233

234234
void SDL_UpdateTrays(void)
235235
{
236-
SDL_UpdateGtk();
236+
if (SDL_HasActiveTrays()) {
237+
SDL_UpdateGtk();
238+
}
237239
}
238240

239241
SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)

src/video/x11/SDL_x11events.c

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -850,16 +850,6 @@ static void X11_HandleClipboardEvent(SDL_VideoDevice *_this, const XEvent *xeven
850850
}
851851
}
852852

853-
static void X11_HandleSettingsEvent(SDL_VideoDevice *_this, const XEvent *xevent)
854-
{
855-
SDL_VideoData *videodata = _this->internal;
856-
857-
SDL_assert(videodata->xsettings_window != None);
858-
SDL_assert(xevent->xany.window == videodata->xsettings_window);
859-
860-
X11_HandleXsettings(_this, xevent);
861-
}
862-
863853
static Bool isMapNotify(Display *display, XEvent *ev, XPointer arg)
864854
{
865855
XUnmapEvent *unmap;
@@ -1228,11 +1218,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
12281218
return;
12291219
}
12301220

1231-
if ((videodata->xsettings_window != None) &&
1232-
(videodata->xsettings_window == xevent->xany.window)) {
1233-
X11_HandleSettingsEvent(_this, xevent);
1234-
return;
1235-
}
1221+
// xsettings internally filters events for the windows it watches
1222+
X11_HandleXsettingsEvent(_this, xevent);
12361223

12371224
data = X11_FindWindow(_this, xevent->xany.window);
12381225

src/video/x11/SDL_x11modes.c

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -50,74 +50,93 @@
5050

5151
float X11_GetGlobalContentScale(SDL_VideoDevice *_this)
5252
{
53-
static double scale_factor = 0.0;
54-
55-
if (scale_factor <= 0.0) {
53+
double scale_factor = 0.0;
54+
55+
// First use the forced scaling factor specified by the app/user
56+
const char *hint = SDL_GetHint(SDL_HINT_VIDEO_X11_SCALING_FACTOR);
57+
if (hint && *hint) {
58+
double value = SDL_atof(hint);
59+
if (value >= 1.0f && value <= 10.0f) {
60+
scale_factor = value;
61+
}
62+
}
5663

57-
// First use the forced scaling factor specified by the app/user
58-
const char *hint = SDL_GetHint(SDL_HINT_VIDEO_X11_SCALING_FACTOR);
59-
if (hint && *hint) {
60-
double value = SDL_atof(hint);
61-
if (value >= 1.0f && value <= 10.0f) {
62-
scale_factor = value;
63-
}
64+
// If that failed, try "Xft.dpi" from the XResourcesDatabase...
65+
// We attempt to read this directly to get the live value, XResourceManagerString
66+
// is cached per display connection.
67+
if (scale_factor <= 0.0)
68+
{
69+
SDL_VideoData *data = _this->internal;
70+
Display *display = data->display;
71+
int status, real_format;
72+
Atom real_type;
73+
unsigned long items_read, items_left;
74+
char *resource_manager;
75+
bool owns_resource_manager = false;
76+
77+
X11_XrmInitialize();
78+
status = X11_XGetWindowProperty(display, RootWindow(display, DefaultScreen(display)),
79+
data->atoms.RESOURCE_MANAGER, 0L, 8192L, False, XA_STRING,
80+
&real_type, &real_format, &items_read, &items_left,
81+
(unsigned char **)&resource_manager);
82+
83+
if (status == Success && resource_manager) {
84+
owns_resource_manager = true;
85+
} else {
86+
// Fall back to XResourceManagerString. This will not be updated if the
87+
// dpi value is later changed but should allow getting the initial value.
88+
resource_manager = X11_XResourceManagerString(display);
6489
}
6590

66-
// If that failed, try "Xft.dpi" from the XResourcesDatabase...
67-
if (scale_factor <= 0.0)
68-
{
69-
SDL_VideoData *data = _this->internal;
70-
Display *display = data->display;
71-
char *resource_manager;
91+
if (resource_manager) {
7292
XrmDatabase db;
7393
XrmValue value;
7494
char *type;
7595

76-
X11_XrmInitialize();
96+
db = X11_XrmGetStringDatabase(resource_manager);
7797

78-
resource_manager = X11_XResourceManagerString(display);
79-
if (resource_manager) {
80-
db = X11_XrmGetStringDatabase(resource_manager);
81-
82-
// Get the value of Xft.dpi from the Database
83-
if (X11_XrmGetResource(db, "Xft.dpi", "String", &type, &value)) {
84-
if (value.addr && type && SDL_strcmp(type, "String") == 0) {
85-
int dpi = SDL_atoi(value.addr);
86-
scale_factor = dpi / 96.0;
87-
}
98+
// Get the value of Xft.dpi from the Database
99+
if (X11_XrmGetResource(db, "Xft.dpi", "String", &type, &value)) {
100+
if (value.addr && type && SDL_strcmp(type, "String") == 0) {
101+
int dpi = SDL_atoi(value.addr);
102+
scale_factor = dpi / 96.0;
88103
}
89-
X11_XrmDestroyDatabase(db);
90104
}
91-
}
105+
X11_XrmDestroyDatabase(db);
92106

93-
// If that failed, try the XSETTINGS keys...
94-
if (scale_factor <= 0.0) {
95-
scale_factor = X11_GetXsettingsIntKey(_this, "Gdk/WindowScalingFactor", -1);
96-
97-
// The Xft/DPI key is stored in increments of 1024th
98-
if (scale_factor <= 0.0) {
99-
int dpi = X11_GetXsettingsIntKey(_this, "Xft/DPI", -1);
100-
if (dpi > 0) {
101-
scale_factor = (double) dpi / 1024.0;
102-
scale_factor /= 96.0;
103-
}
107+
if (owns_resource_manager) {
108+
X11_XFree(resource_manager);
104109
}
105110
}
111+
}
106112

107-
// If that failed, try the GDK_SCALE envvar...
113+
// If that failed, try the XSETTINGS keys...
114+
if (scale_factor <= 0.0) {
115+
scale_factor = X11_GetXsettingsIntKey(_this, "Gdk/WindowScalingFactor", -1);
116+
117+
// The Xft/DPI key is stored in increments of 1024th
108118
if (scale_factor <= 0.0) {
109-
const char *scale_str = SDL_getenv("GDK_SCALE");
110-
if (scale_str) {
111-
scale_factor = SDL_atoi(scale_str);
119+
int dpi = X11_GetXsettingsIntKey(_this, "Xft/DPI", -1);
120+
if (dpi > 0) {
121+
scale_factor = (double) dpi / 1024.0;
122+
scale_factor /= 96.0;
112123
}
113124
}
125+
}
114126

115-
// Nothing or a bad value, just fall back to 1.0
116-
if (scale_factor <= 0.0) {
117-
scale_factor = 1.0;
127+
// If that failed, try the GDK_SCALE envvar...
128+
if (scale_factor <= 0.0) {
129+
const char *scale_str = SDL_getenv("GDK_SCALE");
130+
if (scale_str) {
131+
scale_factor = SDL_atoi(scale_str);
118132
}
119133
}
120134

135+
// Nothing or a bad value, just fall back to 1.0
136+
if (scale_factor <= 0.0) {
137+
scale_factor = 1.0;
138+
}
139+
121140
return (float)scale_factor;
122141
}
123142

src/video/x11/SDL_x11settings.c

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@
2626
#include "SDL_x11video.h"
2727
#include "SDL_x11settings.h"
2828

29-
#include "core/unix/SDL_gtk.h"
30-
3129
#define SDL_XSETTINGS_GDK_WINDOW_SCALING_FACTOR "Gdk/WindowScalingFactor"
30+
#define SDL_XSETTINGS_GDK_UNSCALED_DPI "Gdk/UnscaledDPI"
3231
#define SDL_XSETTINGS_XFT_DPI "Xft/DPI"
3332

3433
static void UpdateContentScale(SDL_VideoDevice *_this)
@@ -44,39 +43,19 @@ static void UpdateContentScale(SDL_VideoDevice *_this)
4443
static void X11_XsettingsNotify(const char *name, XSettingsAction action, XSettingsSetting *setting, void *data)
4544
{
4645
SDL_VideoDevice *_this = data;
47-
UpdateContentScale(_this);
48-
}
4946

50-
static void OnGtkXftDpi(GtkSettings *settings, GParamSpec *pspec, gpointer ptr)
51-
{
52-
SDL_VideoDevice *_this = (SDL_VideoDevice *)ptr;
53-
UpdateContentScale(_this);
47+
if (SDL_strcmp(name, SDL_XSETTINGS_GDK_WINDOW_SCALING_FACTOR) == 0 ||
48+
SDL_strcmp(name, SDL_XSETTINGS_GDK_UNSCALED_DPI) == 0 ||
49+
SDL_strcmp(name, SDL_XSETTINGS_XFT_DPI) == 0) {
50+
UpdateContentScale(_this);
51+
}
5452
}
5553

5654
void X11_InitXsettings(SDL_VideoDevice *_this)
5755
{
5856
SDL_VideoData *data = _this->internal;
5957
SDLX11_SettingsData *xsettings_data = &data->xsettings_data;
6058

61-
GtkSettings *gtksettings = NULL;
62-
guint xft_dpi_signal_handler_id = 0;
63-
64-
SDL_GtkContext *gtk = SDL_Gtk_EnterContext();
65-
if (gtk) {
66-
// Prefer to listen for DPI changes from gtk. In XWayland this is necessary as XSettings
67-
// are not updated dynamically.
68-
gtksettings = gtk->gtk.settings_get_default();
69-
if (gtksettings) {
70-
xft_dpi_signal_handler_id = gtk->g.signal_connect(gtksettings, "notify::gtk-xft-dpi", &OnGtkXftDpi, _this);
71-
}
72-
SDL_Gtk_ExitContext(gtk);
73-
}
74-
75-
if (gtksettings && xft_dpi_signal_handler_id) {
76-
xsettings_data->gtksettings = gtksettings;
77-
xsettings_data->xft_dpi_signal_handler_id = xft_dpi_signal_handler_id;
78-
}
79-
8059
xsettings_data->xsettings = xsettings_client_new(data->display,
8160
DefaultScreen(data->display), X11_XsettingsNotify, NULL, _this);
8261
}
@@ -89,28 +68,15 @@ void X11_QuitXsettings(SDL_VideoDevice *_this)
8968
if (xsettings_data->xsettings) {
9069
xsettings_client_destroy(xsettings_data->xsettings);
9170
}
92-
93-
SDL_GtkContext *gtk = SDL_Gtk_EnterContext();
94-
if (gtk) {
95-
if (xsettings_data->gtksettings && xsettings_data->xft_dpi_signal_handler_id) {
96-
gtk->g.signal_handler_disconnect(xsettings_data->gtksettings, xsettings_data->xft_dpi_signal_handler_id);
97-
}
98-
SDL_Gtk_ExitContext(gtk);
99-
}
100-
101-
SDL_zero(xsettings_data);
10271
}
10372

104-
void X11_HandleXsettings(SDL_VideoDevice *_this, const XEvent *xevent)
73+
void X11_HandleXsettingsEvent(SDL_VideoDevice *_this, const XEvent *xevent)
10574
{
10675
SDL_VideoData *data = _this->internal;
10776
SDLX11_SettingsData *xsettings_data = &data->xsettings_data;
10877

10978
if (xsettings_data->xsettings) {
110-
if (!xsettings_client_process_event(xsettings_data->xsettings, xevent)) {
111-
xsettings_client_destroy(xsettings_data->xsettings);
112-
xsettings_data->xsettings = NULL;
113-
}
79+
xsettings_client_process_event(xsettings_data->xsettings, xevent);
11480
}
11581
}
11682

src/video/x11/SDL_x11settings.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,13 @@
2727
#include <X11/Xlib.h>
2828
#include "xsettings-client.h"
2929

30-
#include "core/unix/SDL_gtk.h"
31-
3230
typedef struct X11_SettingsData {
3331
XSettingsClient *xsettings;
34-
GtkSettings *gtksettings;
35-
guint xft_dpi_signal_handler_id;
3632
} SDLX11_SettingsData;
3733

3834
extern void X11_InitXsettings(SDL_VideoDevice *_this);
3935
extern void X11_QuitXsettings(SDL_VideoDevice *_this);
40-
extern void X11_HandleXsettings(SDL_VideoDevice *_this, const XEvent *xevent);
36+
extern void X11_HandleXsettingsEvent(SDL_VideoDevice *_this, const XEvent *xevent);
4137
extern int X11_GetXsettingsIntKey(SDL_VideoDevice *_this, const char *key, int fallback_value);
4238

4339
#endif // SDL_x11settings_h_

src/video/x11/SDL_x11video.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ static bool X11_VideoInit(SDL_VideoDevice *_this)
395395
GET_ATOM(SDL_SELECTION);
396396
GET_ATOM(TARGETS);
397397
GET_ATOM(SDL_FORMATS);
398+
GET_ATOM(RESOURCE_MANAGER);
398399
GET_ATOM(XdndAware);
399400
GET_ATOM(XdndEnter);
400401
GET_ATOM(XdndLeave);

src/video/x11/SDL_x11video.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ struct SDL_VideoData
103103
Atom SDL_SELECTION;
104104
Atom TARGETS;
105105
Atom SDL_FORMATS;
106+
Atom RESOURCE_MANAGER;
106107
Atom XdndAware;
107108
Atom XdndEnter;
108109
Atom XdndLeave;

0 commit comments

Comments
 (0)