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