]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/utils.mm
Get ShowWindowModal behavior working under OS X Cocoa for file, dir and message dialogs.
[wxWidgets.git] / src / osx / cocoa / utils.mm
CommitLineData
33e90275 1/////////////////////////////////////////////////////////////////////////////
0f9b48d1 2// Name: src/osx/cocoa/utils.mm
33e90275
SC
3// Purpose: various cocoa utility functions
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
7// RCS-ID: $Id: utils.mm 48805 2007-09-19 14:52:25Z SC $
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
33e90275
SC
14#include "wx/utils.h"
15
16#ifndef WX_PRECOMP
17 #include "wx/intl.h"
18 #include "wx/app.h"
19 #if wxUSE_GUI
bfa92264 20 #include "wx/dialog.h"
33e90275
SC
21 #include "wx/toplevel.h"
22 #include "wx/font.h"
23 #endif
24#endif
25
26#include "wx/apptrait.h"
27
28#include "wx/osx/private.h"
29
30#if wxUSE_GUI
31#if wxOSX_USE_COCOA_OR_CARBON
33e90275 32 #include <CoreServices/CoreServices.h>
928e7a7e 33 #include "wx/osx/dcclient.h"
33e90275
SC
34 #include "wx/osx/private/timer.h"
35#endif
36#endif // wxUSE_GUI
37
38#if wxOSX_USE_COCOA
39
40#if wxUSE_BASE
41
42// Emit a beeeeeep
43void wxBell()
44{
45 NSBeep();
46}
47
48// ----------------------------------------------------------------------------
49// Common Event Support
50// ----------------------------------------------------------------------------
51
52void wxMacWakeUp()
53{
3c7eea25
VZ
54 // ensure that we have an auto release pool in place because the event will
55 // be autoreleased from NSEvent:otherEventWithType and we might not have a
56 // global pool during startup or shutdown and we actually never have it if
57 // we're called from another thread
58 //
59 // FIXME: we can't use wxMacAutoreleasePool here because it's in core and
60 // we're in base
61 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
62
63 NSEvent* wakeupEvent = [NSEvent otherEventWithType:NSApplicationDefined
64 location:NSZeroPoint
65 modifierFlags:NSAnyEventMask
66 timestamp:0
67 windowNumber:0
68 context:nil
69 subtype:0
70 data1:0
71 data2:0];
72 [NSApp postEvent:wakeupEvent atStart:NO];
73
74 [pool release];
33e90275
SC
75}
76
77#endif // wxUSE_BASE
945eac79 78
36eca861
SC
79#if wxUSE_GUI
80
c8fdb345 81@interface wxNSAppController : NSObject wxOSX_10_6_AND_LATER(<NSApplicationDelegate>)
c6aa5caf
SC
82{
83}
84
85- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender;
86- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
87- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
88- (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename;
89- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
90- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
91 withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
92@end
93
94@implementation wxNSAppController
95
96- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
97{
d8207702 98 wxUnusedVar(sender);
c6aa5caf
SC
99 // let wx do this, not cocoa
100 return NO;
101}
102
103- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
104{
d8207702 105 wxUnusedVar(sender);
c6aa5caf
SC
106 wxCFStringRef cf(wxCFRetain(filename));
107 wxTheApp->MacOpenFile(cf.AsString()) ;
108 return YES;
109}
110
111- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
112{
d8207702 113 wxUnusedVar(sender);
c6aa5caf
SC
114 wxTheApp->MacNewFile() ;
115 return NO;
116}
117
118- (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
119{
d8207702 120 wxUnusedVar(sender);
c6aa5caf
SC
121 wxCFStringRef cf(wxCFRetain(filename));
122 wxTheApp->MacPrintFile(cf.AsString()) ;
123 return YES;
124}
125
945eac79 126/*
c6aa5caf
SC
127 Allowable return values are:
128 NSTerminateNow - it is ok to proceed with termination
129 NSTerminateCancel - the application should not be terminated
130 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
131 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
132*/
133- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
134{
d8207702 135 wxUnusedVar(sender);
c6aa5caf
SC
136 wxWindow* win = wxTheApp->GetTopWindow() ;
137 if ( win )
138 {
139 wxCommandEvent exitEvent(wxEVT_COMMAND_MENU_SELECTED, wxApp::s_macExitMenuItemId);
945eac79 140 if (!win->GetEventHandler()->ProcessEvent(exitEvent))
c6aa5caf
SC
141 win->Close(true) ;
142 }
143 else
144 {
145 wxTheApp->ExitMainLoop() ;
146 }
147 return NSTerminateCancel;
148}
149
150- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
151{
d8207702
SC
152 wxUnusedVar(flag);
153 wxUnusedVar(sender);
c6aa5caf
SC
154 wxTheApp->MacReopenApp() ;
155 return NO;
156}
157
158- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
159 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
160{
d8207702 161 wxUnusedVar(replyEvent);
c6aa5caf
SC
162 NSString* url = [[event descriptorAtIndex:1] stringValue];
163 wxCFStringRef cf(wxCFRetain(url));
164 wxTheApp->MacOpenURL(cf.AsString()) ;
165}
166@end
167
03647350 168/*
724999ee 169 allows ShowModal to work when using sheets.
03647350 170 see include/wx/osx/cocoa/private.h for more info
724999ee
KO
171*/
172@implementation ModalDialogDelegate
173- (id)init
174{
175 [super init];
176 sheetFinished = NO;
177 resultCode = -1;
bfa92264 178 impl = 0;
724999ee
KO
179 return self;
180}
181
bfa92264
KO
182- (void)setImplementation: (wxDialog *)dialog
183{
184 impl = dialog;
185}
186
03647350 187- (BOOL)finished
724999ee
KO
188{
189 return sheetFinished;
190}
191
192- (int)code
193{
194 return resultCode;
195}
196
197- (void)waitForSheetToFinish
198{
199 while (!sheetFinished)
200 {
201 wxSafeYield();
202 }
203}
204
205- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
206{
d8207702 207 wxUnusedVar(contextInfo);
724999ee
KO
208 resultCode = returnCode;
209 sheetFinished = YES;
037f9d3b
KO
210 // NSAlerts don't need nor respond to orderOut
211 if ([sheet respondsToSelector:@selector(orderOut:)])
212 [sheet orderOut: self];
bfa92264
KO
213
214 if (impl)
215 impl->ModalFinishedCallback(sheet, returnCode);
724999ee
KO
216}
217@end
218
dbeddfb9
SC
219bool wxApp::DoInitGui()
220{
ab9df4fb 221 wxMacAutoreleasePool pool;
dbeddfb9 222 [NSApplication sharedApplication];
c6aa5caf
SC
223
224 if (!sm_isEmbedded)
225 {
226 wxNSAppController* controller = [[wxNSAppController alloc] init];
227 [[NSApplication sharedApplication] setDelegate:controller];
945eac79 228
c6aa5caf
SC
229 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
230 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
231 forEventClass:kInternetEventClass andEventID:kAEGetURL];
44ee9ed8 232 [NSApp finishLaunching];
c6aa5caf 233 }
dbeddfb9
SC
234 return true;
235}
236
237void wxApp::DoCleanUp()
238{
239}
33e90275 240
33e90275
SC
241void wxClientDisplayRect(int *x, int *y, int *width, int *height)
242{
243 NSRect displayRect = [[NSScreen mainScreen] visibleFrame];
244 wxRect r = wxFromNSRect( NULL, displayRect );
245 if ( x )
246 *x = r.x;
247 if ( y )
248 *y = r.y;
249 if ( width )
250 *width = r.GetWidth();
251 if ( height )
252 *height = r.GetHeight();
945eac79 253
33e90275
SC
254}
255
256void wxGetMousePosition( int* x, int* y )
257{
258 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
54f11060
SC
259 if ( x )
260 *x = pt.x;
261 if ( y )
262 *y = pt.y;
33e90275
SC
263};
264
f3769d53
SC
265#if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
266
267wxMouseState wxGetMouseState()
268{
269 wxMouseState ms;
270
271 wxPoint pt = wxGetMousePosition();
272 ms.SetX(pt.x);
273 ms.SetY(pt.y);
274
275 NSUInteger modifiers = [NSEvent modifierFlags];
276 NSUInteger buttons = [NSEvent pressedMouseButtons];
277
278 ms.SetLeftDown( (buttons & 0x01) != 0 );
279 ms.SetMiddleDown( (buttons & 0x04) != 0 );
280 ms.SetRightDown( (buttons & 0x02) != 0 );
281
282 ms.SetControlDown(modifiers & NSControlKeyMask);
283 ms.SetShiftDown(modifiers & NSShiftKeyMask);
284 ms.SetAltDown(modifiers & NSAlternateKeyMask);
285 ms.SetMetaDown(modifiers & NSCommandKeyMask);
286
287 return ms;
288}
289
290
291#endif
292
33e90275
SC
293wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
294{
dbeddfb9 295 return new wxOSXTimerImpl(timer);
33e90275
SC
296}
297
298int gs_wxBusyCursorCount = 0;
299extern wxCursor gMacCurrentCursor;
300wxCursor gMacStoredActiveCursor;
301
302// Set the cursor to the busy cursor for all windows
303void wxBeginBusyCursor(const wxCursor *cursor)
304{
305 if (gs_wxBusyCursorCount++ == 0)
306 {
307 gMacStoredActiveCursor = gMacCurrentCursor;
308 cursor->MacInstall();
309
310 wxSetCursor(*cursor);
311 }
312 //else: nothing to do, already set
313}
314
315// Restore cursor to normal
316void wxEndBusyCursor()
317{
318 wxCHECK_RET( gs_wxBusyCursorCount > 0,
319 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
320
321 if (--gs_wxBusyCursorCount == 0)
322 {
323 gMacStoredActiveCursor.MacInstall();
324 gMacStoredActiveCursor = wxNullCursor;
325
326 wxSetCursor(wxNullCursor);
327 }
328}
329
330// true if we're between the above two calls
331bool wxIsBusy()
332{
333 return (gs_wxBusyCursorCount > 0);
334}
335
928e7a7e
KO
336wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
337{
338 // wxScreenDC is derived from wxWindowDC, so a screen dc will
339 // call this method when a Blit is performed with it as a source.
340 if (!m_window)
341 return wxNullBitmap;
945eac79 342
928e7a7e 343 wxSize sz = m_window->GetSize();
945eac79 344
928e7a7e
KO
345 int left = subrect != NULL ? subrect->x : 0 ;
346 int top = subrect != NULL ? subrect->y : 0 ;
347 int width = subrect != NULL ? subrect->width : sz.x;
348 int height = subrect != NULL ? subrect->height : sz.y ;
945eac79 349
928e7a7e
KO
350 NSRect rect = NSMakeRect(left, top, width, height );
351 NSView* view = (NSView*) m_window->GetHandle();
352 [view lockFocus];
945eac79 353 // we use this method as other methods force a repaint, and this method can be
928e7a7e
KO
354 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
355 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
356 [view unlockFocus];
03647350 357
1034a6bb
SC
358 wxBitmap bitmap(width, height);
359 if ( [rep respondsToSelector:@selector(CGImage)] )
360 {
361 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
945eac79 362
1034a6bb
SC
363 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
364 // since our context is upside down we dont use CGContextDrawImage
365 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
366 CGImageRelease(cgImageRef);
367 cgImageRef = NULL;
368 }
369 else
370 {
371 // TODO for 10.4 in case we can support this for osx_cocoa
372 }
928e7a7e 373 [rep release];
945eac79 374
928e7a7e
KO
375 return bitmap;
376}
377
33e90275
SC
378#endif // wxUSE_GUI
379
3c7eea25 380#endif // wxOSX_USE_COCOA