]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/utils.mm
fix positioning bug with window disabler and hidden windows
[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
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);
c6aa5caf
SC
56}
57
dbbb040c 58- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
c6aa5caf 59{
d8207702 60 wxUnusedVar(sender);
c6aa5caf
SC
61 wxCFStringRef cf(wxCFRetain(filename));
62 wxTheApp->MacOpenFile(cf.AsString()) ;
63 return YES;
64}
65
dbbb040c 66- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
c6aa5caf 67{
d8207702 68 wxUnusedVar(sender);
c6aa5caf
SC
69 wxTheApp->MacNewFile() ;
70 return NO;
71}
72
73- (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
74{
d8207702 75 wxUnusedVar(sender);
c6aa5caf
SC
76 wxCFStringRef cf(wxCFRetain(filename));
77 wxTheApp->MacPrintFile(cf.AsString()) ;
78 return YES;
79}
80
175e9d71
SC
81- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
82{
83 wxUnusedVar(flag);
84 wxUnusedVar(sender);
85 wxTheApp->MacReopenApp() ;
86 return NO;
87}
88
89- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
90 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
91{
92 wxUnusedVar(replyEvent);
93 NSString* url = [[event descriptorAtIndex:1] stringValue];
94 wxCFStringRef cf(wxCFRetain(url));
95 wxTheApp->MacOpenURL(cf.AsString()) ;
96}
97
945eac79 98/*
c6aa5caf
SC
99 Allowable return values are:
100 NSTerminateNow - it is ok to proceed with termination
101 NSTerminateCancel - the application should not be terminated
102 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
103 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
104*/
105- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
106{
d8207702 107 wxUnusedVar(sender);
175e9d71
SC
108 wxCloseEvent event;
109 wxTheApp->OnQueryEndSession(event);
110 if ( event.GetVeto() )
111 return NSTerminateCancel;
112
113 return NSTerminateNow;
c6aa5caf
SC
114}
115
a5d0c88a 116- (void)applicationWillTerminate:(NSNotification *)application {
175e9d71
SC
117 wxUnusedVar(application);
118 wxCloseEvent event;
119 event.SetCanVeto(false);
120 wxTheApp->OnEndSession(event);
121}
122
123- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
c6aa5caf 124{
d8207702 125 wxUnusedVar(sender);
175e9d71 126 // let wx do this, not cocoa
c6aa5caf
SC
127 return NO;
128}
129
c6aa5caf
SC
130@end
131
03647350 132/*
724999ee 133 allows ShowModal to work when using sheets.
03647350 134 see include/wx/osx/cocoa/private.h for more info
724999ee
KO
135*/
136@implementation ModalDialogDelegate
137- (id)init
138{
139 [super init];
140 sheetFinished = NO;
141 resultCode = -1;
bfa92264 142 impl = 0;
724999ee
KO
143 return self;
144}
145
bfa92264
KO
146- (void)setImplementation: (wxDialog *)dialog
147{
148 impl = dialog;
149}
150
03647350 151- (BOOL)finished
724999ee
KO
152{
153 return sheetFinished;
154}
155
156- (int)code
157{
158 return resultCode;
159}
160
161- (void)waitForSheetToFinish
162{
163 while (!sheetFinished)
164 {
165 wxSafeYield();
166 }
167}
168
169- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
170{
d8207702 171 wxUnusedVar(contextInfo);
724999ee
KO
172 resultCode = returnCode;
173 sheetFinished = YES;
037f9d3b
KO
174 // NSAlerts don't need nor respond to orderOut
175 if ([sheet respondsToSelector:@selector(orderOut:)])
176 [sheet orderOut: self];
bfa92264
KO
177
178 if (impl)
179 impl->ModalFinishedCallback(sheet, returnCode);
724999ee
KO
180}
181@end
182
dbeddfb9
SC
183bool wxApp::DoInitGui()
184{
ab9df4fb 185 wxMacAutoreleasePool pool;
dbeddfb9 186 [NSApplication sharedApplication];
c6aa5caf
SC
187
188 if (!sm_isEmbedded)
189 {
190 wxNSAppController* controller = [[wxNSAppController alloc] init];
cc96f525 191 [NSApp setDelegate:controller];
945eac79 192
c6aa5caf
SC
193 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
194 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
195 forEventClass:kInternetEventClass andEventID:kAEGetURL];
e8f25fcf
SC
196
197 // calling finishLaunching so early before running the loop seems to trigger some 'MenuManager compatibility' which leads
198 // to the duplication of menus under 10.5 and a warning under 10.6
199#if 0
cc96f525 200 [NSApp finishLaunching];
e8f25fcf 201#endif
c6aa5caf 202 }
dbeddfb9
SC
203 return true;
204}
205
206void wxApp::DoCleanUp()
207{
208}
33e90275 209
33e90275
SC
210void wxClientDisplayRect(int *x, int *y, int *width, int *height)
211{
5d57348e 212 NSRect displayRect = [wxOSXGetMenuScreen() visibleFrame];
33e90275
SC
213 wxRect r = wxFromNSRect( NULL, displayRect );
214 if ( x )
215 *x = r.x;
216 if ( y )
217 *y = r.y;
218 if ( width )
219 *width = r.GetWidth();
220 if ( height )
221 *height = r.GetHeight();
945eac79 222
33e90275
SC
223}
224
225void wxGetMousePosition( int* x, int* y )
226{
227 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
54f11060
SC
228 if ( x )
229 *x = pt.x;
230 if ( y )
231 *y = pt.y;
33e90275
SC
232};
233
f3769d53
SC
234#if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
235
236wxMouseState wxGetMouseState()
237{
238 wxMouseState ms;
239
240 wxPoint pt = wxGetMousePosition();
241 ms.SetX(pt.x);
242 ms.SetY(pt.y);
243
244 NSUInteger modifiers = [NSEvent modifierFlags];
245 NSUInteger buttons = [NSEvent pressedMouseButtons];
246
247 ms.SetLeftDown( (buttons & 0x01) != 0 );
248 ms.SetMiddleDown( (buttons & 0x04) != 0 );
249 ms.SetRightDown( (buttons & 0x02) != 0 );
250
251 ms.SetControlDown(modifiers & NSControlKeyMask);
252 ms.SetShiftDown(modifiers & NSShiftKeyMask);
253 ms.SetAltDown(modifiers & NSAlternateKeyMask);
254 ms.SetMetaDown(modifiers & NSCommandKeyMask);
255
256 return ms;
257}
258
259
260#endif
261
33e90275
SC
262wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
263{
dbeddfb9 264 return new wxOSXTimerImpl(timer);
33e90275
SC
265}
266
267int gs_wxBusyCursorCount = 0;
268extern wxCursor gMacCurrentCursor;
269wxCursor gMacStoredActiveCursor;
270
271// Set the cursor to the busy cursor for all windows
272void wxBeginBusyCursor(const wxCursor *cursor)
273{
274 if (gs_wxBusyCursorCount++ == 0)
275 {
3ac88921
SC
276 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
277 id object;
278
279 while ((object = [enumerator nextObject])) {
280 [(NSWindow*) object disableCursorRects];
281 }
282
33e90275
SC
283 gMacStoredActiveCursor = gMacCurrentCursor;
284 cursor->MacInstall();
285
286 wxSetCursor(*cursor);
287 }
288 //else: nothing to do, already set
289}
290
291// Restore cursor to normal
292void wxEndBusyCursor()
293{
294 wxCHECK_RET( gs_wxBusyCursorCount > 0,
295 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
296
297 if (--gs_wxBusyCursorCount == 0)
298 {
3ac88921
SC
299 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
300 id object;
301
302 while ((object = [enumerator nextObject])) {
303 [(NSWindow*) object enableCursorRects];
304 }
33e90275
SC
305
306 wxSetCursor(wxNullCursor);
3ac88921
SC
307
308 gMacStoredActiveCursor.MacInstall();
309 gMacStoredActiveCursor = wxNullCursor;
33e90275
SC
310 }
311}
312
313// true if we're between the above two calls
314bool wxIsBusy()
315{
316 return (gs_wxBusyCursorCount > 0);
317}
318
928e7a7e
KO
319wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
320{
321 // wxScreenDC is derived from wxWindowDC, so a screen dc will
322 // call this method when a Blit is performed with it as a source.
323 if (!m_window)
324 return wxNullBitmap;
945eac79 325
928e7a7e 326 wxSize sz = m_window->GetSize();
945eac79 327
928e7a7e
KO
328 int width = subrect != NULL ? subrect->width : sz.x;
329 int height = subrect != NULL ? subrect->height : sz.y ;
945eac79 330
928e7a7e
KO
331 NSView* view = (NSView*) m_window->GetHandle();
332 [view lockFocus];
945eac79 333 // we use this method as other methods force a repaint, and this method can be
928e7a7e
KO
334 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
335 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
336 [view unlockFocus];
03647350 337
1034a6bb
SC
338 wxBitmap bitmap(width, height);
339 if ( [rep respondsToSelector:@selector(CGImage)] )
340 {
341 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
945eac79 342
1034a6bb
SC
343 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
344 // since our context is upside down we dont use CGContextDrawImage
345 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
346 CGImageRelease(cgImageRef);
347 cgImageRef = NULL;
348 }
349 else
350 {
351 // TODO for 10.4 in case we can support this for osx_cocoa
352 }
928e7a7e 353 [rep release];
945eac79 354
928e7a7e
KO
355 return bitmap;
356}
357
33e90275
SC
358#endif // wxUSE_GUI
359
3c7eea25 360#endif // wxOSX_USE_COCOA