Files
noctalia-shell/Services/Control/CurrentScreenDetector.qml
T

106 lines
3.3 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Commons
/**
* Detects which screen the cursor is currently on by creating a temporary
* invisible PanelWindow. Use withTargetScreen() to get the screen asynchronously.
*
* Usage:
* CurrentScreenDetector {
* id: screenDetector
* }
*
* function doSomething() {
* screenDetector.withTargetScreen(function(screen) {
* // screen is the ShellScreen where cursor is
* })
* }
*/
Item {
id: root
// Pending callback to execute once screen is detected
property var pendingCallback: null
// Detected screen
property var detectedScreen: null
// Signal emitted when screen is detected from the PanelWindow
signal screenDetected(var detectedScreen)
onScreenDetected: function (detectedScreen) {
root.detectedScreen = detectedScreen;
screenDetectorDebounce.restart();
}
/**
* Execute callback with the screen where the cursor currently is.
* On single-monitor setups, executes immediately.
* On multi-monitor setups, briefly opens an invisible window to detect the screen.
*/
function withTargetScreen(callback: var): void {
if (root.pendingCallback) {
Logger.w("CurrentScreenDetector", "Another detection is pending, ignoring new call");
return;
}
// Single monitor setup can execute immediately
if (Quickshell.screens.length === 1) {
callback(Quickshell.screens[0]);
} else {
// Multi-monitor setup needs async detection
root.detectedScreen = null;
root.pendingCallback = callback;
screenDetectorLoader.active = true;
}
}
Timer {
id: screenDetectorDebounce
running: false
interval: 20
onTriggered: {
Logger.d("CurrentScreenDetector", "Screen debounced to:", root.detectedScreen?.name || "null");
// Execute pending callback if any
if (root.pendingCallback) {
if (!Settings.data.general.allowPanelsOnScreenWithoutBar) {
// If we explicitly disabled panels on screen without bar, check if bar is configured
// for this screen, and fallback to primary screen if necessary
var monitors = Settings.data.bar.monitors || [];
const hasBar = monitors.length === 0 || monitors.includes(root.detectedScreen?.name);
if (!hasBar) {
root.detectedScreen = Quickshell.screens[0];
}
}
Logger.d("CurrentScreenDetector", "Executing callback on screen:", root.detectedScreen.name);
root.pendingCallback(root.detectedScreen);
root.pendingCallback = null;
}
// Clean up
screenDetectorLoader.active = false;
}
}
// Invisible dummy PanelWindow to detect which screen should receive the action
Loader {
id: screenDetectorLoader
active: false
sourceComponent: PanelWindow {
implicitWidth: 0
implicitHeight: 0
color: Color.transparent
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.namespace: "noctalia-screen-detector"
mask: Region {}
onScreenChanged: root.screenDetected(screen)
}
}
}