Commit 8fb68993 authored by Luis Javier Merino's avatar Luis Javier Merino Committed by Tomaz Canabrava
Browse files

Focus session from notification

Adds a "Show session" button to notifications, which, when clicked, will
focus the originating session.

Original patch by Kasper Laudrup at bug 305162, then updated by Martin
T. H. Sandsmark.

Now updated and extended to silence/activity/process termination
notifications, adding support for focusing a TerminalDisplay inside a
hierarchy of ViewSplitters inside a TabbedViewContainer, and using
KWindowSystem::forceActiveWindow() instead of ::activateWindow().

BUG: 305162
BUG: 344208
parent 416941b7
......@@ -91,6 +91,7 @@ MainWindow::MainWindow()
connect(_viewManager, &Konsole::ViewManager::newViewWithProfileRequest, this, &Konsole::MainWindow::newFromProfile);
connect(_viewManager, &Konsole::ViewManager::newViewRequest, this, &Konsole::MainWindow::newTab);
connect(_viewManager, &Konsole::ViewManager::terminalsDetached, this, &Konsole::MainWindow::terminalsDetached);
connect(_viewManager, &Konsole::ViewManager::activationRequest, this, &Konsole::MainWindow::activationRequest);
setCentralWidget(_viewManager->widget());
......@@ -153,6 +154,11 @@ void MainWindow::updateUseTransparency()
WindowSystemInfo::HAVE_TRANSPARENCY = useTranslucency;
}
void MainWindow::activationRequest()
{
KWindowSystem::forceActiveWindow(winId());
}
void MainWindow::rememberMenuAccelerators()
{
const QList<QAction *> actions = menuBar()->actions();
......
......@@ -169,6 +169,9 @@ private Q_SLOTS:
void applyKonsoleSettings();
// Ask the window manager to show this application window
void activationRequest();
void updateUseTransparency();
public Q_SLOTS:
......
......@@ -768,6 +768,7 @@ TerminalDisplay *ViewManager::createView(Session *session)
session->setDarkBackground(colorSchemeForProfile(profile)->hasDarkBackground());
display->setFocus(Qt::OtherFocusReason);
// updateDetachViewState();
connect(display, &TerminalDisplay::activationRequest, this, &Konsole::ViewManager::activationRequest);
return display;
}
......
......@@ -234,6 +234,8 @@ Q_SIGNALS:
/** Requests creation of a new view, with the selected profile. */
void newViewWithProfileRequest(const QExplicitlySharedDataPointer<Profile> &profile);
void activationRequest();
public Q_SLOTS:
/** DBus slot that returns the number of sessions in the current view. */
Q_SCRIPTABLE int sessionCount();
......
......@@ -622,11 +622,13 @@ void Session::silenceTimerDone()
view = _views.first();
}
KNotification::event(hasFocus() ? QStringLiteral("Silence") : QStringLiteral("SilenceHidden"),
i18n("Silence in '%1' (Session '%2')", _displayTitle, _nameTitle),
QPixmap(),
view,
KNotification::CloseWhenWidgetActivated);
KNotification *notification = KNotification::event(hasFocus() ? QStringLiteral("Silence") : QStringLiteral("SilenceHidden"),
i18n("Silence in '%1' (Session '%2')", _displayTitle, _nameTitle),
QPixmap(),
view,
KNotification::CloseWhenWidgetActivated);
notification->setDefaultAction(i18n("Show session"));
view->connect(notification, &KNotification::defaultActivated, view, &TerminalDisplay::notificationClicked);
setPendingNotification(Notification::Silence);
}
......@@ -1778,11 +1780,13 @@ void Session::handleActivity()
}
if (_monitorActivity && !_notifiedActivity) {
KNotification::event(hasFocus() ? QStringLiteral("Activity") : QStringLiteral("ActivityHidden"),
i18n("Activity in '%1' (Session '%2')", _displayTitle, _nameTitle),
QPixmap(),
view,
KNotification::CloseWhenWidgetActivated);
KNotification *notification = KNotification::event(hasFocus() ? QStringLiteral("Activity") : QStringLiteral("ActivityHidden"),
i18n("Activity in '%1' (Session '%2')", _displayTitle, _nameTitle),
QPixmap(),
view,
KNotification::CloseWhenWidgetActivated);
notification->setDefaultAction(i18n("Show session"));
view->connect(notification, &KNotification::defaultActivated, view, &TerminalDisplay::notificationClicked);
// mask activity notification for a while to avoid flooding
_notifiedActivity = true;
......
......@@ -351,11 +351,14 @@ void SessionController::snapshot()
if (_monitorProcessFinish) {
bool isForegroundProcessActive = session()->isForegroundProcessActive();
if (!_previousForegroundProcessName.isNull() && !isForegroundProcessActive) {
KNotification::event(session()->hasFocus() ? QStringLiteral("ProcessFinished") : QStringLiteral("ProcessFinishedHidden"),
i18n("The process '%1' has finished running in session '%2'", _previousForegroundProcessName, session()->nameTitle()),
QPixmap(),
view(),
KNotification::CloseWhenWidgetActivated);
KNotification *notification =
KNotification::event(session()->hasFocus() ? QStringLiteral("ProcessFinished") : QStringLiteral("ProcessFinishedHidden"),
i18n("The process '%1' has finished running in session '%2'", _previousForegroundProcessName, session()->nameTitle()),
QPixmap(),
view(),
KNotification::CloseWhenWidgetActivated);
notification->setDefaultAction(i18n("Show session"));
view()->connect(notification, &KNotification::defaultActivated, view(), &TerminalDisplay::notificationClicked);
}
_previousForegroundProcessName = isForegroundProcessActive ? session()->foregroundProcessName() : QString();
}
......
......@@ -7,9 +7,11 @@
*/
#include "TerminalBell.h"
#include "TerminalDisplay.h"
#include <QTimer>
#include <KLocalizedString>
#include <KNotification>
#include <chrono>
......@@ -25,19 +27,22 @@ TerminalBell::TerminalBell(Enum::BellModeEnum bellMode)
{
}
void TerminalBell::bell(QWidget *terminalDisplay, const QString &message, bool terminalHasFocus)
void TerminalBell::bell(TerminalDisplay *terminalDisplay, const QString &message, bool terminalHasFocus)
{
switch (_bellMode) {
case Enum::SystemBeepBell:
KNotification::beep();
break;
case Enum::NotifyBell:
case Enum::NotifyBell: {
// STABLE API:
// Please note that these event names, "BellVisible" and "BellInvisible",
// should not change and should be kept stable, because other applications
// that use this code via KPart rely on these names for notifications.
KNotification::event(terminalHasFocus ? QStringLiteral("BellVisible") : QStringLiteral("BellInvisible"), message, QPixmap(), terminalDisplay);
break;
KNotification *notification =
KNotification::event(terminalHasFocus ? QStringLiteral("BellVisible") : QStringLiteral("BellInvisible"), message, QPixmap(), terminalDisplay);
notification->setDefaultAction(i18n("Show session"));
terminalDisplay->connect(notification, &KNotification::defaultActivated, terminalDisplay, &TerminalDisplay::notificationClicked);
} break;
case Enum::VisualBell:
Q_EMIT visualBell();
break;
......
......@@ -15,13 +15,15 @@
namespace Konsole
{
class TerminalDisplay;
class TerminalBell : public QObject
{
Q_OBJECT
public:
explicit TerminalBell(Enum::BellModeEnum bellMode);
void bell(QWidget *td, const QString &message, bool terminalHasFocus);
void bell(TerminalDisplay *td, const QString &message, bool terminalHasFocus);
/**
* Sets the type of effect used to alert the user when a 'bell' occurs in the
......
......@@ -1909,6 +1909,11 @@ Screen::DecodingOptions TerminalDisplay::currentDecodingOptions()
return decodingOptions;
}
void TerminalDisplay::notificationClicked()
{
Q_EMIT activationRequest();
}
void TerminalDisplay::mouseTripleClickEvent(QMouseEvent *ev)
{
if (_screenWindow.isNull()) {
......
......@@ -449,6 +449,8 @@ public Q_SLOTS:
// Used for requestPrint
void printScreen();
void notificationClicked();
Q_SIGNALS:
void requestToggleExpansion();
void requestMoveToNewTab(TerminalDisplay *display);
......@@ -487,6 +489,7 @@ Q_SIGNALS:
*/
void overrideShortcutCheck(QKeyEvent *keyEvent, bool &override);
void activationRequest();
void sendStringToEmu(const QByteArray &local8BitString);
void compositeFocusChanged(bool focused);
......
......@@ -331,6 +331,9 @@ void TabbedViewContainer::addView(TerminalDisplay *view)
connect(viewSplitter, &ViewSplitter::destroyed, this, &TabbedViewContainer::viewDestroyed);
connect(viewSplitter, &ViewSplitter::terminalDisplayDropped, this, &TabbedViewContainer::terminalDisplayDropped);
// Put this view on the foreground if it requests so, eg. on bell activity
connect(view, &TerminalDisplay::activationRequest, this, &Konsole::TabbedViewContainer::activateView);
setCurrentIndex(index);
Q_EMIT viewAdded(view);
}
......@@ -341,6 +344,8 @@ void TabbedViewContainer::splitView(TerminalDisplay *view, Qt::Orientation orien
viewSplitter->clearMaximized();
viewSplitter->addTerminalDisplay(view, orientation);
connectTerminalDisplay(view);
// Put this view on the foreground if it requests so, eg. on bell activity
connect(view, &TerminalDisplay::activationRequest, this, &Konsole::TabbedViewContainer::activateView);
}
void TabbedViewContainer::connectTerminalDisplay(TerminalDisplay *display)
......@@ -389,6 +394,15 @@ void TabbedViewContainer::forgetView()
}
}
void TabbedViewContainer::activateView()
{
if (QWidget *widget = qobject_cast<QWidget *>(sender())) {
auto topLevelSplitter = qobject_cast<ViewSplitter *>(widget->parentWidget())->getToplevelSplitter();
setCurrentWidget(topLevelSplitter);
widget->setFocus();
}
}
void TabbedViewContainer::activateNextView()
{
QWidget *active = currentWidget();
......
......@@ -213,6 +213,7 @@ protected:
private Q_SLOTS:
void viewDestroyed(QObject *view);
void konsoleConfigChanged();
void activateView();
private:
void forgetView();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment