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