2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
9 #ifdef BUILD_ECORE_EVAS_QUARTZ
10 #import <Cocoa/Cocoa.h>
14 #include "ecore_private.h"
15 #include "Ecore_Input.h"
16 #include "Ecore_Input_Evas.h"
18 #include "ecore_evas_private.h"
19 #include "Ecore_Evas.h"
21 #ifdef BUILD_ECORE_EVAS_QUARTZ
22 #include "Ecore_Quartz.h"
23 #include "Evas_Engine_Quartz.h"
25 // FIXME: this engine has lots of problems. only 1 window at a time, drawRect looks wrong, doesnt handle resizes and more
27 static int _ecore_evas_init_count = 0;
28 static Ecore_Evas *ecore_evases = NULL;
29 static Ecore_Event_Handler *ecore_evas_event_handlers[4] = {
30 NULL, NULL, NULL, NULL
32 static Ecore_Idle_Enterer *ecore_evas_idle_enterer = NULL;
33 static Ecore_Poller *ecore_evas_event = NULL;
35 static const char *ecore_evas_quartz_default = "EFL Quartz";
37 @interface EvasView : NSView
43 static EvasView * evas_view;
44 static NSWindow * main_window;
46 @implementation EvasView
58 - (void)drawRect:(NSRect)rect
64 EINA_INLIST_FOREACH(ecore_evases, ee)
67 evas_damage_rectangle_add(ee->evas, 0, 0, 400, 400);
72 ctx = [[NSGraphicsContext currentContext] graphicsPort];
76 - (CGContextRef)context
84 _ecore_evas_quartz_match(void)
90 _ecore_evas_quartz_event_got_focus(void *data __UNUSED__, int type __UNUSED__, void *event)
94 ee = _ecore_evas_quartz_match();
103 _ecore_evas_quartz_event_lost_focus(void *data __UNUSED__, int type __UNUSED__, void *event)
107 ee = _ecore_evas_quartz_match();
110 ee->prop.focused = 0;
116 _ecore_evas_quartz_event_video_resize(void *data __UNUSED__, int type __UNUSED__, void *event)
118 /*Ecore_Quartz_Event_Video_Resize *e;
122 ee = _ecore_evas_quartz_match();
124 if (!ee) return 1; // pass on event
125 evas_output_size_set(ee->evas, e->w, e->h);
131 _ecore_evas_quartz_event_video_expose(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
137 ee = _ecore_evas_quartz_match();
140 evas_output_size_get(ee->evas, &w, &h);
141 evas_damage_rectangle_add(ee->evas, 0, 0, w, h);
147 _ecore_evas_idle_enter(void *data __UNUSED__)
153 EINA_INLIST_FOREACH(ecore_evases, ee)
156 evas_render(ee->evas);
158 evas_norender(ee->evas);
165 _ecore_evas_quartz_event(void *data)
167 ecore_quartz_feed_events();
173 _ecore_evas_quartz_init(int w, int h)
175 _ecore_evas_init_count++;
176 if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
178 ecore_event_evas_init();
180 ecore_evas_idle_enterer = ecore_idle_enterer_add(_ecore_evas_idle_enter, NULL);
181 ecore_evas_event = ecore_poller_add(ECORE_POLLER_CORE, 1, ecore_evas_event, NULL);
182 ecore_poller_poll_interval_set(ECORE_POLLER_CORE, 0.006);
184 ecore_evas_event_handlers[0] = ecore_event_handler_add(ECORE_QUARTZ_EVENT_GOT_FOCUS, _ecore_evas_quartz_event_got_focus, NULL);
185 ecore_evas_event_handlers[1] = ecore_event_handler_add(ECORE_QUARTZ_EVENT_LOST_FOCUS, _ecore_evas_quartz_event_lost_focus, NULL);
186 ecore_evas_event_handlers[2] = ecore_event_handler_add(ECORE_QUARTZ_EVENT_RESIZE, _ecore_evas_quartz_event_video_resize, NULL);
187 ecore_evas_event_handlers[3] = ecore_event_handler_add(ECORE_QUARTZ_EVENT_EXPOSE, _ecore_evas_quartz_event_video_expose, NULL);
189 return _ecore_evas_init_count;
193 _ecore_evas_quartz_shutdown(void)
195 _ecore_evas_init_count--;
196 if (_ecore_evas_init_count == 0)
200 while (ecore_evases) _ecore_evas_free(ecore_evases);
202 for (i = 0; i < sizeof (ecore_evas_event_handlers) / sizeof (Ecore_Event_Handler*); i++)
203 ecore_event_handler_del(ecore_evas_event_handlers[i]);
204 ecore_event_evas_shutdown();
205 ecore_idle_enterer_del(ecore_evas_idle_enterer);
206 ecore_evas_idle_enterer = NULL;
207 ecore_poller_del(ecore_evas_event);
208 ecore_evas_event = NULL;
210 ecore_event_evas_shutdown();
212 if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
213 return _ecore_evas_init_count;
217 _ecore_evas_quartz_free(Ecore_Evas *ee)
219 ecore_evases = (Ecore_Evas *) eina_inlist_remove(EINA_INLIST_GET(ecore_evases), EINA_INLIST_GET(ee));
220 ecore_event_window_unregister(0);
221 _ecore_evas_quartz_shutdown();
222 ecore_quartz_shutdown();
226 _ecore_evas_resize(Ecore_Evas *ee, int w, int h)
228 if ((w == ee->w) && (h == ee->h)) return;
232 evas_output_size_set(ee->evas, ee->w, ee->h);
233 evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
234 evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
236 if (ee->func.fn_resize) ee->func.fn_resize(ee);
240 _ecore_evas_move_resize(Ecore_Evas *ee, int x __UNUSED__, int y __UNUSED__, int w, int h)
242 if ((w == ee->w) && (h == ee->h)) return;
246 evas_output_size_set(ee->evas, ee->w, ee->h);
247 evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
248 evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
250 if (ee->func.fn_resize) ee->func.fn_resize(ee);
254 _ecore_evas_object_cursor_del(void *data, Evas *e, Evas_Object *obj, void *event_info)
260 ee->prop.cursor.object = NULL;
264 _ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
268 if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
272 ee->prop.cursor.object = NULL;
273 ee->prop.cursor.layer = 0;
274 ee->prop.cursor.hot.x = 0;
275 ee->prop.cursor.hot.y = 0;
279 ee->prop.cursor.object = obj;
280 ee->prop.cursor.layer = layer;
281 ee->prop.cursor.hot.x = hot_x;
282 ee->prop.cursor.hot.y = hot_y;
284 evas_pointer_output_xy_get(ee->evas, &x, &y);
285 evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
286 evas_object_move(ee->prop.cursor.object,
287 x - ee->prop.cursor.hot.x,
288 y - ee->prop.cursor.hot.y);
290 evas_object_pass_events_set(ee->prop.cursor.object, 1);
292 if (evas_pointer_inside_get(ee->evas))
293 evas_object_show(ee->prop.cursor.object);
295 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
298 static Ecore_Evas_Engine_Func _ecore_quartz_engine_func =
300 _ecore_evas_quartz_free,
318 _ecore_evas_move_resize,
332 _ecore_evas_object_cursor_set,
350 ecore_evas_quartz_new(const char* name, int w, int h)
352 #ifdef BUILD_ECORE_EVAS_QUARTZ
353 Evas_Engine_Info_Quartz *einfo;
358 name = ecore_evas_quartz_default;
360 rmethod = evas_render_method_lookup("quartz");
361 if (!rmethod) return NULL;
363 if (!ecore_quartz_init(name)) return NULL;
365 ee = calloc(1, sizeof(Ecore_Evas));
367 goto shutdown_ecore_quartz;
369 ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
371 _ecore_evas_quartz_init(w, h);
373 ecore_event_window_register(0, ee, ee->evas, _ecore_evas_mouse_move_process);
375 ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_quartz_engine_func;
377 ee->driver = "quartz";
378 if (name) ee->name = strdup(name);
391 ee->prop.focused = 1;
392 ee->prop.borderless = 1;
393 ee->prop.override = 1;
394 ee->prop.maximized = 1;
395 ee->prop.withdrawn = 0;
399 ee->evas = evas_new();
402 evas_data_attach_set(ee->evas, ee);
403 evas_output_method_set(ee->evas, rmethod);
405 // Set up the Cocoa runtime
406 [[NSAutoreleasePool alloc] init];
407 [NSApplication sharedApplication];
409 // Register ourselves as a full-fledged Cocoa app, instead of a NSUIElement.
410 // This gives benefits like window focus and a dock icon!
411 ProcessSerialNumber psn = { 0, kCurrentProcess };
412 TransformProcessType (&psn, kProcessTransformToForegroundApplication);
414 [NSApp finishLaunching];
416 // Create our main window, and embed an EvasView in it
417 main_window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,w,h) styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask) backing:NSBackingStoreBuffered defer:NO screen:nil];
418 /* FIXME: manage the case where main_window is NULL witht a goto free_evas; */
419 [main_window makeKeyAndOrderFront:NSApp];
420 [main_window setTitle:[NSString stringWithUTF8String:name]];
421 [main_window makeMainWindow];
422 [main_window setAcceptsMouseMovedEvents:YES];
423 [NSApp activateIgnoringOtherApps:YES];
425 evas_view = [[EvasView alloc] initWithFrame:NSMakeRect(0,0,w,h)];
426 [[main_window contentView] addSubview:evas_view];
428 // drawRect: must be run at least once, to make sure we've set ctx
431 evas_output_size_set(ee->evas, w, h);
432 evas_output_viewport_set(ee->evas, 0, 0, w, h);
434 einfo = (Evas_Engine_Info_Quartz*) evas_engine_info_get(ee->evas);
438 einfo->info.context = [[evas_view context] retain];
439 evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
441 ecore_evases = (Ecore_Evas *) eina_inlist_prepend(EINA_INLIST_GET(ecore_evases), EINA_INLIST_GET(ee));
443 evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
444 evas_focus_in(ee->evas);
449 /* FIXME: free window here */
455 _ecore_evas_quartz_shutdown();
457 shutdown_ecore_quartz:
458 ecore_quartz_shutdown();
462 ERR("OUTCH name='%s' size=%dx%d!", name ? name : "", w, h);