[PATCH weston 1/3] Introduce pointer lock interface
Giulio Camuffo
giuliocamuffo at gmail.com
Wed Sep 17 13:16:06 PDT 2014
2014-09-17 23:11 GMT+03:00 Jonas Ådahl <jadahl at gmail.com>:
> On Wed, Sep 17, 2014 at 10:56:13PM +0300, Giulio Camuffo wrote:
>> I haven't looked at the implementation yet, just at the protocol, but
>> isn't _wl_pointer_lock.lock_pointer() returning a new wl_pointer a
>> problem? Objects should have a unique factory interface, or else the
>> version of the interface can't be determined.
>
> Is it really? In the implementation below, the wl_pointer object gets
> the same version as the wl_pointer object that is locked. It is also
> specified in the last paragraph of _wl_pointer_lock.lock_pointer.
Mmh, then maybe it is fine. I'm not convinced actually, but I'm too
tired now. :)
>
> Also, this would not be the first interface that creates objects that
> other interface do as well. For example wl_shm_pool.create_buffer and
> wl_drm.create_buffer both create wl_buffer's.
Yes, indeed wl_buffer and wl_callback version can't be increased, afaik.
--
Giulio
>
>
> Jonas
>
>>
>>
>> --
>> Giulio
>>
>>
>> 2014-09-17 22:39 GMT+03:00 Jonas Ådahl <jadahl at gmail.com>:
>> > Introduce a pointer lock interface and implementation. The interface
>> > consists of a global currently called _wl_pointer_lock. It is prefixed
>> > with an underscore (_) in order to not conflict with a potential
>> > official protocol in Wayland, and if moving it there, the prefixed
>> > should be removed.
>> >
>> > The protocol works by exposing the global _wl_pointer_lock to the
>> > client, and when the client wants to lock the pointer, it creates a new
>> > wl_pointer object using the 'lock_pointer' request. A more detailed
>> > description of the protocol seen in pointer-lock.xml file.
>> >
>> > The interface is based on the W3C pointer lock interface [0].
>> >
>> > [0] http://www.w3.org/TR/pointerlock/
>> >
>> > Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
>> > ---
>> >
>> > The part of the implementation I'm not very happy with is the internal
>> > API change: the extra argument in the pointer lock motion callback used
>> > to determine if the motion event was a result of a relative motion or an
>> > absolute motion. In this implementation absolute events are simply
>> > ignored as they don't tend to behave in any sensible way. One could
>> > generate relative motion events from absolute ones as done from a
>> > touchpad, but one would need some kind of threshold as there are no
>> > "touch down" or "touch up" events.
>> >
>> > With backends where relative and absolute events are indistinguishable
>> > (X11, Wayland) is tricker, as there is no way to know whether the event
>> > is suitable or not. One could also just let the client deal with it
>> > making "detached" absolute motions just result in very long vectors.
>> >
>> >
>> > Jonas
>> >
>> > Makefile.am | 7 +-
>> > desktop-shell/exposay.c | 2 +-
>> > desktop-shell/shell.c | 10 +-
>> > protocol/pointer-lock.xml | 85 ++++++++++++++
>> > src/compositor.c | 4 +
>> > src/compositor.h | 21 +++-
>> > src/input.c | 277 +++++++++++++++++++++++++++++++++++++++++++++-
>> > 7 files changed, 394 insertions(+), 12 deletions(-)
>> > create mode 100644 protocol/pointer-lock.xml
>> >
>> > diff --git a/Makefile.am b/Makefile.am
>> > index b2d6893..ed74983 100644
>> > --- a/Makefile.am
>> > +++ b/Makefile.am
>> > @@ -79,7 +79,9 @@ nodist_weston_SOURCES = \
>> > protocol/workspaces-protocol.c \
>> > protocol/workspaces-server-protocol.h \
>> > protocol/scaler-protocol.c \
>> > - protocol/scaler-server-protocol.h
>> > + protocol/scaler-server-protocol.h \
>> > + protocol/pointer-lock-protocol.c \
>> > + protocol/pointer-lock-server-protocol.h
>> >
>> > BUILT_SOURCES += $(nodist_weston_SOURCES)
>> >
>> > @@ -987,7 +989,8 @@ EXTRA_DIST += \
>> > protocol/wayland-test.xml \
>> > protocol/xdg-shell.xml \
>> > protocol/fullscreen-shell.xml \
>> > - protocol/scaler.xml
>> > + protocol/scaler.xml \
>> > + protocol/pointer-lock.xml
>> >
>> > man_MANS = weston.1 weston.ini.5
>> >
>> > diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c
>> > index 4b65cbd..d6ec6a1 100644
>> > --- a/desktop-shell/exposay.c
>> > +++ b/desktop-shell/exposay.c
>> > @@ -340,7 +340,7 @@ exposay_focus(struct weston_pointer_grab *grab)
>> >
>> > static void
>> > exposay_motion(struct weston_pointer_grab *grab, uint32_t time,
>> > - wl_fixed_t x, wl_fixed_t y)
>> > + wl_fixed_t x, wl_fixed_t y, int rel)
>> > {
>> > struct desktop_shell *shell =
>> > container_of(grab, struct desktop_shell, exposay.grab_ptr);
>> > diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
>> > index 3a5a702..35b05d0 100644
>> > --- a/desktop-shell/shell.c
>> > +++ b/desktop-shell/shell.c
>> > @@ -1651,7 +1651,7 @@ constrain_position(struct weston_move_grab *move, int *cx, int *cy)
>> >
>> > static void
>> > move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
>> > - wl_fixed_t x, wl_fixed_t y)
>> > + wl_fixed_t x, wl_fixed_t y, int rel)
>> > {
>> > struct weston_move_grab *move = (struct weston_move_grab *) grab;
>> > struct weston_pointer *pointer = grab->pointer;
>> > @@ -1772,7 +1772,7 @@ struct weston_resize_grab {
>> >
>> > static void
>> > resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
>> > - wl_fixed_t x, wl_fixed_t y)
>> > + wl_fixed_t x, wl_fixed_t y, int rel)
>> > {
>> > struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
>> > struct weston_pointer *pointer = grab->pointer;
>> > @@ -1981,7 +1981,7 @@ busy_cursor_grab_focus(struct weston_pointer_grab *base)
>> >
>> > static void
>> > busy_cursor_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
>> > - wl_fixed_t x, wl_fixed_t y)
>> > + wl_fixed_t x, wl_fixed_t y, int rel)
>> > {
>> > weston_pointer_move(grab->pointer, x, y);
>> > }
>> > @@ -3063,7 +3063,7 @@ popup_grab_focus(struct weston_pointer_grab *grab)
>> >
>> > static void
>> > popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
>> > - wl_fixed_t x, wl_fixed_t y)
>> > + wl_fixed_t x, wl_fixed_t y, int rel)
>> > {
>> > struct weston_pointer *pointer = grab->pointer;
>> > struct wl_resource *resource;
>> > @@ -4649,7 +4649,7 @@ terminate_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
>> >
>> > static void
>> > rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
>> > - wl_fixed_t x, wl_fixed_t y)
>> > + wl_fixed_t x, wl_fixed_t y, int rel)
>> > {
>> > struct rotate_grab *rotate =
>> > container_of(grab, struct rotate_grab, base.grab);
>> > diff --git a/protocol/pointer-lock.xml b/protocol/pointer-lock.xml
>> > new file mode 100644
>> > index 0000000..e00ff80
>> > --- /dev/null
>> > +++ b/protocol/pointer-lock.xml
>> > @@ -0,0 +1,85 @@
>> > +<?xml version="1.0" encoding="UTF-8"?>
>> > +<protocol name="pointer_lock">
>> > +
>> > + <copyright>
>> > + Copyright © 2013 Intel Corporation
>> > + 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_pointer_lock" version="1">
>> > + <description summary="lock pointer to a surface">
>> > + This interface enables clients to lock pointers to a surface in order
>> > + to only receive relative pointer motion events.
>> > + </description>
>> > +
>> > + <request name="lock_pointer">
>> > + <description summary="return pointer object">
>> > + The lock_pointer request lets the client disable pointer
>> > + motion and request relative motion events.
>> > +
>> > + Relative motion events have the same dimension as regular
>> > + absolute motion events on a non-transformed surface, meaning that
>> > + a relative motion event (dx, dy) is equivalent to the transition
>> > + from the absolute coordinate (x y) to (x + dx, y + dy).
>> > +
>> > + If the surface where the pointer is locked is transformed in
>> > + any way (for example shown as a preview, rotated, etc), the
>> > + motion events of the locked pointer object are sent as if the
>> > + surface was not transformed.
>> > +
>> > + This request initializes the pointer lock and activates it in
>> > + case the surface is active. If the surface isn't active when
>> > + the server receives the request, the compositor will activate
>> > + the pointer_lock when the surface is eventually activated. It's
>> > + up to the compositor and its shell to decide when a surface is
>> > + active.
>> > +
>> > + The lock_pointer request will create a new wl_pointer object.
>> > + When the pointer_lock is activated, the original wl_pointer will
>> > + send a leave event and the pointer_lock wl_pointer object
>> > + will send an enter event. The enter event will contain the
>> > + motion delta (0, 0). The wl_pointer object created with this
>> > + request will always sends relative motion deltas, in contrast
>> > + with a regular wl_pointer which sends surface local absolute
>> > + coordinates.
>> > +
>> > + The compositor can suspend the pointer_lock at any time, for
>> > + example when switching to a different application (eg,
>> > + alt-tab), if a notification pops up or when the screensaver
>> > + starts. When this happens the pointer lock wl_pointer will
>> > + send a leave event. When or if the server activates the
>> > + surface again, the client will receive an enter event again.
>> > +
>> > + The client can break the pointer lock at any time by releasing
>> > + the pointer lock wl_pointer using the wl_pointer.release request.
>> > +
>> > + The interface version of the locked wl_pointer object is the same
>> > + as the original wl_pointer object.
>> > + </description>
>> > + <arg name="id" type="new_id" interface="wl_pointer"/>
>> > + <arg name="surface" type="object" interface="wl_surface"/>
>> > + <arg name="pointer" type="object" interface="wl_pointer"/>
>> > + </request>
>> > + </interface>
>> > +</protocol>
>> > diff --git a/src/compositor.c b/src/compositor.c
>> > index a219766..43b4b95 100644
>> > --- a/src/compositor.c
>> > +++ b/src/compositor.c
>> > @@ -3871,6 +3871,8 @@ weston_compositor_init(struct weston_compositor *ec,
>> >
>> > wl_display_init_shm(display);
>> >
>> > + init_pointer_lock(ec);
>> > +
>> > loop = wl_display_get_event_loop(ec->wl_display);
>> > ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
>> > wl_event_source_timer_update(ec->idle_source, ec->idle_time * 1000);
>> > @@ -3890,6 +3892,8 @@ weston_compositor_shutdown(struct weston_compositor *ec)
>> > {
>> > struct weston_output *output, *next;
>> >
>> > + destroy_pointer_lock(ec);
>> > +
>> > wl_event_source_remove(ec->idle_source);
>> > if (ec->input_loop_source)
>> > wl_event_source_remove(ec->input_loop_source);
>> > diff --git a/src/compositor.h b/src/compositor.h
>> > index 9611dea..e33e341 100644
>> > --- a/src/compositor.h
>> > +++ b/src/compositor.h
>> > @@ -242,7 +242,8 @@ struct weston_pointer_grab;
>> > struct weston_pointer_grab_interface {
>> > void (*focus)(struct weston_pointer_grab *grab);
>> > void (*motion)(struct weston_pointer_grab *grab, uint32_t time,
>> > - wl_fixed_t x, wl_fixed_t y);
>> > + wl_fixed_t x, wl_fixed_t y,
>> > + int is_relative);
>> > void (*button)(struct weston_pointer_grab *grab,
>> > uint32_t time, uint32_t button, uint32_t state);
>> > void (*cancel)(struct weston_pointer_grab *grab);
>> > @@ -321,6 +322,7 @@ struct weston_pointer {
>> > struct wl_listener focus_resource_listener;
>> > struct wl_signal focus_signal;
>> > struct wl_signal motion_signal;
>> > + struct wl_signal destroy_signal;
>> >
>> > struct weston_view *sprite;
>> > struct wl_listener sprite_destroy_listener;
>> > @@ -663,6 +665,8 @@ struct weston_compositor {
>> >
>> > int32_t kb_repeat_rate;
>> > int32_t kb_repeat_delay;
>> > +
>> > + struct wl_global *pointer_lock;
>> > };
>> >
>> > struct weston_buffer {
>> > @@ -899,6 +903,15 @@ struct weston_surface {
>> > */
>> > struct wl_list subsurface_list; /* weston_subsurface::parent_link */
>> > struct wl_list subsurface_list_pending; /* ...::parent_link_pending */
>> > +
>> > + struct {
>> > + struct wl_resource *pointer_resource;
>> > + struct weston_pointer_grab grab;
>> > + struct weston_pointer *pointer;
>> > + struct wl_listener pointer_destroy_listener;
>> > + struct wl_listener keyboard_focus_listener;
>> > + struct wl_listener surface_destroy_listener;
>> > + } pointer_lock;
>> > };
>> >
>> > struct weston_subsurface {
>> > @@ -1020,6 +1033,12 @@ void
>> > notify_touch_frame(struct weston_seat *seat);
>> >
>> > void
>> > +init_pointer_lock(struct weston_compositor *compositor);
>> > +
>> > +void
>> > +destroy_pointer_lock(struct weston_compositor *compositor);
>> > +
>> > +void
>> > weston_layer_entry_insert(struct weston_layer_entry *list,
>> > struct weston_layer_entry *entry);
>> > void
>> > diff --git a/src/input.c b/src/input.c
>> > index 530904d..ffdec49 100644
>> > --- a/src/input.c
>> > +++ b/src/input.c
>> > @@ -33,6 +33,7 @@
>> >
>> > #include "../shared/os-compatibility.h"
>> > #include "compositor.h"
>> > +#include "protocol/pointer-lock-server-protocol.h"
>> >
>> > static void
>> > empty_region(pixman_region32_t *region)
>> > @@ -163,7 +164,7 @@ default_grab_pointer_focus(struct weston_pointer_grab *grab)
>> >
>> > static void
>> > default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
>> > - wl_fixed_t x, wl_fixed_t y)
>> > + wl_fixed_t x, wl_fixed_t y, int rel)
>> > {
>> > struct weston_pointer *pointer = grab->pointer;
>> > struct wl_list *resource_list;
>> > @@ -472,6 +473,7 @@ weston_pointer_create(struct weston_seat *seat)
>> > wl_signal_init(&pointer->motion_signal);
>> > wl_signal_init(&pointer->focus_signal);
>> > wl_list_init(&pointer->focus_view_listener.link);
>> > + wl_signal_init(&pointer->destroy_signal);
>> >
>> > pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
>> >
>> > @@ -490,6 +492,8 @@ weston_pointer_create(struct weston_seat *seat)
>> > WL_EXPORT void
>> > weston_pointer_destroy(struct weston_pointer *pointer)
>> > {
>> > + wl_signal_emit(&pointer->destroy_signal, pointer);
>> > +
>> > if (pointer->sprite)
>> > pointer_unmap_sprite(pointer);
>> >
>> > @@ -943,7 +947,8 @@ notify_motion(struct weston_seat *seat,
>> > struct weston_pointer *pointer = seat->pointer;
>> >
>> > weston_compositor_wake(ec);
>> > - pointer->grab->interface->motion(pointer->grab, time, pointer->x + dx, pointer->y + dy);
>> > + pointer->grab->interface->motion(pointer->grab, time,
>> > + pointer->x + dx, pointer->y + dy, 1);
>> > }
>> >
>> > static void
>> > @@ -990,7 +995,7 @@ notify_motion_absolute(struct weston_seat *seat,
>> > struct weston_pointer *pointer = seat->pointer;
>> >
>> > weston_compositor_wake(ec);
>> > - pointer->grab->interface->motion(pointer->grab, time, x, y);
>> > + pointer->grab->interface->motion(pointer->grab, time, x, y, 0);
>> > }
>> >
>> > WL_EXPORT void
>> > @@ -2309,3 +2314,269 @@ weston_seat_release(struct weston_seat *seat)
>> >
>> > wl_signal_emit(&seat->destroy_signal, seat);
>> > }
>> > +
>> > +static void
>> > +pointer_lock_grab_pointer_focus(struct weston_pointer_grab *grab)
>> > +{
>> > +}
>> > +
>> > +static void
>> > +pointer_lock_grab_pointer_motion(struct weston_pointer_grab *grab,
>> > + uint32_t time,
>> > + wl_fixed_t x, wl_fixed_t y, int rel)
>> > +{
>> > + struct weston_surface *surface =
>> > + container_of(grab, struct weston_surface, pointer_lock.grab);
>> > + struct weston_pointer *pointer = surface->pointer_lock.grab.pointer;
>> > + wl_fixed_t dx, dy;
>> > +
>> > + /* Ignore motion events from non-relative sources. */
>> > + if (!rel)
>> > + return;
>> > +
>> > + dx = x - pointer->x;
>> > + dy = y - pointer->y;
>> > + wl_pointer_send_motion(surface->pointer_lock.pointer_resource,
>> > + time, dx, dy);
>> > +}
>> > +
>> > +static void
>> > +pointer_lock_grab_pointer_button(struct weston_pointer_grab *grab,
>> > + uint32_t time, uint32_t button, uint32_t state)
>> > +{
>> > + struct weston_surface *surface =
>> > + container_of(grab, struct weston_surface, pointer_lock.grab);
>> > + struct wl_resource *resource = surface->pointer_lock.pointer_resource;
>> > + uint32_t serial;
>> > +
>> > + serial = wl_display_next_serial(surface->compositor->wl_display);
>> > + wl_pointer_send_button(resource, serial, time, button, state);
>> > +}
>> > +
>> > +static void
>> > +pointer_lock_grab_pointer_cancel(struct weston_pointer_grab *grab)
>> > +{
>> > +}
>> > +
>> > +static const struct weston_pointer_grab_interface
>> > + pointer_lock_grab_interface = {
>> > + pointer_lock_grab_pointer_focus,
>> > + pointer_lock_grab_pointer_motion,
>> > + pointer_lock_grab_pointer_button,
>> > + pointer_lock_grab_pointer_cancel,
>> > +};
>> > +
>> > +static void
>> > +pointer_lock_pointer_set_cursor(struct wl_client *client,
>> > + struct wl_resource *resource,
>> > + uint32_t serial,
>> > + struct wl_resource *surface_resource,
>> > + int32_t x, int32_t y)
>> > +{
>> > +}
>> > +
>> > +static void
>> > +pointer_lock_pointer_release(struct wl_client *client,
>> > + struct wl_resource *resource)
>> > +{
>> > + wl_resource_destroy(resource);
>> > +}
>> > +
>> > +static const struct wl_pointer_interface pointer_lock_pointer_interface = {
>> > + pointer_lock_pointer_set_cursor,
>> > + pointer_lock_pointer_release
>> > +};
>> > +
>> > +static void
>> > +lock_pointer(struct weston_surface *surface, struct weston_pointer *pointer)
>> > +{
>> > + struct weston_compositor *compositor = surface->compositor;
>> > + uint32_t serial;
>> > +
>> > + if (surface->pointer_lock.pointer->focus == surface)
>> > + return;
>> > +
>> > + weston_pointer_set_focus(pointer, NULL, 0, 0);
>> > +
>> > + serial = wl_display_next_serial(compositor->wl_display);
>> > + wl_pointer_send_enter(surface->pointer_lock.pointer_resource,
>> > + serial,
>> > + surface->resource,
>> > + 0, 0);
>> > +
>> > + if (pointer->sprite)
>> > + pointer_unmap_sprite(pointer);
>> > +
>> > + weston_pointer_start_grab(pointer, &surface->pointer_lock.grab);
>> > +}
>> > +
>> > +static void
>> > +unlock_pointer(struct weston_surface *surface)
>> > +{
>> > + struct weston_compositor *compositor = surface->compositor;
>> > + uint32_t serial;
>> > +
>> > + if (surface->pointer_lock.pointer->focus != surface)
>> > + return;
>> > +
>> > + serial = wl_display_next_serial(compositor->wl_display);
>> > + wl_pointer_send_leave(surface->pointer_lock.pointer_resource,
>> > + serial, surface->resource);
>> > + weston_pointer_end_grab(surface->pointer_lock.grab.pointer);
>> > +}
>> > +
>> > +static void
>> > +start_pointer_lock(struct weston_surface *surface,
>> > + struct weston_pointer *pointer)
>> > +{
>> > + struct weston_seat *seat = pointer->seat;
>> > + struct wl_listener *keyboard_focus_listener =
>> > + &surface->pointer_lock.keyboard_focus_listener;
>> > +
>> > + surface->pointer_lock.pointer = pointer;
>> > +
>> > + wl_signal_add(&seat->pointer->destroy_signal,
>> > + &surface->pointer_lock.pointer_destroy_listener);
>> > + wl_signal_add(&surface->destroy_signal,
>> > + &surface->pointer_lock.surface_destroy_listener);
>> > +
>> > + if (seat->keyboard) {
>> > + wl_signal_add(&seat->keyboard->focus_signal,
>> > + keyboard_focus_listener);
>> > + } else {
>> > + wl_list_init(&keyboard_focus_listener->link);
>> > + }
>> > +
>> > + if (seat->keyboard->focus == surface)
>> > + lock_pointer(surface, pointer);
>> > +}
>> > +
>> > +static void
>> > +end_pointer_lock(struct weston_surface *surface)
>> > +{
>> > + unlock_pointer(surface);
>> > + surface->pointer_lock.pointer_resource = NULL;
>> > + surface->pointer_lock.pointer = NULL;
>> > +
>> > + wl_list_remove(&surface->pointer_lock.pointer_destroy_listener.link);
>> > + wl_list_remove(&surface->pointer_lock.keyboard_focus_listener.link);
>> > + wl_list_remove(&surface->pointer_lock.surface_destroy_listener.link);
>> > +}
>> > +
>> > +static void
>> > +pointer_lock_resource_destroyed(struct wl_resource *resource)
>> > +{
>> > + struct weston_surface *surface = wl_resource_get_user_data(resource);
>> > +
>> > + end_pointer_lock(surface);
>> > +}
>> > +
>> > +static void
>> > +pointer_lock_keyboard_focused(struct wl_listener *listener, void *data)
>> > +{
>> > + struct weston_keyboard *keyboard = data;
>> > + struct weston_surface *surface =
>> > + container_of(listener, struct weston_surface,
>> > + pointer_lock.keyboard_focus_listener);
>> > + struct weston_pointer *pointer = surface->pointer_lock.pointer;
>> > +
>> > + if (keyboard->focus == surface)
>> > + lock_pointer(surface, pointer);
>> > + else
>> > + unlock_pointer(surface);
>> > +}
>> > +
>> > +static void
>> > +pointer_lock_pointer_destroyed(struct wl_listener *listener, void *data)
>> > +{
>> > + struct weston_surface *surface =
>> > + container_of(listener, struct weston_surface,
>> > + pointer_lock.pointer_destroy_listener);
>> > +
>> > + end_pointer_lock(surface);
>> > +}
>> > +
>> > +static void
>> > +pointer_lock_surface_destroyed(struct wl_listener *listener, void *data)
>> > +{
>> > + struct weston_surface *surface =
>> > + container_of(listener, struct weston_surface,
>> > + pointer_lock.surface_destroy_listener);
>> > +
>> > + end_pointer_lock(surface);
>> > +}
>> > +
>> > +static void
>> > +pointer_lock_lock_pointer(struct wl_client *client,
>> > + struct wl_resource *resource,
>> > + uint32_t id,
>> > + struct wl_resource *surface_resource,
>> > + struct wl_resource *pointer_resource)
>> > +{
>> > + struct weston_pointer *pointer =
>> > + wl_resource_get_user_data(pointer_resource);
>> > + struct weston_surface *surface;
>> > + struct wl_resource *cr;
>> > +
>> > + surface = wl_resource_get_user_data(surface_resource);
>> > + if (surface->pointer_lock.pointer_resource) {
>> > + wl_resource_post_error(resource,
>> > + WL_DISPLAY_ERROR_INVALID_OBJECT,
>> > + "pointer already locked");
>> > + return;
>> > + }
>> > +
>> > + cr = wl_resource_create(client, &wl_pointer_interface,
>> > + wl_resource_get_version(pointer_resource), id);
>> > + if (cr == NULL) {
>> > + wl_client_post_no_memory(client);
>> > + return;
>> > + }
>> > +
>> > + wl_resource_set_implementation(cr, &pointer_lock_pointer_interface,
>> > + surface,
>> > + pointer_lock_resource_destroyed);
>> > +
>> > + surface->pointer_lock.pointer_resource = cr;
>> > + surface->pointer_lock.grab.interface = &pointer_lock_grab_interface;
>> > + surface->pointer_lock.pointer_destroy_listener.notify =
>> > + pointer_lock_pointer_destroyed;
>> > + surface->pointer_lock.keyboard_focus_listener.notify =
>> > + pointer_lock_keyboard_focused;
>> > + surface->pointer_lock.surface_destroy_listener.notify =
>> > + pointer_lock_surface_destroyed;
>> > +
>> > + start_pointer_lock(surface, pointer);
>> > +}
>> > +
>> > +static const struct _wl_pointer_lock_interface pointer_lock_interface = {
>> > + pointer_lock_lock_pointer
>> > +};
>> > +
>> > +static void
>> > +bind_pointer_lock(struct wl_client *client, void *data,
>> > + uint32_t version, uint32_t id)
>> > +{
>> > + struct wl_resource *resource;
>> > +
>> > + resource = wl_resource_create(client, &_wl_pointer_lock_interface,
>> > + 1, id);
>> > + wl_resource_set_implementation(resource, &pointer_lock_interface,
>> > + NULL, NULL);
>> > +}
>> > +
>> > +void
>> > +init_pointer_lock(struct weston_compositor *compositor)
>> > +{
>> > + compositor->pointer_lock =
>> > + wl_global_create(compositor->wl_display,
>> > + &_wl_pointer_lock_interface, 1,
>> > + NULL,
>> > + bind_pointer_lock);
>> > +}
>> > +
>> > +void
>> > +destroy_pointer_lock(struct weston_compositor *compositor)
>> > +{
>> > + wl_global_destroy(compositor->pointer_lock);
>> > +}
>> > --
>> > 1.8.5.1
>> >
>> > _______________________________________________
>> > wayland-devel mailing list
>> > wayland-devel at lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list