Index: src/view/kateviewinternal.h =================================================================== --- src/view/kateviewinternal.h +++ src/view/kateviewinternal.h @@ -54,6 +54,7 @@ class KateTextLayout; class KateTextAnimation; class KateAbstractInputMode; +class WheelEventFilter; class QScrollBar; @@ -286,6 +287,8 @@ int m_scrollX; int m_scrollY; + WheelEventFilter *m_wheelEventFilter; + Qt::CursorShape m_mouseCursor; Kate::TextCursor m_cursor; Index: src/view/kateviewinternal.cpp =================================================================== --- src/view/kateviewinternal.cpp +++ src/view/kateviewinternal.cpp @@ -63,6 +63,61 @@ static const bool debugPainting = false; +class WheelEventFilter +{ +public: + WheelEventFilter(KateViewInternal *vi) + : m_vi(vi) + , m_accidentalModifier(false) + , m_lastWheelEventUnmodified(false) + { + } + + bool detectZoomingEvent(QWheelEvent *e, bool unsetModifier=true, Qt::KeyboardModifiers modifier=Qt::ControlModifier) + { + bool skip = false; + const qint64 deltaT = m_lastWheelEvent.elapsed(); + Qt::KeyboardModifiers modState = e->modifiers(); + if (modState == modifier) { + // Pressing the Control/Command key within 200ms of the previous "unmodified" wheelevent + // is not allowed to toggle on text zooming + if (m_lastWheelEventUnmodified && deltaT < 200) { + m_accidentalModifier = true; + } + else { + // hold the Control/Command key for 1s without scrolling to re-allow text zooming + if (deltaT > 1000) { + m_accidentalModifier = false; + } + } + m_lastWheelEventUnmodified = false; + if (m_accidentalModifier) { + //qCWarning(LOG_KTE) << "skipping because of accidental keypress; dT=" << deltaT; + skip = true; + if (unsetModifier) { + // unset the ControlModifier so the view scrollbars can handle the scroll + // event and produce normal, not accelerated scrolling + modState &= ~Qt::ControlModifier; + e->setModifiers(modState); + } + } + } else { + m_lastWheelEventUnmodified = true; + m_accidentalModifier = false; + } + m_lastWheelEvent.start(); + + // ctrl pressed -> change font size (only if angle is reported and not accidentally so) + return !skip && modState == modifier; + } + +protected: + KateViewInternal *m_vi; + QElapsedTimer m_lastWheelEvent; + bool m_accidentalModifier; + bool m_lastWheelEventUnmodified; +}; + KateViewInternal::KateViewInternal(KTextEditor::ViewPrivate *view) : QWidget(view) , editSessionNumber(0) @@ -187,6 +242,7 @@ setAcceptDrops(true); + m_wheelEventFilter = new WheelEventFilter(this); // event filter installEventFilter(this); @@ -245,6 +301,8 @@ delete m_bm; delete m_bmStart; delete m_bmEnd; + + delete m_wheelEventFilter; } void KateViewInternal::prepareForDynWrapChange() @@ -3295,8 +3353,9 @@ void KateViewInternal::wheelEvent(QWheelEvent *e) { - // ctrl pressed -> change font size (only if angle is reported) - if (e->modifiers() == Qt::ControlModifier) { + // check if this event should change the font size (Ctrl pressed, angle reported and not accidentally so) + // Note: if detectZoomingEvent() doesn't unset the ControlModifier we'll get accelerated scrolling. + if (m_wheelEventFilter->detectZoomingEvent(e)) { if (e->angleDelta().y() > 0) { slotIncFontSizes(); } else if (e->angleDelta().y() < 0) {