ecore_cocoa: NSRunLoop integration

Summary: Get rid of the old NSApplicationLoad() which was aimed to be use with Carbon. Unless the NSRunLoop is strictly integrated to the ecore_main_loop() (where cocoa events would be checked when entering the ecore_main_loop) I think the poller is the only option left.

Reviewers: raster, naguirre, raoulh, stefan_schmidt, cedric

@feature

Subscribers: cedric

Differential Revision: https://phab.enlightenment.org/D1222

Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
Jean Guyomarc'h 2014-09-03 20:34:52 +02:00 committed by Cedric BAIL
parent 8f40c291ca
commit c03876d611
7 changed files with 195 additions and 57 deletions

View File

@ -12,6 +12,8 @@ lib/ecore_cocoa/Ecore_Cocoa_Keys.h
lib_ecore_cocoa_libecore_cocoa_la_SOURCES = \
lib/ecore_cocoa/ecore_cocoa.m \
lib/ecore_cocoa/ecore_cocoa_window.m \
lib/ecore_cocoa/ecore_cocoa_app.m \
lib/ecore_cocoa/ecore_cocoa_app.h \
lib/ecore_cocoa/ecore_cocoa_private.h
lib_ecore_cocoa_libecore_cocoa_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_COCOA_CFLAGS@

View File

@ -25,6 +25,8 @@
# define EAPI
#endif
#include <Eina.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -53,7 +55,7 @@ struct _Ecore_Cocoa_Screen
EAPI int ecore_cocoa_init(void);
EAPI int ecore_cocoa_shutdown(void);
EAPI void ecore_cocoa_feed_events(void);
EAPI Eina_Bool ecore_cocoa_feed_events(void *anEvent);
/* Screen */

View File

