1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 21:42:51 -05:00

desktop widgets: add grid/grid size hints

This commit is contained in:
bbedward
2025-12-19 14:04:37 -05:00
parent f2611e0de0
commit 908b4b58cd
15 changed files with 3508 additions and 2367 deletions

View File

@@ -1,9 +1,11 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
@@ -86,6 +88,20 @@ Item {
property bool forceSquare: contentLoader.item?.forceSquare ?? false
property bool isInteracting: dragArea.pressed || resizeArea.pressed
property var _gridSettingsTrigger: SettingsData.desktopWidgetGridSettings
readonly property int gridSize: {
void _gridSettingsTrigger;
return SettingsData.getDesktopWidgetGridSetting(screenKey, "size", 40);
}
readonly property bool gridEnabled: {
void _gridSettingsTrigger;
return SettingsData.getDesktopWidgetGridSetting(screenKey, "enabled", false);
}
function snapToGrid(value) {
return Math.round(value / gridSize) * gridSize;
}
function updateVariantPositions(updates) {
const positions = JSON.parse(JSON.stringify(variantData?.positions || {}));
positions[screenKey] = Object.assign({}, positions[screenKey] || {}, updates);
@@ -141,7 +157,13 @@ Item {
WlrLayershell.namespace: "quickshell:desktop-widget:" + root.pluginId + (root.variantId ? ":" + root.variantId : "")
WlrLayershell.layer: WlrLayer.Bottom
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: (CompositorService.useHyprlandFocusGrab && root.isInteracting) ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
WlrLayershell.keyboardFocus: {
if (!root.isInteracting)
return WlrKeyboardFocus.None;
if (CompositorService.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
HyprlandFocusGrab {
active: CompositorService.isHyprland && root.isInteracting
@@ -238,8 +260,12 @@ Item {
if (!pressed)
return;
const currentPos = root.useGhostPreview ? Qt.point(mouse.x, mouse.y) : mapToGlobal(mouse.x, mouse.y);
const newX = Math.max(0, Math.min(startX + currentPos.x - startPos.x, root.screenWidth - root.widgetWidth));
const newY = Math.max(0, Math.min(startY + currentPos.y - startPos.y, root.screenHeight - root.widgetHeight));
let newX = Math.max(0, Math.min(startX + currentPos.x - startPos.x, root.screenWidth - root.widgetWidth));
let newY = Math.max(0, Math.min(startY + currentPos.y - startPos.y, root.screenHeight - root.widgetHeight));
if (root.gridEnabled) {
newX = Math.max(0, Math.min(root.snapToGrid(newX), root.screenWidth - root.widgetWidth));
newY = Math.max(0, Math.min(root.snapToGrid(newY), root.screenHeight - root.widgetHeight));
}
if (root.useGhostPreview) {
root.previewX = newX;
root.previewY = newY;
@@ -285,6 +311,10 @@ Item {
const currentPos = root.useGhostPreview ? Qt.point(mouse.x, mouse.y) : mapToGlobal(mouse.x, mouse.y);
let newW = Math.max(root.minWidth, Math.min(startWidth + currentPos.x - startPos.x, root.screenWidth - root.widgetX));
let newH = Math.max(root.minHeight, Math.min(startHeight + currentPos.y - startPos.y, root.screenHeight - root.widgetY));
if (root.gridEnabled) {
newW = Math.max(root.minWidth, root.snapToGrid(newW));
newH = Math.max(root.minHeight, root.snapToGrid(newH));
}
if (root.forceSquare) {
const size = Math.max(newW, newH);
newW = Math.min(size, root.screenWidth - root.widgetX);
@@ -330,6 +360,39 @@ Item {
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
Item {
id: gridOverlay
anchors.fill: parent
visible: root.gridEnabled
opacity: 0.3
Repeater {
model: Math.ceil(root.screenWidth / root.gridSize)
Rectangle {
required property int index
x: index * root.gridSize
y: 0
width: 1
height: root.screenHeight
color: Theme.primary
}
}
Repeater {
model: Math.ceil(root.screenHeight / root.gridSize)
Rectangle {
required property int index
x: 0
y: index * root.gridSize
width: root.screenWidth
height: 1
color: Theme.primary
}
}
}
Rectangle {
x: root.previewX
y: root.previewY
@@ -355,4 +418,177 @@ Item {
}
}
}
Loader {
active: root.isInteracting && root.gridEnabled && !root.useGhostPreview
sourceComponent: PanelWindow {
screen: root.screen
color: "transparent"
anchors {
left: true
right: true
top: true
bottom: true
}
mask: Region {}
WlrLayershell.namespace: "quickshell:desktop-widget-grid"
WlrLayershell.layer: WlrLayer.Background
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
Item {
anchors.fill: parent
opacity: 0.3
Repeater {
model: Math.ceil(root.screenWidth / root.gridSize)
Rectangle {
required property int index
x: index * root.gridSize
y: 0
width: 1
height: root.screenHeight
color: Theme.primary
}
}
Repeater {
model: Math.ceil(root.screenHeight / root.gridSize)
Rectangle {
required property int index
x: 0
y: index * root.gridSize
width: root.screenWidth
height: 1
color: Theme.primary
}
}
}
}
}
Loader {
active: root.isInteracting
sourceComponent: PanelWindow {
id: helperWindow
screen: root.screen
color: "transparent"
WlrLayershell.namespace: "quickshell:desktop-widget-helper"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: {
if (CompositorService.useHyprlandFocusGrab)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
HyprlandFocusGrab {
active: CompositorService.isHyprland
windows: [helperWindow]
}
anchors {
bottom: true
left: true
right: true
}
implicitHeight: 60
Item {
anchors.fill: parent
focus: true
Keys.onPressed: event => {
switch (event.key) {
case Qt.Key_G:
SettingsData.setDesktopWidgetGridSetting(root.screenKey, "enabled", !root.gridEnabled);
event.accepted = true;
break;
case Qt.Key_Z:
SettingsData.setDesktopWidgetGridSetting(root.screenKey, "size", Math.max(10, root.gridSize - 10));
event.accepted = true;
break;
case Qt.Key_X:
SettingsData.setDesktopWidgetGridSetting(root.screenKey, "size", Math.min(200, root.gridSize + 10));
event.accepted = true;
break;
}
}
}
Rectangle {
id: helperContent
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: Theme.spacingL
width: helperRow.implicitWidth + Theme.spacingM * 2
height: 32
radius: Theme.cornerRadius
color: Theme.surface
Row {
id: helperRow
anchors.centerIn: parent
spacing: Theme.spacingM
height: parent.height
DankIcon {
name: "grid_on"
size: 16
color: root.gridEnabled ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: root.gridEnabled ? I18n.tr("Grid: ON", "Widget grid snap status") : I18n.tr("Grid: OFF", "Widget grid snap status")
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.fontFamily
color: root.gridEnabled ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
width: 1
height: 16
color: Theme.outline
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: root.gridSize + "px"
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.fontFamily
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
width: 1
height: 16
color: Theme.outline
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: I18n.tr("G: grid • Z/X: size", "Widget grid keyboard hints")
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.fontFamily
font.italic: true
color: Theme.surfaceText
opacity: 0.7
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}
}