Add new option for behavior when window on different desktop is activated

When a window that is on a different virtual desktop than the current one gets
activated, the current behavior is that the active virtual desktop will be switched
to the one the activated window is on. This may seem reasonable for a scenario where
the user explicitly intends to activate an existing window on a different desktop.
However, the following scenario is also (perhaps even more?) common: When an
application responds to a launch command by requesting to activate an existing
instance instead of opening a new one (such as Firefox or KDE System Settings), an
existing window on any desktop will get activated even when what the user had in
mind was opening a new window (on the desktop they are currently in). 

This means that opening an application, such as following a URL or accessing a
system setting, unexpectedly results in the user being teleported to a different
virtual desktop. This can be very irritating. The more expected behavior for these
users would be to have windows always open on the desktop where they are called
from. That's is what this commit adds as a new option.

BUG: 438375
FIXED-IN: 5.26
This commit is contained in:
Natalie Clarius 2022-08-31 18:57:21 +00:00 committed by Nate Graham
parent 3973b7401d
commit 6b38b03724
8 changed files with 109 additions and 5 deletions

View file

@ -16,8 +16,8 @@
<!-- TRANS:ROLES_OF_TRANSLATORS -->
</authorgroup>
<date>2021-04-09</date>
<releaseinfo>Plasma 5.20</releaseinfo>
<date>2022-08-31</date>
<releaseinfo>Plasma 5.26</releaseinfo>
<keywordset>
<keyword>KDE</keyword>
@ -699,6 +699,21 @@ with the proper window type for this feature to work.</para></listitem>
</variablelist>
<sect3 id="action-virtual-desktop-behavior">
<title>Virtual Desktop behavior</title>
<para>Sometimes calling an application will activate an existing window rather than opening a new window. This setting controls what should happen if that activated window is located on a Virtual Desktop other than the current one.</para>
<variablelist>
<varlistentry>
<term><guilabel>Switch to that Virtual Desktop</guilabel></term>
<listitem><para>Will switch to the Virtual Desktop where the window is currently located. Choose this option if you would like the active desktop to automatically follow windows to their assigned desktop.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Bring window to current Virtual Desktop</guilabel></term>
<listitem><para>Will cause the window to jump to the active Virtual Desktop. Choose this option if you would like windows to always open on the current Virtual Desktop, and the active Virtual Desktop to only switch when navigating there manually.</para></listitem>
</varlistentry>
</variablelist>
</sect3>
</sect2>
</sect1>

View file

@ -290,7 +290,14 @@ void Workspace::activateWindow(Window *window, bool force)
raiseWindow(window);
if (!window->isOnCurrentDesktop()) {
++block_focus;
VirtualDesktopManager::self()->setCurrent(window->desktops().constLast());
switch (options->activationDesktopPolicy()) {
case Options::ActivationDesktopPolicy::SwitchToOtherDesktop:
VirtualDesktopManager::self()->setCurrent(window->desktops().constLast());
break;
case Options::ActivationDesktopPolicy::BringToCurrentDesktop:
window->enterDesktop(VirtualDesktopManager::self()->currentDesktop());
break;
}
--block_focus;
}
#if KWIN_BUILD_ACTIVITIES

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>500</height>
<width>1001</width>
<height>297</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
@ -142,6 +142,40 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="activationDesktopPolicyLabel">
<property name="text">
<string>Virtual Desktop behavior:</string>
</property>
<property name="buddy">
<cstring>kcfg_ActivationDesktopPolicy</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="activationDesktopPolicyDescriptionLabel">
<property name="text">
<string>When activating a window on a different Virtual Desktop:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="kcfg_ActivationDesktopPolicy">
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This setting controls what happens when an open window located on a Virtual Desktop other than the current one is activated. &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Switch to other Virtual Desktop&lt;/span&gt; will switch to the Virtual Desktop where the window is currently located. &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Bring window to current Virtual Desktop&lt;/span&gt; will cause the window to jump to the active Virtual Desktop. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<item>
<property name="text">
<string>Switch to that Virtual Desktop</string>
</property>
</item>
<item>
<property name="text">
<string>Bring window to current Virtual Desktop</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<resources/>

View file

@ -54,6 +54,14 @@
<default>true</default>
</entry>
<entry name="ActivationDesktopPolicy" type="Enum">
<choices name="ActivationDesktopPolicyChoices">
<choice name="SwitchToOtherDesktop"></choice>
<choice name="BringToCurrentDesktop"></choice>
</choices>
<default>SwitchToOtherDesktop</default>
</entry>
<entry key="TitlebarDoubleClickCommand" type="Enum">
<default>Maximize</default>
<choices>

View file

@ -257,6 +257,9 @@ void KAdvancedConfig::initialize(KWinOptionsSettings *settings, KWinOptionsKDEGl
// This option lives in the kdeglobals file because it is consumed by
// kxmlgui.
m_ui->kcfg_AllowKDEAppsToRememberWindowPositions->setVisible(KWindowSystem::isPlatformX11());
m_ui->kcfg_ActivationDesktopPolicy->setItemData(KWinOptionsSettings::ActivationDesktopPolicyChoices::SwitchToOtherDesktop, "SwitchToOtherDesktop");
m_ui->kcfg_ActivationDesktopPolicy->setItemData(KWinOptionsSettings::ActivationDesktopPolicyChoices::BringToCurrentDesktop, "BringToCurrentDesktop");
}
void KAdvancedConfig::showEvent(QShowEvent *ev)

