From 48bf1ac4e9549c4a5ea41ba70c642f95e165d7f6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 12 Jul 2025 20:09:33 +0200 Subject: [PATCH] Rewrite event generation and propagation in wxAuiNotebook Do not use events to call wxAuiNotebook functions from wxAuiTabCtrl, as this interfered with handling the events in the application code in highly non-obvious ways. Just call wxAuiNotebook functions directly from wxAuiTabCtrl code and stop handling wxEVT_AUI_XXX in wxAuiNotebook itself. Add wxAuiTabEventSource to avoid making wxAuiTabCtrl itself friend of wxAuiNotebook: this allows to define the subset of private functions of the latter that the former can call. Also fix a couple of places where wrong indices, corresponding to the position of the tabs in their tab control, were used instead of the correct logical page indices. Closes #25544. --- include/wx/aui/auibook.h | 38 +++-- src/aui/auibook.cpp | 321 ++++++++++++++++++--------------------- 2 files changed, 174 insertions(+), 185 deletions(-) diff --git a/include/wx/aui/auibook.h b/include/wx/aui/auibook.h index 62c1d6c2a1..8ccd43128b 100644 --- a/include/wx/aui/auibook.h +++ b/include/wx/aui/auibook.h @@ -372,6 +372,9 @@ public: // tab control in screen coordinates. wxRect GetHintScreenRect() const; + // Get parent notebook (always valid). + wxAuiNotebook* GetBook() const; + protected: // choose the default border for this window virtual wxBorder GetDefaultBorder() const override { return wxBORDER_NONE; } @@ -387,7 +390,6 @@ protected: void OnRightUp(wxMouseEvent& evt); void OnMotion(wxMouseEvent& evt); void OnLeaveWindow(wxMouseEvent& evt); - void OnButton(wxAuiNotebookEvent& evt); void OnSetFocus(wxFocusEvent& event); void OnKillFocus(wxFocusEvent& event); void OnChar(wxKeyEvent& event); @@ -410,6 +412,8 @@ private: // Reset dragging-related fields above to their initial values. void DoEndDragging(); + void OnButton(int tabIdx, int button); + #ifndef SWIG wxDECLARE_CLASS(wxAuiTabCtrl); wxDECLARE_EVENT_TABLE(); @@ -619,21 +623,31 @@ protected: void OnChildFocusNotebook(wxChildFocusEvent& evt); void OnRender(wxAuiManagerEvent& evt); void OnSize(wxSizeEvent& evt); - void OnTabClicked(wxAuiNotebookEvent& evt); - void OnTabBeginDrag(wxAuiNotebookEvent& evt); - void OnTabDragMotion(wxAuiNotebookEvent& evt); - void OnTabEndDrag(wxAuiNotebookEvent& evt); - void OnTabCancelDrag(wxAuiNotebookEvent& evt); - void OnTabButton(wxAuiNotebookEvent& evt); - void OnTabMiddleDown(wxAuiNotebookEvent& evt); - void OnTabMiddleUp(wxAuiNotebookEvent& evt); - void OnTabRightDown(wxAuiNotebookEvent& evt); - void OnTabRightUp(wxAuiNotebookEvent& evt); - void OnTabBgDClick(wxAuiNotebookEvent& evt); void OnNavigationKeyNotebook(wxNavigationKeyEvent& event); void OnSysColourChanged(wxSysColourChangedEvent& event); void OnDpiChanged(wxDPIChangedEvent& event); + // The functions below are called by wxAuiTabCtrl via wxAuiTabEventSource. + // + // They all take the control which generated the event (never null) and all + // but one take the position of the tab associated with the event in this + // control: notice that this is _not_ the same as the index of the page, in + // general, m_tabs.GetIdxFromWindow(wxAuiTabCtrl::GetWindowFromIdx()) must + // be used to get it. + friend class wxAuiTabEventSource; + + void OnTabClicked(wxAuiTabCtrl* ctrl, int tabIdx); + void OnTabBeginDrag(wxAuiTabCtrl* ctrl, int tabIdx); + void OnTabDragMotion(wxAuiTabCtrl* ctrl, int tabIdx); + void OnTabEndDrag(wxAuiTabCtrl* ctrl, int tabIdx); + void OnTabCancelDrag(wxAuiTabCtrl* ctrl, int tabIdx); + void OnTabButton(wxAuiTabCtrl* ctrl, int tabIdx, int button_id); + void OnTabMiddleDown(wxAuiTabCtrl* ctrl, int tabIdx); + void OnTabMiddleUp(wxAuiTabCtrl* ctrl, int tabIdx); + void OnTabRightDown(wxAuiTabCtrl* ctrl, int tabIdx); + void OnTabRightUp(wxAuiTabCtrl* ctrl, int tabIdx); + void OnTabBgDClick(wxAuiTabCtrl* ctrl); + // set selection to the given window (which must be non-null and be one of // our pages, otherwise an assert is raised) void SetSelectionToWindow(wxWindow *win); diff --git a/src/aui/auibook.cpp b/src/aui/auibook.cpp index f6dc3ddd4a..e39e9a3995 100644 --- a/src/aui/auibook.cpp +++ b/src/aui/auibook.cpp @@ -88,6 +88,71 @@ std::vector MakePageButtons(unsigned int flags) } // anonymous namespace +// wxAuiTabEventSource +// +// This class is the "attorney" in "attorney-client" idiom used to allow +// wxAuiTabCtrl to call some (but not all) wxAuiNotebook private functions. +class wxAuiTabEventSource +{ +private: + static void TabClicked(wxAuiTabCtrl* ctrl, int tabIdx) + { + ctrl->GetBook()->OnTabClicked(ctrl, tabIdx); + } + + static void TabBeginDrag(wxAuiTabCtrl* ctrl, int tabIdx) + { + ctrl->GetBook()->OnTabBeginDrag(ctrl, tabIdx); + } + + static void TabDragMotion(wxAuiTabCtrl* ctrl, int tabIdx) + { + ctrl->GetBook()->OnTabDragMotion(ctrl, tabIdx); + } + + static void TabEndDrag(wxAuiTabCtrl* ctrl, int tabIdx) + { + ctrl->GetBook()->OnTabEndDrag(ctrl, tabIdx); + } + + static void TabCancelDrag(wxAuiTabCtrl* ctrl, int tabIdx) + { + ctrl->GetBook()->OnTabCancelDrag(ctrl, tabIdx); + } + + static void TabButton(wxAuiTabCtrl* ctrl, int tabIdx, int button_id) + { + ctrl->GetBook()->OnTabButton(ctrl, tabIdx, button_id); + } + + static void TabMiddleDown(wxAuiTabCtrl* ctrl, int tabIdx) + { + ctrl->GetBook()->OnTabMiddleDown(ctrl, tabIdx); + } + + static void TabMiddleUp(wxAuiTabCtrl* ctrl, int tabIdx) + { + ctrl->GetBook()->OnTabMiddleUp(ctrl, tabIdx); + } + + static void TabRightDown(wxAuiTabCtrl* ctrl, int tabIdx) + { + ctrl->GetBook()->OnTabRightDown(ctrl, tabIdx); + } + + static void TabRightUp(wxAuiTabCtrl* ctrl, int tabIdx) + { + ctrl->GetBook()->OnTabRightUp(ctrl, tabIdx); + } + + static void TabBgDClick(wxAuiTabCtrl* ctrl) + { + ctrl->GetBook()->OnTabBgDClick(ctrl); + } + + friend class wxAuiTabCtrl; +}; + // -- wxAuiTabContainer class implementation -- @@ -1256,7 +1321,6 @@ wxBEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl) EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp) EVT_MOTION(wxAuiTabCtrl::OnMotion) EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow) - EVT_AUINOTEBOOK_BUTTON(wxID_ANY, wxAuiTabCtrl::OnButton) EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus) EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus) EVT_CHAR(wxAuiTabCtrl::OnChar) @@ -1279,6 +1343,12 @@ wxAuiTabCtrl::wxAuiTabCtrl(wxAuiNotebook* parent, wxWindowID id) wxAuiTabCtrl::~wxAuiTabCtrl() = default; +// Our parent is always wxAuiNotebook, by construction, so the cast is safe. +wxAuiNotebook* wxAuiTabCtrl::GetBook() const +{ + return static_cast(GetParent()); +} + void wxAuiTabCtrl::DoShowTab(int idx) { DoShowHide(); @@ -1380,11 +1450,7 @@ void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt) // have multiple tab controls if ((new_selection != GetActivePage()) && !m_hoverButton) { - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_PAGE_CHANGING, m_windowId); - e.SetSelection(new_selection); - e.SetOldSelection(GetActivePage()); - e.SetEventObject(this); - ProcessWindowEvent(e); + wxAuiTabEventSource::TabClicked(this, new_selection); } m_clickPt.x = evt.m_x; @@ -1409,11 +1475,7 @@ void wxAuiTabCtrl::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) DoEndDragging(); - wxAuiNotebookEvent evt(wxEVT_AUINOTEBOOK_CANCEL_DRAG, m_windowId); - evt.SetSelection(GetIdxFromWindow(clickTab)); - evt.SetOldSelection(evt.GetSelection()); - evt.SetEventObject(this); - ProcessWindowEvent(evt); + wxAuiTabEventSource::TabCancelDrag(this, GetIdxFromWindow(clickTab)); } } @@ -1428,11 +1490,7 @@ void wxAuiTabCtrl::OnLeftUp(wxMouseEvent& evt) DoEndDragging(); - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_END_DRAG, m_windowId); - e.SetSelection(GetIdxFromWindow(clickTab)); - e.SetOldSelection(e.GetSelection()); - e.SetEventObject(this); - ProcessWindowEvent(e); + wxAuiTabEventSource::TabEndDrag(this, GetIdxFromWindow(clickTab)); return; } @@ -1458,11 +1516,7 @@ void wxAuiTabCtrl::OnLeftUp(wxMouseEvent& evt) if (!(m_pressedButton->curState & wxAUI_BUTTON_STATE_DISABLED)) { - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_BUTTON, m_windowId); - e.SetSelection(GetIdxFromWindow(m_clickTab)); - e.SetInt(m_pressedButton->id); - e.SetEventObject(this); - ProcessWindowEvent(e); + OnButton(GetIdxFromWindow(m_clickTab), m_pressedButton->id); } m_pressedButton = nullptr; @@ -1477,10 +1531,7 @@ void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent& evt) if (!tabInfo) return; - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP, m_windowId); - e.SetEventObject(this); - e.SetSelection(tabInfo.pos); - ProcessWindowEvent(e); + wxAuiTabEventSource::TabMiddleUp(this, tabInfo.pos); } void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent& evt) @@ -1489,10 +1540,7 @@ void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent& evt) if (!tabInfo) return; - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, m_windowId); - e.SetEventObject(this); - e.SetSelection(tabInfo.pos); - ProcessWindowEvent(e); + wxAuiTabEventSource::TabMiddleDown(this, tabInfo.pos); } void wxAuiTabCtrl::OnRightUp(wxMouseEvent& evt) @@ -1501,10 +1549,7 @@ void wxAuiTabCtrl::OnRightUp(wxMouseEvent& evt) if (!tabInfo) return; - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_RIGHT_UP, m_windowId); - e.SetEventObject(this); - e.SetSelection(tabInfo.pos); - ProcessWindowEvent(e); + wxAuiTabEventSource::TabRightUp(this, tabInfo.pos); } void wxAuiTabCtrl::OnRightDown(wxMouseEvent& evt) @@ -1513,10 +1558,7 @@ void wxAuiTabCtrl::OnRightDown(wxMouseEvent& evt) if (!tabInfo) return; - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN, m_windowId); - e.SetEventObject(this); - e.SetSelection(tabInfo.pos); - ProcessWindowEvent(e); + wxAuiTabEventSource::TabRightDown(this, tabInfo.pos); } void wxAuiTabCtrl::OnLeftDClick(wxMouseEvent& evt) @@ -1525,9 +1567,7 @@ void wxAuiTabCtrl::OnLeftDClick(wxMouseEvent& evt) if (!TabHitTest(pos) && !ButtonHitTest(pos)) { - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_BG_DCLICK, m_windowId); - e.SetEventObject(this); - ProcessWindowEvent(e); + wxAuiTabEventSource::TabBgDClick(this); } } @@ -1602,11 +1642,7 @@ void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt) if (m_isDragging) { - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_DRAG_MOTION, m_windowId); - e.SetSelection(GetIdxFromWindow(m_clickTab)); - e.SetOldSelection(e.GetSelection()); - e.SetEventObject(this); - ProcessWindowEvent(e); + wxAuiTabEventSource::TabDragMotion(this, GetIdxFromWindow(m_clickTab)); return; } @@ -1632,11 +1668,7 @@ void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt) } } - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_BEGIN_DRAG, m_windowId); - e.SetSelection(idx); - e.SetOldSelection(e.GetSelection()); - e.SetEventObject(this); - ProcessWindowEvent(e); + wxAuiTabEventSource::TabBeginDrag(this, idx); m_isDragging = true; } @@ -1655,10 +1687,8 @@ void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event)) SetHoverTab(nullptr); } -void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event) +void wxAuiTabCtrl::OnButton(int tabIdx, int button) { - int button = event.GetInt(); - if (button == wxAUI_BUTTON_LEFT || button == wxAUI_BUTTON_RIGHT) { if (button == wxAUI_BUTTON_LEFT) @@ -1683,16 +1713,12 @@ void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event) if (idx != -1) { - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_PAGE_CHANGING, m_windowId); - e.SetSelection(idx); - e.SetOldSelection(GetActivePage()); - e.SetEventObject(this); - ProcessWindowEvent(e); + wxAuiTabEventSource::TabClicked(this, idx); } } else { - event.Skip(); + wxAuiTabEventSource::TabButton(this, tabIdx, button); } } @@ -1826,11 +1852,7 @@ void wxAuiTabCtrl::OnChar(wxKeyEvent& event) if (newPage != -1) { - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_PAGE_CHANGING, m_windowId); - e.SetSelection(newPage); - e.SetOldSelection(newPage); - e.SetEventObject(this); - this->ProcessWindowEvent(e); + wxAuiTabEventSource::TabClicked(this, newPage); } else event.Skip(); @@ -1987,45 +2009,9 @@ struct wxAuiNotebook::TabInfo : wxAuiNotebookPosition wxAuiNotebookPage* pageInfo = nullptr; }; -#define EVT_AUI_RANGE(id1, id2, event, func) \ - wx__DECLARE_EVT2(event, id1, id2, wxAuiNotebookEventHandler(func)) - wxBEGIN_EVENT_TABLE(wxAuiNotebook, wxBookCtrlBase) EVT_SIZE(wxAuiNotebook::OnSize) EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocusNotebook) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_PAGE_CHANGING, - wxAuiNotebook::OnTabClicked) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_BEGIN_DRAG, - wxAuiNotebook::OnTabBeginDrag) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_END_DRAG, - wxAuiNotebook::OnTabEndDrag) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_CANCEL_DRAG, - wxAuiNotebook::OnTabCancelDrag) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_DRAG_MOTION, - wxAuiNotebook::OnTabDragMotion) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_BUTTON, - wxAuiNotebook::OnTabButton) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, - wxAuiNotebook::OnTabMiddleDown) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP, - wxAuiNotebook::OnTabMiddleUp) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN, - wxAuiNotebook::OnTabRightDown) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_TAB_RIGHT_UP, - wxAuiNotebook::OnTabRightUp) - EVT_AUI_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500, - wxEVT_AUINOTEBOOK_BG_DCLICK, - wxAuiNotebook::OnTabBgDClick) EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKeyNotebook) EVT_SYS_COLOUR_CHANGED(wxAuiNotebook::OnSysColourChanged) EVT_DPI_CHANGED(wxAuiNotebook::OnDpiChanged) @@ -3070,28 +3056,23 @@ void wxAuiNotebook::OnSize(wxSizeEvent& evt) evt.Skip(); } -void wxAuiNotebook::OnTabClicked(wxAuiNotebookEvent& evt) +void wxAuiNotebook::OnTabClicked(wxAuiTabCtrl* ctrl, int tabIdx) { - wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject(); - wxASSERT(ctrl != nullptr); - - wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection()); + wxWindow* const wnd = ctrl->GetWindowFromIdx(tabIdx); wxASSERT(wnd != nullptr); + // Note that this will generate wxEVT_AUINOTEBOOK_PAGE_CHANG{ING,ED} events. SetSelectionToWindow(wnd); } -void wxAuiNotebook::OnTabBgDClick(wxAuiNotebookEvent& evt) +void wxAuiNotebook::OnTabBgDClick(wxAuiTabCtrl* ctrl) { // select the tab ctrl which received the db click - int selection; - wxWindow* wnd; - wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject(); - if ( (ctrl != nullptr) - && ((selection = ctrl->GetActivePage()) != wxNOT_FOUND) - && ((wnd = ctrl->GetWindowFromIdx(selection)) != nullptr)) + const int selection = ctrl->GetActivePage(); + if ( selection != wxNOT_FOUND ) { - SetSelectionToWindow(wnd); + if ( wxWindow* const wnd = ctrl->GetWindowFromIdx(selection) ) + SetSelectionToWindow(wnd); } // notify owner that the tabbar background has been double-clicked @@ -3100,25 +3081,37 @@ void wxAuiNotebook::OnTabBgDClick(wxAuiNotebookEvent& evt) ProcessWindowEvent(e); } -void wxAuiNotebook::OnTabBeginDrag(wxAuiNotebookEvent&) +void wxAuiNotebook::OnTabBeginDrag(wxAuiTabCtrl* ctrl, int tabIdx) { m_lastDropMovePos = -1; + + wxWindow* const wnd = ctrl->GetWindowFromIdx(tabIdx); + + wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_BEGIN_DRAG, m_windowId); + e.SetSelection(m_tabs.GetIdxFromWindow(wnd)); + e.SetOldSelection(e.GetSelection()); + e.SetEventObject(this); + ProcessWindowEvent(e); } -void wxAuiNotebook::OnTabDragMotion(wxAuiNotebookEvent& evt) +void wxAuiNotebook::OnTabDragMotion(wxAuiTabCtrl* src_tabs, int src_idx) { + wxWindow* const wnd = src_tabs->GetWindowFromIdx(src_idx); + + wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_DRAG_MOTION, m_windowId); + e.SetSelection(m_tabs.GetIdxFromWindow(wnd)); + e.SetOldSelection(e.GetSelection()); + e.SetEventObject(this); + ProcessWindowEvent(e); + wxPoint screen_pt = ::wxGetMousePosition(); wxPoint client_pt = ScreenToClient(screen_pt); - wxAuiTabCtrl* const src_tabs = (wxAuiTabCtrl*)evt.GetEventObject(); wxAuiTabCtrl* const dest_tabs = GetTabCtrlFromPoint(client_pt); if (dest_tabs == src_tabs) { - if (src_tabs) - { - src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW)); - } + src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW)); // always hide the hint for inner-tabctrl drag m_mgr.HideHint(); @@ -3140,7 +3133,6 @@ void wxAuiNotebook::OnTabDragMotion(wxAuiNotebookEvent& evt) // this is an inner-tab drag/reposition if (auto const destTabInfo = dest_tabs->TabHitTest(pt, flags)) { - int src_idx = evt.GetSelection(); wxCHECK_RET( src_idx != -1, "Invalid source tab?" ); int dest_idx = destTabInfo.pos; @@ -3255,7 +3247,7 @@ void wxAuiNotebook::OnTabDragMotion(wxAuiNotebookEvent& evt) { if (src_tabs) { - const auto& src_page = src_tabs->GetPage(evt.GetSelection()); + const auto& src_page = src_tabs->GetPage(src_idx); if (GetDropIndex(src_page, dest_tabs, screen_pt) == wxNOT_FOUND) { m_mgr.HideHint(); @@ -3275,14 +3267,12 @@ void wxAuiNotebook::OnTabDragMotion(wxAuiNotebookEvent& evt) -void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent& evt) +void wxAuiNotebook::OnTabEndDrag(wxAuiTabCtrl* src_tabs, int src_idx) { + wxWindow* src_page = src_tabs->GetWindowFromIdx(src_idx); + m_mgr.HideHint(); - - wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject(); - wxCHECK_RET( src_tabs, wxT("no source object?") ); - src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW)); // get the mouse position, which will be used to determine the drop point @@ -3312,8 +3302,8 @@ void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent& evt) // find out from the destination control // if it's ok to drop this tab here wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_ALLOW_DND, m_windowId); - e.SetSelection(evt.GetSelection()); - e.SetOldSelection(evt.GetSelection()); + e.SetSelection(src_idx); + e.SetOldSelection(e.GetSelection()); e.SetEventObject(this); e.SetDragSource(this); e.Veto(); // dropping must be explicitly approved by control owner @@ -3328,8 +3318,6 @@ void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent& evt) } // drop was allowed - int src_idx = evt.GetSelection(); - wxWindow* src_page = src_tabs->GetWindowFromIdx(src_idx); // Check that it's not an impossible parent relationship wxWindow* p = nb; @@ -3377,8 +3365,8 @@ void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent& evt) // notify owner that the tab has been dragged wxAuiNotebookEvent e2(wxEVT_AUINOTEBOOK_DRAG_DONE, m_windowId); - e2.SetSelection(evt.GetSelection()); - e2.SetOldSelection(evt.GetSelection()); + e2.SetSelection(src_idx); + e2.SetOldSelection(src_idx); e2.SetEventObject(this); ProcessWindowEvent(e2); @@ -3395,7 +3383,7 @@ void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent& evt) if ((m_flags & wxAUI_NB_TAB_SPLIT) && m_tabs.GetPageCount() >= 2) { - wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection()); + wxAuiNotebookPage page_info = src_tabs->GetPage(src_idx); // If the pointer is in an existing tab frame, do a tab insert wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt); @@ -3468,24 +3456,26 @@ void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent& evt) // notify owner that the tab has been dragged wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_DRAG_DONE, m_windowId); - e.SetSelection(evt.GetSelection()); - e.SetOldSelection(evt.GetSelection()); + e.SetSelection(m_tabs.GetIdxFromWindow(src_page)); + e.SetOldSelection(e.GetSelection()); e.SetEventObject(this); ProcessWindowEvent(e); } -void wxAuiNotebook::OnTabCancelDrag(wxAuiNotebookEvent& command_evt) +void wxAuiNotebook::OnTabCancelDrag(wxAuiTabCtrl* ctrl, int tabIdx) { - wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt; - m_mgr.HideHint(); - wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject(); - wxCHECK_RET( src_tabs, wxT("no source object?") ); + ctrl->SetCursor(wxCursor(wxCURSOR_ARROW)); - src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW)); + wxWindow* const wnd = ctrl->GetWindowFromIdx(tabIdx); + + wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_CANCEL_DRAG, m_windowId); + e.SetSelection(m_tabs.GetIdxFromWindow(wnd)); + e.SetEventObject(this); + ProcessWindowEvent(e); } wxAuiTabCtrl* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint& pt) @@ -3686,16 +3676,11 @@ void wxAuiNotebook::OnNavigationKeyNotebook(wxNavigationKeyEvent& event) } } -void wxAuiNotebook::OnTabButton(wxAuiNotebookEvent& evt) +void wxAuiNotebook::OnTabButton(wxAuiTabCtrl* tabs, int tabIdx, int button_id) { - wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject(); - - int button_id = evt.GetInt(); - if (button_id == wxAUI_BUTTON_CLOSE) { - int selection = evt.GetSelection(); - + int selection = tabIdx; if (selection == -1) { // if the close button is to the right, use the active @@ -3712,7 +3697,7 @@ void wxAuiNotebook::OnTabButton(wxAuiNotebookEvent& evt) e.SetSelection(m_tabs.GetIdxFromWindow(close_wnd)); const int idx = m_tabs.GetIdxFromWindow(close_wnd); e.SetSelection(idx); - e.SetOldSelection(evt.GetSelection()); + e.SetOldSelection(selection); e.SetEventObject(this); ProcessWindowEvent(e); if (!e.IsAllowed()) @@ -3744,7 +3729,7 @@ void wxAuiNotebook::OnTabButton(wxAuiNotebookEvent& evt) { // For now we don't send any event, this can be always added later if // necessary. - wxWindow* const wnd = tabs->GetWindowFromIdx(evt.GetSelection()); + wxWindow* const wnd = tabs->GetWindowFromIdx(tabIdx); const auto idx = m_tabs.GetIdxFromWindow(wnd); @@ -3772,11 +3757,9 @@ void wxAuiNotebook::OnTabButton(wxAuiNotebookEvent& evt) } -void wxAuiNotebook::OnTabMiddleDown(wxAuiNotebookEvent& evt) +void wxAuiNotebook::OnTabMiddleDown(wxAuiTabCtrl* ctrl, int tabIdx) { - // patch event through to owner - wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject(); - wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection()); + wxWindow* const wnd = ctrl->GetWindowFromIdx(tabIdx); wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, m_windowId); e.SetSelection(m_tabs.GetIdxFromWindow(wnd)); @@ -3784,15 +3767,14 @@ void wxAuiNotebook::OnTabMiddleDown(wxAuiNotebookEvent& evt) ProcessWindowEvent(e); } -void wxAuiNotebook::OnTabMiddleUp(wxAuiNotebookEvent& evt) +void wxAuiNotebook::OnTabMiddleUp(wxAuiTabCtrl* ctrl, int tabIdx) { // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle // click should act like a tab close action. However, first // give the owner an opportunity to handle the middle up event // for custom action - wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject(); - wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection()); + wxWindow* const wnd = ctrl->GetWindowFromIdx(tabIdx); wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP, m_windowId); e.SetSelection(m_tabs.GetIdxFromWindow(wnd)); @@ -3807,15 +3789,13 @@ void wxAuiNotebook::OnTabMiddleUp(wxAuiNotebookEvent& evt) return; // simulate the user pressing the close button on the tab - evt.SetInt(wxAUI_BUTTON_CLOSE); - OnTabButton(evt); + OnTabButton(ctrl, tabIdx, wxAUI_BUTTON_CLOSE); } -void wxAuiNotebook::OnTabRightDown(wxAuiNotebookEvent& evt) +void wxAuiNotebook::OnTabRightDown(wxAuiTabCtrl* ctrl, int tabIdx) { - // patch event through to owner - wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject(); - wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection()); + // Generate corresponding wxEVT_AUI event. + wxWindow* wnd = ctrl->GetWindowFromIdx(tabIdx); wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN, m_windowId); e.SetSelection(m_tabs.GetIdxFromWindow(wnd)); @@ -3823,11 +3803,10 @@ void wxAuiNotebook::OnTabRightDown(wxAuiNotebookEvent& evt) ProcessWindowEvent(e); } -void wxAuiNotebook::OnTabRightUp(wxAuiNotebookEvent& evt) +void wxAuiNotebook::OnTabRightUp(wxAuiTabCtrl* ctrl, int tabIdx) { - // patch event through to owner - wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject(); - wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection()); + // Generate corresponding wxEVT_AUI event. + wxWindow* wnd = ctrl->GetWindowFromIdx(tabIdx); wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_TAB_RIGHT_UP, m_windowId); e.SetSelection(m_tabs.GetIdxFromWindow(wnd)); @@ -3896,11 +3875,7 @@ bool wxAuiNotebook::ShowWindowMenu() if (idx != -1) { - wxAuiNotebookEvent e(wxEVT_AUINOTEBOOK_PAGE_CHANGING, tabCtrl->GetId()); - e.SetSelection(idx); - e.SetOldSelection(tabCtrl->GetActivePage()); - e.SetEventObject(tabCtrl); - ProcessWindowEvent(e); + OnTabClicked(tabCtrl, idx); return true; }