A wl_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 wl_relative_pointer_manager object. When stabilizing it might make more sense to just add it to wl_seat instead of having a single use global interface. All interface names are currently prefixed with underscore in order to avoid any future conflicts with stable protocol. Signed-off-by: Jonas Ådahl <jad...@gmail.com> --- Makefile.am | 7 +- protocol/relative-pointer.xml | 112 +++++++++++++++++++++++++ src/compositor.c | 3 + src/compositor.h | 5 ++ src/input.c | 186 ++++++++++++++++++++++++++++++++++++++---- 5 files changed, 294 insertions(+), 19 deletions(-) create mode 100644 protocol/relative-pointer.xml diff --git a/Makefile.am b/Makefile.am index 0a30cb4..70c436f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -105,7 +105,9 @@ nodist_weston_SOURCES = \ protocol/presentation_timing-protocol.c \ protocol/presentation_timing-server-protocol.h \ protocol/scaler-protocol.c \ - protocol/scaler-server-protocol.h + protocol/scaler-server-protocol.h \ + protocol/relative-pointer-protocol.c \ + protocol/relative-pointer-server-protocol.h BUILT_SOURCES += $(nodist_weston_SOURCES) @@ -1183,7 +1185,8 @@ EXTRA_DIST += \ protocol/presentation_timing.xml \ protocol/scaler.xml \ protocol/ivi-application.xml \ - protocol/ivi-hmi-controller.xml + protocol/ivi-hmi-controller.xml \ + protocol/relative-pointer.xml # # manual test modules in tests subdirectory diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml new file mode 100644 index 0000000..d9632b9 --- /dev/null +++ b/protocol/relative-pointer.xml @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="relative_pointer"> + + <copyright> + Copyright © 2014 Jonas Ådahl + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + </copyright> + + <interface name="_wl_relative_pointer_manager" version="1"> + <description summary="get relative pointer objects"> + A global interface used for getting the relative pointer object for a + given seat. + </description> + + <request name="get_relative_pointer"> + <description summary="get a relative pointer object"> + Create a relative pointer interface given a wl_pointer object. See + the wl_relative_pointer interface for more details. + </description> + + <arg name="id" type="new_id" interface="_wl_relative_pointer"/> + <arg name="pointer" type="object" interface="wl_pointer"/> + </request> + </interface> + + <interface name="_wl_relative_pointer" version="1"> + <description summary="relative pointer object"> + A wl_relative_pointer object is an extension to the wl_pointer interface + used for emitting relative pointer events. It shares the same focus as + wl_pointer objects of the same seat and will only emit events when it + has focus. + </description> + + <request name="release" type="destructor"> + <description summary="release the relative pointer object"/> + </request> + + <event name="relative_motion"> + <description summary="relative pointer motion"> + Relative pointer motion from the pointer of the seat associated with + this object. + + A relative motion is in the same dimension as regular wl_pointer motion + events, except they do not represent an absolute position. For instance, + moving a pointer from (x, y) to (x', y') would have the equivalent + relative motion (x' - x, y' - y). + + This event also contains non-accelerated motion deltas. The + non-accelerated delta is, when applicable, the regular pointer motion + delta as it was before having applied motion acceleration + transformations. The compositor will have applied the same processing + (such as normalization) meaning the events will have roughly the same + magnitude as accelerated motion events. + + Note that it does not represent 'raw' events as they were read from some + device. What acceleration corresponds to is device specific and may be + identical to non-accelerated for some devices, while for others not. + + Relative motions are not coupled to wl_pointer.motion events, and can + be sent in combination with such events, but also independently. There + may also be scenarious where wl_pointer.motion is sent, but there is no + relative motion. + + The motion vectors are encoded as double fixed point values. + + A double fixed point value is a 64 bit data type encoded as two separate + signed 32 bit integers. The integral part of the value is stored in one + of the integers and the fractional part in the other. + </description> + + <arg name="time" type="uint" + summary="timestamp with millisecond granularity"/> + <arg name="dx_int" type="int" + summary="integral part of the x component of the motion vector"/> + <arg name="dx_frac" type="int" + summary="fractional part of the x component of the motion vector"/> + <arg name="dy_int" type="int" + summary="integral part of the y component of the motion vector"/> + <arg name="dy_frac" type="int" + summary="fractional part of the y component of the motion vector"/> + <arg name="dx_unaccel_int" type="int" + summary="integral part of the x component of the unaccelerated motion vector"/> + <arg name="dx_unaccel_frac" type="int" + summary="fractional part of the x component of the unaccelerated motion vector"/> + <arg name="dy_unaccel_int" type="int" + summary="integral part of the y component of the unaccelerated motion vector"/> + <arg name="dy_unaccel_frac" type="int" + summary="fractional part of the y component of the unaccelerated motion vector"/> + </event> + </interface> + +</protocol> diff --git a/src/compositor.c b/src/compositor.c index 5594d30..b462531 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -4560,6 +4560,9 @@ weston_compositor_init(struct weston_compositor *ec, weston_plane_init(&ec->primary_plane, ec, 0, 0); weston_compositor_stack_plane(ec, &ec->primary_plane, NULL); + if (weston_input_init(ec) != 0) + return -1; + s = weston_config_get_section(ec->config, "keyboard", NULL, NULL); weston_config_section_get_string(s, "keymap_rules", (char **) &xkb_names.rules, NULL); diff --git a/src/compositor.h b/src/compositor.h index 331b758..55cc88f 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -340,7 +340,9 @@ struct weston_pointer { struct weston_seat *seat; struct wl_list resource_list; + struct wl_list relative_resource_list; struct wl_list focus_resource_list; + struct wl_list relative_focus_resource_list; struct weston_view *focus; uint32_t focus_serial; struct wl_listener focus_view_listener; @@ -1584,6 +1586,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); + struct weston_compositor * backend_init(struct wl_display *display, int *argc, char *argv[], struct weston_config *config); diff --git a/src/input.c b/src/input.c index 059ab03..47f3868 100644 --- a/src/input.c +++ b/src/input.c @@ -32,7 +32,9 @@ #include <limits.h> #include "../shared/os-compatibility.h" +#include "../shared/util.h" #include "compositor.h" +#include "protocol/relative-pointer-server-protocol.h" static void empty_region(pixman_region32_t *region) @@ -47,6 +49,49 @@ static void unbind_resource(struct wl_resource *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 int +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_NOACCEL) { + *dx = event->dx; + *dy = event->dy; + *dx_unaccel = event->dx_unaccel; + *dy_unaccel = event->dy_unaccel; + return 1; + } else if (event->mask & WESTON_POINTER_MOTION_REL) { + *dx_unaccel = *dx = event->dx; + *dy_unaccel = *dy = event->dy; + return 1; + } else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) { + *dx_unaccel = *dx = event->dx_unaccel; + *dy_unaccel = *dy = event->dy_unaccel; + return 1; + } else { + return 0; + } +} + +WL_EXPORT void weston_seat_repick(struct weston_seat *seat) { const struct weston_pointer *pointer = seat->pointer; @@ -162,6 +207,42 @@ default_grab_pointer_focus(struct weston_pointer_grab *grab) } static void +weston_pointer_send_relative_motion(struct weston_pointer *pointer, + uint32_t time, + struct weston_pointer_motion_event *event) +{ + double dx, dy, dx_unaccel, dy_unaccel; + int32_t dx_int, dx_frac; + int32_t dy_int, dy_frac; + int32_t dx_unaccel_int, dx_unaccel_frac; + int32_t dy_unaccel_int, dy_unaccel_frac; + struct wl_list *resource_list; + struct wl_resource *resource; + + if (weston_pointer_motion_to_rel(pointer, event, + &dx, &dy, + &dx_unaccel, &dy_unaccel)) { + resource_list = &pointer->relative_focus_resource_list; + wl_double_fixed_from_double(dx, &dx_int, &dx_frac); + wl_double_fixed_from_double(dy, &dy_int, &dy_frac); + wl_double_fixed_from_double(dx_unaccel, + &dx_unaccel_int, + &dx_unaccel_frac); + wl_double_fixed_from_double(dy_unaccel, + &dy_unaccel_int, + &dy_unaccel_frac); + wl_resource_for_each(resource, resource_list) { + _wl_relative_pointer_send_relative_motion( + resource, time, + dx_int, dx_frac, + dy_int, dy_frac, + dx_unaccel_int, dx_unaccel_frac, + dy_unaccel_int, dy_unaccel_frac); + } + } +} + +static void default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time, struct weston_pointer_motion_event *event) { @@ -187,6 +268,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 @@ -492,7 +575,9 @@ weston_pointer_create(struct weston_seat *seat) return NULL; wl_list_init(&pointer->resource_list); + wl_list_init(&pointer->relative_resource_list); wl_list_init(&pointer->focus_resource_list); + wl_list_init(&pointer->relative_focus_resource_list); weston_pointer_set_default_grab(pointer, seat->compositor->default_pointer_grab); wl_list_init(&pointer->focus_resource_listener.link); @@ -654,6 +739,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer, struct wl_display *display = pointer->seat->compositor->wl_display; uint32_t serial; struct wl_list *focus_resource_list; + struct wl_list *relative_focus_resource_list; int refocus = 0; if ((!pointer->focus && view) || @@ -663,6 +749,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer, refocus = 1; focus_resource_list = &pointer->focus_resource_list; + relative_focus_resource_list = &pointer->relative_focus_resource_list; if (!wl_list_empty(focus_resource_list) && refocus) { serial = wl_display_next_serial(display); @@ -672,6 +759,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer, } move_resources(&pointer->resource_list, focus_resource_list); + move_resources(&pointer->relative_resource_list, + relative_focus_resource_list); } if (find_resource_for_view(&pointer->resource_list, view) && refocus) { @@ -689,6 +778,9 @@ weston_pointer_set_focus(struct weston_pointer *pointer, move_resources_for_client(focus_resource_list, &pointer->resource_list, surface_client); + move_resources_for_client(relative_focus_resource_list, + &pointer->relative_resource_list, + surface_client); wl_resource_for_each(resource, focus_resource_list) { wl_pointer_send_enter(resource, @@ -921,23 +1013,6 @@ weston_pointer_move_to(struct weston_pointer *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) { @@ -1997,6 +2072,72 @@ 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_release(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct _wl_relative_pointer_interface relative_pointer_interface = { + relative_pointer_release +}; + +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 wl_resource *cr; + struct weston_view *focus; + + cr = wl_resource_create(client, &_wl_relative_pointer_interface, + wl_resource_get_version(resource), id); + if (cr == NULL) { + wl_client_post_no_memory(client); + return; + } + + /* May be moved to focused list later by either + * weston_pointer_set_focus or directly if this client is already + * focused */ + wl_list_insert(&pointer->relative_resource_list, + wl_resource_get_link(cr)); + wl_resource_set_implementation(cr, &relative_pointer_interface, + pointer, + unbind_resource); + + focus = pointer->focus; + if (focus && focus->surface->resource && + wl_resource_get_client(focus->surface->resource) == client) { + wl_list_remove(wl_resource_get_link(cr)); + wl_list_insert(&pointer->relative_focus_resource_list, + wl_resource_get_link(cr)); + } +} + +static const struct _wl_relative_pointer_manager_interface relative_pointer_manager = { + 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, + &_wl_relative_pointer_manager_interface, + 1, id); + wl_resource_set_implementation(resource, &relative_pointer_manager, + compositor, + NULL); +} + #ifdef ENABLE_XKBCOMMON int weston_compositor_xkb_init(struct weston_compositor *ec, @@ -2418,3 +2559,14 @@ weston_seat_release(struct weston_seat *seat) wl_signal_emit(&seat->destroy_signal, seat); } + +int +weston_input_init(struct weston_compositor *compositor) +{ + if (!wl_global_create(compositor->wl_display, + &_wl_relative_pointer_manager_interface, 1, + compositor, bind_relative_pointer_manager)) + return -1; + + return 0; +} -- 2.1.4 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel