]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/utils.mm
cleaning up key handling, closes #10406
[wxWidgets.git] / src / osx / cocoa / utils.mm
CommitLineData
33e90275 1/////////////////////////////////////////////////////////////////////////////
0f9b48d1 2// Name: src/osx/cocoa/utils.mm
33e90275
SC
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
33e90275 33 #include <CoreServices/CoreServices.h>
928e7a7e 34 #include "wx/osx/dcclient.h"
33e90275
SC
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
44void wxBell()
45{
46 NSBeep();
47}
48
49// ----------------------------------------------------------------------------
50// Common Event Support
51// ----------------------------------------------------------------------------
52
53void wxMacWakeUp()
54{
03647350 55 NSEvent* wakeupEvent = [NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
80c765ac
SC
56 modifierFlags:NSAnyEventMask timestamp:0 windowNumber:0 context:nil subtype:0 data1:0 data2:0];
57 [NSApp postEvent:wakeupEvent atStart:NO];
33e90275
SC
58}
59
60#endif // wxUSE_BASE
945eac79 61
36eca861
SC
62#if wxUSE_GUI
63
c6aa5caf
SC
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{
d8207702 81 wxUnusedVar(sender);
c6aa5caf
SC
82 // let wx do this, not cocoa
83 return NO;
84}
85
86- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
87{
d8207702 88 wxUnusedVar(sender);
c6aa5caf
SC
89 wxCFStringRef cf(wxCFRetain(filename));
90 wxTheApp->MacOpenFile(cf.AsString()) ;
91 return YES;
92}
93
94- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
95{
d8207702 96 wxUnusedVar(sender);
c6aa5caf
SC
97 wxTheApp->MacNewFile() ;
98 return NO;
99}
100
101- (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
102{
d8207702 103 wxUnusedVar(sender);
c6aa5caf
SC
104 wxCFStringRef cf(wxCFRetain(filename));
105 wxTheApp->MacPrintFile(cf.AsString()) ;
106 return YES;
107}
108
945eac79 109/*
c6aa5caf
SC
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{
d8207702 118 wxUnusedVar(sender);
c6aa5caf
SC
119 wxWindow* win = wxTheApp->GetTopWindow() ;
120 if ( win )
121 {
122 wxCommandEvent exitEvent(wxEVT_COMMAND_MENU_SELECTED, wxApp::s_macExitMenuItemId);
945eac79 123 if (!win->GetEventHandler()->ProcessEvent(exitEvent))
c6aa5caf
SC
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{
d8207702
SC
135 wxUnusedVar(flag);
136 wxUnusedVar(sender);
c6aa5caf
SC
137 wxTheApp->MacReopenApp() ;
138 return NO;
139}
140
141- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
142 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
143{
d8207702 144 wxUnusedVar(replyEvent);
c6aa5caf
SC
145 NSString* url = [[event descriptorAtIndex:1] stringValue];
146 wxCFStringRef cf(wxCFRetain(url));
147 wxTheApp->MacOpenURL(cf.AsString()) ;
148}
149@end
150
03647350 151/*
724999ee 152 allows ShowModal to work when using sheets.
03647350 153 see include/wx/osx/cocoa/private.h for more info
724999ee
KO
154*/
155@implementation ModalDialogDelegate
156- (id)init
157{
158 [super init];
159 sheetFinished = NO;
160 resultCode = -1;
161 return self;
162}
163
03647350 164- (BOOL)finished
724999ee
KO
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{
d8207702 184 wxUnusedVar(contextInfo);
724999ee
KO
185 resultCode = returnCode;
186 sheetFinished = YES;
037f9d3b
KO
187 // NSAlerts don't need nor respond to orderOut
188 if ([sheet respondsToSelector:@selector(orderOut:)])
189 [sheet orderOut: self];
724999ee
KO
190}
191@end
192
dbeddfb9
SC
193bool wxApp::DoInitGui()
194{
ab9df4fb 195 wxMacAutoreleasePool pool;
dbeddfb9 196 [NSApplication sharedApplication];
c6aa5caf
SC
197
198 if (!sm_isEmbedded)
199 {
200 wxNSAppController* controller = [[wxNSAppController alloc] init];
201 [[NSApplication sharedApplication] setDelegate:controller];
945eac79 202
c6aa5caf
SC
203 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
204 [appleEventManager setEventHandler:controller andSelector:@selector(handleGetURLEvent:withReplyEvent:)
205 forEventClass:kInternetEventClass andEventID:kAEGetURL];
44ee9ed8 206 [NSApp finishLaunching];
c6aa5caf 207 }
dbeddfb9
SC
208 return true;
209}
210
211void wxApp::DoCleanUp()
212{
213}
33e90275 214
33e90275
SC
215void 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();
945eac79 227
33e90275
SC
228}
229
230void wxGetMousePosition( int* x, int* y )
231{
232 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
54f11060
SC
233 if ( x )
234 *x = pt.x;
235 if ( y )
236 *y = pt.y;
33e90275
SC
237};
238
239wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
240{
dbeddfb9 241 return new wxOSXTimerImpl(timer);
33e90275
SC
242}
243
244int gs_wxBusyCursorCount = 0;
245extern wxCursor gMacCurrentCursor;
246wxCursor gMacStoredActiveCursor;
247
248// Set the cursor to the busy cursor for all windows
249void 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
262void 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
277bool wxIsBusy()
278{
279 return (gs_wxBusyCursorCount > 0);
280}
281
928e7a7e
KO
282wxBitmap 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;
945eac79 288
928e7a7e 289 wxSize sz = m_window->GetSize();
945eac79 290
928e7a7e
KO
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 ;
945eac79 295
928e7a7e
KO
296 NSRect rect = NSMakeRect(left, top, width, height );
297 NSView* view = (NSView*) m_window->GetHandle();
298 [view lockFocus];
945eac79 299 // we use this method as other methods force a repaint, and this method can be
928e7a7e
KO
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];
03647350 303
1034a6bb
SC
304 wxBitmap bitmap(width, height);
305 if ( [rep respondsToSelector:@selector(CGImage)] )
306 {
307 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
945eac79 308
1034a6bb
SC
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 }
928e7a7e 319 [rep release];
945eac79 320
928e7a7e
KO
321 return bitmap;
322}
323
33e90275
SC
324#endif // wxUSE_GUI
325
33e90275 326#endif // wxOSX_USE_COCOA