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:
Jonas Ådahl 2015-06-02 16:26:34 +08:00
parent 50099c4c10
commit 5b0eabec51
9 changed files with 218 additions and 2 deletions

2
.gitignore vendored
View File

@ -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

View File

@ -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)
])

View File

@ -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

View File

@ -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 */

View File

@ -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)
{

View File

@ -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

View File

@ -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)
{

View File

@ -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 */

View File

@ -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");