feat: dashboard show on hover, media and weather tabs added

This commit is contained in:
2026-09-30 14:22:22 +02:00
parent d259c6ffbe
commit 2c90339c77
97 changed files with 4480 additions and 990 deletions
+5 -10
View File
@@ -3,28 +3,23 @@ pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import ZShell.Internal
import qs.Components
Item {
id: root
readonly property alias content: contentLoader.item
readonly property PersistentProperties drawingState: PersistentProperties {
property color penColor: "white"
property int penWidth: 4
reloadableId: "drawingState"
}
required property PersistentProperties visibilities
required property ScreenState screenState
Loader {
id: contentLoader
active: root.visibilities.isDrawing
active: root.screenState.isDrawing
anchors.fill: parent
sourceComponent: StrokeCanvas {
penColor: root.drawingState.penColor
penWidth: root.drawingState.penWidth
penColor: root.screenState.penColor
penWidth: root.screenState.penWidth
}
}
}
+75 -55
View File
@@ -19,7 +19,7 @@ Item {
required property ShellScreen screen
property bool singleGestureTriggered: false
property bool utilitiesShortcutActive
required property PersistentProperties visibilities
required property ScreenState screenState
function inBottomPanel(panel: Item, x: real, y: real): bool {
const panelHeight = panel.height * (1 - (panel.offsetScale ?? 0));
@@ -63,7 +63,7 @@ Item {
cursorShape: (active && centroid.pressPosition.y < root.bar.implicitHeight) ? Qt.ClosedHandCursor : undefined
dragThreshold: 0
enabled: !root.visibilities.isDrawing
enabled: !root.screenState.isDrawing
grabPermissions: PointerHandler.CanTakeOverFromHandlersOfSameType | PointerHandler.ApprovesTakeOverByAnything
maximumPointCount: 1
minimumPointCount: 1
@@ -76,48 +76,60 @@ Item {
onCentroidChanged: {
const x = centroid.position.x;
const y = centroid.position.y;
const dragX = x - centroid.pressPosition.x;
const dragY = y - centroid.pressPosition.y;
const pressX = centroid.pressPosition.x;
const pressY = centroid.pressPosition.y;
const dragX = x - pressX;
const dragY = y - pressY;
if (centroid.pressPosition.y >= root.screen.height - Config.bar.border && centroid.pressPosition.x > root.screen.width / 5 && dragY < -Config.launcher.dragThreshold)
root.visibilities.launcher = true;
if (pressY >= root.screen.height - Config.bar.border && pressX > root.screen.width / 5 && dragY < -Config.launcher.dragThreshold)
root.screenState.launcher = true;
if (root.singleGestureTriggered)
return;
if (root.geometry.insetTop(root.borderThickness) > centroid.pressPosition.y) {
if (dragY > 20) {
root.visibilities.settings = true;
root.singleGestureTriggered = true;
} else if (dragY < -20) {
root.visibilities.settings = false;
root.singleGestureTriggered = true;
}
}
// if (root.geometry.insetTop(root.borderThickness) > pressY) {
// if (dragY > 20) {
// root.screenState.settings = true;
// root.singleGestureTriggered = true;
// } else if (dragY < -20) {
// root.screenState.settings = false;
// root.singleGestureTriggered = true;
// }
// }
if (centroid.pressPosition.y > root.screen.height - root.geometry.insetBottom(root.borderThickness) && centroid.pressPosition.x < root.screen.width / 5 && dragY < -50)
root.visibilities.clipboard = true;
if (pressY > root.screen.height - root.geometry.insetBottom(root.borderThickness) && pressX < root.screen.width / 5 && dragY < -50)
root.screenState.clipboard = true;
if (!Config.dock.hoverToReveal && centroid.pressPosition.y > root.screen.height - root.geometry.insetTop(root.borderThickness) && centroid.pressPosition.x > root.screen.width / 5 && !root.visibilities.launcher)
if (!Config.dock.hoverToReveal && pressY > root.screen.height - root.geometry.insetTop(root.borderThickness) && pressX > root.screen.width / 5 && !root.screenState.launcher)
if (dragY < -10) {
root.visibilities.dock = true;
root.screenState.dock = true;
root.singleGestureTriggered = true;
}
if (centroid.pressPosition.x > root.screen.width - Config.bar.border && centroid.pressPosition.y < (root.screen.height / 2) && dragX < -Config.sidebar.dragThreshold) {
root.visibilities.sidebar = true;
if (pressX > root.screen.width - Config.bar.border && pressY < (root.screen.height / 2) && dragX < -Config.sidebar.dragThreshold) {
root.screenState.sidebar = true;
root.singleGestureTriggered = true;
}
if (centroid.pressPosition.x >= root.screen.width - Config.bar.border && centroid.pressPosition.y > (root.screen.height / 2) && dragX < -20) {
if (pressX >= root.screen.width - Config.bar.border && pressY > (root.screen.height / 2) && dragX < -20) {
Hypr.dispatch(`hl.dsp.focus({ workspace = 'r+1', on_current_monitor = true })`);
root.singleGestureTriggered = true;
}
if (centroid.pressPosition.x <= Config.bar.border && dragX > 20) {
if (pressX <= Config.bar.border && dragX > 20) {
Hypr.dispatch(`hl.dsp.focus({ workspace = 'r-1', on_current_monitor = true })`);
root.singleGestureTriggered = true;
}
if (root.inTopPanel(root.panels.dashboardWrapper, pressX, pressY) && root.withinPanelWidth(root.panels.dashboardWrapper, x, y)) {
if (dragY > Config.dashboard.dragThreshold) {
root.screenState.dashboard = true;
root.singleGestureTriggered = true;
} else if (dragY < -Config.dashboard.dragThreshold) {
root.screenState.dashboard = false;
root.singleGestureTriggered = true;
}
}
}
}
@@ -127,7 +139,7 @@ Item {
property bool setInitialPoint: false
acceptedButtons: Qt.LeftButton | Qt.RightButton
enabled: root.visibilities.isDrawing && (!root.inLeftPanel(root.panels.drawing, hoverHandler.point.position.x, hoverHandler.point.position.y) || !root.panels.drawing.expanded)
enabled: root.screenState.isDrawing && (!root.inLeftPanel(root.panels.drawing, hoverHandler.point.position.x, hoverHandler.point.position.y) || !root.panels.drawing.expanded)
onActiveChanged: {
if (!active) {
@@ -178,12 +190,12 @@ Item {
HoverHandler {
id: hoverHandler
cursorShape: root.visibilities.isDrawing && !root.inLeftPanel(root.panels.drawing, point.position.x, point.position.y) ? Qt.BlankCursor : undefined
cursorShape: root.screenState.isDrawing && !root.inLeftPanel(root.panels.drawing, point.position.x, point.position.y) ? Qt.BlankCursor : undefined
onHoveredChanged: {
if (!hovered) {
if (!root.osdShortcutActive) {
root.visibilities.osd = false;
root.screenState.osd = false;
root.panels.osd.hovered = false;
}
@@ -193,13 +205,16 @@ Item {
if (Config.bar.autoHide || root.bar.fullscreen)
root.bar.isHovered = false;
if (root.screenState.dashboard && Config.dashboard.showOnHover)
root.screenState.dashboard = false;
}
}
onPointChanged: {
const x = point.position.x;
const y = point.position.y;
if (root.visibilities.isDrawing) {
if (root.screenState.isDrawing) {
if (root.inLeftPanel(root.panels.drawing, x, y) && !(drawingHandler.point.pressedButtons & Qt.LeftButton)) {
root.panels.drawing.expand();
root.drawing.content.hideHover();
@@ -210,7 +225,7 @@ Item {
return;
}
if (!root.visibilities.bar && Config.bar.autoHide && root.geometry.barContains(x, y, true))
if (!root.screenState.bar && Config.bar.autoHide && root.geometry.barContains(x, y, true))
root.bar.isHovered = true;
if (root.bar.fullscreen && !root.bar.isHovered)
@@ -228,7 +243,7 @@ Item {
const showOsd = outOfSidebar && root.inRightPanel(root.panels.osdWrapper, x, y);
if (!root.osdShortcutActive) {
root.visibilities.osd = showOsd;
root.screenState.osd = showOsd;
root.panels.osd.hovered = showOsd;
} else if (showOsd) {
root.osdShortcutActive = false;
@@ -236,8 +251,13 @@ Item {
}
}
if (Config.dock.enable && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y))
root.visibilities.dock = true;
if (Config.dock.enable && Config.dock.hoverToReveal && !root.screenState.dock && !root.screenState.launcher && root.inBottomPanel(root.panels.dock, x, y))
root.screenState.dock = true;
const inDashboard = root.inTopPanel(root.panels.dashboardWrapper, x, y);
if (Config.dashboard.showOnHover)
root.screenState.dashboard = inDashboard;
if (root.geometry.barContains(x, y))
root.bar.checkPopout(root.geometry.axisPos(x, y));
@@ -246,16 +266,16 @@ Item {
Connections {
function onDashboardChanged() {
if (root.visibilities.dashboard) {
if (root.screenState.dashboard) {
const inDashboardArea = root.inTopPanel(root.panels.dashboard, root.mouseX, root.mouseY);
if (!inDashboardArea) {
root.dashboardShortcutActive = true;
}
if (root.panels.launcher.x + root.panels.launcher.width > root.panels.dashboardWrapper.x)
root.visibilities.launcher = false;
root.screenState.launcher = false;
root.visibilities.settings = false;
root.visibilities.sidebar = false;
root.screenState.settings = false;
root.screenState.sidebar = false;
root.popouts.hasCurrent = false;
} else {
root.dashboardShortcutActive = false;
@@ -263,12 +283,12 @@ Item {
}
function onIsDrawingChanged() {
if (!root.visibilities.isDrawing)
if (!root.screenState.isDrawing)
root.drawing.clear();
}
function onLauncherChanged() {
if (!root.visibilities.launcher) {
if (!root.screenState.launcher) {
root.dashboardShortcutActive = false;
root.osdShortcutActive = false;
root.utilitiesShortcutActive = false;
@@ -276,23 +296,23 @@ Item {
const inOsdArea = root.inRightPanel(root.panels.osd, root.mouseX, root.mouseY);
if (!inOsdArea) {
root.visibilities.osd = false;
root.screenState.osd = false;
root.panels.osd.hovered = false;
}
}
if (root.visibilities.launcher) {
if (root.screenState.launcher) {
if (root.panels.dashboardWrapper.x < root.panels.launcher.x + root.panels.launcher.width) {
root.visibilities.dashboard = false;
root.screenState.dashboard = false;
}
root.visibilities.dock = false;
root.visibilities.settings = false;
root.screenState.dock = false;
root.screenState.settings = false;
}
}
function onOsdChanged() {
if (root.visibilities.osd) {
if (root.screenState.osd) {
const inOsdArea = root.inRightPanel(root.panels.osd, root.mouseX, root.mouseY);
if (!inOsdArea) {
root.osdShortcutActive = true;
@@ -303,32 +323,32 @@ Item {
}
function onResourcesChanged() {
if (root.visibilities.resources && (root.popouts.currentName.startsWith("audio") || root.popouts.currentName.startsWith("updates"))) {
if (root.screenState.resources && (root.popouts.currentName.startsWith("audio") || root.popouts.currentName.startsWith("updates"))) {
root.popouts.hasCurrent = false;
}
if (root.visibilities.resources)
root.visibilities.settings = false;
if (root.screenState.resources)
root.screenState.settings = false;
}
function onSettingsChanged() {
if (root.visibilities.settings) {
root.visibilities.resources = false;
root.visibilities.dashboard = false;
root.visibilities.sidebar = false;
if (root.screenState.settings) {
root.screenState.resources = false;
root.screenState.dashboard = false;
root.screenState.sidebar = false;
root.panels.popouts.hasCurrent = false;
root.visibilities.launcher = false;
root.screenState.launcher = false;
}
}
function onSidebarChanged() {
if (root.visibilities.sidebar) {
root.visibilities.dashboard = false;
root.visibilities.settings = false;
if (root.screenState.sidebar) {
root.screenState.dashboard = false;
root.screenState.settings = false;
root.popouts.hasCurrent = false;
}
}
target: root.visibilities
target: root.screenState
}
}
+16 -19
View File
@@ -42,7 +42,7 @@ Item {
readonly property alias sidebar: sidebar
readonly property alias toasts: toasts
readonly property alias utilities: utilities
required property PersistentProperties visibilities
required property ScreenState screenState
anchors.bottomMargin: geometry.insetBottom(borderThickness)
anchors.fill: parent
@@ -64,7 +64,7 @@ Item {
id: resources
position: root.geometry.position
visibilities: root.visibilities
screenState: root.screenState
}
}
@@ -85,7 +85,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
screen: root.screen
sidebarOrSessionVisible: sidebar.visible
visibilities: root.visibilities
screenState: root.screenState
}
}
@@ -96,7 +96,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
drawing: root.drawingItem
screen: root.screen
visibilities: root.visibilities
screenState: root.screenState
}
Popouts.ClipWrapper {
@@ -122,7 +122,7 @@ Item {
anchors.top: parent.top
panels: root
sidebarPanel: sidebar
visibilities: root.visibilities
screenState: root.screenState
}
Launcher.Wrapper {
@@ -132,7 +132,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
panels: root
screen: root.screen
visibilities: root.visibilities
screenState: root.screenState
}
Utils.Wrapper {
@@ -142,7 +142,7 @@ Item {
anchors.right: parent.right
popouts: popouts
sidebar: sidebar
visibilities: root.visibilities
screenState: root.screenState
}
Item {
@@ -150,13 +150,11 @@ Item {
property real offsetScale: dashboard.shouldBeActive ? 0 : 1
anchors.bottom: root.geometry.barOnLeft || root.geometry.barOnBottom ? parent.bottom : undefined
anchors.left: root.geometry.barOnLeft ? parent.left : undefined
anchors.right: root.geometry.barOnLeft ? undefined : parent.right
anchors.top: root.geometry.barOnBottom || root.geometry.barOnLeft ? undefined : parent.top
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
clip: true
implicitHeight: root.geometry.horizontal ? dashboard.implicitHeight * (1 - offsetScale) : dashboard.implicitHeight
implicitWidth: root.geometry.horizontal ? dashboard.implicitWidth : dashboard.implicitWidth * (1 - offsetScale)
implicitHeight: dashboard.implicitHeight * (1 - offsetScale)
implicitWidth: dashboard.implicitWidth
Behavior on offsetScale {
Anim {
@@ -169,8 +167,7 @@ Item {
id: dashboard
offsetScale: dashboardWrapper.offsetScale
position: root.geometry.position
visibilities: root.visibilities
screenState: root.screenState
}
}
@@ -181,7 +178,7 @@ Item {
anchors.right: parent.right
anchors.top: notifications.bottom
panels: root
visibilities: root.visibilities
screenState: root.screenState
}
Item {
@@ -197,7 +194,7 @@ Item {
anchors.verticalCenterOffset: (-implicitHeight - 5 - ((root.height - implicitHeight) / 2)) * offsetScale
panels: root
screen: root.screen
visibilities: root.visibilities
screenState: root.screenState
}
}
@@ -208,7 +205,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
panels: root
screen: root.screen
visibilities: root.visibilities
screenState: root.screenState
}
Clipboard.Wrapper {
@@ -217,6 +214,6 @@ Item {
anchors.bottom: parent.bottom
anchors.left: parent.left
screen: root.screen
visibilities: root.visibilities
screenState: root.screenState
}
}
+36 -53
View File
@@ -50,16 +50,17 @@ CustomWindow {
readonly property alias menuRegion: regions.menuPopoutRegion
readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen)
property var root: Quickshell.shellDir
readonly property ScreenState screenState: ShellState.forScreen(screen)
readonly property real sdfBorderOffset: 2 * fsTransitionProg
readonly property real shadowOpacity: 0.7 * (1 - (bar.isHovered ? 0 : fsTransitionProg))
property color surfaceColor: Colors.tPalette.m3surface
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: visibilities.launcher || visibilities.settings ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
WlrLayershell.keyboardFocus: screenState.launcher || screenState.settings || screenState.sidebar ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
WlrLayershell.layer: (fsTransitionProg > 0 && Config.general.showOverFullscreen) || (hasSpecialWorkspace && hasFullscreenOnNormalWs) ? WlrLayer.Overlay : WlrLayer.Top
color: "transparent"
contentItem.focus: true
mask: visibilities.isDrawing ? null : (hasFullscreen && !bar.isHovered ? emptyRegion : regions)
mask: screenState.isDrawing ? null : (hasFullscreen && !bar.isHovered ? emptyRegion : regions)
name: "Bar"
Behavior on fsTransitionProg {
@@ -73,26 +74,26 @@ CustomWindow {
contentItem.Keys.onEscapePressed: {
if (Config.bar.autoHide)
visibilities.bar = false;
visibilities.launcher = false;
visibilities.sidebar = false;
visibilities.dashboard = false;
visibilities.osd = false;
visibilities.settings = false;
visibilities.resources = false;
visibilities.dock = false;
visibilities.clipboard = false;
screenState.bar = false;
screenState.launcher = false;
screenState.sidebar = false;
screenState.dashboard = false;
screenState.osd = false;
screenState.settings = false;
screenState.resources = false;
screenState.dock = false;
screenState.clipboard = false;
panels.popouts.hasCurrent = false;
}
onHasFullscreenChanged: {
visibilities.launcher = false;
visibilities.sidebar = false;
visibilities.dashboard = false;
visibilities.osd = false;
visibilities.settings = false;
visibilities.resources = false;
visibilities.clipboard = false;
visibilities.dock = false;
screenState.launcher = false;
screenState.sidebar = false;
screenState.dashboard = false;
screenState.osd = false;
screenState.settings = false;
screenState.resources = false;
screenState.clipboard = false;
screenState.dock = false;
panels.popouts.hasCurrent = false;
}
@@ -144,44 +145,26 @@ CustomWindow {
HyprlandFocusGrab {
id: focusGrab
active: visibilities.dock || visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || visibilities.clipboard || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu") && (!Config.bar.tray.showOnHover || (panels.popouts.current as StackView)?.depth > 1))
active: root.screenState.dock || root.screenState.resources || root.screenState.launcher || root.screenState.sidebar || (!Config.dashboard.showOnHover && root.screenState.dashboard) || root.screenState.settings || root.screenState.clipboard || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu") && (!Config.bar.tray.showOnHover || (panels.popouts.current as StackView)?.depth > 1))
windows: [root]
onCleared: {
visibilities.launcher = false;
visibilities.sidebar = false;
visibilities.dashboard = false;
visibilities.osd = false;
visibilities.settings = false;
visibilities.resources = false;
visibilities.clipboard = false;
visibilities.dock = false;
root.screenState.launcher = false;
root.screenState.sidebar = false;
root.screenState.dashboard = false;
root.screenState.osd = false;
root.screenState.settings = false;
root.screenState.resources = false;
root.screenState.clipboard = false;
root.screenState.dock = false;
panels.popouts.hasCurrent = false;
}
}
PersistentProperties {
id: visibilities
property bool bar
property bool clipboard
property bool dashboard
property bool dock
property bool isDrawing
property bool launcher
property bool notif: NotifServer.popups.length > 0
property bool osd
property bool resources
property bool settings
property bool sidebar
Component.onCompleted: Visibilities.load(root.screen, this)
}
Binding {
property: "bar"
target: visibilities
value: visibilities.sidebar || visibilities.dashboard || visibilities.osd || (!Config.bar.hideWhenNotif && visibilities.notif) || visibilities.resources || visibilities.settings || bar.isHovered
target: root.screenState
value: root.screenState.sidebar || root.screenState.dashboard || root.screenState.osd || (!Config.bar.hideWhenNotif && NotifServer.popups.length > 0) || root.screenState.resources || root.screenState.settings || bar.isHovered
when: Config.bar.autoHide
}
@@ -348,7 +331,7 @@ CustomWindow {
anchors.fill: parent
layer.enabled: true
visibilities: visibilities
screenState: root.screenState
z: 2
layer.effect: MultiEffect {
@@ -389,7 +372,7 @@ CustomWindow {
panels: panels
popouts: panels.popouts
screen: root.screen
visibilities: visibilities
screenState: root.screenState
Panels {
id: panels
@@ -399,7 +382,7 @@ CustomWindow {
drawingItem: drawing
geometry: geometry
screen: root.screen
visibilities: visibilities
screenState: root.screenState
clipboard.transform: Matrix4x4 {
matrix: clipboardBg.deformMatrix
@@ -442,14 +425,14 @@ CustomWindow {
anchors.bottom: geometry.barOnBottom ? parent.bottom : undefined
anchors.left: parent.left
anchors.top: geometry.barOnBottom ? undefined : parent.top
enabled: !visibilities.isDrawing
enabled: !screenState.isDrawing
fullscreen: root.hasFullscreen
height: geometry.horizontal ? implicitHeight : parent.height
popouts: panels.popouts
popoutsWrapper: panels.popoutsWrapper
position: geometry.position
screen: root.screen
visibilities: visibilities
screenState: root.screenState
width: geometry.horizontal ? parent.width : implicitWidth
}
}