[PATCH 2/2] window: Only release the widget grab when all buttons are released

Bill Spitzak spitzak at gmail.com
Mon Jan 23 14:14:42 PST 2012


This looks a little risky, if there is a bug that eats one of the events.

Under X I never did this because of this worry, instead it checked the 
button-down state in the shift flags of the event to see if all were 
released.

Can't the compositor input send some similar indication? I realize that 
a mask of all the buttons might be impractical with modern input 
handling, but just a flag that says if any buttons are down other than 
the one the event is about would be equally useful.

Neil Roberts wrote:
> This copies the algorithm for keeping track of an implicit grab widget
> when a button is pressed from Wayland. Instead of just tracking a
> single button, Wayland keeps a count of all the mouse buttons that are
> down and only releases the grab when all buttons are released. Without
> this it could lose button release events if a second button is pressed
> and held while the original grab button is held because the grab would
> be lost when the grab button is released. Then the release for the
> second mouse button would go nowhere.
> 
> The code makes sure to only release the grab if it there is a grab
> button so that it won't release grabs initiated from window_show_menu.
> ---
>  clients/window.c |   12 +++++++++++-
>  1 files changed, 11 insertions(+), 1 deletions(-)
> 
> diff --git a/clients/window.c b/clients/window.c
> index 1356c75..fb6b307 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -164,6 +164,8 @@ struct input {
>  	struct widget *focus_widget;
>  	struct widget *grab;
>  	uint32_t grab_button;
> +	/* Number of buttons that are held down */
> +	uint32_t button_count;
>  
>  	struct wl_data_device *data_device;
>  	struct data_offer *drag_offer;
> @@ -1524,6 +1526,11 @@ input_handle_button(void *data,
>  	struct input *input = data;
>  	struct widget *widget;
>  
> +	if (state)
> +		input->button_count++;
> +	else
> +		input->button_count--;
> +
>  	if (input->focus_widget && input->grab == NULL && state)
>  		input_grab(input, input->focus_widget, button);
>  
> @@ -1534,7 +1541,10 @@ input_handle_button(void *data,
>  					  button, state,
>  					  input->grab->user_data);
>  
> -	if (input->grab && input->grab_button == button && !state)
> +	/* If we were grabbing because of a button press but there are
> +	 * no longer any buttons being pressed then release the
> +	 * grab */
> +	if (input->grab && input->grab_button != 0 && input->button_count == 0)
>  		input_ungrab(input, time);
>  }
>  


More information about the wayland-devel mailing list