ecore_cocoa: add support for system cursors 68/82868/2
authorJean Guyomarc'h <jean.guyomarch@openwide.fr>
Thu, 8 Oct 2015 09:58:46 +0000 (11:58 +0200)
committerHermet Park <chuneon.park@samsung.com>
Mon, 8 Aug 2016 08:14:21 +0000 (01:14 -0700)
- Ecore_Cocoa_Cursor enum which references system cursors;
- API to show/hide cursor: ecore_cocoa_window_cursor_show();
- API to set system cursor: ecore_cocoa_window_cursor_set();
- Ecore_Evas interface to get Ecore_Cocoa_Window from Ecore_Evas.

@feature

Change-Id: Iadef3d4bbffd5c92fa2c8d040393f7a9160c8ac4
Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
src/Makefile_Ecore_Cocoa.am
src/Makefile_Ecore_Evas.am
src/lib/ecore_cocoa/Ecore_Cocoa.h
src/lib/ecore_cocoa/Ecore_Cocoa_Cursor.h [new file with mode: 0644]
src/lib/ecore_cocoa/ecore_cocoa.m
src/lib/ecore_cocoa/ecore_cocoa_private.h
src/lib/ecore_cocoa/ecore_cocoa_window.m
src/lib/ecore_evas/Ecore_Evas.h
src/lib/ecore_evas/ecore_evas.c
src/lib/ecore_evas/ecore_evas_cocoa.h [new file with mode: 0644]
src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c

index 3321b25..a158767 100644 (file)
@@ -7,6 +7,7 @@ lib_LTLIBRARIES += lib/ecore_cocoa/libecore_cocoa.la
 installed_ecorecocoamainheadersdir = $(includedir)/ecore-cocoa-@VMAJ@
 dist_installed_ecorecocoamainheaders_DATA = \
 lib/ecore_cocoa/Ecore_Cocoa.h \
+lib/ecore_cocoa/Ecore_Cocoa_Cursor.h \
 lib/ecore_cocoa/Ecore_Cocoa_Keys.h
 
 lib_ecore_cocoa_libecore_cocoa_la_SOURCES = \
index a1c50a8..f43b667 100755 (executable)
@@ -20,6 +20,7 @@ lib/ecore_evas/ecore_evas_private.h \
 lib/ecore_evas/ecore_evas_extn.h \
 lib/ecore_evas/ecore_evas_extn.c \
 lib/ecore_evas/ecore_evas_wayland.h \
+lib/ecore_evas/ecore_evas_cocoa.h \
 lib/ecore_evas/ecore_evas_win32.h \
 lib/ecore_evas/ecore_evas_x11.h \
 lib/ecore_evas/ecore_evas_util.c
index 78d15ce..4341389 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include <Eina.h>
+#include "Ecore_Cocoa_Cursor.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -165,6 +166,10 @@ EAPI int ecore_cocoa_titlebar_height_get(void);
 
 EAPI Ecore_Cocoa_Window_Id ecore_cocoa_window_get_window_id(Ecore_Cocoa_Window *window);
 
