On Wed, Sep 17, 2014 at 11:16:06PM +0300, Giulio Camuffo wrote: > 2014-09-17 23:11 GMT+03:00 Jonas Ådahl <jad...@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.
Then, another example, (of a non-final protoc though): wl_input_method_context.grab_keyboard vs wl_seat.get_keyboard, both creating wl_keyboard objects. Jonas > > > -- > Giulio > > > > > > > > Jonas > > > >> > >> > >> -- > >> Giulio > >> > >> > >> 2014-09-17 22:39 GMT+03:00 Jonas Ådahl <jad...@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 <jad...@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@lists.freedesktop.org > >> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel