window: Make press-drag-release menu selection mode work
authorKristian Høgsberg <krh@bitplanet.net>
Tue, 30 Oct 2012 17:45:22 +0000 (13:45 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 30 Oct 2012 17:45:31 +0000 (13:45 -0400)
The intended behavior is that a quick click (press and then release
within 500ms) just pops up the menu and doesn't select anything.  Then
we can mouse around and and click to select an item.  Alternatively, a
click and hold (ie press and release after 500ms) lets you press right
button, mouse down on the menu item you want and release to select it.
This is how menus work in most toolkits.

The handling in weston is fine, it's there to handle the case where
the button release happens outside any client window, since the client
doesn't get those events.  If such a release happens late or we get a
second release outside the popup window we shut down the popup.

The problem is in toytoolkit, where we need to select the item if we
get a release within 500ms or if we get a second release.  A second
release is the case where the first release came after 500ms and
didn't pop down the menu, and the second release event is from a click
on a menu item.

https://bugs.freedesktop.org/show_bug.cgi?id=52456

clients/window.c

index 7b5e351..e699fbc 100644 (file)
@@ -304,6 +304,7 @@ struct menu {
        uint32_t time;
        int current;
        int count;
+       int release_count;
        menu_func_t func;
 };
 
@@ -3350,8 +3351,8 @@ menu_button_handler(struct widget *widget,
 {
        struct menu *menu = data;
 
-       if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
-           time - menu->time > 500) {
+       if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
+           (menu->release_count > 0 || time - menu->time > 500)) {
                /* Either relase after press-drag-release or
                 * click-motion-click. */
                menu->func(menu->window->parent, 
@@ -3359,6 +3360,9 @@ menu_button_handler(struct widget *widget,
                input_ungrab(input);
                menu_destroy(menu);
        }
+
+       if (state == WL_POINTER_BUTTON_STATE_RELEASED)
+               menu->release_count++;
 }
 
 static void
@@ -3426,6 +3430,7 @@ window_show_menu(struct display *display,
        menu->widget = window_add_widget(menu->window, menu);
        menu->entries = entries;
        menu->count = count;
+       menu->release_count = 0;
        menu->current = -1;
        menu->time = time;
        menu->func = func;