Skip to content

Commit 1ad00e0

Browse files
authored
[Wayland] Add support for cursor-shape-v1 protocol (#756)
* backend/xcursor: Support a blank cursor type * [Wayland] Add cursor-shape-v1 protocol support * cursor-shape: add to private protocols * wayland/pointer: Clear cursor shape when disabling/enabling pointer * wayland: Fix thinkos with cursor shape implementation for tablet tools * wayland: Bail early if cursor shape doesn't change * wayland: Allow changing from a cursor shape to a NULL surface * wayland: fix loading legacy cursor themes
1 parent 7453e8d commit 1ad00e0

18 files changed

Lines changed: 920 additions & 107 deletions

src/backends/meta-cursor-sprite-xcursor.c

Lines changed: 208 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -43,56 +43,220 @@ struct _MetaCursorSpriteXcursor
4343
G_DEFINE_TYPE (MetaCursorSpriteXcursor, meta_cursor_sprite_xcursor,
4444
META_TYPE_CURSOR_SPRITE)
4545

46-
static const char *
47-
translate_meta_cursor (MetaCursor cursor)
46+
const char *
47+
meta_cursor_get_name (MetaCursor cursor)
4848
{
4949
switch (cursor)
5050
{
5151
case META_CURSOR_DEFAULT:
5252
return "left_ptr";
53-
case META_CURSOR_NORTH_RESIZE:
53+
case META_CURSOR_CONTEXT_MENU:
54+
return "left_ptr";
55+
case META_CURSOR_HELP:
56+
return "question_arrow";
57+
case META_CURSOR_POINTER:
58+
return "hand";
59+
case META_CURSOR_PROGRESS:
60+
return "left_ptr_watch";
61+
case META_CURSOR_WAIT:
62+
return "watch";
63+
case META_CURSOR_CELL:
64+
return "crosshair";
65+
case META_CURSOR_CROSSHAIR:
66+
return "cross";
67+
case META_CURSOR_TEXT:
68+
return "xterm";
69+
case META_CURSOR_VERTICAL_TEXT:
70+
return "xterm";
71+
case META_CURSOR_ALIAS:
72+
return "dnd-link";
73+
case META_CURSOR_COPY:
74+
return "dnd-copy";
75+
case META_CURSOR_MOVE:
76+
return "dnd-move";
77+
case META_CURSOR_NO_DROP:
78+
return "dnd-none";
79+
case META_CURSOR_NOT_ALLOWED:
80+
return "crossed_circle";
81+
case META_CURSOR_GRAB:
82+
return "hand2";
83+
case META_CURSOR_GRABBING:
84+
return "hand2";
85+
case META_CURSOR_E_RESIZE:
86+
return "right_side";
87+
case META_CURSOR_N_RESIZE:
5488
return "top_side";
55-
case META_CURSOR_SOUTH_RESIZE:
89+
case META_CURSOR_NE_RESIZE:
90+
return "top_right_corner";
91+
case META_CURSOR_NW_RESIZE:
92+
return "top_left_corner";
93+
case META_CURSOR_S_RESIZE:
5694
return "bottom_side";
57-
case META_CURSOR_WEST_RESIZE:
58-
return "left_side";
59-
case META_CURSOR_EAST_RESIZE:
60-
return "right_side";
6195
case META_CURSOR_SE_RESIZE:
6296
return "bottom_right_corner";
6397
case META_CURSOR_SW_RESIZE:
6498
return "bottom_left_corner";
99+
case META_CURSOR_W_RESIZE:
100+
return "left_side";
101+
case META_CURSOR_EW_RESIZE:
102+
return "h_double_arrow";
103+
case META_CURSOR_NS_RESIZE:
104+
return "v_double_arrow";
105+
case META_CURSOR_NESW_RESIZE:
106+
return "fd_double_arrow";
107+
case META_CURSOR_NWSE_RESIZE:
108+
return "bd_double_arrow";
109+
case META_CURSOR_COL_RESIZE:
110+
return "h_double_arrow";
111+
case META_CURSOR_ROW_RESIZE:
112+
return "v_double_arrow";
113+
case META_CURSOR_ALL_SCROLL:
114+
return "left_ptr";
115+
case META_CURSOR_ZOOM_IN:
116+
return "left_ptr";
117+
case META_CURSOR_ZOOM_OUT:
118+
return "left_ptr";
119+
case META_CURSOR_DND_ASK:
120+
return "dnd-copy";
121+
case META_CURSOR_ALL_RESIZE:
122+
return "dnd-move";
123+
case META_CURSOR_INVALID:
124+
case META_CURSOR_NONE:
125+
break;
126+
}
127+
128+
g_assert_not_reached ();
129+
return NULL;
130+
}
131+
132+
const char *
133+
meta_cursor_get_legacy_name (MetaCursor cursor)
134+
{
135+
switch (cursor)
136+
{
137+
case META_CURSOR_DEFAULT:
138+
return "left_ptr";
139+
case META_CURSOR_CONTEXT_MENU:
140+
return "left_ptr";
141+
case META_CURSOR_HELP:
142+
return "question_arrow";
143+
case META_CURSOR_POINTER:
144+
return "hand";
145+
case META_CURSOR_PROGRESS:
146+
return "left_ptr_watch";
147+
case META_CURSOR_WAIT:
148+
return "watch";
149+
case META_CURSOR_CELL:
150+
return "crosshair";
151+
case META_CURSOR_CROSSHAIR:
152+
return "cross";
153+
case META_CURSOR_TEXT:
154+
return "xterm";
155+
case META_CURSOR_VERTICAL_TEXT:
156+
return "xterm";
157+
case META_CURSOR_ALIAS:
158+
return "dnd-link";
159+
case META_CURSOR_COPY:
160+
return "dnd-copy";
161+
case META_CURSOR_MOVE:
162+
return "dnd-move";
163+
case META_CURSOR_NO_DROP:
164+
return "dnd-none";
165+
case META_CURSOR_NOT_ALLOWED:
166+
return "crossed_circle";
167+
case META_CURSOR_GRAB:
168+
return "hand2";
169+
case META_CURSOR_GRABBING:
170+
return "hand2";
171+
case META_CURSOR_E_RESIZE:
172+
return "right_side";
173+
case META_CURSOR_N_RESIZE:
174+
return "top_side";
65175
case META_CURSOR_NE_RESIZE:
66176
return "top_right_corner";
67177
case META_CURSOR_NW_RESIZE:
68178
return "top_left_corner";
69-
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
70-
return "fleur";
71-
case META_CURSOR_BUSY:
72-
return "watch";
73-
case META_CURSOR_DND_IN_DRAG:
74-
return "dnd-none";
75-
case META_CURSOR_DND_MOVE:
76-
return "dnd-move";
77-
case META_CURSOR_DND_COPY:
179+
case META_CURSOR_S_RESIZE:
180+
return "bottom_side";
181+
case META_CURSOR_SE_RESIZE:
182+
return "bottom_right_corner";
183+
case META_CURSOR_SW_RESIZE:
184+
return "bottom_left_corner";
185+
case META_CURSOR_W_RESIZE:
186+
return "left_side";
187+
case META_CURSOR_EW_RESIZE:
188+
return "h_double_arrow";
189+
case META_CURSOR_NS_RESIZE:
190+
return "v_double_arrow";
191+
case META_CURSOR_NESW_RESIZE:
192+
return "fd_double_arrow";
193+
case META_CURSOR_NWSE_RESIZE:
194+
return "bd_double_arrow";
195+
case META_CURSOR_COL_RESIZE:
196+
return "h_double_arrow";
197+
case META_CURSOR_ROW_RESIZE:
198+
return "v_double_arrow";
199+
case META_CURSOR_ALL_SCROLL:
200+
return "left_ptr";
201+
case META_CURSOR_ZOOM_IN:
202+
return "left_ptr";
203+
case META_CURSOR_ZOOM_OUT:
204+
return "left_ptr";
205+
case META_CURSOR_DND_ASK:
78206
return "dnd-copy";
79-
case META_CURSOR_DND_UNSUPPORTED_TARGET:
80-
return "dnd-none";
81-
case META_CURSOR_POINTING_HAND:
82-
return "hand2";
83-
case META_CURSOR_CROSSHAIR:
84-
return "crosshair";
85-
case META_CURSOR_IBEAM:
86-
return "xterm";
207+
case META_CURSOR_ALL_RESIZE:
208+
return "dnd-move";
209+
case META_CURSOR_INVALID:
87210
case META_CURSOR_NONE:
88-
case META_CURSOR_LAST:
89211
break;
90-
}
212+
}
91213

92214
g_assert_not_reached ();
93215
return NULL;
94216
}
95217

