Commit ae31080a authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fix popup palette in WinInk mode

We should eat synthesized events more carefully in the popup
palette. The events may come either to the triangle widget or
to its parent widget, depending on the implementaiton. Therefore
we use a special event filter for that (KisMouseClickEater).

CCBUG:406668
Ref T10935
parent 1baa7942
From 9a2a150476d51d786e011e1ddde4bb77c7b9d146 Mon Sep 17 00:00:00 2001
From 5a518a022d840571e6fb6cb1448fc801a2678aba Mon Sep 17 00:00:00 2001
From: Dmitry Kazakov <dimula73@gmail.com>
Date: Wed, 15 May 2019 19:54:52 +0300
Subject: [PATCH 2/2] Add workaround for handling table press correctly in
WinInk mode
Subject: [PATCH] Add workaround for handling table press correctly in WinInk
mode
Original problem: widgets do not get synthesized mouse-down and
mouse-press events until the stylus is released
......@@ -26,24 +26,19 @@ by using the following rules:
3) All accepted tablet press- and release-events are reported as "accepted",
**but** we artificially synthesize mouse events for them.
TODO: there are still two problems:
TODO: there are still one problem:
1) Perhaps this synthesizeMouseEvent() is not needed at all. But we should
first check if Qt relies on these synthesized messages anywhere in the
code or not.
2) If we still keep synthesizeMouseEvent(), then it should fetch actual
tablet buttons from QGuiApplicationPrivate::tabletDevicePoint(). Right
now it always synthesizes left-click, whatever the button was pressed/
released.
See bug: https://bugs.kde.org/show_bug.cgi?id=406668
---
src/gui/kernel/qguiapplication.cpp | 1 +
src/gui/kernel/qwindowsysteminterface.cpp | 20 ++---
src/gui/kernel/qwindowsysteminterface.h | 8 +-
.../windows/qwindowspointerhandler.cpp | 75 ++++++++++++++++++-
4 files changed, 86 insertions(+), 18 deletions(-)
.../windows/qwindowspointerhandler.cpp | 88 ++++++++++++++++++-
4 files changed, 99 insertions(+), 18 deletions(-)
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 3541c1ae..681cbd85 100644
......@@ -146,7 +141,7 @@ index 1dde9130..0ad89547 100644
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers = Qt::NoModifier);
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 07f4d41e..58a5d19f 100644
index 07f4d41e..e8c98948 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -518,6 +518,58 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
......@@ -208,7 +203,7 @@ index 07f4d41e..58a5d19f 100644
bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et,
MSG msg, PVOID vPenInfo)
{
@@ -610,10 +662,25 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
@@ -610,10 +662,38 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
}
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
......@@ -216,21 +211,34 @@ index 07f4d41e..58a5d19f 100644
- pressure, xTilt, yTilt, tangentialPressure, rotation, z,
- sourceDevice, keyModifiers);
- return false; // Allow mouse messages to be generated.
+ const Qt::MouseButtons oldButtons = QGuiApplicationPrivate::tabletDevicePoint(sourceDevice).state;
+
+ const bool accepted =
+ QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
+ pressure, xTilt, yTilt, tangentialPressure, rotation, z,
+ sourceDevice, keyModifiers);
+
+ /**
+ * TODO: right now we can fake-synthesize only left button clicks. For
+ * synthesizing right button clicks we should fetch tablet state
+ * from QGuiApplicationPrivate::tabletDevicePoint()
+ */
+ if (accepted && (msg.message == WM_POINTERDOWN || msg.message == WM_POINTERUP)) {
+ const Qt::MouseButtons changedButtons =
+ oldButtons ^ QGuiApplicationPrivate::tabletDevicePoint(sourceDevice).state;
+
+ Qt::MouseButton pressedButton = Qt::NoButton;
+
+ const QVector<Qt::MouseButton> supportedButtons =
+ {Qt::LeftButton, Qt::RightButton, Qt::MiddleButton};
+
+ for (Qt::MouseButton button : supportedButtons) {
+ if (changedButtons & button) {
+ pressedButton = button;
+ break;
+ }
+ }
+
+ if (accepted && pressedButton != Qt::NoButton &&
+ (msg.message == WM_POINTERDOWN || msg.message == WM_POINTERUP)) {
+
+ QEvent::Type type = (msg.message == WM_POINTERDOWN) ? QEvent::TabletPress : QEvent::TabletRelease;
+ Qt::MouseButton button = Qt::LeftButton;
+
+ synthesizeMouseEvent(type, button, *penInfo);
+ synthesizeMouseEvent(type, pressedButton, *penInfo);
+ return true;
+ } else {
+ return false; // Allow mouse messages to be generated by OS
......
......@@ -393,7 +393,7 @@ set(kritaui_LIB_SRCS
KisReferenceImage.cpp
flake/KisReferenceImagesLayer.cpp
flake/KisReferenceImagesLayer.h
KisMouseClickEater.cpp
)
if(WIN32)
......
#include "KisMouseClickEater.h"
#include <QMouseEvent>
#include "kis_debug.h"
KisMouseClickEater::KisMouseClickEater(Qt::MouseButtons buttons,
int clicksToEat,
QObject *parent)
: QObject(parent),
m_buttons(buttons),
m_clicksToEat(clicksToEat)
{
reset();
}
KisMouseClickEater::~KisMouseClickEater()
{
}
void KisMouseClickEater::reset()
{
m_clicksHappened = 0;
m_timeSinceReset.start();
m_blockTimedRelease = false;
}
bool KisMouseClickEater::eventFilter(QObject *watched, QEvent *event)
{
#ifdef Q_OS_WIN
const int tabletMouseEventsFlowDelay = 500;
#else
const int tabletMouseEventsFlowDelay = 100;
#endif
if (event->type() == QEvent::TabletMove) {
m_blockTimedRelease = true;
}
if (!m_blockTimedRelease &&
m_timeSinceReset.elapsed() > tabletMouseEventsFlowDelay) {
return QObject::eventFilter(watched, event);
}
if (event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mevent = static_cast<QMouseEvent*>(event);
if (mevent->button() & m_buttons) {
if (m_clicksHappened >= m_clicksToEat) {
return false;
}
if (event->type() == QEvent::MouseButtonRelease) {
m_clicksHappened++;
}
return true;
}
}
if (event->type() == QEvent::MouseMove) {
QMouseEvent *mevent = static_cast<QMouseEvent*>(event);
if (mevent->buttons() & m_buttons) {
return m_clicksHappened < m_clicksToEat;
}
}
return QObject::eventFilter(watched, event);
}
#ifndef KISMOUSECLICKEATER_H
#define KISMOUSECLICKEATER_H
#include <QtGlobal>
#include <QObject>
#include <QElapsedTimer>
class KisMouseClickEater : public QObject
{
public:
KisMouseClickEater(Qt::MouseButtons buttons,
int clicksToEat = 1,
QObject *parent = 0);
~KisMouseClickEater();
void reset();
bool eventFilter(QObject *watched, QEvent *event) override;
private:
Qt::MouseButtons m_buttons = Qt::NoButton;
int m_clicksToEat = 1;
int m_clicksHappened = 0;
bool m_blockTimedRelease = false;
QElapsedTimer m_timeSinceReset;
};
#endif // KISMOUSECLICKEATER_H
......@@ -40,14 +40,15 @@
#include "kis_signals_blocker.h"
#include "kis_canvas_controller.h"
#include "kis_acyclic_signal_connector.h"
#include "KisMouseClickEater.h"
class PopupColorTriangle : public KoTriangleColorSelector
{
public:
PopupColorTriangle(const KoColorDisplayRendererInterface *displayRenderer, QWidget* parent)
: KoTriangleColorSelector(displayRenderer, parent)
, m_dragging(false) {
, m_dragging(false)
{
}
~PopupColorTriangle() override {}
......@@ -108,6 +109,7 @@ KisPopupPalette::KisPopupPalette(KisViewManager* viewManager, KisCoordinatesConv
, m_colorChangeCompressor(new KisSignalCompressor(50, KisSignalCompressor::POSTPONE))
, m_actionCollection(viewManager->actionCollection())
, m_acyclicConnector(new KisAcyclicSignalConnector(this))
, m_clicksEater(new KisMouseClickEater(Qt::RightButton, 1, this))
{
// some UI controls are defined and created based off these variables
......@@ -130,6 +132,15 @@ KisPopupPalette::KisPopupPalette(KisViewManager* viewManager, KisCoordinatesConv
}
m_triangleColorSelector->slotSetColor(fgcolor);
/**
* Tablet support code generates a spurious right-click right after opening
* the window, so we should ignore it. Next right-click will be used for
* closing the popup palette
*/
this->installEventFilter(m_clicksEater);
m_triangleColorSelector->installEventFilter(m_clicksEater);
QRegion maskedRegion(0, 0, m_triangleColorSelector->width(), m_triangleColorSelector->height(), QRegion::Ellipse );
m_triangleColorSelector->setMask(maskedRegion);
......@@ -397,10 +408,6 @@ void KisPopupPalette::showPopupPalette(const QPoint &p)
void KisPopupPalette::showPopupPalette(bool show)
{
if (show) {
m_hadMousePressSinceOpening = false;
m_timeSinceOpening.start();
// don't set the zoom slider if we are outside of the zoom slider bounds. It will change the zoom level to within
// the bounds and cause the canvas to jump between the slider's min and max
if (m_coordinatesConverter->zoomInPercent() > zoomSliderMinValue &&
......@@ -757,24 +764,6 @@ void KisPopupPalette::mousePressEvent(QMouseEvent *event)
QPointF point = event->localPos();
event->accept();
#ifdef Q_OS_WIN
const int tableMouseEventsFlowDelay = 500;
#else
const int tableMouseEventsFlowDelay = 100;
#endif
/**
* Tablet support code generates a spurious right-click right after opening
* the window, so we should ignore it. Next right-click will be used for
* closing the popup palette
*/
if (!m_hadMousePressSinceOpening &&
m_timeSinceOpening.elapsed() > tableMouseEventsFlowDelay) {
m_hadMousePressSinceOpening = true;
}
if (event->button() == Qt::LeftButton) {
//in favorite brushes area
......@@ -843,14 +832,18 @@ void KisPopupPalette::tabletEvent(QTabletEvent *event) {
event->ignore();
}
void KisPopupPalette::showEvent(QShowEvent *event)
{
m_clicksEater->reset();
QWidget::showEvent(event);
}
void KisPopupPalette::mouseReleaseEvent(QMouseEvent *event)
{
QPointF point = event->localPos();
event->accept();
// see a comment in KisPopupPalette::mousePressEvent
if (m_hadMousePressSinceOpening &&
event->buttons() == Qt::NoButton &&
if (event->buttons() == Qt::NoButton &&
event->button() == Qt::RightButton) {
showPopupPalette(false);
......
......@@ -40,6 +40,7 @@ class KisRoundHudButton;
class KisCanvasResourceProvider;
class KisVisualColorSelector;
class KisAcyclicSignalConnector;
class KisMouseClickEater;
class KisPopupPalette : public QWidget
{
......@@ -70,6 +71,7 @@ public:
protected:
void showEvent(QShowEvent *event) override;
void paintEvent(QPaintEvent*) override;
void resizeEvent(QResizeEvent*) override;
void mouseReleaseEvent(QMouseEvent*) override;
......@@ -107,10 +109,6 @@ private:
int m_hoveredColor {0};
int m_selectedColor {0};
QElapsedTimer m_timeSinceOpening;
bool m_hadMousePressSinceOpening {false};
KisCoordinatesConverter *m_coordinatesConverter;
KisViewManager *m_viewManager;
......@@ -151,6 +149,7 @@ private:
// updates the transparency and effects of the whole widget
QGraphicsOpacityEffect *opacityChange {0};
KisMouseClickEater *m_clicksEater;
Q_SIGNALS:
void sigChangeActivePaintop(int);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment