E Comp (wayland): Get important input from X11 (focus in/out, mouse

in/out, mouse down/up, key down/up, etc, etc) and pass it on to
wayland clients in the form that they expect (wayland events).



SVN revision: 67593
This commit is contained in:
Christopher Michael 2012-01-29 20:31:46 +00:00
parent 2b36a0e7ba
commit 9ba038d504
2 changed files with 400 additions and 0 deletions

View File

@ -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

View File

@ -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 <linux/input.h>
#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;
}