@ -4,6 +4,7 @@
#import <Cocoa/Cocoa.h>
#import "ecore_cocoa_window.h"
#import "ecore_cocoa_app.h"
#include <Eina.h>
@ -30,16 +31,24 @@ ecore_cocoa_init(void)
if (++_ecore_cocoa_init_count != 1)
return _ecore_cocoa_init_count;
if (!ecore_event_init())
if (!ecore_init())
return --_ecore_cocoa_init_count;
NSApplicationLoad();
if (!ecore_event_init())
return --_ecore_cocoa_init_count;
ECORE_COCOA_EVENT_GOT_FOCUS = ecore_event_type_new();
ECORE_COCOA_EVENT_LOST_FOCUS = ecore_event_type_new();
ECORE_COCOA_EVENT_RESIZE = ecore_event_type_new();
ECORE_COCOA_EVENT_EXPOSE = ecore_event_type_new();
/* Init the Application handler */
[Ecore_Cocoa_Application sharedApplication];
[NSApp setDelegate:[Ecore_Cocoa_AppDelegate appDelegate]];
/* Start events monitoring */
[NSApp run];
return _ecore_cocoa_init_count;
}
@ -89,21 +98,16 @@ _has_ecore_cocoa_window(NSEvent *event)
return _nsevent_window_is_type_of(event, [EcoreCocoaWindow class]);
}
EAPI void
ecore_cocoa_feed_events(void)
EAPI Eina_Bool
ecore_cocoa_feed_events(void *anEvent)
{
Ecore_Event *ev;
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0.001];
NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:date
inMode:NSDefaultRunLoopMode
dequeue:YES];
[date release];
if (!event) return; // SDL loops until null; maybe we should do that too. or not.
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;
switch([event type])
switch ([event type])
{
case NSMouseMoved:
case NSLeftMouseDragged:
@ -113,7 +117,7 @@ ecore_cocoa_feed_events(void)
if (_has_ecore_cocoa_window(event))
{
Ecore_Event_Mouse_Move * ev = calloc(1, sizeof(Ecore_Event_Mouse_Move));
if (!ev) return;
if (!ev) return pass;
EcoreCocoaWindow *window = (EcoreCocoaWindow *)[event window];
NSView *view = [window contentView];
@ -124,7 +128,7 @@ ecore_cocoa_feed_events(void)
ev->root.x = ev->x;
ev->root.y = ev->y;
ev->timestamp = time;
ev->window = window.ecore_window_data;
ev->window = (Ecore_Window)window.ecore_window_data;
ev->event_window = ev->window;
ev->modifiers = 0; /* FIXME: keep modifier around. */
@ -135,7 +139,7 @@ ecore_cocoa_feed_events(void)
// We might want to handle cases such as events on the menubar.
// If so, let's do it here.
}
[NSApp sendEvent:event]; // pass along mouse events, for window manager
pass = EINA_TRUE;
break;
}
case NSLeftMouseDown:
@ -145,7 +149,7 @@ ecore_cocoa_feed_events(void)
if (_has_ecore_cocoa_window(event))
{
Ecore_Event_Mouse_Button * ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
if (!ev) return;
if (!ev) return pass;
EcoreCocoaWindow *window = (EcoreCocoaWindow *)[event window];
NSView *view = [window contentView];
@ -163,7 +167,7 @@ ecore_cocoa_feed_events(void)
case 2: ev->buttons = 2; break;
default: ev->buttons = 0; break;
}
ev->window = window.ecore_window_data;
ev->window = (Ecore_Window)window.ecore_window_data;
ev->event_window = ev->window;
if ([event clickCount] == 2)
@ -183,7 +187,7 @@ ecore_cocoa_feed_events(void)
// We might want to handle cases such as events on the menubar.
// If so, let's do it here.
}
[NSApp sendEvent:event]; // pass along mouse events, for window manager
pass = EINA_TRUE;
break;
}
case NSLeftMouseUp:
@ -191,7 +195,7 @@ ecore_cocoa_feed_events(void)
case NSOtherMouseUp:
{
Ecore_Event_Mouse_Button * ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
if (!ev) return;
if (!ev) return pass;
if (_has_ecore_cocoa_window(event))
{
@ -211,7 +215,7 @@ ecore_cocoa_feed_events(void)
case 2: ev->buttons = 2; break;
default: ev->buttons = 0; break;
}
ev->window = window.ecore_window_data;
ev->window = (Ecore_Window)window.ecore_window_data;
ev->event_window = ev->window;
if ([event clickCount] == 2)
@ -231,7 +235,7 @@ ecore_cocoa_feed_events(void)
// We might want to handle cases such as events on the menubar.
// If so, let's do it here.
}
[NSApp sendEvent:event]; // pass along mouse events, for window manager
pass = EINA_TRUE;
break;
}
case NSKeyDown:
@ -241,7 +245,7 @@ ecore_cocoa_feed_events(void)
EcoreCocoaWindow *window = (EcoreCocoaWindow *)[event window];
ev = calloc(1, sizeof (Ecore_Event_Key));
if (!ev) return;
if (!ev) return pass;
ev->timestamp = time;
ev->modifiers = _ecore_cocoa_event_modifiers([event modifierFlags]);
@ -253,10 +257,10 @@ ecore_cocoa_feed_events(void)
ev->keyname = keystable[i].name;
ev->key = keystable[i].name;
ev->string = keystable[i].compose;
ev->window = window.ecore_window_data;
ev->window = (Ecore_Window)window.ecore_window_data;
ev->event_window = ev->window;
ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
return;
return pass;
}
}
@ -271,7 +275,7 @@ ecore_cocoa_feed_events(void)
printf("Key Up\n");
ev = calloc(1, sizeof (Ecore_Event_Key));
if (!ev) return;
if (!ev) return pass;
ev->timestamp = time;
ev->modifiers = _ecore_cocoa_event_modifiers([event modifierFlags]);
@ -282,10 +286,10 @@ ecore_cocoa_feed_events(void)
ev->keyname = keystable[i].name;
ev->key = keystable[i].name;
ev->string = keystable[i].compose;
ev->window = window.ecore_window_data;
ev->window = (Ecore_Window)window.ecore_window_data;
ev->event_window = ev->window;
ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
return;
return pass;
}
}
@ -299,13 +303,13 @@ ecore_cocoa_feed_events(void)
Ecore_Event_Key *evUp = NULL;
evDown = calloc(1, sizeof (Ecore_Event_Key));
if (!evDown) return;
if (!evDown) return pass;
evUp = calloc(1, sizeof (Ecore_Event_Key));
if (!evUp)
{
free(evDown);
return;
return pass;
}
// Turn special key flags on
@ -360,7 +364,7 @@ ecore_cocoa_feed_events(void)
ecore_event_add(ECORE_COCOA_EVENT_GOT_FOCUS, NULL, NULL, NULL);
else if ([event subtype] == NSApplicationDeactivatedEventType)
ecore_event_add(ECORE_COCOA_EVENT_LOST_FOCUS, NULL, NULL, NULL);
[NSApp sendEvent:event]; // pass along AppKit events, for window manager
pass = EINA_TRUE; // pass along AppKit events, for window manager
break;
}
case NSScrollWheel:
@ -370,12 +374,12 @@ ecore_cocoa_feed_events(void)
}
default:
{
[NSApp sendEvent:event];
pass = EINA_TRUE;
break;
}
}
[event release];
return pass;
}
EAPI void

View File

@ -0,0 +1,28 @@
#import <Cocoa/Cocoa.h>
#include "Ecore_Cocoa.h"
#include <Ecore.h>
@interface Ecore_Cocoa_Application : NSApplication
{
Ecore_Poller *_poller;
NSDate *_expiration;
}
- (NSDate *)eventExpirationDate;
+ (Ecore_Cocoa_Application *)sharedApplication;
- (void)run;
- (void)sendEvent:(NSEvent *)anEvent;
- (id)init;
- (void)internalUpdate;
@end
@interface Ecore_Cocoa_AppDelegate : NSObject <NSApplicationDelegate>
+ (Ecore_Cocoa_AppDelegate *)appDelegate;
- (id)init;
@end

View File

