Implement the relative pointer protocol

A wp_relative_pointer object is an extension to the wl_pointer interface
only used for emitting relative pointer events. It will only emit events
when the parent pointer has focus.

To get a relative pointer object, use the get_relative_pointer request
of the global wp_relative_pointer_manager object.

The relative pointer protocol is currently an unstable protocol, so
unstable protocol naming conventions has been applied.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Jonas Ådahl 2014-10-22 21:21:17 +02:00
parent de1ed2e73b
commit 30d61d89c1
4 changed files with 179 additions and 19 deletions

View File

@ -135,7 +135,9 @@ nodist_libweston_la_SOURCES = \
protocol/viewporter-protocol.c \
protocol/viewporter-server-protocol.h \
protocol/linux-dmabuf-unstable-v1-protocol.c \
protocol/linux-dmabuf-unstable-v1-server-protocol.h
protocol/linux-dmabuf-unstable-v1-server-protocol.h \
protocol/relative-pointer-unstable-v1-protocol.c \
protocol/relative-pointer-unstable-v1-server-protocol.h
BUILT_SOURCES += $(nodist_libweston_la_SOURCES)

View File

@ -4703,6 +4703,9 @@ weston_compositor_create(struct wl_display *display, void *user_data)
ec, bind_presentation))
goto fail;
if (weston_input_init(ec) != 0)
goto fail;
wl_list_init(&ec->view_list);
wl_list_init(&ec->plane_list);
wl_list_init(&ec->layer_list);

View File

