1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/cocoa/utils.mm
3 // Purpose: various cocoa utility functions
4 // Author: Stefan Csomor
7 // RCS-ID: $Id: utils.mm 48805 2007-09-19 14:52:25Z SC $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
20 #include "wx/dialog.h"
21 #include "wx/toplevel.h"
26 #include "wx/apptrait.h"
28 #include "wx/osx/private.h"
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"
52 @interface wxNSAppController : NSObject wxOSX_10_6_AND_LATER(<NSApplicationDelegate>)
56 - (void)applicationWillFinishLaunching:(NSApplication *)sender;
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;
64 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender;
65 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
66 - (void)applicationWillTerminate:(NSApplication *)sender;
69 @implementation wxNSAppController
71 - (void)applicationWillFinishLaunching:(NSApplication *)application {
72 wxUnusedVar(application);
75 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
78 wxCFStringRef cf(wxCFRetain(filename));
79 wxTheApp->MacOpenFile(cf.AsString()) ;
83 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
86 wxTheApp->MacNewFile() ;
90 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
93 wxCFStringRef cf(wxCFRetain(filename));
94 wxTheApp->MacPrintFile(cf.AsString()) ;
98 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
102 wxTheApp->MacReopenApp() ;
106 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
107 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
109 wxUnusedVar(replyEvent);
110 NSString* url = [[event descriptorAtIndex:1] stringValue];
111 wxCFStringRef cf(wxCFRetain(url));
112 wxTheApp->MacOpenURL(cf.AsString()) ;
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.
122 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
126 wxTheApp->OnQueryEndSession(event);
127 if ( event.GetVeto() )
128 return NSTerminateCancel;
130 return NSTerminateNow;
133 - (void)applicationWillTerminate:(NSApplication *)application {
134 wxUnusedVar(application);
136 event.SetCanVeto(false);
137 wxTheApp->OnEndSession(event);
140 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
143 // let wx do this, not cocoa
150 allows ShowModal to work when using sheets.
151 see include/wx/osx/cocoa/private.h for more info
153 @implementation ModalDialogDelegate
163 - (void)setImplementation: (wxDialog *)dialog
170 return sheetFinished;
178 - (void)waitForSheetToFinish
180 while (!sheetFinished)
186 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
188 wxUnusedVar(contextInfo);
189 resultCode = returnCode;
191 // NSAlerts don't need nor respond to orderOut
192 if ([sheet respondsToSelector:@selector(orderOut:)])
193 [sheet orderOut: self];
196 impl->ModalFinishedCallback(sheet, returnCode);
200 bool wxApp::DoInitGui()
202 wxMacAutoreleasePool pool;
203 [NSApplication sharedApplication];
207 wxNSAppController* controller = [[wxNSAppController alloc] init];
208 [NSApp setDelegate:controller];
210 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
211 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
212 forEventClass:kInternetEventClass andEventID:kAEGetURL];
214 // calling finishLaunching so early before running the loop seems to trigger some 'MenuManager compatibility' which leads
215 // to the duplication of menus under 10.5 and a warning under 10.6
217 [NSApp finishLaunching];
223 void wxApp::DoCleanUp()
227 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
229 NSRect displayRect = [wxOSXGetMenuScreen() visibleFrame];
230 wxRect r = wxFromNSRect( NULL, displayRect );
236 *width = r.GetWidth();
238 *height = r.GetHeight();
242 void wxGetMousePosition( int* x, int* y )
244 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
251 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
253 wxMouseState wxGetMouseState()
257 wxPoint pt = wxGetMousePosition();
261 NSUInteger modifiers = [NSEvent modifierFlags];
262 NSUInteger buttons = [NSEvent pressedMouseButtons];
264 ms.SetLeftDown( (buttons & 0x01) != 0 );
265 ms.SetMiddleDown( (buttons & 0x04) != 0 );
266 ms.SetRightDown( (buttons & 0x02) != 0 );
268 ms.SetControlDown(modifiers & NSControlKeyMask);
269 ms.SetShiftDown(modifiers & NSShiftKeyMask);
270 ms.SetAltDown(modifiers & NSAlternateKeyMask);
271 ms.SetMetaDown(modifiers & NSCommandKeyMask);
279 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
281 return new wxOSXTimerImpl(timer);
284 int gs_wxBusyCursorCount = 0;
285 extern wxCursor gMacCurrentCursor;
286 wxCursor gMacStoredActiveCursor;
288 // Set the cursor to the busy cursor for all windows
289 void wxBeginBusyCursor(const wxCursor *cursor)
291 if (gs_wxBusyCursorCount++ == 0)
293 gMacStoredActiveCursor = gMacCurrentCursor;
294 cursor->MacInstall();
296 wxSetCursor(*cursor);
298 //else: nothing to do, already set
301 // Restore cursor to normal
302 void wxEndBusyCursor()
304 wxCHECK_RET( gs_wxBusyCursorCount > 0,
305 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
307 if (--gs_wxBusyCursorCount == 0)
309 gMacStoredActiveCursor.MacInstall();
310 gMacStoredActiveCursor = wxNullCursor;
312 wxSetCursor(wxNullCursor);
316 // true if we're between the above two calls
319 return (gs_wxBusyCursorCount > 0);
322 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
324 // wxScreenDC is derived from wxWindowDC, so a screen dc will
325 // call this method when a Blit is performed with it as a source.
329 wxSize sz = m_window->GetSize();
331 int width = subrect != NULL ? subrect->width : sz.x;
332 int height = subrect != NULL ? subrect->height : sz.y ;
334 NSView* view = (NSView*) m_window->GetHandle();
336 // we use this method as other methods force a repaint, and this method can be
337 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
338 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
341 wxBitmap bitmap(width, height);
342 if ( [rep respondsToSelector:@selector(CGImage)] )
344 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
346 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
347 // since our context is upside down we dont use CGContextDrawImage
348 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
349 CGImageRelease(cgImageRef);
354 // TODO for 10.4 in case we can support this for osx_cocoa
363 #endif // wxOSX_USE_COCOA