1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        mac/toplevel.cpp 
   3 // Purpose:     implements wxTopLevelWindow for MSW 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2001 SciTech Software, Inc. (www.scitechsoft.com) 
   9 // License:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "toplevel.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  33     #include "wx/toplevel.h" 
  35     #include "wx/string.h" 
  40 #include "wx/mac/uma.h" 
  41 #include "wx/mac/aga.h" 
  43 #include "wx/tooltip.h" 
  46 #include "ToolUtils.h" 
  49 #define wxMAC_DEBUG_REDRAW 0 
  50 #ifndef wxMAC_DEBUG_REDRAW 
  51 #define wxMAC_DEBUG_REDRAW 0 
  54 // ---------------------------------------------------------------------------- 
  56 // ---------------------------------------------------------------------------- 
  58 // list of all frames and modeless dialogs 
  59 wxWindowList       wxModelessWindows
; 
  61 // double click testing 
  62 static   Point     gs_lastWhere
; 
  63 static   long      gs_lastWhen 
= 0; 
  67 static pascal long wxShapedMacWindowDef(short varCode
, WindowRef window
, SInt16 message
, SInt32 param
); 
  70 // ============================================================================ 
  71 // wxTopLevelWindowMac implementation 
  72 // ============================================================================ 
  74 // --------------------------------------------------------------------------- 
  76 // --------------------------------------------------------------------------- 
  80 extern long wxMacTranslateKey(unsigned char key
, unsigned char code
) ; 
  82 static const EventTypeSpec eventList
[] = 
  84     { kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent 
} , 
  86     { kEventClassKeyboard
, kEventRawKeyDown 
} , 
  87     { kEventClassKeyboard
, kEventRawKeyRepeat 
} , 
  88     { kEventClassKeyboard
, kEventRawKeyUp 
} , 
  89     { kEventClassKeyboard
, kEventRawKeyModifiersChanged 
} , 
  91     { kEventClassWindow 
, kEventWindowUpdate 
} , 
  92     { kEventClassWindow 
, kEventWindowActivated 
} , 
  93     { kEventClassWindow 
, kEventWindowDeactivated 
} , 
  94     { kEventClassWindow 
, kEventWindowBoundsChanging 
} , 
  95     { kEventClassWindow 
, kEventWindowBoundsChanged 
} , 
  96     { kEventClassWindow 
, kEventWindowClose 
} , 
  98     { kEventClassMouse 
, kEventMouseDown 
} , 
  99     { kEventClassMouse 
, kEventMouseUp 
} , 
 100     { kEventClassMouse 
, kEventMouseMoved 
} , 
 101     { kEventClassMouse 
, kEventMouseDragged 
} , 
 105 static pascal OSStatus 
TextInputEventHandler( EventHandlerCallRef handler 
, EventRef event 
, void *data 
) 
 107     OSStatus result 
= eventNotHandledErr 
; 
 109     wxWindow
* focus 
= wxWindow::FindFocus() ; 
 114     UInt32 when 
= EventTimeToTicks( GetEventTime( event 
) ) ; 
 118     GetEventParameter( event 
, kEventParamTextInputSendKeyboardEvent 
,typeEventRef
,NULL
,sizeof(rawEvent
),NULL
,&rawEvent 
) ; 
 120     GetEventParameter( rawEvent
, kEventParamKeyMacCharCodes
, typeChar
, NULL
,sizeof(char), NULL
,&charCode 
); 
 121     GetEventParameter( rawEvent
, kEventParamKeyCode
, typeUInt32
, NULL
,  sizeof(UInt32
), NULL
, &keyCode 
); 
 122        GetEventParameter( rawEvent
, kEventParamKeyModifiers
, typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &modifiers
); 
 123     GetEventParameter( rawEvent
, kEventParamMouseLocation
, typeQDPoint
, NULL
, 
 124         sizeof( Point 
), NULL
, &point 
); 
 126     UInt32 message 
= (keyCode 
<< 8) + charCode
; 
 128     switch ( GetEventKind( event 
) ) 
 130         case kEventTextInputUnicodeForKeyEvent 
: 
 131             // this is only called when no default handler has jumped in, eg a wxControl on a floater window does not 
 132             // get its own kEventTextInputUnicodeForKeyEvent, so we route back the  
 133             wxControl
* control 
= wxDynamicCast( focus 
, wxControl 
) ; 
 136                 ControlHandle macControl 
= (ControlHandle
) control
->GetMacControl() ; 
 139                     ::HandleControlKey( macControl 
, keyCode 
, charCode 
, modifiers 
) ; 
 144             // this may lead to double events sent to a window in case all handlers have skipped the key down event 
 145             if ( (focus != NULL) && wxTheApp->MacSendKeyDownEvent( 
 146                 focus , message , modifiers , when , point.h , point.v ) ) 
 157 static pascal OSStatus 
KeyboardEventHandler( EventHandlerCallRef handler 
, EventRef event 
, void *data 
) 
 159     OSStatus result 
= eventNotHandledErr 
; 
 161     wxWindow
* focus 
= wxWindow::FindFocus() ; 
 166     UInt32 when 
= EventTimeToTicks( GetEventTime( event 
) ) ; 
 168     GetEventParameter( event
, kEventParamKeyMacCharCodes
, typeChar
, NULL
,sizeof(char), NULL
,&charCode 
); 
 169     GetEventParameter( event
, kEventParamKeyCode
, typeUInt32
, NULL
,  sizeof(UInt32
), NULL
, &keyCode 
); 
 170        GetEventParameter(event
, kEventParamKeyModifiers
, typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &modifiers
); 
 171     GetEventParameter( event
, kEventParamMouseLocation
, typeQDPoint
, NULL
, 
 172         sizeof( Point 
), NULL
, &point 
); 
 174     UInt32 message 
= (keyCode 
<< 8) + charCode
; 
 175     switch( GetEventKind( event 
) ) 
 177         case kEventRawKeyRepeat 
: 
 178         case kEventRawKeyDown 
