]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/utils.mm
cleaning up key handling, closes #10406
[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 NSEvent* wakeupEvent = [NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
56 modifierFlags:NSAnyEventMask timestamp:0 windowNumber:0 context:nil subtype:0 data1:0 data2:0];
57 [NSApp postEvent:wakeupEvent atStart:NO];
58 }
59
60 #endif // wxUSE_BASE
61
62 #if wxUSE_GUI
63
64 @interface wxNSAppController : NSObject
65 {
66 }
67
68 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender;
69 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
70 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
71 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename;
72 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
73 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
74 withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
75 @end
76
77 @implementation wxNSAppController
78
79 - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
80 {
81 wxUnusedVar(sender);
82 // let wx do this, not cocoa
83 return NO;
84 }
85
86 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
87 {
88 wxUnusedVar(sender);
89 wxCFStringRef cf(wxCFRetain(filename));
90 wxTheApp->MacOpenFile(cf.AsString()) ;
91 return YES;
92 }
93
94 - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
95 {
96 wxUnusedVar(sender);
97 wxTheApp->MacNewFile() ;
98 return NO;
99 }
100
101 - (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
102 {
103 wxUnusedVar(sender);
104 wxCFStringRef cf(wxCFRetain(filename));
105 wxTheApp->MacPrintFile(cf.AsString()) ;
106 return YES;
107 }
108
109 /*
110 Allowable return values are:
111 NSTerminateNow - it is ok to proceed with termination
112 NSTerminateCancel - the application should not be terminated
113 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
114 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
115 */
116 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
117 {
118 wxUnusedVar(sender);
119 wxWindow* win = wxTheApp->GetTopWindow() ;
120 if ( win )
121 {
122 wxCommandEvent exitEvent(wxEVT_COMMAND_MENU_SELECTED, wxApp::s_macExitMenuItemId);
123 if (!win->GetEventHandler()->ProcessEvent(exitEvent))
124 win->Close(true) ;
125 }
126 else
127 {
128 wxTheApp->ExitMainLoop() ;
129 }
130 return NSTerminateCancel;
131 }
132
133 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
134 {
135 wxUnusedVar(flag);
136 wxUnusedVar(sender);
137 wxTheApp->MacReopenApp() ;
138 return NO;
139 }
140
141 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
142 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
143 {
144 wxUnusedVar(replyEvent);
145 NSString* url = [[event descriptorAtIndex:1] stringValue];
146 wxCFStringRef cf(wxCFRetain(url));
147 wxTheApp->MacOpenURL(cf.AsString()) ;
148 }
149 @end
150
151 /*
152 allows ShowModal to work when using sheets.
153 see include/wx/osx/cocoa/private.h for more info
154 */
155 @implementation ModalDialogDelegate
156 - (id)init
157 {
158 [super init];
159 sheetFinished = NO;
160 resultCode = -1;
161 return self;
162 }
163
164 - (BOOL)finished
165 {
166 return sheetFinished;
167 }
168
169 - (int)code
170 {
171 return resultCode;
172 }
173
174 - (void)waitForSheetToFinish
175 {
176 while (!sheetFinished)
177 {
178 wxSafeYield();
179 }
180 }
181
182 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
183 {
184 wxUnusedVar(contextInfo);
185 resultCode = returnCode;
186 sheetFinished = YES;
187 // NSAlerts don't need nor respond to orderOut
188 if ([sheet respondsToSelector:@selector(orderOut:)])
189 [sheet orderOut: self];
190 }
191 @end
192
193 bool wxApp::DoInitGui()
194 {
195 wxMacAutoreleasePool pool;
196 [NSApplication sharedApplication];
197
198 if (!sm_isEmbedded)
199 {
200 wxNSAppController* controller = [[wxNSAppController alloc] init];
201 [[NSApplication sharedApplication] setDelegate:controller];
202
203 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
204 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
205 forEventClass:kInternetEventClass andEventID:kAEGetURL];
206 [NSApp finishLaunching];
207 }
208 return true;
209 }
210
211 void wxApp::DoCleanUp()
212 {
213 }
214
215 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
216 {
217 NSRect displayRect = [[NSScreen mainScreen] visibleFrame];
218 wxRect r = wxFromNSRect( NULL, displayRect );
219 if ( x )
220 *x = r.x;
221 if ( y )
222 *y = r.y;
223 if ( width )
224 *width = r.GetWidth();
225 if ( height )
226 *height = r.GetHeight();
227
228 }
229
230 void wxGetMousePosition( int* x, int* y )
231 {
232 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
233 if ( x )
234 *x = pt.x;
235 if ( y )
236 *y = pt.y;
237 };
238
239 wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
240 {
241 return new wxOSXTimerImpl(timer);
242 }
243
244 int gs_wxBusyCursorCount = 0;
245 extern wxCursor gMacCurrentCursor;
246 wxCursor gMacStoredActiveCursor;
247
248 // Set the cursor to the busy cursor for all windows
249 void wxBeginBusyCursor(const wxCursor *cursor)
250 {
251 if (gs_wxBusyCursorCount++ == 0)
252 {
253 gMacStoredActiveCursor = gMacCurrentCursor;
254 cursor->MacInstall();
255
256 wxSetCursor(*cursor);
257 }
258 //else: nothing to do, already set
259 }
260
261 // Restore cursor to normal
262 void wxEndBusyCursor()
263 {
264 wxCHECK_RET( gs_wxBusyCursorCount > 0,
265 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
266
267 if (--gs_wxBusyCursorCount == 0)
268 {
269 gMacStoredActiveCursor.MacInstall();
270 gMacStoredActiveCursor = wxNullCursor;
271
272 wxSetCursor(wxNullCursor);
273 }
274 }
275
276 // true if we're between the above two calls
277 bool wxIsBusy()
278 {
279 return (gs_wxBusyCursorCount > 0);
280 }
281
282 wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
283 {
284 // wxScreenDC is derived from wxWindowDC, so a screen dc will
285 // call this method when a Blit is performed with it as a source.
286 if (!m_window)
287 return wxNullBitmap;
288
289 wxSize sz = m_window->GetSize();
290
291 int left = subrect != NULL ? subrect->x : 0 ;
292 int top = subrect != NULL ? subrect->y : 0 ;
293 int width = subrect != NULL ? subrect->width : sz.x;
294 int height = subrect != NULL ? subrect->height : sz.y ;
295
296 NSRect rect = NSMakeRect(left, top, width, height );
297 NSView* view = (NSView*) m_window->GetHandle();
298 [view lockFocus];
299 // we use this method as other methods force a repaint, and this method can be
300 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
301 NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]] retain];
302 [view unlockFocus];
303
304 wxBitmap bitmap(width, height);
305 if ( [rep respondsToSelector:@selector(CGImage)] )
306 {
307 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
308
309 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
310 // since our context is upside down we dont use CGContextDrawImage
311 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
312 CGImageRelease(cgImageRef);
313 cgImageRef = NULL;
314 }
315 else
316 {
317 // TODO for 10.4 in case we can support this for osx_cocoa
318 }
319 [rep release];
320
321 return bitmap;
322 }
323
324 #endif // wxUSE_GUI
325
326 #endif // wxOSX_USE_COCOA