Fix handling captured mouse events in a window with scrollbars
Handle some mouse events explicitly when a wxQtScrollArea is set as "mouse captured". The issue arises in that the QScrollArea has two methods: event() and viewportEvent(). Normally a "QAbstractScrollAreaFilter" is set up by Qt which routes any events to the viewportEvent() method. And the normal event() method throws mouse events away (for reasons I'm not aware of - but it is what it is). If a wx window with a scroll area (e.g. wxRichTextCtrl) sets capture, the wxQtScrollArea (QScroll-derived) gets set as the direct "mouse grabber", and all events then bypass the filter and are sent directly to the "event" method, which throws them away. The typical result is that the window setting capture no longer gets mouse events, it keeps capture since it's looking for a mouse up that never comes, and the app more or less locks up since all mouse events are being effectively discarded. This change catches any event that comes in via the event() method and, when the mouse is captured by the widget, forwards it on to the viewportEvent method instead, performing what the filter would do via the normal event routing. It doesn't forward on "mouse press" events because the initial event that causes the capture ends up being fed back again, resulting in a "captured twice" error. The underlying reason I can see for this "being fed back again" is that, for some inexplicable reason, the wxRichTextCtrl "skips" the event even though it has actually processed it and taken capture. That means this solution isn't 100%, but it does fix the 99%+ cases where the capture is only gotten to redirect mouse moves and button ups. Perhaps an alternative solution might be to stop grabbing the mouse in wxQtScrollArea, but this would require more changes. Closes https://github.com/wxWidgets/wxWidgets/pull/1346
This commit is contained in:
committed by
Vadim Zeitlin
parent
5a228ceb91
commit
d66aa35254
@@ -59,9 +59,10 @@ wxQtWidget::wxQtWidget( wxWindowQt *parent, wxWindowQt *handler )
|
||||
|
||||
class wxQtScrollArea : public wxQtEventSignalHandler< QScrollArea, wxWindowQt >
|
||||
{
|
||||
public:
|
||||
wxQtScrollArea(wxWindowQt *parent, wxWindowQt *handler);
|
||||
|
||||
public:
|
||||
wxQtScrollArea( wxWindowQt *parent, wxWindowQt *handler );
|
||||
bool event(QEvent *e) wxOVERRIDE;
|
||||
};
|
||||
|
||||
wxQtScrollArea::wxQtScrollArea( wxWindowQt *parent, wxWindowQt *handler )
|
||||
@@ -69,6 +70,27 @@ wxQtScrollArea::wxQtScrollArea( wxWindowQt *parent, wxWindowQt *handler )
|
||||
{
|
||||
}
|
||||
|
||||
bool wxQtScrollArea::event(QEvent *e)
|
||||
{
|
||||
wxWindowQt* handler = GetHandler();
|
||||
if ( handler && handler->HasCapture() )
|
||||
{
|
||||
switch ( e->type() )
|
||||
{
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::MouseButtonDblClick:
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::Wheel:
|
||||
case QEvent::TouchUpdate:
|
||||
case QEvent::TouchEnd:
|
||||
return viewportEvent(e);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QScrollArea::event(e);
|
||||
}
|
||||
|
||||
class wxQtInternalScrollBar : public wxQtEventSignalHandler< QScrollBar, wxWindowQt >
|
||||
{
|
||||
public:
|
||||
|
Reference in New Issue
Block a user