Own dynamic tiling window workflows

This commit is contained in:
Marco Allegretti 2026-05-22 09:39:11 +02:00
parent 24e410c733
commit 5311dc8fe8
4 changed files with 1008 additions and 33 deletions

View file

@ -48,6 +48,7 @@ MobileShellSettings::MobileShellSettings(QObject *parent)
Q_EMIT gamingDismissHintEnabledChanged(); Q_EMIT gamingDismissHintEnabledChanged();
Q_EMIT dynamicTilingEnabledChanged(); Q_EMIT dynamicTilingEnabledChanged();
Q_EMIT dynamicTilingWindowRequestChanged(); Q_EMIT dynamicTilingWindowRequestChanged();
Q_EMIT dynamicTilingWindowStateChanged();
Q_EMIT snapLayoutsEnabledChanged(); Q_EMIT snapLayoutsEnabledChanged();
Q_EMIT allowLogoutChanged(); Q_EMIT allowLogoutChanged();
} }
@ -326,6 +327,50 @@ void MobileShellSettings::requestDynamicTilingWindowAction(const QString &window
Q_EMIT dynamicTilingWindowRequestChanged(); Q_EMIT dynamicTilingWindowRequestChanged();
} }
QStringList MobileShellSettings::dynamicTilingMaximizedWindowIds() const
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
return group.readEntry("dynamicTilingMaximizedWindowIds", QStringList{});
}
int MobileShellSettings::dynamicTilingWindowStateSerial() const
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
return group.readEntry("dynamicTilingWindowStateSerial", 0);
}
bool MobileShellSettings::isDynamicTilingWindowMaximized(const QString &windowId) const
{
if (windowId.isEmpty()) {
return false;
}
return dynamicTilingMaximizedWindowIds().contains(windowId);
}
void MobileShellSettings::reportDynamicTilingWindowState(const QStringList &maximizedWindowIds)
{
QStringList normalizedIds;
for (const QString &windowId : maximizedWindowIds) {
if (!windowId.isEmpty() && !normalizedIds.contains(windowId)) {
normalizedIds.push_back(windowId);
}
}
normalizedIds.sort(Qt::CaseSensitive);
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
if (group.readEntry("dynamicTilingMaximizedWindowIds", QStringList{}) == normalizedIds) {
return;
}
const int serial = group.readEntry("dynamicTilingWindowStateSerial", 0) + 1;
group.writeEntry("dynamicTilingMaximizedWindowIds", normalizedIds, KConfigGroup::Notify);
group.writeEntry("dynamicTilingWindowStateSerial", serial, KConfigGroup::Notify);
m_config->sync();
Q_EMIT dynamicTilingWindowStateChanged();
}
bool MobileShellSettings::snapLayoutsEnabled() const bool MobileShellSettings::snapLayoutsEnabled() const
{ {
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP}; auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};

View file

