From 314a7cadabcebc093aa46dadd01a508a27895a03 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Thu, 5 Oct 2017 16:19:23 +0200 Subject: [PATCH] - xserver-1.19.4 - Backport tablet support for Xwayland --- ...ys-install-vbe-and-int10-sdk-headers.patch | 8 +- ...et-correct-DRM-event-context-version.patch | 38 -- ...on-wayland-protocols-to-build-tablet.patch | 73 +++ ...-wp_tablet_manager-if-available-and-.patch | 166 ++++++ ...and-Listen-for-wp_tablet_seat-events.patch | 173 ++++++ 0004-xwayland-Handle-wp_tablet-events.patch | 211 ++++++++ 0005-xwayland-Handle-tablet_tool-events.patch | 374 +++++++++++++ ...le-button-events-after-motion-events.patch | 121 +++++ ...or-cursor-management-into-xwl_cursor.patch | 213 ++++++++ ...-cursor-on-tablet-tools-in-proximity.patch | 208 +++++++ 0009-xwayland-add-tablet-pad-support.patch | 511 ++++++++++++++++++ ...tionally-initialize-lists-in-init_ta.patch | 74 +++ ...-off-by-one-error-in-tablet-button-n.patch | 39 ++ ...ment-tablet_tool_wheel-for-scrolling.patch | 78 +++ sources | 2 +- xorg-x11-server.spec | 24 +- 16 files changed, 2266 insertions(+), 47 deletions(-) delete mode 100644 0001-modesetting-Set-correct-DRM-event-context-version.patch create mode 100644 0001-xwayland-Depend-on-wayland-protocols-to-build-tablet.patch create mode 100644 0002-xwayland-Bind-to-wp_tablet_manager-if-available-and-.patch create mode 100644 0003-xwayland-Listen-for-wp_tablet_seat-events.patch create mode 100644 0004-xwayland-Handle-wp_tablet-events.patch create mode 100644 0005-xwayland-Handle-tablet_tool-events.patch create mode 100644 0006-xwayland-handle-button-events-after-motion-events.patch create mode 100644 0007-xwayland-Refactor-cursor-management-into-xwl_cursor.patch create mode 100644 0008-xwayland-update-cursor-on-tablet-tools-in-proximity.patch create mode 100644 0009-xwayland-add-tablet-pad-support.patch create mode 100644 0010-xwayland-Unconditionally-initialize-lists-in-init_ta.patch create mode 100644 0011-xwayland-Correct-off-by-one-error-in-tablet-button-n.patch create mode 100644 0012-xwayland-Implement-tablet_tool_wheel-for-scrolling.patch diff --git a/0001-Always-install-vbe-and-int10-sdk-headers.patch b/0001-Always-install-vbe-and-int10-sdk-headers.patch index 7dd249c..fa7f836 100644 --- a/0001-Always-install-vbe-and-int10-sdk-headers.patch +++ b/0001-Always-install-vbe-and-int10-sdk-headers.patch @@ -1,4 +1,4 @@ -From fc306295751178802405e0faa3f2e4e40cd913f0 Mon Sep 17 00:00:00 2001 +From e96a83d9b1b5a52a41213c7a4840dc96b4f5b06f Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 15 Aug 2012 12:35:21 -0400 Subject: [PATCH] Always install vbe and int10 sdk headers @@ -9,7 +9,7 @@ Signed-off-by: Adam Jackson 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am -index 27f2cc6..f9a078f 100644 +index b876b79..a170b58 100644 --- a/hw/xfree86/Makefile.am +++ b/hw/xfree86/Makefile.am @@ -26,17 +26,9 @@ if VGAHW @@ -27,11 +27,11 @@ index 27f2cc6..f9a078f 100644 -SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \ +SUBDIRS = common ddc x86emu int10 os-support parser \ ramdac $(VGAHW_SUBDIR) loader modes $(DRI_SUBDIR) \ -- $(DRI2_SUBDIR) . $(VBE_SUBDIR) i2c dixmods \ +- $(DRI2_SUBDIR) . $(VBE_SUBDIR) i2c dixmods xkb \ + $(DRI2_SUBDIR) . vbe i2c dixmods \ fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man \ $(GLAMOR_EGL_SUBDIR) drivers -- -2.1.0 +2.13.6 diff --git a/0001-modesetting-Set-correct-DRM-event-context-version.patch b/0001-modesetting-Set-correct-DRM-event-context-version.patch deleted file mode 100644 index 84dd434..0000000 --- a/0001-modesetting-Set-correct-DRM-event-context-version.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0c8e6ed85810e96d84173a52d628863802a78d82 Mon Sep 17 00:00:00 2001 -From: Daniel Stone -Date: Fri, 7 Apr 2017 14:27:58 +0100 -Subject: [PATCH xserver] modesetting: Set correct DRM event context version - -DRM_EVENT_CONTEXT_VERSION is the latest context version supported by -whatever version of libdrm is present. modesetting was blindly asserting -it supported whatever version that may be, even if it actually didn't. - -With libdrm 2.4.78, setting a higher context version than 2 will attempt -to call the page_flip_handler2 vfunc if it was non-NULL, which being a -random chunk of stack memory, it might well have been. - -Set the version as 2, which should be bumped only with the appropriate -version checks. - -Reviewed-by: Adam Jackson -Signed-off-by: Daniel Stone ---- - hw/xfree86/drivers/modesetting/vblank.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/xfree86/drivers/modesetting/vblank.c b/hw/xfree86/drivers/modesetting/vblank.c -index 04a8952..8682f4d 100644 ---- a/hw/xfree86/drivers/modesetting/vblank.c -+++ b/hw/xfree86/drivers/modesetting/vblank.c -@@ -402,7 +402,7 @@ ms_vblank_screen_init(ScreenPtr screen) - modesettingEntPtr ms_ent = ms_ent_priv(scrn); - xorg_list_init(&ms_drm_queue); - -- ms->event_context.version = DRM_EVENT_CONTEXT_VERSION; -+ ms->event_context.version = 2; - ms->event_context.vblank_handler = ms_drm_handler; - ms->event_context.page_flip_handler = ms_drm_handler; - --- -2.9.3 - diff --git a/0001-xwayland-Depend-on-wayland-protocols-to-build-tablet.patch b/0001-xwayland-Depend-on-wayland-protocols-to-build-tablet.patch new file mode 100644 index 0000000..e16b405 --- /dev/null +++ b/0001-xwayland-Depend-on-wayland-protocols-to-build-tablet.patch @@ -0,0 +1,73 @@ +From 7f22271ca7ace43f6fa1168a2acea9af6f2d5896 Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Thu, 13 Oct 2016 10:39:46 -0700 +Subject: [PATCH xserver 01/12] xwayland: Depend on wayland-protocols to build + tablet protocol headers + +Signed-off-by: Jason Gerecke +Signed-off-by: Carlos Garnacho +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +Acked-by: Ping Cheng +(cherry picked from commit 89c841915ac4fba6d2a5ad0051c778f1a76ffbf3) +--- + configure.ac | 2 +- + hw/xwayland/Makefile.am | 9 ++++++++- + hw/xwayland/xwayland-input.c | 1 + + 3 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index e6c5b35de..d34e10538 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2503,7 +2503,7 @@ AM_CONDITIONAL(XFAKESERVER, [test "x$KDRIVE" = xyes && test "x$XFAKE" = xyes]) + + dnl Xwayland DDX + +-XWAYLANDMODULES="wayland-client >= 1.3.0 wayland-protocols >= 1.1 $LIBDRM epoxy" ++XWAYLANDMODULES="wayland-client >= 1.3.0 wayland-protocols >= 1.5 $LIBDRM epoxy" + if test "x$XF86VIDMODE" = xyes; then + XWAYLANDMODULES="$XWAYLANDMODULES $VIDMODEPROTO" + fi +diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am +index a3c9fce48..e376f09dd 100644 +--- a/hw/xwayland/Makefile.am ++++ b/hw/xwayland/Makefile.am +@@ -56,7 +56,9 @@ Xwayland_built_sources += \ + relative-pointer-unstable-v1-client-protocol.h \ + relative-pointer-unstable-v1-protocol.c \ + pointer-constraints-unstable-v1-client-protocol.h \ +- pointer-constraints-unstable-v1-protocol.c ++ pointer-constraints-unstable-v1-protocol.c \ ++ tablet-unstable-v2-client-protocol.h \ ++ tablet-unstable-v2-protocol.c + + nodist_Xwayland_SOURCES = $(Xwayland_built_sources) + CLEANFILES = $(Xwayland_built_sources) +@@ -79,6 +81,11 @@ pointer-constraints-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstab + pointer-constraints-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml + $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ + ++tablet-unstable-v2-protocol.c: $(WAYLAND_PROTOCOLS_DATADIR)/unstable/tablet/tablet-unstable-v2.xml ++ $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@ ++tablet-unstable-v2-client-protocol.h: $(WAYLAND_PROTOCOLS_DATADIR)/unstable/tablet/tablet-unstable-v2.xml ++ $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ ++ + %-protocol.c : %.xml + $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@ + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index f2564d5d3..8fdc875ea 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include "tablet-unstable-v2-client-protocol.h" + + /* Copied from mipointer.c */ + #define MIPOINTER(dev) \ +-- +2.13.5 + diff --git a/0002-xwayland-Bind-to-wp_tablet_manager-if-available-and-.patch b/0002-xwayland-Bind-to-wp_tablet_manager-if-available-and-.patch new file mode 100644 index 0000000..9e750cb --- /dev/null +++ b/0002-xwayland-Bind-to-wp_tablet_manager-if-available-and-.patch @@ -0,0 +1,166 @@ +From 8dcc03fb4a5db18fb52377ee578a2a673d691a1e Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Fri, 15 Jan 2016 17:29:37 -0800 +Subject: [PATCH xserver 02/12] xwayland: Bind to wp_tablet_manager if + available and get its seats + +If we're notified about the existence of the wp_tablet_manager interface, +we bind to it so that we can make use of any tablets that are (or later +become) available. For each seat that exists or comes into existance at +a later point, obtain the associated tablet_seat. + +Signed-off-by: Jason Gerecke +Signed-off-by: Carlos Garnacho +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +Acked-by: Ping Cheng +(cherry picked from commit 7d48b758a601ce0252ebd21297a7c42263adfaaf) +--- + hw/xwayland/xwayland-input.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ + hw/xwayland/xwayland.c | 2 ++ + hw/xwayland/xwayland.h | 4 +++ + 3 files changed, 65 insertions(+) + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index 8fdc875ea..1d2be978e 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -63,6 +63,12 @@ static void + xwl_seat_destroy_confined_pointer(struct xwl_seat *xwl_seat); + + static void ++init_tablet_manager_seat(struct xwl_screen *xwl_screen, ++ struct xwl_seat *xwl_seat); ++static void ++release_tablet_manager_seat(struct xwl_seat *xwl_seat); ++ ++static void + xwl_pointer_control(DeviceIntPtr device, PtrCtrl *ctrl) + { + /* Nothing to do, dix handles all settings */ +@@ -1147,6 +1153,9 @@ create_input_device(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version + + xwl_seat->cursor = wl_compositor_create_surface(xwl_screen->compositor); + wl_seat_add_listener(xwl_seat->seat, &seat_listener, xwl_seat); ++ ++ init_tablet_manager_seat(xwl_screen, xwl_seat); ++ + wl_array_init(&xwl_seat->keys); + + xorg_list_init(&xwl_seat->touches); +@@ -1170,6 +1179,8 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat) + free (p); + } + ++ release_tablet_manager_seat(xwl_seat); ++ + wl_seat_destroy(xwl_seat->seat); + wl_surface_destroy(xwl_seat->cursor); + if (xwl_seat->cursor_frame_cb) +@@ -1178,6 +1189,52 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat) + free(xwl_seat); + } + ++ ++static void ++init_tablet_manager_seat(struct xwl_screen *xwl_screen, ++ struct xwl_seat *xwl_seat) ++{ ++ if (!xwl_screen->tablet_manager) ++ return; ++ ++ xwl_seat->tablet_seat = ++ zwp_tablet_manager_v2_get_tablet_seat(xwl_screen->tablet_manager, ++ xwl_seat->seat); ++} ++ ++static void ++release_tablet_manager_seat(struct xwl_seat *xwl_seat) ++{ ++ if (xwl_seat->tablet_seat) { ++ zwp_tablet_seat_v2_destroy(xwl_seat->tablet_seat); ++ xwl_seat->tablet_seat = NULL; ++ } ++} ++ ++static void ++init_tablet_manager(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version) ++{ ++ struct xwl_seat *xwl_seat; ++ ++ xwl_screen->tablet_manager = wl_registry_bind(xwl_screen->registry, ++ id, ++ &zwp_tablet_manager_v2_interface, ++ min(version,1)); ++ ++ xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { ++ init_tablet_manager_seat(xwl_screen, xwl_seat); ++ } ++} ++ ++void ++xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen) ++{ ++ if (xwl_screen->tablet_manager) { ++ zwp_tablet_manager_v2_destroy(xwl_screen->tablet_manager); ++ xwl_screen->tablet_manager = NULL; ++ } ++} ++ + static void + init_relative_pointer_manager(struct xwl_screen *xwl_screen, + uint32_t id, uint32_t version) +@@ -1211,6 +1268,8 @@ input_handler(void *data, struct wl_registry *registry, uint32_t id, + init_relative_pointer_manager(xwl_screen, id, version); + } else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) { + init_pointer_constraints(xwl_screen, id, version); ++ } else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) { ++ init_tablet_manager(xwl_screen, id, version); + } + } + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index 939f3392c..fa7b81c7a 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -130,6 +130,8 @@ xwl_close_screen(ScreenPtr screen) + &xwl_screen->seat_list, link) + xwl_seat_destroy(xwl_seat); + ++ xwl_screen_release_tablet_manager(xwl_screen); ++ + RemoveNotifyFd(xwl_screen->wayland_fd); + + wl_display_disconnect(xwl_screen->display); +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index 5e5624be0..2752d731c 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -76,6 +76,7 @@ struct xwl_screen { + struct wl_registry *registry; + struct wl_registry *input_registry; + struct wl_compositor *compositor; ++ struct zwp_tablet_manager_v2 *tablet_manager; + struct wl_shm *shm; + struct wl_shell *shell; + struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; +@@ -137,6 +138,7 @@ struct xwl_seat { + struct zwp_relative_pointer_v1 *wp_relative_pointer; + struct wl_keyboard *wl_keyboard; + struct wl_touch *wl_touch; ++ struct zwp_tablet_seat_v2 *tablet_seat; + struct wl_array keys; + struct xwl_window *focus_window; + uint32_t id; +@@ -241,6 +243,8 @@ Bool xwl_screen_init_glamor(struct xwl_screen *xwl_screen, + uint32_t id, uint32_t version); + struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap); + ++void xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen); ++ + #ifdef XV + /* glamor Xv Adaptor */ + Bool xwl_glamor_xv_init(ScreenPtr pScreen); +-- +2.13.5 + diff --git a/0003-xwayland-Listen-for-wp_tablet_seat-events.patch b/0003-xwayland-Listen-for-wp_tablet_seat-events.patch new file mode 100644 index 0000000..308331f --- /dev/null +++ b/0003-xwayland-Listen-for-wp_tablet_seat-events.patch @@ -0,0 +1,173 @@ +From 243eadc7979e35756a4f0e349ee97bbbd3a268c3 Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Fri, 14 Oct 2016 14:50:18 -0700 +Subject: [PATCH xserver 03/12] xwayland: Listen for wp_tablet_seat events + +The wp_tablet_seat interface provides us with notifications as tablets, +tools, and pads are connected to the system. Add listener functions and +store references to the obtained devices. + +Signed-off-by: Jason Gerecke +Signed-off-by: Carlos Garnacho +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +Acked-by: Ping Cheng +(cherry picked from commit 47c4415912b5b16b115135be365beb370858df76) +--- + hw/xwayland/xwayland-input.c | 94 ++++++++++++++++++++++++++++++++++++++++++++ + hw/xwayland/xwayland.h | 22 +++++++++++ + 2 files changed, 116 insertions(+) + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index 1d2be978e..d5d12933c 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -1191,6 +1191,69 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat) + + + static void ++tablet_seat_handle_add_tablet(void *data, struct zwp_tablet_seat_v2 *tablet_seat, ++ struct zwp_tablet_v2 *tablet) ++{ ++ struct xwl_seat *xwl_seat = data; ++ struct xwl_tablet *xwl_tablet; ++ ++ xwl_tablet = calloc(sizeof *xwl_tablet, 1); ++ if (xwl_tablet == NULL) { ++ ErrorF("%s ENOMEM\n", __func__); ++ return; ++ } ++ ++ xwl_tablet->tablet = tablet; ++ xwl_tablet->seat = xwl_seat; ++ ++ xorg_list_add(&xwl_tablet->link, &xwl_seat->tablets); ++} ++ ++static void ++tablet_seat_handle_add_tool(void *data, struct zwp_tablet_seat_v2 *tablet_seat, ++ struct zwp_tablet_tool_v2 *tool) ++{ ++ struct xwl_seat *xwl_seat = data; ++ struct xwl_tablet_tool *xwl_tablet_tool; ++ ++ xwl_tablet_tool = calloc(sizeof *xwl_tablet_tool, 1); ++ if (xwl_tablet_tool == NULL) { ++ ErrorF("%s ENOMEM\n", __func__); ++ return; ++ } ++ ++ xwl_tablet_tool->tool = tool; ++ xwl_tablet_tool->seat = xwl_seat; ++ ++ xorg_list_add(&xwl_tablet_tool->link, &xwl_seat->tablet_tools); ++} ++ ++static void ++tablet_seat_handle_add_pad(void *data, struct zwp_tablet_seat_v2 *tablet_seat, ++ struct zwp_tablet_pad_v2 *pad) ++{ ++ struct xwl_seat *xwl_seat = data; ++ struct xwl_tablet_pad *xwl_tablet_pad; ++ ++ xwl_tablet_pad = calloc(sizeof *xwl_tablet_pad, 1); ++ if (xwl_tablet_pad == NULL) { ++ ErrorF("%s ENOMEM\n", __func__); ++ return; ++ } ++ ++ xwl_tablet_pad->pad = pad; ++ xwl_tablet_pad->seat = xwl_seat; ++ ++ xorg_list_add(&xwl_tablet_pad->link, &xwl_seat->tablet_pads); ++} ++ ++static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { ++ tablet_seat_handle_add_tablet, ++ tablet_seat_handle_add_tool, ++ tablet_seat_handle_add_pad ++}; ++ ++static void + init_tablet_manager_seat(struct xwl_screen *xwl_screen, + struct xwl_seat *xwl_seat) + { +@@ -1200,11 +1263,42 @@ init_tablet_manager_seat(struct xwl_screen *xwl_screen, + xwl_seat->tablet_seat = + zwp_tablet_manager_v2_get_tablet_seat(xwl_screen->tablet_manager, + xwl_seat->seat); ++ ++ xorg_list_init(&xwl_seat->tablets); ++ xorg_list_init(&xwl_seat->tablet_tools); ++ xorg_list_init(&xwl_seat->tablet_pads); ++ ++ zwp_tablet_seat_v2_add_listener(xwl_seat->tablet_seat, &tablet_seat_listener, xwl_seat); + } + + static void + release_tablet_manager_seat(struct xwl_seat *xwl_seat) + { ++ struct xwl_tablet *xwl_tablet, *next_xwl_tablet; ++ struct xwl_tablet_tool *xwl_tablet_tool, *next_xwl_tablet_tool; ++ struct xwl_tablet_pad *xwl_tablet_pad, *next_xwl_tablet_pad; ++ ++ xorg_list_for_each_entry_safe(xwl_tablet_pad, next_xwl_tablet_pad, ++ &xwl_seat->tablet_pads, link) { ++ xorg_list_del(&xwl_tablet_pad->link); ++ zwp_tablet_pad_v2_destroy(xwl_tablet_pad->pad); ++ free(xwl_tablet_pad); ++ } ++ ++ xorg_list_for_each_entry_safe(xwl_tablet_tool, next_xwl_tablet_tool, ++ &xwl_seat->tablet_tools, link) { ++ xorg_list_del(&xwl_tablet_tool->link); ++ zwp_tablet_tool_v2_destroy(xwl_tablet_tool->tool); ++ free(xwl_tablet_tool); ++ } ++ ++ xorg_list_for_each_entry_safe(xwl_tablet, next_xwl_tablet, ++ &xwl_seat->tablets, link) { ++ xorg_list_del(&xwl_tablet->link); ++ zwp_tablet_v2_destroy(xwl_tablet->tablet); ++ free(xwl_tablet); ++ } ++ + if (xwl_seat->tablet_seat) { + zwp_tablet_seat_v2_destroy(xwl_seat->tablet_seat); + xwl_seat->tablet_seat = NULL; +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index 2752d731c..a7f30b3c8 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -174,6 +174,28 @@ struct xwl_seat { + double dx_unaccel; + double dy_unaccel; + } pending_pointer_event; ++ ++ struct xorg_list tablets; ++ struct xorg_list tablet_tools; ++ struct xorg_list tablet_pads; ++}; ++ ++struct xwl_tablet { ++ struct xorg_list link; ++ struct zwp_tablet_v2 *tablet; ++ struct xwl_seat *seat; ++}; ++ ++struct xwl_tablet_tool { ++ struct xorg_list link; ++ struct zwp_tablet_tool_v2 *tool; ++ struct xwl_seat *seat; ++}; ++ ++struct xwl_tablet_pad { ++ struct xorg_list link; ++ struct zwp_tablet_pad_v2 *pad; ++ struct xwl_seat *seat; + }; + + struct xwl_output { +-- +2.13.5 + diff --git a/0004-xwayland-Handle-wp_tablet-events.patch b/0004-xwayland-Handle-wp_tablet-events.patch new file mode 100644 index 0000000..4fb4453 --- /dev/null +++ b/0004-xwayland-Handle-wp_tablet-events.patch @@ -0,0 +1,211 @@ +From 591b08b3311c5217969a8ceb3ed58b58fabc4891 Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Fri, 15 Jan 2016 17:01:38 -0800 +Subject: [PATCH xserver 04/12] xwayland: Handle wp_tablet events + +Creates and maintains the canonical trio of X devices (stylus, eraser, +and cursor) to be shared by all connected tablets. A per-tablet trio +could be created instead, but there are very few benefits to such a +configuration since all tablets still ultimately share control of a +single master pointer. + +The three X devices are modeled after those created by xf86-input-wacom +but use a generic maximum X and Y that should be large enough to +accurately represent values from even the largest currently-available +tablets. + +Signed-off-by: Jason Gerecke +Signed-off-by: Carlos Garnacho +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +Acked-by: Ping Cheng +(cherry picked from commit 5812d1c28f4fb7b7de8b96a81415a21425561fd4) +--- + hw/xwayland/xwayland-input.c | 142 +++++++++++++++++++++++++++++++++++++++++++ + hw/xwayland/xwayland.h | 3 + + 2 files changed, 145 insertions(+) + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index d5d12933c..64655de5f 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -294,6 +294,75 @@ xwl_touch_proc(DeviceIntPtr device, int what) + #undef NTOUCHPOINTS + } + ++static int ++xwl_tablet_proc(DeviceIntPtr device, int what) ++{ ++#define NBUTTONS 9 ++#define NAXES 6 ++ Atom btn_labels[NBUTTONS] = { 0 }; ++ Atom axes_labels[NAXES] = { 0 }; ++ BYTE map[NBUTTONS + 1] = { 0 }; ++ int i; ++ ++ switch (what) { ++ case DEVICE_INIT: ++ device->public.on = FALSE; ++ ++ for (i = 1; i <= NBUTTONS; i++) ++ map[i] = i; ++ ++ axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); ++ axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); ++ axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE); ++ axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X); ++ axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y); ++ axes_labels[5] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_WHEEL); ++ ++ if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels, ++ GetMotionHistorySize(), Absolute)) ++ return BadValue; ++ ++ /* Valuators - match the xf86-input-wacom ranges */ ++ InitValuatorAxisStruct(device, 0, axes_labels[0], ++ 0, 262143, 10000, 0, 10000, Absolute); ++ InitValuatorAxisStruct(device, 1, axes_labels[1], ++ 0, 262143, 10000, 0, 10000, Absolute); ++ /* pressure */ ++ InitValuatorAxisStruct(device, 2, axes_labels[2], ++ 0, 65535, 1, 0, 1, Absolute); ++ /* tilt x */ ++ InitValuatorAxisStruct(device, 3, axes_labels[3], ++ -64, 63, 57, 0, 57, Absolute); ++ /* tilt y */ ++ InitValuatorAxisStruct(device, 4, axes_labels[4], ++ -64, 63, 57, 0, 57, Absolute); ++ /* abs wheel (airbrush) or rotation (artpen) */ ++ InitValuatorAxisStruct(device, 5, axes_labels[5], ++ -900, 899, 1, 0, 1, Absolute); ++ ++ if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control)) ++ return BadValue; ++ ++ if (!InitButtonClassDeviceStruct(device, NBUTTONS, btn_labels, map)) ++ return BadValue; ++ ++ return Success; ++ ++ case DEVICE_ON: ++ device->public.on = TRUE; ++ return Success; ++ ++ case DEVICE_OFF: ++ case DEVICE_CLOSE: ++ device->public.on = FALSE; ++ return Success; ++ } ++ ++ return BadMatch; ++#undef NAXES ++#undef NBUTTONS ++} ++ + static void + pointer_handle_enter(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface, +@@ -1189,6 +1258,77 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat) + free(xwl_seat); + } + ++static void ++tablet_handle_name(void *data, struct zwp_tablet_v2 *tablet, const char *name) ++{ ++} ++ ++static void ++tablet_handle_id(void *data, struct zwp_tablet_v2 *tablet, uint32_t vid, ++ uint32_t pid) ++{ ++} ++ ++static void ++tablet_handle_path(void *data, struct zwp_tablet_v2 *tablet, const char *path) ++{ ++} ++ ++static void ++tablet_handle_done(void *data, struct zwp_tablet_v2 *tablet) ++{ ++ struct xwl_tablet *xwl_tablet = data; ++ struct xwl_seat *xwl_seat = xwl_tablet->seat; ++ ++ if (xwl_seat->stylus == NULL) { ++ xwl_seat->stylus = add_device(xwl_seat, "xwayland-stylus", xwl_tablet_proc); ++ ActivateDevice(xwl_seat->stylus, TRUE); ++ } ++ EnableDevice(xwl_seat->stylus, TRUE); ++ ++ if (xwl_seat->eraser == NULL) { ++ xwl_seat->eraser = add_device(xwl_seat, "xwayland-eraser", xwl_tablet_proc); ++ ActivateDevice(xwl_seat->eraser, TRUE); ++ } ++ EnableDevice(xwl_seat->eraser, TRUE); ++ ++ if (xwl_seat->puck == NULL) { ++ xwl_seat->puck = add_device(xwl_seat, "xwayland-cursor", xwl_tablet_proc); ++ ActivateDevice(xwl_seat->puck, TRUE); ++ } ++ EnableDevice(xwl_seat->puck, TRUE); ++} ++ ++static void ++tablet_handle_removed(void *data, struct zwp_tablet_v2 *tablet) ++{ ++ struct xwl_tablet *xwl_tablet = data; ++ struct xwl_seat *xwl_seat = xwl_tablet->seat; ++ ++ xorg_list_del(&xwl_tablet->link); ++ ++ /* The tablet is merely disabled, not removed. The next tablet ++ will re-use the same X devices */ ++ if (xorg_list_is_empty(&xwl_seat->tablets)) { ++ if (xwl_seat->stylus) ++ DisableDevice(xwl_seat->stylus, TRUE); ++ if (xwl_seat->eraser) ++ DisableDevice(xwl_seat->eraser, TRUE); ++ if (xwl_seat->puck) ++ DisableDevice(xwl_seat->puck, TRUE); ++ } ++ ++ zwp_tablet_v2_destroy(tablet); ++ free(xwl_tablet); ++} ++ ++static const struct zwp_tablet_v2_listener tablet_listener = { ++ tablet_handle_name, ++ tablet_handle_id, ++ tablet_handle_path, ++ tablet_handle_done, ++ tablet_handle_removed ++}; + + static void + tablet_seat_handle_add_tablet(void *data, struct zwp_tablet_seat_v2 *tablet_seat, +@@ -1207,6 +1347,8 @@ tablet_seat_handle_add_tablet(void *data, struct zwp_tablet_seat_v2 *tablet_seat + xwl_tablet->seat = xwl_seat; + + xorg_list_add(&xwl_tablet->link, &xwl_seat->tablets); ++ ++ zwp_tablet_v2_add_listener(tablet, &tablet_listener, xwl_tablet); + } + + static void +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index a7f30b3c8..e7e62882b 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -132,6 +132,9 @@ struct xwl_seat { + DeviceIntPtr relative_pointer; + DeviceIntPtr keyboard; + DeviceIntPtr touch; ++ DeviceIntPtr stylus; ++ DeviceIntPtr eraser; ++ DeviceIntPtr puck; + struct xwl_screen *xwl_screen; + struct wl_seat *seat; + struct wl_pointer *wl_pointer; +-- +2.13.5 + diff --git a/0005-xwayland-Handle-tablet_tool-events.patch b/0005-xwayland-Handle-tablet_tool-events.patch new file mode 100644 index 0000000..5ebc618 --- /dev/null +++ b/0005-xwayland-Handle-tablet_tool-events.patch @@ -0,0 +1,374 @@ +From 4354336014ca0c29270a6cdf83e9f9e5fe16080e Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Fri, 14 Oct 2016 14:31:46 -0700 +Subject: [PATCH xserver 05/12] xwayland: Handle tablet_tool events + +Translates Wayland tablet events into corresponding X11 tablet events. As +with the prior commit, these events are modeled after those created by the +xf86-input-wacom driver to maximize compatibility with existing applications. + +Signed-off-by: Jason Gerecke +Signed-off-by: Carlos Garnacho +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +Acked-by: Ping Cheng +(cherry picked from commit 8a1defcc634daddbb3570519d69ec5c9e39a8b56) +--- + hw/xwayland/xwayland-input.c | 313 +++++++++++++++++++++++++++++++++++++++++++ + hw/xwayland/xwayland.h | 9 ++ + 2 files changed, 322 insertions(+) + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index 64655de5f..142862f7e 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -1331,6 +1331,317 @@ static const struct zwp_tablet_v2_listener tablet_listener = { + }; + + static void ++tablet_tool_receive_type(void *data, struct zwp_tablet_tool_v2 *tool, ++ uint32_t type) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ ++ switch (type) { ++ case ZWP_TABLET_TOOL_V2_TYPE_ERASER: ++ xwl_tablet_tool->xdevice = xwl_seat->eraser; ++ break; ++ case ZWP_TABLET_TOOL_V2_TYPE_MOUSE: ++ case ZWP_TABLET_TOOL_V2_TYPE_LENS: ++ xwl_tablet_tool->xdevice = xwl_seat->puck; ++ break; ++ default: ++ xwl_tablet_tool->xdevice = xwl_seat->stylus; ++ break; ++ } ++} ++ ++static void ++tablet_tool_receive_hardware_serial(void *data, struct zwp_tablet_tool_v2 *tool, ++ uint32_t hi, uint32_t low) ++{ ++} ++ ++static void ++tablet_tool_receive_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *tool, ++ uint32_t hi, uint32_t low) ++{ ++} ++ ++static void ++tablet_tool_receive_capability(void *data, struct zwp_tablet_tool_v2 *tool, ++ uint32_t capability) ++{ ++} ++ ++static void ++tablet_tool_receive_done(void *data, struct zwp_tablet_tool_v2 *tool) ++{ ++} ++ ++static void ++tablet_tool_receive_removed(void *data, struct zwp_tablet_tool_v2 *tool) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ ++ xorg_list_del(&xwl_tablet_tool->link); ++ zwp_tablet_tool_v2_destroy(tool); ++ free(xwl_tablet_tool); ++} ++ ++static void ++tablet_tool_proximity_in(void *data, struct zwp_tablet_tool_v2 *tool, ++ uint32_t serial, struct zwp_tablet_v2 *tablet, ++ struct wl_surface *wl_surface) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ ++ /* There's a race here where if we create and then immediately ++ * destroy a surface, we might end up in a state where the Wayland ++ * compositor sends us an event for a surface that doesn't exist. ++ * ++ * Don't process enter events in this case. ++ * ++ * see pointer_handle_enter() ++ */ ++ if (wl_surface == NULL) ++ return; ++ ++ xwl_seat->focus_window = wl_surface_get_user_data(wl_surface); ++} ++ ++static void ++tablet_tool_proximity_out(void *data, struct zwp_tablet_tool_v2 *tool) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ ++ xwl_seat->focus_window = NULL; ++ ++ xwl_tablet_tool->pressure = 0; ++ xwl_tablet_tool->tilt_x = 0; ++ xwl_tablet_tool->tilt_y = 0; ++ xwl_tablet_tool->rotation = 0; ++ xwl_tablet_tool->slider = 0; ++} ++ ++static void ++tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ ValuatorMask mask; ++ ++ xwl_seat->xwl_screen->serial = serial; ++ ++ valuator_mask_zero(&mask); ++ QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonPress, 1, 0, &mask); ++} ++ ++static void ++tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *tool) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ ValuatorMask mask; ++ ++ valuator_mask_zero(&mask); ++ QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonRelease, 1, 0, &mask); ++} ++ ++static void ++tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool, ++ wl_fixed_t x, wl_fixed_t y) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ int32_t dx, dy; ++ int sx = wl_fixed_to_int(x); ++ int sy = wl_fixed_to_int(y); ++ ++ if (!xwl_seat->focus_window) ++ return; ++ ++ dx = xwl_seat->focus_window->window->drawable.x; ++ dy = xwl_seat->focus_window->window->drawable.y; ++ ++ xwl_tablet_tool->x = dx + sx; ++ xwl_tablet_tool->y = dy + sy; ++} ++ ++static void ++tablet_tool_pressure(void *data, struct zwp_tablet_tool_v2 *tool, ++ uint32_t pressure) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ ++ if (!xwl_seat->focus_window) ++ return; ++ ++ /* normalized to 65535 already */ ++ xwl_tablet_tool->pressure = pressure; ++} ++ ++static void ++tablet_tool_distance(void *data, struct zwp_tablet_tool_v2 *tool, ++ uint32_t distance_raw) ++{ ++} ++ ++static void ++tablet_tool_tilt(void *data, struct zwp_tablet_tool_v2 *tool, ++ wl_fixed_t tilt_x, wl_fixed_t tilt_y) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ ++ if (!xwl_seat->focus_window) ++ return; ++ ++ xwl_tablet_tool->tilt_x = wl_fixed_to_double(tilt_x); ++ xwl_tablet_tool->tilt_y = wl_fixed_to_double(tilt_y); ++} ++ ++static void ++tablet_tool_rotation(void *data, struct zwp_tablet_tool_v2 *tool, ++ wl_fixed_t angle) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ double rotation = wl_fixed_to_double(angle); ++ ++ if (!xwl_seat->focus_window) ++ return; ++ ++ /* change origin (buttons facing right [libinput +90 degrees]) and ++ * scaling (5 points per degree) to match wacom driver behavior ++ */ ++ rotation = remainderf(rotation + 90.0f, 360.0f); ++ rotation *= 5.0f; ++ xwl_tablet_tool->rotation = rotation; ++} ++ ++static void ++tablet_tool_slider(void *data, struct zwp_tablet_tool_v2 *tool, ++ int32_t position_raw) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ float position = position_raw / 65535.0; ++ ++ if (!xwl_seat->focus_window) ++ return; ++ ++ xwl_tablet_tool->slider = (position * 1799.0f) - 900.0f; ++} ++ ++static void ++tablet_tool_wheel(void *data, struct zwp_tablet_tool_v2 *tool, ++ wl_fixed_t degrees, int32_t clicks) ++{ ++} ++ ++static void ++tablet_tool_button_state(void *data, struct zwp_tablet_tool_v2 *tool, ++ uint32_t serial, uint32_t button, uint32_t state) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ int xbtn = 0; ++ ValuatorMask mask; ++ ++ /* BTN_0 .. BTN_9 */ ++ if (button >= 0x100 && button <= 0x109) { ++ xbtn = button - 0x100 + 1; ++ } ++ /* BTN_A .. BTN_Z */ ++ else if (button >= 0x130 && button <= 0x135) { ++ xbtn = button - 0x130 + 10; ++ } ++ /* BTN_BASE .. BTN_BASE6 */ ++ else if (button >= 0x126 && button <= 0x12b) { ++ xbtn = button - 0x126 + 16; ++ } ++ else { ++ switch (button) { ++ case 0x110: /* BTN_LEFT */ ++ case 0x14a: /* BTN_TOUCH */ ++ xbtn = 1; ++ break; ++ ++ case 0x112: /* BTN_MIDDLE */ ++ case 0x14b: /* BTN_STYLUS */ ++ xbtn = 2; ++ break; ++ ++ case 0x111: /* BTN_RIGHT */ ++ case 0x14c: /* BTN_STYLUS2 */ ++ xbtn = 3; ++ break; ++ ++ case 0x113: /* BTN_SIDE */ ++ case 0x116: /* BTN_BACK */ ++ xbtn = 8; ++ break; ++ ++ case 0x114: /* BTN_EXTRA */ ++ case 0x115: /* BTN_FORWARD */ ++ xbtn = 9; ++ break; ++ } ++ } ++ ++ if (!xbtn) { ++ ErrorF("unknown tablet button number %d\n", button); ++ return; ++ } ++ ++ xwl_seat->xwl_screen->serial = serial; ++ ++ valuator_mask_zero(&mask); ++ QueuePointerEvents(xwl_tablet_tool->xdevice, ++ state ? ButtonPress : ButtonRelease, xbtn, 0, &mask); ++} ++ ++static void ++tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ ValuatorMask mask; ++ ++ valuator_mask_zero(&mask); ++ valuator_mask_set(&mask, 0, xwl_tablet_tool->x); ++ valuator_mask_set(&mask, 1, xwl_tablet_tool->y); ++ valuator_mask_set(&mask, 2, xwl_tablet_tool->pressure); ++ valuator_mask_set(&mask, 3, xwl_tablet_tool->tilt_x); ++ valuator_mask_set(&mask, 4, xwl_tablet_tool->tilt_y); ++ valuator_mask_set(&mask, 5, xwl_tablet_tool->rotation + xwl_tablet_tool->slider); ++ ++ /* FIXME: Store button mask in xwl_tablet_tool and send events *HERE* if ++ changed */ ++ QueuePointerEvents(xwl_tablet_tool->xdevice, MotionNotify, 0, ++ POINTER_ABSOLUTE | POINTER_SCREEN, &mask); ++} ++ ++static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = { ++ tablet_tool_receive_type, ++ tablet_tool_receive_hardware_serial, ++ tablet_tool_receive_hardware_id_wacom, ++ tablet_tool_receive_capability, ++ tablet_tool_receive_done, ++ tablet_tool_receive_removed, ++ tablet_tool_proximity_in, ++ tablet_tool_proximity_out, ++ tablet_tool_down, ++ tablet_tool_up, ++ tablet_tool_motion, ++ tablet_tool_pressure, ++ tablet_tool_distance, ++ tablet_tool_tilt, ++ tablet_tool_rotation, ++ tablet_tool_slider, ++ tablet_tool_wheel, ++ tablet_tool_button_state, ++ tablet_tool_frame ++}; ++ ++static void + tablet_seat_handle_add_tablet(void *data, struct zwp_tablet_seat_v2 *tablet_seat, + struct zwp_tablet_v2 *tablet) + { +@@ -1368,6 +1679,8 @@ tablet_seat_handle_add_tool(void *data, struct zwp_tablet_seat_v2 *tablet_seat, + xwl_tablet_tool->seat = xwl_seat; + + xorg_list_add(&xwl_tablet_tool->link, &xwl_seat->tablet_tools); ++ ++ zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, xwl_tablet_tool); + } + + static void +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index e7e62882b..fb9ac4804 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -193,6 +193,15 @@ struct xwl_tablet_tool { + struct xorg_list link; + struct zwp_tablet_tool_v2 *tool; + struct xwl_seat *seat; ++ ++ DeviceIntPtr xdevice; ++ uint32_t x; ++ uint32_t y; ++ uint32_t pressure; ++ float tilt_x; ++ float tilt_y; ++ float rotation; ++ float slider; + }; + + struct xwl_tablet_pad { +-- +2.13.5 + diff --git a/0006-xwayland-handle-button-events-after-motion-events.patch b/0006-xwayland-handle-button-events-after-motion-events.patch new file mode 100644 index 0000000..97b0c48 --- /dev/null +++ b/0006-xwayland-handle-button-events-after-motion-events.patch @@ -0,0 +1,121 @@ +From 317ce1201a2ec848f9066294ea544b756f735385 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 7 Feb 2017 12:23:46 +1000 +Subject: [PATCH xserver 06/12] xwayland: handle button events after motion + events + +Make sure the button events are sent after the motion events into the new +position. + +Signed-off-by: Peter Hutterer +Acked-by: Ping Cheng +(cherry picked from commit 773b04748d0c839bc8b12e33f74bb8d11c447f5b) +--- + hw/xwayland/xwayland-input.c | 44 +++++++++++++++++++++++++++++++++++++------- + hw/xwayland/xwayland.h | 3 +++ + 2 files changed, 40 insertions(+), 7 deletions(-) + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index 142862f7e..50da10839 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include "tablet-unstable-v2-client-protocol.h" + + /* Copied from mipointer.c */ +@@ -1543,8 +1544,8 @@ tablet_tool_button_state(void *data, struct zwp_tablet_tool_v2 *tool, + { + struct xwl_tablet_tool *xwl_tablet_tool = data; + struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ uint32_t *mask = &xwl_tablet_tool->buttons_now; + int xbtn = 0; +- ValuatorMask mask; + + /* BTN_0 .. BTN_9 */ + if (button >= 0x100 && button <= 0x109) { +@@ -1592,11 +1593,14 @@ tablet_tool_button_state(void *data, struct zwp_tablet_tool_v2 *tool, + return; + } + +- xwl_seat->xwl_screen->serial = serial; ++ BUG_RETURN(xbtn >= 8 * sizeof(*mask)); + +- valuator_mask_zero(&mask); +- QueuePointerEvents(xwl_tablet_tool->xdevice, +- state ? ButtonPress : ButtonRelease, xbtn, 0, &mask); ++ if (state) ++ SetBit(mask, xbtn); ++ else ++ ClearBit(mask, xbtn); ++ ++ xwl_seat->xwl_screen->serial = serial; + } + + static void +@@ -1604,6 +1608,8 @@ tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time) + { + struct xwl_tablet_tool *xwl_tablet_tool = data; + ValuatorMask mask; ++ uint32_t released, pressed, diff; ++ int button; + + valuator_mask_zero(&mask); + valuator_mask_set(&mask, 0, xwl_tablet_tool->x); +@@ -1613,10 +1619,34 @@ tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time) + valuator_mask_set(&mask, 4, xwl_tablet_tool->tilt_y); + valuator_mask_set(&mask, 5, xwl_tablet_tool->rotation + xwl_tablet_tool->slider); + +- /* FIXME: Store button mask in xwl_tablet_tool and send events *HERE* if +- changed */ + QueuePointerEvents(xwl_tablet_tool->xdevice, MotionNotify, 0, + POINTER_ABSOLUTE | POINTER_SCREEN, &mask); ++ ++ valuator_mask_zero(&mask); ++ ++ diff = xwl_tablet_tool->buttons_prev ^ xwl_tablet_tool->buttons_now; ++ released = diff & ~xwl_tablet_tool->buttons_now; ++ pressed = diff & xwl_tablet_tool->buttons_now; ++ ++ button = 1; ++ while (released) { ++ if (released & 0x1) ++ QueuePointerEvents(xwl_tablet_tool->xdevice, ++ ButtonRelease, button, 0, &mask); ++ button++; ++ released >>= 1; ++ } ++ ++ button = 1; ++ while (pressed) { ++ if (pressed & 0x1) ++ QueuePointerEvents(xwl_tablet_tool->xdevice, ++ ButtonPress, button, 0, &mask); ++ button++; ++ pressed >>= 1; ++ } ++ ++ xwl_tablet_tool->buttons_prev = xwl_tablet_tool->buttons_now; + } + + static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = { +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index fb9ac4804..bb119dad7 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -202,6 +202,9 @@ struct xwl_tablet_tool { + float tilt_y; + float rotation; + float slider; ++ ++ uint32_t buttons_now, ++ buttons_prev; + }; + + struct xwl_tablet_pad { +-- +2.13.5 + diff --git a/0007-xwayland-Refactor-cursor-management-into-xwl_cursor.patch b/0007-xwayland-Refactor-cursor-management-into-xwl_cursor.patch new file mode 100644 index 0000000..c3bcd11 --- /dev/null +++ b/0007-xwayland-Refactor-cursor-management-into-xwl_cursor.patch @@ -0,0 +1,213 @@ +From 94a88b752a9373656bb0f62897513c8f5e552127 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 4 Nov 2016 19:36:10 +0100 +Subject: [PATCH xserver 07/12] xwayland: Refactor cursor management into + xwl_cursor + +This struct takes away the cursor info in xwl_seat, and has +an update function so we can share the frame handling code +across several xwl_cursors. + +Signed-off-by: Carlos Garnacho +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +Acked-by: Ping Cheng +(cherry picked from commit 6d1ad39fe6c18220dd39b0653fd1e4145140e2dc) +--- + hw/xwayland/xwayland-cursor.c | 39 ++++++++++++++++++++------------------- + hw/xwayland/xwayland-input.c | 38 +++++++++++++++++++++++++++++++------- + hw/xwayland/xwayland.h | 11 ++++++++--- + 3 files changed, 59 insertions(+), 29 deletions(-) + +diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c +index f334f1ca5..fdae3ce85 100644 +--- a/hw/xwayland/xwayland-cursor.c ++++ b/hw/xwayland/xwayland-cursor.c +@@ -96,11 +96,11 @@ xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) + } + + static void +-clear_cursor_frame_callback(struct xwl_seat *xwl_seat) ++clear_cursor_frame_callback(struct xwl_cursor *xwl_cursor) + { +- if (xwl_seat->cursor_frame_cb) { +- wl_callback_destroy (xwl_seat->cursor_frame_cb); +- xwl_seat->cursor_frame_cb = NULL; ++ if (xwl_cursor->frame_cb) { ++ wl_callback_destroy (xwl_cursor->frame_cb); ++ xwl_cursor->frame_cb = NULL; + } + } + +@@ -109,12 +109,12 @@ frame_callback(void *data, + struct wl_callback *callback, + uint32_t time) + { +- struct xwl_seat *xwl_seat = data; ++ struct xwl_cursor *xwl_cursor = data; + +- clear_cursor_frame_callback(xwl_seat); +- if (xwl_seat->cursor_needs_update) { +- xwl_seat->cursor_needs_update = FALSE; +- xwl_seat_set_cursor(xwl_seat); ++ clear_cursor_frame_callback(xwl_cursor); ++ if (xwl_cursor->needs_update) { ++ xwl_cursor->needs_update = FALSE; ++ xwl_cursor->update_proc(xwl_cursor); + } + } + +@@ -125,6 +125,7 @@ static const struct wl_callback_listener frame_listener = { + void + xwl_seat_set_cursor(struct xwl_seat *xwl_seat) + { ++ struct xwl_cursor *xwl_cursor = &xwl_seat->cursor; + PixmapPtr pixmap; + CursorPtr cursor; + int stride; +@@ -135,13 +136,13 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) + if (!xwl_seat->x_cursor) { + wl_pointer_set_cursor(xwl_seat->wl_pointer, + xwl_seat->pointer_enter_serial, NULL, 0, 0); +- clear_cursor_frame_callback(xwl_seat); +- xwl_seat->cursor_needs_update = FALSE; ++ clear_cursor_frame_callback(xwl_cursor); ++ xwl_cursor->needs_update = FALSE; + return; + } + +- if (xwl_seat->cursor_frame_cb) { +- xwl_seat->cursor_needs_update = TRUE; ++ if (xwl_cursor->frame_cb) { ++ xwl_cursor->needs_update = TRUE; + return; + } + +@@ -159,19 +160,19 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) + + wl_pointer_set_cursor(xwl_seat->wl_pointer, + xwl_seat->pointer_enter_serial, +- xwl_seat->cursor, ++ xwl_cursor->surface, + xwl_seat->x_cursor->bits->xhot, + xwl_seat->x_cursor->bits->yhot); +- wl_surface_attach(xwl_seat->cursor, ++ wl_surface_attach(xwl_cursor->surface, + xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0); +- wl_surface_damage(xwl_seat->cursor, 0, 0, ++ wl_surface_damage(xwl_cursor->surface, 0, 0, + xwl_seat->x_cursor->bits->width, + xwl_seat->x_cursor->bits->height); + +- xwl_seat->cursor_frame_cb = wl_surface_frame(xwl_seat->cursor); +- wl_callback_add_listener(xwl_seat->cursor_frame_cb, &frame_listener, xwl_seat); ++ xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface); ++ wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor); + +- wl_surface_commit(xwl_seat->cursor); ++ wl_surface_commit(xwl_cursor->surface); + } + + static void +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index 50da10839..bb520e891 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -424,9 +424,9 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer, + * of our surfaces might not have been shown. In that case we'll + * have a cursor surface frame callback pending which we need to + * clear so that we can continue submitting new cursor frames. */ +- if (xwl_seat->cursor_frame_cb) { +- wl_callback_destroy(xwl_seat->cursor_frame_cb); +- xwl_seat->cursor_frame_cb = NULL; ++ if (xwl_seat->cursor.frame_cb) { ++ wl_callback_destroy(xwl_seat->cursor.frame_cb); ++ xwl_seat->cursor.frame_cb = NULL; + xwl_seat_set_cursor(xwl_seat); + } + +@@ -1203,6 +1203,31 @@ static const struct wl_seat_listener seat_listener = { + }; + + static void ++xwl_cursor_init(struct xwl_cursor *xwl_cursor, struct xwl_screen *xwl_screen, ++ void (* update_proc)(struct xwl_cursor *)) ++{ ++ xwl_cursor->surface = wl_compositor_create_surface(xwl_screen->compositor); ++ xwl_cursor->update_proc = update_proc; ++ xwl_cursor->frame_cb = NULL; ++ xwl_cursor->needs_update = FALSE; ++} ++ ++static void ++xwl_cursor_release(struct xwl_cursor *xwl_cursor) ++{ ++ wl_surface_destroy(xwl_cursor->surface); ++ if (xwl_cursor->frame_cb) ++ wl_callback_destroy(xwl_cursor->frame_cb); ++} ++ ++static void ++xwl_seat_update_cursor(struct xwl_cursor *xwl_cursor) ++{ ++ struct xwl_seat *xwl_seat = wl_container_of(xwl_cursor, xwl_seat, cursor); ++ xwl_seat_set_cursor(xwl_seat); ++} ++ ++static void + create_input_device(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version) + { + struct xwl_seat *xwl_seat; +@@ -1221,7 +1246,8 @@ create_input_device(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version + &wl_seat_interface, min(version, 5)); + xwl_seat->id = id; + +- xwl_seat->cursor = wl_compositor_create_surface(xwl_screen->compositor); ++ xwl_cursor_init(&xwl_seat->cursor, xwl_seat->xwl_screen, ++ xwl_seat_update_cursor); + wl_seat_add_listener(xwl_seat->seat, &seat_listener, xwl_seat); + + init_tablet_manager_seat(xwl_screen, xwl_seat); +@@ -1252,9 +1278,7 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat) + release_tablet_manager_seat(xwl_seat); + + wl_seat_destroy(xwl_seat->seat); +- wl_surface_destroy(xwl_seat->cursor); +- if (xwl_seat->cursor_frame_cb) +- wl_callback_destroy(xwl_seat->cursor_frame_cb); ++ xwl_cursor_release(&xwl_seat->cursor); + wl_array_release(&xwl_seat->keys); + free(xwl_seat); + } +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index bb119dad7..bfa5f47c7 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -127,6 +127,13 @@ struct xwl_pointer_warp_emulator { + struct zwp_locked_pointer_v1 *locked_pointer; + }; + ++struct xwl_cursor { ++ void (* update_proc) (struct xwl_cursor *); ++ struct wl_surface *surface; ++ struct wl_callback *frame_cb; ++ Bool needs_update; ++}; ++ + struct xwl_seat { + DeviceIntPtr pointer; + DeviceIntPtr relative_pointer; +@@ -148,9 +155,7 @@ struct xwl_seat { + uint32_t pointer_enter_serial; + struct xorg_list link; + CursorPtr x_cursor; +- struct wl_surface *cursor; +- struct wl_callback *cursor_frame_cb; +- Bool cursor_needs_update; ++ struct xwl_cursor cursor; + WindowPtr last_xwindow; + + struct xorg_list touches; +-- +2.13.5 + diff --git a/0008-xwayland-update-cursor-on-tablet-tools-in-proximity.patch b/0008-xwayland-update-cursor-on-tablet-tools-in-proximity.patch new file mode 100644 index 0000000..fa5472c --- /dev/null +++ b/0008-xwayland-update-cursor-on-tablet-tools-in-proximity.patch @@ -0,0 +1,208 @@ +From 78a4493bc8e60da7b97342660dd1ff6de844e951 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 4 Nov 2016 19:58:04 +0100 +Subject: [PATCH xserver 08/12] xwayland: update cursor on tablet tools in + proximity + +Each xwl_tablet_tool gets a xwl_cursor, as on wayland each of those +will get an independent cursor that can be set through +zwp_tablet_tool.set_cursor. + +However, all tools (and the pointer) share conceptually the same VCP +on Xwayland, so have cursor changes trigger a xwl_cursor update on +every tool (and the pointer, again). Maybe Xwayland could keep track +of the most recent device and only update that cursor to get better +visual results, but this is simpler, and it's going to be odd +anyway... + +Signed-off-by: Carlos Garnacho +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +Acked-by: Ping Cheng +(cherry picked from commit f471b5b8eb451b442554517c7cb6f0aa90d218c4) +--- + hw/xwayland/xwayland-cursor.c | 56 +++++++++++++++++++++++++++++++++++++++++++ + hw/xwayland/xwayland-input.c | 17 +++++++++++++ + hw/xwayland/xwayland.h | 5 ++++ + 3 files changed, 78 insertions(+) + +diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c +index fdae3ce85..c95f4e830 100644 +--- a/hw/xwayland/xwayland-cursor.c ++++ b/hw/xwayland/xwayland-cursor.c +@@ -175,11 +175,62 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) + wl_surface_commit(xwl_cursor->surface); + } + ++void ++xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool) ++{ ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ struct xwl_cursor *xwl_cursor = &xwl_tablet_tool->cursor; ++ PixmapPtr pixmap; ++ CursorPtr cursor; ++ int stride; ++ ++ if (!xwl_seat->x_cursor) { ++ zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool, ++ xwl_tablet_tool->proximity_in_serial, ++ NULL, 0, 0); ++ return; ++ } ++ ++ if (xwl_cursor->frame_cb) { ++ xwl_cursor->needs_update = TRUE; ++ return; ++ } ++ ++ cursor = xwl_seat->x_cursor; ++ pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key); ++ if (!pixmap) ++ return; ++ ++ stride = cursor->bits->width * 4; ++ if (cursor->bits->argb) ++ memcpy(pixmap->devPrivate.ptr, ++ cursor->bits->argb, cursor->bits->height * stride); ++ else ++ expand_source_and_mask(cursor, pixmap->devPrivate.ptr); ++ ++ zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool, ++ xwl_tablet_tool->proximity_in_serial, ++ xwl_cursor->surface, ++ xwl_seat->x_cursor->bits->xhot, ++ xwl_seat->x_cursor->bits->yhot); ++ wl_surface_attach(xwl_cursor->surface, ++ xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0); ++ wl_surface_damage(xwl_cursor->surface, 0, 0, ++ xwl_seat->x_cursor->bits->width, ++ xwl_seat->x_cursor->bits->height); ++ ++ xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface); ++ wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor); ++ ++ wl_surface_commit(xwl_cursor->surface); ++} ++ + static void + xwl_set_cursor(DeviceIntPtr device, + ScreenPtr screen, CursorPtr cursor, int x, int y) + { + struct xwl_seat *xwl_seat; ++ struct xwl_tablet_tool *xwl_tablet_tool; + Bool cursor_visibility_changed; + + xwl_seat = device->public.devicePrivate; +@@ -194,6 +245,11 @@ xwl_set_cursor(DeviceIntPtr device, + xwl_seat_cursor_visibility_changed(xwl_seat); + + xwl_seat_set_cursor(xwl_seat); ++ ++ xorg_list_for_each_entry(xwl_tablet_tool, &xwl_seat->tablet_tools, link) { ++ if (xwl_tablet_tool->proximity_in_serial != 0) ++ xwl_tablet_tool_set_cursor(xwl_tablet_tool); ++ } + } + + static void +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index bb520e891..77cd42789 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -1405,6 +1405,7 @@ tablet_tool_receive_removed(void *data, struct zwp_tablet_tool_v2 *tool) + struct xwl_tablet_tool *xwl_tablet_tool = data; + + xorg_list_del(&xwl_tablet_tool->link); ++ xwl_cursor_release(&xwl_tablet_tool->cursor); + zwp_tablet_tool_v2_destroy(tool); + free(xwl_tablet_tool); + } +@@ -1428,7 +1429,10 @@ tablet_tool_proximity_in(void *data, struct zwp_tablet_tool_v2 *tool, + if (wl_surface == NULL) + return; + ++ xwl_tablet_tool->proximity_in_serial = serial; + xwl_seat->focus_window = wl_surface_get_user_data(wl_surface); ++ ++ xwl_tablet_tool_set_cursor(xwl_tablet_tool); + } + + static void +@@ -1437,6 +1441,7 @@ tablet_tool_proximity_out(void *data, struct zwp_tablet_tool_v2 *tool) + struct xwl_tablet_tool *xwl_tablet_tool = data; + struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; + ++ xwl_tablet_tool->proximity_in_serial = 0; + xwl_seat->focus_window = NULL; + + xwl_tablet_tool->pressure = 0; +@@ -1717,10 +1722,20 @@ tablet_seat_handle_add_tablet(void *data, struct zwp_tablet_seat_v2 *tablet_seat + } + + static void ++xwl_tablet_tool_update_cursor(struct xwl_cursor *xwl_cursor) ++{ ++ struct xwl_tablet_tool *xwl_tablet_tool = wl_container_of(xwl_cursor, ++ xwl_tablet_tool, ++ cursor); ++ xwl_tablet_tool_set_cursor(xwl_tablet_tool); ++} ++ ++static void + tablet_seat_handle_add_tool(void *data, struct zwp_tablet_seat_v2 *tablet_seat, + struct zwp_tablet_tool_v2 *tool) + { + struct xwl_seat *xwl_seat = data; ++ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; + struct xwl_tablet_tool *xwl_tablet_tool; + + xwl_tablet_tool = calloc(sizeof *xwl_tablet_tool, 1); +@@ -1731,6 +1746,8 @@ tablet_seat_handle_add_tool(void *data, struct zwp_tablet_seat_v2 *tablet_seat, + + xwl_tablet_tool->tool = tool; + xwl_tablet_tool->seat = xwl_seat; ++ xwl_cursor_init(&xwl_tablet_tool->cursor, xwl_screen, ++ xwl_tablet_tool_update_cursor); + + xorg_list_add(&xwl_tablet_tool->link, &xwl_seat->tablet_tools); + +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index bfa5f47c7..02a218c43 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -44,6 +44,7 @@ + + #include "relative-pointer-unstable-v1-client-protocol.h" + #include "pointer-constraints-unstable-v1-client-protocol.h" ++#include "tablet-unstable-v2-client-protocol.h" + + struct xwl_screen { + int width; +@@ -200,6 +201,7 @@ struct xwl_tablet_tool { + struct xwl_seat *seat; + + DeviceIntPtr xdevice; ++ uint32_t proximity_in_serial; + uint32_t x; + uint32_t y; + uint32_t pressure; +@@ -210,6 +212,8 @@ struct xwl_tablet_tool { + + uint32_t buttons_now, + buttons_prev; ++ ++ struct xwl_cursor cursor; + }; + + struct xwl_tablet_pad { +@@ -237,6 +241,7 @@ Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen); + + struct xwl_screen *xwl_screen_get(ScreenPtr screen); + ++void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool); + void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); + + void xwl_seat_destroy(struct xwl_seat *xwl_seat); +-- +2.13.5 + diff --git a/0009-xwayland-add-tablet-pad-support.patch b/0009-xwayland-add-tablet-pad-support.patch new file mode 100644 index 0000000..8158d92 --- /dev/null +++ b/0009-xwayland-add-tablet-pad-support.patch @@ -0,0 +1,511 @@ +From 6f79f4993d351a891a715e994ab9574542e64b35 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 7 Feb 2017 15:04:46 +1000 +Subject: [PATCH xserver 09/12] xwayland: add tablet pad support + +Hooked up a bit differently to the other tools. Those tools can be static for +all and be re-used. The wacom driver initializes the pad with the correct +number of buttons though and we can't do this until we have the pad done event. + +If the tablet is removed and we plug a different one in, we should initialize +that correctly, so unlike the other tools the pad is properly removed and +re-initialized on plug. + +Signed-off-by: Peter Hutterer +Acked-by: Ping Cheng +(cherry picked from commit 8475e6360ce31551d50fd63a26f7a44d1e8928f2) +--- + hw/xwayland/xwayland-input.c | 417 +++++++++++++++++++++++++++++++++++++++++++ + hw/xwayland/xwayland.h | 28 +++ + 2 files changed, 445 insertions(+) + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index 77cd42789..8011b965c 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -1341,6 +1341,7 @@ tablet_handle_removed(void *data, struct zwp_tablet_v2 *tablet) + DisableDevice(xwl_seat->eraser, TRUE); + if (xwl_seat->puck) + DisableDevice(xwl_seat->puck, TRUE); ++ /* pads are removed separately */ + } + + zwp_tablet_v2_destroy(tablet); +@@ -1701,6 +1702,418 @@ static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = { + }; + + static void ++tablet_pad_ring_destroy(struct xwl_tablet_pad_ring *ring) ++{ ++ zwp_tablet_pad_ring_v2_destroy(ring->ring); ++ xorg_list_del(&ring->link); ++ free(ring); ++} ++ ++static void ++tablet_pad_ring_source(void *data, ++ struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, ++ uint32_t source) ++{ ++} ++ ++static void ++tablet_pad_ring_angle(void *data, ++ struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, ++ wl_fixed_t degrees) ++{ ++ struct xwl_tablet_pad_ring *ring = data; ++ struct xwl_tablet_pad *pad = ring->group->pad; ++ double deg = wl_fixed_to_double(degrees); ++ ValuatorMask mask; ++ ++ valuator_mask_zero(&mask); ++ valuator_mask_set(&mask, 5 + ring->index, deg/360.0 * 71); ++ QueuePointerEvents(pad->xdevice, MotionNotify, 0, 0, &mask); ++} ++ ++static void ++tablet_pad_ring_stop(void *data, ++ struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2) ++{ ++} ++ ++static void ++tablet_pad_ring_frame(void *data, ++ struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, ++ uint32_t time) ++{ ++} ++ ++static const struct zwp_tablet_pad_ring_v2_listener tablet_pad_ring_listener = { ++ tablet_pad_ring_source, ++ tablet_pad_ring_angle, ++ tablet_pad_ring_stop, ++ tablet_pad_ring_frame, ++}; ++ ++ ++static void ++tablet_pad_strip_destroy(struct xwl_tablet_pad_strip *strip) ++{ ++ zwp_tablet_pad_strip_v2_destroy(strip->strip); ++ xorg_list_del(&strip->link); ++ free(strip); ++} ++ ++static void ++tablet_pad_strip_source(void *data, ++ struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, ++ uint32_t source) ++{ ++} ++ ++static void ++tablet_pad_strip_position(void *data, ++ struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, ++ uint32_t position) ++{ ++ struct xwl_tablet_pad_strip *strip = data; ++ struct xwl_tablet_pad *pad = strip->group->pad; ++ ValuatorMask mask; ++ ++ valuator_mask_zero(&mask); ++ valuator_mask_set(&mask, 3 + strip->index, position/65535.0 * 2048); ++ QueuePointerEvents(pad->xdevice, MotionNotify, 0, 0, &mask); ++} ++ ++static void ++tablet_pad_strip_stop(void *data, ++ struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2) ++{ ++} ++ ++static void ++tablet_pad_strip_frame(void *data, ++ struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, ++ uint32_t time) ++{ ++} ++ ++static const struct zwp_tablet_pad_strip_v2_listener tablet_pad_strip_listener = { ++ tablet_pad_strip_source, ++ tablet_pad_strip_position, ++ tablet_pad_strip_stop, ++ tablet_pad_strip_frame, ++}; ++ ++static void ++tablet_pad_group_destroy(struct xwl_tablet_pad_group *group) ++{ ++ struct xwl_tablet_pad_ring *r, *tr; ++ struct xwl_tablet_pad_strip *s, *ts; ++ ++ xorg_list_for_each_entry_safe(r, tr, ++ &group->pad_group_ring_list, ++ link) ++ tablet_pad_ring_destroy(r); ++ ++ xorg_list_for_each_entry_safe(s, ts, ++ &group->pad_group_strip_list, ++ link) ++ tablet_pad_strip_destroy(s); ++ ++ zwp_tablet_pad_group_v2_destroy(group->group); ++ xorg_list_del(&group->link); ++ free(group); ++} ++ ++static void ++tablet_pad_group_buttons(void *data, ++ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, ++ struct wl_array *buttons) ++{ ++ ++} ++ ++static void ++tablet_pad_group_ring(void *data, ++ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, ++ struct zwp_tablet_pad_ring_v2 *wp_ring) ++{ ++ static unsigned int ring_index = 0; ++ struct xwl_tablet_pad_group *group = data; ++ struct xwl_tablet_pad_ring *ring; ++ ++ ring = calloc(1, sizeof *ring); ++ if (ring == NULL) { ++ ErrorF("%s ENOMEM\n", __func__); ++ return; ++ } ++ ++ ring->index = ring_index++; ++ ring->group = group; ++ ring->ring = wp_ring; ++ ++ xorg_list_add(&ring->link, &group->pad_group_ring_list); ++ ++ zwp_tablet_pad_ring_v2_add_listener(wp_ring, &tablet_pad_ring_listener, ++ ring); ++} ++ ++static void ++tablet_pad_group_strip(void *data, ++ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, ++ struct zwp_tablet_pad_strip_v2 *wp_strip) ++{ ++ static unsigned int strip_index = 0; ++ struct xwl_tablet_pad_group *group = data; ++ struct xwl_tablet_pad_strip *strip; ++ ++ strip = calloc(1, sizeof *strip); ++ if (strip == NULL) { ++ ErrorF("%s ENOMEM\n", __func__); ++ return; ++ } ++ ++ strip->index = strip_index++; ++ strip->group = group; ++ strip->strip = wp_strip; ++ ++ xorg_list_add(&strip->link, &group->pad_group_strip_list); ++ ++ zwp_tablet_pad_strip_v2_add_listener(wp_strip, &tablet_pad_strip_listener, ++ strip); ++} ++ ++static void ++tablet_pad_group_modes(void *data, ++ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, ++ uint32_t modes) ++{ ++ ++} ++ ++static void ++tablet_pad_group_done(void *data, ++ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2) ++{ ++ ++} ++ ++static void ++tablet_pad_group_mode_switch(void *data, ++ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, ++ uint32_t time, ++ uint32_t serial, ++ uint32_t mode) ++{ ++ ++} ++ ++static struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = { ++ tablet_pad_group_buttons, ++ tablet_pad_group_ring, ++ tablet_pad_group_strip, ++ tablet_pad_group_modes, ++ tablet_pad_group_done, ++ tablet_pad_group_mode_switch, ++}; ++ ++static int ++xwl_tablet_pad_proc(DeviceIntPtr device, int what) ++{ ++ struct xwl_tablet_pad *pad = device->public.devicePrivate; ++ /* Axis layout mirrors that of xf86-input-wacom to have better ++ compatibility with existing clients */ ++#define NAXES 7 ++ Atom axes_labels[NAXES] = { 0 }; ++ BYTE map[MAX_BUTTONS + 1]; ++ int i = 0; ++ Atom btn_labels[MAX_BUTTONS] = { 0 }; /* btn labels are meaningless */ ++ int nbuttons; ++ ++ switch (what) { ++ case DEVICE_INIT: ++ device->public.on = FALSE; ++ ++ axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); ++ axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); ++ /* The others have no good mapping */ ++ ++ if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels, ++ GetMotionHistorySize(), Absolute)) ++ return BadValue; ++ ++ for (i = 1; i <= MAX_BUTTONS; i++) ++ map[i] = i; ++ ++ /* We need at least 7 buttons to allow scrolling */ ++ nbuttons = min(max(pad->nbuttons + 4, 7), MAX_BUTTONS); ++ ++ if (!InitButtonClassDeviceStruct(device, nbuttons, ++ btn_labels, map)) ++ return BadValue; ++ ++ /* Valuators */ ++ InitValuatorAxisStruct(device, 0, axes_labels[0], ++ 0, 100, 1, 0, 1, Absolute); ++ InitValuatorAxisStruct(device, 1, axes_labels[1], ++ 0, 100, 1, 0, 1, Absolute); ++ /* Pressure - unused, for backwards compat only */ ++ InitValuatorAxisStruct(device, 2, axes_labels[2], ++ 0, 2048, 1, 0, 1, Absolute); ++ /* strip x */ ++ InitValuatorAxisStruct(device, 3, axes_labels[3], ++ 0, 2048, 1, 0, 1, Absolute); ++ /* strip y */ ++ InitValuatorAxisStruct(device, 4, axes_labels[4], ++ 0, 2048, 1, 0, 1, Absolute); ++ /* ring */ ++ InitValuatorAxisStruct(device, 5, axes_labels[5], ++ 0, 71, 1, 0, 1, Absolute); ++ /* ring2 */ ++ InitValuatorAxisStruct(device, 6, axes_labels[6], ++ 0, 71, 1, 0, 1, Absolute); ++ ++ if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control)) ++ return BadValue; ++ ++ return Success; ++ ++ case DEVICE_ON: ++ device->public.on = TRUE; ++ return Success; ++ ++ case DEVICE_OFF: ++ case DEVICE_CLOSE: ++ device->public.on = FALSE; ++ return Success; ++ } ++ ++ return BadMatch; ++#undef NAXES ++} ++ ++static void ++tablet_pad_group(void *data, ++ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, ++ struct zwp_tablet_pad_group_v2 *pad_group) ++{ ++ struct xwl_tablet_pad *pad = data; ++ struct xwl_tablet_pad_group *group; ++ ++ group = calloc(1, sizeof *group); ++ if (pad == NULL) { ++ ErrorF("%s ENOMEM\n", __func__); ++ return; ++ } ++ ++ group->pad = pad; ++ group->group = pad_group; ++ xorg_list_init(&group->pad_group_ring_list); ++ xorg_list_init(&group->pad_group_strip_list); ++ ++ xorg_list_add(&group->link, &pad->pad_group_list); ++ ++ zwp_tablet_pad_group_v2_add_listener(pad_group, ++ &tablet_pad_group_listener, ++ group); ++} ++ ++static void ++tablet_pad_path(void *data, ++ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, ++ const char *path) ++{ ++ ++} ++ ++static void ++tablet_pad_buttons(void *data, ++ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, ++ uint32_t buttons) ++{ ++ struct xwl_tablet_pad *pad = data; ++ ++ pad->nbuttons = buttons; ++} ++ ++static void ++tablet_pad_done(void *data, ++ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) ++{ ++ struct xwl_tablet_pad *pad = data; ++ ++ pad->xdevice = add_device(pad->seat, "xwayland-pad", ++ xwl_tablet_pad_proc); ++ pad->xdevice->public.devicePrivate = pad; ++ ActivateDevice(pad->xdevice, TRUE); ++ EnableDevice(pad->xdevice, TRUE); ++} ++ ++static void ++tablet_pad_button(void *data, ++ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, ++ uint32_t time, ++ uint32_t button, ++ uint32_t state) ++{ ++ struct xwl_tablet_pad *pad = data; ++ ValuatorMask mask; ++ ++ button++; /* wayland index vs X's 1-offset */ ++ /* skip scroll wheel buttons 4-7 */ ++ button = button > 3 ? button + 4 : button; ++ ++ valuator_mask_zero(&mask); ++ QueuePointerEvents(pad->xdevice, ++ state ? ButtonPress : ButtonRelease, button, 0, &mask); ++} ++ ++static void ++tablet_pad_enter(void *data, ++ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, ++ uint32_t serial, ++ struct zwp_tablet_v2 *tablet, ++ struct wl_surface *surface) ++{ ++ /* pairs the pad with the tablet but also to set the focus. We ++ * don't care about the pairing and always use X's focus */ ++} ++ ++static void ++tablet_pad_leave(void *data, ++ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, ++ uint32_t serial, ++ struct wl_surface *surface) ++{ ++ /* pairs the pad with the tablet but also to set the focus. We ++ * don't care about the pairing and always use X's focus */ ++} ++ ++static void ++tablet_pad_removed(void *data, ++ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) ++{ ++ struct xwl_tablet_pad *pad = data; ++ struct xwl_tablet_pad_group *g, *tg; ++ ++ xorg_list_for_each_entry_safe(g, tg, &pad->pad_group_list, link) ++ tablet_pad_group_destroy(g); ++ ++ RemoveDevice(pad->xdevice, TRUE); ++ xorg_list_del(&pad->link); ++ zwp_tablet_pad_v2_destroy(pad->pad); ++ free(pad); ++} ++ ++static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = { ++ tablet_pad_group, ++ tablet_pad_path, ++ tablet_pad_buttons, ++ tablet_pad_done, ++ tablet_pad_button, ++ tablet_pad_enter, ++ tablet_pad_leave, ++ tablet_pad_removed, ++}; ++ ++static void + tablet_seat_handle_add_tablet(void *data, struct zwp_tablet_seat_v2 *tablet_seat, + struct zwp_tablet_v2 *tablet) + { +@@ -1769,8 +2182,12 @@ tablet_seat_handle_add_pad(void *data, struct zwp_tablet_seat_v2 *tablet_seat, + + xwl_tablet_pad->pad = pad; + xwl_tablet_pad->seat = xwl_seat; ++ xorg_list_init(&xwl_tablet_pad->pad_group_list); + + xorg_list_add(&xwl_tablet_pad->link, &xwl_seat->tablet_pads); ++ ++ zwp_tablet_pad_v2_add_listener(pad, &tablet_pad_listener, ++ xwl_tablet_pad); + } + + static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index 02a218c43..250564f73 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -216,10 +216,38 @@ struct xwl_tablet_tool { + struct xwl_cursor cursor; + }; + ++struct xwl_tablet_pad_ring { ++ unsigned int index; ++ struct xorg_list link; ++ struct xwl_tablet_pad_group *group; ++ struct zwp_tablet_pad_ring_v2 *ring; ++}; ++ ++struct xwl_tablet_pad_strip { ++ unsigned int index; ++ struct xorg_list link; ++ struct xwl_tablet_pad_group *group; ++ struct zwp_tablet_pad_strip_v2 *strip; ++}; ++ ++struct xwl_tablet_pad_group { ++ struct xorg_list link; ++ struct xwl_tablet_pad *pad; ++ struct zwp_tablet_pad_group_v2 *group; ++ ++ struct xorg_list pad_group_ring_list; ++ struct xorg_list pad_group_strip_list; ++}; ++ + struct xwl_tablet_pad { + struct xorg_list link; + struct zwp_tablet_pad_v2 *pad; + struct xwl_seat *seat; ++ ++ DeviceIntPtr xdevice; ++ ++ unsigned int nbuttons; ++ struct xorg_list pad_group_list; + }; + + struct xwl_output { +-- +2.13.5 + diff --git a/0010-xwayland-Unconditionally-initialize-lists-in-init_ta.patch b/0010-xwayland-Unconditionally-initialize-lists-in-init_ta.patch new file mode 100644 index 0000000..739b5a4 --- /dev/null +++ b/0010-xwayland-Unconditionally-initialize-lists-in-init_ta.patch @@ -0,0 +1,74 @@ +From 81d85fb95d71c0d781328506f1417e7b92c68b97 Mon Sep 17 00:00:00 2001 +From: Lyude +Date: Thu, 4 May 2017 18:04:31 -0400 +Subject: [PATCH xserver 10/12] xwayland: Unconditionally initialize lists in + init_tablet_manager_seat() + +In the event that xwayland gets launched on a wayland compositor that +doesn't yet have support for wp_tablet_manager, we end up skipping the +initialization of the lists. This is wrong, because regardless of +whether or not a tablet is present we still attempt to traverse these +lists later in xwl_set_cursor(), expecting that if the lists are empty +from no tablet manager that we simply won't execute any loop iterations. + +(EE) +(EE) Backtrace: +(EE) 0: Xwayland (OsSigHandler+0x3b) [0x4982f9] +(EE) 1: /lib64/libpthread.so.0 (__restore_rt+0x0) [0x7f73722545bf] +(EE) 2: Xwayland (xwl_set_cursor+0x9f) [0x429974] +(EE) 3: Xwayland (miPointerUpdateSprite+0x261) [0x4fe1ca] +(EE) 4: Xwayland (mieqProcessInputEvents+0x239) [0x4f8d33] +(EE) 5: Xwayland (ProcessInputEvents+0x9) [0x4282f0] +(EE) 6: Xwayland (Dispatch+0x42) [0x43e2d4] +(EE) 7: Xwayland (dix_main+0x5c9) [0x44c6dc] +(EE) 8: Xwayland (main+0x28) [0x61c523] +(EE) 9: /lib64/libc.so.6 (__libc_start_main+0xf1) [0x7f7371e9d401] +(EE) 10: Xwayland (_start+0x2a) [0x4208fa] +(EE) 11: ? (?+0x2a) [0x2a] +(EE) +(EE) Segmentation fault at address 0x28 +(EE) +Fatal server error: +(EE) Caught signal 11 (Segmentation fault). Server aborting +(EE) + +Reproduced when trying to run upstream xwayland under fedora 25's weston +package. + +Signed-off-by: Lyude +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +(cherry picked from commit a06bb73053d9df56d9070ce325a43af3a3c7a6a2) +--- + hw/xwayland/xwayland-input.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index 8011b965c..ee932be60 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -2200,6 +2200,10 @@ static void + init_tablet_manager_seat(struct xwl_screen *xwl_screen, + struct xwl_seat *xwl_seat) + { ++ xorg_list_init(&xwl_seat->tablets); ++ xorg_list_init(&xwl_seat->tablet_tools); ++ xorg_list_init(&xwl_seat->tablet_pads); ++ + if (!xwl_screen->tablet_manager) + return; + +@@ -2207,10 +2211,6 @@ init_tablet_manager_seat(struct xwl_screen *xwl_screen, + zwp_tablet_manager_v2_get_tablet_seat(xwl_screen->tablet_manager, + xwl_seat->seat); + +- xorg_list_init(&xwl_seat->tablets); +- xorg_list_init(&xwl_seat->tablet_tools); +- xorg_list_init(&xwl_seat->tablet_pads); +- + zwp_tablet_seat_v2_add_listener(xwl_seat->tablet_seat, &tablet_seat_listener, xwl_seat); + } + +-- +2.13.5 + diff --git a/0011-xwayland-Correct-off-by-one-error-in-tablet-button-n.patch b/0011-xwayland-Correct-off-by-one-error-in-tablet-button-n.patch new file mode 100644 index 0000000..76e95ec --- /dev/null +++ b/0011-xwayland-Correct-off-by-one-error-in-tablet-button-n.patch @@ -0,0 +1,39 @@ +From edcc95e914079485b7d693cecbfc436d084ad47d Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Fri, 9 Jun 2017 16:02:06 -0700 +Subject: [PATCH xserver 11/12] xwayland: Correct off-by-one error in tablet + button numbering + +The 'tablet_tool_frame' function treats the button masks as though they +are zero-indexed, but 'tablet_tool_button_state' treats them as one- +indexed. The result is that an e.g. middle click event recieved from +Wayland will be sent from the X server as a right-click instead. + +Fixes: 773b04748d0 ("xwayland: handle button events after motion events") +Signed-off-by: Jason Gerecke +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +(cherry picked from commit fbc9814975fe82be25becf1a55d4f8d34298a956) +--- + hw/xwayland/xwayland-input.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index ee932be60..a6d7d9356 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -1626,9 +1626,9 @@ tablet_tool_button_state(void *data, struct zwp_tablet_tool_v2 *tool, + BUG_RETURN(xbtn >= 8 * sizeof(*mask)); + + if (state) +- SetBit(mask, xbtn); ++ SetBit(mask, xbtn - 1); + else +- ClearBit(mask, xbtn); ++ ClearBit(mask, xbtn - 1); + + xwl_seat->xwl_screen->serial = serial; + } +-- +2.13.5 + diff --git a/0012-xwayland-Implement-tablet_tool_wheel-for-scrolling.patch b/0012-xwayland-Implement-tablet_tool_wheel-for-scrolling.patch new file mode 100644 index 0000000..097bcb4 --- /dev/null +++ b/0012-xwayland-Implement-tablet_tool_wheel-for-scrolling.patch @@ -0,0 +1,78 @@ +From d03bf0d1759d7d113216a0311e794b5adb0845de Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Fri, 9 Jun 2017 16:02:07 -0700 +Subject: [PATCH xserver 12/12] xwayland: Implement tablet_tool_wheel for + scrolling + +The 'tablet_tool_wheel' function for tablet scrolling was added back in +8a1defcc634 but left unimplemented. This commit fills in the necessary +details, using the "clicks" count as the number of discrete scroll up/down +events to send. + +Signed-off-by: Jason Gerecke +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +(cherry picked from commit 7c7a540f1e1d6b5466e1c9aa28476a2d7273d5ed) +--- + hw/xwayland/xwayland-input.c | 24 ++++++++++++++++++++++++ + hw/xwayland/xwayland.h | 2 ++ + 2 files changed, 26 insertions(+) + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index a6d7d9356..0cf318623 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -1566,6 +1566,13 @@ static void + tablet_tool_wheel(void *data, struct zwp_tablet_tool_v2 *tool, + wl_fixed_t degrees, int32_t clicks) + { ++ struct xwl_tablet_tool *xwl_tablet_tool = data; ++ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; ++ ++ if (!xwl_seat->focus_window) ++ return; ++ ++ xwl_tablet_tool->wheel_clicks = clicks; + } + + static void +@@ -1677,6 +1684,23 @@ tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time) + } + + xwl_tablet_tool->buttons_prev = xwl_tablet_tool->buttons_now; ++ ++ while (xwl_tablet_tool->wheel_clicks) { ++ if (xwl_tablet_tool->wheel_clicks < 0) { ++ button = 4; ++ xwl_tablet_tool->wheel_clicks++; ++ } ++ else { ++ button = 5; ++ xwl_tablet_tool->wheel_clicks--; ++ } ++ ++ QueuePointerEvents(xwl_tablet_tool->xdevice, ++ ButtonPress, button, 0, &mask); ++ QueuePointerEvents(xwl_tablet_tool->xdevice, ++ ButtonRelease, button, 0, &mask); ++ ++ } + } + + static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = { +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index 250564f73..135aa8761 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -213,6 +213,8 @@ struct xwl_tablet_tool { + uint32_t buttons_now, + buttons_prev; + ++ int32_t wheel_clicks; ++ + struct xwl_cursor cursor; + }; + +-- +2.13.5 + diff --git a/sources b/sources index da90773..aec6b7c 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (xorg-server-1.19.3.tar.bz2) = b988897418399e1361fdcca9465a781f55f8f6fbfdc5a59edfaee9046a0c6ad7a76f348d88b6004ce3d3fb3966b4c5af0b854f6549c32b2b8d7a43758809f669 +SHA512 (xorg-server-1.19.4.tar.bz2) = ff80934e42a7dd2d437e947fe02c74c3b25bdbb3002b7005191d52272d5eae8cb3a83377fa32f40000011be88405830e796f6bd3b914bd7fc163ea8ece76226b diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec index 767566b..97ec39c 100644 --- a/xorg-x11-server.spec +++ b/xorg-x11-server.spec @@ -44,8 +44,8 @@ Summary: X.Org X11 X server Name: xorg-x11-server -Version: 1.19.3 -Release: 9%{?gitdate:.%{gitdate}}%{dist} +Version: 1.19.4 +Release: 1%{?gitdate:.%{gitdate}}%{dist} URL: http://www.x.org License: MIT Group: User Interface/X @@ -90,6 +90,20 @@ Patch14: 0004-xfree86-xf86platformProbe-split-finding-pci-info-and.patch Patch15: 0005-xfree86-Allow-overriding-primary-GPU-detection-from-.patch Patch16: 0006-xfree86-Add-ModulePath-support-for-OutputClass-confi.patch +# Backport tablet support for Xwayland - *NOT* in server-1.19-branch +Patch9901: 0001-xwayland-Depend-on-wayland-protocols-to-build-tablet.patch +Patch9902: 0002-xwayland-Bind-to-wp_tablet_manager-if-available-and-.patch +Patch9903: 0003-xwayland-Listen-for-wp_tablet_seat-events.patch +Patch9904: 0004-xwayland-Handle-wp_tablet-events.patch +Patch9905: 0005-xwayland-Handle-tablet_tool-events.patch +Patch9906: 0006-xwayland-handle-button-events-after-motion-events.patch +Patch9907: 0007-xwayland-Refactor-cursor-management-into-xwl_cursor.patch +Patch9908: 0008-xwayland-update-cursor-on-tablet-tools-in-proximity.patch +Patch9909: 0009-xwayland-add-tablet-pad-support.patch +Patch9910: 0010-xwayland-Unconditionally-initialize-lists-in-init_ta.patch +Patch9911: 0011-xwayland-Correct-off-by-one-error-in-tablet-button-n.patch +Patch9912: 0012-xwayland-Implement-tablet_tool_wheel-for-scrolling.patch + # From Debian use intel ddx driver only for gen4 and older chipsets %if 0%{?fedora} > 25 || 0%{?rhel} > 7 Patch20: 06_use-intel-only-on-pre-gen4.diff @@ -98,8 +112,6 @@ Patch20: 06_use-intel-only-on-pre-gen4.diff # Submitted upstream Patch21: 0001-xf86-dri2-Use-va_gl-as-vdpau_driver-for-Intel-i965-G.patch -Patch22: 0001-modesetting-Set-correct-DRM-event-context-version.patch - #Patch6044: xserver-1.6.99-hush-prerelease-warning.patch Patch7025: 0001-Always-install-vbe-and-int10-sdk-headers.patch @@ -605,6 +617,10 @@ find %{inst_srcdir}/hw/xfree86 -name \*.c -delete %changelog +* Thu Oct 05 2017 Olivier Fourdan - 1.19.4-1 +- xserver-1.19.4 +- Backport tablet support for Xwayland + * Fri Sep 08 2017 Troy Dawson - 1.19.3-9 - Cleanup spec file conditionals