diff --git a/default/quickshell/omarchy-shell/Ui/PanelKeyCatcher.qml b/default/quickshell/omarchy-shell/Ui/PanelKeyCatcher.qml index 786d12f7..b4def79d 100644 --- a/default/quickshell/omarchy-shell/Ui/PanelKeyCatcher.qml +++ b/default/quickshell/omarchy-shell/Ui/PanelKeyCatcher.qml @@ -20,15 +20,16 @@ import QtQuick // } // } // -// Keys.priority: Keys.AfterItem means a focused descendant (e.g. a -// TextField inside an inline password prompt) gets the event first. Only -// events the focused subtree ignores reach this handler — that's what -// lets j/k/Esc keep working in the panel while an input field consumes -// typing. +// Keys.priority: Keys.BeforeItem means this handler gets keys first, +// even when a descendant has activeFocus. That's what lets Up/Down +// arrows drive the cursor instead of being consumed by an inner +// Flickable's built-in scroll handling. When a panel has an inline +// editor (wifi passphrase, gallery TextField demo) the panel must +// set `blocked: editor.activeFocus` so this handler short-circuits +// and the editor receives keys normally. // // blocked: when true, ALL keys are forwarded to descendants without -// triggering signals. Useful when an inline editor is open and the -// caller wants the cursor model frozen. +// triggering signals. Item { id: root @@ -41,7 +42,7 @@ Item { signal textKey(string text) focus: true - Keys.priority: Keys.AfterItem + Keys.priority: Keys.BeforeItem Keys.onPressed: function(event) { if (blocked) return diff --git a/default/quickshell/omarchy-shell/plugins/dev-gallery/GalleryPanel.qml b/default/quickshell/omarchy-shell/plugins/dev-gallery/GalleryPanel.qml index 28c4eb44..dba4ab44 100644 --- a/default/quickshell/omarchy-shell/plugins/dev-gallery/GalleryPanel.qml +++ b/default/quickshell/omarchy-shell/plugins/dev-gallery/GalleryPanel.qml @@ -232,22 +232,17 @@ Item { // hasCursor change handler of every cursor target below. function ensureCursorVisible(item) { if (!item || !scrollArea) return - var sb = scrollArea.ScrollBar.vertical - if (!sb || scrollArea.contentHeight <= scrollArea.height) return - var contentItem = scrollArea.contentItem - if (!contentItem) return - var p = item.mapToItem(contentItem, 0, 0) - var itemTop = p.y - var itemBottom = p.y + item.height - var viewTop = sb.position * scrollArea.contentHeight - var viewBottom = viewTop + scrollArea.height - var pad = 20 - if (itemTop < viewTop + pad) { - sb.position = Math.max(0, (itemTop - pad) / scrollArea.contentHeight) - } else if (itemBottom > viewBottom - pad) { - var newPos = (itemBottom + pad - scrollArea.height) / scrollArea.contentHeight - sb.position = Math.max(0, Math.min(1 - sb.size, newPos)) - } + var flick = scrollArea.contentItem + if (!flick || flick.contentY === undefined) return + var pt = item.mapToItem(flick.contentItem || flick, 0, 0) + var top = pt.y + var bottom = top + (item.height || 0) + var viewTop = flick.contentY + var viewBottom = viewTop + flick.height + var margin = 12 + if (top < viewTop + margin) flick.contentY = Math.max(0, top - margin) + else if (bottom > viewBottom - margin) + flick.contentY = bottom + margin - flick.height } FloatingWindow {