: 
 179             if ( (focus 
!= NULL
) && wxTheApp
->MacSendKeyDownEvent( 
 180                 focus 
, message 
, modifiers 
, when 
, point
.h 
, point
.v 
) ) 
 185         case kEventRawKeyUp 
: 
 186             if ( (focus 
!= NULL
) && wxTheApp
->MacSendKeyUpEvent( 
 187                 focus 
, message 
, modifiers 
, when 
, point
.h 
, point
.v 
) ) 
 192         case kEventRawKeyModifiersChanged 
: 
 194                 wxKeyEvent 
event(wxEVT_KEY_DOWN
); 
 196                 event
.m_shiftDown 
= modifiers 
& shiftKey
; 
 197                 event
.m_controlDown 
= modifiers 
& controlKey
; 
 198                 event
.m_altDown 
= modifiers 
& optionKey
; 
 199                 event
.m_metaDown 
= modifiers 
& cmdKey
; 
 203                 event
.m_timeStamp 
= when
; 
 204                 wxWindow
* focus 
= wxWindow::FindFocus() ; 
 205                 event
.SetEventObject(focus
); 
 207                 if ( focus 
&& (modifiers 
^ wxTheApp
->s_lastModifiers 
) & controlKey 
) 
 209                     event
.m_keyCode 
= WXK_CONTROL 
; 
 210                     event
.SetEventType( ( modifiers 
& controlKey 
) ? wxEVT_KEY_DOWN 
: wxEVT_KEY_UP 
) ; 
 211                     focus
->GetEventHandler()->ProcessEvent( event 
) ; 
 213                 if ( focus 
&& (modifiers 
^ wxTheApp
->s_lastModifiers 
) & shiftKey 
) 
 215                     event
.m_keyCode 
= WXK_SHIFT 
; 
 216                     event
.SetEventType( ( modifiers 
& shiftKey 
) ? wxEVT_KEY_DOWN 
: wxEVT_KEY_UP 
) ; 
 217                     focus
->GetEventHandler()->ProcessEvent( event 
) ; 
 219                 if ( focus 
&& (modifiers 
^ wxTheApp
->s_lastModifiers 
) & optionKey 
) 
 221                     event
.m_keyCode 
= WXK_ALT 
; 
 222                     event
.SetEventType( ( modifiers 
& optionKey 
) ? wxEVT_KEY_DOWN 
: wxEVT_KEY_UP 
) ; 
 223                     focus
->GetEventHandler()->ProcessEvent( event 
) ; 
 225                 wxTheApp
->s_lastModifiers 
= modifiers 
; 
 233 static pascal OSStatus 
MouseEventHandler( EventHandlerCallRef handler 
, EventRef event 
, void *data 
) 
 235     OSStatus result 
= eventNotHandledErr 
; 
 237     wxTopLevelWindowMac
* toplevelWindow 
= (wxTopLevelWindowMac
*) data 
; 
 239     UInt32 modifiers 
= 0; 
 240     EventMouseButton button 
= 0 ; 
 243     GetEventParameter( event
, kEventParamMouseLocation
, typeQDPoint
, NULL
, 
 244         sizeof( Point 
), NULL
, &point 
); 
 245     GetEventParameter( event
, kEventParamKeyModifiers
, typeUInt32
, NULL
, 
 246         sizeof( UInt32 
), NULL
, &modifiers 
); 
 247     GetEventParameter( event
, kEventParamMouseButton
, typeMouseButton
, NULL
, 
 248         sizeof( EventMouseButton 
), NULL
, &button 
); 
 249     GetEventParameter( event
, kEventParamClickCount
, typeUInt32
, NULL
, 
 250         sizeof( UInt32 
), NULL
, &click 
); 
 252     if ( button 
== 0 || GetEventKind( event 
) == kEventMouseUp 
) 
 253         modifiers 
+= btnState 
; 
 256     short windowPart 
= ::FindWindow(point
, &window
); 
 258     if ( IsWindowActive(window
) && windowPart 
== inContent 
) 
 260         switch ( GetEventKind( event 
) ) 
 262             case kEventMouseDown 
: 
 263                 toplevelWindow
->MacFireMouseEvent( mouseDown 
, point
.h 
, point
.v 
, modifiers 
, EventTimeToTicks( GetEventTime( event 
) ) ) ; 
 267                 toplevelWindow
->MacFireMouseEvent( mouseUp 
, point
.h 
, point
.v 
, modifiers 
, EventTimeToTicks( GetEventTime( event 
) ) ) ; 
 270             case kEventMouseMoved 
: 
 271                 toplevelWindow
->MacFireMouseEvent( nullEvent 
, point
.h 
, point
.v 
, modifiers 
, EventTimeToTicks( GetEventTime( event 
) ) ) ; 
 274             case kEventMouseDragged 
: 
 275                 toplevelWindow
->MacFireMouseEvent( nullEvent 
, point
.h 
, point
.v 
, modifiers 
, EventTimeToTicks( GetEventTime( event 
) ) ) ; 
 287 static pascal OSStatus 
WindowEventHandler( EventHandlerCallRef handler 
, EventRef event 
, void *data 
) 
 289     OSStatus result 
= eventNotHandledErr 
; 
 290     OSStatus err 
= noErr 
; 
 293     WindowRef windowRef 
; 
 294     wxTopLevelWindowMac
* toplevelWindow 
= (wxTopLevelWindowMac
*) data 
; 
 296     GetEventParameter( event
, kEventParamDirectObject
, typeWindowRef
, NULL
, 
 297         sizeof( WindowRef 
), NULL
, &windowRef 
); 
 299     switch( GetEventKind( event 
) ) 
 301         case kEventWindowUpdate 
: 
 302             if ( !wxPendingDelete
.Member(toplevelWindow
) ) 
 303                 toplevelWindow
->MacUpdate( EventTimeToTicks( GetEventTime( event 
) ) ) ; 
 306         case kEventWindowActivated 
: 
 307                 toplevelWindow
