redo wl compositor key eventing

* break out key callbacks into EINTERNs
* remove extraneous/unused mouse event handlers
* enforce wl modifier updating in all cases
* ensure keybinds are activated before wl clients receive input
  - block wl client input during grabs

fixes T2565
This commit is contained in:
Mike Blumenkrantz 2015-07-21 14:27:29 -04:00
parent d2fce4ce27
commit 5c00c1009b
3 changed files with 142 additions and 148 deletions

View File

@ -94,7 +94,13 @@ _e_comp_canvas_cb_mouse_wheel(void *d EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Obj
static Eina_Bool
_e_comp_cb_key_down(void *data EINA_UNUSED, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
{
if (e_menu_grab_window_get()) return ECORE_CALLBACK_RENEW;
if (e_menu_grab_window_get() || e_comp->input_key_grabs)
{
#ifdef HAVE_WAYLAND
e_comp_wl_key_down(ev);
#endif
return ECORE_CALLBACK_RENEW;
}
if ((e_comp->comp_type == E_PIXMAP_TYPE_X) && (ev->event_window != e_comp->root))
{
E_Client *ec;
@ -107,15 +113,29 @@ _e_comp_cb_key_down(void *data EINA_UNUSED, int ev_type EINA_UNUSED, Ecore_Event
*/
if ((!ec) || (ev->event_window != e_comp->ee_win)) return ECORE_CALLBACK_RENEW;
}
return !e_bindings_key_down_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(e_comp), ev);
return !e_bindings_key_down_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(e_comp), ev)
#ifdef HAVE_WAYLAND
&& !e_comp_wl_key_down(ev)
#endif
;
}
static Eina_Bool
_e_comp_cb_key_up(void *data EINA_UNUSED, int ev_type EINA_UNUSED, Ecore_Event_Key *ev)
{
if (e_menu_grab_window_get()) return ECORE_CALLBACK_RENEW;
if (e_menu_grab_window_get() || e_comp->input_key_grabs)
{
#ifdef HAVE_WAYLAND
e_comp_wl_key_up(ev);
#endif
return ECORE_CALLBACK_RENEW;
}
if ((e_comp->comp_type == E_PIXMAP_TYPE_X) && (ev->event_window != e_comp->root)) return ECORE_CALLBACK_PASS_ON;
return !e_bindings_key_up_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(e_comp), ev);
return !e_bindings_key_up_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(e_comp), ev)
#ifdef HAVE_WAYLAND
&& !e_comp_wl_key_up(ev)
#endif
;
}
////////////////////////////////////

View File

