X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/788e118f21f73a77c8813caa535a157621ab8fa9..01ffa8f7f7acaf3851a436cf3e6975c43c46648c:/src/mac/carbon/window.cpp diff --git a/src/mac/carbon/window.cpp b/src/mac/carbon/window.cpp index b793d62377..df76db2af7 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" @@ -46,7 +49,9 @@ #define wxWINDOW_HSCROLL 5998 #define wxWINDOW_VSCROLL 5997 -#define MAC_SCROLLBAR_SIZE 16 + +#define MAC_SCROLLBAR_SIZE 15 +#define MAC_SMALL_SCROLLBAR_SIZE 11 #include "wx/mac/uma.h" #ifndef __DARWIN__ @@ -82,8 +87,6 @@ BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase) EVT_NC_PAINT(wxWindowMac::OnNcPaint) EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground) // TODO EVT_PAINT(wxWindowMac::OnPaint) - EVT_SYS_COLOUR_CHANGED(wxWindowMac::OnSysColourChanged) - EVT_INIT_DIALOG(wxWindowMac::OnInitDialog) EVT_SET_FOCUS(wxWindowMac::OnSetFocus) EVT_KILL_FOCUS(wxWindowMac::OnSetFocus) EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent) @@ -98,6 +101,54 @@ END_EVENT_TABLE() #define wxMAC_USE_THEME_BORDER 1 +// --------------------------------------------------------------------------- +// Utility Routines to move between different coordinate systems +// --------------------------------------------------------------------------- + +/* + * Right now we have the following setup : + * a border that is not part of the native control is always outside the + * control's border (otherwise we loose all native intelligence, future ways + * may be to have a second embedding control responsible for drawing borders + * and backgrounds eventually) + * so all this border calculations have to be taken into account when calling + * native methods or getting native oriented data + * so we have three coordinate systems here + * wx client coordinates + * wx window coordinates (including window frames) + * native coordinates + */ + +// +// originating from native control +// + + +void wxMacNativeToWindow( const wxWindow* window , RgnHandle handle ) +{ + OffsetRgn( handle , window->MacGetLeftBorderSize() , window->MacGetTopBorderSize() ) ; +} + +void wxMacNativeToWindow( const wxWindow* window , Rect *rect ) +{ + OffsetRect( rect , window->MacGetLeftBorderSize() , window->MacGetTopBorderSize() ) ; +} + +// +// directed towards native control +// + +void wxMacWindowToNative( const wxWindow* window , RgnHandle handle ) +{ + OffsetRgn( handle , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() ); +} + +void wxMacWindowToNative( const wxWindow* window , Rect *rect ) +{ + OffsetRect( rect , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() ) ; +} + + // --------------------------------------------------------------------------- // Carbon Events // --------------------------------------------------------------------------- @@ -151,13 +202,23 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl case kEventControlDraw : { RgnHandle updateRgn = NULL ; - + RgnHandle allocatedRgn = NULL ; wxRegion visRegion = thisWindow->MacGetVisibleRegion() ; if ( cEvent.GetParameter(kEventParamRgnHandle, &updateRgn) != noErr ) { updateRgn = (RgnHandle) visRegion.GetWXHRGN() ; } - // GrafPtr myport = cEvent.GetParameter(kEventParamGrafPort,typeGrafPtr) ; + else + { + if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 ) + { + allocatedRgn = NewRgn() ; + CopyRgn( updateRgn , allocatedRgn ) ; + // hide the given region by the new region that must be shifted + wxMacNativeToWindow( thisWindow , allocatedRgn ) ; + updateRgn = allocatedRgn ; + } + } #if 0 // in case we would need a coregraphics compliant background erase first @@ -184,6 +245,8 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl #endif if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) ) result = noErr ; + if ( allocatedRgn ) + DisposeRgn( allocatedRgn ) ; } break ; case kEventControlVisibilityChanged : @@ -327,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 ) ) @@ -339,6 +405,7 @@ pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef default : break ; } + wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ; return result ; } @@ -509,7 +576,6 @@ pascal OSStatus wxMacSetupControlBackground( ControlRef iControl , SInt16 iMessa const wxBrush &brush = wx->MacGetBackgroundBrush() ; if ( brush.Ok() ) { - wxDC::MacSetupBackgroundForCurrentPort( brush ) ; */ // this clipping is only needed for non HIView @@ -627,6 +693,39 @@ wxWindowMac::~wxWindowMac() m_isBeingDeleted = TRUE; + if ( m_peer ) + { + // deleting a window while it is shown invalidates the region occupied by border or + // focus + int outerBorder = MacGetLeftBorderSize() ; + if ( m_peer->NeedsFocusRect() && m_peer->HasFocus() ) + outerBorder += 4 ; + + if ( IsShown() && ( 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 ) ; + + GetParent()->m_peer->SetNeedsDisplay( true , updateTotal ) ; + DisposeRgn(updateOuter) ; + DisposeRgn(updateInner) ; + DisposeRgn(updateTotal) ; + } + } + #ifndef __WXUNIVERSAL__ // VS: make sure there's no wxFrame with last focus set to us: for ( wxWindow *win = GetParent(); win; win = win->GetParent() ) @@ -781,7 +880,7 @@ void wxWindowMac::MacPostControlCreate(const wxPoint& pos, const wxSize& size) #if !TARGET_API_MAC_OSX // eventually we can fix some clipping issues be reactivating this hook //if ( m_macIsUserPane ) - // SetControlColorProc( *m_peer , wxMacSetupControlBackgroundUPP ) ; + // SetControlColorProc( m_peer->GetControlRef() , wxMacSetupControlBackgroundUPP ) ; #endif m_peer->SetTitle( wxStripMenuCodes(m_label) ) ; @@ -900,6 +999,11 @@ bool wxWindowMac::SetBackgroundColour(const wxColour& col ) return true ; } +void wxWindowMac::MacSetBackgroundBrush( const wxBrush &brush ) +{ + m_macBackgroundBrush = brush ; + m_peer->SetBackground( brush ) ; +} bool wxWindowMac::MacCanFocus() const { @@ -917,9 +1021,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 @@ -997,6 +1103,9 @@ void wxWindowMac::DragAcceptFiles(bool accept) // TODO } +// Returns the size of the native control. In the case of the toplevel window +// this is the content area root control + void wxWindowMac::MacGetPositionAndSizeFromControl(int& x, int& y, int& w, int& h) const { @@ -1008,17 +1117,10 @@ void wxWindowMac::MacGetPositionAndSizeFromControl(int& x, int& y, y = bounds.top ; w = bounds.right - bounds.left ; h = bounds.bottom - bounds.top ; - - wxTopLevelWindow* tlw = wxDynamicCast( this , wxTopLevelWindow ) ; - if ( tlw ) - { - Point tlworigin = { 0 , 0 } ; - QDLocalToGlobalPoint( UMAGetWindowPort( (WindowRef) tlw->MacGetWindowRef() ) , &tlworigin ) ; - x = tlworigin.h ; - y = tlworigin.v ; - } } +// From a wx position / size calculate the appropriate size of the native control + bool wxWindowMac::MacGetBoundsForControl(const wxPoint& pos, const wxSize& size, int& x, int& y, @@ -1042,23 +1144,25 @@ bool wxWindowMac::MacGetBoundsForControl(const wxPoint& pos, if ( adjustOrigin ) AdjustForParentClientOrigin( x , y ) ; +#if TARGET_API_MAC_OSX + // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border + if ( ! GetParent()->IsTopLevel() ) + { + x -= GetParent()->MacGetLeftBorderSize() ; + y -= GetParent()->MacGetTopBorderSize() ; + } +#endif return true ; } -// Get total size +// Get window size (not client size) void wxWindowMac::DoGetSize(int *x, int *y) const { // take the size of the control and add the borders that have to be drawn outside - int x1 , y1 , w1 ,h1 ; -#if TARGET_API_MAC_OSX + int x1 , y1 , w1 , h1 ; + MacGetPositionAndSizeFromControl( x1 , y1, w1 ,h1 ) ; - -#else - Rect bounds ; - m_peer->GetRect( &bounds ) ; - w1 = bounds.right - bounds.left ; - h1 = bounds.bottom - bounds.top ; -#endif + w1 += MacGetLeftBorderSize() + MacGetRightBorderSize() ; h1 += MacGetTopBorderSize() + MacGetBottomBorderSize() ; @@ -1066,18 +1170,32 @@ void wxWindowMac::DoGetSize(int *x, int *y) const if(y) *y = h1 ; } +// get the position of the bounds of this window in client coordinates of its parent void wxWindowMac::DoGetPosition(int *x, int *y) const { - #if TARGET_API_MAC_OSX int x1 , y1 , w1 ,h1 ; MacGetPositionAndSizeFromControl( x1 , y1, w1 ,h1 ) ; x1 -= MacGetLeftBorderSize() ; y1 -= MacGetTopBorderSize() ; + // to non-client + #if !TARGET_API_MAC_OSX + if ( !GetParent()->IsTopLevel() ) + { + Rect bounds ; + GetControlBounds( (ControlRef) GetParent()->GetHandle() , &bounds ) ; + x1 -= bounds.left ; + y1 -= bounds.top ; + } +#endif if ( !IsTopLevel() ) { wxWindow *parent = GetParent(); if ( parent ) { + // we must first adjust it to be in window coordinates of the parent, as otherwise it gets lost by the clientareaorigin fix + x1 += parent->MacGetLeftBorderSize() ; + y1 += parent->MacGetTopBorderSize() ; + // and now to client coordinates wxPoint pt(parent->GetClientAreaOrigin()); x1 -= pt.x ; y1 -= pt.y ; @@ -1085,31 +1203,6 @@ void wxWindowMac::DoGetPosition(int *x, int *y) const } if(x) *x = x1 ; if(y) *y = y1 ; - #else - Rect bounds ; - m_peer->GetRect( &bounds ) ; - wxCHECK_RET( GetParent() , wxT("Missing Parent") ) ; - - int xx = bounds.left ; - int yy = bounds.top ; - xx -= MacGetLeftBorderSize() ; - yy -= MacGetTopBorderSize() ; - - if ( !GetParent()->IsTopLevel() ) - { - GetControlBounds( (ControlRef) GetParent()->GetHandle() , &bounds ) ; - - xx -= bounds.left ; - yy -= bounds.top ; - } - - wxPoint pt(GetParent()->GetClientAreaOrigin()); - xx -= pt.x; - yy -= pt.y; - - if(x) *x = xx; - if(y) *y = yy; -#endif } void wxWindowMac::DoScreenToClient(int *x, int *y) const @@ -1200,8 +1293,8 @@ void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const { Rect bounds ; m_peer->GetRect( &bounds ) ; - if(x) *x += bounds.left ; - if(y) *y += bounds.top ; + if(x) *x += bounds.left - MacGetLeftBorderSize() ; + if(y) *y += bounds.top - MacGetTopBorderSize() ; } #endif } @@ -1237,8 +1330,8 @@ void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const { Rect bounds ; m_peer->GetRect( &bounds ) ; - if(x) *x -= bounds.left ; - if(y) *y -= bounds.top ; + if(x) *x -= bounds.left + MacGetLeftBorderSize() ; + if(y) *y -= bounds.top + MacGetTopBorderSize() ; } #endif } @@ -1333,10 +1426,11 @@ void wxWindowMac::DoGetClientSize(int *x, int *y) const #endif ww = content.right - content.left ; hh = content.bottom - content.top ; - + /* ww -= MacGetLeftBorderSize( ) + MacGetRightBorderSize( ) ; hh -= MacGetTopBorderSize( ) + MacGetBottomBorderSize( ); - + */ + /* if ( (m_vScrollBar && m_vScrollBar->IsShown()) || (m_hScrollBar && m_hScrollBar->IsShown()) ) { int x1 = 0 ; @@ -1364,7 +1458,7 @@ void wxWindowMac::DoGetClientSize(int *x, int *y) const if (m_hScrollBar && m_hScrollBar->IsShown() ) { - hh -= MAC_SCROLLBAR_SIZE; + hh -= m_hScrollBar->GetSize().y ; // MAC_SCROLLBAR_SIZE ; if ( h-y1 >= totH ) { hh += 1 ; @@ -1372,13 +1466,22 @@ void wxWindowMac::DoGetClientSize(int *x, int *y) const } if (m_vScrollBar && m_vScrollBar->IsShown() ) { - ww -= MAC_SCROLLBAR_SIZE; + ww -= m_vScrollBar->GetSize().x ; // MAC_SCROLLBAR_SIZE; if ( w-x1 >= totW ) { ww += 1 ; } } } + */ + if (m_hScrollBar && m_hScrollBar->IsShown() ) + { + hh -= m_hScrollBar->GetSize().y ; // MAC_SCROLLBAR_SIZE ; + } + if (m_vScrollBar && m_vScrollBar->IsShown() ) + { + ww -= m_vScrollBar->GetSize().x ; // MAC_SCROLLBAR_SIZE; + } if(x) *x = ww; if(y) *y = hh; @@ -1490,17 +1593,20 @@ void wxWindowMac::DoSetToolTip(wxToolTip *tooltip) void wxWindowMac::DoMoveWindow(int x, int y, int width, int height) { + // this is never called for a toplevel window, so we know we have a parent int former_x , former_y , former_w, former_h ; -#if !TARGET_API_MAC_OSX + + // Get true coordinates of former position DoGetPosition( &former_x , &former_y ) ; DoGetSize( &former_w , &former_h ) ; -#else - MacGetPositionAndSizeFromControl( former_x , former_y , former_w , former_h ) ; - former_x -= MacGetLeftBorderSize() ; - former_y -= MacGetTopBorderSize() ; - former_w += MacGetLeftBorderSize() + MacGetRightBorderSize() ; - former_h += MacGetTopBorderSize() + MacGetBottomBorderSize() ; -#endif + + wxWindow *parent = GetParent(); + if ( parent ) + { + wxPoint pt(parent->GetClientAreaOrigin()); + former_x += pt.x ; + former_y += pt.y ; + } int actualWidth = width; int actualHeight = height; @@ -1533,10 +1639,48 @@ void wxWindowMac::DoMoveWindow(int x, int y, int width, int height) // we don't adjust twice for the origin Rect r = wxMacGetBoundsForControl(this , wxPoint( actualX,actualY), wxSize( actualWidth, actualHeight ) , false ) ; 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 ) ; + + OffsetRgn( updateOuter , -parent.x , -parent.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 ) ; @@ -1825,8 +1969,9 @@ bool wxWindowMac::MacIsReallyShown() { // only under OSX the visibility of the TLW is taken into account #if TARGET_API_MAC_OSX - return m_peer->IsVisible(); -#else + if ( m_peer && m_peer->Ok() ) + return m_peer->IsVisible(); +#endif wxWindow* win = this ; while( win->IsShown() ) { @@ -1839,7 +1984,6 @@ bool wxWindowMac::MacIsReallyShown() } ; return false ; -#endif } bool wxWindowMac::MacIsReallyEnabled() @@ -1902,6 +2046,9 @@ void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y, void wxWindowMac::Refresh(bool eraseBack, const wxRect *rect) { + if ( m_peer == NULL ) + return ; + #if TARGET_API_MAC_OSX if ( rect == NULL ) m_peer->SetNeedsDisplay( true ) ; @@ -1912,7 +2059,11 @@ void wxWindowMac::Refresh(bool eraseBack, const wxRect *rect) SectRgn( (RgnHandle) MacGetVisibleRegion().GetWXHRGN() , update , update ) ; wxPoint origin = GetClientAreaOrigin() ; OffsetRgn( update, origin.x , origin.y ) ; - m_peer->SetNeedsDisplay( true , update) ; + // right now this is wx' window coordinates, as our native peer does not have borders, this is + // inset + OffsetRgn( update , -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ; + m_peer->SetNeedsDisplay( true , update) ; + DisposeRgn( update ) ; } #else /* @@ -2040,20 +2191,21 @@ void wxWindowMac::WarpPointer (int x_pos, int y_pos) void wxWindowMac::OnEraseBackground(wxEraseEvent& event) { +#if TARGET_API_MAC_OSX if ( m_macBackgroundBrush.Ok() == false || m_macBackgroundBrush.GetStyle() == wxTRANSPARENT ) { event.Skip() ; } else - event.GetDC()->Clear() ; +#endif + { + event.GetDC()->Clear() ; + } } 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 @@ -2122,74 +2274,39 @@ void wxWindowMac::MacPaintBorders( int left , int top ) if( IsTopLevel() ) return ; - int major,minor; - wxGetOsVersion( &major, &minor ); + Rect rect ; + m_peer->GetRect( &rect ) ; + InsetRect( &rect, -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ; - RGBColor white = { 0xFFFF, 0xFFFF , 0xFFFF } ; - RGBColor face = { 0xDDDD, 0xDDDD , 0xDDDD } ; - - 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; - } + 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 ; + } + } - PenNormal() ; - - int w , h ; - GetSize( &w , &h ) ; - Rect rect = { top , left , h + top , w + left } ; 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 - 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)) { - Rect rect = { top , left , h + top , w + left } ; - RGBForeColor( &darkShadow ) ; - FrameRect( &rect ) ; + Rect srect = rect ; + SInt32 border = 0 ; + GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ; + InsetRect( &srect , border , border ); + DrawThemeListBoxFrame(&rect,IsEnabled() ? kThemeStateActive : kThemeStateInactive) ; } } @@ -2259,7 +2376,7 @@ void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect) // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control // area is scrolled, this does not occur if width and height are 2 pixels less, // TODO write optimal workaround - wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , MacGetLeftBorderSize() + width , MacGetTopBorderSize() + height ) ; + wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ; if ( rect ) { scrollrect.Intersect( *rect ) ; @@ -2276,9 +2393,11 @@ void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect) if( UMAGetSystemVersion() < 0x1030 ) Update() ; else - HIViewRender(*m_peer) ; + HIViewRender(m_peer->GetControlRef()) ; #endif } + // as the native control might be not a 0/0 wx window coordinates, we have to offset + scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ; m_peer->ScrollRect( scrollrect , dx , dy ) ; #else @@ -2388,8 +2507,6 @@ void wxWindowMac::OnSetFocus(wxFocusEvent& event) if ( MacGetTopLevelWindow() && m_peer->NeedsFocusRect() ) { wxMacWindowStateSaver sv( this ) ; -// wxWindowDC dc(this) ; -// wxMacPortSetter helper(&dc) ; int w , h ; int x , y ; @@ -2401,7 +2518,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(); @@ -2532,7 +2667,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() ; @@ -2557,8 +2696,9 @@ wxRegion wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures ) r.top = 0 ; } if ( includeOuterStructures ) - InsetRect( &r , -3 , -3 ) ; + InsetRect( &r , -4 , -4 ) ; RectRgn( visRgn , &r ) ; + if ( !IsTopLevel() ) { wxWindow* child = this ; @@ -2584,12 +2724,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 ; @@ -2611,29 +2758,31 @@ bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time ) { RgnHandle updatergn = (RgnHandle) updatergnr ; bool handled = false ; - - // calculate a client-origin version of the update rgn and set m_updateRegion to that + 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() ; wxSize point = GetClientSize() ; wxPoint origin = GetClientAreaOrigin() ; SetRectRgn( newupdate , origin.x , origin.y , origin.x + point.x , origin.y+point.y ) ; SectRgn( newupdate , updatergn , 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 ) ; m_updateRegion = newupdate ; DisposeRgn( newupdate ) ; - } - if ( !EmptyRgn(updatergn) ) - { - wxWindowDC dc(this); - if (!EmptyRgn(updatergn)) - dc.SetClippingRegion(wxRegion(updatergn)); - - wxEraseEvent eevent( GetId(), &dc ); - eevent.SetEventObject( this ); - GetEventHandler()->ProcessEvent( eevent ); - if ( !m_updateRegion.Empty() ) { // paint the window itself @@ -2642,10 +2791,63 @@ 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) ; + Rect r = childRect ; + OffsetRect( &r , dc.m_macLocalOrigin.x , dc.m_macLocalOrigin.y ) ; + DrawThemeFocusRect( &r , true ) ; + } } } return handled ; @@ -2703,45 +2905,53 @@ void wxWindowMac::MacCreateScrollBars( long style ) { wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ; - bool hasBoth = ( style & wxVSCROLL ) && ( style & wxHSCROLL ) ; - int adjust = hasBoth ? MAC_SCROLLBAR_SIZE - 1: 0 ; - int width, height ; - GetClientSize( &width , &height ) ; + if ( style & ( wxVSCROLL | wxHSCROLL ) ) + { + bool hasBoth = ( style & wxVSCROLL ) && ( style & wxHSCROLL ) ; + int scrlsize = MAC_SCROLLBAR_SIZE ; + wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL ; + if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI ) + { + scrlsize = MAC_SMALL_SCROLLBAR_SIZE ; + variant = wxWINDOW_VARIANT_SMALL ; + } - wxPoint vPoint(width-MAC_SCROLLBAR_SIZE, 0) ; - wxSize vSize(MAC_SCROLLBAR_SIZE, height - adjust) ; - wxPoint hPoint(0 , height-MAC_SCROLLBAR_SIZE ) ; - wxSize hSize( width - adjust, MAC_SCROLLBAR_SIZE) ; + int adjust = hasBoth ? scrlsize - 1: 0 ; + int width, height ; + GetClientSize( &width , &height ) ; - m_vScrollBar = new wxScrollBar(this, wxWINDOW_VSCROLL, vPoint, - vSize , wxVERTICAL); + wxPoint vPoint(width-scrlsize, 0) ; + wxSize vSize(scrlsize, height - adjust) ; + wxPoint hPoint(0 , height-scrlsize ) ; + wxSize hSize( width - adjust, scrlsize) ; - if ( style & wxVSCROLL ) - { - } - else - { - m_vScrollBar->Show(false) ; - } - m_hScrollBar = new wxScrollBar(this, wxWINDOW_HSCROLL, hPoint, - hSize , wxHORIZONTAL); - if ( style & wxHSCROLL ) - { - } - else - { - m_hScrollBar->Show(false) ; + if ( style & wxVSCROLL ) + { + m_vScrollBar = new wxScrollBar(this, wxWINDOW_VSCROLL, vPoint, + vSize , wxVERTICAL); + } + + if ( style & wxHSCROLL ) + { + m_hScrollBar = new wxScrollBar(this, wxWINDOW_HSCROLL, hPoint, + hSize , wxHORIZONTAL); + } } + // because the create does not take into account the client area origin MacRepositionScrollBars() ; // we might have a real position shift } void wxWindowMac::MacRepositionScrollBars() { + if ( !m_hScrollBar && !m_vScrollBar ) + return ; + bool hasBoth = ( m_hScrollBar && m_hScrollBar->IsShown()) && ( m_vScrollBar && m_vScrollBar->IsShown()) ; - int adjust = hasBoth ? MAC_SCROLLBAR_SIZE - 1 : 0 ; + int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ; + int adjust = hasBoth ? scrlsize - 1 : 0 ; // get real client area @@ -2756,7 +2966,7 @@ void wxWindowMac::MacRepositionScrollBars() wxSize vSize(MAC_SCROLLBAR_SIZE, height - adjust) ; wxPoint hPoint(0 , height-MAC_SCROLLBAR_SIZE ) ; wxSize hSize( width - adjust, MAC_SCROLLBAR_SIZE) ; - +/* int x = 0 ; int y = 0 ; int w ; @@ -2802,7 +3012,7 @@ void wxWindowMac::MacRepositionScrollBars() vSize.y += 1 ; hPoint.y += 1 ; } - +*/ if ( m_vScrollBar ) { m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE); @@ -2852,17 +3062,11 @@ long wxWindowMac::MacGetLeftBorderSize( ) const if (m_windowStyle & wxRAISED_BORDER || m_windowStyle & wxSUNKEN_BORDER ) { SInt32 border = 3 ; -#if 0 // wxMAC_USE_THEME_BORDER - GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ; -#endif return border ; } else if ( m_windowStyle &wxDOUBLE_BORDER) { SInt32 border = 3 ; -#if 0 // wxMAC_USE_THEME_BORDER - GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ; -#endif return border ; } else if (m_windowStyle &wxSIMPLE_BORDER) @@ -2892,7 +3096,7 @@ long wxWindowMac::MacGetBottomBorderSize( ) const long wxWindowMac::MacRemoveBordersFromStyle( long style ) { - return style & ~( wxDOUBLE_BORDER | wxSUNKEN_BORDER | wxRAISED_BORDER | wxBORDER | wxSTATIC_BORDER ) ; + return style & ~wxBORDER_MASK ; } // Find the wxWindowMac at the current mouse position, returning the mouse