efl/src/lib/ecore_cocoa/ecore_cocoa.m

430 lines
12 KiB
Objective-C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#import <Cocoa/Cocoa.h>
#import "ecore_cocoa_window.h"
#import "ecore_cocoa_app.h"
#include <Eina.h>
#include <Ecore.h>
#include <Ecore_Input.h>
#include "Ecore_Cocoa.h"
#define _ECORE_COCOA_KEYS_MANUAL_GUARD_
#include "ecore_cocoa_keys.h"
#undef _ECORE_COCOA_KEYS_MANUAL_GUARD_
#include "ecore_cocoa_private.h"
EAPI int ECORE_COCOA_EVENT_WINDOW_UNFOCUSED = 0;
EAPI int ECORE_COCOA_EVENT_WINDOW_FOCUSED = 0;
EAPI int ECORE_COCOA_EVENT_WINDOW_RESIZE_REQUEST = 0;
EAPI int ECORE_COCOA_EVENT_WINDOW_DESTROY = 0;
static int _ecore_cocoa_init_count = 0;
static int old_flags;
int _ecore_cocoa_log_domain = -1;
EAPI int
ecore_cocoa_init(void)
{
if (++_ecore_cocoa_init_count != 1)
return _ecore_cocoa_init_count;
if (!ecore_init())
return --_ecore_cocoa_init_count;
if (!ecore_event_init())
return --_ecore_cocoa_init_count;
_ecore_cocoa_log_domain = eina_log_domain_register("ecore_cocoa", EINA_COLOR_BLUE);
if(_ecore_cocoa_log_domain < 0)
{
EINA_LOG_ERR("Unable to create a log domain for ecore_cocoa.");
return 0;
}
DBG("");
ECORE_COCOA_EVENT_WINDOW_UNFOCUSED = ecore_event_type_new();
ECORE_COCOA_EVENT_WINDOW_FOCUSED = ecore_event_type_new();
ECORE_COCOA_EVENT_WINDOW_RESIZE_REQUEST = ecore_event_type_new();
ECORE_COCOA_EVENT_WINDOW_DESTROY = ecore_event_type_new();
/* Init the Application handler */
[Ecore_Cocoa_Application sharedApplication];
[NSApp setDelegate:[Ecore_Cocoa_AppDelegate appDelegate]];
/* Start events monitoring */
[NSApp run];
if (!_ecore_cocoa_window_init())
return --_ecore_cocoa_init_count;
return _ecore_cocoa_init_count;
}
/**
* Shuts down the Ecore_Cocoa library.
* @return @c The number of times the system has been initialised without
* being shut down.
* @ingroup Ecore_Cocoa_Library_Group
*/
EAPI int
ecore_cocoa_shutdown(void)
{
if (--_ecore_cocoa_init_count != 0)
return _ecore_cocoa_init_count;
DBG("Ecore Cocoa shutdown");
ecore_event_type_flush(ECORE_COCOA_EVENT_WINDOW_UNFOCUSED,
ECORE_COCOA_EVENT_WINDOW_FOCUSED,
ECORE_COCOA_EVENT_WINDOW_RESIZE_REQUEST,
ECORE_COCOA_EVENT_WINDOW_DESTROY);
eina_log_domain_unregister(_ecore_cocoa_log_domain);
ecore_event_shutdown();
ecore_shutdown();
return _ecore_cocoa_init_count;
}
unsigned int
ecore_cocoa_event_modifiers(NSUInteger mod)
{
unsigned int modifiers = 0;
if (mod & NSEventModifierFlagShift) modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
if (mod & NSEventModifierFlagControl) modifiers |= ECORE_EVENT_MODIFIER_CTRL;
if (mod & NSEventModifierFlagOption) modifiers |= ECORE_EVENT_MODIFIER_ALTGR;
if (mod & NSEventModifierFlagCommand) modifiers |= ECORE_EVENT_MODIFIER_WIN;
if (mod & NSEventModifierFlagNumericPad) modifiers |= ECORE_EVENT_LOCK_NUM;
if (mod & NSEventModifierFlagCapsLock) modifiers |= ECORE_EVENT_LOCK_CAPS;
DBG("key modifiers: 0x%lx, %u", mod, modifiers);
return modifiers;
}
static Ecore_Event_Key*
_ecore_cocoa_event_key(NSEvent *event,
NSEventType keyType,
unsigned int time)
{
static Eina_Bool compose = EINA_FALSE;
static NSText *edit;
unsigned int i;
int kchar = -1;
Ecore_Event_Key *ev;
EcoreCocoaWindow *window = (EcoreCocoaWindow *)[event window];
NSString *keychar = [event charactersIgnoringModifiers];
NSString *keycharRaw = [event characters];
DBG("Event Key, keyType : %lu", keyType);
ev = calloc(1, sizeof(*ev));
if (EINA_UNLIKELY(!ev)) return NULL;
if (compose && (keyType == NSEventTypeKeyDown))
{
[edit interpretKeyEvents:[NSArray arrayWithObject:event]];
compose = EINA_FALSE;
}
ev->timestamp = time;
ev->modifiers = ecore_cocoa_event_modifiers([event modifierFlags]);
ev->keycode = event.keyCode;
ev->string = [keycharRaw cStringUsingEncoding:NSUTF8StringEncoding];
ev->compose = ev->string;
ev->window = (Ecore_Window)window.ecore_window_data;
ev->event_window = ev->window;
/*
* Try to look for the keychar data if available.
* If not, try the raw keychar.
*/
if ([keychar length] > 0)
kchar = [keychar characterAtIndex: 0];
if ((kchar < 0) && ([keycharRaw length] > 0))
kchar = [keycharRaw characterAtIndex: 0];
if (kchar >= 0)
{
for (i = 0; i < EINA_C_ARRAY_LENGTH(keystable); ++i)
{
if (keystable[i].code == kchar)
{
ev->keyname = keystable[i].name;
ev->key = ev->keyname;
break;
}
}
}
/* Fallback */
if (!ev->keyname)
{
ev->keyname = "";
ev->key = "";
}
if (([keycharRaw length] == 0) && (keyType == NSEventTypeKeyDown))
{
compose = EINA_TRUE;
edit = [[event window] fieldEditor:YES forObject:nil];
[edit interpretKeyEvents:[NSArray arrayWithObject:event]];
free(ev);
return NULL;
}
return ev;
}
Eina_Bool
_ecore_cocoa_feed_events(void *anEvent)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(anEvent, EINA_FALSE);
NSEvent *event = anEvent;
unsigned int time = (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff);
Eina_Bool pass = EINA_FALSE;
DBG("Feed events, event type ; %lx", [event type]);
switch ([event type])
{
case NSEventTypeMouseMoved:
case NSEventTypeLeftMouseDragged:
case NSEventTypeRightMouseDragged:
case NSEventTypeOtherMouseDragged:
case NSEventTypeLeftMouseDown:
case NSEventTypeRightMouseDown:
case NSEventTypeOtherMouseDown:
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseUp:
case NSEventTypeOtherMouseUp:
{
//mouse events are managed in EcoreCocoaWindow
return EINA_TRUE;
}
case NSEventTypeKeyDown:
{
Ecore_Event_Key *ev;
NSUInteger flags = [event modifierFlags];
if (flags & NSEventModifierFlagCommand)
{
NSString *keychar = [event charactersIgnoringModifiers];
if ([keychar characterAtIndex:0] == 'q')
{
[NSApp performSelector:@selector(terminate:)
withObject:nil afterDelay:0.0];
return EINA_TRUE;
}
}
ev = _ecore_cocoa_event_key(event, NSEventTypeKeyDown, time);
if (ev == NULL) return EINA_TRUE;
ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
break;
}
case NSEventTypeKeyUp:
{
Ecore_Event_Key *ev;
ev = _ecore_cocoa_event_key(event, NSEventTypeKeyUp, time);
if (ev == NULL) return EINA_TRUE;
ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
break;
}
case NSEventTypeFlagsChanged:
{
NSUInteger flags = [event modifierFlags];
EcoreCocoaWindow *window = (EcoreCocoaWindow *)[event window];
Ecore_Event_Key *evDown = NULL;
Ecore_Event_Key *evUp = NULL;
const char *key = NULL;
int keylen;
// Turn special key flags on
if (flags & NSEventModifierFlagShift)
key = "Shift_L";
else if (flags & NSEventModifierFlagControl)
key = "Control_L";
else if (flags & NSEventModifierFlagOption)
key = "Alt_L";
else if (flags & NSEventModifierFlagCommand)
key = "Super_L";
else if (flags & NSEventModifierFlagCapsLock)
key = "Caps_Lock";
else if (flags & NSEventModifierFlagNumericPad)
key = "Num_Lock";
if (key)
{
keylen = strlen(key);
evDown = calloc(1, sizeof (Ecore_Event_Key) + (keylen * 2) + 2);
if (!evDown) return pass;
evDown->keyname = (char *)(evDown + 1);
evDown->key = evDown->keyname + keylen + 1;
strcpy((char *) evDown->keyname, key);
strcpy((char *) evDown->key, key);
evDown->window = (Ecore_Window)window.ecore_window_data;
evDown->event_window = evDown->window;
evDown->timestamp = time;
evDown->string = NULL;
ecore_event_add(ECORE_EVENT_KEY_DOWN, evDown, NULL, NULL);
old_flags = flags;
break;
}
key = NULL;
NSUInteger changed_flags = flags ^ old_flags;
// Turn special key flags off
if (changed_flags & NSEventModifierFlagShift)
key = "Shift_L";
else if (changed_flags & NSEventModifierFlagControl)
key = "Control_L";
else if (changed_flags & NSEventModifierFlagOption)
key = "Alt_L";
else if (changed_flags & NSEventModifierFlagCommand)
key = "Super_L";
else if (changed_flags & NSEventModifierFlagCapsLock)
key = "Caps_Lock";
else if (changed_flags & NSEventModifierFlagNumericPad)
key = "Num_Lock";
if (key)
{
keylen = strlen(key);
evUp = calloc(1, sizeof (Ecore_Event_Key) + (keylen * 2) + 2);
if (!evUp) return pass;
evUp->keyname = (char *)(evUp + 1);
evUp->key = evUp->keyname + keylen + 1;
strcpy((char *) evUp->keyname, key);
strcpy((char *) evUp->key, key);
evUp->window = (Ecore_Window)window.ecore_window_data;
evUp->event_window = evUp->window;
evUp->timestamp = time;
evUp->string = NULL;
ecore_event_add(ECORE_EVENT_KEY_UP, evUp, NULL, NULL);
old_flags = flags;
break;
}
break;
}
case NSEventTypeScrollWheel:
{
DBG("Scroll Wheel");
EcoreCocoaWindow *window = (EcoreCocoaWindow *)[event window];
Ecore_Event_Mouse_Wheel *ev;
float dx, dy = 0;
ev = calloc(1, sizeof(Ecore_Event_Mouse_Wheel));
if (!ev) return pass;
if ([event hasPreciseScrollingDeltas])
{
dx = -[event scrollingDeltaX];
dy = -[event scrollingDeltaY];
}
else
{
dx = -[event deltaX];
dy = -[event deltaY];
}
if (dx == 0 && dy == 0)
{
break;
}
ev->window = (Ecore_Window)window.ecore_window_data;
ev->event_window = ev->window;
ev->modifiers = ecore_cocoa_event_modifiers([event modifierFlags]);
ev->timestamp = time;
if (dy != 0)
{
ev->z = (dy > 0) ? 1 : -1;
}
else
{
ev->z = (dx > 0) ? 1 : -1;
}
ev->direction = (dy != 0) ? 0 : 1;
ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
break;
}
default:
{
pass = EINA_TRUE;
break;
}
}
return pass;
}
EAPI void
ecore_cocoa_screen_size_get(Ecore_Cocoa_Screen *screen EINA_UNUSED, int *w, int *h)
{
NSSize pt = [[[NSScreen screens] objectAtIndex:0] frame].size;
if (w) *w = (int)pt.width;
if (h) *h = (int)pt.height;
DBG("Screen size get : %dx%d", (int)pt.width, (int)pt.height);
}
EAPI int
ecore_cocoa_titlebar_height_get(void)
{
static int height = -1;
if (height == -1)
{
NSRect frame = NSMakeRect(0, 0, 100, 100);
NSRect contentRect;
contentRect = [NSWindow contentRectForFrameRect:frame
styleMask:NSWindowStyleMaskTitled];
height = (frame.size.height - contentRect.size.height);
DBG("Titlebar Heigt : %d", height);
}
return height;
}
EAPI void
ecore_cocoa_terminate_cb_set(Ecore_Cocoa_Terminate_Cb cb)
{
EINA_SAFETY_ON_NULL_RETURN(cb);
[NSApp setTerminateCb: cb];
}