+
+EAPI void ecore_cocoa_window_cursor_set(Ecore_Cocoa_Window *win, Ecore_Cocoa_Cursor c);
+EAPI void ecore_cocoa_window_cursor_show(Ecore_Cocoa_Window *win, Eina_Bool show);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/lib/ecore_cocoa/Ecore_Cocoa_Cursor.h b/src/lib/ecore_cocoa/Ecore_Cocoa_Cursor.h
new file mode 100644 (file)
index 0000000..6bca47f
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __ECORE_COCOA_CURSOR_H__
+#define __ECORE_COCOA_CURSOR_H__
+
+typedef enum
+{
+   ECORE_COCOA_CURSOR_ARROW                     = 0,
+   ECORE_COCOA_CURSOR_CONTEXTUAL_MENU,
+   ECORE_COCOA_CURSOR_CLOSED_HAND,
+   ECORE_COCOA_CURSOR_CROSSHAIR,
+   ECORE_COCOA_CURSOR_DISAPPEARING_ITEM,
+   ECORE_COCOA_CURSOR_DRAG_COPY,
+   ECORE_COCOA_CURSOR_DRAG_LINK,
+   ECORE_COCOA_CURSOR_IBEAM,
+   ECORE_COCOA_CURSOR_OPEN_HAND,
+   ECORE_COCOA_CURSOR_OPERATION_NOT_ALLOWED,
+   ECORE_COCOA_CURSOR_POINTING_HAND,
+   ECORE_COCOA_CURSOR_RESIZE_DOWN,
+   ECORE_COCOA_CURSOR_RESIZE_LEFT,
+   ECORE_COCOA_CURSOR_RESIZE_LEFT_RIGHT,
+   ECORE_COCOA_CURSOR_RESIZE_RIGHT,
+   ECORE_COCOA_CURSOR_RESIZE_UP,
+   ECORE_COCOA_CURSOR_RESIZE_UP_DOWN,
+   ECORE_COCOA_CURSOR_IBEAM_VERTICAL,
+
+   __ECORE_COCOA_CURSOR_LAST, /* Sentinel */
+
+   ECORE_COCOA_CURSOR_DEFAULT = ECORE_COCOA_CURSOR_ARROW
+
+} Ecore_Cocoa_Cursor;
+
+#endif /* ! __ECORE_COCOA_CURSOR_H__ */
+
index 979d557..aae3c02 100644 (file)
@@ -61,6 +61,9 @@ ecore_cocoa_init(void)
    /* Start events monitoring */
    [NSApp run];
 
+   if (!_ecore_cocoa_window_init())
+     return --_ecore_cocoa_init_count;
+
    return _ecore_cocoa_init_count;
 }
 
index ffe48ab..9952278 100644 (file)
@@ -62,4 +62,8 @@ struct _Ecore_Cocoa_Window
 };
 
 
+/* Internal init */
+Eina_Bool _ecore_cocoa_window_init(void);
+
+
 #endif
index 53137a0..de905c5 100644 (file)
@@ -6,9 +6,13 @@
 
 #include <Ecore.h>
 #include <Ecore_Cocoa.h>
+#include <Ecore_Cocoa_Cursor.h>
 #import "ecore_cocoa_window.h"
 #include "ecore_cocoa_private.h"
 
+static NSCursor *_cursors[__ECORE_COCOA_CURSOR_LAST];
+
+
 @implementation EcoreCocoaWindow
 
 @synthesize ecore_window_data;
@@ -501,3 +505,52 @@ Ecore_Cocoa_Window_Id ecore_cocoa_window_get_window_id(Ecore_Cocoa_Window *windo
 
   return window->window;
 }
