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