Fix bug with broken AUI sash drag in some layout

Don't end the AUI resize action when the new size can't be computed, as
can happen for a perfectly ordinary layout: it's enough to have a
resizable pane followed in its dock by a fixed one. This is the case for
the panes in the bottom row of the "aui" sample itself, after all panes
are shown using the corresponding "Perspectives" menu item.

This fixes a serious user-visible problem as mouse renamed captured
forever and the application was left with the resize cursor and with
keyboard input going to the capturing window.

Add a unit test checking for this problem: without the fix in this
commit, "stillCaptured" remained true in it.

Closes #27025.

Co-authored-by: Vadim Zeitlin <vadim@wxwidgets.org>
This commit is contained in:
Claude
2026-09-20 19:28:07 +02:00
committed by Vadim Zeitlin
co-authored by Vadim Zeitlin
parent 10c4a5611a
commit 9992152ce3
2 changed files with 43 additions and 7 deletions
-3
View File
@@ -5239,10 +5239,7 @@ bool wxAuiManager::DoEndResizeAction(wxMouseEvent& event)
// prevent division by zero
if (dock_pixels == 0 || total_proportion == 0 || borrow_pane == -1)
{
m_action = actionNone;
return false;
}
// calculate the new proportion of the pane
int new_proportion = (new_pixsize*total_proportion)/dock_pixels;
+43 -4
View File
@@ -83,6 +83,12 @@ public:
}
void ClickWithoutMoving(wxAuiDockUIPart* part)
{
DragBy(part, wxPoint());
}
// Simulate a complete drag of the given sash by the given offset.
void DragBy(wxAuiDockUIPart* part, const wxPoint& offset)
{
const wxPoint pos = part->rect.GetPosition() +
wxPoint(part->rect.GetWidth()/2, part->rect.GetHeight()/2);
@@ -93,13 +99,13 @@ public:
OnLeftDown(down);
wxMouseEvent motion(wxEVT_MOTION);
motion.m_x = pos.x;
motion.m_y = pos.y;
motion.m_x = pos.x + offset.x;
motion.m_y = pos.y + offset.y;
OnMotion(motion);
wxMouseEvent up(wxEVT_LEFT_UP);
up.m_x = pos.x;
up.m_y = pos.y;
up.m_x = pos.x + offset.x;
up.m_y = pos.y + offset.y;
OnLeftUp(up);
}
};
@@ -201,6 +207,39 @@ TEST_CASE_METHOD(AuiManagerTestCase, "wxAuiManager::SizerClick", "[aui]")
CHECK( manager.GetPane(second).dock_proportion == secondProportion );
}
TEST_CASE_METHOD(AuiManagerTestCase, "wxAuiManager::SizerDragReleasesMouse", "[aui]")
{
// Use a dock in which the resizable pane is followed by a fixed one: there
// is then no pane after it to take the space from and DoEndResizeAction()
// gives up -- but this must still not leave the mouse captured once the
// drag is over.
wxWindow* const first = new wxPanel(frame.get());
wxWindow* const second = new wxPanel(frame.get());
wxWindow* const center = new wxPanel(frame.get());
REQUIRE( manager.AddPane(first, wxAuiPaneInfo().Top().
MinSize(200, 100).CaptionVisible(false).PaneBorder(false)) );
REQUIRE( manager.AddPane(second, wxAuiPaneInfo().Top().Fixed().
MinSize(200, 100).CaptionVisible(false).PaneBorder(false)) );
REQUIRE( manager.AddPane(center, wxAuiPaneInfo().CenterPane()) );
manager.Update();
wxAuiDockUIPart* const sizer = manager.FindPaneSizer();
REQUIRE( sizer );
manager.DragBy(sizer, wxPoint(20, 0));
const bool stillCaptured = wxWindow::GetCapture() == frame.get();
// Don't let the rest of the tests run with the mouse captured even if the
// check below fails.
if ( stillCaptured )
frame->ReleaseMouse();
CHECK( !stillCaptured );
}
TEST_CASE_METHOD(AuiNotebookTestCase, "wxAuiNotebook::DoGetBestSize", "[aui]")
{
wxPanel *p = new wxPanel(nb.get());