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