]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/carbon/window.cpp
fixing native font info support bugs
[wxWidgets.git] / src / osx / carbon / window.cpp
index a24d1a6f555a325a134973fe7bb6e9f85fd072fa..875b62a41e969be8ba75dcb24af4d13ab4908b04 100644 (file)
 #define wxMAC_DEBUG_REDRAW 0
 #endif
 
-
-WX_DECLARE_HASH_MAP(WXWidget, wxWindow*, wxPointerHash, wxPointerEqual, MacControlMap);
-
-static MacControlMap wxWinMacControlList;
-
-wxWindowMac *wxFindWindowFromWXWidget(WXWidget inControl )
+// Get the window with the focus
+WXWidget wxWidgetImpl::FindFocus()
 {
-    MacControlMap::iterator node = wxWinMacControlList.find(inControl);
-
-    return (node == wxWinMacControlList.end()) ? NULL : node->second;
-}
-
-void wxAssociateWindowWithWXWidget(WXWidget inControl, wxWindow *control)
-{
-    // adding NULL ControlRef is (first) surely a result of an error and
-    // (secondly) breaks native event processing
-    wxCHECK_RET( inControl != (WXWidget) NULL, wxT("attempt to add a NULL WindowRef to window list") );
-
-    wxWinMacControlList[inControl] = control;
-}
-
-void wxRemoveWXWidgetAssociation(wxWindow *control)
-{
-   // iterate over all the elements in the class
-    // is the iterator stable ? as we might have two associations pointing to the same wxWindow
-    // we should go on...
-
-    bool found = true ;
-    while ( found )
-    {
-        found = false ;
-        MacControlMap::iterator it;
-        for ( it = wxWinMacControlList.begin(); it != wxWinMacControlList.end(); ++it )
-        {
-            if ( it->second == control )
-            {
-                wxWinMacControlList.erase(it);
-                found = true ;
-                break;
-            }
-        }
-    }
+    ControlRef control = NULL ;
+    GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
+    return control;
 }
 
 // ---------------------------------------------------------------------------
@@ -175,24 +139,23 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl
     {
         case kEventControlDraw :
             {
-                RgnHandle updateRgn = NULL ;
-                RgnHandle allocatedRgn = NULL ;
+                HIShapeRef updateRgn = NULL ;
+                HIMutableShapeRef allocatedRgn = NULL ;
                 wxRegion visRegion = thisWindow->MacGetVisibleRegion() ;
 
-                if ( cEvent.GetParameter<RgnHandle>(kEventParamRgnHandle, &updateRgn) != noErr )
+                // according to the docs: redraw entire control if param not present
+                if ( cEvent.GetParameter<HIShapeRef>(kEventParamShape, &updateRgn) != noErr )
                 {
-                    HIShapeGetAsQDRgn( visRegion.GetWXHRGN(), updateRgn );
+                    updateRgn = visRegion.GetWXHRGN();
                 }
                 else
                 {
                     if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 )
                     {
                         // as this update region is in native window locals we must adapt it to wx window local
-                        allocatedRgn = NewRgn() ;
-                        CopyRgn( updateRgn , allocatedRgn ) ;
-
+                        allocatedRgn = HIShapeCreateMutableCopy(updateRgn);
+                        HIShapeOffset(allocatedRgn, thisWindow->MacGetLeftBorderSize() , thisWindow->MacGetTopBorderSize());
                         // hide the given region by the new region that must be shifted
-                        OffsetRgn( allocatedRgn , thisWindow->MacGetLeftBorderSize() , thisWindow->MacGetTopBorderSize() ) ;
                         updateRgn = allocatedRgn ;
                     }
                 }
@@ -254,11 +217,23 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl
                             CGContextClearRect( cgContext, bounds );
                         }
 
-
-
-                        if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) )
-                            result = noErr ;
-
+                        if ( !HIShapeIsEmpty(updateRgn) )
+                        {
+                            // refcount increase because wxRegion constructor takes ownership of the native region
+                            CFRetain(updateRgn);
+                            thisWindow->GetUpdateRegion() = wxRegion(updateRgn);
+                            if ( !thisWindow->MacDoRedraw( cEvent.GetTicks() ) )
+                            {
+                               // for native controls: call their native paint method
+                                if ( !thisWindow->MacIsUserPane() || 
+                                    ( thisWindow->IsTopLevel() && thisWindow->GetBackgroundStyle() == wxBG_STYLE_SYSTEM ) )
+                                {
+                                    if ( thisWindow->GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT )
+                                        CallNextEventHandler( handler ,event ) ;
+                                }
+                            }
+                            thisWindow->MacPaintChildrenBorders();
+                        }
                         thisWindow->MacSetCGContextRef( NULL ) ;
                     }
 
