diff --git a/toonz/sources/include/tools/tool.h b/toonz/sources/include/tools/tool.h index 4ee09ea..b4fc823 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,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) | diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index cb0a19c..7974032 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -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(); } diff --git a/toonz/sources/toonz/sceneviewer.h b/toonz/sources/toonz/sceneviewer.h index 574df1a..111e459 100644 --- a/toonz/sources/toonz/sceneviewer.h +++ b/toonz/sources/toonz/sceneviewer.h @@ -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(); diff --git a/toonz/sources/toonz/sceneviewerevents.cpp b/toonz/sources/toonz/sceneviewerevents.cpp index 667cc8e..e0b52e3 100644 --- a/toonz/sources/toonz/sceneviewerevents.cpp +++ b/toonz/sources/toonz/sceneviewerevents.cpp @@ -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(); 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