efl/legacy/ecore/src/lib/ecore_wayland/ecore_wl.c

725 lines
22 KiB
C

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "Ecore.h"
#include "ecore_private.h"
#include "Ecore_Input.h"
#include "ecore_wl_private.h"
#include "Ecore_Wayland.h"
/* FIXME: This gives BTN_LEFT/RIGHT/MIDDLE for linux systems ...
* What about other OSs ?? */
#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
#include <X11/extensions/XKBcommon.h>
/* local function prototypes */
static Eina_Bool _ecore_wl_shutdown(Eina_Bool close_display);
static void _ecore_wl_cb_disp_handle_global(struct wl_display *disp, uint32_t id, const char *interface, uint32_t version __UNUSED__, void *data __UNUSED__);
static int _ecore_wl_cb_disp_event_mask_update(uint32_t mask, void *data __UNUSED__);
static void _ecore_wl_cb_shm_format_iterate(void *data __UNUSED__, struct wl_shm *shm __UNUSED__, uint32_t format);
static void _ecore_wl_cb_disp_handle_geometry(void *data __UNUSED__, struct wl_output *output __UNUSED__, int x, int y, int pw __UNUSED__, int ph __UNUSED__, int subpixel __UNUSED__, const char *make __UNUSED__, const char *model __UNUSED__);
static void _ecore_wl_cb_disp_handle_mode(void *data __UNUSED__, struct wl_output *output __UNUSED__, uint32_t flags, int w, int h, int refresh __UNUSED__);
static Eina_Bool _ecore_wl_cb_fd_handle(void *data, Ecore_Fd_Handler *hdl __UNUSED__);
static void _ecore_wl_cb_handle_motion(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, int32_t x, int32_t y, int32_t sx, int32_t sy);
static void _ecore_wl_cb_handle_button(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, uint32_t btn, uint32_t state);
static void _ecore_wl_cb_handle_key(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, uint32_t key, uint32_t state);
static void _ecore_wl_cb_handle_pointer_focus(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, struct wl_surface *surface, int32_t x, int32_t y, int32_t sx, int32_t sy);
static void _ecore_wl_cb_handle_keyboard_focus(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, struct wl_surface *surface, struct wl_array *keys);
static void _ecore_wl_mouse_out_send(void);
static void _ecore_wl_mouse_in_send(void);
static void _ecore_wl_focus_out_send(void);
static void _ecore_wl_focus_in_send(void);
/* local variables */
static int _ecore_wl_init_count = 0;
static struct wl_display *_ecore_wl_disp = NULL;
static uint32_t _ecore_wl_disp_mask = 0;
static uint32_t _ecore_wl_disp_format = WL_SHM_FORMAT_PREMULTIPLIED_ARGB32;
static Eina_Rectangle _ecore_wl_screen;
static Ecore_Fd_Handler *_ecore_wl_fd_hdl = NULL;
static int _ecore_wl_screen_x = 0;
static int _ecore_wl_screen_y = 0;
static int _ecore_wl_surface_x = 0;
static int _ecore_wl_surface_y = 0;
static int _ecore_wl_input_modifiers = 0;
static struct xkb_desc *_ecore_wl_xkb;
static struct wl_compositor *_ecore_wl_comp;
static struct wl_shm *_ecore_wl_shm;
static struct wl_shell *_ecore_wl_shell;
static struct wl_output *_ecore_wl_output;
static struct wl_input_device *_ecore_wl_input;
static struct wl_surface *_ecore_wl_input_surface;
static struct wl_data_device_manager *_ecore_wl_dnd_manager;
static struct wl_data_device *_ecore_wl_dnd_dev;
static const struct wl_shm_listener _ecore_wl_shm_listener =
{
_ecore_wl_cb_shm_format_iterate
};
static const struct wl_output_listener _ecore_wl_output_listener =
{
_ecore_wl_cb_disp_handle_geometry,
_ecore_wl_cb_disp_handle_mode
};
static const struct wl_input_device_listener _ecore_wl_input_listener =
{
_ecore_wl_cb_handle_motion,
_ecore_wl_cb_handle_button,
_ecore_wl_cb_handle_key,
_ecore_wl_cb_handle_pointer_focus,
_ecore_wl_cb_handle_keyboard_focus,
NULL, // touch down
NULL, // touch up
NULL, // touch motion
NULL, // touch frame
NULL, // touch cancel
};
/* static const struct wl_data_source_listener _ecore_wl_dnd_listener = */
/* { */
/* _ecore_wl_cb_dnd_target, */
/* _ecore_wl_cb_dnd_send, */
/* _ecore_wl_cb_dnd_cancelled */
/* }; */
/* static const struct wl_data_device_listener _ecore_wl_data_listener = */
/* { */
/* _ecore_wl_cb_dnd_offer, */
/* _ecore_wl_cb_dnd_enter, */
/* _ecore_wl_cb_dnd_leave, */
/* _ecore_wl_cb_dnd_motion, */
/* _ecore_wl_cb_dnd_drop, */
/* _ecore_wl_cb_dnd_selection */
/* }; */
/* external variables */
int _ecore_wl_log_dom = -1;
EAPI int ECORE_WL_EVENT_MOUSE_IN = 0;
EAPI int ECORE_WL_EVENT_MOUSE_OUT = 0;
EAPI int ECORE_WL_EVENT_FOCUS_IN = 0;
EAPI int ECORE_WL_EVENT_FOCUS_OUT = 0;
EAPI int
ecore_wl_init(const char *name)
{
struct xkb_rule_names xkb_names;
int fd = 0;
if (++_ecore_wl_init_count != 1)
return _ecore_wl_init_count;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!eina_init()) return --_ecore_wl_init_count;
_ecore_wl_log_dom =
eina_log_domain_register("ecore_wl", ECORE_WL_DEFAULT_LOG_COLOR);
if (_ecore_wl_log_dom < 0)
{
EINA_LOG_ERR("Cannot create a log domain for Ecore Wayland.");
eina_shutdown();
return --_ecore_wl_init_count;
}
if (!ecore_init())
{
eina_log_domain_unregister(_ecore_wl_log_dom);
_ecore_wl_log_dom = -1;
eina_shutdown();
return --_ecore_wl_init_count;
}
if (!ecore_event_init())
{
eina_log_domain_unregister(_ecore_wl_log_dom);
_ecore_wl_log_dom = -1;
ecore_shutdown();
eina_shutdown();
return --_ecore_wl_init_count;
}
if (!ECORE_WL_EVENT_MOUSE_IN)
{
ECORE_WL_EVENT_MOUSE_IN = ecore_event_type_new();
ECORE_WL_EVENT_MOUSE_OUT = ecore_event_type_new();
ECORE_WL_EVENT_FOCUS_IN = ecore_event_type_new();
ECORE_WL_EVENT_FOCUS_OUT = ecore_event_type_new();
}
/* init xkb */
/* FIXME: Somehow make this portable to other languages/countries */
xkb_names.rules = "evdev";
xkb_names.model = "evdev";
xkb_names.layout = "us";
xkb_names.variant = "";
xkb_names.options = "";
if (!(_ecore_wl_xkb = xkb_compile_keymap_from_rules(&xkb_names)))
{
ERR("Could not compile keymap");
eina_log_domain_unregister(_ecore_wl_log_dom);
_ecore_wl_log_dom = -1;
ecore_event_shutdown();
ecore_shutdown();
eina_shutdown();
return --_ecore_wl_init_count;
}
/* connect to the wayland display */
if (!(_ecore_wl_disp = wl_display_connect(name)))
{
eina_log_domain_unregister(_ecore_wl_log_dom);
_ecore_wl_log_dom = -1;
ecore_event_shutdown();
ecore_shutdown();
eina_shutdown();
return --_ecore_wl_init_count;
}
/* setup handler for wayland interfaces */
wl_display_add_global_listener(_ecore_wl_disp,
_ecore_wl_cb_disp_handle_global, NULL);
/* process connection events */
wl_display_iterate(_ecore_wl_disp, WL_DISPLAY_READABLE);
fd = wl_display_get_fd(_ecore_wl_disp,
_ecore_wl_cb_disp_event_mask_update, NULL);
/* NB: DO NOT TOUCH THIS OR YOU WILL PAY THE PRICE OF FAILURE !! */
/* Without a ECORE_FD_WRITE, then animators/timers break */
_ecore_wl_fd_hdl =
ecore_main_fd_handler_add(fd, ECORE_FD_READ | ECORE_FD_WRITE,
_ecore_wl_cb_fd_handle, _ecore_wl_disp,
NULL, NULL);
if (!_ecore_wl_fd_hdl)
{
wl_display_destroy(_ecore_wl_disp);
_ecore_wl_disp = NULL;
eina_log_domain_unregister(_ecore_wl_log_dom);
_ecore_wl_log_dom = -1;
ecore_event_shutdown();
ecore_shutdown();
eina_shutdown();
return --_ecore_wl_init_count;
}
return _ecore_wl_init_count;
}
EAPI int
ecore_wl_shutdown(void)
{
return _ecore_wl_shutdown(EINA_TRUE);
}
EAPI struct wl_display *
ecore_wl_display_get(void)
{
return _ecore_wl_disp;
}
EAPI struct wl_shm *
ecore_wl_shm_get(void)
{
return _ecore_wl_shm;
}
EAPI struct wl_compositor *
ecore_wl_compositor_get(void)
{
return _ecore_wl_comp;
}
EAPI struct wl_shell *
ecore_wl_shell_get(void)
{
return _ecore_wl_shell;
}
EAPI struct wl_input_device *
ecore_wl_input_device_get(void)
{
return _ecore_wl_input;
}
EAPI void
ecore_wl_screen_size_get(int *w, int *h)
{
if (w) *w = _ecore_wl_screen.w;
if (h) *h = _ecore_wl_screen.h;
}
EAPI unsigned int
ecore_wl_format_get(void)
{
return _ecore_wl_disp_format;
}
EAPI void
ecore_wl_flush(void)
{
wl_display_flush(_ecore_wl_disp);
/* if (_ecore_wl_disp_mask & WL_DISPLAY_WRITABLE) */
/* wl_display_iterate(_ecore_wl_disp, WL_DISPLAY_WRITABLE); */
}
EAPI void
ecore_wl_sync(void)
{
wl_display_iterate(_ecore_wl_disp, WL_DISPLAY_READABLE);
}
EAPI void
ecore_wl_pointer_xy_get(int *x, int *y)
{
if (x) *x = _ecore_wl_screen_x;
if (y) *y = _ecore_wl_screen_y;
}
/* local functions */
static Eina_Bool
_ecore_wl_shutdown(Eina_Bool close_display)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (--_ecore_wl_init_count != 0)
return _ecore_wl_init_count;
if (!_ecore_wl_disp) return _ecore_wl_init_count;
if (_ecore_wl_xkb) free(_ecore_wl_xkb);
if (_ecore_wl_fd_hdl) ecore_main_fd_handler_del(_ecore_wl_fd_hdl);
_ecore_wl_fd_hdl = NULL;
if (close_display)
{
if (_ecore_wl_dnd_dev) wl_data_device_destroy(_ecore_wl_dnd_dev);
if (_ecore_wl_input) wl_input_device_destroy(_ecore_wl_input);
if (_ecore_wl_dnd_manager)
wl_data_device_manager_destroy(_ecore_wl_dnd_manager);
if (_ecore_wl_shell) wl_shell_destroy(_ecore_wl_shell);
if (_ecore_wl_shm) wl_shm_destroy(_ecore_wl_shm);
if (_ecore_wl_comp) wl_compositor_destroy(_ecore_wl_comp);
if (_ecore_wl_disp) wl_display_destroy(_ecore_wl_disp);
_ecore_wl_disp = NULL;
}
eina_log_domain_unregister(_ecore_wl_log_dom);
_ecore_wl_log_dom = -1;
ecore_event_shutdown();
ecore_shutdown();
eina_shutdown();
return _ecore_wl_init_count;
}
static void
_ecore_wl_cb_disp_handle_global(struct wl_display *disp, uint32_t id, const char *interface, uint32_t version __UNUSED__, void *data __UNUSED__)
{
// LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (disp != _ecore_wl_disp) return;
if (!strcmp(interface, "wl_compositor"))
{
_ecore_wl_comp =
wl_display_bind(_ecore_wl_disp, id, &wl_compositor_interface);
}
else if (!strcmp(interface, "wl_shm"))
{
_ecore_wl_shm =
wl_display_bind(_ecore_wl_disp, id, &wl_shm_interface);
wl_shm_add_listener(_ecore_wl_shm, &_ecore_wl_shm_listener, NULL);
}
else if (!strcmp(interface, "wl_output"))
{
_ecore_wl_output =
wl_display_bind(_ecore_wl_disp, id, &wl_output_interface);
wl_output_add_listener(_ecore_wl_output,
&_ecore_wl_output_listener, NULL);
}
else if (!strcmp(interface, "wl_shell"))
{
_ecore_wl_shell =
wl_display_bind(_ecore_wl_disp, id, &wl_shell_interface);
}
else if (!strcmp(interface, "wl_input_device"))
{
_ecore_wl_input =
wl_display_bind(_ecore_wl_disp, id, &wl_input_device_interface);
wl_input_device_add_listener(_ecore_wl_input,
&_ecore_wl_input_listener, NULL);
_ecore_wl_dnd_dev =
wl_data_device_manager_get_data_device(_ecore_wl_dnd_manager,
_ecore_wl_input);
/* wl_data_device_add_listener(_ecore_wl_dnd_dev, */
/* &_ecore_wl_data_listener, NULL); */
}
else if (!strcmp(interface, "wl_data_device_manager"))
{
_ecore_wl_dnd_manager =
wl_display_bind(_ecore_wl_disp, id,
&wl_data_device_manager_interface);
}
}
static int
_ecore_wl_cb_disp_event_mask_update(uint32_t mask, void *data __UNUSED__)
{
// LOGFN(__FILE__, __LINE__, __FUNCTION__);
_ecore_wl_disp_mask = mask;
return 0;
}
static void
_ecore_wl_cb_shm_format_iterate(void *data __UNUSED__, struct wl_shm *shm __UNUSED__, uint32_t format)
{
// LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (_ecore_wl_disp_format < 2) return;
switch (format)
{
case WL_SHM_FORMAT_ARGB32:
/* NB: Ignore argb32. We prefer premul */
break;
case WL_SHM_FORMAT_PREMULTIPLIED_ARGB32:
_ecore_wl_disp_format = format;
break;
case WL_SHM_FORMAT_XRGB32:
_ecore_wl_disp_format = format;
break;
default:
break;
}
}
static void
_ecore_wl_cb_disp_handle_geometry(void *data __UNUSED__, struct wl_output *output __UNUSED__, int x, int y, int pw __UNUSED__, int ph __UNUSED__, int subpixel __UNUSED__, const char *make __UNUSED__, const char *model __UNUSED__)
{
_ecore_wl_screen.x = x;
_ecore_wl_screen.y = y;
}
static void
_ecore_wl_cb_disp_handle_mode(void *data __UNUSED__, struct wl_output *output __UNUSED__, uint32_t flags, int w, int h, int refresh __UNUSED__)
{
if (flags & WL_OUTPUT_MODE_CURRENT)
{
_ecore_wl_screen.w = w;
_ecore_wl_screen.h = h;
}
}
static Eina_Bool
_ecore_wl_cb_fd_handle(void *data, Ecore_Fd_Handler *hdl __UNUSED__)
{
struct wl_display *disp;
if (!(disp = data)) return ECORE_CALLBACK_RENEW;
if (disp != _ecore_wl_disp) return ECORE_CALLBACK_RENEW;
// LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* NB: This handles iterate for writable AND readable.
* DO NOT TOUCH THIS OR YOU WILL PAY THE PRICE OF FAILURE !!
* Without this, animators/timers die */
if (_ecore_wl_disp_mask & (WL_DISPLAY_READABLE | WL_DISPLAY_WRITABLE))
wl_display_roundtrip(_ecore_wl_disp);
return ECORE_CALLBACK_RENEW;
}
static void
_ecore_wl_cb_handle_motion(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, int32_t x, int32_t y, int32_t sx, int32_t sy)
{
Ecore_Event_Mouse_Move *ev;
if (dev != _ecore_wl_input) return;
if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Move)))) return;
_ecore_wl_screen_x = x;
_ecore_wl_screen_y = y;
_ecore_wl_surface_x = sx;
_ecore_wl_surface_y = sy;
ev->timestamp = t;
ev->x = _ecore_wl_surface_x;
ev->y = _ecore_wl_surface_y;
ev->root.x = _ecore_wl_screen_x;
ev->root.y = _ecore_wl_screen_y;
if (_ecore_wl_input_surface)
{
unsigned int id = 0;
if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
{
ev->window = id;
ev->event_window = id;
}
}
ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
}
static void
_ecore_wl_cb_handle_button(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, uint32_t btn, uint32_t state)
{
if (dev != _ecore_wl_input) return;
if ((btn >= BTN_SIDE) && (btn <= BTN_BACK))
{
Ecore_Event_Mouse_Wheel *ev;
if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Wheel)))) return;
ev->timestamp = t;
ev->x = _ecore_wl_surface_x;
ev->y = _ecore_wl_surface_y;
ev->root.x = _ecore_wl_screen_x;
ev->root.y = _ecore_wl_screen_y;
ev->modifiers = _ecore_wl_input_modifiers;
ev->direction = 0;
if (_ecore_wl_input_surface)
{
unsigned int id = 0;
if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
{
ev->window = id;
ev->event_window = id;
}
}
/* NB: (FIXME) Currently Wayland provides no measure of how much the
* wheel has scrolled (read: delta of movement). So for now, we will
* just assume that the amount scrolled is 1 */
if ((btn == BTN_EXTRA) || (btn == BTN_FORWARD)) // down
ev->z = 1;
else if ((btn == BTN_SIDE) || (btn == BTN_BACK)) // up
ev->z = -1;
ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
}
else
{
Ecore_Event_Mouse_Button *ev;
/* NB: Maybe need to handle _ecore_mouse_move here ?? */
if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Button)))) return;
if (btn == BTN_LEFT)
ev->buttons = 1;
else if (btn == BTN_MIDDLE)
ev->buttons = 2;
else if (btn == BTN_RIGHT)
ev->buttons = 3;
ev->timestamp = t;
ev->x = _ecore_wl_surface_x;
ev->y = _ecore_wl_surface_y;
ev->root.x = _ecore_wl_screen_x;
ev->root.y = _ecore_wl_screen_y;
ev->modifiers = _ecore_wl_input_modifiers;
if (_ecore_wl_input_surface)
{
unsigned int id = 0;
if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
{
ev->window = id;
ev->event_window = id;
}
}
if (state)
ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
else
ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
}
}
static void
_ecore_wl_cb_handle_key(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, uint32_t key, uint32_t state)
{
unsigned int keycode = 0;
if (dev != _ecore_wl_input) return;
keycode = key + _ecore_wl_xkb->min_key_code;
if (state)
_ecore_wl_input_modifiers |= _ecore_wl_xkb->map->modmap[keycode];
else
_ecore_wl_input_modifiers &= ~_ecore_wl_xkb->map->modmap[keycode];
}
static void
_ecore_wl_cb_handle_pointer_focus(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, struct wl_surface *surface, int32_t x, int32_t y, int32_t sx, int32_t sy)
{
if (dev != _ecore_wl_input) return;
_ecore_wl_screen_x = x;
_ecore_wl_screen_y = y;
_ecore_wl_surface_x = sx;
_ecore_wl_surface_y = sy;
if (surface)
{
if (_ecore_wl_input_surface)
{
if (_ecore_wl_input_surface != surface)
{
/* NB: Pointer focus in different window. Send mouse & focus
* out events for previous window */
_ecore_wl_mouse_out_send();
_ecore_wl_focus_out_send();
/* NB: Send mouse & focus in events for new window */
_ecore_wl_input_surface = surface;
_ecore_wl_mouse_in_send();
_ecore_wl_focus_in_send();
}
}
else
{
_ecore_wl_input_surface = surface;
_ecore_wl_mouse_in_send();
_ecore_wl_focus_in_send();
/* printf("\tPointer Focus In New Window\n"); */
}
}
else
{
if (_ecore_wl_input_surface)
{
_ecore_wl_mouse_out_send();
_ecore_wl_focus_out_send();
/* printf("\tPointer Focus Not On a Window\n"); */
}
else
printf("\tUnhandled Pointer Focus Case !!!\n");
_ecore_wl_input_surface = NULL;
}
}
static void
_ecore_wl_cb_handle_keyboard_focus(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, struct wl_surface *surface, struct wl_array *keys)
{
unsigned int *keyend = 0, *i = 0;
if (dev != _ecore_wl_input) return;
if ((surface) && (surface != _ecore_wl_input_surface))
_ecore_wl_input_surface = surface;
else if (!surface)
_ecore_wl_input_surface = NULL;
keyend = keys->data + keys->size;
_ecore_wl_input_modifiers = 0;
for (i = keys->data; i < keyend; i++)
_ecore_wl_input_modifiers |= _ecore_wl_xkb->map->modmap[*i];
}
static void
_ecore_wl_mouse_out_send(void)
{
Ecore_Wl_Event_Mouse_Out *ev;
if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Mouse_Out)))) return;
ev->x = _ecore_wl_surface_x;
ev->y = _ecore_wl_surface_y;
ev->root.x = _ecore_wl_screen_x;
ev->root.y = _ecore_wl_screen_y;
ev->modifiers = _ecore_wl_input_modifiers;
ev->time = ecore_time_get();
if (_ecore_wl_input_surface)
{
unsigned int id = 0;
if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
ev->window = id;
}
ecore_event_add(ECORE_WL_EVENT_MOUSE_OUT, ev, NULL, NULL);
}
static void
_ecore_wl_mouse_in_send(void)
{
Ecore_Wl_Event_Mouse_In *ev;
if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Mouse_In)))) return;
ev->x = _ecore_wl_surface_x;
ev->y = _ecore_wl_surface_y;
ev->root.x = _ecore_wl_screen_x;
ev->root.y = _ecore_wl_screen_y;
ev->modifiers = _ecore_wl_input_modifiers;
ev->time = ecore_time_get();
if (_ecore_wl_input_surface)
{
unsigned int id = 0;
if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
ev->window = id;
}
ecore_event_add(ECORE_WL_EVENT_MOUSE_IN, ev, NULL, NULL);
}
static void
_ecore_wl_focus_out_send(void)
{
Ecore_Wl_Event_Focus_Out *ev;
if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Focus_Out)))) return;
ev->time = ecore_time_get();
if (_ecore_wl_input_surface)
{
unsigned int id = 0;
if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
ev->window = id;
}
ecore_event_add(ECORE_WL_EVENT_FOCUS_OUT, ev, NULL, NULL);
}
static void
_ecore_wl_focus_in_send(void)
{
Ecore_Wl_Event_Focus_In *ev;
if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Focus_In)))) return;
ev->time = ecore_time_get();
if (_ecore_wl_input_surface)
{
unsigned int id = 0;
if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
ev->window = id;
}
ecore_event_add(ECORE_WL_EVENT_FOCUS_IN, ev, NULL, NULL);
}