From c7fdb41fcdb5f8153268aea43995c2293c566ef0 Mon Sep 17 00:00:00 2001 From: ali kettab Date: Wed, 27 Dec 2023 19:16:18 +0100 Subject: [PATCH 1/4] Implement wxNonOwnedWindow::SetShape() taking wxGraphicsPath under wxQt This is a copy and paste of wxMac's implementation to make wxRichToolTip work under wxQt. --- interface/wx/nonownedwnd.h | 4 ++-- src/qt/nonownedwnd.cpp | 27 ++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/interface/wx/nonownedwnd.h b/interface/wx/nonownedwnd.h index fde840b262..e91783c70b 100644 --- a/interface/wx/nonownedwnd.h +++ b/interface/wx/nonownedwnd.h @@ -62,8 +62,8 @@ public: resized using SetSize(). As the overload above, this method is not guaranteed to work on all - platforms but currently does work in wxMSW, wxOSX/Cocoa and wxGTK (with - the appropriate but almost always present X11 extensions) ports. + platforms but currently does work in wxMSW, wxOSX/Cocoa, wxGTK and wxQt + (with the appropriate but almost always present X11 extensions) ports. @since 2.9.3 */ diff --git a/src/qt/nonownedwnd.cpp b/src/qt/nonownedwnd.cpp index 7923c8f161..c8fe400a1a 100644 --- a/src/qt/nonownedwnd.cpp +++ b/src/qt/nonownedwnd.cpp @@ -18,12 +18,12 @@ #ifndef WX_PRECOMP - #include "wx/dcclient.h" - #include "wx/region.h" + #include "wx/dcmemory.h" #include "wx/region.h" #endif // WX_PRECOMP #include "wx/nonownedwnd.h" +#include "wx/graphics.h" #include "wx/qt/private/converter.h" #include "wx/qt/private/utils.h" @@ -57,10 +57,27 @@ bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region) } #if wxUSE_GRAPHICS_CONTEXT -bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& WXUNUSED(path)) +bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path) { - wxMISSING_IMPLEMENTATION( __FUNCTION__ ); - return true; + // 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. + wxBitmap bmp(GetSize()); + + { + wxMemoryDC dc(bmp); + dc.SetBackground(*wxBLACK_BRUSH); + dc.Clear(); + + std::unique_ptr context(wxGraphicsContext::Create(dc)); + context->SetBrush(*wxWHITE_BRUSH); + context->SetAntialiasMode(wxANTIALIAS_NONE); + context->FillPath(path); + } + + bmp.SetMask(new wxMask(bmp, *wxBLACK)); + + return DoSetRegionShape(wxRegion(bmp)); } #endif From 40a6d74aaf206fbde506fad0fea20e92b24582f4 Mon Sep 17 00:00:00 2001 From: ali kettab Date: Wed, 27 Dec 2023 19:31:33 +0100 Subject: [PATCH 2/4] Create the wxPopupWindow with a parent under wxQt The fact that we cannot create a wxPopupWindow with a parent is no longer valid after the recent changes to the wxQt port. The wxRichToolTip (an instance of wxPopupWindow) will crash if created without a parent under this port. --- src/qt/popupwin.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/qt/popupwin.cpp b/src/qt/popupwin.cpp index 1ebc46eb45..b9adaace09 100644 --- a/src/qt/popupwin.cpp +++ b/src/qt/popupwin.cpp @@ -42,9 +42,9 @@ wxPopupWindow::wxPopupWindow(wxWindow *parent, int flags) Create(parent, flags); } -bool wxPopupWindow::Create( wxWindow *WXUNUSED(parent), int style ) +bool wxPopupWindow::Create( wxWindow *parent, int style ) { - m_qtWindow = new wxQtPopupWindow(nullptr, this); + m_qtWindow = new wxQtPopupWindow(parent, this); m_qtWindow->setWindowFlag(Qt::Popup); m_qtWindow->setFocusPolicy(Qt::NoFocus); @@ -55,7 +55,6 @@ bool wxPopupWindow::Create( wxWindow *WXUNUSED(parent), int style ) // Unlike windows, top level windows are created hidden by default. m_isShown = false; - // Under wxQt, popups should be created without parent. Otherwise, the - // application would crash (caused by double deletion) when it's shut down. - return wxPopupWindowBase::Create( nullptr, style ); + return wxPopupWindowBase::Create(parent, style) && + wxWindow::Create( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style ); } From 7dea9423c564592d8ea14ef728dec7103ac4a56f Mon Sep 17 00:00:00 2001 From: ali kettab Date: Wed, 27 Dec 2023 19:48:25 +0100 Subject: [PATCH 3/4] Fix wxPopupTransientWindow::Dismiss() implementation Remove installed event handlers before trying to hide the popup, as this could result in Destroy() being called twice under wxQt. This happens to wxRichToolTip for example. i.e. Destroy() is called once from wxPopupFocusHandler::OnKillFocus() after the call to Hide() then, from wxRichToolTipPopup::OnTimer(). --- src/common/popupcmn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/popupcmn.cpp b/src/common/popupcmn.cpp index bf11efccbc..a0b9e8b721 100644 --- a/src/common/popupcmn.cpp +++ b/src/common/popupcmn.cpp @@ -431,8 +431,8 @@ bool wxPopupTransientWindow::Show( bool show ) void wxPopupTransientWindow::Dismiss() { - Hide(); PopHandlers(); + Hide(); } #if defined(__WXMAC__) && wxOSX_USE_COCOA_OR_CARBON From b2842601912169e6c3e5b124bb3bf5d886cf0be2 Mon Sep 17 00:00:00 2001 From: AliKet Date: Thu, 28 Dec 2023 16:35:23 +0100 Subject: [PATCH 4/4] Update interface/wx/nonownedwnd.h Co-authored-by: VZ --- interface/wx/nonownedwnd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/wx/nonownedwnd.h b/interface/wx/nonownedwnd.h index e91783c70b..5232ce49f2 100644 --- a/interface/wx/nonownedwnd.h +++ b/interface/wx/nonownedwnd.h @@ -62,8 +62,8 @@ public: resized using SetSize(). As the overload above, this method is not guaranteed to work on all - platforms but currently does work in wxMSW, wxOSX/Cocoa, wxGTK and wxQt - (with the appropriate but almost always present X11 extensions) ports. + platforms but currently does work in wxMSW, wxOSX/Cocoa, wxGTK (with + the appropriate but almost always present X11 extensions) and wxQt ports. @since 2.9.3 */