From 3ad3455551be0d7859ecb02290376206d5e66498 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sun, 22 Apr 2012 09:20:32 +1000 Subject: And actually include new files, plus elementary libraries. --- .../ecore/src/lib/ecore_wayland/ecore_wl_dnd.c | 189 ++++++ .../ecore/src/lib/ecore_wayland/ecore_wl_input.c | 658 +++++++++++++++++++++ .../ecore/src/lib/ecore_wayland/ecore_wl_output.c | 79 +++ .../ecore/src/lib/ecore_wayland/ecore_wl_window.c | 440 ++++++++++++++ 4 files changed, 1366 insertions(+) create mode 100644 libraries/ecore/src/lib/ecore_wayland/ecore_wl_dnd.c create mode 100644 libraries/ecore/src/lib/ecore_wayland/ecore_wl_input.c create mode 100644 libraries/ecore/src/lib/ecore_wayland/ecore_wl_output.c create mode 100644 libraries/ecore/src/lib/ecore_wayland/ecore_wl_window.c (limited to 'libraries/ecore/src') diff --git a/libraries/ecore/src/lib/ecore_wayland/ecore_wl_dnd.c b/libraries/ecore/src/lib/ecore_wayland/ecore_wl_dnd.c new file mode 100644 index 0000000..5d81225 --- /dev/null +++ b/libraries/ecore/src/lib/ecore_wayland/ecore_wl_dnd.c @@ -0,0 +1,189 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_wl_private.h" +#include "Ecore_Wayland.h" + +/* local function prototypes */ +static void _ecore_wl_dnd_offer(void *data, struct wl_data_offer *wl_data_offer __UNUSED__, const char *type); +static void _ecore_wl_dnd_cb_enter_free(void *data __UNUSED__, void *event); + +/* wayland listeners */ +static const struct wl_data_offer_listener _ecore_wl_data_offer_listener = +{ + _ecore_wl_dnd_offer, +}; + +void +_ecore_wl_dnd_add(Ecore_Wl_Input *input, struct wl_data_device *data_device, unsigned int id) +{ + Ecore_Wl_Dnd_Source *source; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(source = malloc(sizeof(Ecore_Wl_Dnd_Source)))) return; + wl_array_init(&source->types); + source->refcount = 1; + source->input = input; + /* FIXME: Change this when wayland has typesafe wrapper for it */ + source->offer = (struct wl_data_offer *) + wl_proxy_create_for_id((struct wl_proxy *)data_device, + id, &wl_data_offer_interface); + wl_data_offer_add_listener(source->offer, + &_ecore_wl_data_offer_listener, source); +} + +void +_ecore_wl_dnd_enter(void *data, struct wl_data_device *data_device __UNUSED__, unsigned int timestamp __UNUSED__, struct wl_surface *surface, int x, int y, struct wl_data_offer *offer) +{ + Ecore_Wl_Event_Dnd_Enter *event; + Ecore_Wl_Input *input; + Ecore_Wl_Window *win; + char **p; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + input->drag_source = wl_data_offer_get_user_data(offer); + + win = wl_surface_get_user_data(surface); +// input->pointer_focus = win; + + p = wl_array_add(&input->drag_source->types, sizeof(*p)); + *p = NULL; + + if (!(event = calloc(1, sizeof(Ecore_Wl_Event_Dnd_Enter)))) return; + + event->win = win->id; + event->source = input->drag_source->input->keyboard_focus->id; + event->position.x = x; + event->position.y = y; + event->num_types = input->drag_source->types.size; + event->types = input->drag_source->types.data; + + ecore_event_add(ECORE_WL_EVENT_DND_ENTER, event, + _ecore_wl_dnd_cb_enter_free, NULL); +} + +void +_ecore_wl_dnd_leave(void *data, struct wl_data_device *data_device __UNUSED__) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + _ecore_wl_dnd_del(input->drag_source); + input->drag_source = NULL; +} + +void +_ecore_wl_dnd_motion(void *data, struct wl_data_device *data_device __UNUSED__, unsigned int timestamp __UNUSED__, int x, int y) +{ + Ecore_Wl_Event_Dnd_Position *event; + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + input->sx = x; + input->sy = y; + + if (!(event = calloc(1, sizeof(Ecore_Wl_Event_Dnd_Position)))) return; + + event->win = input->drag_source->input->pointer_focus->id; + event->source = input->drag_source->input->keyboard_focus->id; + event->position.x = x; + event->position.y = y; + + ecore_event_add(ECORE_WL_EVENT_DND_POSITION, event, NULL, NULL); +} + +void +_ecore_wl_dnd_drop(void *data, struct wl_data_device *data_device __UNUSED__) +{ + Ecore_Wl_Event_Dnd_Drop *event; + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + if (!(event = calloc(1, sizeof(Ecore_Wl_Event_Dnd_Drop)))) return; + + event->win = input->drag_source->input->pointer_focus->id; + event->source = input->drag_source->input->keyboard_focus->id; + event->position.x = input->sx; + event->position.y = input->sy; + + ecore_event_add(ECORE_WL_EVENT_DND_DROP, event, NULL, NULL); +} + +void +_ecore_wl_dnd_selection(void *data, struct wl_data_device *data_device __UNUSED__, struct wl_data_offer *offer) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + if (input->selection_source) _ecore_wl_dnd_del(input->selection_source); + input->selection_source = NULL; + if (offer) + { + char **p; + + input->selection_source = wl_data_offer_get_user_data(offer); + p = wl_array_add(&input->selection_source->types, sizeof(*p)); + *p = NULL; + } +} + +void +_ecore_wl_dnd_del(Ecore_Wl_Dnd_Source *source) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!source) return; + source->refcount--; + if (source->refcount == 0) + { + char **p; + + wl_data_offer_destroy(source->offer); + for (p = source->types.data; *p; p++) + free(*p); + wl_array_release(&source->types); + free(source); + } +} + +/* local functions */ +static void +_ecore_wl_dnd_offer(void *data, struct wl_data_offer *wl_data_offer __UNUSED__, const char *type) +{ + Ecore_Wl_Dnd_Source *source; + char **p; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(source = data)) return; + p = wl_array_add(&source->types, sizeof(*p)); + *p = strdup(type); +} + +static void +_ecore_wl_dnd_cb_enter_free(void *data __UNUSED__, void *event) +{ + Ecore_Wl_Event_Dnd_Enter *ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ev = event)) return; + free(ev); +} diff --git a/libraries/ecore/src/lib/ecore_wayland/ecore_wl_input.c b/libraries/ecore/src/lib/ecore_wayland/ecore_wl_input.c new file mode 100644 index 0000000..d44daa7 --- /dev/null +++ b/libraries/ecore/src/lib/ecore_wayland/ecore_wl_input.c @@ -0,0 +1,658 @@ +#ifdef HAVE_CONFIG_H +# include +#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 +#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 + +/* local function prototypes */ +static void _ecore_wl_input_cb_motion(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, int sx, int sy); +static void _ecore_wl_input_cb_button(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, unsigned int button, unsigned int state); +static void _ecore_wl_input_cb_key(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp __UNUSED__, unsigned int key, unsigned int state); +static void _ecore_wl_input_cb_pointer_enter(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, struct wl_surface *surface, int sx, int sy); +static void _ecore_wl_input_cb_pointer_leave(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, struct wl_surface *surface __UNUSED__); +static void _ecore_wl_input_cb_keyboard_enter(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, struct wl_surface *surface, struct wl_array *keys); +static void _ecore_wl_input_cb_keyboard_leave(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, struct wl_surface *surface __UNUSED__); +static void _ecore_wl_input_cb_touch_down(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, struct wl_surface *surface __UNUSED__, int id __UNUSED__, int x, int y); +static void _ecore_wl_input_cb_touch_up(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, int id __UNUSED__); +static void _ecore_wl_input_cb_touch_motion(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, int id __UNUSED__, int x, int y); +static void _ecore_wl_input_cb_touch_frame(void *data __UNUSED__, struct wl_input_device *input_device __UNUSED__); +static void _ecore_wl_input_cb_touch_cancel(void *data __UNUSED__, struct wl_input_device *input_device __UNUSED__); +static void _ecore_wl_input_cb_data_offer(void *data, struct wl_data_device *data_device, unsigned int id); +static void _ecore_wl_input_cb_data_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); +static void _ecore_wl_input_cb_data_leave(void *data, struct wl_data_device *data_device); +static void _ecore_wl_input_cb_data_motion(void *data, struct wl_data_device *data_device, unsigned int timestamp, int x, int y); +static void _ecore_wl_input_cb_data_drop(void *data, struct wl_data_device *data_device); +static void _ecore_wl_input_cb_data_selection(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer); + +static void _ecore_wl_input_keyboard_focus_remove(Ecore_Wl_Input *input, unsigned int timestamp); +static void _ecore_wl_input_pointer_focus_remove(Ecore_Wl_Input *input, unsigned int timestamp); +static void _ecore_wl_input_mouse_move_send(Ecore_Wl_Input *input, unsigned int timestamp); +static void _ecore_wl_input_cb_mouse_move_free(void *data __UNUSED__, void *event); +static void _ecore_wl_input_mouse_in_send(Ecore_Wl_Input *input, unsigned int timestamp); +static void _ecore_wl_input_mouse_out_send(Ecore_Wl_Input *input, unsigned int timestamp); +static void _ecore_wl_input_focus_in_send(Ecore_Wl_Input *input, unsigned int timestamp); +static void _ecore_wl_input_focus_out_send(Ecore_Wl_Input *input, unsigned int timestamp); +static void _ecore_wl_input_mouse_down_send(Ecore_Wl_Input *input, unsigned int timestamp); +static void _ecore_wl_input_mouse_up_send(Ecore_Wl_Input *input, unsigned int timestamp); + +/* wayland interfaces */ +static const struct wl_input_device_listener _ecore_wl_input_listener = +{ + _ecore_wl_input_cb_motion, + _ecore_wl_input_cb_button, + _ecore_wl_input_cb_key, + _ecore_wl_input_cb_pointer_enter, + _ecore_wl_input_cb_pointer_leave, + _ecore_wl_input_cb_keyboard_enter, + _ecore_wl_input_cb_keyboard_leave, + _ecore_wl_input_cb_touch_down, + _ecore_wl_input_cb_touch_up, + _ecore_wl_input_cb_touch_motion, + _ecore_wl_input_cb_touch_frame, + _ecore_wl_input_cb_touch_cancel +}; + +static const struct wl_data_device_listener _ecore_wl_data_listener = +{ + _ecore_wl_input_cb_data_offer, + _ecore_wl_input_cb_data_enter, + _ecore_wl_input_cb_data_leave, + _ecore_wl_input_cb_data_motion, + _ecore_wl_input_cb_data_drop, + _ecore_wl_input_cb_data_selection +}; + +/* local variables */ +static int _pointer_x, _pointer_y; + +void +_ecore_wl_input_add(Ecore_Wl_Display *ewd, unsigned int id) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = malloc(sizeof(Ecore_Wl_Input)))) return; + + memset(input, 0, sizeof(Ecore_Wl_Input)); + + input->display = ewd; + input->pointer_focus = NULL; + input->keyboard_focus = NULL; + + input->input_device = + wl_display_bind(ewd->wl.display, id, &wl_input_device_interface); + wl_list_insert(ewd->inputs.prev, &input->link); + wl_input_device_add_listener(input->input_device, + &_ecore_wl_input_listener, input); + wl_input_device_set_user_data(input->input_device, input); + + input->data_device = + wl_data_device_manager_get_data_device(ewd->wl.data_device_manager, + input->input_device); + wl_data_device_add_listener(input->data_device, + &_ecore_wl_data_listener, input); +} + +void +_ecore_wl_input_del(Ecore_Wl_Input *input) +{ + if (!input) return; + + _ecore_wl_input_keyboard_focus_remove(input, 0); + _ecore_wl_input_pointer_focus_remove(input, 0); + + if (input->drag_source) _ecore_wl_dnd_del(input->drag_source); + input->drag_source = NULL; + + if (input->selection_source) _ecore_wl_dnd_del(input->selection_source); + input->selection_source = NULL; + + if (input->data_device) wl_data_device_destroy(input->data_device); + if (input->input_device) wl_input_device_destroy(input->input_device); + wl_list_remove(&input->link); + free(input); +} + +void +_ecore_wl_input_pointer_xy_get(int *x, int *y) +{ + if (x) *x = _pointer_x; + if (y) *y = _pointer_y; +} + +/* local functions */ +static void +_ecore_wl_input_cb_motion(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, int sx, int sy) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + _pointer_x = sx; + _pointer_y = sy; + + input->sx = sx; + input->sy = sy; + + /* TODO: FIXME: NB: Weston window code has set pointer image here also */ + _ecore_wl_input_mouse_move_send(input, timestamp); +} + +static void +_ecore_wl_input_cb_button(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, unsigned int button, unsigned int state) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + input->timestamp = timestamp; + + _ecore_wl_input_mouse_move_send(input, timestamp); + + if ((button >= BTN_SIDE) && (button <= BTN_BACK)) + { + /* TODO: raise mouse wheel */ + printf("Raise Mouse Wheel Event\n"); + } + else + { + if (state) + { + input->button = button; + _ecore_wl_input_mouse_down_send(input, timestamp); + } + else + { + _ecore_wl_input_mouse_up_send(input, timestamp); + input->button = 0; + } + } +} + +static void +_ecore_wl_input_cb_key(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp __UNUSED__, unsigned int key, unsigned int state) +{ + Ecore_Wl_Input *input; + Ecore_Wl_Window *win; + unsigned int keycode = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + win = input->keyboard_focus; + if ((!win) || (win->keyboard_device != input)) return; + + /* FIXME: NB: I believe this should be min_key_code rather than 8, + * but weston code has it like this */ + keycode = key + 8; + + /* if ((input->modifiers & XKB_COMMON_SHIFT_MASK) && */ + /* (XkbKeyGroupWidth(_ecore_wl_disp->xkb, keycode, 0) > 1)) */ + /* level = 1; */ + /* keysym = XkbKeySymEntry(_ecore_wl_disp->xkb, keycode, level, 0); */ + + if (state) + input->modifiers |= _ecore_wl_disp->xkb->map->modmap[keycode]; + else + input->modifiers &= ~_ecore_wl_disp->xkb->map->modmap[keycode]; +} + +static void +_ecore_wl_input_cb_pointer_enter(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, struct wl_surface *surface, int sx, int sy) +{ + Ecore_Wl_Input *input; + Ecore_Wl_Window *win = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + input->sx = sx; + input->sy = sy; + + _ecore_wl_input_mouse_move_send(input, timestamp); + + win = input->pointer_focus; + if ((win) && (win->surface != surface)) + { + if (!input->button) + _ecore_wl_input_pointer_focus_remove(input, timestamp); + } + + if (surface) + { + if ((win = wl_surface_get_user_data(surface))) + { + input->pointer_focus = win; + win->pointer_device = input; + } + if (input->button) + { + _ecore_wl_input_mouse_up_send(input, timestamp); + input->button = 0; + } + else + _ecore_wl_input_mouse_in_send(input, timestamp); + } +} + +static void +_ecore_wl_input_cb_pointer_leave(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, struct wl_surface *surface __UNUSED__) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + _ecore_wl_input_pointer_focus_remove(input, timestamp); +} + +static void +_ecore_wl_input_cb_keyboard_enter(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, struct wl_surface *surface, struct wl_array *keys) +{ + Ecore_Wl_Input *input; + Ecore_Wl_Window *win = NULL; + unsigned int *k, *end; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + end = keys->data + keys->size; + input->modifiers = 0; + for (k = keys->data; k < end; k++) + input->modifiers |= _ecore_wl_disp->xkb->map->modmap[*k]; + + if (surface) + { + if ((win = wl_surface_get_user_data(surface))) + { + input->keyboard_focus = win; + win->keyboard_device = input; + } + else + input->keyboard_focus = NULL; + _ecore_wl_input_focus_in_send(input, timestamp); + } +} + +static void +_ecore_wl_input_cb_keyboard_leave(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, struct wl_surface *surface __UNUSED__) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + _ecore_wl_input_keyboard_focus_remove(input, timestamp); +} + +static void +_ecore_wl_input_cb_touch_down(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, struct wl_surface *surface __UNUSED__, int id __UNUSED__, int x, int y) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + /* FIXME: NB: Not sure yet if input->timestamp should be set here. + * This needs to be tested with an actual touch device */ + /* input->timestamp = timestamp; */ + input->button = 0; + input->sx = x; + input->sy = y; + _ecore_wl_input_mouse_down_send(input, timestamp); +} + +static void +_ecore_wl_input_cb_touch_up(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, int id __UNUSED__) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + /* FIXME: NB: Not sure yet if input->timestamp should be set here. + * This needs to be tested with an actual touch device */ + /* input->timestamp = timestamp; */ + input->button = 0; + _ecore_wl_input_mouse_up_send(input, timestamp); +} + +static void +_ecore_wl_input_cb_touch_motion(void *data, struct wl_input_device *input_device __UNUSED__, unsigned int timestamp, int id __UNUSED__, int x, int y) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(input = data)) return; + + /* FIXME: NB: Not sure yet if input->timestamp should be set here. + * This needs to be tested with an actual touch device */ + /* input->timestamp = timestamp; */ + input->sx = x; + input->sy = y; + + _ecore_wl_input_mouse_move_send(input, timestamp); +} + +static void +_ecore_wl_input_cb_touch_frame(void *data __UNUSED__, struct wl_input_device *input_device __UNUSED__) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +static void +_ecore_wl_input_cb_touch_cancel(void *data __UNUSED__, struct wl_input_device *input_device __UNUSED__) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +static void +_ecore_wl_input_cb_data_offer(void *data, struct wl_data_device *data_device, unsigned int id) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_wl_dnd_add(data, data_device, id); +} + +static void +_ecore_wl_input_cb_data_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) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_wl_dnd_enter(data, data_device, timestamp, surface, x, y, offer); +} + +static void +_ecore_wl_input_cb_data_leave(void *data, struct wl_data_device *data_device) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_wl_dnd_leave(data, data_device); +} + +static void +_ecore_wl_input_cb_data_motion(void *data, struct wl_data_device *data_device, unsigned int timestamp, int x, int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_wl_dnd_motion(data, data_device, timestamp, x, y); +} + +static void +_ecore_wl_input_cb_data_drop(void *data, struct wl_data_device *data_device) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_wl_dnd_drop(data, data_device); +} + +static void +_ecore_wl_input_cb_data_selection(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_wl_dnd_selection(data, data_device, offer); +} + +static void +_ecore_wl_input_keyboard_focus_remove(Ecore_Wl_Input *input, unsigned int timestamp) +{ + Ecore_Wl_Window *win; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_wl_input_focus_out_send(input, timestamp); + if ((win = input->keyboard_focus)) + win->keyboard_device = NULL; + input->keyboard_focus = NULL; +} + +static void +_ecore_wl_input_pointer_focus_remove(Ecore_Wl_Input *input, unsigned int timestamp) +{ + Ecore_Wl_Window *win; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!input->button) + _ecore_wl_input_mouse_out_send(input, timestamp); + + if ((win = input->pointer_focus)) + win->pointer_device = NULL; + input->pointer_focus = NULL; +} + +static void +_ecore_wl_input_mouse_move_send(Ecore_Wl_Input *input, unsigned int timestamp) +{ + Ecore_Event_Mouse_Move *ev; + Ecore_Event *event; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Move)))) return; + + ev->timestamp = timestamp; + ev->x = input->sx; + ev->y = input->sy; + ev->modifiers = input->modifiers; + ev->multi.device = 0; + ev->multi.radius = 1; + ev->multi.radius_x = 1; + ev->multi.radius_y = 1; + ev->multi.pressure = 1.0; + ev->multi.angle = 0.0; + ev->multi.x = input->sx; + ev->multi.y = input->sy; + + if (input->pointer_focus) + { + ev->window = input->pointer_focus->id; + ev->event_window = input->pointer_focus->id; + } + + event = ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, + _ecore_wl_input_cb_mouse_move_free, NULL); +} + +static void +_ecore_wl_input_cb_mouse_move_free(void *data __UNUSED__, void *event) +{ + Ecore_Event_Mouse_Move *ev; + + if ((ev = event)) free(ev); +} + +static void +_ecore_wl_input_mouse_in_send(Ecore_Wl_Input *input, unsigned int timestamp) +{ + Ecore_Wl_Event_Mouse_In *ev; + Ecore_Event *event; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Mouse_In)))) return; + + ev->x = input->sx; + ev->y = input->sy; + ev->modifiers = input->modifiers; + ev->timestamp = timestamp; + + if (input->pointer_focus) + { + ev->win = input->pointer_focus->id; + ev->event_win = input->pointer_focus->id; + } + + event = ecore_event_add(ECORE_WL_EVENT_MOUSE_IN, ev, NULL, NULL); +} + +static void +_ecore_wl_input_mouse_out_send(Ecore_Wl_Input *input, unsigned int timestamp) +{ + Ecore_Wl_Event_Mouse_Out *ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Mouse_Out)))) return; + + ev->x = input->sx; + ev->y = input->sy; + ev->modifiers = input->modifiers; + ev->timestamp = timestamp; + + if (input->pointer_focus) + { + ev->win = input->pointer_focus->id; + ev->event_win = input->pointer_focus->id; + } + + ecore_event_add(ECORE_WL_EVENT_MOUSE_OUT, ev, NULL, NULL); +} + +static void +_ecore_wl_input_focus_in_send(Ecore_Wl_Input *input, unsigned int timestamp) +{ + Ecore_Wl_Event_Focus_In *ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Focus_In)))) return; + ev->timestamp = timestamp; + if (input->keyboard_focus) + ev->win = input->keyboard_focus->id; + ecore_event_add(ECORE_WL_EVENT_FOCUS_IN, ev, NULL, NULL); +} + +static void +_ecore_wl_input_focus_out_send(Ecore_Wl_Input *input, unsigned int timestamp) +{ + Ecore_Wl_Event_Focus_Out *ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Focus_Out)))) return; + ev->timestamp = timestamp; + if (input->keyboard_focus) + ev->win = input->keyboard_focus->id; + ecore_event_add(ECORE_WL_EVENT_FOCUS_OUT, ev, NULL, NULL); +} + +static void +_ecore_wl_input_mouse_down_send(Ecore_Wl_Input *input, unsigned int timestamp) +{ + Ecore_Event_Mouse_Button *ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Button)))) return; + + if (input->button == BTN_LEFT) + ev->buttons = 1; + else if (input->button == BTN_MIDDLE) + ev->buttons = 2; + else if (input->button == BTN_RIGHT) + ev->buttons = 3; + else + ev->buttons = input->button; + + ev->timestamp = timestamp; + ev->x = input->sx; + ev->y = input->sy; + ev->modifiers = input->modifiers; + + /* FIXME: Need to get these from wayland somehow */ + ev->double_click = 0; + ev->triple_click = 0; + + ev->multi.device = 0; + ev->multi.radius = 1; + ev->multi.radius_x = 1; + ev->multi.radius_y = 1; + ev->multi.pressure = 1.0; + ev->multi.angle = 0.0; + ev->multi.x = input->sx; + ev->multi.y = input->sy; + + if (input->pointer_focus) + { + ev->window = input->pointer_focus->id; + ev->event_window = input->pointer_focus->id; + } + + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL); +} + +static void +_ecore_wl_input_mouse_up_send(Ecore_Wl_Input *input, unsigned int timestamp) +{ + Ecore_Event_Mouse_Button *ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Button)))) return; + + if (input->button == BTN_LEFT) + ev->buttons = 1; + else if (input->button == BTN_MIDDLE) + ev->buttons = 2; + else if (input->button == BTN_RIGHT) + ev->buttons = 3; + else + ev->buttons = input->button; + + ev->timestamp = timestamp; + ev->x = input->sx; + ev->y = input->sy; + ev->modifiers = input->modifiers; + + /* FIXME: Need to get these from wayland somehow */ + ev->double_click = 0; + ev->triple_click = 0; + + ev->multi.device = 0; + ev->multi.radius = 1; + ev->multi.radius_x = 1; + ev->multi.radius_y = 1; + ev->multi.pressure = 1.0; + ev->multi.angle = 0.0; + ev->multi.x = input->sx; + ev->multi.y = input->sy; + + if (input->pointer_focus) + { + ev->window = input->pointer_focus->id; + ev->event_window = input->pointer_focus->id; + } + + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL); +} diff --git a/libraries/ecore/src/lib/ecore_wayland/ecore_wl_output.c b/libraries/ecore/src/lib/ecore_wayland/ecore_wl_output.c new file mode 100644 index 0000000..9f540d4 --- /dev/null +++ b/libraries/ecore/src/lib/ecore_wayland/ecore_wl_output.c @@ -0,0 +1,79 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_wl_private.h" +#include "Ecore_Wayland.h" + +/* local function prototypes */ +static void _ecore_wl_output_cb_geometry(void *data, struct wl_output *wl_output __UNUSED__, int x, int y, int w __UNUSED__, int h __UNUSED__, int subpixel __UNUSED__, const char *make __UNUSED__, const char *model __UNUSED__); +static void _ecore_wl_output_cb_mode(void *data, struct wl_output *wl_output __UNUSED__, unsigned int flags, int w, int h, int refresh __UNUSED__); + +/* wayland listeners */ +static const struct wl_output_listener _ecore_wl_output_listener = +{ + _ecore_wl_output_cb_geometry, + _ecore_wl_output_cb_mode +}; + +void +_ecore_wl_output_add(Ecore_Wl_Display *ewd, unsigned int id) +{ + Ecore_Wl_Output *output; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(output = malloc(sizeof(Ecore_Wl_Output)))) return; + + memset(output, 0, sizeof(Ecore_Wl_Output)); + + output->display = ewd; + + output->output = wl_display_bind(ewd->wl.display, id, &wl_output_interface); + wl_list_insert(ewd->outputs.prev, &output->link); + wl_output_add_listener(output->output, &_ecore_wl_output_listener, output); +} + +void +_ecore_wl_output_del(Ecore_Wl_Output *output) +{ + if (!output) return; + if (output->destroy) (*output->destroy)(output, output->data); + if (output->output) wl_output_destroy(output->output); + wl_list_remove(&output->link); + free(output); +} + +/* local functions */ +static void +_ecore_wl_output_cb_geometry(void *data, struct wl_output *wl_output __UNUSED__, int x, int y, int w __UNUSED__, int h __UNUSED__, int subpixel __UNUSED__, const char *make __UNUSED__, const char *model __UNUSED__) +{ + Ecore_Wl_Output *output; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + output = data; + output->allocation.x = x; + output->allocation.y = y; +} + +static void +_ecore_wl_output_cb_mode(void *data, struct wl_output *wl_output __UNUSED__, unsigned int flags, int w, int h, int refresh __UNUSED__) +{ + Ecore_Wl_Output *output; + Ecore_Wl_Display *ewd; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + output = data; + ewd = output->display; + if (flags & WL_OUTPUT_MODE_CURRENT) + { + output->allocation.w = w; + output->allocation.h = h; + _ecore_wl_disp->output = output; + if (ewd->output_configure) (*ewd->output_configure)(output, ewd->data); + } +} diff --git a/libraries/ecore/src/lib/ecore_wayland/ecore_wl_window.c b/libraries/ecore/src/lib/ecore_wayland/ecore_wl_window.c new file mode 100644 index 0000000..e8a8bfb --- /dev/null +++ b/libraries/ecore/src/lib/ecore_wayland/ecore_wl_window.c @@ -0,0 +1,440 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_wl_private.h" +#include "Ecore_Wayland.h" + +/* local function prototypes */ +static void _ecore_wl_window_cb_configure(void *data, struct wl_shell_surface *shell_surface __UNUSED__, unsigned int timestamp, unsigned int edges, int w, int h); +static void _ecore_wl_window_cb_popup_done(void *data, struct wl_shell_surface *shell_surface __UNUSED__); +static void _ecore_wl_window_configure_send(Ecore_Wl_Window *win, int w, int h, unsigned int timestamp); + +/* local variables */ +static Eina_Hash *_windows = NULL; + +/* wayland listeners */ +static const struct wl_shell_surface_listener _ecore_wl_shell_surface_listener = +{ + _ecore_wl_window_cb_configure, + _ecore_wl_window_cb_popup_done +}; + +/* internal functions */ +void +_ecore_wl_window_init(void) +{ + if (!_windows) _windows = eina_hash_pointer_new(free); +} + +void +_ecore_wl_window_shutdown(void) +{ + eina_hash_free(_windows); + _windows = NULL; +} + +/** + * @defgroup Ecore_Wl_Window_Group Wayland Library Init and Shutdown Functions + * + * Functions that can be used to create a Wayland window. + */ + +/** + * Creates a new window + * + * @param parent The parent window to use. If @p parent is @c 0, the root window + * of the default display is used. + * @param x X Position + * @param y Y position + * @param w Width + * @param h Height + * + * @return The new window + * + * @ingroup Ecore_Wl_Window_Group + * @since 1.2 + */ +EAPI Ecore_Wl_Window * +ecore_wl_window_new(Ecore_Wl_Window *parent, int x, int y, int w, int h, int buffer_type) +{ + Ecore_Wl_Window *win; + static int _win_id = 1; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(win = malloc(sizeof(Ecore_Wl_Window)))) + { + ERR("Failed to allocate an Ecore Wayland Window"); + return NULL; + } + + memset(win, 0, sizeof(Ecore_Wl_Window)); + + win->display = _ecore_wl_disp; + win->parent = parent; + win->allocation.x = x; + win->allocation.y = y; + win->allocation.w = w; + win->allocation.h = h; + win->saved_allocation = win->allocation; + win->transparent = EINA_TRUE; + win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL; + win->buffer_type = buffer_type; + win->id = _win_id++; + + eina_hash_add(_windows, &win->id, win); + return win; +} + +/** + * Deletes the given window + * + * @param win The given window + * + * @ingroup Ecore_Wl_Window_Group + * @since 1.2 + */ +EAPI void +ecore_wl_window_free(Ecore_Wl_Window *win) +{ + Ecore_Wl_Input *input; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + + eina_hash_del(_windows, &win->id, NULL); + + wl_list_for_each(input, &_ecore_wl_disp->inputs, link) + { + if ((input->pointer_focus) && (input->pointer_focus == win)) + input->pointer_focus = NULL; + if ((input->keyboard_focus) && (input->keyboard_focus == win)) + input->keyboard_focus = NULL; + } + + if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface); + win->shell_surface = NULL; + + if (win->surface) wl_surface_destroy(win->surface); + win->surface = NULL; + +// free(win); +} + +/** + * Signals for Wayland to initiate a window move. + * + * The position requested (@p x, @p y) is not honored by Wayland because + * Wayland does not allow specific window placement to be set. + * + * @param win The window to move. + * @param x X Position + * @param y Y Position + * + * @ingroup Ecore_Wl_Window_Group + * @since 1.2 + */ +EAPI void +ecore_wl_window_move(Ecore_Wl_Window *win, int x, int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + win->allocation.x = x; + win->allocation.y = y; + if (win->shell_surface) + { + Ecore_Wl_Input *input; + + input = win->keyboard_device; + wl_shell_surface_move(win->shell_surface, input->input_device, + input->timestamp); + } +} + +/** + * Signals for Wayland to initiate a window resize. + * + * The size requested (@p w, @p h) is not honored by Wayland because + * Wayland does not allow specific window sizes to be set. + * + * @param win The window to resize. + * @param w Width + * @param h Height + * @param location The edge of the window from where the resize should start. + * + * @ingroup Ecore_Wl_Window_Group + * @since 1.2 + */ +EAPI void +ecore_wl_window_resize(Ecore_Wl_Window *win, int w, int h, int location) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + win->allocation.w = w; + win->allocation.h = h; + if (win->shell_surface) + { + Ecore_Wl_Input *input; + + input = win->keyboard_device; + wl_shell_surface_resize(win->shell_surface, input->input_device, + input->timestamp, location); + } +} + +EAPI void +ecore_wl_window_damage(Ecore_Wl_Window *win, int x, int y, int w, int h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + if (win->surface) + wl_surface_damage(win->surface, x, y, w, h); +} + +EAPI void +ecore_wl_window_buffer_attach(Ecore_Wl_Window *win, struct wl_buffer *buffer, int x, int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + if ((win->surface) && (buffer)) + wl_surface_attach(win->surface, buffer, x, y); +} + +/** + * Shows a window + * + * Synonymous to "mapping" a window in Wayland System terminology. + * + * @param win The window to show. + * + * @ingroup Ecore_Wl_Window_Group + * @since 1.2 + */ +EAPI void +ecore_wl_window_show(Ecore_Wl_Window *win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + if (win->surface) return; + + win->surface = wl_compositor_create_surface(_ecore_wl_disp->wl.compositor); + wl_surface_set_user_data(win->surface, win); + + win->shell_surface = + wl_shell_get_shell_surface(_ecore_wl_disp->wl.shell, win->surface); + wl_shell_surface_add_listener(win->shell_surface, + &_ecore_wl_shell_surface_listener, win); + + switch (win->type) + { + case ECORE_WL_WINDOW_TYPE_FULLSCREEN: + wl_shell_surface_set_fullscreen(win->shell_surface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + 0, NULL); + break; + case ECORE_WL_WINDOW_TYPE_MAXIMIZED: + wl_shell_surface_set_maximized(win->shell_surface, NULL); + break; + case ECORE_WL_WINDOW_TYPE_TRANSIENT: + wl_shell_surface_set_transient(win->shell_surface, + win->parent->shell_surface, + win->allocation.x, win->allocation.y, 0); + break; + case ECORE_WL_WINDOW_TYPE_MENU: + wl_shell_surface_set_popup(win->shell_surface, + win->pointer_device->input_device, + win->pointer_device->timestamp, + win->parent->shell_surface, + win->allocation.x, win->allocation.y, 0); + break; + case ECORE_WL_WINDOW_TYPE_TOPLEVEL: + default: + wl_shell_surface_set_toplevel(win->shell_surface); + break; + } +} + +/** + * Hides a window + * + * Synonymous to "unmapping" a window in Wayland System terminology. + * + * @param win The window to hide. + * + * @ingroup Ecore_Wl_Window_Group + * @since 1.2 + */ +EAPI void +ecore_wl_window_hide(Ecore_Wl_Window *win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface); + win->shell_surface = NULL; + if (win->surface) wl_surface_destroy(win->surface); + win->surface = NULL; +} + +/** + * Raises a window + * + * @param win The window to raise. + * + * @ingroup Ecore_Wl_Window_Group + * @since 1.2 + */ +EAPI void +ecore_wl_window_raise(Ecore_Wl_Window *win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + if (win->shell_surface) + wl_shell_surface_set_toplevel(win->shell_surface); +} + +EAPI void +ecore_wl_window_maximized_set(Ecore_Wl_Window *win, Eina_Bool maximized) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + if ((win->type == ECORE_WL_WINDOW_TYPE_MAXIMIZED) == maximized) return; + if (win->type == ECORE_WL_WINDOW_TYPE_TOPLEVEL) + { + win->saved_allocation = win->allocation; + if (win->shell_surface) + wl_shell_surface_set_maximized(win->shell_surface, NULL); + win->type = ECORE_WL_WINDOW_TYPE_MAXIMIZED; + } + else + { + Ecore_Wl_Input *input; + + input = win->keyboard_device; + + if (win->shell_surface) + wl_shell_surface_set_toplevel(win->shell_surface); + win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL; + win->allocation = win->saved_allocation; + _ecore_wl_window_configure_send(win, win->allocation.w, + win->allocation.h, input->timestamp); + } +} + +EAPI void +ecore_wl_window_fullscreen_set(Ecore_Wl_Window *win, Eina_Bool fullscreen) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + if ((win->type == ECORE_WL_WINDOW_TYPE_FULLSCREEN) == fullscreen) return; + if (fullscreen) + { + win->type = ECORE_WL_WINDOW_TYPE_FULLSCREEN; + win->saved_allocation = win->allocation; + if (win->shell_surface) + wl_shell_surface_set_fullscreen(win->shell_surface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + 0, NULL); + } + else + { + Ecore_Wl_Input *input; + + input = win->keyboard_device; + + if (win->shell_surface) + wl_shell_surface_set_toplevel(win->shell_surface); + win->type = ECORE_WL_WINDOW_TYPE_TOPLEVEL; + win->allocation = win->saved_allocation; + _ecore_wl_window_configure_send(win, win->allocation.w, + win->allocation.h, input->timestamp); + } +} + +EAPI void +ecore_wl_window_update_size(Ecore_Wl_Window *win, int w, int h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + win->allocation.w = w; + win->allocation.h = h; +} + +EAPI struct wl_surface * +ecore_wl_window_surface_get(Ecore_Wl_Window *win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return NULL; + return win->surface; +} + +EAPI Ecore_Wl_Window * +ecore_wl_window_find(unsigned int id) +{ + Ecore_Wl_Window *win; + + if (!id) return NULL; + win = eina_hash_find(_windows, &id); + if (win) return win; + return NULL; +} + +/* local functions */ +static void +_ecore_wl_window_cb_configure(void *data, struct wl_shell_surface *shell_surface __UNUSED__, unsigned int timestamp, unsigned int edges, int w, int h) +{ + Ecore_Wl_Window *win; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(win = data)) return; + if ((w <= 0) || (h <= 0)) return; + + win->edges = edges; + win->allocation.w = w; + win->allocation.h = h; + _ecore_wl_window_configure_send(win, w, h, timestamp); +} + +static void +_ecore_wl_window_cb_popup_done(void *data, struct wl_shell_surface *shell_surface __UNUSED__) +{ + Ecore_Wl_Window *win; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(win = data)) return; + /* TODO: handle popup destroy */ +} + +static void +_ecore_wl_window_configure_send(Ecore_Wl_Window *win, int w, int h, unsigned int timestamp) +{ + Ecore_Wl_Event_Window_Configure *ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Window_Configure)))) return; + ev->win = win->id; + ev->event_win = win->id; + ev->x = win->allocation.x; + ev->y = win->allocation.y; + ev->w = w; + ev->h = h; + ev->timestamp = timestamp; + ecore_event_add(ECORE_WL_EVENT_WINDOW_CONFIGURE, ev, NULL, NULL); +} -- cgit v1.1