x11: Dynamically update the scale factor
If the text-scaling-factor setting is available via D-Bus, add a listener and update the content scale values for the displays if the value is changed during runtime. Factors out the D-Bus message pump from the system theme detection code to the general D-Bus code, as it's now used for more purposes than just the system theme.
This commit is contained in:
parent
068d3da366
commit
d5f07730be
@ -498,4 +498,16 @@ SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
|
|||||||
|
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDL_DBus_PumpEvents(void)
|
||||||
|
{
|
||||||
|
if (dbus.session_conn) {
|
||||||
|
dbus.connection_read_write(dbus.session_conn, 0);
|
||||||
|
|
||||||
|
while (dbus.connection_dispatch(dbus.session_conn) == DBUS_DISPATCH_DATA_REMAINS) {
|
||||||
|
/* Do nothing, actual work happens in DBus_MessageFilter */
|
||||||
|
SDL_DelayNS(SDL_US_TO_NS(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -94,6 +94,8 @@ extern SDL_bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const c
|
|||||||
extern void SDL_DBus_ScreensaverTickle(void);
|
extern void SDL_DBus_ScreensaverTickle(void);
|
||||||
extern SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit);
|
extern SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit);
|
||||||
|
|
||||||
|
extern void SDL_DBus_PumpEvents(void);
|
||||||
|
|
||||||
#endif /* HAVE_DBUS_DBUS_H */
|
#endif /* HAVE_DBUS_DBUS_H */
|
||||||
|
|
||||||
#endif /* SDL_dbus_h_ */
|
#endif /* SDL_dbus_h_ */
|
||||||
|
@ -158,18 +158,3 @@ SDL_SystemTheme_Get(void)
|
|||||||
{
|
{
|
||||||
return system_theme_data.theme;
|
return system_theme_data.theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
SDL_SystemTheme_PumpEvents(void)
|
|
||||||
{
|
|
||||||
SDL_DBusContext *dbus = system_theme_data.dbus;
|
|
||||||
DBusConnection *conn;
|
|
||||||
if (dbus == NULL) return;
|
|
||||||
conn = dbus->session_conn;
|
|
||||||
dbus->connection_read_write(conn, 0);
|
|
||||||
|
|
||||||
while (dbus->connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS) {
|
|
||||||
/* Do nothing, actual work happens in DBus_MessageFilter */
|
|
||||||
usleep(10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -26,6 +26,5 @@
|
|||||||
|
|
||||||
extern SDL_bool SDL_SystemTheme_Init(void);
|
extern SDL_bool SDL_SystemTheme_Init(void);
|
||||||
extern SDL_SystemTheme SDL_SystemTheme_Get(void);
|
extern SDL_SystemTheme SDL_SystemTheme_Get(void);
|
||||||
extern void SDL_SystemTheme_PumpEvents(void);
|
|
||||||
|
|
||||||
#endif /* SDL_system_theme_h_ */
|
#endif /* SDL_system_theme_h_ */
|
||||||
|
@ -391,7 +391,7 @@ int Wayland_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_USE_LIBDBUS
|
#ifdef SDL_USE_LIBDBUS
|
||||||
SDL_SystemTheme_PumpEvents();
|
SDL_DBus_PumpEvents();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If key repeat is active, we'll need to cap our maximum wait time to handle repeats */
|
/* If key repeat is active, we'll need to cap our maximum wait time to handle repeats */
|
||||||
@ -464,7 +464,7 @@ void Wayland_PumpEvents(SDL_VideoDevice *_this)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_USE_LIBDBUS
|
#ifdef SDL_USE_LIBDBUS
|
||||||
SDL_SystemTheme_PumpEvents();
|
SDL_DBus_PumpEvents();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBDECOR_H
|
#ifdef HAVE_LIBDECOR_H
|
||||||
|
@ -1706,7 +1706,7 @@ int X11_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_USE_LIBDBUS
|
#ifdef SDL_USE_LIBDBUS
|
||||||
SDL_SystemTheme_PumpEvents();
|
SDL_DBus_PumpEvents();
|
||||||
#endif
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1751,7 +1751,7 @@ void X11_PumpEvents(SDL_VideoDevice *_this)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_USE_LIBDBUS
|
#ifdef SDL_USE_LIBDBUS
|
||||||
SDL_SystemTheme_PumpEvents();
|
SDL_DBus_PumpEvents();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* FIXME: Only need to do this when there are pending focus changes */
|
/* FIXME: Only need to do this when there are pending focus changes */
|
||||||
|
@ -41,15 +41,22 @@
|
|||||||
|
|
||||||
#ifdef SDL_USE_LIBDBUS
|
#ifdef SDL_USE_LIBDBUS
|
||||||
|
|
||||||
|
#define SCALE_FACTOR_NODE "org.freedesktop.portal.Desktop"
|
||||||
|
#define SCALE_FACTOR_PATH "/org/freedesktop/portal/desktop"
|
||||||
|
#define SCALE_FACTOR_INTERFACE "org.freedesktop.portal.Settings"
|
||||||
|
#define SCALE_FACTOR_NAMESPACE "org.gnome.desktop.interface"
|
||||||
|
#define SCALE_FACTOR_SIGNAL_NAME "SettingChanged"
|
||||||
|
#define SCALE_FACTOR_KEY "text-scaling-factor"
|
||||||
|
|
||||||
static DBusMessage *ReadDBusSetting(SDL_DBusContext *dbus, const char *key)
|
static DBusMessage *ReadDBusSetting(SDL_DBusContext *dbus, const char *key)
|
||||||
{
|
{
|
||||||
static const char *iface = "org.gnome.desktop.interface";
|
static const char *iface = SCALE_FACTOR_NAMESPACE;
|
||||||
|
|
||||||
DBusMessage *reply = NULL;
|
DBusMessage *reply = NULL;
|
||||||
DBusMessage *msg = dbus->message_new_method_call("org.freedesktop.portal.Desktop", /* Node */
|
DBusMessage *msg = dbus->message_new_method_call(SCALE_FACTOR_NODE,
|
||||||
"/org/freedesktop/portal/desktop", /* Path */
|
SCALE_FACTOR_PATH,
|
||||||
"org.freedesktop.portal.Settings", /* Interface */
|
SCALE_FACTOR_INTERFACE,
|
||||||
"Read"); /* Method */
|
"Read"); /* Method */
|
||||||
|
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (dbus->message_append_args(msg, DBUS_TYPE_STRING, &iface, DBUS_TYPE_STRING, &key, DBUS_TYPE_INVALID)) {
|
if (dbus->message_append_args(msg, DBUS_TYPE_STRING, &iface, DBUS_TYPE_STRING, &key, DBUS_TYPE_INVALID)) {
|
||||||
@ -85,11 +92,75 @@ static SDL_bool ParseDBusReply(SDL_DBusContext *dbus, DBusMessage *reply, int ty
|
|||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void UpdateDisplayContentScale(float scale)
|
||||||
|
{
|
||||||
|
SDL_VideoDevice *viddevice = SDL_GetVideoDevice();
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (viddevice) {
|
||||||
|
for (i = 0; i < viddevice->num_displays; ++i) {
|
||||||
|
SDL_SetDisplayContentScale(&viddevice->displays[i], scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
|
||||||
|
{
|
||||||
|
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||||
|
double *scale_factor = (double *)data;
|
||||||
|
double new_scale = 0.0;
|
||||||
|
|
||||||
|
if (dbus->message_is_signal(msg, SCALE_FACTOR_INTERFACE, SCALE_FACTOR_SIGNAL_NAME)) {
|
||||||
|
DBusMessageIter signal_iter, variant_iter;
|
||||||
|
const char *namespace, *key;
|
||||||
|
|
||||||
|
dbus->message_iter_init(msg, &signal_iter);
|
||||||
|
/* Check if the parameters are what we expect */
|
||||||
|
if (dbus->message_iter_get_arg_type(&signal_iter) != DBUS_TYPE_STRING) {
|
||||||
|
goto not_our_signal;
|
||||||
|
}
|
||||||
|
dbus->message_iter_get_basic(&signal_iter, &namespace);
|
||||||
|
if (SDL_strcmp(SCALE_FACTOR_NAMESPACE, namespace) != 0) {
|
||||||
|
goto not_our_signal;
|
||||||
|
}
|
||||||
|
if (!dbus->message_iter_next(&signal_iter)) {
|
||||||
|
goto not_our_signal;
|
||||||
|
}
|
||||||
|
if (dbus->message_iter_get_arg_type(&signal_iter) != DBUS_TYPE_STRING) {
|
||||||
|
goto not_our_signal;
|
||||||
|
}
|
||||||
|
dbus->message_iter_get_basic(&signal_iter, &key);
|
||||||
|
if (SDL_strcmp(SCALE_FACTOR_KEY, key) != 0) {
|
||||||
|
goto not_our_signal;
|
||||||
|
}
|
||||||
|
if (!dbus->message_iter_next(&signal_iter)) {
|
||||||
|
goto not_our_signal;
|
||||||
|
}
|
||||||
|
if (dbus->message_iter_get_arg_type(&signal_iter) != DBUS_TYPE_VARIANT) {
|
||||||
|
goto not_our_signal;
|
||||||
|
}
|
||||||
|
dbus->message_iter_recurse(&signal_iter, &variant_iter);
|
||||||
|
if (dbus->message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_DOUBLE) {
|
||||||
|
goto not_our_signal;
|
||||||
|
}
|
||||||
|
dbus->message_iter_get_basic(&variant_iter, &new_scale);
|
||||||
|
|
||||||
|
if (new_scale > 0.0) {
|
||||||
|
*scale_factor = new_scale;
|
||||||
|
UpdateDisplayContentScale(new_scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DBUS_HANDLER_RESULT_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
not_our_signal:
|
||||||
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static float GetGlobalContentScale()
|
static float GetGlobalContentScale()
|
||||||
{
|
{
|
||||||
static const char *text_scaling_factor = "text-scaling-factor";
|
|
||||||
static double scale_factor = 0.0;
|
static double scale_factor = 0.0;
|
||||||
|
|
||||||
if (scale_factor <= 0.0) {
|
if (scale_factor <= 0.0) {
|
||||||
@ -99,8 +170,16 @@ static float GetGlobalContentScale()
|
|||||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||||
|
|
||||||
if (dbus) {
|
if (dbus) {
|
||||||
if ((reply = ReadDBusSetting(dbus, text_scaling_factor))) {
|
if ((reply = ReadDBusSetting(dbus, SCALE_FACTOR_KEY))) {
|
||||||
ParseDBusReply(dbus, reply, DBUS_TYPE_DOUBLE, &scale_factor);
|
if (ParseDBusReply(dbus, reply, DBUS_TYPE_DOUBLE, &scale_factor)) {
|
||||||
|
/* If the setting exists, register a listener for scale changes. */
|
||||||
|
dbus->bus_add_match(dbus->session_conn,
|
||||||
|
"type='signal', interface='"SCALE_FACTOR_INTERFACE"',"
|
||||||
|
"member='"SCALE_FACTOR_SIGNAL_NAME"', arg0='"SCALE_FACTOR_NAMESPACE"',"
|
||||||
|
"arg1='"SCALE_FACTOR_KEY"'", NULL);
|
||||||
|
dbus->connection_add_filter(dbus->session_conn, &DBus_MessageFilter, &scale_factor, NULL);
|
||||||
|
dbus->connection_flush(dbus->session_conn);
|
||||||
|
}
|
||||||
dbus->message_unref(reply);
|
dbus->message_unref(reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user