]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/utils.mm
fix positioning bug with window disabler and hidden windows
[wxWidgets.git] / src / osx / cocoa / utils.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/cocoa/utils.mm
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
14 #include "wx/utils.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/intl.h"
18 #include "wx/app.h"
19 #if wxUSE_GUI
20 #include "wx/dialog.h"
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
32 #include <CoreServices/CoreServices.h>
33 #include "wx/osx/dcclient.h"
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
43 void wxBell()
44 {
45 NSBeep();
46 }
47
48 #endif // wxUSE_BASE
49
50 #if wxUSE_GUI
51
52 @implementation wxNSAppController
53
54 - (void)applicationWillFinishLaunching:(NSNotification *)application {
55 wxUnusedVar(application);
56 }
57
58 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
59 {
60 wxUnusedVar(sender);
61 wxCFStringRef cf(wxCFRetain(filename));
62 wxTheApp->MacOpenFile(cf.AsString()) ;
63 return YES;
64 }
65
66 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
67 {
68 wxUnusedVar(sender);
69 wxTheApp->MacNewFile() ;
70 return NO;
71 }
72
73 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
74 {
75 wxUnusedVar(sender);
76 wxCFStringRef cf(wxCFRetain(filename));
77 wxTheApp->MacPrintFile(cf.AsString()) ;
78 return YES;
79 }
80
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
98 /*
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 {
107 wxUnusedVar(sender);
108 wxCloseEvent event;
109 wxTheApp->OnQueryEndSession(event);
110 if ( event.GetVeto() )
111 return NSTerminateCancel;
112
113 return NSTerminateNow;
114 }
115
116 - (void)applicationWillTerminate:(NSNotification *)application {
117 wxUnusedVar(application);
118 wxCloseEvent event;
119 event.SetCanVeto(false);
120 wxTheApp->OnEndSession(event);
121 }
122
123 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
124 {
125 wxUnusedVar(sender);
126 // let wx do this, not cocoa
127 return NO;
128 }
129
130 @end
131
132 /*
133 allows ShowModal to work when using sheets.
134 see include/wx/osx/cocoa/private.h for more info
135 */
136 @implementation ModalDialogDelegate
137 - (id)init
138 {
139 [super init];
140 sheetFinished = NO;
141 resultCode = -1;
142 impl = 0;
143 return self;
144 }
145
146 - (void)setImplementation: (wxDialog *)dialog
147 {
148 impl = dialog;
149 }
150
151 - (BOOL)finished
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 {
171 wxUnusedVar(contextInfo);
172 resultCode = returnCode;
173 sheetFinished = YES;
174 // NSAlerts don't need nor respond to orderOut
175 if ([sheet respondsToSelector:@selector(orderOut:)])
176 [sheet orderOut: self];
177
178 if (impl)
179 impl->ModalFinishedCallback(sheet, returnCode);
180 }
181 @end
182
183 bool wxApp::DoInitGui()
184 {
185 wxMacAutoreleasePool pool;
186 [NSApplication sharedApplication];
187
188 if (!sm_isEmbedded)
189 {
190 wxNSAppController* controller = [[wxNSAppController alloc] init];
191 [NSApp setDelegate:controller];
192
193 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
194 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
195 forEventClass:kInternetEventClass andEventID:kAEGetURL];
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
200 [NSApp finishLaunching];
201 #endif
202 }
203 return true;
204 }
205
206 void wxApp::DoCleanUp()
207 {
208 }
209
210 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
211 {
212 NSRect displayRect = [wxOSXGetMenuScreen() visibleFrame];
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();
222
223 }
224
225 void wxGetMousePosition( int* x, int* y )
226 {
227 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
228 if ( x )
229 *x = pt.x;
230 if ( y )
231 *y = pt.y;
232 };
233
234 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
235
236 wxMouseState 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
262 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
263 {
264 return new wxOSXTimerImpl(timer);
265 }
266
267 int gs_wxBusyCursorCount = 0;
268 extern wxCursor gMacCurrentCursor;
269 wxCursor gMacStoredActiveCursor;
270
271 // Set the cursor to the busy cursor for all windows
272 void wxBeginBusyCursor(const wxCursor *cursor)
273 {
274 if (gs_wxBusyCursorCount++ == 0)
275 {
276 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
277 id object;
278
279 while ((object = [enumerator nextObject])) {
280 [(NSWindow*) object disableCursorRects];
281 }
282
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
292 void wxEndBusyCursor()
293 {
294 wxCHECK_RET( gs_wxBusyCursorCount > 0,
295 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
296
297 if (--gs_wxBusyCursorCount == 0)
298 {
299 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
300 id object;
301
302 while ((object = [enumerator nextObject])) {
303 [(NSWindow*) object enableCursorRects];
304 }
305
306 wxSetCursor(wxNullCursor);
307
308 gMacStoredActiveCursor.MacInstall();
309 gMacStoredActiveCursor = wxNullCursor;
310 }
311 }
312
313 // true if we're between the above two calls
314 bool wxIsBusy()
315 {
316 return (gs_wxBusyCursorCount > 0);
317 }
318
319 wxBitmap 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;
325
326 wxSize sz = m_window->GetSize();
327
328 int width = subrect != NULL ? subrect->width : sz.x;
329 int height = subrect != NULL ? subrect->height : sz.y ;
330
331 NSView* view = (NSView*) m_window->GetHandle();
332 [view lockFocus];
333 // we use this method as other methods force a repaint, and this method can be
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];
337
338 wxBitmap bitmap(width, height);
339 if ( [rep respondsToSelector:@selector(CGImage)] )
340 {
341 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
342
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 }
353 [rep release];
354
355 return bitmap;
356 }
357
358 #endif // wxUSE_GUI
359
360 #endif // wxOSX_USE_COCOA