[Git][wxwidgets/wxwidgets][master] 26 commits: Set pane min size more efficiently in wxAUI code

1 view
Skip to first unread message

Vadim Zeitlin (@_VZ_)

unread,
Feb 27, 2026, 9:03:07 AM (10 days ago) Feb 27
to wx-commi...@googlegroups.com


Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets


Commits:
91afca8a by Vadim Zeitlin at 2026-02-23T20:26:03+01:00
Set pane min size more efficiently in wxAUI code

No real changes, just directly use wxSizerItem that we already have
instead of calling wxSizer::SetItemMinSize() that would need to search
for this sizer item before calling SetMinSize() on it.

- - - - -
f776a256 by Vadim Zeitlin at 2026-02-23T20:26:03+01:00
Update hint window size after unsplitting wxAuiNotebook

The old hint window size, calculated for multiple panes, is not correct
any more after UnsplitAll() removed all panes but one.

- - - - -
452b9e3f by Vadim Zeitlin at 2026-02-23T20:26:03+01:00
Update hint window size after loading wxAuiNotebook layout

This is similar to the previous commit: loading a new layout may render
the old hint window size incorrect, so update it after doing it.

- - - - -
876f466e by Vadim Zeitlin at 2026-02-23T20:26:03+01:00
Add a comment about dock sizes to wxAuiManager::LayoutAll()

No real changes, just explain why we can only reset the size of the
docks whose size is fixed, i.e. those that can't be interactively
resized by the user.

- - - - -
c8bbfe5d by Vadim Zeitlin at 2026-02-23T20:26:03+01:00
Replace hardcoded value with wxAuiManager::GetMinPaneSize()

This will allow reusing the same minimum dock/pane size elsewhere and
will also make it easy to customize it, if necessary.

No real changes.

- - - - -
bdd5b597 by Vadim Zeitlin at 2026-02-23T20:26:03+01:00
Don't account for status bar twice in wxAuiManager

There is no need to subtract the status bar height from the frame client
size as this is already done by wxFrame::GetClientSize() itself and
doing it again just wrongly decreased the available height too much.

- - - - -
6dbe1bb0 by Vadim Zeitlin at 2026-02-23T20:26:03+01:00
Don't add empty docks unnecessarily in wxAuiManager::LayoutAll()

The code always added a new dock, even if the current pane was not going
to be added to it because it was floating or hidden.

This was harmless because empty docks were pruned from the array of
docks after this loop, but unnecessary, so simply don't do it and only
create the dock when we know that we really need it for this pane.

This commit is best viewed with Git --color-moved option.

- - - - -
00ebfc92 by Vadim Zeitlin at 2026-02-24T23:18:40+01:00
Fix handling right and middle clicks in vertical wxAuiToolBar

They were wrongly recognized as clicks on the overflow item due to the
hit test check being correct for horizontal toolbars only.

Fix this by using the same, simpler and much more obviously correct,
check that was already used for the left mouse button and just tests if
GetOverflowRect() contains the point.

Closes #26242.

- - - - -
3e070399 by Vadim Zeitlin at 2026-02-24T23:22:00+01:00
Simplify wxAuiToolBar::GetOverflowRect()

Don't call m_overflowSizerItem->GetRect() unnecessarily: all fields of
overflow_rect were overwritten immediately after assigning the result of
this call to it, so this was just useless.

Also replace "cli_rect" with "cli_size" as we only used the size part
anyhow.

No real changes.

- - - - -
f07e3d16 by Vadim Zeitlin at 2026-02-24T23:26:29+01:00
Use wxRect::Contains() overload taking wxPoint

This is shorter and arguably more clear than passing pairs of
coordinates everywhere, so change the code to consistently do it.

Also remove unnecessary temporary variables.

No real changes.

- - - - -
1806e40a by Vadim Zeitlin at 2026-02-24T23:28:27+01:00
Only call wxGetMouseState() in wxAuiToolBar code

Don't call wxGetMousePosition() when this information is already
available as part of wxGetMouseState() return value that we may need
anyhow.

No real changes.

- - - - -
1b840d97 by Vadim Zeitlin at 2026-02-24T23:35:22+01:00
Don't duplicate same code twice in wxAuiToolBar::OnRightUp()

For unknown reasons we used exactly the same code for sending event with
valid and invalid tool ID instead of just setting a variable containing
the tool ID and then using it.

Fix this now.

No real changes.

- - - - -
8b0f92e6 by Vadim Zeitlin at 2026-02-24T23:38:17+01:00
Remove unused wxRect variables in wxAuiToolBar mouse handlers

No real changes.

- - - - -
960b815e by Vadim Zeitlin at 2026-02-24T23:39:02+01:00
Replace another wxRect whose position is not used with wxSize

No real changes.

- - - - -
68b689f8 by Vadim Zeitlin at 2026-02-24T23:44:29+01:00
Don't push/pop event handlers for showing popup menu

Just use GetPopupMenuSelectionFromUser() which handles this internally.

Also document that ShowDropDown() returns -1 if the menu is dismissed.

No real changes.

- - - - -
55a84f46 by Vadim Zeitlin at 2026-02-24T23:46:39+01:00
Generate wxEVT_AUITOOLBAR_MIDDLE_CLICK when not on normal item

There doesn't seem to be any reason to generate right click events in
any case, whether there is an item under the mouse or not, but only
generate middle clicks if there is a normal (and not any other kind of)
item under the mouse.

Change the code to also do it unconditionally for consistency.

- - - - -
84236e8b by Vadim Zeitlin at 2026-02-24T23:49:40+01:00
Fold common code for right/middle button clicks in wxAuiToolBar

