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"
14 #include "wx/wxprec.h"
22 #include "wx/toplevel.h"
27 #include "wx/apptrait.h"
29 #include "wx/osx/private.h"
32 #if wxOSX_USE_COCOA_OR_CARBON
33 #include <CoreServices/CoreServices.h>
34 #include "wx/osx/dcclient.h"
35 #include "wx/osx/private/timer.h"
49 // ----------------------------------------------------------------------------
50 // Common Event Support
51 // ----------------------------------------------------------------------------
55 // ensure that we have an auto release pool in place because the event will
56 // be autoreleased from NSEvent:otherEventWithType and we might not have a
57 // global pool during startup or shutdown and we actually never have it if
58 // we're called from another thread
60 // FIXME: we can't use wxMacAutoreleasePool here because it's in core and
62 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
64 NSEvent* wakeupEvent = [NSEvent otherEventWithType:NSApplicationDefined
66 modifierFlags:NSAnyEventMask
73 [NSApp postEvent:wakeupEvent atStart:NO];
82 @interface wxNSAppController : NSObject wxOSX_10_6_AND_LATER(<NSApplicationDelegate>)
86 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender;
87 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
88 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
89 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename;
90 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
91 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
92 withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
95 @implementation wxNSAppController
97 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
100 // let wx do this, not cocoa
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()) ;
128 Allowable return values are:
129 NSTerminateNow - it is ok to proceed with termination
130 NSTerminateCancel - the application should not be terminated
131 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
132 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
134 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
137 wxWindow* win = wxTheApp->GetTopWindow() ;
140 wxCommandEvent exitEvent(wxEVT_COMMAND_MENU_SELECTED, wxApp::s_macExitMenuItemId);
141 if (!win->GetEventHandler()->ProcessEvent(exitEvent))
146 wxTheApp->ExitMainLoop() ;
148 return NSTerminateCancel;
151 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
155 wxTheApp->MacReopenApp() ;
159 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
160 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
162 wxUnusedVar(replyEvent);
163 NSString* url = [[event descriptorAtIndex:1] stringValue];
164 wxCFStringRef cf(wxCFRetain(url));
165 wxTheApp->MacOpenURL(cf.AsString()) ;
170 allows ShowModal to work when using sheets.
171 see include/wx/osx/cocoa/private.h for more info
173 @implementation ModalDialogDelegate
184 return sheetFinished;
192 - (void)waitForSheetToFinish
194 while (!sheetFinished)
200 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
202 wxUnusedVar(contextInfo);
203 resultCode = returnCode;
205 // NSAlerts don't need nor respond to orderOut
206 if ([sheet respondsToSelector:@selector(orderOut:)])
207 [sheet orderOut: self];
211 bool wxApp::DoInitGui()
213 wxMacAutoreleasePool pool;
214 [NSApplication sharedApplication];
218 wxNSAppController* controller = [[wxNSAppController alloc] init];
219 [[NSApplication sharedApplication] setDelegate:controller];
221 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
222 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
223 forEventClass:kInternetEventClass andEventID:kAEGetURL];
224 [NSApp finishLaunching];
229 void wxApp::DoCleanUp()
233 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
235 NSRect displayRect = [[NSScreen mainScreen] visibleFrame];
236 wxRect r = wxFromNSRect( NULL, displayRect );
242 *width = r.GetWidth();
244 *height = r.GetHeight();
248 void wxGetMousePosition( int* x, int* y )
250 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
257 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
259 wxMouseState wxGetMouseState()
263 wxPoint pt = wxGetMousePosition();
267 NSUInteger modifiers = [NSEvent modifierFlags];
268 NSUInteger buttons = [NSEvent pressedMouseButtons];
270 ms.SetLeftDown( (buttons & 0x01) != 0 );
271 ms.SetMiddleDown( (buttons & 0x04) != 0 );
272 ms.SetRightDown( (buttons & 0x02) != 0 );
274 ms.SetControlDown(modifiers & NSControlKeyMask);
275 ms.SetShiftDown(modifiers & NSShiftKeyMask);
276 ms.SetAltDown(modifiers & NSAlternateKeyMask);
277 ms.SetMetaDown(modifiers & NSCommandKeyMask);
285 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
287 return new wxOSXTimerImpl(timer);
290 int gs_wxBusyCursorCount = 0;
291 extern wxCursor gMacCurrentCursor;
292 wxCursor gMacStoredActiveCursor;
294 // Set the cursor to the busy cursor for all windows
295 void wxBeginBusyCursor(const wxCursor *cursor)
297 if (gs_wxBusyCursorCount++ == 0)
299 gMacStoredActiveCursor = gMacCurrentCursor;
300 cursor->MacInstall();
302 wxSetCursor(*cursor);
304 //else: nothing to do, already set
307 // Restore cursor to normal
308 void wxEndBusyCursor()
310 wxCHECK_RET( gs_wxBusyCursorCount > 0,
311 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
313 if (--gs_wxBusyCursorCount == 0)
315 gMacStoredActiveCursor.MacInstall();
316 gMacStoredActiveCursor = wxNullCursor;
318 wxSetCursor(wxNullCursor);
322 // true if we're between the above two calls
325 return (gs_wxBusyCursorCount > 0);
328 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
330 // wxScreenDC is derived from wxWindowDC, so a screen dc will
331 // call this method when a Blit is performed with it as a source.
335 wxSize sz = m_window->GetSize();
337 int left = subrect != NULL ? subrect->x : 0 ;
338 int top = subrect != NULL ? subrect->y : 0 ;
339 int width = subrect != NULL ? subrect->width : sz.x;
340 int height = subrect != NULL ? subrect->height : sz.y ;
342 NSRect rect = NSMakeRect(left, top, width, height );
343 NSView* view = (NSView*) m_window->GetHandle();
345 // we use this method as other methods force a repaint, and this method can be
346 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
347 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
350 wxBitmap bitmap(width, height);
351 if ( [rep respondsToSelector:@selector(CGImage)] )
353 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
355 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
356 // since our context is upside down we dont use CGContextDrawImage
357 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
358 CGImageRelease(cgImageRef);
363 // TODO for 10.4 in case we can support this for osx_cocoa
372 #endif // wxOSX_USE_COCOA