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 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 {
@@ -13,8 +13,18 @@ Item {
implicitWidth: 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 {
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.smooth: true
preferredRendererType: Shape.CurveRenderer
@@ -1,3 +1,4 @@
import qs
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
@@ -10,6 +11,12 @@ import Quickshell.Hyprland
Scope {
id: screenCorners
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 {
id: cornerPanelWindow
@@ -19,25 +26,55 @@ Scope {
exclusionMode: ExclusionMode.Ignore
mask: Region {
item: null
item: sidebarCornerOpenInteractionLoader.active ? sidebarCornerOpenInteractionLoader : null
}
WlrLayershell.namespace: "quickshell:screenCorners"
WlrLayershell.layer: WlrLayer.Overlay
color: "transparent"
anchors {
top: cornerPanelWindow.corner === RoundCorner.CornerEnum.TopLeft || cornerPanelWindow.corner === RoundCorner.CornerEnum.TopRight
left: cornerPanelWindow.corner === RoundCorner.CornerEnum.TopLeft || cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomLeft
bottom: cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomLeft || cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomRight
right: cornerPanelWindow.corner === RoundCorner.CornerEnum.TopRight || cornerPanelWindow.corner === RoundCorner.CornerEnum.BottomRight
top: cornerWidget.isTopLeft || cornerWidget.isTopRight
left: cornerWidget.isBottomLeft || cornerWidget.isTopLeft
bottom: cornerWidget.isBottomLeft || cornerWidget.isBottomRight
right: cornerWidget.isTopRight || cornerWidget.isBottomRight
}
implicitWidth: cornerWidget.implicitWidth
implicitHeight: cornerWidget.implicitHeight
RoundCorner {
id: cornerWidget
implicitSize: Appearance.rounding.screenRounding
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)
// Hide when fullscreen
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 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 bool fullscreen: activeWorkspaceWithFullscreen != undefined
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")
}
}
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 {
@@ -465,7 +524,7 @@ ContentPage {
}
}
}
ContentSection {
title: Translation.tr("Language")