Add snap layouts shell setting

Expose snapLayoutsEnabled through MobileShellSettings and store it\nin plasmamobilerc.\n\nUse the setting in the Shift snap assist effect eligibility logic\nand add a Convergence KCM switch to control it.\n\nKeep the switch disabled when convergence is off, gaming mode is on,\nor dynamic tiling is enabled so window-placement ownership stays\nconsistent.
This commit is contained in:
Marco Allegretti 2026-05-06 11:44:54 +02:00
parent 8d59ce6153
commit 3fba9798e4
4 changed files with 51 additions and 1 deletions

View file

@ -47,6 +47,7 @@ MobileShellSettings::MobileShellSettings(QObject *parent)
Q_EMIT gamingModeEnabledChanged(); Q_EMIT gamingModeEnabledChanged();
Q_EMIT gamingDismissHintEnabledChanged(); Q_EMIT gamingDismissHintEnabledChanged();
Q_EMIT dynamicTilingEnabledChanged(); Q_EMIT dynamicTilingEnabledChanged();
Q_EMIT snapLayoutsEnabledChanged();
Q_EMIT allowLogoutChanged(); Q_EMIT allowLogoutChanged();
} }
if (group.name() == LOCKSCREEN_CONFIG_GROUP) { if (group.name() == LOCKSCREEN_CONFIG_GROUP) {
@ -290,6 +291,19 @@ void MobileShellSettings::setDynamicTilingEnabled(bool enabled)
m_config->sync(); m_config->sync();
} }
bool MobileShellSettings::snapLayoutsEnabled() const
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
return group.readEntry("snapLayoutsEnabled", true);
}
void MobileShellSettings::setSnapLayoutsEnabled(bool enabled)
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
group.writeEntry("snapLayoutsEnabled", enabled, KConfigGroup::Notify);
m_config->sync();
}
void MobileShellSettings::updateNavigationBarsInPlasma() void MobileShellSettings::updateNavigationBarsInPlasma()
{ {
// Do not update panels when not in Plasma Mobile // Do not update panels when not in Plasma Mobile

View file

@ -60,6 +60,9 @@ class MobileShellSettings : public QObject
// When false, KWin's native quick-tile behaviour is used unmodified. // When false, KWin's native quick-tile behaviour is used unmodified.
Q_PROPERTY(bool dynamicTilingEnabled READ dynamicTilingEnabled WRITE setDynamicTilingEnabled NOTIFY dynamicTilingEnabledChanged) Q_PROPERTY(bool dynamicTilingEnabled READ dynamicTilingEnabled WRITE setDynamicTilingEnabled NOTIFY dynamicTilingEnabledChanged)
// Snap layout picker — only meaningful in convergence mode when dynamic tiling is off.
Q_PROPERTY(bool snapLayoutsEnabled READ snapLayoutsEnabled WRITE setSnapLayoutsEnabled NOTIFY snapLayoutsEnabledChanged)
// logout dialog // logout dialog
Q_PROPERTY(bool allowLogout READ allowLogout READ allowLogout NOTIFY allowLogoutChanged) Q_PROPERTY(bool allowLogout READ allowLogout READ allowLogout NOTIFY allowLogoutChanged)
@ -286,6 +289,14 @@ public:
bool dynamicTilingEnabled() const; bool dynamicTilingEnabled() const;
void setDynamicTilingEnabled(bool enabled); void setDynamicTilingEnabled(bool enabled);
/**
* Whether the SHIFT snap layout picker is enabled.
* Defaults to true; only takes effect in convergence mode when gaming mode
* and dynamic tiling are off.
*/
bool snapLayoutsEnabled() const;
void setSnapLayoutsEnabled(bool enabled);
/** /**
* Whether logout button is shown in the logout/shutdown dialog. * Whether logout button is shown in the logout/shutdown dialog.
*/ */
@ -335,6 +346,7 @@ Q_SIGNALS:
void gamingModeEnabledChanged(); void gamingModeEnabledChanged();
void gamingDismissHintEnabledChanged(); void gamingDismissHintEnabledChanged();
void dynamicTilingEnabledChanged(); void dynamicTilingEnabledChanged();
void snapLayoutsEnabledChanged();
void allowLogoutChanged(); void allowLogoutChanged();
void lockscreenLeftButtonActionChanged(); void lockscreenLeftButtonActionChanged();
void lockscreenRightButtonActionChanged(); void lockscreenRightButtonActionChanged();

View file

@ -95,7 +95,24 @@ KCM.SimpleKCM {
} }
} }
FormCard.FormDelegateSeparator { above: dynamicTilingSwitch; below: autoHidePanels } FormCard.FormDelegateSeparator { above: dynamicTilingSwitch; below: snapLayoutsSwitch }
FormCard.FormSwitchDelegate {
id: snapLayoutsSwitch
text: i18n("Snap Layouts")
description: i18n("Show the snap layout picker from the maximize button. Disabled while convergence mode is off, gaming mode is active, or dynamic tiling is enabled.")
enabled: ShellSettings.Settings.convergenceModeEnabled
&& !ShellSettings.Settings.gamingModeEnabled
&& !ShellSettings.Settings.dynamicTilingEnabled
checked: ShellSettings.Settings.snapLayoutsEnabled
onCheckedChanged: {
if (checked != ShellSettings.Settings.snapLayoutsEnabled) {
ShellSettings.Settings.snapLayoutsEnabled = checked;
}
}
}
FormCard.FormDelegateSeparator { above: snapLayoutsSwitch; below: autoHidePanels }
FormCard.FormSwitchDelegate { FormCard.FormSwitchDelegate {
id: autoHidePanels id: autoHidePanels

View file

@ -24,6 +24,7 @@ KWinComponents.SceneEffect {
readonly property bool snapLayoutsEligible: ShellSettings.Settings.convergenceModeEnabled readonly property bool snapLayoutsEligible: ShellSettings.Settings.convergenceModeEnabled
&& !ShellSettings.Settings.gamingModeEnabled && !ShellSettings.Settings.gamingModeEnabled
&& !ShellSettings.Settings.dynamicTilingEnabled && !ShellSettings.Settings.dynamicTilingEnabled
&& ShellSettings.Settings.snapLayoutsEnabled
readonly property int hoverBarHeight: 30 readonly property int hoverBarHeight: 30
readonly property int decorationButtonSize: 16 readonly property int decorationButtonSize: 16
readonly property int decorationButtonSpacing: 8 readonly property int decorationButtonSpacing: 8
@ -372,6 +373,12 @@ KWinComponents.SceneEffect {
effect.hideSnapLayouts(); effect.hideSnapLayouts();
} }
} }
function onSnapLayoutsEnabledChanged() {
if (!effect.snapLayoutsEligible) {
effect.hideSnapLayouts();
}
}
} }
// Gap constant (must match shift-tiling) // Gap constant (must match shift-tiling)