]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/utils.mm
common wxMacWakeUp code across all platforms
[wxWidgets.git] / src / osx / cocoa / utils.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/cocoa/utils.mm
3 // Purpose: various cocoa utility functions
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id: utils.mm 48805 2007-09-19 14:52:25Z SC $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #include "wx/utils.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/intl.h"
18 #include "wx/app.h"
19 #if wxUSE_GUI
20 #include "wx/dialog.h"
21 #include "wx/toplevel.h"
22 #include "wx/font.h"
23 #endif
24 #endif
25
26 #include "wx/apptrait.h"
27
28 #include "wx/osx/private.h"
29
30 #if wxUSE_GUI
31 #if wxOSX_USE_COCOA_OR_CARBON
32 #include <CoreServices/CoreServices.h>
33 #include "wx/osx/dcclient.h"
34 #include "wx/osx/private/timer.h"
35 #endif
36 #endif // wxUSE_GUI
37
38 #if wxOSX_USE_COCOA
39
40 #if wxUSE_BASE
41
42 // Emit a beeeeeep
43 void wxBell()
44 {
45 NSBeep();
46 }
47
48 #endif // wxUSE_BASE
49
50 #if wxUSE_GUI
51
52 @interface wxNSAppController : NSObject wxOSX_10_6_AND_LATER(<NSApplicationDelegate>)
53 {
54 }
55
56 - (void)applicationWillFinishLaunching:(NSApplication *)sender;
57
58 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
59 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
60 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename;
61 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
62 withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
63
64 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender;
65 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
66 - (void)applicationWillTerminate:(NSApplication *)sender;
67 @end
68
69 @implementation wxNSAppController
70
71 - (void)applicationWillFinishLaunching:(NSApplication *)application {
72 wxUnusedVar(application);
73 }
74
75 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
76 {
77 wxUnusedVar(sender);
78 wxCFStringRef cf(wxCFRetain(filename));
79 wxTheApp->MacOpenFile(cf.AsString()) ;
80 return YES;
81 }
82
83 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
84 {
85 wxUnusedVar(sender);
86 wxTheApp->MacNewFile() ;
87 return NO;
88 }
89
90 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
91 {
92 wxUnusedVar(sender);
93 wxCFStringRef cf(wxCFRetain(filename));
94 wxTheApp->MacPrintFile(cf.AsString()) ;
95 return YES;
96 }
97
98 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
99 {
100 wxUnusedVar(flag);
101 wxUnusedVar(sender);
102 wxTheApp->MacReopenApp() ;
103 return NO;
104 }
105
106 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
107 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
108 {
109 wxUnusedVar(replyEvent);
110 NSString* url = [[event descriptorAtIndex:1] stringValue];
111 wxCFStringRef cf(wxCFRetain(url));
112 wxTheApp->MacOpenURL(cf.AsString()) ;
113 }
114
115 /*
116 Allowable return values are:
117 NSTerminateNow - it is ok to proceed with termination
118 NSTerminateCancel - the application should not be terminated
119 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
120 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
121 */
122 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
123 {
124 wxUnusedVar(sender);
125 wxCloseEvent event;
126 wxTheApp->OnQueryEndSession(event);
127 if ( event.GetVeto() )
128 return NSTerminateCancel;
129
130 return NSTerminateNow;
131 }
132
133 - (void)applicationWillTerminate:(NSApplication *)application {
134 wxUnusedVar(application);
135 wxCloseEvent event;
136 event.SetCanVeto(false);
137 wxTheApp->OnEndSession(event);
138 }
139
140 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
141 {
142 wxUnusedVar(sender);
143 // let wx do this, not cocoa
144 return NO;
145 }
146
147 @end
148
149 /*
150 allows ShowModal to work when using sheets.
151 see include/wx/osx/cocoa/private.h for more info
152 */
153 @implementation ModalDialogDelegate
154 - (id)init
155 {
156 [super init];
157 sheetFinished = NO;
158 resultCode = -1;
159 impl = 0;
160 return self;
161 }
162
163 - (void)setImplementation: (wxDialog *)dialog
164 {
165 impl = dialog;
166 }
167
168 - (BOOL)finished
169 {
170 return sheetFinished;
171 }
172
173 - (int)code
174 {
175 return resultCode;
176 }
177
178 - (void)waitForSheetToFinish
179 {
180 while (!sheetFinished)
181 {
182 wxSafeYield();
183 }
184 }
185
186 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
187 {
188 wxUnusedVar(contextInfo);
189 resultCode = returnCode;
190 sheetFinished = YES;
191 // NSAlerts don't need nor respond to orderOut
192 if ([sheet respondsToSelector:@selector(orderOut:)])
193 [sheet orderOut: self];
194
195 if (impl)
196 impl->ModalFinishedCallback(sheet, returnCode);
197 }
198 @end
199
200 bool wxApp::DoInitGui()
201 {
202 wxMacAutoreleasePool pool;
203 [NSApplication sharedApplication];
204
205 if (!sm_isEmbedded)
206 {
207 wxNSAppController* controller = [[wxNSAppController alloc] init];
208 [NSApp setDelegate:controller];
209
210 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
211 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
212 forEventClass:kInternetEventClass andEventID:kAEGetURL];
213
214 [NSApp finishLaunching];
215 }
216 return true;
217 }
218
219 void wxApp::DoCleanUp()
220 {
221 }
222
223 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
224 {
225 NSRect displayRect = [[NSScreen mainScreen] visibleFrame];
226 wxRect r = wxFromNSRect( NULL, displayRect );
227 if ( x )
228 *x = r.x;
229 if ( y )
230 *y = r.y;
231 if ( width )
232 *width = r.GetWidth();
233 if ( height )
234 *height = r.GetHeight();
235
236 }
237
238 void wxGetMousePosition( int* x, int* y )
239 {
240 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
241 if ( x )
242 *x = pt.x;
243 if ( y )
244 *y = pt.y;
245 };
246
247 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
248
249 wxMouseState wxGetMouseState()
250 {
251 wxMouseState ms;
252
253 wxPoint pt = wxGetMousePosition();
254 ms.SetX(pt.x);
255 ms.SetY(pt.y);
256
257 NSUInteger modifiers = [NSEvent modifierFlags];
258 NSUInteger buttons = [NSEvent pressedMouseButtons];
259
260 ms.SetLeftDown( (buttons & 0x01) != 0 );
261 ms.SetMiddleDown( (buttons & 0x04) != 0 );
262 ms.SetRightDown( (buttons & 0x02) != 0 );
263
264 ms.SetControlDown(modifiers & NSControlKeyMask);
265 ms.SetShiftDown(modifiers & NSShiftKeyMask);
266 ms.SetAltDown(modifiers & NSAlternateKeyMask);
267 ms.SetMetaDown(modifiers & NSCommandKeyMask);
268
269 return ms;
270 }
271
272
273 #endif
274
275 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
276 {
277 return new wxOSXTimerImpl(timer);
278 }
279
280 int gs_wxBusyCursorCount = 0;
281 extern wxCursor gMacCurrentCursor;
282 wxCursor gMacStoredActiveCursor;
283
284 // Set the cursor to the busy cursor for all windows
285 void wxBeginBusyCursor(const wxCursor *cursor)
286 {
287 if (gs_wxBusyCursorCount++ == 0)
288 {
289 gMacStoredActiveCursor = gMacCurrentCursor;
290 cursor->MacInstall();
291
292 wxSetCursor(*cursor);
293 }
294 //else: nothing to do, already set
295 }
296
297 // Restore cursor to normal
298 void wxEndBusyCursor()
299 {
300 wxCHECK_RET( gs_wxBusyCursorCount > 0,
301 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
302
303 if (--gs_wxBusyCursorCount == 0)
304 {
305 gMacStoredActiveCursor.MacInstall();
306 gMacStoredActiveCursor = wxNullCursor;
307
308 wxSetCursor(wxNullCursor);
309 }
310 }
311
312 // true if we're between the above two calls
313 bool wxIsBusy()
314 {
315 return (gs_wxBusyCursorCount > 0);
316 }
317
318 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
319 {
320 // wxScreenDC is derived from wxWindowDC, so a screen dc will
321 // call this method when a Blit is performed with it as a source.
322 if (!m_window)
323 return wxNullBitmap;
324
325 wxSize sz = m_window->GetSize();
326
327 int left = subrect != NULL ? subrect->x : 0 ;
328 int top = subrect != NULL ? subrect->y : 0 ;
329 int width = subrect != NULL ? subrect->width : sz.x;
330 int height = subrect != NULL ? subrect->height : sz.y ;
331
332 NSRect rect = NSMakeRect(left, top, width, height );
333 NSView* view = (NSView*) m_window->GetHandle();
334 [view lockFocus];
335 // we use this method as other methods force a repaint, and this method can be
336 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
337 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
338 [view unlockFocus];
339
340 wxBitmap bitmap(width, height);
341 if ( [rep respondsToSelector:@selector(CGImage)] )
342 {
343 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
344
345 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
346 // since our context is upside down we dont use CGContextDrawImage
347 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
348 CGImageRelease(cgImageRef);
349 cgImageRef = NULL;
350 }
351 else
352 {
353 // TODO for 10.4 in case we can support this for osx_cocoa
354 }
355 [rep release];
356
357 return bitmap;
358 }
359
360 #endif // wxUSE_GUI
361
362 #endif // wxOSX_USE_COCOA