From 6e217f067800541ccb9596cf03d52093b2909385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Tue, 6 Jan 2015 18:13:27 +0000 Subject: QColorDialog: Don't loose focus while color picking On Windows mouse grabbing doesn't work across processes, which means we're interacting with other windows when picking colors. Workaround that by having a transparent 1x1 window below the cursor at all times so we catch the mouse click. Clicking before the window is below the cursor won't happen because our timer interval is 30ms, so it's quite fast. It's hacky but it's what we can do for a feature which was very broken on Windows. Task-number: QTBUG-43663 Change-Id: I295378e033ddc6d9c2230335f0953a727c21e1dd Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qcolordialog.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'src/widgets/dialogs/qcolordialog.cpp') diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 882bb999fb..b133c49b5e 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -1579,12 +1579,17 @@ void QColorDialogPrivate::_q_pickScreenColor() q->grabMouse(); #endif -#ifdef Q_OS_WIN +#ifdef Q_OS_WIN32 // excludes WinCE and WinRT // On Windows mouse tracking doesn't work over other processes's windows updateTimer->start(30); + + // HACK: Because mouse grabbing doesn't work across processes, we have to have a dummy, + // invisible window to catch the mouse click, otherwise we will click whatever we clicked + // and loose focus. + dummyTransparentWindow.show(); #endif q->grabKeyboard(); - /* With setMouseTracking(true) the desired color can be more precisedly picked up, + /* With setMouseTracking(true) the desired color can be more precisely picked up, * and continuously pushing the mouse button is not necessary. */ q->setMouseTracking(true); @@ -1606,8 +1611,9 @@ void QColorDialogPrivate::releaseColorPicking() cp->setCrossVisible(true); q->removeEventFilter(colorPickingEventFilter); q->releaseMouse(); -#ifdef Q_OS_WIN +#ifdef Q_OS_WIN32 updateTimer->stop(); + dummyTransparentWindow.setVisible(false); #endif q->releaseKeyboard(); q->setMouseTracking(false); @@ -1635,6 +1641,10 @@ void QColorDialogPrivate::init(const QColor &initial) #ifdef Q_WS_MAC delegate = 0; #endif +#ifdef Q_OS_WIN32 + dummyTransparentWindow.resize(1, 1); + dummyTransparentWindow.setFlags(Qt::Tool | Qt::FramelessWindowHint); +#endif q->setCurrentColor(initial); } @@ -1791,7 +1801,7 @@ void QColorDialogPrivate::initWidgets() cancel = buttons->addButton(QDialogButtonBox::Cancel); QObject::connect(cancel, SIGNAL(clicked()), q, SLOT(reject())); -#ifdef Q_OS_WIN +#ifdef Q_OS_WIN32 updateTimer = new QTimer(q); QObject::connect(updateTimer, SIGNAL(timeout()), q, SLOT(_q_updateColorPicking())); #endif @@ -2219,8 +2229,12 @@ void QColorDialogPrivate::_q_updateColorPicking() return; lastGlobalPos = newGlobalPos; - if (!q->rect().contains(q->mapFromGlobal(newGlobalPos))) // Inside the dialog mouse tracking works, handleColorPickingMouseMove will be called + if (!q->rect().contains(q->mapFromGlobal(newGlobalPos))) { // Inside the dialog mouse tracking works, handleColorPickingMouseMove will be called updateColorPicking(newGlobalPos); +#ifdef Q_OS_WIN32 + dummyTransparentWindow.setPosition(newGlobalPos); +#endif + } #endif // ! QT_NO_CURSOR } -- cgit v1.2.3