]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/utils.mm
add watch cursor to osx_cocoa
[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 gMacStoredActiveCursor = gMacCurrentCursor;
277 cursor->MacInstall();
278
279 wxSetCursor(*cursor);
280 }
281 //else: nothing to do, already set
282 }
283
284 // Restore cursor to normal
285 void wxEndBusyCursor()
286 {
287 wxCHECK_RET( gs_wxBusyCursorCount > 0,
288 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
289
290 if (--gs_wxBusyCursorCount == 0)
291 {
292 gMacStoredActiveCursor.MacInstall();
293 gMacStoredActiveCursor = wxNullCursor;
294
295 wxSetCursor(wxNullCursor);
296 }
297 }
298
299 // true if we're between the above two calls
300 bool wxIsBusy()
301 {
302 return (gs_wxBusyCursorCount > 0);
303 }
304
305 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
306 {
307 // wxScreenDC is derived from wxWindowDC, so a screen dc will
308 // call this method when a Blit is performed with it as a source.
309 if (!m_window)
310 return wxNullBitmap;
311
312 wxSize sz = m_window->GetSize();
313
314 int width = subrect != NULL ? subrect->width : sz.x;
315 int height = subrect != NULL ? subrect->height : sz.y ;
316
317 NSView* view = (NSView*) m_window->GetHandle();
318 [view lockFocus];
319 // we use this method as other methods force a repaint, and this method can be
320 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
321 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
322 [view unlockFocus];
323
324 wxBitmap bitmap(width, height);
325 if ( [rep respondsToSelector:@selector(CGImage)] )
326 {
327 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
328
329 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
330 // since our context is upside down we dont use CGContextDrawImage
331 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
332 CGImageRelease(cgImageRef);
333 cgImageRef = NULL;
334 }
335 else
336 {
337 // TODO for 10.4 in case we can support this for osx_cocoa
338 }
339 [rep release];
340
341 return bitmap;
342 }
343
344 #endif // wxUSE_GUI
345
346 #endif // wxOSX_USE_COCOA