[PATCH 5/5] resizor: Lock pointer on click

Kristian Høgsberg hoegsberg at gmail.com
Thu Feb 28 09:42:42 PST 2013


On Tue, Feb 26, 2013 at 02:16:37PM +0200, Pekka Paalanen wrote:
> On Mon, 25 Feb 2013 21:33:25 -0500
> Kristian Høgsberg <krh at bitplanet.net> wrote:
> 
> > We add a resize mode to resizor where you can click to resize it using
> > pointer lock and relative motion.
> > ---
> >  clients/resizor.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 74 insertions(+)
> > 
> > diff --git a/clients/resizor.c b/clients/resizor.c
> > index 27879a0..563a1ac 100644
> > --- a/clients/resizor.c
> > +++ b/clients/resizor.c
> > @@ -47,6 +47,7 @@ struct resizor {
> >  	struct spring width;
> >  	struct spring height;
> >  	struct wl_callback *frame_callback;
> > +	struct wl_pointer *pointer_lock;
> >  };
> >  
> >  static void
> > @@ -213,14 +214,87 @@ show_menu(struct resizor *resizor, struct input *input, uint32_t time)
> >  			 x - 10, y - 10, menu_func, entries, 4);
> >  }
> >  
> > +
> > +static void
> > +pointer_handle_enter(void *data, struct wl_pointer *pointer,
> > +		     uint32_t serial, struct wl_surface *surface,
> > +		     wl_fixed_t sx_w, wl_fixed_t sy_w)
> > +{
> > +}
> > +
> > +static void
> > +pointer_handle_leave(void *data, struct wl_pointer *pointer,
> > +		     uint32_t serial, struct wl_surface *surface)
> > +{
> > +}
> > +
> > +static void
> > +pointer_handle_motion(void *data, struct wl_pointer *pointer,
> > +		      uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
> > +{
> > +	struct resizor *resizor = data;
> > +
> > +	resizor->width.current += wl_fixed_to_double(sx_w);
> > +	resizor->width.previous = resizor->width.current;
> > +	resizor->width.target = resizor->width.current;
> > +
> > +	resizor->height.current += wl_fixed_to_double(sy_w);
> > +	resizor->height.previous = resizor->height.current;
> > +	resizor->height.target = resizor->height.current;
> > +
> > +	widget_schedule_resize(resizor->widget,
> > +			       resizor->width.current,
> > +			       resizor->height.current);
> > +}
> > +
> > +static void
> > +pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
> > +		      uint32_t time, uint32_t button, uint32_t state)
> > +{
> > +	struct resizor *resizor = data;
> > +
> > +	if (state != WL_POINTER_BUTTON_STATE_PRESSED)
> > +		return;
> > +
> > +	wl_pointer_release(resizor->pointer_lock);
> > +	resizor->pointer_lock = NULL;
> > +}
> > +
> > +static void
> > +pointer_handle_axis(void *data, struct wl_pointer *pointer,
> > +		    uint32_t time, uint32_t axis, wl_fixed_t value)
> > +{
> > +}
> > +
> > +static const struct wl_pointer_listener pointer_listener = {
> > +	pointer_handle_enter,
> > +	pointer_handle_leave,
> > +	pointer_handle_motion,
> > +	pointer_handle_button,
> > +	pointer_handle_axis,
> > +};
> > +
> >  static void
> >  button_handler(struct widget *widget,
> >  	       struct input *input, uint32_t time,
> >  	       uint32_t button, enum wl_pointer_button_state state, void *data)
> >  {
> >  	struct resizor *resizor = data;
> > +	struct wl_seat *seat;
> > +	struct wl_surface *surface;
> >  
> >  	switch (button) {
> > +	case BTN_LEFT:
> > +		if (state != WL_POINTER_BUTTON_STATE_PRESSED)
> > +			break;
> > +
> > +		seat = input_get_seat(input);
> > +		surface = window_get_wl_surface(resizor->window);
> > +		resizor->pointer_lock = wl_seat_lock_pointer(seat, surface);
> > +		wl_pointer_add_listener(resizor->pointer_lock,
> > +					&pointer_listener, resizor);
> > +		break;
> > +
> >  	case BTN_RIGHT:
> >  		if (state == WL_POINTER_BUTTON_STATE_PRESSED)
> >  			show_menu(resizor, input, time);
> 
> Hi Kristian,
> 
> on the first try without any tricks, the pointer lock seems to work
> nicely. However, after I click again to release the lock, I cannot
> afterwards interact with the decorations. Any left-click will always
> just activate the pointer lock again. Also highlighting the window
> buttons doesn't work. The same happens with both x11 and drm backends.
> If I right-click to bring out the titlebar context menu and dismiss it,
> the situation is fixed.

Ah, yes, the toytoolkit widget needs to release its grab.  Fixed here.
It's the same case as when we click the titlebar and call
shell_surface.move().

> Anyway, the demo proves that the protocol runs.
> 
> Another thing, from the protocol dump:
> 
> [1989156.722] wl_pointer at 21.motion(375651311, 183.000000, 188.000000)
> [1989771.085] wl_shell_surface at 15.ping(405)
> [1989771.132]  -> wl_shell_surface at 15.pong(405)
> [1989771.155] wl_pointer at 21.button(406, 375651925, 272, 1)
> [1989771.202]  -> wl_seat at 7.lock_pointer(new id wl_pointer at 16, wl_surface at 14)
> [1989771.530] wl_pointer at 21.leave(407, wl_surface at 14)
> [1989771.582] wl_pointer at 16.enter(408, wl_surface at 14, 183.000000, 188.000000)
> [1989826.518] wl_pointer at 16.motion(375651981, 0.000000, 1.000000)
> <client renders a new size>
> [1989914.548] wl_pointer at 16.button(412, 375652069, 272, 0)
> 
> I see normal wl_pointer button down, leave. Lock wl_pointer enter,
> move, button up. Button down and up are both non-matching, since they
> are from different wl_pointer object. Is this intended behaviour?
> I'm not too clear on what grabs should eat which input events when.

Yes, this is intended behavior and similar to the asymmetry we have
when the shell steals the passive grab to move or resize a surface.

Kristian


More information about the wayland-devel mailing list