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);
104 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
107 wxCFStringRef cf(wxCFRetain(filename));
108 wxTheApp->MacOpenFile(cf.AsString()) ;
112 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
115 wxTheApp->MacNewFile() ;
119 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
122 wxCFStringRef cf(wxCFRetain(filename));
123 wxTheApp->MacPrintFile(cf.AsString()) ;
127 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
131 wxTheApp->MacReopenApp() ;
135 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
136 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
138 wxUnusedVar(replyEvent);
139 NSString* url = [[event descriptorAtIndex:1] stringValue];
140 wxCFStringRef cf(wxCFRetain(url));
141 wxTheApp->MacOpenURL(cf.AsString()) ;
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.
151 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
155 wxTheApp->OnQueryEndSession(event);
156 if ( event.GetVeto() )
157 return NSTerminateCancel;
159 return NSTerminateNow;
162 - (void)applicationWillTerminate:(NSApplication *)application {
163 wxUnusedVar(application);
165 event.SetCanVeto(false);
166 wxTheApp->OnEndSession(event);
169 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
172 // let wx do this, not cocoa
179 allows ShowModal to work when using sheets.
180 see include/wx/osx/cocoa/private.h for more info
182 @implementation ModalDialogDelegate
192 - (void)setImplementation: (wxDialog *)dialog
199 return sheetFinished;
207 - (void)waitForSheetToFinish
209 while (!sheetFinished)
215 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
217 wxUnusedVar(contextInfo);
218 resultCode = returnCode;
220 // NSAlerts don't need nor respond to orderOut
221 if ([sheet respondsToSelector:@selector(orderOut:)])
222 [sheet orderOut: self];
225 impl->ModalFinishedCallback(sheet, returnCode);
229 bool wxApp::DoInitGui()
231 wxMacAutoreleasePool pool;
232 [NSApplication sharedApplication];
236 wxNSAppController* controller = [[wxNSAppController alloc] init];
237 [[NSApplication sharedApplication] setDelegate:controller];
239 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
240 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
241 forEventClass:kInternetEventClass andEventID:kAEGetURL];
246 void wxApp::DoCleanUp()
250 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
252 NSRect displayRect = [[NSScreen mainScreen] visibleFrame];
253 wxRect r = wxFromNSRect( NULL, displayRect );
259 *width = r.GetWidth();
261 *height = r.GetHeight();
265 void wxGetMousePosition( int* x, int* y )
267 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
274 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
276 wxMouseState wxGetMouseState()
280 wxPoint pt = wxGetMousePosition();
284 NSUInteger modifiers = [NSEvent modifierFlags];
285 NSUInteger buttons = [NSEvent pressedMouseButtons];
287 ms.SetLeftDown( (buttons & 0x01) != 0 );
288 ms.SetMiddleDown( (buttons & 0x04) != 0 );
289 ms.SetRightDown( (buttons & 0x02) != 0 );
291 ms.SetControlDown(modifiers & NSControlKeyMask);
292 ms.SetShiftDown(modifiers & NSShiftKeyMask);
293 ms.SetAltDown(modifiers & NSAlternateKeyMask);
294 ms.SetMetaDown(modifiers & NSCommandKeyMask);
302 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
304 return new wxOSXTimerImpl(timer);
307 int gs_wxBusyCursorCount = 0;
308 extern wxCursor gMacCurrentCursor;
309 wxCursor gMacStoredActiveCursor;
311 // Set the cursor to the busy cursor for all windows
312 void wxBeginBusyCursor(const wxCursor *cursor)
314 if (gs_wxBusyCursorCount++ == 0)
316 gMacStoredActiveCursor = gMacCurrentCursor;
317 cursor->MacInstall();
319 wxSetCursor(*cursor);
321 //else: nothing to do, already set
324 // Restore cursor to normal
325 void wxEndBusyCursor()
327 wxCHECK_RET( gs_wxBusyCursorCount > 0,
328 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
330 if (--gs_wxBusyCursorCount == 0)
332 gMacStoredActiveCursor.MacInstall();
333 gMacStoredActiveCursor = wxNullCursor;
335 wxSetCursor(wxNullCursor);
339 // true if we're between the above two calls
342 return (gs_wxBusyCursorCount > 0);
345 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
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.
352 wxSize sz = m_window->GetSize();
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 ;
359 NSRect rect = NSMakeRect(left, top, width, height );
360 NSView* view = (NSView*) m_window->GetHandle();
362 // we use this method as other methods force a repaint, and this method can be
363 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
364 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
367 wxBitmap bitmap(width, height);
368 if ( [rep respondsToSelector:@selector(CGImage)] )
370 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
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);
380 // TODO for 10.4 in case we can support this for osx_cocoa
389 #endif // wxOSX_USE_COCOA