diff --git a/app/config/appearancesettings.ui b/app/config/appearancesettings.ui
index b198905..383b779 100644
--- a/app/config/appearancesettings.ui
+++ b/app/config/appearancesettings.ui
@@ -1,282 +1,291 @@
AppearanceSettings
0
0
- 713
- 909
+ 582
+ 470
0
0
0
0
-
General
-
Enabling this option will make Yakuake briefly display a colored overlay above the newly focused terminal when moving focus between multiple terminals in a session, as well as over the currently focused terminal when switching to a session with multiple terminals.
Highlight terminals when moving focus between them
-
Window Background
-
-
Background color:
-
-
Qt::Horizontal
41
20
-
Translucency requires support by the selected skin as well as your desktop environment. The default skin supports translucency.
Use skin translucency if supported
-
7
-
Qt::Horizontal
QSizePolicy::Fixed
20
20
-
false
Background color opacity:
-
false
When using translucency, the background color will be filled in using the given opacity before the skin elements are painted on top of the background. This allows influencing the opacity and color tint of translucent areas of the skin.
%
100
50
-
Qt::Horizontal
64
17
-
Skin
-
Get New Skins...
- -
-
-
-
- 0
- 0
-
-
-
- Qt::NoContextMenu
-
-
- Qt::ScrollBarAlwaysOff
-
-
-
- -
-
-
- false
-
-
-
-
false
Remove Skin
-
true
Install Skin...
-
+ -
+
+
+ false
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Qt::NoContextMenu
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+
KColorButton
QPushButton
kcfg_TerminalHighlightOnManualActivation
kcfg_BackgroundColor
kcfg_Translucency
kcfg_BackgroundColorOpacity
skinList
installButton
removeButton
ghnsButton
kcfg_Skin
kcfg_SkinInstalledWithKns
kcfg_Translucency
toggled(bool)
kcfg_BackgroundColorOpacity
setEnabled(bool)
152
76
192
106
kcfg_Translucency
toggled(bool)
backgroundColorOpacityLabel
setEnabled(bool)
152
76
95
106
diff --git a/app/mainwindow.cpp b/app/mainwindow.cpp
index 6f29193..c9bbc46 100644
--- a/app/mainwindow.cpp
+++ b/app/mainwindow.cpp
@@ -1,1544 +1,1545 @@
/*
Copyright (C) 2008-2014 by Eike Hein
Copyright (C) 2009 by Juan Carlos Torres
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 2 of
the License or (at your option) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor appro-
ved by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
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 http://www.gnu.org/licenses/.
*/
#include "mainwindow.h"
#include "settings.h"
#include "config/appearancesettings.h"
#include "config/windowsettings.h"
#include "firstrundialog.h"
#include "sessionstack.h"
#include "skin.h"
#include "tabbar.h"
#include "terminal.h"
#include "titlebar.h"
#include "ui_behaviorsettings.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if HAVE_X11
#include
#include
#include
#endif
#if HAVE_KWAYLAND
#include
#include
#include
#include
#endif
MainWindow::MainWindow(QWidget* parent)
: KMainWindow(parent, Qt::CustomizeWindowHint | Qt::FramelessWindowHint)
{
QDBusConnection::sessionBus().registerObject(QStringLiteral("/yakuake/window"), this, QDBusConnection::ExportScriptableSlots);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_DeleteOnClose, false);
setAttribute(Qt::WA_QuitOnClose, true);
m_skin = new Skin();
m_menu = new QMenu(this);
m_helpMenu = new KHelpMenu(this, KAboutData::applicationData());
m_sessionStack = new SessionStack(this);
m_tabBar = new TabBar(this);
m_titleBar = new TitleBar(this);
m_firstRunDialog = NULL;
m_isFullscreen = false;
#if HAVE_X11
m_kwinAssistPropSet = false;
m_isX11 = KWindowSystem::isPlatformX11();
#else
m_isX11 = false;
#endif
m_isWayland = KWindowSystem::isPlatformWayland();
#if HAVE_KWAYLAND
m_plasmaShell = Q_NULLPTR;
m_plasmaShellSurface = Q_NULLPTR;
initWayland();
#endif
m_toggleLock = false;
setupActions();
setupMenu();
connect(m_tabBar, SIGNAL(newTabRequested()), m_sessionStack, SLOT(addSession()));
connect(m_tabBar, SIGNAL(lastTabClosed()), m_tabBar, SIGNAL(newTabRequested()));
connect(m_tabBar, SIGNAL(lastTabClosed()), this, SLOT(handleLastTabClosed()));
connect(m_tabBar, SIGNAL(tabSelected(int)), m_sessionStack, SLOT(raiseSession(int)));
connect(m_tabBar, SIGNAL(tabClosed(int)), m_sessionStack, SLOT(removeSession(int)));
connect(m_tabBar, SIGNAL(requestTerminalHighlight(int)), m_sessionStack, SLOT(handleTerminalHighlightRequest(int)));
connect(m_tabBar, SIGNAL(requestRemoveTerminalHighlight()), m_sessionStack, SIGNAL(removeTerminalHighlight()));
connect(m_tabBar, SIGNAL(tabContextMenuClosed()), m_sessionStack, SIGNAL(removeTerminalHighlight()));
connect(m_sessionStack, SIGNAL(sessionAdded(int,QString)),
m_tabBar, SLOT(addTab(int,QString)));
connect(m_sessionStack, SIGNAL(sessionRaised(int)), m_tabBar, SLOT(selectTab(int)));
connect(m_sessionStack, SIGNAL(sessionRemoved(int)), m_tabBar, SLOT(removeTab(int)));
connect(m_sessionStack, SIGNAL(activeTitleChanged(QString)),
m_titleBar, SLOT(setTitle(QString)));
connect(m_sessionStack, SIGNAL(activeTitleChanged(QString)),
this, SLOT(setWindowTitle(QString)));
connect(&m_mousePoller, SIGNAL(timeout()), this, SLOT(pollMouse()));
connect(KWindowSystem::self(), SIGNAL(workAreaChanged()), this, SLOT(applyWindowGeometry()));
connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), this, SLOT(updateScreenMenu()));
applySettings();
m_sessionStack->addSession();
if (Settings::firstRun())
{
QMetaObject::invokeMethod(this, "toggleWindowState", Qt::QueuedConnection);
QMetaObject::invokeMethod(this, "showFirstRunDialog", Qt::QueuedConnection);
}
else
{
showStartupPopup();
if (Settings::pollMouse()) toggleMousePoll(true);
}
if (Settings::openAfterStart())
QMetaObject::invokeMethod(this, "toggleWindowState", Qt::QueuedConnection);
}
MainWindow::~MainWindow()
{
Settings::self()->save();
delete m_skin;
}
#if HAVE_KWAYLAND
void MainWindow::initWayland()
{
if (!m_isWayland) {
return;
}
using namespace KWayland::Client;
auto connection = ConnectionThread::fromApplication(this);
if (!connection) {
return;
}
Registry *registry = new Registry(this);
registry->create(connection);
QObject::connect(registry, &Registry::interfacesAnnounced, this,
[registry, this] {
const auto interface = registry->interface(Registry::Interface::PlasmaShell);
if (interface.name != 0) {
m_plasmaShell = registry->createPlasmaShell(interface.name, interface.version, this);
}
}
);
registry->setup();
connection->roundtrip();
}
void MainWindow::initWaylandSurface()
{
if (m_plasmaShellSurface) {
return;
}
if (!m_plasmaShell) {
return;
}
if (auto surface = KWayland::Client::Surface::fromWindow(windowHandle())) {
m_plasmaShellSurface = m_plasmaShell->createSurface(surface, this);
m_plasmaShellSurface->setPosition(pos());
}
}
#endif
bool MainWindow::queryClose()
{
bool confirmQuit = Settings::confirmQuit();
bool hasUnclosableSessions = m_sessionStack->hasUnclosableSessions();
QString closeQuestion = xi18nc("@info","Are you sure you want to quit?");
QString warningMessage;
if ((confirmQuit && m_sessionStack->count() > 1) || hasUnclosableSessions)
{
if (confirmQuit && m_sessionStack->count() > 1)
{
if (hasUnclosableSessions)
warningMessage = xi18nc("@info", "There are multiple open sessions, some of which you have locked to prevent closing them accidentally. These will be killed if you continue.");
else
warningMessage = xi18nc("@info", "There are multiple open sessions. These will be killed if you continue.");
}
else if (hasUnclosableSessions)
{
warningMessage = xi18nc("@info", "There are one or more open sessions that you have locked to prevent closing them accidentally. These will be killed if you continue.");
}
int result = KMessageBox::warningContinueCancel(this,
warningMessage + QStringLiteral("
") + closeQuestion,
xi18nc("@title:window", "Really Quit?"), KStandardGuiItem::quit(), KStandardGuiItem::cancel());
return result != KMessageBox::Cancel;
}
return true;
}
void MainWindow::setupActions()
{
m_actionCollection = new KActionCollection(this);
KToggleFullScreenAction* fullScreenAction = new KToggleFullScreenAction(this);
fullScreenAction->setWindow(this);
actionCollection()->setDefaultShortcut(fullScreenAction, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_F11));
m_actionCollection->addAction(QStringLiteral("view-full-screen"), fullScreenAction);
connect(fullScreenAction, SIGNAL(toggled(bool)), this, SLOT(setFullScreen(bool)));
QAction* action = KStandardAction::quit(this, SLOT(close()), actionCollection());
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Q));
action = KStandardAction::aboutApp(m_helpMenu, SLOT(aboutApplication()), actionCollection());
action = KStandardAction::reportBug(m_helpMenu, SLOT(reportBug()), actionCollection());
action = KStandardAction::aboutKDE(m_helpMenu, SLOT(aboutKDE()), actionCollection());
action = KStandardAction::keyBindings(this, SLOT(configureKeys()), actionCollection());
action = KStandardAction::configureNotifications(this, SLOT(configureNotifications()), actionCollection());
action = KStandardAction::preferences(this, SLOT(configureApp()), actionCollection());
action = KStandardAction::whatsThis(this, SLOT(whatsThis()), actionCollection());
action = actionCollection()->addAction(QStringLiteral("toggle-window-state"));
action->setText(xi18nc("@action", "Open/Retract Yakuake"));
action->setIcon(QIcon::fromTheme(QStringLiteral("yakuake")));
#ifndef Q_OS_WIN /* PORT */
KGlobalAccel::self()->setGlobalShortcut(action, QList() << QKeySequence(Qt::Key_F12));
#else
KGlobalAccel::self()->setGlobalShortcut(action, QList() << QKeySequence(Qt::Key_F11));
#endif
connect(action, SIGNAL(triggered()), this, SLOT(toggleWindowState()));
action = actionCollection()->addAction(QStringLiteral("keep-open"));
action->setText(xi18nc("@action", "Keep window open when it loses focus"));
action->setCheckable(true);
connect(action, SIGNAL(toggled(bool)), this, SLOT(setKeepOpen(bool)));
action = actionCollection()->addAction(QStringLiteral("manage-profiles"));
action->setText(xi18nc("@action", "Manage Profiles..."));
action->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
connect(action, SIGNAL(triggered()), m_sessionStack, SIGNAL(manageProfiles()));
action = actionCollection()->addAction(QStringLiteral("edit-profile"));
action->setText(xi18nc("@action", "Edit Current Profile..."));
action->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("increase-window-width"));
action->setText(xi18nc("@action", "Increase Window Width"));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_Right));
connect(action, SIGNAL(triggered()), this, SLOT(increaseWindowWidth()));
action = actionCollection()->addAction(QStringLiteral("decrease-window-width"));
action->setText(xi18nc("@action", "Decrease Window Width"));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_Left));
connect(action, SIGNAL(triggered()), this, SLOT(decreaseWindowWidth()));
action = actionCollection()->addAction(QStringLiteral("increase-window-height"));
action->setText(xi18nc("@action", "Increase Window Height"));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_Down));
connect(action, SIGNAL(triggered()), this, SLOT(increaseWindowHeight()));
action = actionCollection()->addAction(QStringLiteral("decrease-window-height"));
action->setText(xi18nc("@action", "Decrease Window Height"));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_Up));
connect(action, SIGNAL(triggered()), this, SLOT(decreaseWindowHeight()));
action = actionCollection()->addAction(QStringLiteral("new-session"));
action->setText(xi18nc("@action", "New Session"));
action->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_T));
connect(action, SIGNAL(triggered()), m_sessionStack, SLOT(addSession()));
action = actionCollection()->addAction(QStringLiteral("new-session-two-horizontal"));
action->setText(xi18nc("@action", "Two Terminals, Horizontally"));
action->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
connect(action, SIGNAL(triggered()), m_sessionStack, SLOT(addSessionTwoHorizontal()));
action = actionCollection()->addAction(QStringLiteral("new-session-two-vertical"));
action->setText(xi18nc("@action", "Two Terminals, Vertically"));
action->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
connect(action, SIGNAL(triggered()), m_sessionStack, SLOT(addSessionTwoVertical()));
action = actionCollection()->addAction(QStringLiteral("new-session-quad"));
action->setText(xi18nc("@action", "Four Terminals, Grid"));
action->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
connect(action, SIGNAL(triggered()), m_sessionStack, SLOT(addSessionQuad()));
action = actionCollection()->addAction(QStringLiteral("close-session"));
action->setText(xi18nc("@action", "Close Session"));
action->setIcon(QIcon::fromTheme(QStringLiteral("tab-close")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_W));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("previous-session"));
action->setText(xi18nc("@action", "Previous Session"));
action->setIcon(QIcon::fromTheme(QStringLiteral("go-previous")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::SHIFT + Qt::Key_Left));
connect(action, SIGNAL(triggered()), m_tabBar, SLOT(selectPreviousTab()));
action = actionCollection()->addAction(QStringLiteral("next-session"));
action->setText(xi18nc("@action", "Next Session"));
action->setIcon(QIcon::fromTheme(QStringLiteral("go-next")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::SHIFT + Qt::Key_Right));
connect(action, SIGNAL(triggered()), m_tabBar, SLOT(selectNextTab()));
action = actionCollection()->addAction(QStringLiteral("move-session-left"));
action->setText(xi18nc("@action", "Move Session Left"));
action->setIcon(QIcon::fromTheme(QStringLiteral("arrow-left")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Left));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("move-session-right"));
action->setText(xi18nc("@action", "Move Session Right"));
action->setIcon(QIcon::fromTheme(QStringLiteral("arrow-right")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Right));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("grow-terminal-right"));
action->setText(xi18nc("@action", "Grow Terminal to the Right"));
action->setIcon(QIcon::fromTheme(QStringLiteral("arrow-right")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Right));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("grow-terminal-left"));
action->setText(xi18nc("@action", "Grow Terminal to the Left"));
action->setIcon(QIcon::fromTheme(QStringLiteral("arrow-left")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Left));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("grow-terminal-top"));
action->setText(xi18nc("@action", "Grow Terminal to the Top"));
action->setIcon(QIcon::fromTheme(QStringLiteral("arrow-up")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Up));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("grow-terminal-bottom"));
action->setText(xi18nc("@action", "Grow Terminal to the Bottom"));
action->setIcon(QIcon::fromTheme(QStringLiteral("arrow-down")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Down));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("rename-session"));
action->setText(xi18nc("@action", "Rename Session..."));
action->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_S));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("previous-terminal"));
action->setText(xi18nc("@action", "Previous Terminal"));
action->setIcon(QIcon::fromTheme(QStringLiteral("go-previous")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Up));
connect(action, SIGNAL(triggered()), m_sessionStack, SIGNAL(previousTerminal()));
action = actionCollection()->addAction(QStringLiteral("next-terminal"));
action->setText(xi18nc("@action", "Next Terminal"));
action->setIcon(QIcon::fromTheme(QStringLiteral("go-next")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Down));
connect(action, SIGNAL(triggered()), m_sessionStack, SIGNAL(nextTerminal()));
action = actionCollection()->addAction(QStringLiteral("close-active-terminal"));
action->setText(xi18nc("@action", "Close Active Terminal"));
action->setIcon(QIcon::fromTheme(QStringLiteral("view-close")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_R));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("split-left-right"));
action->setText(xi18nc("@action", "Split Left/Right"));
action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-left-right")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL+ Qt::Key_ParenLeft));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("split-top-bottom"));
action->setText(xi18nc("@action", "Split Top/Bottom"));
action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-top-bottom")));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_ParenRight));
connect(action, SIGNAL(triggered()), this, SLOT(handleContextDependentAction()));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("toggle-session-prevent-closing"));
action->setText(xi18nc("@action", "Prevent Closing"));
action->setCheckable(true);
connect(action, SIGNAL(triggered(bool)), this, SLOT(handleContextDependentToggleAction(bool)));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("toggle-session-keyboard-input"));
action->setText(xi18nc("@action", "Disable Keyboard Input"));
action->setCheckable(true);
connect(action, SIGNAL(triggered(bool)), this, SLOT(handleContextDependentToggleAction(bool)));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("toggle-session-monitor-activity"));
action->setText(xi18nc("@action", "Monitor for Activity"));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_A));
action->setCheckable(true);
connect(action, SIGNAL(triggered(bool)), this, SLOT(handleContextDependentToggleAction(bool)));
m_contextDependentActions << action;
action = actionCollection()->addAction(QStringLiteral("toggle-session-monitor-silence"));
action->setText(xi18nc("@action", "Monitor for Silence"));
actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I));
action->setCheckable(true);
connect(action, SIGNAL(triggered(bool)), this, SLOT(handleContextDependentToggleAction(bool)));
m_contextDependentActions << action;
for (uint i = 1; i <= 10; ++i)
{
action = actionCollection()->addAction(QString(QStringLiteral("switch-to-session-%1")).arg(i));
action->setText(xi18nc("@action", "Switch to Session %1", i));
action->setData(i);
connect(action, SIGNAL(triggered()), this, SLOT(handleSwitchToAction()));
}
m_actionCollection->associateWidget(this);
m_actionCollection->readSettings();
}
void MainWindow::handleContextDependentAction(QAction* action, int sessionId)
{
if (sessionId == -1) sessionId = m_sessionStack->activeSessionId();
if (sessionId == -1) return;
if (!action) action = qobject_cast(QObject::sender());
if (action == actionCollection()->action(QStringLiteral("edit-profile")))
m_sessionStack->editProfile(sessionId);
if (action == actionCollection()->action(QStringLiteral("close-session")))
m_sessionStack->removeSession(sessionId);
if (action == actionCollection()->action(QStringLiteral("move-session-left")))
m_tabBar->moveTabLeft(sessionId);
if (action == actionCollection()->action(QStringLiteral("move-session-right")))
m_tabBar->moveTabRight(sessionId);
if (action == actionCollection()->action(QStringLiteral("rename-session")))
m_tabBar->interactiveRename(sessionId);
if (action == actionCollection()->action(QStringLiteral("close-active-terminal")))
m_sessionStack->closeActiveTerminal(sessionId);
if (action == actionCollection()->action(QStringLiteral("split-left-right")))
m_sessionStack->splitSessionLeftRight(sessionId);
if (action == actionCollection()->action(QStringLiteral("split-top-bottom")))
m_sessionStack->splitSessionTopBottom(sessionId);
if (action == actionCollection()->action(QStringLiteral("grow-terminal-right")))
m_sessionStack->tryGrowTerminalRight(m_sessionStack->activeTerminalId());
if (action == actionCollection()->action(QStringLiteral("grow-terminal-left")))
m_sessionStack->tryGrowTerminalLeft(m_sessionStack->activeTerminalId());
if (action == actionCollection()->action(QStringLiteral("grow-terminal-top")))
m_sessionStack->tryGrowTerminalTop(m_sessionStack->activeTerminalId());
if (action == actionCollection()->action(QStringLiteral("grow-terminal-bottom")))
m_sessionStack->tryGrowTerminalBottom(m_sessionStack->activeTerminalId());
}
void MainWindow::handleContextDependentToggleAction(bool checked, QAction* action, int sessionId)
{
if (sessionId == -1) sessionId = m_sessionStack->activeSessionId();
if (sessionId == -1) return;
if (!action) action = qobject_cast(QObject::sender());
if (action == actionCollection()->action(QStringLiteral("toggle-session-prevent-closing"))) {
m_sessionStack->setSessionClosable(sessionId, !checked);
// Repaint the tab bar when the Prevent Closing action is toggled
// so the lock icon is added to or removed from the tab label.
m_tabBar->repaint();
}
if (action == actionCollection()->action(QStringLiteral("toggle-session-keyboard-input")))
m_sessionStack->setSessionKeyboardInputEnabled(sessionId, !checked);
if (action == actionCollection()->action(QStringLiteral("toggle-session-monitor-activity")))
m_sessionStack->setSessionMonitorActivityEnabled(sessionId, checked);
if (action == actionCollection()->action(QStringLiteral("toggle-session-monitor-silence")))
m_sessionStack->setSessionMonitorSilenceEnabled(sessionId, checked);
}
void MainWindow::setContextDependentActionsQuiet(bool quiet)
{
QListIterator i(m_contextDependentActions);
while (i.hasNext()) i.next()->blockSignals(quiet);
}
void MainWindow::handleToggleTerminalKeyboardInput(bool checked)
{
QAction* action = qobject_cast(QObject::sender());
if (!action || action->data().isNull()) return;
bool ok = false;
int terminalId = action->data().toInt(&ok);
if (!ok) return;
m_sessionStack->setTerminalKeyboardInputEnabled(terminalId, !checked);
}
void MainWindow::handleToggleTerminalMonitorActivity(bool checked)
{
QAction* action = qobject_cast(QObject::sender());
if (!action || action->data().isNull()) return;
bool ok = false;
int terminalId = action->data().toInt(&ok);
if (!ok) return;
m_sessionStack->setTerminalMonitorActivityEnabled(terminalId, checked);
}
void MainWindow::handleToggleTerminalMonitorSilence(bool checked)
{
QAction* action = qobject_cast(QObject::sender());
if (!action || action->data().isNull()) return;
bool ok = false;
int terminalId = action->data().toInt(&ok);
if (!ok) return;
m_sessionStack->setTerminalMonitorSilenceEnabled(terminalId, checked);
}
void MainWindow::handleTerminalActivity(Terminal* terminal)
{
Session* session = qobject_cast(sender());
if (session)
{
disconnect(terminal, SIGNAL(activityDetected(Terminal*)), session, SIGNAL(activityDetected(Terminal*)));
QString message(xi18nc("@info", "Activity detected in monitored terminal in session \"%1\".",
m_tabBar->tabTitle(session->id())));
KNotification::event(QLatin1String("activity"), message, QPixmap(), terminal->partWidget(),
KNotification::CloseWhenWidgetActivated);
}
}
void MainWindow::handleTerminalSilence(Terminal* terminal)
{
Session* session = qobject_cast(sender());
if (session)
{
QString message(xi18nc("@info", "Silence detected in monitored terminal in session \"%1\".",
m_tabBar->tabTitle(session->id())));
KNotification::event(QLatin1String("silence"), message, QPixmap(), terminal->partWidget(),
KNotification::CloseWhenWidgetActivated);
}
}
void MainWindow::handleLastTabClosed()
{
if (isVisible() && !Settings::keepOpenAfterLastSessionCloses())
toggleWindowState();
}
void MainWindow::handleSwitchToAction()
{
QAction* action = qobject_cast(QObject::sender());
if (action && !action->data().isNull())
m_sessionStack->raiseSession(m_tabBar->sessionAtTab(action->data().toInt()-1));
}
void MainWindow::setupMenu()
{
m_menu->insertSection(0, xi18nc("@title:menu", "Help"));
m_menu->addAction(actionCollection()->action(QLatin1String(KStandardAction::name(KStandardAction::WhatsThis))));
m_menu->addAction(actionCollection()->action(QLatin1String(KStandardAction::name(KStandardAction::ReportBug))));
m_menu->addAction(actionCollection()->action(QLatin1String(KStandardAction::name(KStandardAction::AboutApp))));
m_menu->addAction(actionCollection()->action(QLatin1String(KStandardAction::name(KStandardAction::AboutKDE))));
m_menu->insertSection(0, xi18nc("@title:menu", "Quick Options"));
m_menu->addAction(actionCollection()->action(QStringLiteral("view-full-screen")));
m_menu->addAction(actionCollection()->action(QStringLiteral("keep-open")));
m_screenMenu = new QMenu(this);
connect(m_screenMenu, SIGNAL(triggered(QAction*)), this, SLOT(setScreen(QAction*)));
m_screenMenu->setTitle(xi18nc("@title:menu", "Screen"));
m_menu->addMenu(m_screenMenu);
m_windowWidthMenu = new QMenu(this);
connect(m_windowWidthMenu, SIGNAL(triggered(QAction*)), this, SLOT(setWindowWidth(QAction*)));
m_windowWidthMenu->setTitle(xi18nc("@title:menu", "Width"));
m_menu->addMenu(m_windowWidthMenu);
m_windowHeightMenu = new QMenu(this);
connect(m_windowHeightMenu, SIGNAL(triggered(QAction*)), this, SLOT(setWindowHeight(QAction*)));
m_windowHeightMenu->setTitle(xi18nc("@title:menu", "Height"));
m_menu->addMenu(m_windowHeightMenu);
m_menu->insertSection(0, xi18nc("@title:menu", "Settings"));
m_menu->addAction(actionCollection()->action(QStringLiteral("manage-profiles")));
m_menu->addAction(actionCollection()->action(QLatin1String(KStandardAction::name(KStandardAction::KeyBindings))));
m_menu->addAction(actionCollection()->action(QLatin1String(KStandardAction::name(KStandardAction::ConfigureNotifications))));
m_menu->addAction(actionCollection()->action(QLatin1String(KStandardAction::name(KStandardAction::Preferences))));
}
void MainWindow::updateScreenMenu()
{
QAction* action;
m_screenMenu->clear();
action = m_screenMenu->addAction(xi18nc("@item:inmenu", "At mouse location"));
action->setCheckable(true);
action->setData(0);
action->setChecked(Settings::screen() == 0);
for (int i = 1; i <= QApplication::desktop()->screenCount(); i++)
{
action = m_screenMenu->addAction(xi18nc("@item:inmenu", "Screen %1", i));
action->setCheckable(true);
action->setData(i);
action->setChecked(i == Settings::screen());
}
action = m_screenMenu->menuAction();
action->setVisible(QApplication::desktop()->screenCount() > 1);
}
void MainWindow::updateWindowSizeMenus()
{
updateWindowWidthMenu();
updateWindowHeightMenu();
}
void MainWindow::updateWindowWidthMenu()
{
QAction* action = 0;
if (m_windowWidthMenu->isEmpty())
{
for (int i = 10; i <= 100; i += 10)
{
action = m_windowWidthMenu->addAction(QString::number(i) + QStringLiteral("%"));
action->setCheckable(true);
action->setData(i);
action->setChecked(i == Settings::width());
}
}
else
{
QListIterator i(m_windowWidthMenu->actions());
while (i.hasNext())
{
action = i.next();
action->setChecked(action->data().toInt() == Settings::width());
}
}
}
void MainWindow::updateWindowHeightMenu()
{
QAction* action = 0;
if (m_windowHeightMenu->isEmpty())
{
for (int i = 10; i <= 100; i += 10)
{
action = m_windowHeightMenu->addAction(QString::number(i) + QStringLiteral("%"));
action->setCheckable(true);
action->setData(i);
action->setChecked(i == Settings::height());
}
}
else
{
QListIterator i(m_windowHeightMenu->actions());
while (i.hasNext())
{
action = i.next();
action->setChecked(action->data().toInt() == Settings::height());
}
}
}
void MainWindow::configureKeys()
{
KShortcutsDialog::configure(actionCollection());
}
void MainWindow::configureNotifications()
{
KNotifyConfigWidget::configure(this);
}
void MainWindow::configureApp()
{
if (KConfigDialog::showDialog(QStringLiteral("settings"))) return;
KConfigDialog* settingsDialog = new KConfigDialog(this, QStringLiteral("settings"), Settings::self());
+ settingsDialog->setMinimumHeight(560);
settingsDialog->setFaceType(KPageDialog::List);
connect(settingsDialog, &KConfigDialog::settingsChanged, this, &MainWindow::applySettings);
WindowSettings* windowSettings = new WindowSettings(settingsDialog);
settingsDialog->addPage(windowSettings, xi18nc("@title Preferences page name", "Window"), QStringLiteral("preferences-system-windows-move"));
connect(windowSettings, SIGNAL(updateWindowGeometry(int,int,int)),
this, SLOT(setWindowGeometry(int,int,int)));
QWidget* behaviorSettings = new QWidget(settingsDialog);
Ui::BehaviorSettings behaviorSettingsUi;
behaviorSettingsUi.setupUi(behaviorSettings);
settingsDialog->addPage(behaviorSettings, xi18nc("@title Preferences page name", "Behavior"),
QStringLiteral("preferences-system-windows-actions"));
AppearanceSettings* appearanceSettings = new AppearanceSettings(settingsDialog);
settingsDialog->addPage(appearanceSettings, xi18nc("@title Preferences page name", "Appearance"),
QStringLiteral("preferences-desktop-theme"));
connect(settingsDialog, &QDialog::rejected, appearanceSettings, &AppearanceSettings::resetSelection);
settingsDialog->button(QDialogButtonBox::Help)->hide();
settingsDialog->button(QDialogButtonBox::Cancel)->setFocus();
connect(settingsDialog, &QDialog::finished, [=]() {
m_toggleLock = true;
KWindowSystem::activateWindow(winId());
KWindowSystem::forceActiveWindow(winId());
});
settingsDialog->show();
}
void MainWindow::applySettings()
{
if (Settings::dynamicTabTitles())
{
connect(m_sessionStack, SIGNAL(titleChanged(int,QString)),
m_tabBar, SLOT(setTabTitle(int,QString)));
m_sessionStack->emitTitles();
}
else
{
disconnect(m_sessionStack, SIGNAL(titleChanged(int,QString)),
m_tabBar, SLOT(setTabTitle(int,QString)));
}
m_animationTimer.setInterval(Settings::frames() ? 10 : 0);
m_tabBar->setVisible(Settings::showTabBar());
setKeepOpen(Settings::keepOpen());
updateScreenMenu();
updateWindowSizeMenus();
updateUseTranslucency();
applySkin();
applyWindowGeometry();
applyWindowProperties();
}
void MainWindow::applySkin()
{
bool gotSkin = m_skin->load(Settings::skin(), Settings::skinInstalledWithKns());
if (!gotSkin)
{
Settings::setSkin(QStringLiteral("default"));
gotSkin = m_skin->load(Settings::skin());
}
if (!gotSkin)
{
KMessageBox::error(parentWidget(),
xi18nc("@info", "Yakuake was unable to load a skin. It is likely that it was installed incorrectly."
"The application will now quit."),
xi18nc("@title:window", "Cannot Load Skin"));
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
}
m_titleBar->applySkin();
m_tabBar->applySkin();
}
void MainWindow::applyWindowProperties()
{
if (Settings::keepOpen() && !Settings::keepAbove())
{
KWindowSystem::clearState(winId(), NET::KeepAbove);
KWindowSystem::setState(winId(), NET::Sticky | NET::SkipTaskbar | NET::SkipPager);
}
else
KWindowSystem::setState(winId(), NET::KeepAbove | NET::Sticky | NET::SkipTaskbar | NET::SkipPager);
KWindowSystem::setOnAllDesktops(winId(), Settings::showOnAllDesktops());
}
void MainWindow::applyWindowGeometry()
{
int width, height;
QAction* action = actionCollection()->action(QStringLiteral("view-full-screen"));
if (action->isChecked())
{
width = 100;
height = 100;
}
else
{
width = Settings::width();
height = Settings::height();
}
setWindowGeometry(width, height, Settings::position());
}
void MainWindow::setWindowGeometry(int newWidth, int newHeight, int newPosition)
{
QRect workArea = getDesktopGeometry();
int maxHeight = workArea.height() * newHeight / 100;
int targetWidth = workArea.width() * newWidth / 100;
setGeometry(workArea.x() + workArea.width() * newPosition * (100 - newWidth) / 10000,
workArea.y(), targetWidth, maxHeight);
#if HAVE_KWAYLAND
initWaylandSurface();
#endif
maxHeight -= m_titleBar->height();
m_titleBar->setGeometry(0, maxHeight, targetWidth, m_titleBar->height());
if (!isVisible()) m_titleBar->updateMask();
if (Settings::frames() > 0)
m_animationStepSize = maxHeight / Settings::frames();
else
m_animationStepSize = maxHeight;
if (Settings::showTabBar())
{
maxHeight -= m_tabBar->height();
m_tabBar->setGeometry(m_skin->borderWidth(), maxHeight,
width() - 2 * m_skin->borderWidth(), m_tabBar->height());
}
m_sessionStack->setGeometry(m_skin->borderWidth(), 0,
width() - 2 * m_skin->borderWidth(), maxHeight);
updateMask();
}
void MainWindow::setScreen(QAction* action)
{
Settings::setScreen(action->data().toInt());
Settings::self()->save();
applyWindowGeometry();
updateScreenMenu();
}
void MainWindow::setWindowWidth(int width)
{
Settings::setWidth(width);
Settings::self()->save();
applyWindowGeometry();
updateWindowWidthMenu();
}
void MainWindow::setWindowHeight(int height)
{
Settings::setHeight(height);
Settings::self()->save();
applyWindowGeometry();
updateWindowHeightMenu();
}
void MainWindow::setWindowWidth(QAction* action)
{
setWindowWidth(action->data().toInt());
}
void MainWindow::setWindowHeight(QAction* action)
{
setWindowHeight(action->data().toInt());
}
void MainWindow::increaseWindowWidth()
{
if (Settings::width() <= 90) setWindowWidth(Settings::width() + 10);
}
void MainWindow:: decreaseWindowWidth()
{
if (Settings::width() >= 20) setWindowWidth(Settings::width() - 10);
}
void MainWindow::increaseWindowHeight()
{
if (Settings::height() <= 90) setWindowHeight(Settings::height() + 10);
}
void MainWindow::decreaseWindowHeight()
{
if (Settings::height() >= 20) setWindowHeight(Settings::height() - 10);
}
void MainWindow::updateMask()
{
QRegion region = m_titleBar->mask();
region.translate(0, m_titleBar->y());
region += QRegion(0, 0, width(), m_titleBar->y());
setMask(region);
}
void MainWindow::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
if (useTranslucency())
{
painter.setOpacity(qreal(Settings::backgroundColorOpacity()) / 100);
painter.fillRect(rect(), Settings::backgroundColor());
painter.setOpacity(1.0);
}
else
painter.fillRect(rect(), Settings::backgroundColor());
QRect leftBorder(0, 0, m_skin->borderWidth(), height() - m_titleBar->height());
painter.fillRect(leftBorder, m_skin->borderColor());
QRect rightBorder(width() - m_skin->borderWidth(), 0, m_skin->borderWidth(),
height() - m_titleBar->height());
painter.fillRect(rightBorder, m_skin->borderColor());
KMainWindow::paintEvent(event);
}
void MainWindow::moveEvent(QMoveEvent* event)
{
if (Settings::screen() && QApplication::desktop()->screenNumber(this) != getScreen())
{
Settings::setScreen(QApplication::desktop()->screenNumber(this)+1);
updateScreenMenu();
applyWindowGeometry();
}
KMainWindow::moveEvent(event);
}
void MainWindow::closeEvent(QCloseEvent *event)
{
KMainWindow::closeEvent(event);
if (event->isAccepted()) {
QApplication::quit();
}
}
void MainWindow::wmActiveWindowChanged()
{
if (m_toggleLock) {
m_toggleLock = false;
return;
}
KWindowInfo info(KWindowSystem::activeWindow(), 0, NET::WM2TransientFor);
if (info.valid() && info.transientFor() == winId()) {
return;
}
if (m_isX11) {
if (!Settings::keepOpen() && isVisible() && KWindowSystem::activeWindow() != winId()) {
toggleWindowState();
}
} else {
if (!Settings::keepOpen() && hasFocus()) {
toggleWindowState();
}
}
}
void MainWindow::changeEvent(QEvent* event)
{
if (event->type() == QEvent::WindowStateChange
&& (windowState() & Qt::WindowMaximized)
&& Settings::width() != 100
&& Settings::height() != 100)
{
Settings::setWidth(100);
Settings::setHeight(100);
applyWindowGeometry();
updateWindowWidthMenu();
updateWindowHeightMenu();
}
KMainWindow::changeEvent(event);
}
bool MainWindow::event(QEvent* event)
{
if (event->type() == QEvent::Expose) {
// FIXME TODO: We can remove this once we depend on Qt 5.6.1+.
// See: https://bugreports.qt.io/browse/QTBUG-26978
applyWindowProperties();
#if (QT_VERSION > QT_VERSION_CHECK(5, 5, 0))
} else if (event->type() == QEvent::PlatformSurface) {
const QPlatformSurfaceEvent *pSEvent = static_cast(event);
if (pSEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) {
applyWindowProperties();
}
#endif
}
return KMainWindow::event(event);
}
void MainWindow::toggleWindowState()
{
bool visible = isVisible();
if (visible && KWindowSystem::activeWindow() != winId() && Settings::keepOpen())
{
// Window is open but doesn't have focus; it's set to stay open
// regardless of focus loss.
if (Settings::toggleToFocus())
{
// The open/retract action is set to focus the window when it's
// open but lacks focus. The following will cause it to receive
// focus, and in an environment with multiple virtual desktops
// will also cause the window manager to switch to the virtual
// desktop the window resides on.
KWindowSystem::activateWindow(winId());
KWindowSystem::forceActiveWindow(winId());
return;
}
else if (!Settings::showOnAllDesktops()
&& KWindowInfo(winId(), NET::WMDesktop).desktop() != KWindowSystem::currentDesktop())
{
// The open/restrict action isn't set to focus the window, but
// the window is currently on another virtual desktop (the option
// to show it on all of them is disabled), so closing it doesn't
// make sense and we're opting to show it instead to avoid
// requiring the user to invoke the action twice to get to see
// Yakuake. Just forcing focus would cause the window manager to
// switch to the virtual desktop the window currently resides on,
// so move the window to the current desktop before doing so.
KWindowSystem::setOnDesktop(winId(), KWindowSystem::currentDesktop());
KWindowSystem::activateWindow(winId());
KWindowSystem::forceActiveWindow(winId());
return;
}
}
#if HAVE_X11
if (!Settings::useWMAssist() && m_kwinAssistPropSet)
kwinAssistPropCleanup();
if (m_isX11 && Settings::useWMAssist() && KWindowSystem::compositingActive())
kwinAssistToggleWindowState(visible);
else
#endif
if (!m_isWayland) {
xshapeToggleWindowState(visible);
} else {
if (visible)
{
sharedPreHideWindow();
hide();
sharedAfterHideWindow();
}
else
{
sharedPreOpenWindow();
if (KWindowEffects::isEffectAvailable(KWindowEffects::Slide)) {
KWindowEffects::slideWindow(this, KWindowEffects::TopEdge);
}
show();
sharedAfterOpenWindow();
}
}
}
#if HAVE_X11
void MainWindow::kwinAssistToggleWindowState(bool visible)
{
bool gotEffect = false;
Display* display = QX11Info::display();
Atom atom = XInternAtom(display, "_KDE_SLIDE", false);
int count;
Atom* list = XListProperties(display, DefaultRootWindow(display), &count);
if (list != NULL)
{
gotEffect = (qFind(list, list + count, atom) != list + count);
XFree(list);
}
if (gotEffect)
{
Atom atom = XInternAtom(display, "_KDE_SLIDE", false);
if (Settings::frames() > 0)
{
QVarLengthArray data(4);
data[0] = 0;
data[1] = 1;
data[2] = Settings::frames() * 10;
data[3] = Settings::frames() * 10;
XChangeProperty(display, winId(), atom, atom, 32, PropModeReplace,
reinterpret_cast(data.data()), data.size());
m_kwinAssistPropSet = true;
}
else
XDeleteProperty(display, winId(), atom);
if (visible)
{
sharedPreHideWindow();
hide();
sharedAfterHideWindow();
}
else
{
sharedPreOpenWindow();
show();
sharedAfterOpenWindow();
}
return;
}
// Fall back to legacy animation strategy if kwin doesn't have the
// effect loaded.
xshapeToggleWindowState(visible);
}
void MainWindow::kwinAssistPropCleanup()
{
if (!QX11Info::isPlatformX11())
return;
Display* display = QX11Info::display();
Atom atom = XInternAtom(display, "_KDE_SLIDE", false);
XDeleteProperty(display, winId(), atom);
m_kwinAssistPropSet = false;
}
#endif
void MainWindow::xshapeToggleWindowState(bool visible)
{
if (m_animationTimer.isActive()) return;
if (visible)
{
sharedPreHideWindow();
m_animationFrame = Settings::frames();
connect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(xshapeRetractWindow()));
m_animationTimer.start();
}
else
{
m_animationFrame = 0;
connect(&m_animationTimer, SIGNAL(timeout()), this, SLOT(xshapeOpenWindow()));
m_animationTimer.start();
}
}
void MainWindow::xshapeOpenWindow()
{
if (m_animationFrame == 0)
{
sharedPreOpenWindow();
show();
sharedAfterOpenWindow();
}
if (m_animationFrame == Settings::frames())
{
m_animationTimer.stop();
m_animationTimer.disconnect();
m_titleBar->move(0, height() - m_titleBar->height());
updateMask();
}
else
{
int maskHeight = m_animationStepSize * m_animationFrame;
QRegion newMask = m_titleBar->mask();
newMask.translate(0, maskHeight);
newMask += QRegion(0, 0, width(), maskHeight);
m_titleBar->move(0, maskHeight);
setMask(newMask);
m_animationFrame++;
}
}
void MainWindow::xshapeRetractWindow()
{
if (m_animationFrame == 0)
{
m_animationTimer.stop();
m_animationTimer.disconnect();
hide();
sharedAfterHideWindow();
}
else
{
m_titleBar->move(0,m_titleBar->y() - m_animationStepSize);
setMask(QRegion(mask()).translated(0, -m_animationStepSize));
--m_animationFrame;
}
}
void MainWindow::sharedPreOpenWindow()
{
applyWindowGeometry();
updateUseTranslucency();
if (Settings::pollMouse()) toggleMousePoll(false);
if (Settings::rememberFullscreen()) setFullScreen(m_isFullscreen);
}
void MainWindow::sharedAfterOpenWindow()
{
if (!Settings::firstRun()) KWindowSystem::forceActiveWindow(winId());
connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged,
this, &MainWindow::wmActiveWindowChanged);
applyWindowProperties();
#if HAVE_KWAYLAND
initWaylandSurface();
#endif
emit windowOpened();
}
void MainWindow::sharedPreHideWindow()
{
disconnect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged,
this, &MainWindow::wmActiveWindowChanged);
}
void MainWindow::sharedAfterHideWindow()
{
if (Settings::pollMouse()) toggleMousePoll(true);
#if HAVE_KWAYLAND
delete m_plasmaShellSurface;
m_plasmaShellSurface = Q_NULLPTR;
#endif
emit windowClosed();
}
void MainWindow::activate()
{
KWindowSystem::activateWindow(winId());
}
void MainWindow::toggleMousePoll(bool poll)
{
if (poll)
m_mousePoller.start(Settings::pollInterval());
else
m_mousePoller.stop();
}
void MainWindow::pollMouse()
{
QPoint pos = QCursor::pos();
QRect workArea = getDesktopGeometry();
int windowX = workArea.x() + workArea.width() * Settings::position() * (100 - Settings::width()) / 10000;
int windowWidth = workArea.width() * Settings::width() / 100;
if (pos.y() == 0 && pos.x() >= windowX && pos.x() <= (windowX + windowWidth))
toggleWindowState();
}
void MainWindow::setKeepOpen(bool keepOpen)
{
if (Settings::keepOpen() != keepOpen)
{
Settings::setKeepOpen(keepOpen);
Settings::self()->save();
applyWindowProperties();
}
actionCollection()->action(QStringLiteral("keep-open"))->setChecked(keepOpen);
m_titleBar->setFocusButtonState(keepOpen);
}
void MainWindow::setFullScreen(bool state)
{
if (isVisible()) m_isFullscreen = state;
if (state)
{
setWindowState(windowState() | Qt::WindowFullScreen);
setWindowGeometry(100, 100, Settings::position());
}
else
{
setWindowState(windowState() & ~Qt::WindowFullScreen);
setWindowGeometry(Settings::width(), Settings::height(), Settings::position());
}
}
int MainWindow::getScreen()
{
if (!Settings::screen())
return QApplication::desktop()->screenNumber(QCursor::pos());
else
return Settings::screen() - 1;
}
QRect MainWindow::getDesktopGeometry()
{
QRect screenGeometry = QApplication::desktop()->screenGeometry(getScreen());
QAction* action = actionCollection()->action(QStringLiteral("view-full-screen"));
if (action->isChecked())
return screenGeometry;
if (m_isWayland) {
// on Wayland it's not possible to get the work area
return screenGeometry;
}
if (QApplication::desktop()->screenCount() > 1)
{
const QList allWindows = KWindowSystem::windows();
QList offScreenWindows;
QListIterator i(allWindows);
while (i.hasNext())
{
WId windowId = i.next();
if (KWindowSystem::hasWId(windowId))
{
KWindowInfo windowInfo = KWindowInfo(windowId, NET::WMDesktop, NET::WM2ExtendedStrut);
// If windowInfo is valid and the window is located at the same (current)
// desktop with the yakuake window...
if (windowInfo.valid() && windowInfo.isOnCurrentDesktop())
{
NETExtendedStrut strut = windowInfo.extendedStrut();
// Get the area covered by each strut.
QRect topStrut(strut.top_start, 0, strut.top_end - strut.top_start, strut.top_width);
QRect bottomStrut(strut.bottom_start, screenGeometry.bottom() - strut.bottom_width,
strut.bottom_end - strut.bottom_start, strut.bottom_width);
QRect leftStrut(0, strut.left_width, strut.left_start, strut.left_end - strut.left_start);
QRect rightStrut(screenGeometry.right() - strut.right_width, strut.right_start,
strut.right_end - strut.right_start, strut.right_width);
// If the window has no strut, no need to bother further.
if (topStrut.isEmpty() && bottomStrut.isEmpty() && leftStrut.isEmpty() && rightStrut.isEmpty())
continue;
// If any of the strut intersects with our screen geometry, it will be correctly handled
// by workArea().
if (topStrut.intersects(screenGeometry) || bottomStrut.intersects(screenGeometry) ||
leftStrut.intersects(screenGeometry) || rightStrut.intersects(screenGeometry))
continue;
// This window has a strut on the same desktop as us but which does not cover our screen
// geometry. It should be ignored, otherwise the returned work area will wrongly include
// the strut.
offScreenWindows << windowId;
}
}
}
return KWindowSystem::workArea(offScreenWindows).intersected(screenGeometry);
}
return KWindowSystem::workArea();
}
void MainWindow::whatsThis()
{
QWhatsThis::enterWhatsThisMode();
}
void MainWindow::showStartupPopup()
{
QAction* action = static_cast(actionCollection()->action(QStringLiteral("toggle-window-state")));
const QList &shortcuts = KGlobalAccel::self()->shortcut(action);
if (shortcuts.isEmpty())
return;
QString shortcut(shortcuts.first().toString(QKeySequence::NativeText));
QString message(xi18nc("@info", "Application successfully started." "Press %1 to use it ...", shortcut));
KNotification::event(QLatin1String("startup"), message, QPixmap(), this);
}
void MainWindow::showFirstRunDialog()
{
if (!m_firstRunDialog)
{
m_firstRunDialog = new FirstRunDialog(this);
connect(m_firstRunDialog, &QDialog::finished, this, &MainWindow::firstRunDialogFinished);
connect(m_firstRunDialog, &QDialog::accepted, this, &MainWindow::firstRunDialogOk);
}
m_firstRunDialog->show();
}
void MainWindow::firstRunDialogFinished()
{
Settings::setFirstRun(false);
Settings::self()->save();
m_firstRunDialog->deleteLater();
KWindowSystem::forceActiveWindow(winId());
}
void MainWindow::firstRunDialogOk()
{
QAction* action = static_cast(actionCollection()->action(QStringLiteral("toggle-window-state")));
KGlobalAccel::self()->setShortcut(action, QList() << m_firstRunDialog->keySequence(),
KGlobalAccel::NoAutoloading);
actionCollection()->writeSettings();
}
void MainWindow::updateUseTranslucency()
{
m_useTranslucency = (Settings::translucency() && KWindowSystem::compositingActive());
}