[vlc-commits] xdg-shell: show/hide the left_ptr cursor

Rémi Denis-Courmont git at videolan.org
Thu May 24 19:33:20 CEST 2018


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Thu May 24 20:27:07 2018 +0300| [3caea5a4e848410ce2f4d4c1d438c921cccde0d0] | committer: Rémi Denis-Courmont

xdg-shell: show/hide the left_ptr cursor

Add timeout handling in the Wayland client loop, show the left pointer
image as cursor on entry/movement/button/axis, and hide it after the
usual timeout. This fixes #20531.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=3caea5a4e848410ce2f4d4c1d438c921cccde0d0
---

 modules/video_output/wayland/input.c     | 83 ++++++++++++++++++++++++++++++--
 modules/video_output/wayland/input.h     |  7 +++
 modules/video_output/wayland/xdg-shell.c |  8 ++-
 3 files changed, 92 insertions(+), 6 deletions(-)

diff --git a/modules/video_output/wayland/input.c b/modules/video_output/wayland/input.c
index eddbd11e02..8147df1d2f 100644
--- a/modules/video_output/wayland/input.c
+++ b/modules/video_output/wayland/input.c
@@ -45,7 +45,12 @@ struct seat_data
 {
     vout_window_t *owner;
     struct wl_seat *seat;
+
     struct wl_pointer *pointer;
+    mtime_t cursor_timeout;
+    mtime_t cursor_deadline;
+    uint32_t cursor_serial;
+
 #ifdef HAVE_XKBCOMMON
     struct xkb_context *xkb;
     struct wl_keyboard *keyboard;
@@ -58,12 +63,27 @@ struct seat_data
     struct wl_list node;
 };
 
