]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/utils.mm
simplifying code, removing outdated API
[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/wxprec.h"
15
16 #include "wx/utils.h"
17
18 #ifndef WX_PRECOMP
19 #include "wx/intl.h"
20 #include "wx/app.h"
21 #if wxUSE_GUI
22 #include "wx/toplevel.h"
23 #include "wx/font.h"
24 #endif
25 #endif
26
27 #include "wx/apptrait.h"
28
29 #include "wx/osx/private.h"
30
31 #if wxUSE_GUI
32 #if wxOSX_USE_COCOA_OR_CARBON
33 #include <CoreServices/CoreServices.h>
34 #include "wx/osx/dcclient.h"
35 #include "wx/osx/private/timer.h"
36 #endif
37 #endif // wxUSE_GUI
38
39 #if wxOSX_USE_COCOA
40
41 #if wxUSE_BASE
42
43 // Emit a beeeeeep
44 void wxBell()
45 {
46 NSBeep();
47 }
48
49 // ----------------------------------------------------------------------------
50 // Common Event Support
51 // ----------------------------------------------------------------------------
52
53 void wxMacWakeUp()
54 {
55 // ensure that we have an auto release pool in place because the event will
56 // be autoreleased from NSEvent:otherEventWithType and we might not have a
57 // global pool during startup or shutdown and we actually never have it if
58 // we're called from another thread
59 //
60 // FIXME: we can't use wxMacAutoreleasePool here because it's in core and
61 // we're in base
62 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
63
64 NSEvent* wakeupEvent = [NSEvent otherEventWithType:NSApplicationDefined
65 location:NSZeroPoint
66 modifierFlags:NSAnyEventMask
67 timestamp:0
68 windowNumber:0
69 context:nil
70 subtype:0
71 data1:0
72 data2:0];
73 [NSApp postEvent:wakeupEvent atStart:NO];
74
75 [pool release];
76 }
77
78 #endif // wxUSE_BASE
79
80 #if wxUSE_GUI
81
82 @interface wxNSAppController : NSObject wxOSX_10_6_AND_LATER(<NSApplicationDelegate>)
83 {
84 }
85
86 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender;
87 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
88 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
89 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename;
90 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
91 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
92 withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
93 @end
94
95 @implementation wxNSAppController
96
97 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
98 {
99 wxUnusedVar(sender);
100 // let wx do this, not cocoa
101 return NO;
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 /*
128 Allowable return values are:
129 NSTerminateNow - it is ok to proceed with termination
130 NSTerminateCancel - the application should not be terminated
131 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
132 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
133 */
134 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
135 {
136 wxUnusedVar(sender);
137 wxWindow* win = wxTheApp->GetTopWindow() ;
138 if ( win )
139 {
140 wxCommandEvent exitEvent(wxEVT_COMMAND_MENU_SELECTED, wxApp::s_macExitMenuItemId);
141 if (!win->GetEventHandler()->ProcessEvent(exitEvent))
142 win->Close(true) ;
143 }
144 else
145 {
146 wxTheApp->ExitMainLoop() ;
147 }
148 return NSTerminateCancel;
149 }
150
151 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
152 {
153 wxUnusedVar(flag);
154 wxUnusedVar(sender);
155 wxTheApp->MacReopenApp() ;
156 return NO;
157 }
158
159 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
160 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
161 {
162 wxUnusedVar(replyEvent);
163 NSString* url = [[event descriptorAtIndex:1] stringValue];
164 wxCFStringRef cf(wxCFRetain(url));
165 wxTheApp->MacOpenURL(cf.AsString()) ;
166 }
167 @end
168
169 /*
170 allows ShowModal to work when using sheets.
171 see include/wx/osx/cocoa/private.h for more info
172 */
173 @implementation ModalDialogDelegate
174 - (id)init
175 {
176 [super init];
177 sheetFinished = NO;
178 resultCode = -1;
179 return self;
180 }
181
182 - (BOOL)finished
183 {
184 return sheetFinished;
185 }
186
187 - (int)code
188 {
189 return resultCode;
190 }
191
192 - (void)waitForSheetToFinish
193 {
194 while (!sheetFinished)
195 {
196 wxSafeYield();
197 }
198 }
199
200 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
201 {
202 wxUnusedVar(contextInfo);
203 resultCode = returnCode;
204 sheetFinished = YES;
205 // NSAlerts don't need nor respond to orderOut
206 if ([sheet respondsToSelector:@selector(orderOut:)])
207 [sheet orderOut: self];
208 }
209 @end
210
211 bool wxApp::DoInitGui()
212 {
213 wxMacAutoreleasePool pool;
214 [NSApplication sharedApplication];
215
216 if (!sm_isEmbedded)
217 {
218 wxNSAppController* controller = [[wxNSAppController alloc] init];
219 [[NSApplication sharedApplication] setDelegate:controller];
220
221 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
222 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
223 forEventClass:kInternetEventClass andEventID:kAEGetURL];
224 [NSApp finishLaunching];
225 }
226 return true;
227 }
228
229 void wxApp::DoCleanUp()
230 {
231 }
232
233 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
234 {
235 NSRect displayRect = [[NSScreen mainScreen] visibleFrame];
236 wxRect r = wxFromNSRect( NULL, displayRect );
237 if ( x )
238 *x = r.x;
239 if ( y )
240 *y = r.y;
241 if ( width )
242 *width = r.GetWidth();
243 if ( height )
244 *height = r.GetHeight();
245
246 }
247
248 void wxGetMousePosition( int* x, int* y )
249 {
250 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
251 if ( x )
252 *x = pt.x;
253 if ( y )
254 *y = pt.y;
255 };
256
257 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
258
259 wxMouseState wxGetMouseState()
260 {
261 wxMouseState ms;
262
263 wxPoint pt = wxGetMousePosition();
264 ms.SetX(pt.x);
265 ms.SetY(pt.y);
266
267 NSUInteger modifiers = [NSEvent modifierFlags];
268 NSUInteger buttons = [NSEvent pressedMouseButtons];
269
270 ms.SetLeftDown( (buttons & 0x01) != 0 );
271 ms.SetMiddleDown( (buttons & 0x04) != 0 );
272 ms.SetRightDown( (buttons & 0x02) != 0 );
273
274 ms.SetControlDown(modifiers & NSControlKeyMask);
275 ms.SetShiftDown(modifiers & NSShiftKeyMask);
276 ms.SetAltDown(modifiers & NSAlternateKeyMask);
277 ms.SetMetaDown(modifiers & NSCommandKeyMask);
278
279 return ms;
280 }
281
282
283 #endif
284
285 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
286 {
287 return new wxOSXTimerImpl(timer);
288 }
289
290 int gs_wxBusyCursorCount = 0;
291 extern wxCursor gMacCurrentCursor;
292 wxCursor gMacStoredActiveCursor;
293
294 // Set the cursor to the busy cursor for all windows
295 void wxBeginBusyCursor(const wxCursor *cursor)
296 {
297 if (gs_wxBusyCursorCount++ == 0)
298 {
299 gMacStoredActiveCursor = gMacCurrentCursor;
300 cursor->MacInstall();
301
302 wxSetCursor(*cursor);
303 }
304 //else: nothing to do, already set
305 }
306
307 // Restore cursor to normal
308 void wxEndBusyCursor()
309 {
310 wxCHECK_RET( gs_wxBusyCursorCount > 0,
311 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
312
313 if (--gs_wxBusyCursorCount == 0)
314 {
315 gMacStoredActiveCursor.MacInstall();
316 gMacStoredActiveCursor = wxNullCursor;
317
318 wxSetCursor(wxNullCursor);
319 }
320 }
321
322 // true if we're between the above two calls
323 bool wxIsBusy()
324 {
325 return (gs_wxBusyCursorCount > 0);
326 }
327
328 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
329 {
330 // wxScreenDC is derived from wxWindowDC, so a screen dc will
331 // call this method when a Blit is performed with it as a source.
332 if (!m_window)
333 return wxNullBitmap;
334
335 wxSize sz = m_window->GetSize();
336
337 int left = subrect != NULL ? subrect->x : 0 ;
338 int top = subrect != NULL ? subrect->y : 0 ;
339 int width = subrect != NULL ? subrect->width : sz.x;
340 int height = subrect != NULL ? subrect->height : sz.y ;
341
342 NSRect rect = NSMakeRect(left, top, width, height );
343 NSView* view = (NSView*) m_window->GetHandle();
344 [view lockFocus];
345 // we use this method as other methods force a repaint, and this method can be
346 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
347 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
348 [view unlockFocus];
349
350 wxBitmap bitmap(width, height);
351 if ( [rep respondsToSelector:@selector(CGImage)] )
352 {
353 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
354
355 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
356 // since our context is upside down we dont use CGContextDrawImage
357 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
358 CGImageRelease(cgImageRef);
359 cgImageRef = NULL;
360 }
361 else
362 {
363 // TODO for 10.4 in case we can support this for osx_cocoa
364 }
365 [rep release];
366
367 return bitmap;
368 }
369
370 #endif // wxUSE_GUI
371
372 #endif // wxOSX_USE_COCOA