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