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 - (void)application:(NSApplication *)sender openFiles:(NSArray *)fileNames
61 wxArrayString fileList;
63 const size_t count = [fileNames count];
64 for (i = 0; i < count; i++)
66 fileList.Add( wxCFStringRef::AsString([fileNames objectAtIndex:i]) );
69 wxTheApp->MacOpenFiles(fileList);
72 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
75 wxTheApp->MacNewFile() ;
79 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
82 wxCFStringRef cf(wxCFRetain(filename));
83 wxTheApp->MacPrintFile(cf.AsString()) ;
87 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
91 wxTheApp->MacReopenApp() ;
95 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
96 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
98 wxUnusedVar(replyEvent);
99 NSString* url = [[event descriptorAtIndex:1] stringValue];
100 wxCFStringRef cf(wxCFRetain(url));
101 wxTheApp->MacOpenURL(cf.AsString()) ;
105 Allowable return values are:
106 NSTerminateNow - it is ok to proceed with termination
107 NSTerminateCancel - the application should not be terminated
108 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
109 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
111 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
115 wxTheApp->OnQueryEndSession(event);
116 if ( event.GetVeto() )
117 return NSTerminateCancel;
119 return NSTerminateNow;
122 - (void)applicationWillTerminate:(NSNotification *)application {
123 wxUnusedVar(application);
125 event.SetCanVeto(false);
126 wxTheApp->OnEndSession(event);
129 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
132 // let wx do this, not cocoa
136 - (void)applicationDidBecomeActive:(NSNotification *)notification
138 wxUnusedVar(notification);
140 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(),
141 end = wxTopLevelWindows.end();
145 wxTopLevelWindow * const win = static_cast<wxTopLevelWindow *>(*i);
146 wxNonOwnedWindowImpl* winimpl = win ? win->GetNonOwnedPeer() : NULL;
147 WXWindow nswindow = win ? win->GetWXWindow() : nil;
149 if ( nswindow && [nswindow hidesOnDeactivate] == NO && winimpl)
150 winimpl->RestoreWindowLevel();
153 wxTheApp->SetActive( true , NULL ) ;
156 - (void)applicationWillResignActive:(NSNotification *)notification
158 wxUnusedVar(notification);
159 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(),
160 end = wxTopLevelWindows.end();
164 wxTopLevelWindow * const win = static_cast<wxTopLevelWindow *>(*i);
165 WXWindow nswindow = win ? win->GetWXWindow() : nil;
167 if ( nswindow && [nswindow level] == kCGFloatingWindowLevel && [nswindow hidesOnDeactivate] == NO )
168 [nswindow setLevel:kCGNormalWindowLevel];
172 - (void)applicationDidResignActive:(NSNotification *)notification
174 wxUnusedVar(notification);
176 wxTheApp->SetActive( false , NULL ) ;
182 allows ShowModal to work when using sheets.
183 see include/wx/osx/cocoa/private.h for more info
185 @implementation ModalDialogDelegate
195 - (void)setImplementation: (wxDialog *)dialog
202 return sheetFinished;
210 - (void)waitForSheetToFinish
212 while (!sheetFinished)
218 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
220 wxUnusedVar(contextInfo);
221 resultCode = returnCode;
223 // NSAlerts don't need nor respond to orderOut
224 if ([sheet respondsToSelector:@selector(orderOut:)])
225 [sheet orderOut: self];
228 impl->ModalFinishedCallback(sheet, returnCode);
232 bool wxApp::DoInitGui()
234 wxMacAutoreleasePool pool;
235 [NSApplication sharedApplication];
239 wxNSAppController* controller = [[wxNSAppController alloc] init];
240 [NSApp setDelegate:controller];
242 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
243 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
244 forEventClass:kInternetEventClass andEventID:kAEGetURL];
246 // calling finishLaunching so early before running the loop seems to trigger some 'MenuManager compatibility' which leads
247 // to the duplication of menus under 10.5 and a warning under 10.6
249 [NSApp finishLaunching];
255 void wxApp::DoCleanUp()
259 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
261 NSRect displayRect = [wxOSXGetMenuScreen() 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 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
328 while ((object = [enumerator nextObject])) {
329 [(NSWindow*) object disableCursorRects];
332 gMacStoredActiveCursor = gMacCurrentCursor;
333 cursor->MacInstall();
335 wxSetCursor(*cursor);
337 //else: nothing to do, already set
340 // Restore cursor to normal
341 void wxEndBusyCursor()
343 wxCHECK_RET( gs_wxBusyCursorCount > 0,
344 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
346 if (--gs_wxBusyCursorCount == 0)
348 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
351 while ((object = [enumerator nextObject])) {
352 [(NSWindow*) object enableCursorRects];
355 wxSetCursor(wxNullCursor);
357 gMacStoredActiveCursor.MacInstall();
358 gMacStoredActiveCursor = wxNullCursor;
362 // true if we're between the above two calls
365 return (gs_wxBusyCursorCount > 0);
368 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
370 // wxScreenDC is derived from wxWindowDC, so a screen dc will
371 // call this method when a Blit is performed with it as a source.
375 wxSize sz = m_window->GetSize();
377 int width = subrect != NULL ? subrect->width : sz.x;
378 int height = subrect != NULL ? subrect->height : sz.y ;
380 wxBitmap bitmap(width, height);
382 NSView* view = (NSView*) m_window->GetHandle();
383 if ( [view isHiddenOrHasHiddenAncestor] == NO )
386 // we use this method as other methods force a repaint, and this method can be
387 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
388 NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]];
390 if ( [rep respondsToSelector:@selector(CGImage)] )
392 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
394 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
395 // since our context is upside down we dont use CGContextDrawImage
396 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
400 // TODO for 10.4 in case we can support this for osx_cocoa
410 #endif // wxOSX_USE_COCOA