@ -843,143 +843,13 @@ _e_comp_wl_cb_comp_object_add(void *data EINA_UNUSED, int type EINA_UNUSED, E_Ev
return ECORE_CALLBACK_RENEW;
}
static void
_e_comp_wl_cb_key_down(void *event)
{
E_Comp_Wl_Data *cdata;
E_Client *ec;
Ecore_Event_Key *ev;
uint32_t serial, *end, *k, keycode;
ev = event;
if (ev->window != e_comp->ee_win) return;
keycode = (ev->keycode - 8);
if (!(cdata = e_comp->wl_comp_data)) return;
#ifndef E_RELEASE_BUILD
if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
((ev->modifiers & ECORE_EVENT_MODIFIER_ALT) ||
(ev->modifiers & ECORE_EVENT_MODIFIER_ALTGR)) &&
eina_streq(ev->key, "BackSpace"))
exit(0);
#endif
end = (uint32_t *)cdata->kbd.keys.data + (cdata->kbd.keys.size / sizeof(*k));
for (k = cdata->kbd.keys.data; k < end; k++)
{
/* ignore server-generated key repeats */
if (*k == keycode) return;
}
cdata->kbd.keys.size = (const char *)end - (const char *)cdata->kbd.keys.data;
if (!(k = wl_array_add(&cdata->kbd.keys, sizeof(*k))))
{
DBG("wl_array_add: Out of memory\n");
return;
}
*k = keycode;
if ((ec = e_client_focused_get()))
{
if (ec->comp_data->surface && (!e_client_action_get()) && (!e_comp->input_key_grabs))
{
struct wl_client *wc;
struct wl_resource *res;
Eina_List *l;
if (eina_list_count(cdata->kbd.resources))
{
wc = wl_resource_get_client(ec->comp_data->surface);
serial = wl_display_next_serial(cdata->wl.disp);
EINA_LIST_FOREACH(cdata->kbd.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
wl_keyboard_send_key(res, serial, ev->timestamp,
keycode, WL_KEYBOARD_KEY_STATE_PRESSED);
}
}
}
}
/* update modifier state */
e_comp_wl_input_keyboard_state_update(keycode, EINA_TRUE);
}
static void
_e_comp_wl_cb_key_up(void *event)
{
E_Client *ec;
E_Comp_Wl_Data *cdata;
Ecore_Event_Key *ev;
uint32_t serial, *end, *k, keycode;
struct wl_client *wc = NULL;
struct wl_resource *res;
Eina_List *l;
ev = event;
if (ev->window != e_comp->ee_win) return;
keycode = (ev->keycode - 8);
if (!(cdata = e_comp->wl_comp_data)) return;
end = (uint32_t *)cdata->kbd.keys.data + (cdata->kbd.keys.size / sizeof(*k));
for (k = cdata->kbd.keys.data; k < end; k++)
if (*k == keycode) *k = *--end;
cdata->kbd.keys.size = (const char *)end - (const char *)cdata->kbd.keys.data;
ec = e_client_focused_get();
if ((ec) && (ec->comp_data->surface) && (!e_client_action_get()) && (!e_comp->input_key_grabs))
{
wc = wl_resource_get_client(ec->comp_data->surface);
}
if (eina_list_count(cdata->kbd.resources))
{
serial = wl_display_next_serial(cdata->wl.disp);
EINA_LIST_FOREACH(cdata->kbd.resources, l, res)
{
if (wc)
{
if (wl_resource_get_client(res) != wc) continue;
}
wl_keyboard_send_key(res, serial, ev->timestamp,
keycode, WL_KEYBOARD_KEY_STATE_RELEASED);
}
}
/* update modifier state */
e_comp_wl_input_keyboard_state_update(keycode, EINA_FALSE);
}
static void
_e_comp_wl_cb_mouse_move(void *event)
{
E_Comp_Wl_Data *cdata;
Ecore_Event_Mouse_Move *ev;
if (!(cdata = e_comp->wl_comp_data)) return;
ev = event;
cdata->ptr.x = wl_fixed_from_int(ev->x);
cdata->ptr.y = wl_fixed_from_int(ev->y);
}
static Eina_Bool
_e_comp_wl_cb_input_event(void *data EINA_UNUSED, int type, void *ev)
_e_comp_wl_cb_mouse_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
{
_last_event_time = ecore_loop_time_get();
if (type == ECORE_EVENT_KEY_DOWN)
_e_comp_wl_cb_key_down(ev);
else if (type == ECORE_EVENT_KEY_UP)
_e_comp_wl_cb_key_up(ev);
else if (type == ECORE_EVENT_MOUSE_MOVE)
_e_comp_wl_cb_mouse_move(ev);
e_comp->wl_comp_data->ptr.x = wl_fixed_from_int(ev->x);
e_comp->wl_comp_data->ptr.y = wl_fixed_from_int(ev->y);
return ECORE_CALLBACK_RENEW;
}
@ -2728,18 +2598,8 @@ e_comp_wl_init(void)
E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMP_OBJECT_ADD,
_e_comp_wl_cb_comp_object_add, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_KEY_DOWN,
_e_comp_wl_cb_input_event, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_KEY_UP,
_e_comp_wl_cb_input_event, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN,
_e_comp_wl_cb_input_event, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_UP,
_e_comp_wl_cb_input_event, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_MOVE,
_e_comp_wl_cb_input_event, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_WHEEL,
_e_comp_wl_cb_input_event, NULL);
_e_comp_wl_cb_mouse_move, NULL);
/* add hooks to catch e_client events */
e_client_hook_add(E_CLIENT_HOOK_NEW_CLIENT, _e_comp_wl_client_cb_new, NULL);
@ -3101,6 +2961,116 @@ e_comp_wl_output_remove(const char *id)
}
}
EINTERN Eina_Bool
e_comp_wl_key_down(Ecore_Event_Key *ev)
{
E_Comp_Wl_Data *cdata;
E_Client *ec = NULL;
uint32_t serial, *end, *k, keycode;
if ((e_comp_>comp_type != E_PIXMAP_TYPE_WL) || (ev->window != e_comp->ee_win)) return EINA_FALSE;
_last_event_time = ecore_loop_time_get();
keycode = (ev->keycode - 8);
if (!(cdata = e_comp->wl_comp_data)) return EINA_FALSE;
#ifndef E_RELEASE_BUILD
if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
((ev->modifiers & ECORE_EVENT_MODIFIER_ALT) ||
(ev->modifiers & ECORE_EVENT_MODIFIER_ALTGR)) &&
eina_streq(ev->key, "BackSpace"))
exit(0);
#endif
end = (uint32_t *)cdata->kbd.keys.data + (cdata->kbd.keys.size / sizeof(*k));
for (k = cdata->kbd.keys.data; k < end; k++)
{
/* ignore server-generated key repeats */
if (*k == keycode) return EINA_FALSE;
}
cdata->kbd.keys.size = (const char *)end - (const char *)cdata->kbd.keys.data;
if (!(k = wl_array_add(&cdata->kbd.keys, sizeof(*k))))
{
DBG("wl_array_add: Out of memory\n");
return EINA_FALSE;
}
*k = keycode;
if ((!e_client_action_get()) && (!e_comp->input_key_grabs) && (!e_menu_grab_window_get()))
{
ec = e_client_focused_get();
if (ec && ec->comp_data->surface && cdata->kbd.resources)
{
struct wl_client *wc;
struct wl_resource *res;
Eina_List *l;
wc = wl_resource_get_client(ec->comp_data->surface);
serial = wl_display_next_serial(cdata->wl.disp);
EINA_LIST_FOREACH(cdata->kbd.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
wl_keyboard_send_key(res, serial, ev->timestamp,
keycode, WL_KEYBOARD_KEY_STATE_PRESSED);
}
}
}
/* update modifier state */
e_comp_wl_input_keyboard_state_update(keycode, EINA_TRUE);
return !!ec;
}
EINTERN Eina_Bool
e_comp_wl_key_up(Ecore_Event_Key *ev)
{
E_Client *ec = NULL;
E_Comp_Wl_Data *cdata;
uint32_t serial, *end, *k, keycode;
struct wl_resource *res;
Eina_List *l;
if ((e_comp_>comp_type != E_PIXMAP_TYPE_WL) || (ev->window != e_comp->ee_win)) return EINA_FALSE;
_last_event_time = ecore_loop_time_get();
keycode = (ev->keycode - 8);
if (!(cdata = e_comp->wl_comp_data)) return EINA_FALSE;
end = (uint32_t *)cdata->kbd.keys.data + (cdata->kbd.keys.size / sizeof(*k));
for (k = cdata->kbd.keys.data; k < end; k++)
if (*k == keycode) *k = *--end;
cdata->kbd.keys.size = (const char *)end - (const char *)cdata->kbd.keys.data;
if ((!e_client_action_get()) && (!e_comp->input_key_grabs) && (!e_menu_grab_window_get()))
{
struct wl_client *wc = NULL;
ec = e_client_focused_get();
if (ec && ec->comp_data->surface)
{
wc = wl_resource_get_client(ec->comp_data->surface);
}
if (wc && cdata->kbd.resources)
{
serial = wl_display_next_serial(cdata->wl.disp);
EINA_LIST_FOREACH(cdata->kbd.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
wl_keyboard_send_key(res, serial, ev->timestamp,
keycode, WL_KEYBOARD_KEY_STATE_RELEASED);
}
}
}
/* update modifier state */
e_comp_wl_input_keyboard_state_update(keycode, EINA_FALSE);
return !!ec;
}
EINTERN void
e_comp_wl_xwayland_client_queue(E_Client *ec)
{

View File

@ -320,6 +320,10 @@ E_API struct wl_signal e_comp_wl_surface_create_signal_get(void);
E_API double e_comp_wl_idle_time_get(void);
E_API Eina_Bool e_comp_wl_output_init(const char *id, const char *make, const char *model, int x, int y, int w, int h, int pw, int ph, unsigned int refresh, unsigned int subpixel, unsigned int transform);
E_API void e_comp_wl_output_remove(const char *id);
EINTERN Eina_Bool e_comp_wl_key_down(Ecore_Event_Key *ev);
EINTERN Eina_Bool e_comp_wl_key_up(Ecore_Event_Key *ev);
# ifndef HAVE_WAYLAND_ONLY
EINTERN void e_comp_wl_xwayland_client_queue(E_Client *ec);
static inline E_Comp_X_Client_Data *