1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00

dankbar: add generic bar widget IPC for popouts

fixes #750
This commit is contained in:
bbedward
2025-11-24 19:52:26 -05:00
parent d341a5a60b
commit fa98a27c90
5 changed files with 278 additions and 27 deletions

View File

@@ -563,4 +563,42 @@ Item {
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 list(): string {
const widgets = BarWidgetService.getRegisteredWidgetIds();
if (widgets.length === 0)
return "No widgets registered";
return widgets.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";
}
target: "widget"
}
}

View File

@@ -155,35 +155,56 @@ Loader {
}
onLoaded: {
if (item) {
contentItemReady(item);
if (axis && "isVertical" in item) {
try {
item.isVertical = axis.isVertical;
} catch (e) {}
}
if (!item)
return;
if (item.pluginService !== undefined) {
var parts = widgetId.split(":");
var pluginId = parts[0];
var variantId = parts.length > 1 ? parts[1] : null;
contentItemReady(item);
if (item.pluginId !== undefined) {
item.pluginId = pluginId;
}
if (item.variantId !== undefined) {
item.variantId = variantId;
}
if (item.variantData !== undefined && variantId) {
item.variantData = PluginService.getPluginVariantData(pluginId, variantId);
}
item.pluginService = PluginService;
}
if (item.popoutService !== undefined) {
item.popoutService = PopoutService;
}
if (axis && "isVertical" in item) {
try {
item.isVertical = axis.isVertical;
} catch (e) {}
}
if (item.pluginService !== undefined) {
var parts = widgetId.split(":");
var pluginId = parts[0];
var variantId = parts.length > 1 ? parts[1] : null;
if (item.pluginId !== undefined)
item.pluginId = pluginId;
if (item.variantId !== undefined)
item.variantId = variantId;
if (item.variantData !== undefined && variantId)
item.variantData = PluginService.getPluginVariantData(pluginId, variantId);
item.pluginService = PluginService;
}
if (item.popoutService !== undefined)
item.popoutService = PopoutService;
registerWidgetIfEligible();
}
Component.onDestruction: {
unregisterWidget();
}
function registerWidgetIfEligible() {
if (!item || !widgetId || !parentScreen?.name)
return;
const hasPopout = item.popoutTarget !== undefined || typeof item.triggerPopout === "function" || typeof item.clicked === "function";
if (!hasPopout)
return;
BarWidgetService.registerWidget(widgetId, parentScreen.name, item);
}
function unregisterWidget() {
if (!widgetId || !parentScreen?.name)
return;
BarWidgetService.unregisterWidget(widgetId, parentScreen.name);
}
function getWidgetComponent(widgetId, components) {

View File

@@ -186,6 +186,32 @@ Item {
}
}
function triggerPopout() {
if (pillClickAction) {
if (pillClickAction.length === 0) {
pillClickAction();
return;
}
const pill = isVertical ? verticalPill : horizontalPill;
const globalPos = pill.mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, pill.width);
pillClickAction(pos.x, pos.y, pos.width, section, currentScreen);
return;
}
if (!hasPopout)
return;
const pill = isVertical ? verticalPill : horizontalPill;
const globalPos = pill.visualContent.mapToGlobal(0, 0);
const currentScreen = parentScreen || Screen;
const barPosition = axis?.edge === "left" ? 2 : (axis?.edge === "right" ? 3 : (axis?.edge === "top" ? 0 : 1));
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, pill.visualWidth, barSpacing, barPosition, barConfig);
pluginPopout.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen, barPosition, barThickness, barSpacing, barConfig);
pluginPopout.toggle();
}
PluginPopout {
id: pluginPopout
contentWidth: root.popoutWidth

View File

@@ -55,7 +55,7 @@ Column {
cursorShape: Qt.PointingHandCursor
onPressed: {
if (root.closePopout) {
root.closePopout()
root.closePopout();
}
}
}

View File

@@ -0,0 +1,166 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Hyprland
import Quickshell.I3
Singleton {
id: root
property var widgetRegistry: ({})
property var dankBarRepeater: null
signal widgetRegistered(string widgetId, string screenName)
signal widgetUnregistered(string widgetId, string screenName)
function registerWidget(widgetId, screenName, widgetRef) {
if (!widgetId || !screenName || !widgetRef)
return;
if (!widgetRegistry[widgetId])
widgetRegistry[widgetId] = {};
widgetRegistry[widgetId][screenName] = widgetRef;
widgetRegistered(widgetId, screenName);
}
function unregisterWidget(widgetId, screenName) {
if (!widgetId || !screenName)
return;
if (!widgetRegistry[widgetId])
return;
delete widgetRegistry[widgetId][screenName];
if (Object.keys(widgetRegistry[widgetId]).length === 0)
delete widgetRegistry[widgetId];
widgetUnregistered(widgetId, screenName);
}
function getWidget(widgetId, screenName) {
if (!widgetRegistry[widgetId])
return null;
if (screenName)
return widgetRegistry[widgetId][screenName] || null;
const screens = Object.keys(widgetRegistry[widgetId]);
return screens.length > 0 ? widgetRegistry[widgetId][screens[0]] : null;
}
function getWidgetOnFocusedScreen(widgetId) {
if (!widgetRegistry[widgetId])
return null;
const focusedScreen = getFocusedScreenName();
if (focusedScreen && widgetRegistry[widgetId][focusedScreen])
return widgetRegistry[widgetId][focusedScreen];
const screens = Object.keys(widgetRegistry[widgetId]);
return screens.length > 0 ? widgetRegistry[widgetId][screens[0]] : null;
}
function getFocusedScreenName() {
if (CompositorService.isHyprland && Hyprland.focusedWorkspace?.monitor)
return Hyprland.focusedWorkspace.monitor.name;
if (CompositorService.isNiri && NiriService.currentOutput)
return NiriService.currentOutput;
if (CompositorService.isSway) {
const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true);
return focusedWs?.monitor?.name || "";
}
return "";
}
function getRegisteredWidgetIds() {
return Object.keys(widgetRegistry);
}
function hasWidget(widgetId) {
return widgetRegistry[widgetId] && Object.keys(widgetRegistry[widgetId]).length > 0;
}
function triggerWidgetPopout(widgetId) {
const widget = getWidgetOnFocusedScreen(widgetId);
if (!widget)
return false;
if (typeof widget.triggerPopout === "function") {
widget.triggerPopout();
return true;
}
const signalMap = {
"battery": "toggleBatteryPopup",
"vpn": "toggleVpnPopup",
"layout": "toggleLayoutPopup",
"clock": "clockClicked",
"cpuUsage": "cpuClicked",
"memUsage": "ramClicked",
"cpuTemp": "cpuTempClicked",
"gpuTemp": "gpuTempClicked"
};
const signalName = signalMap[widgetId];
if (signalName && typeof widget[signalName] === "function") {
widget[signalName]();
return true;
}
if (typeof widget.clicked === "function") {
widget.clicked();
return true;
}
if (widget.popoutTarget?.toggle) {
widget.popoutTarget.toggle();
return true;
}
return false;
}
function getBarWindowForScreen(screenName) {
if (!dankBarRepeater)
return null;
for (var i = 0; i < dankBarRepeater.count; i++) {
const loader = dankBarRepeater.itemAt(i);
if (!loader?.item)
continue;
const barItem = loader.item;
if (!barItem.barVariants?.instances)
continue;
for (var j = 0; j < barItem.barVariants.instances.length; j++) {
const barInstance = barItem.barVariants.instances[j];
if (barInstance.modelData?.name === screenName)
return barInstance;
}
}
return null;
}
function getBarWindowOnFocusedScreen() {
const focusedScreen = getFocusedScreenName();
if (!focusedScreen)
return getFirstBarWindow();
return getBarWindowForScreen(focusedScreen) || getFirstBarWindow();
}
function getFirstBarWindow() {
if (!dankBarRepeater || dankBarRepeater.count === 0)
return null;
const loader = dankBarRepeater.itemAt(0);
if (!loader?.item)
return null;
const barItem = loader.item;
if (!barItem.barVariants?.instances || barItem.barVariants.instances.length === 0)
return null;
return barItem.barVariants.instances[0];
}
}