No real changes, this is a pure refactoring after the changes of the
parent commit which resolved another inconsistency in handling of right
and middle mouse button clicks.

- - - - -
1bfece51 by Vadim Zeitlin at 2026-02-24T23:50:20+01:00
Ignore commit changing naming convention in wxAUI when blaming

It touched a lot of lines but didn't make any real changes.

Also add a date which was missing for another commit in this file for
some reason.

- - - - -
22c45e5a by Vadim Zeitlin at 2026-02-26T16:13:11+01:00
Correct comment in wxGLCanvasEGL dtor

This should have been part of 8ed1469743 (Fix crash on wxGLCanvasEGL
destruction, 2026-02-26).

No real changes.

- - - - -
b9628930 by Vadim Zeitlin at 2026-02-26T23:36:31+01:00
Add wxAuiManager::SplitPane()

This function is very simple for now, but it needs to be in wxAuiManager
itself, and not in wxAuiNotebook, where it previously was, to be
enhanced later.

It can also be useful for splitting any kind of panes, not just the
notebook one.

- - - - -
ed768cea by Vadim Zeitlin at 2026-02-26T23:36:31+01:00
Use new wxAuiManager::CalculateNewSplitSize() from wxAuiNotebook

Add a new function doing what the function with the same name in
wxAuiNotebook used to do but doing it better, i.e. at least not
returning a hardcoded 180x180 size if there are 2 or more existing
panes.

The current, very simple, algorithm seems to be not too bad (and using
1/N seems to be better in practice than using 1/2^N), but it could be
always improved in the future.

Document the existing virtual wxAuiNotebook::CalculateNewSplitSize() as
well because it provides a way for the application to customize the size
used for the splits if the default algorithm is not appropriate.

- - - - -
d1a283cb by Vadim Zeitlin at 2026-02-26T23:36:31+01:00
Resize all AUI panes to have the same size in the split direction

This is not ideal because it loses the sizes before splitting, but is
better than preserving the same sizes for the existing docks as we did
before because this resulted in there not being enough size for all of
them and some docks became completely hidden.

A future improvement could consist in preserving the current proportions
of the docks, but it's not really clear if it's worth doing this.

Closes #26081.

- - - - -
554e7384 by Vadim Zeitlin at 2026-02-26T23:36:46+01:00
Give correct type to wxAuiLayoutObject::m_dir

For some unknown reason this variable was an unsigned char even though
it only contained the value of an enum.

Give it the enum type for clarity and ease of debugging.

No real changes.

- - - - -
66b13fcc by Vadim Zeitlin at 2026-02-27T14:49:54+01:00
Don't accumulate timer events when calling YieldFor() in wxMSW

Repeated calls to this function could result in unbounded input queue
growth because timer events were synthesized for each call to it, put
back into the queue if not processed, and then another event would be
synthesized again during the next call.

Fix this by discarding timer events instead. This is not ideal when
using one-off timers, but better than the alternative.

Document this limitation of wxMSW.

See #26204.

Closes #26192.

- - - - -
33a595c9 by Vadim Zeitlin at 2026-02-27T14:52:00+01:00
Merge branch 'auibar-findtool-fix'

Fix for right/middle click handling in wxAuiToolBar and related cleanup.

See #26243

- - - - -
475182cd by Vadim Zeitlin at 2026-02-27T14:52:53+01:00
Merge branch 'auibook-split'

Improve wxAuiNotebook splitting behaviour.

See #26233.

- - - - -


14 changed files:

- .git-blame-ignore-revs
- include/wx/aui/auibar.h
- include/wx/aui/framemanager.h
- interface/wx/aui/auibar.h
- interface/wx/aui/auibook.h
- interface/wx/aui/framemanager.h
- interface/wx/event.h
- interface/wx/evtloop.h
- interface/wx/progdlg.h
- src/aui/auibar.cpp
- src/aui/auibook.cpp
- src/aui/framemanager.cpp
- src/msw/evtloop.cpp
- src/unix/glegl.cpp


Changes:

=====================================
.git-blame-ignore-revs
=====================================
@@ -52,9 +52,12 @@ f58ea625968953ca93585ea7f93dcc07ad032d8f
# Remove trailing whitespace from several files, 2018-04-11
496da2e550ce1f562f727230babc363da190530e

-# Remove all lines containing cvs/svn "$Id$" keyword.
+# Remove all lines containing cvs/svn "$Id$" keyword., 2013-07-26
3f66f6a5b3583b02c34854556eb83e3a808524ce

+# Change variables naming convention in wxAUI code., 2011-10-30
+9a29fe70bc90b08b4f0bd4c23c1d12ad17cbbed2
+
# No changes, just removed hard tabs and trailing white space., 2009-08-21
03647350fc7cd141953c72e0284e928847d30f44



=====================================
include/wx/aui/auibar.h
=====================================
@@ -724,6 +724,9 @@ private:
// Common part of OnLeaveWindow() and OnCaptureLost().
void DoResetMouseState();

+ // Common part of On{Right,Middle}Up().
+ void DoRightOrMiddleUp(wxMouseEvent& evt, wxEventType eventType);
+
wxSize RealizeHelper(wxReadOnlyDC& dc, wxOrientation orientation);

void UpdateBackgroundBitmap(const wxSize& size);


=====================================
include/wx/aui/framemanager.h
=====================================
@@ -453,6 +453,9 @@ public:
void SetArtProvider(wxAuiDockArt* artProvider);
wxAuiDockArt* GetArtProvider() const;

+ // Return the minimum size for any pane.
+ wxSize GetMinPaneSize() const;
+
// Change the sides where docks for minimized panes can be created.
// Must include one or more of wxLEFT, wxRIGHT, wxTOP, wxBOTTOM and must
// currently be called before there any minimized panes.
@@ -483,6 +486,11 @@ public:
const wxAuiPaneInfo& insertLocation,
int insertLevel = wxAUI_INSERT_PANE);

