Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/contents/config/main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,10 @@ waterfox-default</default>
<entry name="printMonitorInfoToLog" type="Bool">
<default>false</default>
</entry>
<entry name="liveBackupInterval" type="Int">
<default>30</default>
<min>0</min>
<max>3600</max>
</entry>
</group>
</kcfg>
86 changes: 79 additions & 7 deletions src/contents/ui/config.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1183,13 +1183,85 @@ When upgrading from an earlier version, a reboot might be required to enable the
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="kcfg_onlySaveOnShutdown">
<property name="text">
<string>Only save during shutdown (on script closure) - enable this if you experience lag when using the script - this could be caused by using a hard disk drive (HDD) as your /home drive</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="kcfg_onlySaveOnShutdown">
<property name="text">
<string>Only save during shutdown (on script closure) - enable this if you experience lag when using the script - this could be caused by using a hard disk drive (HDD) as your /home drive</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_liveBackup">
<property name="title">
<string>Live Window Position Backup</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_liveBackup">
<item>
<widget class="QLabel" name="label_liveBackupExplanation">
<property name="text">
<string>Periodically saves the current positions of all open windows to disk. If the system shuts down unexpectedly (battery runs out, power button forced shutdown), window positions can still be restored from the last backup. Set to 0 to disable. Higher values reduce disk writes but increase the risk of losing recent window changes.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="kcfg_liveBackupInterval">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>3600</number>
</property>
<property name="value">
<number>30</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TickPosition::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>5</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="hBoxLayout_liveBackupInterval">
<item>
<widget class="QLabel" name="label_liveBackupIntervalMin">
<property name="text">
<string> 0 (off)</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_liveBackupIntervalInfo">
<property name="text">
<string>seconds between backups</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_liveBackupIntervalMax">
<property name="text">
<string>3600 </string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_minimumCaptionMatch">
<property name="title">
Expand Down
144 changes: 144 additions & 0 deletions src/contents/ui/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ Item {
printApplicationNameToLog: KWin.readConfig("printApplicationNameToLog", true),
printMonitorInfoToLog: KWin.readConfig("printMonitorInfoToLog", false),
onlySaveOnShutdown: KWin.readConfig("onlySaveOnShutdown", false),
liveBackupInterval: KWin.readConfig("liveBackupInterval", 30),
// confidence
confidence: [
{ caption: 100, matchingDimentions: 2, allowHeightShrinking: false }, // Caption and size match
Expand Down Expand Up @@ -1358,6 +1359,14 @@ Item {
}
}

Timer {
id: liveBackupTimer

repeat: true
running: false
onTriggered: saveLiveBackup()
}

function clearSessionRestoreSaves() {
while (sessionRestoreSaves.length > 0) {
if (sessionRestoreSaves[0].closeTime < Date.now() - config.sessionRestoreTime * 1000) {
Expand Down Expand Up @@ -1594,6 +1603,74 @@ Item {
}
}

logE('Loaded ' + Object.keys(convertedWindows).length + ' apps from settings');

let liveBackups = JSON.parse(settings.rememberwindowpositions_liveBackups);
let liveCount = 0;
for (let key in liveBackups) {
let liveBackupIsNewer = liveBackups[key].l && (!convertedWindows[key] || liveBackups[key].l >= convertedWindows[key].lastAccessTime);
if (!convertedWindows[key] || convertedWindows[key].saved.length === 0 || liveBackupIsNewer) {
let live = liveBackups[key];
if (convertedWindows[key] && convertedWindows[key].saved.length > 0 && liveBackupIsNewer) {
logE('Live backup is newer than saved data for: ' + key + ' - using live backup');
} else {
logE('Using live backup for: ' + key + ' windowCountLastSession: ' + live.w);
}
convertedWindows[key] = {
saved : [],
lastAccessTime : live.l || Date.now(),
windowCountLastSession : live.w,
windowCount : 0,
instantMatchRestored : 0,
restoredTotal : 0,
loading : [],
closed : []
};
for (let i = 0; i < live.s.length; i++) {
let save = live.s[i];
convertedWindows[key].saved.push({
caption : save.c,
x : save.x,
y : save.y,
width : save.w,
height : save.h,
minimized : save.m == 1,
keepAbove : save.k == 1,
keepBelow : save.b == 1,
stackingOrder : save.s,
desktopNumber : save.d,
activities : save.a,
rememberAlways : save.r == 1,
singleWindow : save.n == 1,
position : save.p ? {
x : save.p.x,
y : save.p.y,
serialNumber : save.p.s,
name : save.p.n
} : undefined,
sessionRestore : save.z == 1,
alreadyMatched : false,
tile : save.t ? {
quick : save.t.q == 1,
x : save.t.x,
y : save.t.y,
width : save.t.w,
height : save.t.h,
left : save.t.l,
right : save.t.r,
top : save.t.t,
bottom : save.t.b
} : undefined,
mouseTilerAuto : save.o
});
}
liveCount++;
}
}
if (liveCount > 0) {
logE('Loaded ' + liveCount + ' apps from live backup');
}

//log('Load - converted windows: ' + JSON.stringify(convertedWindows));
config.windows = convertedWindows;
}
Expand Down Expand Up @@ -1669,6 +1746,66 @@ Item {
log('Windows saved!');
}

function saveLiveBackup() {
if (config.liveBackupInterval <= 0) return;
let liveData = {};
const clients = Workspace.stackingOrder;
for (let i = 0; i < clients.length; i++) {
let client = clients[i];
if (!isValidWindow(client)) continue;
let currentConfig = getCurrentConfig(client);
if (currentConfig.blocked || currentConfig.rememberNever) continue;

let name = client.resourceClass;
if (!liveData[name]) {
liveData[name] = {
s: [],
l: Date.now(),
w: 0
};
}
liveData[name].w++;

let convertedPosition = client.output.mapFromGlobal(client.pos);
let tileData = convertTileData(client);
liveData[name].s.push({
c: client.caption.toString(),
x: client.x,
y: client.y,
w: client.width,
h: client.height,
m: client.minimized ? 1 : 0,
k: client.keepAbove ? 1 : 0,
b: client.keepBelow ? 1 : 0,
s: i,
d: client.onAllDesktops ? -1 : client.desktops[0].x11DesktopNumber,
a: [...client.activities],
r: 0,
n: 0,
p: {
x: convertedPosition.x,
y: convertedPosition.y,
s: client.output.serialNumber,
n: client.output.name
},
z: 0,
t: tileData ? {
q: tileData.quick ? 1 : 0,
x: tileData.x,
y: tileData.y,
w: tileData.width,
h: tileData.height,
l: tileData.left,
r: tileData.right,
t: tileData.top,
b: tileData.bottom
} : undefined,
o: client.mt_autoRestore ? client.mt_autoRestore : 0
});
}
settings.rememberwindowpositions_liveBackups = JSON.stringify(liveData);
}

function addDefaultOverrides() {
// settings.rememberwindowpositions_currentDefaultOverrideCount = 0;
const defaultOverrides = [
Expand Down Expand Up @@ -1842,6 +1979,7 @@ Item {
id: settings
property string rememberwindowpositions_windows: "{}"
property string rememberwindowpositions_configOverrides: "{}"
property string rememberwindowpositions_liveBackups: "{}"
property int rememberwindowpositions_currentDefaultOverrideCount: 0
// property bool rememberwindowpositions_autoShowMainMenu: true
}
Expand Down Expand Up @@ -1884,6 +2022,11 @@ Item {
// Clear expired apps to reduce used save-file space
clearExpiredApps();

if (config.liveBackupInterval > 0) {
liveBackupTimer.interval = config.liveBackupInterval * 1000;
liveBackupTimer.start();
}

// if (settings.rememberwindowpositions_autoShowMainMenu) {
// showMainMenu();
// }
Expand All @@ -1893,6 +2036,7 @@ Item {
log('Closing...');
updateSessionRestoreSaves();
saveWindowsToSettings(true);
saveLiveBackup();
saveOverridesToSettings();
}

Expand Down