diff --git a/src/lib/lib.pro b/src/lib/lib.pro index ad48e1adb..be6d0d824 100644 --- a/src/lib/lib.pro +++ b/src/lib/lib.pro @@ -218,6 +218,7 @@ SOURCES += \ webtab/searchtoolbar.cpp \ webtab/tabbedwebview.cpp \ webtab/webtab.cpp \ + tools/wheelhelper.cpp \ HEADERS += \ 3rdparty/fancytabwidget.h \ @@ -399,6 +400,7 @@ HEADERS += \ webtab/searchtoolbar.h \ webtab/tabbedwebview.h \ webtab/webtab.h \ + tools/wheelhelper.h \ FORMS += \ adblock/adblockaddsubscriptiondialog.ui \ diff --git a/src/lib/tabwidget/combotabbar.cpp b/src/lib/tabwidget/combotabbar.cpp index 3aecb080d..c36daa699 100644 --- a/src/lib/tabwidget/combotabbar.cpp +++ b/src/lib/tabwidget/combotabbar.cpp @@ -1,7 +1,7 @@ /* ============================================================ -* QupZilla - WebKit based browser +* QupZilla - Qt web browser * Copyright (C) 2013-2014 S. Razi Alavizadeh -* Copyright (C) 2014-2016 David Rosca +* Copyright (C) 2014-2017 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -615,8 +615,24 @@ void ComboTabBar::wheelEvent(QWheelEvent* event) { event->accept(); - if (qzSettings->alwaysSwitchTabsWithWheel) { - setCurrentNextEnabledIndex(event->delta() > 0 ? -1 : 1); + if (qzSettings->alwaysSwitchTabsWithWheel || (!m_mainTabBarWidget->isOverflowed() && !m_pinnedTabBarWidget->isOverflowed())) { + m_wheelHelper.processEvent(event); + while (WheelHelper::Direction direction = m_wheelHelper.takeDirection()) { + switch (direction) { + case WheelHelper::WheelUp: + case WheelHelper::WheelLeft: + setCurrentNextEnabledIndex(-1); + break; + + case WheelHelper::WheelDown: + case WheelHelper::WheelRight: + setCurrentNextEnabledIndex(1); + break; + + default: + break; + } + } return; } @@ -636,10 +652,6 @@ void ComboTabBar::wheelEvent(QWheelEvent* event) m_mainTabBarWidget->scrollByWheel(event); } } - - if (!m_mainTabBarWidget->isOverflowed() && !m_pinnedTabBarWidget->isOverflowed()) { - setCurrentNextEnabledIndex(event->delta() > 0 ? -1 : 1); - } } bool ComboTabBar::eventFilter(QObject* obj, QEvent* ev) diff --git a/src/lib/tabwidget/combotabbar.h b/src/lib/tabwidget/combotabbar.h index 67ff3cce1..91e161bd9 100644 --- a/src/lib/tabwidget/combotabbar.h +++ b/src/lib/tabwidget/combotabbar.h @@ -1,7 +1,7 @@ /* ============================================================ -* QupZilla - WebKit based browser +* QupZilla - Qt web browser * Copyright (C) 2013-2014 S. Razi Alavizadeh -* Copyright (C) 2014-2016 David Rosca +* Copyright (C) 2014-2017 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #define COMBOTABBAR_H #include "qzcommon.h" +#include "wheelhelper.h" #include #include @@ -203,6 +204,8 @@ private: bool m_usesScrollButtons; bool m_blockCurrentChangedSignal; + WheelHelper m_wheelHelper; + friend class TabBarHelper; friend class TabStackedWidget; }; diff --git a/src/lib/tools/buttonwithmenu.cpp b/src/lib/tools/buttonwithmenu.cpp index cab4ecb99..cfddb9b1e 100644 --- a/src/lib/tools/buttonwithmenu.cpp +++ b/src/lib/tools/buttonwithmenu.cpp @@ -1,6 +1,6 @@ /* ============================================================ -* QupZilla - WebKit based browser -* Copyright (C) 2010-2014 David Rosca +* QupZilla - Qt web browser +* Copyright (C) 2010-2017 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -122,13 +122,23 @@ void ButtonWithMenu::setCurrentIndex(int index, bool emitSignal) void ButtonWithMenu::wheelEvent(QWheelEvent* event) { - if (event->delta() > 0) { - selectPreviousItem(); - } - else { - selectNextItem(); - } + m_wheelHelper.processEvent(event); + while (WheelHelper::Direction direction = m_wheelHelper.takeDirection()) { + switch (direction) { + case WheelHelper::WheelUp: + case WheelHelper::WheelLeft: + selectPreviousItem(); + break; + case WheelHelper::WheelDown: + case WheelHelper::WheelRight: + selectNextItem(); + break; + + default: + break; + } + } event->accept(); } diff --git a/src/lib/tools/buttonwithmenu.h b/src/lib/tools/buttonwithmenu.h index 7e812f973..9d1025b6d 100644 --- a/src/lib/tools/buttonwithmenu.h +++ b/src/lib/tools/buttonwithmenu.h @@ -1,6 +1,6 @@ /* ============================================================ -* QupZilla - WebKit based browser -* Copyright (C) 2010-2014 David Rosca +* QupZilla - Qt web browser +* Copyright (C) 2010-2017 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ #include #include "toolbutton.h" -#include "qzcommon.h" +#include "wheelhelper.h" // Only to be used in WebSearchBar class ButtonWithMenu : public ToolButton @@ -88,6 +88,7 @@ private: QMenu* m_menu; QVector m_items; Item m_currentItem; + WheelHelper m_wheelHelper; }; // Hint to QVector to use std::realloc on item moving diff --git a/src/lib/tools/wheelhelper.cpp b/src/lib/tools/wheelhelper.cpp new file mode 100644 index 000000000..c8a75967c --- /dev/null +++ b/src/lib/tools/wheelhelper.cpp @@ -0,0 +1,78 @@ +/* ============================================================ +* QupZilla - Qt web browser +* Copyright (C) 2017 David Rosca +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* ============================================================ */ +#include "wheelhelper.h" + +#include + +WheelHelper::WheelHelper() +{ +} + +void WheelHelper::reset() +{ + m_wheelDelta = 0; + m_directions.clear(); +} + +void WheelHelper::processEvent(QWheelEvent *event) +{ + int delta = event->angleDelta().x() ? event->angleDelta().x() : event->angleDelta().y(); + bool directionY = delta == event->angleDelta().y(); + + // When scroll to both directions, prefer the major one + if (event->angleDelta().x() && event->angleDelta().y()) { + if (std::abs(event->angleDelta().y()) > std::abs(event->angleDelta().x())) { + delta = event->angleDelta().y(); + directionY = true; + } else { + delta = event->angleDelta().x(); + directionY = false; + } + } + + // Reset when direction changes + if ((delta < 0 && m_wheelDelta > 0) || (delta > 0 && m_wheelDelta < 0)) { + m_wheelDelta = 0; + } + + m_wheelDelta += delta; + + // Angle delta 120 for common "one click" + // See: http://qt-project.org/doc/qt-5/qml-qtquick-wheelevent.html#angleDelta-prop + while (m_wheelDelta >= 120) { + m_wheelDelta -= 120; + if (directionY) { + m_directions.enqueue(WheelUp); + } else { + m_directions.enqueue(WheelLeft); + } + } + while (m_wheelDelta <= -120) { + m_wheelDelta += 120; + if (directionY) { + m_directions.enqueue(WheelDown); + } else { + m_directions.enqueue(WheelRight); + } + } +} + +WheelHelper::Direction WheelHelper::takeDirection() +{ + return m_directions.isEmpty() ? None : m_directions.dequeue(); +} diff --git a/src/lib/tools/wheelhelper.h b/src/lib/tools/wheelhelper.h new file mode 100644 index 000000000..a6c413705 --- /dev/null +++ b/src/lib/tools/wheelhelper.h @@ -0,0 +1,49 @@ +/* ============================================================ +* QupZilla - Qt web browser +* Copyright (C) 2017 David Rosca +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* ============================================================ */ +#ifndef WHEELHELPER_H +#define WHEELHELPER_H + +#include + +#include "qzcommon.h" + +class QWheelEvent; + +class QUPZILLA_EXPORT WheelHelper +{ +public: + enum Direction { + None = 0, + WheelUp, + WheelDown, + WheelLeft, + WheelRight + }; + + explicit WheelHelper(); + + void reset(); + void processEvent(QWheelEvent *event); + Direction takeDirection(); + +private: + int m_wheelDelta = 0; + QQueue m_directions; +}; + +#endif // WHEELHELPER_H diff --git a/src/lib/webengine/webview.cpp b/src/lib/webengine/webview.cpp index e9ef26040..2d2bf580e 100644 --- a/src/lib/webengine/webview.cpp +++ b/src/lib/webengine/webview.cpp @@ -1019,11 +1019,29 @@ void WebView::_wheelEvent(QWheelEvent *event) } if (event->modifiers() & Qt::ControlModifier) { - event->delta() > 0 ? zoomIn() : zoomOut(); + m_wheelHelper.processEvent(event); + while (WheelHelper::Direction direction = m_wheelHelper.takeDirection()) { + switch (direction) { + case WheelHelper::WheelUp: + case WheelHelper::WheelLeft: + zoomIn(); + break; + + case WheelHelper::WheelDown: + case WheelHelper::WheelRight: + zoomOut(); + break; + + default: + break; + } + } event->accept(); return; } + m_wheelHelper.reset(); + // QtWebEngine ignores QApplication::wheelScrollLines() and instead always scrolls 3 lines if (event->spontaneous()) { const qreal multiplier = QApplication::wheelScrollLines() / 3.0; diff --git a/src/lib/webengine/webview.h b/src/lib/webengine/webview.h index 3a56bb4f3..00d15944b 100644 --- a/src/lib/webengine/webview.h +++ b/src/lib/webengine/webview.h @@ -23,6 +23,7 @@ #include "qzcommon.h" #include "loadrequest.h" +#include "wheelhelper.h" class WebPage; class LoadRequest; @@ -189,6 +190,7 @@ private: bool m_firstLoad; QPointer m_rwhvqt; + WheelHelper m_wheelHelper; static bool s_forceContextMenuOnMouseRelease; };