@ -355,6 +355,7 @@ struct weston_pointer_client {
struct wl_list link;
struct wl_client *client;
struct wl_list pointer_resources;
struct wl_list relative_pointer_resources;
};
struct weston_pointer {
@ -1694,6 +1695,9 @@ weston_output_mode_switch_to_native(struct weston_output *output);
int
noop_renderer_init(struct weston_compositor *ec);
int
weston_input_init(struct weston_compositor *compositor);
int
backend_init(struct weston_compositor *c,
struct weston_backend_config *config_base);

View File

@ -37,6 +37,7 @@
#include "shared/helpers.h"
#include "shared/os-compatibility.h"
#include "compositor.h"
#include "protocol/relative-pointer-unstable-v1-server-protocol.h"
static void
empty_region(pixman_region32_t *region)
@ -56,6 +57,7 @@ weston_pointer_client_create(struct wl_client *client)
pointer_client->client = client;
wl_list_init(&pointer_client->pointer_resources);
wl_list_init(&pointer_client->relative_pointer_resources);
return pointer_client;
}
@ -69,7 +71,8 @@ weston_pointer_client_destroy(struct weston_pointer_client *pointer_client)
static bool
weston_pointer_client_is_empty(struct weston_pointer_client *pointer_client)
{
return wl_list_empty(&pointer_client->pointer_resources);
return (wl_list_empty(&pointer_client->pointer_resources) &&
wl_list_empty(&pointer_client->relative_pointer_resources));
}
static struct weston_pointer_client *
@ -139,6 +142,49 @@ static void unbind_resource(struct wl_resource *resource)
wl_list_remove(wl_resource_get_link(resource));
}
WL_EXPORT void
weston_pointer_motion_to_abs(struct weston_pointer *pointer,
struct weston_pointer_motion_event *event,
wl_fixed_t *x, wl_fixed_t *y)
{
if (event->mask & WESTON_POINTER_MOTION_ABS) {
*x = wl_fixed_from_double(event->x);
*y = wl_fixed_from_double(event->y);
} else if (event->mask & WESTON_POINTER_MOTION_REL) {
*x = pointer->x + wl_fixed_from_double(event->dx);
*y = pointer->y + wl_fixed_from_double(event->dy);
} else {
assert(!"invalid motion event");
*x = *y = 0;
}
}
static bool
weston_pointer_motion_to_rel(struct weston_pointer *pointer,
struct weston_pointer_motion_event *event,
double *dx, double *dy,
double *dx_unaccel, double *dy_unaccel)
{
if (event->mask & WESTON_POINTER_MOTION_REL &&
event->mask & WESTON_POINTER_MOTION_REL_UNACCEL) {
*dx = event->dx;
*dy = event->dy;
*dx_unaccel = event->dx_unaccel;
*dy_unaccel = event->dy_unaccel;
return true;
} else if (event->mask & WESTON_POINTER_MOTION_REL) {
*dx_unaccel = *dx = event->dx;
*dy_unaccel = *dy = event->dy;
return true;
} else if (event->mask & WESTON_POINTER_MOTION_REL_UNACCEL) {
*dx_unaccel = *dx = event->dx_unaccel;
*dy_unaccel = *dy = event->dy_unaccel;
return true;
} else {
return false;
}
}
WL_EXPORT void
weston_seat_repick(struct weston_seat *seat)
{
@ -254,6 +300,45 @@ default_grab_pointer_focus(struct weston_pointer_grab *grab)
weston_pointer_set_focus(pointer, view, sx, sy);
}
static void
weston_pointer_send_relative_motion(struct weston_pointer *pointer,
uint32_t time,
struct weston_pointer_motion_event *event)
{
uint64_t time_usec;
double dx, dy, dx_unaccel, dy_unaccel;
wl_fixed_t dxf, dyf, dxf_unaccel, dyf_unaccel;
struct wl_list *resource_list;
struct wl_resource *resource;
if (!pointer->focus_client)
return;
if (!weston_pointer_motion_to_rel(pointer, event,
&dx, &dy,
&dx_unaccel, &dy_unaccel))
return;
resource_list = &pointer->focus_client->relative_pointer_resources;
time_usec = event->time_usec;
if (time_usec == 0)
time_usec = time * 1000ULL;
dxf = wl_fixed_from_double(dx);
dyf = wl_fixed_from_double(dy);
dxf_unaccel = wl_fixed_from_double(dx_unaccel);
dyf_unaccel = wl_fixed_from_double(dy_unaccel);
wl_resource_for_each(resource, resource_list) {
zwp_relative_pointer_v1_send_relative_motion(
resource,
(uint32_t) (time_usec >> 32),
(uint32_t) time_usec,
dxf, dyf,
dxf_unaccel, dyf_unaccel);
}
}
static void
default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
struct weston_pointer_motion_event *event)
@ -281,6 +366,8 @@ default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
pointer->sx, pointer->sy);
}
}
weston_pointer_send_relative_motion(pointer, time, event);
}
static void
@ -1158,23 +1245,6 @@ weston_pointer_move_to(struct weston_pointer *pointer,
wl_signal_emit(&pointer->motion_signal, pointer);
}
WL_EXPORT void
weston_pointer_motion_to_abs(struct weston_pointer *pointer,
struct weston_pointer_motion_event *event,
wl_fixed_t *x, wl_fixed_t *y)
{
if (event->mask & WESTON_POINTER_MOTION_ABS) {
*x = wl_fixed_from_double(event->x);
*y = wl_fixed_from_double(event->y);
} else if (event->mask & WESTON_POINTER_MOTION_REL) {
*x = pointer->x + wl_fixed_from_double(event->dx);
*y = pointer->y + wl_fixed_from_double(event->dy);
} else {
assert(!"invalid motion event");
*x = *y = 0;
}
}
WL_EXPORT void
weston_pointer_move(struct weston_pointer *pointer,
struct weston_pointer_motion_event *event)
@ -2292,6 +2362,76 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
wl_seat_send_name(resource, seat->seat_name);
}
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)
{
struct weston_pointer *pointer =
wl_resource_get_user_data(pointer_resource);
struct weston_pointer_client *pointer_client;
struct wl_resource *cr;
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;
}
pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
if (!pointer_client) {
wl_client_post_no_memory(client);
return;
}
wl_list_insert(&pointer_client->relative_pointer_resources,
wl_resource_get_link(cr));
wl_resource_set_implementation(cr, &relative_pointer_interface,
pointer,
unbind_pointer_client_resource);
}
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)
{
struct weston_compositor *compositor = data;
struct wl_resource *resource;
resource = wl_resource_create(client,
&zwp_relative_pointer_manager_v1_interface,
1, id);
wl_resource_set_implementation(resource, &relative_pointer_manager,
compositor,
NULL);
}
#ifdef ENABLE_XKBCOMMON
WL_EXPORT int
weston_compositor_set_xkb_rule_names(struct weston_compositor *ec,
@ -2799,3 +2939,14 @@ weston_seat_set_keyboard_focus(struct weston_seat *seat,
inc_activate_serial(compositor);
wl_signal_emit(&compositor->activate_signal, surface);
}
int
weston_input_init(struct weston_compositor *compositor)
{
if (!wl_global_create(compositor->wl_display,
&zwp_relative_pointer_manager_v1_interface, 1,
compositor, bind_relative_pointer_manager))
return -1;
return 0;
}