->MacActivate( EventTimeToTicks( GetEventTime( event 
) ) , true) ; 
 310         case kEventWindowDeactivated 
: 
 311                 toplevelWindow
->MacActivate( EventTimeToTicks( GetEventTime( event 
) ) , false) ; 
 314         case kEventWindowClose 
: 
 315                 toplevelWindow
->Close() ; 
 318         case kEventWindowBoundsChanged 
: 
 319             err 
= GetEventParameter( event
, kEventParamAttributes
, typeUInt32
, 
 320                         NULL
, sizeof( UInt32 
), NULL
, &attributes 
); 
 323                 Rect newContentRect 
; 
 325                 GetEventParameter( event
, kEventParamCurrentBounds
, typeQDRectangle
, NULL
, 
 326                     sizeof( newContentRect 
), NULL
, &newContentRect 
); 
 328                 toplevelWindow
->SetSize( newContentRect
.left 
, newContentRect
.top 
, 
 329                     newContentRect
.right 
- newContentRect
.left 
, 
 330                     newContentRect
.bottom 
- newContentRect
.top
, wxSIZE_USE_EXISTING
); 
 341 pascal OSStatus 
wxMacWindowEventHandler( EventHandlerCallRef handler 
, EventRef event 
, void *data 
) 
 343     OSStatus result 
= eventNotHandledErr 
; 
 345     switch ( GetEventClass( event 
) ) 
 347         case kEventClassKeyboard 
: 
 348             result 
= KeyboardEventHandler( handler
, event 
, data 
) ; 
 350         case kEventClassTextInput 
: 
 351             result 
= TextInputEventHandler( handler
, event 
, data 
) ; 
 353         case kEventClassWindow 
: 
 354             result 
= WindowEventHandler( handler
, event 
, data 
) ; 
 356         case kEventClassMouse 
: 
 357             result 
= MouseEventHandler( handler
, event 
, data 
) ; 
 365 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler 
) 
 367 // Patch 531199 defined a window event handler, as follows. 
 368 // TODO: merge the moving/sizing event handling with the event 
 371 static pascal OSStatus
 
 372 WindowHandler( EventHandlerCallRef inHandler
, EventRef inEvent
, void* userData 
) 
 375     SInt16              height
, width
; 
 377     OSStatus    result 
= eventNotHandledErr
; 
 379     GetEventParameter( inEvent
, kEventParamAttributes
, typeUInt32
, NULL
, sizeof( UInt32 
), NULL
, &attributes 
); 
 381     if ((attributes 
& (kWindowBoundsChangeSizeChanged 
| kWindowBoundsChangeOriginChanged
)) != 0) 
 383         // Extract the current bounds. This is the paramter you get to modify to 
 384         // alter the window position or size during a window resizing. 
 385         GetEventParameter( inEvent
, kEventParamCurrentBounds
, typeQDRectangle
, NULL
, sizeof( bounds 
), NULL
, &bounds 
); 
 388         rect
.SetLeft(bounds
.left
); 
 389         rect
.SetTop(bounds
.top
); 
 390         rect
.SetRight(bounds
.right
); 
 391         rect
.SetBottom(bounds
.bottom
); 
 394         wxWindowMac 
