From: devilhorns Date: Tue, 28 Feb 2012 21:55:51 +0000 (+0000) Subject: Ecore_Wayland: Refactor all the ecore_wayland code to improve running X-Git-Tag: 2.0_alpha~68^2~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ee61c5283681622b34c13760658c99cc69655e6f;p=framework%2Fuifw%2Fecore.git Ecore_Wayland: Refactor all the ecore_wayland code to improve running EFL applications as Wayland Clients. NB: This (along with the ecore_evas changes) fixes most (if not all) outstanding issues what I am aware of, including the nasty resize bug with wayland_egl. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@68515 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- diff --git a/src/lib/ecore_wayland/Ecore_Wayland.h b/src/lib/ecore_wayland/Ecore_Wayland.h index 2d04cff..ca048b2 100644 --- a/src/lib/ecore_wayland/Ecore_Wayland.h +++ b/src/lib/ecore_wayland/Ecore_Wayland.h @@ -3,6 +3,10 @@ # include # include +# include // NB: already includes wayland-client.h +# include +# include +# include # ifdef EAPI # undef EAPI @@ -18,71 +22,226 @@ # define EAPI # endif +typedef enum _Ecore_Wl_Window_Type Ecore_Wl_Window_Type; +typedef enum _Ecore_Wl_Window_Buffer_Type Ecore_Wl_Window_Buffer_Type; + +typedef struct _Ecore_Wl_Display Ecore_Wl_Display; +typedef struct _Ecore_Wl_Output Ecore_Wl_Output; +typedef struct _Ecore_Wl_Input Ecore_Wl_Input; +# ifndef _ECORE_WAYLAND_WINDOW_PREDEF +typedef struct _Ecore_Wl_Window Ecore_Wl_Window; +# endif +typedef struct _Ecore_Wl_Dnd_Source Ecore_Wl_Dnd_Source; +typedef struct _Ecore_Wl_Dnd_Target Ecore_Wl_Dnd_Target; + typedef struct _Ecore_Wl_Event_Mouse_In Ecore_Wl_Event_Mouse_In; typedef struct _Ecore_Wl_Event_Mouse_Out Ecore_Wl_Event_Mouse_Out; typedef struct _Ecore_Wl_Event_Focus_In Ecore_Wl_Event_Focus_In; typedef struct _Ecore_Wl_Event_Focus_Out Ecore_Wl_Event_Focus_Out; +typedef struct _Ecore_Wl_Event_Window_Configure Ecore_Wl_Event_Window_Configure; +typedef struct _Ecore_Wl_Event_Dnd_Enter Ecore_Wl_Event_Dnd_Enter; +typedef struct _Ecore_Wl_Event_Dnd_Position Ecore_Wl_Event_Dnd_Position; +typedef struct _Ecore_Wl_Event_Dnd_Leave Ecore_Wl_Event_Dnd_Leave; +typedef struct _Ecore_Wl_Event_Dnd_Drop Ecore_Wl_Event_Dnd_Drop; -typedef struct _Ecore_Wl_Drag_Source Ecore_Wl_Drag_Source; +enum _Ecore_Wl_Window_Type +{ + ECORE_WL_WINDOW_TYPE_TOPLEVEL, + ECORE_WL_WINDOW_TYPE_FULLSCREEN, + ECORE_WL_WINDOW_TYPE_MAXIMIZED, + ECORE_WL_WINDOW_TYPE_TRANSIENT, + ECORE_WL_WINDOW_TYPE_MENU, + ECORE_WL_WINDOW_TYPE_CUSTOM +}; -typedef struct _Ecore_Wl_Event_Drag_Start Ecore_Wl_Event_Drag_Start; -typedef struct _Ecore_Wl_Event_Drag_Stop Ecore_Wl_Event_Drag_Stop; +enum _Ecore_Wl_Window_Buffer_Type +{ + ECORE_WL_WINDOW_BUFFER_TYPE_EGL_WINDOW, + ECORE_WL_WINDOW_BUFFER_TYPE_EGL_IMAGE, + ECORE_WL_WINDOW_BUFFER_TYPE_SHM +}; -struct _Ecore_Wl_Event_Mouse_In +struct _Ecore_Wl_Display { - int modifiers; - int x, y; + struct + { + struct wl_display *display; + struct wl_compositor *compositor; + struct wl_shell *shell; + struct wl_shm *shm; + struct wl_data_device_manager *data_device_manager; + } wl; struct { - int x, y; - } root; + EGLDisplay display; + EGLConfig rgb_config; + EGLConfig argb_config; + EGLContext rgb_context; + EGLContext argb_context; + } egl; + + int fd; + unsigned int mask; + Ecore_Fd_Handler *fd_hdl; + + struct wl_list inputs; + struct wl_list outputs; + + struct xkb_desc *xkb; + + Ecore_Wl_Output *output; + + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; + PFNEGLCREATEIMAGEKHRPROC create_image; + PFNEGLDESTROYIMAGEKHRPROC destroy_image; + + void (*output_configure)(Ecore_Wl_Output *output, void *data); + void *data; +}; + +struct _Ecore_Wl_Output +{ + Ecore_Wl_Display *display; + struct wl_output *output; + Eina_Rectangle allocation; + struct wl_list link; + + void (*destroy) (Ecore_Wl_Output *output, void *data); + void *data; +}; + +struct _Ecore_Wl_Input +{ + Ecore_Wl_Display *display; + struct wl_input_device *input_device; + struct wl_data_device *data_device; + + Ecore_Wl_Window *pointer_focus; + Ecore_Wl_Window *keyboard_focus; + + unsigned int button; + unsigned int timestamp; + unsigned int modifiers; + int sx, sy; + + struct wl_list link; + + /* TODO: grab */ + unsigned int grab_button; + + Ecore_Wl_Dnd_Source *drag_source; + Ecore_Wl_Dnd_Source *selection_source; +}; + +struct _Ecore_Wl_Window +{ + Ecore_Wl_Display *display; + Ecore_Wl_Window *parent; + + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + + int id; + int x, y; + int edges; + + Eina_Rectangle allocation, pending_allocation; + Eina_Rectangle saved_allocation, server_allocation; + + Eina_Bool redraw_scheduled : 1; + Eina_Bool resize_scheduled : 1; + Eina_Bool transparent : 1; + + Ecore_Wl_Window_Type type; + Ecore_Wl_Window_Buffer_Type buffer_type; - unsigned int window; + Ecore_Wl_Input *pointer_device; + Ecore_Wl_Input *keyboard_device; - unsigned int time; + void *data; }; -struct _Ecore_Wl_Event_Mouse_Out +struct _Ecore_Wl_Event_Mouse_In { int modifiers; int x, y; + struct + { + int x, y; + } root; + unsigned int win; + unsigned int event_win; + unsigned int root_win; + unsigned int timestamp; +}; +struct _Ecore_Wl_Event_Mouse_Out +{ + int modifiers; + int x, y; struct { int x, y; } root; + unsigned int win; + unsigned int event_win; + unsigned int root_win; + unsigned int timestamp; +}; - unsigned int window; +struct _Ecore_Wl_Event_Focus_In +{ + unsigned int win; + unsigned int timestamp; +}; - unsigned int time; +struct _Ecore_Wl_Event_Focus_Out +{ + unsigned int win; + unsigned int timestamp; }; -struct _Ecore_Wl_Event_Focus_In +struct _Ecore_Wl_Event_Window_Configure { - unsigned int window; - /* TODO: mode & detail */ - unsigned int time; + unsigned int win; + unsigned int event_win; + int x, y, w, h; + unsigned int timestamp; }; -struct _Ecore_Wl_Event_Focus_Out +struct _Ecore_Wl_Event_Dnd_Enter { - unsigned int window; - /* TODO: mode & detail */ - unsigned int time; + unsigned int win, source; + char **types; + int num_types; + struct + { + int x, y; + } position; }; -struct _Ecore_Wl_Event_Drag_Start +struct _Ecore_Wl_Event_Dnd_Position { - struct wl_data_device *device; - struct wl_surface *surface; - const char *mime_type; - uint32_t timestamp; + unsigned int win, source; + struct + { + int x, y; + } position; }; -struct _Ecore_Wl_Event_Drag_Stop +struct _Ecore_Wl_Event_Dnd_Leave { + unsigned int win, source; +}; +struct _Ecore_Wl_Event_Dnd_Drop +{ + unsigned int win, source; + struct + { + int x, y; + } position; }; /** @@ -95,30 +254,37 @@ struct _Ecore_Wl_Event_Drag_Stop * @li @ref Ecore_Wl_Init_Group */ +EAPI extern int ECORE_WL_EVENT_MOUSE_IN; +EAPI extern int ECORE_WL_EVENT_MOUSE_OUT; +EAPI extern int ECORE_WL_EVENT_FOCUS_IN; +EAPI extern int ECORE_WL_EVENT_FOCUS_OUT; +EAPI extern int ECORE_WL_EVENT_WINDOW_CONFIGURE; +EAPI extern int ECORE_WL_EVENT_DND_ENTER; +EAPI extern int ECORE_WL_EVENT_DND_POSITION; +EAPI extern int ECORE_WL_EVENT_DND_LEAVE; +EAPI extern int ECORE_WL_EVENT_DND_DROP; + EAPI int ecore_wl_init(const char *name); EAPI int ecore_wl_shutdown(void); - -EAPI struct wl_display *ecore_wl_display_get(void); -EAPI struct wl_shm *ecore_wl_shm_get(void); -EAPI struct wl_compositor *ecore_wl_compositor_get(void); -EAPI struct wl_shell *ecore_wl_shell_get(void); -EAPI struct wl_input_device *ecore_wl_input_device_get(void); -EAPI void ecore_wl_screen_size_get(int *w, int *h); -EAPI unsigned int ecore_wl_format_get(void); EAPI void ecore_wl_flush(void); EAPI void ecore_wl_sync(void); -EAPI void ecore_wl_pointer_xy_get(int *x, int *y); -EAPI unsigned int ecore_wl_input_timestamp_get(void); - -EAPI Ecore_Wl_Drag_Source *ecore_wl_drag_source_create(int hotspot_x, int hotspot_y, int offset_x, int offset_y, const char *mimetype, unsigned int timestamp, void *data); -EAPI void ecore_wl_drag_start(Ecore_Wl_Drag_Source *source, struct wl_surface *surface, struct wl_buffer *buffer); -EAPI void ecore_wl_drag_stop(void); +EAPI struct wl_shm *ecore_wl_shm_get(void); +EAPI struct wl_display *ecore_wl_display_get(void); +EAPI void ecore_wl_screen_size_get(int *w, int *h); -EAPI extern int ECORE_WL_EVENT_MOUSE_IN; -EAPI extern int ECORE_WL_EVENT_MOUSE_OUT; -EAPI extern int ECORE_WL_EVENT_FOCUS_IN; -EAPI extern int ECORE_WL_EVENT_FOCUS_OUT; -EAPI extern int ECORE_WL_EVENT_DRAG_START; -EAPI extern int ECORE_WL_EVENT_DRAG_STOP; +EAPI Ecore_Wl_Window *ecore_wl_window_new(Ecore_Wl_Window *parent, int x, int y, int w, int h, int buffer_type); +EAPI void ecore_wl_window_free(Ecore_Wl_Window *win); +EAPI void ecore_wl_window_move(Ecore_Wl_Window *win, int x, int y); +EAPI void ecore_wl_window_resize(Ecore_Wl_Window *win, int w, int h, int location); +EAPI void ecore_wl_window_damage(Ecore_Wl_Window *win, int x, int y, int w, int h); +EAPI void ecore_wl_window_buffer_attach(Ecore_Wl_Window *win, struct wl_buffer *buffer, int x, int y); +EAPI void ecore_wl_window_show(Ecore_Wl_Window *win); +EAPI void ecore_wl_window_hide(Ecore_Wl_Window *win); +EAPI void ecore_wl_window_raise(Ecore_Wl_Window *win); +EAPI void ecore_wl_window_maximized_set(Ecore_Wl_Window *win, Eina_Bool maximized); +EAPI void ecore_wl_window_fullscreen_set(Ecore_Wl_Window *win, Eina_Bool fullscreen); +EAPI void ecore_wl_window_update_size(Ecore_Wl_Window *win, int w, int h); +EAPI struct wl_surface *ecore_wl_window_surface_get(Ecore_Wl_Window *win); +EAPI Ecore_Wl_Window *ecore_wl_window_find(unsigned int id); #endif diff --git a/src/lib/ecore_wayland/Makefile.am b/src/lib/ecore_wayland/Makefile.am index ea005b2..f6b801d 100644 --- a/src/lib/ecore_wayland/Makefile.am +++ b/src/lib/ecore_wayland/Makefile.am @@ -14,9 +14,11 @@ includes_HEADERS = Ecore_Wayland.h includesdir = $(includedir)/ecore-@VMAJ@ libecore_wayland_la_SOURCES = \ -ecore_wl.c - -## ecore_wl_window.c +ecore_wl.c \ +ecore_wl_output.c \ +ecore_wl_input.c \ +ecore_wl_window.c \ +ecore_wl_dnd.c libecore_wayland_la_LIBADD = \ $(top_builddir)/src/lib/ecore/libecore.la \ diff --git a/src/lib/ecore_wayland/ecore_wl.c b/src/lib/ecore_wayland/ecore_wl.c index df25ee4..9b28ab4 100644 --- a/src/lib/ecore_wayland/ecore_wl.c +++ b/src/lib/ecore_wayland/ecore_wl.c @@ -1,16 +1,11 @@ #ifdef HAVE_CONFIG_H -# include "config.h" +# include #endif -#include "Ecore.h" -#include "ecore_private.h" -#include "Ecore_Input.h" -#include "ecore_wl_private.h" -#include "Ecore_Wayland.h" +#include /* FIXME: This gives BTN_LEFT/RIGHT/MIDDLE for linux systems ... * What about other OSs ?? */ -#include #ifdef __linux__ # include #else @@ -23,152 +18,85 @@ # define BTN_BACK 0x116 #endif -#include +#include "Ecore.h" +#include "ecore_private.h" +#include "Ecore_Input.h" +#include "ecore_wl_private.h" +#include "Ecore_Wayland.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_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 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, struct wl_surface *surface, 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_cb_handle_touch_down(void *data __UNUSED__, struct wl_input_device *dev __UNUSED__, uint32_t timestamp, struct wl_surface *surface, int32_t id, int32_t x, int32_t y); -static void _ecore_wl_cb_handle_touch_up(void *data __UNUSED__, struct wl_input_device *dev __UNUSED__, uint32_t timestamp, int32_t id); -static void _ecore_wl_cb_handle_touch_motion(void *data __UNUSED__, struct wl_input_device *dev __UNUSED__, uint32_t timestamp, int32_t id, int32_t x, int32_t y); -static void _ecore_wl_cb_handle_touch_frame(void *data __UNUSED__, struct wl_input_device *dev __UNUSED__); -static void _ecore_wl_cb_handle_touch_cancel(void *data __UNUSED__, struct wl_input_device *dev __UNUSED__); -static void _ecore_wl_cb_source_target(void *data, struct wl_data_source *source __UNUSED__, const char *mime_type __UNUSED__); -static void _ecore_wl_cb_source_send(void *data, struct wl_data_source *source, const char *mime_type, int32_t fd); -static void _ecore_wl_cb_source_cancelled(void *data, struct wl_data_source *source __UNUSED__); -static void _ecore_wl_cb_source_offer(void *data, struct wl_data_offer *offer __UNUSED__, const char *type); -static void _ecore_wl_cb_data_offer(void *data, struct wl_data_device *data_dev, uint32_t id); -static void _ecore_wl_cb_data_enter(void *data __UNUSED__, struct wl_data_device *data_dev, uint32_t timestamp, struct wl_surface *surface, int32_t x, int32_t y, struct wl_data_offer *offer); -static void _ecore_wl_cb_data_leave(void *data __UNUSED__, struct wl_data_device *data_dev); -static void _ecore_wl_cb_data_motion(void *data __UNUSED__, struct wl_data_device *data_dev, uint32_t timestamp, int32_t x, int32_t y); -static void _ecore_wl_cb_data_drop(void *data __UNUSED__, struct wl_data_device *data_dev); -static void _ecore_wl_cb_data_selection(void *data, struct wl_data_device *data_dev, struct wl_data_offer *offer); -static void _ecore_wl_cb_mouse_move_free(void *data __UNUSED__, void *event); - -static void _ecore_wl_mouse_move_send(uint32_t timestamp); -static void _ecore_wl_mouse_out_send(struct wl_surface *surface, uint32_t timestamp); -static void _ecore_wl_mouse_in_send(struct wl_surface *surface, uint32_t timestamp); -static void _ecore_wl_mouse_up_send(struct wl_surface *surface, uint32_t button, uint32_t timestamp); -static void _ecore_wl_mouse_down_send(struct wl_surface *surface, uint32_t button, uint32_t timestamp); -static void _ecore_wl_focus_out_send(struct wl_surface *surface, uint32_t timestamp); -static void _ecore_wl_focus_in_send(struct wl_surface *surface, uint32_t timestamp); +static Eina_Bool _ecore_wl_shutdown(Eina_Bool close); +static int _ecore_wl_cb_event_mask_update(unsigned int mask, void *data); +static Eina_Bool _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl __UNUSED__); +static void _ecore_wl_cb_handle_global(struct wl_display *disp, unsigned int id, const char *interface, unsigned int version __UNUSED__, void *data); +static Eina_Bool _ecore_wl_egl_init(Ecore_Wl_Display *ewd); +static Eina_Bool _ecore_wl_egl_shutdown(Ecore_Wl_Display *ewd); +static Eina_Bool _ecore_wl_xkb_init(Ecore_Wl_Display *ewd); +static Eina_Bool _ecore_wl_xkb_shutdown(Ecore_Wl_Display *ewd); /* 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_ARGB8888; -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_touch_x = 0; -static int _ecore_wl_touch_y = 0; -static int _ecore_wl_input_modifiers = 0; -static struct xkb_desc *_ecore_wl_xkb = NULL; -static uint32_t _ecore_wl_input_button = 0; -static uint32_t _ecore_wl_input_timestamp = 0; - -static struct wl_compositor *_ecore_wl_comp = NULL; -static struct wl_shm *_ecore_wl_shm = NULL; -static struct wl_shell *_ecore_wl_shell = NULL; -static struct wl_output *_ecore_wl_output = NULL; -static struct wl_input_device *_ecore_wl_input_dev = NULL; -static struct wl_surface *_ecore_wl_input_surface = NULL; -static struct wl_surface *_ecore_wl_touch_surface = NULL; -static struct wl_data_device_manager *_ecore_wl_data_manager = NULL; -static struct wl_data_device *_ecore_wl_data_dev = NULL; - -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, - _ecore_wl_cb_handle_touch_down, - _ecore_wl_cb_handle_touch_up, - _ecore_wl_cb_handle_touch_motion, - _ecore_wl_cb_handle_touch_frame, - _ecore_wl_cb_handle_touch_cancel, -}; -static const struct wl_data_source_listener _ecore_wl_source_listener = -{ - _ecore_wl_cb_source_target, - _ecore_wl_cb_source_send, - _ecore_wl_cb_source_cancelled -}; -static const struct wl_data_device_listener _ecore_wl_data_listener = -{ - _ecore_wl_cb_data_offer, - _ecore_wl_cb_data_enter, - _ecore_wl_cb_data_leave, - _ecore_wl_cb_data_motion, - _ecore_wl_cb_data_drop, - _ecore_wl_cb_data_selection -}; -static const struct wl_data_offer_listener _ecore_wl_offer_listener = -{ - _ecore_wl_cb_source_offer, -}; /* external variables */ int _ecore_wl_log_dom = -1; +Ecore_Wl_Display *_ecore_wl_disp = NULL; + 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_EVENT_DRAG_START = 0; -EAPI int ECORE_WL_EVENT_DRAG_STOP = 0; - +EAPI int ECORE_WL_EVENT_WINDOW_CONFIGURE = 0; +EAPI int ECORE_WL_EVENT_DND_ENTER = 0; +EAPI int ECORE_WL_EVENT_DND_POSITION = 0; +EAPI int ECORE_WL_EVENT_DND_LEAVE = 0; +EAPI int ECORE_WL_EVENT_DND_DROP = 0; + +/** + * @defgroup Ecore_Wl_Init_Group Wayland Library Init and Shutdown Functions + * + * Functions that start and shutdown the Ecore Wayland Library. + */ + +/** + * Initialize the Wayland display connection to the given display. + * + * @param name Display target name. if @c NULL, the default display is + * assumed. + * @return The number of times the library has been initialized without being + * shut down. 0 is returned if an error occurs. + * + * @ingroup Ecore_Wl_Init_Group + */ EAPI int -ecore_wl_init(const char *name) +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 (++_ecore_wl_init_count != 1) return _ecore_wl_init_count; + 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) + if (_ecore_wl_log_dom < 0) { - EINA_LOG_ERR("Cannot create a log domain for Ecore Wayland."); + EINA_LOG_ERR("Cannot create a log domain for Ecore Wayland"); eina_shutdown(); return --_ecore_wl_init_count; } - if (!ecore_init()) + if (!ecore_init()) { + ERR("Could not initialize ecore"); eina_log_domain_unregister(_ecore_wl_log_dom); _ecore_wl_log_dom = -1; eina_shutdown(); return --_ecore_wl_init_count; } - if (!ecore_event_init()) + if (!ecore_event_init()) { + ERR("Could not initialize ecore_event"); eina_log_domain_unregister(_ecore_wl_log_dom); _ecore_wl_log_dom = -1; ecore_shutdown(); @@ -176,26 +104,22 @@ ecore_wl_init(const char *name) return --_ecore_wl_init_count; } - if (!ECORE_WL_EVENT_MOUSE_IN) + 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(); - ECORE_WL_EVENT_DRAG_START = ecore_event_type_new(); - ECORE_WL_EVENT_DRAG_STOP = ecore_event_type_new(); + ECORE_WL_EVENT_WINDOW_CONFIGURE = ecore_event_type_new(); + ECORE_WL_EVENT_DND_ENTER = ecore_event_type_new(); + ECORE_WL_EVENT_DND_POSITION = ecore_event_type_new(); + ECORE_WL_EVENT_DND_LEAVE = ecore_event_type_new(); + ECORE_WL_EVENT_DND_DROP = 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))) + if (!(_ecore_wl_disp = malloc(sizeof(Ecore_Wl_Display)))) { - ERR("Could not compile keymap"); + ERR("Could not allocate memory for Ecore_Wl_Display structure"); eina_log_domain_unregister(_ecore_wl_log_dom); _ecore_wl_log_dom = -1; ecore_event_shutdown(); @@ -204,10 +128,11 @@ ecore_wl_init(const char *name) return --_ecore_wl_init_count; } - /* connect to the wayland display */ - if (!(_ecore_wl_disp = wl_display_connect(name))) + memset(_ecore_wl_disp, 0, sizeof(Ecore_Wl_Display)); + + if (!(_ecore_wl_disp->wl.display = wl_display_connect(name))) { - ERR("Could not connect to display"); + ERR("Could not connect to Wayland display"); eina_log_domain_unregister(_ecore_wl_log_dom); _ecore_wl_log_dom = -1; ecore_event_shutdown(); @@ -216,23 +141,28 @@ ecore_wl_init(const char *name) 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); + _ecore_wl_disp->fd = + wl_display_get_fd(_ecore_wl_disp->wl.display, + _ecore_wl_cb_event_mask_update, _ecore_wl_disp); - /* process connection events */ - wl_display_iterate(_ecore_wl_disp, WL_DISPLAY_READABLE); + _ecore_wl_disp->fd_hdl = + ecore_main_fd_handler_add(_ecore_wl_disp->fd, ECORE_FD_READ, + _ecore_wl_cb_handle_data, _ecore_wl_disp, + NULL, NULL); - fd = wl_display_get_fd(_ecore_wl_disp, - _ecore_wl_cb_disp_event_mask_update, NULL); + wl_list_init(&_ecore_wl_disp->inputs); + wl_list_init(&_ecore_wl_disp->outputs); - _ecore_wl_fd_hdl = - ecore_main_fd_handler_add(fd, ECORE_FD_READ, _ecore_wl_cb_fd_handle, - _ecore_wl_disp, NULL, NULL); - if (!_ecore_wl_fd_hdl) + wl_display_add_global_listener(_ecore_wl_disp->wl.display, + _ecore_wl_cb_handle_global, _ecore_wl_disp); + + /* FIXME: Process connection events ?? */ + /* wl_display_iterate(_ecore_wl_disp->wl.display, WL_DISPLAY_READABLE); */ + + if (!_ecore_wl_egl_init(_ecore_wl_disp)) { - wl_display_destroy(_ecore_wl_disp); - _ecore_wl_disp = NULL; + ERR("Could not initialize EGL"); + free(_ecore_wl_disp); eina_log_domain_unregister(_ecore_wl_log_dom); _ecore_wl_log_dom = -1; ecore_event_shutdown(); @@ -241,1015 +171,302 @@ ecore_wl_init(const char *name) return --_ecore_wl_init_count; } - return _ecore_wl_init_count; -} + _ecore_wl_disp->image_target_texture_2d = + (void *)eglGetProcAddress("glEGLImageTargetTexture2DOES"); + _ecore_wl_disp->create_image = + (void *)eglGetProcAddress("eglCreateImageKHR"); + _ecore_wl_disp->destroy_image = + (void *)eglGetProcAddress("eglDestroyImageKHR"); -EAPI int -ecore_wl_shutdown(void) -{ - return _ecore_wl_shutdown(EINA_TRUE); -} + /* TODO: create pointer surfaces */ -EAPI struct wl_display * -ecore_wl_display_get(void) -{ - return _ecore_wl_disp; -} + if (!_ecore_wl_xkb_init(_ecore_wl_disp)) + { + ERR("Could not initialize XKB"); + _ecore_wl_egl_shutdown(_ecore_wl_disp); + free(_ecore_wl_disp); + 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; + } -EAPI struct wl_shm * -ecore_wl_shm_get(void) -{ - return _ecore_wl_shm; -} + _ecore_wl_window_init(); -EAPI struct wl_compositor * -ecore_wl_compositor_get(void) -{ - return _ecore_wl_comp; + return _ecore_wl_init_count; } -EAPI struct wl_shell * -ecore_wl_shell_get(void) +/** + * Shuts down the Ecore Wayland Library + * + * In shutting down the library, the Wayland display connection is terminated + * and any event handlers for it are removed. + * + * @return The number of times the library has been initialized without + * being shut down. + * + * @ingroup Ecore_Wl_Init_Group + */ +EAPI int +ecore_wl_shutdown(void) { - return _ecore_wl_shell; -} + LOGFN(__FILE__, __LINE__, __FUNCTION__); -EAPI struct wl_input_device * -ecore_wl_input_device_get(void) -{ - return _ecore_wl_input_dev; + return _ecore_wl_shutdown(EINA_TRUE); } EAPI void -ecore_wl_screen_size_get(int *w, int *h) +ecore_wl_flush(void) { - if (w) *w = _ecore_wl_screen.w; - if (h) *h = _ecore_wl_screen.h; -} + LOGFN(__FILE__, __LINE__, __FUNCTION__); -EAPI unsigned int -ecore_wl_format_get(void) -{ - return _ecore_wl_disp_format; -} + while (_ecore_wl_disp->mask & WL_DISPLAY_WRITABLE) + wl_display_iterate(_ecore_wl_disp->wl.display, WL_DISPLAY_WRITABLE); -EAPI void -ecore_wl_flush(void) -{ - wl_display_flush(_ecore_wl_disp); +// wl_display_flush(_ecore_wl_disp->wl.display); // old flush code } EAPI void -ecore_wl_sync(void) +ecore_wl_sync(void) { - wl_display_iterate(_ecore_wl_disp, WL_DISPLAY_READABLE); -} + LOGFN(__FILE__, __LINE__, __FUNCTION__); -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; + wl_display_roundtrip(_ecore_wl_disp->wl.display); + // old sync code +// wl_display_iterate(_ecore_wl_disp->wl.display, WL_DISPLAY_READABLE); } -EAPI unsigned int -ecore_wl_input_timestamp_get(void) -{ - return _ecore_wl_input_timestamp; -} - -EAPI Ecore_Wl_Drag_Source * -ecore_wl_drag_source_create(int hotspot_x, int hotspot_y, int offset_x, int offset_y, const char *mimetype, unsigned int timestamp, void *data) +EAPI struct wl_shm * +ecore_wl_shm_get(void) { - Ecore_Wl_Drag_Source *source; - - if (!(source = calloc(1, sizeof(Ecore_Wl_Drag_Source)))) return NULL; - - source->data_dev = _ecore_wl_data_dev; - source->hotspot_x = hotspot_x; - source->hotspot_y = hotspot_y; - source->offset_x = offset_x; - source->offset_y = offset_y; - source->mimetype = mimetype; - source->timestamp = timestamp; - source->data = data; - - source->data_source = - wl_data_device_manager_create_data_source(_ecore_wl_data_manager); - - wl_data_source_add_listener(source->data_source, - &_ecore_wl_source_listener, source); - - wl_data_source_offer(source->data_source, source->mimetype); - - /* NB: Do we add some default mimetypes here ?? */ - /* text/plain, etc */ - - return source; + return _ecore_wl_disp->wl.shm; } -EAPI void -ecore_wl_drag_start(Ecore_Wl_Drag_Source *source, struct wl_surface *surface, struct wl_buffer *buffer) +EAPI struct wl_display * +ecore_wl_display_get(void) { - source->buffer = buffer; - - wl_data_device_start_drag(source->data_dev, source->data_source, - surface, surface, source->timestamp); + return _ecore_wl_disp->wl.display; } EAPI void -ecore_wl_drag_stop(void) +ecore_wl_screen_size_get(int *w, int *h) { + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (w) *w = _ecore_wl_disp->output->allocation.w; + if (h) *h = _ecore_wl_disp->output->allocation.h; } /* local functions */ static Eina_Bool -_ecore_wl_shutdown(Eina_Bool close_display) +_ecore_wl_shutdown(Eina_Bool close) { LOGFN(__FILE__, __LINE__, __FUNCTION__); - if (--_ecore_wl_init_count != 0) - return _ecore_wl_init_count; - + 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); + _ecore_wl_window_shutdown(); - if (_ecore_wl_fd_hdl) ecore_main_fd_handler_del(_ecore_wl_fd_hdl); - _ecore_wl_fd_hdl = NULL; + if (_ecore_wl_disp->fd_hdl) + ecore_main_fd_handler_del(_ecore_wl_disp->fd_hdl); - if (close_display) + if (close) { - if (_ecore_wl_data_dev) wl_data_device_destroy(_ecore_wl_data_dev); - if (_ecore_wl_input_dev) wl_input_device_destroy(_ecore_wl_input_dev); - if (_ecore_wl_data_manager) - wl_data_device_manager_destroy(_ecore_wl_data_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) + Ecore_Wl_Output *out, *tout; + Ecore_Wl_Input *in, *tin; + + wl_list_for_each_safe(out, tout, &_ecore_wl_disp->outputs, link) + _ecore_wl_output_del(out); + + wl_list_for_each_safe(in, tin, &_ecore_wl_disp->inputs, link) + _ecore_wl_input_del(in); + + _ecore_wl_xkb_shutdown(_ecore_wl_disp); + _ecore_wl_egl_shutdown(_ecore_wl_disp); + + if (_ecore_wl_disp->wl.shell) + wl_shell_destroy(_ecore_wl_disp->wl.shell); + if (_ecore_wl_disp->wl.shm) wl_shm_destroy(_ecore_wl_disp->wl.shm); + if (_ecore_wl_disp->wl.data_device_manager) + wl_data_device_manager_destroy(_ecore_wl_disp->wl.data_device_manager); + if (_ecore_wl_disp->wl.compositor) + wl_compositor_destroy(_ecore_wl_disp->wl.compositor); + if (_ecore_wl_disp->wl.display) { - wl_display_flush(_ecore_wl_disp); - wl_display_destroy(_ecore_wl_disp); + wl_display_flush(_ecore_wl_disp->wl.display); + wl_display_destroy(_ecore_wl_disp->wl.display); } - _ecore_wl_disp = NULL; + free(_ecore_wl_disp); } - eina_log_domain_unregister(_ecore_wl_log_dom); - _ecore_wl_log_dom = -1; - ecore_event_shutdown(); ecore_shutdown(); + + eina_log_domain_unregister(_ecore_wl_log_dom); + _ecore_wl_log_dom = -1; 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); - } - 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_dev = - wl_display_bind(_ecore_wl_disp, id, &wl_input_device_interface); - wl_input_device_add_listener(_ecore_wl_input_dev, - &_ecore_wl_input_listener, NULL); - } - else if (!strcmp(interface, "wl_data_device_manager")) - { - _ecore_wl_data_manager = - wl_display_bind(_ecore_wl_disp, id, - &wl_data_device_manager_interface); - } - - if ((_ecore_wl_input_dev) && (_ecore_wl_data_manager) && (!_ecore_wl_data_dev)) - { - _ecore_wl_data_dev = - wl_data_device_manager_get_data_device(_ecore_wl_data_manager, - _ecore_wl_input_dev); - wl_data_device_add_listener(_ecore_wl_data_dev, - &_ecore_wl_data_listener, NULL); - } -} - static int -_ecore_wl_cb_disp_event_mask_update(uint32_t mask, void *data __UNUSED__) +_ecore_wl_cb_event_mask_update(unsigned int mask, void *data) { -// LOGFN(__FILE__, __LINE__, __FUNCTION__); + Ecore_Wl_Display *ewd; - _ecore_wl_disp_mask = mask; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ewd = data; + ewd->mask = mask; return 0; } -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__) +_ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl __UNUSED__) { - struct wl_display *disp; - -// LOGFN(__FILE__, __LINE__, __FUNCTION__); - - if (!(disp = data)) return ECORE_CALLBACK_RENEW; - if (disp != _ecore_wl_disp) return ECORE_CALLBACK_RENEW; + Ecore_Wl_Display *ewd; - if (_ecore_wl_disp_mask & WL_DISPLAY_WRITABLE) - wl_display_iterate(_ecore_wl_disp, WL_DISPLAY_WRITABLE); - - if (_ecore_wl_disp_mask & WL_DISPLAY_READABLE) - wl_display_iterate(_ecore_wl_disp, WL_DISPLAY_READABLE); + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!(ewd = data)) return ECORE_CALLBACK_RENEW; + wl_display_iterate(ewd->wl.display, ewd->mask); return ECORE_CALLBACK_RENEW; } static void -_ecore_wl_cb_handle_motion(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, int32_t sx, int32_t sy) +_ecore_wl_cb_handle_global(struct wl_display *disp, unsigned int id, const char *interface, unsigned int version __UNUSED__, void *data) { -// LOGFN(__FILE__, __LINE__, __FUNCTION__); - - if (dev != _ecore_wl_input_dev) return; - - /* _ecore_wl_screen_x = x; */ - /* _ecore_wl_screen_y = y; */ - _ecore_wl_surface_x = sx; - _ecore_wl_surface_y = sy; - - _ecore_wl_mouse_move_send(t); -} + Ecore_Wl_Display *ewd; -static void -_ecore_wl_cb_handle_button(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, uint32_t btn, uint32_t state) -{ LOGFN(__FILE__, __LINE__, __FUNCTION__); - if (dev != _ecore_wl_input_dev) 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 + ewd = data; + if (!strcmp(interface, "wl_compositor")) + ewd->wl.compositor = wl_display_bind(disp, id, &wl_compositor_interface); + else if (!strcmp(interface, "wl_output")) + _ecore_wl_output_add(ewd, id); + else if (!strcmp(interface, "wl_input_device")) + _ecore_wl_input_add(ewd, id); + else if (!strcmp(interface, "wl_shell")) + ewd->wl.shell = wl_display_bind(disp, id, &wl_shell_interface); + else if (!strcmp(interface, "wl_shm")) + ewd->wl.shm = wl_display_bind(disp, id, &wl_shm_interface); + else if (!strcmp(interface, "wl_data_device_manager")) { - _ecore_wl_mouse_move_send(t); - - if (state) - { - _ecore_wl_input_button = btn; - if (_ecore_wl_input_surface) - _ecore_wl_mouse_down_send(_ecore_wl_input_surface, btn, t); - - /* NB: Ideally, this is not the place to check for drags. - * IMO, drags should be handled by the client. EG: we raise the - * mouse_down to the client, and the client can 'request' a - * drag_start from ecore_wl */ - if ((_ecore_wl_input_surface) || (_ecore_wl_touch_surface)) - { - /* record item which was grabbed. - * create drag source. start drag */ - } - } - else - { - if ((_ecore_wl_input_surface) || (_ecore_wl_touch_surface)) - { - /* release grabbed button and finish drag */ - if ((_ecore_wl_input_button) && - (_ecore_wl_input_button == btn)) - { - - } - } - _ecore_wl_input_button = 0; - if (_ecore_wl_input_surface) - _ecore_wl_mouse_up_send(_ecore_wl_input_surface, btn, t); - } + ewd->wl.data_device_manager = + wl_display_bind(disp, id, &wl_data_device_manager_interface); } } -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 ((!_ecore_wl_input_surface) || (dev != _ecore_wl_input_dev)) 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, struct wl_surface *surface, int32_t sx, int32_t sy) +static Eina_Bool +_ecore_wl_egl_init(Ecore_Wl_Display *ewd) { - if (dev != _ecore_wl_input_dev) return; - - /* NB: Wayland pointer focus is weird. It's not pointer focus in the normal - * sense...Wayland 'moving/resizing' (and maybe other stuff) has a habit - * of stealing the pointer focus and thus this cannot be used to control - * normal pointer focus. On mouse down, the 'active' surface is stolen - * by Wayland for the grab, so 'surface' here ends up being NULL. When a - * move or resize is finished, we get this event again, but this time - * with an active surface */ - - /* _ecore_wl_screen_x = x; */ - /* _ecore_wl_screen_y = y; */ - _ecore_wl_surface_x = sx; - _ecore_wl_surface_y = sy; - - if ((_ecore_wl_input_surface) && (_ecore_wl_input_surface != surface)) + EGLint major, minor, n; + static const EGLint context_attribs[] = { - if (!_ecore_wl_input_button) - _ecore_wl_mouse_out_send(_ecore_wl_input_surface, t); - } - - if (surface) + EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE + }; + static const EGLint argb_attribs[] = { - if (_ecore_wl_input_button) - { - _ecore_wl_mouse_up_send(surface, _ecore_wl_input_button, t); - _ecore_wl_input_button = 0; - } - else - _ecore_wl_mouse_in_send(surface, t); - } -} - -static void -_ecore_wl_cb_handle_keyboard_focus(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, struct wl_surface *surface, struct wl_array *keys) -{ - unsigned int *keyend = 0, *i = 0; + EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 1, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, EGL_NONE + }; LOGFN(__FILE__, __LINE__, __FUNCTION__); - if (dev != _ecore_wl_input_dev) return; - - /* NB: Remove old keyboard focus */ - if ((_ecore_wl_input_surface) && (_ecore_wl_input_surface != surface)) - _ecore_wl_focus_out_send(_ecore_wl_input_surface, t); - - _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]; - - if (surface) + ewd->egl.display = eglGetDisplay(ewd->wl.display); + if (!eglInitialize(ewd->egl.display, &major, &minor)) { - /* set new input surface */ - _ecore_wl_input_surface = surface; - - /* send mouse in to new surface */ - /* _ecore_wl_mouse_in_send(surface, t); */ - - /* send focus to new surface */ - _ecore_wl_focus_in_send(surface, t); + ERR("Failed to initialize EGL display"); + return EINA_FALSE; } -} - -static void -_ecore_wl_cb_handle_touch_down(void *data __UNUSED__, struct wl_input_device *dev __UNUSED__, uint32_t timestamp, struct wl_surface *surface, int32_t id, int32_t x, int32_t y) -{ - Ecore_Event_Mouse_Button *ev; - - LOGFN(__FILE__, __LINE__, __FUNCTION__); - - _ecore_wl_touch_surface = surface; - _ecore_wl_touch_x = x; - _ecore_wl_touch_y = y; - - if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Button)))) return; - - ev->timestamp = timestamp; - - /* NB: Need to verify using x,y for these */ - ev->x = x; - ev->y = y; - ev->root.x = x; - ev->root.y = y; - ev->modifiers = 0; - ev->buttons = 0; - ev->same_screen = 1; - - /* FIXME: Need to get these from Wayland somehow */ - ev->double_click = 0; - ev->triple_click = 0; - - ev->multi.device = id; - ev->multi.radius = 1; - ev->multi.radius_x = 1; - ev->multi.radius_y = 1; - ev->multi.pressure = 1.0; - ev->multi.angle = 0.0; - /* NB: Need to verify using x,y for these */ - ev->multi.x = x; - ev->multi.y = y; - ev->multi.root.x = x; - ev->multi.root.y = y; + if (!eglBindAPI(EGL_OPENGL_ES_API)) { - unsigned int id = 0; - - if ((id = (unsigned int)wl_surface_get_user_data(surface))) - { - ev->window = id; - ev->event_window = id; - } + ERR("Failed to bind EGL Api"); + return EINA_FALSE; } - ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL); -} - -static void -_ecore_wl_cb_handle_touch_up(void *data __UNUSED__, struct wl_input_device *dev __UNUSED__, uint32_t timestamp, int32_t id) -{ - Ecore_Event_Mouse_Button *ev; - - LOGFN(__FILE__, __LINE__, __FUNCTION__); - - if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Button)))) return; - - ev->timestamp = timestamp; - - /* TODO: Need to verify using x,y for these */ - ev->x = _ecore_wl_touch_x; - ev->y = _ecore_wl_touch_y; - ev->root.x = _ecore_wl_touch_x; - ev->root.y = _ecore_wl_touch_y; - ev->modifiers = 0; - ev->buttons = 0; - ev->same_screen = 1; - - /* FIXME: Need to get these from Wayland somehow */ - ev->double_click = 0; - ev->triple_click = 0; - - ev->multi.device = id; - ev->multi.radius = 1; - ev->multi.radius_x = 1; - ev->multi.radius_y = 1; - ev->multi.pressure = 1.0; - ev->multi.angle = 0.0; - - /* TODO: Need to verify using x,y for these */ - ev->multi.x = _ecore_wl_touch_x; - ev->multi.y = _ecore_wl_touch_y; - ev->multi.root.x = _ecore_wl_touch_x; - ev->multi.root.y = _ecore_wl_touch_y; - + if ((!eglChooseConfig(ewd->egl.display, argb_attribs, &ewd->egl.argb_config, + 1, &n)) || (n == 0)) { - unsigned int id = 0; - - if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_touch_surface))) - { - ev->window = id; - ev->event_window = id; - } + ERR("Failed to choose ARGB config"); + return EINA_FALSE; } - _ecore_wl_touch_surface = NULL; - - ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL); -} - -static void -_ecore_wl_cb_handle_touch_motion(void *data __UNUSED__, struct wl_input_device *dev __UNUSED__, uint32_t timestamp, int32_t id, int32_t x, int32_t y) -{ - Ecore_Event_Mouse_Move *ev; - - LOGFN(__FILE__, __LINE__, __FUNCTION__); - - if (!_ecore_wl_touch_surface) return; - - if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Move)))) return; - - ev->timestamp = timestamp; - /* TODO: Need to verify using x,y for these */ - ev->x = x; - ev->y = y; - ev->root.x = x; - ev->root.y = y; - ev->modifiers = 0; //_ecore_wl_input_modifiers; - ev->same_screen = 1; - - ev->multi.device = id; - ev->multi.radius = 1; - ev->multi.radius_x = 1; - ev->multi.radius_y = 1; - ev->multi.pressure = 1.0; - ev->multi.angle = 0.0; - - /* TODO: Need to verify using x,y for these */ - ev->multi.x = x; - ev->multi.y = y; - ev->multi.root.x = x; - ev->multi.root.y = y; - + ewd->egl.argb_context = + eglCreateContext(ewd->egl.display, ewd->egl.argb_config, + EGL_NO_CONTEXT, context_attribs); + if (!ewd->egl.argb_context) { - unsigned int id = 0; - - if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_touch_surface))) - { - ev->window = id; - ev->event_window = id; - } + ERR("Failed to create ARGB context"); + return EINA_FALSE; } - ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL); -} - -static void -_ecore_wl_cb_handle_touch_frame(void *data __UNUSED__, struct wl_input_device *dev __UNUSED__) -{ - LOGFN(__FILE__, __LINE__, __FUNCTION__); - - /* FIXME: Need to get a device and actually test what happens here */ -} - -static void -_ecore_wl_cb_handle_touch_cancel(void *data __UNUSED__, struct wl_input_device *dev __UNUSED__) -{ - LOGFN(__FILE__, __LINE__, __FUNCTION__); - - /* FIXME: Need to get a device and actually test what happens here */ - _ecore_wl_touch_surface = NULL; -} - -static void -_ecore_wl_cb_source_target(void *data, struct wl_data_source *source __UNUSED__, const char *mime_type __UNUSED__) -{ - Ecore_Wl_Drag_Source *s; - - LOGFN(__FILE__, __LINE__, __FUNCTION__); - - printf("Ecore_Wl Source Target\n"); - if (!(s = data)) return; - printf("\tHave Drag Source\n"); - - /* FIXME: buffer here should really be the mouse cursor buffer */ - /* wl_data_device_attach(s->data_dev, s->timestamp, s->buffer, */ - /* s->hotspot_x, s->hotspot_y); */ -} - -static void -_ecore_wl_cb_source_send(void *data, struct wl_data_source *source, const char *mime_type, int32_t fd) -{ - Ecore_Wl_Drag_Source *s; - - LOGFN(__FILE__, __LINE__, __FUNCTION__); - - printf("Ecore_Wl Source Send\n"); - if (!(s = data)) return; - printf("\tHave Drag Source\n"); - - /* FIXME: write message to fd */ - - /* NB: Wayland really sucks in this regard. Why should selection stuff - * require an 'fd' ?? */ -} - -static void -_ecore_wl_cb_source_cancelled(void *data, struct wl_data_source *source __UNUSED__) -{ - Ecore_Wl_Drag_Source *s; - - LOGFN(__FILE__, __LINE__, __FUNCTION__); - - /* The cancelled event usually means source is no longer in use by - * the drag (or selection). */ - - printf("Ecore_Wl Source Cancel\n"); - if (!(s = data)) return; - printf("\tHave Drag Source\n"); - - /* FIXME: raise this to ecore_evas so the surface/buffer - * of the drag can be destroyed */ - - if (s->data_source) wl_data_source_destroy(s->data_source); - s->data_source = NULL; - - free(s); -} - -static void -_ecore_wl_cb_source_offer(void *data, struct wl_data_offer *offer __UNUSED__, const char *type) -{ - Ecore_Wl_Dnd_Source *s; - - if (!(s = data)) return; - eina_array_push(s->types, strdup(type)); -} - -static void -_ecore_wl_cb_data_offer(void *data, struct wl_data_device *data_dev, uint32_t id) -{ - Ecore_Wl_Dnd_Source *source; - - /* create a new 'data offer' structure and setup a listener for it */ - if (!(source = calloc(1, sizeof(Ecore_Wl_Dnd_Source)))) return; - - source->types = eina_array_new(1); - source->data = data; - source->refs = 1; - - /* FIXME: This will need to change when Wayland has typesafe wrappers for this */ - source->offer = (struct wl_data_offer *) - wl_proxy_create_for_id((struct wl_proxy *)data_dev, - id, &wl_data_offer_interface); - - wl_data_device_set_user_data(data_dev, source); - wl_data_offer_add_listener(source->offer, &_ecore_wl_offer_listener, source); -} - -static void -_ecore_wl_cb_data_enter(void *data __UNUSED__, struct wl_data_device *data_dev, uint32_t timestamp, struct wl_surface *surface, int32_t x, int32_t y, struct wl_data_offer *offer) -{ - Ecore_Wl_Dnd_Source *source; - - if (!(source = wl_data_device_get_user_data(data_dev))) return; - - /* TODO: maybe set pointer focus here ?? */ - - source->timestamp = timestamp; -} - -static void -_ecore_wl_cb_data_leave(void *data __UNUSED__, struct wl_data_device *data_dev) -{ - Ecore_Wl_Dnd_Source *source; - - if (!(source = wl_data_device_get_user_data(data_dev))) return; - - /* destroy drag offer */ - wl_data_offer_destroy(source->offer); - - while (eina_array_count(source->types)) - free(eina_array_pop(source->types)); - - eina_array_free(source->types); - free(source); - - wl_data_device_set_user_data(data_dev, NULL); -} - -static void -_ecore_wl_cb_data_motion(void *data __UNUSED__, struct wl_data_device *data_dev, uint32_t timestamp, int32_t x, int32_t y) -{ - Ecore_Wl_Dnd_Source *source; - - if (!(source = wl_data_device_get_user_data(data_dev))) return; - /* TODO: Here we should raise motion events for dragging */ -} - -static void -_ecore_wl_cb_data_drop(void *data __UNUSED__, struct wl_data_device *data_dev) -{ - Ecore_Wl_Dnd_Source *source; - - if (!(source = wl_data_device_get_user_data(data_dev))) return; - - /* TODO: Raise event for drop */ - - wl_data_offer_accept(source->offer, source->timestamp, NULL); -// eina_array_data_get(source->types, 0)); -} - -static void -_ecore_wl_cb_data_selection(void *data, struct wl_data_device *data_dev, struct wl_data_offer *offer) -{ - Ecore_Wl_Dnd_Source *source; - - printf("Ecore_Wl Data Selection\n"); - if ((source = wl_data_device_get_user_data(data_dev))) - { - /* destroy old source */ - wl_data_offer_destroy(source->offer); - - while (eina_array_count(source->types)) - free(eina_array_pop(source->types)); - - eina_array_free(source->types); - free(source); - - wl_data_device_set_user_data(data_dev, NULL); - } -} - -static void -_ecore_wl_cb_mouse_move_free(void *data __UNUSED__, void *event) -{ - Ecore_Event_Mouse_Move *ev; - - if ((ev = event)) free(ev); -} - -static void -_ecore_wl_mouse_move_send(uint32_t timestamp) -{ - Ecore_Event_Mouse_Move *ev; - Ecore_Event *event; - -// if (!_ecore_wl_input_surface) return; - - if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Move)))) return; - - ev->timestamp = timestamp; - - 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->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 = _ecore_wl_surface_x; - ev->multi.y = _ecore_wl_surface_y; - /* ev->multi.root.x = _ecore_wl_screen_x; */ - /* ev->multi.root.y = _ecore_wl_screen_y; */ - + if (!eglMakeCurrent(ewd->egl.display, EGL_NO_SURFACE, + EGL_NO_SURFACE, ewd->egl.argb_context)) { - unsigned int id = 0; - - if (_ecore_wl_input_surface) - { - LOGFN(__FILE__, __LINE__, __FUNCTION__); - - if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface))) - { - ev->window = id; - ev->event_window = id; - } - } + ERR("Failed to make ARGB context current"); + return EINA_FALSE; } - event = ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, - _ecore_wl_cb_mouse_move_free, NULL); + return EINA_TRUE; } -static void -_ecore_wl_mouse_out_send(struct wl_surface *surface, uint32_t timestamp) +static Eina_Bool +_ecore_wl_egl_shutdown(Ecore_Wl_Display *ewd) { - 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 = timestamp; - - if (surface) - { - unsigned int id = 0; - - if ((id = (unsigned int)wl_surface_get_user_data(surface))) - ev->window = id; - } + LOGFN(__FILE__, __LINE__, __FUNCTION__); - ecore_event_add(ECORE_WL_EVENT_MOUSE_OUT, ev, NULL, NULL); -} + eglMakeCurrent(ewd->egl.display, + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); -static void -_ecore_wl_mouse_in_send(struct wl_surface *surface, uint32_t timestamp) -{ - Ecore_Wl_Event_Mouse_In *ev; + eglDestroyContext(ewd->egl.display, ewd->egl.argb_context); - if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Mouse_In)))) return; + /* NB: This is hanging when we run elm apps as wayland clients + * inside the weston compositor */ - 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 = timestamp; + /* printf("Egl Terminate\n"); */ + /* eglTerminate(ewd->egl.display); */ + /* printf("Egl Terminate Done\n"); */ - if (surface) - { - unsigned int id = 0; + eglReleaseThread(); - if ((id = (unsigned int)wl_surface_get_user_data(surface))) - ev->window = id; - } - - ecore_event_add(ECORE_WL_EVENT_MOUSE_IN, ev, NULL, NULL); + return EINA_TRUE; } -static void -_ecore_wl_mouse_up_send(struct wl_surface *surface, uint32_t button, uint32_t timestamp) +static Eina_Bool +_ecore_wl_xkb_init(Ecore_Wl_Display *ewd) { - Ecore_Event_Mouse_Button *ev; + struct xkb_rule_names names; LOGFN(__FILE__, __LINE__, __FUNCTION__); - if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Button)))) return; - - if (button == BTN_LEFT) - ev->buttons = 1; - else if (button == BTN_MIDDLE) - ev->buttons = 2; - else if (button == BTN_RIGHT) - ev->buttons = 3; - - ev->timestamp = timestamp; - 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; - - /* 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 = _ecore_wl_surface_x; - ev->multi.y = _ecore_wl_surface_y; - /* ev->multi.root.x = _ecore_wl_screen_x; */ - /* ev->multi.root.y = _ecore_wl_screen_y; */ + names.rules = "evdev"; + names.model = "evdev"; + names.layout = "us"; + names.variant = ""; + names.options = ""; + if (!(ewd->xkb = xkb_compile_keymap_from_rules(&names))) { - unsigned int id = 0; - - if ((id = (unsigned int)wl_surface_get_user_data(surface))) - { - ev->window = id; - ev->event_window = id; - } + ERR("Failed to compile keymap"); + return EINA_FALSE; } - ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL); + return EINA_TRUE; } -static void -_ecore_wl_mouse_down_send(struct wl_surface *surface, uint32_t button, uint32_t timestamp) +static Eina_Bool +_ecore_wl_xkb_shutdown(Ecore_Wl_Display *ewd) { - Ecore_Event_Mouse_Button *ev; - LOGFN(__FILE__, __LINE__, __FUNCTION__); - if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Button)))) return; - - if (button == BTN_LEFT) - ev->buttons = 1; - else if (button == BTN_MIDDLE) - ev->buttons = 2; - else if (button == BTN_RIGHT) - ev->buttons = 3; - - _ecore_wl_input_timestamp = timestamp; - ev->timestamp = timestamp; - 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; - - /* 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 = _ecore_wl_surface_x; - ev->multi.y = _ecore_wl_surface_y; - /* ev->multi.root.x = _ecore_wl_screen_x; */ - /* ev->multi.root.y = _ecore_wl_screen_y; */ - - { - unsigned int id = 0; - - if ((id = (unsigned int)wl_surface_get_user_data(surface))) - { - ev->window = id; - ev->event_window = id; - } - } - - ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL); -} - -static void -_ecore_wl_focus_out_send(struct wl_surface *surface, uint32_t timestamp) -{ - Ecore_Wl_Event_Focus_Out *ev; - - if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Focus_Out)))) return; - ev->time = timestamp; - if (surface) - { - unsigned int id = 0; - - if ((id = (unsigned int)wl_surface_get_user_data(surface))) - ev->window = id; - } - ecore_event_add(ECORE_WL_EVENT_FOCUS_OUT, ev, NULL, NULL); -} - -static void -_ecore_wl_focus_in_send(struct wl_surface *surface, uint32_t timestamp) -{ - Ecore_Wl_Event_Focus_In *ev; - - if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Focus_In)))) return; - ev->time = timestamp; - if (surface) - { - unsigned int id = 0; - - if ((id = (unsigned int)wl_surface_get_user_data(surface))) - ev->window = id; - } - ecore_event_add(ECORE_WL_EVENT_FOCUS_IN, ev, NULL, NULL); + if (ewd->xkb) xkb_free_keymap(ewd->xkb); + return EINA_TRUE; } diff --git a/src/lib/ecore_wayland/ecore_wl_dnd.c b/src/lib/ecore_wayland/ecore_wl_dnd.c new file mode 100644 index 0000000..5d81225 --- /dev/null +++ b/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/src/lib/ecore_wayland/ecore_wl_input.c b/src/lib/ecore_wayland/ecore_wl_input.c new file mode 100644 index 0000000..d99c708 --- /dev/null +++ b/src/lib/ecore_wayland/ecore_wl_input.c @@ -0,0 +1,622 @@ +#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_focus(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_keyboard_focus(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_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_focus, + _ecore_wl_input_cb_keyboard_focus, + _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 +}; + +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); +} + +/* 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; + + 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_focus(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)) + _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_keyboard_focus(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; + + win = input->keyboard_focus; + if ((win) && (win->surface != surface)) + _ecore_wl_input_keyboard_focus_remove(input, timestamp); + + 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_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; + } + + /* NB: Hmmmm, smells like this could be a leak. No free function */ + 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; + } + + /* NB: Hmmmm, smells like this could be a leak. No free function */ + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL); +} diff --git a/src/lib/ecore_wayland/ecore_wl_output.c b/src/lib/ecore_wayland/ecore_wl_output.c new file mode 100644 index 0000000..9f540d4 --- /dev/null +++ b/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/src/lib/ecore_wayland/ecore_wl_private.h b/src/lib/ecore_wayland/ecore_wl_private.h index eec5ffe..63d99f6 100644 --- a/src/lib/ecore_wayland/ecore_wl_private.h +++ b/src/lib/ecore_wayland/ecore_wl_private.h @@ -2,8 +2,11 @@ # define _ECORE_WAYLAND_PRIVATE_H # include +# include -//# define LOGFNS 1 +# include "Ecore_Wayland.h" + +# define LOGFNS 1 # ifdef LOGFNS # include @@ -13,6 +16,7 @@ # endif extern int _ecore_wl_log_dom; +extern Ecore_Wl_Display *_ecore_wl_disp; # ifdef ECORE_WL_DEFAULT_LOG_COLOR # undef ECORE_WL_DEFAULT_LOG_COLOR @@ -44,42 +48,39 @@ extern int _ecore_wl_log_dom; # endif # define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_wl_log_dom, __VA_ARGS__) -typedef struct _Ecore_Wl_Dnd_Source +struct _Ecore_Wl_Dnd_Source { struct wl_data_offer *offer; - int refs; - - Eina_Array *types; + Ecore_Wl_Input *input; + struct wl_array types; + int refcount; + int fd; + int x, y; - uint32_t timestamp; + /* TODO: task & data_func */ void *data; -} Ecore_Wl_Dnd_Source; +}; -typedef struct _Ecore_Wl_Dnd_Target +struct _Ecore_Wl_Dnd_Target { - /* NB: These are not the real fields for this structure, - * and it is Bound to change....soon */ - struct wl_data_offer *offer; - int refs; - - Eina_Array *types; + Ecore_Wl_Dnd_Source *source; +}; - uint32_t timestamp; - void *data; -} Ecore_Wl_Dnd_Target; +void _ecore_wl_window_init(void); +void _ecore_wl_window_shutdown(void); -struct _Ecore_Wl_Drag_Source -{ - struct wl_data_device *data_dev; - struct wl_buffer *buffer; +void _ecore_wl_output_add(Ecore_Wl_Display *ewd, unsigned int id); +void _ecore_wl_output_del(Ecore_Wl_Output *output); - int32_t hotspot_x, hotspot_y; - int32_t offset_x, offset_y; - const char *mimetype; - uint32_t timestamp; - void *data; +void _ecore_wl_input_add(Ecore_Wl_Display *ewd, unsigned int id); +void _ecore_wl_input_del(Ecore_Wl_Input *input); - struct wl_data_source *data_source; -}; +void _ecore_wl_dnd_add(Ecore_Wl_Input *input, struct wl_data_device *data_device, unsigned int id); +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); +void _ecore_wl_dnd_leave(void *data, struct wl_data_device *data_device __UNUSED__); +void _ecore_wl_dnd_motion(void *data, struct wl_data_device *data_device __UNUSED__, unsigned int timestamp __UNUSED__, int x, int y); +void _ecore_wl_dnd_drop(void *data, struct wl_data_device *data_device __UNUSED__); +void _ecore_wl_dnd_selection(void *data, struct wl_data_device *data_device __UNUSED__, struct wl_data_offer *offer); +void _ecore_wl_dnd_del(Ecore_Wl_Dnd_Source *source); #endif diff --git a/src/lib/ecore_wayland/ecore_wl_window.c b/src/lib/ecore_wayland/ecore_wl_window.c new file mode 100644 index 0000000..4fd9ba3 --- /dev/null +++ b/src/lib/ecore_wayland/ecore_wl_window.c @@ -0,0 +1,356 @@ +#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; +} + +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; +} + +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); +} + +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); + } +} + +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); +} + +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; + } +} + +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; +} + +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); +}