]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/utils.mm
guard XTI
[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
a9a4f229 7// RCS-ID: $Id$
33e90275
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
33e90275 48#endif // wxUSE_BASE
945eac79 49
36eca861
SC
50#if wxUSE_GUI
51
c6aa5caf
SC
52@implementation wxNSAppController
53
a5d0c88a 54- (void)applicationWillFinishLaunching:(NSNotification *)application {
175e9d71 55 wxUnusedVar(application);
77aa5fa0 56
6a0d7a98
SC
57 // we must install our handlers later than setting the app delegate, because otherwise our handlers
58 // get overwritten in the meantime
77aa5fa0
SC
59
60 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
61
62 [appleEventManager setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:)
63 forEventClass:kInternetEventClass andEventID:kAEGetURL];
64
65 [appleEventManager setEventHandler:self andSelector:@selector(handleOpenAppEvent:withReplyEvent:)
66 forEventClass:kCoreEventClass andEventID:kAEOpenApplication];
67
c6aa5caf
SC
68}
69
ee7553e9 70- (void)application:(NSApplication *)sender openFiles:(NSArray *)fileNames
c6aa5caf 71{
d8207702 72 wxUnusedVar(sender);
ee7553e9
DS
73 wxArrayString fileList;
74 size_t i;
75 const size_t count = [fileNames count];
76 for (i = 0; i < count; i++)
77 {
78 fileList.Add( wxCFStringRef::AsString([fileNames objectAtIndex:i]) );
79 }
80
81 wxTheApp->MacOpenFiles(fileList);
c6aa5caf
SC
82}
83
c6aa5caf
SC
84- (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
85{
d8207702 86 wxUnusedVar(sender);
c6aa5caf
SC
87 wxCFStringRef cf(wxCFRetain(filename));
88 wxTheApp->MacPrintFile(cf.AsString()) ;
89 return YES;
90}
91
175e9d71
SC
92- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
93{
94 wxUnusedVar(flag);
95 wxUnusedVar(sender);
96 wxTheApp->MacReopenApp() ;
97 return NO;
98}
99
100- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
101 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
102{
103 wxUnusedVar(replyEvent);
104 NSString* url = [[event descriptorAtIndex:1] stringValue];
105 wxCFStringRef cf(wxCFRetain(url));
106 wxTheApp->MacOpenURL(cf.AsString()) ;
107}
108
77aa5fa0
SC
109- (void)handleOpenAppEvent:(NSAppleEventDescriptor *)event
110 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
111{
112 wxUnusedVar(replyEvent);
113 wxTheApp->MacNewFile() ;
114}
115
945eac79 116/*
c6aa5caf
SC
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.
122*/
123- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
124{
d8207702 125 wxUnusedVar(sender);
175e9d71
SC
126 wxCloseEvent event;
127 wxTheApp->OnQueryEndSession(event);
128 if ( event.GetVeto() )
129 return NSTerminateCancel;
130
131 return NSTerminateNow;
c6aa5caf
SC
132}
133
a5d0c88a 134- (void)applicationWillTerminate:(NSNotification *)application {
175e9d71
SC
135 wxUnusedVar(application);
136 wxCloseEvent event;
137 event.SetCanVeto(false);
138 wxTheApp->OnEndSession(event);
139}
140
141- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
c6aa5caf 142{
d8207702 143 wxUnusedVar(sender);
175e9d71 144 // let wx do this, not cocoa
c6aa5caf
SC
145 return NO;
146}
147
74518cea
SC
148- (void)applicationDidBecomeActive:(NSNotification *)notification
149{
150 wxUnusedVar(notification);
151
152 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(),
153 end = wxTopLevelWindows.end();
154 i != end;
155 ++i )
156 {
157 wxTopLevelWindow * const win = static_cast<wxTopLevelWindow *>(*i);
158 wxNonOwnedWindowImpl* winimpl = win ? win->GetNonOwnedPeer() : NULL;
159 WXWindow nswindow = win ? win->GetWXWindow() : nil;
160
161 if ( nswindow && [nswindow hidesOnDeactivate] == NO && winimpl)
162 winimpl->RestoreWindowLevel();
163 }
164 if ( wxTheApp )
165 wxTheApp->SetActive( true , NULL ) ;
166}
167
168- (void)applicationWillResignActive:(NSNotification *)notification
169{
170 wxUnusedVar(notification);
171 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(),
172 end = wxTopLevelWindows.end();
173 i != end;
174 ++i )
175 {
176 wxTopLevelWindow * const win = static_cast<wxTopLevelWindow *>(*i);
177 WXWindow nswindow = win ? win->GetWXWindow() : nil;
178
179 if ( nswindow && [nswindow level] == kCGFloatingWindowLevel && [nswindow hidesOnDeactivate] == NO )
180 [nswindow setLevel:kCGNormalWindowLevel];
181 }
182}
183
184- (void)applicationDidResignActive:(NSNotification *)notification
185{
186 wxUnusedVar(notification);
187 if ( wxTheApp )
188 wxTheApp->SetActive( false , NULL ) ;
189}
190
c6aa5caf
SC
191@end
192
03647350 193/*
724999ee 194 allows ShowModal to work when using sheets.
03647350 195 see include/wx/osx/cocoa/private.h for more info
724999ee
KO
196*/
197@implementation ModalDialogDelegate
198- (id)init
199{
e5062a31 200 self = [super init];
724999ee
KO
201 sheetFinished = NO;
202 resultCode = -1;
bfa92264 203 impl = 0;
724999ee
KO
204 return self;
205}
206
bfa92264
KO
207- (void)setImplementation: (wxDialog *)dialog
208{
209 impl = dialog;
210}
211
03647350 212- (BOOL)finished
724999ee
KO
213{
214 return sheetFinished;
215}
216
217- (int)code
218{
219 return resultCode;
220}
221
222- (void)waitForSheetToFinish
223{
224 while (!sheetFinished)
225 {
226 wxSafeYield();
227 }
228}
229
230- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
231{
d8207702 232 wxUnusedVar(contextInfo);
724999ee
KO
233 resultCode = returnCode;
234 sheetFinished = YES;
037f9d3b
KO
235 // NSAlerts don't need nor respond to orderOut
236 if ([sheet respondsToSelector:@selector(orderOut:)])
237 [sheet orderOut: self];
bfa92264
KO
238
239 if (impl)
240 impl->ModalFinishedCallback(sheet, returnCode);
724999ee
KO
241}
242@end
243
e1875c78
SC
244wxNSAppController* appcontroller = nil;
245
dbeddfb9
SC
246bool wxApp::DoInitGui()
247{
ab9df4fb 248 wxMacAutoreleasePool pool;
dbeddfb9 249 [NSApplication sharedApplication];
c6aa5caf
SC
250
251 if (!sm_isEmbedded)
252 {
e1875c78
SC
253 appcontroller = [[wxNSAppController alloc] init];
254 [NSApp setDelegate:appcontroller];
945eac79 255
e8f25fcf
SC
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
258#if 0
cc96f525 259 [NSApp finishLaunching];
e8f25fcf 260#endif
c6aa5caf 261 }
dbeddfb9
SC
262 return true;
263}
264
265void wxApp::DoCleanUp()
266{
e1875c78
SC
267 if ( appcontroller != nil )
268 {
269 [NSApp setDelegate:nil];
270 [appcontroller release];
271 appcontroller = nil;
272 }
dbeddfb9 273}
33e90275 274
33e90275
SC
275void wxClientDisplayRect(int *x, int *y, int *width, int *height)
276{
5d57348e 277 NSRect displayRect = [wxOSXGetMenuScreen() visibleFrame];
33e90275
SC
278 wxRect r = wxFromNSRect( NULL, displayRect );
279 if ( x )
280 *x = r.x;
281 if ( y )
282 *y = r.y;
283 if ( width )
284 *width = r.GetWidth();
285 if ( height )
286 *height = r.GetHeight();
945eac79 287
33e90275
SC
288}
289
290void wxGetMousePosition( int* x, int* y )
291{
292 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
54f11060
SC
293 if ( x )
294 *x = pt.x;
295 if ( y )
296 *y = pt.y;
33e90275
SC
297};
298
f3769d53
SC
299#if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
300
301wxMouseState wxGetMouseState()
302{
303 wxMouseState ms;
304
305 wxPoint pt = wxGetMousePosition();
306 ms.SetX(pt.x);
307 ms.SetY(pt.y);
308
309 NSUInteger modifiers = [NSEvent modifierFlags];
310 NSUInteger buttons = [NSEvent pressedMouseButtons];
311
312 ms.SetLeftDown( (buttons & 0x01) != 0 );
313 ms.SetMiddleDown( (buttons & 0x04) != 0 );
314 ms.SetRightDown( (buttons & 0x02) != 0 );
315
8b14528f 316 ms.SetRawControlDown(modifiers & NSControlKeyMask);
f3769d53
SC
317 ms.SetShiftDown(modifiers & NSShiftKeyMask);
318 ms.SetAltDown(modifiers & NSAlternateKeyMask);
dd9ec596 319 ms.SetControlDown(modifiers & NSCommandKeyMask);
f3769d53
SC
320
321 return ms;
322}
323
324
325#endif
326
33e90275
SC
327wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
328{
dbeddfb9 329 return new wxOSXTimerImpl(timer);
33e90275
SC
330}
331
332int gs_wxBusyCursorCount = 0;
333extern wxCursor gMacCurrentCursor;
334wxCursor gMacStoredActiveCursor;
335
336// Set the cursor to the busy cursor for all windows
337void wxBeginBusyCursor(const wxCursor *cursor)
338{
339 if (gs_wxBusyCursorCount++ == 0)
340 {
3ac88921
SC
341 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
342 id object;
343
344 while ((object = [enumerator nextObject])) {
345 [(NSWindow*) object disableCursorRects];
346 }
347
33e90275
SC
348 gMacStoredActiveCursor = gMacCurrentCursor;
349 cursor->MacInstall();
350
351 wxSetCursor(*cursor);
352 }
353 //else: nothing to do, already set
354}
355
356// Restore cursor to normal
357void wxEndBusyCursor()
358{
359 wxCHECK_RET( gs_wxBusyCursorCount > 0,
360 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
361
362 if (--gs_wxBusyCursorCount == 0)
363 {
3ac88921
SC
364 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
365 id object;
366
367 while ((object = [enumerator nextObject])) {
368 [(NSWindow*) object enableCursorRects];
369 }
33e90275
SC
370
371 wxSetCursor(wxNullCursor);
3ac88921
SC
372
373 gMacStoredActiveCursor.MacInstall();
374 gMacStoredActiveCursor = wxNullCursor;
33e90275
SC
375 }
376}
377
378// true if we're between the above two calls
379bool wxIsBusy()
380{
381 return (gs_wxBusyCursorCount > 0);
382}
383
928e7a7e
KO
384wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
385{
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.
388 if (!m_window)
389 return wxNullBitmap;
945eac79 390
928e7a7e 391 wxSize sz = m_window->GetSize();
945eac79 392
928e7a7e
KO
393 int width = subrect != NULL ? subrect->width : sz.x;
394 int height = subrect != NULL ? subrect->height : sz.y ;
945eac79 395
1034a6bb 396 wxBitmap bitmap(width, height);
945eac79 397
bda7c353
SC
398 NSView* view = (NSView*) m_window->GetHandle();
399 if ( [view isHiddenOrHasHiddenAncestor] == NO )
1034a6bb 400 {
bda7c353
SC
401 [view lockFocus];
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)
e5062a31 404 NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]];
bda7c353
SC
405 [view unlockFocus];
406 if ( [rep respondsToSelector:@selector(CGImage)] )
407 {
408 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
409
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 ) ;
bda7c353
SC
413 }
414 else
415 {
416 // TODO for 10.4 in case we can support this for osx_cocoa
417 }
418 [rep release];
1034a6bb 419 }
945eac79 420
928e7a7e
KO
421 return bitmap;
422}
423
33e90275
SC
424#endif // wxUSE_GUI
425
3c7eea25 426#endif // wxOSX_USE_COCOA