diff --git a/.travis.yml b/.travis.yml index bed9ac30014..3d345164008 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: c++ matrix: include: - os: linux - dist: trusty + dist: xenial sudo: required compiler: gcc @@ -37,7 +37,7 @@ addons: - libtag1-dev - libupower-glib-dev - libusb-1.0-0-dev - - libvamp-hostsdk3 + - libvamp-hostsdk3v5 - libwavpack-dev - portaudio19-dev - protobuf-compiler @@ -65,7 +65,7 @@ install: - export COMMON="-j4 qt5=1 test=1 mad=1 faad=1 ffmpeg=1 opus=1 modplug=1 wv=1 hss1394=0 virtualize=0 debug_assertions_fatal=1 verbose=0" ##### - # Ubuntu Trusty Build + # Ubuntu Xenial Build #### # OS X Build diff --git a/CHANGELOG b/CHANGELOG index 21dae471d8e..f42ae9ed2ca 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ * Use 6 instead of only 4 compatible musical keys (major/minor) #3205 * Fix possible memory corruption using JACK on Linux * Fix possible crash when trying to refocus the tracks table while another Mixxx window has focus #3201 +* Fix touch control lp:1895431 ==== 2.2.4 2020-05-10 ==== diff --git a/src/mixxx.cpp b/src/mixxx.cpp index 19610fcfbdd..515e1f5c66c 100644 --- a/src/mixxx.cpp +++ b/src/mixxx.cpp @@ -219,7 +219,6 @@ void MixxxMainWindow::initialize(QApplication* pApp, const CmdlineArgs& args) { pConfig->getValue(ConfigKey("[Controls]", "Tooltips"), static_cast(mixxx::TooltipsPreference::TOOLTIPS_ON))); - setAttribute(Qt::WA_AcceptTouchEvents); m_pTouchShift = new ControlPushButton(ConfigKey("[Controls]", "touch_shift")); m_pChannelHandleFactory = new ChannelHandleFactory(); @@ -1365,26 +1364,6 @@ bool MixxxMainWindow::eventFilter(QObject* obj, QEvent* event) { return QObject::eventFilter(obj, event); } -bool MixxxMainWindow::event(QEvent* e) { - switch(e->type()) { - case QEvent::TouchBegin: - case QEvent::TouchUpdate: - case QEvent::TouchEnd: - { - // If the touch event falls through to the main widget, no touch widget - // was touched, so we resend it as a mouse event. - // We have to accept it here, so QApplication will continue to deliver - // the following events of this touch point as well. - QTouchEvent* touchEvent = static_cast(e); - touchEvent->accept(); - return true; - } - default: - break; - } - return QWidget::event(e); -} - void MixxxMainWindow::closeEvent(QCloseEvent *event) { // WARNING: We can receive a CloseEvent while only partially // initialized. This is because we call QApplication::processEvents to diff --git a/src/mixxx.h b/src/mixxx.h index 4559890144b..842655f26f8 100644 --- a/src/mixxx.h +++ b/src/mixxx.h @@ -110,9 +110,8 @@ class MixxxMainWindow : public QMainWindow { protected: // Event filter to block certain events (eg. tooltips if tooltips are disabled) - virtual bool eventFilter(QObject *obj, QEvent *event); - virtual void closeEvent(QCloseEvent *event); - virtual bool event(QEvent* e); + bool eventFilter(QObject *obj, QEvent *event) override; + void closeEvent(QCloseEvent *event) override; private: void initialize(QApplication *app, const CmdlineArgs& args); diff --git a/src/mixxxapplication.cpp b/src/mixxxapplication.cpp index 2b31c3df7df..2b520333919 100644 --- a/src/mixxxapplication.cpp +++ b/src/mixxxapplication.cpp @@ -41,13 +41,24 @@ Q_IMPORT_PLUGIN(qtaccessiblewidgets) #endif #endif +namespace { + +/// This class allows to change the button of a mouse event on the fly. +/// This is required because we want to change the behaviour of Qts mouse +/// buttony synthesizer without duplicate all the code. +class QMouseEventEditable : public QMouseEvent { + public: + void setButton(Qt::MouseButton button) { + b = button; + } +}; + +} // anonymous namespace MixxxApplication::MixxxApplication(int& argc, char** argv) : QApplication(argc, argv), - m_fakeMouseSourcePointId(0), - m_fakeMouseWidget(NULL), - m_activeTouchButton(Qt::NoButton), - m_pTouchShift(NULL) { + m_rightPressedButtons(0), + m_pTouchShift(nullptr) { registerMetaTypes(); } @@ -207,10 +218,47 @@ bool MixxxApplication::notify(QObject* target, QEvent* event) { #endif // QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #endif // Q_OS_MAC +bool MixxxApplication::notify(QObject* target, QEvent* event) { + // All touch events are translated into two simultaneous events: one for + // the target QWidgetWindow and one for the target QWidget. + // A second touch becomes a mouse move without additional press and release + // events. + switch (event->type()) { + case QEvent::MouseButtonPress: { + QMouseEventEditable* mouseEvent = static_cast(event); + if (mouseEvent->source() == Qt::MouseEventSynthesizedByQt && + mouseEvent->button() == Qt::LeftButton && + touchIsRightButton()) { + // Assert the assumption that QT synthesizes only one click at a time + // = two events (see above) + VERIFY_OR_DEBUG_ASSERT(m_rightPressedButtons < 2) { + break; + } + mouseEvent->setButton(Qt::RightButton); + m_rightPressedButtons++; + } + break; + } + case QEvent::MouseButtonRelease: { + QMouseEventEditable* mouseEvent = static_cast(event); + if (mouseEvent->source() == Qt::MouseEventSynthesizedByQt && + mouseEvent->button() == Qt::LeftButton && + m_rightPressedButtons > 0) { + mouseEvent->setButton(Qt::RightButton); + m_rightPressedButtons--; + } + break; + } + default: + break; + } + return QApplication::notify(target, event); +} + bool MixxxApplication::touchIsRightButton() { if (!m_pTouchShift) { m_pTouchShift = new ControlProxy( "[Controls]", "touch_shift", this); } - return (m_pTouchShift->get() != 0.0); + return m_pTouchShift->toBool(); } diff --git a/src/mixxxapplication.h b/src/mixxxapplication.h index b512f68a8cd..f0dfc94ce2a 100644 --- a/src/mixxxapplication.h +++ b/src/mixxxapplication.h @@ -17,13 +17,13 @@ class MixxxApplication : public QApplication { #endif #endif + bool notify(QObject*, QEvent*) override; + private: bool touchIsRightButton(); void registerMetaTypes(); - int m_fakeMouseSourcePointId; - QWidget* m_fakeMouseWidget; - enum Qt::MouseButton m_activeTouchButton; + int m_rightPressedButtons; ControlProxy* m_pTouchShift; }; diff --git a/src/widget/wwidget.cpp b/src/widget/wwidget.cpp index 4bbd4679ce2..6f29abe7584 100644 --- a/src/widget/wwidget.cpp +++ b/src/widget/wwidget.cpp @@ -38,7 +38,7 @@ WWidget::~WWidget() { } bool WWidget::touchIsRightButton() { - return (m_pTouchShift->get() != 0.0); + return m_pTouchShift->toBool(); } bool WWidget::event(QEvent* e) { @@ -91,11 +91,13 @@ bool WWidget::event(QEvent* e) { const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().first(); QMouseEvent mouseEvent(eventType, - touchPoint.pos().toPoint(), - touchPoint.screenPos().toPoint(), + touchPoint.pos(), + touchPoint.pos(), + touchPoint.screenPos(), m_activeTouchButton, // Button that causes the event Qt::NoButton, // Not used, so no need to fake a proper value. - touchEvent->modifiers()); + touchEvent->modifiers(), + Qt::MouseEventSynthesizedByApplication); return QWidget::event(&mouseEvent); }