Fix clipping of scrolled windows under macOS Sonoma
We need to use a native clip view for things to behave correctly under this OS version, otherwise scrollbars can be overdrawn by the window contents. Closes #24067. Closes #24073.
This commit is contained in:
parent
8ca312b17c
commit
bcbc31e97f
5 changed files with 98 additions and 4 deletions
|
|
@ -220,8 +220,13 @@ public :
|
|||
// from the same pimpl class.
|
||||
virtual void controlTextDidChange();
|
||||
|
||||
virtual void AdjustClippingView(wxScrollBar* horizontal, wxScrollBar* vertical) override;
|
||||
virtual void UseClippingView(bool clip) override;
|
||||
virtual WXWidget GetContainer() const override { return m_osxClipView ? m_osxClipView : m_osxView; }
|
||||
|
||||
protected:
|
||||
WXWidget m_osxView;
|
||||
WXWidget m_osxClipView;
|
||||
|
||||
// begins processing of native key down event, storing the native event for later wx event generation
|
||||
void BeginNativeKeyDownEvent( NSEvent* event );
|
||||
|
|
|
|||
|
|
@ -365,6 +365,14 @@ public :
|
|||
|
||||
virtual bool EnableTouchEvents(int eventsMask) = 0;
|
||||
|
||||
// scrolling views need a clip subview that acts as parent for native children
|
||||
// (except for the scollbars) which are children of the view itself
|
||||
virtual void AdjustClippingView(wxScrollBar* horizontal, wxScrollBar* vertical);
|
||||
virtual void UseClippingView(bool clip);
|
||||
|
||||
// returns native view which acts as a parent for native children
|
||||
virtual WXWidget GetContainer() const;
|
||||
|
||||
// Mechanism used to keep track of whether a change should send an event
|
||||
// Do SendEvents(false) when starting actions that would trigger programmatic events
|
||||
// and SendEvents(true) at the end of the block.
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ public:
|
|||
// returns true if children have to clipped to the content area
|
||||
// (e.g., scrolled windows)
|
||||
bool MacClipChildren() const { return m_clipChildren ; }
|
||||
void MacSetClipChildren( bool clip ) { m_clipChildren = clip ; }
|
||||
void MacSetClipChildren( bool clip );
|
||||
|
||||
// returns true if the grandchildren need to be clipped to the children's content area
|
||||
// (e.g., splitter windows)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "wx/textctrl.h"
|
||||
#include "wx/combobox.h"
|
||||
#include "wx/radiobut.h"
|
||||
#include "wx/scrolbar.h"
|
||||
#endif
|
||||
|
||||
#ifdef __WXMAC__
|
||||
|
|
@ -2562,6 +2563,7 @@ wxWidgetImpl( peer, flags )
|
|||
{
|
||||
Init();
|
||||
m_osxView = w;
|
||||
m_osxClipView = nil;
|
||||
|
||||
// check if the user wants to create the control initially hidden
|
||||
if ( !peer->IsShown() )
|
||||
|
|
@ -3215,6 +3217,21 @@ bool wxWidgetCocoaImpl::CanFocus() const
|
|||
return canFocus;
|
||||
}
|
||||
|
||||
@interface wxNSClipView : NSClipView
|
||||
|
||||
@end
|
||||
|
||||
@implementation wxNSClipView
|
||||
|
||||
#if wxOSX_USE_NATIVE_FLIPPED
|
||||
- (BOOL)isFlipped
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
bool wxWidgetCocoaImpl::HasFocus() const
|
||||
{
|
||||
NSView* targetView = m_osxView;
|
||||
|
|
@ -3305,7 +3322,13 @@ void wxWidgetCocoaImpl::RemoveFromParent()
|
|||
|
||||
void wxWidgetCocoaImpl::Embed( wxWidgetImpl *parent )
|
||||
{
|
||||
NSView* container = parent->GetWXWidget() ;
|
||||
NSView* container = nil;
|
||||
|
||||
if ( m_wxPeer->MacIsWindowScrollbar( parent->GetWXPeer()))
|
||||
container = parent->GetWXWidget();
|
||||
else
|
||||
container = parent->GetContainer();
|
||||
|
||||
wxASSERT_MSG( container != nullptr , wxT("No valid mac container control") ) ;
|
||||
[container addSubview:m_osxView];
|
||||
|
||||
|
|
@ -4034,6 +4057,41 @@ void wxWidgetCocoaImpl::SetDrawingEnabled(bool enabled)
|
|||
[[m_osxView window] disableFlushWindow];
|
||||
}
|
||||
}
|
||||
|
||||
void wxWidgetCocoaImpl::AdjustClippingView(wxScrollBar* horizontal, wxScrollBar* vertical)
|
||||
{
|
||||
if( m_osxClipView )
|
||||
{
|
||||
NSRect bounds = m_osxView.bounds;
|
||||
if( horizontal && horizontal->IsShown() )
|
||||
{
|
||||
int sz = horizontal->GetSize().y;
|
||||
bounds.size.height -= sz;
|
||||
}
|
||||
if( vertical && vertical->IsShown() )
|
||||
{
|
||||
int sz = vertical->GetSize().x;
|
||||
bounds.size.width -= sz;
|
||||
}
|
||||
m_osxClipView.frame = bounds;
|
||||
}
|
||||
}
|
||||
|
||||
void wxWidgetCocoaImpl::UseClippingView(bool clip)
|
||||
{
|
||||
wxWindow* peer = m_wxPeer;
|
||||
|
||||
if ( peer && m_osxClipView == nil)
|
||||
{
|
||||
m_osxClipView = [[wxNSClipView alloc] initWithFrame: m_osxView.bounds];
|
||||
[(NSClipView*)m_osxClipView setDrawsBackground: NO];
|
||||
[m_osxView addSubview:m_osxClipView];
|
||||
|
||||
// TODO check for additional subwindows which might have to be moved to the clip view ?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Factory methods
|
||||
//
|
||||
|
|
|
|||
|
|
@ -261,6 +261,13 @@ wxWindowMac::~wxWindowMac()
|
|||
delete GetPeer() ;
|
||||
}
|
||||
|
||||
void wxWindowMac::MacSetClipChildren( bool clip )
|
||||
{
|
||||
m_clipChildren = clip ;
|
||||
if ( m_peer )
|
||||
m_peer->UseClippingView(clip);
|
||||
}
|
||||
|
||||
WXWidget wxWindowMac::GetHandle() const
|
||||
{
|
||||
if ( GetPeer() )
|
||||
|
|
@ -386,6 +393,8 @@ bool wxWindowMac::Create(wxWindowMac *parent,
|
|||
{
|
||||
SetPeer(wxWidgetImpl::CreateUserPane( this, parent, id, pos, size , style, GetExtraStyle() ));
|
||||
MacPostControlCreate(pos, size) ;
|
||||
if ( m_clipChildren )
|
||||
m_peer->UseClippingView(m_clipChildren);
|
||||
}
|
||||
|
||||
wxWindowCreateEvent event((wxWindow*)this);
|
||||
|
|
@ -2139,6 +2148,7 @@ void wxWindowMac::MacRepositionScrollBars()
|
|||
m_growBox->Hide();
|
||||
}
|
||||
}
|
||||
m_peer->AdjustClippingView(m_hScrollBar, m_vScrollBar);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -2700,3 +2710,16 @@ bool wxWidgetImpl::NeedsFrame() const
|
|||
void wxWidgetImpl::SetDrawingEnabled(bool WXUNUSED(enabled))
|
||||
{
|
||||
}
|
||||
|
||||
void wxWidgetImpl::AdjustClippingView(wxScrollBar* WXUNUSED(horizontal), wxScrollBar* WXUNUSED(vertical))
|
||||
{
|
||||
}
|
||||
|
||||
void wxWidgetImpl::UseClippingView(bool WXUNUSED(clip))
|
||||
{
|
||||
}
|
||||
|
||||
WXWidget wxWidgetImpl::GetContainer() const
|
||||
{
|
||||
return GetWXWidget();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue