]> git.tdb.fi Git - libs/gui.git/blob - source/graphics/cocoa/cocoadisplay.m
Fix application activation on OS X <10.6
[libs/gui.git] / source / graphics / cocoa / cocoadisplay.m
1 #include <stdlib.h>
2 #include <string.h>
3 #import <AppKit/NSApplication.h>
4 #import <AppKit/NSEvent.h>
5 #import <Foundation/NSAutoReleasePool.h>
6 #import <Foundation/NSRunLoop.h>
7 #import <ApplicationServices/ApplicationServices.h>
8 #include "cocoadisplay.h"
9
10 void convert_event(NSEvent *, CocoaEvent *);
11
12 struct _CocoaDisplay
13 {
14         NSApplication *app;
15         NSAutoreleasePool *arp;
16         CFMutableArrayRef event_queue;
17 };
18
19 void make_foreground_app(NSApplication *);
20 const void *copy_event(CFAllocatorRef, const void *);
21 void free_event(CFAllocatorRef, const void *);
22
23 CocoaDisplay *create_display()
24 {
25         CocoaDisplay *display = (CocoaDisplay *)malloc(sizeof(CocoaDisplay));
26         display->arp = [[NSAutoreleasePool alloc] init];
27         display->app = [NSApplication sharedApplication];
28         make_foreground_app(display->app);
29         [display->app finishLaunching];
30
31         CFArrayCallBacks callbacks;
32         callbacks.version = 0;
33         callbacks.retain = copy_event;
34         callbacks.release = free_event;
35         callbacks.copyDescription = NULL;
36         callbacks.equal = NULL;
37         display->event_queue = CFArrayCreateMutable(NULL, 0, &callbacks);
38
39         return display;
40 }
41
42 void make_foreground_app(NSApplication *app)
43 {
44 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
45         // This makes windows appear when run from terminal
46         if([app respondsToSelector:@selector(setActivationPolicy:)])
47         {
48                 [app setActivationPolicy:NSApplicationActivationPolicyRegular];
49                 return;
50         }
51 #else
52         (void)app;
53 #endif
54
55         ProcessSerialNumber psn = { 0, kCurrentProcess };
56         TransformProcessType(&psn, kProcessTransformToForegroundApplication);
57         SetFrontProcess(&psn);
58 }
59
60 void destroy_display(CocoaDisplay *display)
61 {
62         CFRelease(display->event_queue);
63         [display->arp release];
64         free(display);
65 }
66
67 void queue_event(CocoaDisplay *display, CocoaEvent *event)
68 {
69         CFArrayAppendValue(display->event_queue, event);
70 }
71
72 bool get_event(CocoaDisplay *display, CocoaEvent *buf)
73 {
74         if(CFArrayGetCount(display->event_queue))
75         {
76                 *buf = *(const CocoaEvent *)CFArrayGetValueAtIndex(display->event_queue, 0);
77                 CFArrayRemoveValueAtIndex(display->event_queue, 0);
78                 return true;
79         }
80
81         NSEvent *event = [display->app nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES];
82         if(event)
83         {
84                 [event retain];
85                 [display->app sendEvent:event];
86                 convert_event(event, buf);
87                 [event release];
88                 return true;
89         }
90
91         return false;
92 }
93
94 const void *copy_event(CFAllocatorRef allocator, const void *event)
95 {
96         void *copy = CFAllocatorAllocate(allocator, sizeof(CocoaEvent), 0);
97         memcpy(copy, event, sizeof(CocoaEvent));
98         return copy;
99 }
100
101 void free_event(CFAllocatorRef allocator, const void *event)
102 {
103         CFAllocatorDeallocate(allocator, (void *)event);
104 }