171 lines
4.7 KiB
JavaScript
171 lines
4.7 KiB
JavaScript
/**
|
|
* KWin Scratchpad — i3-like hide/show/cycle behavior.
|
|
*
|
|
* Two shortcuts:
|
|
* Meta+Shift+- : Move active window to scratchpad (hide it).
|
|
* Meta+- : Show/hide/cycle through scratchpad windows.
|
|
*
|
|
* Cycle behavior (Meta+-):
|
|
* - If a scratchpad window is visible: hide it.
|
|
* - If no scratchpad window is visible: show the next one.
|
|
* - Wraps around the list.
|
|
*
|
|
* A window leaves the scratchpad ONLY when:
|
|
* - It is closed.
|
|
* - It is explicitly moved to a desktop.
|
|
*/
|
|
|
|
(function () {
|
|
"use strict";
|
|
|
|
// --- State ---
|
|
var scratchpad = []; // ordered list of windows in the scratchpad
|
|
var visibleWindow = null; // the currently-visible scratchpad window, or null
|
|
var nextIndex = 0; // which window to show on the next "show" press
|
|
|
|
// --- Helpers ---
|
|
|
|
function indexInScratchpad(win) {
|
|
for (var i = 0; i < scratchpad.length; i++) {
|
|
if (scratchpad[i] === win) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
function isScratchpadWindow(win) {
|
|
return indexInScratchpad(win) >= 0;
|
|
}
|
|
|
|
function removeScratchpadWindow(win) {
|
|
var i = indexInScratchpad(win);
|
|
if (i < 0) return false;
|
|
|
|
scratchpad.splice(i, 1);
|
|
|
|
if (win === visibleWindow) {
|
|
visibleWindow = null;
|
|
}
|
|
|
|
// Keep nextIndex in bounds
|
|
if (scratchpad.length === 0) {
|
|
nextIndex = 0;
|
|
} else if (nextIndex >= scratchpad.length) {
|
|
nextIndex = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function hideWindow(win) {
|
|
win.minimized = true;
|
|
win.skipTaskbar = true;
|
|
win.skipPager = true;
|
|
win.skipSwitcher = true;
|
|
}
|
|
|
|
function showWindow(win) {
|
|
win.desktops = [workspace.currentDesktop];
|
|
win.minimized = false;
|
|
win.skipTaskbar = true;
|
|
win.skipPager = true;
|
|
win.skipSwitcher = true;
|
|
workspace.activeWindow = win;
|
|
}
|
|
|
|
function restoreWindow(win) {
|
|
win.minimized = false;
|
|
win.skipTaskbar = false;
|
|
win.skipPager = false;
|
|
win.skipSwitcher = false;
|
|
}
|
|
|
|
// --- Shortcut 1: Add to scratchpad (Meta+Shift+-) ---
|
|
|
|
function scratchpadAdd() {
|
|
var active = workspace.activeWindow;
|
|
if (!active) return;
|
|
if (active.desktopWindow || active.dock || active.specialWindow) return;
|
|
if (isScratchpadWindow(active)) return;
|
|
|
|
scratchpad.push(active);
|
|
hideWindow(active);
|
|
print("Scratchpad: added — " + active.caption + " (" + scratchpad.length + " total)");
|
|
}
|
|
|
|
// --- Shortcut 2: Show/hide/cycle (Meta+-) ---
|
|
|
|
function scratchpadCycle() {
|
|
if (scratchpad.length === 0) return;
|
|
|
|
// If a scratchpad window is currently visible — hide it. Full stop.
|
|
if (visibleWindow !== null) {
|
|
hideWindow(visibleWindow);
|
|
// Advance nextIndex past the one we just hid
|
|
var idx = indexInScratchpad(visibleWindow);
|
|
if (idx >= 0) {
|
|
nextIndex = (idx + 1) % scratchpad.length;
|
|
}
|
|
visibleWindow = null;
|
|
return;
|
|
}
|
|
|
|
// No scratchpad window is visible — show the next one.
|
|
if (nextIndex >= scratchpad.length) {
|
|
nextIndex = 0;
|
|
}
|
|
visibleWindow = scratchpad[nextIndex];
|
|
showWindow(visibleWindow);
|
|
}
|
|
|
|
// --- Track window closure ---
|
|
|
|
workspace.windowRemoved.connect(function (win) {
|
|
removeScratchpadWindow(win);
|
|
});
|
|
|
|
// --- Track desktop changes (window explicitly moved to a desktop) ---
|
|
|
|
function watchDesktopChange(win) {
|
|
win.desktopsChanged.connect(function () {
|
|
if (!isScratchpadWindow(win)) return;
|
|
|
|
// If it's the visible one and not minimized, this is likely our
|
|
// own showWindow() call — ignore.
|
|
if (win === visibleWindow && !win.minimized) {
|
|
return;
|
|
}
|
|
|
|
// User moved it to a desktop — release from scratchpad.
|
|
removeScratchpadWindow(win);
|
|
restoreWindow(win);
|
|
print("Scratchpad: window released to desktop — " + win.caption);
|
|
});
|
|
}
|
|
|
|
var clients = workspace.stackingOrder;
|
|
for (var i = 0; i < clients.length; i++) {
|
|
watchDesktopChange(clients[i]);
|
|
}
|
|
|
|
workspace.windowAdded.connect(function (win) {
|
|
watchDesktopChange(win);
|
|
});
|
|
|
|
// --- Register shortcuts ---
|
|
|
|
registerShortcut(
|
|
"ScratchpadAdd",
|
|
"Move Window to Scratchpad",
|
|
"Meta+Shift+-",
|
|
scratchpadAdd
|
|
);
|
|
|
|
registerShortcut(
|
|
"ScratchpadCycle",
|
|
"Scratchpad Show/Hide/Cycle",
|
|
"Meta+-",
|
|
scratchpadCycle
|
|
);
|
|
|
|
print("KWin Scratchpad loaded");
|
|
})();
|