summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/FocusedApp.qml
diff options
context:
space:
mode:
authorAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
committerAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
commit70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 (patch)
treeab1123d4067c1b086dd6faa7ee4ea643236b565a /raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/FocusedApp.qml
parent5d94c0a7d44a2255b81815a52a7056a94a39842d (diff)
downloadRaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.tar.gz
RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.zip
Replaced file structures for themes in the correct format
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/FocusedApp.qml')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/FocusedApp.qml317
1 files changed, 317 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/FocusedApp.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/FocusedApp.qml
new file mode 100644
index 0000000..a4ad4d2
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankBar/Widgets/FocusedApp.qml
@@ -0,0 +1,317 @@
+import QtQuick
+import QtQuick.Effects
+import Quickshell
+import Quickshell.Wayland
+import Quickshell.Widgets
+import Quickshell.Hyprland
+import qs.Common
+import qs.Modules.Plugins
+import qs.Services
+import qs.Widgets
+
+BasePill {
+ id: root
+
+ property var widgetData: null
+ property bool compactMode: widgetData?.focusedWindowCompactMode !== undefined ? widgetData.focusedWindowCompactMode : SettingsData.focusedWindowCompactMode
+ property int availableWidth: 400
+ readonly property int maxNormalWidth: 456
+ readonly property int maxCompactWidth: 288
+ property Toplevel activeWindow: null
+ property var activeDesktopEntry: null
+ property bool isHovered: mouseArea.containsMouse
+ property bool isAutoHideBar: false
+
+ readonly property real minTooltipY: {
+ if (!parentScreen || !isVerticalOrientation) {
+ return 0;
+ }
+
+ if (isAutoHideBar) {
+ return 0;
+ }
+
+ if (parentScreen.y > 0) {
+ return barThickness + (barSpacing || 4);
+ }
+
+ return 0;
+ }
+
+ function updateActiveWindow() {
+ const active = ToplevelManager.activeToplevel;
+
+ if (!active) {
+ // Only clear if our tracked window is no longer alive
+ if (activeWindow) {
+ const alive = ToplevelManager.toplevels?.values;
+ if (alive && !Array.from(alive).some(t => t === activeWindow))
+ activeWindow = null;
+ }
+ return;
+ }
+
+ if (!parentScreen || CompositorService.filterCurrentDisplay([active], parentScreen?.name)?.length > 0) {
+ activeWindow = active;
+ }
+ // else: active window is on a different screen so keep the previous value
+ }
+
+ Component.onCompleted: {
+ updateActiveWindow();
+ updateDesktopEntry();
+ }
+
+ Connections {
+ target: ToplevelManager
+ function onActiveToplevelChanged() {
+ root.updateActiveWindow();
+ }
+ }
+
+ Connections {
+ target: CompositorService
+ function onToplevelsChanged() {
+ root.updateActiveWindow();
+ }
+ }
+
+ Connections {
+ target: DesktopEntries
+ function onApplicationsChanged() {
+ root.updateDesktopEntry();
+ }
+ }
+
+ Connections {
+ target: root
+ function onActiveWindowChanged() {
+ root.updateDesktopEntry();
+ }
+ }
+
+ Connections {
+ target: SettingsData
+ function onAppIdSubstitutionsChanged() {
+ root.updateDesktopEntry();
+ }
+ }
+
+ function updateDesktopEntry() {
+ if (activeWindow && activeWindow.appId) {
+ const moddedId = Paths.moddedAppId(activeWindow.appId);
+ activeDesktopEntry = DesktopEntries.heuristicLookup(moddedId);
+ } else {
+ activeDesktopEntry = null;
+ }
+ }
+ readonly property bool hasWindowsOnCurrentWorkspace: {
+ if (CompositorService.isNiri) {
+ let currentWorkspaceId = null;
+ for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
+ const ws = NiriService.allWorkspaces[i];
+ if (ws.is_focused) {
+ currentWorkspaceId = ws.id;
+ break;
+ }
+ }
+
+ if (!currentWorkspaceId) {
+ return false;
+ }
+
+ const workspaceWindows = NiriService.windows.filter(w => w.workspace_id === currentWorkspaceId);
+ return workspaceWindows.length > 0 && activeWindow && (activeWindow.title || activeWindow.appId);
+ }
+
+ if (CompositorService.isHyprland) {
+ if (!Hyprland.focusedWorkspace || !activeWindow || !(activeWindow.title || activeWindow.appId)) {
+ return false;
+ }
+
+ try {
+ if (!Hyprland.toplevels)
+ return false;
+ const hyprlandToplevels = Array.from(Hyprland.toplevels.values);
+ const activeHyprToplevel = hyprlandToplevels.find(t => t?.wayland === activeWindow);
+
+ if (!activeHyprToplevel || !activeHyprToplevel.workspace) {
+ return false;
+ }
+
+ return activeHyprToplevel.workspace.id === Hyprland.focusedWorkspace.id;
+ } catch (e) {
+ return false;
+ }
+ }
+
+ return activeWindow && (activeWindow.title || activeWindow.appId);
+ }
+
+ width: hasWindowsOnCurrentWorkspace ? (isVerticalOrientation ? barThickness : visualWidth) : 0
+ height: hasWindowsOnCurrentWorkspace ? (isVerticalOrientation ? visualHeight : barThickness) : 0
+ visible: hasWindowsOnCurrentWorkspace
+
+ content: Component {
+ Item {
+ implicitWidth: {
+ if (!root.hasWindowsOnCurrentWorkspace)
+ return 0;
+ if (root.isVerticalOrientation)
+ return root.widgetThickness - root.horizontalPadding * 2;
+ const baseWidth = contentRow.implicitWidth;
+ return compactMode ? Math.min(baseWidth, maxCompactWidth - root.horizontalPadding * 2) : Math.min(baseWidth, maxNormalWidth - root.horizontalPadding * 2);
+ }
+ implicitHeight: root.widgetThickness - root.horizontalPadding * 2
+ clip: false
+
+ IconImage {
+ id: appIcon
+ anchors.centerIn: parent
+ width: 18
+ height: 18
+ visible: root.isVerticalOrientation && activeWindow && status === Image.Ready
+ source: {
+ if (!activeWindow || !activeWindow.appId)
+ return "";
+ return Paths.getAppIcon(activeWindow.appId, activeDesktopEntry);
+ }
+ smooth: true
+ mipmap: true
+ asynchronous: true
+ layer.enabled: activeWindow && (activeWindow.appId === "org.quickshell" || activeWindow.appId === "com.danklinux.dms")
+ layer.smooth: true
+ layer.mipmap: true
+ layer.effect: MultiEffect {
+ saturation: 0
+ colorization: 1
+ colorizationColor: Theme.primary
+ }
+ }
+
+ DankIcon {
+ anchors.centerIn: parent
+ size: 18
+ name: "sports_esports"
+ color: Theme.widgetTextColor
+ visible: root.isVerticalOrientation && activeWindow && activeWindow.appId && appIcon.status !== Image.Ready && Paths.isSteamApp(activeWindow.appId)
+ }
+
+ Text {
+ anchors.centerIn: parent
+ visible: root.isVerticalOrientation && activeWindow && activeWindow.appId && appIcon.status !== Image.Ready && !Paths.isSteamApp(activeWindow.appId)
+ text: {
+ if (!activeWindow || !activeWindow.appId)
+ return "?";
+ const appName = Paths.getAppName(activeWindow.appId, activeDesktopEntry);
+ return appName.charAt(0).toUpperCase();
+ }
+ font.pixelSize: 10
+ color: Theme.widgetTextColor
+ }
+
+ Row {
+ id: contentRow
+ anchors.centerIn: parent
+ spacing: Theme.spacingS
+ visible: !root.isVerticalOrientation
+
+ StyledText {
+ id: appText
+ text: {
+ if (!activeWindow || !activeWindow.appId)
+ return "";
+ return Paths.getAppName(activeWindow.appId, activeDesktopEntry);
+ }
+ font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
+ color: Theme.widgetTextColor
+ anchors.verticalCenter: parent.verticalCenter
+ elide: Text.ElideRight
+ maximumLineCount: 1
+ width: Math.min(implicitWidth, compactMode ? 80 : 180)
+ visible: !compactMode && text.length > 0
+ }
+
+ StyledText {
+ text: "•"
+ font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
+ color: Theme.outlineButton
+ anchors.verticalCenter: parent.verticalCenter
+ visible: !compactMode && appText.text && titleText.text
+ }
+
+ StyledText {
+ id: titleText
+ text: {
+ const title = activeWindow && activeWindow.title ? activeWindow.title : "";
+ const appName = appText.text;
+
+ if (compactMode) {
+ if (!title || title === appName)
+ return title || appName;
+ if (title.endsWith(appName))
+ return title.substring(0, title.length - appName.length).replace(/ (-|—) $/, "") || appName;
+ return title;
+ }
+
+ if (!title || !appName)
+ return title;
+
+ if (title.endsWith(appName))
+ return title.substring(0, title.length - appName.length).replace(/ (-|—) $/, "");
+
+ return title;
+ }
+ font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
+ color: Theme.widgetTextColor
+ anchors.verticalCenter: parent.verticalCenter
+ elide: Text.ElideRight
+ maximumLineCount: 1
+ width: Math.min(implicitWidth, compactMode ? 280 : 250)
+ visible: text.length > 0
+ }
+ }
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: root.isVerticalOrientation
+ acceptedButtons: Qt.NoButton
+ onEntered: {
+ if (root.isVerticalOrientation && activeWindow && activeWindow.appId && root.parentScreen) {
+ tooltipLoader.active = true;
+ if (tooltipLoader.item) {
+ const globalPos = mapToGlobal(width / 2, height / 2);
+ const currentScreen = root.parentScreen;
+ const screenX = currentScreen ? currentScreen.x : 0;
+ const screenY = currentScreen ? currentScreen.y : 0;
+ const relativeY = globalPos.y - screenY;
+ // Add minTooltipY offset to account for top bar
+ const adjustedY = relativeY + root.minTooltipY;
+ const tooltipX = root.axis?.edge === "left" ? (Theme.barHeight + (barConfig?.spacing ?? 4) + Theme.spacingXS) : (currentScreen.width - Theme.barHeight - (barConfig?.spacing ?? 4) - Theme.spacingXS);
+
+ const appName = Paths.getAppName(activeWindow.appId, activeDesktopEntry);
+ const title = activeWindow.title || "";
+ const tooltipText = appName + (title ? " • " + title : "");
+
+ const isLeft = root.axis?.edge === "left";
+ tooltipLoader.item.show(tooltipText, screenX + tooltipX, adjustedY, currentScreen, isLeft, !isLeft);
+ }
+ }
+ }
+ onExited: {
+ if (tooltipLoader.item) {
+ tooltipLoader.item.hide();
+ }
+ tooltipLoader.active = false;
+ }
+ }
+
+ Loader {
+ id: tooltipLoader
+ active: false
+ sourceComponent: DankTooltip {}
+ }
+}