From 785103493c6eb66429d55d06e0c30cfa185a4778 Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Wed, 17 Jul 2019 08:22:47 +0100 Subject: [PATCH 01/38] Use setLabel when creating a wxStaticText under wxQT --- src/qt/stattext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/stattext.cpp b/src/qt/stattext.cpp index 369d15f7e2..3d3be67e96 100644 --- a/src/qt/stattext.cpp +++ b/src/qt/stattext.cpp @@ -47,7 +47,7 @@ bool wxStaticText::Create(wxWindow *parent, const wxString &name) { m_qtLabel = new wxQtStaticText( parent, this ); - m_qtLabel->setText( wxQtConvertString( label ) ); + SetLabel(label); // Set the buddy to itself to get the mnemonic key but ensure that we don't have // any unwanted side effects, so disable the interaction: From a1d8a6a244929131ed135d4fb989487d1f79d658 Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Wed, 17 Jul 2019 08:29:25 +0100 Subject: [PATCH 02/38] Move call to SetLabel after base-class create so that flags have been set --- src/qt/stattext.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/qt/stattext.cpp b/src/qt/stattext.cpp index 3d3be67e96..1aaa885277 100644 --- a/src/qt/stattext.cpp +++ b/src/qt/stattext.cpp @@ -47,7 +47,6 @@ bool wxStaticText::Create(wxWindow *parent, const wxString &name) { m_qtLabel = new wxQtStaticText( parent, this ); - SetLabel(label); // Set the buddy to itself to get the mnemonic key but ensure that we don't have // any unwanted side effects, so disable the interaction: @@ -64,7 +63,12 @@ bool wxStaticText::Create(wxWindow *parent, else m_qtLabel->setAlignment(Qt::AlignLeft); - return QtCreateControl( parent, id, pos, size, style, wxDefaultValidator, name ); + if ( !QtCreateControl(parent, id, pos, size, style, wxDefaultValidator, name) ) + return false; + + SetLabel(label); + + return true; } void wxStaticText::SetLabel(const wxString& label) From 616fc76173e79ee9d65477d8185f44370f4c468d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 15 Sep 2019 01:35:16 +0200 Subject: [PATCH 03/38] Don't use default window style hints in wxFrame Building on windowFlags() meant that we inherited a bunch of default flags that were not affected by Qt::CustomizeWindowHint because we explicitly specified them when calling setWindowFlags(). Instead of doing this, start with nothing and just add the styles that we need. This notably ensures that the frames created without wxCLOSE_BOX style actually don't have any close button. Closes https://github.com/wxWidgets/wxWidgets/pull/1335 --- src/qt/frame.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qt/frame.cpp b/src/qt/frame.cpp index be927ce2cd..20c84d747a 100644 --- a/src/qt/frame.cpp +++ b/src/qt/frame.cpp @@ -134,15 +134,16 @@ void wxFrame::SetWindowStyleFlag( long style ) { wxWindow::SetWindowStyleFlag( style ); - QMainWindow *qtFrame = GetQMainWindow(); - Qt::WindowFlags qtFlags = qtFrame->windowFlags(); - qtFlags |= Qt::CustomizeWindowHint; + Qt::WindowFlags qtFlags = Qt::CustomizeWindowHint; if ( HasFlag( wxFRAME_TOOL_WINDOW ) ) { - qtFlags &= ~Qt::WindowType_Mask; qtFlags |= Qt::Tool; } + else + { + qtFlags |= Qt::Window; + } if ( HasFlag(wxCAPTION) ) { @@ -183,8 +184,7 @@ void wxFrame::SetWindowStyleFlag( long style ) qtFlags |= Qt::FramelessWindowHint; } - qtFrame->setWindowFlags(qtFlags); - + GetQMainWindow()->setWindowFlags(qtFlags); } void wxFrame::AddChild( wxWindowBase *child ) From b8d5c85ecb51c842605fdcfc90d90f9572dded92 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 15 Sep 2019 01:25:34 +0200 Subject: [PATCH 04/38] Make Reparent() work for wxFrame in wxQt Use the correct parent window, i.e. the one of the central widget and not of the frame itself. --- include/wx/qt/frame.h | 2 ++ include/wx/qt/window.h | 6 ++++++ src/qt/frame.cpp | 7 ++++++- src/qt/window.cpp | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/wx/qt/frame.h b/include/wx/qt/frame.h index 4905911d79..ea515def5c 100644 --- a/include/wx/qt/frame.h +++ b/include/wx/qt/frame.h @@ -57,6 +57,8 @@ public: protected: virtual void DoGetClientSize(int *width, int *height) const wxOVERRIDE; + virtual QWidget* QtGetParentWidget() const wxOVERRIDE; + private: // Common part of all ctors. void Init() diff --git a/include/wx/qt/window.h b/include/wx/qt/window.h index 98608b1fa2..ace2a71711 100644 --- a/include/wx/qt/window.h +++ b/include/wx/qt/window.h @@ -215,6 +215,12 @@ protected: virtual bool DoPopupMenu(wxMenu *menu, int x, int y) wxOVERRIDE; #endif // wxUSE_MENUS + // Return the parent to use for children being reparented to us: this is + // overridden in wxFrame to use its central widget rather than the frame + // itself. + virtual QWidget* QtGetParentWidget() const { return GetHandle(); } + + QWidget *m_qtWindow; private: diff --git a/src/qt/frame.cpp b/src/qt/frame.cpp index 20c84d747a..e32bf8ec98 100644 --- a/src/qt/frame.cpp +++ b/src/qt/frame.cpp @@ -187,11 +187,16 @@ void wxFrame::SetWindowStyleFlag( long style ) GetQMainWindow()->setWindowFlags(qtFlags); } +QWidget* wxFrame::QtGetParentWidget() const +{ + return GetQMainWindow()->centralWidget(); +} + void wxFrame::AddChild( wxWindowBase *child ) { // Make sure all children are children of the central widget: - QtReparent( child->GetHandle(), GetQMainWindow()->centralWidget() ); + QtReparent( child->GetHandle(), QtGetParentWidget() ); wxFrameBase::AddChild( child ); } diff --git a/src/qt/window.cpp b/src/qt/window.cpp index 7ccb774ab5..43bec0e3e9 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -437,7 +437,7 @@ bool wxWindowQt::Reparent( wxWindowBase *parent ) if ( !wxWindowBase::Reparent( parent )) return false; - QtReparent( GetHandle(), parent->GetHandle() ); + QtReparent( GetHandle(), static_cast(parent)->QtGetParentWidget() ); return true; } From 4bfb3a5f018a8d63b62c8dc7b9f3b0c7136d56c2 Mon Sep 17 00:00:00 2001 From: Liam Treacy Date: Tue, 4 Jun 2019 16:02:41 +0100 Subject: [PATCH 05/38] Implement wxFrame::DoSetClientSize() Resize the central widget to fit the new size. See https://github.com/wxWidgets/wxWidgets/pull/1340 --- include/wx/qt/frame.h | 1 + src/qt/frame.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/wx/qt/frame.h b/include/wx/qt/frame.h index ea515def5c..f640911a46 100644 --- a/include/wx/qt/frame.h +++ b/include/wx/qt/frame.h @@ -56,6 +56,7 @@ public: protected: virtual void DoGetClientSize(int *width, int *height) const wxOVERRIDE; + virtual void DoSetClientSize(int width, int height) wxOVERRIDE; virtual QWidget* QtGetParentWidget() const wxOVERRIDE; diff --git a/src/qt/frame.cpp b/src/qt/frame.cpp index e32bf8ec98..08f1c43f98 100644 --- a/src/qt/frame.cpp +++ b/src/qt/frame.cpp @@ -231,6 +231,19 @@ void wxFrame::DoGetClientSize(int *width, int *height) const } } +void wxFrame::DoSetClientSize(int width, int height) +{ + wxWindow::DoSetClientSize(width, height); + + int adjustedWidth, adjustedHeight; + DoGetClientSize(&adjustedWidth, &adjustedHeight); + + QWidget *centralWidget = GetQMainWindow()->centralWidget(); + QRect geometry = centralWidget->geometry(); + geometry.setSize(QSize(adjustedWidth, adjustedHeight)); + centralWidget->setGeometry(geometry); +} + QMainWindow *wxFrame::GetQMainWindow() const { return static_cast(m_qtWindow); From 5a228ceb91410fcb48c1f851fc4af8e14f10d3ba Mon Sep 17 00:00:00 2001 From: Liam Treacy Date: Tue, 4 Jun 2019 16:02:59 +0100 Subject: [PATCH 06/38] Show docking hint under wxQt too in wxAUI See https://github.com/wxWidgets/wxWidgets/pull/1340 --- src/aui/framemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aui/framemanager.cpp b/src/aui/framemanager.cpp index b6bd4575d2..9e777274bf 100644 --- a/src/aui/framemanager.cpp +++ b/src/aui/framemanager.cpp @@ -848,7 +848,7 @@ void wxAuiManager::UpdateHintWindowConfig() if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) && can_do_transparent) { // Make a window to use for a transparent hint - #if defined(__WXMSW__) || defined(__WXGTK__) + #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXQT__) m_hintWnd = new wxFrame(m_frame, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(1,1), wxFRAME_TOOL_WINDOW | From d66aa35254abe27790e08946f484a0575756a2f5 Mon Sep 17 00:00:00 2001 From: Jay Nabonne Date: Mon, 10 Jun 2019 15:33:31 +0100 Subject: [PATCH 07/38] Fix handling captured mouse events in a window with scrollbars Handle some mouse events explicitly when a wxQtScrollArea is set as "mouse captured". The issue arises in that the QScrollArea has two methods: event() and viewportEvent(). Normally a "QAbstractScrollAreaFilter" is set up by Qt which routes any events to the viewportEvent() method. And the normal event() method throws mouse events away (for reasons I'm not aware of - but it is what it is). If a wx window with a scroll area (e.g. wxRichTextCtrl) sets capture, the wxQtScrollArea (QScroll-derived) gets set as the direct "mouse grabber", and all events then bypass the filter and are sent directly to the "event" method, which throws them away. The typical result is that the window setting capture no longer gets mouse events, it keeps capture since it's looking for a mouse up that never comes, and the app more or less locks up since all mouse events are being effectively discarded. This change catches any event that comes in via the event() method and, when the mouse is captured by the widget, forwards it on to the viewportEvent method instead, performing what the filter would do via the normal event routing. It doesn't forward on "mouse press" events because the initial event that causes the capture ends up being fed back again, resulting in a "captured twice" error. The underlying reason I can see for this "being fed back again" is that, for some inexplicable reason, the wxRichTextCtrl "skips" the event even though it has actually processed it and taken capture. That means this solution isn't 100%, but it does fix the 99%+ cases where the capture is only gotten to redirect mouse moves and button ups. Perhaps an alternative solution might be to stop grabbing the mouse in wxQtScrollArea, but this would require more changes. Closes https://github.com/wxWidgets/wxWidgets/pull/1346 --- src/qt/window.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/qt/window.cpp b/src/qt/window.cpp index 43bec0e3e9..4410308d7e 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -59,9 +59,10 @@ wxQtWidget::wxQtWidget( wxWindowQt *parent, wxWindowQt *handler ) class wxQtScrollArea : public wxQtEventSignalHandler< QScrollArea, wxWindowQt > { +public: + wxQtScrollArea(wxWindowQt *parent, wxWindowQt *handler); - public: - wxQtScrollArea( wxWindowQt *parent, wxWindowQt *handler ); + bool event(QEvent *e) wxOVERRIDE; }; wxQtScrollArea::wxQtScrollArea( wxWindowQt *parent, wxWindowQt *handler ) @@ -69,6 +70,27 @@ wxQtScrollArea::wxQtScrollArea( wxWindowQt *parent, wxWindowQt *handler ) { } +bool wxQtScrollArea::event(QEvent *e) +{ + wxWindowQt* handler = GetHandler(); + if ( handler && handler->HasCapture() ) + { + switch ( e->type() ) + { + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::Wheel: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + return viewportEvent(e); + default: + break; + } + } + return QScrollArea::event(e); +} + class wxQtInternalScrollBar : public wxQtEventSignalHandler< QScrollBar, wxWindowQt > { public: From 3a4538a18cd5d4b5ee835ba3c96ea814a85ee5f1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 20 Sep 2019 03:26:59 +0200 Subject: [PATCH 08/38] Rewrite client size unit test without using CppUnit macros No real changes, just simplify the test. --- tests/window/clientsize.cpp | 82 +++++++++---------------------------- 1 file changed, 20 insertions(+), 62 deletions(-) diff --git a/tests/window/clientsize.cpp b/tests/window/clientsize.cpp index 27e13b4459..48d9ec8da3 100644 --- a/tests/window/clientsize.cpp +++ b/tests/window/clientsize.cpp @@ -21,78 +21,36 @@ #include "wx/window.h" #endif // WX_PRECOMP -// ---------------------------------------------------------------------------- -// test class -// ---------------------------------------------------------------------------- +#include "wx/scopedptr.h" -class ClientSizeTestCase : public CppUnit::TestCase -{ -public: - ClientSizeTestCase() { } - - virtual void setUp() wxOVERRIDE; - virtual void tearDown() wxOVERRIDE; - -private: - CPPUNIT_TEST_SUITE( ClientSizeTestCase ); - CPPUNIT_TEST( ClientToWindow ); - CPPUNIT_TEST( ClientSizeNotNegative ); - CPPUNIT_TEST( WindowToClient ); - CPPUNIT_TEST_SUITE_END(); - - void ClientToWindow(); - void ClientSizeNotNegative(); - void WindowToClient(); - - wxWindow *m_win; - - wxDECLARE_NO_COPY_CLASS(ClientSizeTestCase); -}; - -// register in the unnamed registry so that these tests are run by default -CPPUNIT_TEST_SUITE_REGISTRATION( ClientSizeTestCase ); - -// also include in its own registry so that these tests can be run alone -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ClientSizeTestCase, "ClientSizeTestCase" ); - -// ---------------------------------------------------------------------------- -// test initialization -// ---------------------------------------------------------------------------- - -void ClientSizeTestCase::setUp() -{ - m_win = wxTheApp->GetTopWindow(); -} - -void ClientSizeTestCase::tearDown() -{ - m_win = NULL; -} +#include "asserthelper.h" // ---------------------------------------------------------------------------- // tests themselves // ---------------------------------------------------------------------------- -void ClientSizeTestCase::ClientToWindow() +TEST_CASE("wxWindow::ClientWindowSizeRoundTrip", "[window][client-size]") { - CPPUNIT_ASSERT(m_win->GetSize() == - m_win->ClientToWindowSize(m_win->GetClientSize())); + wxWindow* const w = wxTheApp->GetTopWindow(); + REQUIRE( w ); + + const wxSize sizeWindow = w->GetSize(); + const wxSize sizeClient = w->GetClientSize(); + + INFO("client size: " << sizeClient); + CHECK( sizeWindow == w->ClientToWindowSize(sizeClient) ); + + INFO("window size: " << sizeWindow); + CHECK( sizeClient == w->WindowToClientSize(sizeWindow) ); } -void ClientSizeTestCase::ClientSizeNotNegative() +TEST_CASE("wxWindow::MinClientSize", "[window][client-size]") { - wxWindow* w = new wxWindow(wxTheApp->GetTopWindow(), -1, - wxDefaultPosition, wxDefaultSize, - wxBORDER_THEME); + wxScopedPtr w(new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY, + wxDefaultPosition, wxDefaultSize, + wxBORDER_THEME)); w->SetSize(wxSize(1,1)); const wxSize szw = w->GetClientSize(); - CPPUNIT_ASSERT(szw.GetWidth() >= 0); - CPPUNIT_ASSERT(szw.GetHeight() >= 0); - w->Destroy(); -} - -void ClientSizeTestCase::WindowToClient() -{ - CPPUNIT_ASSERT(m_win->GetClientSize() == - m_win->WindowToClientSize(m_win->GetSize())); + CHECK(szw.GetWidth() >= 0); + CHECK(szw.GetHeight() >= 0); } From baca938ce36e76d088c9afc2aa7498169e279406 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 22 Sep 2019 00:43:59 +0200 Subject: [PATCH 09/38] Rewrite SetSizeTestCase to not use CppUnit macros neither Do the same thing as in the previous commit to another test. No real changes. --- tests/window/setsize.cpp | 113 ++++++++++++++------------------------- 1 file changed, 41 insertions(+), 72 deletions(-) diff --git a/tests/window/setsize.cpp b/tests/window/setsize.cpp index d99200ac52..c12dc40761 100644 --- a/tests/window/setsize.cpp +++ b/tests/window/setsize.cpp @@ -21,97 +21,66 @@ #include "wx/window.h" #endif // WX_PRECOMP +#include "wx/scopedptr.h" + #include "asserthelper.h" // ---------------------------------------------------------------------------- -// test class +// tests helpers // ---------------------------------------------------------------------------- -class SetSizeTestCase : public CppUnit::TestCase +namespace +{ + +// Helper class overriding DoGetBestSize() for testing purposes. +class MyWindow : public wxWindow { public: - SetSizeTestCase() { } - - virtual void setUp() wxOVERRIDE; - virtual void tearDown() wxOVERRIDE; - -private: - CPPUNIT_TEST_SUITE( SetSizeTestCase ); - CPPUNIT_TEST( SetSize ); - CPPUNIT_TEST( SetSizeLessThanMinSize ); - CPPUNIT_TEST( BestSize ); - CPPUNIT_TEST_SUITE_END(); - - void SetSize(); - void SetSizeLessThanMinSize(); - void BestSize(); - - // Helper class overriding DoGetBestSize() for testing purposes. - class MyWindow : public wxWindow + MyWindow(wxWindow* parent) + : wxWindow(parent, wxID_ANY) { - public: - MyWindow(wxWindow* parent) - : wxWindow(parent, wxID_ANY) - { - } + } - protected: - virtual wxSize DoGetBestSize() const wxOVERRIDE { return wxSize(50, 250); } - }; - - wxWindow *m_win; - - wxDECLARE_NO_COPY_CLASS(SetSizeTestCase); +protected: + virtual wxSize DoGetBestSize() const wxOVERRIDE { return wxSize(50, 250); } }; -// register in the unnamed registry so that these tests are run by default -CPPUNIT_TEST_SUITE_REGISTRATION( SetSizeTestCase ); - -// also include in its own registry so that these tests can be run alone -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SetSizeTestCase, "SetSizeTestCase" ); - -// ---------------------------------------------------------------------------- -// test initialization -// ---------------------------------------------------------------------------- - -void SetSizeTestCase::setUp() -{ - m_win = new MyWindow(wxTheApp->GetTopWindow()); -} - -void SetSizeTestCase::tearDown() -{ - delete m_win; - m_win = NULL; -} +} // anonymous namespace // ---------------------------------------------------------------------------- // tests themselves // ---------------------------------------------------------------------------- -void SetSizeTestCase::SetSize() +TEST_CASE("wxWindow::SetSize", "[window][size]") { - const wxSize size(127, 35); - m_win->SetSize(size); - CPPUNIT_ASSERT_EQUAL( size, m_win->GetSize() ); + wxScopedPtr w(new MyWindow(wxTheApp->GetTopWindow())); + + SECTION("Simple") + { + const wxSize size(127, 35); + w->SetSize(size); + CHECK( size == w->GetSize() ); + } + + SECTION("With min size") + { + w->SetMinSize(wxSize(100, 100)); + + const wxSize size(200, 50); + w->SetSize(size); + CHECK( size == w->GetSize() ); + } } -void SetSizeTestCase::SetSizeLessThanMinSize() +TEST_CASE("wxWindow::GetBestSize", "[window][size][best-size]") { - m_win->SetMinSize(wxSize(100, 100)); + wxScopedPtr w(new MyWindow(wxTheApp->GetTopWindow())); - const wxSize size(200, 50); - m_win->SetSize(size); - CPPUNIT_ASSERT_EQUAL( size, m_win->GetSize() ); -} - -void SetSizeTestCase::BestSize() -{ - CPPUNIT_ASSERT_EQUAL( wxSize(50, 250), m_win->GetBestSize() ); - - m_win->SetMinSize(wxSize(100, 100)); - CPPUNIT_ASSERT_EQUAL( wxSize(100, 250), m_win->GetBestSize() ); - - m_win->SetMaxSize(wxSize(200, 200)); - CPPUNIT_ASSERT_EQUAL( wxSize(100, 200), m_win->GetBestSize() ); + CHECK( wxSize(50, 250) == w->GetBestSize() ); + + w->SetMinSize(wxSize(100, 100)); + CHECK( wxSize(100, 250) == w->GetBestSize() ); + + w->SetMaxSize(wxSize(200, 200)); + CHECK( wxSize(100, 200) == w->GetBestSize() ); } From be22e8fa95f5bbb0b9faf0b1d75d943c8524536e Mon Sep 17 00:00:00 2001 From: Jay Nabonne Date: Wed, 12 Jun 2019 10:27:42 +0100 Subject: [PATCH 10/38] Fix DoMoveWindow() to take into account the frame extent Using "move" is correct for positioning, as it takes into account the frame extent. Unfortunately, there is no corresponding API to set the frame size. So we need to compute the effective client size and use "resize". We can't use "setGeometry" for this purpose, since a widget's "geometry" excludes the frame size. We would need to adjust the position to go from frame to client coordinates. It's more straightforward to simply have Qt do it with "move". Closes https://github.com/wxWidgets/wxWidgets/pull/1349 --- src/qt/window.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/qt/window.cpp b/src/qt/window.cpp index 4410308d7e..93d72d8ff8 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -977,9 +977,19 @@ void wxWindowQt::DoMoveWindow(int x, int y, int width, int height) QWidget *qtWidget = GetHandle(); qtWidget->move( x, y ); - qtWidget->resize( width, height ); -} + // There doesn't seem to be any way to change Qt frame size directly, so + // change the widget size, but take into account the extra margins + // corresponding to the frame decorations. + const QSize frameSize = qtWidget->frameSize(); + const QSize innerSize = qtWidget->geometry().size(); + const QSize frameSizeDiff = frameSize - innerSize; + + const int clientWidth = std::max(width - frameSizeDiff.width(), 0); + const int clientHeight = std::max(height - frameSizeDiff.height(), 0); + + qtWidget->resize(clientWidth, clientHeight); +} #if wxUSE_TOOLTIPS void wxWindowQt::QtApplyToolTip(const wxString& text) From da8cecbfe51192c2ab1bf9c5760441b1e390ba5c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 22 Sep 2019 00:49:11 +0200 Subject: [PATCH 11/38] Add a unit test checking that Move() doesn't change frame size This used to be broken in wxQt until it was fixed by the previous commit. See https://github.com/swig/swig/pull/1613 --- tests/window/setsize.cpp | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/window/setsize.cpp b/tests/window/setsize.cpp index c12dc40761..37a10842c4 100644 --- a/tests/window/setsize.cpp +++ b/tests/window/setsize.cpp @@ -18,10 +18,12 @@ #ifndef WX_PRECOMP #include "wx/app.h" + #include "wx/frame.h" #include "wx/window.h" #endif // WX_PRECOMP #include "wx/scopedptr.h" +#include "wx/stopwatch.h" #include "asserthelper.h" @@ -45,6 +47,29 @@ protected: virtual wxSize DoGetBestSize() const wxOVERRIDE { return wxSize(50, 250); } }; +// Class used to check if we received the (first) paint event. +class WaitForPaint +{ +public: + // Note that we have to use a pointer here, i.e. we can't just store the + // flag inside the class itself because it's going to be cloned inside wx + // and querying the flag of the original copy is not going to work. + explicit WaitForPaint(bool* painted) + : m_painted(*painted) + { + m_painted = false; + } + + void operator()(wxPaintEvent& event) + { + event.Skip(); + m_painted = true; + } + +private: + bool& m_painted; +}; + } // anonymous namespace // ---------------------------------------------------------------------------- @@ -84,3 +109,38 @@ TEST_CASE("wxWindow::GetBestSize", "[window][size][best-size]") w->SetMaxSize(wxSize(200, 200)); CHECK( wxSize(100, 200) == w->GetBestSize() ); } + +TEST_CASE("wxWindow::MovePreservesSize", "[window][size][move]") +{ + wxScopedPtr + w(new wxFrame(wxTheApp->GetTopWindow(), wxID_ANY, "Test child frame")); + + // Unfortunately showing the window is asynchronous, at least when using + // X11, so we have to wait for some time before retrieving its true + // geometry. And it's not clear how long should we wait, so we do it until + // we get the first paint event -- by then the window really should have + // its final size. + bool painted; + WaitForPaint waitForPaint(&painted); + w->Bind(wxEVT_PAINT, waitForPaint); + + w->Show(); + + wxStopWatch sw; + while ( !painted ) + { + wxYield(); + + if ( sw.Time() > 250 ) + { + WARN("Didn't get a paint event until timeout expiration"); + break; + } + } + + const wxRect rectOrig = w->GetRect(); + + // Check that moving the window doesn't change its size. + w->Move(rectOrig.GetPosition() + wxPoint(100, 100)); + CHECK( w->GetSize() == rectOrig.GetSize() ); +} From 35de675830afffad3d73654c2053232d812d0ec0 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 22 Sep 2019 00:55:31 +0200 Subject: [PATCH 12/38] Extract waiting for the first paint event in a reusable function No real changes, this is just a refactoring to allow reusing the same loop waiting until we can get the real window geometry in other tests. This commit is best viewed with --color-moved. --- tests/window/setsize.cpp | 51 +++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/tests/window/setsize.cpp b/tests/window/setsize.cpp index 37a10842c4..81b3eeb8d5 100644 --- a/tests/window/setsize.cpp +++ b/tests/window/setsize.cpp @@ -70,6 +70,34 @@ private: bool& m_painted; }; +// This function should be used to show the window and wait until we can get +// its real geometry. +void ShowAndWaitForPaint(wxWindow* w) +{ + // Unfortunately showing the window is asynchronous, at least when using + // X11, so we have to wait for some time before retrieving its true + // geometry. And it's not clear how long should we wait, so we do it until + // we get the first paint event -- by then the window really should have + // its final size. + bool painted; + WaitForPaint waitForPaint(&painted); + w->Bind(wxEVT_PAINT, waitForPaint); + + w->Show(); + + wxStopWatch sw; + while ( !painted ) + { + wxYield(); + + if ( sw.Time() > 250 ) + { + WARN("Didn't get a paint event until timeout expiration"); + break; + } + } +} + } // anonymous namespace // ---------------------------------------------------------------------------- @@ -115,28 +143,7 @@ TEST_CASE("wxWindow::MovePreservesSize", "[window][size][move]") wxScopedPtr w(new wxFrame(wxTheApp->GetTopWindow(), wxID_ANY, "Test child frame")); - // Unfortunately showing the window is asynchronous, at least when using - // X11, so we have to wait for some time before retrieving its true - // geometry. And it's not clear how long should we wait, so we do it until - // we get the first paint event -- by then the window really should have - // its final size. - bool painted; - WaitForPaint waitForPaint(&painted); - w->Bind(wxEVT_PAINT, waitForPaint); - - w->Show(); - - wxStopWatch sw; - while ( !painted ) - { - wxYield(); - - if ( sw.Time() > 250 ) - { - WARN("Didn't get a paint event until timeout expiration"); - break; - } - } + ShowAndWaitForPaint(w.get()); const wxRect rectOrig = w->GetRect(); From 71ad73fdbe2755188a7f0916db3aa1ca05f24b74 Mon Sep 17 00:00:00 2001 From: Matthew Griffin <45285214+matthew-griffin@users.noreply.github.com> Date: Wed, 12 Jun 2019 15:04:48 +0100 Subject: [PATCH 13/38] Fix wrong position in wxMouseEvent generated by sub-window Use screen coordinates, as the window coordinates in QMouseEvent may be relative to a different window. Closes https://github.com/wxWidgets/wxWidgets/pull/1351 --- src/qt/window.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/qt/window.cpp b/src/qt/window.cpp index 93d72d8ff8..2eb51fee4b 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -1456,11 +1456,15 @@ bool wxWindowQt::QtHandleMouseEvent ( QWidget *handler, QMouseEvent *event ) } // Fill the event - QPoint mousePos = event->pos(); + + // Use screen position as the event might originate from a different + // Qt window than this one. + wxPoint mousePos = ScreenToClient(wxQtConvertPoint(event->globalPos())); + wxMouseEvent e( wxType ); e.SetEventObject(this); e.m_clickCount = -1; - e.SetPosition( wxQtConvertPoint( mousePos ) ); + e.SetPosition(mousePos); // Mouse buttons wxQtFillMouseButtons( event->buttons(), &e ); @@ -1472,8 +1476,8 @@ bool wxWindowQt::QtHandleMouseEvent ( QWidget *handler, QMouseEvent *event ) // Determine if mouse is inside the widget bool mouseInside = true; - if ( mousePos.x() < 0 || mousePos.x() > handler->width() || - mousePos.y() < 0 || mousePos.y() > handler->height() ) + if ( mousePos.x < 0 || mousePos.x > handler->width() || + mousePos.y < 0 || mousePos.y > handler->height() ) mouseInside = false; if ( e.GetEventType() == wxEVT_MOTION ) From 0c7f261c4af7392c5f103d1451e9d4e94c447ad3 Mon Sep 17 00:00:00 2001 From: Matthew Griffin <45285214+matthew-griffin@users.noreply.github.com> Date: Wed, 12 Jun 2019 15:48:14 +0100 Subject: [PATCH 14/38] Fix position for wxContextMenuEvent generated from keyboard The position was wrong for the keyboard-triggered menu events in wxWindows containing multiple sub-windows, such as wxListCtrl. Closes https://github.com/wxWidgets/wxWidgets/pull/1352 --- src/qt/window.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/window.cpp b/src/qt/window.cpp index 2eb51fee4b..cabf652879 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -1568,7 +1568,11 @@ bool wxWindowQt::QtHandleCloseEvent ( QWidget *handler, QCloseEvent *WXUNUSED( e bool wxWindowQt::QtHandleContextMenuEvent ( QWidget *WXUNUSED( handler ), QContextMenuEvent *event ) { wxContextMenuEvent e( wxEVT_CONTEXT_MENU, GetId() ); - e.SetPosition( wxQtConvertPoint( event->globalPos() ) ); + e.SetPosition( + event->reason() == QContextMenuEvent::Keyboard + ? wxDefaultPosition + : wxQtConvertPoint( event->globalPos() ) + ); e.SetEventObject(this); return ProcessWindowEvent( e ); From 9a64acbb79fffa1e51c7845d0ea3e05735916837 Mon Sep 17 00:00:00 2001 From: Mick Waites Date: Tue, 18 Jun 2019 10:51:25 +0100 Subject: [PATCH 15/38] Ensure correct previous page is sent for notebook events Qt notebook page changed events had the wrong "previous page" index in circumstances where the page has been changed by methods other than clicking on the tabs, for example using the "Pages->Next page" menu option in the notebook sample. Closes https://github.com/wxWidgets/wxWidgets/pull/1359 --- src/qt/notebook.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/notebook.cpp b/src/qt/notebook.cpp index 0f4c2ae062..ade55ec5f1 100644 --- a/src/qt/notebook.cpp +++ b/src/qt/notebook.cpp @@ -192,8 +192,8 @@ int wxNotebook::SetSelection(size_t page) int selOld = GetSelection(); // change the QTabWidget selected page: - m_selection = page; m_qtTabWidget->setCurrentIndex( page ); + m_selection = page; return selOld; } From fcd6ee532432eed24a8c3904bad0c6c9c37dbf05 Mon Sep 17 00:00:00 2001 From: Jay Nabonne Date: Thu, 20 Jun 2019 12:02:12 +0100 Subject: [PATCH 16/38] Disable Qt's automatic "auto default" state for buttons Let the wx layer handle default-ness, as the auto behaviour has unhappy consequences that can't be controlled via the wx API. (For example, a Delete button being considered default simply because it's the first button in the dialog.) Closes https://github.com/wxWidgets/wxWidgets/pull/1366 --- src/qt/anybutton.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qt/anybutton.cpp b/src/qt/anybutton.cpp index 1bf235bd46..5c6f880c6b 100644 --- a/src/qt/anybutton.cpp +++ b/src/qt/anybutton.cpp @@ -85,8 +85,9 @@ wxAnyButton::wxAnyButton() : void wxAnyButton::QtCreate(wxWindow *parent) { - // create the default push button (used in button and bmp button) - m_qtPushButton = new wxQtPushButton( parent, this ); + // create the basic push button (used in button and bmp button) + m_qtPushButton = new wxQtPushButton(parent, this); + m_qtPushButton->setAutoDefault(false); } void wxAnyButton::QtSetBitmap( const wxBitmap &bitmap ) From 9434a443f583ee559257504f72e70bac25d9c3fc Mon Sep 17 00:00:00 2001 From: Matthew Griffin <45285214+matthew-griffin@users.noreply.github.com> Date: Fri, 28 Jun 2019 09:40:11 +0100 Subject: [PATCH 17/38] Ensure that QCloseEvents can be vetoed by wx These events use a different convention from all the other ones in Qt and need to be ignored, rather than accepted, to prevent the default action from occurring. And these events are also sent to disabled windows, which are never supposed to receive them in wx API. Closes https://github.com/wxWidgets/wxWidgets/pull/1371 --- include/wx/qt/private/winevent.h | 2 +- src/qt/window.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/wx/qt/private/winevent.h b/include/wx/qt/private/winevent.h index 5137f6d00e..f29b329e67 100644 --- a/include/wx/qt/private/winevent.h +++ b/include/wx/qt/private/winevent.h @@ -104,7 +104,7 @@ protected: if ( !this->GetHandler()->QtHandleCloseEvent(this, event) ) Widget::closeEvent(event); else - event->accept(); + event->ignore(); } //wxContextMenuEvent diff --git a/src/qt/window.cpp b/src/qt/window.cpp index cabf652879..c67e9606ea 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -1557,12 +1557,17 @@ bool wxWindowQt::QtHandleChangeEvent ( QWidget *handler, QEvent *event ) return false; } +// Returns true if the closing should be vetoed and false if the window should be closed. bool wxWindowQt::QtHandleCloseEvent ( QWidget *handler, QCloseEvent *WXUNUSED( event ) ) { if ( GetHandle() != handler ) return false; - return Close(); + // This is required as Qt will still send out close events when the window is disabled. + if ( !IsEnabled() ) + return true; + + return !Close(); } bool wxWindowQt::QtHandleContextMenuEvent ( QWidget *WXUNUSED( handler ), QContextMenuEvent *event ) From 273448fb8068deb4558cdd5683abaa9bd970a213 Mon Sep 17 00:00:00 2001 From: Matthew Griffin <45285214+matthew-griffin@users.noreply.github.com> Date: Mon, 8 Jul 2019 16:53:55 +0100 Subject: [PATCH 18/38] Fix Qt implementation of wxTreeCtrl::Toggle() It was mistakenly implemented as toggling selected item, not whether item is collapsed or expanded. Closes https://github.com/wxWidgets/wxWidgets/pull/1395 --- src/qt/treectrl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/treectrl.cpp b/src/qt/treectrl.cpp index 89325fba02..13feb0bf75 100644 --- a/src/qt/treectrl.cpp +++ b/src/qt/treectrl.cpp @@ -1158,7 +1158,7 @@ void wxTreeCtrl::Toggle(const wxTreeItemId& item) wxCHECK_RET(item.IsOk(), "invalid tree item"); QTreeWidgetItem *qTreeItem = wxQtConvertTreeItem(item); - qTreeItem->setSelected(!qTreeItem->isSelected()); + qTreeItem->setExpanded(!qTreeItem->isExpanded()); } void wxTreeCtrl::Unselect() From cc1ec9e56201a84b5c7bb299b19d5e825c9aca3f Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Tue, 9 Jul 2019 14:14:40 +0100 Subject: [PATCH 19/38] Show tooltip in wxTreeCtrl when item text doesn't fit on screen This matches the behaviour of the native control in wxMSW and is generally useful. Closes https://github.com/wxWidgets/wxWidgets/pull/1397 --- include/wx/qt/private/treeitemdelegate.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/wx/qt/private/treeitemdelegate.h b/include/wx/qt/private/treeitemdelegate.h index 65025de442..632172f6ec 100644 --- a/include/wx/qt/private/treeitemdelegate.h +++ b/include/wx/qt/private/treeitemdelegate.h @@ -11,6 +11,7 @@ #define _WX_QT_PRIVATE_TREEITEM_DELEGATE_H #include +#include #include "wx/app.h" #include "wx/textctrl.h" @@ -67,6 +68,28 @@ public: QStyledItemDelegate::setModelData(editor, model, index); } + bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index) + { + if ( event->type() == QEvent::ToolTip ) + { + const QRect &itemRect = view->visualRect(index); + const QSize &bestSize = sizeHint(option, index); + if ( itemRect.width() < bestSize.width() ) + { + const QString &value = index.data(Qt::DisplayRole).toString(); + QToolTip::showText(event->globalPos(), value, view); + } + else + { + QToolTip::hideText(); + } + + return true; + } + + return QStyledItemDelegate::helpEvent(event, view, option, index); + } + private: wxWindow* m_parent; mutable wxTextCtrl* m_textCtrl; From 18b87b2ab55574ffafd2d441cf78f30c0383a245 Mon Sep 17 00:00:00 2001 From: David Roberts Date: Wed, 10 Jul 2019 16:23:32 +0100 Subject: [PATCH 20/38] Send wxEVT_CHECKLISTBOX when a checkbox is clicked Fix sending events from wxCheckListBox in wxQt. Closes https://github.com/wxWidgets/wxWidgets/pull/1403 --- include/wx/qt/listbox.h | 2 +- src/qt/listbox.cpp | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/wx/qt/listbox.h b/include/wx/qt/listbox.h index 9ebaf91a66..3108bb62f8 100644 --- a/include/wx/qt/listbox.h +++ b/include/wx/qt/listbox.h @@ -60,7 +60,7 @@ public: virtual QWidget *GetHandle() const wxOVERRIDE; - void QtSendEvent(wxEventType evtType, const QModelIndex &index, bool selected); + void QtSendEvent(wxEventType evtType, int rowIndex, bool selected); protected: virtual void DoSetFirstItem(int n) wxOVERRIDE; diff --git a/src/qt/listbox.cpp b/src/qt/listbox.cpp index 0e395c4744..a704c60f0f 100644 --- a/src/qt/listbox.cpp +++ b/src/qt/listbox.cpp @@ -21,6 +21,7 @@ public: private: void clicked( const QModelIndex &index ); void doubleClicked( const QModelIndex &index ); + void itemChanged(QListWidgetItem *item); }; wxQtListWidget::wxQtListWidget( wxWindow *parent, wxListBox *handler ) @@ -28,22 +29,35 @@ wxQtListWidget::wxQtListWidget( wxWindow *parent, wxListBox *handler ) { connect(this, &QListWidget::clicked, this, &wxQtListWidget::clicked); connect(this, &QListWidget::doubleClicked, this, &wxQtListWidget::doubleClicked); + connect(this, &QListWidget::itemChanged, this, &wxQtListWidget::itemChanged); } void wxQtListWidget::clicked(const QModelIndex &index ) { wxListBox *handler = GetHandler(); if ( handler ) - handler->QtSendEvent(wxEVT_LISTBOX, index, true); + handler->QtSendEvent(wxEVT_LISTBOX, index.row(), true); } void wxQtListWidget::doubleClicked( const QModelIndex &index ) { wxListBox *handler = GetHandler(); if ( handler ) - handler->QtSendEvent(wxEVT_LISTBOX_DCLICK, index, true); + handler->QtSendEvent(wxEVT_LISTBOX_DCLICK, index.row(), true); } +void wxQtListWidget::itemChanged(QListWidgetItem *item) +{ + if ( item->flags() & Qt::ItemIsUserCheckable ) + { + wxListBox *handler = GetHandler(); + if ( handler ) + { + int rowIndex = this->row(item); + handler->QtSendEvent(wxEVT_CHECKLISTBOX, rowIndex, true); + } + } +} wxListBox::wxListBox() : m_qtListWidget(NULL) @@ -282,9 +296,9 @@ QWidget *wxListBox::GetHandle() const return m_qtListWidget; } -void wxListBox::QtSendEvent(wxEventType evtType, const QModelIndex &index, bool selected) +void wxListBox::QtSendEvent(wxEventType evtType, int rowIndex, bool selected) { - SendEvent(evtType, index.row(), selected); + SendEvent(evtType, rowIndex, selected); } QScrollArea *wxListBox::QtGetScrollBarsContainer() const From cd7594e639ab8b69e2d89ace3ff755b132e59122 Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Mon, 15 Jul 2019 16:34:49 +0100 Subject: [PATCH 21/38] Don't include scrollbars in client area size Return the size of just the viewport when using QScrollArea. Closes https://github.com/wxWidgets/wxWidgets/pull/1418 --- include/wx/qt/window.h | 5 +++++ src/qt/window.cpp | 22 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/wx/qt/window.h b/include/wx/qt/window.h index ace2a71711..77eca2de6f 100644 --- a/include/wx/qt/window.h +++ b/include/wx/qt/window.h @@ -230,6 +230,11 @@ private: QScrollBar *m_horzScrollBar; // owned by m_qtWindow when allocated QScrollBar *m_vertScrollBar; // owned by m_qtWindow when allocated + // Return the viewport of m_qtContainer, if it's used, or just m_qtWindow. + // + // Always returns non-null pointer if the window has been already created. + QWidget *QtGetClientWidget() const; + QScrollBar *QtGetScrollBar( int orientation ) const; QScrollBar *QtSetScrollBar( int orientation, QScrollBar *scrollBar=NULL ); diff --git a/src/qt/window.cpp b/src/qt/window.cpp index c67e9606ea..21d9b6f1ab 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -582,6 +582,23 @@ void wxWindowQt::DoGetTextExtent(const wxString& string, int *x, int *y, int *de *externalLeading = fontMetrics.lineSpacing(); } +QWidget *wxWindowQt::QtGetClientWidget() const +{ + QWidget *qtWidget = NULL; + if ( m_qtContainer != NULL ) + { + qtWidget = m_qtContainer->viewport(); + } + + if ( qtWidget == NULL ) + { + // We don't have scrollbars or the QScrollArea has no children + qtWidget = GetHandle(); + } + + return qtWidget; +} + /* Returns a scrollbar for the given orientation, or NULL if the scrollbar * has not been previously created and create is false */ QScrollBar *wxWindowQt::QtGetScrollBar( int orientation ) const @@ -957,7 +974,8 @@ void wxWindowQt::DoSetSize(int x, int y, int width, int height, int sizeFlags ) void wxWindowQt::DoGetClientSize(int *width, int *height) const { - QRect geometry = GetHandle()->geometry(); + QWidget *qtWidget = QtGetClientWidget(); + const QRect geometry = qtWidget->geometry(); if (width) *width = geometry.width(); if (height) *height = geometry.height(); } @@ -965,7 +983,7 @@ void wxWindowQt::DoGetClientSize(int *width, int *height) const void wxWindowQt::DoSetClientSize(int width, int height) { - QWidget *qtWidget = GetHandle(); + QWidget *qtWidget = QtGetClientWidget(); QRect geometry = qtWidget->geometry(); geometry.setWidth( width ); geometry.setHeight( height ); From 54c1359d1fc1d55a7cd55e745ab5a993e42ad6f2 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 22 Sep 2019 02:38:59 +0200 Subject: [PATCH 22/38] Add precondition checks to Do{Get,Set}ClientSize() Don't crash if these methods are called before the window is created. --- src/qt/window.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/window.cpp b/src/qt/window.cpp index 21d9b6f1ab..2530a016cf 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -975,6 +975,8 @@ void wxWindowQt::DoSetSize(int x, int y, int width, int height, int sizeFlags ) void wxWindowQt::DoGetClientSize(int *width, int *height) const { QWidget *qtWidget = QtGetClientWidget(); + wxCHECK_RET( qtWidget, "window must be created" ); + const QRect geometry = qtWidget->geometry(); if (width) *width = geometry.width(); if (height) *height = geometry.height(); @@ -984,6 +986,8 @@ void wxWindowQt::DoGetClientSize(int *width, int *height) const void wxWindowQt::DoSetClientSize(int width, int height) { QWidget *qtWidget = QtGetClientWidget(); + wxCHECK_RET( qtWidget, "window must be created" ); + QRect geometry = qtWidget->geometry(); geometry.setWidth( width ); geometry.setHeight( height ); From c8eef72417f3f17479bf010ae59b6f61897f8e7b Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Tue, 16 Jul 2019 08:15:47 +0100 Subject: [PATCH 23/38] Fix wxNotebook::CalcSizeFromPage() to account for tabs height Actually implement this function instead of just returning the size passed into it. Closes https://github.com/wxWidgets/wxWidgets/pull/1425 --- src/qt/notebook.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/notebook.cpp b/src/qt/notebook.cpp index ade55ec5f1..06c5439436 100644 --- a/src/qt/notebook.cpp +++ b/src/qt/notebook.cpp @@ -14,6 +14,7 @@ #include "wx/qt/private/winevent.h" #include +#include class wxQtTabWidget : public wxQtEventSignalHandler< QTabWidget, wxNotebook > { @@ -162,7 +163,10 @@ bool wxNotebook::InsertPage(size_t n, wxWindow *page, const wxString& text, wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const { - return sizePage; + QTabBar *tabBar = m_qtTabWidget->tabBar(); + const QSize &tabBarSize = tabBar->size(); + return wxSize(sizePage.GetWidth(), + sizePage.GetHeight() + tabBarSize.height()); } bool wxNotebook::DeleteAllPages() From 39cb3370080e70533d4c4aa2cb63137c46eca80c Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Tue, 30 Jul 2019 16:20:00 +0100 Subject: [PATCH 24/38] Generate events when selecting tree items programmatically In wx API, calling wxTreeCtrl::SelectItem() is supposed to generate an event. Also use Qt selection model to support single-selection mode. Closes https://github.com/wxWidgets/wxWidgets/pull/1453 --- src/qt/treectrl.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/qt/treectrl.cpp b/src/qt/treectrl.cpp index 13feb0bf75..6b1676f724 100644 --- a/src/qt/treectrl.cpp +++ b/src/qt/treectrl.cpp @@ -244,6 +244,12 @@ public: return m_placeHolderImage; } + void select(QTreeWidgetItem* item, QItemSelectionModel::SelectionFlag selectionFlag) + { + const QModelIndex &index = indexFromItem(item); + selectionModel()->select(index, selectionFlag); + } + protected: virtual void drawRow( QPainter *painter, @@ -1164,19 +1170,13 @@ void wxTreeCtrl::Toggle(const wxTreeItemId& item) void wxTreeCtrl::Unselect() { QTreeWidgetItem *current = m_qtTreeWidget->currentItem(); - if ( current != NULL ) - current->setSelected(false); + m_qtTreeWidget->select(current, QItemSelectionModel::Deselect); } void wxTreeCtrl::UnselectAll() { - QList selections = m_qtTreeWidget->selectedItems(); - const size_t selectedCount = selections.size(); - for ( size_t i = 0; i < selectedCount; ++i) - { - selections[i]->setSelected(false); - } + m_qtTreeWidget->selectionModel()->clearSelection(); } void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select) @@ -1189,7 +1189,15 @@ void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select) } QTreeWidgetItem *qTreeItem = wxQtConvertTreeItem(item); - qTreeItem->setSelected(select); + + if ( qTreeItem ) + { + m_qtTreeWidget->select(qTreeItem, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect); + if ( select && m_qtTreeWidget->selectionMode() == QTreeWidget::SingleSelection ) + { + m_qtTreeWidget->setCurrentItem(qTreeItem); + } + } } void wxTreeCtrl::SelectChildren(const wxTreeItemId& parent) @@ -1201,7 +1209,7 @@ void wxTreeCtrl::SelectChildren(const wxTreeItemId& parent) for ( int i = 0; i < childCount; ++i ) { - qTreeItem->child(i)->setSelected(true); + m_qtTreeWidget->select(qTreeItem->child(i), QItemSelectionModel::Select); } } From 8c18ee8c25f5f63a15be0c4f1d8ef6143b533f1d Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Wed, 28 Aug 2019 16:09:06 +0100 Subject: [PATCH 25/38] Apply font family for wxFont in wxQt Closes https://github.com/wxWidgets/wxWidgets/pull/1512 --- src/qt/font.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/font.cpp b/src/qt/font.cpp index f9e5b1fd9b..6cfebf895e 100644 --- a/src/qt/font.cpp +++ b/src/qt/font.cpp @@ -563,7 +563,7 @@ void wxNativeFontInfo::SetFamily(wxFontFamily family) { m_qtFont.setStyleHint(ConvertFontFamily(family)); // reset the face name to force qt to choose a new font - m_qtFont.setFamily(""); + m_qtFont.setFamily(m_qtFont.defaultFamily()); } void wxNativeFontInfo::SetEncoding(wxFontEncoding WXUNUSED(encoding)) From 337644f7024391b10e97837478e938178c2e2f77 Mon Sep 17 00:00:00 2001 From: Matthew Griffin <45285214+matthew-griffin@users.noreply.github.com> Date: Mon, 2 Sep 2019 09:24:50 +0100 Subject: [PATCH 26/38] Cancel any edit in progress when wxTreeCtrl is scrolled Otherwise the editor could be scrolled out of view, confusing the user. Closes https://github.com/wxWidgets/wxWidgets/pull/1522 --- src/qt/treectrl.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qt/treectrl.cpp b/src/qt/treectrl.cpp index 6b1676f724..84213cec7f 100644 --- a/src/qt/treectrl.cpp +++ b/src/qt/treectrl.cpp @@ -23,6 +23,7 @@ #include #include +#include #include namespace @@ -142,6 +143,8 @@ public: this, &wxQTreeWidget::OnItemCollapsed); connect(this, &QTreeWidget::itemExpanded, this, &wxQTreeWidget::OnItemExpanded); + connect(verticalScrollBar(), &QScrollBar::valueChanged, + this, &wxQTreeWidget::OnTreeScrolled); setItemDelegate(&m_item_delegate); setDragEnabled(true); @@ -438,6 +441,12 @@ private: EmitEvent(expandedEvent); } + void OnTreeScrolled(int) + { + if ( GetEditControl() != NULL ) + closeEditor(GetEditControl()->GetHandle(), QAbstractItemDelegate::RevertModelCache); + } + void tryStartDrag(const QMouseEvent *event) { wxEventType command = event->buttons() & Qt::RightButton From cd9a8fb695ad068c8df155d4c5c9ad061c5b2a08 Mon Sep 17 00:00:00 2001 From: Jay Nabonne Date: Mon, 2 Sep 2019 10:59:06 +0100 Subject: [PATCH 27/38] Do not switch state if drag-and-drop is not allowed in wxTreeCtrl Avoid setting state to DragSelectingState unless dragging items in wxTreeCtrl is explicitly allowed, as this this causes bad behaviour downstream with subsequent selections when the client does anything in the event handler beyond simply not allowing the event. Basically, we can't be guaranteed of the mouse state on return from the event handler, so dropping into drag selection mode is potentially inappropriate (or just plain bad). Closes https://github.com/wxWidgets/wxWidgets/pull/1523 --- src/qt/treectrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/treectrl.cpp b/src/qt/treectrl.cpp index 84213cec7f..ef478911bb 100644 --- a/src/qt/treectrl.cpp +++ b/src/qt/treectrl.cpp @@ -463,14 +463,14 @@ private: tree_event.SetPoint(wxQtConvertPoint(event->pos())); - // Vetoed unless explicitly accepted. + // Client must explicitly accept drag and drop. Vetoed by default. tree_event.Veto(); EmitEvent(tree_event); if ( !tree_event.IsAllowed() ) { - setState(DragSelectingState); + setState(NoState); } } From 1214676988989a8fe501aac11978f2bd0da26945 Mon Sep 17 00:00:00 2001 From: Mick Waites Date: Mon, 2 Sep 2019 11:18:44 +0100 Subject: [PATCH 28/38] Set default page size for wxSlider as in the other ports Make the page size 1/10 of the total range, as in wxMSW. Closes https://github.com/wxWidgets/wxWidgets/pull/1524 --- src/qt/slider.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/slider.cpp b/src/qt/slider.cpp index 1b8e1f96a7..a97f78db60 100644 --- a/src/qt/slider.cpp +++ b/src/qt/slider.cpp @@ -80,6 +80,7 @@ bool wxSlider::Create(wxWindow *parent, m_qtSlider->blockSignals(true); SetRange( minValue, maxValue ); m_qtSlider->blockSignals(false); + SetPageSize(wxMax(1, (maxValue - minValue) / 10)); #if 0 // there are not normally ticks for a wxSlider // draw ticks marks (default bellow if horizontal, right if vertical): From 631ce0e380d8222bcf9712fdaf7f622e6b38b485 Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Mon, 2 Sep 2019 15:35:31 +0100 Subject: [PATCH 29/38] Send events when items are selected from keyboard in wxListBox Handle selection rather than clicks in wxListBox in wxQt to allow keyboard interactions to generate events. Closes https://github.com/wxWidgets/wxWidgets/pull/1526 --- src/qt/listbox.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/qt/listbox.cpp b/src/qt/listbox.cpp index a704c60f0f..1408f6f9d2 100644 --- a/src/qt/listbox.cpp +++ b/src/qt/listbox.cpp @@ -19,7 +19,7 @@ public: wxQtListWidget( wxWindow *parent, wxListBox *handler ); private: - void clicked( const QModelIndex &index ); + void OnCurrentItemChange(QListWidgetItem *current, QListWidgetItem *previous); void doubleClicked( const QModelIndex &index ); void itemChanged(QListWidgetItem *item); }; @@ -27,16 +27,22 @@ private: wxQtListWidget::wxQtListWidget( wxWindow *parent, wxListBox *handler ) : wxQtEventSignalHandler< QListWidget, wxListBox >( parent, handler ) { - connect(this, &QListWidget::clicked, this, &wxQtListWidget::clicked); + connect(this, &QListWidget::currentItemChanged, this, &wxQtListWidget::OnCurrentItemChange); connect(this, &QListWidget::doubleClicked, this, &wxQtListWidget::doubleClicked); connect(this, &QListWidget::itemChanged, this, &wxQtListWidget::itemChanged); } -void wxQtListWidget::clicked(const QModelIndex &index ) +void wxQtListWidget::OnCurrentItemChange(QListWidgetItem *current, QListWidgetItem *) { + if ( !current ) + return; + wxListBox *handler = GetHandler(); if ( handler ) + { + const QModelIndex &index = indexFromItem(current); handler->QtSendEvent(wxEVT_LISTBOX, index.row(), true); + } } void wxQtListWidget::doubleClicked( const QModelIndex &index ) From 2c91463c81fef4ffa72c5490a680e072fe627272 Mon Sep 17 00:00:00 2001 From: Matthew Griffin <45285214+matthew-griffin@users.noreply.github.com> Date: Fri, 13 Sep 2019 13:17:27 +0100 Subject: [PATCH 30/38] Enable mouse tracking on construction of every wxQt widget Not all controls use wxWindow::Create(), so move setMouseTracking() call where it is always executed. Closes https://github.com/wxWidgets/wxWidgets/pull/1528 --- include/wx/qt/private/winevent.h | 1 + src/qt/window.cpp | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/wx/qt/private/winevent.h b/include/wx/qt/private/winevent.h index f29b329e67..87623cf605 100644 --- a/include/wx/qt/private/winevent.h +++ b/include/wx/qt/private/winevent.h @@ -61,6 +61,7 @@ public: QObject::connect( this, &QObject::destroyed, this, &wxQtEventSignalHandler::HandleDestroyedSignal ); + Widget::setMouseTracking(true); } void HandleDestroyedSignal() diff --git a/src/qt/window.cpp b/src/qt/window.cpp index 2530a016cf..84e8e0ace1 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -319,8 +319,6 @@ bool wxWindowQt::Create( wxWindowQt * parent, wxWindowID id, const wxPoint & pos m_qtWindow = new wxQtWidget( parent, this ); } - - GetHandle()->setMouseTracking(true); if ( !wxWindowBase::CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) return false; From 3668ff51702ce15cd5f942143c3eca15bb15ffdc Mon Sep 17 00:00:00 2001 From: Graham Dawes Date: Thu, 5 Sep 2019 15:51:23 +0100 Subject: [PATCH 31/38] Update menu UI before showing a popup menu in wxQt Give the application code a possibility to disable or otherwise change the menu items before the popup menu is shown, as in the other ports. Closes https://github.com/wxWidgets/wxWidgets/pull/1532 --- src/qt/window.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt/window.cpp b/src/qt/window.cpp index 84e8e0ace1..1f5b35743d 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -1035,9 +1035,10 @@ void wxWindowQt::DoSetToolTip( wxToolTip *tip ) #if wxUSE_MENUS bool wxWindowQt::DoPopupMenu(wxMenu *menu, int x, int y) { + menu->UpdateUI(); menu->GetHandle()->exec( GetHandle()->mapToGlobal( QPoint( x, y ) ) ); - return ( true ); + return true; } #endif // wxUSE_MENUS From 8c2b9423c228e1c07639f00ba2ddd100796b981c Mon Sep 17 00:00:00 2001 From: catalinr Date: Fri, 6 Sep 2019 00:13:43 +0300 Subject: [PATCH 32/38] Fix compilation by using appropriate subdirs for Qt headers This fixes wxQt build under MSW. Closes https://github.com/wxWidgets/wxWidgets/pull/1533 --- src/qt/dnd.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qt/dnd.cpp b/src/qt/dnd.cpp index ed8ca9e898..b7655f56d5 100644 --- a/src/qt/dnd.cpp +++ b/src/qt/dnd.cpp @@ -16,10 +16,10 @@ #include "wx/qt/private/converter.h" -#include -#include -#include -#include +#include +#include +#include +#include namespace { From a6efd027da029359693cf19730013f0a3e272782 Mon Sep 17 00:00:00 2001 From: Liam Treacy Date: Tue, 10 Sep 2019 13:42:29 +0100 Subject: [PATCH 33/38] Support accelerator keys in wxMenuItem::SetItemLabel() Closes https://github.com/wxWidgets/wxWidgets/pull/1544 --- src/qt/menuitem.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/qt/menuitem.cpp b/src/qt/menuitem.cpp index 1889702327..f554294a7d 100644 --- a/src/qt/menuitem.cpp +++ b/src/qt/menuitem.cpp @@ -51,6 +51,20 @@ void wxMenuItem::SetItemLabel( const wxString &label ) { wxMenuItemBase::SetItemLabel( label ); +#if wxUSE_ACCEL + QString qlabel = wxQtConvertString( label ); + int index = qlabel.lastIndexOf( QChar( '\t' ) ); + + if ( index != -1 ) + { + QList shortcuts = m_qtAction->shortcuts(); + QString shortcut_key = qlabel.remove( 0, index+1 ); + + shortcuts.append( QKeySequence( shortcut_key ) ); + m_qtAction->setShortcuts( shortcuts ); + } +#endif // wxUSE_ACCEL + m_qtAction->setText( wxQtConvertString( label )); } From 3a918864f9bccf107e6390d7c2a37fa5c2db755d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 27 Sep 2019 13:44:55 +0200 Subject: [PATCH 34/38] Make accelerators work for menu items created in the code too The previous commit fixed accelerators support in wxQt for the items created in XRC, but not for those created directly in the code, as wxMenuItem::SetItemLabel() is not called in this case. Refactor the code to extract UpdateShortcutsFromLabel() from SetItemLabel() and call the new function both from there and from wxMenuItem ctor, to ensure that the accelerators are taken into account in any case. This commit is best viewed with "git diff --color-moved". See https://github.com/wxWidgets/wxWidgets/pull/1544 --- include/wx/qt/menuitem.h | 3 ++- src/qt/menuitem.cpp | 36 +++++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/include/wx/qt/menuitem.h b/include/wx/qt/menuitem.h index c91a16a4e1..24e5e27003 100644 --- a/include/wx/qt/menuitem.h +++ b/include/wx/qt/menuitem.h @@ -12,6 +12,7 @@ #include "wx/bitmap.h" class QAction; +class wxQtAction; class WXDLLIMPEXP_FWD_CORE wxMenu; @@ -41,7 +42,7 @@ public: private: // Qt is using an action instead of a menu item. - QAction *m_qtAction; + wxQtAction *m_qtAction; wxBitmap m_bitmap; wxDECLARE_DYNAMIC_CLASS( wxMenuItem ); diff --git a/src/qt/menuitem.cpp b/src/qt/menuitem.cpp index f554294a7d..9471909fa1 100644 --- a/src/qt/menuitem.cpp +++ b/src/qt/menuitem.cpp @@ -25,6 +25,10 @@ public: wxQtAction( wxMenu *parent, int id, const wxString &text, const wxString &help, wxItemKind kind, wxMenu *subMenu, wxMenuItem *handler ); + // Set the action shortcut to correspond to the accelerator specified by + // the given label. + void UpdateShortcutsFromLabel(const wxString& text); + private: void onActionTriggered( bool checked ); }; @@ -51,19 +55,7 @@ void wxMenuItem::SetItemLabel( const wxString &label ) { wxMenuItemBase::SetItemLabel( label ); -#if wxUSE_ACCEL - QString qlabel = wxQtConvertString( label ); - int index = qlabel.lastIndexOf( QChar( '\t' ) ); - - if ( index != -1 ) - { - QList shortcuts = m_qtAction->shortcuts(); - QString shortcut_key = qlabel.remove( 0, index+1 ); - - shortcuts.append( QKeySequence( shortcut_key ) ); - m_qtAction->setShortcuts( shortcuts ); - } -#endif // wxUSE_ACCEL + m_qtAction->UpdateShortcutsFromLabel( label ); m_qtAction->setText( wxQtConvertString( label )); } @@ -175,8 +167,26 @@ wxQtAction::wxQtAction( wxMenu *parent, int id, const wxString &text, const wxSt } connect( this, &QAction::triggered, this, &wxQtAction::onActionTriggered ); + + UpdateShortcutsFromLabel( text ); } +void wxQtAction::UpdateShortcutsFromLabel(const wxString& text) +{ +#if wxUSE_ACCEL + QString qlabel = wxQtConvertString( text ); + int index = qlabel.lastIndexOf( QChar( '\t' ) ); + + if ( index != -1 ) + { + QList shortcuts = m_qtAction->shortcuts(); + QString shortcut_key = qlabel.remove( 0, index+1 ); + + shortcuts.append( QKeySequence( shortcut_key ) ); + setShortcuts( shortcuts ); + } +#endif // wxUSE_ACCEL +} void wxQtAction::onActionTriggered( bool checked ) { From 8339f12636946740362cb545bf55e7cbabaa86af Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 27 Sep 2019 13:47:54 +0200 Subject: [PATCH 35/38] Remove old shortcuts when setting new accelerator Setting a new accelerator should replace the old one, not add to it. See https://github.com/wxWidgets/wxWidgets/pull/1544 --- src/qt/menuitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/menuitem.cpp b/src/qt/menuitem.cpp index 9471909fa1..268c8300b4 100644 --- a/src/qt/menuitem.cpp +++ b/src/qt/menuitem.cpp @@ -179,7 +179,7 @@ void wxQtAction::UpdateShortcutsFromLabel(const wxString& text) if ( index != -1 ) { - QList shortcuts = m_qtAction->shortcuts(); + QList shortcuts; QString shortcut_key = qlabel.remove( 0, index+1 ); shortcuts.append( QKeySequence( shortcut_key ) ); From 41caeebd8cef6bf3e50e50e3f9bb6c8ce096af50 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 27 Sep 2019 13:51:01 +0200 Subject: [PATCH 36/38] Use wxString rather than QString methods It's preferable to use code which is simpler to understand to wx developers not necessarily familiar with Qt API and which can also be reused with the other ports if necessary. In this particular case, using wxString::AfterFirst() also results in shorter and more clear code too. See https://github.com/wxWidgets/wxWidgets/pull/1544 --- src/qt/menuitem.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/qt/menuitem.cpp b/src/qt/menuitem.cpp index 268c8300b4..0792230ad7 100644 --- a/src/qt/menuitem.cpp +++ b/src/qt/menuitem.cpp @@ -174,15 +174,11 @@ wxQtAction::wxQtAction( wxMenu *parent, int id, const wxString &text, const wxSt void wxQtAction::UpdateShortcutsFromLabel(const wxString& text) { #if wxUSE_ACCEL - QString qlabel = wxQtConvertString( text ); - int index = qlabel.lastIndexOf( QChar( '\t' ) ); - - if ( index != -1 ) + const wxString accelStr = text.AfterFirst('\t'); + if ( !accelStr.empty() ) { QList shortcuts; - QString shortcut_key = qlabel.remove( 0, index+1 ); - - shortcuts.append( QKeySequence( shortcut_key ) ); + shortcuts.append( QKeySequence( wxQtConvertString(accelStr) ) ); setShortcuts( shortcuts ); } #endif // wxUSE_ACCEL From 99bbc523f76efcb8b94c4725b0c8c9205297af0f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 27 Sep 2019 13:52:42 +0200 Subject: [PATCH 37/38] Use QAction::setShortcut() rather than setShortcuts() This is simpler and we don't need a list of shortcuts here, as we only allow specifying a single one anyhow. See https://github.com/wxWidgets/wxWidgets/pull/1544 --- src/qt/menuitem.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/qt/menuitem.cpp b/src/qt/menuitem.cpp index 0792230ad7..a2f84822d6 100644 --- a/src/qt/menuitem.cpp +++ b/src/qt/menuitem.cpp @@ -177,9 +177,7 @@ void wxQtAction::UpdateShortcutsFromLabel(const wxString& text) const wxString accelStr = text.AfterFirst('\t'); if ( !accelStr.empty() ) { - QList shortcuts; - shortcuts.append( QKeySequence( wxQtConvertString(accelStr) ) ); - setShortcuts( shortcuts ); + setShortcut( QKeySequence( wxQtConvertString(accelStr) ) ); } #endif // wxUSE_ACCEL } From f608b340c2c24795683208b863950cae7e25fa91 Mon Sep 17 00:00:00 2001 From: Matthew Griffin <45285214+matthew-griffin@users.noreply.github.com> Date: Fri, 13 Sep 2019 14:50:19 +0100 Subject: [PATCH 38/38] Send set cursor events whenever there is mouse movement This is required in order to allow application code to change the cursor dynamically. Closes https://github.com/wxWidgets/wxWidgets/pull/1549 --- include/wx/qt/window.h | 1 + src/qt/window.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/wx/qt/window.h b/include/wx/qt/window.h index 77eca2de6f..a4d49516d8 100644 --- a/include/wx/qt/window.h +++ b/include/wx/qt/window.h @@ -168,6 +168,7 @@ public: static void QtStoreWindowPointer( QWidget *widget, const wxWindowQt *window ); static wxWindowQt *QtRetrieveWindowPointer( const QWidget *widget ); + static void QtSendSetCursorEvent(wxWindowQt* win, wxPoint posClient); #if wxUSE_ACCEL virtual void QtHandleShortcut ( int command ); diff --git a/src/qt/window.cpp b/src/qt/window.cpp index 1f5b35743d..7a31b7a928 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -215,6 +215,30 @@ static const char WINDOW_POINTER_PROPERTY_NAME[] = "wxWindowPointer"; return const_cast< wxWindowQt * >( ( variant.value< const wxWindow * >() )); } +/* static */ +void wxWindowQt::QtSendSetCursorEvent(wxWindowQt* win, wxPoint posScreen) +{ + wxWindowQt* w = win; + for ( ;; ) + { + const wxPoint posClient = w->ScreenToClient(posScreen); + wxSetCursorEvent event(posClient.x, posClient.y); + event.SetEventObject(w); + + const bool processedEvtSetCursor = w->ProcessWindowEvent(event); + if ( processedEvtSetCursor && event.HasCursor() ) + { + win->SetCursor(event.GetCursor()); + return; + } + + w = w->GetParent(); + if ( w == NULL ) + break; + } + win->SetCursor(wxCursor(wxCURSOR_ARROW)); +} + static wxWindowQt *s_capturedWindow = NULL; /* static */ wxWindowQt *wxWindowBase::DoFindFocus() @@ -1517,6 +1541,8 @@ bool wxWindowQt::QtHandleMouseEvent ( QWidget *handler, QMouseEvent *event ) ProcessWindowEvent( e ); } + + QtSendSetCursorEvent(this, wxQtConvertPoint( event->globalPos())); } m_mouseInside = mouseInside;