+ bool SplitPane(wxWindow* window,
+ wxWindow* newWindow,
+ int direction,
+ const wxPoint& dropPos = wxDefaultPosition);
+
bool DetachPane(wxWindow* window);

void Update();
@@ -524,6 +532,8 @@ public:
const wxPoint& pt,
const wxPoint& offset = wxPoint{});

+ wxSize CalculateNewSplitSize() const;
+
void DrawHintRect(
wxWindow* paneWindow,
const wxPoint& pt,


=====================================
interface/wx/aui/auibar.h
=====================================
@@ -716,6 +716,12 @@ public:
*/
virtual void SetElementSize(int elementId, int size) = 0;

+ /**
+ Show a drop down menu with the given items.
+
+ @return ID of the item selected in the menu or -1 if the menu was
+ dismissed
+ */
virtual int ShowDropDown(
wxWindow* wnd,
const wxAuiToolBarItemArray& items) = 0;


=====================================
interface/wx/aui/auibook.h
=====================================
@@ -793,6 +793,18 @@ public:
@since 3.1.4
*/
bool FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx);
+
+protected:
+ /**
+ Called to determine the size of a new split tab control.
+
+ This function may be overridden to customize the initial size of the
+ newly created tab control when the user drags a tab out of the main one
+ (if ::wxAUI_NB_TAB_SPLIT style is used) or when Split() is called.
+
+ The default implementation calls wxAuiManager::CalculateNewSplitSize().
+ */
+ virtual wxSize CalculateNewSplitSize();
};

/**


=====================================
interface/wx/aui/framemanager.h
=====================================
@@ -367,6 +367,24 @@ public:
const wxPoint& pt,
const wxPoint& offset = wxPoint{0, 0});

+ /**
+ Return a reasonable size to use for a new split.
+
+ This function currently calculates the number of columns and rows in
+ the current layout and returns the size of the managed window divided
+ by one more than that number, i.e. returns half of the available size
+ if there is currently just one row or column, a third if there are two
+ rows or columns, and so on.
+
+ The implementation may change in the future, but it will always return
+ some reasonable size to use for a new split.
+
+ @see SplitPane(), wxAuiNotebook::CalculateNewSplitSize()
+
+ @since 3.3.2
+ */
+ wxSize CalculateNewSplitSize() const;
+
/**
Check if a key modifier is pressed (actually ::WXK_CONTROL or
::WXK_ALT) while dragging the frame to not dock the window.
@@ -686,6 +704,32 @@ public:
*/
virtual void ShowHint(const wxRect& rect);

+ /**
+ Create a new pane with the given window near an existing pane.
+
+ The size of the new pane is determined by CalculateNewSplitSize() and
+ the existing panes are resized to have the same size in the split
+ direction.
+
+ Note that this function calls Update() internally, so there is no need
+ to call it separately.
+
+ @param window A window already managed by this wxAuiManager identifying
+ the pane to split.
+ @param newWindow The window to be added as a new pane.
+ @param direction The direction where the new pane should be added, one
+ of ::wxLEFT, ::wxRIGHT, ::wxTOP or ::wxBOTTOM.
+ @param dropPos The position where the pane is dropped, if this function
+ is called in response to a drag-and-drop operation. If not
+ specified, the position is determined by @a direction.
+
+ @since 3.3.2
+ */
+ bool SplitPane(wxWindow* window,
+ wxWindow* newWindow,
+ int direction,
+ const wxPoint& dropPos = wxDefaultPosition);
+
/**
Mostly used internally to define the drag action parameters.
*/


=====================================
interface/wx/event.h
=====================================
@@ -48,7 +48,14 @@ enum wxEventCategory
/// This category is for wxSocketEvent
wxEVT_CATEGORY_SOCKET = 4,

- /// This category is for wxTimerEvent
+ /**
+ This category is for wxTimerEvent.
+
+ @note Under wxMSW, if this category is not specified when calling
+ wxEventLoopBase::YieldFor, events from one-off timers may be lost,
+ so it's recommended to either pass this category to it or use
+ repeatedly firing timers instead.
+ */
wxEVT_CATEGORY_TIMER = 8,

/**


=====================================
interface/wx/evtloop.h
=====================================
@@ -262,6 +262,11 @@ public:
wxWidgets events posted using wxEvtHandler::AddPendingEvent or
wxEvtHandler::QueueEvent are instead selectively processed by all ports.

+ @note Under wxMSW, if @a eventsToProcess doesn't include
+ ::wxEVT_CATEGORY_TIMER, events from one-off timers may be lost,
+ so it's recommended to either include this category in the argument or
+ use repeatedly firing timers instead.
+
@see wxEvent::GetEventCategory
*/
bool YieldFor(long eventsToProcess);


=====================================
interface/wx/progdlg.h
=====================================
@@ -27,11 +27,16 @@
essentially be the same as this class.

Note that you must be aware that wxProgressDialog internally calls
- wxEventLoopBase::YieldFor with @c wxEVT_CATEGORY_UI and @c wxEVT_CATEGORY_USER_INPUT
+ wxEventLoopBase::YieldFor with ::wxEVT_CATEGORY_UI and ::wxEVT_CATEGORY_USER_INPUT
and this may cause unwanted re-entrancies or the out-of-order processing
of pending events (to help preventing the last problem if you're using
wxProgressDialog in a multi-threaded application you should be sure to use
- wxThreadEvent for your inter-threads communications).
+ wxThreadEvent for your inter-threads communications). Additionally because
+ events from one-off timers, i.e. those started with wxTimer::StartOnce(),
+ are discarded by wxEventLoopBase::YieldFor() when it's called with these
+ flags in wxMSW, any such timers firing while the progress dialog is shown
+ will not be processed at all, so it is recommended not to start such timers
+ before showing the progress dialog.

