ecore/wayland: Send a mouse up event when the implicit grab starts.

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.

Should fix T468.
This commit is contained in:
Rafael Antognolli 2013-11-29 16:04:18 -02:00
parent 2c95c5ee1d
commit a14ee372e0
3 changed files with 38 additions and 37 deletions

View File

@ -165,6 +165,28 @@ 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->pointer_focus,
0, input->grab_button, input->grab_timestamp);
ecore_wl_input_ungrab(input);
}
static void
_pointer_update_stop(Ecore_Wl_Input *input)
{
@ -497,7 +519,10 @@ _ecore_wl_input_cb_pointer_button(void *data, struct wl_pointer *pointer EINA_UN
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;
}
if (input->pointer_focus)
_ecore_wl_input_mouse_down_send(input, input->pointer_focus,
@ -861,37 +886,6 @@ _ecore_wl_input_cb_pointer_enter(void *data, struct wl_pointer *pointer EINA_UNU
_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, 0,
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, 0,
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
@ -1011,6 +1005,12 @@ _ecore_wl_input_cb_touch_down(void *data, struct wl_touch *touch EINA_UNUSED, un
_ecore_wl_input_mouse_move_send(input, input->pointer_focus, timestamp, id);
_ecore_wl_input_cb_pointer_enter(data, NULL, serial, surface, x, y);
if ((input->touch_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->touch_focus,
id, 0, timestamp);
}
@ -1029,6 +1029,8 @@ _ecore_wl_input_cb_touch_up(void *data, struct wl_touch *touch EINA_UNUSED, unsi
input->display->serial = serial;
_ecore_wl_input_mouse_up_send(input, input->touch_focus, id, 0, timestamp);
if ((input->grab) && (input->grab_button == BTN_LEFT))
ecore_wl_input_ungrab(input);
}
static void

View File

@ -129,8 +129,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;
Eina_Bool has_buffer : 1;
Ecore_Wl_Window_Type type;
@ -183,6 +181,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;
@ -258,6 +257,7 @@ void _ecore_wl_output_del(Ecore_Wl_Output *output);
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_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, unsigned int timestamp, struct wl_surface *surface, int x, int y, struct wl_data_offer *offer);

View File

@ -136,8 +136,6 @@ ecore_wl_window_move(Ecore_Wl_Window *win, int x, int y)
if (!win) return;
win->moving = EINA_TRUE;
ecore_wl_window_update_location(win, x, y);
if (win->shell_surface)
@ -155,6 +153,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);
}
@ -167,7 +166,6 @@ ecore_wl_window_resize(Ecore_Wl_Window *win, int w, int h, int location)
if (!win) return;
win->resizing = EINA_TRUE;
ecore_wl_window_update_size(win, w, h);
if (win->shell_surface)
@ -185,6 +183,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);
}