added wxEVT_MOUSE_CAPTURE_LOST event and code for correctly handling capture loss (bug #1153662)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@40391 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -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{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}
|
||||
|
@@ -29,6 +29,7 @@ function that takes a wxMouseCaptureChangedEvent argument.
|
||||
|
||||
\wxheading{See also}
|
||||
|
||||
\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
|
||||
\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.
|
||||
|
||||
|
||||
\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.
|
||||
|
@@ -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
|
||||
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}
|
||||
\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
|
||||
|
||||
|
||||
\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{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
|
||||
\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{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
|
||||
\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{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
|
||||
\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
|
||||
|
||||
|
||||
|
@@ -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_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)
|
||||
@@ -1797,6 +1797,29 @@ private:
|
||||
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
|
||||
*/
|
||||
@@ -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::*wxMouseCaptureLostEventFunction)(wxMouseCaptureLostEvent&);
|
||||
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)
|
||||
#define wxMouseCaptureLostEventHandler(func) \
|
||||
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxMouseCaptureLostEventFunction, &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_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))
|
||||
|
@@ -409,6 +409,7 @@ protected:
|
||||
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)
|
||||
|
@@ -1328,12 +1328,21 @@ protected:
|
||||
// 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;
|
||||
// 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)
|
||||
|
@@ -87,6 +87,7 @@
|
||||
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
|
||||
|
||||
@@ -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_MOUSE_CAPTURE_LOST)
|
||||
DEFINE_EVENT_TYPE(wxEVT_PAINT)
|
||||
DEFINE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND)
|
||||
DEFINE_EVENT_TYPE(wxEVT_NC_PAINT)
|
||||
|
@@ -2334,11 +2334,17 @@ struct WXDLLEXPORT wxWindowNext
|
||||
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));
|
||||
|
||||
wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive CaptureMouse call?") );
|
||||
|
||||
ms_winCaptureChanging = true;
|
||||
|
||||
wxWindow *winOld = GetCapture();
|
||||
if ( winOld )
|
||||
{
|
||||
@@ -2353,19 +2359,28 @@ void wxWindowBase::CaptureMouse()
|
||||
//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));
|
||||
|
||||
wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive ReleaseMouse call?") );
|
||||
|
||||
wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") );
|
||||
|
||||
ms_winCaptureChanging = true;
|
||||
|
||||
DoReleaseMouse();
|
||||
ms_winCaptureCurrent = NULL;
|
||||
|
||||
if ( ms_winCaptureNext )
|
||||
{
|
||||
((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
|
||||
ms_winCaptureCurrent = ms_winCaptureNext->win;
|
||||
|
||||
wxWindowNext *item = ms_winCaptureNext;
|
||||
ms_winCaptureNext = item->next;
|
||||
@@ -2373,11 +2388,51 @@ void wxWindowBase::ReleaseMouse()
|
||||
}
|
||||
//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()));
|
||||
}
|
||||
|
||||
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
|
||||
|
@@ -1135,6 +1135,19 @@ void wxHtmlWindow::OnMouseUp(wxMouseEvent& 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()
|
||||
@@ -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_MOUSE_CAPTURE_LOST(wxHtmlWindow::OnMouseCaptureLost)
|
||||
EVT_KEY_UP(wxHtmlWindow::OnKeyUp)
|
||||
EVT_MENU(wxID_COPY, wxHtmlWindow::OnCopy)
|
||||
#endif // wxUSE_CLIPBOARD
|
||||
|
@@ -4107,9 +4107,14 @@ bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user