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