ecore/wayland: Send a mouse up event when the implicit grab starts. 60/13660/2
authorRafael Antognolli <rafael.antognolli@intel.com>
Wed, 11 Dec 2013 21:01:28 +0000 (19:01 -0200)
committerRusty Lynch <rusty.lynch@intel.com>
Wed, 11 Dec 2013 21:56:21 +0000 (13:56 -0800)
The previous workaround used to send a mouse up event to the
application, using the pointer enter callback to determine when an
implicit grab has finished.  This was "simulating" a mouse up event when
the surface move or resize finished.

However, this doesn't work for touch-based move. The pointer enter isn't
emitted, because the wl_touch interface doesn't have the concept of a
pointer.

Changing this code to make it more similar to what Weston's toytoolkit
does, the mouse up event is sent as soon as the move or resize grab
starts. After that, the compositor takes care of the move/resize almost
entirely.

Change-Id: Ib8daac999137be2fd1e66f82aa3b07b474666a88
Signed-off-by: Rafael Antognolli <rafael.antognolli@intel.com>
src/lib/ecore_evas/ecore_evas_wayland_egl.c
src/lib/ecore_evas/ecore_evas_wayland_shm.c
src/lib/ecore_wayland/Ecore_Wayland.h
src/lib/ecore_wayland/ecore_wl_input.c
src/lib/ecore_wayland/ecore_wl_private.h
src/lib/ecore_wayland/ecore_wl_window.c

index 89abd8e..5d34943 100644 (file)
@@ -1001,7 +1001,6 @@ _ecore_evas_wayland_egl_resize(Ecore_Evas *ee, int location)
                ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
           }
 
-        ee->engine.wl.win->resizing = EINA_TRUE;
         ecore_wl_window_resize(ee->engine.wl.win, ee->w, ee->h, location);
      }
 }
@@ -1014,7 +1013,6 @@ _ecore_evas_wayland_egl_move(Ecore_Evas *ee, int x, int y)
    if (!ee) return;
    if (ee->engine.wl.win) 
      {
-        ee->engine.wl.win->moving = EINA_TRUE;
         ecore_wl_window_move(ee->engine.wl.win, x, y);
      }
 }
index 55c411e..626c7f6 100644 (file)
@@ -1180,7 +1180,6 @@ _ecore_evas_wayland_shm_resize(Ecore_Evas *ee, int location)
    if (!ee) return;
    if (ee->engine.wl.win) 
      {
-        ee->engine.wl.win->resizing = EINA_TRUE;
         ecore_wl_window_resize(ee->engine.wl.win, ee->w, ee->h, location);
      }
 }
@@ -1193,7 +1192,6 @@ _ecore_evas_wayland_shm_move(Ecore_Evas *ee, int x, int y)
    if (!ee) return;
    if (ee->engine.wl.win) 
      {
-        ee->engine.wl.win->moving = EINA_TRUE;
         ecore_wl_window_move(ee->engine.wl.win, x, y);
      }
 }
index 4738086..4d1ad25 100644 (file)
@@ -165,6 +165,7 @@ struct _Ecore_Wl_Input
 
    Ecore_Wl_Window *grab;
    unsigned int grab_button;
+   unsigned int grab_timestamp;
 
    Ecore_Wl_Dnd_Source *drag_source;
    Ecore_Wl_Dnd_Source *selection_source;
@@ -211,8 +212,6 @@ struct _Ecore_Wl_Window
    /* Eina_Bool resize_scheduled : 1; */
    Eina_Bool alpha : 1;
    Eina_Bool transparent : 1;
-   Eina_Bool moving : 1;
-   Eina_Bool resizing : 1;
 
    Ecore_Wl_Window_Type type;
    Ecore_Wl_Window_Buffer_Type buffer_type;
index 07b9a26..3c380c5 100644 (file)
@@ -150,6 +150,27 @@ ecore_wl_input_ungrab(Ecore_Wl_Input *input)
    input->grab_button = 0;
 }
 
