Windows: Fix QColorDialog's live updates while picking outside color
Microsoft's SetCapture() doesn't work on windows owned by other processes, so instead we use a timer. This is the same approach as used by qttools/src/pixeltool. The mouse move approach however is more elegant and doesn't hammer the CPU with QCursor::pos() calls when idle. For this reason the workaround is Q_OS_WIN only. Task-number: QTBUG-34538 Change-Id: I40a6f7df5bf2a3a29ade8fe4a92f5b5c4ece7efb Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
This commit is contained in:
parent
b699ac070c
commit
38a3158d2f
@ -57,6 +57,7 @@
|
||||
#include "qdialogbuttonbox.h"
|
||||
#include "qscreen.h"
|
||||
#include "qcursor.h"
|
||||
#include "qtimer.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -1577,6 +1578,11 @@ void QColorDialogPrivate::_q_pickScreenColor()
|
||||
#else
|
||||
q->grabMouse();
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// On Windows mouse tracking doesn't work over other processes's windows
|
||||
updateTimer->start(30);
|
||||
#endif
|
||||
q->grabKeyboard();
|
||||
/* With setMouseTracking(true) the desired color can be more precisedly picked up,
|
||||
* and continuously pushing the mouse button is not necessary.
|
||||
@ -1600,6 +1606,9 @@ void QColorDialogPrivate::releaseColorPicking()
|
||||
cp->setCrossVisible(true);
|
||||
q->removeEventFilter(colorPickingEventFilter);
|
||||
q->releaseMouse();
|
||||
#ifdef Q_OS_WIN
|
||||
updateTimer->stop();
|
||||
#endif
|
||||
q->releaseKeyboard();
|
||||
q->setMouseTracking(false);
|
||||
lblScreenColorInfo->setText(QLatin1String("\n"));
|
||||
@ -1782,6 +1791,10 @@ void QColorDialogPrivate::initWidgets()
|
||||
cancel = buttons->addButton(QDialogButtonBox::Cancel);
|
||||
QObject::connect(cancel, SIGNAL(clicked()), q, SLOT(reject()));
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
updateTimer = new QTimer(q);
|
||||
QObject::connect(updateTimer, SIGNAL(timeout()), q, SLOT(_q_updateColorPicking()));
|
||||
#endif
|
||||
retranslateStrings();
|
||||
}
|
||||
|
||||
@ -2196,18 +2209,37 @@ void QColorDialog::changeEvent(QEvent *e)
|
||||
QDialog::changeEvent(e);
|
||||
}
|
||||
|
||||
bool QColorDialogPrivate::handleColorPickingMouseMove(QMouseEvent *e)
|
||||
void QColorDialogPrivate::_q_updateColorPicking()
|
||||
{
|
||||
// If the cross is visible the grabbed color will be black most of the times
|
||||
cp->setCrossVisible(!cp->geometry().contains(e->pos()));
|
||||
#ifndef QT_NO_CURSOR
|
||||
Q_Q(QColorDialog);
|
||||
static QPoint lastGlobalPos;
|
||||
QPoint newGlobalPos = QCursor::pos();
|
||||
if (lastGlobalPos == newGlobalPos)
|
||||
return;
|
||||
lastGlobalPos = newGlobalPos;
|
||||
|
||||
const QPoint globalPos = e->globalPos();
|
||||
if (!q->rect().contains(q->mapFromGlobal(newGlobalPos))) // Inside the dialog mouse tracking works, handleColorPickingMouseMove will be called
|
||||
updateColorPicking(newGlobalPos);
|
||||
#endif // ! QT_NO_CURSOR
|
||||
}
|
||||
|
||||
void QColorDialogPrivate::updateColorPicking(const QPoint &globalPos)
|
||||
{
|
||||
const QColor color = grabScreenColor(globalPos);
|
||||
// QTBUG-39792, do not change standard, custom color selectors while moving as
|
||||
// otherwise it is not possible to pre-select a custom cell for assignment.
|
||||
setCurrentColor(color, ShowColor);
|
||||
lblScreenColorInfo->setText(QColorDialog::tr("Cursor at %1, %2, color: %3\nPress ESC to cancel")
|
||||
.arg(globalPos.x()).arg(globalPos.y()).arg(color.name()));
|
||||
}
|
||||
|
||||
bool QColorDialogPrivate::handleColorPickingMouseMove(QMouseEvent *e)
|
||||
{
|
||||
// If the cross is visible the grabbed color will be black most of the times
|
||||
cp->setCrossVisible(!cp->geometry().contains(e->pos()));
|
||||
|
||||
updateColorPicking(e->globalPos());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,7 @@ private:
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_newCustom(int, int))
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_newStandard(int, int))
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_pickScreenColor())
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_updateColorPicking())
|
||||
friend class QColorShower;
|
||||
};
|
||||
|
||||
|
@ -63,6 +63,7 @@ class QVBoxLayout;
|
||||
class QPushButton;
|
||||
class QWellArray;
|
||||
class QColorPickingEventFilter;
|
||||
class QTimer;
|
||||
|
||||
class QColorDialogPrivate : public QDialogPrivate
|
||||
{
|
||||
@ -75,7 +76,11 @@ public:
|
||||
SetColorAll = ShowColor | SelectColor
|
||||
};
|
||||
|
||||
QColorDialogPrivate() : options(new QColorDialogOptions) {}
|
||||
QColorDialogPrivate() : options(new QColorDialogOptions)
|
||||
#ifdef Q_OS_WIN
|
||||
, updateTimer(0)
|
||||
#endif
|
||||
{}
|
||||
|
||||
QPlatformColorDialogHelper *platformColorDialogHelper() const
|
||||
{ return static_cast<QPlatformColorDialogHelper *>(platformHelper()); }
|
||||
@ -104,6 +109,8 @@ public:
|
||||
void _q_newCustom(int, int);
|
||||
void _q_newStandard(int, int);
|
||||
void _q_pickScreenColor();
|
||||
void _q_updateColorPicking();
|
||||
void updateColorPicking(const QPoint &pos);
|
||||
void releaseColorPicking();
|
||||
bool handleColorPickingMouseMove(QMouseEvent *e);
|
||||
bool handleColorPickingMouseButtonRelease(QMouseEvent *e);
|
||||
@ -136,6 +143,9 @@ public:
|
||||
|
||||
QPointer<QObject> receiverToDisconnectOnClose;
|
||||
QByteArray memberToDisconnectOnClose;
|
||||
#ifdef Q_OS_WIN
|
||||
QTimer *updateTimer;
|
||||
#endif
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
void openCocoaColorPanel(const QColor &initial,
|
||||
|
Loading…
Reference in New Issue
Block a user