pragma ComponentBehavior: Bound import Quickshell import Quickshell.Hyprland import Quickshell.Wayland import QtQuick import qs.widgets.theme // Variant 9 — asymmetric Blade application launcher. Scope { id: root property bool active: false function toggle() { root.active = !root.active; } GlobalShortcut { name: "launcher9" description: "Toggle app launcher (Blade matrix)" onPressed: root.toggle() } PanelWindow { id: win visible: root.active WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive exclusionMode: ExclusionMode.Ignore color: Theme.textAlpha(0) anchors { top: true; left: true; right: true; bottom: true } property int selectedIndex: 0 function clampSelection(index) { return model.apps.length === 0 ? 0 : Math.max(0, Math.min(model.apps.length - 1, index)); } function move(delta) { const count = model.apps.length; if (count === 0) return; selectedIndex = ((selectedIndex + delta) % count + count) % count; } function launch(index) { if (model.launch(index)) root.active = false; } onVisibleChanged: { if (visible) { content.clearSearch(); selectedIndex = 0; content.focusSearch(); } } AppModel { id: model; search: content.query } Rectangle { anchors.fill: parent color: Theme.surface opacity: 0.78 MouseArea { anchors.fill: parent; onClicked: root.active = false } } BladeLauncherContent { id: content anchors.centerIn: parent width: 1120 height: 640 scale: Math.min(1, (parent.width - 56) / width, (parent.height - 56) / height) transformOrigin: Item.Center apps: model.apps selectedIndex: win.selectedIndex onSelectionRequested: index => win.selectedIndex = win.clampSelection(index) onMoveRequested: delta => win.move(delta) onLaunchRequested: index => win.launch(index) onDismissRequested: root.active = false } } }