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

Neil Roberts neil at linux.intel.com
Mon Jan 23 11:11:19 PST 2012

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,
-	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