summaryrefslogtreecommitdiff
path: root/src/lib/ecore_cocoa/ecore_cocoa_app.m
blob: 8df1be1830d649b7ad5b01a8e0980a67106453f3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#import "ecore_cocoa_app.h"
#import "ecore_cocoa_window.h"
#include "ecore_cocoa_private.h"

static Eina_Bool
_ecore_cocoa_run_loop_cb(void *data EINA_UNUSED)
{
        @try {
             NSEvent *e;
             do {
                  e = [NSApp nextEventMatchingMask:NSEventMaskAny
                                         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 != NSEventTypePeriodic) &&
                           (type != NSEventTypeMouseMoved)) {
                            [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) {
      CRI("Failed to [super init]");
      return nil;
   }
   NSApp = self; // NSApp is used EVERYWHERE! Set it right now!

   /* Set the process to be a foreground process,
    * without that it prevents the window to become the key window and
    * receive all mouse mouve events. */
   [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
   [NSApp activateIgnoringOtherApps:YES];

   return NSApp;
}

- (NSDate *)eventExpirationDate
{
   return _expiration;
}

- (void)run
{
   [self finishLaunching];

   _running = 1;
   _expiration = [NSDate distantPast];

   _timer = ecore_timer_add(ECORE_COCOA_MAINLOOP_PERIOD,
                             _ecore_cocoa_run_loop_cb, NULL);
}


- (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];
}

- (void) pauseNSRunLoopMonitoring
{
   /*
    * After calling this method, we will run an iteration of
    * the main loop. We don't want this timer to be fired while
    * calling manually the ecore loop, because it will query the
    * NSRunLoop, which blocks during live resize.
    */
   ecore_timer_freeze(_timer);
}

- (void) resumeNSRunLoopMonitoring
{
   ecore_timer_thaw(_timer);
}

- (void)setTerminateCb:(Ecore_Cocoa_Terminate_Cb)cb
{
   _terminate_cb = cb;
}

- (Ecore_Cocoa_Terminate_Cb)terminateCb
{
   return _terminate_cb;
}

@end



static Ecore_Cocoa_AppDelegate *_appDelegate = nil;

@implementation Ecore_Cocoa_AppDelegate

+ (Ecore_Cocoa_AppDelegate *)appDelegate
{
   if (_appDelegate == nil) {
        _appDelegate = [[self alloc] init];
   }
   return _appDelegate;
}

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *) EINA_UNUSED sender
{
   // XXX This should be alterable (by Elm_Window policy)
   return NO;
}

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
   NSApplicationTerminateReply status = NSTerminateNow;
   const Ecore_Cocoa_Terminate_Cb cb = [(Ecore_Cocoa_Application *)sender terminateCb];
   if (cb)
     {
         const Eina_Bool ret = cb(sender);
         if (!ret) status = NSTerminateCancel;
     }
   return status;
}

@end