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