]> git.saurik.com Git - wxWidgets.git/commitdiff
added wxEVT_MOUSE_CAPTURE_LOST event and code for correctly handling capture loss...
authorVáclav Slavík <vslavik@fastmail.fm>
Mon, 31 Jul 2006 09:27:54 +0000 (09:27 +0000)
committerVáclav Slavík <vslavik@fastmail.fm>
Mon, 31 Jul 2006 09:27:54 +0000 (09:27 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@40391 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/latex/wx/category.tex
docs/latex/wx/mcaptevt.tex
docs/latex/wx/window.tex
include/wx/event.h
include/wx/html/htmlwin.h
include/wx/window.h
src/common/event.cpp
src/common/wincmn.cpp
src/html/htmlwin.cpp
src/msw/window.cpp

index 4c095c6535afc3f91634ed7d1750f74a48653372..a4843b42e2fe1988ef1a254f4ec98d17c20b8847 100644 (file)
@@ -257,6 +257,7 @@ An event object contains information about a specific event. Event handlers
 \twocolitem{\helpref{wxMaximizeEvent}{wxmaximizeevent}}{A maximize event}
 \twocolitem{\helpref{wxMenuEvent}{wxmenuevent}}{A menu event}
 \twocolitem{\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}}{A mouse capture changed event}
 \twocolitem{\helpref{wxMaximizeEvent}{wxmaximizeevent}}{A maximize event}
 \twocolitem{\helpref{wxMenuEvent}{wxmenuevent}}{A menu event}
 \twocolitem{\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}}{A mouse capture changed event}
+\twocolitem{\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}}{A mouse capture lost event}
 \twocolitem{\helpref{wxMouseEvent}{wxmouseevent}}{A mouse event}
 \twocolitem{\helpref{wxMoveEvent}{wxmoveevent}}{A move event}
 \twocolitem{\helpref{wxNotebookEvent}{wxnotebookevent}}{A notebook control event}
 \twocolitem{\helpref{wxMouseEvent}{wxmouseevent}}{A mouse event}
 \twocolitem{\helpref{wxMoveEvent}{wxmoveevent}}{A move event}
 \twocolitem{\helpref{wxNotebookEvent}{wxnotebookevent}}{A notebook control event}
index acdec6c832a04f4d82cd3290e838cd1bebbf7870..fc6d032f9d80b0bbf665bbf8f3372bd847e8c7e0 100644 (file)
@@ -29,6 +29,7 @@ function that takes a wxMouseCaptureChangedEvent argument.
 
 \wxheading{See also}
 
 
 \wxheading{See also}
 
+\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
 \helpref{Event handling overview}{eventhandlingoverview}, 
 \helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse}, 
 \helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse}, 
 \helpref{Event handling overview}{eventhandlingoverview}, 
 \helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse}, 
 \helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse}, 
@@ -48,3 +49,51 @@ Constructor.
 
 Returns the window that gained the capture, or NULL if it was a non-wxWidgets window.
 
 
 Returns the window that gained the capture, or NULL if it was a non-wxWidgets window.
 
+
+\section{\class{wxMouseCaptureLostEvent}}\label{wxmousecapturelostevent}
+
+An mouse capture lost event is sent to a window that obtained mouse capture,
+which was subsequently loss due to "external" event, for example when a dialog
+box is shown or if another application captures the mouse.
+
+If this happens, this event is sent to all windows that are on capture stack
+(i.e. called CaptureMouse, but didn't call ReleaseMouse yet). The event is
+{\em not} sent if the capture changes because of a call to CaptureMouse or
+ReleaseMouse.
+
+This event is currently emitted under Windows only.
+
+\wxheading{Derived from}
+
+\helpref{wxEvent}{wxevent}\\
+\helpref{wxObject}{wxobject}
+
+\wxheading{Include files}
+
+<wx/event.h>
+
+\wxheading{Event table macros}
+
+To process this event, use the following event handler macro to direct input to
+a member function that takes a wxMouseCaptureLostEvent argument.
+
+\twocolwidtha{7cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf EVT\_MOUSE\_CAPTURE\_LOST(func)}}{Process a wxEVT\_MOUSE\_CAPTURE\_LOST event.}
+\end{twocollist}
+
+\wxheading{See also}
+
+\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
+\helpref{Event handling overview}{eventhandlingoverview}, 
+\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse}, 
+\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse}, 
+\helpref{wxWindow::GetCapture}{wxwindowgetcapture}
+
+\latexignore{\rtfignore{\wxheading{Members}}}
+
+\membersection{wxMouseCaptureLostEvent::wxMouseCaptureLostEvent}\label{wxmousecapturelosteventctor}
+
+\func{}{wxMouseCaptureLostEvent}{\param{wxWindowID }{windowId = 0}}
+
+Constructor.
index f30b18f3660568ee65ba7b251887f5cc7fe4ad24..9ac167e736eaec2e31d314e1ff6c7541be55a46a 100644 (file)
@@ -203,11 +203,18 @@ Note that wxWidgets maintains the stack of windows having captured the mouse
 and when the mouse is released the capture returns to the window which had had
 captured it previously and it is only really released if there were no previous
 window. In particular, this means that you must release the mouse as many times
 and when the mouse is released the capture returns to the window which had had
 captured it previously and it is only really released if there were no previous
 window. In particular, this means that you must release the mouse as many times