@@ -267,7 +242,7 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl
                 }
 
                 if ( allocatedRgn )
-                    DisposeRgn( allocatedRgn ) ;
+                    CFRelease( allocatedRgn ) ;
             }
             break ;
 
@@ -331,8 +306,8 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl
                         thisWindow->GetCaret()->OnKillFocus();
 #endif
 
-                    wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow));
-
+                    wxLogTrace(_T("Focus"), _T("focus lost(%p)"), static_cast<void*>(thisWindow));
+                    
                     // remove this as soon as posting the synthesized event works properly
                     static bool inKillFocusEvent = false ;
 
@@ -351,7 +326,7 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl
                 {
                     // set focus
                     // panel wants to track the window which was the last to have focus in it
-                    wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow));
+                    wxLogTrace(_T("Focus"), _T("focus set(%p)"), static_cast<void*>(thisWindow));
                     wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
                     thisWindow->HandleWindowEvent(eventFocus);
 
@@ -379,12 +354,12 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl
                 if ( controlPart != kControlFocusNoPart )
                 {
                     targetFocusWindow = thisWindow;
-                    wxLogTrace(_T("Focus"), _T("focus to be set(%p)"), wx_static_cast(void*, thisWindow));
+                    wxLogTrace(_T("Focus"), _T("focus to be set(%p)"), static_cast<void*>(thisWindow));
                 }
                 else
                 {
                     formerFocusWindow = thisWindow;
-                    wxLogTrace(_T("Focus"), _T("focus to be lost(%p)"), wx_static_cast(void*, thisWindow));
+                    wxLogTrace(_T("Focus"), _T("focus to be lost(%p)"), static_cast<void*>(thisWindow));
                 }
                 
                 ControlPartCode previousControlPart = 0;
@@ -437,7 +412,7 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl
                             thisWindow->GetCaret()->OnKillFocus();
 #endif
 
-                        wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow));
+                        wxLogTrace(_T("Focus"), _T("focus lost(%p)"), static_cast<void*>(thisWindow));
 
                         static bool inKillFocusEvent = false ;
 
@@ -453,7 +428,7 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl
                     else
                     {
                         // panel wants to track the window which was the last to have focus in it
-                        wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow));
+                        wxLogTrace(_T("Focus"), _T("focus set(%p)"), static_cast<void*>(thisWindow));
                         wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
                         thisWindow->HandleWindowEvent(eventFocus);
 
@@ -814,13 +789,46 @@ pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode p
     {
         wxWindow*  wx = wxFindWindowFromWXWidget(  (WXWidget) control ) ;
         if ( wx )
-            wx->MacHandleControlClick( (WXWidget) control , partCode , true /* stillDown */ ) ;
+        {   
+            wxEventType scrollEvent = wxEVT_NULL;
+            switch ( partCode )
+            {
+            case kControlUpButtonPart:
+                scrollEvent = wxEVT_SCROLL_LINEUP;
+                break;
+
+            case kControlDownButtonPart:
+                scrollEvent = wxEVT_SCROLL_LINEDOWN;
+                break;
+
+            case kControlPageUpPart:
+                scrollEvent = wxEVT_SCROLL_PAGEUP;
+                break;
+
+            case kControlPageDownPart:
+                scrollEvent = wxEVT_SCROLL_PAGEDOWN;
+                break;
+
+            case kControlIndicatorPart:
+                scrollEvent = wxEVT_SCROLL_THUMBTRACK;
+                // when this is called as a live proc, mouse is always still down
+                // so no need for thumbrelease
+                // scrollEvent = wxEVT_SCROLL_THUMBRELEASE;
+                break;
+            }
+            wx->TriggerScrollEvent(scrollEvent) ;
+        }
     }
 }
 wxMAC_DEFINE_PROC_GETTER( ControlActionUPP , wxMacLiveScrollbarActionProc ) ;
 
