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"
48 // ----------------------------------------------------------------------------
49 // Common Event Support
50 // ----------------------------------------------------------------------------
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
59 // FIXME: we can't use wxMacAutoreleasePool here because it's in core and
61 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
63 NSEvent* wakeupEvent = [NSEvent otherEventWithType:NSApplicationDefined
65 modifierFlags:NSAnyEventMask
72 [NSApp postEvent:wakeupEvent atStart:NO];
81 @interface wxNSAppController : NSObject wxOSX_10_6_AND_LATER(<NSApplicationDelegate>)
85 - (void)applicationWillFinishLaunching:(NSApplication *)sender;
87 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
88 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
89 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename;
90 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
91 withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
93 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender;
94 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
95 - (void)applicationWillTerminate:(NSApplication *)sender;
98 @implementation wxNSAppController
100 - (void)applicationWillFinishLaunching:(NSApplication *)application {
101 wxUnusedVar(application);
105 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
108 wxCFStringRef cf(wxCFRetain(filename));
109 wxTheApp->MacOpenFile(cf.AsString()) ;
113 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
116 wxTheApp->MacNewFile() ;
120 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
123 wxCFStringRef cf(wxCFRetain(filename));
124 wxTheApp->MacPrintFile(cf.AsString()) ;
128 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
132 wxTheApp->MacReopenApp() ;
136 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
137 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
139 wxUnusedVar(replyEvent);
140 NSString* url = [[event descriptorAtIndex:1] stringValue];
141 wxCFStringRef cf(wxCFRetain(url));
142 wxTheApp->MacOpenURL(cf.AsString()) ;
146 Allowable return values are:
147 NSTerminateNow - it is ok to proceed with termination
148 NSTerminateCancel - the application should not be terminated
149 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
150 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
152 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
156 wxTheApp->OnQueryEndSession(event);
157 if ( event.GetVeto() )
158 return NSTerminateCancel;
160 return NSTerminateNow;
163 - (void)applicationWillTerminate:(NSApplication *)application {
164 wxUnusedVar(application);
166 event.SetCanVeto(false);
167 wxTheApp->OnEndSession(event);
170 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
173 // let wx do this, not cocoa
180 allows ShowModal to work when using sheets.
181 see include/wx/osx/cocoa/private.h for more info
183 @implementation ModalDialogDelegate
193 - (void)setImplementation: (wxDialog *)dialog
200 return sheetFinished;
208 - (void)waitForSheetToFinish
210 while (!sheetFinished)
216 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
218 wxUnusedVar(contextInfo);
219 resultCode = returnCode;
221 // NSAlerts don't need nor respond to orderOut
222 if ([sheet respondsToSelector:@selector(orderOut:)])
223 [sheet orderOut: self];
226 impl->ModalFinishedCallback(sheet, returnCode);
230 bool wxApp::CallOnInit()
238 bool wxApp::DoInitGui()
240 wxMacAutoreleasePool pool;
241 [NSApplication sharedApplication];
245 wxNSAppController* controller = [[wxNSAppController alloc] init];
246 [[NSApplication sharedApplication] setDelegate:controller];
248 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
249 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
250 forEventClass:kInternetEventClass andEventID:kAEGetURL];
255 void wxApp::DoCleanUp()
259 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
261 NSRect displayRect = [[NSScreen mainScreen] visibleFrame];
262 wxRect r = wxFromNSRect( NULL, displayRect );
268 *width = r.GetWidth();
270 *height = r.GetHeight();
274 void wxGetMousePosition( int* x, int* y )
276 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
283 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
285 wxMouseState wxGetMouseState()
289 wxPoint pt = wxGetMousePosition();
293 NSUInteger modifiers = [NSEvent modifierFlags];
294 NSUInteger buttons = [NSEvent pressedMouseButtons];
296 ms.SetLeftDown( (buttons & 0x01) != 0 );
297 ms.SetMiddleDown( (buttons & 0x04) != 0 );
298 ms.SetRightDown( (buttons & 0x02) != 0 );
300 ms.SetControlDown(modifiers & NSControlKeyMask);
301 ms.SetShiftDown(modifiers & NSShiftKeyMask);
302 ms.SetAltDown(modifiers & NSAlternateKeyMask);
303 ms.SetMetaDown(modifiers & NSCommandKeyMask);
311 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
313 return new wxOSXTimerImpl(timer);
316 int gs_wxBusyCursorCount = 0;
317 extern wxCursor gMacCurrentCursor;
318 wxCursor gMacStoredActiveCursor;
320 // Set the cursor to the busy cursor for all windows
321 void wxBeginBusyCursor(const wxCursor *cursor)
323 if (gs_wxBusyCursorCount++ == 0)
325 gMacStoredActiveCursor = gMacCurrentCursor;
326 cursor->MacInstall();
328 wxSetCursor(*cursor);
330 //else: nothing to do, already set
333 // Restore cursor to normal
334 void wxEndBusyCursor()
336 wxCHECK_RET( gs_wxBusyCursorCount > 0,
337 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
339 if (--gs_wxBusyCursorCount == 0)
341 gMacStoredActiveCursor.MacInstall();
342 gMacStoredActiveCursor = wxNullCursor;
344 wxSetCursor(wxNullCursor);
348 // true if we're between the above two calls
351 return (gs_wxBusyCursorCount > 0);
354 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
356 // wxScreenDC is derived from wxWindowDC, so a screen dc will
357 // call this method when a Blit is performed with it as a source.
361 wxSize sz = m_window->GetSize();
363 int left = subrect != NULL ? subrect->x : 0 ;
364 int top = subrect != NULL ? subrect->y : 0 ;
365 int width = subrect != NULL ? subrect->width : sz.x;
366 int height = subrect != NULL ? subrect->height : sz.y ;
368 NSRect rect = NSMakeRect(left, top, width, height );
369 NSView* view = (NSView*) m_window->GetHandle();
371 // we use this method as other methods force a repaint, and this method can be
372 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
373 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
376 wxBitmap bitmap(width, height);
377 if ( [rep respondsToSelector:@selector(CGImage)] )
379 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
381 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
382 // since our context is upside down we dont use CGContextDrawImage
383 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
384 CGImageRelease(cgImageRef);
389 // TODO for 10.4 in case we can support this for osx_cocoa
398 #endif // wxOSX_USE_COCOA