-as you capture it.
+as you capture it, unless the window receives
+the \helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent} event.
+
+Any application which captures the mouse in the beginning of some operation
+{\em must} handle \helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
+and cancel this operation when it receives the event. The event handler must
+not recapture mouse.
 
 \wxheading{See also}
 
 \helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse}
 
 \wxheading{See also}
 
 \helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse}
+\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
 
 
 \membersection{wxWindow::Center}\label{wxwindowcenter}
 
 
 \membersection{wxWindow::Center}\label{wxwindowcenter}
@@ -787,6 +794,7 @@ Returns the currently captured window.
 \helpref{wxWindow::HasCapture}{wxwindowhascapture},
 \helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
 \helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
 \helpref{wxWindow::HasCapture}{wxwindowhascapture},
 \helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
 \helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
+\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
 \helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
 
 
 \helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
 
 
@@ -1390,6 +1398,7 @@ Returns {\tt true} if this window has the current mouse capture.
 
 \helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
 \helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
 
 \helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
 \helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
+\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
 \helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
 
 
 \helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
 
 
@@ -2361,6 +2370,7 @@ Releases mouse input captured with \helpref{wxWindow::CaptureMouse}{wxwindowcapt
 \helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
 \helpref{wxWindow::HasCapture}{wxwindowhascapture},
 \helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
 \helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
 \helpref{wxWindow::HasCapture}{wxwindowhascapture},
 \helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
+\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
 \helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
 
 
 \helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
 
 
index 63c852c61786d3cda2babdbab09a5ebc30f49d09..4de9cac013b4803a0a82323d1b09643c57ea35c8 100644 (file)
@@ -238,14 +238,14 @@ BEGIN_DECLARE_EVENT_TYPES()
     DECLARE_EVENT_TYPE(wxEVT_ICONIZE, 413)
     DECLARE_EVENT_TYPE(wxEVT_MAXIMIZE, 414)
     DECLARE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_CHANGED, 415)
     DECLARE_EVENT_TYPE(wxEVT_ICONIZE, 413)
     DECLARE_EVENT_TYPE(wxEVT_MAXIMIZE, 414)
     DECLARE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_CHANGED, 415)
-    DECLARE_EVENT_TYPE(wxEVT_PAINT, 416)
-    DECLARE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND, 417)
-    DECLARE_EVENT_TYPE(wxEVT_NC_PAINT, 418)
-    DECLARE_EVENT_TYPE(wxEVT_PAINT_ICON, 419)
-    DECLARE_EVENT_TYPE(wxEVT_MENU_OPEN, 420)
-    DECLARE_EVENT_TYPE(wxEVT_MENU_CLOSE, 421)
-    DECLARE_EVENT_TYPE(wxEVT_MENU_HIGHLIGHT, 422)
-    // DECLARE_EVENT_TYPE(wxEVT_POPUP_MENU_INIT, 423) -- free slot
+    DECLARE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_LOST, 416)
+    DECLARE_EVENT_TYPE(wxEVT_PAINT, 417)
+    DECLARE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND, 418)
+    DECLARE_EVENT_TYPE(wxEVT_NC_PAINT, 419)
+    DECLARE_EVENT_TYPE(wxEVT_PAINT_ICON, 420)
+    DECLARE_EVENT_TYPE(wxEVT_MENU_OPEN, 421)
+    DECLARE_EVENT_TYPE(wxEVT_MENU_CLOSE, 422)
+    DECLARE_EVENT_TYPE(wxEVT_MENU_HIGHLIGHT, 423)
     DECLARE_EVENT_TYPE(wxEVT_CONTEXT_MENU, 424)
     DECLARE_EVENT_TYPE(wxEVT_SYS_COLOUR_CHANGED, 425)
     DECLARE_EVENT_TYPE(wxEVT_DISPLAY_CHANGED, 426)
     DECLARE_EVENT_TYPE(wxEVT_CONTEXT_MENU, 424)
     DECLARE_EVENT_TYPE(wxEVT_SYS_COLOUR_CHANGED, 425)
     DECLARE_EVENT_TYPE(wxEVT_DISPLAY_CHANGED, 426)