@ -11,6 +11,7 @@
#include <KSharedConfig> #include <KSharedConfig>
#include <QDBusConnection> #include <QDBusConnection>
#include <QObject> #include <QObject>
#include <QStringList>
#include <qqmlregistration.h> #include <qqmlregistration.h>
/** /**
@ -62,6 +63,8 @@ class MobileShellSettings : public QObject
Q_PROPERTY(QString dynamicTilingWindowRequestAction READ dynamicTilingWindowRequestAction NOTIFY dynamicTilingWindowRequestChanged) Q_PROPERTY(QString dynamicTilingWindowRequestAction READ dynamicTilingWindowRequestAction NOTIFY dynamicTilingWindowRequestChanged)
Q_PROPERTY(QString dynamicTilingWindowRequestId READ dynamicTilingWindowRequestId NOTIFY dynamicTilingWindowRequestChanged) Q_PROPERTY(QString dynamicTilingWindowRequestId READ dynamicTilingWindowRequestId NOTIFY dynamicTilingWindowRequestChanged)
Q_PROPERTY(int dynamicTilingWindowRequestSerial READ dynamicTilingWindowRequestSerial NOTIFY dynamicTilingWindowRequestChanged) Q_PROPERTY(int dynamicTilingWindowRequestSerial READ dynamicTilingWindowRequestSerial NOTIFY dynamicTilingWindowRequestChanged)
Q_PROPERTY(QStringList dynamicTilingMaximizedWindowIds READ dynamicTilingMaximizedWindowIds NOTIFY dynamicTilingWindowStateChanged)
Q_PROPERTY(int dynamicTilingWindowStateSerial READ dynamicTilingWindowStateSerial NOTIFY dynamicTilingWindowStateChanged)
// Snap layout picker — only meaningful in convergence mode when dynamic tiling is off. // Snap layout picker — only meaningful in convergence mode when dynamic tiling is off.
Q_PROPERTY(bool snapLayoutsEnabled READ snapLayoutsEnabled WRITE setSnapLayoutsEnabled NOTIFY snapLayoutsEnabledChanged) Q_PROPERTY(bool snapLayoutsEnabled READ snapLayoutsEnabled WRITE setSnapLayoutsEnabled NOTIFY snapLayoutsEnabledChanged)
@ -295,6 +298,10 @@ public:
QString dynamicTilingWindowRequestId() const; QString dynamicTilingWindowRequestId() const;
int dynamicTilingWindowRequestSerial() const; int dynamicTilingWindowRequestSerial() const;
Q_INVOKABLE void requestDynamicTilingWindowAction(const QString &windowId, const QString &action); Q_INVOKABLE void requestDynamicTilingWindowAction(const QString &windowId, const QString &action);
QStringList dynamicTilingMaximizedWindowIds() const;
int dynamicTilingWindowStateSerial() const;
Q_INVOKABLE bool isDynamicTilingWindowMaximized(const QString &windowId) const;
Q_INVOKABLE void reportDynamicTilingWindowState(const QStringList &maximizedWindowIds);
/** /**
* Whether the SHIFT snap layout picker is enabled. * Whether the SHIFT snap layout picker is enabled.
@ -354,6 +361,7 @@ Q_SIGNALS:
void gamingDismissHintEnabledChanged(); void gamingDismissHintEnabledChanged();
void dynamicTilingEnabledChanged(); void dynamicTilingEnabledChanged();
void dynamicTilingWindowRequestChanged(); void dynamicTilingWindowRequestChanged();
void dynamicTilingWindowStateChanged();
void snapLayoutsEnabledChanged(); void snapLayoutsEnabledChanged();
void allowLogoutChanged(); void allowLogoutChanged();
void lockscreenLeftButtonActionChanged(); void lockscreenLeftButtonActionChanged();

View file

@ -28,6 +28,7 @@ Loader {
root.pendingConstrainWindows = [] root.pendingConstrainWindows = []
for (const window of windows) { for (const window of windows) {
if (!window || window.deleted || !window.normalWindow) continue if (!window || window.deleted || !window.normalWindow) continue
if (root.dynamicTilingOwnsWindowPlacement()) continue
if (!ShellSettings.Settings.convergenceModeEnabled) continue if (!ShellSettings.Settings.convergenceModeEnabled) continue
if (ShellSettings.Settings.gamingModeEnabled) continue if (ShellSettings.Settings.gamingModeEnabled) continue
@ -52,11 +53,22 @@ Loader {
} }
} }
function dynamicTilingOwnsWindowPlacement() {
return ShellSettings.Settings.convergenceModeEnabled
&& ShellSettings.Settings.dynamicTilingEnabled
&& !ShellSettings.Settings.gamingModeEnabled;
}
function run(window) { function run(window) {
if (!window || window.deleted || !window.normalWindow) { if (!window || window.deleted || !window.normalWindow) {
return; return;
} }
if (root.dynamicTilingOwnsWindowPlacement()) {
window.noBorder = false;
return;
}
// HACK: don't maximize xwaylandvideobridge // HACK: don't maximize xwaylandvideobridge
// see: https://invent.kde.org/plasma/plasma-mobile/-/issues/324 // see: https://invent.kde.org/plasma/plasma-mobile/-/issues/324
if (window.resourceClass === 'xwaylandvideobridge') { if (window.resourceClass === 'xwaylandvideobridge') {
@ -153,6 +165,16 @@ Loader {
} }
} }
} }
function onDynamicTilingEnabledChanged() {
const windows = KWinComponents.Workspace.windows;
for (let i = 0; i < windows.length; i++) {
if (windows[i].normalWindow) {
root.run(windows[i]);
}
}
}
} }
Connections { Connections {

File diff suppressed because it is too large Load diff