#ifdef HAVE_CONFIG_H # include #endif #import #import "ecore_cocoa_window.h" #import "ecore_cocoa_app.h" #include #include #include #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]; }