@@ -1797,6 +1797,29 @@ private:
     DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxMouseCaptureChangedEvent)
 };
 
     DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxMouseCaptureChangedEvent)
 };
 
+/*
+ wxEVT_MOUSE_CAPTURE_LOST
+ The window losing the capture receives this message, unless it released it
+ it itself or unless wxWindow::CaptureMouse was called on another window
+ (and so capture will be restored when the new capturer releases it).
+ */
+
+class WXDLLIMPEXP_CORE wxMouseCaptureLostEvent : public wxEvent
+{
+public:
+    wxMouseCaptureLostEvent(wxWindowID winid = 0)
+        : wxEvent(winid, wxEVT_MOUSE_CAPTURE_LOST)
+    {}
+
+    wxMouseCaptureLostEvent(const wxMouseCaptureLostEvent& event)
+        : wxEvent(event)
+    {}
+
+    virtual wxEvent *Clone() const { return new wxMouseCaptureLostEvent(*this); }
+
+    DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxMouseCaptureLostEvent)
+};
+
 /*
  wxEVT_DISPLAY_CHANGED
  */
 /*
  wxEVT_DISPLAY_CHANGED
  */
@@ -2584,6 +2607,7 @@ typedef void (wxEvtHandler::*wxNotifyEventFunction)(wxNotifyEvent&);
 typedef void (wxEvtHandler::*wxHelpEventFunction)(wxHelpEvent&);
 typedef void (wxEvtHandler::*wxContextMenuEventFunction)(wxContextMenuEvent&);
 typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureChangedEvent&);
 typedef void (wxEvtHandler::*wxHelpEventFunction)(wxHelpEvent&);
 typedef void (wxEvtHandler::*wxContextMenuEventFunction)(wxContextMenuEvent&);
 typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureChangedEvent&);
+typedef void (wxEvtHandler::*wxMouseCaptureLostEventFunction)(wxMouseCaptureLostEvent&);
 typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&);
 
 // these typedefs don't have the same name structure as the others, keep for
 typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&);
 
 // these typedefs don't have the same name structure as the others, keep for
@@ -2665,6 +2689,8 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
     (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxContextMenuEventFunction, &func)
 #define wxMouseCaptureChangedEventHandler(func) \
     (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxMouseCaptureChangedEventFunction, &func)
     (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxContextMenuEventFunction, &func)
 #define wxMouseCaptureChangedEventHandler(func) \
     (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxMouseCaptureChangedEventFunction, &func)
+#define wxMouseCaptureLostEventHandler(func) \
+    (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxMouseCaptureLostEventFunction, &func)
 #define wxClipboardTextEventHandler(func) \
     (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxClipboardTextEventFunction, &func)
 
 #define wxClipboardTextEventHandler(func) \
     (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxClipboardTextEventFunction, &func)
 
@@ -2883,6 +2909,7 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
 #define EVT_WINDOW_DESTROY(func) wx__DECLARE_EVT0(wxEVT_DESTROY, wxWindowDestroyEventHandler(func))
 #define EVT_SET_CURSOR(func) wx__DECLARE_EVT0(wxEVT_SET_CURSOR, wxSetCursorEventHandler(func))
 #define EVT_MOUSE_CAPTURE_CHANGED(func) wx__DECLARE_EVT0(wxEVT_MOUSE_CAPTURE_CHANGED, wxMouseCaptureChangedEventHandler(func))
 #define EVT_WINDOW_DESTROY(func) wx__DECLARE_EVT0(wxEVT_DESTROY, wxWindowDestroyEventHandler(func))
 #define EVT_SET_CURSOR(func) wx__DECLARE_EVT0(wxEVT_SET_CURSOR, wxSetCursorEventHandler(func))
 #define EVT_MOUSE_CAPTURE_CHANGED(func) wx__DECLARE_EVT0(wxEVT_MOUSE_CAPTURE_CHANGED, wxMouseCaptureChangedEventHandler(func))
