]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/toplevel.cpp
Correct signature of HitTest()
[wxWidgets.git] / src / mac / carbon / toplevel.cpp
CommitLineData
a15eb0a5 1///////////////////////////////////////////////////////////////////////////////
fb5246be 2// Name: src/mac/carbon/toplevel.cpp
d66c3960
SC
3// Purpose: implements wxTopLevelWindow for Mac
4// Author: Stefan Csomor
a15eb0a5
SC
5// Modified by:
6// Created: 24.09.01
7// RCS-ID: $Id$
d66c3960 8// Copyright: (c) 2001-2004 Stefan Csomor
65571936 9// License: wxWindows licence
a15eb0a5
SC
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
a15eb0a5
SC
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
1832043f
WS
27#include "wx/toplevel.h"
28
a15eb0a5
SC
29#ifndef WX_PRECOMP
30 #include "wx/app.h"
422644a3 31 #include "wx/frame.h"
a15eb0a5
SC
32 #include "wx/string.h"
33 #include "wx/log.h"
34 #include "wx/intl.h"
37ec2bd3 35 #include "wx/settings.h"
2d17efa9 36 #include "wx/strconv.h"
179e085f 37 #include "wx/control.h"
a15eb0a5
SC
38#endif //WX_PRECOMP
39
5f0b2f22 40#include "wx/mac/uma.h"
422644a3 41#include "wx/mac/aga.h"
5f0b2f22 42#include "wx/tooltip.h"
a07c1212 43#include "wx/dnd.h"
a979e444 44
1f90939c
SC
45#if wxUSE_SYSTEM_OPTIONS
46 #include "wx/sysopt.h"
47#endif
5f0b2f22 48
3c393c0a 49#ifndef __DARWIN__
7f0c3a63 50#include <ToolUtils.h>
3c393c0a 51#endif
dd49c691 52
a979e444 53// for targeting OSX
eab19a7c
RN
54#include "wx/mac/private.h"
55
f02a4ffa
VZ
56// ----------------------------------------------------------------------------
57// constants
58// ----------------------------------------------------------------------------
59
893727e5
KO
60// unified title and toolbar constant - not in Tiger headers, so we duplicate it here
61#define kWindowUnifiedTitleAndToolbarAttribute (1 << 7)
62
f02a4ffa
VZ
63// trace mask for activation tracing messages
64static const wxChar *TRACE_ACTIVATE = _T("activation");
65
a15eb0a5
SC
66// ----------------------------------------------------------------------------
67// globals
68// ----------------------------------------------------------------------------
69
70// list of all frames and modeless dialogs
32b5be3d
RR
71wxWindowList wxModelessWindows;
72
6a7e6411
RD
73static pascal long wxShapedMacWindowDef(short varCode, WindowRef window, SInt16 message, SInt32 param);
74
a15eb0a5
SC
75// ============================================================================
76// wxTopLevelWindowMac implementation
77// ============================================================================
78
facd6764
SC
79BEGIN_EVENT_TABLE(wxTopLevelWindowMac, wxTopLevelWindowBase)
80END_EVENT_TABLE()
81
82
851b3a88
SC
83// ---------------------------------------------------------------------------
84// Carbon Events
85// ---------------------------------------------------------------------------
86
1542ea39 87static const EventTypeSpec eventList[] =
851b3a88 88{
a979e444 89 // TODO: remove control related event like key and mouse (except for WindowLeave events)
ffc75ee4 90
e40298d5 91 { kEventClassKeyboard, kEventRawKeyDown } ,
c5c9378c
SC
92 { kEventClassKeyboard, kEventRawKeyRepeat } ,
93 { kEventClassKeyboard, kEventRawKeyUp } ,
94 { kEventClassKeyboard, kEventRawKeyModifiersChanged } ,
95
ffc75ee4
SC
96 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
97 { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } ,
30c23e74 98
16a76184 99 { kEventClassWindow , kEventWindowShown } ,
851b3a88
SC
100 { kEventClassWindow , kEventWindowActivated } ,
101 { kEventClassWindow , kEventWindowDeactivated } ,
102 { kEventClassWindow , kEventWindowBoundsChanging } ,
103 { kEventClassWindow , kEventWindowBoundsChanged } ,
104 { kEventClassWindow , kEventWindowClose } ,
105
a979e444
DS
106 // we have to catch these events on the toplevel window level,
107 // as controls don't get the raw mouse events anymore
902725ee 108
851b3a88
SC
109 { kEventClassMouse , kEventMouseDown } ,
110 { kEventClassMouse , kEventMouseUp } ,
de127c69 111 { kEventClassMouse , kEventMouseWheelMoved } ,
851b3a88
SC
112 { kEventClassMouse , kEventMouseMoved } ,
113 { kEventClassMouse , kEventMouseDragged } ,
851b3a88
SC
114} ;
115
c5c9378c
SC
116static pascal OSStatus KeyboardEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
117{
118 OSStatus result = eventNotHandledErr ;
b3bd613a 119 // call DoFindFocus instead of FindFocus, because for Composite Windows(like WxGenericListCtrl)
a979e444 120 // FindFocus does not return the actual focus window, but the enclosing window
b3bd613a 121 wxWindow* focus = wxWindow::DoFindFocus();
92a7272f 122 if ( focus == NULL )
ccf1ef0f 123 focus = (wxTopLevelWindowMac*) data ;
52c3df99 124
19fc48c6 125 unsigned char charCode ;
f3097709 126 wxChar uniChar[2] ;
670f9935
WS
127 uniChar[0] = 0;
128 uniChar[1] = 0;
129
1542ea39 130 UInt32 keyCode ;
c5c9378c 131 UInt32 modifiers ;
e40298d5
JS
132 Point point ;
133 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
134
2d17efa9 135#if wxUSE_UNICODE
7cd7bc23 136 ByteCount dataSize = 0 ;
a979e444 137 if ( GetEventParameter( event, kEventParamKeyUnicodes, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr )
2d17efa9
SC
138 {
139 UniChar buf[2] ;
f3097709 140 int numChars = dataSize / sizeof( UniChar) + 1;
902725ee 141
2d17efa9 142 UniChar* charBuf = buf ;
902725ee 143
f3097709
SC
144 if ( numChars * 2 > 4 )
145 charBuf = new UniChar[ numChars ] ;
2d17efa9 146 GetEventParameter( event, kEventParamKeyUnicodes, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ;
670f9935 147 charBuf[ numChars - 1 ] = 0;
a979e444 148
2d17efa9
SC
149#if SIZEOF_WCHAR_T == 2
150 uniChar = charBuf[0] ;
151#else
d9d488cf 152 wxMBConvUTF16 converter ;
0cc00f4f 153 converter.MB2WC( uniChar , (const char*)charBuf , 2 ) ;
902725ee 154#endif
a979e444 155
f3097709 156 if ( numChars * 2 > 4 )
2d17efa9
SC
157 delete[] charBuf ;
158 }
159#endif
160
a979e444 161 GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
52c3df99
DS
162 GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
163 GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
164 GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
902725ee 165
e40298d5 166 UInt32 message = (keyCode << 8) + charCode;
a979e444 167 switch ( GetEventKind( event ) )
e40298d5
JS
168 {
169 case kEventRawKeyRepeat :
170 case kEventRawKeyDown :
e40298d5 171 {
404f1d80
SC
172 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
173 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
174 wxTheApp->MacSetCurrentEvent( event , handler ) ;
902725ee 175 if ( /* focus && */ wxTheApp->MacSendKeyDownEvent(
f3097709 176 focus , message , modifiers , when , point.h , point.v , uniChar[0] ) )
404f1d80
SC
177 {
178 result = noErr ;
179 }
180 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
e40298d5
JS
181 }
182 break ;
52c3df99 183
e40298d5 184 case kEventRawKeyUp :
902725ee 185 if ( /* focus && */ wxTheApp->MacSendKeyUpEvent(
f3097709 186 focus , message , modifiers , when , point.h , point.v , uniChar[0] ) )
e40298d5
JS
187 {
188 result = noErr ;
189 }
190 break ;
52c3df99 191
e40298d5
JS
192 case kEventRawKeyModifiersChanged :
193 {
194 wxKeyEvent event(wxEVT_KEY_DOWN);
195
196 event.m_shiftDown = modifiers & shiftKey;
197 event.m_controlDown = modifiers & controlKey;
198 event.m_altDown = modifiers & optionKey;
199 event.m_metaDown = modifiers & cmdKey;
a979e444
DS
200 event.m_x = point.h;
201 event.m_y = point.v;
202
2d17efa9 203#if wxUSE_UNICODE
0cc00f4f 204 event.m_uniChar = uniChar[0] ;
2d17efa9 205#endif
a979e444 206
687706f5 207 event.SetTimestamp(when);
e40298d5
JS
208 event.SetEventObject(focus);
209
902725ee 210 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & controlKey )
e40298d5
JS
211 {
212 event.m_keyCode = WXK_CONTROL ;
213 event.SetEventType( ( modifiers & controlKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
214 focus->GetEventHandler()->ProcessEvent( event ) ;
215 }
902725ee 216 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & shiftKey )
e40298d5
JS
217 {
218 event.m_keyCode = WXK_SHIFT ;
219 event.SetEventType( ( modifiers & shiftKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
220 focus->GetEventHandler()->ProcessEvent( event ) ;
221 }
902725ee 222 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & optionKey )
e40298d5
JS
223 {
224 event.m_keyCode = WXK_ALT ;
225 event.SetEventType( ( modifiers & optionKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
226 focus->GetEventHandler()->ProcessEvent( event ) ;
227 }
902725ee 228 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & cmdKey )
b7aec135
SC
229 {
230 event.m_keyCode = WXK_COMMAND ;
231 event.SetEventType( ( modifiers & cmdKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
232 focus->GetEventHandler()->ProcessEvent( event ) ;
233 }
a979e444 234
2a1f999f 235 wxApp::s_lastModifiers = modifiers ;
e40298d5 236 }
902725ee 237 break ;
52c3df99
DS
238
239 default:
240 break;
e40298d5 241 }
851b3a88
SC
242
243 return result ;
244}
245
facd6764 246// we don't interfere with foreign controls on our toplevel windows, therefore we always give back eventNotHandledErr
52c3df99 247// for windows that we didn't create (like eg Scrollbars in a databrowser), or for controls where we did not handle the
facd6764 248// mouse down at all
52c3df99 249//
facd6764 250// This handler can also be called from app level where data (ie target window) may be null or a non wx window
1542ea39 251
facd6764 252wxWindow* g_MacLastWindow = NULL ;
a3195b73 253
bdf895fd 254EventMouseButton g_lastButton = 0 ;
8736cc48 255bool g_lastButtonWasFakeRight = false ;
86a9144f 256
bdf895fd 257void SetupMouseEvent( wxMouseEvent &wxevent , wxMacCarbonEvent &cEvent )
facd6764
SC
258{
259 UInt32 modifiers = cEvent.GetParameter<UInt32>(kEventParamKeyModifiers, typeUInt32) ;
260 Point screenMouseLocation = cEvent.GetParameter<Point>(kEventParamMouseLocation) ;
67245665 261
902725ee 262 // this parameter are not given for all events
facd6764 263 EventMouseButton button = 0 ;
902725ee 264 UInt32 clickCount = 0 ;
a979e444
DS
265 cEvent.GetParameter<EventMouseButton>( kEventParamMouseButton, typeMouseButton , &button ) ;
266 cEvent.GetParameter<UInt32>( kEventParamClickCount, typeUInt32 , &clickCount ) ;
facd6764
SC
267
268 wxevent.m_x = screenMouseLocation.h;
269 wxevent.m_y = screenMouseLocation.v;
270 wxevent.m_shiftDown = modifiers & shiftKey;
271 wxevent.m_controlDown = modifiers & controlKey;
272 wxevent.m_altDown = modifiers & optionKey;
273 wxevent.m_metaDown = modifiers & cmdKey;
274 wxevent.SetTimestamp( cEvent.GetTicks() ) ;
52c3df99 275
8736cc48
SC
276 // a control click is interpreted as a right click
277 bool thisButtonIsFakeRight = false ;
facd6764 278 if ( button == kEventMouseButtonPrimary && (modifiers & controlKey) )
8736cc48 279 {
facd6764 280 button = kEventMouseButtonSecondary ;
8736cc48
SC
281 thisButtonIsFakeRight = true ;
282 }
b343fb9f 283 // otherwise we report double clicks by connecting a left click with a ctrl-left click
bdf895fd 284 if ( clickCount > 1 && button != g_lastButton )
b343fb9f 285 clickCount = 1 ;
902725ee 286
86a9144f
SC
287 // we must make sure that our synthetic 'right' button corresponds in
288 // mouse down, moved and mouse up, and does not deliver a right down and left up
902725ee 289
86a9144f 290 if ( cEvent.GetKind() == kEventMouseDown )
8736cc48 291 {
bdf895fd 292 g_lastButton = button ;
8736cc48
SC
293 g_lastButtonWasFakeRight = thisButtonIsFakeRight ;
294 }
902725ee 295
4e4e6dce 296 if ( button == 0 )
8736cc48 297 {
bdf895fd 298 g_lastButton = 0 ;
8736cc48
SC
299 g_lastButtonWasFakeRight = false ;
300 }
301 else if ( g_lastButton == kEventMouseButtonSecondary && g_lastButtonWasFakeRight )
bdf895fd 302 button = g_lastButton ;
facd6764 303
a979e444
DS
304 // determine the correct down state, wx does not want a 'down' for a mouseUp event,
305 // while mac delivers this button
facd6764
SC
306 if ( button != 0 && cEvent.GetKind() != kEventMouseUp )
307 {
a979e444 308 switch ( button )
e40298d5 309 {
facd6764
SC
310 case kEventMouseButtonPrimary :
311 wxevent.m_leftDown = true ;
e40298d5 312 break ;
52c3df99 313
facd6764
SC
314 case kEventMouseButtonSecondary :
315 wxevent.m_rightDown = true ;
e40298d5 316 break ;
52c3df99 317
facd6764
SC
318 case kEventMouseButtonTertiary :
319 wxevent.m_middleDown = true ;
e40298d5 320 break ;
52c3df99
DS
321
322 default:
323 break ;
facd6764
SC
324 }
325 }
52c3df99 326
90ff87d7
SC
327 // translate into wx types
328 switch ( cEvent.GetKind() )
facd6764 329 {
90ff87d7 330 case kEventMouseDown :
52c3df99 331 switch ( button )
90ff87d7
SC
332 {
333 case kEventMouseButtonPrimary :
a979e444 334 wxevent.SetEventType( clickCount > 1 ? wxEVT_LEFT_DCLICK : wxEVT_LEFT_DOWN ) ;
90ff87d7 335 break ;
52c3df99 336
90ff87d7
SC
337 case kEventMouseButtonSecondary :
338 wxevent.SetEventType( clickCount > 1 ? wxEVT_RIGHT_DCLICK : wxEVT_RIGHT_DOWN ) ;
339 break ;
52c3df99 340
90ff87d7 341 case kEventMouseButtonTertiary :
a979e444 342 wxevent.SetEventType( clickCount > 1 ? wxEVT_MIDDLE_DCLICK : wxEVT_MIDDLE_DOWN ) ;
90ff87d7 343 break ;
52c3df99
DS
344
345 default:
346 break ;
90ff87d7
SC
347 }
348 break ;
52c3df99 349
90ff87d7 350 case kEventMouseUp :
52c3df99 351 switch ( button )
90ff87d7
SC
352 {
353 case kEventMouseButtonPrimary :
354 wxevent.SetEventType( wxEVT_LEFT_UP ) ;
355 break ;
52c3df99 356
90ff87d7
SC
357 case kEventMouseButtonSecondary :
358 wxevent.SetEventType( wxEVT_RIGHT_UP ) ;
359 break ;
52c3df99 360
90ff87d7
SC
361 case kEventMouseButtonTertiary :
362 wxevent.SetEventType( wxEVT_MIDDLE_UP ) ;
363 break ;
52c3df99
DS
364
365 default:
366 break ;
90ff87d7
SC
367 }
368 break ;
52c3df99 369
2cce9b11 370 case kEventMouseWheelMoved :
52c3df99 371 {
a979e444 372 wxevent.SetEventType( wxEVT_MOUSEWHEEL ) ;
facd6764 373
74fa3253 374 EventMouseWheelAxis axis = cEvent.GetParameter<EventMouseWheelAxis>(kEventParamMouseWheelAxis, typeMouseWheelAxis) ;
7cd7bc23 375 SInt32 delta = cEvent.GetParameter<SInt32>(kEventParamMouseWheelDelta, typeSInt32) ;
facd6764
SC
376
377 wxevent.m_wheelRotation = delta;
378 wxevent.m_wheelDelta = 1;
379 wxevent.m_linesPerAction = 1;
74fa3253
SC
380 if ( axis == kEventMouseWheelAxisX )
381 wxevent.m_wheelAxis = 1;
52c3df99
DS
382 }
383 break ;
384
90ff87d7 385 default :
a979e444 386 wxevent.SetEventType( wxEVT_MOTION ) ;
90ff87d7 387 break ;
902725ee 388 }
facd6764
SC
389}
390
fbfb8bcc 391ControlRef wxMacFindSubControl( wxTopLevelWindowMac* toplevelWindow, const Point& location , ControlRef superControl , ControlPartCode *outPart )
facd6764
SC
392{
393 if ( superControl )
394 {
395 UInt16 childrenCount = 0 ;
a979e444
DS
396 ControlHandle sibling ;
397 Rect r ;
902725ee 398 OSStatus err = CountSubControls( superControl , &childrenCount ) ;
facd6764
SC
399 if ( err == errControlIsNotEmbedder )
400 return NULL ;
a979e444 401
facd6764 402 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") ) ;
902725ee 403
facd6764
SC
404 for ( UInt16 i = childrenCount ; i >=1 ; --i )
405 {
facd6764
SC
406 err = GetIndexedSubControl( superControl , i , & sibling ) ;
407 if ( err == errControlIsNotEmbedder )
408 return NULL ;
902725ee 409
facd6764
SC
410 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") ) ;
411 if ( IsControlVisible( sibling ) )
412 {
d6fd667b 413 UMAGetControlBoundsInWindowCoords( sibling , &r ) ;
facd6764 414 if ( MacPtInRect( location , &r ) )
de127c69 415 {
789ae0cf 416 ControlHandle child = wxMacFindSubControl( toplevelWindow , location , sibling , outPart ) ;
facd6764 417 if ( child )
a979e444 418 {
facd6764 419 return child ;
a979e444 420 }
facd6764 421 else
de127c69 422 {
d6fd667b 423 Point testLocation = location ;
789ae0cf 424
f21449ae 425 if ( toplevelWindow )
789ae0cf
SC
426 {
427 testLocation.h -= r.left ;
428 testLocation.v -= r.top ;
429 }
902725ee 430
d6fd667b 431 *outPart = TestControl( sibling , testLocation ) ;
a979e444 432
facd6764 433 return sibling ;
de127c69
GD
434 }
435 }
facd6764 436 }
e40298d5
JS
437 }
438 }
52c3df99 439
facd6764
SC
440 return NULL ;
441}
1542ea39 442
fbfb8bcc 443ControlRef wxMacFindControlUnderMouse( wxTopLevelWindowMac* toplevelWindow , const Point& location , WindowRef window , ControlPartCode *outPart )
facd6764
SC
444{
445#if TARGET_API_MAC_OSX
f21449ae 446 if ( UMAGetSystemVersion() >= 0x1030 )
30e0b1c9
SC
447 return FindControlUnderMouse( location , window , outPart ) ;
448#endif
a979e444 449
facd6764
SC
450 ControlRef rootControl = NULL ;
451 verify_noerr( GetRootControl( window , &rootControl ) ) ;
30e0b1c9 452
a979e444 453 return wxMacFindSubControl( toplevelWindow , location , rootControl , outPart ) ;
facd6764 454}
3c393c0a
SC
455
456#define NEW_CAPTURE_HANDLING 1
457
facd6764
SC
458pascal OSStatus wxMacTopLevelMouseEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
459{
789ae0cf 460 wxTopLevelWindowMac* toplevelWindow = (wxTopLevelWindowMac*) data ;
902725ee 461
facd6764
SC
462 OSStatus result = eventNotHandledErr ;
463
464 wxMacCarbonEvent cEvent( event ) ;
902725ee 465
facd6764
SC
466 Point screenMouseLocation = cEvent.GetParameter<Point>(kEventParamMouseLocation) ;
467 Point windowMouseLocation = screenMouseLocation ;
468
30c23e74 469 WindowRef window = NULL;
facd6764
SC
470 short windowPart = ::FindWindow(screenMouseLocation, &window);
471
472 wxWindow* currentMouseWindow = NULL ;
d88ffaaa 473 ControlRef control = NULL ;
902725ee 474
3c393c0a
SC
475#if NEW_CAPTURE_HANDLING
476 if ( wxApp::s_captureWindow )
477 {
478 window = (WindowRef) wxApp::s_captureWindow->MacGetTopLevelWindowRef() ;
8fc754bf 479 windowPart = inContent ;
3c393c0a
SC
480 }
481#endif
fb5246be 482
facd6764
SC
483 if ( window )
484 {
7cd7bc23 485 wxMacGlobalToLocal( window, &windowMouseLocation ) ;
facd6764 486
3c393c0a
SC
487 if ( wxApp::s_captureWindow
488#if !NEW_CAPTURE_HANDLING
489 && wxApp::s_captureWindow->MacGetTopLevelWindowRef() == (WXWindow) window && windowPart == inContent
490#endif
491 )
facd6764 492 {
2a1f999f 493 currentMouseWindow = wxApp::s_captureWindow ;
facd6764
SC
494 }
495 else if ( (IsWindowActive(window) && windowPart == inContent) )
496 {
497 ControlPartCode part ;
789ae0cf 498 control = wxMacFindControlUnderMouse( toplevelWindow , windowMouseLocation , window , &part ) ;
d88ffaaa 499 // if there is no control below the mouse position, send the event to the toplevel window itself
b19bf058 500 if ( control == 0 )
a979e444 501 {
b19bf058 502 currentMouseWindow = (wxWindow*) data ;
a979e444 503 }
b19bf058 504 else
b16f4bfa 505 {
b19bf058 506 currentMouseWindow = wxFindControlFromMacControl( control ) ;
8198ae50 507 if ( currentMouseWindow == NULL && cEvent.GetKind() == kEventMouseMoved )
b16f4bfa 508 {
179e085f 509#if wxUSE_TOOLBAR
902725ee
WS
510 // for wxToolBar to function we have to send certaint events to it
511 // instead of its children (wxToolBarTools)
b16f4bfa
SC
512 ControlRef parent ;
513 GetSuperControl(control, &parent );
514 wxWindow *wxParent = wxFindControlFromMacControl( parent ) ;
515 if ( wxParent && wxParent->IsKindOf( CLASSINFO( wxToolBar ) ) )
516 currentMouseWindow = wxParent ;
179e085f 517#endif
b16f4bfa
SC
518 }
519 }
f0756835
VZ
520
521 // disabled windows must not get any input messages
522 if ( currentMouseWindow && !currentMouseWindow->MacIsReallyEnabled() )
523 currentMouseWindow = NULL;
902725ee 524 }
facd6764 525 }
902725ee 526
facd6764
SC
527 wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
528 SetupMouseEvent( wxevent , cEvent ) ;
529
530 // handle all enter / leave events
902725ee 531
facd6764
SC
532 if ( currentMouseWindow != g_MacLastWindow )
533 {
534 if ( g_MacLastWindow )
535 {
536 wxMouseEvent eventleave(wxevent);
537 eventleave.SetEventType( wxEVT_LEAVE_WINDOW );
538 g_MacLastWindow->ScreenToClient( &eventleave.m_x, &eventleave.m_y );
539 eventleave.SetEventObject( g_MacLastWindow ) ;
d4bd6c97 540 wxevent.SetId( g_MacLastWindow->GetId() ) ;
a979e444 541
facd6764
SC
542#if wxUSE_TOOLTIPS
543 wxToolTip::RelayEvent( g_MacLastWindow , eventleave);
a979e444
DS
544#endif
545
facd6764
SC
546 g_MacLastWindow->GetEventHandler()->ProcessEvent(eventleave);
547 }
52c3df99 548
facd6764
SC
549 if ( currentMouseWindow )
550 {
551 wxMouseEvent evententer(wxevent);
552 evententer.SetEventType( wxEVT_ENTER_WINDOW );
553 currentMouseWindow->ScreenToClient( &evententer.m_x, &evententer.m_y );
554 evententer.SetEventObject( currentMouseWindow ) ;
d4bd6c97 555 wxevent.SetId( currentMouseWindow->GetId() ) ;
a979e444 556
facd6764 557#if wxUSE_TOOLTIPS
a979e444
DS
558 wxToolTip::RelayEvent( currentMouseWindow , evententer );
559#endif
560
facd6764
SC
561 currentMouseWindow->GetEventHandler()->ProcessEvent(evententer);
562 }
52c3df99 563
facd6764
SC
564 g_MacLastWindow = currentMouseWindow ;
565 }
902725ee 566
facd6764
SC
567 if ( windowPart == inMenuBar )
568 {
569 // special case menu bar, as we are having a low-level runloop we must do it ourselves
570 if ( cEvent.GetKind() == kEventMouseDown )
571 {
572 ::MenuSelect( screenMouseLocation ) ;
573 result = noErr ;
574 }
52c3df99 575 }
facd6764
SC
576 else if ( currentMouseWindow )
577 {
e10e9469 578 wxWindow *currentMouseWindowParent = currentMouseWindow->GetParent();
62ade180
RR
579
580 currentMouseWindow->ScreenToClient( &wxevent.m_x , &wxevent.m_y ) ;
902725ee 581
facd6764 582 wxevent.SetEventObject( currentMouseWindow ) ;
d4bd6c97 583 wxevent.SetId( currentMouseWindow->GetId() ) ;
facd6764 584
facd6764 585 // make tooltips current
902725ee 586
a979e444 587#if wxUSE_TOOLTIPS
f124c908 588 if ( wxevent.GetEventType() == wxEVT_MOTION )
a979e444
DS
589 wxToolTip::RelayEvent( currentMouseWindow , wxevent );
590#endif
591
facd6764 592 if ( currentMouseWindow->GetEventHandler()->ProcessEvent(wxevent) )
62ade180 593 {
902725ee 594 if ((currentMouseWindowParent != NULL) &&
62ade180
RR
595 (currentMouseWindowParent->GetChildren().Find(currentMouseWindow) == NULL))
596 currentMouseWindow = NULL;
902725ee 597
facd6764 598 result = noErr;
62ade180 599 }
30e0b1c9
SC
600 else
601 {
f90387b4
VZ
602 // if the user code did _not_ handle the event, then perform the
603 // default processing
604 if ( wxevent.GetEventType() == wxEVT_LEFT_DOWN )
605 {
606 // ... that is set focus to this window
ad02525d 607 if (currentMouseWindow->CanAcceptFocus() && wxWindow::FindFocus()!=currentMouseWindow)
f90387b4
VZ
608 currentMouseWindow->SetFocus();
609 }
610
30e0b1c9
SC
611 ControlPartCode dummyPart ;
612 // if built-in find control is finding the wrong control (ie static box instead of overlaid
613 // button, we cannot let the standard handler do its job, but must handle manually
614
902725ee 615 if ( ( cEvent.GetKind() == kEventMouseDown )
23ad132c 616#ifdef __WXMAC_OSX__
902725ee
WS
617 &&
618 (FindControlUnderMouse(windowMouseLocation , window , &dummyPart) !=
619 wxMacFindControlUnderMouse( toplevelWindow , windowMouseLocation , window , &dummyPart ) )
23ad132c
SC
620#endif
621 )
30e0b1c9 622 {
902725ee 623 if ( currentMouseWindow->MacIsReallyEnabled() )
7ce1a4e1
SC
624 {
625 EventModifiers modifiers = cEvent.GetParameter<EventModifiers>(kEventParamKeyModifiers, typeUInt32) ;
626 Point clickLocation = windowMouseLocation ;
789ae0cf 627
f21449ae 628 currentMouseWindow->MacRootWindowToWindow( &clickLocation.h , &clickLocation.v ) ;
789ae0cf 629
7ce1a4e1
SC
630 HandleControlClick( (ControlRef) currentMouseWindow->GetHandle() , clickLocation ,
631 modifiers , (ControlActionUPP ) -1 ) ;
902725ee
WS
632
633 if ((currentMouseWindowParent != NULL) &&
62ade180 634 (currentMouseWindowParent->GetChildren().Find(currentMouseWindow) == NULL))
a979e444 635 {
e10e9469 636 currentMouseWindow = NULL;
a979e444 637 }
7ce1a4e1 638 }
a979e444 639
30e0b1c9
SC
640 result = noErr ;
641 }
642 }
52c3df99 643
2a1f999f 644 if ( cEvent.GetKind() == kEventMouseUp && wxApp::s_captureWindow )
facd6764 645 {
2a1f999f 646 wxApp::s_captureWindow = NULL ;
facd6764
SC
647 // update cursor ?
648 }
6d63e2fc
SC
649
650 // update cursor
902725ee 651
6d63e2fc
SC
652 wxWindow* cursorTarget = currentMouseWindow ;
653 wxPoint cursorPoint( wxevent.m_x , wxevent.m_y ) ;
654
52c3df99 655 while ( cursorTarget && !cursorTarget->MacSetupCursor( cursorPoint ) )
6d63e2fc
SC
656 {
657 cursorTarget = cursorTarget->GetParent() ;
658 if ( cursorTarget )
e10e9469 659 cursorPoint += cursorTarget->GetPosition();
6d63e2fc
SC
660 }
661
f124c908
VZ
662 }
663 else // currentMouseWindow == NULL
d88ffaaa
SC
664 {
665 // don't mess with controls we don't know about
666 // for some reason returning eventNotHandledErr does not lead to the correct behaviour
667 // so we try sending them the correct control directly
e4b7e0b4 668 if ( cEvent.GetKind() == kEventMouseDown && toplevelWindow && control )
d88ffaaa
SC
669 {
670 EventModifiers modifiers = cEvent.GetParameter<EventModifiers>(kEventParamKeyModifiers, typeUInt32) ;
671 Point clickLocation = windowMouseLocation ;
f124c908 672#if TARGET_API_MAC_OSX
f21449ae
SC
673 HIPoint hiPoint ;
674 hiPoint.x = clickLocation.h ;
675 hiPoint.y = clickLocation.v ;
676 HIViewConvertPoint( &hiPoint , (ControlRef) toplevelWindow->GetHandle() , control ) ;
677 clickLocation.h = (int)hiPoint.x ;
678 clickLocation.v = (int)hiPoint.y ;
f124c908 679#endif // TARGET_API_MAC_OSX
52c3df99
DS
680
681 HandleControlClick( control , clickLocation , modifiers , (ControlActionUPP ) -1 ) ;
d88ffaaa
SC
682 result = noErr ;
683 }
684 }
a979e444 685
facd6764 686 return result ;
851b3a88 687}
facd6764
SC
688
689static pascal OSStatus wxMacTopLevelWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
851b3a88
SC
690{
691 OSStatus result = eventNotHandledErr ;
851b3a88 692
facd6764 693 wxMacCarbonEvent cEvent( event ) ;
902725ee 694
facd6764 695 // WindowRef windowRef = cEvent.GetParameter<WindowRef>(kEventParamDirectObject) ;
e40298d5 696 wxTopLevelWindowMac* toplevelWindow = (wxTopLevelWindowMac*) data ;
1542ea39 697
52c3df99 698 switch ( GetEventKind( event ) )
e40298d5 699 {
e40298d5 700 case kEventWindowActivated :
facd6764
SC
701 {
702 toplevelWindow->MacActivate( cEvent.GetTicks() , true) ;
facd6764
SC
703 wxActivateEvent wxevent(wxEVT_ACTIVATE, true , toplevelWindow->GetId());
704 wxevent.SetTimestamp( cEvent.GetTicks() ) ;
705 wxevent.SetEventObject(toplevelWindow);
706 toplevelWindow->GetEventHandler()->ProcessEvent(wxevent);
73fe67bd 707 // we still sending an eventNotHandledErr in order to allow for default processing
facd6764 708 }
52c3df99
DS
709 break ;
710
e40298d5 711 case kEventWindowDeactivated :
facd6764
SC
712 {
713 toplevelWindow->MacActivate(cEvent.GetTicks() , false) ;
714 wxActivateEvent wxevent(wxEVT_ACTIVATE, false , toplevelWindow->GetId());
715 wxevent.SetTimestamp( cEvent.GetTicks() ) ;
716 wxevent.SetEventObject(toplevelWindow);
717 toplevelWindow->GetEventHandler()->ProcessEvent(wxevent);
73fe67bd 718 // we still sending an eventNotHandledErr in order to allow for default processing
facd6764 719 }
52c3df99
DS
720 break ;
721
902725ee 722 case kEventWindowShown :
902725ee
WS
723 toplevelWindow->Refresh() ;
724 result = noErr ;
725 break ;
52c3df99 726
e40298d5 727 case kEventWindowClose :
52c3df99 728 toplevelWindow->Close() ;
e40298d5
JS
729 result = noErr ;
730 break ;
52c3df99 731
e40298d5 732 case kEventWindowBoundsChanged :
facd6764 733 {
52c3df99 734 UInt32 attributes = cEvent.GetParameter<UInt32>(kEventParamAttributes, typeUInt32) ;
facd6764
SC
735 Rect newRect = cEvent.GetParameter<Rect>(kEventParamCurrentBounds) ;
736 wxRect r( newRect.left , newRect.top , newRect.right - newRect.left , newRect.bottom - newRect.top ) ;
737 if ( attributes & kWindowBoundsChangeSizeChanged )
e40298d5 738 {
facd6764
SC
739 // according to the other ports we handle this within the OS level
740 // resize event, not within a wxSizeEvent
741 wxFrame *frame = wxDynamicCast( toplevelWindow , wxFrame ) ;
742 if ( frame )
743 {
6f02a879 744 frame->PositionBars();
facd6764 745 }
1542ea39 746
facd6764
SC
747 wxSizeEvent event( r.GetSize() , toplevelWindow->GetId() ) ;
748 event.SetEventObject( toplevelWindow ) ;
851b3a88 749
facd6764 750 toplevelWindow->GetEventHandler()->ProcessEvent(event) ;
5e533062 751 toplevelWindow->wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
e40298d5 752 }
52c3df99 753
facd6764
SC
754 if ( attributes & kWindowBoundsChangeOriginChanged )
755 {
756 wxMoveEvent event( r.GetLeftTop() , toplevelWindow->GetId() ) ;
757 event.SetEventObject( toplevelWindow ) ;
758 toplevelWindow->GetEventHandler()->ProcessEvent(event) ;
759 }
52c3df99 760
facd6764 761 result = noErr ;
facd6764 762 }
52c3df99
DS
763 break ;
764
f81bfef9 765 case kEventWindowBoundsChanging :
facd6764
SC
766 {
767 UInt32 attributes = cEvent.GetParameter<UInt32>(kEventParamAttributes,typeUInt32) ;
768 Rect newRect = cEvent.GetParameter<Rect>(kEventParamCurrentBounds) ;
83901ec2 769
facd6764
SC
770 if ( (attributes & kWindowBoundsChangeSizeChanged) || (attributes & kWindowBoundsChangeOriginChanged) )
771 {
29281095
SC
772 // all (Mac) rects are in content area coordinates, all wxRects in structure coordinates
773 int left , top , right , bottom ;
774 toplevelWindow->MacGetContentAreaInset( left , top , right , bottom ) ;
52c3df99
DS
775
776 wxRect r(
777 newRect.left - left,
778 newRect.top - top,
779 newRect.right - newRect.left + left + right,
780 newRect.bottom - newRect.top + top + bottom ) ;
781
facd6764
SC
782 // this is a EVT_SIZING not a EVT_SIZE type !
783 wxSizeEvent wxevent( r , toplevelWindow->GetId() ) ;
784 wxevent.SetEventObject( toplevelWindow ) ;
785 wxRect adjustR = r ;
786 if ( toplevelWindow->GetEventHandler()->ProcessEvent(wxevent) )
facd6764 787 adjustR = wxevent.GetRect() ;
29281095 788
facd6764
SC
789 if ( toplevelWindow->GetMaxWidth() != -1 && adjustR.GetWidth() > toplevelWindow->GetMaxWidth() )
790 adjustR.SetWidth( toplevelWindow->GetMaxWidth() ) ;
2c25bd55 791 if ( toplevelWindow->GetMaxHeight() != -1 && adjustR.GetHeight() > toplevelWindow->GetMaxHeight() )
facd6764
SC
792 adjustR.SetHeight( toplevelWindow->GetMaxHeight() ) ;
793 if ( toplevelWindow->GetMinWidth() != -1 && adjustR.GetWidth() < toplevelWindow->GetMinWidth() )
794 adjustR.SetWidth( toplevelWindow->GetMinWidth() ) ;
2c25bd55 795 if ( toplevelWindow->GetMinHeight() != -1 && adjustR.GetHeight() < toplevelWindow->GetMinHeight() )
facd6764 796 adjustR.SetHeight( toplevelWindow->GetMinHeight() ) ;
4a5f2351 797 const Rect adjustedRect = { adjustR.y + top , adjustR.x + left , adjustR.y + adjustR.height - bottom , adjustR.x + adjustR.width - right } ;
facd6764 798 if ( !EqualRect( &newRect , &adjustedRect ) )
1f919f38 799 cEvent.SetParameter<Rect>( kEventParamCurrentBounds , &adjustedRect ) ;
4817190d 800 toplevelWindow->wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
f81bfef9 801 }
facd6764 802
902725ee 803 result = noErr ;
facd6764 804 }
52c3df99
DS
805 break ;
806
e40298d5
JS
807 default :
808 break ;
809 }
52c3df99 810
e40298d5 811 return result ;
851b3a88
SC
812}
813
ffc75ee4
SC
814// mix this in from window.cpp
815pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) ;
816
facd6764 817pascal OSStatus wxMacTopLevelEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
851b3a88
SC
818{
819 OSStatus result = eventNotHandledErr ;
820
821 switch ( GetEventClass( event ) )
822 {
ffc75ee4
SC
823 case kEventClassTextInput :
824 result = wxMacUnicodeTextEventHandler( handler, event , data ) ;
825 break ;
826
c5c9378c 827 case kEventClassKeyboard :
e40298d5 828 result = KeyboardEventHandler( handler, event , data ) ;
c5c9378c 829 break ;
52c3df99 830
851b3a88 831 case kEventClassWindow :
facd6764 832 result = wxMacTopLevelWindowEventHandler( handler, event , data ) ;
e40298d5 833 break ;
52c3df99 834
851b3a88 835 case kEventClassMouse :
facd6764 836 result = wxMacTopLevelMouseEventHandler( handler, event , data ) ;
e40298d5 837 break ;
52c3df99 838
851b3a88
SC
839 default :
840 break ;
841 }
52c3df99 842
851b3a88
SC
843 return result ;
844}
845
facd6764 846DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacTopLevelEventHandler )
851b3a88 847
5f0b2f22
SC
848// ---------------------------------------------------------------------------
849// wxWindowMac utility functions
850// ---------------------------------------------------------------------------
851
852// Find an item given the Macintosh Window Reference
853
71f2fb52
RN
854WX_DECLARE_HASH_MAP(WindowRef, wxTopLevelWindowMac*, wxPointerHash, wxPointerEqual, MacWindowMap);
855
856static MacWindowMap wxWinMacWindowList;
857
858wxTopLevelWindowMac *wxFindWinFromMacWindow(WindowRef inWindowRef)
859{
860 MacWindowMap::iterator node = wxWinMacWindowList.find(inWindowRef);
861
862 return (node == wxWinMacWindowList.end()) ? NULL : node->second;
863}
864
865void wxAssociateWinWithMacWindow(WindowRef inWindowRef, wxTopLevelWindowMac *win) ;
866void wxAssociateWinWithMacWindow(WindowRef inWindowRef, wxTopLevelWindowMac *win)
867{
868 // adding NULL WindowRef is (first) surely a result of an error and
869 // nothing else :-)
870 wxCHECK_RET( inWindowRef != (WindowRef) NULL, wxT("attempt to add a NULL WindowRef to window list") );
871
872 wxWinMacWindowList[inWindowRef] = win;
873}
874
875void wxRemoveMacWindowAssociation(wxTopLevelWindowMac *win) ;
876void wxRemoveMacWindowAssociation(wxTopLevelWindowMac *win)
877{
878 MacWindowMap::iterator it;
879 for ( it = wxWinMacWindowList.begin(); it != wxWinMacWindowList.end(); ++it )
880 {
881 if ( it->second == win )
882 {
883 wxWinMacWindowList.erase(it);
884 break;
885 }
886 }
887}
5f0b2f22 888
a15eb0a5
SC
889// ----------------------------------------------------------------------------
890// wxTopLevelWindowMac creation
891// ----------------------------------------------------------------------------
892
245f3581 893wxTopLevelWindowMac *wxTopLevelWindowMac::s_macDeactivateWindow = NULL;
5f0b2f22 894
902725ee 895typedef struct
c5985061
SC
896{
897 wxPoint m_position ;
902725ee 898 wxSize m_size ;
f3b2e2d7 899 bool m_wasResizable ;
716d0327 900} FullScreenData ;
c5985061 901
a15eb0a5
SC
902void wxTopLevelWindowMac::Init()
903{
904 m_iconized =
902725ee 905 m_maximizeOnShow = false;
6a17ca35 906 m_macWindow = NULL ;
52c3df99 907
7c091673 908 m_macEventHandler = NULL ;
c5985061 909 m_macFullScreenData = NULL ;
a15eb0a5
SC
910}
911
118f012e
SC
912class wxMacDeferredWindowDeleter : public wxObject
913{
914public :
1542ea39
RD
915 wxMacDeferredWindowDeleter( WindowRef windowRef )
916 {
917 m_macWindow = windowRef ;
118f012e 918 }
52c3df99 919
1542ea39
RD
920 virtual ~wxMacDeferredWindowDeleter()
921 {
922 UMADisposeWindow( (WindowRef) m_macWindow ) ;
118f012e 923 }
52c3df99
DS
924
925protected :
118f012e
SC
926 WindowRef m_macWindow ;
927} ;
928
a15eb0a5
SC
929bool wxTopLevelWindowMac::Create(wxWindow *parent,
930 wxWindowID id,
931 const wxString& title,
932 const wxPoint& pos,
933 const wxSize& size,
934 long style,
935 const wxString& name)
936{
937 // init our fields
938 Init();
939
940 m_windowStyle = style;
941
52c3df99 942 SetName( name );
a15eb0a5
SC
943
944 m_windowId = id == -1 ? NewControlId() : id;
fb5246be 945 wxWindow::SetLabel( title ) ;
a15eb0a5 946
a0232aa5 947 MacCreateRealWindow( title, pos , size , style , name ) ;
facd6764 948
94d1d0f4 949 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
902725ee 950
5bd78bbc
JS
951 if (GetExtraStyle() & wxFRAME_EX_METAL)
952 MacSetMetalAppearance(true);
94d1d0f4 953
a15eb0a5
SC
954 wxTopLevelWindows.Append(this);
955
956 if ( parent )
957 parent->AddChild(this);
958
902725ee 959 return true;
a15eb0a5
SC
960}
961
962wxTopLevelWindowMac::~wxTopLevelWindowMac()
963{
6a17ca35
SC
964 if ( m_macWindow )
965 {
c81c6d54 966#if wxUSE_TOOLTIPS
6a17ca35 967 wxToolTip::NotifyWindowDelete(m_macWindow) ;
c81c6d54 968#endif
118f012e 969 wxPendingDelete.Append( new wxMacDeferredWindowDeleter( (WindowRef) m_macWindow ) ) ;
6a17ca35 970 }
1542ea39 971
7c091673
SC
972 if ( m_macEventHandler )
973 {
974 ::RemoveEventHandler((EventHandlerRef) m_macEventHandler);
975 m_macEventHandler = NULL ;
976 }
851b3a88 977
5f0b2f22
SC
978 wxRemoveMacWindowAssociation( this ) ;
979
a15eb0a5
SC
980 if ( wxModelessWindows.Find(this) )
981 wxModelessWindows.DeleteObject(this);
902725ee 982
c5985061
SC
983 FullScreenData *data = (FullScreenData *) m_macFullScreenData ;
984 delete data ;
985 m_macFullScreenData = NULL ;
09ac36f8
SC
986
987 // avoid dangling refs
988 if ( s_macDeactivateWindow == this )
989 s_macDeactivateWindow = NULL;
a15eb0a5
SC
990}
991
992
993// ----------------------------------------------------------------------------
994// wxTopLevelWindowMac maximize/minimize
995// ----------------------------------------------------------------------------
996
997void wxTopLevelWindowMac::Maximize(bool maximize)
998{
6643c354
SC
999 Point idealSize = { 0 , 0 } ;
1000 if ( maximize )
1001 {
7cd7bc23
SC
1002#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
1003 HIRect bounds ;
1004 HIWindowGetAvailablePositioningBounds(kCGNullDirectDisplay,kHICoordSpace72DPIGlobal,
1005 &bounds);
1006 idealSize.h = bounds.size.width;
1007 idealSize.v = bounds.size.height;
1008#else
6643c354
SC
1009 Rect rect ;
1010 GetAvailableWindowPositioningBounds(GetMainDevice(),&rect) ;
1011 idealSize.h = rect.right - rect.left ;
1012 idealSize.v = rect.bottom - rect.top ;
7cd7bc23 1013#endif
6643c354
SC
1014 }
1015 ZoomWindowIdeal( (WindowRef)m_macWindow , maximize ? inZoomOut : inZoomIn , &idealSize ) ;
a15eb0a5
SC
1016}
1017
1018bool wxTopLevelWindowMac::IsMaximized() const
1019{
a979e444 1020 return IsWindowInStandardState( (WindowRef)m_macWindow , NULL , NULL ) ;
a15eb0a5
SC
1021}
1022
1023void wxTopLevelWindowMac::Iconize(bool iconize)
1024{
52c3df99
DS
1025 if ( IsWindowCollapsable( (WindowRef)m_macWindow) )
1026 CollapseWindow( (WindowRef)m_macWindow , iconize ) ;
a15eb0a5
SC
1027}
1028
1029bool wxTopLevelWindowMac::IsIconized() const
1030{
b7aec135 1031 return IsWindowCollapsed((WindowRef)m_macWindow ) ;
a15eb0a5
SC
1032}
1033
1034void wxTopLevelWindowMac::Restore()
1035{
902725ee 1036 if ( IsMaximized() )
699b6af4 1037 Maximize(false);
902725ee 1038 else if ( IsIconized() )
699b6af4 1039 Iconize(false);
a15eb0a5
SC
1040}
1041
1042// ----------------------------------------------------------------------------
1043// wxTopLevelWindowMac misc
1044// ----------------------------------------------------------------------------
1045
facd6764
SC
1046wxPoint wxTopLevelWindowMac::GetClientAreaOrigin() const
1047{
52c3df99 1048 return wxPoint(0, 0) ;
facd6764
SC
1049}
1050
facd6764 1051void wxTopLevelWindowMac::MacSetBackgroundBrush( const wxBrush &brush )
902725ee 1052{
facd6764
SC
1053 wxTopLevelWindowBase::MacSetBackgroundBrush( brush ) ;
1054
1055 if ( m_macBackgroundBrush.Ok() && m_macBackgroundBrush.GetStyle() != wxTRANSPARENT && m_macBackgroundBrush.MacGetBrushKind() == kwxMacBrushTheme )
1056 {
1057 SetThemeWindowBackground( (WindowRef) m_macWindow , m_macBackgroundBrush.MacGetTheme() , false ) ;
1058 }
1059}
1060
902725ee 1061void wxTopLevelWindowMac::MacInstallTopLevelWindowEventHandler()
949cb163
SC
1062{
1063 if ( m_macEventHandler != NULL )
1064 {
1065 verify_noerr( ::RemoveEventHandler( (EventHandlerRef) m_macEventHandler ) ) ;
1066 }
52c3df99
DS
1067
1068 InstallWindowEventHandler(
1069 MAC_WXHWND(m_macWindow), GetwxMacTopLevelEventHandlerUPP(),
1070 GetEventTypeCount(eventList), eventList, this, (EventHandlerRef *)&m_macEventHandler );
949cb163
SC
1071}
1072
a979e444
DS
1073void wxTopLevelWindowMac::MacCreateRealWindow(
1074 const wxString& title,
1075 const wxPoint& pos,
1076 const wxSize& size,
1077 long style,
1078 const wxString& name )
5f0b2f22 1079{
47ac4f9b 1080 OSStatus err = noErr ;
e40298d5
JS
1081 SetName(name);
1082 m_windowStyle = style;
902725ee 1083 m_isShown = false;
1542ea39 1084
e40298d5 1085 // create frame.
facd6764
SC
1086 int x = (int)pos.x;
1087 int y = (int)pos.y;
902725ee 1088
52c3df99 1089 Rect theBoundsRect;
5a486641
SC
1090 wxRect display = wxGetClientDisplayRect() ;
1091
1092 if ( x == wxDefaultPosition.x )
1093 x = display.x ;
902725ee 1094
5a486641
SC
1095 if ( y == wxDefaultPosition.y )
1096 y = display.y ;
1542ea39 1097
facd6764
SC
1098 int w = WidthDefault(size.x);
1099 int h = HeightDefault(size.y);
1542ea39 1100
facd6764 1101 ::SetRect(&theBoundsRect, x, y , x + w, y + h);
1542ea39 1102
5f0b2f22 1103 // translate the window attributes in the appropriate window class and attributes
5f0b2f22
SC
1104 WindowClass wclass = 0;
1105 WindowAttributes attr = kWindowNoAttributes ;
e353795e 1106 WindowGroupRef group = NULL ;
1542ea39 1107
f5744893 1108 if ( HasFlag( wxFRAME_TOOL_WINDOW) )
5f0b2f22 1109 {
1542ea39 1110 if (
f5744893
SC
1111 HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) ||
1112 HasFlag( wxSYSTEM_MENU ) || HasFlag( wxCAPTION ) ||
1113 HasFlag(wxTINY_CAPTION_HORIZ) || HasFlag(wxTINY_CAPTION_VERT)
e40298d5 1114 )
5f0b2f22 1115 {
f5744893 1116 wclass = kFloatingWindowClass ;
52c3df99 1117
f5744893 1118 if ( HasFlag(wxTINY_CAPTION_VERT) )
f5744893 1119 attr |= kWindowSideTitlebarAttribute ;
f5744893
SC
1120 }
1121 else
1122 {
1123 wclass = kPlainWindowClass ;
5f0b2f22
SC
1124 }
1125 }
a0232aa5
RD
1126 else if ( HasFlag( wxPOPUP_WINDOW ) )
1127 {
1128 // TEMPORARY HACK!
1129 // Until we've got a real wxPopupWindow class on wxMac make it a
1130 // little easier for wxFrame to be used to emulate it and workaround
1131 // the lack of wxPopupWindow.
1132 if ( HasFlag( wxBORDER_NONE ) )
1133 wclass = kHelpWindowClass ; // has no border
1134 else
1135 wclass = kPlainWindowClass ; // has a single line border, it will have to do for now
1136 //attr |= kWindowNoShadowAttribute; // turn off the shadow Should we??
1137 group = GetWindowGroupOfClass( // float above other windows
1138 kFloatingWindowClass) ;
1139 }
5f0b2f22
SC
1140 else if ( HasFlag( wxCAPTION ) )
1141 {
1542ea39 1142 wclass = kDocumentWindowClass ;
22e3c5bd 1143 attr |= kWindowInWindowMenuAttribute ;
5f0b2f22 1144 }
eab19a7c 1145#if defined( __WXMAC__ ) && TARGET_API_MAC_OSX && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2 )
3e17bc3f
RN
1146 else if ( HasFlag( wxFRAME_DRAWER ) )
1147 {
1148 wclass = kDrawerWindowClass;
3e17bc3f
RN
1149 }
1150#endif //10.2 and up
5f0b2f22
SC
1151 else
1152 {
f5744893 1153 if ( HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) ||
47ac4f9b 1154 HasFlag( wxCLOSE_BOX ) || HasFlag( wxSYSTEM_MENU ) )
f5744893
SC
1155 {
1156 wclass = kDocumentWindowClass ;
1157 }
1158 else
1159 {
1160 wclass = kPlainWindowClass ;
1161 }
5f0b2f22 1162 }
1542ea39 1163
52c3df99 1164 if ( wclass != kPlainWindowClass )
5f0b2f22 1165 {
52c3df99
DS
1166 if ( HasFlag( wxMINIMIZE_BOX ) )
1167 attr |= kWindowCollapseBoxAttribute ;
1168
1169 if ( HasFlag( wxMAXIMIZE_BOX ) )
1170 attr |= kWindowFullZoomAttribute ;
1171
1172 if ( HasFlag( wxRESIZE_BORDER ) )
1173 attr |= kWindowResizableAttribute ;
1174
1175 if ( HasFlag( wxCLOSE_BOX) )
1176 attr |= kWindowCloseBoxAttribute ;
5f0b2f22 1177 }
1542ea39 1178
52c3df99 1179 // turn on live resizing (OS X only)
eb630bf1 1180 if (UMAGetSystemVersion() >= 0x1000)
eb630bf1 1181 attr |= kWindowLiveResizeAttribute;
eb630bf1 1182
e353795e 1183 if ( HasFlag(wxSTAY_ON_TOP) )
e353795e 1184 group = GetWindowGroupOfClass(kUtilityWindowClass) ;
6a7e6411 1185
a0232aa5
RD
1186 if ( HasFlag( wxFRAME_FLOAT_ON_PARENT ) )
1187 group = GetWindowGroupOfClass(kFloatingWindowClass) ;
1188
f21449ae 1189 attr |= kWindowCompositingAttribute;
24fcd264
SC
1190#if 0 // wxMAC_USE_CORE_GRAPHICS ; TODO : decide on overall handling of high dpi screens (pixel vs userscale)
1191 attr |= kWindowFrameworkScaledAttribute;
d66c3960 1192#endif
902725ee 1193
6a7e6411
RD
1194 if ( HasFlag(wxFRAME_SHAPED) )
1195 {
1196 WindowDefSpec customWindowDefSpec;
1197 customWindowDefSpec.defType = kWindowDefProcPtr;
7cd7bc23
SC
1198 customWindowDefSpec.u.defProc =
1199#ifdef __LP64__
1200 (WindowDefUPP) wxShapedMacWindowDef;
1201#else
1202 NewWindowDefUPP(wxShapedMacWindowDef);
1203#endif
47ac4f9b 1204 err = ::CreateCustomWindow( &customWindowDefSpec, wclass,
6a7e6411
RD
1205 attr, &theBoundsRect,
1206 (WindowRef*) &m_macWindow);
1207 }
1208 else
1209 {
47ac4f9b 1210 err = ::CreateNewWindow( wclass , attr , &theBoundsRect , (WindowRef*)&m_macWindow ) ;
6a7e6411
RD
1211 }
1212
e353795e
SC
1213 if ( err == noErr && m_macWindow != NULL && group != NULL )
1214 SetWindowGroup( (WindowRef) m_macWindow , group ) ;
1215
47ac4f9b 1216 wxCHECK_RET( err == noErr, wxT("Mac OS error when trying to create new window") );
f83b6761 1217
832f330f
SC
1218 // setup a separate group for each window, so that overlays can be handled easily
1219 verify_noerr( CreateWindowGroup( kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrHideOnCollapse, &group ));
1220 verify_noerr( SetWindowGroupParent( group, GetWindowGroup( (WindowRef) m_macWindow )));
1221 verify_noerr( SetWindowGroup( (WindowRef) m_macWindow , group ));
1222
a979e444
DS
1223 // the create commands are only for content rect,
1224 // so we have to set the size again as structure bounds
f83b6761
SC
1225 SetWindowBounds( (WindowRef) m_macWindow , kWindowStructureRgn , &theBoundsRect ) ;
1226
facd6764
SC
1227 wxAssociateWinWithMacWindow( (WindowRef) m_macWindow , this ) ;
1228 UMASetWTitle( (WindowRef) m_macWindow , title , m_font.GetEncoding() ) ;
1f1c8bd4 1229 m_peer = new wxMacControl(this , true /*isRootControl*/) ;
902725ee 1230
f21449ae
SC
1231 // There is a bug in 10.2.X for ::GetRootControl returning the window view instead of
1232 // the content view, so we have to retrieve it explicitly
1233 HIViewFindByID( HIViewGetRoot( (WindowRef) m_macWindow ) , kHIViewWindowContentID ,
1234 m_peer->GetControlRefAddr() ) ;
1235 if ( !m_peer->Ok() )
789ae0cf 1236 {
f21449ae
SC
1237 // compatibility mode fallback
1238 GetRootControl( (WindowRef) m_macWindow , m_peer->GetControlRefAddr() ) ;
789ae0cf 1239 }
52c3df99
DS
1240
1241 // the root control level handler
5ca0d812 1242 MacInstallEventHandler( (WXWidget) m_peer->GetControlRef() ) ;
facd6764 1243
9dc1d180
JS
1244 // Causes the inner part of the window not to be metal
1245 // if the style is used before window creation.
1246#if 0 // TARGET_API_MAC_OSX
8ec0a8fa
SC
1247 if ( m_macUsesCompositing && m_macWindow != NULL )
1248 {
1249 if ( GetExtraStyle() & wxFRAME_EX_METAL )
1250 MacSetMetalAppearance( true ) ;
1251 }
1252#endif
52c3df99 1253
893727e5
KO
1254#if TARGET_API_MAC_OSX
1255 if ( m_macWindow != NULL )
1256 {
1257 MacSetUnifiedAppearance( true ) ;
1258 }
1259#endif
1260
73fe67bd 1261 // the frame window event handler
e40298d5 1262 InstallStandardEventHandler( GetWindowEventTarget(MAC_WXHWND(m_macWindow)) ) ;
949cb163 1263 MacInstallTopLevelWindowEventHandler() ;
b19bf058 1264
14c96cf2
SC
1265 DoSetWindowVariant( m_windowVariant ) ;
1266
facd6764 1267 m_macFocus = NULL ;
6a7e6411
RD
1268
1269 if ( HasFlag(wxFRAME_SHAPED) )
1270 {
1271 // default shape matches the window size
52c3df99
DS
1272 wxRegion rgn( 0, 0, w, h );
1273 SetShape( rgn );
6a7e6411 1274 }
3dfafdb9
RD
1275
1276 wxWindowCreateEvent event(this);
1277 GetEventHandler()->ProcessEvent(event);
5f0b2f22
SC
1278}
1279
5d2e69e8 1280void wxTopLevelWindowMac::ClearBackground()
5f0b2f22 1281{
5d2e69e8 1282 wxWindow::ClearBackground() ;
5f0b2f22
SC
1283}
1284
5f0b2f22
SC
1285// Raise the window to the top of the Z order
1286void wxTopLevelWindowMac::Raise()
1287{
7f3c339c 1288 ::SelectWindow( (WindowRef)m_macWindow ) ;
5f0b2f22
SC
1289}
1290
1291// Lower the window to the bottom of the Z order
1292void wxTopLevelWindowMac::Lower()
1293{
76a5e5d2 1294 ::SendBehind( (WindowRef)m_macWindow , NULL ) ;
5f0b2f22
SC
1295}
1296
245f3581
DE
1297void wxTopLevelWindowMac::MacDelayedDeactivation(long timestamp)
1298{
52c3df99 1299 if (s_macDeactivateWindow)
245f3581 1300 {
f02a4ffa
VZ
1301 wxLogTrace(TRACE_ACTIVATE,
1302 wxT("Doing delayed deactivation of %p"),
1303 s_macDeactivateWindow);
52c3df99 1304
245f3581
DE
1305 s_macDeactivateWindow->MacActivate(timestamp, false);
1306 }
1307}
1308
851b3a88 1309void wxTopLevelWindowMac::MacActivate( long timestamp , bool inIsActivating )
5f0b2f22 1310{
f02a4ffa 1311 wxLogTrace(TRACE_ACTIVATE, wxT("TopLevel=%p::MacActivate"), this);
17f8d2a7 1312
52c3df99
DS
1313 if (s_macDeactivateWindow == this)
1314 s_macDeactivateWindow = NULL;
1315
245f3581 1316 MacDelayedDeactivation(timestamp);
8ab50549 1317 MacPropagateHiliteChanged() ;
5f0b2f22
SC
1318}
1319
1320void wxTopLevelWindowMac::SetTitle(const wxString& title)
1321{
fb5246be 1322 wxWindow::SetLabel( title ) ;
16a76184 1323 UMASetWTitle( (WindowRef)m_macWindow , title , m_font.GetEncoding() ) ;
5f0b2f22
SC
1324}
1325
d4bd6c97 1326wxString wxTopLevelWindowMac::GetTitle() const
fb5246be
WS
1327{
1328 return wxWindow::GetLabel();
1329}
1330
5f0b2f22
SC
1331bool wxTopLevelWindowMac::Show(bool show)
1332{
facd6764 1333 if ( !wxTopLevelWindowBase::Show(show) )
902725ee 1334 return false;
5f0b2f22 1335
21e77aa1
DS
1336 bool plainTransition = false;
1337
a979e444 1338#if wxUSE_SYSTEM_OPTIONS
21e77aa1
DS
1339 // code contributed by Ryan Wilcox December 18, 2003
1340 plainTransition = UMAGetSystemVersion() >= 0x1000 ;
1341 if ( wxSystemOptions::HasOption(wxMAC_WINDOW_PLAIN_TRANSITION) )
1342 plainTransition = ( wxSystemOptions::GetOptionInt( wxMAC_WINDOW_PLAIN_TRANSITION ) == 1 ) ;
1343#endif
52c3df99 1344
21e77aa1
DS
1345 if (show)
1346 {
8c8f6a4b 1347 if ( plainTransition )
1f90939c 1348 ::ShowWindow( (WindowRef)m_macWindow );
1f90939c 1349 else
52c3df99 1350 ::TransitionWindow( (WindowRef)m_macWindow, kWindowZoomTransitionEffect, kWindowShowTransitionAction, NULL );
52c3df99 1351
1f90939c 1352 ::SelectWindow( (WindowRef)m_macWindow ) ;
52c3df99
DS
1353
1354 // because apps expect a size event to occur at this moment
a979e444 1355 wxSizeEvent event(GetSize() , m_windowId);
1f90939c
SC
1356 event.SetEventObject(this);
1357 GetEventHandler()->ProcessEvent(event);
5f0b2f22
SC
1358 }
1359 else
1360 {
8c8f6a4b 1361 if ( plainTransition )
21e77aa1 1362 ::HideWindow( (WindowRef)m_macWindow );
1f90939c 1363 else
21e77aa1 1364 ::TransitionWindow( (WindowRef)m_macWindow, kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL );
5f0b2f22
SC
1365 }
1366
facd6764 1367 MacPropagateVisibilityChanged() ;
5f0b2f22 1368
902725ee 1369 return true ;
5f0b2f22
SC
1370}
1371
c5985061 1372bool wxTopLevelWindowMac::ShowFullScreen(bool show, long style)
902725ee 1373{
c5985061
SC
1374 if ( show )
1375 {
1376 FullScreenData *data = (FullScreenData *)m_macFullScreenData ;
1377 delete data ;
1378 data = new FullScreenData() ;
902725ee 1379
c5985061
SC
1380 m_macFullScreenData = data ;
1381 data->m_position = GetPosition() ;
1382 data->m_size = GetSize() ;
f3b2e2d7 1383 data->m_wasResizable = MacGetWindowAttributes() & kWindowResizableAttribute ;
902725ee 1384
c5985061 1385 if ( style & wxFULLSCREEN_NOMENUBAR )
52c3df99
DS
1386 HideMenuBar() ;
1387
c5985061
SC
1388 wxRect client = wxGetClientDisplayRect() ;
1389
52c3df99 1390 int left , top , right , bottom ;
c5985061 1391 int x, y, w, h ;
902725ee 1392
c5985061
SC
1393 x = client.x ;
1394 y = client.y ;
1395 w = client.width ;
1396 h = client.height ;
902725ee 1397
c5985061
SC
1398 MacGetContentAreaInset( left , top , right , bottom ) ;
1399
1400 if ( style & wxFULLSCREEN_NOCAPTION )
1401 {
1402 y -= top ;
1403 h += top ;
1404 }
52c3df99 1405
c5985061
SC
1406 if ( style & wxFULLSCREEN_NOBORDER )
1407 {
1408 x -= left ;
1409 w += left + right ;
1410 h += bottom ;
1411 }
52c3df99 1412
c5985061
SC
1413 if ( style & wxFULLSCREEN_NOTOOLBAR )
1414 {
3c86150d
SC
1415 // TODO
1416 }
52c3df99 1417
3c86150d
SC
1418 if ( style & wxFULLSCREEN_NOSTATUSBAR )
1419 {
1420 // TODO
c5985061 1421 }
52c3df99 1422
c5985061 1423 SetSize( x , y , w, h ) ;
172da31f 1424 if ( data->m_wasResizable )
f3b2e2d7 1425 MacChangeWindowAttributes( kWindowNoAttributes , kWindowResizableAttribute ) ;
c5985061
SC
1426 }
1427 else
1428 {
1429 ShowMenuBar() ;
1430 FullScreenData *data = (FullScreenData *) m_macFullScreenData ;
172da31f 1431 if ( data->m_wasResizable )
f3b2e2d7 1432 MacChangeWindowAttributes( kWindowResizableAttribute , kWindowNoAttributes ) ;
c5985061
SC
1433 SetPosition( data->m_position ) ;
1434 SetSize( data->m_size ) ;
52c3df99 1435
c5985061
SC
1436 delete data ;
1437 m_macFullScreenData = NULL ;
1438 }
52c3df99 1439
902725ee 1440 return false;
c5985061
SC
1441}
1442
902725ee
WS
1443bool wxTopLevelWindowMac::IsFullScreen() const
1444{
1445 return m_macFullScreenData != NULL ;
c5985061
SC
1446}
1447
50f3c41d 1448
07880314 1449bool wxTopLevelWindowMac::SetTransparent(wxByte alpha)
50f3c41d 1450{
24fcd264 1451 OSStatus result = SetWindowAlpha((WindowRef)m_macWindow, float(alpha)/255.0);
50f3c41d
RD
1452 return result == noErr;
1453}
1454
1455
07880314 1456bool wxTopLevelWindowMac::CanSetTransparent()
50f3c41d
RD
1457{
1458 return true;
1459}
1460
1461
30c23e74 1462void wxTopLevelWindowMac::SetExtraStyle(long exStyle)
8ec0a8fa
SC
1463{
1464 if ( GetExtraStyle() == exStyle )
1465 return ;
30c23e74 1466
8ec0a8fa 1467 wxTopLevelWindowBase::SetExtraStyle( exStyle ) ;
52c3df99 1468
8ec0a8fa 1469#if TARGET_API_MAC_OSX
f21449ae 1470 if ( m_macWindow != NULL )
8ec0a8fa
SC
1471 {
1472 bool metal = GetExtraStyle() & wxFRAME_EX_METAL ;
893727e5 1473
8ec0a8fa 1474 if ( MacGetMetalAppearance() != metal )
893727e5
KO
1475 {
1476 if ( MacGetUnifiedAppearance() )
1477 MacSetUnifiedAppearance( !metal ) ;
1478
8ec0a8fa 1479 MacSetMetalAppearance( metal ) ;
893727e5 1480 }
8ec0a8fa
SC
1481 }
1482#endif
1483}
1484
30c23e74 1485// TODO: switch to structure bounds -
21e77aa1 1486// we are still using coordinates of the content view
21e77aa1 1487//
29281095
SC
1488void wxTopLevelWindowMac::MacGetContentAreaInset( int &left , int &top , int &right , int &bottom )
1489{
21e77aa1
DS
1490 Rect content, structure ;
1491
29281095
SC
1492 GetWindowBounds( (WindowRef) m_macWindow, kWindowStructureRgn , &structure ) ;
1493 GetWindowBounds( (WindowRef) m_macWindow, kWindowContentRgn , &content ) ;
1494
1495 left = content.left - structure.left ;
1496 top = content.top - structure.top ;
1497 right = structure.right - content.right ;
1498 bottom = structure.bottom - content.bottom ;
1499}
1500
5f0b2f22
SC
1501void wxTopLevelWindowMac::DoMoveWindow(int x, int y, int width, int height)
1502{
c9698388 1503 m_cachedClippedRectValid = false ;
facd6764
SC
1504 Rect bounds = { y , x , y + height , x + width } ;
1505 verify_noerr(SetWindowBounds( (WindowRef) m_macWindow, kWindowStructureRgn , &bounds )) ;
4817190d 1506 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
5f0b2f22
SC
1507}
1508
facd6764 1509void wxTopLevelWindowMac::DoGetPosition( int *x, int *y ) const
5f0b2f22 1510{
facd6764 1511 Rect bounds ;
52c3df99 1512
facd6764 1513 verify_noerr(GetWindowBounds((WindowRef) m_macWindow, kWindowStructureRgn , &bounds )) ;
52c3df99
DS
1514
1515 if (x)
1516 *x = bounds.left ;
1517 if (y)
1518 *y = bounds.top ;
facd6764 1519}
52c3df99 1520
facd6764
SC
1521void wxTopLevelWindowMac::DoGetSize( int *width, int *height ) const
1522{
1523 Rect bounds ;
52c3df99 1524
facd6764 1525 verify_noerr(GetWindowBounds((WindowRef) m_macWindow, kWindowStructureRgn , &bounds )) ;
52c3df99
DS
1526
1527 if (width)
1528 *width = bounds.right - bounds.left ;
1529 if (height)
1530 *height = bounds.bottom - bounds.top ;
facd6764 1531}
1542ea39 1532
facd6764
SC
1533void wxTopLevelWindowMac::DoGetClientSize( int *width, int *height ) const
1534{
1535 Rect bounds ;
52c3df99 1536
facd6764 1537 verify_noerr(GetWindowBounds((WindowRef) m_macWindow, kWindowContentRgn , &bounds )) ;
52c3df99
DS
1538
1539 if (width)
1540 *width = bounds.right - bounds.left ;
1541 if (height)
1542 *height = bounds.bottom - bounds.top ;
facd6764 1543}
1542ea39 1544
902725ee 1545void wxTopLevelWindowMac::MacSetMetalAppearance( bool set )
facd6764
SC
1546{
1547#if TARGET_API_MAC_OSX
893727e5
KO
1548 if ( MacGetUnifiedAppearance() )
1549 MacSetUnifiedAppearance( false ) ;
1550
902725ee 1551 MacChangeWindowAttributes( set ? kWindowMetalAttribute : kWindowNoAttributes ,
facd6764
SC
1552 set ? kWindowNoAttributes : kWindowMetalAttribute ) ;
1553#endif
1554}
1542ea39 1555
902725ee 1556bool wxTopLevelWindowMac::MacGetMetalAppearance() const
6aab345b
SC
1557{
1558#if TARGET_API_MAC_OSX
1559 return MacGetWindowAttributes() & kWindowMetalAttribute ;
1560#else
893727e5 1561 return false;
6aab345b
SC
1562#endif
1563}
1564
893727e5
KO
1565void wxTopLevelWindowMac::MacSetUnifiedAppearance( bool set )
1566{
1567#if TARGET_API_MAC_OSX
1568 if ( UMAGetSystemVersion() >= 0x1040 )
1569 {
1570 if ( MacGetMetalAppearance() )
1571 MacSetMetalAppearance( false ) ;
1572
1573 MacChangeWindowAttributes( set ? kWindowUnifiedTitleAndToolbarAttribute : kWindowNoAttributes ,
1574 set ? kWindowNoAttributes : kWindowUnifiedTitleAndToolbarAttribute) ;
1575
1576 // For some reason, Tiger uses white as the background color for this appearance,
1577 // while most apps using it use the typical striped background. Restore that behavior
1578 // for wx.
1579 // TODO: Determine if we need this on Leopard as well. (should be harmless either way,
1580 // though)
1581 SetBackgroundColour( wxSYS_COLOUR_WINDOW ) ;
1582 }
1583#endif
1584}
1585
1586bool wxTopLevelWindowMac::MacGetUnifiedAppearance() const
1587{
1588#if TARGET_API_MAC_OSX
1589 if ( UMAGetSystemVersion() >= 0x1040 )
1590 return MacGetWindowAttributes() & kWindowUnifiedTitleAndToolbarAttribute ;
1591 else
1592#endif
1593 return false;
1594}
1595
902725ee 1596void wxTopLevelWindowMac::MacChangeWindowAttributes( wxUint32 attributesToSet , wxUint32 attributesToClear )
facd6764 1597{
52c3df99 1598 ChangeWindowAttributes( (WindowRef)m_macWindow, attributesToSet, attributesToClear ) ;
facd6764 1599}
1542ea39 1600
902725ee 1601wxUint32 wxTopLevelWindowMac::MacGetWindowAttributes() const
facd6764
SC
1602{
1603 UInt32 attr = 0 ;
52c3df99
DS
1604 GetWindowAttributes( (WindowRef) m_macWindow, &attr ) ;
1605
facd6764 1606 return attr ;
5f0b2f22 1607}
a07c1212 1608
902725ee 1609void wxTopLevelWindowMac::MacPerformUpdates()
92346151 1610{
92346151 1611#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
f21449ae
SC
1612 // for composited windows this also triggers a redraw of all
1613 // invalid views in the window
1614 if ( UMAGetSystemVersion() >= 0x1030 )
1615 HIWindowFlush((WindowRef) m_macWindow) ;
92346151
SC
1616 else
1617#endif
1618 {
f21449ae
SC
1619 // the only way to trigger the redrawing on earlier systems is to call
1620 // ReceiveNextEvent
902725ee 1621
f21449ae
SC
1622 EventRef currentEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
1623 UInt32 currentEventClass = 0 ;
f21449ae 1624 if ( currentEvent != NULL )
902725ee 1625 {
f21449ae 1626 currentEventClass = ::GetEventClass( currentEvent ) ;
716d0327 1627 ::GetEventKind( currentEvent ) ;
902725ee 1628 }
52c3df99 1629
f21449ae
SC
1630 if ( currentEventClass != kEventClassMenu )
1631 {
1632 // when tracking a menu, strange redraw errors occur if we flush now, so leave..
1633 EventRef theEvent;
716d0327 1634 ReceiveNextEvent( 0 , NULL , kEventDurationNoWait , false , &theEvent ) ;
f21449ae 1635 }
92346151
SC
1636 }
1637}
1638
3feeb1e1
SC
1639// Attracts the users attention to this window if the application is
1640// inactive (should be called when a background event occurs)
1641
1642static pascal void wxMacNMResponse( NMRecPtr ptr )
1643{
1644 NMRemove( ptr ) ;
a979e444 1645 DisposePtr( (Ptr)ptr ) ;
3feeb1e1
SC
1646}
1647
3feeb1e1
SC
1648void wxTopLevelWindowMac::RequestUserAttention(int flags )
1649{
1650 NMRecPtr notificationRequest = (NMRecPtr) NewPtr( sizeof( NMRec) ) ;
52c3df99
DS
1651 static wxMacNMUPP nmupp( wxMacNMResponse );
1652
3feeb1e1
SC
1653 memset( notificationRequest , 0 , sizeof(*notificationRequest) ) ;
1654 notificationRequest->qType = nmType ;
1655 notificationRequest->nmMark = 1 ;
1656 notificationRequest->nmIcon = 0 ;
1657 notificationRequest->nmSound = 0 ;
1658 notificationRequest->nmStr = NULL ;
1659 notificationRequest->nmResp = nmupp ;
52c3df99 1660
3feeb1e1
SC
1661 verify_noerr( NMInstall( notificationRequest ) ) ;
1662}
1663
facd6764
SC
1664// ---------------------------------------------------------------------------
1665// Shape implementation
1666// ---------------------------------------------------------------------------
1667
6a7e6411 1668
1542ea39
RD
1669bool wxTopLevelWindowMac::SetShape(const wxRegion& region)
1670{
902725ee 1671 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
6a7e6411
RD
1672 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));
1673
a979e444
DS
1674 // The empty region signifies that the shape
1675 // should be removed from the window.
6a7e6411
RD
1676 if ( region.IsEmpty() )
1677 {
1678 wxSize sz = GetClientSize();
1679 wxRegion rgn(0, 0, sz.x, sz.y);
3c393c0a
SC
1680 if ( rgn.IsEmpty() )
1681 return false ;
1682 else
1683 return SetShape(rgn);
6a7e6411
RD
1684 }
1685
1686 // Make a copy of the region
1687 RgnHandle shapeRegion = NewRgn();
1688 CopyRgn( (RgnHandle)region.GetWXHRGN(), shapeRegion );
1689
1690 // Dispose of any shape region we may already have
1691 RgnHandle oldRgn = (RgnHandle)GetWRefCon( (WindowRef)MacGetWindowRef() );
1692 if ( oldRgn )
1693 DisposeRgn(oldRgn);
1694
1695 // Save the region so we can use it later
7cd7bc23 1696 SetWRefCon((WindowRef)MacGetWindowRef(), (URefCon)shapeRegion);
6a7e6411 1697
52c3df99 1698 // inform the window manager that the window has changed shape
6a7e6411 1699 ReshapeCustomWindow((WindowRef)MacGetWindowRef());
52c3df99 1700
902725ee 1701 return true;
6a7e6411
RD
1702}
1703
6a7e6411
RD
1704// ---------------------------------------------------------------------------
1705// Support functions for shaped windows, based on Apple's CustomWindow sample at
1706// http://developer.apple.com/samplecode/Sample_Code/Human_Interface_Toolbox/Mac_OS_High_Level_Toolbox/CustomWindow.htm
1707// ---------------------------------------------------------------------------
1708
6a7e6411
RD
1709static void wxShapedMacWindowGetPos(WindowRef window, Rect* inRect)
1710{
1711 GetWindowPortBounds(window, inRect);
7cd7bc23
SC
1712 Point pt = { inRect->top ,inRect->left };
1713 wxMacLocalToGlobal( window, &pt ) ;
1714 inRect->bottom += pt.v - inRect->top;
1715 inRect->right += pt.h - inRect->left;
6a7e6411
RD
1716 inRect->top = pt.v;
1717 inRect->left = pt.h;
6a7e6411
RD
1718}
1719
6a7e6411
RD
1720static SInt32 wxShapedMacWindowGetFeatures(WindowRef window, SInt32 param)
1721{
1722 /*------------------------------------------------------
1723 Define which options your custom window supports.
1724 --------------------------------------------------------*/
1725 //just enable everything for our demo
52c3df99
DS
1726 *(OptionBits*)param =
1727 //kWindowCanGrow |
1728 //kWindowCanZoom |
1729 //kWindowCanCollapse |
1730 //kWindowCanGetWindowRegion |
1731 //kWindowHasTitleBar |
1732 //kWindowSupportsDragHilite |
1733 kWindowCanDrawInCurrentPort |
1734 //kWindowCanMeasureTitle |
1735 kWindowWantsDisposeAtProcessDeath |
1736 kWindowSupportsGetGrowImageRegion |
1737 kWindowDefSupportsColorGrafPort;
1738
6a7e6411 1739 return 1;
1542ea39 1740}
6a7e6411
RD
1741
1742// The content region is left as a rectangle matching the window size, this is
1743// so the origin in the paint event, and etc. still matches what the
1744// programmer expects.
1745static void wxShapedMacWindowContentRegion(WindowRef window, RgnHandle rgn)
1746{
1747 SetEmptyRgn(rgn);
1748 wxTopLevelWindowMac* win = wxFindWinFromMacWindow(window);
1749 if (win)
1750 {
b19bf058 1751 Rect r ;
52c3df99 1752 wxShapedMacWindowGetPos( window, &r ) ;
b19bf058 1753 RectRgn( rgn , &r ) ;
6a7e6411
RD
1754 }
1755}
1756
1757// The structure region is set to the shape given to the SetShape method.
1758static void wxShapedMacWindowStructureRegion(WindowRef window, RgnHandle rgn)
1759{
1760 RgnHandle cachedRegion = (RgnHandle) GetWRefCon(window);
1761
1762 SetEmptyRgn(rgn);
1763 if (cachedRegion)
1764 {
1765 Rect windowRect;
902725ee
WS
1766 wxShapedMacWindowGetPos(window, &windowRect); // how big is the window
1767 CopyRgn(cachedRegion, rgn); // make a copy of our cached region
6a7e6411 1768 OffsetRgn(rgn, windowRect.left, windowRect.top); // position it over window
902725ee 1769 //MapRgn(rgn, &mMaskSize, &windowRect); //scale it to our actual window size
6a7e6411
RD
1770 }
1771}
1772
6a7e6411
RD
1773static SInt32 wxShapedMacWindowGetRegion(WindowRef window, SInt32 param)
1774{
52c3df99
DS
1775 GetWindowRegionPtr rgnRec = (GetWindowRegionPtr)param;
1776
1777 if (rgnRec == NULL)
1778 return paramErr;
6a7e6411 1779
52c3df99 1780 switch (rgnRec->regionCode)
6a7e6411
RD
1781 {
1782 case kWindowStructureRgn:
1783 wxShapedMacWindowStructureRegion(window, rgnRec->winRgn);
1784 break;
52c3df99 1785
6a7e6411
RD
1786 case kWindowContentRgn:
1787 wxShapedMacWindowContentRegion(window, rgnRec->winRgn);
1788 break;
52c3df99 1789
6a7e6411
RD
1790 default:
1791 SetEmptyRgn(rgnRec->winRgn);
52c3df99
DS
1792 break;
1793 }
6a7e6411
RD
1794
1795 return noErr;
1796}
1797
52c3df99
DS
1798// Determine the region of the window which was hit
1799//
1800static SInt32 wxShapedMacWindowHitTest(WindowRef window, SInt32 param)
6a7e6411 1801{
6a7e6411 1802 Point hitPoint;
52c3df99 1803 static RgnHandle tempRgn = NULL;
6a7e6411 1804
52c3df99
DS
1805 if (tempRgn == NULL)
1806 tempRgn = NewRgn();
6a7e6411 1807
52c3df99
DS
1808 // get the point clicked
1809 SetPt( &hitPoint, LoWord(param), HiWord(param) );
6a7e6411 1810
52c3df99 1811 // Mac OS 8.5 or later
6a7e6411 1812 wxShapedMacWindowStructureRegion(window, tempRgn);
52c3df99 1813 if (PtInRgn( hitPoint, tempRgn )) //in window content region?
6a7e6411
RD
1814 return wInContent;
1815
52c3df99
DS
1816 // no significant area was hit
1817 return wNoHit;
6a7e6411
RD
1818}
1819
6a7e6411
RD
1820static pascal long wxShapedMacWindowDef(short varCode, WindowRef window, SInt16 message, SInt32 param)
1821{
52c3df99 1822 switch (message)
6a7e6411
RD
1823 {
1824 case kWindowMsgHitTest:
52c3df99 1825 return wxShapedMacWindowHitTest(window, param);
6a7e6411
RD
1826
1827 case kWindowMsgGetFeatures:
52c3df99 1828 return wxShapedMacWindowGetFeatures(window, param);
6a7e6411
RD
1829
1830 // kWindowMsgGetRegion is sent during CreateCustomWindow and ReshapeCustomWindow
1831 case kWindowMsgGetRegion:
52c3df99
DS
1832 return wxShapedMacWindowGetRegion(window, param);
1833
1834 default:
1835 break;
6a7e6411
RD
1836 }
1837
1838 return 0;
1839}