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