[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