Skip to content

Commit

Permalink
Added mouse cursor auto-hiding to QTermWidget (#582)
Browse files Browse the repository at this point in the history
Mouse cursor auto-hiding was implemented by @luebking: b150d85

Apart from adding mouse auto-hiding to `QTermWidget`, this patch fixes two issues of the above implementation:

 1. `focusInEvent` and `focusOutEvent` weren't good for controlling auto-hiding, because the hidden mouse cursor can be near other widgets of the app (tab, menu-bar, …), in which case, it wasn't shown when put on them. Therefore, `enterEvent`, and `leaveEvent` are used instead.
 2. The scrollbar needed a separate handling because it's a child of `TerminalDisplay`.

NOTE: A related PR for QTerminal will follow this one.
  • Loading branch information
tsujan authored Feb 7, 2025
1 parent b150d85 commit 6d1f8bb
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 25 deletions.
55 changes: 40 additions & 15 deletions lib/TerminalDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
#include <QPainter>
#include <QPixmap>
#include <QRegularExpression>
#include <QScrollBar>
#include <QStyle>
#include <QTimer>
#include <QtDebug>
Expand Down Expand Up @@ -397,7 +396,7 @@ TerminalDisplay::TerminalDisplay(QWidget *parent)

// create scroll bar for scrolling output up and down
// set the scroll bar's slider to occupy the whole area of the scroll bar initially
_scrollBar = new QScrollBar(this);
_scrollBar = new ScrollBar(this);
// since the contrast with the terminal background may not be enough,
// the scrollbar should be auto-filled if not transient
if (!_scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar))
Expand Down Expand Up @@ -1374,11 +1373,6 @@ void TerminalDisplay::focusOutEvent(QFocusEvent*)
blinkEvent();

_blinkTimer->stop();
if (gs_deadSpot.x() > -1 && QApplication::activeWindow()) // we lost the focus internally
{
gs_deadSpot = QPoint(-1,-1);
QApplication::restoreOverrideCursor();
}
}
void TerminalDisplay::focusInEvent(QFocusEvent*)
{
Expand All @@ -1391,12 +1385,28 @@ void TerminalDisplay::focusInEvent(QFocusEvent*)

if (_hasBlinker)
_blinkTimer->start();
}

if (gs_deadSpot.x() < 0 && _hideMouseTimer)
{
gs_futureDeadSpot = mapFromGlobal(QCursor::pos());
_hideMouseTimer->start(_mouseAutohideDelay);
}
void TerminalDisplay::enterEvent(QEnterEvent* event)
{
if (gs_deadSpot.x() < 0 && _hideMouseTimer
// NOTE: scrollBar->underMouse() doesn't work here
&& !_scrollBar->rect().contains(_scrollBar->mapFromParent(event->position().toPoint())))
{
gs_futureDeadSpot = event->position().toPoint();
_hideMouseTimer->start(_mouseAutohideDelay);
}
QWidget::enterEvent(event);
}

void TerminalDisplay::leaveEvent(QEvent* event)
{
if (gs_deadSpot.x() > -1)
{
gs_deadSpot = QPoint(-1,-1);
QApplication::restoreOverrideCursor();
}
QWidget::leaveEvent(event);
}

void TerminalDisplay::paintEvent( QPaintEvent* pe )
Expand Down Expand Up @@ -2155,6 +2165,8 @@ void TerminalDisplay::hideStaleMouse() const
return;
if (QApplication::activeWindow() && QApplication::activeWindow() != window()) // some other app window has the focus
return;
if (_scrollBar->underMouse()) // the mouse is over the scrollbar
return;
gs_deadSpot = gs_futureDeadSpot;
QApplication::setOverrideCursor(Qt::BlankCursor);
}
Expand Down Expand Up @@ -2187,7 +2199,7 @@ void TerminalDisplay::mouseMoveEvent(QMouseEvent* ev)
gs_deadSpot = QPoint(-1,-1);
QApplication::restoreOverrideCursor();
}
gs_futureDeadSpot = ev->pos();
gs_futureDeadSpot = ev->position().toPoint();
Q_ASSERT(_hideMouseTimer);
_hideMouseTimer->start(_mouseAutohideDelay);
}
Expand All @@ -2199,7 +2211,7 @@ void TerminalDisplay::mouseMoveEvent(QMouseEvent* ev)
&& !_scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, _scrollBar))
? _scrollBar->width() : 0);

getCharacterPosition(ev->pos(),charLine,charColumn);
getCharacterPosition(ev->position().toPoint(),charLine,charColumn);

// handle filters
// change link hot-spot appearance on mouse-over
Expand Down Expand Up @@ -2299,7 +2311,7 @@ void TerminalDisplay::mouseMoveEvent(QMouseEvent* ev)
// don't extend selection while pasting
if (ev->buttons() & Qt::MiddleButton) return;