Although wxProgressDialog is not really modal, it should be created on the
stack, and not the heap, as other modal dialogs, e.g. use it like this:


=====================================
src/aui/auibar.cpp
=====================================
@@ -86,31 +86,6 @@ static bool IsThemeDark()



-class ToolbarCommandCapture : public wxEvtHandler
-{
-public:
-
- ToolbarCommandCapture() { m_lastId = 0; }
- int GetCommandId() const { return m_lastId; }
-
- bool ProcessEvent(wxEvent& evt) override
- {
- if (evt.GetEventType() == wxEVT_MENU)
- {
- m_lastId = evt.GetId();
- return true;
- }
-
- if (GetNextHandler())
- return GetNextHandler()->ProcessEvent(evt);
-
- return false;
- }
-
-private:
- int m_lastId;
-};
-
wxBitmap wxAuiToolBarItem::GetCurrentBitmapFor(wxWindow* wnd) const
{
// We suppose that we don't have disabled bitmap if we don't have the
@@ -869,13 +844,9 @@ int wxAuiGenericToolBarArt::ShowDropDown(wxWindow* wnd,
wxRect cli_rect = wnd->GetClientRect();
pt.y = cli_rect.y + cli_rect.height;

- ToolbarCommandCapture* cc = new ToolbarCommandCapture;
- wnd->PushEventHandler(cc);
- wnd->PopupMenu(&menuPopup, pt);
- int command = cc->GetCommandId();
- wnd->PopEventHandler(true);
+ const int command = wnd->GetPopupMenuSelectionFromUser(menuPopup, pt);

- return command;
+ return command == wxID_NONE ? -1 : command;
}


@@ -1648,17 +1619,16 @@ void wxAuiToolBar::RefreshOverflowState()

int overflow_state = 0;

- wxRect overflow_rect = GetOverflowRect();
-

// find out the mouse's current position
- wxPoint pt = ::wxGetMousePosition();
+ const wxMouseState mouseState = ::wxGetMouseState();
+ wxPoint pt = mouseState.GetPosition();
pt = this->ScreenToClient(pt);

// find out if the mouse cursor is inside the dropdown rectangle
- if (overflow_rect.Contains(pt.x, pt.y))
+ if (GetOverflowRect().Contains(pt))
{
- if (::wxGetMouseState().LeftIsDown())
+ if (mouseState.LeftIsDown())
overflow_state = wxAUI_BUTTON_STATE_PRESSED;
else
overflow_state = wxAUI_BUTTON_STATE_HOVER;
@@ -2244,23 +2214,23 @@ int wxAuiToolBar::GetOverflowState() const

wxRect wxAuiToolBar::GetOverflowRect() const
{
- wxRect cli_rect(wxPoint(0,0), GetClientSize());
- wxRect overflow_rect = m_overflowSizerItem->GetRect();
+ const wxSize cli_size = GetClientSize();
+ wxRect overflow_rect;
int overflow_size = m_art->GetElementSizeForWindow(wxAUI_TBART_OVERFLOW_SIZE, this);

if (m_orientation == wxVERTICAL)
{
- overflow_rect.y = cli_rect.height - overflow_size;
+ overflow_rect.y = cli_size.y - overflow_size;
overflow_rect.x = 0;
- overflow_rect.width = cli_rect.width;
+ overflow_rect.width = cli_size.x;
overflow_rect.height = overflow_size;
}
else
{
- overflow_rect.x = cli_rect.width - overflow_size;
+ overflow_rect.x = cli_size.x - overflow_size;
overflow_rect.y = 0;
overflow_rect.width = overflow_size;
- overflow_rect.height = cli_rect.height;
+ overflow_rect.height = cli_size.y;
}

return overflow_rect;
@@ -2552,7 +2522,7 @@ void wxAuiToolBar::UpdateBackgroundBitmap(const wxSize& size)
void wxAuiToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
{
wxAutoBufferedPaintDC dc(this);
- wxRect cli_rect(wxPoint(0,0), GetClientSize());
+ const wxSize cli_size = GetClientSize();


bool horizontal = m_orientation == wxHORIZONTAL;
@@ -2576,9 +2546,9 @@ void wxAuiToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
// calculated how far we can draw items
int last_extent;
if (horizontal)
- last_extent = cli_rect.width;
+ last_extent = cli_size.x;
else
- last_extent = cli_rect.height;
+ last_extent = cli_size.y;
if (m_overflowVisible)
last_extent -= overflowSize;

@@ -2649,7 +2619,7 @@ void wxAuiToolBar::OnLeftDown(wxMouseEvent& evt)
if (m_gripperSizerItem)
{
wxRect gripper_rect = m_gripperSizerItem->GetRect();
- if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
+ if (gripper_rect.Contains(evt.GetPosition()))
{
// find aui manager
wxAuiManager* manager = wxAuiManager::GetManager(this);
@@ -2667,9 +2637,7 @@ void wxAuiToolBar::OnLeftDown(wxMouseEvent& evt)

if (m_overflowSizerItem && m_overflowVisible && m_art)
{
- wxRect overflow_rect = GetOverflowRect();
-
- if (overflow_rect.Contains(evt.m_x, evt.m_y))
+ if (GetOverflowRect().Contains(evt.GetPosition()))
{
wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_OVERFLOW_CLICK, -1);
e.SetEventObject(this);
@@ -2841,25 +2809,16 @@ void wxAuiToolBar::OnRightDown(wxMouseEvent& evt)
if (HasCapture())
return;

- wxRect cli_rect(wxPoint(0,0), GetClientSize());
-
if (m_gripperSizerItem)
{
- wxRect gripper_rect = m_gripperSizerItem->GetRect();
- if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
+ if (m_gripperSizerItem->GetRect().Contains(evt.GetPosition()))
return;
}

- if (m_overflowSizerItem && m_art)
+ if (m_overflowSizerItem && m_overflowVisible && m_art)
{
- int overflowSize = m_art->GetElementSizeForWindow(wxAUI_TBART_OVERFLOW_SIZE, this);
- if (overflowSize > 0 &&
- evt.m_x > cli_rect.width - overflowSize &&
- evt.m_y >= 0 &&
- evt.m_y < cli_rect.height)
- {
+ if (GetOverflowRect().Contains(evt.GetPosition()))
return;
- }
}

m_actionPos = wxPoint(evt.GetX(), evt.GetY());
@@ -2875,7 +2834,7 @@ void wxAuiToolBar::OnRightDown(wxMouseEvent& evt)
UnsetToolTip();
}

-void wxAuiToolBar::OnRightUp(wxMouseEvent& evt)
+void wxAuiToolBar::DoRightOrMiddleUp(wxMouseEvent& evt, wxEventType eventType)
{
if (HasCapture())
return;
@@ -2883,55 +2842,49 @@ void wxAuiToolBar::OnRightUp(wxMouseEvent& evt)
wxAuiToolBarItem* hitItem;
hitItem = FindToolByPosition(evt.GetX(), evt.GetY());

+ int toolId;
if (m_actionItem && hitItem == m_actionItem)
{
- wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_RIGHT_CLICK, m_actionItem->m_toolId);
- e.SetEventObject(this);
- e.SetToolId(m_actionItem->m_toolId);
- e.SetClickPoint(m_actionPos);
- GetEventHandler()->ProcessEvent(e);
- DoIdleUpdate();
+ toolId = m_actionItem->m_toolId;
}
else
{
// right-clicked on the invalid area of the toolbar
- wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_RIGHT_CLICK, -1);
- e.SetEventObject(this);
- e.SetToolId(-1);
- e.SetClickPoint(m_actionPos);
- GetEventHandler()->ProcessEvent(e);
- DoIdleUpdate();
+ toolId = wxNOT_FOUND;
}

+ wxAuiToolBarEvent e(eventType, toolId);
+ e.SetEventObject(this);
+ e.SetToolId(toolId);
+ e.SetClickPoint(m_actionPos);
+ GetEventHandler()->ProcessEvent(e);
+ DoIdleUpdate();
+
// reset member variables
m_actionPos = wxPoint(-1,-1);
m_actionItem = nullptr;
}

+void wxAuiToolBar::OnRightUp(wxMouseEvent& evt)
+{
+ DoRightOrMiddleUp(evt, wxEVT_AUITOOLBAR_RIGHT_CLICK);
+}
+
void wxAuiToolBar::OnMiddleDown(wxMouseEvent& evt)
{
if (HasCapture())
return;

- wxRect cli_rect(wxPoint(0,0), GetClientSize());
-
if (m_gripperSizerItem)
{
- wxRect gripper_rect = m_gripperSizerItem->GetRect();
- if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
+ if (m_gripperSizerItem->GetRect().Contains(evt.GetPosition()))
return;
}

- if (m_overflowSizerItem && m_art)
+ if (m_overflowSizerItem && m_overflowVisible && m_art)
{
- int overflowSize = m_art->GetElementSizeForWindow(wxAUI_TBART_OVERFLOW_SIZE, this);
- if (overflowSize > 0 &&
- evt.m_x > cli_rect.width - overflowSize &&
- evt.m_y >= 0 &&
- evt.m_y < cli_rect.height)
- {
+ if (GetOverflowRect().Contains(evt.GetPosition()))
return;
- }
}

m_actionPos = wxPoint(evt.GetX(), evt.GetY());
@@ -2952,28 +2905,7 @@ void wxAuiToolBar::OnMiddleDown(wxMouseEvent& evt)

void wxAuiToolBar::OnMiddleUp(wxMouseEvent& evt)
{
- if (HasCapture())
- return;
-
- wxAuiToolBarItem* hitItem;
- hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
-
- if (m_actionItem && hitItem == m_actionItem)
- {
- if (hitItem->m_kind == wxITEM_NORMAL)
- {
- wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_MIDDLE_CLICK, m_actionItem->m_toolId);
- e.SetEventObject(this);
- e.SetToolId(m_actionItem->m_toolId);
- e.SetClickPoint(m_actionPos);
- GetEventHandler()->ProcessEvent(e);
- DoIdleUpdate();
- }
- }
-
- // reset member variables
- m_actionPos = wxPoint(-1,-1);
- m_actionItem = nullptr;
+ DoRightOrMiddleUp(evt, wxEVT_AUITOOLBAR_MIDDLE_CLICK);
}

void wxAuiToolBar::OnMotion(wxMouseEvent& evt)
@@ -3083,8 +3015,7 @@ void wxAuiToolBar::OnSetCursor(wxSetCursorEvent& evt)

if (m_gripperSizerItem)
{
- wxRect gripper_rect = m_gripperSizerItem->GetRect();
- if (gripper_rect.Contains(evt.GetX(), evt.GetY()))
+ if (m_gripperSizerItem->GetRect().Contains(evt.GetPosition()))
{
cursor = wxCursor(wxCURSOR_SIZING);
}


=====================================
src/aui/auibook.cpp
=====================================
@@ -2263,27 +2263,7 @@ void wxAuiNotebook::UpdateHintWindowSize()
// calculates the size of the new split
wxSize wxAuiNotebook::CalculateNewSplitSize()
{
- // One of the panes corresponds to the dummy window, the rest are tabs.
- const int tab_ctrl_count = m_mgr.GetAllPanes().size() - 1;
-
- wxSize new_split_size;
-
- // if there is only one tab control, the first split
- // should happen around the middle
- if (tab_ctrl_count < 2)
- {
- new_split_size = GetClientSize();
- new_split_size.x /= 2;
- new_split_size.y /= 2;
- }
- else
- {
- // this is in place of a more complicated calculation
- // that needs to be implemented
- new_split_size = FromDIP(wxSize(180,180));
- }
-
- return new_split_size;
+ return m_mgr.CalculateNewSplitSize();
}

int wxAuiNotebook::CalculateTabCtrlHeight()
@@ -2949,8 +2929,6 @@ wxAuiNotebook::GetPagesInDisplayOrder(wxAuiTabCtrl* tabCtrl) const

void wxAuiNotebook::Split(size_t page, int direction)
{
- wxSize cli_size = GetClientSize();
-
// get the page's window pointer
wxWindow* wnd = GetPage(page);
if (!wnd)
@@ -2971,34 +2949,7 @@ void wxAuiNotebook::Split(size_t page, int direction)
wxAuiTabFrame* new_tabs = CreateTabFrame(CalculateNewSplitSize());
wxAuiTabCtrl* const dest_tabs = new_tabs->m_tabs;

- // create a pane info structure with the information
- // about where the pane should be added
- wxAuiPaneInfo paneInfo = wxAuiPaneInfo().Bottom().CaptionVisible(false);
- wxPoint mouse_pt;
-
- if (direction == wxLEFT)
- {
- paneInfo.Left();
- mouse_pt = wxPoint(0, cli_size.y/2);
- }
- else if (direction == wxRIGHT)
- {
- paneInfo.Right();
- mouse_pt = wxPoint(cli_size.x, cli_size.y/2);
- }
- else if (direction == wxTOP)
- {
- paneInfo.Top();
- mouse_pt = wxPoint(cli_size.x/2, 0);
- }
- else if (direction == wxBOTTOM)
- {
- paneInfo.Bottom();
- mouse_pt = wxPoint(cli_size.x/2, cli_size.y);
- }
-
- m_mgr.AddPane(new_tabs, paneInfo, mouse_pt);
- m_mgr.Update();
+ m_mgr.SplitPane(GetTabFrameFromTabCtrl(src_tabs), new_tabs, direction);

// remove the page from the source tabs
wxAuiNotebookPage page_info = *srcTabInfo.pageInfo;
@@ -3065,6 +3016,8 @@ void wxAuiNotebook::UnsplitAll()
RemoveEmptyTabFrames();

DoSizing();
+
+ UpdateHintWindowSize();
}
}

@@ -3431,11 +3384,11 @@ void wxAuiNotebook::OnTabEndDrag(wxAuiTabCtrl* src_tabs, int src_idx)

// If there is no tabframe at all, create one
wxAuiTabFrame* new_tabs = CreateTabFrame(CalculateNewSplitSize());
+ m_mgr.SplitPane(GetTabFrameFromTabCtrl(src_tabs),
+ new_tabs,
+ wxBOTTOM,
+ mouse_client_pt);

- m_mgr.AddPane(new_tabs,
- wxAuiPaneInfo().Bottom().CaptionVisible(false),
- mouse_client_pt);
- m_mgr.Update();
dest_tabs = new_tabs->m_tabs;
insert_idx = 0;
}
@@ -3992,7 +3945,7 @@ namespace
class wxAuiLayoutObject
{
public:
- enum
+ enum DockDir
{
DockDir_Center,
DockDir_Left,
@@ -4055,7 +4008,7 @@ public:

wxSize m_size;
const wxAuiPaneInfo *m_pInfo;
- unsigned char m_dir;
+ DockDir m_dir;

/*
As the calculation is done from the inner to the outermost pane, the
@@ -4648,6 +4601,8 @@ wxAuiNotebook::LoadLayout(const wxString& name,
if ( activeInMainTab )
m_curPage = m_tabs.GetIdxFromWindow(activeInMainTab);

+ UpdateHintWindowSize();
+
m_mgr.Update();
}



=====================================
src/aui/framemanager.cpp
=====================================
@@ -843,6 +843,12 @@ wxAuiDockArt* wxAuiManager::GetArtProvider() const
return m_art;
}

+wxSize wxAuiManager::GetMinPaneSize() const
+{
+ // This is pretty arbitrary, should we make it configurable?
+ return wxWindow::FromDIP(wxSize(10, 10), m_frame);
+}
+
void wxAuiManager::AllowDocksForMinPanes(int directions)
{
wxCHECK_RET( directions, "Must specify at least one direction" );
@@ -1136,6 +1142,183 @@ bool wxAuiManager::InsertPane(wxWindow* window, const wxAuiPaneInfo& paneInfo,
return true;
}

+wxSize wxAuiManager::CalculateNewSplitSize() const
+{
+ // Don't do anything if we're not fully initialized yet.
+ if ( !m_frame || m_docks.empty() )
+ return GetMinPaneSize();
+
+ // Calculate the number of vertical and horizontal rows that we have.
+ int numColumns = 0;
+ int numRows = 0;
+
+ // We could have called FindDocks() multiple times here, but it is more
+ // efficient to count the docks ourselves just once.
+ for ( const auto& d : m_docks )
+ {
+ switch ( d.dock_direction )
+ {
+ case wxAUI_DOCK_LEFT:
+ case wxAUI_DOCK_RIGHT:
+ numColumns++;
+ break;
+
+ case wxAUI_DOCK_TOP:
+ case wxAUI_DOCK_BOTTOM:
+ numRows++;
+ break;
+
+ case wxAUI_DOCK_CENTER:
+ // Center dock counts as both a row and a column.
+ numColumns++;
+ numRows++;
+ break;
+
+ case wxAUI_DOCK_NONE:
+ wxFAIL_MSG( "Unexpected dock direction when calculating new split size" );
+ }
+ }
+
+ // We don't know if the new split is going to be horizontal or vertical,
+ // but it doesn't matter because the other size component won't be used, so
+ // we can just set each of them as if the split was in that direction.
+ wxSize size = m_frame->GetClientSize();
+
+ // When we have only one pane, the new split should be half of the total
+ // available size, hence +1.
+ size.x /= numColumns + 1;
+ size.y /= numRows + 1;
+
+ // Always use some minimum size to avoid creating too small panes or
+ // showing tiny hint window (because this function is also used to
+ // determine its size).
+ size.IncTo(GetMinPaneSize());
+
+ return size;
+}
+
+bool
+wxAuiManager::SplitPane(wxWindow* window,
+ wxWindow* newWindow,
+ int direction,
+ const wxPoint& dropPos)
+{
+ const wxAuiPaneInfo& paneOrig = GetPane(window);
+ wxCHECK_MSG( paneOrig.IsOk(), false, "Window being split must be present" );
+
+ wxAuiPaneInfo paneInfo = wxAuiPaneInfo().CaptionVisible(false);
+
+ wxPoint defaultDropPos;
+ const wxSize sizeWindow = m_frame->GetClientSize();
+
+ if (direction == wxLEFT)
+ {
+ paneInfo.Left();
+ defaultDropPos = wxPoint(0, sizeWindow.y/2);
+ }
+ else if (direction == wxRIGHT)
+ {
+ paneInfo.Right();
+ defaultDropPos = wxPoint(sizeWindow.x, sizeWindow.y/2);
+ }
+ else if (direction == wxTOP)
+ {
+ paneInfo.Top();
+ defaultDropPos = wxPoint(sizeWindow.x/2, 0);
+ }
+ else if (direction == wxBOTTOM)
+ {
+ paneInfo.Bottom();
+ defaultDropPos = wxPoint(sizeWindow.x/2, sizeWindow.y);
+ }
+
+ // Get the new split size before adding the pane, as this would change it.
+ const wxSize size = CalculateNewSplitSize();
+
+ AddPane(newWindow, paneInfo,
+ dropPos != wxDefaultPosition ? dropPos : defaultDropPos);
+
+ // The direction specified in the pane info may be overridden by the drop
+ // position, so get the real direction of the new pane now.
+ bool adjustHorz = false;
+ bool adjustVert = false;
+ switch ( GetPane(newWindow).dock_direction )
+ {
+ case wxAUI_DOCK_LEFT:
+ case wxAUI_DOCK_RIGHT:
+ adjustHorz = true;
+ break;
+
+ case wxAUI_DOCK_TOP:
+ case wxAUI_DOCK_BOTTOM:
+ adjustVert = true;
+ break;
+
+ case wxAUI_DOCK_CENTER:
+ case wxAUI_DOCK_NONE:
+ wxFAIL_MSG( "Unexpected dock direction for new pane after split" );
+ }
+
+ // Adjust all the existing docks to have the same size as the new one in
+ // the split direction.
+ for ( auto& d : m_docks )
+ {
+ switch ( d.dock_direction )
+ {
+ case wxAUI_DOCK_LEFT:
+ case wxAUI_DOCK_RIGHT:
+ if ( adjustHorz )
+ d.size = size.x;
+ break;
+
+ case wxAUI_DOCK_TOP:
+ case wxAUI_DOCK_BOTTOM:
+ if ( adjustVert )
+ d.size = size.y;
+ break;
+
+ case wxAUI_DOCK_CENTER:
+ d.size = adjustHorz ? size.x : size.y;
+ break;
+
+ case wxAUI_DOCK_NONE:
+ wxFAIL_MSG( "Unexpected dock direction when calculating new split size" );
+ }
+ }
+
+ // And if we need to create a new dock for the new pane, set its size to be
+ // the same too.
+ //
+ // Note: this is similar to the code in LayoutAll() and we could also call
+ // Update() to do this, but then we'd need to call it again to take the
+ // changed dock size into account, so we prefer to set the size here to
+ // avoid an extra call to Update().
+ //
+ // Also note that it is _not_ sufficient to check if the dock is going to
+ // be created for the new pane, in some layouts it can go into an existing
+ // dock and a new dock is created for an existing pane, so we really need
+ // to iterate over all of them.
+ for ( const auto& p : m_panes )
+ {
+ if ( FindDocks(m_docks,
+ p.dock_direction,
+ p.dock_layer,
+ p.dock_row,
+ FindDocksFlags::OnlyFirst).IsEmpty() )
+ {
+ wxAuiDockInfo d;
+ d.dock_direction = p.dock_direction;
+ d.dock_layer = p.dock_layer;
+ d.dock_row = p.dock_row;
+ d.size = adjustHorz ? size.x : size.y;
+ m_docks.Add(d);
+ }
+ }
+
+ Update();
+
+ return true;
+}

// DetachPane() removes a pane from the frame manager. This
// method will not destroy the window that is removed.
@@ -2270,9 +2453,7 @@ void wxAuiManager::LayoutAddPane(wxSizer* cont,

if (min_size != wxDefaultSize)
{
- vert_pane_sizer->SetItemMinSize(
- vert_pane_sizer->GetChildren().GetCount()-1,
- min_size.x, min_size.y);
+ sizer_item->SetMinSize(min_size);
}


@@ -2484,6 +2665,10 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes,
// the contained windows may have been resized
dock.size = 0;
}
+ //else: non-fixed docks must keep their size to allow resizing them
+ // interactively, if we reset their size too here, they would always
+ // have the size determined by their contents and drag-resizing them
+ // wouldn't work
}


@@ -2509,6 +2694,14 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes,
if ( dock->size == 0 )
dock->size = p.dock_size;
}
+
+ if ( !p.IsDocked() || !p.IsShown() )
+ {
+ // remove the pane from any existing docks
+ RemovePaneFromDocks(docks, p);
+ continue;
+ }
+
if ( !dock )
{
// dock was not found, so we need to create a new one
@@ -2522,22 +2715,13 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes,
}


- if (p.IsDocked() && p.IsShown())
- {
- // remove the pane from any existing docks except this one
- RemovePaneFromDocks(docks, p, dock);
-
- // pane needs to be added to the dock,
- // if it doesn't already exist
- if (!FindPaneInDock(*dock, p.window))
- dock->panes.Add(&p);
- }
- else
- {
- // remove the pane from any existing docks
- RemovePaneFromDocks(docks, p);
- }
+ // remove the pane from any existing docks except this one
+ RemovePaneFromDocks(docks, p, dock);

+ // pane needs to be added to the dock,
+ // if it doesn't already exist
+ if (!FindPaneInDock(*dock, p.window))
+ dock->panes.Add(&p);
}

// remove any empty docks
@@ -2569,6 +2753,8 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes,
if (pane_size == wxDefaultSize)
pane_size = pane.window->GetSize();

+ pane_size.IncTo(GetMinPaneSize());
+
if (dock.IsHorizontal())
size = wxMax(pane_size.y, size);
else
@@ -2612,9 +2798,6 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes,
else
size = wxMin(size, max_dock_x_size);

- // absolute minimum size for a dock is 10 pixels
- size = wxMax(size, m_frame->FromDIP(10));
-
dock.size = size;
}

@@ -4583,22 +4766,6 @@ bool wxAuiManager::DoEndResizeAction(wxMouseEvent& event)
int available_width = client_size.GetWidth() - used_width;
int available_height = client_size.GetHeight() - used_height;

-
-#if wxUSE_STATUSBAR
- // if there's a status control, the available
- // height decreases accordingly
- if (wxDynamicCast(m_frame, wxFrame))
- {
- wxFrame* frame = static_cast<wxFrame*>(m_frame);
- wxStatusBar* status = frame->GetStatusBar();
- if (status)
- {
- wxSize status_client_size = status->GetClientSize();
- available_height -= status_client_size.GetHeight();
- }
- }
-#endif
-
const wxRect& rect = m_actionPart->dock->rect;

wxPoint new_pos(event.m_x - m_actionOffset.x,


=====================================
src/msw/evtloop.cpp
=====================================
@@ -273,6 +273,7 @@ void wxGUIEventLoop::DoYieldFor(long eventsToProcess)

// choose a wxEventCategory for this Windows message
bool processNow;
+ bool processLater = true;
switch (msg.message)
{
case WM_NCMOUSEMOVE:
@@ -338,6 +339,18 @@ void wxGUIEventLoop::DoYieldFor(long eventsToProcess)

case WM_TIMER:
processNow = (eventsToProcess & wxEVT_CATEGORY_TIMER) != 0;
+
+ // Timer messages are synthesized by Windows whenever there are
+ // no other messages and so will keep accumulating in the queue
+ // if we don't process them, so to prevent this from happening,
+ // don't put them back into the queue, as this would result in
+ // it growing with each call to this function, which is
+ // especially bad if it's called in a loop, as it happens in
+ // wxGenericProgressDialog.
+ //
+ // This is not ideal, as events from one off timers will be
+ // lost, but it's better than the alternative.
+ processLater = false;
break;

default:
@@ -369,9 +382,13 @@ void wxGUIEventLoop::DoYieldFor(long eventsToProcess)
}
else
{
- // remove the message and store it
+ // remove the message from the queue to ensure that we don't loop
+ // forever here in any case
::GetMessage(&msg, nullptr, 0, 0);
- msgsToProcess.push_back(msg);
+
+ // and perhaps save it for processing later
+ if ( processLater )
+ msgsToProcess.push_back(msg);
}
}



=====================================
src/unix/glegl.cpp
=====================================
@@ -685,10 +685,10 @@ void wxGLCanvasEGL::OnRealized()

wxGLCanvasEGL::~wxGLCanvasEGL()
{
- // Our "unmap" signal handler would be called from the base class dtor, so
- // disconnect it to avoid accessing this object when it's already
- // half-destroyed (and it is useless anyhow now as all it does is to call
- // DestroyWaylandSubsurface() which we already do just below).
+ // Our "unmap" signal handler would be called from wxWindow dtor, so
+ // disconnect it to avoid accessing this object when it's already destroyed
+ // by wxGLCanvas dtor (and it is useless anyhow now as all it does is to
+ // call DestroyWaylandSubsurface() which we already do just below).
if ( m_canvas && m_canvas->m_widget )
{
g_signal_handlers_disconnect_by_func(



View it on GitLab: https://gitlab.com/wxwidgets/wxwidgets/-/compare/926af1cc542b4aea72a6b6a3ceb512fc3f836b89...475182cd9c1a729e8b47788eee6e51933852d83f

--
View it on GitLab: https://gitlab.com/wxwidgets/wxwidgets/-/compare/926af1cc542b4aea72a6b6a3ceb512fc3f836b89...475182cd9c1a729e8b47788eee6e51933852d83f
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help


Reply all
Reply to author
Forward
0 new messages