+#define EVT_MOUSE_CAPTURE_LOST(func) wx__DECLARE_EVT0(wxEVT_MOUSE_CAPTURE_LOST, wxMouseCaptureLostEventHandler(func))
 
 // Mouse events
 #define EVT_LEFT_DOWN(func) wx__DECLARE_EVT0(wxEVT_LEFT_DOWN, wxMouseEventHandler(func))
 
 // Mouse events
 #define EVT_LEFT_DOWN(func) wx__DECLARE_EVT0(wxEVT_LEFT_DOWN, wxMouseEventHandler(func))
index dd22df3b2dfb51890d8857c028a8feea6384bd96..c79131c587b1ac73c9aa57bdbc858608438449c2 100644 (file)
@@ -409,6 +409,7 @@ protected:
     void OnCopy(wxCommandEvent& event);
     void OnMouseEnter(wxMouseEvent& event);
     void OnMouseLeave(wxMouseEvent& event);
     void OnCopy(wxCommandEvent& event);
     void OnMouseEnter(wxMouseEvent& event);
     void OnMouseLeave(wxMouseEvent& event);
+    void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
 #endif // wxUSE_CLIPBOARD
 
     // Returns new filter (will be stored into m_DefaultFilter variable)
 #endif // wxUSE_CLIPBOARD
 
     // Returns new filter (will be stored into m_DefaultFilter variable)
index 8f76c9e7e7fc2cad7e11a3bbcbf4802bc7f9337f..338073b554e34e1c693ecb40f2ee19ee5cdf96e9 100644 (file)
@@ -1328,12 +1328,21 @@ protected:
     // implements the window variants
     virtual void DoSetWindowVariant( wxWindowVariant variant ) ;
 
     // implements the window variants
     virtual void DoSetWindowVariant( wxWindowVariant variant ) ;
 
+    // Must be called when mouse capture is lost to send
+    // wxMouseCaptureLostEvent to windows on capture stack. The argument is
+    // the window gaining capture or NULL if outside of wx code or none.
+    static void NotifyCaptureLost(wxWindow *gainedCapture);
+
 private:
     // contains the last id generated by NewControlId
     static int ms_lastControlId;
 
     // the stack of windows which have captured the mouse
     static struct WXDLLEXPORT wxWindowNext *ms_winCaptureNext;
 private:
     // contains the last id generated by NewControlId
     static int ms_lastControlId;
 
     // the stack of windows which have captured the mouse
     static struct WXDLLEXPORT wxWindowNext *ms_winCaptureNext;
+    // the window that currently has mouse capture
+    static wxWindow *ms_winCaptureCurrent;
+    // indicates if execution is inside CaptureMouse/ReleaseMouse
+    static bool ms_winCaptureChanging;
 
     DECLARE_ABSTRACT_CLASS(wxWindowBase)
     DECLARE_NO_COPY_CLASS(wxWindowBase)
 
     DECLARE_ABSTRACT_CLASS(wxWindowBase)
     DECLARE_NO_COPY_CLASS(wxWindowBase)
index a22b1b0407440a9b23d2b5c1e712807b6579c3b8..5e40721437f53ac56ea78d16ec3973f6413cde5d 100644 (file)
@@ -87,6 +87,7 @@
     IMPLEMENT_DYNAMIC_CLASS(wxHelpEvent, wxCommandEvent)
     IMPLEMENT_DYNAMIC_CLASS(wxContextMenuEvent, wxCommandEvent)
     IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureChangedEvent, wxEvent)
     IMPLEMENT_DYNAMIC_CLASS(wxHelpEvent, wxCommandEvent)
     IMPLEMENT_DYNAMIC_CLASS(wxContextMenuEvent, wxCommandEvent)
     IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureChangedEvent, wxEvent)
