forked from AuroraMiddleware/gtk
wayland: Support scaling of theme based cursors
Support scaling of cursors created from themes. The default scale is always 1, but if the pointer cursor surface enters an output with a higher scale, load the larger version of the cursor theme and use the image from that theme. This assumes the theme size is set to one that fits with an output scale = 1. https://bugzilla.gnome.org/show_bug.cgi?id=746141
This commit is contained in:
parent
7b2cdabc2e
commit
465647e964
@ -59,6 +59,7 @@ struct _GdkWaylandCursor
|
||||
} surface;
|
||||
|
||||
struct wl_cursor *wl_cursor;
|
||||
int scale;
|
||||
};
|
||||
|
||||
struct _GdkWaylandCursorClass
|
||||
@ -83,11 +84,18 @@ _gdk_wayland_display_finalize_cursors (GdkWaylandDisplay *display)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_cursor_from_theme (GdkWaylandCursor *cursor,
|
||||
struct wl_cursor_theme *theme)
|
||||
_gdk_wayland_cursor_update (GdkWaylandDisplay *wayland_display,
|
||||
GdkWaylandCursor *cursor)
|
||||
{
|
||||
struct wl_cursor *c;
|
||||
struct wl_cursor_theme *theme;
|
||||
|
||||
/* Do nothing if this is not a wl_cursor cursor. */
|
||||
if (cursor->name == NULL)
|
||||
return FALSE;
|
||||
|
||||
theme = _gdk_wayland_display_get_scaled_cursor_theme (wayland_display,
|
||||
cursor->scale);
|
||||
c = wl_cursor_theme_get_cursor (theme, cursor->name);
|
||||
if (!c)
|
||||
{
|
||||
@ -106,8 +114,7 @@ set_cursor_from_theme (GdkWaylandCursor *cursor,
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_display_update_cursors (GdkWaylandDisplay *display,
|
||||
struct wl_cursor_theme *theme)
|
||||
_gdk_wayland_display_update_cursors (GdkWaylandDisplay *display)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
const char *name;
|
||||
@ -116,7 +123,7 @@ _gdk_wayland_display_update_cursors (GdkWaylandDisplay *display,
|
||||
g_hash_table_iter_init (&iter, display->cursor_cache);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &cursor))
|
||||
set_cursor_from_theme (cursor, theme);
|
||||
_gdk_wayland_cursor_update (display, cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -169,7 +176,7 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
|
||||
|
||||
*w = image->width;
|
||||
*h = image->height;
|
||||
*scale = 1;
|
||||
*scale = wayland_cursor->scale;
|
||||
|
||||
return wl_cursor_image_get_buffer (image);
|
||||
}
|
||||
@ -217,6 +224,28 @@ _gdk_wayland_cursor_get_next_image_index (GdkCursor *cursor,
|
||||
return current_image_index;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_wayland_cursor_set_scale (GdkCursor *cursor,
|
||||
guint scale)
|
||||
{
|
||||
GdkWaylandDisplay *wayland_display =
|
||||
GDK_WAYLAND_DISPLAY (gdk_cursor_get_display (cursor));
|
||||
GdkWaylandCursor *wayland_cursor = GDK_WAYLAND_CURSOR (cursor);
|
||||
|
||||
if (scale > GDK_WAYLAND_MAX_THEME_SCALE)
|
||||
{
|
||||
g_warning (G_STRLOC ": cursor theme size %u too large", scale);
|
||||
scale = GDK_WAYLAND_MAX_THEME_SCALE;
|
||||
}
|
||||
|
||||
if (wayland_cursor->scale == scale)
|
||||
return;
|
||||
|
||||
wayland_cursor->scale = scale;
|
||||
|
||||
_gdk_wayland_cursor_update (wayland_display, wayland_cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_wayland_cursor_class_init (GdkWaylandCursorClass *wayland_cursor_class)
|
||||
{
|
||||
@ -233,9 +262,15 @@ _gdk_wayland_cursor_init (GdkWaylandCursor *cursor)
|
||||
{
|
||||
}
|
||||
|
||||
static GdkCursor *
|
||||
_gdk_wayland_display_get_cursor_for_name_with_scale (GdkDisplay *display,
|
||||
const gchar *name,
|
||||
guint scale);
|
||||
|
||||
GdkCursor *
|
||||
_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display,
|
||||
GdkCursorType cursor_type)
|
||||
_gdk_wayland_display_get_cursor_for_type_with_scale (GdkDisplay *display,
|
||||
GdkCursorType cursor_type,
|
||||
guint scale)
|
||||
{
|
||||
GEnumClass *enum_class;
|
||||
GEnumValue *enum_value;
|
||||
@ -248,7 +283,9 @@ _gdk_wayland_display_get_cursor_for_type (GdkDisplay *display,
|
||||
g_strdelimit (cursor_name, "-", '_');
|
||||
g_type_class_unref (enum_class);
|
||||
|
||||
result = _gdk_wayland_display_get_cursor_for_name (display, cursor_name);
|
||||
result = _gdk_wayland_display_get_cursor_for_name_with_scale (display,
|
||||
cursor_name,
|
||||
scale);
|
||||
|
||||
g_free (cursor_name);
|
||||
|
||||
@ -256,8 +293,18 @@ _gdk_wayland_display_get_cursor_for_type (GdkDisplay *display,
|
||||
}
|
||||
|
||||
GdkCursor *
|
||||
_gdk_wayland_display_get_cursor_for_name (GdkDisplay *display,
|
||||
const gchar *name)
|
||||
_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display,
|
||||
GdkCursorType cursor_type)
|
||||
{
|
||||
return _gdk_wayland_display_get_cursor_for_type_with_scale (display,
|
||||
cursor_type,
|
||||
1);
|
||||
}
|
||||
|
||||
static GdkCursor *
|
||||
_gdk_wayland_display_get_cursor_for_name_with_scale (GdkDisplay *display,
|
||||
const gchar *name,
|
||||
guint scale)
|
||||
{
|
||||
GdkWaylandCursor *private;
|
||||
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (display);
|
||||
@ -273,12 +320,13 @@ _gdk_wayland_display_get_cursor_for_name (GdkDisplay *display,
|
||||
"display", display,
|
||||
NULL);
|
||||
private->name = g_strdup (name);
|
||||
private->scale = scale;
|
||||
|
||||
/* Blank cursor case */
|
||||
if (!name || g_str_equal (name, "blank_cursor"))
|
||||
return GDK_CURSOR (private);
|
||||
|
||||
if (!set_cursor_from_theme (private, wayland_display->cursor_theme))
|
||||
if (!_gdk_wayland_cursor_update (wayland_display, private))
|
||||
return GDK_CURSOR (private);
|
||||
|
||||
/* Insert into cache. */
|
||||
@ -286,6 +334,13 @@ _gdk_wayland_display_get_cursor_for_name (GdkDisplay *display,
|
||||
return GDK_CURSOR (private);
|
||||
}
|
||||
|
||||
GdkCursor *
|
||||
_gdk_wayland_display_get_cursor_for_name (GdkDisplay *display,
|
||||
const gchar *name)
|
||||
{
|
||||
return _gdk_wayland_display_get_cursor_for_name_with_scale (display, name, 1);
|
||||
}
|
||||
|
||||
GdkCursor *
|
||||
_gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
|
||||
cairo_surface_t *surface,
|
||||
|
@ -93,6 +93,8 @@ struct _GdkWaylandDeviceData
|
||||
GdkDragContext *drop_context;
|
||||
|
||||
struct wl_surface *pointer_surface;
|
||||
guint current_output_scale;
|
||||
GSList *pointer_surface_outputs;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDevice
|
||||
@ -253,7 +255,15 @@ gdk_wayland_device_set_window_cursor (GdkDevice *device,
|
||||
* the default cursor
|
||||
*/
|
||||
if (!cursor)
|
||||
cursor = _gdk_wayland_display_get_cursor_for_type (device->display, GDK_LEFT_PTR);
|
||||
{
|
||||
guint scale = wd->current_output_scale;
|
||||
cursor =
|
||||
_gdk_wayland_display_get_cursor_for_type_with_scale (wd->display,
|
||||
GDK_LEFT_PTR,
|
||||
scale);
|
||||
}
|
||||
else
|
||||
_gdk_wayland_cursor_set_scale (cursor, wd->current_output_scale);
|
||||
|
||||
if (cursor == wd->cursor)
|
||||
return;
|
||||
@ -1756,6 +1766,78 @@ init_devices (GdkWaylandDeviceData *device)
|
||||
_gdk_device_set_associated_device (device->master_keyboard, device->master_pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_surface_update_scale (GdkWaylandDeviceData *device)
|
||||
{
|
||||
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (device->display);
|
||||
guint32 scale;
|
||||
GSList *l;
|
||||
|
||||
if (wayland_display->compositor_version < WL_SURFACE_HAS_BUFFER_SCALE)
|
||||
{
|
||||
/* We can't set the scale on this surface */
|
||||
return;
|
||||
}
|
||||
|
||||
scale = 1;
|
||||
for (l = device->pointer_surface_outputs; l != NULL; l = l->next)
|
||||
{
|
||||
guint32 output_scale =
|
||||
_gdk_wayland_screen_get_output_scale (wayland_display->screen,
|
||||
l->data);
|
||||
scale = MAX (scale, output_scale);
|
||||
}
|
||||
|
||||
device->current_output_scale = scale;
|
||||
|
||||
if (device->grab_cursor)
|
||||
_gdk_wayland_cursor_set_scale (device->grab_cursor, scale);
|
||||
if (device->cursor)
|
||||
_gdk_wayland_cursor_set_scale (device->cursor, scale);
|
||||
|
||||
gdk_wayland_device_update_window_cursor (device);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_surface_enter (void *data,
|
||||
struct wl_surface *wl_surface,
|
||||
struct wl_output *output)
|
||||
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("pointer surface of device %p entered output %p",
|
||||
device, output));
|
||||
|
||||
device->pointer_surface_outputs =
|
||||
g_slist_append (device->pointer_surface_outputs, output);
|
||||
|
||||
pointer_surface_update_scale (device);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_surface_leave (void *data,
|
||||
struct wl_surface *wl_surface,
|
||||
struct wl_output *output)
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("pointer surface of device %p left output %p",
|
||||
device, output));
|
||||
|
||||
device->pointer_surface_outputs =
|
||||
g_slist_remove (device->pointer_surface_outputs, output);
|
||||
|
||||
pointer_surface_update_scale (device);
|
||||
}
|
||||
|
||||
static const struct wl_surface_listener pointer_surface_listener = {
|
||||
pointer_surface_enter,
|
||||
pointer_surface_leave
|
||||
};
|
||||
|
||||
void
|
||||
_gdk_wayland_device_manager_add_seat (GdkDeviceManager *device_manager,
|
||||
guint32 id,
|
||||
@ -1786,8 +1868,12 @@ _gdk_wayland_device_manager_add_seat (GdkDeviceManager *device_manager,
|
||||
wl_data_device_add_listener (device->data_device,
|
||||
&data_device_listener, device);
|
||||
|
||||
device->current_output_scale = 1;
|
||||
device->pointer_surface =
|
||||
wl_compositor_create_surface (display_wayland->compositor);
|
||||
wl_surface_add_listener (device->pointer_surface,
|
||||
&pointer_surface_listener,
|
||||
device);
|
||||
|
||||
init_devices (device);
|
||||
}
|
||||
|
@ -581,6 +581,7 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay *display,
|
||||
{
|
||||
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY(display);
|
||||
struct wl_cursor_theme *theme;
|
||||
int i;
|
||||
|
||||
g_assert (wayland_display);
|
||||
g_assert (wayland_display->shm);
|
||||
@ -592,11 +593,49 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay *display,
|
||||
return;
|
||||
}
|
||||
|
||||
_gdk_wayland_display_update_cursors (wayland_display, theme);
|
||||
for (i = 0; i < GDK_WAYLAND_THEME_SCALES_COUNT; i++)
|
||||
{
|
||||
if (wayland_display->scaled_cursor_themes[i])
|
||||
{
|
||||
wl_cursor_theme_destroy (wayland_display->scaled_cursor_themes[i]);
|
||||
wayland_display->scaled_cursor_themes[i] = NULL;
|
||||
}
|
||||
}
|
||||
wayland_display->scaled_cursor_themes[0] = theme;
|
||||
if (wayland_display->cursor_theme_name != NULL)
|
||||
free (wayland_display->cursor_theme_name);
|
||||
wayland_display->cursor_theme_name = g_strdup (name);
|
||||
wayland_display->cursor_theme_size = size;
|
||||
|
||||
if (wayland_display->cursor_theme != NULL)
|
||||
wl_cursor_theme_destroy (wayland_display->cursor_theme);
|
||||
wayland_display->cursor_theme = theme;
|
||||
_gdk_wayland_display_update_cursors (wayland_display);
|
||||
}
|
||||
|
||||
struct wl_cursor_theme *
|
||||
_gdk_wayland_display_get_scaled_cursor_theme (GdkWaylandDisplay *wayland_display,
|
||||
guint scale)
|
||||
{
|
||||
struct wl_cursor_theme *theme;
|
||||
|
||||
g_assert (wayland_display->cursor_theme_name);
|
||||
g_assert (scale <= GDK_WAYLAND_MAX_THEME_SCALE);
|
||||
g_assert (scale >= 1);
|
||||
|
||||
theme = wayland_display->scaled_cursor_themes[scale - 1];
|
||||
if (!theme)
|
||||
{
|
||||
theme = wl_cursor_theme_load (wayland_display->cursor_theme_name,
|
||||
wayland_display->cursor_theme_size * scale,
|
||||
wayland_display->shm);
|
||||
if (theme == NULL)
|
||||
{
|
||||
g_warning ("Failed to load cursor theme %s with scale %u\n",
|
||||
wayland_display->cursor_theme_name, scale);
|
||||
return NULL;
|
||||
}
|
||||
wayland_display->scaled_cursor_themes[scale - 1] = theme;
|
||||
}
|
||||
|
||||
return theme;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -42,6 +42,9 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_WAYLAND_MAX_THEME_SCALE 2
|
||||
#define GDK_WAYLAND_THEME_SCALES_COUNT GDK_WAYLAND_MAX_THEME_SCALE
|
||||
|
||||
typedef struct _GdkWaylandSelection GdkWaylandSelection;
|
||||
|
||||
struct _GdkWaylandDisplay
|
||||
@ -69,7 +72,9 @@ struct _GdkWaylandDisplay
|
||||
struct wl_data_device_manager *data_device_manager;
|
||||
struct wl_subcompositor *subcompositor;
|
||||
|
||||
struct wl_cursor_theme *cursor_theme;
|
||||
struct wl_cursor_theme *scaled_cursor_themes[GDK_WAYLAND_THEME_SCALES_COUNT];
|
||||
gchar *cursor_theme_name;
|
||||
int cursor_theme_size;
|
||||
GHashTable *cursor_cache;
|
||||
|
||||
GSource *event_source;
|
||||
|
@ -56,11 +56,16 @@ gboolean _gdk_wayland_keymap_key_is_modifier (GdkKeymap *keymap,
|
||||
|
||||
void _gdk_wayland_display_init_cursors (GdkWaylandDisplay *display);
|
||||
void _gdk_wayland_display_finalize_cursors (GdkWaylandDisplay *display);
|
||||
void _gdk_wayland_display_update_cursors (GdkWaylandDisplay *display,
|
||||
struct wl_cursor_theme *theme);
|
||||
void _gdk_wayland_display_update_cursors (GdkWaylandDisplay *display);
|
||||
|
||||
struct wl_cursor_theme * _gdk_wayland_display_get_scaled_cursor_theme (GdkWaylandDisplay *wayland_display,
|
||||
guint scale);
|
||||
|
||||
GdkCursor *_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display,
|
||||
GdkCursorType cursor_type);
|
||||
GdkCursor *_gdk_wayland_display_get_cursor_for_type_with_scale (GdkDisplay *display,
|
||||
GdkCursorType cursor_type,
|
||||
guint scale);
|
||||
GdkCursor *_gdk_wayland_display_get_cursor_for_name (GdkDisplay *display,
|
||||
const gchar *name);
|
||||
GdkCursor *_gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
|
||||
@ -87,6 +92,9 @@ guint _gdk_wayland_cursor_get_next_image_index (GdkCursor *cursor,
|
||||
guint current_image_index,
|
||||
guint *next_image_delay);
|
||||
|
||||
void _gdk_wayland_cursor_set_scale (GdkCursor *cursor,
|
||||
guint scale);
|
||||
|
||||
GdkDragProtocol _gdk_wayland_window_get_drag_protocol (GdkWindow *window,
|
||||
GdkWindow **target);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user