modification on mac_tablet

This commit is contained in:
shun_iwasawa 2017-07-31 20:25:26 +09:00
parent e5fcdf6e0d
commit 491a524dd4
8 changed files with 231 additions and 69 deletions

View file

@ -16,6 +16,7 @@
// Qt includes
#include <QString>
#include <QPoint>
#undef DVAPI
#undef DVVAR
@ -91,16 +92,25 @@ public:
ModifierMask m_modifiersMask; //!< Bitmask specifying key modifiers applying
//! on the event.
bool m_leftButtonPressed;
Qt::MouseButtons m_buttons;
Qt::MouseButton m_button;
QPoint m_mousePos; // mouse position obtained with QMouseEvent::pos() or
// QTabletEvent::pos()
public:
TMouseEvent()
: m_pressure(255), m_modifiersMask(NO_KEY), m_leftButtonPressed(false) {}
: m_pressure(255)
, m_modifiersMask(NO_KEY)
, m_buttons(Qt::NoButton)
, m_button(Qt::NoButton) {}
bool isShiftPressed() const { return (m_modifiersMask & SHIFT_KEY); }
bool isAltPressed() const { return (m_modifiersMask & ALT_KEY); }
bool isCtrlPressed() const { return (m_modifiersMask & CTRL_KEY); }
bool isLeftButtonPressed() const { return m_leftButtonPressed; }
bool isLeftButtonPressed() const { return (m_buttons & Qt::LeftButton) != 0; }
Qt::MouseButtons buttons() const { return m_buttons; }
Qt::MouseButton button() const { return m_button; }
QPoint mousePos() const { return m_mousePos; }
void setModifiers(bool shiftPressed, bool altPressed, bool ctrlPressed) {
m_modifiersMask = ModifierMask((shiftPressed << SHIFT_BITSHIFT) |

View file

@ -508,7 +508,8 @@ SceneViewer::SceneViewer(ImageUtils::FullScreenWidget *parent)
, m_toolDisableReason("")
, m_editPreviewSubCamera(false)
, m_locator(NULL)
, m_isLocator(false) {
, m_isLocator(false)
, m_isBusyOnTabletMove(false) {
m_visualSettings.m_sceneProperties =
TApp::instance()->getCurrentScene()->getScene()->getProperties();
// Enables multiple key input.
@ -518,6 +519,8 @@ SceneViewer::SceneViewer(ImageUtils::FullScreenWidget *parent)
setFocusPolicy(Qt::StrongFocus);
setAcceptDrops(true);
this->setMouseTracking(true);
// to be introduced from Qt 5.9
// this->setTabletTracking(true);
for (int i = 0; i < tArrayCount(m_viewAff); i++)
setViewMatrix(getNormalZoomScale(), i);
@ -837,6 +840,8 @@ void SceneViewer::showEvent(QShowEvent *) {
connect(app->getCurrentTool(), SIGNAL(toolCursorTypeChanged()), this,
SLOT(onToolChanged()));
connect(app, SIGNAL(tabletLeft()), this, SLOT(resetTabletStatus()));
if (m_hRuler && m_vRuler) {
if (!viewRulerToggle.getStatus()) {
m_hRuler->hide();
@ -887,6 +892,7 @@ void SceneViewer::hideEvent(QHideEvent *) {
ToolHandle *toolHandle = app->getCurrentTool();
if (toolHandle) toolHandle->disconnect(this);
disconnect(app, SIGNAL(tabletLeft()), this, SLOT(resetTabletStatus()));
// hide locator
if (m_locator && m_locator->isVisible()) m_locator->hide();
}

View file

@ -139,6 +139,8 @@ class SceneViewer final : public GLWidgetForHighDpi,
bool m_isLocator;
bool m_isStyleShortcutSwitchable;
bool m_isBusyOnTabletMove;
// iwsw commented out temporarily
// Ghibli3DLutUtil * m_ghibli3DLutUtil;
public:
@ -284,6 +286,11 @@ protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void onPress(const TMouseEvent &event);
void onMove(const TMouseEvent &event);
void onRelease(const TMouseEvent &event);
void wheelEvent(QWheelEvent *) override;
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
@ -367,6 +374,10 @@ public slots:
// delete preview-subcamera executed from context menu
void doDeleteSubCamera();
void resetTabletStatus();
void releaseBusyOnTabletMove() { m_isBusyOnTabletMove = false; }
signals:
void onZoomChanged();

View file

@ -74,29 +74,49 @@ int modifiers = 0;
//-----------------------------------------------------------------------------
void initToonzEvent(TMouseEvent &toonzEvent, QMouseEvent *event,
int widgetHeight, double pressure, bool isTablet,
bool isClick, int devPixRatio) {
int widgetHeight, double pressure, int devPixRatio) {
toonzEvent.m_pos = TPoint(event->pos().x() * devPixRatio,
widgetHeight - 1 - event->pos().y() * devPixRatio);
toonzEvent.m_pressure = isTablet ? int(255 * pressure) : 255;
toonzEvent.m_mousePos = event->pos();
toonzEvent.m_pressure = 255;
toonzEvent.setModifiers(event->modifiers() & Qt::ShiftModifier,
event->modifiers() & Qt::AltModifier,
event->modifiers() & Qt::ControlModifier);
toonzEvent.m_leftButtonPressed = (event->buttons() & Qt::LeftButton) != 0;
toonzEvent.m_buttons = event->buttons();
toonzEvent.m_button = event->button();
}
//-----------------------------------------------------------------------------
void initToonzEvent(TMouseEvent &toonzEvent, QTabletEvent *event,
int widgetHeight, double pressure, int devPixRatio) {
toonzEvent.m_pos = TPoint(event->pos().x() * devPixRatio,
widgetHeight - 1 - event->pos().y() * devPixRatio);
toonzEvent.m_mousePos = event->pos();
toonzEvent.m_pressure = int(255 * pressure);
toonzEvent.setModifiers(event->modifiers() & Qt::ShiftModifier,
event->modifiers() & Qt::AltModifier,
event->modifiers() & Qt::ControlModifier);
toonzEvent.m_buttons = event->buttons();
toonzEvent.m_button = event->button();
}
//-----------------------------------------------------------------------------
void initToonzEvent(TMouseEvent &toonzEvent, QKeyEvent *event) {
toonzEvent.m_pos = TPoint();
toonzEvent.m_mousePos = QPoint();
toonzEvent.m_pressure = 0;
toonzEvent.setModifiers(event->modifiers() & Qt::ShiftModifier,
event->modifiers() & Qt::AltModifier,
event->modifiers() & Qt::ControlModifier);
toonzEvent.m_leftButtonPressed = false;
toonzEvent.m_buttons = Qt::NoButton;
toonzEvent.m_button = Qt::NoButton;
}
//-----------------------------------------------------------------------------
@ -201,15 +221,11 @@ void SceneViewer::onButtonPressed(FlipConsole::EGadget button) {
void SceneViewer::tabletEvent(QTabletEvent *e) {
if (m_freezedStatus != NO_FREEZED) return;
m_tabletEvent = true;
m_pressure = e->pressure();
m_tabletPressed = false;
m_tabletReleased = false;
m_tabletMove = false;
int type = e->type();
if (type == 92) m_tabletPressed = true;
if (type == 93) m_tabletReleased = true;
if (type == 87) m_tabletMove = true;
m_tabletEvent = true;
m_pressure = e->pressure();
m_tabletPressed = false;
m_tabletReleased = false;
m_tabletMove = false;
// Management of the Eraser pointer
ToolHandle *toolHandle = TApp::instance()->getCurrentTool();
if (e->pointerType() == QTabletEvent::Eraser) {
@ -229,7 +245,58 @@ void SceneViewer::tabletEvent(QTabletEvent *e) {
m_eraserPointerOn = false;
}
}
e->ignore();
switch (e->type()) {
case QEvent::TabletPress: {
// In OSX tablet action may cause only tabletEvent, not followed by
// mousePressEvent.
// So call onPress here in order to enable processing.
// This separation done is only for the left Button (regular pen touch),
// because
// the current Qt seems to fail to catch the Wacom's button binding properly
// with QTabletEvent->button() when pressing middle or right button.
// So, in such case set m_tabletEvent = FALSE and let the mousePressEvent to
// work.
if (e->button() == Qt::LeftButton) {
TMouseEvent mouseEvent;
initToonzEvent(mouseEvent, e, height(), e->pressure(), getDevPixRatio());
m_tabletPressed = true;
onPress(mouseEvent);
} else
m_tabletEvent = false;
} break;
case QEvent::TabletRelease: {
if (m_tabletActive) {
m_tabletReleased = true;
TMouseEvent mouseEvent;
initToonzEvent(mouseEvent, e, height(), e->pressure(), getDevPixRatio());
onRelease(mouseEvent);
} else
m_tabletEvent = false;
} break;
// for now "TabletMove" will be called only when with some button.
// setTabletTracking(bool) will be introduced in Qt5.9
case QEvent::TabletMove: {
if (m_tabletActive) {
QPoint curPos = e->pos() * getDevPixRatio();
// It seems that the tabletEvent is called more often than mouseMoveEvent.
// So I fire the interval timer in order to limit the following process
// to be called in 50fps in maximum.
if (curPos != m_lastMousePos && !m_isBusyOnTabletMove) {
m_isBusyOnTabletMove = true;
TMouseEvent mouseEvent;
initToonzEvent(mouseEvent, e, height(), e->pressure(),
getDevPixRatio());
m_tabletMove = true;
QTimer::singleShot(20, this, SLOT(releaseBusyOnTabletMove()));
onMove(mouseEvent);
}
} else
m_tabletEvent = false;
} break;
default:
break;
}
e->accept();
}
//-----------------------------------------------------------------------------
@ -278,9 +345,30 @@ void SceneViewer::enterEvent(QEvent *) {
//-----------------------------------------------------------------------------
void SceneViewer::mouseMoveEvent(QMouseEvent *event) {
// if this is called just after tabletEvent, skip the execution
if (m_tabletEvent) return;
// there are three cases to come here :
// 1. on mouse is moved (no tablet is used)
// 2. on tablet is moved, with middle or right button is pressed
// 3. on tablet is moved, BUT tabletEvent was not called
// 4. on tablet is moved without pen touching (i.e. floating move)
// the case 3 sometimes occurs on OSX. (reporteed in QTBUG-26532 for Qt4, but
// not confirmed in Qt5)
// the case 4 can be removed once start using Qt5.9 and call
// setTabletTracking(true).
TMouseEvent mouseEvent;
initToonzEvent(mouseEvent, event, height(), 1.0, getDevPixRatio());
onMove(mouseEvent);
}
//-----------------------------------------------------------------------------
void SceneViewer::onMove(const TMouseEvent &event) {
if (m_freezedStatus != NO_FREEZED) return;
QPoint curPos = event->pos() * getDevPixRatio();
QPoint curPos = event.mousePos() * getDevPixRatio();
bool cursorSet = false;
m_lastMousePos = curPos;
@ -346,9 +434,7 @@ void SceneViewer::mouseMoveEvent(QMouseEvent *event) {
}
// if the middle mouse button is pressed while dragging, then do panning
Qt::MouseButtons mousebuttons;
mousebuttons = event->buttons();
if (mousebuttons & Qt::MidButton) {
if (event.buttons() & Qt::MidButton) {
// panning
QPoint p = curPos - m_pos;
if (m_pos == QPoint(0, 0) && p.manhattanLength() > 300) return;
@ -363,9 +449,6 @@ void SceneViewer::mouseMoveEvent(QMouseEvent *event) {
return;
}
tool->setViewer(this);
TMouseEvent toonzEvent;
initToonzEvent(toonzEvent, event, height(), m_pressure, m_tabletEvent,
false, getDevPixRatio());
TPointD worldPos = winToWorld(curPos);
TPointD pos = tool->getMatrix().inv() * worldPos;
@ -387,35 +470,32 @@ void SceneViewer::mouseMoveEvent(QMouseEvent *event) {
// don't perform a drag event if tablet not active
if (m_tabletActive && !m_tabletMove) return;
if (m_tabletEvent && m_tabletActive && m_tabletMove) {
tool->leftButtonDrag(pos, toonzEvent);
tool->leftButtonDrag(pos, event);
}
else if (m_mouseButton == Qt::LeftButton) {
// sometimes the mousePressedEvent is postponed to a wrong mouse move
// event!
if (m_buttonClicked && !m_toolSwitched)
tool->leftButtonDrag(pos, toonzEvent);
if (m_buttonClicked && !m_toolSwitched) tool->leftButtonDrag(pos, event);
} else if (m_pressure == 0) {
tool->mouseMove(pos, toonzEvent);
// m_tabletEvent=false;
tool->mouseMove(pos, event);
}
if (!cursorSet) setToolCursor(this, tool->getCursorId());
m_pos = curPos;
m_tabletMove = false;
} else if (m_mouseButton == Qt::MidButton) {
if ((event->buttons() & Qt::MidButton) == 0)
m_mouseButton = Qt::NoButton;
else
// scrub with shift and middle click
if (event->modifiers() & Qt::ShiftModifier) {
if ((event.buttons() & Qt::MidButton) == 0) m_mouseButton = Qt::NoButton;
// scrub with shift and middle click
else if (event.isShiftPressed()) {
if (curPos.x() > m_pos.x()) {
CommandManager::instance()->execute("MI_NextFrame");
} else if (curPos.x() < m_pos.x()) {
CommandManager::instance()->execute("MI_PrevFrame");
}
} else
} else {
// panning
panQt(curPos - m_pos);
}
m_pos = curPos;
return;
@ -425,6 +505,24 @@ void SceneViewer::mouseMoveEvent(QMouseEvent *event) {
//-----------------------------------------------------------------------------
void SceneViewer::mousePressEvent(QMouseEvent *event) {
// if this is called just after tabletEvent, skip the execution
if (m_tabletEvent) return;
// For now OSX has a critical problem that mousePressEvent is called just
// after releasing the stylus, which causes the irregular stroke while
// float-moving.
// In such case resetTabletStatus() will be called on
// QEvent::TabletLeaveProximity
// and will cancel the onPress operation called here.
TMouseEvent mouseEvent;
initToonzEvent(mouseEvent, event, height(), 1.0, getDevPixRatio());
onPress(mouseEvent);
}
//-----------------------------------------------------------------------------
void SceneViewer::onPress(const TMouseEvent &event) {
// evita i press ripetuti
if (m_buttonClicked) return;
m_buttonClicked = true;
@ -433,16 +531,15 @@ void SceneViewer::mousePressEvent(QMouseEvent *event) {
if (m_mouseButton != Qt::NoButton) return;
m_pos = event->pos() * getDevPixRatio();
m_mouseButton = event->button();
m_pos = event.mousePos() * getDevPixRatio();
m_mouseButton = event.button();
// when using tablet, avoid unexpected drawing behavior occurs when
// middle-click
Qt::MouseButtons mousebuttons;
mousebuttons = event->buttons();
if (m_tabletEvent && m_mouseButton == Qt::MidButton &&
(mousebuttons | Qt::LeftButton))
event.isLeftButtonPressed()) {
return;
}
if (is3DView() && m_current3DDevice != NONE &&
m_mouseButton == Qt::LeftButton)
@ -488,9 +585,6 @@ void SceneViewer::mousePressEvent(QMouseEvent *event) {
tool->setViewer(this);
}
TMouseEvent toonzEvent;
initToonzEvent(toonzEvent, event, height(), m_pressure, m_tabletEvent, true,
getDevPixRatio());
// if(!m_tabletEvent) qDebug() << "-----------------MOUSE PRESS 'PURO'.
// POSSIBILE EMBOLO";
TPointD pos = tool->getMatrix().inv() * winToWorld(m_pos);
@ -503,18 +597,31 @@ void SceneViewer::mousePressEvent(QMouseEvent *event) {
// separate tablet and mouse events
if (m_tabletEvent && m_tabletPressed) {
m_tabletActive = true;
tool->leftButtonDown(pos, toonzEvent);
tool->leftButtonDown(pos, event);
} else if (m_mouseButton == Qt::LeftButton) {
TApp::instance()->getCurrentTool()->setToolBusy(true);
tool->leftButtonDown(pos, toonzEvent);
tool->leftButtonDown(pos, event);
}
if (m_mouseButton == Qt::RightButton) tool->rightButtonDown(pos, toonzEvent);
if (m_mouseButton == Qt::RightButton) tool->rightButtonDown(pos, event);
m_tabletPressed = false;
}
//-----------------------------------------------------------------------------
void SceneViewer::mouseReleaseEvent(QMouseEvent *event) {
// if this is called just after tabletEvent, skip the execution
if (m_tabletEvent) {
m_tabletEvent = false;
return;
}
TMouseEvent mouseEvent;
initToonzEvent(mouseEvent, event, height(), 1.0, getDevPixRatio());
onRelease(mouseEvent);
}
//-----------------------------------------------------------------------------
void SceneViewer::onRelease(const TMouseEvent &event) {
// evita i release ripetuti
if (!m_buttonClicked) return;
m_buttonClicked = false;
@ -528,7 +635,7 @@ void SceneViewer::mouseReleaseEvent(QMouseEvent *event) {
if (m_freezedStatus != NO_FREEZED) return;
if (m_mouseButton != event->button()) return;
if (m_mouseButton != event.button()) return;
// reject if tablet was active and the up button is not actually the pen.
if (m_tabletActive && !m_tabletReleased) return;
@ -546,7 +653,7 @@ void SceneViewer::mouseReleaseEvent(QMouseEvent *event) {
}
if (m_mouseButton == Qt::LeftButton && m_editPreviewSubCamera) {
if (!PreviewSubCameraManager::instance()->mouseReleaseEvent(this, event))
if (!PreviewSubCameraManager::instance()->mouseReleaseEvent(this))
goto quit;
}
@ -561,11 +668,8 @@ void SceneViewer::mouseReleaseEvent(QMouseEvent *event) {
tool->setViewer(this);
{
TMouseEvent toonzEvent;
initToonzEvent(toonzEvent, event, height(), m_pressure, m_tabletEvent,
false, getDevPixRatio());
TPointD pos =
tool->getMatrix().inv() * winToWorld(event->pos() * getDevPixRatio());
TPointD pos = tool->getMatrix().inv() *
winToWorld(event.mousePos() * getDevPixRatio());
TObjectHandle *objHandle = TApp::instance()->getCurrentObject();
if (tool->getToolType() & TTool::LevelTool && !objHandle->isSpline()) {
@ -574,13 +678,32 @@ void SceneViewer::mouseReleaseEvent(QMouseEvent *event) {
}
if (m_mouseButton == Qt::LeftButton || m_tabletReleased) {
if (!m_toolSwitched) tool->leftButtonUp(pos, toonzEvent);
if (!m_toolSwitched) tool->leftButtonUp(pos, event);
TApp::instance()->getCurrentTool()->setToolBusy(false);
}
}
quit:
m_mouseButton = Qt::NoButton;
m_tabletPressed = false;
m_tabletActive = false;
m_tabletReleased = false;
m_tabletMove = false;
m_pressure = 0;
// Leave m_tabletEvent as-is in order to check whether the onRelease is called
// from tabletEvent or not in mouseReleaseEvent.
}
//-----------------------------------------------------------------------------
// on OSX, there is a critical bug that SceneViewer::mousePressEvent is called
// when leaving the stylus and it causes unwanted stroke drawn while
// hover-moving of the pen.
// When QEvent::TabletLeaveProximity is detected, call this function
// in order to force initializing such irregular mouse press.
// NOTE: For now QEvent::TabletLeaveProximity is NOT detected on Windows. See
// QTBUG-53628.
void SceneViewer::resetTabletStatus() {
if (!m_buttonClicked) return;
m_mouseButton = Qt::NoButton;
m_tabletEvent = false;
m_tabletPressed = false;
@ -588,6 +711,9 @@ quit:
m_tabletReleased = false;
m_tabletMove = false;
m_pressure = 0;
m_buttonClicked = false;
if (TApp::instance()->getCurrentTool()->isToolBusy())
TApp::instance()->getCurrentTool()->setToolBusy(false);
}
//-----------------------------------------------------------------------------
@ -1027,8 +1153,7 @@ void SceneViewer::mouseDoubleClickEvent(QMouseEvent *event) {
TTool *tool = TApp::instance()->getCurrentTool()->getTool();
if (!tool || !tool->isEnabled()) return;
TMouseEvent toonzEvent;
initToonzEvent(toonzEvent, event, height(), m_pressure, m_tabletEvent, true,
getDevPixRatio());
initToonzEvent(toonzEvent, event, height(), 1.0, getDevPixRatio());
TPointD pos =
tool->getMatrix().inv() * winToWorld(event->pos() * getDevPixRatio());
TObjectHandle *objHandle = TApp::instance()->getCurrentObject();

View file

@ -115,11 +115,11 @@ TPoint PreviewSubCameraManager::cameraToWin(SceneViewer *viewer,
//----------------------------------------------------------------------
bool PreviewSubCameraManager::mousePressEvent(SceneViewer *viewer,
QMouseEvent *event) {
const TMouseEvent &event) {
if (viewer->is3DView()) return true;
m_mousePressed = true;
m_mousePressPos = event->pos() * viewer->getDevPixRatio();
m_mousePressPos = event.mousePos() * viewer->getDevPixRatio();
m_dragType = getSubCameraDragEnum(viewer, m_mousePressPos);
if (bitwiseExclude(m_dragType, OUTER))
@ -131,10 +131,10 @@ bool PreviewSubCameraManager::mousePressEvent(SceneViewer *viewer,
//----------------------------------------------------------------------
bool PreviewSubCameraManager::mouseMoveEvent(SceneViewer *viewer,
QMouseEvent *event) {
const TMouseEvent &event) {
if (viewer->is3DView()) return true;
QPoint curPos(event->pos() * viewer->getDevPixRatio());
if (event->buttons() == Qt::LeftButton) {
QPoint curPos(event.mousePos() * viewer->getDevPixRatio());
if (event.buttons() == Qt::LeftButton) {
if (!bitwiseContains(m_dragType, INNER)) {
if (abs(curPos.x() - m_mousePressPos.x()) > 10 ||
abs(curPos.y() - m_mousePressPos.y()) > 10)
@ -230,13 +230,12 @@ bool PreviewSubCameraManager::mouseMoveEvent(SceneViewer *viewer,
}
// In case, perform the pan
return event->buttons() == Qt::MidButton;
return event.buttons() == Qt::MidButton;
}
//----------------------------------------------------------------------
bool PreviewSubCameraManager::mouseReleaseEvent(SceneViewer *viewer,
QMouseEvent *event) {
bool PreviewSubCameraManager::mouseReleaseEvent(SceneViewer *viewer) {
if (viewer->is3DView()) return true;
m_mousePressed = false;

View file

@ -99,9 +99,9 @@ public:
TRectD getEditingCameraInterestStageRect() const;
bool mousePressEvent(SceneViewer *viewer, QMouseEvent *event) override;
bool mouseMoveEvent(SceneViewer *viewer, QMouseEvent *event) override;
bool mouseReleaseEvent(SceneViewer *viewer, QMouseEvent *event) override;
bool mousePressEvent(SceneViewer *viewer, const TMouseEvent &event);
bool mouseMoveEvent(SceneViewer *viewer, const TMouseEvent &event);
bool mouseReleaseEvent(SceneViewer *viewer);
void deleteSubCamera(SceneViewer *viewer);

View file

@ -726,6 +726,7 @@ bool TApp::eventFilter(QObject *watched, QEvent *e) {
qApp->processEvents();
m_isPenCloseToTablet = false;
emit tabletLeft();
}
return false; // I want just peek at the event. It must be processed anyway.

View file

@ -232,6 +232,16 @@ protected slots:
void onToolEditingFinished();
void onStartAutoSave();
void onStopAutoSave();
signals:
// on OSX, there is a critical bug that SceneViewer::mousePressEvent is called
// when leaving the stylus and it causes unwanted stroke drawn while
// hover-moving of the pen.
// This signal is to detect tablet leave and force initializing such irregular
// mouse press.
// NOTE: For now QEvent::TabletLeaveProximity is NOT detected on Windows. See
// QTBUG-53628.
void tabletLeft();
};
#endif // TAPP_H