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);
57 // we must install our handlers later than setting the app delegate, because otherwise our handlers
58 // get overwritten in the meantime
60 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
62 [appleEventManager setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:)
63 forEventClass:kInternetEventClass andEventID:kAEGetURL];
65 [appleEventManager setEventHandler:self andSelector:@selector(handleOpenAppEvent:withReplyEvent:)
66 forEventClass:kCoreEventClass andEventID:kAEOpenApplication];
70 - (void)application:(NSApplication *)sender openFiles:(NSArray *)fileNames
73 wxArrayString fileList;
75 const size_t count = [fileNames count];
76 for (i = 0; i < count; i++)
78 fileList.Add( wxCFStringRef::AsString([fileNames objectAtIndex:i]) );
81 wxTheApp->MacOpenFiles(fileList);
84 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
87 wxCFStringRef cf(wxCFRetain(filename));
88 wxTheApp->MacPrintFile(cf.AsString()) ;
92 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
96 wxTheApp->MacReopenApp() ;
100 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
101 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
103 wxUnusedVar(replyEvent);
104 NSString* url = [[event descriptorAtIndex:1] stringValue];
105 wxCFStringRef cf(wxCFRetain(url));
106 wxTheApp->MacOpenURL(cf.AsString()) ;
109 - (void)handleOpenAppEvent:(NSAppleEventDescriptor *)event
110 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
112 wxUnusedVar(replyEvent);
113 wxTheApp->MacNewFile() ;
117 Allowable return values are:
118 NSTerminateNow - it is ok to proceed with termination
119 NSTerminateCancel - the application should not be terminated
120 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
121 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
123 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
127 wxTheApp->OnQueryEndSession(event);
128 if ( event.GetVeto() )
129 return NSTerminateCancel;
131 return NSTerminateNow;
134 - (void)applicationWillTerminate:(NSNotification *)application {
135 wxUnusedVar(application);
137 event.SetCanVeto(false);
138 wxTheApp->OnEndSession(event);
141 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
144 // let wx do this, not cocoa
148 - (void)applicationDidBecomeActive:(NSNotification *)notification
150 wxUnusedVar(notification);
152 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(),
153 end = wxTopLevelWindows.end();
157 wxTopLevelWindow * const win = static_cast<wxTopLevelWindow *>(*i);
158 wxNonOwnedWindowImpl* winimpl = win ? win->GetNonOwnedPeer() : NULL;
159 WXWindow nswindow = win ? win->GetWXWindow() : nil;
161 if ( nswindow && [nswindow hidesOnDeactivate] == NO && winimpl)
162 winimpl->RestoreWindowLevel();
165 wxTheApp->SetActive( true , NULL ) ;
168 - (void)applicationWillResignActive:(NSNotification *)notification
170 wxUnusedVar(notification);
171 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(),
172 end = wxTopLevelWindows.end();
176 wxTopLevelWindow * const win = static_cast<wxTopLevelWindow *>(*i);
177 WXWindow nswindow = win ? win->GetWXWindow() : nil;
179 if ( nswindow && [nswindow level] == kCGFloatingWindowLevel && [nswindow hidesOnDeactivate] == NO )
180 [nswindow setLevel:kCGNormalWindowLevel];
184 - (void)applicationDidResignActive:(NSNotification *)notification
186 wxUnusedVar(notification);
188 wxTheApp->SetActive( false , NULL ) ;
194 allows ShowModal to work when using sheets.
195 see include/wx/osx/cocoa/private.h for more info
197 @implementation ModalDialogDelegate
207 - (void)setImplementation: (wxDialog *)dialog
214 return sheetFinished;
222 - (void)waitForSheetToFinish
224 while (!sheetFinished)
230 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
232 wxUnusedVar(contextInfo);
233 resultCode = returnCode;
235 // NSAlerts don't need nor respond to orderOut
236 if ([sheet respondsToSelector:@selector(orderOut:)])
237 [sheet orderOut: self];
240 impl->ModalFinishedCallback(sheet, returnCode);
244 bool wxApp::DoInitGui()
246 wxMacAutoreleasePool pool;
247 [NSApplication sharedApplication];
251 wxNSAppController* controller = [[wxNSAppController alloc] init];
252 [NSApp setDelegate:controller];
254 // calling finishLaunching so early before running the loop seems to trigger some 'MenuManager compatibility' which leads
255 // to the duplication of menus under 10.5 and a warning under 10.6
257 [NSApp finishLaunching];
263 void wxApp::DoCleanUp()
267 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
269 NSRect displayRect = [wxOSXGetMenuScreen() visibleFrame];
270 wxRect r = wxFromNSRect( NULL, displayRect );
276 *width = r.GetWidth();
278 *height = r.GetHeight();
282 void wxGetMousePosition( int* x, int* y )
284 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
291 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
293 wxMouseState wxGetMouseState()
297 wxPoint pt = wxGetMousePosition();
301 NSUInteger modifiers = [NSEvent modifierFlags];
302 NSUInteger buttons = [NSEvent pressedMouseButtons];
304 ms.SetLeftDown( (buttons & 0x01) != 0 );
305 ms.SetMiddleDown( (buttons & 0x04) != 0 );
306 ms.SetRightDown( (buttons & 0x02) != 0 );
308 ms.SetRealControlDown(modifiers & NSControlKeyMask);
309 ms.SetShiftDown(modifiers & NSShiftKeyMask);
310 ms.SetAltDown(modifiers & NSAlternateKeyMask);
311 ms.SetControlDown(modifiers & NSCommandKeyMask);
319 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
321 return new wxOSXTimerImpl(timer);
324 int gs_wxBusyCursorCount = 0;
325 extern wxCursor gMacCurrentCursor;
326 wxCursor gMacStoredActiveCursor;
328 // Set the cursor to the busy cursor for all windows
329 void wxBeginBusyCursor(const wxCursor *cursor)
331 if (gs_wxBusyCursorCount++ == 0)
333 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
336 while ((object = [enumerator nextObject])) {
337 [(NSWindow*) object disableCursorRects];
340 gMacStoredActiveCursor = gMacCurrentCursor;
341 cursor->MacInstall();
343 wxSetCursor(*cursor);
345 //else: nothing to do, already set
348 // Restore cursor to normal
349 void wxEndBusyCursor()
351 wxCHECK_RET( gs_wxBusyCursorCount > 0,
352 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
354 if (--gs_wxBusyCursorCount == 0)
356 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
359 while ((object = [enumerator nextObject])) {
360 [(NSWindow*) object enableCursorRects];
363 wxSetCursor(wxNullCursor);
365 gMacStoredActiveCursor.MacInstall();
366 gMacStoredActiveCursor = wxNullCursor;
370 // true if we're between the above two calls
373 return (gs_wxBusyCursorCount > 0);
376 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
378 // wxScreenDC is derived from wxWindowDC, so a screen dc will
379 // call this method when a Blit is performed with it as a source.
383 wxSize sz = m_window->GetSize();
385 int width = subrect != NULL ? subrect->width : sz.x;
386 int height = subrect != NULL ? subrect->height : sz.y ;
388 wxBitmap bitmap(width, height);
390 NSView* view = (NSView*) m_window->GetHandle();
391 if ( [view isHiddenOrHasHiddenAncestor] == NO )
394 // we use this method as other methods force a repaint, and this method can be
395 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
396 NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]];
398 if ( [rep respondsToSelector:@selector(CGImage)] )
400 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
402 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
403 // since our context is upside down we dont use CGContextDrawImage
404 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
408 // TODO for 10.4 in case we can support this for osx_cocoa
418 #endif // wxOSX_USE_COCOA