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