diff --git a/toonz/sources/include/tools/tool.h b/toonz/sources/include/tools/tool.h index f8d2856..fb95237 100644 --- a/toonz/sources/include/tools/tool.h +++ b/toonz/sources/include/tools/tool.h @@ -16,6 +16,7 @@ // Qt includes #include +#include #undef DVAPI #undef DVVAR @@ -91,17 +92,28 @@ 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() bool m_isTablet; public: TMouseEvent() - : m_pressure(255), m_modifiersMask(NO_KEY), m_leftButtonPressed(false), m_isTablet(false) {} + : m_pressure(255) + , m_modifiersMask(NO_KEY) + , m_buttons(Qt::NoButton) + , m_button(Qt::NoButton) + , m_isTablet(false) {} 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; } bool isTablet() const { return m_isTablet; } void setModifiers(bool shiftPressed, bool altPressed, bool ctrlPressed) { diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index 9016ac6..7974032 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -472,6 +472,10 @@ SceneViewer::SceneViewer(ImageUtils::FullScreenWidget *parent) , m_mouseButton(Qt::NoButton) , m_foregroundDrawing(false) , m_tabletEvent(false) + , m_tabletActive(false) + , m_tabletMove(false) + , m_tabletPressed(false) + , m_tabletReleased(false) , m_buttonClicked(false) , m_referenceMode(NORMAL_REFERENCE) , m_previewMode(NO_PREVIEW) @@ -504,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. @@ -514,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); @@ -833,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(); @@ -883,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(); } diff --git a/toonz/sources/toonz/sceneviewer.h b/toonz/sources/toonz/sceneviewer.h index 8e2c3b3..111e459 100644 --- a/toonz/sources/toonz/sceneviewer.h +++ b/toonz/sources/toonz/sceneviewer.h @@ -66,7 +66,8 @@ class SceneViewer final : public GLWidgetForHighDpi, Qt::MouseButton m_mouseButton; bool m_foregroundDrawing; - bool m_tabletEvent; + bool m_tabletEvent, m_tabletPressed, m_tabletReleased, m_tabletMove, + m_tabletActive; // used to handle wrong mouse drag events! bool m_buttonClicked, m_toolSwitched; bool m_shownOnce = false; @@ -138,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: @@ -283,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; @@ -366,6 +374,10 @@ public slots: // delete preview-subcamera executed from context menu void doDeleteSubCamera(); + void resetTabletStatus(); + + void releaseBusyOnTabletMove() { m_isBusyOnTabletMove = false; } + signals: void onZoomChanged(); diff --git a/toonz/sources/toonz/sceneviewerevents.cpp b/toonz/sources/toonz/sceneviewerevents.cpp index dcdd25d..98767b5 100644 --- a/toonz/sources/toonz/sceneviewerevents.cpp +++ b/toonz/sources/toonz/sceneviewerevents.cpp @@ -74,30 +74,51 @@ 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_isTablet = isTablet; + toonzEvent.m_buttons = event->buttons(); + toonzEvent.m_button = event->button(); + toonzEvent.m_isTablet = false; +} + +//----------------------------------------------------------------------------- + +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(); + toonzEvent.m_isTablet = true; } //----------------------------------------------------------------------------- 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; toonzEvent.m_isTablet = false; } @@ -203,9 +224,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_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) { @@ -225,7 +248,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(); } //----------------------------------------------------------------------------- @@ -274,9 +348,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; @@ -342,9 +437,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; @@ -359,9 +452,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; @@ -378,31 +468,37 @@ void SceneViewer::mouseMoveEvent(QMouseEvent *event) { // qDebug() << "mouseMoveEvent. " << (m_tabletEvent?"tablet":"mouse") // << " pressure=" << m_pressure << " mouseButton=" << m_mouseButton // << " buttonClicked=" << m_buttonClicked; - if ((m_tabletEvent && m_pressure > 0) || m_mouseButton == Qt::LeftButton) { + + // separate tablet events from mouse events + // 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, 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_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; @@ -412,6 +508,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; @@ -420,16 +534,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) @@ -475,12 +588,6 @@ void SceneViewer::mousePressEvent(QMouseEvent *event) { tool->setViewer(this); } - TMouseEvent toonzEvent; - if (m_pressure > 0 && !m_tabletEvent) m_tabletEvent = true; - - if (TApp::instance()->isPenCloseToTablet()) m_tabletEvent = true; - 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); @@ -490,16 +597,34 @@ void SceneViewer::mousePressEvent(QMouseEvent *event) { pos.x /= m_dpiScale.x; pos.y /= m_dpiScale.y; } - if (m_mouseButton == Qt::LeftButton) { + // separate tablet and mouse events + if (m_tabletEvent && m_tabletPressed) { + m_tabletActive = true; + 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; @@ -513,8 +638,10 @@ 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; if (m_current3DDevice != NONE) { m_mouseButton = Qt::NoButton; m_tabletEvent = false; @@ -529,7 +656,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; } @@ -544,11 +671,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()) { @@ -556,17 +680,43 @@ void SceneViewer::mouseReleaseEvent(QMouseEvent *event) { pos.y /= m_dpiScale.y; } - if (m_mouseButton == Qt::LeftButton) { - if (!m_toolSwitched) tool->leftButtonUp(pos, toonzEvent); + if (m_mouseButton == Qt::LeftButton || m_tabletReleased) { + 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. +} - m_mouseButton = Qt::NoButton; - m_tabletEvent = false; - m_pressure = 0; +//----------------------------------------------------------------------------- +// 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; + m_tabletActive = false; + m_tabletReleased = false; + m_tabletMove = false; + m_pressure = 0; + m_buttonClicked = false; + if (TApp::instance()->getCurrentTool()->isToolBusy()) + TApp::instance()->getCurrentTool()->setToolBusy(false); } //----------------------------------------------------------------------------- @@ -669,42 +819,42 @@ bool SceneViewer::event(QEvent *e) { } /* -switch(e->type()) -{ -case QEvent::Enter: -qDebug() << "************************** Enter"; -break; -case QEvent::Leave: -qDebug() << "************************** Leave"; -break; - -case QEvent::TabletPress: -qDebug() << "************************** TabletPress" << m_pressure; -break; -case QEvent::TabletMove: -qDebug() << "************************** TabletMove"; -break; -case QEvent::TabletRelease: -qDebug() << "************************** TabletRelease"; -break; - - -case QEvent::MouseButtonPress: -qDebug() << "**************************MouseButtonPress" << m_pressure << " " -<< m_tabletEvent; -break; -case QEvent::MouseMove: -qDebug() << "**************************MouseMove" << m_pressure; -break; -case QEvent::MouseButtonRelease: -qDebug() << "**************************MouseButtonRelease"; -break; - -case QEvent::MouseButtonDblClick: -qDebug() << "============================== MouseButtonDblClick"; -break; -} -*/ + switch(e->type()) + { + case QEvent::Enter: + qDebug() << "************************** Enter"; + break; + case QEvent::Leave: + qDebug() << "************************** Leave"; + break; + + case QEvent::TabletPress: + qDebug() << "************************** TabletPress" << m_pressure; + break; + case QEvent::TabletMove: + qDebug() << "************************** TabletMove"; + break; + case QEvent::TabletRelease: + qDebug() << "************************** TabletRelease"; + break; + + + case QEvent::MouseButtonPress: + qDebug() << "**************************MouseButtonPress" << m_pressure << " " + << m_tabletEvent; + break; + case QEvent::MouseMove: + qDebug() << "**************************MouseMove" << m_pressure; + break; + case QEvent::MouseButtonRelease: + qDebug() << "**************************MouseButtonRelease"; + break; + + case QEvent::MouseButtonDblClick: + qDebug() << "============================== MouseButtonDblClick"; + break; + } + */ return QGLWidget::event(e); } @@ -1006,8 +1156,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(); diff --git a/toonz/sources/toonz/subcameramanager.cpp b/toonz/sources/toonz/subcameramanager.cpp index 0b53d45..3975403 100644 --- a/toonz/sources/toonz/subcameramanager.cpp +++ b/toonz/sources/toonz/subcameramanager.cpp @@ -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; diff --git a/toonz/sources/toonz/subcameramanager.h b/toonz/sources/toonz/subcameramanager.h index e77e9d5..44c42b0 100644 --- a/toonz/sources/toonz/subcameramanager.h +++ b/toonz/sources/toonz/subcameramanager.h @@ -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); diff --git a/toonz/sources/toonz/tapp.cpp b/toonz/sources/toonz/tapp.cpp index 5988f2c..8318336 100644 --- a/toonz/sources/toonz/tapp.cpp +++ b/toonz/sources/toonz/tapp.cpp @@ -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. diff --git a/toonz/sources/toonz/tapp.h b/toonz/sources/toonz/tapp.h index e057482..22e6ee6 100644 --- a/toonz/sources/toonz/tapp.h +++ b/toonz/sources/toonz/tapp.h @@ -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