-wxWidgetImplType* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, wxWindowMac* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
-                            long style, long extraStyle)
+wxWidgetImplType* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, 
+                            wxWindowMac* WXUNUSED(parent), 
+                            wxWindowID WXUNUSED(id), 
+                            const wxPoint& pos, 
+                            const wxSize& size,
+                            long WXUNUSED(style), 
+                            long WXUNUSED(extraStyle))
 {
     OSStatus err = noErr;
     Rect bounds = wxMacGetBoundsForControl( wxpeer , pos , size ) ;
@@ -842,11 +850,11 @@ wxWidgetImplType* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, wxWindowMac
 }
 
 
-void wxMacControl::MacInstallEventHandler( ControlRef control, wxWindowMac* wxPeer )
+void wxMacControl::InstallEventHandler( WXWidget control )
 {
-    wxAssociateWindowWithWXWidget( (WXWidget) control , wxPeer ) ;
-    ::InstallControlEventHandler( control , GetwxMacWindowEventHandlerUPP(),
-        GetEventTypeCount(eventList), eventList, wxPeer, NULL);
+    wxWidgetImpl::Associate( control ? control : (WXWidget) m_controlRef , this ) ;
+    ::InstallControlEventHandler( control ? (ControlRef) control : m_controlRef , GetwxMacWindowEventHandlerUPP(),
+        GetEventTypeCount(eventList), eventList, GetWXPeer(), NULL);
 }
 
 IMPLEMENT_DYNAMIC_CLASS( wxMacControl , wxWidgetImpl )
@@ -869,7 +877,7 @@ wxMacControl::~wxMacControl()
         wxASSERT_MSG( m_controlRef != NULL , wxT("Control Handle already NULL, Dispose called twice ?") );
         wxASSERT_MSG( IsValidControlHandle(m_controlRef) , wxT("Invalid Control Handle (maybe already released) in Dispose") );
 
-        wxRemoveWXWidgetAssociation( m_wxPeer) ;
+        wxWidgetImpl::RemoveAssociations( this ) ;
         // we cannot check the ref count here anymore, as autorelease objects might delete their refs later
         // we can have situations when being embedded, where the control gets deleted behind our back, so only
         // CFRelease if we are safe
@@ -885,22 +893,15 @@ void wxMacControl::Init()
     m_macControlEventHandler = NULL;
 }
 
-void wxMacControl::SetReference( URefCon data )
-{
-    SetControlReference( m_controlRef , data );
-}
-
 void wxMacControl::RemoveFromParent()
 {
     // nothing to do here for carbon
+    HIViewRemoveFromSuperview(m_controlRef);
 }
 
 void wxMacControl::Embed( wxWidgetImpl *parent )
 {
-    // copied from MacPostControlCreate
-    ControlRef container = (ControlRef) parent->GetWXWidget() ;
-    wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
-    ::EmbedControl( m_controlRef , container ) ;
+    HIViewAddSubview((ControlRef)parent->GetWXWidget(), m_controlRef);
 }
 
 void wxMacControl::SetNeedsDisplay( const wxRect* rect )
@@ -929,19 +930,24 @@ void wxMacControl::Lower()
 
 void wxMacControl::GetContentArea(int &left , int &top , int &width , int &height) const
 {
-    RgnHandle rgn = NewRgn() ;
-    Rect content ;
-    if ( GetControlRegion( m_controlRef, kControlContentMetaPart , rgn ) == noErr )
-        GetRegionBounds( rgn , &content ) ;
+    HIShapeRef rgn = NULL;
+    Rect content ;  
+
+    if ( HIViewCopyShape(m_controlRef, kHIViewContentMetaPart, &rgn) == noErr)
+    {
+        CGRect cgrect;
+        HIShapeGetBounds(rgn, &cgrect);
+        content = (Rect){ cgrect.origin.y, cgrect.origin.x, cgrect.origin.y+cgrect.size.height, cgrect.origin.x+cgrect.size.width };
+        CFRelease(rgn);
+    }
     else
     {
-        GetControlBounds( m_controlRef , &content );
+        GetControlBounds(m_controlRef, &content);
         content.right -= content.left;
         content.left = 0;
         content.bottom -= content.top;
         content.top = 0;
     }
-    DisposeRgn( rgn ) ;
 
     left = content.left;
     top = content.top;
@@ -1089,6 +1095,47 @@ bool wxMacControl::HasFocus() const
     return control == m_controlRef;
 }
 
