Share pointer movement gate across menus
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import QtQuick
|
||||
|
||||
// Filters synthetic hover churn from moving delegates under a stationary
|
||||
// pointer. Call reset() after keyboard/list mutations, then moved() from a
|
||||
// row MouseArea's onPositionChanged before changing cursor selection.
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
property Item referenceItem: null
|
||||
property real threshold: 1
|
||||
property bool primed: false
|
||||
property real lastX: 0
|
||||
property real lastY: 0
|
||||
|
||||
function reset() {
|
||||
root.primed = false
|
||||
root.lastX = 0
|
||||
root.lastY = 0
|
||||
}
|
||||
|
||||
function moved(item, mouse) {
|
||||
if (!item || !mouse) {
|
||||
root.reset()
|
||||
return false
|
||||
}
|
||||
|
||||
var target = root.referenceItem || item
|
||||
var point = item.mapToItem(target, mouse.x, mouse.y)
|
||||
var didMove = root.primed
|
||||
&& (Math.abs(point.x - root.lastX) > root.threshold || Math.abs(point.y - root.lastY) > root.threshold)
|
||||
|
||||
root.lastX = point.x
|
||||
root.lastY = point.y
|
||||
root.primed = true
|
||||
|
||||
return didMove
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ PanelSectionHeader 1.0 PanelSectionHeader.qml
|
||||
PanelSeparator 1.0 PanelSeparator.qml
|
||||
PanelSlider 1.0 PanelSlider.qml
|
||||
PanelToolTip 1.0 PanelToolTip.qml
|
||||
PointerMoveGate 1.0 PointerMoveGate.qml
|
||||
PopupCard 1.0 PopupCard.qml
|
||||
SearchableDropdown 1.0 SearchableDropdown.qml
|
||||
TextField 1.0 TextField.qml
|
||||
|
||||
@@ -14,8 +14,6 @@ Item {
|
||||
property string filterText: ""
|
||||
property int selectedIndex: 0
|
||||
property bool cursorActive: false
|
||||
property real lastPointerX: -1
|
||||
property real lastPointerY: -1
|
||||
property bool clearConfirmOpen: false
|
||||
property var history: []
|
||||
|
||||
@@ -180,21 +178,11 @@ Item {
|
||||
}
|
||||
|
||||
function disarmPointer() {
|
||||
root.lastPointerX = -1
|
||||
root.lastPointerY = -1
|
||||
}
|
||||
|
||||
function pointerMovedInCard(item, mouse) {
|
||||
var point = item.mapToItem(card, mouse.x, mouse.y)
|
||||
var moved = root.lastPointerX >= 0
|
||||
&& (Math.abs(point.x - root.lastPointerX) > 1 || Math.abs(point.y - root.lastPointerY) > 1)
|
||||
root.lastPointerX = point.x
|
||||
root.lastPointerY = point.y
|
||||
return moved
|
||||
pointerGate.reset()
|
||||
}
|
||||
|
||||
function selectFromPointer(index, item, mouse) {
|
||||
if (!root.pointerMovedInCard(item, mouse)) return
|
||||
if (!pointerGate.moved(item, mouse)) return
|
||||
root.cursorActive = true
|
||||
root.selectedIndex = index
|
||||
}
|
||||
@@ -247,6 +235,11 @@ Item {
|
||||
|
||||
ListModel { id: displayModel }
|
||||
|
||||
PointerMoveGate {
|
||||
id: pointerGate
|
||||
referenceItem: card
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: historyFile
|
||||
path: root.historyPath
|
||||
|
||||
@@ -19,9 +19,6 @@ Item {
|
||||
property string filterText: ""
|
||||
property int selectedIndex: 0
|
||||
property bool cursorActive: true
|
||||
property bool hoverArmed: false
|
||||
property real lastPointerX: -1
|
||||
property real lastPointerY: -1
|
||||
property var filteredEntries: []
|
||||
property int launchSerial: 0
|
||||
property int launchToplevelCount: 0
|
||||
@@ -133,23 +130,11 @@ Item {
|
||||
}
|
||||
|
||||
function disarmHover() {
|
||||
root.hoverArmed = false
|
||||
root.lastPointerX = -1
|
||||
root.lastPointerY = -1
|
||||
}
|
||||
|
||||
function pointerMovedInCard(item, mouse) {
|
||||
var point = item.mapToItem(card, mouse.x, mouse.y)
|
||||
var moved = root.lastPointerX >= 0
|
||||
&& (Math.abs(point.x - root.lastPointerX) > 1 || Math.abs(point.y - root.lastPointerY) > 1)
|
||||
root.lastPointerX = point.x
|
||||
root.lastPointerY = point.y
|
||||
return moved
|
||||
pointerGate.reset()
|
||||
}
|
||||
|
||||
function selectFromPointer(index, item, mouse) {
|
||||
if (!root.pointerMovedInCard(item, mouse)) return
|
||||
root.hoverArmed = true
|
||||
if (!pointerGate.moved(item, mouse)) return
|
||||
root.cursorActive = true
|
||||
root.selectedIndex = index
|
||||
}
|
||||
@@ -380,6 +365,11 @@ Item {
|
||||
onLoadFailed: root.loadConfiguredHides("")
|
||||
}
|
||||
|
||||
PointerMoveGate {
|
||||
id: pointerGate
|
||||
referenceItem: card
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ToplevelManager.toplevels
|
||||
function onValuesChanged() { root.maybeFinishLaunchFeedback() }
|
||||
@@ -638,10 +628,6 @@ Item {
|
||||
onPositionChanged: function(mouse) {
|
||||
root.selectFromPointer(row.index, row, mouse)
|
||||
}
|
||||
onContainsMouseChanged: if (containsMouse && root.hoverArmed) {
|
||||
root.cursorActive = true
|
||||
root.selectedIndex = row.index
|
||||
}
|
||||
onClicked: {
|
||||
root.cursorActive = true
|
||||
root.selectedIndex = row.index
|
||||
|
||||
@@ -501,6 +501,7 @@ Item {
|
||||
function select(delta) {
|
||||
if (displayModel.count === 0) return
|
||||
|
||||
root.disarmPointer()
|
||||
if (!cursorActive) {
|
||||
cursorActive = true
|
||||
selectedIndex = delta < 0 ? displayModel.count - 1 : 0
|
||||
@@ -514,6 +515,7 @@ Item {
|
||||
root.filterText = nextFilter
|
||||
root.selectedIndex = 0
|
||||
root.cursorActive = root.mode !== "input"
|
||||
root.disarmPointer()
|
||||
if (!root.dmenuActive && root.filterText.trim()) root.loadProvidersForSearch()
|
||||
root.rebuildDisplay()
|
||||
}
|
||||
@@ -525,6 +527,7 @@ Item {
|
||||
root.filterText = ""
|
||||
root.selectedIndex = 0
|
||||
root.cursorActive = true
|
||||
root.disarmPointer()
|
||||
root.rebuildDisplay()
|
||||
root.loadProviderForMenu(id)
|
||||
}
|
||||
@@ -598,6 +601,7 @@ Item {
|
||||
filterText = ""
|
||||
selectedIndex = 0
|
||||
cursorActive = true
|
||||
root.disarmPointer()
|
||||
root.evaluateGuards()
|
||||
opened = true
|
||||
rebuildDisplay()
|
||||
@@ -621,6 +625,7 @@ Item {
|
||||
filterText = ""
|
||||
selectedIndex = 0
|
||||
cursorActive = mode !== "input"
|
||||
root.disarmPointer()
|
||||
opened = true
|
||||
rebuildDisplay()
|
||||
|
||||
@@ -667,6 +672,16 @@ Item {
|
||||
return "ok"
|
||||
}
|
||||
|
||||
function disarmPointer() {
|
||||
pointerGate.reset()
|
||||
}
|
||||
|
||||
function selectFromPointer(index, item, mouse) {
|
||||
if (!pointerGate.moved(item, mouse)) return
|
||||
root.cursorActive = true
|
||||
root.selectedIndex = index
|
||||
}
|
||||
|
||||
Process {
|
||||
id: providerProc
|
||||
property string menuId: ""
|
||||
@@ -693,6 +708,11 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
PointerMoveGate {
|
||||
id: pointerGate
|
||||
referenceItem: card
|
||||
}
|
||||
|
||||
// The JSONC sources are watched so live edits to the default file (or the
|
||||
// user extension at ~/.config/omarchy/extensions/omarchy-menu.jsonc) take
|
||||
// effect without restarting the shell.
|
||||
@@ -1020,11 +1040,14 @@ Item {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPositionChanged: {
|
||||
onPositionChanged: function(mouse) {
|
||||
root.selectFromPointer(row.index, row, mouse)
|
||||
}
|
||||
onClicked: {
|
||||
root.cursorActive = true
|
||||
root.selectedIndex = row.index
|
||||
root.activateIndex(row.index)
|
||||
}
|
||||
onClicked: root.activateIndex(row.index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user