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