diff --git a/.gitignore b/.gitignore index 7a3d9d309..62a274376 100644 --- a/.gitignore +++ b/.gitignore @@ -68,6 +68,8 @@ src/xdg-shell-unstable-v*-protocol.c src/xdg-shell-unstable-v*-server-protocol.h src/pointer-gestures-unstable-v*-protocol.c src/pointer-gestures-unstable-v*-server-protocol.h +src/relative-pointer-unstable-v*-protocol.c +src/relative-pointer-unstable-v*-server-protocol.h src/meta/meta-version.h doc/reference/*.args doc/reference/*.bak diff --git a/configure.ac b/configure.ac index 8731079da..412bb8590 100644 --- a/configure.ac +++ b/configure.ac @@ -221,7 +221,7 @@ AS_IF([test "$have_wayland" = "yes"], [ AC_SUBST([WAYLAND_SCANNER]) AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support]) - PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.0], + PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.1], [ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`]) AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir) ]) diff --git a/src/Makefile.am b/src/Makefile.am index 5468d47ed..71aa02674 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,6 +51,8 @@ mutter_built_sources += \ gtk-shell-server-protocol.h \ xdg-shell-unstable-v5-protocol.c \ xdg-shell-unstable-v5-server-protocol.h \ + relative-pointer-unstable-v1-protocol.c \ + relative-pointer-unstable-v1-server-protocol.h \ $(NULL) endif diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h index d2c627657..6fa468da6 100644 --- a/src/backends/meta-backend-private.h +++ b/src/backends/meta-backend-private.h @@ -87,6 +87,13 @@ struct _MetaBackendClass void (* update_screen_size) (MetaBackend *backend, int width, int height); void (* select_stage_events) (MetaBackend *backend); + + gboolean (* get_relative_motion_deltas) (MetaBackend *backend, + const ClutterEvent *event, + double *dx, + double *dy, + double *dx_unaccel, + double *dy_unaccel); }; MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend, @@ -110,4 +117,11 @@ struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend); void meta_backend_update_last_device (MetaBackend *backend, int device_id); +gboolean meta_backend_get_relative_motion_deltas (MetaBackend *backend, + const ClutterEvent *event, + double *dx, + double *dy, + double *dx_unaccel, + double *dy_unaccel); + #endif /* META_BACKEND_PRIVATE_H */ diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c index 819747803..05d160d96 100644 --- a/src/backends/meta-backend.c +++ b/src/backends/meta-backend.c @@ -353,6 +353,17 @@ meta_backend_real_select_stage_events (MetaBackend *backend) /* Do nothing */ } +static gboolean +meta_backend_real_get_relative_motion_deltas (MetaBackend *backend, + const ClutterEvent *event, + double *dx, + double *dy, + double *dx_unaccel, + double *dy_unaccel) +{ + return FALSE; +} + static void meta_backend_class_init (MetaBackendClass *klass) { @@ -366,6 +377,7 @@ meta_backend_class_init (MetaBackendClass *klass) klass->ungrab_device = meta_backend_real_ungrab_device; klass->update_screen_size = meta_backend_real_update_screen_size; klass->select_stage_events = meta_backend_real_select_stage_events; + klass->get_relative_motion_deltas = meta_backend_real_get_relative_motion_deltas; g_signal_new ("keymap-changed", G_TYPE_FROM_CLASS (object_class), @@ -544,6 +556,21 @@ meta_backend_update_last_device (MetaBackend *backend, } } +gboolean +meta_backend_get_relative_motion_deltas (MetaBackend *backend, + const ClutterEvent *event, + double *dx, + double *dy, + double *dx_unaccel, + double *dy_unaccel) +{ + MetaBackendClass *klass = META_BACKEND_GET_CLASS (backend); + return klass->get_relative_motion_deltas (backend, + event, + dx, dy, + dx_unaccel, dy_unaccel); +} + static GType get_backend_type (void) { diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index d22bed10a..5a1c1b48f 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -306,6 +306,19 @@ meta_backend_native_lock_layout_group (MetaBackend *backend, g_signal_emit_by_name (backend, "keymap-layout-group-changed", idx, 0); } +static gboolean +meta_backend_native_get_relative_motion_deltas (MetaBackend *backend, + const ClutterEvent *event, + double *dx, + double *dy, + double *dx_unaccel, + double *dy_unaccel) +{ + return clutter_evdev_event_get_relative_motion (event, + dx, dy, + dx_unaccel, dy_unaccel); +} + static void meta_backend_native_class_init (MetaBackendNativeClass *klass) { @@ -323,6 +336,7 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass) backend_class->set_keymap = meta_backend_native_set_keymap; backend_class->get_keymap = meta_backend_native_get_keymap; backend_class->lock_layout_group = meta_backend_native_lock_layout_group; + backend_class->get_relative_motion_deltas = meta_backend_native_get_relative_motion_deltas; } static void diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index 92acffaa4..ef3228ec4 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -63,6 +63,8 @@ #include "backends/meta-cursor-tracker-private.h" #include "backends/meta-cursor-renderer.h" +#include "relative-pointer-unstable-v1-server-protocol.h" + #ifdef HAVE_NATIVE_BACKEND #include "backends/native/meta-backend-native.h" #endif @@ -96,6 +98,7 @@ meta_wayland_pointer_client_new (void) wl_list_init (&pointer_client->pointer_resources); wl_list_init (&pointer_client->swipe_gesture_resources); wl_list_init (&pointer_client->pinch_gesture_resources); + wl_list_init (&pointer_client->relative_pointer_resources); return pointer_client; } @@ -124,6 +127,11 @@ meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client) wl_list_remove (wl_resource_get_link (resource)); wl_list_init (wl_resource_get_link (resource)); } + wl_resource_for_each_safe (resource, next, &pointer_client->relative_pointer_resources) + { + wl_list_remove (wl_resource_get_link (resource)); + wl_list_init (wl_resource_get_link (resource)); + } g_slice_free (MetaWaylandPointerClient, pointer_client); } @@ -133,7 +141,8 @@ meta_wayland_pointer_client_is_empty (MetaWaylandPointerClient *pointer_client) { return (wl_list_empty (&pointer_client->pointer_resources) && wl_list_empty (&pointer_client->swipe_gesture_resources) && - wl_list_empty (&pointer_client->pinch_gesture_resources)); + wl_list_empty (&pointer_client->pinch_gesture_resources) && + wl_list_empty (&pointer_client->relative_pointer_resources)); } MetaWaylandPointerClient * @@ -264,6 +273,53 @@ meta_wayland_pointer_broadcast_frame (MetaWaylandPointer *pointer) } } +static void +meta_wayland_pointer_send_relative_motion (MetaWaylandPointer *pointer, + const ClutterEvent *event) +{ + struct wl_resource *resource; + double dx, dy; + double dx_unaccel, dy_unaccel; + uint64_t time_us; + uint32_t time_us_hi; + uint32_t time_us_lo; + wl_fixed_t dxf, dyf; + wl_fixed_t dx_unaccelf, dy_unaccelf; + + if (!pointer->focus_client) + return; + + if (!meta_backend_get_relative_motion_deltas (meta_get_backend (), + event, + &dx, &dy, + &dx_unaccel, &dy_unaccel)) + return; + +#ifdef HAVE_NATIVE_BACKEND + time_us = clutter_evdev_event_get_time_usec (event); + if (time_us == 0) +#endif + time_us = clutter_event_get_time (event) * 1000ULL; + time_us_hi = (uint32_t) (time_us >> 32); + time_us_lo = (uint32_t) time_us; + dxf = wl_fixed_from_double (dx); + dyf = wl_fixed_from_double (dy); + dx_unaccelf = wl_fixed_from_double (dx_unaccel); + dy_unaccelf = wl_fixed_from_double (dy_unaccel); + + wl_resource_for_each (resource, + &pointer->focus_client->relative_pointer_resources) + { + zwp_relative_pointer_v1_send_relative_motion (resource, + time_us_hi, + time_us_lo, + dxf, + dyf, + dx_unaccelf, + dy_unaccelf); + } +} + void meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer, const ClutterEvent *event) @@ -285,6 +341,8 @@ meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer, wl_pointer_send_motion (resource, time, sx, sy); } + meta_wayland_pointer_send_relative_motion (pointer, event); + meta_wayland_pointer_broadcast_frame (pointer); } @@ -1097,6 +1155,101 @@ meta_wayland_pointer_get_top_popup (MetaWaylandPointer *pointer) return meta_wayland_popup_grab_get_top_popup(grab); } +static void +relative_pointer_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static const struct zwp_relative_pointer_v1_interface relative_pointer_interface = { + relative_pointer_destroy +}; + +static void +relative_pointer_manager_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static void +relative_pointer_manager_get_relative_pointer (struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *pointer_resource) +{ + MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource); + struct wl_resource *cr; + MetaWaylandPointerClient *pointer_client; + + cr = wl_resource_create (client, &zwp_relative_pointer_v1_interface, + wl_resource_get_version (resource), id); + if (cr == NULL) + { + wl_client_post_no_memory (client); + return; + } + + wl_resource_set_implementation (cr, &relative_pointer_interface, + pointer, + meta_wayland_pointer_unbind_pointer_client_resource); + + pointer_client = meta_wayland_pointer_ensure_pointer_client (pointer, client); + + wl_list_insert (&pointer_client->relative_pointer_resources, + wl_resource_get_link (cr)); +} + +static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = { + relative_pointer_manager_destroy, + relative_pointer_manager_get_relative_pointer, +}; + +static void +bind_relative_pointer_manager (struct wl_client *client, + void *data, + uint32_t version, + uint32_t id) +{ + MetaWaylandCompositor *compositor = data; + struct wl_resource *resource; + + resource = wl_resource_create (client, + &zwp_relative_pointer_manager_v1_interface, + 1, id); + + if (version != 1) + wl_resource_post_error (resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "bound invalid version %u of " + "wp_relative_pointer_manager", + version); + + wl_resource_set_implementation (resource, &relative_pointer_manager, + compositor, + NULL); +} + +void +meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor) +{ + /* Relative pointer events are currently only supported by the native backend + * so lets just advertise the extension when the native backend is used. + */ +#ifdef HAVE_NATIVE_BACKEND + if (!META_IS_BACKEND_NATIVE (meta_get_backend ())) + return; +#else + return; +#endif + + if (!wl_global_create (compositor->wayland_display, + &zwp_relative_pointer_manager_v1_interface, 1, + compositor, bind_relative_pointer_manager)) + g_error ("Could not create relative pointer manager global"); +} + static void cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role) { diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h index 7e31da9e4..cfe1b460f 100644 --- a/src/wayland/meta-wayland-pointer.h +++ b/src/wayland/meta-wayland-pointer.h @@ -58,6 +58,7 @@ struct _MetaWaylandPointerClient struct wl_list pointer_resources; struct wl_list swipe_gesture_resources; struct wl_list pinch_gesture_resources; + struct wl_list relative_pointer_resources; }; struct _MetaWaylandPointer @@ -142,4 +143,6 @@ MetaWaylandPointerClient * meta_wayland_pointer_get_pointer_client (MetaWaylandP struct wl_client *client); void meta_wayland_pointer_unbind_pointer_client_resource (struct wl_resource *resource); +void meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor); + #endif /* META_WAYLAND_POINTER_H */ diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index 523fbceb7..a878f323d 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -328,6 +328,7 @@ meta_wayland_init (void) meta_wayland_shell_init (compositor); meta_wayland_pointer_gestures_init (compositor); meta_wayland_seat_init (compositor); + meta_wayland_relative_pointer_init (compositor); if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display)) g_error ("Failed to start X Wayland");