@ -0,0 +1,125 @@
#import "ecore_cocoa_app.h"
static Eina_Bool
_ecore_cocoa_run_loop_cb(void *data EINA_UNUSED)
{
@autoreleasepool {
@try {
NSEvent *e;
do {
e = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSApp eventExpirationDate]
inMode:NSDefaultRunLoopMode
dequeue:YES];
if (e != nil) {
//NSLog(@"Catching event %@", e);
[NSApp sendEvent:e];
/* Update (en/disable) the services menu's items */
NSEventType type = [e type];
if (type != NSPeriodic && type != NSMouseMoved) {
[NSApp internalUpdate];
}
}
} while (e != nil);
}
@catch (NSException *except) {
NSLog(@"EXCEPTION: %@: %@", [except name], [except reason]);
/* Show the "fancy" annoying report panel */
[NSApp reportException:except];
// XXX Maybe use Eina_Log to report the error instead
}
}
return ECORE_CALLBACK_RENEW;
}
@implementation Ecore_Cocoa_Application
+ (Ecore_Cocoa_Application *)sharedApplication
{
return (Ecore_Cocoa_Application *)[super sharedApplication];
}
- (void)internalUpdate
{
[_mainMenu update];
// FIXME Will not compile with GNUStep (member is named "_main_menu")
}
- (id)init
{
self = [super init];
if (self == nil) {
// XXX Critical error. Abort right now! Log?
return nil;
}
NSApp = self; // NSApp is used EVERYWHERE! Set it right now!
return NSApp;
}
- (NSDate *)eventExpirationDate
{
return _expiration;
}
- (void)run
{
[self finishLaunching];
_running = 1;
_expiration = [NSDate distantPast];
_poller = ecore_poller_add(ECORE_POLLER_CORE,
ecore_poller_poll_interval_get(ECORE_POLLER_CORE),
_ecore_cocoa_run_loop_cb, NULL);
if (_poller == NULL) {
// XXX ERROR
}
}
- (void)sendEvent:(NSEvent *)anEvent
{
Eina_Bool to_super;
/* Some events shall be handled by Ecore (like single non-command keys).
* If we dispatch all events right to NSApplication, it will complain
* with NSBeep() when an event is not authorized */
to_super = ecore_cocoa_feed_events(anEvent);
if (to_super)
[super sendEvent:anEvent];
}
@end
static Ecore_Cocoa_AppDelegate *_appDelegate = nil;
@implementation Ecore_Cocoa_AppDelegate
+ (Ecore_Cocoa_AppDelegate *)appDelegate
{
if (_appDelegate == nil) {
_appDelegate = [[self alloc] init];
}
return _appDelegate;
}
- (id)init
{
self = [super init];
return self;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
// XXX This should be alterable (by Elm_Window policy)
return YES;
}
@end

View File

@ -65,7 +65,6 @@
event->w = size.width;
event->h = size.height -
(([self isFullScreen] == YES) ? 0 : ecore_cocoa_titlebar_height_get());
printf("Is fullscreen: %i\n", [self isFullScreen]);
ecore_event_add(ECORE_COCOA_EVENT_RESIZE, event, NULL, NULL);
}

View File

@ -22,7 +22,6 @@ static Ecore_Event_Handler *ecore_evas_event_handlers[4] = {
NULL, NULL, NULL, NULL
};
static Ecore_Idle_Enterer *ecore_evas_idle_enterer = NULL;
static Ecore_Poller *ecore_evas_event = NULL;
//static const char *ecore_evas_cocoa_default = "EFL Cocoa";
@ -198,17 +197,6 @@ _ecore_evas_cocoa_event_video_expose(void *data EINA_UNUSED, int type EINA_UNUSE
// return EINA_TRUE;
//}
static Eina_Bool
_ecore_evas_cocoa_event(void *data EINA_UNUSED)
{
//Ecore_Evas *ee = data;
DBG("Cocoa Event");
ecore_cocoa_feed_events();
return ECORE_CALLBACK_PASS_ON;
}
static int
_ecore_evas_cocoa_init(void)
@ -246,8 +234,6 @@ _ecore_evas_cocoa_shutdown(void)
ecore_event_evas_shutdown();
ecore_idle_enterer_del(ecore_evas_idle_enterer);
ecore_evas_idle_enterer = NULL;
ecore_poller_del(ecore_evas_event);
ecore_evas_event = NULL;
ecore_event_evas_shutdown();
}
@ -529,14 +515,6 @@ ecore_evas_cocoa_new_internal(Ecore_Cocoa_Window *parent EINA_UNUSED, int x, int
ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_cocoa_engine_func;
/* this is pretty bad: poller? and set poll time? pol time is meant to be
* adjustable for things like polling battery state, or amoutn of spare
* memory etc. I know it's bad but cedric did it for ecore_evas_sdl
* so why not me ? BTW why 0.006s ?
*/
ecore_evas_event = ecore_poller_add(ECORE_POLLER_CORE, 1, _ecore_evas_cocoa_event, ee);
ecore_poller_poll_interval_set(ECORE_POLLER_CORE, 0.006);
if (w < 1) w = 1;
if (h < 1) h = 1;
ee->visible = 1;