+    IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureLostEvent, wxEvent)
     IMPLEMENT_DYNAMIC_CLASS(wxClipboardTextEvent, wxCommandEvent)
 #endif // wxUSE_GUI
 
     IMPLEMENT_DYNAMIC_CLASS(wxClipboardTextEvent, wxCommandEvent)
 #endif // wxUSE_GUI
 
@@ -260,6 +261,7 @@ DEFINE_EVENT_TYPE(wxEVT_SHOW)
 DEFINE_EVENT_TYPE(wxEVT_ICONIZE)
 DEFINE_EVENT_TYPE(wxEVT_MAXIMIZE)
 DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_CHANGED)
 DEFINE_EVENT_TYPE(wxEVT_ICONIZE)
 DEFINE_EVENT_TYPE(wxEVT_MAXIMIZE)
 DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_CHANGED)
+DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_LOST)
 DEFINE_EVENT_TYPE(wxEVT_PAINT)
 DEFINE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND)
 DEFINE_EVENT_TYPE(wxEVT_NC_PAINT)
 DEFINE_EVENT_TYPE(wxEVT_PAINT)
 DEFINE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND)
 DEFINE_EVENT_TYPE(wxEVT_NC_PAINT)
index 7ce145ca2482df539fa538e4fad26913eab01472..101c995e7fa33c1d6664810bb088d4882ec9bc4f 100644 (file)
@@ -2334,11 +2334,17 @@ struct WXDLLEXPORT wxWindowNext
     wxWindow *win;
     wxWindowNext *next;
 } *wxWindowBase::ms_winCaptureNext = NULL;
     wxWindow *win;
     wxWindowNext *next;
 } *wxWindowBase::ms_winCaptureNext = NULL;
+wxWindow *wxWindowBase::ms_winCaptureCurrent = NULL;
+bool wxWindowBase::ms_winCaptureChanging = false;
 
 void wxWindowBase::CaptureMouse()
 {
     wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), wx_static_cast(void*, this));
 
 
 void wxWindowBase::CaptureMouse()
 {
     wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), wx_static_cast(void*, this));
 
+    wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive CaptureMouse call?") );
+
+    ms_winCaptureChanging = true;
+
     wxWindow *winOld = GetCapture();
     if ( winOld )
     {
     wxWindow *winOld = GetCapture();
     if ( winOld )
     {
@@ -2353,19 +2359,28 @@ void wxWindowBase::CaptureMouse()
     //else: no mouse capture to save
 
     DoCaptureMouse();
     //else: no mouse capture to save
 
     DoCaptureMouse();
+    ms_winCaptureCurrent = (wxWindow*)this;
+
+    ms_winCaptureChanging = false;
 }
 
 void wxWindowBase::ReleaseMouse()
 {
     wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), wx_static_cast(void*, this));
 
 }
 
 void wxWindowBase::ReleaseMouse()
 {
     wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), wx_static_cast(void*, this));
 
+    wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive ReleaseMouse call?") );
+
     wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") );
 
     wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") );
 
+    ms_winCaptureChanging = true;
+
     DoReleaseMouse();
     DoReleaseMouse();
+    ms_winCaptureCurrent = NULL;
 
     if ( ms_winCaptureNext )
     {
         ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
 
     if ( ms_winCaptureNext )
     {
         ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
+        ms_winCaptureCurrent = ms_winCaptureNext->win;
 
         wxWindowNext *item = ms_winCaptureNext;
         ms_winCaptureNext = item->next;
 
         wxWindowNext *item = ms_winCaptureNext;
         ms_winCaptureNext = item->next;
@@ -2373,11 +2388,51 @@ void wxWindowBase::ReleaseMouse()
     }
     //else: stack is empty, no previous capture
 
     }
     //else: stack is empty, no previous capture
 
+    ms_winCaptureChanging = false;
+
     wxLogTrace(_T("mousecapture"),
         (const wxChar *) _T("After ReleaseMouse() mouse is captured by %p"),
         wx_static_cast(void*, GetCapture()));
 }
 
     wxLogTrace(_T("mousecapture"),
         (const wxChar *) _T("After ReleaseMouse() mouse is captured by %p"),
         wx_static_cast(void*, GetCapture()));
 }
 
