diff --git a/src/modules/comp/e_mod_comp_wl.h b/src/modules/comp/e_mod_comp_wl.h index afcf5732a..207003dd6 100644 --- a/src/modules/comp/e_mod_comp_wl.h +++ b/src/modules/comp/e_mod_comp_wl.h @@ -151,6 +151,7 @@ struct _Wayland_Input struct wl_input_device input_device; int32_t hotspot_x, hotspot_y; struct wl_list link; + uint32_t modifier_state; }; struct wl_shell diff --git a/src/modules/comp/e_mod_comp_wl_comp.c b/src/modules/comp/e_mod_comp_wl_comp.c index 55e59b5d5..0d057668e 100644 --- a/src/modules/comp/e_mod_comp_wl_comp.c +++ b/src/modules/comp/e_mod_comp_wl_comp.c @@ -4,15 +4,45 @@ # include "e_mod_comp_wl.h" # include "e_mod_comp_wl_comp.h" # include "e_mod_comp_wl_shm.h" +# include "e_mod_comp_wl_input.h" # include "e_mod_comp_wl_surface.h" #endif +#ifdef __linux__ +# include +#else +# define BTN_LEFT 0x110 +# define BTN_RIGHT 0x111 +# define BTN_MIDDLE 0x112 +# define BTN_SIDE 0x113 +# define BTN_EXTRA 0x114 +# define BTN_FORWARD 0x115 +# define BTN_BACK 0x116 +#endif + +#define MODIFIER_CTRL (1 << 8) +#define MODIFIER_ALT (1 << 9) +#define MODIFIER_SUPER (1 << 10) + /* local function prototypes */ static Eina_Bool _e_mod_comp_wl_comp_egl_init(void); static void _e_mod_comp_wl_comp_egl_shutdown(void); static void _e_mod_comp_wl_comp_destroy(void); static void _e_mod_comp_wl_comp_bind(struct wl_client *client, void *data, uint32_t version __UNUSED__, uint32_t id); static void _e_mod_comp_wl_comp_surface_create(struct wl_client *client, struct wl_resource *resource, uint32_t id); +static Eina_Bool _e_mod_comp_wl_cb_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event); +static Eina_Bool _e_mod_comp_wl_cb_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event); +static Eina_Bool _e_mod_comp_wl_cb_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event); +static Eina_Bool _e_mod_comp_wl_cb_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event); +static Eina_Bool _e_mod_comp_wl_cb_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event); +static Eina_Bool _e_mod_comp_wl_cb_mouse_down(void *data __UNUSED__, int type __UNUSED__, void *event); +static Eina_Bool _e_mod_comp_wl_cb_mouse_up(void *data __UNUSED__, int type __UNUSED__, void *event); +static Eina_Bool _e_mod_comp_wl_cb_key_down(void *data __UNUSED__, int type __UNUSED__, void *event); +static Eina_Bool _e_mod_comp_wl_cb_key_up(void *data __UNUSED__, int type __UNUSED__, void *event); + +static void _e_mod_comp_wl_comp_repick(struct wl_input_device *device, uint32_t timestamp); +static Wayland_Surface *_e_mod_comp_wl_comp_pick_surface(int32_t x __UNUSED__, int32_t y __UNUSED__, int32_t *sx, int32_t *sy); +static void _e_mod_comp_wl_comp_update_modifier(Wayland_Input *input, uint32_t key, uint32_t state); /* wayland interfaces */ static const struct wl_compositor_interface _wl_comp_interface = @@ -29,6 +59,7 @@ static const struct wl_surface_interface _wl_surface_interface = /* private variables */ static Wayland_Compositor *_wl_comp; +static Eina_List *_wl_event_handlers = NULL; Eina_Bool e_mod_comp_wl_comp_init(void) @@ -93,6 +124,43 @@ e_mod_comp_wl_comp_init(void) wl_list_init(&_wl_comp->surfaces); + _wl_event_handlers = + eina_list_append(_wl_event_handlers, + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, + _e_mod_comp_wl_cb_focus_in, NULL)); + _wl_event_handlers = + eina_list_append(_wl_event_handlers, + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, + _e_mod_comp_wl_cb_focus_out, NULL)); + _wl_event_handlers = + eina_list_append(_wl_event_handlers, + ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN, + _e_mod_comp_wl_cb_mouse_in, NULL)); + _wl_event_handlers = + eina_list_append(_wl_event_handlers, + ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT, + _e_mod_comp_wl_cb_mouse_out, NULL)); + _wl_event_handlers = + eina_list_append(_wl_event_handlers, + ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, + _e_mod_comp_wl_cb_mouse_move, NULL)); + _wl_event_handlers = + eina_list_append(_wl_event_handlers, + ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, + _e_mod_comp_wl_cb_mouse_down, NULL)); + _wl_event_handlers = + eina_list_append(_wl_event_handlers, + ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, + _e_mod_comp_wl_cb_mouse_up, NULL)); + _wl_event_handlers = + eina_list_append(_wl_event_handlers, + ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, + _e_mod_comp_wl_cb_key_down, NULL)); + _wl_event_handlers = + eina_list_append(_wl_event_handlers, + ecore_event_handler_add(ECORE_EVENT_KEY_UP, + _e_mod_comp_wl_cb_key_up, NULL)); + return EINA_TRUE; } @@ -101,6 +169,8 @@ e_mod_comp_wl_comp_shutdown(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); + E_FREE_LIST(_wl_event_handlers, ecore_event_handler_del); + if (_wl_comp) _wl_comp->destroy(); } @@ -242,3 +312,332 @@ _e_mod_comp_wl_comp_surface_create(struct wl_client *client, struct wl_resource wl_client_add_resource(client, &ws->surface.resource); } + + +static Eina_Bool +_e_mod_comp_wl_cb_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Wayland_Input *input; + Wayland_Surface *ws; + Ecore_X_Event_Window_Focus_In *ev; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ev = event; + if (wl_list_empty(&_wl_comp->surfaces)) return ECORE_CALLBACK_PASS_ON; + + input = e_mod_comp_wl_input_get(); + wl_list_for_each(ws, &_wl_comp->surfaces, link) + { + if (((ws->win) && (ws->win->border)) + && (ws->win->border->win == ev->win)) + { + wl_input_device_set_keyboard_focus(&input->input_device, + &ws->surface, ev->time); + break; + } + } + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_mod_comp_wl_cb_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Wayland_Input *input; + Ecore_X_Event_Window_Focus_Out *ev; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ev = event; + input = e_mod_comp_wl_input_get(); + wl_input_device_set_keyboard_focus(&input->input_device, NULL, ev->time); + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_mod_comp_wl_cb_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Wayland_Input *input; + Ecore_X_Event_Mouse_In *ev; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ev = event; + if (wl_list_empty(&_wl_comp->surfaces)) return ECORE_CALLBACK_PASS_ON; + input = e_mod_comp_wl_input_get(); + input->input_device.x = ev->x; + input->input_device.y = ev->y; + + _e_mod_comp_wl_comp_repick(&input->input_device, ev->time); + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_mod_comp_wl_cb_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Wayland_Input *input; + Ecore_X_Event_Mouse_Out *ev; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ev = event; + if (wl_list_empty(&_wl_comp->surfaces)) return ECORE_CALLBACK_PASS_ON; + input = e_mod_comp_wl_input_get(); + + _e_mod_comp_wl_comp_repick(&input->input_device, ev->time); + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_mod_comp_wl_cb_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Wayland_Input *input; + Ecore_Event_Mouse_Move *ev; + struct wl_input_device *device; + const struct wl_grab_interface *interface; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ev = event; + if (wl_list_empty(&_wl_comp->surfaces)) return ECORE_CALLBACK_PASS_ON; + + input = e_mod_comp_wl_input_get(); + device = &input->input_device; + device->x = ev->x; + device->y = ev->y; + + _e_mod_comp_wl_comp_repick(device, ev->timestamp); + + interface = device->grab->interface; + interface->motion(device->grab, ev->timestamp, + device->grab->x, device->grab->y); + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_mod_comp_wl_cb_mouse_down(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Wayland_Input *input; + Ecore_Event_Mouse_Button *ev; + struct wl_input_device *device; + int btn = 0; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ev = event; + if (wl_list_empty(&_wl_comp->surfaces)) return ECORE_CALLBACK_PASS_ON; + + switch (ev->buttons) + { + case 1: + btn = ev->buttons + BTN_LEFT - 1; + break; + case 2: + btn = BTN_MIDDLE; + break; + case 3: + btn = BTN_RIGHT; + break; + } + + input = e_mod_comp_wl_input_get(); + device = &input->input_device; + if (device->button_count == 0) + { + device->grab_button = btn; + device->grab_time = ev->timestamp; + device->grab_x = device->x; + device->grab_y = device->y; + } + + device->button_count++; + + /* TODO: Run binding ?? */ + device->grab->interface->button(device->grab, ev->timestamp, btn, 1); + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_mod_comp_wl_cb_mouse_up(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Wayland_Input *input; + Ecore_Event_Mouse_Button *ev; + struct wl_input_device *device; + int btn = 0; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ev = event; + if (wl_list_empty(&_wl_comp->surfaces)) return ECORE_CALLBACK_PASS_ON; + + switch (ev->buttons) + { + case 1: + btn = ev->buttons + BTN_LEFT - 1; + break; + case 2: + btn = BTN_MIDDLE; + break; + case 3: + btn = BTN_RIGHT; + break; + } + + input = e_mod_comp_wl_input_get(); + device = &input->input_device; + + device->button_count--; + + /* TODO: Run binding ?? */ + device->grab->interface->button(device->grab, ev->timestamp, btn, 0); + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_mod_comp_wl_cb_key_down(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Wayland_Input *input; + Ecore_Event_Key *ev; + struct wl_input_device *device; + uint32_t *k, *end, key = 0; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ev = event; + if (wl_list_empty(&_wl_comp->surfaces)) return ECORE_CALLBACK_PASS_ON; + + input = e_mod_comp_wl_input_get(); + device = &input->input_device; + + key = ecore_x_keysym_keycode_get(ev->key); + + _e_mod_comp_wl_comp_update_modifier(input, key, 1); + + end = device->keys.data + device->keys.size; + for (k = device->keys.data; k < end; k++) + if (*k == key) *k = *--end; + device->keys.size = (void *)end - device->keys.data; + + k = wl_array_add(&device->keys, sizeof(*k)); + *k = key; + + if (device->keyboard_focus_resource) + wl_resource_post_event(device->keyboard_focus_resource, + WL_INPUT_DEVICE_KEY, ev->timestamp, key, 1); + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_e_mod_comp_wl_cb_key_up(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Wayland_Input *input; + Ecore_Event_Key *ev; + struct wl_input_device *device; + uint32_t *k, *end, key = 0; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ev = event; + if (wl_list_empty(&_wl_comp->surfaces)) return ECORE_CALLBACK_PASS_ON; + + input = e_mod_comp_wl_input_get(); + device = &input->input_device; + + key = ecore_x_keysym_keycode_get(ev->key); + + _e_mod_comp_wl_comp_update_modifier(input, key, 0); + + end = device->keys.data + device->keys.size; + for (k = device->keys.data; k < end; k++) + if (*k == key) *k = *--end; + device->keys.size = (void *)end - device->keys.data; + + /* k = wl_array_add(&device->keys, sizeof(*k)); */ + /* *k = ev->key; */ + + if (device->keyboard_focus_resource) + wl_resource_post_event(device->keyboard_focus_resource, + WL_INPUT_DEVICE_KEY, ev->timestamp, key, 0); + + return ECORE_CALLBACK_PASS_ON; +} + +static void +_e_mod_comp_wl_comp_repick(struct wl_input_device *device, uint32_t timestamp) +{ + Wayland_Surface *ws, *focus; + + ws = + _e_mod_comp_wl_comp_pick_surface(device->x, device->y, + &device->current_x, &device->current_y); + if (&ws->surface != device->current) + { + const struct wl_grab_interface *interface; + + interface = device->grab->interface; + interface->focus(device->grab, timestamp, &ws->surface, + device->current_x, device->current_y); + device->current = &ws->surface; + } + + if ((focus = (Wayland_Surface *)device->grab->focus)) + { + device->grab->x = device->x - focus->x; + device->grab->y = device->y - focus->y; + } +} + +static Wayland_Surface * +_e_mod_comp_wl_comp_pick_surface(int32_t x __UNUSED__, int32_t y __UNUSED__, int32_t *sx, int32_t *sy) +{ + Wayland_Surface *ws; + + if (wl_list_empty(&_wl_comp->surfaces)) return NULL; + wl_list_for_each(ws, &_wl_comp->surfaces, link) + { + if (ws->surface.resource.client == NULL) continue; + if ((0 <= *sx) && (*sx < ws->w) && + (0 <= *sy) && (*sy < ws->h)) + return ws; + } + + return NULL; +} + +static void +_e_mod_comp_wl_comp_update_modifier(Wayland_Input *input, uint32_t key, uint32_t state) +{ + uint32_t mod; + + switch (key) + { + case KEY_LEFTCTRL: + case KEY_RIGHTCTRL: + mod = MODIFIER_CTRL; + break; + case KEY_LEFTALT: + case KEY_RIGHTALT: + mod = MODIFIER_ALT; + break; + case KEY_LEFTMETA: + case KEY_RIGHTMETA: + mod = MODIFIER_SUPER; + break; + default: + mod = 0; + break; + } + + if (state) + input->modifier_state |= mod; + else + input->modifier_state &= ~mod; +}