forked from gentoo/gentoo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dev-qt/qtgui: Fix desktop icon hover
Recommended by KDE. See also: https://mail.kde.org/pipermail/kde-distro-packagers/2018-February/000303.html See also: https://bugreports.qt.io/browse/QTBUG-66103 See also: https://codereview.qt-project.org/#/c/215939/ Package-Manager: Portage-2.3.24, Repoman-2.3.6
- Loading branch information
Showing
2 changed files
with
343 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
From 4a7771f206d4b29be549d3827c36a46679d90de6 Mon Sep 17 00:00:00 2001 | ||
From: Eike Hein <[email protected]> | ||
Date: Sun, 7 Jan 2018 13:02:01 +0900 | ||
Subject: [PATCH] QSimpleDrag: Fix mouse release coords for delayed event | ||
transmission | ||
|
||
On platforms such as XCB, the drag cursor pixmap is shown via a window | ||
(a QShapedPixmapWindow) under the cursor. | ||
|
||
The mouse button release event at the end of the drag is received in | ||
this QXcbWindow, but intercepted by an event filter that QSimpleDrag | ||
installs on the QApplication. It then resends it unmodified(!) after | ||
the drag has ended and the drag pixmap window destroyed, causing it to | ||
be delivered to the new top-level window. | ||
|
||
The local coordinates in the unmodified QMouseEvent are local to the | ||
drag pixmap window and don't match the window it is delayed-transmitted | ||
to. | ||
|
||
This ends up having fatal, user-visible effects particularly in Qt | ||
Quick: QQuickWindow synthesizes a hover event once per frame using | ||
the last received mouse coordinates, here: the release posted by | ||
QSimpleDrag. This is done to update the hover event state for items | ||
under the cursor when the mouse hasn't moved (e.g. QQuickMouseArea:: | ||
containsMouse). The bogus event coordinates in the release event then | ||
usually end up causing an item near the top-left of the QQuickWindow | ||
to assume it is hovered (because drag pixmap windows tend to be small), | ||
even when the mouse cursor is actually far away from it at the end of | ||
the drag. | ||
|
||
This shows up e.g. in the Plasma 5 desktop, where dragging an icon | ||
on the desktop will cause the icon at the top-left of the screen (if | ||
any) to switch to hovered state, as the release coordinates on the | ||
drag pixmap window (showing a dragged icon) fall into the geometry | ||
of the top-left icon. | ||
|
||
QSimpleDrag contains a topLevelAt() function to find the top-level | ||
window under the global cursor coordinates that is not the drag | ||
pixmap window. This is used by the drop event delivery code. | ||
|
||
This patch uses this function to find the relevant top-level window, | ||
then asks it to map the global cusor coordinates to its local | ||
coordinate system, then synthesizes a new QMouseEvent with local | ||
coordinates computed in this fashion. As a result the window now | ||
gets a release event with coordinates that make sense and are | ||
correct. | ||
|
||
Task-number: QTBUG-66103 | ||
Change-Id: I04ebe6ccd4a991fdd4b540ff0227973ea8896a9d | ||
Reviewed-by: Eike Hein <[email protected]> | ||
Reviewed-by: Shawn Rutledge <[email protected]> | ||
--- | ||
src/gui/kernel/qsimpledrag.cpp | 32 +++++++++++++++++++++++++++----- | ||
src/gui/kernel/qsimpledrag_p.h | 6 +++--- | ||
2 files changed, 30 insertions(+), 8 deletions(-) | ||
|
||
diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp | ||
index a1e25dc..87d3ba5 100644 | ||
--- a/src/gui/kernel/qsimpledrag.cpp | ||
+++ b/src/gui/kernel/qsimpledrag.cpp | ||
@@ -58,6 +58,7 @@ | ||
|
||
#include <QtCore/QEventLoop> | ||
#include <QtCore/QDebug> | ||
+#include <QtCore/QLoggingCategory> | ||
|
||
#include <private/qguiapplication_p.h> | ||
#include <private/qdnd_p.h> | ||
@@ -69,6 +70,8 @@ QT_BEGIN_NAMESPACE | ||
|
||
#ifndef QT_NO_DRAGANDDROP | ||
|
||
+Q_LOGGING_CATEGORY(lcDnd, "qt.gui.dnd") | ||
+ | ||
static QWindow* topLevelAt(const QPoint &pos) | ||
{ | ||
QWindowList list = QGuiApplication::topLevelWindows(); | ||
@@ -94,10 +97,10 @@ static QWindow* topLevelAt(const QPoint &pos) | ||
*/ | ||
|
||
QBasicDrag::QBasicDrag() : | ||
- m_restoreCursor(false), m_eventLoop(0), | ||
+ m_current_window(nullptr), m_restoreCursor(false), m_eventLoop(nullptr), | ||
m_executed_drop_action(Qt::IgnoreAction), m_can_drop(false), | ||
- m_drag(0), m_drag_icon_window(0), m_useCompositing(true), | ||
- m_screen(Q_NULLPTR) | ||
+ m_drag(nullptr), m_drag_icon_window(nullptr), m_useCompositing(true), | ||
+ m_screen(nullptr) | ||
{ | ||
} | ||
|
||
@@ -161,6 +164,7 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) | ||
return true; // Eat all mouse move events | ||
} | ||
case QEvent::MouseButtonRelease: | ||
+ { | ||
disableEventFilter(); | ||
if (canDrop()) { | ||
QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window); | ||
@@ -169,8 +173,25 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) | ||
cancel(); | ||
} | ||
exitDndEventLoop(); | ||
- QCoreApplication::postEvent(o, new QMouseEvent(*static_cast<QMouseEvent *>(e))); | ||
+ | ||
+ // If a QShapedPixmapWindow (drag feedback) is being dragged along, the | ||
+ // mouse event's localPos() will be relative to that, which is useless. | ||
+ // We want a position relative to the window where the drag ends, if possible (?). | ||
+ // If there is no such window (belonging to this Qt application), | ||
+ // make the event relative to the window where the drag started. (QTBUG-66103) | ||
+ const QMouseEvent *release = static_cast<QMouseEvent *>(e); | ||
+ const QWindow *releaseWindow = topLevelAt(release->globalPos()); | ||
+ qCDebug(lcDnd) << "mouse released over" << releaseWindow << "after drag from" << m_current_window << "globalPos" << release->globalPos(); | ||
+ if (!releaseWindow) | ||
+ releaseWindow = m_current_window; | ||
+ QPoint releaseWindowPos = (releaseWindow ? releaseWindow->mapFromGlobal(release->globalPos()) : release->globalPos()); | ||
+ QMouseEvent *newRelease = new QMouseEvent(release->type(), | ||
+ releaseWindowPos, releaseWindowPos, release->screenPos(), | ||
+ release->button(), release->buttons(), | ||
+ release->modifiers(), release->source()); | ||
+ QCoreApplication::postEvent(o, newRelease); | ||
return true; // defer mouse release events until drag event loop has returned | ||
+ } | ||
case QEvent::MouseButtonDblClick: | ||
case QEvent::Wheel: | ||
return true; | ||
@@ -349,7 +370,7 @@ static inline QPoint fromNativeGlobalPixels(const QPoint &point) | ||
into account. | ||
*/ | ||
|
||
-QSimpleDrag::QSimpleDrag() : m_current_window(0) | ||
+QSimpleDrag::QSimpleDrag() | ||
{ | ||
} | ||
|
||
@@ -373,6 +394,7 @@ void QSimpleDrag::startDrag() | ||
updateCursor(Qt::IgnoreAction); | ||
} | ||
setExecutedDropAction(Qt::IgnoreAction); | ||
+ qCDebug(lcDnd) << "drag began from" << m_current_window<< "cursor pos" << QCursor::pos() << "can drop?" << canDrop(); | ||
} | ||
|
||
void QSimpleDrag::cancel() | ||
diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h | ||
index 0b8a0bc..bbd7f7f 100644 | ||
--- a/src/gui/kernel/qsimpledrag_p.h | ||
+++ b/src/gui/kernel/qsimpledrag_p.h | ||
@@ -105,6 +105,9 @@ protected: | ||
|
||
QDrag *drag() const { return m_drag; } | ||
|
||
+protected: | ||
+ QWindow *m_current_window; | ||
+ | ||
private: | ||
void enableEventFilter(); | ||
void disableEventFilter(); | ||
@@ -132,9 +135,6 @@ protected: | ||
virtual void cancel() Q_DECL_OVERRIDE; | ||
virtual void move(const QPoint &globalPos) Q_DECL_OVERRIDE; | ||
virtual void drop(const QPoint &globalPos) Q_DECL_OVERRIDE; | ||
- | ||
-private: | ||
- QWindow *m_current_window; | ||
}; | ||
|
||
#endif // QT_NO_DRAGANDDROP | ||
-- | ||
2.7.4 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
# Copyright 1999-2018 Gentoo Foundation | ||
# Distributed under the terms of the GNU General Public License v2 | ||
|
||
EAPI=6 | ||
QT5_MODULE="qtbase" | ||
inherit qt5-build | ||
|
||
DESCRIPTION="The GUI module and platform plugins for the Qt5 framework" | ||
|
||
if [[ ${QT5_BUILD_TYPE} == release ]]; then | ||
KEYWORDS="~amd64 ~arm ~arm64 ~hppa ~ppc ~ppc64 ~x86" | ||
fi | ||
|
||
# TODO: linuxfb | ||
|
||
IUSE="accessibility dbus egl eglfs evdev +gif gles2 ibus | ||
jpeg +libinput +png tslib tuio +udev vnc +xcb" | ||
REQUIRED_USE=" | ||
|| ( eglfs xcb ) | ||
accessibility? ( dbus xcb ) | ||
eglfs? ( egl ) | ||
ibus? ( dbus ) | ||
libinput? ( udev ) | ||
xcb? ( gles2? ( egl ) ) | ||
" | ||
|
||
RDEPEND=" | ||
dev-libs/glib:2 | ||
~dev-qt/qtcore-${PV} | ||
media-libs/fontconfig | ||
>=media-libs/freetype-2.6.1:2 | ||
>=media-libs/harfbuzz-1.0.6:= | ||
>=sys-libs/zlib-1.2.5 | ||
virtual/opengl | ||
dbus? ( ~dev-qt/qtdbus-${PV} ) | ||
egl? ( media-libs/mesa[egl] ) | ||
eglfs? ( | ||
media-libs/mesa[gbm] | ||
x11-libs/libdrm | ||
) | ||
evdev? ( sys-libs/mtdev ) | ||
gles2? ( media-libs/mesa[gles2] ) | ||
jpeg? ( virtual/jpeg:0 ) | ||
libinput? ( | ||
dev-libs/libinput:= | ||
x11-libs/libxkbcommon | ||
) | ||
png? ( media-libs/libpng:0= ) | ||
tslib? ( x11-libs/tslib ) | ||
tuio? ( ~dev-qt/qtnetwork-${PV} ) | ||
udev? ( virtual/libudev:= ) | ||
vnc? ( ~dev-qt/qtnetwork-${PV} ) | ||
xcb? ( | ||
x11-libs/libICE | ||
x11-libs/libSM | ||
x11-libs/libX11 | ||
>=x11-libs/libXi-1.7.5 | ||
>=x11-libs/libxcb-1.10:=[xkb] | ||
>=x11-libs/libxkbcommon-0.4.1[X] | ||
x11-libs/xcb-util-image | ||
x11-libs/xcb-util-keysyms | ||
x11-libs/xcb-util-renderutil | ||
x11-libs/xcb-util-wm | ||
) | ||
" | ||
DEPEND="${RDEPEND} | ||
evdev? ( sys-kernel/linux-headers ) | ||
udev? ( sys-kernel/linux-headers ) | ||
" | ||
PDEPEND=" | ||
ibus? ( app-i18n/ibus ) | ||
" | ||
|
||
PATCHES=( | ||
"${FILESDIR}/${P}-qsimpledrag.patch" # QTBUG-66103 | ||
) | ||
|
||
QT5_TARGET_SUBDIRS=( | ||
src/gui | ||
src/openglextensions | ||
src/platformheaders | ||
src/platformsupport | ||
src/plugins/generic | ||
src/plugins/imageformats | ||
src/plugins/platforms | ||
src/plugins/platforminputcontexts | ||
) | ||
|
||
QT5_GENTOO_CONFIG=( | ||
accessibility:accessibility-atspi-bridge | ||
egl | ||
eglfs | ||
eglfs:eglfs_egldevice: | ||
eglfs:eglfs_gbm: | ||
evdev | ||
evdev:mtdev: | ||
:fontconfig | ||
:system-freetype:FREETYPE | ||
!:no-freetype: | ||
!gif:no-gif: | ||
gles2::OPENGL_ES | ||
gles2:opengles2:OPENGL_ES_2 | ||
!:no-gui: | ||
:system-harfbuzz:HARFBUZZ | ||
!:no-harfbuzz: | ||
jpeg:system-jpeg:IMAGEFORMAT_JPEG | ||
!jpeg:no-jpeg: | ||
libinput | ||
libinput:xkbcommon-evdev: | ||
:opengl | ||
png:png: | ||
png:system-png:IMAGEFORMAT_PNG | ||
!png:no-png: | ||
tslib | ||
udev:libudev: | ||
xcb:xcb: | ||
xcb:xcb-glx: | ||
xcb:xcb-plugin: | ||
xcb:xcb-render: | ||
xcb:xcb-sm: | ||
xcb:xcb-xlib: | ||
xcb:xinput2: | ||
xcb::XKB | ||
) | ||
|
||
QT5_GENTOO_PRIVATE_CONFIG=( | ||
:gui | ||
) | ||
|
||
src_prepare() { | ||
# egl_x11 is activated when both egl and xcb are enabled | ||
use egl && QT5_GENTOO_CONFIG+=(xcb:egl_x11) || QT5_GENTOO_CONFIG+=(egl:egl_x11) | ||
|
||
qt_use_disable_config dbus dbus \ | ||
src/platformsupport/themes/genericunix/genericunix.pri | ||
|
||
qt_use_disable_config tuio udpsocket src/plugins/generic/generic.pro | ||
|
||
qt_use_disable_mod ibus dbus \ | ||
src/plugins/platforminputcontexts/platforminputcontexts.pro | ||
|
||
use vnc || sed -i -e '/SUBDIRS += vnc/d' \ | ||
src/plugins/platforms/platforms.pro || die | ||
|
||
qt5-build_src_prepare | ||
} | ||
|
||
src_configure() { | ||
local myconf=( | ||
$(usex dbus -dbus-linked '') | ||
$(qt_use egl) | ||
$(qt_use eglfs) | ||
$(usex eglfs '-gbm -kms' '') | ||
$(qt_use evdev) | ||
$(qt_use evdev mtdev) | ||
-fontconfig | ||
-system-freetype | ||
$(usex gif '' -no-gif) | ||
-gui | ||
-system-harfbuzz | ||
$(qt_use jpeg libjpeg system) | ||
$(qt_use libinput) | ||
$(qt_use libinput xkbcommon-evdev) | ||
-opengl $(usex gles2 es2 desktop) | ||
$(qt_use png libpng system) | ||
$(qt_use tslib) | ||
$(qt_use udev libudev) | ||
$(qt_use xcb xcb system) | ||
$(qt_use xcb xkbcommon-x11 system) | ||
$(usex xcb '-xcb-xlib -xinput2 -xkb' '') | ||
) | ||
qt5-build_src_configure | ||
} |