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 "qdialogbuttonbox.h"
|
||||||
#include "qscreen.h"
|
#include "qscreen.h"
|
||||||
#include "qcursor.h"
|
#include "qcursor.h"
|
||||||
|
#include "qtimer.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -1577,6 +1578,11 @@ void QColorDialogPrivate::_q_pickScreenColor()
|
|||||||
#else
|
#else
|
||||||
q->grabMouse();
|
q->grabMouse();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// On Windows mouse tracking doesn't work over other processes's windows
|
||||||
|
updateTimer->start(30);
|
||||||
|
#endif
|
||||||
q->grabKeyboard();
|
q->grabKeyboard();
|
||||||
/* With setMouseTracking(true) the desired color can be more precisedly picked up,
|
/* With setMouseTracking(true) the desired color can be more precisedly picked up,
|
||||||
* and continuously pushing the mouse button is not necessary.
|
* and continuously pushing the mouse button is not necessary.
|
||||||
@ -1600,6 +1606,9 @@ void QColorDialogPrivate::releaseColorPicking()
|
|||||||
cp->setCrossVisible(true);
|
cp->setCrossVisible(true);
|
||||||
q->removeEventFilter(colorPickingEventFilter);
|
q->removeEventFilter(colorPickingEventFilter);
|
||||||
q->releaseMouse();
|
q->releaseMouse();
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
updateTimer->stop();
|
||||||
|
#endif
|
||||||
q->releaseKeyboard();
|
q->releaseKeyboard();
|
||||||
q->setMouseTracking(false);
|
q->setMouseTracking(false);
|
||||||
lblScreenColorInfo->setText(QLatin1String("\n"));
|
lblScreenColorInfo->setText(QLatin1String("\n"));
|
||||||
@ -1782,6 +1791,10 @@ void QColorDialogPrivate::initWidgets()
|
|||||||
cancel = buttons->addButton(QDialogButtonBox::Cancel);
|
cancel = buttons->addButton(QDialogButtonBox::Cancel);
|
||||||
QObject::connect(cancel, SIGNAL(clicked()), q, SLOT(reject()));
|
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();
|
retranslateStrings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2196,18 +2209,37 @@ void QColorDialog::changeEvent(QEvent *e)
|
|||||||
QDialog::changeEvent(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
|
#ifndef QT_NO_CURSOR
|
||||||
cp->setCrossVisible(!cp->geometry().contains(e->pos()));
|
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);
|
const QColor color = grabScreenColor(globalPos);
|
||||||
// QTBUG-39792, do not change standard, custom color selectors while moving as
|
// 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.
|
// otherwise it is not possible to pre-select a custom cell for assignment.
|
||||||
setCurrentColor(color, ShowColor);
|
setCurrentColor(color, ShowColor);
|
||||||
lblScreenColorInfo->setText(QColorDialog::tr("Cursor at %1, %2, color: %3\nPress ESC to cancel")
|
lblScreenColorInfo->setText(QColorDialog::tr("Cursor at %1, %2, color: %3\nPress ESC to cancel")
|
||||||
.arg(globalPos.x()).arg(globalPos.y()).arg(color.name()));
|
.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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +116,7 @@ private:
|
|||||||
Q_PRIVATE_SLOT(d_func(), void _q_newCustom(int, int))
|
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_newStandard(int, int))
|
||||||
Q_PRIVATE_SLOT(d_func(), void _q_pickScreenColor())
|
Q_PRIVATE_SLOT(d_func(), void _q_pickScreenColor())
|
||||||
|
Q_PRIVATE_SLOT(d_func(), void _q_updateColorPicking())
|
||||||
friend class QColorShower;
|
friend class QColorShower;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ class QVBoxLayout;
|
|||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QWellArray;
|
class QWellArray;
|
||||||
class QColorPickingEventFilter;
|
class QColorPickingEventFilter;
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
class QColorDialogPrivate : public QDialogPrivate
|
class QColorDialogPrivate : public QDialogPrivate
|
||||||
{
|
{
|
||||||
@ -75,7 +76,11 @@ public:
|
|||||||
SetColorAll = ShowColor | SelectColor
|
SetColorAll = ShowColor | SelectColor
|
||||||
};
|
};
|
||||||
|
|
||||||
QColorDialogPrivate() : options(new QColorDialogOptions) {}
|
QColorDialogPrivate() : options(new QColorDialogOptions)
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
, updateTimer(0)
|
||||||
|
#endif
|
||||||
|
{}
|
||||||
|
|
||||||
QPlatformColorDialogHelper *platformColorDialogHelper() const
|
QPlatformColorDialogHelper *platformColorDialogHelper() const
|
||||||
{ return static_cast<QPlatformColorDialogHelper *>(platformHelper()); }
|
{ return static_cast<QPlatformColorDialogHelper *>(platformHelper()); }
|
||||||
@ -104,6 +109,8 @@ public:
|
|||||||
void _q_newCustom(int, int);
|
void _q_newCustom(int, int);
|
||||||
void _q_newStandard(int, int);
|
void _q_newStandard(int, int);
|
||||||
void _q_pickScreenColor();
|
void _q_pickScreenColor();
|
||||||
|
void _q_updateColorPicking();
|
||||||
|
void updateColorPicking(const QPoint &pos);
|
||||||
void releaseColorPicking();
|
void releaseColorPicking();
|
||||||
bool handleColorPickingMouseMove(QMouseEvent *e);
|
bool handleColorPickingMouseMove(QMouseEvent *e);
|
||||||
bool handleColorPickingMouseButtonRelease(QMouseEvent *e);
|
bool handleColorPickingMouseButtonRelease(QMouseEvent *e);
|
||||||
@ -136,6 +143,9 @@ public:
|
|||||||
|
|
||||||
QPointer<QObject> receiverToDisconnectOnClose;
|
QPointer<QObject> receiverToDisconnectOnClose;
|
||||||
QByteArray memberToDisconnectOnClose;
|
QByteArray memberToDisconnectOnClose;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QTimer *updateTimer;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef Q_WS_MAC
|
#ifdef Q_WS_MAC
|
||||||
void openCocoaColorPanel(const QColor &initial,
|
void openCocoaColorPanel(const QColor &initial,
|
||||||
|
Loading…
Reference in New Issue
Block a user