+
+EAPI void
+ecore_cocoa_window_cursor_set(Ecore_Cocoa_Window *win,
+                              Ecore_Cocoa_Cursor  c)
+{
+   EINA_SAFETY_ON_NULL_RETURN(win);
+   EINA_SAFETY_ON_FALSE_RETURN((c >= 0) && (c <= __ECORE_COCOA_CURSOR_LAST));
+
+   NSCursor *cursor = _cursors[c];
+
+   DBG("Setting cursor %i (%s)", c, [[cursor description] UTF8String]);
+   [cursor set];
+}
+
+EAPI void
+ecore_cocoa_window_cursor_show(Ecore_Cocoa_Window *win,
+                               Eina_Bool           show)
+{
+   EINA_SAFETY_ON_NULL_RETURN(win);
+
+   if (show) [NSCursor unhide];
+   else [NSCursor hide];
+}
+
+Eina_Bool
+_ecore_cocoa_window_init(void)
+{
+   _cursors[ECORE_COCOA_CURSOR_ARROW]                 = [NSCursor arrowCursor];
+   _cursors[ECORE_COCOA_CURSOR_CONTEXTUAL_MENU]       = [NSCursor contextualMenuCursor];
+   _cursors[ECORE_COCOA_CURSOR_CLOSED_HAND]           = [NSCursor closedHandCursor];
+   _cursors[ECORE_COCOA_CURSOR_CROSSHAIR]             = [NSCursor crosshairCursor];
+   _cursors[ECORE_COCOA_CURSOR_DISAPPEARING_ITEM]     = [NSCursor disappearingItemCursor];
+   _cursors[ECORE_COCOA_CURSOR_DRAG_COPY]             = [NSCursor dragCopyCursor];
+   _cursors[ECORE_COCOA_CURSOR_DRAG_LINK]             = [NSCursor dragLinkCursor];
+   _cursors[ECORE_COCOA_CURSOR_IBEAM]                 = [NSCursor IBeamCursor];
+   _cursors[ECORE_COCOA_CURSOR_OPEN_HAND]             = [NSCursor openHandCursor];
+   _cursors[ECORE_COCOA_CURSOR_OPERATION_NOT_ALLOWED] = [NSCursor operationNotAllowedCursor];
+   _cursors[ECORE_COCOA_CURSOR_POINTING_HAND]         = [NSCursor pointingHandCursor];
+   _cursors[ECORE_COCOA_CURSOR_RESIZE_DOWN]           = [NSCursor resizeDownCursor];
+   _cursors[ECORE_COCOA_CURSOR_RESIZE_LEFT]           = [NSCursor resizeLeftCursor];
+   _cursors[ECORE_COCOA_CURSOR_RESIZE_LEFT_RIGHT]     = [NSCursor resizeLeftRightCursor];
+   _cursors[ECORE_COCOA_CURSOR_RESIZE_RIGHT]          = [NSCursor resizeRightCursor];
+   _cursors[ECORE_COCOA_CURSOR_RESIZE_UP]             = [NSCursor resizeUpCursor];
+   _cursors[ECORE_COCOA_CURSOR_RESIZE_UP_DOWN]        = [NSCursor resizeUpDownCursor];
+   _cursors[ECORE_COCOA_CURSOR_IBEAM_VERTICAL]        = [NSCursor IBeamCursorForVerticalLayout];
+
+   return EINA_TRUE;
+}
+
index f960147..92ea827 100755 (executable)
@@ -1378,6 +1378,8 @@ EAPI void            ecore_evas_wayland_pointer_set(Ecore_Evas *ee, int hot_x, i
 EAPI void            ecore_evas_wayland_type_set(Ecore_Evas *ee, int type);
 EAPI Ecore_Wl_Window *ecore_evas_wayland_window_get(const Ecore_Evas *ee);
 
+EAPI Ecore_Cocoa_Window *ecore_evas_cocoa_window_get(const Ecore_Evas *ee);
+
 EAPI Ecore_Evas     *ecore_evas_drm_new(const char *device, unsigned int parent, int x, int y, int w, int h);
 EAPI Ecore_Evas     *ecore_evas_gl_drm_new(const char *device, unsigned int parent, int x, int y, int w, int h); /** @since 1.12 */
 
index c5721b8..237bc57 100755 (executable)
@@ -30,6 +30,7 @@
 #include "ecore_evas_private.h"
 #include "ecore_evas_x11.h"
 #include "ecore_evas_wayland.h"
+#include "ecore_evas_cocoa.h"
 #include "ecore_evas_extn.h"
 #include "ecore_evas_win32.h"
 
@@ -4277,6 +4278,15 @@ ecore_evas_wayland_window_get(const Ecore_Evas *ee)
    return iface->window_get(ee);
 }
 
+EAPI Ecore_Cocoa_Window *
+ecore_evas_cocoa_window_get(const Ecore_Evas *ee)
+{
+   Ecore_Evas_Interface_Cocoa *iface;
+   iface = (Ecore_Evas_Interface_Cocoa *)_ecore_evas_interface_get(ee, "opengl_cocoa");
+   EINA_SAFETY_ON_NULL_RETURN_VAL(iface, NULL);
+   return iface->window_get(ee);
+}
+
 EAPI Ecore_Evas *
 ecore_evas_drm_new(const char *disp_name, unsigned int parent,
                    int x, int y, int w, int h)
