Skip to content

Commit b8529b8

Browse files
authored
Merge pull request #669 from blackbartblues/feat/plugin-manager
feat(plugin-manager): add Plugin Manager with README viewer
2 parents ceb5091 + d3af76d commit b8529b8

31 files changed

Lines changed: 3654 additions & 0 deletions

plugin-manager/AddToBarMenu.qml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import QtQuick
2+
import Quickshell
3+
import Quickshell.Wayland
4+
import qs.Commons
5+
import qs.Services.UI
6+
import qs.Widgets
7+
8+
// Fullscreen overlay that positions an NPopupContextMenu at the cursor.
9+
// Cross-compositor — relies on standard wl_pointer hover events delivered
10+
// by any Wayland compositor (Hyprland, Niri, Sway, ...). No hyprctl.
11+
PanelWindow {
12+
id: root
13+
14+
required property ShellScreen screen
15+
property var pluginApi: null
16+
property var menuItems: []
17+
18+
signal actionSelected(string action)
19+
signal cancelled
20+
21+
property bool _menuShown: false
22+
23+
anchors.top: true
24+
anchors.left: true
25+
anchors.right: true
26+
anchors.bottom: true
27+
visible: false
28+
color: "transparent"
29+
30+
WlrLayershell.layer: WlrLayer.Overlay
31+
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
32+
WlrLayershell.namespace: "noctalia-plugin-manager-add-to-bar-" + (screen?.name || "unknown")
33+
WlrLayershell.exclusionMode: ExclusionMode.Ignore
34+
35+
function show(items) {
36+
menuItems = items || []
37+
_menuShown = false
38+
visible = true
39+
// Fallback: show menu after 300 ms even if no pointer event arrives
40+
// (e.g. cursor outside screen). Normally the first wl_pointer.enter or
41+
// wl_pointer.motion reaching cursorArea fires _showMenuAtCursor sooner.
42+
fallbackTimer.restart()
43+
}
44+
45+
function close() {
46+
fallbackTimer.stop()
47+
_menuShown = false
48+
visible = false
49+
contextMenu.visible = false
50+
}
51+
52+
function _showMenuAtCursor() {
53+
if (_menuShown || !visible) return
54+
_menuShown = true
55+
fallbackTimer.stop()
56+
anchorPoint.x = cursorArea.mouseX
57+
anchorPoint.y = cursorArea.mouseY
58+
contextMenu.model = root.menuItems
59+
contextMenu.anchorItem = anchorPoint
60+
contextMenu.visible = true
61+
}
62+
63+
Timer {
64+
id: fallbackTimer
65+
interval: 300
66+
repeat: false
67+
onTriggered: root._showMenuAtCursor()
68+
}
69+
70+
NPopupContextMenu {
71+
id: contextMenu
72+
visible: false
73+
screen: root.screen
74+
minWidth: 200
75+
76+
onTriggered: (action, item) => {
77+
root.actionSelected(action)
78+
root.close()
79+
}
80+
}
81+
82+
Item {
83+
id: anchorPoint
84+
width: 1
85+
height: 1
86+
x: 0
87+
y: 0
88+
}
89+
90+
MouseArea {
91+
id: cursorArea
92+
anchors.fill: parent
93+
hoverEnabled: true
94+
acceptedButtons: Qt.LeftButton | Qt.RightButton
95+
96+
onEntered: root._showMenuAtCursor()
97+
onPositionChanged: mouse => root._showMenuAtCursor()
98+
99+
onClicked: mouse => {
100+
root.cancelled()
101+
root.close()
102+
}
103+
}
104+
105+
Component.onDestruction: {
106+
close()
107+
}
108+
}

0 commit comments

Comments
 (0)