diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/AiChat.qml b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/AiChat.qml index 0e0eeb2b9..820626b51 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/AiChat.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/AiChat.qml @@ -395,7 +395,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) shown: Ai.messageIDs.length === 0 icon: "neurology" title: Translation.tr("Large language models") - description: Translation.tr("Type /key to get started with online models\nCtrl+O to expand the sidebar\nCtrl+P to detach sidebar into a window") + description: Translation.tr("Type /key to get started with online models\nCtrl+O to expand sidebar\nCtrl+P to pin sidebar\nCtrl+D to detach sidebar") shape: MaterialShape.Shape.PixelCircle } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/SidebarLeft.qml b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/SidebarLeft.qml index 9a26b07be..fc275976c 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/SidebarLeft.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/SidebarLeft.qml @@ -11,9 +11,53 @@ import Quickshell.Hyprland Scope { // Scope id: root property bool detach: false + property bool pin: false property Component contentComponent: SidebarLeftContent {} property Item sidebarContent + function toggleDetach() { + root.detach = !root.detach; + } + + Process { // Dodge cursor away, pin, move cursor back + id: pinWithFunnyHyprlandWorkaroundProc + property var hook: null + property int cursorX; + property int cursorY; + function doIt() { + command = ["hyprctl", "cursorpos"] + hook = (output) => { + cursorX = parseInt(output.split(",")[0]); + cursorY = parseInt(output.split(",")[1]); + doIt2(); + } + running = true; + } + function doIt2(output) { + command = ["bash", "-c", "hyprctl dispatch movecursor 9999 9999"]; + hook = () => { + doIt3(); + } + running = true; + } + function doIt3(output) { + root.pin = !root.pin; + command = ["bash", "-c", `sleep 0.01; hyprctl dispatch movecursor ${cursorX} ${cursorY}`]; + hook = null + running = true; + } + stdout: StdioCollector { + onStreamFinished: { + pinWithFunnyHyprlandWorkaroundProc.hook(text); + } + } + } + + function togglePin() { + if (!root.pin) pinWithFunnyHyprlandWorkaroundProc.doIt() + else root.pin = !root.pin; + } + Component.onCompleted: { root.sidebarContent = contentComponent.createObject(null, { "scopeRoot": root, @@ -51,11 +95,12 @@ Scope { // Scope GlobalStates.sidebarLeftOpen = false } - exclusiveZone: 0 + exclusionMode: ExclusionMode.Normal + exclusiveZone: root.pin ? sidebarWidth : 0 implicitWidth: Appearance.sizes.sidebarWidthExtended + Appearance.sizes.elevationMargin WlrLayershell.namespace: "quickshell:sidebarLeft" // Hyprland 0.49: OnDemand is Exclusive, Exclusive just breaks click-outside-to-close - // WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand + WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand color: "transparent" anchors { @@ -71,7 +116,7 @@ Scope { // Scope HyprlandFocusGrab { // Click outside to close id: grab windows: [ sidebarRoot ] - active: sidebarRoot.visible + active: sidebarRoot.visible && !root.pin onActiveChanged: { // Focus the selected tab if (active) sidebarLeftBackground.children[0].focusActiveItem() } @@ -109,9 +154,10 @@ Scope { // Scope if (event.modifiers === Qt.ControlModifier) { if (event.key === Qt.Key_O) { sidebarRoot.extend = !sidebarRoot.extend; - } - else if (event.key === Qt.Key_P) { - root.detach = !root.detach; + } else if (event.key === Qt.Key_D) { + root.toggleDetach(); + } else if (event.key === Qt.Key_P) { + root.togglePin(); } event.accepted = true; } @@ -141,8 +187,8 @@ Scope { // Scope Keys.onPressed: (event) => { if (event.modifiers === Qt.ControlModifier) { - if (event.key === Qt.Key_P) { - root.detach = !root.detach; + if (event.key === Qt.Key_D) { + root.toggleDetach(); } event.accepted = true; }