+static void DoNotifyWindowAboutCaptureLost(wxWindow *win)
+{
+    wxMouseCaptureLostEvent event(win->GetId());
+    event.SetEventObject(win);
+    bool processed = win->GetEventHandler()->ProcessEvent(event);
+
+    wxASSERT_MSG( processed,
+                  _T("window that captured mouse didn't process wxEVT_MOUSE_CAPTURE_LOST") );
+}
+
+/* static */
+void wxWindowBase::NotifyCaptureLost(wxWindow *gainedCapture)
+{
+    // don't do anything if capture lost was expected, i.e. resulted from
+    // a wx call to ReleaseMouse or CaptureMouse:
+    if ( ms_winCaptureChanging )
+        return;
+
+    // if the capture was lost unexpectedly, notify every window that has
+    // capture (on stack or current) about it and clear the stack:
+
+    if ( ms_winCaptureCurrent )
+    {
+        DoNotifyWindowAboutCaptureLost(ms_winCaptureCurrent);
+        ms_winCaptureCurrent = NULL;
+    }
+
+    while ( ms_winCaptureNext )
+    {
+        wxWindowNext *item = ms_winCaptureNext;
+        ms_winCaptureNext = item->next;
+
+        DoNotifyWindowAboutCaptureLost(item->win);
+
+        delete item;
+    }
+}
+
 #if wxUSE_HOTKEY
 
 bool
 #if wxUSE_HOTKEY
 
 bool
index aee43219c08bcc6c23671a131c9890954e8aa6cd..19bc93a9dad37ace8f6720a72328654963e984f1 100644 (file)
@@ -1135,6 +1135,19 @@ void wxHtmlWindow::OnMouseUp(wxMouseEvent& event)
     wxHtmlWindowMouseHelper::HandleMouseClick(m_Cell, pos, event);
 }
 
     wxHtmlWindowMouseHelper::HandleMouseClick(m_Cell, pos, event);
 }
 
+#if wxUSE_CLIPBOARD
+void wxHtmlWindow::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
+{
+    if ( !m_makingSelection )
+        return;
+
+    // discard the selecting operation
+    m_makingSelection = false;
+    wxDELETE(m_selection);
+    m_tmpSelFromCell = NULL;
+    Refresh();
+}
+#endif // wxUSE_CLIPBOARD
 
 
 void wxHtmlWindow::OnInternalIdle()
 
 
 void wxHtmlWindow::OnInternalIdle()
@@ -1499,6 +1512,7 @@ BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow)
     EVT_LEFT_DCLICK(wxHtmlWindow::OnDoubleClick)
     EVT_ENTER_WINDOW(wxHtmlWindow::OnMouseEnter)
     EVT_LEAVE_WINDOW(wxHtmlWindow::OnMouseLeave)
     EVT_LEFT_DCLICK(wxHtmlWindow::OnDoubleClick)
     EVT_ENTER_WINDOW(wxHtmlWindow::OnMouseEnter)
     EVT_LEAVE_WINDOW(wxHtmlWindow::OnMouseLeave)
+    EVT_MOUSE_CAPTURE_LOST(wxHtmlWindow::OnMouseCaptureLost)
     EVT_KEY_UP(wxHtmlWindow::OnKeyUp)
     EVT_MENU(wxID_COPY, wxHtmlWindow::OnCopy)
 #endif // wxUSE_CLIPBOARD
     EVT_KEY_UP(wxHtmlWindow::OnKeyUp)
     EVT_MENU(wxID_COPY, wxHtmlWindow::OnCopy)
 #endif // wxUSE_CLIPBOARD
index 0515fe88be44d7bea076d5e4aab2b57e8213ebbe..2d079a591868df7edab64df68b8668a6b469101d 100644 (file)
@@ -4107,9 +4107,14 @@ bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
 
 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
 {
 
 bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
 {
-    wxMouseCaptureChangedEvent event(GetId(), wxFindWinFromHandle(hWndGainedCapture));
-    event.SetEventObject(this);
+    wxWindow *win = wxFindWinFromHandle(hWndGainedCapture);
+
+    // notify windows on the capture stack about lost capture
+    // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
+    wxWindowBase::NotifyCaptureLost(win);
 
 
+    wxMouseCaptureChangedEvent event(GetId(), win);
+    event.SetEventObject(this);
     return GetEventHandler()->ProcessEvent(event);
 }
 
     return GetEventHandler()->ProcessEvent(event);
 }