diff --git a/src/lib/ecore_evas/ecore_evas_cocoa.h b/src/lib/ecore_evas/ecore_evas_cocoa.h
new file mode 100644 (file)
index 0000000..edc8e05
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __ECORE_EVAS_COCOA_H__
+#define __ECORE_EVAS_COCOA_H__
+
+typedef struct _Ecore_Evas_Interface_Cocoa Ecore_Evas_Interface_Cocoa;
+
+struct _Ecore_Evas_Interface_Cocoa
+{
+   Ecore_Evas_Interface base;
+
+   Ecore_Cocoa_Window *(*window_get)(const Ecore_Evas *ee);
+};
+
+#endif /* ! __ECORE_EVAS_COCOA_H__ */
+
index 22c8fb6..da296fd 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "Ecore_Evas.h"
 #include "ecore_evas_private.h"
+#include "ecore_evas_cocoa.h"
 
 #ifdef EAPI
 # undef EAPI
@@ -44,6 +45,9 @@ static Eina_List                *ecore_evases = NULL;
 static Ecore_Event_Handler      *ecore_evas_event_handlers[5] = { 0 };
 static Ecore_Idle_Enterer       *ecore_evas_idle_enterer = NULL;
 
+static const char *_iface_name = "opengl_cocoa";
+static const int _iface_version = 1;
+
 static int
 _render_updates_process(Ecore_Evas *ee, Eina_List *updates)
 {
@@ -528,16 +532,19 @@ static void
 _ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
 {
    int x, y;
+   Evas_Object *old;
+   Ecore_Cocoa_Window *win = (Ecore_Cocoa_Window *)(ee->prop.window);
    DBG("");
-   if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
 
+   old = ee->prop.cursor.object;
    if (obj == NULL)
      {
         ee->prop.cursor.object = NULL;
         ee->prop.cursor.layer = 0;
         ee->prop.cursor.hot.x = 0;
         ee->prop.cursor.hot.y = 0;
-        return;
+        ecore_cocoa_window_cursor_show(win, EINA_TRUE);
+        goto end;
      }
 
    ee->prop.cursor.object = obj;
@@ -546,17 +553,27 @@ _ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int h
    ee->prop.cursor.hot.y = hot_y;
 
    evas_pointer_output_xy_get(ee->evas, &x, &y);
-   evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
+   if (obj != old)
+     {
+        ecore_cocoa_window_cursor_show(win, EINA_FALSE);
+        evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
+        evas_object_pass_events_set(ee->prop.cursor.object, 1);
+        if (evas_pointer_inside_get(ee->evas))
+          evas_object_show(ee->prop.cursor.object);
+        evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
+                                       _ecore_evas_object_cursor_del, ee);
+     }
    evas_object_move(ee->prop.cursor.object,
                     x - ee->prop.cursor.hot.x,
                     y - ee->prop.cursor.hot.y);
 
-   evas_object_pass_events_set(ee->prop.cursor.object, 1);
-
-   if (evas_pointer_inside_get(ee->evas))
-     evas_object_show(ee->prop.cursor.object);
-
-   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
+end:
+   if ((old) && (obj != old))
+     {
+        evas_object_event_callback_del_full(old, EVAS_CALLBACK_DEL,
+                                            _ecore_evas_object_cursor_del, ee);
+        evas_object_del(old);
+     }
 }
 
 static void
@@ -688,10 +705,19 @@ static Ecore_Evas_Engine_Func _ecore_cocoa_engine_func =
     NULL  // msg_send
   };
 
+static Ecore_Cocoa_Window *
+_ecore_evas_cocoa_window_get(const Ecore_Evas *ee)
+{
+   /* See affectation of ee->prop.window in ecore_evas_cocoa_new_internal */
+   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_Interface_Cocoa *iface;
 
    if (!ecore_cocoa_init())
      return NULL;
@@ -755,6 +781,18 @@ ecore_evas_cocoa_new_internal(Ecore_Cocoa_Window *parent EINA_UNUSED, int x, int
         return NULL;
      }
 
+   /* Interface setup */
+   iface = calloc(1, sizeof(*iface));
+   if (EINA_UNLIKELY(!iface))
+     {
+        _ecore_evas_cocoa_shutdown();
+        free(ee);
+        return NULL;
+     }
+   iface->base.name = _iface_name;
+   iface->base.version = _iface_version;
+   iface->window_get = _ecore_evas_cocoa_window_get;
+   ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface);
 
    ee->engine.func->fn_render = _ecore_evas_cocoa_render;
    _ecore_evas_register(ee);