wayland: Use D-Bus to retrieve the cursor size and theme on GNOME GNOME exposes the cursor size and theme via the org.freedesktop.portal.Settings interface of the xdg-desktop portal, so query these values via D-Bus, if available. The XCURSOR_SIZE/XCURSOR_THEME envvars will be tried first, so as not to override any user specified sizes or themes, then D-Bus, then, failing that, it will fall back to default values.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c
index 4545c66..4b3d6f7 100644
--- a/src/video/wayland/SDL_waylandmouse.c
+++ b/src/video/wayland/SDL_waylandmouse.c
@@ -55,6 +55,106 @@ typedef struct {
void *shm_data;
} Wayland_CursorData;
+#ifdef SDL_USE_LIBDBUS
+
+#include "../../core/linux/SDL_dbus.h"
+
+static DBusMessage*
+wayland_read_dbus_setting(SDL_DBusContext *dbus, const char *key)
+{
+ static const char *iface = "org.gnome.desktop.interface";
+
+ DBusMessage *reply = NULL;
+ DBusMessage *msg = dbus->message_new_method_call("org.freedesktop.portal.Desktop", /* Node */
+ "/org/freedesktop/portal/desktop", /* Path */
+ "org.freedesktop.portal.Settings", /* Interface */
+ "Read"); /* Method */
+
+ if (msg) {
+ if (dbus->message_append_args(msg, DBUS_TYPE_STRING, &iface, DBUS_TYPE_STRING, &key, DBUS_TYPE_INVALID)) {
+ reply = dbus->connection_send_with_reply_and_block(dbus->session_conn, msg, DBUS_TIMEOUT_USE_DEFAULT, NULL);
+ }
+ dbus->message_unref(msg);
+ }
+
+ return reply;
+}
+
+static SDL_bool
+wayland_parse_dbus_reply(SDL_DBusContext *dbus, DBusMessage *reply, int type, void *value)
+{
+ DBusMessageIter iter[3];
+
+ dbus->message_iter_init(reply, &iter[0]);
+ if (dbus->message_iter_get_arg_type(&iter[0]) != DBUS_TYPE_VARIANT) {
+ return SDL_FALSE;
+ }
+
+ dbus->message_iter_recurse(&iter[0], &iter[1]);
+ if (dbus->message_iter_get_arg_type(&iter[1]) != DBUS_TYPE_VARIANT) {
+ return SDL_FALSE;
+ }
+
+ dbus->message_iter_recurse(&iter[1], &iter[2]);
+ if (dbus->message_iter_get_arg_type(&iter[2]) != type) {
+ return SDL_FALSE;
+ }
+
+ dbus->message_iter_get_basic(&iter[2], value);
+
+ return SDL_TRUE;
+}
+
+static SDL_bool
+wayland_dbus_read_cursor_size(int *size)
+{
+ static const char *cursor_size_value = "cursor-size";
+
+ DBusMessage *reply;
+ SDL_DBusContext *dbus = SDL_DBus_GetContext();
+
+ if (!dbus || !size) {
+ return SDL_FALSE;
+ }
+
+ if ((reply = wayland_read_dbus_setting(dbus, cursor_size_value))) {
+ if (wayland_parse_dbus_reply(dbus, reply, DBUS_TYPE_INT32, size)) {
+ dbus->message_unref(reply);
+ return SDL_TRUE;
+ }
+ dbus->message_unref(reply);
+ }
+
+ return SDL_FALSE;
+}
+
+static SDL_bool
+wayland_dbus_read_cursor_theme(char **theme)
+{
+ static const char *cursor_theme_value = "cursor-theme";
+
+ DBusMessage *reply;
+ SDL_DBusContext *dbus = SDL_DBus_GetContext();
+
+ if (!dbus || !theme) {
+ return SDL_FALSE;
+ }
+
+ if ((reply = wayland_read_dbus_setting(dbus, cursor_theme_value))) {
+ const char *temp;
+ if (wayland_parse_dbus_reply(dbus, reply, DBUS_TYPE_STRING, &temp)) {
+ *theme = SDL_strdup(temp);
+ dbus->message_unref(reply);
+ return SDL_TRUE;
+ }
+ dbus->message_unref(reply);
+ }
+
+ return SDL_FALSE;
+}
+
+#endif
+
static SDL_bool
wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorData *cdata, float *scale)
{
@@ -68,20 +168,25 @@ wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorData *cdata, float
SDL_WindowData *focusdata;
int i;
- /* FIXME: We need to be able to query the cursor size from the desktop at
- * some point! For a while this was 32, but when testing on real desktops it
- * seems like most of them default to 24. We'll need a protocol to get this
- * for real, but for now this is a pretty safe bet.
- * -flibit
+ /*
+ * GNOME based desktops expose the cursor size and theme via the
+ * org.freedesktop.portal.Settings interface of the xdg-desktop portal.
+ * Try XCURSOR_SIZE and XCURSOR_THEME first, so user specified sizes and
+ * themes take precedence over all, then try D-Bus if the envvar isn't
+ * set, then fall back to the defaults if none of the preceding values
+ * are available or valid.
*/
- xcursor_size = SDL_getenv("XCURSOR_SIZE");
- if (xcursor_size != NULL) {
+ if ((xcursor_size = SDL_getenv("XCURSOR_SIZE"))) {
size = SDL_atoi(xcursor_size);
}
+#if SDL_USE_LIBDBUS
+ if (size <= 0) {
+ wayland_dbus_read_cursor_size(&size);
+ }
+#endif
if (size <= 0) {
size = 24;
}
-
/* First, find the appropriate theme based on the current scale... */
focus = SDL_GetMouse()->focus;
if (focus == NULL) {
@@ -98,15 +203,29 @@ wayland_get_system_cursor(SDL_VideoData *vdata, Wayland_CursorData *cdata, float
}
}
if (theme == NULL) {
+ char *xcursor_theme = NULL;
+ SDL_bool free_theme_str = SDL_FALSE;
+
vdata->cursor_themes = SDL_realloc(vdata->cursor_themes,
sizeof(SDL_WaylandCursorTheme) * (vdata->num_cursor_themes + 1));
if (vdata->cursor_themes == NULL) {
SDL_OutOfMemory();
return SDL_FALSE;
}
- theme = WAYLAND_wl_cursor_theme_load(SDL_getenv("XCURSOR_THEME"), size, vdata->shm);
+ xcursor_theme = SDL_getenv("XCURSOR_THEME");
+#if SDL_USE_LIBDBUS
+ if (xcursor_theme == NULL) {
+ /* Allocates the string with SDL_strdup, which must be freed. */
+ free_theme_str = wayland_dbus_read_cursor_theme(&xcursor_theme);
+ }
+#endif
+ theme = WAYLAND_wl_cursor_theme_load(xcursor_theme, size, vdata->shm);
vdata->cursor_themes[vdata->num_cursor_themes].size = size;
vdata->cursor_themes[vdata->num_cursor_themes++].theme = theme;
+
+ if (free_theme_str) {
+ SDL_free(xcursor_theme);
+ }
}
/* Next, find the cursor from the theme... */