From 0ca1391cf50d7e8fe7cd938bc7f8ae8f17ede59d Mon Sep 17 00:00:00 2001 From: Mariusz Glebocki Date: Fri, 30 Mar 2018 20:57:29 -0400 Subject: [PATCH] Properly handle mouse in read-only mode Summary: * Do not send mouse events and emulated up/down keys to programs when read-only mode is enabled. * Set the currentTerminalDisplay before sending key events, like in keyPressEvent. * wheelEvent code is restructured a bit to easily separate code not allowed in read-only mode. Test Plan: * Start Konsole * Run `man man`, do not press any key after enter * Turn on read only mode * Try to scroll using mouse wheel. * Expected result: scrolling does not work in read-only mode * Actual result: scrolling works in read only mode (but only when no key has been pressed before on 2nd terminal screen) * Start konsole * Run a program which uses mouse events, e.g. `vim` (enable mouse with `:set mouse=a`) * Make the program state suitable for using mouse events, e.g. enter a few lines of text * Confirm that mouse events (clicks, selection, wheel) work in the program * Turn on read-only mode * Try: * Click (left/right/middle button), double click * Mouse wheel * Click and move (selecting) * Expected result: mouse events are not passed to the program in read-only mode; nothing happens * Actual result: mouse events are passed to the program Reviewers: #konsole, hindenburg Reviewed By: #konsole, hindenburg Subscribers: hindenburg, #konsole Tags: #konsole Differential Revision: https://phabricator.kde.org/D11763 --- src/TerminalDisplay.cpp | 90 +++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/src/TerminalDisplay.cpp b/src/TerminalDisplay.cpp index 1a120553..b5b5990b 100644 --- a/src/TerminalDisplay.cpp +++ b/src/TerminalDisplay.cpp @@ -2174,7 +2174,9 @@ void TerminalDisplay::mousePressEvent(QMouseEvent* ev) _actSel = 1; // left mouse button pressed but nothing selected yet. } } else { - emit mouseSignal(0, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 0); + if(!_readOnly) { + emit mouseSignal(0, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 0); + } } if ((_openLinksByDirectClick || ((ev->modifiers() & Qt::ControlModifier) != 0u))) { @@ -2192,7 +2194,9 @@ void TerminalDisplay::mousePressEvent(QMouseEvent* ev) if (_mouseMarks || ((ev->modifiers() & Qt::ShiftModifier) != 0u)) { emit configureRequest(ev->pos()); } else { - emit mouseSignal(2, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 0); + if(!_readOnly) { + emit mouseSignal(2, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 0); + } } } } @@ -2618,11 +2622,13 @@ void TerminalDisplay::processMidButtonClick(QMouseEvent* ev) Q_ASSERT(false); } } else { - int charLine = 0; - int charColumn = 0; - getCharacterPosition(ev->pos(), charLine, charColumn); + if(!_readOnly) { + int charLine = 0; + int charColumn = 0; + getCharacterPosition(ev->pos(), charLine, charColumn); - emit mouseSignal(1, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 0); + emit mouseSignal(1, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 0); + } } } @@ -2650,11 +2656,13 @@ void TerminalDisplay::mouseDoubleClickEvent(QMouseEvent* ev) // pass on double click as two clicks. if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) { - // Send just _ONE_ click event, since the first click of the double click - // was already sent by the click handler - emit mouseSignal(0, charColumn + 1, - charLine + 1 + _scrollBar->value() - _scrollBar->maximum(), - 0); // left button + if(!_readOnly) { + // Send just _ONE_ click event, since the first click of the double click + // was already sent by the click handler + emit mouseSignal(0, charColumn + 1, + charLine + 1 + _scrollBar->value() - _scrollBar->maximum(), + 0); // left button + } return; } @@ -2733,10 +2741,10 @@ void TerminalDisplay::wheelEvent(QWheelEvent* ev) const int modifiers = ev->modifiers(); - _scrollWheelState.addWheelEvent(ev); - // ctrl+ for zooming, like in konqueror and firefox if (((modifiers & Qt::ControlModifier) != 0u) && mouseWheelZoom()) { + _scrollWheelState.addWheelEvent(ev); + int steps = _scrollWheelState.consumeLegacySteps(ScrollState::DEFAULT_ANGLE_SCROLL_LINE); for (;steps > 0; --steps) { // wheel-up for increasing font size @@ -2746,21 +2754,22 @@ void TerminalDisplay::wheelEvent(QWheelEvent* ev) // wheel-down for decreasing font size decreaseFontSize(); } + } else if (_mouseMarks && (_scrollBar->maximum() > 0)) { + // If the program running in the terminal is not interested in mouse events, + // send the event to the scrollbar if the slider has room to move - return; - } + _scrollWheelState.addWheelEvent(ev); + + _scrollBar->event(ev); + _sessionController->setSearchStartToWindowCurrentLine(); + _scrollWheelState.clearAll(); + } else if (!_readOnly) { + _scrollWheelState.addWheelEvent(ev); + + if(_mouseMarks && !_isPrimaryScreen) { + // Send simulated up / down key presses to the terminal program + // for the benefit of programs such as 'less' (which use the alternate screen) - // If the program running in the terminal is not interested in mouse events: - // - Send the event to the scrollbar if the slider has room to move - // - Otherwise, send simulated up / down key presses to the terminal program - // for the benefit of programs such as 'less' (which use the alternate screen) - if (_mouseMarks) { - const bool canScroll = _scrollBar->maximum() > 0; - if (canScroll) { - _scrollBar->event(ev); - _sessionController->setSearchStartToWindowCurrentLine(); - _scrollWheelState.clearAll(); - } else if (!_isPrimaryScreen) { // assume that each Up / Down key event will cause the terminal application // to scroll by one line. // @@ -2773,22 +2782,23 @@ void TerminalDisplay::wheelEvent(QWheelEvent* ev) QKeyEvent keyEvent(QEvent::KeyPress, keyCode, Qt::NoModifier); for (int i = 0; i < abs(lines); i++) { + _screenWindow->screen()->setCurrentTerminalDisplay(this); emit keyPressedSignal(&keyEvent); } - } - } else { - // terminal program wants notification of mouse activity - - int charLine; - int charColumn; - getCharacterPosition(ev->pos() , charLine , charColumn); - const int steps = _scrollWheelState.consumeLegacySteps(ScrollState::DEFAULT_ANGLE_SCROLL_LINE); - const int button = (steps > 0) ? 4 : 5; - for (int i = 0; i < abs(steps); ++i) { - emit mouseSignal(button, - charColumn + 1, - charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , - 0); + } else if (!_mouseMarks) { + // terminal program wants notification of mouse activity + + int charLine; + int charColumn; + getCharacterPosition(ev->pos() , charLine , charColumn); + const int steps = _scrollWheelState.consumeLegacySteps(ScrollState::DEFAULT_ANGLE_SCROLL_LINE); + const int button = (steps > 0) ? 4 : 5; + for (int i = 0; i < abs(steps); ++i) { + emit mouseSignal(button, + charColumn + 1, + charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , + 0); + } } } }