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 wxNSAppController* appcontroller = nil;
246 bool wxApp::DoInitGui()
248 wxMacAutoreleasePool pool;
249 [NSApplication sharedApplication];
253 appcontroller = [[wxNSAppController alloc] init];
254 [NSApp setDelegate:appcontroller];
256 // calling finishLaunching so early before running the loop seems to trigger some 'MenuManager compatibility' which leads
257 // to the duplication of menus under 10.5 and a warning under 10.6
259 [NSApp finishLaunching];
265 void wxApp::DoCleanUp()
267 if ( appcontroller != nil )
269 [NSApp setDelegate:nil];
270 [appcontroller release];
275 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
277 NSRect displayRect = [wxOSXGetMenuScreen() visibleFrame];
278 wxRect r = wxFromNSRect( NULL, displayRect );
284 *width = r.GetWidth();
286 *height = r.GetHeight();
290 void wxGetMousePosition( int* x, int* y )
292 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
299 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
301 wxMouseState wxGetMouseState()
305 wxPoint pt = wxGetMousePosition();
309 NSUInteger modifiers = [NSEvent modifierFlags];
310 NSUInteger buttons = [NSEvent pressedMouseButtons];
312 ms.SetLeftDown( (buttons & 0x01) != 0 );
313 ms.SetMiddleDown( (buttons & 0x04) != 0 );
314 ms.SetRightDown( (buttons & 0x02) != 0 );
316 ms.SetRawControlDown(modifiers & NSControlKeyMask);
317 ms.SetShiftDown(modifiers & NSShiftKeyMask);
318 ms.SetAltDown(modifiers & NSAlternateKeyMask);
319 ms.SetControlDown(modifiers & NSCommandKeyMask);
327 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
329 return new wxOSXTimerImpl(timer);
332 int gs_wxBusyCursorCount = 0;
333 extern wxCursor gMacCurrentCursor;
334 wxCursor gMacStoredActiveCursor;
336 // Set the cursor to the busy cursor for all windows
337 void wxBeginBusyCursor(const wxCursor *cursor)
339 if (gs_wxBusyCursorCount++ == 0)
341 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
344 while ((object = [enumerator nextObject])) {
345 [(NSWindow*) object disableCursorRects];
348 gMacStoredActiveCursor = gMacCurrentCursor;
349 cursor->MacInstall();
351 wxSetCursor(*cursor);
353 //else: nothing to do, already set
356 // Restore cursor to normal
357 void wxEndBusyCursor()
359 wxCHECK_RET( gs_wxBusyCursorCount > 0,
360 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
362 if (--gs_wxBusyCursorCount == 0)
364 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
367 while ((object = [enumerator nextObject])) {
368 [(NSWindow*) object enableCursorRects];
371 wxSetCursor(wxNullCursor);
373 gMacStoredActiveCursor.MacInstall();
374 gMacStoredActiveCursor = wxNullCursor;
378 // true if we're between the above two calls
381 return (gs_wxBusyCursorCount > 0);
384 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
386 // wxScreenDC is derived from wxWindowDC, so a screen dc will
387 // call this method when a Blit is performed with it as a source.
391 wxSize sz = m_window->GetSize();
393 int width = subrect != NULL ? subrect->width : sz.x;
394 int height = subrect != NULL ? subrect->height : sz.y ;
396 wxBitmap bitmap(width, height);
398 NSView* view = (NSView*) m_window->GetHandle();
399 if ( [view isHiddenOrHasHiddenAncestor] == NO )
402 // we use this method as other methods force a repaint, and this method can be
403 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
404 NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]];
406 if ( [rep respondsToSelector:@selector(CGImage)] )
408 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
410 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
411 // since our context is upside down we dont use CGContextDrawImage
412 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
416 // TODO for 10.4 in case we can support this for osx_cocoa
426 #endif // wxOSX_USE_COCOA