summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2020-02-14 14:10:44 +0100
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2020-03-08 10:59:46 +0100
commitc731cf56d5d242441d029907ea749ada6eb32ed6 (patch)
tree7593beb3c4b72a65f6c0f9fa9e97f0449039452c
parent06b793351274db94149a3199211d26e9a3e1fee2 (diff)
downloadefl-c731cf56d5d242441d029907ea749ada6eb32ed6.tar.gz
ecore_evas: Introduce cnp support for cocoa
with this commit you can do limited cnp for cocoa. You still cannot copy and paste pictures or markup arround, only text is supported so far. However, text on its own works quite stable and good. Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Differential Revision: https://phab.enlightenment.org/D11351
-rw-r--r--src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c137
1 files changed, 136 insertions, 1 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..3352efb135 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,125 @@ _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_Internal_Delivery delivery, Ecore_Evas_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;
+ Eina_Rw_Slice slice;
+
+ data = ecore_cocoa_clipboard_get(&size, mime_type);
+ if (!strncmp(mime_type, "text", strlen("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);
+ }
+ else
+ {
+ slice.len = size;
+ slice.mem = data;
+ }
+ content = eina_content_new(eina_rw_slice_slice_get(slice), mime_type);
+ 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 +632,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 +646,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 +661,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 +739,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();