forked from Shinonome/dots-hyprland
hefty: morphing thingy
This commit is contained in:
Submodule dots/.config/quickshell/ii/modules/common/widgets/shapes updated: 7f0f0709ec...5916b5ae6f
@@ -0,0 +1,32 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract morphed panel to be used in TopLayerPanel.
|
||||||
|
* Screen width and height are to be supplied when declared in the top layer panel
|
||||||
|
* Others are to be declared by panels deriving from this
|
||||||
|
*
|
||||||
|
* To make sure morph movements don't look weird:
|
||||||
|
* - Follow the convention of having points start from bottom-middle and go clockwise
|
||||||
|
* - Make sure the number of points is "balanced" in all directions
|
||||||
|
* - Tip: Sometimes symmetry is not enough. Try to have more intermediate points if ones you have are too spaced out and act funny.
|
||||||
|
*/
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
// To be fed
|
||||||
|
required property int screenWidth
|
||||||
|
required property int screenHeight
|
||||||
|
|
||||||
|
// Some info
|
||||||
|
property int reservedTop: 0
|
||||||
|
property int reservedBottom: 0
|
||||||
|
property int reservedLeft: 0
|
||||||
|
property int reservedRight: 0
|
||||||
|
|
||||||
|
// Main stuff
|
||||||
|
property var backgroundPolygon
|
||||||
|
property Region maskRegion: Region {
|
||||||
|
item: root
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.modules.common
|
||||||
|
import "../../common/widgets/shapes/material-shapes.js" as MaterialShapes
|
||||||
|
import "../../common/widgets/shapes/shapes/corner-rounding.js" as CornerRounding
|
||||||
|
import "../../common/widgets/shapes/geometry/offset.js" as Offset
|
||||||
|
|
||||||
|
HAbstractMorphedPanel {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
// Own props
|
||||||
|
property int barHeight: Appearance.sizes.baseBarHeight
|
||||||
|
function getRounding(cornerStyle) {
|
||||||
|
switch(cornerStyle) {
|
||||||
|
case 0: return Appearance.rounding.screenRounding;
|
||||||
|
case 1: return Appearance.rounding.windowRounding;
|
||||||
|
case 2: return 0;
|
||||||
|
default: return Appearance.rounding.screenRounding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getEdgeGap(cornerStyle) {
|
||||||
|
switch(cornerStyle) {
|
||||||
|
case 0: return 0;
|
||||||
|
case 1: return Appearance.sizes.hyprlandGapsOut;
|
||||||
|
case 2: return 0;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getEdgeRounding(cornerStyle) {
|
||||||
|
switch(cornerStyle) {
|
||||||
|
case 0: return 0;
|
||||||
|
case 1: return Appearance.rounding.windowRounding;
|
||||||
|
case 2: return 0;
|
||||||
|
default: return Appearance.rounding.windowRounding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getHug(cornerStyle) {
|
||||||
|
return cornerStyle === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some info
|
||||||
|
reservedTop: barHeight + getEdgeGap(Config.options.bar.cornerStyle)
|
||||||
|
|
||||||
|
// Background
|
||||||
|
backgroundPolygon: {
|
||||||
|
// It's certainly cleaner to have the below props declared outside, but we do this
|
||||||
|
// to make sure config change only makes this re-evaluate exactly once
|
||||||
|
const cornerStyle = Config.options.bar.cornerStyle
|
||||||
|
const rounding = root.getRounding(cornerStyle)
|
||||||
|
const edgeGap = root.getEdgeGap(cornerStyle)
|
||||||
|
const edgeRounding = root.getEdgeRounding(cornerStyle)
|
||||||
|
const hug = root.getHug(cornerStyle)
|
||||||
|
const points = [
|
||||||
|
|
||||||
|
// bottom-middle
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth / 2, root.barHeight + edgeGap), new CornerRounding.CornerRounding(0)),
|
||||||
|
|
||||||
|
// bottom-left /||
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap + rounding, edgeGap + barHeight), new CornerRounding.CornerRounding(0)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap, edgeGap + barHeight), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap, edgeGap + barHeight + rounding * (hug ? 1 : -1)), new CornerRounding.CornerRounding(edgeRounding)),
|
||||||
|
// top-left |/-
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap, edgeGap + rounding), new CornerRounding.CornerRounding(0)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap, edgeGap), new CornerRounding.CornerRounding(edgeRounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap + rounding, edgeGap), new CornerRounding.CornerRounding(0)),
|
||||||
|
|
||||||
|
// top-middle
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth / 2, edgeGap), new CornerRounding.CornerRounding(0)),
|
||||||
|
|
||||||
|
// top-right -\|
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap - rounding, edgeGap), new CornerRounding.CornerRounding(0)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap, edgeGap), new CornerRounding.CornerRounding(edgeRounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap, edgeGap + rounding), new CornerRounding.CornerRounding(0)),
|
||||||
|
|
||||||
|
// bottom-right ||\
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap, root.barHeight + edgeGap + rounding * (hug ? 1 : -1)), new CornerRounding.CornerRounding(edgeRounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap, root.barHeight + edgeGap), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap - rounding, root.barHeight + edgeGap), new CornerRounding.CornerRounding(0)),
|
||||||
|
]
|
||||||
|
return MaterialShapes.customPolygon(points, 1, new Offset.Offset(root.screenWidth / 2, edgeGap + barHeight / 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Content
|
||||||
|
implicitHeight: barHeight + getEdgeGap(Config.options.bar.cornerStyle) * 2
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import qs
|
||||||
|
import qs.modules.common
|
||||||
|
import "../../common/widgets/shapes/material-shapes.js" as MaterialShapes
|
||||||
|
import "../../common/widgets/shapes/shapes/corner-rounding.js" as CornerRounding
|
||||||
|
import "../../common/widgets/shapes/geometry/offset.js" as Offset
|
||||||
|
|
||||||
|
HAbstractMorphedPanel {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
// Own props
|
||||||
|
property int edgeGap: Appearance.sizes.hyprlandGapsOut
|
||||||
|
property real rounding: Appearance.rounding.windowRounding
|
||||||
|
property real contentHeight: 300 // For now
|
||||||
|
|
||||||
|
// Background
|
||||||
|
backgroundPolygon: MaterialShapes.customPolygon([
|
||||||
|
// bottom-middle
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth / 2, edgeGap + root.contentHeight), new CornerRounding.CornerRounding(0)),
|
||||||
|
// bottom-left
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap + rounding, edgeGap + root.contentHeight), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap, edgeGap + root.contentHeight), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap, edgeGap + root.contentHeight - rounding), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
// top-left
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap, edgeGap + rounding), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap, edgeGap), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(edgeGap + rounding, edgeGap), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
// top-middle
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth / 2, edgeGap), new CornerRounding.CornerRounding(0)),
|
||||||
|
// top-right
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap - rounding, edgeGap), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap, edgeGap), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap, edgeGap + rounding), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
|
||||||
|
// bottom-right
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap, edgeGap + root.contentHeight - rounding), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap, edgeGap + root.contentHeight), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
new MaterialShapes.PointNRound(new Offset.Offset(root.screenWidth - edgeGap - rounding, edgeGap + root.contentHeight), new CornerRounding.CornerRounding(rounding)),
|
||||||
|
], 1, new Offset.Offset(root.screenWidth / 2, edgeGap + contentHeight / 2))
|
||||||
|
|
||||||
|
// Keybinds
|
||||||
|
GlobalShortcut {
|
||||||
|
name: "searchToggle"
|
||||||
|
description: "Toggles search on press"
|
||||||
|
|
||||||
|
onPressed: {
|
||||||
|
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GlobalShortcut {
|
||||||
|
name: "searchToggleRelease"
|
||||||
|
description: "Toggles search on release"
|
||||||
|
|
||||||
|
onPressed: {
|
||||||
|
GlobalStates.superReleaseMightTrigger = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onReleased: {
|
||||||
|
if (!GlobalStates.superReleaseMightTrigger) {
|
||||||
|
GlobalStates.superReleaseMightTrigger = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GlobalShortcut {
|
||||||
|
name: "searchToggleReleaseInterrupt"
|
||||||
|
description: "Interrupts possibility of search being toggled on release. " + "This is necessary because GlobalShortcut.onReleased in quickshell triggers whether or not you press something else while holding the key. " + "To make sure this works consistently, use binditn = MODKEYS, catchall in an automatically triggered submap that includes everything."
|
||||||
|
|
||||||
|
onPressed: {
|
||||||
|
GlobalStates.superReleaseMightTrigger = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
|
||||||
|
// The stuff that sits on the "top" layer for layershells. Not to be confused with "toplevels" as in windows.
|
||||||
|
Scope {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
Variants {
|
||||||
|
model: Quickshell.screens
|
||||||
|
delegate: HTopLayerPanel {
|
||||||
|
required property var modelData
|
||||||
|
screen: modelData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import qs
|
||||||
|
import "../../common"
|
||||||
|
import "../../common/widgets/shapes" as S
|
||||||
|
import "../../common/widgets/shapes/material-shapes.js" as MaterialShapes
|
||||||
|
import "../../common/widgets/shapes/shapes/corner-rounding.js" as CornerRounding
|
||||||
|
import "../../common/widgets/shapes/geometry/offset.js" as Offset
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fullscreen layer. Uses masking to not block clicks on windows n' stuff.
|
||||||
|
*/
|
||||||
|
PanelWindow {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
///////////////// Window //////////////////
|
||||||
|
color: "transparent"
|
||||||
|
WlrLayershell.namespace: "quickshell:topLayerPanel"
|
||||||
|
exclusionMode: ExclusionMode.Ignore
|
||||||
|
anchors {
|
||||||
|
top: true
|
||||||
|
left: true
|
||||||
|
right: true
|
||||||
|
bottom: true
|
||||||
|
}
|
||||||
|
|
||||||
|
mask: Region {
|
||||||
|
item: root.currentPanel
|
||||||
|
}
|
||||||
|
// HyprlandWindow.visibleMask: mask // TODO: use this later to optimize hyprland's rendering
|
||||||
|
|
||||||
|
///////////////// Content //////////////////
|
||||||
|
|
||||||
|
property alias roundedPolygon: backgroundShape.roundedPolygon
|
||||||
|
S.ShapeCanvas {
|
||||||
|
id: backgroundShape
|
||||||
|
anchors.fill: parent
|
||||||
|
polygonIsNormalized: false
|
||||||
|
roundedPolygon: MaterialShapes.customPolygon([new MaterialShapes.PointNRound(new Offset.Offset(root.screen.width, 0), new CornerRounding.CornerRounding(9999)),])
|
||||||
|
animation: NumberAnimation {
|
||||||
|
duration: 500
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: Appearance.animationCurves.expressiveDefaultSpatial
|
||||||
|
}
|
||||||
|
// animation: SpringAnimation {
|
||||||
|
// spring: 3.5
|
||||||
|
// damping: 0.3
|
||||||
|
// }
|
||||||
|
color: Appearance.colors.colLayer0
|
||||||
|
borderWidth: (root.currentPanel === bar && Config.options.bar.cornerStyle !== 1) ? 0 : 1
|
||||||
|
borderColor: Appearance.colors.colLayer0Border
|
||||||
|
visible: false // cuz there's already the shadow
|
||||||
|
// debug: true
|
||||||
|
}
|
||||||
|
DropShadow {
|
||||||
|
id: shadow
|
||||||
|
source: backgroundShape
|
||||||
|
anchors.fill: backgroundShape
|
||||||
|
radius: 10
|
||||||
|
samples: radius * 2 + 1 // Ideally radius * 2 + 1, see qt docs
|
||||||
|
color: "#44000000"
|
||||||
|
}
|
||||||
|
|
||||||
|
property HAbstractMorphedPanel currentPanel: bar
|
||||||
|
roundedPolygon: currentPanel.backgroundPolygon
|
||||||
|
|
||||||
|
// Do we want to have reserved area always follow the bar or maybe differ per panel?
|
||||||
|
EdgeReservedArea {
|
||||||
|
anchors.top: true
|
||||||
|
exclusiveZone: bar.reservedTop
|
||||||
|
}
|
||||||
|
EdgeReservedArea {
|
||||||
|
anchors.bottom: true
|
||||||
|
exclusiveZone: bar.reservedBottom
|
||||||
|
}
|
||||||
|
EdgeReservedArea {
|
||||||
|
anchors.left: true
|
||||||
|
exclusiveZone: bar.reservedLeft
|
||||||
|
}
|
||||||
|
EdgeReservedArea {
|
||||||
|
anchors.right: true
|
||||||
|
exclusiveZone: bar.reservedRight
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////// Content: Panels ///////////////
|
||||||
|
|
||||||
|
HBar {
|
||||||
|
id: bar
|
||||||
|
screenWidth: root.width
|
||||||
|
screenHeight: root.height
|
||||||
|
}
|
||||||
|
|
||||||
|
HOverview {
|
||||||
|
id: overview
|
||||||
|
screenWidth: root.width
|
||||||
|
screenHeight: root.height
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: GlobalStates
|
||||||
|
function onOverviewOpenChanged() {
|
||||||
|
if (GlobalStates.overviewOpen) {
|
||||||
|
currentPanel = overview;
|
||||||
|
} else {
|
||||||
|
currentPanel = bar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////// Components /////////////////
|
||||||
|
|
||||||
|
component EdgeReservedArea: PanelWindow {
|
||||||
|
WlrLayershell.namespace: "quickshell:edgeReservedArea"
|
||||||
|
implicitWidth: 0
|
||||||
|
implicitHeight: 0
|
||||||
|
mask: Region {
|
||||||
|
item: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
|
||||||
|
import qs.modules.common
|
||||||
|
import qs.modules.ii.background
|
||||||
|
import qs.modules.ii.cheatsheet
|
||||||
|
import qs.modules.ii.dock
|
||||||
|
import qs.modules.ii.lock
|
||||||
|
import qs.modules.ii.mediaControls
|
||||||
|
import qs.modules.ii.notificationPopup
|
||||||
|
import qs.modules.ii.onScreenDisplay
|
||||||
|
import qs.modules.ii.onScreenKeyboard
|
||||||
|
import qs.modules.ii.overview
|
||||||
|
import qs.modules.ii.polkit
|
||||||
|
import qs.modules.ii.regionSelector
|
||||||
|
import qs.modules.ii.screenCorners
|
||||||
|
import qs.modules.ii.sessionScreen
|
||||||
|
import qs.modules.ii.sidebarLeft
|
||||||
|
import qs.modules.ii.sidebarRight
|
||||||
|
import qs.modules.ii.overlay
|
||||||
|
import qs.modules.ii.verticalBar
|
||||||
|
import qs.modules.ii.wallpaperSelector
|
||||||
|
|
||||||
|
import qs.modules.hefty.topLayer
|
||||||
|
|
||||||
|
Scope {
|
||||||
|
// New
|
||||||
|
PanelLoader { component: HTopLayer {} }
|
||||||
|
|
||||||
|
// Fallbacks
|
||||||
|
PanelLoader { component: Background {} }
|
||||||
|
PanelLoader { component: Cheatsheet {} }
|
||||||
|
PanelLoader { extraCondition: Config.options.dock.enable; component: Dock {} }
|
||||||
|
PanelLoader { component: Lock {} }
|
||||||
|
PanelLoader { component: MediaControls {} }
|
||||||
|
PanelLoader { component: NotificationPopup {} }
|
||||||
|
PanelLoader { component: OnScreenDisplay {} }
|
||||||
|
PanelLoader { component: OnScreenKeyboard {} }
|
||||||
|
PanelLoader { component: Overlay {} }
|
||||||
|
// PanelLoader { component: Overview {} }
|
||||||
|
PanelLoader { component: Polkit {} }
|
||||||
|
PanelLoader { component: RegionSelector {} }
|
||||||
|
PanelLoader { component: ScreenCorners {} }
|
||||||
|
PanelLoader { component: SessionScreen {} }
|
||||||
|
PanelLoader { component: SidebarLeft {} }
|
||||||
|
PanelLoader { component: SidebarRight {} }
|
||||||
|
PanelLoader { component: WallpaperSelector {} }
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ ShellRoot {
|
|||||||
|
|
||||||
|
|
||||||
// Panel families
|
// Panel families
|
||||||
property list<string> families: ["ii", "waffle"]
|
property list<string> families: ["ii", "waffle", "hefty"]
|
||||||
function cyclePanelFamily() {
|
function cyclePanelFamily() {
|
||||||
const currentIndex = families.indexOf(Config.options.panelFamily)
|
const currentIndex = families.indexOf(Config.options.panelFamily)
|
||||||
const nextIndex = (currentIndex + 1) % families.length
|
const nextIndex = (currentIndex + 1) % families.length
|
||||||
@@ -57,6 +57,11 @@ ShellRoot {
|
|||||||
component: WaffleFamily {}
|
component: WaffleFamily {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PanelFamilyLoader {
|
||||||
|
identifier: "hefty"
|
||||||
|
component: HeftyHypeFamily {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Shortcuts
|
// Shortcuts
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
|
|||||||
Reference in New Issue
Block a user