Update the ungrabMouse hack for Qt 5.8

Summary:
There was an unidentified bug where when opening a context menu in
response to a mousePress event led to the next click events not being
registered. The mouse got grabbed by the item in the mousePressEvent,
but when we open a menu it didn't get released. The next click goes to
the currently grabbed item.

A workaround was added back in 2015 (and copied into various other parts
of Plasma) to ungrab the mouse after launching the context menu inside
our rightClickEvent. This doesn't work because qquickwindow code is
shuffled. It now sends the event and then grabs the mouse.

qquickwindow.cpp:653 on Qt5.8.0

Which means we're now trying to do the ungrab, before QWindow has set
our item as the grabber. That obviously doesn't work.

This real bug needs fixing in Qt, (I now know the root cause!)
but we have a workaround here already, we may as well make it work.

FWIW, the root cause of all of these bugs is:
The way it should work is:
    QQuickItem is pressed
    QtQuick internally says "this item has the mouse"
    you release the mouse, that gets reset
    you change window focus, that gets reset

In our case, we don't get either of the last two because:

We spawn a QMenu on mousePress; this takes focus and more importantly
does a mouse grab (a different type. At an X level, not in QtQuick) so
our QQuickWindow never gets a mouseReleaseEvent

Test Plan:
Had 1 reproducible case
Added this. No longer could reproduce

Reviewers: #plasma

Subscribers: plasma-devel, #frameworks

Tags: #plasma, #frameworks

Differential Revision: https://phabricator.kde.org/D5515
This commit is contained in:
David Edmundson 2017-04-19 18:37:19 +01:00
parent 95601054e5
commit 29f1ee3858

View File

@ -27,6 +27,7 @@
#include <QQmlExpression>
#include <QQmlProperty>
#include <QMimeData>
#include <QVersionNumber>
#include <kactioncollection.h>
#include <KAcceleratorManager>
@ -1015,9 +1016,30 @@ void ContainmentInterface::mousePressEvent(QMouseEvent *event)
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
//end workaround
if (window() && window()->mouseGrabberItem()) {
window()->mouseGrabberItem()->ungrabMouse();
//this is a workaround where Qt will fail to realise a mouse has been released
// this happens if a window which does not accept focus spawns a new window that takes focus and X grab
// whilst the mouse is depressed
// https://bugreports.qt.io/browse/QTBUG-59044
// this causes the next click to go missing
//by releasing manually we avoid that situation
auto ungrabMouseHack = [this]() {
if (window() && window()->mouseGrabberItem()) {
window()->mouseGrabberItem()->ungrabMouse();
}
};
//pre 5.8.0 QQuickWindow code is "item->grabMouse(); sendEvent(item, mouseEvent)"
//post 5.8.0 QQuickWindow code is sendEvent(item, mouseEvent); item->grabMouse()
if (QVersionNumber::fromString(qVersion()) > QVersionNumber(5, 8, 0)) {
QTimer::singleShot(0, this, ungrabMouseHack);
}
else {
ungrabMouseHack();
}
//end workaround
QPoint pos = event->globalPos();
if (window() && m_containment->containmentType() == Plasma::Types::PanelContainment) {