View file

@ -133,6 +133,13 @@
#endif
}()</default>
</entry>
<entry name="ActivationDesktopPolicy" type="Enum">
<choices name="KWin::Options::ActivationDesktopPolicy">
<choice name="SwitchToOtherDesktop"/>
<choice name="BringToCurrentDesktop"/>
</choices>
<default>KWin::Options::ActivationDesktopPolicy::SwitchToOtherDesktop</default>
</entry>
<entry name="AutoRaise" type="Bool">
<default>false</default>
</entry>

View file

@ -44,6 +44,7 @@ Options::Options(QObject *parent)
, m_separateScreenFocus(false)
, m_activeMouseScreen(false)
, m_placement(Placement::NoPlacement)
, m_activationDesktopPolicy(Options::defaultActivationDesktopPolicy())
, m_borderSnapZone(0)
, m_windowSnapZone(0)
, m_centerSnapZone(0)
@ -243,6 +244,15 @@ void Options::setPlacement(int placement)
Q_EMIT placementChanged();
}
void Options::setActivationDesktopPolicy(ActivationDesktopPolicy activationDesktopPolicy)
{
if (m_activationDesktopPolicy == activationDesktopPolicy) {
return;
}
m_activationDesktopPolicy = activationDesktopPolicy;
Q_EMIT activationDesktopPolicyChanged();
}
void Options::setBorderSnapZone(int borderSnapZone)
{
if (m_borderSnapZone == borderSnapZone) {
@ -759,6 +769,7 @@ void Options::syncFromKcfgc()
setActiveMouseScreen(m_settings->activeMouseScreen());
setRollOverDesktops(m_settings->rollOverDesktops());
setFocusStealingPreventionLevel(m_settings->focusStealingPreventionLevel());
setActivationDesktopPolicy(m_settings->activationDesktopPolicy());
setXwaylandCrashPolicy(m_settings->xwaylandCrashPolicy());
setXwaylandMaxCrashCount(m_settings->xwaylandMaxCrashCount());
setPlacement(m_settings->placement());

View file

@ -105,6 +105,7 @@ class KWIN_EXPORT Options : public QObject
Q_PROPERTY(bool separateScreenFocus READ isSeparateScreenFocus WRITE setSeparateScreenFocus NOTIFY separateScreenFocusChanged)
Q_PROPERTY(bool activeMouseScreen READ activeMouseScreen WRITE setActiveMouseScreen NOTIFY activeMouseScreenChanged)
Q_PROPERTY(int placement READ placement WRITE setPlacement NOTIFY placementChanged)
Q_PROPERTY(ActivationDesktopPolicy activationDesktopPolicy READ activationDesktopPolicy WRITE setActivationDesktopPolicy NOTIFY activationDesktopPolicyChanged)
Q_PROPERTY(bool focusPolicyIsReasonable READ focusPolicyIsReasonable NOTIFY focusPolicyIsResonableChanged)
/**
* The size of the zone that triggers snapping on desktop borders.
@ -327,6 +328,17 @@ public:
return m_focusPolicy == ClickToFocus || m_focusPolicy == FocusFollowsMouse;
}
enum ActivationDesktopPolicy {
SwitchToOtherDesktop,
BringToCurrentDesktop
};
Q_ENUM(ActivationDesktopPolicy)
ActivationDesktopPolicy activationDesktopPolicy() const
{
return m_activationDesktopPolicy;
}
/**
* The size of the zone that triggers snapping on desktop borders.
*/
@ -688,6 +700,7 @@ public:
void setSeparateScreenFocus(bool separateScreenFocus);
void setActiveMouseScreen(bool activeMouseScreen);
void setPlacement(int placement);
void setActivationDesktopPolicy(ActivationDesktopPolicy activationDesktopPolicy);
void setBorderSnapZone(int borderSnapZone);
void setWindowSnapZone(int windowSnapZone);
void setCenterSnapZone(int centerSnapZone);
@ -861,6 +874,10 @@ public:
{
return RenderTimeEstimatorMaximum;
}
static ActivationDesktopPolicy defaultActivationDesktopPolicy()
{
return ActivationDesktopPolicy::SwitchToOtherDesktop;
}
/**
* Performs loading all settings except compositing related.
*/
@ -888,6 +905,7 @@ Q_SIGNALS:
void separateScreenFocusChanged(bool);
void activeMouseScreenChanged();
void placementChanged();
void activationDesktopPolicyChanged();
void borderSnapZoneChanged();
void windowSnapZoneChanged();
void centerSnapZoneChanged();
@ -950,6 +968,7 @@ private:
bool m_separateScreenFocus;
bool m_activeMouseScreen;
Placement::Policy m_placement;
ActivationDesktopPolicy m_activationDesktopPolicy;
int m_borderSnapZone;
int m_windowSnapZone;
int m_centerSnapZone;