218+
static Cursor
219+
create_blank_cursor (Display *xdisplay)
220+
{
221+
Pixmap pixmap;
222+
XColor color;
223+
Cursor cursor;
224+
XGCValues gc_values;
225+
GC gc;
226+
227+
pixmap = XCreatePixmap (xdisplay, DefaultRootWindow (xdisplay), 1, 1, 1);
228+
229+
gc_values.foreground = BlackPixel (xdisplay, DefaultScreen (xdisplay));
230+
gc = XCreateGC (xdisplay, pixmap, GCForeground, &gc_values);
231+
232+
XFillRectangle (xdisplay, pixmap, gc, 0, 0, 1, 1);
233+
234+
color.pixel = 0;
235+
color.red = color.blue = color.green = 0;
236+
237+
cursor = XCreatePixmapCursor (xdisplay, pixmap, pixmap, &color, &color, 1, 1);
238+
239+
XFreeGC (xdisplay, gc);
240+
XFreePixmap (xdisplay, pixmap);
241+
242+
return cursor;
243+
}
244+
245+
static XcursorImages *
246+
create_blank_cursor_images (void)
247+
{
248+
XcursorImages *images;
249+
250+
images = XcursorImagesCreate (1);
251+
images->images[0] = XcursorImageCreate (1, 1);
252+
253+
images->images[0]->xhot = 0;
254+
images->images[0]->yhot = 0;
255+
memset (images->images[0]->pixels, 0, sizeof(int32_t));
256+
257+
return images;
258+
}
259+
96260
MetaCursor
97261
meta_cursor_sprite_xcursor_get_cursor (MetaCursorSpriteXcursor *sprite_xcursor)
98262
{
@@ -103,17 +267,30 @@ Cursor
103267
meta_create_x_cursor (Display *xdisplay,
104268
MetaCursor cursor)
105269
{
106-
return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
270+
Cursor result;
271+
272+
if (cursor == META_CURSOR_NONE)
273+
return create_blank_cursor (xdisplay);
274+
275+
result = XcursorLibraryLoadCursor (xdisplay, meta_cursor_get_name (cursor));
276+
if (!result)
277+
result = XcursorLibraryLoadCursor (xdisplay, meta_cursor_get_legacy_name (cursor));
278+
279+
return result;
107280
}
108281

109282
static XcursorImages *
110-
load_cursor_on_client (MetaCursor cursor, int scale)
283+
load_cursor_on_client (MetaCursor cursor,
284+
int scale)
111285
{
286+
if (cursor == META_CURSOR_INVALID)
287+
return create_blank_cursor_images ();
288+
112289
XcursorImages *xcursor_images;
113290
int fallback_size;
114291

115292
xcursor_images =
116-
XcursorLibraryLoadImages (translate_meta_cursor (cursor),
293+
XcursorLibraryLoadImages (meta_cursor_get_name (cursor),
117294
meta_prefs_get_cursor_theme (),
118295
meta_prefs_get_cursor_size () * scale);
119296
if (xcursor_images)
@@ -248,7 +425,7 @@ load_cursor_from_theme (MetaCursorSprite *sprite)
248425
{
249426
MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite);
250427

251-
g_assert (sprite_xcursor->cursor != META_CURSOR_NONE);
428+
g_assert (sprite_xcursor->cursor != META_CURSOR_INVALID);
252429

253430
sprite_xcursor->theme_dirty = FALSE;
254431

src/backends/meta-cursor-sprite-xcursor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,8 @@ XcursorImage * meta_cursor_sprite_xcursor_get_current_image (MetaCursorSpriteXcu
4040
Cursor meta_create_x_cursor (Display *xdisplay,
4141
MetaCursor cursor);
4242

43+
const char * meta_cursor_get_name (MetaCursor cursor);
44+
45+
const char * meta_cursor_get_legacy_name (MetaCursor cursor);
46+
4347
#endif /* META_CURSOR_SPRITE_XCURSOR_H */

src/backends/x11/meta-cursor-renderer-x11.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,14 @@ meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer,
7272
Cursor xcursor;
7373

7474
xcursor = meta_create_x_cursor (xdisplay, cursor);
75-
XDefineCursor (xdisplay, xwindow, xcursor);
76-
XFlush (xdisplay);
77-
XFreeCursor (xdisplay, xcursor);
78-
79-
has_server_cursor = TRUE;
75+
if (xcursor)
76+
{
77+
XDefineCursor (xdisplay, xwindow, xcursor);
78+
XFlush (xdisplay);
79+
XFreeCursor (xdisplay, xcursor);
80+
81+
has_server_cursor = TRUE;
82+
}
8083
}
8184
}
8285

src/core/display.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,15 +1664,15 @@ meta_cursor_for_grab_op (MetaGrabOp op)
16641664
break;
16651665
case META_GRAB_OP_RESIZING_S:
16661666
case META_GRAB_OP_KEYBOARD_RESIZING_S:
1667-
return META_CURSOR_SOUTH_RESIZE;
1667+
return META_CURSOR_S_RESIZE;
16681668
break;
16691669
case META_GRAB_OP_RESIZING_SW:
16701670
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
16711671
return META_CURSOR_SW_RESIZE;
16721672
break;
16731673
case META_GRAB_OP_RESIZING_N:
16741674
case META_GRAB_OP_KEYBOARD_RESIZING_N:
1675-
return META_CURSOR_NORTH_RESIZE;
1675+
return META_CURSOR_N_RESIZE;
16761676
break;
16771677
case META_GRAB_OP_RESIZING_NE:
16781678
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
@@ -1684,16 +1684,16 @@ meta_cursor_for_grab_op (MetaGrabOp op)
16841684
break;
16851685
case META_GRAB_OP_RESIZING_W:
16861686
case META_GRAB_OP_KEYBOARD_RESIZING_W:
1687-
return META_CURSOR_WEST_RESIZE;
1687+
return META_CURSOR_W_RESIZE;
16881688
break;
16891689
case META_GRAB_OP_RESIZING_E:
16901690
case META_GRAB_OP_KEYBOARD_RESIZING_E:
1691-
return META_CURSOR_EAST_RESIZE;
1691+
return META_CURSOR_E_RESIZE;
16921692
break;
16931693
case META_GRAB_OP_MOVING:
16941694
case META_GRAB_OP_KEYBOARD_MOVING:
16951695
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
1696-
return META_CURSOR_MOVE_OR_RESIZE_WINDOW;
1696+
return META_CURSOR_MOVE;
16971697
break;
16981698
default:
16991699
break;

src/core/startup-notification.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ meta_startup_notification_update_feedback (MetaStartupNotification *sn)
137137
{
138138
meta_topic (META_DEBUG_STARTUP,
139139
"Setting busy cursor\n");
140-
meta_display_set_cursor (display, META_CURSOR_BUSY);
140+
meta_display_set_cursor (display, META_CURSOR_WAIT);
141141
}
142142
else
143143
{

src/meson.build

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,8 @@ if have_wayland
500500
'wayland/meta-wayland.c',
501501
'wayland/meta-wayland-cursor-surface.c',
502502
'wayland/meta-wayland-cursor-surface.h',
503+
'wayland/meta-wayland-cursor-shape.c',
504+
'wayland/meta-wayland-cursor-shape.h',
503505
'wayland/meta-wayland-data-device.c',
504506
'wayland/meta-wayland-data-device.h',
505507
'wayland/meta-wayland-data-device-primary.c',
@@ -804,6 +806,7 @@ if have_wayland
804806
# - protocol stability ('private', 'stable' or 'unstable')
805807
# - protocol version (if stability is 'unstable')
806808
wayland_protocols = [
809+
['cursor-shape-v1', 'private', ],
807810
['gtk-shell', 'private', ],
808811
['idle-inhibit', 'unstable', 'v1', ],
809812
['keyboard-shortcuts-inhibit', 'unstable', 'v1', ],

0 commit comments

Comments
 (0)