+/* NB: This function should be called just before shell move and shell resize
+ * functions. Those requests will trigger a mouse/touch implicit grab on the
+ * compositor that will prevent the respective mouse/touch up events being
+ * released after the end of the operation. This function checks if such grab
+ * is in place for those windows and, if so, emit the respective mouse up
+ * event. It's a workaround to the fact that wayland doesn't inform the
+ * application about this move or resize grab being finished.
+ */
+void
+_ecore_wl_input_grab_release(Ecore_Wl_Input *input, Ecore_Wl_Window *win)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   if (!input) return;
+   if (input->grab != win) return;
+
+   _ecore_wl_input_mouse_up_send(input, input->grab,
+                                 input->grab_button, input->grab_timestamp);
+   ecore_wl_input_ungrab(input);
+}
+
 EAPI void
 ecore_wl_input_pointer_set(Ecore_Wl_Input *input, struct wl_surface *surface, int hot_x, int hot_y)
 {
@@ -404,7 +425,10 @@ _ecore_wl_input_cb_pointer_button(void *data, struct wl_pointer *pointer __UNUSE
    if (state)
      {
         if ((input->pointer_focus) && (!input->grab) && (state))
-          ecore_wl_input_grab(input, input->pointer_focus, button);
+          {
+             ecore_wl_input_grab(input, input->pointer_focus, button);
+             input->grab_timestamp = timestamp;
+          }
 
         _ecore_wl_input_mouse_down_send(input, input->pointer_focus, 
                                         button, timestamp);
@@ -704,37 +728,6 @@ _ecore_wl_input_cb_pointer_enter(void *data, struct wl_pointer *pointer __UNUSED
 
         _ecore_wl_input_mouse_in_send(input, win, input->timestamp);
      }
-
-   /* NB: This whole 'if' below is a major HACK due to wayland's stupidness 
-    * of not sending a mouse_up (or any notification at all for that matter) 
-    * when a move or resize grab is finished */
-   if (input->grab)
-     {
-        /* NB: This COULD mean a move has finished, or it could mean that 
-         * a 'drag' is being done to a different surface */
-
-        if ((input->grab == win) && (win->moving))
-          {
-             /* NB: 'Fake' a mouse_up for move finished */
-             win->moving = EINA_FALSE;
-             _ecore_wl_input_mouse_up_send(input, win, BTN_LEFT,
-                                           input->timestamp);
-
-             if ((input->grab) && (input->grab_button == BTN_LEFT))
-               ecore_wl_input_ungrab(input);
-          }
-        else if ((input->grab == win) && (win->resizing))
-          {
-             /* NB: 'Fake' a mouse_up for resize finished */
-             win->resizing = EINA_FALSE;
-             _ecore_wl_input_mouse_up_send(input, win, BTN_LEFT,
-                                           input->timestamp);
-
-             if ((input->grab) && (input->grab_button == BTN_LEFT))
-               ecore_wl_input_ungrab(input);
-          }
-        /* FIXME: Test d-n-d and potentially add needed case here */
-     }
 }
 
 static void 
@@ -855,6 +848,12 @@ _ecore_wl_input_cb_touch_down(void *data, struct wl_touch *touch __UNUSED__, uns
    input->sx = wl_fixed_to_int(x);
    input->sy = wl_fixed_to_int(y);
    _ecore_wl_input_cb_pointer_enter(data, NULL, serial, surface, x, y);
+   if ((input->pointer_focus) && (!input->grab))
+     {
+        ecore_wl_input_grab(input, input->pointer_focus, BTN_LEFT);
+        input->grab_timestamp = timestamp;
+     }
+
    _ecore_wl_input_mouse_down_send(input, input->pointer_focus, BTN_LEFT, timestamp);
 }
 
@@ -872,6 +871,8 @@ _ecore_wl_input_cb_touch_up(void *data, struct wl_touch *touch __UNUSED__, unsig
    /* input->timestamp = timestamp; */
    input->display->serial = serial;
    _ecore_wl_input_mouse_up_send(input, input->pointer_focus, BTN_LEFT, timestamp);
+   if ((input->grab) && (input->grab_button == BTN_LEFT))
+     ecore_wl_input_ungrab(input);
 }
 
 static void 
index 40beee1..228f3e7 100644 (file)
@@ -90,6 +90,7 @@ void _ecore_wl_input_add(Ecore_Wl_Display *ewd, unsigned int id);
 void _ecore_wl_input_del(Ecore_Wl_Input *input);
 void _ecore_wl_input_pointer_xy_get(int *x, int *y);
 void _ecore_wl_input_set_selection(Ecore_Wl_Input *input, struct wl_data_source *source);
+void _ecore_wl_input_grab_release(Ecore_Wl_Input *input, Ecore_Wl_Window *win);
 
 void _ecore_wl_dnd_add(Ecore_Wl_Input *input, struct wl_data_device *data_device, struct wl_data_offer *offer);
 void _ecore_wl_dnd_enter(void *data, struct wl_data_device *data_device __UNUSED__, unsigned int timestamp __UNUSED__, struct wl_surface *surface, int x, int y, struct wl_data_offer *offer);
index fd1ccc1..682b402 100644 (file)
@@ -206,6 +206,7 @@ ecore_wl_window_move(Ecore_Wl_Window *win, int x, int y)
 
         if ((!input) || (!input->seat)) return;
 
+        _ecore_wl_input_grab_release(input, win);
         wl_shell_surface_move(win->shell_surface, input->seat,
                               input->display->serial);
      }
@@ -266,6 +267,7 @@ ecore_wl_window_resize(Ecore_Wl_Window *win, int w, int h, int location)
 
         if ((!input) || (!input->seat)) return;
 
+        _ecore_wl_input_grab_release(input, win);
         wl_shell_surface_resize(win->shell_surface, input->seat, 
                                 input->display->serial, location);
      }