noctalia
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
|
||||
// Universal selection context menu that appears at cursor position
|
||||
PanelWindow {
|
||||
id: root
|
||||
|
||||
required property ShellScreen screen
|
||||
property var pluginApi: null
|
||||
property var menuItems: []
|
||||
|
||||
signal itemSelected(string action)
|
||||
signal cancelled
|
||||
|
||||
anchors.top: true
|
||||
anchors.left: true
|
||||
anchors.right: true
|
||||
anchors.bottom: true
|
||||
visible: false
|
||||
color: "transparent"
|
||||
|
||||
WlrLayershell.layer: WlrLayer.Overlay
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||
WlrLayershell.namespace: "noctalia-selection-menu-" + (screen?.name || "unknown")
|
||||
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
||||
|
||||
property int cursorX: 0
|
||||
property int cursorY: 0
|
||||
|
||||
function show(items) {
|
||||
menuItems = items || [];
|
||||
visible = true;
|
||||
getCursorPositionProcess.running = true;
|
||||
}
|
||||
|
||||
function close() {
|
||||
visible = false;
|
||||
contextMenu.visible = false;
|
||||
}
|
||||
|
||||
// Get cursor position from hyprctl
|
||||
Process {
|
||||
id: getCursorPositionProcess
|
||||
command: ["hyprctl", "cursorpos", "-j"]
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
id: cursorStdout
|
||||
}
|
||||
|
||||
onExited: (exitCode, exitStatus) => {
|
||||
if (exitCode === 0) {
|
||||
try {
|
||||
const data = JSON.parse(cursorStdout.text);
|
||||
root.cursorX = data.x || 0;
|
||||
root.cursorY = data.y || 0;
|
||||
|
||||
// Position menu at cursor
|
||||
anchorPoint.x = root.cursorX;
|
||||
anchorPoint.y = root.cursorY;
|
||||
contextMenu.model = root.menuItems;
|
||||
contextMenu.anchorItem = anchorPoint;
|
||||
contextMenu.visible = true;
|
||||
} catch (e) {
|
||||
ToastService.showError(pluginApi?.tr("toast.failed-to-get-cursor-position"));
|
||||
root.close();
|
||||
}
|
||||
} else {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Context menu
|
||||
NPopupContextMenu {
|
||||
id: contextMenu
|
||||
visible: false
|
||||
screen: root.screen
|
||||
minWidth: 200
|
||||
|
||||
onTriggered: (action, item) => {
|
||||
root.itemSelected(action);
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Anchor point for menu positioning
|
||||
Item {
|
||||
id: anchorPoint
|
||||
width: 1
|
||||
height: 1
|
||||
x: 0
|
||||
y: 0
|
||||
}
|
||||
|
||||
// Fullscreen mouse area to capture outside clicks
|
||||
MouseArea {
|
||||
id: mouseCapture
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
onClicked: mouse => {
|
||||
root.cancelled();
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
if (getCursorPositionProcess.running) {
|
||||
getCursorPositionProcess.terminate();
|
||||
}
|
||||
close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user