Use a simple stack of windows instead of a separate singly linked list and a
separate current capture pointer.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74675
c3d73ce0-8a6f-49c7-b76d-
6d57e0e08775
namespace wxMouseCapture
{
namespace wxMouseCapture
{
-// the stack of windows which have captured the mouse
-struct WindowNext
-{
- wxWindow *win;
- WindowNext *next;
-} *next = NULL;
-
-// the window that currently has mouse capture
-wxWindow *current = NULL;
+// Stack of the windows which previously had the capture, the top most element
+// is the window that has the mouse capture now.
+//
+// NB: We use wxVector and not wxStack to be able to examine all of the stack
+// elements for debug checks, but only the stack operations should be
+// performed with this vector.
+wxVector<wxWindow*> stack;
// Flag preventing reentrancy in {Capture,Release}Mouse().
wxRecursionGuardFlag changing;
// Flag preventing reentrancy in {Capture,Release}Mouse().
wxRecursionGuardFlag changing;
wxWindow *winOld = GetCapture();
if ( winOld )
wxWindow *winOld = GetCapture();
if ( winOld )
((wxWindowBase*) winOld)->DoReleaseMouse();
((wxWindowBase*) winOld)->DoReleaseMouse();
- // save it on stack
- wxMouseCapture::WindowNext *item = new wxMouseCapture::WindowNext;
- item->win = winOld;
- item->next = wxMouseCapture::next;
- wxMouseCapture::next = item;
- }
- //else: no mouse capture to save
-
- wxMouseCapture::current = (wxWindow*)this;
+
+ wxMouseCapture::stack.push_back(static_cast<wxWindow*>(this));
}
void wxWindowBase::ReleaseMouse()
}
void wxWindowBase::ReleaseMouse()
wxASSERT_MSG( GetCapture() == this,
"attempt to release mouse, but this window hasn't captured it" );
wxASSERT_MSG( GetCapture() == this,
"attempt to release mouse, but this window hasn't captured it" );
- wxASSERT_MSG( wxMouseCapture::current == this,
- "attempt to release mouse, but this window hasn't captured it" );
- wxMouseCapture::current = NULL;
- if ( wxMouseCapture::next )
- {
- ((wxWindowBase*)wxMouseCapture::next->win)->DoCaptureMouse();
- wxMouseCapture::current = wxMouseCapture::next->win;
+ wxCHECK_RET( !wxMouseCapture::stack.empty(),
+ "Releasing mouse capture but capture stack empty?" );
+ wxCHECK_RET( wxMouseCapture::stack.back() == this,
+ "Window releasing mouse capture not top of capture stack?" );
+
+ wxMouseCapture::stack.pop_back();
- wxMouseCapture::WindowNext *item = wxMouseCapture::next;
- wxMouseCapture::next = item->next;
- delete item;
+ // Restore the capture to the previous window, if any.
+ if ( !wxMouseCapture::stack.empty() )
+ {
+ ((wxWindowBase*)wxMouseCapture::stack.back())->DoCaptureMouse();
- //else: stack is empty, no previous capture
wxLogTrace(wxT("mousecapture"),
(const wxChar *) wxT("After ReleaseMouse() mouse is captured by %p"),
wxLogTrace(wxT("mousecapture"),
(const wxChar *) wxT("After ReleaseMouse() mouse is captured by %p"),
// if the capture was lost unexpectedly, notify every window that has
// capture (on stack or current) about it and clear the stack:
// if the capture was lost unexpectedly, notify every window that has
// capture (on stack or current) about it and clear the stack:
-
- if ( wxMouseCapture::current )
+ while ( !wxMouseCapture::stack.empty() )
- DoNotifyWindowAboutCaptureLost(wxMouseCapture::current);
- wxMouseCapture::current = NULL;
- }
-
- while ( wxMouseCapture::next )
- {
- wxMouseCapture::WindowNext *item = wxMouseCapture::next;
- wxMouseCapture::next = item->next;
-
- DoNotifyWindowAboutCaptureLost(item->win);
+ DoNotifyWindowAboutCaptureLost(wxMouseCapture::stack.back());
+ wxMouseCapture::stack.pop_back();