mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-16 16:24:00 -04:00
window rules: percent sizing for niri column width and height, explain float default
fixes #3687
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
.pragma library
|
||||
|
||||
const PERCENT = "%";
|
||||
const PIXELS = "px";
|
||||
|
||||
function parse(value) {
|
||||
const parts = String(value || "").trim().split(/\s+/);
|
||||
if (parts[0] !== "proportion")
|
||||
return {
|
||||
unit: PIXELS,
|
||||
amount: parts[parts.length - 1] || ""
|
||||
};
|
||||
const fraction = parseFloat(parts[1]);
|
||||
return {
|
||||
unit: PERCENT,
|
||||
amount: isNaN(fraction) ? "" : String(Math.round(fraction * 10000) / 100)
|
||||
};
|
||||
}
|
||||
|
||||
function format(unit, amount) {
|
||||
const number = parseFloat(amount);
|
||||
if (isNaN(number) || number <= 0)
|
||||
return "";
|
||||
if (unit === PERCENT)
|
||||
return "proportion " + Math.round(number * 100) / 10000;
|
||||
return "fixed " + Math.round(number);
|
||||
}
|
||||
|
||||
function label(value) {
|
||||
const size = parse(value);
|
||||
return size.amount + size.unit;
|
||||
}
|
||||
@@ -298,11 +298,13 @@ FocusScope {
|
||||
width: transcript.width
|
||||
height: vocals.implicitHeight
|
||||
|
||||
// Positioners relayout on polish, so the list would measure reused and rescaled rows at their old height.
|
||||
Column {
|
||||
id: vocals
|
||||
width: parent.width
|
||||
|
||||
Repeater {
|
||||
onItemAdded: vocals.forceLayout()
|
||||
model: root.controller.synced ? lyric.modelData.parts : [
|
||||
{
|
||||
x: lyric.modelData,
|
||||
@@ -326,6 +328,7 @@ FocusScope {
|
||||
distance: lyric ? Math.abs(lyric.index - root.activeIndex) : 0
|
||||
animationsEnabled: root.animationsEnabled
|
||||
smoothHighlight: root.smoothHighlight
|
||||
onImplicitHeightChanged: vocals.forceLayout()
|
||||
inViewport: {
|
||||
if (!lyric)
|
||||
return false;
|
||||
|
||||
@@ -352,6 +352,7 @@ Column {
|
||||
tags: ["floating", "window", "tile", "tiling", "compositor", "rule", "niri", "hyprland", "mango"]
|
||||
settingKey: "dmsWindowsFloating"
|
||||
text: I18n.tr("Open floating")
|
||||
description: I18n.tr("Adds a compositor window rule so DMS windows such as Settings open floating", "theme floating windows section, open floating toggle description")
|
||||
visible: windowRulesInclude.compositorSupported
|
||||
checked: CompositorService.dmsWindowFloatingActive
|
||||
modified: !checked
|
||||
|
||||
@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import "../../Common/WindowRuleSize.js" as WindowRuleSize
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.Settings.Widgets
|
||||
@@ -36,6 +37,8 @@ DankDialog {
|
||||
property string blockOutValue: ""
|
||||
property string columnDisplayValue: ""
|
||||
property string floatingRelativeValue: "top-left"
|
||||
property string columnWidthUnit: WindowRuleSize.PIXELS
|
||||
property string windowHeightUnit: WindowRuleSize.PIXELS
|
||||
|
||||
readonly property var triLabels: [I18n.tr("Default"), I18n.tr("On"), I18n.tr("Off")]
|
||||
readonly property var blockOutOptions: ["", "screencast", "screen-capture"]
|
||||
@@ -263,6 +266,8 @@ DankDialog {
|
||||
blockOutValue = "";
|
||||
columnDisplayValue = "";
|
||||
floatingRelativeValue = "top-left";
|
||||
columnWidthUnit = WindowRuleSize.PIXELS;
|
||||
windowHeightUnit = WindowRuleSize.PIXELS;
|
||||
blurCond.triState = 0;
|
||||
xrayCond.triState = 0;
|
||||
for (const field of [outputInput, workspaceInput, columnWidthInput, windowHeightInput, floatingXInput, floatingYInput, minWidthInput, maxWidthInput, minHeightInput, maxHeightInput, moveXInput, moveYInput, sizeWInput, sizeHInput, monitorInput, hyprWorkspaceInput, mangoTagsInput, mangoMonitorInput, mangoSizeInput])
|
||||
@@ -326,8 +331,12 @@ DankDialog {
|
||||
|
||||
outputInput.text = actions.openOnOutput || "";
|
||||
workspaceInput.text = actions.openOnWorkspace || "";
|
||||
columnWidthInput.text = actions.defaultColumnWidth || "";
|
||||
windowHeightInput.text = actions.defaultWindowHeight || "";
|
||||
const columnWidth = WindowRuleSize.parse(actions.defaultColumnWidth);
|
||||
const windowHeight = WindowRuleSize.parse(actions.defaultWindowHeight);
|
||||
columnWidthUnit = columnWidth.unit;
|
||||
windowHeightUnit = windowHeight.unit;
|
||||
columnWidthInput.text = columnWidth.amount;
|
||||
windowHeightInput.text = windowHeight.amount;
|
||||
floatingXInput.text = (actions.defaultFloatingX !== undefined && actions.defaultFloatingX !== null) ? String(actions.defaultFloatingX) : "";
|
||||
floatingYInput.text = (actions.defaultFloatingY !== undefined && actions.defaultFloatingY !== null) ? String(actions.defaultFloatingY) : "";
|
||||
floatingRelativeValue = actions.defaultFloatingRelativeTo || "top-left";
|
||||
@@ -422,10 +431,12 @@ DankDialog {
|
||||
actions.maxHeight = maxH;
|
||||
|
||||
if (isNiri) {
|
||||
if (columnWidthInput.text.trim())
|
||||
actions.defaultColumnWidth = columnWidthInput.text.trim();
|
||||
if (windowHeightInput.text.trim())
|
||||
actions.defaultWindowHeight = windowHeightInput.text.trim();
|
||||
const columnWidth = WindowRuleSize.format(columnWidthUnit, columnWidthInput.text);
|
||||
const windowHeight = WindowRuleSize.format(windowHeightUnit, windowHeightInput.text);
|
||||
if (columnWidth)
|
||||
actions.defaultColumnWidth = columnWidth;
|
||||
if (windowHeight)
|
||||
actions.defaultWindowHeight = windowHeight;
|
||||
if (dynamicFlags.includes("vrr"))
|
||||
actions.variableRefreshRate = true;
|
||||
if (dynamicFlags.includes("clip"))
|
||||
@@ -606,6 +617,35 @@ DankDialog {
|
||||
onAccepted: root.submit()
|
||||
}
|
||||
|
||||
component SizeField: Field {
|
||||
id: sizeField
|
||||
|
||||
property string unit: WindowRuleSize.PIXELS
|
||||
property string pixelsPlaceholder: ""
|
||||
|
||||
signal unitSelected(string unit)
|
||||
|
||||
placeholderText: unit === WindowRuleSize.PERCENT ? "50" : pixelsPlaceholder
|
||||
rightAccessoryWidth: unitPicker.width + Theme.spacingS
|
||||
|
||||
DankButtonGroup {
|
||||
id: unitPicker
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.spacingS
|
||||
y: sizeField.containerTop + (sizeField.containerHeight - height) / 2
|
||||
size: "small"
|
||||
checkEnabled: false
|
||||
arrowKeysSelect: false
|
||||
enabled: sizeField.enabled
|
||||
model: [I18n.tr("px"), WindowRuleSize.PERCENT]
|
||||
currentIndex: sizeField.unit === WindowRuleSize.PERCENT ? 1 : 0
|
||||
onSelectionChanged: (index, selected) => {
|
||||
if (selected)
|
||||
sizeField.unitSelected(index === 1 ? WindowRuleSize.PERCENT : WindowRuleSize.PIXELS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readonly property var matchConditions: [condFloating, condActive, condFocused, condActiveInColumn, condCastTarget, condUrgent, condAtStartup, condXwayland, condFullscreen, condPinned, condInitialised]
|
||||
|
||||
actions: [
|
||||
@@ -814,6 +854,7 @@ DankDialog {
|
||||
SettingsButtonGroupRow {
|
||||
visible: root.isNiri
|
||||
text: I18n.tr("Float")
|
||||
description: I18n.tr("Default leaves it to niri, which floats dialogs and fixed-size windows and tiles the rest", "window rule float option, explains the Default choice")
|
||||
model: root.triLabels
|
||||
currentIndex: root.floatingTri
|
||||
enabled: root.fieldsEnabled
|
||||
@@ -856,18 +897,22 @@ DankDialog {
|
||||
FieldRow {
|
||||
visible: root.isNiri
|
||||
|
||||
Field {
|
||||
SizeField {
|
||||
id: columnWidthInput
|
||||
leftIconName: "width"
|
||||
labelText: I18n.tr("Column Width")
|
||||
placeholderText: "800"
|
||||
pixelsPlaceholder: "800"
|
||||
unit: root.columnWidthUnit
|
||||
onUnitSelected: unit => root.columnWidthUnit = unit
|
||||
}
|
||||
|
||||
Field {
|
||||
SizeField {
|
||||
id: windowHeightInput
|
||||
leftIconName: "height"
|
||||
labelText: I18n.tr("Window Height")
|
||||
placeholderText: "600"
|
||||
pixelsPlaceholder: "600"
|
||||
unit: root.windowHeightUnit
|
||||
onUnitSelected: unit => root.windowHeightUnit = unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Common
|
||||
import "../../Common/ConfigIncludeResolve.js" as ConfigIncludeResolve
|
||||
import "../../Common/WindowRuleSize.js" as WindowRuleSize
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.Settings.Widgets
|
||||
@@ -73,6 +74,8 @@ Item {
|
||||
const label = root.actionLabels[k] || k;
|
||||
if (typeof a[k] === "boolean")
|
||||
return a[k] ? label : label + ": " + I18n.tr("Off");
|
||||
if (k === "defaultColumnWidth" || k === "defaultWindowHeight")
|
||||
return label + ": " + WindowRuleSize.label(a[k]);
|
||||
return label + ": " + a[k];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1042,14 +1042,18 @@
|
||||
"tabIndex": -1,
|
||||
"category": "Interface style",
|
||||
"keywords": [
|
||||
"adds",
|
||||
"authentication",
|
||||
"compositor",
|
||||
"floating",
|
||||
"foreground",
|
||||
"interface",
|
||||
"notepad",
|
||||
"opacity",
|
||||
"open",
|
||||
"override",
|
||||
"polkit",
|
||||
"rule",
|
||||
"settings",
|
||||
"style",
|
||||
"tile",
|
||||
@@ -1058,7 +1062,8 @@
|
||||
"window",
|
||||
"windows"
|
||||
],
|
||||
"page": "theme_surfaces"
|
||||
"page": "theme_surfaces",
|
||||
"description": "Adds a compositor window rule so DMS windows such as Settings open floating"
|
||||
},
|
||||
{
|
||||
"section": "focusRingEnabled",
|
||||
@@ -1818,6 +1823,7 @@
|
||||
"tabIndex": -1,
|
||||
"category": "Interface style",
|
||||
"keywords": [
|
||||
"adds",
|
||||
"compositor",
|
||||
"floating",
|
||||
"hyprland",
|
||||
@@ -1826,12 +1832,15 @@
|
||||
"niri",
|
||||
"open",
|
||||
"rule",
|
||||
"settings",
|
||||
"style",
|
||||
"tile",
|
||||
"tiling",
|
||||
"window"
|
||||
"window",
|
||||
"windows"
|
||||
],
|
||||
"page": "theme_surfaces"
|
||||
"page": "theme_surfaces",
|
||||
"description": "Adds a compositor window rule so DMS windows such as Settings open floating"
|
||||
},
|
||||
{
|
||||
"section": "notificationOverlayEnabled",
|
||||
|
||||
Reference in New Issue
Block a user