*pWindow 
= (wxWindowMac
*)userData
; 
 395         if ((attributes 
& kWindowBoundsChangeSizeChanged
) != 0) { 
 396             wxSizeEvent 
event(rect
, pWindow
->GetId()); 
 397             event
.SetEventObject(pWindow
); 
 398             rc 
= pWindow
->GetEventHandler()->ProcessEvent(event
); 
 399             rect 
= event
.GetRect(); 
 402             wxMoveEvent 
event(rect
, pWindow
->GetId()); 
 403             event
.SetEventObject(pWindow
); 
 404             rc 
= pWindow
->GetEventHandler()->ProcessEvent(event
); 
 405             rect 
= event
.GetRect(); 
 409             bounds
.left 
= rect
.GetLeft(); 
 410             bounds
.top 
= rect
.GetTop(); 
 411             bounds
.right 
= rect
.GetRight(); 
 412             bounds
.bottom 
= rect
.GetBottom(); 
 415         // Set the current bounds parameter to our adjusted bounds. Return 
 416         // noErr to indicate we handled this event. 
 417         SetEventParameter( inEvent
, kEventParamCurrentBounds
, typeQDRectangle
, sizeof( bounds 
), &bounds 
); 
 427 // --------------------------------------------------------------------------- 
 428 // wxWindowMac utility functions 
 429 // --------------------------------------------------------------------------- 
 431 // Find an item given the Macintosh Window Reference 
 433 wxList 
*wxWinMacWindowList 
= NULL
; 
 434 wxTopLevelWindowMac 
*wxFindWinFromMacWindow(WXWindow inWindowRef
) 
 436     wxNode 
*node 
= wxWinMacWindowList
->Find((long)inWindowRef
); 
 439     return (wxTopLevelWindowMac 
*)node
->GetData(); 
 442 void wxAssociateWinWithMacWindow(WXWindow inWindowRef
, wxTopLevelWindowMac 
*win
) 
 444     // adding NULL WindowRef is (first) surely a result of an error and 
 445     // (secondly) breaks menu command processing 
 446     wxCHECK_RET( inWindowRef 
!= (WindowRef
) NULL
, wxT("attempt to add a NULL WindowRef to window list") ); 
 448     if ( !wxWinMacWindowList
->Find((long)inWindowRef
) ) 
 449         wxWinMacWindowList
->Append((long)inWindowRef
, win
); 
 452 void wxRemoveMacWindowAssociation(wxTopLevelWindowMac 
*win
) 
 454     wxWinMacWindowList
->DeleteObject(win
); 
 458 // ---------------------------------------------------------------------------- 
 459 // wxTopLevelWindowMac creation 
 460 // ---------------------------------------------------------------------------- 
 462 WXHWND 
wxTopLevelWindowMac::s_macWindowInUpdate 
= NULL
; 
 464 void wxTopLevelWindowMac::Init() 
 467     m_maximizeOnShow 
= FALSE
; 
 468     m_macNoEraseUpdateRgn 
= NewRgn() ; 
 469     m_macNeedsErasing 
= false ; 
 472     m_macEventHandler 
= NULL 
; 
 476 class wxMacDeferredWindowDeleter 
: public wxObject
 
 479     wxMacDeferredWindowDeleter( WindowRef windowRef 
) 
 481         m_macWindow 
= windowRef 
; 
 483     virtual ~wxMacDeferredWindowDeleter() 
 485         UMADisposeWindow( (WindowRef
) m_macWindow 
) ; 
 488     WindowRef m_macWindow 
; 
 491 bool wxTopLevelWindowMac::Create(wxWindow 
*parent
, 
 493                                  const wxString
& title
, 
 497                                  const wxString
& name
) 
 502     m_windowStyle 
= style
; 
 506     m_windowId 
= id 
== -1 ? NewControlId() : id
; 
 508     wxTopLevelWindows
.Append(this); 
 511         parent
->AddChild(this); 
 516 wxTopLevelWindowMac::~wxTopLevelWindowMac() 
 520         wxToolTip::NotifyWindowDelete(m_macWindow
) ; 
 521         wxPendingDelete
.Append( new wxMacDeferredWindowDeleter( (WindowRef
) m_macWindow 
) ) ; 
 525     if ( m_macEventHandler 
) 
 527         ::RemoveEventHandler((EventHandlerRef
) m_macEventHandler
); 
 528         m_macEventHandler 
= NULL 
; 
 532     wxRemoveMacWindowAssociation( this ) ; 
 534     if ( wxModelessWindows
.Find(this) ) 
 535         wxModelessWindows
.DeleteObject(this); 
 537     DisposeRgn( (RgnHandle
) m_macNoEraseUpdateRgn 
) ; 
 541 // ---------------------------------------------------------------------------- 
 542 // wxTopLevelWindowMac maximize/minimize 
 543 // ---------------------------------------------------------------------------- 
 545 void wxTopLevelWindowMac::Maximize(bool maximize
) 
 547     // not available on mac 
 550 bool wxTopLevelWindowMac::IsMaximized() const 
 555 void wxTopLevelWindowMac::Iconize(bool iconize
) 
 557     // not available on mac 
 560 bool wxTopLevelWindowMac::IsIconized() const 
 562     // mac dialogs cannot be iconized 
 566 void wxTopLevelWindowMac::Restore() 
 568     // not available on mac 
 571 // ---------------------------------------------------------------------------- 
 572 // wxTopLevelWindowMac misc 
 573 // ---------------------------------------------------------------------------- 
 575 void wxTopLevelWindowMac::SetIcon(const wxIcon
& icon
) 
 578     wxTopLevelWindowBase::SetIcon(icon
); 
 581 void  wxTopLevelWindowMac::MacCreateRealWindow( const wxString
& title
, 
 585            const wxString
& name 
) 
 588     m_windowStyle 
= style
; 
 609     ::SetRect(&theBoundsRect
, m_x
, m_y 
, m_x 
+ m_width
, m_y 
+ m_height
); 
 611     // translate the window attributes in the appropriate window class and attributes 
 613     WindowClass wclass 
= 0; 
 614     WindowAttributes attr 
= kWindowNoAttributes 
; 
 616     if ( HasFlag( wxFRAME_TOOL_WINDOW
) ) 
 619             HasFlag( wxMINIMIZE_BOX 
) || HasFlag( wxMAXIMIZE_BOX 
) || 
 620             HasFlag( wxSYSTEM_MENU 
) || HasFlag( wxCAPTION 
) || 
 621             HasFlag(wxTINY_CAPTION_HORIZ
) ||  HasFlag(wxTINY_CAPTION_VERT
) 
 624             wclass 
= kFloatingWindowClass 
; 
 625             if ( HasFlag(wxTINY_CAPTION_VERT
) ) 
 627                 attr 
|= kWindowSideTitlebarAttribute 
; 
 633             wclass 
= kPlainWindowClass 
; 
 635             wclass 
= kFloatingWindowClass 
; 
 639     else if ( HasFlag( wxCAPTION 
) ) 
 641         wclass 
= kDocumentWindowClass 
; 
 645         if ( HasFlag( wxMINIMIZE_BOX 
) || HasFlag( wxMAXIMIZE_BOX 
) || 
 646             HasFlag( wxSYSTEM_MENU 
) ) 
 648             wclass 
= kDocumentWindowClass 
; 
 653             wclass 
= kPlainWindowClass 
; 
 655             wclass 
= kModalWindowClass 
; 
 660     if ( HasFlag( wxMINIMIZE_BOX 
) || HasFlag( wxMAXIMIZE_BOX 
) ) 
 662         attr 
|= kWindowFullZoomAttribute 
; 
 663         attr 
|= kWindowCollapseBoxAttribute 
; 
 665     if ( HasFlag( wxRESIZE_BORDER 
) ) 
 667         attr 
|= kWindowResizableAttribute 
; 
 669     if ( HasFlag( wxSYSTEM_MENU 
) ) 
 671         attr 
|= kWindowCloseBoxAttribute 
; 
 675 #if 0 //  having problems right now with that 
 676     if (HasFlag(wxSTAY_ON_TOP
)) 
 677         wclass 
= kUtilityWindowClass
; 
 682     if ( HasFlag(wxFRAME_SHAPED
) ) 
 684         WindowDefSpec customWindowDefSpec
; 
 685         customWindowDefSpec
.defType 
= kWindowDefProcPtr
; 
 686         customWindowDefSpec
.u
.defProc 
= NewWindowDefUPP(wxShapedMacWindowDef
); 
 688         ::CreateCustomWindow( &customWindowDefSpec
, wclass
, 
 689                               attr
, &theBoundsRect
, 
 690                               (WindowRef
*) &m_macWindow
); 
 695         ::CreateNewWindow( wclass 
, attr 
, &theBoundsRect 
, (WindowRef
*)&m_macWindow 
) ; 
 698     wxAssociateWinWithMacWindow( m_macWindow 
, this ) ; 
 699     UMASetWTitle( (WindowRef
)m_macWindow 
, title 
) ; 
 700     ::CreateRootControl( (WindowRef
)m_macWindow 
, (ControlHandle
*)&m_macRootControl 
) ; 
 702     InstallStandardEventHandler( GetWindowEventTarget(MAC_WXHWND(m_macWindow
)) ) ; 
 703     InstallWindowEventHandler(MAC_WXHWND(m_macWindow
), GetwxMacWindowEventHandlerUPP(), 
 704         GetEventTypeCount(eventList
), eventList
, this, &((EventHandlerRef
)m_macEventHandler
)); 
 706     // Patch 531199 also defined a window event handler, as follows: 
 708     // install a window event handler to send wxEVT_MOVING and wxEVT_SIZING events 
 709     EventTypeSpec events
[] = { { kEventClassWindow
, kEventWindowBoundsChanging 
} }; 
 710     EventHandlerUPP     handlerProc 
= NewEventHandlerUPP( WindowHandler 
); 
 711     EventHandlerRef eventHandlerRef
; 
 712     InstallWindowEventHandler( m_macWindowData
->m_macWindow
, handlerProc
, GetEventTypeCount(events
), 
 713         events
, (void*)this, &eventHandlerRef
); 
 721     if ( HasFlag(wxFRAME_SHAPED
) ) 
 723         // default shape matches the window size 
 724         wxRegion 
rgn(0, 0, m_width
, m_height
); 
 730 void wxTopLevelWindowMac::MacGetPortParams(WXPOINTPTR localOrigin
, WXRECTPTR clipRect
, WXHWND 
*window  
, wxWindowMac
** rootwin
) 
 732     ((Point
*)localOrigin
)->h 
= 0; 
 733     ((Point
*)localOrigin
)->v 
= 0; 
 734     ((Rect
*)clipRect
)->left 
= 0; 
 735     ((Rect
*)clipRect
)->top 
= 0; 
 736     ((Rect
*)clipRect
)->right 
= m_width
; 
 737     ((Rect
*)clipRect
)->bottom 
= m_height
; 
 738     *window 
= m_macWindow 
; 
 742 void wxTopLevelWindowMac::Clear() 
 747 WXWidget 
wxTopLevelWindowMac::MacGetContainerForEmbedding() 
 749     return m_macRootControl 
; 
 753 void wxTopLevelWindowMac::MacUpdate( long timestamp
) 
 755     wxMacPortStateHelper 
help( (GrafPtr
) GetWindowPort( (WindowRef
) m_macWindow
) ) ; 
 757     RgnHandle       visRgn 
= NewRgn() ; 
 758     GetPortVisibleRegion( GetWindowPort( (WindowRef
)m_macWindow 
), visRgn 
); 
 759     BeginUpdate( (WindowRef
)m_macWindow 
) ; 
 761     RgnHandle       updateRgn 
= NewRgn(); 
 762     RgnHandle       diffRgn 
= NewRgn() ; 
 764     if ( updateRgn 
&& diffRgn 
) 
 767         // macos internal control redraws clean up areas we'd like to redraw ourselves 
 768         // therefore we pick the boundary rect and make sure we can redraw it 
 769         // this has to be intersected by the visRgn in order to avoid drawing over its own 
 771         RgnHandle trueUpdateRgn 
= NewRgn() ; 
 772         Rect trueUpdateRgnBoundary 
; 
 773         GetPortVisibleRegion( GetWindowPort( (WindowRef
)m_macWindow 
), trueUpdateRgn 
); 
 774         GetRegionBounds( trueUpdateRgn 
, &trueUpdateRgnBoundary 
) ; 
 775         RectRgn( updateRgn 
, &trueUpdateRgnBoundary 
) ; 
 776         SectRgn( updateRgn 
, visRgn 
, updateRgn 
) ; 
 778             DisposeRgn( trueUpdateRgn 
) ; 
 779         SetPortVisibleRegion(  GetWindowPort( (WindowRef
)m_macWindow 
), updateRgn 
) ; 
 781         GetPortVisibleRegion( GetWindowPort( (WindowRef
)m_macWindow 
), updateRgn 
); 
 783         DiffRgn( updateRgn 
, (RgnHandle
) m_macNoEraseUpdateRgn 
, diffRgn 
) ; 
 784         if ( !EmptyRgn( updateRgn 
) ) 
 786             MacRedraw( updateRgn 
, timestamp 
, m_macNeedsErasing 
|| !EmptyRgn( diffRgn 
)  ) ; 
 790         DisposeRgn( updateRgn 
); 
 792         DisposeRgn( diffRgn 
); 
 794         DisposeRgn( visRgn 
) ; 
 796     EndUpdate( (WindowRef
)m_macWindow 
) ; 
 797     SetEmptyRgn( (RgnHandle
) m_macNoEraseUpdateRgn 
) ; 
 798     m_macNeedsErasing 
= false ; 
 802 // Raise the window to the top of the Z order 
 803 void wxTopLevelWindowMac::Raise() 
 805     ::SelectWindow( (WindowRef
)m_macWindow 
) ; 
 808 // Lower the window to the bottom of the Z order 
 809 void wxTopLevelWindowMac::Lower() 
 811     ::SendBehind( (WindowRef
)m_macWindow 
, NULL 
) ; 
 814 void wxTopLevelWindowMac::MacFireMouseEvent( 
 815     wxUint16 kind 
, wxInt32 x 
, wxInt32 y 
,wxUint32 modifiers 
, long timestamp 
) 
 817     wxMouseEvent 
event(wxEVT_LEFT_DOWN
); 
 818     bool isDown 
= !(modifiers 
& btnState
) ; // 1 is for up 
 819     bool controlDown 
= modifiers 
& controlKey 
; // for simulating right mouse 
 821     event
.m_leftDown 
= isDown 
&& !controlDown
; 
 823     event
.m_middleDown 
= FALSE
; 
 824     event
.m_rightDown 
= isDown 
&& controlDown
; 
 826     if ( kind 
== mouseDown 
) 
 829             event
.SetEventType(wxEVT_RIGHT_DOWN 
) ; 
 831             event
.SetEventType(wxEVT_LEFT_DOWN 
) ; 
 833     else if ( kind 
== mouseUp 
) 
 836             event
.SetEventType(wxEVT_RIGHT_UP 
) ; 
 838             event
.SetEventType(wxEVT_LEFT_UP 
) ; 
 842         event
.SetEventType(wxEVT_MOTION 
) ; 
 845     event
.m_shiftDown 
= modifiers 
& shiftKey
; 
 846     event
.m_controlDown 
= modifiers 
& controlKey
; 
 847     event
.m_altDown 
= modifiers 
& optionKey
; 
 848     event
.m_metaDown 
= modifiers 
& cmdKey
; 
 856     ::SetPort( UMAGetWindowPort( (WindowRef
)m_macWindow 
) ) ; 
 857     ::GlobalToLocal( &localwhere 
) ; 
 860     if ( kind 
== mouseDown 
) 
 862         if ( timestamp 
- gs_lastWhen 
<= (long) GetDblTime() ) 
 864             if ( abs( localwhere
.h 
- gs_lastWhere
.h 
) < 3 && abs( localwhere
.v 
- gs_lastWhere
.v 
) < 3 ) 
 866                 // This is not right if the second mouse down 
 867                 // event occured in a differen window. We 
 868                 // correct this in MacDispatchMouseEvent. 
 870                     event
.SetEventType(wxEVT_RIGHT_DCLICK 
) ; 
 872                     event
.SetEventType(wxEVT_LEFT_DCLICK 
) ; 
 878             gs_lastWhen 
= timestamp 
; 
 880         gs_lastWhere 
= localwhere 
; 
 883     event
.m_x 
= localwhere
.h
; 
 884     event
.m_y 
= localwhere
.v
; 
 888     event
.m_timeStamp 
= timestamp
; 
 889     event
.SetEventObject(this); 
 890     if ( wxTheApp
->s_captureWindow 
) 
 894         wxTheApp
->s_captureWindow
->ScreenToClient( &x 
, &y 
) ; 
 897         event
.SetEventObject( wxTheApp
->s_captureWindow 
) ; 
 898         wxTheApp
->s_captureWindow
->GetEventHandler()->ProcessEvent( event 
) ; 
 900         if ( kind 
== mouseUp 
) 
 902             wxTheApp
->s_captureWindow 
= NULL 
; 
 905                 m_cursor
.MacInstall() ; 
 911         MacDispatchMouseEvent( event 
) ; 
 917 void wxTopLevelWindowMac::MacMouseDown( WXEVENTREF ev 
, short part
) 
 919     MacFireMouseEvent( mouseDown 
, ((EventRecord
*)ev
)->where
.h 
, ((EventRecord
*)ev
)->where
.v 
, 
 920         ((EventRecord
*)ev
)->modifiers 
, ((EventRecord
*)ev
)->when 
) ; 
 923 void wxTopLevelWindowMac::MacMouseUp( WXEVENTREF ev 
, short part
) 
 929                 MacFireMouseEvent( mouseUp 
, ((EventRecord
*)ev
)->where
.h 
, ((EventRecord
*)ev
)->where
.v 
, 
 930                     ((EventRecord
*)ev
)->modifiers 
, ((EventRecord
*)ev
)->when 
) ; 
 936 void wxTopLevelWindowMac::MacMouseMoved( WXEVENTREF ev 
, short part
) 
 942                 MacFireMouseEvent( nullEvent 
/*moved*/ , ((EventRecord
*)ev
)->where
.h 
, ((EventRecord
*)ev
)->where
.v 
, 
 943                     ((EventRecord
*)ev
)->modifiers 
, ((EventRecord
*)ev
)->when 
) ; 
 951 void wxTopLevelWindowMac::MacActivate( long timestamp 
, bool inIsActivating 
) 
 953     wxActivateEvent 
event(wxEVT_ACTIVATE
, inIsActivating 
, m_windowId
); 
 954     event
.m_timeStamp 
= timestamp 
; 
 955     event
.SetEventObject(this); 
 957     GetEventHandler()->ProcessEvent(event
); 
 959     UMAHighlightAndActivateWindow( (WindowRef
)m_macWindow 
, inIsActivating 
) ; 
 961     // Early versions of MacOS X don't refresh backgrounds properly, 
 962     // so refresh the whole window on activation and deactivation. 
 963     long osVersion 
= UMAGetSystemVersion(); 
 964     if (osVersion 
>= 0x1000 && osVersion 
< 0x1020 ) 
 970         // for the moment we have to resolve some redrawing issues like this 
 971         // the OS is stealing some redrawing areas as soon as it draws a control 
 978 void wxTopLevelWindowMac::MacKeyDown( WXEVENTREF ev 
) 
 984 void wxTopLevelWindowMac::SetTitle(const wxString
& title
) 
 986     wxWindow::SetTitle( title 
) ; 
 987     UMASetWTitle( (WindowRef
)m_macWindow 
, title 
) ; 
 990 bool wxTopLevelWindowMac::Show(bool show
) 
 992     if ( !wxWindow::Show(show
) ) 
 997       ::TransitionWindow((WindowRef
)m_macWindow
,kWindowZoomTransitionEffect
,kWindowShowTransitionAction
,nil
); 
 998       ::SelectWindow( (WindowRef
)m_macWindow 
) ; 
 999       // no need to generate events here, they will get them triggered by macos 
1000       // actually they should be , but apparently they are not 
1001       wxSize 
size(m_width
, m_height
); 
1002       wxSizeEvent 
event(size
, m_windowId
); 
1003       event
.SetEventObject(this); 
1004       GetEventHandler()->ProcessEvent(event
); 
1008       ::TransitionWindow((WindowRef
)m_macWindow
,kWindowZoomTransitionEffect
,kWindowHideTransitionAction
,nil
); 
1022 void wxTopLevelWindowMac::DoMoveWindow(int x
, int y
, int width
, int height
) 
1024     int former_x 
= m_x 
; 
1025     int former_y 
= m_y 
; 
1026     int former_w 
= m_width 
; 
1027     int former_h 
= m_height 
; 
1029     int actualWidth 
= width
; 
1030     int actualHeight 
= height
; 
1034     if ((m_minWidth 
!= -1) && (actualWidth 
< m_minWidth
)) 
1035         actualWidth 
= m_minWidth
; 
1036     if ((m_minHeight 
!= -1) && (actualHeight 
< m_minHeight
)) 
1037         actualHeight 
= m_minHeight
; 
1038     if ((m_maxWidth 
!= -1) && (actualWidth 
> m_maxWidth
)) 
1039         actualWidth 
= m_maxWidth
; 
1040     if ((m_maxHeight 
!= -1) && (actualHeight 
> m_maxHeight
)) 
1041         actualHeight 
= m_maxHeight
; 
1043     bool doMove 
= false ; 
1044     bool doResize 
= false ; 
1046     if ( actualX 
!= former_x 
|| actualY 
!= former_y 
) 
1050     if ( actualWidth 
!= former_w 
|| actualHeight 
!= former_h 
) 
1055     if ( doMove 
|| doResize 
) 
1059         m_width 
= actualWidth 
; 
1060         m_height 
= actualHeight 
; 
1063             ::MoveWindow((WindowRef
)m_macWindow
, m_x
, m_y  
, false); // don't make frontmost 
1066             ::SizeWindow((WindowRef
)m_macWindow
, m_width
, m_height  
, true); 
1068         // the OS takes care of invalidating and erasing the new area so we only have to 
1069         // take care of refreshing for full repaints 
1071         if ( doResize 
&& !HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
) ) 
1075         if ( IsKindOf( CLASSINFO( wxFrame 
) ) ) 
1077             wxFrame
* frame 
= (wxFrame
*) this ; 
1078             frame
->PositionStatusBar(); 
1079             frame
->PositionToolBar(); 
1082             wxWindowMac::MacTopLevelWindowChangedPosition() ; // like this only children will be notified 
1084         MacRepositionScrollBars() ; 
1087             wxPoint 
point(m_x
, m_y
); 
1088             wxMoveEvent 
event(point
, m_windowId
); 
1089             event
.SetEventObject(this); 
1090             GetEventHandler()->ProcessEvent(event
) ; 
1094              MacRepositionScrollBars() ; 
1095              wxSize 
size(m_width
, m_height
); 
1096              wxSizeEvent 
event(size
, m_windowId
); 
1097              event
.SetEventObject(this); 
1098              GetEventHandler()->ProcessEvent(event
); 
1105  * Invalidation Mechanism 
1107  * The update mechanism reflects exactely the windows mechanism 
1108  * the rect gets added to the window invalidate region, if the eraseBackground flag 
1109  * has been true for any part of the update rgn the background is erased in the entire region 
1110  * not just in the specified rect. 
1112  * In order to achive this, we also have an internal m_macNoEraseUpdateRgn, all rects that have 
1113  * the eraseBackground flag set to false are also added to this rgn. upon receiving an update event 
1114  * the update rgn is compared to the m_macNoEraseUpdateRgn and in case they differ, every window 
1115  * will get the eraseBackground event first 
1118 void wxTopLevelWindowMac::MacInvalidate( const WXRECTPTR rect
, bool eraseBackground 
) 
1120     GrafPtr formerPort 
; 
1121     GetPort( &formerPort 
) ; 
1122     SetPortWindowPort( (WindowRef
)m_macWindow 
) ; 
1124     m_macNeedsErasing 
|= eraseBackground 
; 
1126     // if we already know that we will have to erase, there's no need to track the rest 
1127     if ( !m_macNeedsErasing
) 
1129         // we end only here if eraseBackground is false 
1130         // if we already have a difference between m_macNoEraseUpdateRgn and UpdateRgn 
1131         // we will have to erase anyway 
1133         RgnHandle       updateRgn 
= NewRgn(); 
1134         RgnHandle       diffRgn 
= NewRgn() ; 
1135         if ( updateRgn 
&& diffRgn 
) 
1137             GetWindowUpdateRgn( (WindowRef
)m_macWindow 
, updateRgn 
); 
1139             LocalToGlobal( &pt 
) ; 
1140             OffsetRgn( updateRgn 
, -pt
.h 
, -pt
.v 
) ; 
1141             DiffRgn( updateRgn 
, (RgnHandle
) m_macNoEraseUpdateRgn 
, diffRgn 
) ; 
1142             if ( !EmptyRgn( diffRgn 
) ) 
1144                 m_macNeedsErasing 
= true ; 
1148             DisposeRgn( updateRgn 
); 
1150             DisposeRgn( diffRgn 
); 
1152         if ( !m_macNeedsErasing 
) 
1154             RgnHandle rectRgn 
= NewRgn() ; 
1155             SetRectRgn( rectRgn 
, ((Rect
*)rect
)->left 
, ((Rect
*)rect
)->top 
, ((Rect
*)rect
)->right 
, ((Rect
*)rect
)->bottom 
) ; 
1156             UnionRgn( (RgnHandle
) m_macNoEraseUpdateRgn 
, rectRgn 
, (RgnHandle
) m_macNoEraseUpdateRgn 
) ; 
1157             DisposeRgn( rectRgn 
) ; 
1160     InvalWindowRect( (WindowRef
)m_macWindow 
, (Rect
*)rect 
) ; 
1161     // turn this on to debug the refreshing cycle 
1162 #if wxMAC_DEBUG_REDRAW 
1165     SetPort( formerPort 
) ; 
1169 bool wxTopLevelWindowMac::SetShape(const wxRegion
& region
) 
1171     wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), FALSE
, 
1172                  _T("Shaped windows must be created with the wxFRAME_SHAPED style.")); 
1175     // The empty region signifies that the shape should be removed from the 
1177     if ( region
.IsEmpty() ) 
1179         wxSize sz 
= GetClientSize(); 
1180         wxRegion 
rgn(0, 0, sz
.x
, sz
.y
); 
1181         return SetShape(rgn
); 
1184     // Make a copy of the region 
1185     RgnHandle  shapeRegion 
= NewRgn(); 
1186     CopyRgn( (RgnHandle
)region
.GetWXHRGN(), shapeRegion 
); 
1188     // Dispose of any shape region we may already have 
1189     RgnHandle oldRgn 
= (RgnHandle
)GetWRefCon( (WindowRef
)MacGetWindowRef() ); 
1193     // Save the region so we can use it later 
1194     SetWRefCon((WindowRef
)MacGetWindowRef(), (SInt32
)shapeRegion
); 
1196     // Tell the window manager that the window has changed shape 
1197     ReshapeCustomWindow((WindowRef
)MacGetWindowRef()); 
1204 // --------------------------------------------------------------------------- 
1205 // Support functions for shaped windows, based on Apple's CustomWindow sample at 
1206 // http://developer.apple.com/samplecode/Sample_Code/Human_Interface_Toolbox/Mac_OS_High_Level_Toolbox/CustomWindow.htm 
1207 // --------------------------------------------------------------------------- 
1211 static void wxShapedMacWindowGetPos(WindowRef window
, Rect
* inRect
) 
1213     GetWindowPortBounds(window
, inRect
); 
1214     Point pt 
= {inRect
->left
, inRect
->top
}; 
1215     SetPort((GrafPtr
) GetWindowPort(window
)); 
1218     inRect
->left 
= pt
.h
; 
1219     inRect
->bottom 
+= pt
.v
; 
1220     inRect
->right 
+= pt
.h
; 
1224 static SInt32 
wxShapedMacWindowGetFeatures(WindowRef window
, SInt32 param
) 
1226     /*------------------------------------------------------ 
1227         Define which options your custom window supports. 
1228     --------------------------------------------------------*/ 
1229     //just enable everything for our demo 
1230     *(OptionBits
*)param
=//kWindowCanGrow| 
1232                         //kWindowCanCollapse| 
1233                         //kWindowCanGetWindowRegion| 
1234                         //kWindowHasTitleBar| 
1235                         //kWindowSupportsDragHilite| 
1236                         kWindowCanDrawInCurrentPort
| 
1237                         //kWindowCanMeasureTitle| 
1238                         kWindowWantsDisposeAtProcessDeath
| 
1239                         kWindowSupportsSetGrowImageRegion
| 
1240                         kWindowDefSupportsColorGrafPort
; 
1244 // The content region is left as a rectangle matching the window size, this is 
1245 // so the origin in the paint event, and etc. still matches what the 
1246 // programmer expects. 
1247 static void wxShapedMacWindowContentRegion(WindowRef window
, RgnHandle rgn
) 
1250     wxTopLevelWindowMac
* win 
= wxFindWinFromMacWindow(window
); 
1253         wxRect r 
= win
->GetRect(); 
1254         SetRectRgn(rgn
, r
.GetLeft(), r
.GetTop(), r
.GetRight(), r
.GetBottom()); 
1258 // The structure region is set to the shape given to the SetShape method. 
1259 static void wxShapedMacWindowStructureRegion(WindowRef window
, RgnHandle rgn
) 
1261     RgnHandle cachedRegion 
= (RgnHandle
) GetWRefCon(window
); 
1267         wxShapedMacWindowGetPos(window
, &windowRect
);   //how big is the window 
1268         CopyRgn(cachedRegion
, rgn
);             //make a copy of our cached region 
1269         OffsetRgn(rgn
, windowRect
.left
, windowRect
.top
); // position it over window 
1270         //MapRgn(rgn, &mMaskSize, &windowRect); //scale it to our actual window size 
1276 static SInt32 
wxShapedMacWindowGetRegion(WindowRef window
, SInt32 param
) 
1278     GetWindowRegionPtr rgnRec
=(GetWindowRegionPtr
)param
; 
1280     switch(rgnRec
->regionCode
) 
1282         case kWindowStructureRgn
: 
1283             wxShapedMacWindowStructureRegion(window
, rgnRec
->winRgn
); 
1285         case kWindowContentRgn
: 
1286             wxShapedMacWindowContentRegion(window
, rgnRec
->winRgn
); 
1289             SetEmptyRgn(rgnRec
->winRgn
); 
1296 static SInt32 
wxShapedMacWindowHitTest(WindowRef window
,SInt32 param
) 
1298     /*------------------------------------------------------ 
1299         Determine the region of the window which was hit 
1300     --------------------------------------------------------*/ 
1302     static RgnHandle tempRgn
=nil
; 
1307     SetPt(&hitPoint
,LoWord(param
),HiWord(param
));//get the point clicked 
1309      //Mac OS 8.5 or later 
1310     wxShapedMacWindowStructureRegion(window
, tempRgn
); 
1311     if (PtInRgn(hitPoint
, tempRgn
)) //in window content region? 
1314     return wNoHit
;//no significant area was hit. 
1318 static pascal long wxShapedMacWindowDef(short varCode
, WindowRef window
, SInt16 message
, SInt32 param
) 
1322         case kWindowMsgHitTest
: 
1323             return wxShapedMacWindowHitTest(window
,param
); 
1325         case kWindowMsgGetFeatures
: 
1326             return wxShapedMacWindowGetFeatures(window
,param
); 
1328         // kWindowMsgGetRegion is sent during CreateCustomWindow and ReshapeCustomWindow 
1329         case kWindowMsgGetRegion
: 
1330             return wxShapedMacWindowGetRegion(window
,param
); 
1337 // ---------------------------------------------------------------------------