1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/cocoa/utils.mm
3 // Purpose: various cocoa utility functions
4 // Author: Stefan Csomor
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 @implementation wxNSAppController
54 - (void)applicationWillFinishLaunching:(NSNotification *)application {
55 wxUnusedVar(application);
58 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
61 wxCFStringRef cf(wxCFRetain(filename));
62 wxTheApp->MacOpenFile(cf.AsString()) ;
66 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
69 wxTheApp->MacNewFile() ;
73 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
76 wxCFStringRef cf(wxCFRetain(filename));
77 wxTheApp->MacPrintFile(cf.AsString()) ;
81 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
85 wxTheApp->MacReopenApp() ;
89 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
90 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
92 wxUnusedVar(replyEvent);
93 NSString* url = [[event descriptorAtIndex:1] stringValue];
94 wxCFStringRef cf(wxCFRetain(url));
95 wxTheApp->MacOpenURL(cf.AsString()) ;
99 Allowable return values are:
100 NSTerminateNow - it is ok to proceed with termination
101 NSTerminateCancel - the application should not be terminated
102 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
103 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
105 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
109 wxTheApp->OnQueryEndSession(event);
110 if ( event.GetVeto() )
111 return NSTerminateCancel;
113 return NSTerminateNow;
116 - (void)applicationWillTerminate:(NSNotification *)application {
117 wxUnusedVar(application);
119 event.SetCanVeto(false);
120 wxTheApp->OnEndSession(event);
123 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
126 // let wx do this, not cocoa
130 - (void)applicationDidBecomeActive:(NSNotification *)notification
132 wxUnusedVar(notification);
134 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(),
135 end = wxTopLevelWindows.end();
139 wxTopLevelWindow * const win = static_cast<wxTopLevelWindow *>(*i);
140 wxNonOwnedWindowImpl* winimpl = win ? win->GetNonOwnedPeer() : NULL;
141 WXWindow nswindow = win ? win->GetWXWindow() : nil;
143 if ( nswindow && [nswindow hidesOnDeactivate] == NO && winimpl)
144 winimpl->RestoreWindowLevel();
147 wxTheApp->SetActive( true , NULL ) ;
150 - (void)applicationWillResignActive:(NSNotification *)notification
152 wxUnusedVar(notification);
153 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(),
154 end = wxTopLevelWindows.end();
158 wxTopLevelWindow * const win = static_cast<wxTopLevelWindow *>(*i);
159 WXWindow nswindow = win ? win->GetWXWindow() : nil;
161 if ( nswindow && [nswindow level] == kCGFloatingWindowLevel && [nswindow hidesOnDeactivate] == NO )
162 [nswindow setLevel:kCGNormalWindowLevel];
166 - (void)applicationDidResignActive:(NSNotification *)notification
168 wxUnusedVar(notification);
170 wxTheApp->SetActive( false , NULL ) ;
176 allows ShowModal to work when using sheets.
177 see include/wx/osx/cocoa/private.h for more info
179 @implementation ModalDialogDelegate
189 - (void)setImplementation: (wxDialog *)dialog
196 return sheetFinished;
204 - (void)waitForSheetToFinish
206 while (!sheetFinished)
212 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
214 wxUnusedVar(contextInfo);
215 resultCode = returnCode;
217 // NSAlerts don't need nor respond to orderOut
218 if ([sheet respondsToSelector:@selector(orderOut:)])
219 [sheet orderOut: self];
222 impl->ModalFinishedCallback(sheet, returnCode);
226 bool wxApp::DoInitGui()
228 wxMacAutoreleasePool pool;
229 [NSApplication sharedApplication];
233 wxNSAppController* controller = [[wxNSAppController alloc] init];
234 [NSApp setDelegate:controller];
236 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
237 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
238 forEventClass:kInternetEventClass andEventID:kAEGetURL];
240 // calling finishLaunching so early before running the loop seems to trigger some 'MenuManager compatibility' which leads
241 // to the duplication of menus under 10.5 and a warning under 10.6
243 [NSApp finishLaunching];
249 void wxApp::DoCleanUp()
253 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
255 NSRect displayRect = [wxOSXGetMenuScreen() visibleFrame];
256 wxRect r = wxFromNSRect( NULL, displayRect );
262 *width = r.GetWidth();
264 *height = r.GetHeight();
268 void wxGetMousePosition( int* x, int* y )
270 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
277 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
279 wxMouseState wxGetMouseState()
283 wxPoint pt = wxGetMousePosition();
287 NSUInteger modifiers = [NSEvent modifierFlags];
288 NSUInteger buttons = [NSEvent pressedMouseButtons];
290 ms.SetLeftDown( (buttons & 0x01) != 0 );
291 ms.SetMiddleDown( (buttons & 0x04) != 0 );
292 ms.SetRightDown( (buttons & 0x02) != 0 );
294 ms.SetControlDown(modifiers & NSControlKeyMask);
295 ms.SetShiftDown(modifiers & NSShiftKeyMask);
296 ms.SetAltDown(modifiers & NSAlternateKeyMask);
297 ms.SetMetaDown(modifiers & NSCommandKeyMask);
305 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
307 return new wxOSXTimerImpl(timer);
310 int gs_wxBusyCursorCount = 0;
311 extern wxCursor gMacCurrentCursor;
312 wxCursor gMacStoredActiveCursor;
314 // Set the cursor to the busy cursor for all windows
315 void wxBeginBusyCursor(const wxCursor *cursor)
317 if (gs_wxBusyCursorCount++ == 0)
319 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
322 while ((object = [enumerator nextObject])) {
323 [(NSWindow*) object disableCursorRects];
326 gMacStoredActiveCursor = gMacCurrentCursor;
327 cursor->MacInstall();
329 wxSetCursor(*cursor);
331 //else: nothing to do, already set
334 // Restore cursor to normal
335 void wxEndBusyCursor()
337 wxCHECK_RET( gs_wxBusyCursorCount > 0,
338 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
340 if (--gs_wxBusyCursorCount == 0)
342 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
345 while ((object = [enumerator nextObject])) {
346 [(NSWindow*) object enableCursorRects];
349 wxSetCursor(wxNullCursor);
351 gMacStoredActiveCursor.MacInstall();
352 gMacStoredActiveCursor = wxNullCursor;
356 // true if we're between the above two calls
359 return (gs_wxBusyCursorCount > 0);
362 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
364 // wxScreenDC is derived from wxWindowDC, so a screen dc will
365 // call this method when a Blit is performed with it as a source.
369 wxSize sz = m_window->GetSize();
371 int width = subrect != NULL ? subrect->width : sz.x;
372 int height = subrect != NULL ? subrect->height : sz.y ;
374 wxBitmap bitmap(width, height);
376 NSView* view = (NSView*) m_window->GetHandle();
377 if ( [view isHiddenOrHasHiddenAncestor] == NO )
380 // we use this method as other methods force a repaint, and this method can be
381 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
382 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
384 if ( [rep respondsToSelector:@selector(CGImage)] )
386 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
388 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
389 // since our context is upside down we dont use CGContextDrawImage
390 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
391 CGImageRelease(cgImageRef);
396 // TODO for 10.4 in case we can support this for osx_cocoa
406 #endif // wxOSX_USE_COCOA