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