wayland: Implement support for wp_relative_pointer
Add support for sending relative pointer motion deltas to clients who request such events by creating wp_relative_pointer objects via wp_relative_pointer_manager. This currently implements the unstable version 1 from wayland-protocols. https://bugzilla.gnome.org/show_bug.cgi?id=744104
This commit is contained in:
parent
50099c4c10
commit
5b0eabec51
9 changed files with 218 additions and 2 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
])
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in a new issue