+static void pointer_show(struct seat_data *sd, struct wl_pointer *pointer)
+{
+    int hsx, hsy;
+    struct wl_surface *surface = window_get_cursor(sd->owner, &hsx, &hsy);
+
+    if (surface != NULL)
+    {
+        wl_pointer_set_cursor(pointer, sd->cursor_serial, surface, hsx, hsy);
+        sd->cursor_deadline = mdate() + sd->cursor_timeout;
+    }
+}
+
 static void pointer_enter_cb(void *data, struct wl_pointer *pointer,
                              uint32_t serial, struct wl_surface *surface,
                              wl_fixed_t sx, wl_fixed_t sy)
 {
-    (void) data; (void) pointer; (void) serial; (void) surface;
-    (void) sx; (void) sy; /* TODO: set_cursor */
+    struct seat_data *sd = data;
+
+    sd->cursor_serial = serial;
+    pointer_show(sd, pointer);
+    (void) surface; (void) sx; (void) sy;
 }
 
 static void pointer_leave_cb(void *data, struct wl_pointer *pointer,
@@ -77,9 +97,10 @@ static void pointer_motion_cb(void *data, struct wl_pointer *pointer,
 {
     struct seat_data *sd = data;
 
+    pointer_show(sd, pointer);
     vout_window_ReportMouseMoved(sd->owner,
                                  wl_fixed_to_int(sx), wl_fixed_to_int(sy));
-    (void) pointer; (void) time;
+    (void) time;
 }
 
 static void pointer_button_cb(void *data, struct wl_pointer *pointer,
@@ -89,6 +110,8 @@ static void pointer_button_cb(void *data, struct wl_pointer *pointer,
     struct seat_data *sd = data;
     int button;
 
+    pointer_show(sd, pointer);
+
     switch (keycode)
     {
         case BTN_LEFT:
@@ -114,7 +137,7 @@ static void pointer_button_cb(void *data, struct wl_pointer *pointer,
             break;
     }
 
-    (void) pointer; (void) serial; (void) time;
+    (void) serial; (void) time;
 }
 
 static void pointer_axis_cb(void *data, struct wl_pointer *pointer,
@@ -125,6 +148,7 @@ static void pointer_axis_cb(void *data, struct wl_pointer *pointer,
     int button;
     bool plus = value > 0;
 
+    pointer_show(sd, pointer);
     value = abs(value);
 
     switch (type)
@@ -145,7 +169,7 @@ static void pointer_axis_cb(void *data, struct wl_pointer *pointer,
         vout_window_ReportMouseReleased(wnd, button);
         value -= wl_fixed_from_int(10);
     }
-    (void) pointer; (void) serial;
+    (void) serial;
 }
 
 static void pointer_frame_cb(void *data, struct wl_pointer *pointer)
@@ -192,6 +216,10 @@ static void pointer_create(struct seat_data *sd)
     sd->pointer = wl_seat_get_pointer(sd->seat);
     if (likely(sd->pointer != NULL))
         wl_pointer_add_listener(sd->pointer, &pointer_cbs, sd);
+
+    sd->cursor_timeout = var_InheritInteger(sd->owner, "mouse-hide-timeout")
+                         * (CLOCK_FREQ / 1000);
+    sd->cursor_deadline = INT64_MAX;
 }
 
 static void pointer_destroy(struct seat_data *sd)
@@ -425,6 +453,20 @@ int seat_create(vout_window_t *wnd, struct wl_registry *registry,
     return 0;
 }
 
+static mtime_t seat_next_deadline(const struct seat_data *sd)
+{
+    return (sd->pointer != NULL) ? sd->cursor_deadline : INT64_MAX;
+}
+
+static void seat_refresh(struct seat_data *sd, mtime_t now)
+{
+    if (sd->pointer != NULL && sd->cursor_deadline <= now)
+    {   /* Hide cursor */
+        wl_pointer_set_cursor(sd->pointer, sd->cursor_serial, NULL, 0, 0);
+        sd->cursor_deadline = INT64_MAX;
+    }
+}
+
 static void seat_destroy(struct seat_data *sd)
 {
     wl_list_remove(&sd->node);
@@ -466,3 +508,34 @@ void seat_destroy_all(struct wl_list *list)
     while (!wl_list_empty(list))
         seat_destroy(container_of(list->next, struct seat_data, node));
 }
+
+int seat_next_timeout(const struct wl_list *list)
+{
+    struct seat_data *sd;
+    mtime_t deadline = INT64_MAX;
+
+    wl_list_for_each(sd, list, node)
+    {
+        mtime_t d = seat_next_deadline(sd);
+        if (deadline > d)
+            deadline = d;
+    }
+
+    if (deadline == INT64_MAX)
+        return -1;
+
+    mtime_t now = mdate();
+    if (now >= deadline)
+        return 0;
+
+    return (deadline - now) / 1000 + 1;
+}
+
+void seat_timeout(struct wl_list *list)
+{
+    struct seat_data *sd;
+    mtime_t now = mdate();
+
+    wl_list_for_each(sd, list, node)
+        seat_refresh(sd, now);
+}
diff --git a/modules/video_output/wayland/input.h b/modules/video_output/wayland/input.h
index 6c34141f6e..c7df35bab3 100644
--- a/modules/video_output/wayland/input.h
+++ b/modules/video_output/wayland/input.h
@@ -20,9 +20,16 @@
 
 struct vout_window_t;
 struct wl_registry;
+struct wl_surface;
 struct wl_list;
 
 int seat_create(struct vout_window_t *wnd, struct wl_registry *,
                 uint32_t name, uint32_t version, struct wl_list *list);
 int seat_destroy_one(struct wl_list *list, uint32_t name);
 void seat_destroy_all(struct wl_list *list);
+
+int seat_next_timeout(const struct wl_list *list);
+void seat_timeout(struct wl_list *list);
+
+struct wl_surface *window_get_cursor(vout_window_t *wnd, int32_t *hotspot_x,
+                                     int32_t *hotspot_y);
diff --git a/modules/video_output/wayland/xdg-shell.c b/modules/video_output/wayland/xdg-shell.c
index c6ddc92341..c9e133e1ee 100644
--- a/modules/video_output/wayland/xdg-shell.c
+++ b/modules/video_output/wayland/xdg-shell.c
@@ -124,15 +124,21 @@ static void *Thread(void *data)
 
     for (;;)
     {
+        int timeout;
+
         while (wl_display_prepare_read(display) != 0)
             wl_display_dispatch_pending(display);
 
         wl_display_flush(display);
+        timeout = seat_next_timeout(&sys->seats);
         vlc_restorecancel(canc);
 
-        while (poll(ufd, 1, -1) < 0);
+        int val = poll(ufd, 1, timeout);
 
         canc = vlc_savecancel();
+        if (val == 0)
+            seat_timeout(&sys->seats);
+
         wl_display_read_events(display);
         wl_display_dispatch_pending(display);
     }



More information about the vlc-commits mailing list