From b57fdc4ff6f72946729e551a0df44e8f6378f10d Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Mon, 20 Jul 2020 13:03:29 +0200 Subject: [PATCH 1/4] Invalidate wxDisplay cache on monitor [dis]connection under Mac Avoid returning outdated information from wxDisplay methods if the system configuration changes. Closes #18318. --- src/osx/carbon/app.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/osx/carbon/app.cpp b/src/osx/carbon/app.cpp index 441dbbe538..4d4f3a89ce 100644 --- a/src/osx/carbon/app.cpp +++ b/src/osx/carbon/app.cpp @@ -45,6 +45,7 @@ // mac #include "wx/osx/private.h" +#include "wx/display.h" #if defined(WXMAKINGDLL_CORE) # include @@ -324,6 +325,18 @@ bool wxApp::Initialize(int& argc, wxChar **argv) return true; } +#ifdef __WXOSX_COCOA__ +void wxCGDisplayReconfigurationCallBack(CGDirectDisplayID WXUNUSED(display), + CGDisplayChangeSummaryFlags WXUNUSED(flags), + void* WXUNUSED(userInfo)) +{ + // flags could be tested to know about removal, addition etc. right now + // this is called multiple times for a change but for invalidating the + // cache these things don't matter yet + wxDisplay::InvalidateCache(); +} +#endif + bool wxApp::OnInitGui() { if ( !wxAppBase::OnInitGui() ) @@ -332,6 +345,10 @@ bool wxApp::OnInitGui() if ( !DoInitGui() ) return false; +#ifdef __WXOSX_COCOA__ + CGDisplayRegisterReconfigurationCallback(wxCGDisplayReconfigurationCallBack, NULL); +#endif + return true ; } From d7d7505974c97d1d7ef8ae541871a090af77ecce Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Mon, 20 Jul 2020 15:30:51 +0200 Subject: [PATCH 2/4] Fix generating mouse (and other) events in wxOSX wxStaticBitmap Use custom subclass for native static bitmap, to ensure that we call wxOSXCocoaClassAddWXMethods() for it. This notably allows to get mouse click events for this control. Closes #18545. --- src/osx/cocoa/statbmp.mm | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/osx/cocoa/statbmp.mm b/src/osx/cocoa/statbmp.mm index a1833634ff..20fd645f7c 100644 --- a/src/osx/cocoa/statbmp.mm +++ b/src/osx/cocoa/statbmp.mm @@ -32,6 +32,30 @@ #include "wx/osx/private.h" +@interface wxStaticBitmapView : NSImageView +{ +} +@end + +@implementation wxStaticBitmapView + ++ (void)initialize +{ + static BOOL initialized = NO; + if (!initialized) + { + initialized = YES; + wxOSXCocoaClassAddWXMethods( self ); + } +} + +- (instancetype)initWithFrame:(NSRect)frameRect +{ + self = [super initWithFrame:frameRect]; + return self; +} +@end + class wxStaticBitmapCocoaImpl : public wxWidgetCocoaImpl { public : @@ -51,7 +75,7 @@ public : void SetScaleMode(wxStaticBitmap::ScaleMode scaleMode) { - NSImageView* v = (NSImageView*) m_osxView; + wxStaticBitmapView* v = (wxStaticBitmapView*) m_osxView; NSImageScaling scaling = NSImageScaleNone; switch ( scaleMode ) @@ -92,7 +116,7 @@ wxWidgetImplType* wxWidgetImpl::CreateStaticBitmap( wxWindowMac* wxpeer, long WXUNUSED(extraStyle)) { NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ; - NSImageView* v = [[NSImageView alloc] initWithFrame:r]; + wxStaticBitmapView* v = [[wxStaticBitmapView alloc] initWithFrame:r]; wxWidgetCocoaImpl* c = new wxStaticBitmapCocoaImpl( wxpeer, v ); return c; From d58e3e3ce6081b76a358fb2d3a07391e970d1539 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Mon, 20 Jul 2020 17:57:33 +0200 Subject: [PATCH 3/4] Fix returning wrong client size for some controls in wxOSX Make sure we are not neglecting the layout insets, for controls like button, choice and gauge, otherwise client sizes became larger than control sizes. Closes #18717. --- src/osx/cocoa/window.mm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 2fd1559bae..62fb443d5e 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -3083,6 +3083,13 @@ void wxWidgetCocoaImpl::GetContentArea( int&left, int &top, int &width, int &hei { left = top = 0; GetSize( width, height ); + + int leftinset, topinset, rightinset, bottominset; + GetLayoutInset( leftinset, topinset, rightinset, bottominset); + left += leftinset; + top += topinset; + width -= leftinset + rightinset; + height -= topinset + bottominset; } } From e93e9558f46f424a9c81dc0868c981b500d55716 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Tue, 21 Jul 2020 08:54:28 +0200 Subject: [PATCH 4/4] Fix change the shaped of a shaped window under Mac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shape path was not reset when another region shape was set, so add a workaround to trigger a recalculation of the TLW’s outer shape. Closes #18775. --- src/osx/cocoa/nonownedwnd.mm | 7 +++++++ src/osx/nonownedwnd_osx.cpp | 15 +++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/osx/cocoa/nonownedwnd.mm b/src/osx/cocoa/nonownedwnd.mm index c118d47b08..f38eeddde4 100644 --- a/src/osx/cocoa/nonownedwnd.mm +++ b/src/osx/cocoa/nonownedwnd.mm @@ -997,6 +997,13 @@ void wxNonOwnedWindowCocoaImpl::GetContentArea( int& left, int &top, int &width, bool wxNonOwnedWindowCocoaImpl::SetShape(const wxRegion& WXUNUSED(region)) { + // macOS caches the contour of the drawn area, so when the region is changed and the content view redrawn + // the shape of the tlw does not change, this is a workaround I found that leads to a contour-refresh ... + NSRect formerFrame = [m_macWindow frame]; + NSSize formerSize = [NSWindow contentRectForFrameRect:formerFrame styleMask:[m_macWindow styleMask]].size; + [m_macWindow setContentSize:NSMakeSize(10,10)]; + [m_macWindow setContentSize:formerSize]; + [m_macWindow setOpaque:NO]; [m_macWindow setBackgroundColor:[NSColor clearColor]]; diff --git a/src/osx/nonownedwnd_osx.cpp b/src/osx/nonownedwnd_osx.cpp index d17624f029..d5118be241 100644 --- a/src/osx/nonownedwnd_osx.cpp +++ b/src/osx/nonownedwnd_osx.cpp @@ -510,6 +510,7 @@ void *wxNonOwnedWindow::OSXGetViewOrWindow() const bool wxNonOwnedWindow::DoClearShape() { m_shape.Clear(); + m_shapePath = wxGraphicsPath(); wxSize sz = GetClientSize(); wxRegion region(0, 0, sz.x, sz.y); @@ -519,11 +520,13 @@ bool wxNonOwnedWindow::DoClearShape() bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region) { + m_shapePath = wxGraphicsPath(); m_shape = region; // set the native content view to transparency, this is an implementation detail // no reflected in the wx BackgroundStyle GetPeer()->SetBackgroundStyle(wxBG_STYLE_TRANSPARENT); + GetPeer()->SetNeedsDisplay(); return m_nowpeer->SetShape(region); } @@ -534,8 +537,6 @@ bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region) bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path) { - m_shapePath = path; - // Convert the path to wxRegion by rendering the path on a window-sized // bitmap, creating a mask from it and finally creating the region from // this mask. @@ -548,12 +549,18 @@ bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path) wxScopedPtr context(wxGraphicsContext::Create(dc)); context->SetBrush(*wxWHITE); - context->FillPath(m_shapePath); + context->FillPath(path); } bmp.SetMask(new wxMask(bmp, *wxBLACK)); - return DoSetRegionShape(wxRegion(bmp)); + // the shape path has to be set AFTER the region is set, because that method + // clears any former path + bool success = DoSetRegionShape(wxRegion(bmp)); + if ( success ) + m_shapePath = path; + + return success; } void