X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1a02aff92534301c5e54f0617b5df1faec2cb057..a2fe01c96d43777db58041ec470e8aaa27f1e3b2:/src/mac/carbon/window.cpp?ds=sidebyside diff --git a/src/mac/carbon/window.cpp b/src/mac/carbon/window.cpp index a261d56279..ba16258f53 100644 --- a/src/mac/carbon/window.cpp +++ b/src/mac/carbon/window.cpp @@ -24,6 +24,7 @@ #include "wx/layout.h" #include "wx/dialog.h" #include "wx/scrolbar.h" +#include "wx/scrolwin.h" #include "wx/statbox.h" #include "wx/button.h" #include "wx/settings.h" @@ -36,6 +37,8 @@ #include "wx/log.h" #include "wx/geometry.h" #include "wx/textctrl.h" +#include "wx/laywin.h" +#include "wx/splitter.h" #include "wx/toolbar.h" #include "wx/dc.h" @@ -387,6 +390,9 @@ static pascal OSStatus wxMacWindowServiceEventHandler( EventHandlerCallRef handl pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) { + EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ; + EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ; + wxTheApp->MacSetCurrentEvent( event , handler ) ; OSStatus result = eventNotHandledErr ; switch ( GetEventClass( event ) ) @@ -399,6 +405,7 @@ pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef default : break ; } + wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ; return result ; } @@ -981,9 +988,11 @@ void wxWindowMac::SetFocus() { if ( AcceptsFocus() ) { -#if !TARGET_API_MAC_OSX + wxWindow* former = FindFocus() ; -#endif + if ( former == this ) + return ; + OSStatus err = m_peer->SetFocus( kControlFocusNextPart ) ; // as we cannot rely on the control features to find out whether we are in full keyboard mode, we can only // leave in case of an error @@ -1599,10 +1608,50 @@ void wxWindowMac::DoMoveWindow(int x, int y, int width, int height) } #endif bool vis = m_peer->IsVisible(); + + int outerBorder = MacGetLeftBorderSize() ; + if ( m_peer->NeedsFocusRect() && m_peer->HasFocus() ) + outerBorder = 4 ; + + if ( vis && ( outerBorder > 0 ) ) + { + // as the borders are drawn on the parent we have to properly invalidate all these areas + RgnHandle updateInner = NewRgn() , updateOuter = NewRgn() , updateTotal = NewRgn() ; + + Rect rect ; + + m_peer->GetRect( &rect ) ; + RectRgn( updateInner , &rect ) ; + InsetRect( &rect , -outerBorder , -outerBorder ) ; + RectRgn( updateOuter , &rect ) ; + DiffRgn( updateOuter , updateInner ,updateOuter ) ; + wxPoint parent(0,0); + GetParent()->MacWindowToRootWindow( &parent.x , &parent.y ) ; + parent -= GetParent()->GetClientAreaOrigin() ; + OffsetRgn( updateOuter , -parent.x , -parent.y ) ; + CopyRgn( updateOuter , updateTotal ) ; + + rect = r ; + RectRgn( updateInner , &rect ) ; + InsetRect( &rect , -outerBorder , -outerBorder ) ; + RectRgn( updateOuter , &rect ) ; + DiffRgn( updateOuter , updateInner ,updateOuter ) ; + wxPoint parentorig(0,0); + GetParent()->MacWindowToRootWindow( &parentorig.x , &parentorig.y ) ; + parent -= GetParent()->GetClientAreaOrigin() ; + OffsetRgn( updateOuter , -parentorig.x , -parentorig.y ) ; + UnionRgn( updateOuter , updateTotal , updateTotal ) ; + + GetParent()->m_peer->SetNeedsDisplay( true , updateTotal ) ; + DisposeRgn(updateOuter) ; + DisposeRgn(updateInner) ; + DisposeRgn(updateTotal) ; + } // the HIViewSetFrame call itself should invalidate the areas, but when testing with the UnicodeTextCtrl it does not ! if ( vis ) m_peer->SetVisibility( false , true ) ; + m_peer->SetRect( &r ) ; if ( vis ) m_peer->SetVisibility( true , true ) ; @@ -2125,10 +2174,7 @@ void wxWindowMac::OnEraseBackground(wxEraseEvent& event) void wxWindowMac::OnNcPaint( wxNcPaintEvent& event ) { - wxWindowDC dc(this) ; - wxMacPortSetter helper(&dc) ; - - MacPaintBorders( dc.m_macLocalOrigin.x , dc.m_macLocalOrigin.y) ; + event.Skip() ; } int wxWindowMac::GetScrollPos(int orient) const @@ -2197,81 +2243,39 @@ void wxWindowMac::MacPaintBorders( int left , int top ) if( IsTopLevel() ) return ; - int major,minor; - wxGetOsVersion( &major, &minor ); - - RGBColor darkShadow = { 0x0000, 0x0000 , 0x0000 } ; - RGBColor lightShadow = { 0x4444, 0x4444 , 0x4444 } ; - // OS X has lighter border edges than classic: - if (major >= 10) - { - darkShadow.red = 0x8E8E; - darkShadow.green = 0x8E8E; - darkShadow.blue = 0x8E8E; - lightShadow.red = 0xBDBD; - lightShadow.green = 0xBDBD; - lightShadow.blue = 0xBDBD; - } - - PenNormal() ; + Rect rect ; + m_peer->GetRect( &rect ) ; + InsetRect( &rect, -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ; - int w , h ; - GetSize( &w , &h ) ; - Rect rect = { top , left , h + top , w + left } ; + if ( !IsTopLevel() ) + { + wxTopLevelWindowMac* top = MacGetTopLevelWindow(); + if (top) + { + wxPoint pt(0,0) ; + wxMacControl::Convert( &pt , GetParent()->m_peer , top->m_peer ) ; + rect.left += pt.x ; + rect.right += pt.x ; + rect.top += pt.y ; + rect.bottom += pt.y ; + } + } + if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) ) { -#if wxMAC_USE_THEME_BORDER + Rect srect = rect ; SInt32 border = 0 ; GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ; - InsetRect( &rect , border , border ); - DrawThemeEditTextFrame(&rect,IsEnabled() ? kThemeStateActive : kThemeStateInactive) ; -#else - RGBColor white = { 0xFFFF, 0xFFFF , 0xFFFF } ; - RGBColor face = { 0xDDDD, 0xDDDD , 0xDDDD } ; - - bool sunken = HasFlag( wxSUNKEN_BORDER ) ; - RGBForeColor( &face ); - MoveTo( left + 0 , top + h - 2 ); - LineTo( left + 0 , top + 0 ); - LineTo( left + w - 2 , top + 0 ); - - MoveTo( left + 2 , top + h - 3 ); - LineTo( left + w - 3 , top + h - 3 ); - LineTo( left + w - 3 , top + 2 ); - - RGBForeColor( sunken ? &face : &darkShadow ); - MoveTo( left + 0 , top + h - 1 ); - LineTo( left + w - 1 , top + h - 1 ); - LineTo( left + w - 1 , top + 0 ); - - RGBForeColor( sunken ? &lightShadow : &white ); - MoveTo( left + 1 , top + h - 3 ); - LineTo( left + 1, top + 1 ); - LineTo( left + w - 3 , top + 1 ); - - RGBForeColor( sunken ? &white : &lightShadow ); - MoveTo( left + 1 , top + h - 2 ); - LineTo( left + w - 2 , top + h - 2 ); - LineTo( left + w - 2 , top + 1 ); - - RGBForeColor( sunken ? &darkShadow : &face ); - MoveTo( left + 2 , top + h - 4 ); - LineTo( left + 2 , top + 2 ); - LineTo( left + w - 4 , top + 2 ); -#endif + InsetRect( &srect , border , border ); + DrawThemeEditTextFrame(&srect,IsEnabled() ? kThemeStateActive : kThemeStateInactive) ; } else if (HasFlag(wxSIMPLE_BORDER)) { -#if wxMAC_USE_THEME_BORDER + Rect srect = rect ; SInt32 border = 0 ; GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ; - InsetRect( &rect , border , border ); + InsetRect( &srect , border , border ); DrawThemeListBoxFrame(&rect,IsEnabled() ? kThemeStateActive : kThemeStateInactive) ; -#else - Rect rect = { top , left , h + top , w + left } ; - RGBForeColor( &darkShadow ) ; - FrameRect( &rect ) ; -#endif } } @@ -2483,7 +2487,25 @@ void wxWindowMac::OnSetFocus(wxFocusEvent& event) if ( event.GetEventType() == wxEVT_SET_FOCUS ) DrawThemeFocusRect( &rect , true ) ; else + { DrawThemeFocusRect( &rect , false ) ; + + // as this erases part of the frame we have to redraw borders + // and because our z-ordering is not always correct (staticboxes) + // we have to invalidate things, we cannot simple redraw + RgnHandle updateInner = NewRgn() , updateOuter = NewRgn() ; + RectRgn( updateInner , &rect ) ; + InsetRect( &rect , -4 , -4 ) ; + RectRgn( updateOuter , &rect ) ; + DiffRgn( updateOuter , updateInner ,updateOuter ) ; + wxPoint parent(0,0); + GetParent()->MacWindowToRootWindow( &parent.x , &parent.y ) ; + parent -= GetParent()->GetClientAreaOrigin() ; + OffsetRgn( updateOuter , -parent.x , -parent.y ) ; + GetParent()->m_peer->SetNeedsDisplay( true , updateOuter ) ; + DisposeRgn(updateOuter) ; + DisposeRgn(updateInner) ; + } } event.Skip(); @@ -2614,7 +2636,11 @@ wxTopLevelWindowMac* wxWindowMac::MacGetTopLevelWindow() const } wxRegion wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures ) { - + // includeOuterStructures is true if we try to draw somthing like a focus ring etc. + // also a window dc uses this, in this case we only clip in the hierarchy for hard + // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having + // to add focus borders everywhere + Rect r ; RgnHandle visRgn = NewRgn() ; RgnHandle tempRgn = NewRgn() ; @@ -2639,7 +2665,7 @@ wxRegion wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures ) r.top = 0 ; } if ( includeOuterStructures ) - InsetRect( &r , -3 , -3 ) ; + InsetRect( &r , -4 , -4 ) ; RectRgn( visRgn , &r ) ; if ( !IsTopLevel() ) @@ -2667,12 +2693,19 @@ wxRegion wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures ) parent->MacWindowToRootWindow( &x, &y ) ; MacRootWindowToWindow( &x , &y ) ; - SetRectRgn( tempRgn , - x + parent->MacGetLeftBorderSize() , y + parent->MacGetTopBorderSize() , - x + size.x - parent->MacGetRightBorderSize(), - y + size.y - parent->MacGetBottomBorderSize()) ; + if ( !includeOuterStructures || ( + parent->IsKindOf( CLASSINFO( wxScrolledWindow ) ) || + parent->IsKindOf( CLASSINFO( wxSashLayoutWindow ) ) || + ( parent->GetParent() && parent->GetParent()->IsKindOf( CLASSINFO( wxSplitterWindow ) ) ) + ) ) + { + SetRectRgn( tempRgn , + x + parent->MacGetLeftBorderSize() , y + parent->MacGetTopBorderSize() , + x + size.x - parent->MacGetRightBorderSize(), + y + size.y - parent->MacGetBottomBorderSize()) ; - SectRgn( visRgn , tempRgn , visRgn ) ; + SectRgn( visRgn , tempRgn , visRgn ) ; + } if ( parent->IsTopLevel() ) break ; child = parent ; @@ -2696,7 +2729,7 @@ bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time ) bool handled = false ; Rect updatebounds ; GetRegionBounds( updatergn , &updatebounds ) ; - +// wxLogDebug("update for %s bounds %d , %d , %d , %d",typeid(*this).name() , updatebounds.left , updatebounds.top , updatebounds.right , updatebounds.bottom ) ; if ( !EmptyRgn(updatergn) ) { RgnHandle newupdate = NewRgn() ; @@ -2705,14 +2738,14 @@ bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time ) SetRectRgn( newupdate , origin.x , origin.y , origin.x + point.x , origin.y+point.y ) ; SectRgn( newupdate , updatergn , newupdate ) ; -// if (!EmptyRgn(newupdate)) -// { + // first send an erase event to the entire update area + { wxWindowDC dc(this); dc.SetClippingRegion(wxRegion(updatergn)); wxEraseEvent eevent( GetId(), &dc ); eevent.SetEventObject( this ); GetEventHandler()->ProcessEvent( eevent ); -// } + } // calculate a client-origin version of the update rgn and set m_updateRegion to that OffsetRgn( newupdate , -origin.x , -origin.y ) ; @@ -2727,10 +2760,62 @@ bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time ) event.SetEventObject(this); handled = GetEventHandler()->ProcessEvent(event); - // paint custom borders - wxNcPaintEvent eventNc( GetId() ); - eventNc.SetEventObject( this ); - GetEventHandler()->ProcessEvent( eventNc ); + // we have to call the default built-in handler, as otherwise our frames will be drawn and immediately erased afterwards + if ( !handled ) + { + if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL ) + { + CallNextEventHandler((EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ; + handled = true ; + } + } + + } + + // now we cannot rely on having its borders drawn by a window itself, as it does not + // get the updateRgn wide enough to always do so, so we do it from the parent + // this would also be the place to draw any custom backgrounds for native controls + // in Composited windowing + wxPoint clientOrigin = GetClientAreaOrigin() ; + + for (wxWindowListNode *node = GetChildren().GetFirst(); node; node = node->GetNext()) + { + wxWindowMac *child = node->GetData(); + if (child == m_vScrollBar) continue; + if (child == m_hScrollBar) continue; + if (child->IsTopLevel()) continue; + if (!child->IsShown()) continue; + + int x,y; + child->GetPosition( &x, &y ); + int w,h; + child->GetSize( &w, &h ); + Rect childRect = { y , x , y + h , x + w } ; + OffsetRect( &childRect , clientOrigin.x , clientOrigin.y ) ; + if ( child->MacGetTopBorderSize() ) + { + if ( RectInRgn( &childRect , updatergn ) ) + { + // paint custom borders + wxNcPaintEvent eventNc( child->GetId() ); + eventNc.SetEventObject( child ); + if ( !child->GetEventHandler()->ProcessEvent( eventNc ) ) + { + wxWindowDC dc(this) ; + dc.SetClippingRegion(wxRegion(updatergn)); + wxMacPortSetter helper(&dc) ; + child->MacPaintBorders( dc.m_macLocalOrigin.x + childRect.left , dc.m_macLocalOrigin.y + childRect.top) ; + } + } + } + if ( child->m_peer->NeedsFocusRect() && child->m_peer->HasFocus() ) + { + wxWindowDC dc(this) ; + dc.SetClippingRegion(wxRegion(updatergn)); + wxMacPortSetter helper(&dc) ; + OffsetRect( &childRect , dc.m_macLocalOrigin.x , dc.m_macLocalOrigin.y ) ; + DrawThemeFocusRect( &childRect , true ) ; + } } } return handled ;