extendSelection( ev->pos() );
extendSelection(ev->position().toPoint());
}

void TerminalDisplay::extendSelection( const QPoint& position )
Expand Down Expand Up @@ -3543,4 +3555,17 @@ bool AutoScrollHandler::eventFilter(QObject* watched,QEvent* event)
return false;
}

ScrollBar::ScrollBar(QWidget* parent) : QScrollBar(parent) {}

void ScrollBar::enterEvent(QEnterEvent* event)
{
// show the mouse cursor that was auto-hidden
if (gs_deadSpot.x() > -1)
{
gs_deadSpot = QPoint(-1,-1);
QApplication::restoreOverrideCursor();
}
QScrollBar::enterEvent(event);
}

//#include "TerminalDisplay.moc"
30 changes: 21 additions & 9 deletions lib/TerminalDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
// Qt
#include <QColor>
#include <QPointer>
#include <QWidget>
#include <QScrollBar>

// Konsole
#include "Filter.h"
Expand All @@ -41,7 +41,6 @@ class QTimer;
class QEvent;
class QGridLayout;
class QKeyEvent;
class QScrollBar;
class QShowEvent;
class QHideEvent;
class QTimerEvent;
Expand Down Expand Up @@ -73,6 +72,7 @@ namespace Konsole
extern unsigned short vt100_graphics[32];

class ScreenWindow;
class ScrollBar;

/**
* A widget which displays output from a terminal emulation and sends input keypresses and mouse activity
Expand Down Expand Up @@ -435,6 +435,12 @@ class KONSOLEPRIVATE_EXPORT TerminalDisplay : public QWidget

int mouseAutohideDelay() const { return _mouseAutohideDelay; }

/**
* hide the mouse cursor after @param delay milliseconds of inactivity
* @param delay < 0 deactivates the behavior
*/
void autoHideMouseAfter(int delay);

public slots:

/**
Expand Down Expand Up @@ -528,12 +534,6 @@ public slots:
*/
void setForegroundColor(const QColor& color);

/**
* hide the mouse cursor after @param delay milliseconds of inactivity
* @param delay < 0 deactivates the behavior
*/
void autoHideMouseAfter(int delay);

void selectionChanged();

signals:
Expand Down Expand Up @@ -596,6 +596,8 @@ public slots:
virtual void fontChange(const QFont &font);
void focusInEvent(QFocusEvent* event) override;
void focusOutEvent(QFocusEvent* event) override;
void enterEvent(QEnterEvent* event) override;
void leaveEvent(QEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* ev) override;
void mousePressEvent( QMouseEvent* ) override;
Expand Down Expand Up @@ -795,7 +797,7 @@ private slots:
bool _columnSelectionMode;

QClipboard* _clipboard;
QScrollBar* _scrollBar;
ScrollBar* _scrollBar;
QTermWidget::ScrollBarPosition _scrollbarLocation;
QString _wordCharacters;
int _bellMode;
Expand Down Expand Up @@ -896,6 +898,16 @@ Q_OBJECT
int _timerId;
};

class ScrollBar : public QScrollBar
{
Q_OBJECT

public:
ScrollBar(QWidget* parent = nullptr);
protected:
void enterEvent(QEnterEvent* event) override;
};

}

#endif // TERMINALDISPLAY_H
6 changes: 5 additions & 1 deletion lib/qtermwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,8 +832,12 @@ void QTermWidget::setWordCharacters(const QString& chars)
m_impl->m_terminalDisplay->setWordCharacters(chars);
}


QTermWidgetInterface* QTermWidget::createWidget(int startnow) const
{
return new QTermWidget(startnow);
}

void QTermWidget::autoHideMouseAfter(int delay)
{
m_impl->m_terminalDisplay->autoHideMouseAfter(delay);
}
2 changes: 2 additions & 0 deletions lib/qtermwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ class QTERMWIDGET_EXPORT QTermWidget : public QWidget, public QTermWidgetInterfa
void setWordCharacters(const QString& chars) override;

QTermWidgetInterface *createWidget(int startnow) const override;

void autoHideMouseAfter(int delay) override;
signals:
void finished();
void copyAvailable(bool);
Expand Down
1 change: 1 addition & 0 deletions lib/qtermwidget_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class QTermWidgetInterface {
virtual QString wordCharacters() const = 0;
virtual void setWordCharacters(const QString& chars) = 0;
virtual QTermWidgetInterface* createWidget(int startnow) const = 0;
virtual void autoHideMouseAfter(int delay) = 0;
};

#define QTermWidgetInterface_iid "lxqt.qtermwidget.QTermWidgetInterface/1.5"
Expand Down

0 comments on commit 6d1f8bb

Please sign in to comment.