feat: add dynamic preview panel resizing and individual window instance close button

This commit is contained in:
Sho 2026-08-02 15:04:58 +09:00
parent 7e815d4a51
commit f40fc29e3f
4 changed files with 88 additions and 4 deletions

View File

@ -495,10 +495,14 @@ Item {
GlassPanel { GlassPanel {
id: previewGlass id: previewGlass
implicitWidth: previewMainCol.implicitWidth + 20 implicitWidth: previewMainCol.implicitWidth + 24
implicitHeight: previewMainCol.implicitHeight + 16 implicitHeight: previewMainCol.implicitHeight + 16
anchors.fill: parent anchors.fill: parent
Behavior on implicitWidth {
NumberAnimation { duration: 180; easing.type: Easing.OutCubic }
}
opacity: dockWindowPreview.animProgress opacity: dockWindowPreview.animProgress
scale: 0.90 + 0.10 * dockWindowPreview.animProgress scale: 0.90 + 0.10 * dockWindowPreview.animProgress
transformOrigin: Item.Bottom transformOrigin: Item.Bottom
@ -634,7 +638,10 @@ Item {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onClicked: { onClicked: {
TaskService.closeApp(modelData.appId) TaskService.closeSpecificWindow(modelData)
let rem = root.previewWindowInstances ? root.previewWindowInstances.filter(w => w.id !== modelData.id) : []
root.previewWindowInstances = rem
if (!rem || rem.length === 0) {
previewPopIn.running = false previewPopIn.running = false
previewPopOut.restart() previewPopOut.restart()
} }
@ -642,6 +649,7 @@ Item {
} }
} }
} }
}
// Miniature Glass Window Preview Container // Miniature Glass Window Preview Container
Rectangle { Rectangle {

View File

@ -169,6 +169,16 @@ Item {
proc.running = true proc.running = true
} }
function closeSpecificWindow(winObj) {
if (!winObj) return;
let winId = (winObj.id || "").toString().trim()
let query = (winObj.caption || winObj.appId || "").toLowerCase().trim()
proc.running = false
proc.command = ["python3", Quickshell.env("HOME") + "/.config/quickshell/services/python/kwin_close.py", winId, query]
proc.running = true
}
function focusApp(appId, cmd, iconX, iconY) { function focusApp(appId, cmd, iconX, iconY) {
if (!appId) return; if (!appId) return;
let lower = appId.toLowerCase().trim() let lower = appId.toLowerCase().trim()

View File

@ -0,0 +1,30 @@
// KWin JavaScript Script: Gracefully Close Specific Window Instance
var targetId = "%WIN_ID%".trim();
var targetQuery = "%TARGET_QUERY%".toLowerCase().trim();
if (targetId || targetQuery) {
var windows = workspace.windowList();
for (var i = 0; i < windows.length; i++) {
var win = windows[i];
var id = String(win.internalId || win.windowId || "");
var cls = (win.desktopFileName || win.resourceClass || win.resourceName || "").toLowerCase().trim();
var caption = (win.caption || "").toLowerCase().trim();
var matches = false;
if (targetId && id && (id === targetId || id.indexOf(targetId) !== -1)) {
matches = true;
}
if (!matches && targetQuery) {
if (caption && caption.indexOf(targetQuery) !== -1) {
matches = true;
} else if (cls && cls.indexOf(targetQuery) !== -1) {
matches = true;
}
}
if (matches) {
win.closeWindow();
break;
}
}
}

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python3
import sys
import os
import subprocess
JS_TEMPLATE_PATH = os.path.expanduser('~/.config/quickshell/services/js/kwin_close.js')
def close_window(win_id="", target_query=""):
try:
with open(JS_TEMPLATE_PATH, 'r', encoding='utf-8') as f:
template = f.read()
script = template.replace('%WIN_ID%', win_id).replace('%TARGET_QUERY%', target_query)
target_js = '/tmp/kwin_close.js'
with open(target_js, 'w', encoding='utf-8') as f:
f.write(script)
# Unload previous script instance to prevent KWin memory leaks
subprocess.run(['busctl', '--user', 'call', 'org.kde.KWin', '/Scripting', 'org.kde.kwin.Scripting', 'unloadScript', 's', target_js], capture_output=True)
res = subprocess.check_output(
['busctl', '--user', 'call', 'org.kde.KWin', '/Scripting', 'org.kde.kwin.Scripting', 'loadScript', 's', target_js],
text=True
)
sid = res.strip().split()[-1]
subprocess.run(['busctl', '--user', 'call', 'org.kde.KWin', f'/Scripting/Script{sid}', 'org.kde.kwin.Script', 'run'], capture_output=True)
subprocess.run(['busctl', '--user', 'call', 'org.kde.KWin', f'/Scripting/Script{sid}', 'org.kde.kwin.Script', 'stop'], capture_output=True)
subprocess.run(['busctl', '--user', 'call', 'org.kde.KWin', '/Scripting', 'org.kde.kwin.Scripting', 'unloadScript', 's', target_js], capture_output=True)
except Exception:
pass
if __name__ == '__main__':
win_id = sys.argv[1] if len(sys.argv) >= 2 else ""
target_query = sys.argv[2] if len(sys.argv) >= 3 else ""
close_window(win_id, target_query)