+void wxMacControl::SetCursor(const wxCursor& cursor)
+{
+    wxWindowMac *mouseWin = 0 ;
+    WindowRef window = GetControlOwner( m_controlRef ) ;
+
+    wxNonOwnedWindow* tlwwx = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) window ) ;
+    if ( tlwwx != NULL )
+    {
+        ControlPartCode part ;
+        ControlRef control ;
+        Point pt ;
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+        HIPoint hiPoint ;
+        HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint);
+        pt.h = hiPoint.x;
+        pt.v = hiPoint.y;
+#else
+        GetGlobalMouse( &pt );
+        int x = pt.h;
+        int y = pt.v;
+        tlwwx->ScreenToClient(&x, &y);
+        pt.h = x;
+        pt.v = y;
+#endif
+        control = FindControlUnderMouse( pt , window , &part ) ;
+        if ( control )
+            mouseWin = wxFindWindowFromWXWidget( (WXWidget) control ) ;
+    }
+
+    if ( mouseWin == tlwwx && !wxIsBusy() )
+        cursor.MacInstall() ;
+}
+
+void wxMacControl::CaptureMouse()
+{
+}
+
+void wxMacControl::ReleaseMouse()
+{
+}
+
 //
 // subclass specifics
 //
@@ -1142,17 +1189,15 @@ wxInt32 wxMacControl::GetValue() const
     return ::GetControl32BitValue( m_controlRef );
 }
 
-SInt32 wxMacControl::GetMaximum() const
+wxInt32 wxMacControl::GetMaximum() const
 {
     return ::GetControl32BitMaximum( m_controlRef );
 }
 
-/*
 wxInt32 wxMacControl::GetMinimum() const
 {
     return ::GetControl32BitMinimum( m_controlRef );
 }
-*/
 
 void wxMacControl::SetValue( wxInt32 v )
 {
@@ -1184,7 +1229,7 @@ void wxMacControl::SuperChangedPosition()
 {
 }
 
-void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle )
+void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle, bool ignoreBlack )
 {
     m_font = font;
 #if wxOSX_USE_CORE_TEXT
@@ -1196,10 +1241,10 @@ void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , l
             flush = kHIThemeTextHorizontalFlushCenter;
         else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
             flush = kHIThemeTextHorizontalFlushRight;
-        HIViewSetTextFont( m_controlRef , part , (CTFontRef) font.MacGetCTFont() );
+        HIViewSetTextFont( m_controlRef , part , (CTFontRef) font.OSXGetCTFont() );
         HIViewSetTextHorizontalFlush( m_controlRef, part, flush );
 
-        if ( foreground != *wxBLACK )
+        if ( foreground != *wxBLACK || ignoreBlack == false )
         {
             ControlFontStyleRec fontStyle;
             foreground.GetRGBColor( &fontStyle.foreColor );
@@ -1237,7 +1282,7 @@ void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , l
     {
         fontStyle.font = font.MacGetFontNum();
         fontStyle.style = font.MacGetFontStyle();
-        fontStyle.size = font.MacGetFontSize();
+        fontStyle.size = font.GetPointSize();
         fontStyle.flags = kControlUseFontMask | kControlUseFaceMask | kControlUseSizeMask;
     }
 
@@ -1252,7 +1297,7 @@ void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , l
     // we only should do this in case of a non-standard color, as otherwise 'disabled' controls
     // won't get grayed out by the system anymore
 
-    if ( foreground != *wxBLACK )
+    if ( foreground != *wxBLACK || ignoreBlack == false )
     {
         foreground.GetRGBColor( &fontStyle.foreColor );
         fontStyle.flags |= kControlUseForeColorMask;
@@ -1362,12 +1407,6 @@ void wxMacControl::GetFeatures( UInt32 * features )
     GetControlFeatures( m_controlRef , features );
 }
 
-OSStatus wxMacControl::GetRegion( ControlPartCode partCode , RgnHandle region )
-{
-    OSStatus err = GetControlRegion( m_controlRef , partCode , region );
-    return err;
-}
-
 void wxMacControl::PulseGauge()
 {
 }