]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/wincmn.cpp
Avoid using wxHtmlTag::HasParam() unnecessarily.
[wxWidgets.git] / src / common / wincmn.cpp
index b3479ab8d031ab939431cab645f2590f04c5d4ff..ad4887093bfde750c559657f53c9189170704fd2 100644 (file)
@@ -89,6 +89,14 @@ wxMenu *wxCurrentPopupMenu = NULL;
 
 extern WXDLLEXPORT_DATA(const char) wxPanelNameStr[] = "panel";
 
 
 extern WXDLLEXPORT_DATA(const char) wxPanelNameStr[] = "panel";
 
+namespace wxMouseCapture
+{
+
+// Check if the given window is in the capture stack.
+bool IsInCaptureStack(wxWindowBase* win);
+
+} // wxMouseCapture
+
 // ----------------------------------------------------------------------------
 // static data
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // static data
 // ----------------------------------------------------------------------------
@@ -448,7 +456,9 @@ bool wxWindowBase::ToggleWindowStyle(int flag)
 // common clean up
 wxWindowBase::~wxWindowBase()
 {
 // common clean up
 wxWindowBase::~wxWindowBase()
 {
-    wxASSERT_MSG( GetCapture() != this, wxT("attempt to destroy window with mouse capture") );
+    wxASSERT_MSG( !wxMouseCapture::IsInCaptureStack(this),
+                    "Destroying window before releasing mouse capture: this "
+                    "will result in a crash later." );
 
     // FIXME if these 2 cases result from programming errors in the user code
     //       we should probably assert here instead of silently fixing them
 
     // FIXME if these 2 cases result from programming errors in the user code
     //       we should probably assert here instead of silently fixing them
@@ -1103,6 +1113,12 @@ void wxWindowBase::SendSizeEventToParent(int flags)
         parent->SendSizeEvent(flags);
 }
 
         parent->SendSizeEvent(flags);
 }
 
+bool wxWindowBase::CanScroll(int orient) const
+{
+    return (m_windowStyle &
+            (orient == wxHORIZONTAL ? wxHSCROLL : wxVSCROLL)) != 0;
+}
+
 bool wxWindowBase::HasScrollbar(int orient) const
 {
     // if scrolling in the given direction is disabled, we can't have the
 bool wxWindowBase::HasScrollbar(int orient) const
 {
     // if scrolling in the given direction is disabled, we can't have the
@@ -1824,6 +1840,12 @@ wxWindow *wxWindowBase::FindWindow(long id) const
     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
     {
         wxWindowBase *child = node->GetData();
     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
     {
         wxWindowBase *child = node->GetData();
+
+        // As usual, don't recurse into child dialogs, finding a button in a
+        // child dialog when looking in this window would be unexpected.
+        if ( child->IsTopLevel() )
+            continue;
+
         res = child->FindWindow( id );
     }
 
         res = child->FindWindow( id );
     }
 
@@ -1840,6 +1862,11 @@ wxWindow *wxWindowBase::FindWindow(const wxString& name) const
     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
     {
         wxWindow *child = node->GetData();
     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
     {
         wxWindow *child = node->GetData();
+
+        // As in FindWindow() overload above, never recurse into child dialogs.
+        if ( child->IsTopLevel() )
+            continue;
+
         res = child->FindWindow(name);
     }
 
         res = child->FindWindow(name);
     }
 
@@ -3207,19 +3234,30 @@ wxHitTest wxWindowBase::DoHitTest(wxCoord x, wxCoord y) const
 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;
 
+bool IsInCaptureStack(wxWindowBase* win)
+{
+    for ( wxVector<wxWindow*>::const_iterator it = stack.begin();
+          it != stack.end();
+          ++it )
+    {
+        if ( *it == win )
+            return true;
+    }
+
+    return false;
+}
+
 } // wxMouseCapture
 
 void wxWindowBase::CaptureMouse()
 } // wxMouseCapture
 
 void wxWindowBase::CaptureMouse()
@@ -3229,21 +3267,16 @@ void wxWindowBase::CaptureMouse()
     wxRecursionGuard guard(wxMouseCapture::changing);
     wxASSERT_MSG( !guard.IsInside(), wxT("recursive CaptureMouse call?") );
 
     wxRecursionGuard guard(wxMouseCapture::changing);
     wxASSERT_MSG( !guard.IsInside(), wxT("recursive CaptureMouse call?") );
 
+    wxASSERT_MSG( !wxMouseCapture::IsInCaptureStack(this),
+                    "Recapturing the mouse in the same window?" );
+
     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
-
     DoCaptureMouse();
     DoCaptureMouse();
-    wxMouseCapture::current = (wxWindow*)this;
+
+    wxMouseCapture::stack.push_back(static_cast<wxWindow*>(this));
 }
 
 void wxWindowBase::ReleaseMouse()
 }
 
 void wxWindowBase::ReleaseMouse()
@@ -3253,27 +3286,50 @@ void wxWindowBase::ReleaseMouse()
     wxRecursionGuard guard(wxMouseCapture::changing);
     wxASSERT_MSG( !guard.IsInside(), wxT("recursive ReleaseMouse call?") );
 
     wxRecursionGuard guard(wxMouseCapture::changing);
     wxASSERT_MSG( !guard.IsInside(), wxT("recursive ReleaseMouse call?") );
 
-    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" );
+#if wxDEBUG_LEVEL
+    wxWindow* const winCapture = GetCapture();
+    if ( !winCapture )
+    {
+        wxFAIL_MSG
+        (
+          wxString::Format
+          (
+            "Releasing mouse in %p(%s) but it is not captured",
+            this, GetClassInfo()->GetClassName()
+          )
+        );
+    }
+    else if ( winCapture != this )
+    {
+        wxFAIL_MSG
+        (
+          wxString::Format
+          (
+            "Releasing mouse in %p(%s) but it is captured by %p(%s)",
+            this, GetClassInfo()->GetClassName(),
+            winCapture, winCapture->GetClassInfo()->GetClassName()
+          )
+        );
+    }
+#endif // wxDEBUG_LEVEL
 
     DoReleaseMouse();
 
     DoReleaseMouse();
-    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::WindowNext *item = wxMouseCapture::next;
-        wxMouseCapture::next = item->next;
-        delete item;
+    wxMouseCapture::stack.pop_back();
+
+    // 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"),
 
     wxLogTrace(wxT("mousecapture"),
-        (const wxChar *) wxT("After ReleaseMouse() mouse is captured by %p"),
+        wxT("After ReleaseMouse() mouse is captured by %p"),
         static_cast<void*>(GetCapture()));
 }
 
         static_cast<void*>(GetCapture()));
 }
 
@@ -3302,21 +3358,11 @@ void wxWindowBase::NotifyCaptureLost()
 
     // 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());
 
 
-        delete item;
+        wxMouseCapture::stack.pop_back();
     }
 }
 
     }
 }