diff options
Diffstat (limited to 'src/modules/ecore_evas')
19 files changed, 2094 insertions, 368 deletions
diff --git a/src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c b/src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c index e1c5a66670..7018a66691 100644 --- a/src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c +++ b/src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c @@ -34,6 +34,11 @@ static Ecore_Event_Handler *ecore_evas_event_handlers[4]; static const char *_iface_name = "opengl_cocoa"; static const int _iface_version = 1; +typedef struct { + Ecore_Evas_Selection_Callbacks clipboard; + Eina_Future *delivery; +} Ecore_Evas_Cocoa_Engine_Data; + static inline Ecore_Evas * _ecore_evas_cocoa_match(Ecore_Cocoa_Object *cocoa_win) { @@ -422,6 +427,130 @@ _ecore_evas_callback_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func ee->func.fn_delete_request = func; } +static Eina_Value +_delivery(void *data, const Eina_Value value EINA_UNUSED, const Eina_Future *dead_future EINA_UNUSED) +{ + Ecore_Evas *ee = data; + Ecore_Evas_Cocoa_Engine_Data *edata = ee->engine.data; + Eina_Rw_Slice slice; + const char *mime_type = NULL; + + EINA_SAFETY_ON_NULL_GOTO(edata->delivery, end); + + for (unsigned int i = 0; i < eina_array_count(edata->clipboard.available_types); ++i) + { + mime_type = eina_array_data_get(edata->clipboard.available_types, i); + if (!strncmp("text/", mime_type, strlen("text/"))) + break; + } + if (mime_type) + { + edata->clipboard.delivery(ee, 1, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER, mime_type, &slice); + EINA_SAFETY_ON_FALSE_GOTO(ecore_cocoa_clipboard_set(slice.mem, slice.len, mime_type), end); + } + else + { + ERR("No compatible mime type found"); + } + +end: + return EINA_VALUE_EMPTY; +} + +static Eina_Bool +_ecore_evas_cocoa_selection_claim(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Ecore_Evas_Selection_Internal_Delivery delivery, Ecore_Evas_Selection_Internal_Cancel cancel) +{ + if (selection != ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER) + return EINA_FALSE; + + if (!delivery && !cancel) + { + ecore_cocoa_clipboard_clear(); + return EINA_TRUE; + } + else + { + Ecore_Evas_Cocoa_Engine_Data *edata = ee->engine.data; + + if (edata->clipboard.cancel) + { + edata->clipboard.cancel(ee, seat, selection); + eina_array_free(edata->clipboard.available_types); + } + + edata->delivery = efl_loop_job(efl_main_loop_get()); + eina_future_then(edata->delivery, _delivery, ee); + edata->clipboard.delivery = delivery; + edata->clipboard.cancel = cancel; + edata->clipboard.available_types = available_types; + return EINA_TRUE; + } +} + +Eina_Future* +_ecore_evas_cocoa_selection_request(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type) +{ + Eina_Future *future; + Eina_Promise *promise; + const char *mime_type; + + if (selection != ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER) + return eina_future_rejected(efl_loop_future_scheduler_get(efl_main_loop_get()), ecore_evas_no_selection); + + promise = efl_loop_promise_new(efl_main_loop_get()); + future = eina_future_new(promise); + + for (unsigned int i = 0; i < eina_array_count(acceptable_type); ++i) + { + mime_type = eina_array_data_get(acceptable_type, i); + if (!strncmp("text/", mime_type, strlen("text/"))) + break; + } + if (!mime_type) + { + eina_promise_reject(promise, ecore_evas_no_matching_type); + } + else + { + int size; + void *data; + Eina_Content *content = NULL; + Eina_Rw_Slice slice; + + data = ecore_cocoa_clipboard_get(&size, mime_type); + + if (eina_str_has_prefix(mime_type,"text")) + { + //ensure that we always have a \0 at the end, there is no assertion that \0 is included here. + slice.len = size + 1; + slice.mem = eina_memdup(data, size, EINA_TRUE); + free(data); + } + else + { + slice.len = size; + slice.mem = data; + } + if (slice.mem) + content = eina_content_new(eina_rw_slice_slice_get(slice), mime_type); + free(slice.mem); //memory got duplicated in eina_content_new + if (!content) // construction can fail because of some validation reasons + eina_promise_reject(promise, ecore_evas_no_matching_type); + else + eina_promise_resolve(promise, eina_value_content_init(content)); + + } + return future; +} + +static Eina_Bool +_ecore_evas_cocoa_selection_has_owner(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection EINA_UNUSED) +{ + if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER) + return ecore_cocoa_clipboard_exists(); + return EINA_FALSE; +} + static Ecore_Evas_Engine_Func _ecore_cocoa_engine_func = { _ecore_evas_cocoa_free, @@ -508,6 +637,11 @@ static Ecore_Evas_Engine_Func _ecore_cocoa_engine_func = NULL, //fn_pointer_device_xy_get NULL, //fn_prepare NULL, //fn_last_tick_get + _ecore_evas_cocoa_selection_claim, //fn_selection_claim + _ecore_evas_cocoa_selection_has_owner, //fn_selection_has_owner + _ecore_evas_cocoa_selection_request, //fn_selection_request + NULL, //fn_dnd_start + NULL, //fn_dnd_stop }; static Ecore_Cocoa_Window * @@ -517,11 +651,11 @@ _ecore_evas_cocoa_window_get(const Ecore_Evas *ee) return (Ecore_Cocoa_Window *)(ee->prop.window); } - EAPI Ecore_Evas * ecore_evas_cocoa_new_internal(Ecore_Cocoa_Window *parent EINA_UNUSED, int x, int y, int w, int h) { Ecore_Evas *ee; + Ecore_Evas_Cocoa_Engine_Data *edata; Ecore_Evas_Interface_Cocoa *iface; if (!ecore_cocoa_init()) @@ -532,6 +666,10 @@ ecore_evas_cocoa_new_internal(Ecore_Cocoa_Window *parent EINA_UNUSED, int x, int ee = calloc(1, sizeof(Ecore_Evas)); if (!ee) goto shutdown_ecore_cocoa; + edata = calloc(1, sizeof(Ecore_Evas_Cocoa_Engine_Data)); + if (!edata) + goto shutdown_ecore_cocoa_engine_data; + ee->engine.data = edata; ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); @@ -606,6 +744,8 @@ ecore_evas_cocoa_new_internal(Ecore_Cocoa_Window *parent EINA_UNUSED, int x, int free(ee->name); //free_ee: _ecore_evas_cocoa_shutdown(); + free(edata); + shutdown_ecore_cocoa_engine_data: free(ee); shutdown_ecore_cocoa: ecore_cocoa_shutdown(); diff --git a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c index 35eadc002b..c8f0eb8c24 100644 --- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c +++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c @@ -142,9 +142,8 @@ _drm_device_change(void *d EINA_UNUSED, int t EINA_UNUSED, void *event) static int _ecore_evas_drm_init(Ecore_Evas *ee, Ecore_Evas_Engine_Drm_Data *edata, const char *device) { - // XXX: this is broken. we init once but in a per ecore evas struct so - // we assume there will be only 1 of these drm ecore evas's ever... - if (++_drm_init_count != 1) return _drm_init_count; + _drm_init_count++; + if (_drm_init_count > 1) return _drm_init_count; if (!ecore_drm2_init()) { @@ -201,24 +200,31 @@ static int _ecore_evas_drm_shutdown(Ecore_Evas_Engine_Drm_Data *edata) { Ecore_Event_Handler *h; - if (--_drm_init_count != 0) return _drm_init_count; - if (edata->focus_job) + _drm_init_count--; + if (_drm_init_count == 0) { - ecore_job_del(edata->focus_job); - edata->focus_job = NULL; - } - if (edata->dev) - { - ecore_drm2_outputs_destroy(edata->dev); - ecore_drm2_device_close(edata->dev); - edata->dev = NULL; + if (edata->focus_job) + { + ecore_job_del(edata->focus_job); + edata->focus_job = NULL; + } + + if (edata->dev) + { + ecore_drm2_outputs_destroy(edata->dev); + ecore_drm2_device_close(edata->dev); + edata->dev = NULL; + } + + ecore_drm2_shutdown(); + ecore_event_evas_shutdown(); + + EINA_LIST_FREE(handlers, h) + ecore_event_handler_del(h); } - ecore_drm2_shutdown(); - ecore_event_evas_shutdown(); - EINA_LIST_FREE(handlers, h) - ecore_event_handler_del(h); + if (_drm_init_count < 0) _drm_init_count = 0; return _drm_init_count; } @@ -398,8 +404,6 @@ _drm_show(Ecore_Evas *ee) if (ee->func.fn_state_change) ee->func.fn_state_change(ee); } - if (ee->visible) return; - ee->visible = 1; if (ee->func.fn_show) ee->func.fn_show(ee); @@ -717,6 +721,7 @@ _cb_pageflip(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int se ecore_drm2_output_info_get(output, &x, &y, &w, &h, NULL); if (!edata->once) t = ecore_time_get(); +// printf("ECORE_EVAS: drm tick %1.5f @ %1.5f\n", t, ecore_time_get()); ecore_evas_animator_tick(ee, &(Eina_Rectangle){x, y, w, h}, t - edata->offset); } diff --git a/src/modules/ecore_evas/engines/drm/meson.build b/src/modules/ecore_evas/engines/drm/meson.build index 584cc56159..58071010d0 100644 --- a/src/modules/ecore_evas/engines/drm/meson.build +++ b/src/modules/ecore_evas/engines/drm/meson.build @@ -1,7 +1,3 @@ -if get_option('opengl') != 'none' - config_h.set('BUILD_ECORE_EVAS_GL_DRM', '1') -endif - engine_src = files(['ecore_evas_drm.c']) engine_deps = [ecore_drm2, ecore_input, eeze, elput, libdrm, engine_drm] diff --git a/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c b/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c index 28f743ae71..37963fe664 100644 --- a/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c +++ b/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c @@ -753,7 +753,7 @@ _ecore_evas_extn_cb_focus_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj E Extn *extn; Evas_Device *dev; - dev = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_SEAT); + dev = evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_SEAT); if (ecore_evas_focus_device_get(ee, dev)) return; ee->prop.focused_by = eina_list_append(ee->prop.focused_by, dev); extn = bdata->data; @@ -770,7 +770,7 @@ _ecore_evas_extn_cb_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj Extn *extn; ee->prop.focused_by = eina_list_remove(ee->prop.focused_by, - evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_SEAT)); + evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_SEAT)); extn = bdata->data; if (!extn) return; if (!extn->ipc.server) return; @@ -1030,7 +1030,7 @@ _ipc_server_data(void *data, int type EINA_UNUSED, void *event) Ipc_Data_Update *ipc; int n = e->response; - /* b->lockfd is not enough to ensure the size is same + /* b->lockfd is not enough to ensure the size is same * between what server knows, and client knows. * So should check file lock also. */ if ((n >= 0) && (n < NBUF)) diff --git a/src/modules/ecore_evas/engines/extn/ecore_evas_extn_buf.c b/src/modules/ecore_evas/engines/extn/ecore_evas_extn_buf.c index 986dde06ff..055e744c6f 100644 --- a/src/modules/ecore_evas/engines/extn/ecore_evas_extn_buf.c +++ b/src/modules/ecore_evas/engines/extn/ecore_evas_extn_buf.c @@ -86,7 +86,7 @@ _extnbuf_free(Extnbuf *b) if (b->file) shm_unlink(b->file); if (b->lock) unlink(b->lock); } - + if (b->addr != MAP_FAILED) munmap(b->addr, b->size); if (b->fd >= 0) close(b->fd); if (b->lockfd >= 0) close(b->lockfd); diff --git a/src/modules/ecore_evas/engines/extn/meson.build b/src/modules/ecore_evas/engines/extn/meson.build index 901a126f52..4a912b4fbd 100644 --- a/src/modules/ecore_evas/engines/extn/meson.build +++ b/src/modules/ecore_evas/engines/extn/meson.build @@ -2,6 +2,7 @@ engine_src = files(['ecore_evas_extn.c', 'ecore_evas_extn_buf.c', 'ecore_evas_ex engine_deps = [ecore_input, ecore_ipc] shared_module(mod_full_name, engine_src, + c_args : package_c_args, include_directories : config_dir + [engine_include_dir], dependencies : [eina, ecore_evas, ecore_input_evas, rt] + engine_deps, install : true, diff --git a/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c b/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c index 17bf83f7c1..ce671e2e3e 100644 --- a/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c +++ b/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c @@ -61,7 +61,7 @@ _ecore_evas_mouse_move_process_fb(Ecore_Evas *ee, int x, int y) ecore_fb_size_get(&fbw, &fbh); - pointer = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_MOUSE); + pointer = evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_MOUSE); pointer = evas_device_parent_get(pointer); cursor = eina_hash_find(ee->prop.cursors, &pointer); EINA_SAFETY_ON_NULL_RETURN(cursor); @@ -330,7 +330,7 @@ _ecore_evas_rotation_set(Ecore_Evas *ee, int rotation, int resize EINA_UNUSED) Evas_Engine_Info_FB *einfo; int rot_dif; - pointer = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_MOUSE); + pointer = evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_MOUSE); pointer = evas_device_parent_get(pointer); cursor = eina_hash_find(ee->prop.cursors, &pointer); EINA_SAFETY_ON_NULL_RETURN(cursor); diff --git a/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c b/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c index 8abc7401b6..ef4ba057b9 100644 --- a/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c +++ b/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c @@ -455,6 +455,9 @@ static Ecore_Evas_Engine_Func _ecore_sdl_engine_func = NULL, //fn_pointer_device_xy_get NULL, //fn_prepare NULL, //fn_last_tick_get + NULL, //fn_selection_claim + NULL, //fn_selection_has_owner + NULL, //fn_selection_request }; static Ecore_Evas* diff --git a/src/modules/ecore_evas/engines/sdl/meson.build b/src/modules/ecore_evas/engines/sdl/meson.build index 94b990df92..030ca6561a 100644 --- a/src/modules/ecore_evas/engines/sdl/meson.build +++ b/src/modules/ecore_evas/engines/sdl/meson.build @@ -2,6 +2,7 @@ engine_src = files(['ecore_evas_sdl.c']) engine_deps = [ecore_sdl, ecore_input, ecore, dependency('sdl2')] shared_module(mod_full_name, engine_src, + c_args : package_c_args, include_directories : config_dir + [engine_include_dir], dependencies : [eina, ecore_evas, ecore_input_evas] + engine_deps, install : true, diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c index ad922474cd..1cec016ebc 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c @@ -4,9 +4,10 @@ #include "ecore_evas_wayland_private.h" #include <Evas_Engine_Wayland.h> +#include "ecore_wl2_internal.h" -extern EAPI Eina_List *_evas_canvas_image_data_unset(Evas *eo_e); -extern EAPI void _evas_canvas_image_data_regenerate(Eina_List *list); +EAPI extern Eina_List *_evas_canvas_image_data_unset(Evas *eo_e); +EAPI extern void _evas_canvas_image_data_regenerate(Eina_List *list); #define _smart_frame_type "ecore_evas_wl_frame" @@ -32,19 +33,27 @@ static Eina_Array *_ecore_evas_wl_event_hdls; static void _ecore_evas_wayland_resize(Ecore_Evas *ee, int location); static void _ecore_evas_wl_common_rotation_set(Ecore_Evas *ee, int rotation, int resize); +static void _ecore_evas_wl_selection_init(Ecore_Evas *ee); /* local functions */ static void -_anim_cb_tick(Ecore_Wl2_Window *win EINA_UNUSED, uint32_t timestamp EINA_UNUSED, void *data) +_anim_cb_tick(Ecore_Wl2_Window *win EINA_UNUSED, uint32_t timestamp, void *data) { Ecore_Evas *ee = data; Ecore_Evas_Engine_Wl_Data *edata; + double t;//, rt; + /* static double pt = 0.0, prt = 0.0; */ edata = ee->engine.data; if (!edata->ticking) return; - - ecore_evas_animator_tick(ee, NULL, ecore_loop_time_get()); + t = ((double)timestamp / 1000.0); + ecore_loop_time_set(t); + /* rt = ecore_time_get(); */ + /* printf("ECORE_EVAS: wl client anim tick %p | %p - %1.5f @ %1.5f delt=%1.5f | %1.5f\n", ee, edata, t, ecore_time_get(), t - pt, rt - prt); */ + ecore_evas_animator_tick(ee, NULL, t); + /* pt = t; */ + /* prt = rt; */ } static void @@ -57,8 +66,8 @@ _ecore_evas_wl_common_animator_register(Ecore_Evas *ee) EINA_SAFETY_ON_TRUE_RETURN(edata->ticking); EINA_SAFETY_ON_TRUE_RETURN(edata->frame != NULL); - edata->frame = ecore_wl2_window_frame_callback_add(edata->win, - _anim_cb_tick, ee); + edata->frame = + ecore_wl2_window_frame_callback_add(edata->win, _anim_cb_tick, ee); if (!ecore_wl2_window_pending_get(edata->win) && !ee->in_async_render && !ee->animator_ticked && !ee->animator_ran && !ee->draw_block) ecore_wl2_window_false_commit(edata->win); @@ -112,7 +121,7 @@ _ecore_evas_wl_common_cb_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Evas *ee; Ecore_Event_Mouse_IO *ev; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; ev = event; ee = ecore_event_window_match((Ecore_Window)ev->window); @@ -133,12 +142,13 @@ _ecore_evas_wl_common_cb_mouse_out(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Evas *ee; Ecore_Event_Mouse_IO *ev; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; ev = event; ee = ecore_event_window_match((Ecore_Window)ev->window); if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; - if ((Ecore_Window)ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON; + if ((Ecore_Window)ev->window != ee->prop.window) + return ECORE_CALLBACK_PASS_ON; if (!_ecore_evas_mouse_in_check(ee, ev->dev)) return ECORE_CALLBACK_PASS_ON; ecore_event_evas_seat_modifier_lock_update(ee->evas, @@ -155,12 +165,13 @@ _ecore_evas_wl_common_cb_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Evas *ee; Ecore_Wl2_Event_Focus_In *ev; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; ev = event; ee = ecore_event_window_match((Ecore_Window)ev->window); if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; - if ((Ecore_Window)ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON; + if ((Ecore_Window)ev->window != ee->prop.window) + return ECORE_CALLBACK_PASS_ON; _ecore_evas_focus_device_set(ee, ev->dev, EINA_TRUE); return ECORE_CALLBACK_PASS_ON; } @@ -171,12 +182,13 @@ _ecore_evas_wl_common_cb_focus_out(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Evas *ee; Ecore_Wl2_Event_Focus_Out *ev; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; ev = event; ee = ecore_event_window_match((Ecore_Window)ev->window); if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; - if ((Ecore_Window)ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON; + if ((Ecore_Window)ev->window != ee->prop.window) + return ECORE_CALLBACK_PASS_ON; _ecore_evas_focus_device_set(ee, ev->dev, EINA_FALSE); return ECORE_CALLBACK_PASS_ON; } @@ -282,9 +294,7 @@ _ecore_evas_wayland_window_update(Ecore_Evas *ee, Ecore_Evas_Engine_Wl_Data *wda */ else if (!ee->alpha) { - ecore_wl2_window_opaque_region_set(wdata->win, - 0, 0, - fullw, fullh); + ecore_wl2_window_opaque_region_set(wdata->win, 0, 0, fullw, fullh); } /* alpha is set and we might use it, so we'd better clear the * opaque region, let the compositor blend it all. @@ -302,9 +312,9 @@ _ecore_evas_wayland_window_update(Ecore_Evas *ee, Ecore_Evas_Engine_Wl_Data *wda if (!change) return; if (ECORE_EVAS_PORTRAIT(ee)) - evas_damage_rectangle_add(ee->evas, 0, 0, fullw, fullh); + evas_damage_rectangle_add(ee->evas, 0, 0, fullw, fullh); else - evas_damage_rectangle_add(ee->evas, 0, 0, fullh, fullw); + evas_damage_rectangle_add(ee->evas, 0, 0, fullh, fullw); ee->shadow.changed = EINA_FALSE; } @@ -313,10 +323,10 @@ static void _ecore_evas_wl_common_resize(Ecore_Evas *ee, int w, int h) { Ecore_Evas_Engine_Wl_Data *wdata; - int ow, oh, ew, eh; + int ow, oh, ew, eh, fw, fh, ww, hh; int diff = 0; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; @@ -326,6 +336,8 @@ _ecore_evas_wl_common_resize(Ecore_Evas *ee, int w, int h) ee->req.w = w; ee->req.h = h; + evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh); + /* TODO: wayland client can resize the ecore_evas directly. * In the future, we will remove ee->req value in wayland backend */ ew = ee->w; @@ -333,85 +345,81 @@ _ecore_evas_wl_common_resize(Ecore_Evas *ee, int w, int h) ee->w = w; ee->h = h; - if (wdata->win->xdg_set_min_size && wdata->win->xdg_toplevel && wdata->win->pending.min) + if (wdata->win->xdg_set_min_size && wdata->win->xdg_toplevel && + wdata->win->pending.min) { - wdata->win->xdg_set_min_size(wdata->win->xdg_toplevel, ee->prop.min.w, ee->prop.min.h); + ww = ee->prop.min.w + fw; + hh = ee->prop.min.h + fh; + if (ww < 1) ww = 1; + if (hh < 1) hh = 1; + wdata->win->xdg_set_min_size(wdata->win->xdg_toplevel, ww, hh); wdata->win->pending.min = 0; } - if (wdata->win->xdg_set_max_size && wdata->win->xdg_toplevel && wdata->win->pending.max) + if (wdata->win->xdg_set_max_size && wdata->win->xdg_toplevel && + wdata->win->pending.max) { - wdata->win->xdg_set_max_size(wdata->win->xdg_toplevel, ee->prop.max.w, ee->prop.max.h); + ww = ee->prop.max.w + fw; + hh = ee->prop.max.h + fh; + if (ww < 0) ww = 0; + if (hh < 0) hh = 0; + wdata->win->xdg_set_max_size(wdata->win->xdg_toplevel, ww, hh); wdata->win->pending.max = 0; } - if (wdata->win->zxdg_set_min_size && wdata->win->zxdg_toplevel && wdata->win->pending.min) + if (wdata->win->zxdg_set_min_size && wdata->win->zxdg_toplevel && + wdata->win->pending.min) { - wdata->win->zxdg_set_min_size(wdata->win->zxdg_toplevel, ee->prop.min.w, ee->prop.min.h); + ww = ee->prop.min.w + fw; + hh = ee->prop.min.h + fh; + if (ww < 1) ww = 1; + if (hh < 1) hh = 1; + wdata->win->zxdg_set_min_size(wdata->win->zxdg_toplevel, ww, hh); wdata->win->pending.min = 0; } - if (wdata->win->zxdg_set_max_size && wdata->win->zxdg_toplevel && wdata->win->pending.max) + if (wdata->win->zxdg_set_max_size && wdata->win->zxdg_toplevel && + wdata->win->pending.max) { - wdata->win->zxdg_set_max_size(wdata->win->zxdg_toplevel, ee->prop.max.w, ee->prop.max.h); + ww = ee->prop.max.w + fw; + hh = ee->prop.max.h + fh; + if (ww < 0) ww = 0; + if (hh < 0) hh = 0; + wdata->win->zxdg_set_max_size(wdata->win->zxdg_toplevel, ww, hh); wdata->win->pending.max = 0; } if (!ee->prop.fullscreen) { - int fw = 0, fh = 0; int maxw = 0, maxh = 0; int minw = 0, minh = 0; - evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh); - - if (ECORE_EVAS_PORTRAIT(ee)) - { - if (ee->prop.min.w > 0) - minw = (ee->prop.min.w - fw); - if (ee->prop.min.h > 0) - minh = (ee->prop.min.h - fh); - if (ee->prop.max.w > 0) - maxw = (ee->prop.max.w + fw); - if (ee->prop.max.h > 0) - maxh = (ee->prop.max.h + fh); - } - else - { - if (ee->prop.min.w > 0) - minw = (ee->prop.min.w - fh); - if (ee->prop.min.h > 0) - minh = (ee->prop.min.h - fw); - if (ee->prop.max.w > 0) - maxw = (ee->prop.max.w + fh); - if (ee->prop.max.h > 0) - maxh = (ee->prop.max.h + fw); - } + if (ee->prop.min.w > 0) minw = (ee->prop.min.w); + if (ee->prop.min.h > 0) minh = (ee->prop.min.h); + if (ee->prop.max.w > 0) maxw = (ee->prop.max.w); + if (ee->prop.max.h > 0) maxh = (ee->prop.max.h); - if ((maxw > 0) && (w > maxw)) - w = maxw; - else if (w < minw) - w = minw; + if ((maxw > 0) && (w > maxw)) w = maxw; + else if (w < minw) w = minw; - if ((maxh > 0) && (h > maxh)) - h = maxh; - else if (h < minh) - h = minh; + if ((maxh > 0) && (h > maxh)) h = maxh; + else if (h < minh) h = minh; if (!ee->prop.maximized) { /* calc new size using base size & step size */ if (ee->prop.step.w > 1) { - int bw = ee->prop.base.w ?: minw; + int bw = ee->prop.base.w; w = (bw + (((w - bw) / ee->prop.step.w) * ee->prop.step.w)); } if (ee->prop.step.h > 1) { - int bh = ee->prop.base.h ?: minh; + int bh = ee->prop.base.h; h = (bh + (((h - bh) / ee->prop.step.h) * ee->prop.step.h)); } - if (!wdata->win->display->wl.efl_hints && EINA_DBL_NONZERO(ee->prop.aspect)) + if (!wdata->win->display->wl.efl_hints && + EINA_DBL_NONZERO(ee->prop.aspect)) { /* copied from e_client.c */ Evas_Aspect_Control aspect; @@ -479,9 +487,9 @@ _ecore_evas_wl_common_resize(Ecore_Evas *ee, int w, int h) } if (ECORE_EVAS_PORTRAIT(ee)) - evas_output_size_get(ee->evas, &ow, &oh); + evas_output_size_get(ee->evas, &ow, &oh); else - evas_output_size_get(ee->evas, &oh, &ow); + evas_output_size_get(ee->evas, &oh, &ow); if (ECORE_EVAS_PORTRAIT(ee) && ((ow != w) || (oh != h))) diff = 1; @@ -589,7 +597,7 @@ _ecore_evas_wl_common_cb_window_configure(void *data EINA_UNUSED, int type EINA_ int framew, frameh; Eina_Bool active, prev_max, prev_full, state_change = EINA_FALSE; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; ev = event; ee = ecore_event_window_match((Ecore_Window)ev->win); @@ -605,9 +613,11 @@ _ecore_evas_wl_common_cb_window_configure(void *data EINA_UNUSED, int type EINA_ prev_max = ee->prop.maximized; prev_full = ee->prop.fullscreen; ee->prop.maximized = - (ev->states & ECORE_WL2_WINDOW_STATE_MAXIMIZED) == ECORE_WL2_WINDOW_STATE_MAXIMIZED; + (ev->states & ECORE_WL2_WINDOW_STATE_MAXIMIZED) == + ECORE_WL2_WINDOW_STATE_MAXIMIZED; ee->prop.fullscreen = - (ev->states & ECORE_WL2_WINDOW_STATE_FULLSCREEN) == ECORE_WL2_WINDOW_STATE_FULLSCREEN; + (ev->states & ECORE_WL2_WINDOW_STATE_FULLSCREEN) == + ECORE_WL2_WINDOW_STATE_FULLSCREEN; active = wdata->activated; wdata->activated = ecore_wl2_window_activated_get(wdata->win); @@ -718,7 +728,7 @@ _ecore_evas_wl_common_cb_window_configure_complete(void *data EINA_UNUSED, int t Evas_Engine_Info_Wayland *einfo; Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; ev = event; ee = ecore_event_window_match((Ecore_Window)ev->win); @@ -771,8 +781,10 @@ _ecore_evas_wl_common_cb_aux_hint_supported(void *data EINA_UNUSED, int type EI if (!ee) return ECORE_CALLBACK_PASS_ON; if ((Ecore_Window)ev->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON; wdata = ee->engine.data; - EINA_LIST_FREE(ee->prop.aux_hint.supported_list, hint) eina_stringshare_del(hint); - ee->prop.aux_hint.supported_list = ecore_wl2_window_aux_hints_supported_get(wdata->win); + EINA_LIST_FREE(ee->prop.aux_hint.supported_list, hint) + eina_stringshare_del(hint); + ee->prop.aux_hint.supported_list = + ecore_wl2_window_aux_hints_supported_get(wdata->win); return ECORE_CALLBACK_RENEW; } @@ -811,7 +823,7 @@ _ecore_evas_wl_common_cb_window_rotate(void *data EINA_UNUSED, int type EINA_UNU Ecore_Evas *ee; Ecore_Wl2_Event_Window_Rotation *ev; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; ev = event; ee = ecore_event_window_match((Ecore_Window)ev->win); @@ -882,14 +894,14 @@ _rotation_do(Ecore_Evas *ee, int rotation, int resize) { /* resize the canvas */ evas_output_size_set(ee->evas, ee->req.w, ee->req.h); - evas_output_viewport_set(ee->evas, 0, 0, + evas_output_viewport_set(ee->evas, 0, 0, ee->req.w, ee->req.h); } else { /* resize the canvas */ evas_output_size_set(ee->evas, ee->req.h, ee->req.w); - evas_output_viewport_set(ee->evas, 0, 0, + evas_output_viewport_set(ee->evas, 0, 0, ee->req.h, ee->req.w); } } @@ -975,43 +987,6 @@ _rotation_do(Ecore_Evas *ee, int rotation, int resize) } } -static Eina_Bool -_ecore_evas_wl_common_cb_www_drag(void *d EINA_UNUSED, int t EINA_UNUSED, void *event) -{ - Ecore_Wl2_Event_Window_WWW_Drag *ev = event; - Ecore_Evas_Engine_Wl_Data *wdata; - Ecore_Evas *ee; - - ee = ecore_event_window_match((Ecore_Window)ev->window); - if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; - if ((Ecore_Window)ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON; - - wdata = ee->engine.data; - wdata->dragging = !!ev->dragging; - if (!ev->dragging) - evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); - return ECORE_CALLBACK_RENEW; -} - -static Eina_Bool -_ecore_evas_wl_common_cb_www(void *d EINA_UNUSED, int t EINA_UNUSED, void *event) -{ - Ecore_Wl2_Event_Window_WWW *ev = event; - Ecore_Evas_Engine_Wl_Data *wdata; - Ecore_Evas *ee; - - ee = ecore_event_window_match((Ecore_Window)ev->window); - if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; - if ((Ecore_Window)ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON; - - wdata = ee->engine.data; - wdata->x_rel += ev->x_rel; - wdata->y_rel += ev->y_rel; - wdata->timestamp = ev->timestamp; - evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); - return ECORE_CALLBACK_RENEW; -} - static void _ecore_evas_wl_common_cb_device_event_free(void *user_data, void *func_data) { @@ -1081,7 +1056,7 @@ _ecore_evas_wl_common_cb_global_added(void *d EINA_UNUSED, int t EINA_UNUSED, vo EE_Wl_Device *device; if ((!ev->interface) || (strcmp(ev->interface, "wl_seat"))) - return ECORE_CALLBACK_PASS_ON; + return ECORE_CALLBACK_PASS_ON; EINA_LIST_FOREACH(ee_list, l, ee) { @@ -1130,7 +1105,7 @@ _ecore_evas_wl_common_cb_global_removed(void *d EINA_UNUSED, int t EINA_UNUSED, Eina_List *l, *ll; if ((!ev->interface) || (strcmp(ev->interface, "wl_seat"))) - return ECORE_CALLBACK_PASS_ON; + return ECORE_CALLBACK_PASS_ON; EINA_LIST_FOREACH(ee_list, l, ee) { @@ -1320,7 +1295,7 @@ static int _ecore_evas_wl_common_init(void) { Ecore_Event_Handler *h; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (++_ecore_evas_wl_init_count != 1) return _ecore_evas_wl_init_count; @@ -1347,14 +1322,6 @@ _ecore_evas_wl_common_init(void) _ecore_evas_wl_common_cb_window_configure, NULL); eina_array_push(_ecore_evas_wl_event_hdls, h); - h = ecore_event_handler_add(_ecore_wl2_event_window_www, - _ecore_evas_wl_common_cb_www, NULL); - eina_array_push(_ecore_evas_wl_event_hdls, h); - - h = ecore_event_handler_add(_ecore_wl2_event_window_www_drag, - _ecore_evas_wl_common_cb_www_drag, NULL); - eina_array_push(_ecore_evas_wl_event_hdls, h); - h = ecore_event_handler_add(ECORE_WL2_EVENT_DISCONNECT, _ecore_evas_wl_common_cb_disconnect, NULL); eina_array_push(_ecore_evas_wl_event_hdls, h); @@ -1409,7 +1376,7 @@ _ecore_evas_wl_common_init(void) static int _ecore_evas_wl_common_shutdown(void) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (--_ecore_evas_wl_init_count != 0) return _ecore_evas_wl_init_count; @@ -1430,7 +1397,7 @@ _ecore_evas_wl_common_free(Ecore_Evas *ee) Ecore_Evas_Engine_Wl_Data *wdata; EE_Wl_Device *device; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; @@ -1441,6 +1408,15 @@ _ecore_evas_wl_common_free(Ecore_Evas *ee) if (wdata->frame) ecore_wl2_window_frame_callback_del(wdata->frame); wdata->frame = NULL; ecore_event_handler_del(wdata->sync_handler); + ecore_event_handler_del(wdata->changed_handler); + ecore_event_handler_del(wdata->send_handler); + ecore_event_handler_del(wdata->offer_handler); + ecore_event_handler_del(wdata->dnd_leave_handler); + ecore_event_handler_del(wdata->dnd_enter_handler); + ecore_event_handler_del(wdata->dnd_motion_handler); + ecore_event_handler_del(wdata->dnd_drop_handler); + ecore_event_handler_del(wdata->dnd_end_handler); + if (wdata->win) { ecore_wl2_window_close_callback_set(wdata->win, NULL, NULL); @@ -1450,7 +1426,7 @@ _ecore_evas_wl_common_free(Ecore_Evas *ee) ecore_wl2_display_disconnect(wdata->display); EINA_LIST_FREE(wdata->devices_list, device) - free(device); + free(device); free(wdata); @@ -1464,7 +1440,7 @@ _ecore_evas_wl_common_free(Ecore_Evas *ee) static void _ecore_evas_wl_common_move_resize(Ecore_Evas *ee, int x EINA_UNUSED, int y EINA_UNUSED, int w, int h) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if ((ee->w != w) || (ee->h != h)) @@ -1526,10 +1502,12 @@ _ecore_evas_wl_common_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_C Ecore_Evas_Engine_Wl_Data *wdata; Ecore_Wl2_Input *input; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; wdata = ee->engine.data; - input = ecore_wl2_display_input_find_by_name(ecore_wl2_window_display_get(wdata->win), "default"); + input = + ecore_wl2_display_input_find_by_name + (ecore_wl2_window_display_get(wdata->win), "default"); if (input) ecore_wl2_input_pointer_xy_get(input, x, y); } @@ -1601,12 +1579,14 @@ _ecore_evas_wl_common_pointer_device_xy_get(const Ecore_Evas *ee, const Efl_Inpu Ecore_Wl2_Input *input; const Eo *seat; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; wdata = ee->engine.data; seat = evas_device_parent_get(pointer); EINA_SAFETY_ON_NULL_RETURN(seat); - input = ecore_wl2_display_input_find(ecore_wl2_window_display_get(wdata->win), evas_device_seat_id_get(seat)); + input = + ecore_wl2_display_input_find + (ecore_wl2_window_display_get(wdata->win), evas_device_seat_id_get(seat)); EINA_SAFETY_ON_NULL_RETURN(input); ecore_wl2_input_pointer_xy_get(input, x, y); } @@ -1616,11 +1596,12 @@ _ecore_evas_wl_common_aux_hints_supported_update(Ecore_Evas *ee) { Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; wdata = ee->engine.data; - ee->prop.aux_hint.supported_list = ecore_wl2_window_aux_hints_supported_get(wdata->win); + ee->prop.aux_hint.supported_list = + ecore_wl2_window_aux_hints_supported_get(wdata->win); } static void @@ -1628,7 +1609,7 @@ _ecore_evas_wl_common_title_set(Ecore_Evas *ee, const char *title) { Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (eina_streq(ee->prop.title, title)) return; @@ -1647,7 +1628,7 @@ _ecore_evas_wl_common_name_class_set(Ecore_Evas *ee, const char *n, const char * { Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; wdata = ee->engine.data; @@ -1671,8 +1652,9 @@ _ecore_evas_wl_common_name_class_set(Ecore_Evas *ee, const char *n, const char * static void _ecore_evas_wl_common_size_min_set(Ecore_Evas *ee, int w, int h) { + int fw, fh, ww, hh; Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; @@ -1682,14 +1664,23 @@ _ecore_evas_wl_common_size_min_set(Ecore_Evas *ee, int w, int h) ee->prop.min.w = w; ee->prop.min.h = h; wdata = ee->engine.data; + evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh); if (wdata->win->xdg_set_min_size && wdata->win->xdg_toplevel) { - wdata->win->xdg_set_min_size(wdata->win->xdg_toplevel, w, h); + ww = w + fw; + hh = h + fh; + if (ww < 1) ww = 1; + if (hh < 1) hh = 1; + wdata->win->xdg_set_min_size(wdata->win->xdg_toplevel, ww, hh); wdata->win->pending.min = 0; } if (wdata->win->zxdg_set_min_size && wdata->win->zxdg_toplevel) { - wdata->win->zxdg_set_min_size(wdata->win->zxdg_toplevel, w, h); + ww = w + fw; + hh = h + fh; + if (ww < 1) ww = 1; + if (hh < 1) hh = 1; + wdata->win->zxdg_set_min_size(wdata->win->zxdg_toplevel, ww, hh); wdata->win->pending.min = 0; } else @@ -1700,8 +1691,9 @@ _ecore_evas_wl_common_size_min_set(Ecore_Evas *ee, int w, int h) static void _ecore_evas_wl_common_size_max_set(Ecore_Evas *ee, int w, int h) { + int fw, fh, ww, hh; Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (w < 0) w = 0; @@ -1710,14 +1702,23 @@ _ecore_evas_wl_common_size_max_set(Ecore_Evas *ee, int w, int h) ee->prop.max.w = w; ee->prop.max.h = h; wdata = ee->engine.data; + evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh); if (wdata->win->xdg_set_max_size && wdata->win->xdg_toplevel) { - wdata->win->xdg_set_max_size(wdata->win->xdg_toplevel, w, h); + ww = w + fw; + hh = h + fh; + if (ww < 0) ww = 0; + if (hh < 0) hh = 0; + wdata->win->xdg_set_max_size(wdata->win->xdg_toplevel, ww, hh); wdata->win->pending.max = 0; } if (wdata->win->zxdg_set_max_size && wdata->win->zxdg_toplevel) { - wdata->win->zxdg_set_max_size(wdata->win->zxdg_toplevel, w, h); + ww = w + fw; + hh = h + fh; + if (ww < 0) ww = 0; + if (hh < 0) hh = 0; + wdata->win->zxdg_set_max_size(wdata->win->zxdg_toplevel, ww, hh); wdata->win->pending.max = 0; } else @@ -1728,7 +1729,7 @@ _ecore_evas_wl_common_size_max_set(Ecore_Evas *ee, int w, int h) static void _ecore_evas_wl_common_size_base_set(Ecore_Evas *ee, int w, int h) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (w < 0) w = 0; @@ -1742,7 +1743,7 @@ _ecore_evas_wl_common_size_base_set(Ecore_Evas *ee, int w, int h) static void _ecore_evas_wl_common_size_step_set(Ecore_Evas *ee, int w, int h) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (w < 0) w = 0; @@ -1756,7 +1757,7 @@ _ecore_evas_wl_common_size_step_set(Ecore_Evas *ee, int w, int h) static void _ecore_evas_wl_common_aspect_set(Ecore_Evas *ee, double aspect) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (EINA_FLT_EQ(ee->prop.aspect, aspect)) return; @@ -1784,14 +1785,16 @@ _ecore_evas_wl_common_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int la wdata = ee->engine.data; if (obj == _ecore_evas_default_cursor_image_get(ee)) return; - input = ecore_wl2_display_input_find_by_name(ecore_wl2_window_display_get(wdata->win), "default"); + input = + ecore_wl2_display_input_find_by_name + (ecore_wl2_window_display_get(wdata->win), "default"); if (input) ecore_wl2_input_pointer_set(input, NULL, hot_x, hot_y); } static void _ecore_evas_wl_common_layer_set(Ecore_Evas *ee, int layer) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (ee->prop.layer == layer) return; @@ -1806,7 +1809,7 @@ _ecore_evas_wl_common_iconified_set(Ecore_Evas *ee, Eina_Bool on) { Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; ee->prop.iconified = on; @@ -1818,7 +1821,7 @@ _ecore_evas_wl_common_iconified_set(Ecore_Evas *ee, Eina_Bool on) static void _ecore_evas_wl_common_borderless_set(Ecore_Evas *ee, Eina_Bool on) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (ee->prop.borderless == on) return; @@ -1832,7 +1835,7 @@ _ecore_evas_wl_common_maximized_set(Ecore_Evas *ee, Eina_Bool on) { Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (ee->prop.maximized == on) return; @@ -1846,7 +1849,7 @@ _ecore_evas_wl_common_fullscreen_set(Ecore_Evas *ee, Eina_Bool on) { Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (ee->prop.fullscreen == on) return; @@ -1858,7 +1861,7 @@ _ecore_evas_wl_common_fullscreen_set(Ecore_Evas *ee, Eina_Bool on) static void _ecore_evas_wl_common_ignore_events_set(Ecore_Evas *ee, int ignore) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; ee->ignore_events = ignore; @@ -1923,7 +1926,7 @@ _ecore_evas_wayland_alpha_do(Ecore_Evas *ee, int alpha) { Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (ee->alpha == alpha) return; @@ -1973,7 +1976,7 @@ _ecore_evas_wl_common_prepare(Ecore_Evas *ee) static void _ecore_evas_wl_common_withdrawn_set(Ecore_Evas *ee, Eina_Bool on) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (ee->prop.withdrawn == on) return; @@ -1992,7 +1995,7 @@ _ecore_evas_wl_common_screen_geometry_get(const Ecore_Evas *ee, int *x, int *y, { Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (x) *x = 0; if (y) *y = 0; @@ -2008,7 +2011,7 @@ _ecore_evas_wl_common_screen_dpi_get(const Ecore_Evas *ee, int *xdpi, int *ydpi) Ecore_Wl2_Output *output; int dpi = 0; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; if (xdpi) *xdpi = 0; @@ -2029,7 +2032,7 @@ _ecore_evas_wayland_resize(Ecore_Evas *ee, int location) { Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; wdata = ee->engine.data; @@ -2042,7 +2045,7 @@ _ecore_evas_wayland_move(Ecore_Evas *ee, int x EINA_UNUSED, int y EINA_UNUSED) { Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!ee) return; wdata = ee->engine.data; @@ -2136,8 +2139,9 @@ _ecore_evas_wl_common_show(Ecore_Evas *ee) { Evas_Engine_Info_Wayland *einfo; Ecore_Evas_Engine_Wl_Data *wdata; + int ww, hh; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if ((!ee) || (ee->visible)) return; @@ -2153,31 +2157,50 @@ _ecore_evas_wl_common_show(Ecore_Evas *ee) { int fw, fh; - if (wdata->win->xdg_set_min_size && wdata->win->xdg_toplevel && wdata->win->pending.min) + evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh); + if (wdata->win->xdg_set_min_size && wdata->win->xdg_toplevel && + wdata->win->pending.min) { - wdata->win->xdg_set_min_size(wdata->win->xdg_toplevel, ee->prop.min.w, ee->prop.min.h); + ww = ee->prop.min.w + fw; + hh = ee->prop.min.h + fh; + if (ww < 1) ww = 1; + if (hh < 1) hh = 1; + wdata->win->xdg_set_min_size(wdata->win->xdg_toplevel, ww, hh); wdata->win->pending.min = 0; } - if (wdata->win->xdg_set_max_size && wdata->win->xdg_toplevel && wdata->win->pending.max) + if (wdata->win->xdg_set_max_size && wdata->win->xdg_toplevel && + wdata->win->pending.max) { - wdata->win->xdg_set_max_size(wdata->win->xdg_toplevel, ee->prop.max.w, ee->prop.max.h); + ww = ee->prop.max.w + fw; + hh = ee->prop.max.h + fh; + if (ww < 0) ww = 0; + if (hh < 0) hh = 0; + wdata->win->xdg_set_max_size(wdata->win->xdg_toplevel, ww, hh); wdata->win->pending.max = 0; } - if (wdata->win->zxdg_set_min_size && wdata->win->zxdg_toplevel && wdata->win->pending.min) + if (wdata->win->zxdg_set_min_size && wdata->win->zxdg_toplevel && + wdata->win->pending.min) { - wdata->win->zxdg_set_min_size(wdata->win->zxdg_toplevel, ee->prop.min.w, ee->prop.min.h); + ww = ee->prop.min.w + fw; + hh = ee->prop.min.h + fh; + if (ww < 1) ww = 1; + if (hh < 1) hh = 1; + wdata->win->zxdg_set_min_size(wdata->win->zxdg_toplevel, ww, hh); wdata->win->pending.min = 0; } - if (wdata->win->zxdg_set_max_size && wdata->win->zxdg_toplevel && wdata->win->pending.max) + if (wdata->win->zxdg_set_max_size && wdata->win->zxdg_toplevel && + wdata->win->pending.max) { - wdata->win->zxdg_set_max_size(wdata->win->zxdg_toplevel, ee->prop.max.w, ee->prop.max.h); + ww = ee->prop.max.w + fw; + hh = ee->prop.max.h + fh; + if (ww < 0) ww = 0; + if (hh < 0) hh = 0; + wdata->win->zxdg_set_max_size(wdata->win->zxdg_toplevel, ww, hh); wdata->win->pending.max = 0; } _ecore_evas_wayland_window_update(ee, wdata, ee->alpha); - evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh); - ecore_wl2_window_show(wdata->win); einfo = (Evas_Engine_Info_Wayland *)evas_engine_info_get(ee->evas); if (einfo) @@ -2185,7 +2208,6 @@ _ecore_evas_wl_common_show(Ecore_Evas *ee) einfo->info.destination_alpha = ee_needs_alpha(ee); einfo->info.wl2_win = wdata->win; einfo->info.hidden = wdata->win->pending.configure; //EINA_FALSE; - einfo->www_avail = !!wdata->win->www_surface; if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) ERR("Failed to set Evas Engine Info for '%s'", ee->driver); if (ECORE_EVAS_PORTRAIT(ee)) @@ -2208,7 +2230,7 @@ _ecore_evas_wl_common_hide(Ecore_Evas *ee) Evas_Engine_Info_Wayland *einfo; Ecore_Evas_Engine_Wl_Data *wdata; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if ((!ee) || (!ee->visible)) return; wdata = ee->engine.data; @@ -2257,7 +2279,7 @@ _ecore_evas_wl_common_alpha_set(Ecore_Evas *ee, int alpha) static void _ecore_evas_wl_common_rotation_set(Ecore_Evas *ee, int rotation, int resize) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (ee->rotation == rotation) return; @@ -2387,6 +2409,518 @@ _ecore_wl2_devices_setup(Ecore_Evas *ee, Ecore_Wl2_Display *display) return r; } +static void +_reeval_seat(unsigned int *seat, Ecore_Evas *ee) +{ + if (*seat == 0) + { + *seat = + evas_device_seat_id_get(evas_default_device_get + (ee->evas, EVAS_DEVICE_CLASS_SEAT)); + } +} + +static inline void +_clear_selection(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection) +{ + Ecore_Evas_Engine_Wl_Data *edata = ee->engine.data; + Ecore_Evas_Selection_Callbacks *cbs; + + cbs = &edata->selection_data[selection].callbacks; + EINA_SAFETY_ON_FALSE_RETURN(cbs->cancel); + + cbs->cancel(ee, seat, selection); + eina_array_free(cbs->available_types); + memset(cbs, 0, sizeof(Ecore_Evas_Selection_Callbacks)); +} + +static void +_store_selection_cbs(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Ecore_Evas_Selection_Internal_Delivery delivery, Ecore_Evas_Selection_Internal_Cancel cancel) +{ + Ecore_Evas_Wl_Selection_Data *sdata; + Ecore_Evas_Engine_Wl_Data *edata; + Ecore_Evas_Selection_Callbacks *cbs; + + edata = ee->engine.data; + sdata = &edata->selection_data[selection]; + cbs = &sdata->callbacks; + + if (cbs->cancel) + { + _clear_selection(ee, seat, selection); + } + + cbs->delivery = delivery; + cbs->cancel = cancel; + cbs->available_types = available_types; +} + +static inline Ecore_Wl2_Input* +_fetch_input(Ecore_Evas *ee, unsigned int seat) +{ + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + return ecore_wl2_display_input_find(ecore_wl2_window_display_get(wdata->win), seat); +} + +static Eina_Bool +_ecore_evas_wl_selection_claim(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Ecore_Evas_Selection_Internal_Delivery delivery, Ecore_Evas_Selection_Internal_Cancel cancel) +{ + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + Ecore_Evas_Wl_Selection_Data *data = &wdata->selection_data[selection]; + char *tmp_array[eina_array_count(available_types) + 1]; + + if (selection == ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER) + { + _store_selection_cbs(ee, seat, selection, available_types, + delivery, cancel); + return EINA_TRUE; + } + + _reeval_seat(&seat, ee); + _store_selection_cbs(ee, seat, selection, available_types, delivery, cancel); + + for (unsigned int i = 0; i < eina_array_count(available_types); ++i) + { + tmp_array[i] = eina_array_data_get(available_types, i); + } + tmp_array[eina_array_count(available_types)] = NULL; + + data->sent_serial = + ecore_wl2_dnd_selection_set(_fetch_input(ee, seat), + (const char**)tmp_array); + return EINA_TRUE; +} + + +static Eina_Future* +_ecore_evas_wl_selection_request(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_types) +{ + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + Ecore_Evas_Wl_Selection_Data *data = &wdata->selection_data[selection]; + Ecore_Wl2_Input *input; + Ecore_Wl2_Offer *offer = NULL; + Eina_Future *future; + + _reeval_seat(&seat, ee); + input = _fetch_input(ee, seat); + + if (data->delivery) + { + eina_promise_reject(data->delivery, ecore_evas_request_replaced); + data->delivery = NULL; + } + data->delivery = efl_loop_promise_new(efl_main_loop_get()); + future = eina_future_new(data->delivery); + + if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) + { + offer = data->offer = wdata->external_offer; + } + else if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER) + { + offer = data->offer = ecore_wl2_dnd_selection_get(input); + } + + if (!offer) + { + eina_promise_reject(data->delivery, ecore_evas_no_selection); + data->delivery = NULL; + } + else + { + Eina_Array *available_types = ecore_wl2_offer_mimes_get(offer); + char *selected_type = NULL; + + for (unsigned int i = 0; i < eina_array_count(available_types) && !selected_type; ++i) + { + char *available_type = eina_array_data_get(available_types, i); + for (unsigned int j = 0; j < eina_array_count(acceptable_types) && !selected_type; ++j) + { + Eina_Iterator *convertions; + const char *convert_available_type; + char *acceptable_type; + + acceptable_type = eina_array_data_get(acceptable_types, j); + if (eina_streq(acceptable_type, available_type)) + { + selected_type = available_type; + data->later_convert = NULL; + break; + } + + convertions = + eina_content_converter_possible_conversions(available_type); + + EINA_ITERATOR_FOREACH(convertions, convert_available_type) + { + if (eina_streq(convert_available_type, acceptable_type)) + { + selected_type = available_type; + data->later_convert = acceptable_type; + } + } + eina_iterator_free(convertions); + } + + } + if (selected_type) + { + ecore_wl2_offer_receive(offer, selected_type); + ecore_wl2_display_flush(ecore_wl2_input_display_get(input)); + } + else + { + eina_promise_reject(data->delivery, ecore_evas_no_matching_type); + data->delivery = NULL; + } + } + + return future; +} + +static Eina_Bool +_ecore_evas_wl_selection_has_owner(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection EINA_UNUSED) +{ + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + Ecore_Wl2_Input *input; + + _reeval_seat(&seat, ee); + input = _fetch_input(ee, seat); + + if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER ) + return !!ecore_wl2_dnd_selection_get(input); + else if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) + { + Ecore_Evas_Wl_Selection_Data *data = &wdata->selection_data[selection]; + return !!data->offer; + } + + return EINA_FALSE; //the selection buffer is not supportet in wayland +} + +static Eina_Bool +_wl_selection_changed(void *data, int type EINA_UNUSED, void *event EINA_UNUSED) +{ + Ecore_Wl2_Event_Seat_Selection *sel = event; + Ecore_Evas *ee = data; + Ecore_Wl2_Input *input; + unsigned int seat = sel->seat; + + _reeval_seat(&seat, ee); + input = _fetch_input(ee, seat); + if (!ecore_wl2_dnd_selection_get(input)) + return ECORE_CALLBACK_PASS_ON; + + if (ee->func.fn_selection_changed) + { + ee->func.fn_selection_changed + (ee, 0, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER); + } + + return ECORE_CALLBACK_PASS_ON; +} + +typedef struct +{ + Eina_Rw_Slice slice; + unsigned int written_bytes; +} Delayed_Writing; + +static Eina_Bool +_write_to_fd(void *data, Ecore_Fd_Handler *fd_handler) +{ + int fd; + size_t len; + Delayed_Writing *slice = data; + + fd = ecore_main_fd_handler_fd_get(fd_handler); + if (fd < 0) goto end; + + len = write(fd, (char*)slice->slice.mem + slice->written_bytes, + slice->slice.len - slice->written_bytes); + + slice->written_bytes += len; + if (slice->written_bytes != slice->slice.len) + { + return EINA_TRUE; + } + else + { +end: + ecore_main_fd_handler_del(fd_handler); + free(slice->slice.mem); + free(slice); + if (fd > -1) close(fd); + return EINA_FALSE; + } +} + +static Eina_Bool +_wl_interaction_send(void *data, int type EINA_UNUSED, void *event) +{ + Ecore_Wl2_Event_Data_Source_Send *ev = event; + Ecore_Evas *ee = data; + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + Ecore_Evas_Wl_Selection_Data *selection = NULL; + Delayed_Writing *forign_slice = calloc(1, sizeof(Delayed_Writing)); + Ecore_Evas_Selection_Buffer buffer = ECORE_EVAS_SELECTION_BUFFER_LAST; + + if (ev->serial == wdata->selection_data[ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER].sent_serial) + buffer = ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER; + else if (ev->serial == wdata->selection_data[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER].sent_serial) + { + buffer = ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER; + ee->drag.accepted = EINA_TRUE; + } + + if (buffer == ECORE_EVAS_SELECTION_BUFFER_LAST) + { + //silent return, this send request was *not* for this window + goto end; + } + + selection = &wdata->selection_data[buffer]; + EINA_SAFETY_ON_NULL_GOTO(selection, end); + EINA_SAFETY_ON_NULL_GOTO(selection->callbacks.delivery, end); + EINA_SAFETY_ON_FALSE_GOTO(selection->callbacks.delivery + (ee, ev->seat, buffer, ev->type, + &forign_slice->slice), end); + ecore_main_fd_handler_add(ev->fd, ECORE_FD_WRITE, _write_to_fd, + forign_slice, NULL, NULL); + + return ECORE_CALLBACK_PASS_ON; + +end: + free(forign_slice); + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_wl_selection_receive(void *data, int type EINA_UNUSED, void *event) +{ + Ecore_Evas *ee = data; + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + Ecore_Wl2_Event_Offer_Data_Ready *ready = event; + Ecore_Evas_Selection_Buffer selection = ECORE_EVAS_SELECTION_BUFFER_LAST; + + if ((!ready->data) || (ready->len < 1)) + { + ERR("no selection data"); + return ECORE_CALLBACK_PASS_ON; + } + for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i) + { + if (wdata->selection_data[i].offer == ready->offer) + { + selection = i; + break; + } + } + + if (selection == ECORE_EVAS_SELECTION_BUFFER_LAST) + return ECORE_CALLBACK_PASS_ON; + + //Now deliver the content + Eina_Slice slice; + + if (eina_str_has_prefix(ready->mimetype,"text")) + { + //ensure that we always have a \0 at the end, there is no assertion that \0 is included here. + slice.len = ready->len + 1; + slice.mem = + eina_memdup((unsigned char*)ready->data, ready->len, EINA_TRUE); + } + else + { + slice.len = ready->len; + slice.mem = ready->data; + } + + Eina_Content *content = eina_content_new(slice, ready->mimetype); + + if (wdata->selection_data[selection].later_convert) + { + Eina_Content *tmp; + + tmp = eina_content_convert(content, wdata->selection_data[selection].later_convert); + wdata->selection_data[selection].later_convert = NULL; + eina_content_free(content); + content = tmp; + } + + eina_promise_resolve(wdata->selection_data[selection].delivery, + eina_value_content_init(content)); + wdata->selection_data[selection].delivery = NULL; + eina_content_free(content); + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_wl_selection_dnd_leave(void *data, int type EINA_UNUSED, void *event) +{ + Ecore_Evas *ee = data; + Eina_Position2D cpos; + Eina_Position2D fpos = EINA_POSITION2D(0, 0); + Ecore_Wl2_Event_Dnd_Leave *ev = event; + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + + if (ee->prop.window != (Ecore_Window)ev->win) return ECORE_CALLBACK_PASS_ON; + + //evas_output_framespace_get(ee->evas, &fpos.x, &fpos.y, NULL, NULL); + ecore_wl2_input_pointer_xy_get(ecore_wl2_display_input_find + (ev->display, ev->seat), &cpos.x, &cpos.y); + ecore_evas_dnd_leave(data, ev->seat, EINA_POSITION2D(cpos.x - fpos.x, + cpos.y - fpos.y)); + wdata->external_offer = NULL; + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_wl_selection_dnd_motion(void *data, int type EINA_UNUSED, void *event) +{ + Ecore_Evas *ee = data; + Ecore_Wl2_Event_Dnd_Motion *ev = event; + Eina_Position2D fpos = EINA_POSITION2D(0, 0); + + if (ee->prop.window != (Ecore_Window)ev->win) return ECORE_CALLBACK_PASS_ON; + + evas_output_framespace_get(ee->evas, &fpos.x, &fpos.y, NULL, NULL); + ecore_evas_dnd_position_set(data, ev->seat, + EINA_POSITION2D(ev->x - fpos.x, ev->y - fpos.y)); + return ECORE_CALLBACK_PASS_ON; +} +static Eina_Bool +_wl_selection_dnd_enter(void *data, int type EINA_UNUSED, void *event) +{ + Ecore_Evas *ee = data; + Ecore_Wl2_Event_Dnd_Enter *ev = event; + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + Eina_Position2D fpos = EINA_POSITION2D(0, 0); + + if (ee->prop.window != (Ecore_Window)ev->win) return ECORE_CALLBACK_PASS_ON; + + evas_output_framespace_get(ee->evas, &fpos.x, &fpos.y, NULL, NULL); + ecore_evas_dnd_enter(data, ev->seat, + eina_array_iterator_new + (ecore_wl2_offer_mimes_get(ev->offer)), + EINA_POSITION2D(ev->x - fpos.x, ev->y - fpos.y)); + ecore_wl2_offer_mimes_set(ev->offer, ecore_wl2_offer_mimes_get(ev->offer)); + wdata->external_offer = ev->offer; + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_wl_selection_dnd_drop(void *data, int type EINA_UNUSED, void *event) +{ + Ecore_Evas *ee = data; + Ecore_Wl2_Event_Dnd_Drop *ev = event; + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + if (ee->prop.window != (Ecore_Window)ev->win) return ECORE_CALLBACK_PASS_ON; + wdata = ee->engine.data; + + if (ee->func.fn_dnd_drop) + { + ee->func.fn_dnd_drop(ee, ev->seat, + ecore_evas_dnd_pos_get(ee, ev->seat), "ask"); + } + + ecore_wl2_dnd_drag_end(_fetch_input(ee, ev->seat)); + wdata->external_offer = NULL; + + return ECORE_CALLBACK_PASS_ON; +} +static Eina_Bool +_wl_selection_dnd_end(void *data, int type EINA_UNUSED, void *event) +{ + Ecore_Evas *ee = data; + Ecore_Wl2_Event_Dnd_End *ev = event; + + if (ee->prop.window != (Ecore_Window)ev->win) return ECORE_CALLBACK_PASS_ON; + + + if (ee->drag.free) + ee->drag.free(ee, ev->seat, ee->drag.data, ee->drag.accepted); + ee->drag.free = NULL; + //we got dropped, we should call + + return ECORE_CALLBACK_PASS_ON; +} + +static void +_ecore_evas_wl_selection_init(Ecore_Evas *ee) +{ + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + + wdata->changed_handler = + ecore_event_handler_add(ECORE_WL2_EVENT_SEAT_SELECTION, + _wl_selection_changed, ee); + wdata->send_handler = + ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_SEND, + _wl_interaction_send, ee); + wdata->offer_handler = + ecore_event_handler_add(ECORE_WL2_EVENT_OFFER_DATA_READY, + _wl_selection_receive, ee); + wdata->dnd_leave_handler = + ecore_event_handler_add(ECORE_WL2_EVENT_DND_LEAVE, + _wl_selection_dnd_leave, ee); + wdata->dnd_motion_handler = + ecore_event_handler_add(ECORE_WL2_EVENT_DND_MOTION, + _wl_selection_dnd_motion, ee); + wdata->dnd_enter_handler = + ecore_event_handler_add(ECORE_WL2_EVENT_DND_ENTER, + _wl_selection_dnd_enter, ee); + wdata->dnd_drop_handler = + ecore_event_handler_add(ECORE_WL2_EVENT_DND_DROP, + _wl_selection_dnd_drop, ee); + wdata->dnd_end_handler = + ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_END, + _wl_selection_dnd_end, ee); + + for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i) + { + wdata->selection_data[i].callbacks.available_types = NULL; + wdata->selection_data[i].callbacks.delivery = NULL; + wdata->selection_data[i].callbacks.cancel = NULL; + } +} + +static Eina_Bool +_ecore_evas_wl_dnd_start(Ecore_Evas *ee, unsigned int seat, Eina_Array *available_types, Ecore_Evas *drag_rep, Ecore_Evas_Selection_Internal_Delivery delivery, Ecore_Evas_Selection_Internal_Cancel cancel, const char *action EINA_UNUSED) +{ + Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data; + const char *tmp_array[eina_array_count(available_types) + 1]; + + _reeval_seat(&seat, ee); + _store_selection_cbs(ee, seat, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER, + available_types, delivery, cancel); + + for (unsigned int i = 0; i < eina_array_count(available_types); ++i) + { + tmp_array[i] = eina_array_data_get(available_types, i); + } + tmp_array[eina_array_count(available_types)] = NULL; + + ecore_wl2_dnd_drag_types_set(_fetch_input(ee, seat), + (const char**)tmp_array); + wdata->selection_data[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER].sent_serial = + ecore_wl2_dnd_drag_start(_fetch_input(ee, seat), + _ecore_evas_wayland_window_get(ee), + _ecore_evas_wayland_window_get(drag_rep)); + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_evas_wl_dnd_stop(Ecore_Evas *ee, unsigned int seat) +{ + _clear_selection(ee, seat, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER); + _reeval_seat(&seat, ee); + ecore_wl2_dnd_drag_end(_fetch_input(ee, seat)); + return EINA_TRUE; +} + static Ecore_Evas_Engine_Func _ecore_wl_engine_func = { _ecore_evas_wl_common_free, @@ -2472,6 +3006,11 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func = _ecore_evas_wl_common_pointer_device_xy_get, _ecore_evas_wl_common_prepare, NULL, //fn_last_tick_get + _ecore_evas_wl_selection_claim, //fn_selection_claim + _ecore_evas_wl_selection_has_owner, //fn_selection_has_owner + _ecore_evas_wl_selection_request, //fn_selection_request + _ecore_evas_wl_dnd_start, //fn_dnd_start + _ecore_evas_wl_dnd_stop, //fn_dnd_stop }; static void @@ -2496,7 +3035,7 @@ _ecore_evas_wl_common_new_internal(const char *disp_name, Ecore_Window parent, i Ecore_Evas *ee = NULL; int method = 0; - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; if (!(method = evas_render_method_lookup(engine_name))) { @@ -2648,6 +3187,7 @@ _ecore_evas_wl_common_new_internal(const char *disp_name, Ecore_Window parent, i } _ecore_evas_wl_common_wm_rotation_protocol_set(ee); + _ecore_evas_wl_selection_init(ee); ecore_evas_done(ee, EINA_FALSE); diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c index f5530bc61d..fd9415de41 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c @@ -31,7 +31,7 @@ EAPI Ecore_Evas * ecore_evas_wayland_egl_new_internal(const char *disp_name, Ecore_Window parent, int x, int y, int w, int h, Eina_Bool frame, const int *opt) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; return _ecore_evas_wl_common_new_internal(disp_name, parent, x, y, w, h, frame, diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h index e69970f262..8213dc2b32 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h @@ -11,10 +11,10 @@ //#define LOGFNS 1 # ifdef LOGFNS # include <stdio.h> -# define LOGFN(fl, ln, fn) \ - printf("-ECORE_EVAS-WL: %25s: %5i - %s\n", fl, ln, fn); +# define LOGFN \ + printf("-ECORE_EVAS-WL: %25s: %5i - %s\n", __FILE__, __LINE__, __func__) # else -# define LOGFN(fl, ln, fn) +# define LOGFN # endif # include <Eina.h> @@ -34,12 +34,23 @@ typedef struct _Ecore_Evas_Engine_Wl_Data Ecore_Evas_Engine_Wl_Data; +typedef struct _Ecore_Evas_Wl_Selection_Data Ecore_Evas_Wl_Selection_Data; + +struct _Ecore_Evas_Wl_Selection_Data +{ + Ecore_Evas_Selection_Callbacks callbacks; + Eina_Promise *delivery; + Ecore_Wl2_Offer *offer; + const char *later_convert; + uint32_t sent_serial; //The serial of the last sent selection op +}; + struct _Ecore_Evas_Engine_Wl_Data { Ecore_Wl2_Display *display; Eina_List *regen_objs; Ecore_Wl2_Window *parent, *win; - Ecore_Event_Handler *sync_handler; + Ecore_Event_Handler *sync_handler, *changed_handler, *end_handler, *send_handler, *offer_handler, *dnd_leave_handler, *dnd_motion_handler, *dnd_enter_handler, *dnd_drop_handler, *dnd_end_handler; int fx, fy, fw, fh; Ecore_Wl2_Frame_Cb_Handle *frame; int x_rel; @@ -47,7 +58,8 @@ struct _Ecore_Evas_Engine_Wl_Data uint32_t timestamp; Eina_List *devices_list; int cw, ch; - + Ecore_Evas_Wl_Selection_Data selection_data[ECORE_EVAS_SELECTION_BUFFER_LAST]; + Ecore_Wl2_Offer *external_offer; struct { Eina_Bool supported : 1; diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c index 252b1ffa02..1481bf6f2b 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c @@ -31,7 +31,7 @@ EAPI Ecore_Evas * ecore_evas_wayland_shm_new_internal(const char *disp_name, Ecore_Window parent, int x, int y, int w, int h, Eina_Bool frame) { - LOGFN(__FILE__, __LINE__, __FUNCTION__); + LOGFN; return _ecore_evas_wl_common_new_internal(disp_name, parent, x, y, w, h, frame, NULL, "wayland_shm"); diff --git a/src/modules/ecore_evas/engines/wayland/meson.build b/src/modules/ecore_evas/engines/wayland/meson.build index fbc27a396b..259d8bcdd8 100644 --- a/src/modules/ecore_evas/engines/wayland/meson.build +++ b/src/modules/ecore_evas/engines/wayland/meson.build @@ -11,7 +11,7 @@ engine_src = files([ 'ecore_evas_wayland_private.h' ]) -engine_deps = [ecore_wl2, ecore_input] +engine_deps = [ecore_wl2, ecore_input] + ecore_wl2_ext_deps engine_include_dir += include_directories(join_paths('..', '..', '..', 'evas', 'engines', 'wayland_common')) diff --git a/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c b/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c index 39def9d49f..623515da95 100644 --- a/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c +++ b/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c @@ -54,6 +54,8 @@ #define ECORE_EVAS_EVENT_COUNT 11 +#define EE_SZ(sz_) (ee->sz_ == 0) ? 1 : (ee->sz_) + static int _ecore_evas_init_count = 0; static Ecore_Event_Handler *ecore_evas_event_handlers[ECORE_EVAS_EVENT_COUNT]; @@ -62,11 +64,16 @@ static const int interface_win32_version = 1; typedef struct _Ecore_Evas_Engine_Data_Win32 Ecore_Evas_Engine_Data_Win32; -struct _Ecore_Evas_Engine_Data_Win32 { +struct _Ecore_Evas_Engine_Data_Win32 +{ Ecore_Win32_Window *parent; - struct { - unsigned char region : 1; - unsigned char fullscreen : 1; + Ecore_Evas_Selection_Callbacks clipboard; + Eina_Future *delivery; + struct + { + unsigned char region : 1; + unsigned char fullscreen : 1; + unsigned char maximized : 1; } state; }; @@ -94,6 +101,7 @@ static Eina_Bool _ecore_evas_win32_event_window_delete_request(void *data EINA_U static Eina_Bool _ecore_evas_win32_event_window_property_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); + /* Private functions */ static int @@ -370,13 +378,13 @@ _ecore_evas_win32_event_window_configure(void *data EINA_UNUSED, int type EINA_U if (ECORE_EVAS_PORTRAIT(ee)) { - evas_output_size_set(ee->evas, ee->w, ee->h); - evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + evas_output_size_set(ee->evas, EE_SZ(w), EE_SZ(h)); + evas_output_viewport_set(ee->evas, 0, 0, EE_SZ(w), EE_SZ(h)); } else { - evas_output_size_set(ee->evas, ee->h, ee->w); - evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); + evas_output_size_set(ee->evas, EE_SZ(h), EE_SZ(w)); + evas_output_viewport_set(ee->evas, 0, 0, EE_SZ(h), EE_SZ(w)); } if (ee->prop.avoid_damage) { @@ -427,9 +435,11 @@ _ecore_evas_win32_event_window_property_change(void *data EINA_UNUSED, int type { struct { struct { + unsigned char maximized : 1; unsigned char fullscreen : 1; } win32; struct { + Eina_Bool maximized : 1; Eina_Bool fullscreen : 1; } prop; } prev; @@ -449,12 +459,16 @@ _ecore_evas_win32_event_window_property_change(void *data EINA_UNUSED, int type wdata = ee->engine.data; prev.win32.fullscreen = wdata->state.fullscreen; + prev.win32.maximized = wdata->state.maximized; prev.prop.fullscreen = ee->prop.fullscreen; + prev.prop.maximized = ee->prop.maximized; wdata->state.fullscreen = 0; + wdata->state.maximized = 0; ee->prop.fullscreen = EINA_FALSE; + ee->prop.maximized = EINA_FALSE; /* we get the states status */ ecore_win32_window_state_get(e->window, &state, &num); @@ -468,6 +482,10 @@ _ecore_evas_win32_event_window_property_change(void *data EINA_UNUSED, int type ee->prop.fullscreen = 1; wdata->state.fullscreen = 1; break; + case ECORE_WIN32_WINDOW_STATE_MAXIMIZED: + ee->prop.maximized = 1; + wdata->state.maximized = 1; + break; default: break; } @@ -476,7 +494,9 @@ _ecore_evas_win32_event_window_property_change(void *data EINA_UNUSED, int type } if ((prev.win32.fullscreen != wdata->state.fullscreen) || - (prev.prop.fullscreen != ee->prop.fullscreen)) + (prev.prop.fullscreen != ee->prop.fullscreen) || + (prev.win32.maximized != wdata->state.maximized) || + (prev.prop.maximized != ee->prop.maximized)) { if (ee->func.fn_state_change) ee->func.fn_state_change(ee); @@ -501,6 +521,8 @@ _ecore_evas_win32_state_update(Ecore_Evas *ee) state[num++] = ECORE_WIN32_WINDOW_STATE_MAXIMIZED_VERT; if (ee->prop.maximized) state[num++] = ECORE_WIN32_WINDOW_STATE_MAXIMIZED_HORZ; + if (ee->prop.maximized) + state[num++] = ECORE_WIN32_WINDOW_STATE_MAXIMIZED; // if (bd->client.netwm.state.shaded) // state[num++] = ECORE_WIN32_WINDOW_STATE_SHADED; /* if (ee->prop.focus_skip) */ @@ -599,13 +621,13 @@ _ecore_evas_win32_move_resize(Ecore_Evas *ee, int x, int y, int width, int heigh x, y, width, height); if (ECORE_EVAS_PORTRAIT(ee)) { - evas_output_size_set(ee->evas, ee->w, ee->h); - evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + evas_output_size_set(ee->evas, EE_SZ(w), EE_SZ(h)); + evas_output_viewport_set(ee->evas, 0, 0, EE_SZ(w), EE_SZ(h)); } else { - evas_output_size_set(ee->evas, ee->h, ee->w); - evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); + evas_output_size_set(ee->evas, EE_SZ(h), EE_SZ(w)); + evas_output_viewport_set(ee->evas, 0, 0, EE_SZ(h), EE_SZ(w)); } if (ee->prop.avoid_damage) { @@ -664,13 +686,13 @@ _ecore_evas_win32_rotation_set_internal(Ecore_Evas *ee, int rotation) h, w); if (ECORE_EVAS_PORTRAIT(ee)) { - evas_output_size_set(ee->evas, ee->w, ee->h); - evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + evas_output_size_set(ee->evas, EE_SZ(w), EE_SZ(h)); + evas_output_viewport_set(ee->evas, 0, 0, EE_SZ(w), EE_SZ(h)); } else { - evas_output_size_set(ee->evas, ee->h, ee->w); - evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); + evas_output_size_set(ee->evas, EE_SZ(h), EE_SZ(w)); + evas_output_viewport_set(ee->evas, 0, 0, EE_SZ(h), EE_SZ(w)); } if (ee->func.fn_resize) ee->func.fn_resize(ee); } @@ -824,7 +846,8 @@ _ecore_evas_win32_activate(Ecore_Evas *ee) { INF("ecore evas activate"); - ecore_win32_window_focus((Ecore_Win32_Window *)ee->prop.window); + ecore_evas_show(ee); + ecore_win32_window_activate((Ecore_Win32_Window *)ee->prop.window); } static void @@ -967,6 +990,30 @@ _ecore_evas_win32_override_set(Ecore_Evas *ee, Eina_Bool on) } static void +_ecore_evas_win32_maximized_set(Ecore_Evas *ee, Eina_Bool on) +{ + Ecore_Evas_Engine_Data_Win32 *wdata = ee->engine.data; + + INF("ecore evas maximized set"); + + wdata->state.maximized = !!on; + if (ee->should_be_visible) + { + struct _Ecore_Win32_Window *window; + + window = (Ecore_Win32_Window *)ee->prop.window; + ecore_win32_window_maximized_set(window, on); + } + else + { + if (ee->prop.maximized == on) return; + ee->prop.maximized = on; + wdata->state.maximized = on; + _ecore_evas_win32_state_update(ee); + } +} + +static void _ecore_evas_win32_fullscreen_set(Ecore_Evas *ee, Eina_Bool on) { Ecore_Evas_Engine_Data_Win32 *wdata = ee->engine.data; @@ -1197,93 +1244,225 @@ _ecore_evas_win32_screen_dpi_get(const Ecore_Evas *ee, int *xdpi, int *ydpi) *ydpi = y_dpi; } +static Eina_Value +_delivery(void *data, const Eina_Value value EINA_UNUSED, const Eina_Future *dead_future EINA_UNUSED) +{ + Ecore_Evas *ee = data; + Ecore_Evas_Engine_Data_Win32 *edata = ee->engine.data; + Eina_Rw_Slice slice; + const char *mime_type = NULL; + + EINA_SAFETY_ON_NULL_GOTO(edata->delivery, end); + + for (unsigned int i = 0; i < eina_array_count(edata->clipboard.available_types); ++i) + { + mime_type = eina_array_data_get(edata->clipboard.available_types, i); + if (eina_str_has_prefix(mime_type, "text/")) + break; + } + if (mime_type) + { + edata->clipboard.delivery(ee, 1, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER, mime_type, &slice); + EINA_SAFETY_ON_FALSE_GOTO(ecore_win32_clipboard_set((Ecore_Win32_Window *)ee->prop.window, slice.mem, slice.len, mime_type), end); + } + else + { + ERR("No compatible mime type found"); + } + +end: + return EINA_VALUE_EMPTY; +} + +static Eina_Bool +_ecore_evas_win32_selection_claim(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Ecore_Evas_Selection_Internal_Delivery delivery, Ecore_Evas_Selection_Internal_Cancel cancel) +{ + Ecore_Evas_Engine_Data_Win32 *edata = ee->engine.data; + + if (selection != ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER) + return EINA_FALSE; + + if (!delivery && !cancel) + { + edata->clipboard.delivery = NULL; + edata->clipboard.cancel = NULL; + eina_array_clean(edata->clipboard.available_types); + ecore_win32_clipboard_clear((Ecore_Win32_Window *)ee->prop.window); + return EINA_TRUE; + } + else + { + if (edata->clipboard.cancel) + { + edata->clipboard.cancel(ee, seat, selection); + eina_array_free(edata->clipboard.available_types); + } + + edata->delivery = efl_loop_job(efl_main_loop_get()); + eina_future_then(edata->delivery, _delivery, ee); + edata->clipboard.delivery = delivery; + edata->clipboard.cancel = cancel; + edata->clipboard.available_types = available_types; + return EINA_TRUE; + } +} + +Eina_Future* +_ecore_evas_win32_selection_request(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type) +{ + Eina_Future *future; + Eina_Promise *promise; + const char *mime_type = NULL; + + if (selection != ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER) + return eina_future_rejected(efl_loop_future_scheduler_get(efl_main_loop_get()), ecore_evas_no_selection); + + promise = efl_loop_promise_new(efl_main_loop_get()); + future = eina_future_new(promise); + + for (unsigned int i = 0; i < eina_array_count(acceptable_type); ++i) + { + mime_type = eina_array_data_get(acceptable_type, i); + if (eina_str_has_prefix(mime_type, "text/")) + break; + } + if (!mime_type) + { + eina_promise_reject(promise, ecore_evas_no_matching_type); + } + else + { + size_t size; + void *data; + Eina_Content *content; + Eina_Rw_Slice slice; + + data = ecore_win32_clipboard_get((Ecore_Win32_Window *)ee->prop.window, &size, mime_type); + if (size != 0) + { + if (eina_str_has_prefix(mime_type, "text/")) + { + //ensure that we always have a \0 at the end, there is no assertion that \0 is included here. + slice.len = size + 1; + slice.mem = eina_memdup(data, size, EINA_TRUE); + free(data); + } + else + { + slice.len = size; + slice.mem = data; + } + content = eina_content_new(eina_rw_slice_slice_get(slice), mime_type); + free(slice.mem); //memory got duplicated in eina_content_new + if (!content) // construction can fail because of some validation reasons + eina_promise_reject(promise, ecore_evas_no_matching_type); + else + eina_promise_resolve(promise, eina_value_content_init(content)); + } + else + eina_promise_reject(promise, ecore_evas_no_matching_type); + } + return future; +} + +static Eina_Bool +_ecore_evas_win32_selection_has_owner(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection) +{ + return (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER); +} + static Ecore_Evas_Engine_Func _ecore_win32_engine_func = { _ecore_evas_win32_free, - NULL, - NULL, - NULL, - NULL, - _ecore_evas_win32_callback_delete_request_set, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - _ecore_evas_win32_move, - NULL, - _ecore_evas_win32_resize, - _ecore_evas_win32_move_resize, - _ecore_evas_win32_rotation_set, - _ecore_evas_win32_shaped_set, - _ecore_evas_win32_show, - _ecore_evas_win32_hide, - _ecore_evas_win32_raise, - _ecore_evas_win32_lower, - _ecore_evas_win32_activate, - _ecore_evas_win32_title_set, - NULL, /* _ecore_evas_x_name_class_set */ - _ecore_evas_win32_size_min_set, - _ecore_evas_win32_size_max_set, - _ecore_evas_win32_size_base_set, - _ecore_evas_win32_size_step_set, - _ecore_evas_win32_object_cursor_set, - _ecore_evas_win32_object_cursor_unset, - NULL, /* _ecore_evas_x_layer_set */ - _ecore_evas_win32_focus_set, - _ecore_evas_win32_iconified_set, - _ecore_evas_win32_borderless_set, - _ecore_evas_win32_override_set, - NULL, - _ecore_evas_win32_fullscreen_set, - NULL, /* _ecore_evas_x_avoid_damage_set */ - NULL, /* _ecore_evas_x_withdrawn_set */ - NULL, /* _ecore_evas_x_sticky_set */ - NULL, /* _ecore_evas_x_ignore_events_set */ - _ecore_evas_win32_alpha_set, - NULL, //transparent - NULL, // profiles_set - NULL, // profile_set - - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, // render - _ecore_evas_win32_screen_geometry_get, - _ecore_evas_win32_screen_dpi_get, - NULL, - NULL, // msg_send - - NULL, // pointer_xy_get - NULL, // pointer_warp - - NULL, // wm_rot_preferred_rotation_set - NULL, // wm_rot_available_rotations_set - NULL, // wm_rot_manual_rotation_done_set - NULL, // wm_rot_manual_rotation_done - - NULL, // aux_hints_set - - NULL, // fn_animator_register - NULL, // fn_animator_unregister - - NULL, // fn_evas_changed - NULL, //fn_focus_device_set - NULL, //fn_callback_focus_device_in_set - NULL, //fn_callback_focus_device_out_set - NULL, //fn_callback_device_mouse_in_set - NULL, //fn_callback_device_mouse_out_set - NULL, //fn_pointer_device_xy_get - NULL, //fn_prepare - NULL, //fn_last_tick_get + NULL, + NULL, + NULL, + NULL, + _ecore_evas_win32_callback_delete_request_set, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + _ecore_evas_win32_move, + NULL, + _ecore_evas_win32_resize, + _ecore_evas_win32_move_resize, + _ecore_evas_win32_rotation_set, + _ecore_evas_win32_shaped_set, + _ecore_evas_win32_show, + _ecore_evas_win32_hide, + _ecore_evas_win32_raise, + _ecore_evas_win32_lower, + _ecore_evas_win32_activate, + _ecore_evas_win32_title_set, + NULL, /* _ecore_evas_x_name_class_set */ + _ecore_evas_win32_size_min_set, + _ecore_evas_win32_size_max_set, + _ecore_evas_win32_size_base_set, + _ecore_evas_win32_size_step_set, + _ecore_evas_win32_object_cursor_set, + _ecore_evas_win32_object_cursor_unset, + NULL, /* _ecore_evas_x_layer_set */ + _ecore_evas_win32_focus_set, + _ecore_evas_win32_iconified_set, + _ecore_evas_win32_borderless_set, + _ecore_evas_win32_override_set, + _ecore_evas_win32_maximized_set, + _ecore_evas_win32_fullscreen_set, + NULL, /* _ecore_evas_x_avoid_damage_set */ + NULL, /* _ecore_evas_x_withdrawn_set */ + NULL, /* _ecore_evas_x_sticky_set */ + NULL, /* _ecore_evas_x_ignore_events_set */ + _ecore_evas_win32_alpha_set, + NULL, //transparent + NULL, // profiles_set + NULL, // profile_set + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, // render + _ecore_evas_win32_screen_geometry_get, + _ecore_evas_win32_screen_dpi_get, + NULL, + NULL, // msg_send + + NULL, // pointer_xy_get + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL, // wm_rot_manual_rotation_done + + NULL, // aux_hints_set + + NULL, // fn_animator_register + NULL, // fn_animator_unregister + + NULL, // fn_evas_changed + NULL, //fn_focus_device_set + NULL, //fn_callback_focus_device_in_set + NULL, //fn_callback_focus_device_out_set + NULL, //fn_callback_device_mouse_in_set + NULL, //fn_callback_device_mouse_out_set + NULL, //fn_pointer_device_xy_get + NULL, //fn_prepare + NULL, //fn_last_tick_get + _ecore_evas_win32_selection_claim, //fn_selection_claim + _ecore_evas_win32_selection_has_owner, //fn_selection_has_owner + _ecore_evas_win32_selection_request, //fn_selection_request + NULL, //fn_dnd_start + NULL, //fn_dnd_stop }; #endif /* BUILD_ECORE_EVAS_WIN32 */ diff --git a/src/modules/ecore_evas/engines/win32/meson.build b/src/modules/ecore_evas/engines/win32/meson.build index 65fbfc1bb1..197f306e83 100644 --- a/src/modules/ecore_evas/engines/win32/meson.build +++ b/src/modules/ecore_evas/engines/win32/meson.build @@ -6,6 +6,7 @@ config_h.set('BUILD_ECORE_EVAS_SOFTWARE_GDI', '1') engine_deps = [engine_software_ddraw, engine_software_gdi] shared_module(mod_full_name, engine_src, + c_args : package_c_args, include_directories : config_dir + [engine_include_dir], dependencies : [eina, ecore_win32, ecore_input, ecore_evas, ecore_input_evas] + engine_deps, install : true, diff --git a/src/modules/ecore_evas/engines/x/ecore_evas_x.c b/src/modules/ecore_evas/engines/x/ecore_evas_x.c index 97e5fb2d10..bb5f02c853 100644 --- a/src/modules/ecore_evas/engines/x/ecore_evas_x.c +++ b/src/modules/ecore_evas/engines/x/ecore_evas_x.c @@ -13,6 +13,7 @@ #include <Ecore_X.h> #include <Ecore_X_Atoms.h> +#include <Efreet.h> #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11 # include <Evas_Engine_Software_X11.h> @@ -48,6 +49,8 @@ # endif #endif /* ! _WIN32 */ +#define ECORE_EVAS_X11_SELECTION 0x7F + #define EDBG(...) \ EINA_LOG(_ecore_evas_log_dom, EINA_LOG_LEVEL_DBG + 1, __VA_ARGS__); @@ -73,6 +76,17 @@ static Eina_Bool wm_exists; typedef struct _Ecore_Evas_Engine_Data_X11 Ecore_Evas_Engine_Data_X11; +typedef struct { + EINA_MAGIC; + Ecore_Evas_Selection_Callbacks callbacks; + Ecore_Evas_Selection_Buffer buffer; + Ecore_Evas *ee; + Eina_Promise *delivery; + Eina_Array *acceptable_type; + Eina_Stringshare *requested_type; + Eina_Stringshare *later_conversion; +} Ecore_Evas_X11_Selection_Data; + struct _Ecore_Evas_Engine_Data_X11 { Ecore_X_Window win_root; Eina_List *win_extra; @@ -128,6 +142,11 @@ struct _Ecore_Evas_Engine_Data_X11 { void *visual; // store visual used to create pixmap unsigned long colormap; // store colormap used to create pixmap } pixmap; + Ecore_Evas_X11_Selection_Data selection_data[ECORE_EVAS_SELECTION_BUFFER_LAST]; + Eina_Array *xserver_atom_name_during_dnd; + Ecore_Event_Handler *mouse_up_handler; + Ecore_Job *init_job; + int skip_clean_event; Eina_Bool destroyed : 1; // X window has been deleted and cannot be used Eina_Bool fully_obscured : 1; // X window is fully obscured Eina_Bool configured : 1; // X window has been configured @@ -151,6 +170,8 @@ static void _alpha_do(Ecore_Evas *, int); static void _transparent_do(Ecore_Evas *, int); static void _avoid_damage_do(Ecore_Evas *, int); static void _rotation_do(Ecore_Evas *, int, int); +static void _ecore_evas_x_selection_init(void); +static void _ecore_evas_x_selection_window_init(Ecore_Evas *ee); #define SWAP_INT(a, b) do { a ^= b; b ^= a; a ^= b; } while (0) @@ -361,7 +382,7 @@ _ecore_evas_x_aux_hints_supported_update(Ecore_Evas *ee) for (i = 0; i < num; i++) { hint = eina_stringshare_add(str[i]); - ee->prop.aux_hint.supported_list = + ee->prop.aux_hint.supported_list = eina_list_append(ee->prop.aux_hint.supported_list, hint); } @@ -414,7 +435,7 @@ _ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y, op++; einfo->vsync = opt[op]; } -#ifdef EVAS_ENGINE_GL_X11_SWAP_MODE_EXISTS +#ifdef EVAS_ENGINE_GL_X11_SWAP_MODE_EXISTS else if (opt[op] == ECORE_EVAS_GL_X11_OPT_SWAP_MODE) { op++; @@ -768,7 +789,12 @@ _resize_shape_do(Ecore_Evas *ee) evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh); - if (edata->mask) ecore_x_pixmap_free(edata->mask); + if (edata->mask) + { + ecore_x_pixmap_free(edata->mask); + edata->mask = 0; + } + if (!ee->shaped) return; edata->mask = ecore_x_pixmap_new(ee->prop.window, ee->w + fw, ee->h + fh, 1); foreground = 0; gc = ecore_x_gc_new(edata->mask, @@ -845,7 +871,7 @@ _ecore_evas_x_event_property_change(void *data EINA_UNUSED, int type EINA_UNUSED Eina_Bool focus_skip : 1; } prop; } prev; - + prev.x.modal = edata->state.modal; prev.x.sticky = edata->state.sticky; prev.x.maximized_v = edata->state.maximized_v; @@ -856,7 +882,7 @@ _ecore_evas_x_event_property_change(void *data EINA_UNUSED, int type EINA_UNUSED prev.x.fullscreen = edata->state.fullscreen; prev.x.above = edata->state.above; prev.x.below = edata->state.below; - + prev.prop.modal = ee->prop.modal; prev.prop.maximized = ee->prop.maximized; prev.prop.sticky = ee->prop.sticky; @@ -879,7 +905,7 @@ _ecore_evas_x_event_property_change(void *data EINA_UNUSED, int type EINA_UNUSED ee->prop.sticky = EINA_FALSE; ee->prop.fullscreen = EINA_FALSE; // ee->prop.focus_skip = EINA_FALSE; - + ecore_x_netwm_window_state_get(e->win, &state, &num); if (state) { @@ -1253,7 +1279,7 @@ _ecore_evas_x_event_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, void if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */ if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON; edata = ee->engine.data; -/* +/* { time_t t; char *ct; @@ -1304,7 +1330,7 @@ _ecore_evas_x_event_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, void edata->outdelay = NULL; _fake_out(ee); } - + /* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */ if (!_ecore_evas_mouse_in_check(ee, NULL)) { @@ -1388,7 +1414,7 @@ _ecore_evas_x_event_mouse_out(void *data EINA_UNUSED, int type EINA_UNUSED, void ecore_timer_del(edata->outdelay); edata->outdelay = NULL; } - + // if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; // printf("OUT: ee->in=%i, e->mode=%i, e->detail=%i, dount_count=%i\n", // ee->in, e->mode, e->detail, evas_event_down_count_get(ee->evas)); @@ -1417,7 +1443,7 @@ _ecore_evas_x_event_window_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED ee = ecore_event_window_match(e->win); if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */ if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON; -//xx// filtering with these doesnt help +//xx// filtering with these doesnt help //xx// if (e->mode == ECORE_X_EVENT_MODE_UNGRAB) return ECORE_CALLBACK_PASS_ON; _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE); return ECORE_CALLBACK_PASS_ON; @@ -1433,7 +1459,7 @@ _ecore_evas_x_event_window_focus_out(void *data EINA_UNUSED, int type EINA_UNUSE ee = ecore_event_window_match(e->win); if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */ if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON; -//xx// filtering with these doesnt help +//xx// filtering with these doesnt help //xx// if (e->mode == ECORE_X_EVENT_MODE_GRAB) return ECORE_CALLBACK_PASS_ON; // if (ee->prop.fullscreen) @@ -1534,6 +1560,8 @@ _ecore_evas_x_shadow_update(Ecore_Evas *ee) ECORE_X_ATOM_CARDINAL, 32, shadow, 4); } +static void _ecore_evas_x_size_pos_hints_update(Ecore_Evas *ee); + static Eina_Bool _ecore_evas_x_event_window_configure(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { @@ -1568,7 +1596,7 @@ _ecore_evas_x_event_window_configure(void *data EINA_UNUSED, int type EINA_UNUSE } if (edata->direct_resize) return ECORE_CALLBACK_PASS_ON; - pointer = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_MOUSE); + pointer = evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_MOUSE); pointer = evas_device_parent_get(pointer); cursor = eina_hash_find(ee->prop.cursors, &pointer); EINA_SAFETY_ON_NULL_RETURN_VAL(cursor, ECORE_CALLBACK_PASS_ON); @@ -1672,6 +1700,8 @@ _ecore_evas_x_event_window_configure(void *data EINA_UNUSED, int type EINA_UNUSE } } } + if (framespace_resized) + _ecore_evas_x_size_pos_hints_update(ee); } return ECORE_CALLBACK_PASS_ON; } @@ -1763,15 +1793,19 @@ _ecore_evas_x_event_window_hide(void *data EINA_UNUSED, int type EINA_UNUSED, vo static void _ecore_evas_x_size_pos_hints_update(Ecore_Evas *ee) { + int fw, fh; + + fw = ee->framespace.w; + fh = ee->framespace.h; ecore_x_icccm_size_pos_hints_set(ee->prop.window, ee->prop.request_pos /*request_pos */, ECORE_X_GRAVITY_NW /* gravity */, - ee->prop.min.w /* min_w */, - ee->prop.min.h /* min_h */, - ee->prop.max.w /* max_w */, - ee->prop.max.h /* max_h */, - ee->prop.base.w /* base_w */, - ee->prop.base.h /* base_h */, + ee->prop.min.w + fw /* min_w */, + ee->prop.min.h + fh /* min_h */, + ee->prop.max.w + fw /* max_w */, + ee->prop.max.h + fh /* max_h */, + ee->prop.base.w + fw /* base_w */, + ee->prop.base.h + fh /* base_h */, ee->prop.step.w /* step_x */, ee->prop.step.h /* step_y */, ee->prop.aspect /* min_aspect */, @@ -1962,6 +1996,7 @@ _ecore_evas_x_init(void) ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE, _ecore_evas_x_event_window_create, NULL); ecore_event_evas_init(); + _ecore_evas_x_selection_init(); return _ecore_evas_init_count; } @@ -1989,6 +2024,7 @@ _ecore_evas_x_free(Ecore_Evas *ee) { Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; + ecore_job_del(edata->init_job); if (edata->pixmap.back) ecore_x_pixmap_free(edata->pixmap.back); if (edata->pixmap.front) @@ -2137,7 +2173,7 @@ _ecore_evas_x_resize(Ecore_Evas *ee, int w, int h) } /* check for valid property window - * + * * NB: If we do not have one, check for valid pixmap rendering */ if (!ee->prop.window) { @@ -2145,7 +2181,7 @@ _ecore_evas_x_resize(Ecore_Evas *ee, int w, int h) if ((edata->pixmap.w != vw) || (edata->pixmap.h != vh)) { /* free the backing pixmap */ - if (edata->pixmap.back) + if (edata->pixmap.back) ecore_x_pixmap_free(edata->pixmap.back); } } @@ -2294,7 +2330,7 @@ _ecore_evas_x_rotation_set_internal(Ecore_Evas *ee, int rotation, int resize, Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; int fw = 0, fh = 0; - pointer = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_MOUSE); + pointer = evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_MOUSE); pointer = evas_device_parent_get(pointer); cursor = eina_hash_find(ee->prop.cursors, &pointer); EINA_SAFETY_ON_NULL_RETURN(cursor); @@ -2688,6 +2724,7 @@ _alpha_do(Ecore_Evas *ee, int alpha) _ecore_evas_x_aux_hints_supported_update(ee); _ecore_evas_x_aux_hints_update(ee); _ecore_evas_x_size_pos_hints_update(ee); + _ecore_evas_x_selection_window_init(ee); #endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */ if ((id = getenv("DESKTOP_STARTUP_ID"))) { @@ -2842,6 +2879,7 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha) _ecore_evas_x_aux_hints_supported_update(ee); _ecore_evas_x_aux_hints_update(ee); _ecore_evas_x_size_pos_hints_update(ee); + _ecore_evas_x_selection_window_init(ee); #endif /* BUILD_ECORE_EVAS_OPENGL_X11 */ if ((id = getenv("DESKTOP_STARTUP_ID"))) { @@ -2910,7 +2948,7 @@ _ecore_evas_x_aspect_set(Ecore_Evas *ee, double aspect) ee->prop.aspect = aspect; _ecore_evas_x_size_pos_hints_update(ee); -// netwm state +// netwm state // if (ee->should_be_visible) // ecore_x_netwm_state_request_send(ee->prop.window, ee->engine.x.win_root, // ECORE_X_WINDOW_STATE_STICKY, -1, sticky); @@ -3265,20 +3303,21 @@ _ecore_evas_x_maximized_set(Ecore_Evas *ee, Eina_Bool on) { Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; - if (ee->prop.maximized == on) return; - ee->prop.maximized = 1; - edata->state.maximized_h = 1; - edata->state.maximized_v = 1; -// ee->prop.maximized = on; if (ee->should_be_visible) { ecore_x_netwm_state_request_send(ee->prop.window, edata->win_root, - ECORE_X_WINDOW_STATE_MAXIMIZED_VERT, -1, on); - ecore_x_netwm_state_request_send(ee->prop.window, edata->win_root, - ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ, -1, on); + ECORE_X_WINDOW_STATE_MAXIMIZED_VERT, + ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ, + on); } else - _ecore_evas_x_state_update(ee); + { + if (ee->prop.maximized == on) return; + ee->prop.maximized = on; + edata->state.maximized_h = on; + edata->state.maximized_v = on; + _ecore_evas_x_state_update(ee); + } } static void @@ -3537,14 +3576,14 @@ norandr: if (!found) goto norandr; } -static void +static void _ecore_evas_x_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y) { if (ee->prop.window) ecore_x_pointer_xy_get(ee->prop.window, x, y); } -static Eina_Bool +static Eina_Bool _ecore_evas_x_pointer_warp(const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y) { return ecore_x_pointer_warp(ee->prop.window, x, y); @@ -3659,6 +3698,804 @@ _ecore_evas_x_aux_hints_set(Ecore_Evas *ee, const char *hints) (ee->prop.window, ECORE_X_ATOM_E_WINDOW_AUX_HINT); } +static Ecore_X_Atom ecore_evas_selection_to_atom[] = {0, 0, 0, 0}; +static Ecore_Event_Handler *ecore_evas_selection_handlers[8]; + +static inline Ecore_Evas_Selection_Buffer +_atom_to_selection(Ecore_X_Atom atom) +{ + for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i) + { + if (ecore_evas_selection_to_atom[i] == atom) + return i; + } + return ECORE_EVAS_SELECTION_BUFFER_LAST; +} + +static Eina_Stringshare* +_decrypt_type(const char *target) +{ + // reference https://tronche.com/gui/x/icccm/sec-2.html + if (eina_streq(target, "TEXT")) return eina_stringshare_add("text/plain"); + //FIXME no support in eina_content for that so far + if (eina_streq(target, "COMPOUND_TEXT")) return eina_stringshare_add("text/plain"); + // reference https://tronche.com/gui/x/icccm/sec-2.html + if (eina_streq(target, "STRING")) return eina_stringshare_add("text/plain;charset=iso-8859-1"); + if (eina_streq(target, "UTF8_STRING")) return eina_stringshare_add("text/plain;charset=utf-8"); + + return eina_stringshare_add(target); +} + +static Eina_Stringshare* +_mime_to_xserver_type(const char *target) +{ + // FIXME // reference https://tronche.com/gui/x/icccm/sec-2.html says it is in the owners choice of encoding, not sure what this means directly here + if (eina_streq(target, "text/plain")) return eina_stringshare_add("TEXT"); + // reference https://tronche.com/gui/x/icccm/sec-2.html + if (eina_streq(target, "text/plain;charset=iso-8859-1")) return eina_stringshare_add("STRING"); + if (eina_streq(target, "text/plain;charset=utf-8")) return eina_stringshare_add("UTF8_STRING"); + + return eina_stringshare_add(target); +} + +static inline void +_clear_selection(Ecore_Evas *ee, Ecore_Evas_Selection_Buffer selection) +{ + Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; + Ecore_Evas_Selection_Callbacks *cbs = &edata->selection_data[selection].callbacks; + + EINA_SAFETY_ON_FALSE_RETURN(cbs->cancel); + + cbs->cancel(ee, 1, selection); + eina_array_free(cbs->available_types); + + cbs->delivery = NULL; + cbs->cancel = NULL; + cbs->available_types = NULL; +} + +static void +_clear_selection_delivery(Ecore_Evas *ee, Ecore_Evas_Selection_Buffer selection) +{ + Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; + eina_stringshare_replace(&edata->selection_data[selection].requested_type, NULL); + eina_stringshare_replace(&edata->selection_data[selection].later_conversion, NULL); + edata->selection_data[selection].delivery = NULL; + eina_array_free(edata->selection_data[selection].acceptable_type); + edata->selection_data[selection].acceptable_type = NULL; +} + +static void +_ecore_x_selection_request(Ecore_X_Window win, Ecore_Evas_Selection_Buffer selection, const char *type) +{ + if (selection == ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER) + ecore_x_selection_primary_request(win, type); + else if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER) + ecore_x_selection_clipboard_request(win, type); + else + ecore_x_selection_xdnd_request(win, type); +} + +static void +_search_fitting_type(Ecore_Evas *ee, Ecore_Evas_Engine_Data_X11 *edata, Ecore_Evas_Selection_Buffer selection, Eina_Array *arr) +{ + Eina_Stringshare *mime_type; + Eina_Bool found_conversion = EINA_FALSE; + +#define HANDLE_TYPE() \ + { \ + edata->selection_data[selection].requested_type = eina_stringshare_add(x11_name); \ + edata->selection_data[selection].later_conversion = eina_stringshare_add(acceptable_type);\ + found_conversion = EINA_TRUE; \ + break; \ + } + + EINA_SAFETY_ON_NULL_RETURN(edata->selection_data[selection].acceptable_type); + + for (unsigned int i = 0; i < eina_array_count(arr) && !found_conversion; ++i) + { + const char *x11_name = eina_array_data_get(arr, i); + mime_type = _decrypt_type(x11_name); + + for (unsigned int j = 0; j < eina_array_count(edata->selection_data[selection].acceptable_type) && !found_conversion; ++j) + { + const char *acceptable_type = (const char*) eina_array_data_get(edata->selection_data[selection].acceptable_type, j); + + if (mime_type == acceptable_type) + HANDLE_TYPE() + + //if there is no available type yet, check if we can convert to the desired type via this type + if (!found_conversion) + { + const char *convertion_type = NULL; + Eina_Iterator *iter = eina_content_converter_possible_conversions(mime_type); + EINA_ITERATOR_FOREACH(iter, convertion_type) + { + if (convertion_type == acceptable_type) + HANDLE_TYPE() + } + eina_iterator_free(iter); + } + } + eina_stringshare_del(mime_type); + } + if (found_conversion) + { + _ecore_x_selection_request(ee->prop.window, selection, edata->selection_data[selection].requested_type); + } + else + { + eina_promise_resolve(edata->selection_data[selection].delivery, eina_value_error_init(ecore_evas_no_matching_type)); + _clear_selection_delivery(ee, selection); + } + +#undef HANDLE_TYPE +} + +static void +_search_fitting_type_from_event(Ecore_Evas *ee, Ecore_Evas_Engine_Data_X11 *edata, Ecore_Evas_Selection_Buffer selection, Ecore_X_Event_Selection_Notify *ev) +{ + Ecore_X_Atom *available_atoms; + Ecore_X_Selection_Data_Targets *targets; + Eina_Array *tmp = eina_array_new(10); + + targets = ev->data; + available_atoms = (Ecore_X_Atom *)targets->data.data; + for (int i = 0; i < targets->data.length; ++i) + { + Ecore_X_Atom atom = available_atoms[i]; + eina_array_push(tmp, ecore_x_atom_name_get(atom)); + } + _search_fitting_type(ee, edata, selection, tmp); + eina_array_free(tmp); +} + +static Eina_Content* +_create_delivery_content(unsigned long int size, const void *mem, const char *mime_type) +{ + Eina_Content *content; + + content = eina_content_new((Eina_Slice){.len = size, .mem = mem}, mime_type); + + return content; +} + +static void +_deliver_content(Ecore_Evas *ee, Ecore_Evas_Engine_Data_X11 *edata, Ecore_Evas_Selection_Buffer selection, Ecore_X_Event_Selection_Notify *ev) +{ + Eina_Content *result = NULL; + Eina_Stringshare *mime_type = _decrypt_type(edata->selection_data[selection].requested_type); + + EINA_SAFETY_ON_NULL_GOTO(ev->data, err); + if (eina_streq(mime_type, "text/uri-list")) + { + Ecore_X_Selection_Data_Files *files = ev->data; + Efreet_Uri *uri; + Eina_Strbuf *strbuf; + int i; + + strbuf = eina_strbuf_new(); + + for (i = 0; i < files->num_files ; i++) + { + uri = efreet_uri_decode(files->files[i]); + if (uri) + { + eina_strbuf_append(strbuf, uri->path); + efreet_uri_free(uri); + } + else + { + eina_strbuf_append(strbuf, files->files[i]); + } + if (i < (files->num_files - 1)) + eina_strbuf_append(strbuf, "\n"); + } + result = _create_delivery_content(eina_strbuf_length_get(strbuf) + 1, eina_strbuf_string_get(strbuf), mime_type); + eina_strbuf_free(strbuf); + } + else if (eina_str_has_prefix(mime_type,"text")) + { + Ecore_X_Selection_Data *x11_data = ev->data; + //ensure that we always have a \0 at the end, there is no assertion that \0 is included here. + void *null_terminated = eina_memdup(x11_data->data, x11_data->length, EINA_TRUE); + + result = _create_delivery_content(x11_data->length + 1, null_terminated, mime_type); + free(null_terminated); + } + else if (eina_str_has_prefix(mime_type,"image")) + { + Ecore_X_Selection_Data *x11_data = ev->data; + Eina_Content *tmp_container = eina_content_new((Eina_Slice){.len = x11_data->length, .mem = x11_data->data}, mime_type); + const char *file = eina_content_as_file(tmp_container); + + result = _create_delivery_content(strlen(file), file, mime_type); + eina_content_free(tmp_container); + } + else + { + Ecore_X_Selection_Data *x11_data = ev->data; + result = _create_delivery_content(x11_data->length, x11_data->data, mime_type); + } + EINA_SAFETY_ON_NULL_GOTO(result, err); + + //ensure that we deliver the correct type, we might have choosen a convertion before + if (edata->selection_data[selection].later_conversion != mime_type) + { + Eina_Content *tmp = eina_content_convert(result, edata->selection_data[selection].later_conversion); + eina_content_free(result); + result = tmp; + } + + eina_promise_resolve(edata->selection_data[selection].delivery, eina_value_content_init(result)); + eina_content_free(result); + _clear_selection_delivery(ee, selection); + + if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) + ecore_x_dnd_send_finished(); + return; +err: + eina_promise_reject(edata->selection_data[selection].delivery, ecore_evas_no_selection); + + if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) + ecore_x_dnd_send_finished(); +} + +static Eina_Bool +_ecore_evas_x_selection_notify(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Selection_Notify *ev = event; + Ecore_Evas_Selection_Buffer selection; + Ecore_Evas_Engine_Data_X11 *edata; + Ecore_Evas *ee; + + ee = ecore_event_window_match(ev->win); + selection = _atom_to_selection(ev->atom); + EINA_SAFETY_ON_FALSE_GOTO(!!ee, end); + EINA_SAFETY_ON_FALSE_GOTO(selection != ECORE_EVAS_SELECTION_BUFFER_LAST, end); + edata = ee->engine.data; + + //if dnd drops above us, and even if we did not request anything, we are getting notified, refuse to do anything + if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER && + !edata->selection_data[selection].later_conversion) + { + ecore_x_dnd_send_finished(); + } + else + { + if (eina_streq(ev->target, "TARGETS") || eina_streq(ev->target, "ATOMS")) + { + //This will decide for a type, and will sent that via _ecore_x_selection_request + EINA_SAFETY_ON_FALSE_RETURN_VAL(!edata->selection_data[selection].later_conversion, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(!edata->selection_data[selection].requested_type, EINA_FALSE); + _search_fitting_type_from_event(ee, edata, selection, ev); + } + else + { + //This will read the data, fill it into a Eina_Content apply all conversions required. + EINA_SAFETY_ON_FALSE_RETURN_VAL(edata->selection_data[selection].later_conversion, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(edata->selection_data[selection].requested_type, EINA_FALSE); + _deliver_content(ee, edata, selection, ev); + } + } +end: + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_ecore_evas_x_selection_clear(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Selection_Clear *ev = event; + Ecore_Evas_Selection_Callbacks *cbs; + Ecore_Evas_Engine_Data_X11 *edata; + Ecore_Evas_Selection_Buffer selection; + Ecore_Evas *ee; + + ee = ecore_event_window_match(ev->win); + selection = _atom_to_selection(ev->atom); + EINA_SAFETY_ON_FALSE_GOTO(ee, end); + EINA_SAFETY_ON_FALSE_GOTO(selection != ECORE_EVAS_SELECTION_BUFFER_LAST, end); + edata = ee->engine.data; + cbs = &edata->selection_data[selection].callbacks; + + //skip clean event + if (edata->skip_clean_event) + { + edata->skip_clean_event --; + goto end; + } + + if (cbs->cancel) + _clear_selection(ee, selection); +end: + return ECORE_CALLBACK_PASS_ON; +} + +static void +_force_stop_self_dnd(Ecore_Evas *ee) +{ + Ecore_Evas_Engine_Data_X11 *edata; + + EINA_SAFETY_ON_NULL_RETURN(ee); + edata = ee->engine.data; + EINA_SAFETY_ON_NULL_RETURN(edata); + + //Never clear the buffer for selection here. + //Selection buffer is freed as a response to the FINISHED event. + ecore_x_pointer_ungrab(); + ecore_x_dnd_self_drop(); + ecore_x_dnd_aware_set(ee->prop.window, EINA_FALSE); + ecore_event_handler_del(edata->mouse_up_handler); + edata->mouse_up_handler = NULL; + + if (ee->drag.free) + ee->drag.free(ee, 1, ee->drag.data, ee->drag.accepted); + ee->drag.free = NULL; +} + +static Eina_Bool +_ecore_evas_x_selection_fixes_notify(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Fixes_Selection_Notify *ev = event; + Ecore_Evas *ee; + Ecore_Evas_Selection_Buffer selection; + + ee = ecore_event_window_match(ev->win); + selection = _atom_to_selection(ev->atom); + EINA_SAFETY_ON_FALSE_GOTO(!!ee, end); + EINA_SAFETY_ON_FALSE_GOTO(selection != ECORE_EVAS_SELECTION_BUFFER_LAST, end); + + //notify that the selection has changed on this ecore evas + if (ee->func.fn_selection_changed) + ee->func.fn_selection_changed(ee, 0, selection); +end: + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_eina_content_converter(char *target, void *data, int size EINA_UNUSED, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize) +{ + Ecore_Evas_X11_Selection_Data *sdata = data; + Eina_Bool ret = EINA_FALSE;; + + if (size != sizeof(Ecore_Evas_X11_Selection_Data)) return EINA_FALSE; + + if (!EINA_MAGIC_CHECK(sdata, ECORE_EVAS_X11_SELECTION)) return EINA_FALSE; + + if (eina_streq(target, "TARGETS") || eina_streq(target, "ATOM")) + { + //list all available types that we have currently + Ecore_X_Atom *result = calloc(eina_array_count(sdata->callbacks.available_types), sizeof(Ecore_X_Atom)); + for (unsigned int i = 0; i < eina_array_count(sdata->callbacks.available_types); ++i) + { + result[i] = ecore_x_atom_get(eina_array_data_get(sdata->callbacks.available_types, i)); + } + *size_ret = eina_array_count(sdata->callbacks.available_types); + *data_ret = result; + *ttype = ECORE_X_ATOM_ATOM; + *typesize = 32; /* urk */ + ret = EINA_TRUE; + } + else + { + const char *mime_type = _decrypt_type(target); + for (unsigned int i = 0; i < eina_array_count(sdata->callbacks.available_types); ++i) + { + if (mime_type == eina_array_data_get(sdata->callbacks.available_types, i)) + { + Eina_Rw_Slice slice; + sdata->callbacks.delivery(sdata->ee, 1, sdata->buffer, mime_type, &slice); + *size_ret = slice.len; + *data_ret = slice.mem; + *ttype = ecore_x_atom_get(target); //use here target in order to get the correct atom + //FIXME in selection manager we never set here the typesize, isn't that weird ? + ret = EINA_TRUE; + // XXX: fixup for strings to not include nul byte if last + // byte is nul byte + if (((!strncmp(target, "text/", 5)) || + (!strcmp(target, "tex")) || + (!strcmp(target, "TEXT")) || + (!strcmp(target, "COMPOUND_TEXT")) || + (!strcmp(target, "STRING")) || + (!strcmp(target, "UTF8_STRING"))) && + (slice.len > 0) && (slice.bytes[slice.len - 1] == '\0')) + { + *size_ret = *size_ret - 1; + } + break; + } + } + eina_stringshare_del(mime_type); + } + + return ret; +} + +static Eina_Bool +_ecore_evas_x_dnd_enter(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Xdnd_Enter *enter = event; + Eina_Array *mime_tmp; + Ecore_Evas_Engine_Data_X11 *edata; + Ecore_Evas *ee; + + mime_tmp = eina_array_new(10); + ee = ecore_event_window_match(enter->win); + EINA_SAFETY_ON_NULL_GOTO(ee, end); + edata = ee->engine.data; + edata->xserver_atom_name_during_dnd = eina_array_new(10); + for (int i = 0; i < enter->num_types; ++i) + { + const char *mime_type = _decrypt_type(enter->types[i]); + eina_array_push(mime_tmp, mime_type); + eina_array_push(edata->xserver_atom_name_during_dnd, eina_stringshare_add(enter->types[i])); + } + ecore_evas_dnd_enter(ee, 1, eina_array_iterator_new(mime_tmp), EINA_POSITION2D(0,0)); //FIXME + +end: + eina_array_free(mime_tmp); + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_ecore_evas_x_dnd_leave(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Xdnd_Leave *leave = event; + Ecore_Evas_Engine_Data_X11 *edata; + Ecore_Evas *ee; + + ee = ecore_event_window_match(leave->win); + EINA_SAFETY_ON_NULL_GOTO(ee, end); + edata = ee->engine.data; + ecore_evas_dnd_leave(ee, 1, EINA_POSITION2D(0,0)); + for (unsigned int i = 0; i < eina_array_count(edata->xserver_atom_name_during_dnd); ++i) + { + eina_stringshare_del(eina_array_data_get(edata->xserver_atom_name_during_dnd, i)); + } + eina_array_free(edata->xserver_atom_name_during_dnd); + edata->xserver_atom_name_during_dnd = NULL; +end: + return ECORE_CALLBACK_PASS_ON; +} + +static Ecore_X_Atom +_x11_dnd_action_rev_map(const char* action) +{ + if (eina_streq(action, "copy")) return ECORE_X_ATOM_XDND_ACTION_COPY; + if (eina_streq(action, "move")) return ECORE_X_ATOM_XDND_ACTION_MOVE; + else if (eina_streq(action, "privat")) return ECORE_X_ATOM_XDND_ACTION_PRIVATE; + else if (eina_streq(action, "ask")) return ECORE_X_ATOM_XDND_ACTION_ASK; + else if (eina_streq(action, "list")) return ECORE_X_ATOM_XDND_ACTION_LIST; + else if (eina_streq(action, "link")) return ECORE_X_ATOM_XDND_ACTION_LINK; + else if (eina_streq(action, "description")) return ECORE_X_ATOM_XDND_ACTION_DESCRIPTION; + return 0; +} + +static const char* +_x11_dnd_action_map(Ecore_X_Atom action) +{ + if (action == ECORE_X_DND_ACTION_COPY) return "copy"; + if (action == ECORE_X_ATOM_XDND_ACTION_MOVE) return "move"; + if (action == ECORE_X_ATOM_XDND_ACTION_PRIVATE) return "privat"; + if (action == ECORE_X_ATOM_XDND_ACTION_ASK) return "ask"; + if (action == ECORE_X_ATOM_XDND_ACTION_LIST) return "list"; + if (action == ECORE_X_ATOM_XDND_ACTION_LINK) return "link"; + if (action == ECORE_X_ATOM_XDND_ACTION_DESCRIPTION) return "description"; + + return "unknown"; +} + +static Eina_Bool +_ecore_evas_x_dnd_position(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Xdnd_Position *pos = event; + int x, y, w, h; + Ecore_Evas *ee; + + ee = ecore_event_window_match(pos->win); + EINA_SAFETY_ON_NULL_GOTO(ee, end); + ecore_evas_geometry_get(ee, &x, &y, &w, &h); + Eina_Bool used = ecore_evas_dnd_position_set(ee, 1, EINA_POSITION2D(pos->position.x - x, pos->position.y - y)); + ecore_x_dnd_send_status(used, EINA_FALSE, (Ecore_X_Rectangle){x,y,w,h}, pos->action); +end: + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_ecore_evas_x_dnd_drop(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Xdnd_Drop *drop = event; + Ecore_Evas_Engine_Data_X11 *edata; + Ecore_Evas *ee; + + ee = ecore_event_window_match(drop->win); + EINA_SAFETY_ON_NULL_GOTO(ee, end); + edata = ee->engine.data; + if (ee->func.fn_dnd_drop) + ee->func.fn_dnd_drop(ee, 1, ecore_evas_dnd_pos_get(ee, 1), _x11_dnd_action_map(drop->action)); + if (edata->selection_data[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER].delivery && + !edata->selection_data[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER].requested_type) + { + //only abort dnd if we have something to deliver here, otherwise some other dnd implementation in our own window is handling that + ecore_x_dnd_send_finished(); + } + ecore_evas_dnd_leave(ee, 1, EINA_POSITION2D(drop->position.x ,drop->position.y)); + eina_array_free(edata->xserver_atom_name_during_dnd); + edata->xserver_atom_name_during_dnd = NULL; +end: + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_ecore_evas_x_finished(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_X_Event_Xdnd_Finished *finished = event; + Ecore_Evas *ee; + + ee = ecore_event_window_match(finished->win); + EINA_SAFETY_ON_NULL_GOTO(ee, end); + + _clear_selection(ee, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER); +end: + return ECORE_CALLBACK_PASS_ON; +} + +static void +_ecore_evas_x_selection_init(void) +{ + Ecore_X_Atom _ecore_evas_selection_to_atom[] = {ECORE_X_ATOM_SELECTION_PRIMARY, ECORE_X_ATOM_SELECTION_CLIPBOARD, ECORE_X_ATOM_SELECTION_XDND}; + + for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i) + { + ecore_evas_selection_to_atom[i] = _ecore_evas_selection_to_atom[i]; + } + + ecore_evas_selection_handlers[0] = + ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, + _ecore_evas_x_selection_notify, NULL); + ecore_evas_selection_handlers[1] = + ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, + _ecore_evas_x_selection_clear, NULL); + if (ECORE_X_EVENT_FIXES_SELECTION_NOTIFY) + ecore_evas_selection_handlers[2] = + ecore_event_handler_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY, + _ecore_evas_x_selection_fixes_notify, NULL); + + ecore_evas_selection_handlers[3] = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER, + _ecore_evas_x_dnd_enter, NULL); + ecore_evas_selection_handlers[4] = ecore_event_handler_add(ECORE_X_EVENT_XDND_LEAVE, + _ecore_evas_x_dnd_leave, NULL); + ecore_evas_selection_handlers[5] = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION, + _ecore_evas_x_dnd_position, NULL); + ecore_evas_selection_handlers[6] = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP, + _ecore_evas_x_dnd_drop, NULL); + ecore_evas_selection_handlers[7] = ecore_event_handler_add(ECORE_X_EVENT_XDND_FINISHED, + _ecore_evas_x_finished, NULL); + /* for us known type */ + char *supported_types[] = { + "text/plain", + "text/plain;charset=utf-8", + "image/png", + "image/jpeg", + "image/x-ms-bmp", + "image/gif", + "image/tiff", + "image/svg+xml", + "image/x-xpixmap", + "image/x-tga", + "image/x-portable-pixmap", + "TEXT", + "COMPOUND_TEXT", + "STRING", + "UTF8_STRING", + "text/x-vcard", + "text/uri-list", + "application/x-elementary-markup", + "ATOM", + "TARGETS", + NULL + }; + for (int i = 0; supported_types[i]; ++i) + { + ecore_x_selection_converter_add(supported_types[i], _eina_content_converter); + } +} + +static Eina_Bool +_ecore_evas_x_selection_has_owner(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection) +{ + return !!ecore_x_selection_owner_get(ecore_evas_selection_to_atom[selection]); +} + +static void +_deliver_selection_changed(void *data) +{ + Ecore_Evas *ee = data; + Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; + + if (!ee->func.fn_selection_changed) + goto end; + + if (_ecore_evas_x_selection_has_owner(ee, 1, ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER)) + ee->func.fn_selection_changed(ee, 1, ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER); + if (_ecore_evas_x_selection_has_owner(ee, 1, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)) + ee->func.fn_selection_changed(ee, 1, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER); + if (_ecore_evas_x_selection_has_owner(ee, 1, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)) + ee->func.fn_selection_changed(ee, 1, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER); +end: + edata->init_job = NULL; +} + +static void +_ecore_evas_x_selection_window_init(Ecore_Evas *ee) +{ + Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; + for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i) + { + ecore_x_fixes_window_selection_notification_request(ee->prop.window, ecore_evas_selection_to_atom[i]); + edata->selection_data[i].ee = ee; + edata->selection_data[i].buffer = i; + EINA_MAGIC_SET(&edata->selection_data[i], ECORE_EVAS_X11_SELECTION); + } + ecore_x_dnd_aware_set(ee->prop.window, EINA_TRUE); + edata->init_job = ecore_job_add(_deliver_selection_changed, ee); +} + +static void +_store_selection_cbs(Ecore_Evas *ee, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Eina_Bool (*delivery)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, const char *type, Eina_Rw_Slice *slice), void (*cancel)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer)) +{ + Ecore_Evas_X11_Selection_Data *sdata; + Ecore_Evas_Engine_Data_X11 *edata; + Ecore_Evas_Selection_Callbacks *cbs; + + edata = ee->engine.data; + sdata = &edata->selection_data[selection]; + cbs = &sdata->callbacks; + + if (cbs->cancel) + { + _clear_selection(ee, selection); + edata->skip_clean_event ++; //we are going to overwrite our own selection, this will emit a clean event, but we already freed it. + } + + cbs->delivery = delivery; + cbs->cancel = cancel; + cbs->available_types = available_types; +} + +static Eina_Bool +_ecore_evas_x_selection_claim(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Ecore_Evas_Selection_Internal_Delivery delivery, Ecore_Evas_Selection_Internal_Cancel cancel) +{ + Ecore_Evas_X11_Selection_Data *sdata; + Ecore_Evas_Engine_Data_X11 *edata; + + edata = ee->engine.data; + sdata = &edata->selection_data[selection]; + + _store_selection_cbs(ee, selection, available_types, delivery, cancel); + + if (eina_array_count(available_types) > 0) + { + //the commands below will *copy* the content of sdata, this you have to ensure that clear is called when sdata is changed. + if (selection == ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER) + ecore_x_selection_primary_set(ee->prop.window, sdata, sizeof(Ecore_Evas_X11_Selection_Data)); + else if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER) + ecore_x_selection_clipboard_set(ee->prop.window, sdata, sizeof(Ecore_Evas_X11_Selection_Data)); + } + else + { + if (selection == ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER) + ecore_x_selection_primary_clear(); + else if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER) + ecore_x_selection_clipboard_clear(); + } + + //for drag and drop, we are not calling anything in here + + return EINA_TRUE; +} + +Eina_Future* +_ecore_evas_x_selection_request(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type) +{ + Ecore_Evas_X11_Selection_Data *sdata; + Ecore_Evas_Engine_Data_X11 *edata; + Eina_Future *future; + + edata = ee->engine.data; + sdata = &edata->selection_data[selection]; + + if (sdata->delivery) + { + eina_promise_reject(sdata->delivery, ecore_evas_request_replaced); + _clear_selection_delivery(ee, selection); + } + sdata->delivery = efl_loop_promise_new(efl_main_loop_get()); + sdata->acceptable_type = acceptable_type; + future = eina_future_new(sdata->delivery); + + if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) + { + //when in dnd - we are requesting out of the set that we know from the enter event + EINA_SAFETY_ON_FALSE_RETURN_VAL(!edata->selection_data[selection].later_conversion, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(!edata->selection_data[selection].requested_type, NULL); + _search_fitting_type(ee, edata, selection, edata->xserver_atom_name_during_dnd); + } + else + { + //when not dnd - we are first wanting to know what is available + _ecore_x_selection_request(ee->prop.window, selection, ECORE_X_SELECTION_TARGET_TARGETS); + } + + return future; +} + +static void +_x11_drag_move(void *data, Ecore_X_Xdnd_Position *pos) +{ + Ecore_Evas *ee = data; + Eina_Rect rect; + + ecore_evas_geometry_get(ee->drag.rep, &rect.x, &rect.y, &rect.w, &rect.h); + + ecore_evas_move(ee->drag.rep, pos->position.x - rect.w / 2, pos->position.y - rect.h/2); +} + +static Eina_Bool +_x11_drag_mouse_up(void *data, int etype EINA_UNUSED, void *event EINA_UNUSED) +{ + Ecore_Evas *ee = data; + + _force_stop_self_dnd(ee); + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_evas_x_dnd_start(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Array *available_types, Ecore_Evas *drag_rep, Eina_Bool (*delivery)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, const char *type, Eina_Rw_Slice *slice), void (*cancel)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer), const char* action) +{ + Ecore_Evas_X11_Selection_Data *sdata; + Ecore_Evas_Engine_Data_X11 *edata; + Ecore_X_Atom actx; + + edata = ee->engine.data; + sdata = &edata->selection_data[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER]; + _store_selection_cbs(ee, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER, available_types, delivery, cancel); + + //first set all types we have + ecore_x_dnd_types_set(ee->prop.window, NULL, 0); + for (unsigned int i = 0; i < eina_array_count(available_types); ++i) + { + const char *xserver_mime_type = _mime_to_xserver_type(eina_array_data_get(available_types, i)); + ecore_x_dnd_type_set(ee->prop.window, xserver_mime_type, EINA_TRUE); + eina_stringshare_del(xserver_mime_type); + } + ecore_x_dnd_aware_set(ee->prop.window, EINA_TRUE); + ecore_x_dnd_callback_pos_update_set(_x11_drag_move, ee); + ecore_x_dnd_self_begin(ee->prop.window, (unsigned char*)sdata, sizeof(Ecore_Evas_X11_Selection_Data)); + actx = _x11_dnd_action_rev_map(action); + ecore_x_dnd_source_action_set(actx); + ecore_x_pointer_grab(ee->prop.window); + + ecore_x_window_ignore_set(drag_rep->prop.window, EINA_TRUE); + + if (edata->mouse_up_handler) + ecore_event_handler_del(edata->mouse_up_handler); + edata->mouse_up_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, + _x11_drag_mouse_up, ee); + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_evas_x_dnd_stop(Ecore_Evas *ee, unsigned int seat EINA_UNUSED) +{ + _force_stop_self_dnd(ee); + _clear_selection(ee, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER); + ecore_x_selection_xdnd_clear(); //This is needed otherwise a outdated sdata struct will be accessed + return EINA_TRUE; +} + static Ecore_Evas_Engine_Func _ecore_x_engine_func = { _ecore_evas_x_free, @@ -3746,6 +4583,11 @@ static Ecore_Evas_Engine_Func _ecore_x_engine_func = NULL, //fn_pointer_device_xy_get NULL, //fn_prepare NULL, //fn_last_tick_get + _ecore_evas_x_selection_claim, //fn_selection_claim + _ecore_evas_x_selection_has_owner, //fn_selection_has_owner + _ecore_evas_x_selection_request, //fn_selection_request + _ecore_evas_x_dnd_start, //fn_dnd_start + _ecore_evas_x_dnd_stop, //fn_dnd_stop }; /* @@ -3764,19 +4606,19 @@ _ecore_evas_x_render_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_ /* printf("\tPixman Size: %d %d\n", edata->pixmap.w, edata->pixmap.h); */ /* printf("\tEE Size: %d %d\n", ee->w, ee->h); */ - /* before rendering to the back buffer pixmap, we should check the - * size. If the back buffer is not the proper size, destroy it and + /* before rendering to the back buffer pixmap, we should check the + * size. If the back buffer is not the proper size, destroy it and * create a new one at the proper size */ if ((edata->pixmap.w != ee->w) || (edata->pixmap.h != ee->h)) { int fw = 0, fh = 0; /* free the backing pixmap */ - if (edata->pixmap.back) + if (edata->pixmap.back) ecore_x_pixmap_free(edata->pixmap.back); - edata->pixmap.back = - ecore_x_pixmap_new(edata->win_root, ee->w, ee->h, + edata->pixmap.back = + ecore_x_pixmap_new(edata->win_root, ee->w, ee->h, edata->pixmap.depth); evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh); @@ -3795,7 +4637,7 @@ _ecore_evas_x_render_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_ if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) { - ERR("evas_engine_info_set() init engine '%s' failed.", + ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver); } } @@ -3813,7 +4655,7 @@ _ecore_evas_x_render_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_ if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) { - ERR("evas_engine_info_set() init engine '%s' failed.", + ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver); } } @@ -3836,8 +4678,8 @@ _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_ /* printf("\tBack Pixmap: %d\n", edata->pixmap.back); */ /* printf("\tFront Pixmap: %d\n", edata->pixmap.front); */ - /* done drawing to the back buffer. flip it to the front so that - * any calls to "fetch pixmap" will return the front buffer already + /* done drawing to the back buffer. flip it to the front so that + * any calls to "fetch pixmap" will return the front buffer already * pre-rendered */ /* record the current front buffer */ @@ -3862,7 +4704,7 @@ _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_ if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) { - ERR("evas_engine_info_set() init engine '%s' failed.", + ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver); } } @@ -3880,7 +4722,7 @@ _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_ if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) { - ERR("evas_engine_info_set() init engine '%s' failed.", + ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver); } } @@ -4109,6 +4951,7 @@ ecore_evas_software_x11_new_internal(const char *disp_name, Ecore_X_Window paren _ecore_evas_x_wm_rotation_protocol_set(ee); _ecore_evas_x_aux_hints_supported_update(ee); _ecore_evas_x_aux_hints_update(ee); + _ecore_evas_x_selection_window_init(ee); ee->engine.func->fn_render = _ecore_evas_x_render; ee->draw_block = EINA_TRUE; @@ -4299,9 +5142,9 @@ ecore_evas_software_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Windo edata->pixmap.colormap = einfo->info.colormap; /* create front and back pixmaps for double-buffer rendering */ - edata->pixmap.front = + edata->pixmap.front = ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth); - edata->pixmap.back = + edata->pixmap.back = ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth); einfo->info.drawable = edata->pixmap.back; @@ -4314,7 +5157,7 @@ ecore_evas_software_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Windo } } - /* FIXME: Allow of these set properties or do something with the + /* FIXME: Allow of these set properties or do something with the * ee->prop.window (x window), which we do not have in pixmap case */ /* _ecore_evas_x_hints_update(ee); */ @@ -4362,7 +5205,7 @@ _ecore_evas_software_x11_pixmap_visual_get(const Ecore_Evas *ee) return edata->pixmap.visual; } -static unsigned long +static unsigned long _ecore_evas_software_x11_pixmap_colormap_get(const Ecore_Evas *ee) { if (!(!strcmp(ee->driver, "software_x11"))) return 0; @@ -4370,7 +5213,7 @@ _ecore_evas_software_x11_pixmap_colormap_get(const Ecore_Evas *ee) return edata->pixmap.colormap; } -static int +static int _ecore_evas_software_x11_pixmap_depth_get(const Ecore_Evas *ee) { if (!(!strcmp(ee->driver, "software_x11"))) return 0; @@ -4545,6 +5388,7 @@ ecore_evas_gl_x11_options_new_internal(const char *disp_name, Ecore_X_Window par _ecore_evas_x_wm_rotation_protocol_set(ee); _ecore_evas_x_aux_hints_supported_update(ee); _ecore_evas_x_aux_hints_update(ee); + _ecore_evas_x_selection_window_init(ee); ee->draw_block = 1; if (!wm_exists) edata->configured = 1; @@ -4711,9 +5555,9 @@ ecore_evas_gl_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Window pare edata->pixmap.colormap = einfo->info.colormap; /* create front and back pixmaps for double-buffer rendering */ - edata->pixmap.front = + edata->pixmap.front = ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth); - edata->pixmap.back = + edata->pixmap.back = ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth); einfo->info.drawable = edata->pixmap.back; @@ -4771,7 +5615,7 @@ _ecore_evas_gl_x11_pixmap_visual_get(const Ecore_Evas *ee) return edata->pixmap.visual; } -static unsigned long +static unsigned long _ecore_evas_gl_x11_pixmap_colormap_get(const Ecore_Evas *ee) { if (!(!strcmp(ee->driver, "opengl_x11"))) return 0; @@ -4779,7 +5623,7 @@ _ecore_evas_gl_x11_pixmap_colormap_get(const Ecore_Evas *ee) return edata->pixmap.colormap; } -static int +static int _ecore_evas_gl_x11_pixmap_depth_get(const Ecore_Evas *ee) { if (!(!strcmp(ee->driver, "opengl_x11"))) return 0; diff --git a/src/modules/ecore_evas/engines/x/meson.build b/src/modules/ecore_evas/engines/x/meson.build index 582a782115..1108f9c755 100644 --- a/src/modules/ecore_evas/engines/x/meson.build +++ b/src/modules/ecore_evas/engines/x/meson.build @@ -14,7 +14,7 @@ endif shared_module(mod_full_name, engine_src, include_directories : config_dir + [engine_include_dir], - dependencies : [eina, ecore_evas, ecore_input_evas] + engine_deps, + dependencies : [eina, ecore_evas, ecore_input_evas, efreet] + engine_deps, install : true, install_dir : mod_install_dir, name_suffix : sys_mod_extension diff --git a/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.c b/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.c index 636026f4b1..85110d4d7f 100644 --- a/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.c +++ b/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.c @@ -1,4 +1,8 @@ -#include <linux/input-event-codes.h> +#if defined(__linux__) + #include <linux/input-event-codes.h> +#elif defined(__FreeBSD__) + #include <dev/evdev/input-event-codes.h> +#endif #include <rfb/keysym.h> #include <stdlib.h> #include <limits.h> |