sidebars: open by hovering (or clicking) corners

This commit is contained in:
end-4
2025-08-26 10:51:40 +07:00
parent 63b7a3a36c
commit e7ffd2455a
4 changed files with 123 additions and 10 deletions
@@ -293,6 +293,13 @@ Singleton {
property string username: "[unset]" property string username: "[unset]"
} }
} }
property JsonObject cornerOpen: JsonObject {
property bool enable: true
property bool clickless: true
property real cornerRegionWidth: 30
property real cornerRegionHeight: 2
property bool visualize: false
}
} }
property JsonObject time: JsonObject { property JsonObject time: JsonObject {
@@ -13,8 +13,18 @@ Item {
implicitWidth: implicitSize implicitWidth: implicitSize
implicitHeight: implicitSize implicitHeight: implicitSize
property bool isTopLeft: corner === RoundCorner.CornerEnum.TopLeft
property bool isBottomLeft: corner === RoundCorner.CornerEnum.BottomLeft
property bool isTopRight: corner === RoundCorner.CornerEnum.TopRight
property bool isBottomRight: corner === RoundCorner.CornerEnum.BottomRight
Shape { Shape {
anchors.fill: parent anchors {
top: (isTopLeft || isTopRight) ? parent.top : undefined
bottom: (isBottomLeft || isBottomRight) ? parent.bottom : undefined
left: (isTopLeft || isBottomLeft) ? parent.left : undefined
right: (isTopRight || isBottomRight) ? parent.right : undefined
}
layer.enabled: true layer.enabled: true
layer.smooth: true layer.smooth: true
preferredRendererType: Shape.CurveRenderer preferredRendererType: Shape.CurveRenderer
@@ -1,3 +1,4 @@
import qs
import qs.modules.common import qs.modules.common
import qs.modules.common.widgets import qs.modules.common.widgets
import QtQuick import QtQuick
@@ -10,6 +11,12 @@ import Quickshell.Hyprland
Scope { Scope {
id: screenCorners id: screenCorners
readonly property Toplevel activeWindow: ToplevelManager.activeToplevel readonly property Toplevel activeWindow: ToplevelManager.activeToplevel
property var actionForCorner: ({
[RoundCorner.CornerEnum.TopLeft]: () => GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen,
[RoundCorner.CornerEnum.BottomLeft]: () => GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen,
[RoundCorner.CornerEnum.TopRight]: () => GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen,
[RoundCorner.CornerEnum.BottomRight]: () => GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen
})
component CornerPanelWindow: PanelWindow { component CornerPanelWindow: PanelWindow {
id: cornerPanelWindow id: cornerPanelWindow
@@ -19,25 +26,55 @@ Scope {
exclusionMode: ExclusionMode.Ignore exclusionMode: ExclusionMode.Ignore
mask: Region { mask: Region {
item: null item: sidebarCornerOpenInteractionLoader.active ? sidebarCornerOpenInteractionLoader : null
} }
WlrLayershell.namespace: "quickshell:screenCorners" WlrLayershell.namespace: "quickshell:screenCorners"
WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.layer: WlrLayer.Overlay
color: "transparent" color: "transparent"
anchors { anchors {
top: cornerPanelWindow.corner === RoundCorner.CornerEnum.TopLeft || cornerPanelWindow.corner === RoundCorner.CornerEnum.TopRight top: cornerWidget.isTopLeft || cornerWidget.isTopRight
left: cornerPanelWindow.corner === RoundCorner.CornerEnum.TopLeft || cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomLeft left: cornerWidget.isBottomLeft || cornerWidget.isTopLeft
bottom: cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomLeft || cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomRight bottom: cornerWidget.isBottomLeft || cornerWidget.isBottomRight
right: cornerPanelWindow.corner === RoundCorner.CornerEnum.TopRight || cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomRight right: cornerWidget.isTopRight || cornerWidget.isBottomRight
} }
implicitWidth: cornerWidget.implicitWidth implicitWidth: cornerWidget.implicitWidth
implicitHeight: cornerWidget.implicitHeight implicitHeight: cornerWidget.implicitHeight
RoundCorner { RoundCorner {
id: cornerWidget id: cornerWidget
implicitSize: Appearance.rounding.screenRounding
corner: cornerPanelWindow.corner corner: cornerPanelWindow.corner
implicitSize: Appearance.rounding.screenRounding
implicitHeight: Math.max(implicitSize, sidebarCornerOpenInteractionLoader.implicitHeight)
implicitWidth: Math.max(implicitSize, sidebarCornerOpenInteractionLoader.implicitWidth)
Loader {
id: sidebarCornerOpenInteractionLoader
active: !fullscreen && Config.options.sidebar.cornerOpen.enabled
anchors {
top: (cornerWidget.isTopLeft || cornerWidget.isTopRight) ? parent.top : undefined
bottom: (cornerWidget.isBottomLeft || cornerWidget.isBottomRight) ? parent.bottom : undefined
left: (cornerWidget.isTopLeft || cornerWidget.isBottomLeft) ? parent.left : undefined
right: (cornerWidget.isTopRight || cornerWidget.isBottomRight) ? parent.right : undefined
}
sourceComponent: MouseArea {
implicitWidth: Config.options.sidebar.cornerOpen.cornerRegionWidth
implicitHeight: Config.options.sidebar.cornerOpen.cornerRegionHeight
hoverEnabled: Config.options.sidebar.cornerOpen.clickless
onEntered: screenCorners.actionForCorner[cornerPanelWindow.corner]()
Loader {
active: Config.options.sidebar.cornerOpen.visualize
anchors.fill: parent
sourceComponent: Rectangle {
// DEBUG
color: Appearance.colors.colPrimary
}
}
}
}
} }
} }
@@ -50,8 +87,8 @@ Scope {
property HyprlandMonitor monitor: Hyprland.monitorFor(modelData) property HyprlandMonitor monitor: Hyprland.monitorFor(modelData)
// Hide when fullscreen // Hide when fullscreen
property list<HyprlandWorkspace> workspacesForMonitor: Hyprland.workspaces.values.filter(workspace=>workspace.monitor && workspace.monitor.name == monitor.name) property list<HyprlandWorkspace> workspacesForMonitor: Hyprland.workspaces.values.filter(workspace => workspace.monitor && workspace.monitor.name == monitor.name)
property var activeWorkspaceWithFullscreen: workspacesForMonitor.filter(workspace=>((workspace.toplevels.values.filter(window=>window.wayland.fullscreen)[0] != undefined) && workspace.active))[0] property var activeWorkspaceWithFullscreen: workspacesForMonitor.filter(workspace => ((workspace.toplevels.values.filter(window => window.wayland.fullscreen)[0] != undefined) && workspace.active))[0]
property bool fullscreen: activeWorkspaceWithFullscreen != undefined property bool fullscreen: activeWorkspaceWithFullscreen != undefined
CornerPanelWindow { CornerPanelWindow {
@@ -391,6 +391,65 @@ ContentPage {
content: Translation.tr("When enabled keeps the content of the right sidebar loaded to reduce the delay when opening,\nat the cost of around 15MB of consistent RAM usage. Delay significance depends on your system's performance.\nUsing a custom kernel like linux-cachyos might help") content: Translation.tr("When enabled keeps the content of the right sidebar loaded to reduce the delay when opening,\nat the cost of around 15MB of consistent RAM usage. Delay significance depends on your system's performance.\nUsing a custom kernel like linux-cachyos might help")
} }
} }
ContentSubsection {
title: Translation.tr("Corner open")
tooltip: Translation.tr("Allows you to open sidebars by clicking or hovering screen corners regardless of bar position")
ConfigRow {
uniform: true
ConfigSwitch {
text: Translation.tr("Enable")
checked: Config.options.sidebar.cornerOpen.enable
onCheckedChanged: {
Config.options.sidebar.cornerOpen.enable = checked;
}
}
ConfigSwitch {
text: Translation.tr("Hover to trigger")
checked: Config.options.sidebar.cornerOpen.clickless
onCheckedChanged: {
Config.options.sidebar.cornerOpen.clickless = checked;
}
StyledToolTip {
content: "When this is off you'll have to click"
}
}
}
ConfigSwitch {
text: Translation.tr("Visualize region")
checked: Config.options.sidebar.cornerOpen.visualize
onCheckedChanged: {
Config.options.sidebar.cornerOpen.visualize = checked;
}
StyledToolTip {
content: "When this is off you'll have to click"
}
}
ConfigRow {
ConfigSpinBox {
text: Translation.tr("Region width")
value: Config.options.sidebar.cornerOpen.cornerRegionWidth
from: 1
to: 300
stepSize: 1
onValueChanged: {
Config.options.sidebar.cornerOpen.cornerRegionWidth = value;
}
}
ConfigSpinBox {
text: Translation.tr("Region height")
value: Config.options.sidebar.cornerOpen.cornerRegionHeight
from: 1
to: 300
stepSize: 1
onValueChanged: {
Config.options.sidebar.cornerOpen.cornerRegionHeight = value;
}
}
}
}
} }
ContentSection { ContentSection {
@@ -465,7 +524,7 @@ ContentPage {
} }
} }
} }
ContentSection { ContentSection {
title: Translation.tr("Language") title: Translation.tr("Language")