diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/DMSShellIPC.qml')
| -rw-r--r-- | raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/DMSShellIPC.qml | 1728 |
1 files changed, 1728 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/DMSShellIPC.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/DMSShellIPC.qml new file mode 100644 index 0000000..4a111c5 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/DMSShellIPC.qml @@ -0,0 +1,1728 @@ +import QtQuick +import Quickshell.Io +import Quickshell.Hyprland +import Quickshell.Wayland +import Quickshell.Services.SystemTray +import qs.Common +import qs.Services +import qs.Modules.Settings.DisplayConfig + +Item { + id: root + + required property var powerMenuModalLoader + required property var processListModalLoader + required property var controlCenterLoader + required property var dankDashPopoutLoader + required property var notepadSlideoutVariants + required property var hyprKeybindsModalLoader + required property var dankBarRepeater + required property var hyprlandOverviewLoader + required property var workspaceRenameModalLoader + required property var windowRuleModalLoader + + function getPreferredBar(refPropertyName) { + if (!root.dankBarRepeater || root.dankBarRepeater.count === 0) + return null; + + const focusedScreenName = BarWidgetService.getFocusedScreenName(); + + const loaders = Array.from({ + length: root.dankBarRepeater.count + }, (_, i) => root.dankBarRepeater.itemAt(i)); + + let currentBar = null; + + for (const loader of loaders) { + const instances = loader?.item?.barVariants?.instances || []; + for (const bar of instances) { + if (!bar) + continue; + + const onFocusedScreen = focusedScreenName && bar.modelData?.name === focusedScreenName; + const hasRef = !refPropertyName || !!bar[refPropertyName]; + + if (hasRef) { + currentBar = bar; + + if (onFocusedScreen) + break; + } + } + } + + return currentBar; + } + + IpcHandler { + function open() { + root.powerMenuModalLoader.active = true; + if (root.powerMenuModalLoader.item) + root.powerMenuModalLoader.item.openCentered(); + + return "POWERMENU_OPEN_SUCCESS"; + } + + function close() { + if (root.powerMenuModalLoader.item) + root.powerMenuModalLoader.item.close(); + + return "POWERMENU_CLOSE_SUCCESS"; + } + + function toggle() { + root.powerMenuModalLoader.active = true; + if (root.powerMenuModalLoader.item) { + if (root.powerMenuModalLoader.item.shouldBeVisible) { + root.powerMenuModalLoader.item.close(); + } else { + root.powerMenuModalLoader.item.openCentered(); + } + } + + return "POWERMENU_TOGGLE_SUCCESS"; + } + + target: "powermenu" + } + + IpcHandler { + function open(): string { + root.processListModalLoader.active = true; + if (root.processListModalLoader.item) + root.processListModalLoader.item.show(); + + return "PROCESSLIST_OPEN_SUCCESS"; + } + + function close(): string { + if (root.processListModalLoader.item) + root.processListModalLoader.item.hide(); + + return "PROCESSLIST_CLOSE_SUCCESS"; + } + + function toggle(): string { + root.processListModalLoader.active = true; + if (root.processListModalLoader.item) + root.processListModalLoader.item.toggle(); + + return "PROCESSLIST_TOGGLE_SUCCESS"; + } + + function focusOrToggle(): string { + root.processListModalLoader.active = true; + if (root.processListModalLoader.item) + root.processListModalLoader.item.focusOrToggle(); + + return "PROCESSLIST_FOCUS_OR_TOGGLE_SUCCESS"; + } + + target: "processlist" + } + + IpcHandler { + function open(): string { + const bar = root.getPreferredBar("controlCenterButtonRef"); + if (bar) { + bar.triggerControlCenter(); + return "CONTROL_CENTER_OPEN_SUCCESS"; + } + return "CONTROL_CENTER_OPEN_FAILED"; + } + + function hide(): string { + if (root.controlCenterLoader.item && root.controlCenterLoader.item.shouldBeVisible) { + root.controlCenterLoader.item.close(); + return "CONTROL_CENTER_HIDE_SUCCESS"; + } + return "CONTROL_CENTER_HIDE_FAILED"; + } + + function toggle(): string { + if (root.controlCenterLoader.item?.shouldBeVisible) { + root.controlCenterLoader.item.close(); + return "CONTROL_CENTER_TOGGLE_SUCCESS"; + } + + const bar = root.getPreferredBar("controlCenterButtonRef"); + if (bar) { + bar.triggerControlCenter(); + return "CONTROL_CENTER_TOGGLE_SUCCESS"; + } + return "CONTROL_CENTER_TOGGLE_FAILED"; + } + + function status(): string { + return (root.controlCenterLoader.item && root.controlCenterLoader.item.shouldBeVisible) ? "visible" : "hidden"; + } + + target: "control-center" + } + + IpcHandler { + function open(tab: string): string { + const bar = root.getPreferredBar("clockButtonRef"); + if (!bar) + return "DASH_OPEN_FAILED"; + + const dash = root.dankDashPopoutLoader.item; + const onSameScreen = dash && dash.shouldBeVisible && dash.triggerScreen?.name === bar.screen?.name; + + if (!onSameScreen) { + bar.triggerWallpaperBrowser(); + } + + if (!root.dankDashPopoutLoader.item) + return "DASH_OPEN_FAILED"; + + switch (tab.toLowerCase()) { + case "media": + root.dankDashPopoutLoader.item.currentTabIndex = 1; + break; + case "wallpaper": + root.dankDashPopoutLoader.item.currentTabIndex = 2; + break; + case "weather": + root.dankDashPopoutLoader.item.currentTabIndex = SettingsData.weatherEnabled ? 3 : 0; + break; + default: + root.dankDashPopoutLoader.item.currentTabIndex = 0; + break; + } + + root.dankDashPopoutLoader.item.dashVisible = true; + return "DASH_OPEN_SUCCESS"; + } + + function close(): string { + if (root.dankDashPopoutLoader.item) { + root.dankDashPopoutLoader.item.dashVisible = false; + return "DASH_CLOSE_SUCCESS"; + } + return "DASH_CLOSE_FAILED"; + } + + function toggle(tab: string): string { + if (root.dankDashPopoutLoader.item?.dashVisible) { + root.dankDashPopoutLoader.item.dashVisible = false; + return "DASH_TOGGLE_SUCCESS"; + } + + const bar = root.getPreferredBar("clockButtonRef"); + if (bar) { + bar.triggerWallpaperBrowser(); + if (root.dankDashPopoutLoader.item) { + switch (tab.toLowerCase()) { + case "media": + root.dankDashPopoutLoader.item.currentTabIndex = 1; + break; + case "wallpaper": + root.dankDashPopoutLoader.item.currentTabIndex = 2; + break; + case "weather": + root.dankDashPopoutLoader.item.currentTabIndex = SettingsData.weatherEnabled ? 3 : 0; + break; + default: + root.dankDashPopoutLoader.item.currentTabIndex = 0; + break; + } + } + return "DASH_TOGGLE_SUCCESS"; + } + return "DASH_TOGGLE_FAILED"; + } + + target: "dash" + } + + IpcHandler { + function getFocusedScreenName() { + if (CompositorService.isHyprland && Hyprland.focusedWorkspace && Hyprland.focusedWorkspace.monitor) { + return Hyprland.focusedWorkspace.monitor.name; + } + if (CompositorService.isNiri && NiriService.currentOutput) { + return NiriService.currentOutput; + } + if ((CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) && I3.workspaces?.values) { + const focusedWs = I3.workspaces.values.find(ws => ws.focused === true); + return focusedWs?.monitor?.name || ""; + } + if (CompositorService.isDwl && DwlService.activeOutput) { + return DwlService.activeOutput; + } + return ""; + } + + function getActiveNotepadInstance() { + if (root.notepadSlideoutVariants.instances.length === 0) { + return null; + } + + if (root.notepadSlideoutVariants.instances.length === 1) { + return root.notepadSlideoutVariants.instances[0]; + } + + var focusedScreen = getFocusedScreenName(); + if (focusedScreen && root.notepadSlideoutVariants.instances.length > 0) { + for (var i = 0; i < root.notepadSlideoutVariants.instances.length; i++) { + var slideout = root.notepadSlideoutVariants.instances[i]; + if (slideout.modelData && slideout.modelData.name === focusedScreen) { + return slideout; + } + } + } + + for (var i = 0; i < root.notepadSlideoutVariants.instances.length; i++) { + var slideout = root.notepadSlideoutVariants.instances[i]; + if (slideout.isVisible) { + return slideout; + } + } + + return root.notepadSlideoutVariants.instances[0]; + } + + function open(): string { + var instance = getActiveNotepadInstance(); + if (instance) { + instance.show(); + return "NOTEPAD_OPEN_SUCCESS"; + } + return "NOTEPAD_OPEN_FAILED"; + } + + function close(): string { + var instance = getActiveNotepadInstance(); + if (instance) { + instance.hide(); + return "NOTEPAD_CLOSE_SUCCESS"; + } + return "NOTEPAD_CLOSE_FAILED"; + } + + function toggle(): string { + var instance = getActiveNotepadInstance(); + if (instance) { + instance.toggle(); + return "NOTEPAD_TOGGLE_SUCCESS"; + } + return "NOTEPAD_TOGGLE_FAILED"; + } + + target: "notepad" + } + + IpcHandler { + function toggle(): string { + SessionService.toggleIdleInhibit(); + return SessionService.idleInhibited ? "Idle inhibit enabled" : "Idle inhibit disabled"; + } + + function enable(): string { + SessionService.enableIdleInhibit(); + return "Idle inhibit enabled"; + } + + function disable(): string { + SessionService.disableIdleInhibit(); + return "Idle inhibit disabled"; + } + + function status(): string { + return SessionService.idleInhibited ? "Idle inhibit is enabled" : "Idle inhibit is disabled"; + } + + function reason(newReason: string): string { + if (!newReason) { + return `Current reason: ${SessionService.inhibitReason}`; + } + + SessionService.setInhibitReason(newReason); + return `Inhibit reason set to: ${newReason}`; + } + + target: "inhibit" + } + + IpcHandler { + function list(): string { + return MprisController.availablePlayers.map(p => p.identity).join("\n"); + } + + function play(): void { + if (MprisController.activePlayer && MprisController.activePlayer.canPlay) { + MprisController.activePlayer.play(); + } + } + + function pause(): void { + if (MprisController.activePlayer && MprisController.activePlayer.canPause) { + MprisController.activePlayer.pause(); + } + } + + function playPause(): void { + if (MprisController.activePlayer && MprisController.activePlayer.canTogglePlaying) { + MprisController.activePlayer.togglePlaying(); + } + } + + function previous(): void { + MprisController.previousOrRewind(); + } + + function next(): void { + if (MprisController.activePlayer && MprisController.activePlayer.canGoNext) { + MprisController.activePlayer.next(); + } + } + + function stop(): void { + if (MprisController.activePlayer) { + MprisController.activePlayer.stop(); + } + } + + function increment(step: string): string { + if (MprisController.activePlayer && MprisController.activePlayer.volumeSupported) { + const currentVolume = Math.round(MprisController.activePlayer.volume * 100); + const stepValue = parseInt(step || "5"); + const newVolume = Math.max(0, Math.min(100, currentVolume + stepValue)); + + MprisController.activePlayer.volume = newVolume / 100; + return `Player volume increased to ${newVolume}%`; + } + } + + function decrement(step: string): string { + if (MprisController.activePlayer && MprisController.activePlayer.volumeSupported) { + const currentVolume = Math.round(MprisController.activePlayer.volume * 100); + const stepValue = parseInt(step || "5"); + const newVolume = Math.max(0, Math.min(100, currentVolume - stepValue)); + + MprisController.activePlayer.volume = newVolume / 100; + return `Player volume decreased to ${newVolume}%`; + } + } + + function setvolume(percentage: string): string { + if (MprisController.activePlayer && MprisController.activePlayer.volumeSupported) { + const clampedVolume = Math.max(0, Math.min(100, percentage)); + MprisController.activePlayer.volume = clampedVolume / 100; + return `Player volume set to ${clampedVolume}%`; + } + } + + target: "mpris" + } + + IpcHandler { + function toggle(provider: string): string { + if (!provider) + return "ERROR: No provider specified"; + + KeybindsService.loadCheatsheet(provider); + root.hyprKeybindsModalLoader.active = true; + + if (!root.hyprKeybindsModalLoader.item) + return `KEYBINDS_TOGGLE_FAILED: ${provider}`; + + if (root.hyprKeybindsModalLoader.item.shouldBeVisible) + root.hyprKeybindsModalLoader.item.close(); + else + root.hyprKeybindsModalLoader.item.open(); + return `KEYBINDS_TOGGLE_SUCCESS: ${provider}`; + } + + function toggleWithPath(provider: string, path: string): string { + if (!provider) + return "ERROR: No provider specified"; + + KeybindsService.loadCheatsheet(provider); + root.hyprKeybindsModalLoader.active = true; + + if (!root.hyprKeybindsModalLoader.item) + return `KEYBINDS_TOGGLE_FAILED: ${provider}`; + + if (root.hyprKeybindsModalLoader.item.shouldBeVisible) + root.hyprKeybindsModalLoader.item.close(); + else + root.hyprKeybindsModalLoader.item.open(); + return `KEYBINDS_TOGGLE_SUCCESS: ${provider} (${path})`; + } + + function open(provider: string): string { + if (!provider) + return "ERROR: No provider specified"; + + KeybindsService.loadCheatsheet(provider); + root.hyprKeybindsModalLoader.active = true; + + if (!root.hyprKeybindsModalLoader.item) + return `KEYBINDS_OPEN_FAILED: ${provider}`; + + root.hyprKeybindsModalLoader.item.open(); + return `KEYBINDS_OPEN_SUCCESS: ${provider}`; + } + + function openWithPath(provider: string, path: string): string { + if (!provider) + return "ERROR: No provider specified"; + + KeybindsService.loadCheatsheet(provider); + root.hyprKeybindsModalLoader.active = true; + + if (!root.hyprKeybindsModalLoader.item) + return `KEYBINDS_OPEN_FAILED: ${provider}`; + + root.hyprKeybindsModalLoader.item.open(); + return `KEYBINDS_OPEN_SUCCESS: ${provider} (${path})`; + } + + function close(): string { + if (!root.hyprKeybindsModalLoader.item) + return "KEYBINDS_CLOSE_FAILED"; + + root.hyprKeybindsModalLoader.item.close(); + return "KEYBINDS_CLOSE_SUCCESS"; + } + + target: "keybinds" + } + + IpcHandler { + function openBinds(): string { + if (!CompositorService.isHyprland) + return "HYPR_NOT_AVAILABLE"; + + KeybindsService.currentProvider = "hyprland"; + KeybindsService.loadBinds(); + root.hyprKeybindsModalLoader.active = true; + + if (!root.hyprKeybindsModalLoader.item) + return "HYPR_KEYBINDS_OPEN_FAILED"; + + root.hyprKeybindsModalLoader.item.open(); + return "HYPR_KEYBINDS_OPEN_SUCCESS"; + } + + function closeBinds(): string { + if (!CompositorService.isHyprland) + return "HYPR_NOT_AVAILABLE"; + + if (!root.hyprKeybindsModalLoader.item) + return "HYPR_KEYBINDS_CLOSE_FAILED"; + + root.hyprKeybindsModalLoader.item.close(); + return "HYPR_KEYBINDS_CLOSE_SUCCESS"; + } + + function toggleBinds(): string { + if (!CompositorService.isHyprland) + return "HYPR_NOT_AVAILABLE"; + + KeybindsService.currentProvider = "hyprland"; + KeybindsService.loadBinds(); + root.hyprKeybindsModalLoader.active = true; + + if (!root.hyprKeybindsModalLoader.item) + return "HYPR_KEYBINDS_TOGGLE_FAILED"; + + if (root.hyprKeybindsModalLoader.item.shouldBeVisible) { + root.hyprKeybindsModalLoader.item.close(); + } else { + root.hyprKeybindsModalLoader.item.open(); + } + return "HYPR_KEYBINDS_TOGGLE_SUCCESS"; + } + + function toggleOverview(): string { + if (!CompositorService.isHyprland || !root.hyprlandOverviewLoader.item) { + return "HYPR_NOT_AVAILABLE"; + } + root.hyprlandOverviewLoader.item.overviewOpen = !root.hyprlandOverviewLoader.item.overviewOpen; + return root.hyprlandOverviewLoader.item.overviewOpen ? "OVERVIEW_OPEN_SUCCESS" : "OVERVIEW_CLOSE_SUCCESS"; + } + + function closeOverview(): string { + if (!CompositorService.isHyprland || !root.hyprlandOverviewLoader.item) { + return "HYPR_NOT_AVAILABLE"; + } + root.hyprlandOverviewLoader.item.overviewOpen = false; + return "OVERVIEW_CLOSE_SUCCESS"; + } + + function openOverview(): string { + if (!CompositorService.isHyprland || !root.hyprlandOverviewLoader.item) { + return "HYPR_NOT_AVAILABLE"; + } + root.hyprlandOverviewLoader.item.overviewOpen = true; + return "OVERVIEW_OPEN_SUCCESS"; + } + + target: "hypr" + } + + IpcHandler { + function wallpaper(): string { + const bar = root.getPreferredBar("clockButtonRef"); + if (bar) { + bar.triggerWallpaperBrowser(); + return "SUCCESS: Toggled wallpaper browser"; + } + return "ERROR: Failed to toggle wallpaper browser"; + } + + target: "dankdash" + } + + function getBarConfig(selector: string, value: string): var { + const barSelectors = ["id", "name", "index"]; + if (!barSelectors.includes(selector)) + return { + error: "BAR_INVALID_SELECTOR" + }; + const index = selector === "index" ? Number(value) : SettingsData.barConfigs.findIndex(bar => bar[selector] == value); + const barConfig = SettingsData.barConfigs?.[index]; + if (!barConfig) + return { + error: "BAR_NOT_FOUND" + }; + return { + barConfig + }; + } + + IpcHandler { + function reveal(selector: string, value: string): string { + const { + barConfig, + error + } = getBarConfig(selector, value); + if (error) + return error; + SettingsData.updateBarConfig(barConfig.id, { + visible: true + }); + return "BAR_SHOW_SUCCESS"; + } + + function hide(selector: string, value: string): string { + const { + barConfig, + error + } = getBarConfig(selector, value); + if (error) + return error; + SettingsData.updateBarConfig(barConfig.id, { + visible: false + }); + return "BAR_HIDE_SUCCESS"; + } + + function toggle(selector: string, value: string): string { + const { + barConfig, + error + } = getBarConfig(selector, value); + if (error) + return error; + SettingsData.updateBarConfig(barConfig.id, { + visible: !barConfig.visible + }); + return !barConfig.visible ? "BAR_SHOW_SUCCESS" : "BAR_HIDE_SUCCESS"; + } + + function status(selector: string, value: string): string { + const { + barConfig, + error + } = getBarConfig(selector, value); + if (error) + return error; + return barConfig.visible ? "visible" : "hidden"; + } + + function autoHide(selector: string, value: string): string { + const { + barConfig, + error + } = getBarConfig(selector, value); + if (error) + return error; + SettingsData.updateBarConfig(barConfig.id, { + autoHide: true + }); + return "BAR_AUTO_HIDE_SUCCESS"; + } + + function manualHide(selector: string, value: string): string { + const { + barConfig, + error + } = getBarConfig(selector, value); + if (error) + return error; + SettingsData.updateBarConfig(barConfig.id, { + autoHide: false + }); + return "BAR_MANUAL_HIDE_SUCCESS"; + } + + function toggleAutoHide(selector: string, value: string): string { + const { + barConfig, + error + } = getBarConfig(selector, value); + if (error) + return error; + SettingsData.updateBarConfig(barConfig.id, { + autoHide: !barConfig.autoHide + }); + return barConfig.autoHide ? "BAR_MANUAL_HIDE_SUCCESS" : "BAR_AUTO_HIDE_SUCCESS"; + } + + function getPosition(selector: string, value: string): string { + const { + barConfig, + error + } = getBarConfig(selector, value); + if (error) + return error; + const positions = ["top", "bottom", "left", "right"]; + return positions[barConfig.position] || "unknown"; + } + + function setPosition(selector: string, value: string, position: string): string { + const { + barConfig, + error + } = getBarConfig(selector, value); + if (error) + return error; + const positionMap = { + "top": SettingsData.Position.Top, + "bottom": SettingsData.Position.Bottom, + "left": SettingsData.Position.Left, + "right": SettingsData.Position.Right + }; + const posValue = positionMap[position.toLowerCase()]; + if (posValue === undefined) + return "BAR_INVALID_POSITION"; + SettingsData.updateBarConfig(barConfig.id, { + position: posValue + }); + return "BAR_POSITION_SET_SUCCESS"; + } + + target: "bar" + } + + IpcHandler { + function reveal(): string { + SettingsData.setShowDock(true); + return "DOCK_SHOW_SUCCESS"; + } + + function hide(): string { + SettingsData.setShowDock(false); + return "DOCK_HIDE_SUCCESS"; + } + + function toggle(): string { + SettingsData.toggleShowDock(); + return SettingsData.showDock ? "DOCK_SHOW_SUCCESS" : "DOCK_HIDE_SUCCESS"; + } + + function status(): string { + return SettingsData.showDock ? "visible" : "hidden"; + } + + function autoHide(): string { + SettingsData.dockAutoHide = true; + SettingsData.saveSettings(); + return "BAR_AUTO_HIDE_SUCCESS"; + } + + function manualHide(): string { + SettingsData.dockAutoHide = false; + SettingsData.saveSettings(); + return "BAR_MANUAL_HIDE_SUCCESS"; + } + + function toggleAutoHide(): string { + SettingsData.dockAutoHide = !SettingsData.dockAutoHide; + SettingsData.saveSettings(); + return SettingsData.dockAutoHide ? "BAR_AUTO_HIDE_SUCCESS" : "BAR_MANUAL_HIDE_SUCCESS"; + } + + target: "dock" + } + + IpcHandler { + function open(): string { + PopoutService.openSettings(); + return "SETTINGS_OPEN_SUCCESS"; + } + + function openWith(tab: string): string { + if (!tab) + return "SETTINGS_OPEN_FAILED: No tab specified"; + PopoutService.openSettingsWithTab(tab); + return `SETTINGS_OPEN_SUCCESS: ${tab}`; + } + + function close(): string { + PopoutService.closeSettings(); + return "SETTINGS_CLOSE_SUCCESS"; + } + + function toggle(): string { + PopoutService.toggleSettings(); + return "SETTINGS_TOGGLE_SUCCESS"; + } + + function toggleWith(tab: string): string { + if (!tab) + return "SETTINGS_TOGGLE_FAILED: No tab specified"; + PopoutService.toggleSettingsWithTab(tab); + return `SETTINGS_TOGGLE_SUCCESS: ${tab}`; + } + + function focusOrToggle(): string { + PopoutService.focusOrToggleSettings(); + return "SETTINGS_FOCUS_OR_TOGGLE_SUCCESS"; + } + + function focusOrToggleWith(tab: string): string { + if (!tab) + return "SETTINGS_FOCUS_OR_TOGGLE_FAILED: No tab specified"; + PopoutService.focusOrToggleSettingsWithTab(tab); + return `SETTINGS_FOCUS_OR_TOGGLE_SUCCESS: ${tab}`; + } + + function tabs(): string { + if (!PopoutService.settingsModal) + return "wallpaper\ntheme\ntypography\ntime_weather\nsounds\ndankbar\ndankbar_settings\ndankbar_widgets\nworkspaces\nmedia_player\nnotifications\nosd\nrunning_apps\nupdater\ndock\nlauncher\nkeybinds\ndisplays\nnetwork\nprinters\nlock_screen\npower_sleep\nplugins\nabout"; + var modal = PopoutService.settingsModal; + var ids = []; + var structure = modal.sidebar?.categoryStructure ?? []; + for (var i = 0; i < structure.length; i++) { + var cat = structure[i]; + if (cat.separator) + continue; + if (cat.id) + ids.push(cat.id); + if (cat.children) { + for (var j = 0; j < cat.children.length; j++) { + if (cat.children[j].id) + ids.push(cat.children[j].id); + } + } + } + return ids.join("\n"); + } + + function get(key: string): string { + return JSON.stringify(SettingsData?.[key]); + } + + function set(key: string, value: string): string { + if (!(key in SettingsData)) { + console.warn("Cannot set property, not found:", key); + return "SETTINGS_INVALID_KEY"; + } + + const typeName = typeof SettingsData?.[key]; + + try { + switch (typeName) { + case "boolean": + if (value === "true" || value === "false") + value = (value === "true"); + else + throw `${value} is not a Boolean`; + break; + case "number": + value = Number(value); + if (isNaN(value)) + throw `${value} is not a Number`; + break; + case "string": + value = String(value); + break; + case "object": + // NOTE: Parsing lists is messed up upstream and not sure if we want + // to make sure objects are well structured or just let people set + // whatever they want but risking messed up settings. + // Objects & Arrays are disabled for now + // https://github.com/quickshell-mirror/quickshell/pull/22 + throw "Setting Objects and Arrays not supported"; + default: + throw "Unsupported type"; + } + + console.warn("Setting:", key, value); + SettingsData[key] = value; + SettingsData.saveSettings(); + return "SETTINGS_SET_SUCCESS"; + } catch (e) { + console.warn("Failed to set property:", key, "error:", e); + return "SETTINGS_SET_FAILURE"; + } + } + + target: "settings" + } + + IpcHandler { + function browse(type: string) { + const modal = PopoutService.settingsModal; + if (modal) { + if (type === "wallpaper") { + modal.openWallpaperBrowser(false); + } else if (type === "profile") { + modal.openProfileBrowser(false); + } + } else { + PopoutService.openSettings(); + } + } + + target: "file" + } + + IpcHandler { + function toggle(widgetId: string): string { + if (!widgetId) + return "ERROR: No widget ID specified"; + + if (!BarWidgetService.hasWidget(widgetId)) + return `WIDGET_NOT_FOUND: ${widgetId}`; + + const success = BarWidgetService.triggerWidgetPopout(widgetId); + return success ? `WIDGET_TOGGLE_SUCCESS: ${widgetId}` : `WIDGET_TOGGLE_FAILED: ${widgetId}`; + } + + function openWith(widgetId: string, mode: string): string { + if (!widgetId) + return "ERROR: No widget ID specified"; + if (!BarWidgetService.hasWidget(widgetId)) + return `WIDGET_NOT_FOUND: ${widgetId}`; + + const widget = BarWidgetService.getWidgetOnFocusedScreen(widgetId); + if (!widget) + return `WIDGET_NOT_AVAILABLE: ${widgetId}`; + if (typeof widget.openWithMode !== "function") + return `WIDGET_OPEN_WITH_NOT_SUPPORTED: ${widgetId}`; + + widget.openWithMode(mode || "all"); + return `WIDGET_OPEN_WITH_SUCCESS: ${widgetId} ${mode}`; + } + + function toggleWith(widgetId: string, mode: string): string { + if (!widgetId) + return "ERROR: No widget ID specified"; + if (!BarWidgetService.hasWidget(widgetId)) + return `WIDGET_NOT_FOUND: ${widgetId}`; + + const widget = BarWidgetService.getWidgetOnFocusedScreen(widgetId); + if (!widget) + return `WIDGET_NOT_AVAILABLE: ${widgetId}`; + if (typeof widget.toggleWithMode !== "function") + return `WIDGET_TOGGLE_WITH_NOT_SUPPORTED: ${widgetId}`; + + widget.toggleWithMode(mode || "all"); + return `WIDGET_TOGGLE_WITH_SUCCESS: ${widgetId} ${mode}`; + } + + function openQuery(widgetId: string, query: string): string { + if (!widgetId) + return "ERROR: No widget ID specified"; + if (!BarWidgetService.hasWidget(widgetId)) + return `WIDGET_NOT_FOUND: ${widgetId}`; + + const widget = BarWidgetService.getWidgetOnFocusedScreen(widgetId); + if (!widget) + return `WIDGET_NOT_AVAILABLE: ${widgetId}`; + if (typeof widget.openWithQuery !== "function") + return `WIDGET_OPEN_QUERY_NOT_SUPPORTED: ${widgetId}`; + + widget.openWithQuery(query || ""); + return `WIDGET_OPEN_QUERY_SUCCESS: ${widgetId}`; + } + + function toggleQuery(widgetId: string, query: string): string { + if (!widgetId) + return "ERROR: No widget ID specified"; + if (!BarWidgetService.hasWidget(widgetId)) + return `WIDGET_NOT_FOUND: ${widgetId}`; + + const widget = BarWidgetService.getWidgetOnFocusedScreen(widgetId); + if (!widget) + return `WIDGET_NOT_AVAILABLE: ${widgetId}`; + if (typeof widget.toggleWithQuery !== "function") + return `WIDGET_TOGGLE_QUERY_NOT_SUPPORTED: ${widgetId}`; + + widget.toggleWithQuery(query || ""); + return `WIDGET_TOGGLE_QUERY_SUCCESS: ${widgetId}`; + } + + function list(): string { + const widgets = BarWidgetService.getRegisteredWidgetIds(); + if (widgets.length === 0) + return "No widgets registered"; + + const lines = []; + for (const widgetId of widgets) { + const widget = BarWidgetService.getWidgetOnFocusedScreen(widgetId); + let state = ""; + if (widget?.effectiveVisible !== undefined) + state = widget.effectiveVisible ? " [visible]" : " [hidden]"; + lines.push(widgetId + state); + } + return lines.join("\n"); + } + + function status(widgetId: string): string { + if (!widgetId) + return "ERROR: No widget ID specified"; + + if (!BarWidgetService.hasWidget(widgetId)) + return `WIDGET_NOT_FOUND: ${widgetId}`; + + const widget = BarWidgetService.getWidgetOnFocusedScreen(widgetId); + if (!widget) + return `WIDGET_NOT_AVAILABLE: ${widgetId}`; + + if (widget.popoutTarget?.shouldBeVisible) + return "visible"; + return "hidden"; + } + + function reveal(widgetId: string): string { + if (!widgetId) + return "ERROR: No widget ID specified"; + + if (!BarWidgetService.hasWidget(widgetId)) + return `WIDGET_NOT_FOUND: ${widgetId}`; + + const widget = BarWidgetService.getWidgetOnFocusedScreen(widgetId); + if (!widget) + return `WIDGET_NOT_AVAILABLE: ${widgetId}`; + + if (typeof widget.setVisibilityOverride === "function") { + widget.setVisibilityOverride(true); + return `WIDGET_REVEAL_SUCCESS: ${widgetId}`; + } + return `WIDGET_REVEAL_NOT_SUPPORTED: ${widgetId}`; + } + + function hide(widgetId: string): string { + if (!widgetId) + return "ERROR: No widget ID specified"; + + if (!BarWidgetService.hasWidget(widgetId)) + return `WIDGET_NOT_FOUND: ${widgetId}`; + + const widget = BarWidgetService.getWidgetOnFocusedScreen(widgetId); + if (!widget) + return `WIDGET_NOT_AVAILABLE: ${widgetId}`; + + if (typeof widget.setVisibilityOverride === "function") { + widget.setVisibilityOverride(false); + return `WIDGET_HIDE_SUCCESS: ${widgetId}`; + } + return `WIDGET_HIDE_NOT_SUPPORTED: ${widgetId}`; + } + + function reset(widgetId: string): string { + if (!widgetId) + return "ERROR: No widget ID specified"; + + if (!BarWidgetService.hasWidget(widgetId)) + return `WIDGET_NOT_FOUND: ${widgetId}`; + + const widget = BarWidgetService.getWidgetOnFocusedScreen(widgetId); + if (!widget) + return `WIDGET_NOT_AVAILABLE: ${widgetId}`; + + if (typeof widget.clearVisibilityOverride === "function") { + widget.clearVisibilityOverride(); + return `WIDGET_RESET_SUCCESS: ${widgetId}`; + } + return `WIDGET_RESET_NOT_SUPPORTED: ${widgetId}`; + } + + function visibility(widgetId: string): string { + if (!widgetId) + return "ERROR: No widget ID specified"; + + if (!BarWidgetService.hasWidget(widgetId)) + return `WIDGET_NOT_FOUND: ${widgetId}`; + + const widget = BarWidgetService.getWidgetOnFocusedScreen(widgetId); + if (!widget) + return `WIDGET_NOT_AVAILABLE: ${widgetId}`; + + if (widget.effectiveVisible !== undefined) + return widget.effectiveVisible ? "visible" : "hidden"; + return "unknown"; + } + + target: "widget" + } + + IpcHandler { + function reload(pluginId: string): string { + if (!pluginId) + return "ERROR: No plugin ID specified"; + + if (!PluginService.availablePlugins[pluginId]) + return `PLUGIN_NOT_FOUND: ${pluginId}`; + + if (!PluginService.isPluginLoaded(pluginId)) { + const success = PluginService.enablePlugin(pluginId); + return success ? `PLUGIN_RELOAD_SUCCESS: ${pluginId}` : `PLUGIN_RELOAD_FAILED: ${pluginId}`; + } + + const success = PluginService.reloadPlugin(pluginId); + return success ? `PLUGIN_RELOAD_SUCCESS: ${pluginId}` : `PLUGIN_RELOAD_FAILED: ${pluginId}`; + } + + function enable(pluginId: string): string { + if (!pluginId) + return "ERROR: No plugin ID specified"; + + if (!PluginService.availablePlugins[pluginId]) + return `PLUGIN_NOT_FOUND: ${pluginId}`; + + const success = PluginService.enablePlugin(pluginId); + return success ? `PLUGIN_ENABLE_SUCCESS: ${pluginId}` : `PLUGIN_ENABLE_FAILED: ${pluginId}`; + } + + function disable(pluginId: string): string { + if (!pluginId) + return "ERROR: No plugin ID specified"; + + if (!PluginService.availablePlugins[pluginId]) + return `PLUGIN_NOT_FOUND: ${pluginId}`; + + const success = PluginService.disablePlugin(pluginId); + return success ? `PLUGIN_DISABLE_SUCCESS: ${pluginId}` : `PLUGIN_DISABLE_FAILED: ${pluginId}`; + } + + function toggle(pluginId: string): string { + if (!pluginId) + return "ERROR: No plugin ID specified"; + + if (!PluginService.availablePlugins[pluginId]) + return `PLUGIN_NOT_FOUND: ${pluginId}`; + + const success = PluginService.togglePlugin(pluginId); + return success ? `PLUGIN_TOGGLE_SUCCESS: ${pluginId}` : `PLUGIN_TOGGLE_FAILED: ${pluginId}`; + } + + function list(): string { + const plugins = PluginService.getAvailablePlugins(); + if (plugins.length === 0) + return "No plugins available"; + return plugins.map(p => `${p.id} [${p.loaded ? "loaded" : "disabled"}]`).join("\n"); + } + + function status(pluginId: string): string { + if (!pluginId) + return "ERROR: No plugin ID specified"; + + if (!PluginService.availablePlugins[pluginId]) + return `PLUGIN_NOT_FOUND: ${pluginId}`; + + return PluginService.isPluginLoaded(pluginId) ? "loaded" : "disabled"; + } + + target: "plugins" + } + + IpcHandler { + function open(): string { + if (!PopoutService.clipboardHistoryModal) { + return "CLIPBOARD_NOT_AVAILABLE"; + } + PopoutService.clipboardHistoryModal.show(); + return "CLIPBOARD_OPEN_SUCCESS"; + } + + function close(): string { + if (!PopoutService.clipboardHistoryModal) { + return "CLIPBOARD_NOT_AVAILABLE"; + } + PopoutService.clipboardHistoryModal.hide(); + return "CLIPBOARD_CLOSE_SUCCESS"; + } + + function toggle(): string { + if (!PopoutService.clipboardHistoryModal) { + return "CLIPBOARD_NOT_AVAILABLE"; + } + PopoutService.clipboardHistoryModal.toggle(); + return "CLIPBOARD_TOGGLE_SUCCESS"; + } + + target: "clipboard" + } + + // ! spotlight and launcher should be synonymous for backwards compat + IpcHandler { + function open(): string { + PopoutService.openDankLauncherV2(); + return "LAUNCHER_OPEN_SUCCESS"; + } + + function close(): string { + PopoutService.closeDankLauncherV2(); + return "LAUNCHER_CLOSE_SUCCESS"; + } + + function toggle(): string { + PopoutService.toggleDankLauncherV2(); + return "LAUNCHER_TOGGLE_SUCCESS"; + } + + function openWith(mode: string): string { + if (!mode) + return "LAUNCHER_OPEN_FAILED: No mode specified"; + PopoutService.openDankLauncherV2WithMode(mode); + return `LAUNCHER_OPEN_SUCCESS: ${mode}`; + } + + function toggleWith(mode: string): string { + if (!mode) + return "LAUNCHER_TOGGLE_FAILED: No mode specified"; + PopoutService.toggleDankLauncherV2WithMode(mode); + return `LAUNCHER_TOGGLE_SUCCESS: ${mode}`; + } + + function openQuery(query: string): string { + PopoutService.openDankLauncherV2WithQuery(query); + return "LAUNCHER_OPEN_QUERY_SUCCESS"; + } + + function toggleQuery(query: string): string { + PopoutService.toggleDankLauncherV2WithQuery(query); + return "LAUNCHER_TOGGLE_QUERY_SUCCESS"; + } + + target: "launcher" + } + + // ! spotlight and launcher should be synonymous for backwards compat + IpcHandler { + function open(): string { + PopoutService.openDankLauncherV2(); + return "SPOTLIGHT_OPEN_SUCCESS"; + } + + function close(): string { + PopoutService.closeDankLauncherV2(); + return "SPOTLIGHT_CLOSE_SUCCESS"; + } + + function toggle(): string { + PopoutService.toggleDankLauncherV2(); + return "SPOTLIGHT_TOGGLE_SUCCESS"; + } + + function openWith(mode: string): string { + if (!mode) + return "SPOTLIGHT_OPEN_FAILED: No mode specified"; + PopoutService.openDankLauncherV2WithMode(mode); + return `SPOTLIGHT_OPEN_SUCCESS: ${mode}`; + } + + function toggleWith(mode: string): string { + if (!mode) + return "SPOTLIGHT_TOGGLE_FAILED: No mode specified"; + PopoutService.toggleDankLauncherV2WithMode(mode); + return `SPOTLIGHT_TOGGLE_SUCCESS: ${mode}`; + } + + function openQuery(query: string): string { + PopoutService.openDankLauncherV2WithQuery(query); + return "SPOTLIGHT_OPEN_QUERY_SUCCESS"; + } + + function toggleQuery(query: string): string { + PopoutService.toggleDankLauncherV2WithQuery(query); + return "SPOTLIGHT_TOGGLE_QUERY_SUCCESS"; + } + + target: "spotlight" + } + + IpcHandler { + function info(message: string): string { + if (!message) + return "ERROR: No message specified"; + + ToastService.showInfo(message); + return "TOAST_INFO_SUCCESS"; + } + + function infoWith(message: string, details: string, command: string, category: string): string { + if (!message) + return "ERROR: No message specified"; + + ToastService.showInfo(message, details, command, category); + return "TOAST_INFO_SUCCESS"; + } + + function warn(message: string): string { + if (!message) + return "ERROR: No message specified"; + + ToastService.showWarning(message); + return "TOAST_WARN_SUCCESS"; + } + + function warnWith(message: string, details: string, command: string, category: string): string { + if (!message) + return "ERROR: No message specified"; + + ToastService.showWarning(message, details, command, category); + return "TOAST_WARN_SUCCESS"; + } + + function error(message: string): string { + if (!message) + return "ERROR: No message specified"; + + ToastService.showError(message); + return "TOAST_ERROR_SUCCESS"; + } + + function errorWith(message: string, details: string, command: string, category: string): string { + if (!message) + return "ERROR: No message specified"; + + ToastService.showError(message, details, command, category); + return "TOAST_ERROR_SUCCESS"; + } + + function hide(): string { + ToastService.hideToast(); + return "TOAST_HIDE_SUCCESS"; + } + + function dismiss(category: string): string { + if (!category) + return "ERROR: No category specified"; + + ToastService.dismissCategory(category); + return "TOAST_DISMISS_SUCCESS"; + } + + function status(): string { + if (!ToastService.toastVisible) + return "hidden"; + + const levels = ["info", "warn", "error"]; + return `visible:${levels[ToastService.currentLevel]}:${ToastService.currentMessage}`; + } + + target: "toast" + } + + IpcHandler { + function open(): string { + FirstLaunchService.showWelcome(); + return "WELCOME_OPEN_SUCCESS"; + } + + function doctor(): string { + FirstLaunchService.showDoctor(); + return "WELCOME_DOCTOR_SUCCESS"; + } + + function page(pageNum: string): string { + const num = parseInt(pageNum) || 0; + FirstLaunchService.showGreeter(num); + return `WELCOME_PAGE_SUCCESS: ${num}`; + } + + target: "welcome" + } + + IpcHandler { + function toggleOverlay(instanceId: string): string { + if (!instanceId) + return "ERROR: No instance ID specified"; + + const instance = SettingsData.getDesktopWidgetInstance(instanceId); + if (!instance) + return `DESKTOP_WIDGET_NOT_FOUND: ${instanceId}`; + + const currentValue = instance.config?.showOnOverlay ?? false; + SettingsData.updateDesktopWidgetInstanceConfig(instanceId, { + showOnOverlay: !currentValue + }); + return !currentValue ? `DESKTOP_WIDGET_OVERLAY_ENABLED: ${instanceId}` : `DESKTOP_WIDGET_OVERLAY_DISABLED: ${instanceId}`; + } + + function setOverlay(instanceId: string, enabled: string): string { + if (!instanceId) + return "ERROR: No instance ID specified"; + + const instance = SettingsData.getDesktopWidgetInstance(instanceId); + if (!instance) + return `DESKTOP_WIDGET_NOT_FOUND: ${instanceId}`; + + const enabledBool = enabled === "true" || enabled === "1"; + SettingsData.updateDesktopWidgetInstanceConfig(instanceId, { + showOnOverlay: enabledBool + }); + return enabledBool ? `DESKTOP_WIDGET_OVERLAY_ENABLED: ${instanceId}` : `DESKTOP_WIDGET_OVERLAY_DISABLED: ${instanceId}`; + } + + function list(): string { + const instances = SettingsData.desktopWidgetInstances || []; + if (instances.length === 0) + return "No desktop widgets configured"; + return instances.map(i => `${i.id} [${i.widgetType}] ${i.name || i.widgetType} ${i.enabled ? "[enabled]" : "[disabled]"}`).join("\n"); + } + + function status(instanceId: string): string { + if (!instanceId) + return "ERROR: No instance ID specified"; + + const instance = SettingsData.getDesktopWidgetInstance(instanceId); + if (!instance) + return `DESKTOP_WIDGET_NOT_FOUND: ${instanceId}`; + + const enabled = instance.enabled ?? true; + const overlay = instance.config?.showOnOverlay ?? false; + const overview = instance.config?.showOnOverview ?? false; + const clickThrough = instance.config?.clickThrough ?? false; + const syncPosition = instance.config?.syncPositionAcrossScreens ?? false; + return `enabled: ${enabled}, overlay: ${overlay}, overview: ${overview}, clickThrough: ${clickThrough}, syncPosition: ${syncPosition}`; + } + + function enable(instanceId: string): string { + if (!instanceId) + return "ERROR: No instance ID specified"; + + const instance = SettingsData.getDesktopWidgetInstance(instanceId); + if (!instance) + return `DESKTOP_WIDGET_NOT_FOUND: ${instanceId}`; + + SettingsData.updateDesktopWidgetInstance(instanceId, { + enabled: true + }); + return `DESKTOP_WIDGET_ENABLED: ${instanceId}`; + } + + function disable(instanceId: string): string { + if (!instanceId) + return "ERROR: No instance ID specified"; + + const instance = SettingsData.getDesktopWidgetInstance(instanceId); + if (!instance) + return `DESKTOP_WIDGET_NOT_FOUND: ${instanceId}`; + + SettingsData.updateDesktopWidgetInstance(instanceId, { + enabled: false + }); + return `DESKTOP_WIDGET_DISABLED: ${instanceId}`; + } + + function toggleEnabled(instanceId: string): string { + if (!instanceId) + return "ERROR: No instance ID specified"; + + const instance = SettingsData.getDesktopWidgetInstance(instanceId); + if (!instance) + return `DESKTOP_WIDGET_NOT_FOUND: ${instanceId}`; + + const currentValue = instance.enabled ?? true; + SettingsData.updateDesktopWidgetInstance(instanceId, { + enabled: !currentValue + }); + return !currentValue ? `DESKTOP_WIDGET_ENABLED: ${instanceId}` : `DESKTOP_WIDGET_DISABLED: ${instanceId}`; + } + + function toggleClickThrough(instanceId: string): string { + if (!instanceId) + return "ERROR: No instance ID specified"; + + const instance = SettingsData.getDesktopWidgetInstance(instanceId); + if (!instance) + return `DESKTOP_WIDGET_NOT_FOUND: ${instanceId}`; + + const currentValue = instance.config?.clickThrough ?? false; + SettingsData.updateDesktopWidgetInstanceConfig(instanceId, { + clickThrough: !currentValue + }); + return !currentValue ? `DESKTOP_WIDGET_CLICK_THROUGH_ENABLED: ${instanceId}` : `DESKTOP_WIDGET_CLICK_THROUGH_DISABLED: ${instanceId}`; + } + + function setClickThrough(instanceId: string, enabled: string): string { + if (!instanceId) + return "ERROR: No instance ID specified"; + + const instance = SettingsData.getDesktopWidgetInstance(instanceId); + if (!instance) + return `DESKTOP_WIDGET_NOT_FOUND: ${instanceId}`; + + const enabledBool = enabled === "true" || enabled === "1"; + SettingsData.updateDesktopWidgetInstanceConfig(instanceId, { + clickThrough: enabledBool + }); + return enabledBool ? `DESKTOP_WIDGET_CLICK_THROUGH_ENABLED: ${instanceId}` : `DESKTOP_WIDGET_CLICK_THROUGH_DISABLED: ${instanceId}`; + } + + function toggleSyncPosition(instanceId: string): string { + if (!instanceId) + return "ERROR: No instance ID specified"; + + const instance = SettingsData.getDesktopWidgetInstance(instanceId); + if (!instance) + return `DESKTOP_WIDGET_NOT_FOUND: ${instanceId}`; + + const currentValue = instance.config?.syncPositionAcrossScreens ?? false; + SettingsData.updateDesktopWidgetInstanceConfig(instanceId, { + syncPositionAcrossScreens: !currentValue + }); + return !currentValue ? `DESKTOP_WIDGET_SYNC_POSITION_ENABLED: ${instanceId}` : `DESKTOP_WIDGET_SYNC_POSITION_DISABLED: ${instanceId}`; + } + + function setSyncPosition(instanceId: string, enabled: string): string { + if (!instanceId) + return "ERROR: No instance ID specified"; + + const instance = SettingsData.getDesktopWidgetInstance(instanceId); + if (!instance) + return `DESKTOP_WIDGET_NOT_FOUND: ${instanceId}`; + + const enabledBool = enabled === "true" || enabled === "1"; + SettingsData.updateDesktopWidgetInstanceConfig(instanceId, { + syncPositionAcrossScreens: enabledBool + }); + return enabledBool ? `DESKTOP_WIDGET_SYNC_POSITION_ENABLED: ${instanceId}` : `DESKTOP_WIDGET_SYNC_POSITION_DISABLED: ${instanceId}`; + } + + target: "desktopWidget" + } + + IpcHandler { + function open(): string { + root.workspaceRenameModalLoader.active = true; + if (root.workspaceRenameModalLoader.item) { + const ws = NiriService.workspaces[NiriService.focusedWorkspaceId]; + root.workspaceRenameModalLoader.item.show(ws?.name || ""); + return "WORKSPACE_RENAME_MODAL_OPENED"; + } + return "WORKSPACE_RENAME_MODAL_NOT_FOUND"; + } + + function close(): string { + if (root.workspaceRenameModalLoader.item) { + root.workspaceRenameModalLoader.item.hide(); + return "WORKSPACE_RENAME_MODAL_CLOSED"; + } + return "WORKSPACE_RENAME_MODAL_NOT_FOUND"; + } + + function toggle(): string { + root.workspaceRenameModalLoader.active = true; + if (root.workspaceRenameModalLoader.item) { + if (root.workspaceRenameModalLoader.item.visible) { + root.workspaceRenameModalLoader.item.hide(); + return "WORKSPACE_RENAME_MODAL_CLOSED"; + } + const ws = NiriService.workspaces[NiriService.focusedWorkspaceId]; + root.workspaceRenameModalLoader.item.show(ws?.name || ""); + return "WORKSPACE_RENAME_MODAL_OPENED"; + } + return "WORKSPACE_RENAME_MODAL_NOT_FOUND"; + } + + target: "workspace-rename" + } + + IpcHandler { + function getFocusedWindow() { + const active = ToplevelManager.activeToplevel; + if (!active) + return null; + return { + appId: active.appId || "", + title: active.title || "" + }; + } + + function open(): string { + if (!CompositorService.isNiri) + return "WINDOW_RULES_NIRI_ONLY"; + root.windowRuleModalLoader.active = true; + if (root.windowRuleModalLoader.item) { + root.windowRuleModalLoader.item.show(getFocusedWindow()); + return "WINDOW_RULE_MODAL_OPENED"; + } + return "WINDOW_RULE_MODAL_NOT_FOUND"; + } + + function close(): string { + if (root.windowRuleModalLoader.item) { + root.windowRuleModalLoader.item.hide(); + return "WINDOW_RULE_MODAL_CLOSED"; + } + return "WINDOW_RULE_MODAL_NOT_FOUND"; + } + + function toggle(): string { + if (!CompositorService.isNiri) + return "WINDOW_RULES_NIRI_ONLY"; + root.windowRuleModalLoader.active = true; + if (root.windowRuleModalLoader.item) { + if (root.windowRuleModalLoader.item.visible) { + root.windowRuleModalLoader.item.hide(); + return "WINDOW_RULE_MODAL_CLOSED"; + } + root.windowRuleModalLoader.item.show(getFocusedWindow()); + return "WINDOW_RULE_MODAL_OPENED"; + } + return "WINDOW_RULE_MODAL_NOT_FOUND"; + } + + target: "window-rules" + } + + IpcHandler { + function listProfiles(): string { + const profiles = DisplayConfigState.validatedProfiles; + const activeId = SettingsData.getActiveDisplayProfile(CompositorService.compositor); + const matchedId = DisplayConfigState.matchedProfile; + const lines = []; + + for (const id in profiles) { + const p = profiles[id]; + const flags = []; + if (id === activeId) + flags.push("active"); + if (id === matchedId) + flags.push("matched"); + const flagStr = flags.length > 0 ? " [" + flags.join(",") + "]" : ""; + lines.push(p.name + flagStr + " -> " + JSON.stringify(p.outputSet)); + } + + if (lines.length === 0) + return "No profiles configured"; + return lines.join("\n"); + } + + function setProfile(profileName: string): string { + if (!profileName) + return "ERROR: No profile name specified"; + + if (SettingsData.displayProfileAutoSelect) + return "ERROR: Auto profile selection is enabled. Use toggleAuto first"; + + const profiles = DisplayConfigState.validatedProfiles; + let profileId = null; + + for (const id in profiles) { + if (profiles[id].name === profileName) { + profileId = id; + break; + } + } + + if (!profileId) + return `ERROR: Profile not found: ${profileName}`; + + DisplayConfigState.activateProfile(profileId); + return `PROFILE_SET_SUCCESS: ${profileName}`; + } + + // ! TODO - auto profile switching is buggy on niri and other compositors + function toggleAuto(): string { + return "ERROR: Auto profile selection is temporarily disabled due to compositor bugs"; + } + + function status(): string { + const auto = "off"; // disabled for now + const activeId = SettingsData.getActiveDisplayProfile(CompositorService.compositor); + const matchedId = DisplayConfigState.matchedProfile; + const profiles = DisplayConfigState.validatedProfiles; + const activeName = profiles[activeId]?.name || "none"; + const matchedName = profiles[matchedId]?.name || "none"; + const currentOutputs = JSON.stringify(DisplayConfigState.currentOutputSet); + + return `auto: ${auto}\nactive: ${activeName}\nmatched: ${matchedName}\noutputs: ${currentOutputs}`; + } + + function current(): string { + return JSON.stringify(DisplayConfigState.currentOutputSet); + } + + function refresh(): string { + DisplayConfigState.currentOutputSet = DisplayConfigState.buildCurrentOutputSet(); + DisplayConfigState.validateProfiles(); + return "Refreshed output state"; + } + + target: "outputs" + } + + IpcHandler { + function findTrayItem(itemId: string): var { + if (!itemId) + return null; + + return SystemTray.items.values.find(item => { + const id = item?.id || ""; + const title = item?.tooltipTitle || ""; + const fullKey = title ? `${id}::${title}` : id; + return fullKey === itemId || id === itemId; + }); + } + + function list(): string { + const items = SystemTray.items.values; + if (items.length === 0) + return "No tray items available"; + + return items.map(item => { + const id = item?.id || ""; + const title = item?.tooltipTitle || ""; + const fullKey = title ? `${id}::${title}` : id; + const hasMenu = item?.hasMenu ? " [menu]" : ""; + return fullKey + hasMenu; + }).join("\n"); + } + + function activate(itemId: string): string { + const item = findTrayItem(itemId); + if (!item) + return `ERROR: Tray item not found: ${itemId}`; + + item.activate(); + return `SUCCESS: Activated ${itemId}`; + } + + function status(itemId: string): string { + const item = findTrayItem(itemId); + if (!item) + return `ERROR: Tray item not found: ${itemId}`; + + const id = item?.id || ""; + const title = item?.tooltipTitle || ""; + const hasMenu = item?.hasMenu || false; + const onlyMenu = item?.onlyMenu || false; + + return `id: ${id}\ntitle: ${title}\nhasMenu: ${hasMenu}\nonlyMenu: ${onlyMenu}`; + } + + target: "tray" + } +} |