]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/utils.mm
Enable the wxMediaCtrl backend for wxOSX-cocoa in the build and fix some bugs that...
[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
a9a4f229 7// RCS-ID: $Id$
33e90275
SC
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
33e90275
SC
14#include "wx/utils.h"
15
16#ifndef WX_PRECOMP
17 #include "wx/intl.h"
18 #include "wx/app.h"
19 #if wxUSE_GUI
bfa92264 20 #include "wx/dialog.h"
33e90275
SC
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
33e90275 32 #include <CoreServices/CoreServices.h>
928e7a7e 33 #include "wx/osx/dcclient.h"
33e90275
SC
34 #include "wx/osx/private/timer.h"
35#endif
36#endif // wxUSE_GUI
37
38#if wxOSX_USE_COCOA
39
598fe99d 40#if wxUSE_GUI
33e90275
SC
41
42// Emit a beeeeeep
43void wxBell()
44{
45 NSBeep();
46}
47
c6aa5caf
SC
48@implementation wxNSAppController
49
a5d0c88a 50- (void)applicationWillFinishLaunching:(NSNotification *)application {
175e9d71 51 wxUnusedVar(application);
77aa5fa0 52
6a0d7a98
SC
53 // we must install our handlers later than setting the app delegate, because otherwise our handlers
54 // get overwritten in the meantime
77aa5fa0
SC
55
56 NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
57
58 [appleEventManager setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:)
59 forEventClass:kInternetEventClass andEventID:kAEGetURL];
60
61 [appleEventManager setEventHandler:self andSelector:@selector(handleOpenAppEvent:withReplyEvent:)
62 forEventClass:kCoreEventClass andEventID:kAEOpenApplication];
63
c6aa5caf
SC
64}
65
ee7553e9 66- (void)application:(NSApplication *)sender openFiles:(NSArray *)fileNames
c6aa5caf 67{
d8207702 68 wxUnusedVar(sender);
ee7553e9
DS
69 wxArrayString fileList;
70 size_t i;
71 const size_t count = [fileNames count];
72 for (i = 0; i < count; i++)
73 {
74 fileList.Add( wxCFStringRef::AsString([fileNames objectAtIndex:i]) );
75 }
76
77 wxTheApp->MacOpenFiles(fileList);
c6aa5caf
SC
78}
79
c6aa5caf
SC
80- (BOOL)application:(NSApplication *)sender printFile:(NSString *)filename
81{
d8207702 82 wxUnusedVar(sender);
c6aa5caf
SC
83 wxCFStringRef cf(wxCFRetain(filename));
84 wxTheApp->MacPrintFile(cf.AsString()) ;
85 return YES;
86}
87
175e9d71
SC
88- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
89{
90 wxUnusedVar(flag);
91 wxUnusedVar(sender);
92 wxTheApp->MacReopenApp() ;
93 return NO;
94}
95
96- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
97 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
98{
99 wxUnusedVar(replyEvent);
100 NSString* url = [[event descriptorAtIndex:1] stringValue];
101 wxCFStringRef cf(wxCFRetain(url));
102 wxTheApp->MacOpenURL(cf.AsString()) ;
103}
104
77aa5fa0
SC
105- (void)handleOpenAppEvent:(NSAppleEventDescriptor *)event
106 withReplyEvent:(NSAppleEventDescriptor *)replyEvent
107{
108 wxUnusedVar(replyEvent);
109 wxTheApp->MacNewFile() ;
110}
111
945eac79 112/*
c6aa5caf
SC
113 Allowable return values are:
114 NSTerminateNow - it is ok to proceed with termination
115 NSTerminateCancel - the application should not be terminated
116 NSTerminateLater - it may be ok to proceed with termination later. The application must call -replyToApplicationShouldTerminate: with YES or NO once the answer is known
117 this return value is for delegates who need to provide document modal alerts (sheets) in order to decide whether to quit.
118*/
119- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
120{
d8207702 121 wxUnusedVar(sender);
175e9d71
SC
122 wxCloseEvent event;
123 wxTheApp->OnQueryEndSession(event);
124 if ( event.GetVeto() )
125 return NSTerminateCancel;
126
127 return NSTerminateNow;
c6aa5caf
SC
128}
129
a5d0c88a 130- (void)applicationWillTerminate:(NSNotification *)application {
175e9d71
SC
131 wxUnusedVar(application);
132 wxCloseEvent event;
133 event.SetCanVeto(false);
134 wxTheApp->OnEndSession(event);
135}
136
137- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
c6aa5caf 138{
d8207702 139 wxUnusedVar(sender);
175e9d71 140 // let wx do this, not cocoa
c6aa5caf
SC
141 return NO;
142}
143
74518cea
SC
144- (void)applicationDidBecomeActive:(NSNotification *)notification
145{
146 wxUnusedVar(notification);
147
148 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(),
149 end = wxTopLevelWindows.end();
150 i != end;
151 ++i )
152 {
153 wxTopLevelWindow * const win = static_cast<wxTopLevelWindow *>(*i);
154 wxNonOwnedWindowImpl* winimpl = win ? win->GetNonOwnedPeer() : NULL;
155 WXWindow nswindow = win ? win->GetWXWindow() : nil;
156
157 if ( nswindow && [nswindow hidesOnDeactivate] == NO && winimpl)
158 winimpl->RestoreWindowLevel();
159 }
160 if ( wxTheApp )
161 wxTheApp->SetActive( true , NULL ) ;
162}
163
164- (void)applicationWillResignActive:(NSNotification *)notification
165{
166 wxUnusedVar(notification);
167 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin(),
168 end = wxTopLevelWindows.end();
169 i != end;
170 ++i )
171 {
172 wxTopLevelWindow * const win = static_cast<wxTopLevelWindow *>(*i);
173 WXWindow nswindow = win ? win->GetWXWindow() : nil;
174
175 if ( nswindow && [nswindow level] == kCGFloatingWindowLevel && [nswindow hidesOnDeactivate] == NO )
176 [nswindow setLevel:kCGNormalWindowLevel];
177 }
178}
179
180- (void)applicationDidResignActive:(NSNotification *)notification
181{
182 wxUnusedVar(notification);
183 if ( wxTheApp )
184 wxTheApp->SetActive( false , NULL ) ;
185}
186
c6aa5caf
SC
187@end
188
03647350 189/*
724999ee 190 allows ShowModal to work when using sheets.
03647350 191 see include/wx/osx/cocoa/private.h for more info
724999ee
KO
192*/
193@implementation ModalDialogDelegate
194- (id)init
195{
e5062a31 196 self = [super init];
724999ee
KO
197 sheetFinished = NO;
198 resultCode = -1;
bfa92264 199 impl = 0;
724999ee
KO
200 return self;
201}
202
bfa92264
KO
203- (void)setImplementation: (wxDialog *)dialog
204{
205 impl = dialog;
206}
207
03647350 208- (BOOL)finished
724999ee
KO
209{
210 return sheetFinished;
211}
212
213- (int)code
214{
215 return resultCode;
216}
217
218- (void)waitForSheetToFinish
219{
220 while (!sheetFinished)
221 {
222 wxSafeYield();
223 }
224}
225
226- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
227{
d8207702 228 wxUnusedVar(contextInfo);
724999ee
KO
229 resultCode = returnCode;
230 sheetFinished = YES;
037f9d3b
KO
231 // NSAlerts don't need nor respond to orderOut
232 if ([sheet respondsToSelector:@selector(orderOut:)])
233 [sheet orderOut: self];
bfa92264
KO
234
235 if (impl)
236 impl->ModalFinishedCallback(sheet, returnCode);
724999ee
KO
237}
238@end
239
e1875c78
SC
240wxNSAppController* appcontroller = nil;
241
dbeddfb9
SC
242bool wxApp::DoInitGui()
243{
ab9df4fb 244 wxMacAutoreleasePool pool;
dbeddfb9 245 [NSApplication sharedApplication];
c6aa5caf
SC
246
247 if (!sm_isEmbedded)
248 {
e1875c78
SC
249 appcontroller = [[wxNSAppController alloc] init];
250 [NSApp setDelegate:appcontroller];
945eac79 251
e8f25fcf
SC
252 // calling finishLaunching so early before running the loop seems to trigger some 'MenuManager compatibility' which leads
253 // to the duplication of menus under 10.5 and a warning under 10.6
254#if 0
cc96f525 255 [NSApp finishLaunching];
e8f25fcf 256#endif
c6aa5caf 257 }
dbeddfb9
SC
258 return true;
259}
260
261void wxApp::DoCleanUp()
262{
e1875c78
SC
263 if ( appcontroller != nil )
264 {
265 [NSApp setDelegate:nil];
266 [appcontroller release];
267 appcontroller = nil;
268 }
dbeddfb9 269}
33e90275 270
33e90275
SC
271void wxClientDisplayRect(int *x, int *y, int *width, int *height)
272{
5d57348e 273 NSRect displayRect = [wxOSXGetMenuScreen() visibleFrame];
33e90275
SC
274 wxRect r = wxFromNSRect( NULL, displayRect );
275 if ( x )
276 *x = r.x;
277 if ( y )
278 *y = r.y;
279 if ( width )
280 *width = r.GetWidth();
281 if ( height )
282 *height = r.GetHeight();
945eac79 283
33e90275
SC
284}
285
286void wxGetMousePosition( int* x, int* y )
287{
288 wxPoint pt = wxFromNSPoint(NULL, [NSEvent mouseLocation]);
54f11060
SC
289 if ( x )
290 *x = pt.x;
291 if ( y )
292 *y = pt.y;
33e90275
SC
293};
294
f3769d53
SC
295#if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
296
297wxMouseState wxGetMouseState()
298{
299 wxMouseState ms;
300
301 wxPoint pt = wxGetMousePosition();
302 ms.SetX(pt.x);
303 ms.SetY(pt.y);
304
305 NSUInteger modifiers = [NSEvent modifierFlags];
306 NSUInteger buttons = [NSEvent pressedMouseButtons];
307
308 ms.SetLeftDown( (buttons & 0x01) != 0 );
309 ms.SetMiddleDown( (buttons & 0x04) != 0 );
310 ms.SetRightDown( (buttons & 0x02) != 0 );
311
8b14528f 312 ms.SetRawControlDown(modifiers & NSControlKeyMask);
f3769d53
SC
313 ms.SetShiftDown(modifiers & NSShiftKeyMask);
314 ms.SetAltDown(modifiers & NSAlternateKeyMask);
dd9ec596 315 ms.SetControlDown(modifiers & NSCommandKeyMask);
f3769d53
SC
316
317 return ms;
318}
319
320
321#endif
322
33e90275
SC
323wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer *timer)
324{
dbeddfb9 325 return new wxOSXTimerImpl(timer);
33e90275
SC
326}
327
328int gs_wxBusyCursorCount = 0;
329extern wxCursor gMacCurrentCursor;
330wxCursor gMacStoredActiveCursor;
331
332// Set the cursor to the busy cursor for all windows
333void wxBeginBusyCursor(const wxCursor *cursor)
334{
335 if (gs_wxBusyCursorCount++ == 0)
336 {
3ac88921
SC
337 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
338 id object;
339
340 while ((object = [enumerator nextObject])) {
341 [(NSWindow*) object disableCursorRects];
342 }
343
33e90275
SC
344 gMacStoredActiveCursor = gMacCurrentCursor;
345 cursor->MacInstall();
346
347 wxSetCursor(*cursor);
348 }
349 //else: nothing to do, already set
350}
351
352// Restore cursor to normal
353void wxEndBusyCursor()
354{
355 wxCHECK_RET( gs_wxBusyCursorCount > 0,
356 wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
357
358 if (--gs_wxBusyCursorCount == 0)
359 {
3ac88921
SC
360 NSEnumerator *enumerator = [[[NSApplication sharedApplication] windows] objectEnumerator];
361 id object;
362
363 while ((object = [enumerator nextObject])) {
364 [(NSWindow*) object enableCursorRects];
365 }
33e90275
SC
366
367 wxSetCursor(wxNullCursor);
3ac88921
SC
368
369 gMacStoredActiveCursor.MacInstall();
370 gMacStoredActiveCursor = wxNullCursor;
33e90275
SC
371 }
372}
373
374// true if we're between the above two calls
375bool wxIsBusy()
376{
377 return (gs_wxBusyCursorCount > 0);
378}
379
928e7a7e
KO
380wxBitmap wxWindowDCImpl::DoGetAsBitmap(const wxRect *subrect) const
381{
382 // wxScreenDC is derived from wxWindowDC, so a screen dc will
383 // call this method when a Blit is performed with it as a source.
384 if (!m_window)
385 return wxNullBitmap;
945eac79 386
928e7a7e 387 wxSize sz = m_window->GetSize();
945eac79 388
928e7a7e
KO
389 int width = subrect != NULL ? subrect->width : sz.x;
390 int height = subrect != NULL ? subrect->height : sz.y ;
945eac79 391
1034a6bb 392 wxBitmap bitmap(width, height);
945eac79 393
bda7c353
SC
394 NSView* view = (NSView*) m_window->GetHandle();
395 if ( [view isHiddenOrHasHiddenAncestor] == NO )
1034a6bb 396 {
bda7c353
SC
397 [view lockFocus];
398 // we use this method as other methods force a repaint, and this method can be
399 // called from OnPaint, even with the window's paint dc as source (see wxHTMLWindow)
e5062a31 400 NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect: [view bounds]];
bda7c353
SC
401 [view unlockFocus];
402 if ( [rep respondsToSelector:@selector(CGImage)] )
403 {
404 CGImageRef cgImageRef = (CGImageRef)[rep CGImage];
405
406 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
407 // since our context is upside down we dont use CGContextDrawImage
408 wxMacDrawCGImage( (CGContextRef) bitmap.GetHBITMAP() , &r, cgImageRef ) ;
bda7c353
SC
409 }
410 else
411 {
412 // TODO for 10.4 in case we can support this for osx_cocoa
413 }
414 [rep release];
1034a6bb 415 }
945eac79 416
928e7a7e
KO
417 return bitmap;
418}
419
33e90275
SC
420#endif // wxUSE_GUI
421
3c7eea25 422#endif // wxOSX_USE_COCOA