import QtCore import QtQuick import qs.Common import qs.Services import qs.DCommon.Widgets import qs.Modules.Settings.Widgets Item { id: root readonly property var log: Log.scoped("CompositorLayoutTab") property var parentModal: null LayoutMirroring.enabled: I18n.isRtl LayoutMirroring.childrenInherit: true property string xrayConflictSource: "" ConfigInclude { id: layoutInclude includeKind: "layout" onFixed: SettingsData.updateCompositorLayout() } function checkXrayConflicts() { if (!CompositorService.isNiri) return; const configDir = Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)); const script = `cd "${configDir}/niri" 2>/dev/null || exit 0 files="config.kdl" for f in $(sed -nE 's/^[[:space:]]*include[[:space:]]+"([^"]+)".*/\\1/p' config.kdl 2>/dev/null); do case "$f" in dms/*|/*dms/*) continue ;; esac [ -f "$f" ] && files="$files $f" done awk '$1 == "xray" { print FILENAME ":" FNR; exit }' $files 2>/dev/null`; Proc.runCommand("check-xray-conflict", ["sh", "-c", script], (output, exitCode) => { xrayConflictSource = exitCode === 0 ? output.trim() : ""; }); } Component.onCompleted: checkXrayConflicts() SettingsPage { id: layoutColumn IncludeSetupBanner { include: layoutInclude visibleCondition: layoutInclude.compositorSupported } StyledRect { width: parent.width height: xrayConflictRow.implicitHeight + Theme.spacingL * 2 radius: Theme.cornerRadius color: Theme.withAlpha(Theme.primary, 0.15) border.color: Theme.withAlpha(Theme.primary, 0.3) border.width: Theme.outlineWidth visible: root.xrayConflictSource !== "" Row { id: xrayConflictRow anchors.fill: parent anchors.margins: Theme.spacingL spacing: Theme.spacingM DIcon { name: "warning" size: Theme.iconSize color: Theme.primary anchors.verticalCenter: parent.verticalCenter } StyledText { width: parent.width - Theme.iconSize - Theme.spacingM anchors.verticalCenter: parent.verticalCenter text: I18n.tr("An xray rule at %1 may conflict with the Xray settings below", "compositor layout warning, %1 is a config location").arg(root.xrayConflictSource) font.pixelSize: Theme.fontSizeSmall color: Theme.surfaceVariantText wrapMode: Text.WordWrap } } } SettingsCard { width: parent.width tags: ["niri", "layout", "gaps", "radius", "window", "border"] title: I18n.tr("Layout overrides") settingKey: "niriLayout" iconName: "layers" visible: CompositorService.isNiri SettingsButtonGroupRow { tags: ["niri", "gaps", "override", "unmanaged"] settingKey: "niriLayoutGapsMode" resetKeys: ["niriLayoutGapsOverride"] text: I18n.tr("Gaps", "noun, window gaps mode in compositor layout settings") description: I18n.tr("Auto follows bar spacing, Off keeps your %1 config", "gaps mode description, %1 is the compositor name").arg("niri") model: [I18n.tr("Auto"), I18n.tr("Custom"), I18n.tr("Off")] currentIndex: { if (SettingsData.niriLayoutGapsOverride === -2) return 2; return SettingsData.niriLayoutGapsOverride >= 0 ? 1 : 0; } onSelectionChanged: (index, selected) => { if (!selected) return; switch (index) { case 1: SettingsData.set("niriLayoutGapsOverride", Math.max(4, (SettingsData.getPrimaryBarConfig()?.spacing ?? 4))); return; case 2: SettingsData.set("niriLayoutGapsOverride", -2); return; default: SettingsData.set("niriLayoutGapsOverride", -1); } } } SettingsSliderRow { tags: ["niri", "gaps", "override"] settingKey: "niriLayoutGapsOverride" resetKeys: [] text: I18n.tr("Window gaps") visible: SettingsData.niriLayoutGapsOverride >= 0 value: Math.max(0, SettingsData.niriLayoutGapsOverride) minimum: 0 maximum: 50 unit: "px" onSliderValueChanged: newValue => SettingsData.set("niriLayoutGapsOverride", newValue) } SettingsControlledBy { target: "surfaces" parentModal: root.parentModal section: "windowRadius" settingLabel: I18n.tr("Window radius") reason: Math.round(Theme.windowRadius) + "px" } SettingsToggleSliderRow { tags: ["niri", "border", "override", "focus-ring"] settingKey: "niriLayoutBorderSizeEnabled" text: I18n.tr("Override border size") checked: SettingsData.niriLayoutBorderSize >= 0 value: Math.max(0, SettingsData.niriLayoutBorderSize) minimum: 0 maximum: 10 unit: "px" onToggled: checked => SettingsData.set("niriLayoutBorderSize", checked ? 2 : -1) onSliderValueChanged: newValue => SettingsData.set("niriLayoutBorderSize", newValue) } SettingsToggleRow { visible: CompositorService.isNiri tags: ["niri", "xray", "blur", "background-effect", "performance"] settingKey: "niriLayoutXrayEnabled" text: I18n.tr("Xray blur") description: I18n.tr("Blurred surfaces show the wallpaper, not the windows beneath") checked: NiriService.layoutXrayEnabled onToggled: checked => NiriService.setLayoutXray(checked) } SettingsToggleRow { visible: CompositorService.isNiri && !SettingsData.connectedFrameModeActive tags: ["niri", "xray", "bar", "frame", "performance"] settingKey: "niriLayoutBarXrayEnabled" text: SettingsData.frameEnabled ? I18n.tr("Frame xray") : I18n.tr("Bar xray") description: I18n.tr("Blur against the wallpaper even with xray off") checked: NiriService.layoutBarXrayEnabled onToggled: checked => NiriService.setLayoutBarXray(checked) } } SettingsCard { width: parent.width tags: ["compositor", "toast"] title: I18n.tr("Notifications") settingKey: "compositorNotifications" iconName: "notifications" visible: CompositorService.isNiri || CompositorService.isMango SettingsToggleRow { tags: ["compositor", "toast", "reload"] settingKey: "showConfigReloadToast" text: I18n.tr("Show \"config reloaded\" toast") checked: SessionData.showConfigReloadToast onToggled: checked => SessionData.showConfigReloadToast = checked } } SettingsCard { width: parent.width tags: ["niri", "overview", "window", "focus", "launch", "launcher", "dock", "settings"] title: I18n.tr("Overview") settingKey: "niriOverview" iconName: "overview" visible: CompositorService.isNiri SettingsToggleRow { tags: ["niri", "overview", "window", "focus", "launch", "launcher", "dock", "settings"] settingKey: "closeNiriOverviewOnWindowFocus" text: I18n.tr("Close on window focus") description: I18n.tr("Leaves the overview when DMS launches an app or focuses a window", "niri overview close on window focus toggle description") checked: SettingsData.closeNiriOverviewOnWindowFocus onToggled: checked => SettingsData.set("closeNiriOverviewOnWindowFocus", checked) } } SettingsCard { id: hyprTilingCard width: parent.width tags: ["hyprland", "layout", "tiling", "dwindle", "master", "scrolling", "general:layout"] title: I18n.tr("Tiling layout", "Hyprland settings card title") settingKey: "hyprlandTilingLayout" iconName: "view_quilt" visible: CompositorService.isHyprland readonly property var layoutIds: ["", "dwindle", "master", "scrolling"] SettingsButtonGroupRow { tags: ["hyprland", "layout", "tiling", "dwindle", "master", "scrolling"] settingKey: "hyprlandTilingLayout" text: I18n.tr("Layout") model: [I18n.tr("Off"), I18n.tr("Dwindle", "Hyprland tiling layout name"), I18n.tr("Master", "Hyprland tiling layout name"), I18n.tr("Scrolling", "Hyprland tiling layout name")] currentIndex: Math.max(0, hyprTilingCard.layoutIds.indexOf(SettingsData.hyprlandTilingLayout)) onSelectionChanged: (index, selected) => { if (!selected) return; SettingsData.set("hyprlandTilingLayout", hyprTilingCard.layoutIds[index]); } } SettingsToggleRow { tags: ["hyprland", "dwindle", "preserve", "split"] settingKey: "hyprlandDwindlePreserveSplit" visible: SettingsData.hyprlandTilingLayout === "dwindle" text: I18n.tr("Preserve split", "Hyprland dwindle layout toggle") description: I18n.tr("Split direction stays fixed when the container resizes", "Hyprland preserve split toggle description") checked: SettingsData.hyprlandDwindlePreserveSplit onToggled: checked => SettingsData.set("hyprlandDwindlePreserveSplit", checked) } SettingsToggleRow { tags: ["hyprland", "dwindle", "smart", "split", "cursor"] settingKey: "hyprlandDwindleSmartSplit" visible: SettingsData.hyprlandTilingLayout === "dwindle" text: I18n.tr("Smart split", "Hyprland dwindle layout toggle") description: I18n.tr("Split direction follows the cursor position in the window", "Hyprland smart split toggle description") checked: SettingsData.hyprlandDwindleSmartSplit onToggled: checked => SettingsData.set("hyprlandDwindleSmartSplit", checked) } SettingsButtonGroupRow { tags: ["hyprland", "dwindle", "force", "split", "direction"] settingKey: "hyprlandDwindleForceSplit" visible: SettingsData.hyprlandTilingLayout === "dwindle" text: I18n.tr("Force split", "Hyprland dwindle layout dropdown, which side new windows split to") model: [I18n.tr("Follow mouse", "Hyprland force split option, the split side follows the pointer"), I18n.tr("Left"), I18n.tr("Right")] currentIndex: SettingsData.hyprlandDwindleForceSplit onSelectionChanged: (index, selected) => { if (!selected) return; SettingsData.set("hyprlandDwindleForceSplit", index); } } SettingsDropdownRow { readonly property var ids: ["left", "right", "top", "bottom", "center"] tags: ["hyprland", "master", "orientation", "position"] settingKey: "hyprlandMasterOrientation" visible: SettingsData.hyprlandTilingLayout === "master" text: I18n.tr("Master position", "Hyprland master layout dropdown, where the master window sits") options: [I18n.tr("Left"), I18n.tr("Right"), I18n.tr("Top"), I18n.tr("Bottom"), I18n.tr("Center")] currentValue: options[Math.max(0, ids.indexOf(SettingsData.hyprlandMasterOrientation))] onValueChanged: value => SettingsData.set("hyprlandMasterOrientation", ids[Math.max(0, options.indexOf(value))]) } SettingsButtonGroupRow { readonly property var ids: ["slave", "master", "inherit"] tags: ["hyprland", "master", "new", "window", "status", "slave"] settingKey: "hyprlandMasterNewStatus" visible: SettingsData.hyprlandTilingLayout === "master" text: I18n.tr("New windows", "Hyprland master layout dropdown, where new windows go") model: [I18n.tr("Stack", "Hyprland master layout option, new windows join the stack"), I18n.tr("Master", "Hyprland tiling layout name"), I18n.tr("Inherit")] currentIndex: Math.max(0, ids.indexOf(SettingsData.hyprlandMasterNewStatus)) onSelectionChanged: (index, selected) => { if (!selected) return; SettingsData.set("hyprlandMasterNewStatus", ids[index]); } } SettingsToggleRow { tags: ["hyprland", "master", "new", "top", "stack"] settingKey: "hyprlandMasterNewOnTop" visible: SettingsData.hyprlandTilingLayout === "master" text: I18n.tr("New windows on top of the stack", "Hyprland master layout toggle") checked: SettingsData.hyprlandMasterNewOnTop onToggled: checked => SettingsData.set("hyprlandMasterNewOnTop", checked) } SettingsSliderRow { tags: ["hyprland", "master", "size", "mfact", "ratio"] settingKey: "hyprlandMasterSize" visible: SettingsData.hyprlandTilingLayout === "master" text: I18n.tr("Master size", "Hyprland master layout slider, share of the screen the master window takes") value: SettingsData.hyprlandMasterSize minimum: 10 maximum: 90 onSliderValueChanged: newValue => SettingsData.set("hyprlandMasterSize", newValue) } SettingsButtonGroupRow { readonly property var ids: ["right", "left", "down", "up"] tags: ["hyprland", "scrolling", "direction"] settingKey: "hyprlandScrollingDirection" visible: SettingsData.hyprlandTilingLayout === "scrolling" text: I18n.tr("Direction") model: [I18n.tr("Right"), I18n.tr("Left"), I18n.tr("Down", "Hyprland scrolling layout direction"), I18n.tr("Up", "Hyprland scrolling layout direction")] currentIndex: Math.max(0, ids.indexOf(SettingsData.hyprlandScrollingDirection)) onSelectionChanged: (index, selected) => { if (!selected) return; SettingsData.set("hyprlandScrollingDirection", ids[index]); } } SettingsSliderRow { tags: ["hyprland", "scrolling", "column", "width"] settingKey: "hyprlandScrollingColumnWidth" visible: SettingsData.hyprlandTilingLayout === "scrolling" text: I18n.tr("Column Width") value: SettingsData.hyprlandScrollingColumnWidth minimum: 10 maximum: 100 onSliderValueChanged: newValue => SettingsData.set("hyprlandScrollingColumnWidth", newValue) } SettingsToggleRow { tags: ["hyprland", "scrolling", "fullscreen", "single", "column"] settingKey: "hyprlandScrollingFullscreenOneColumn" visible: SettingsData.hyprlandTilingLayout === "scrolling" text: I18n.tr("Fullscreen single column", "Hyprland scrolling layout toggle, a lone column fills the screen") checked: SettingsData.hyprlandScrollingFullscreenOneColumn onToggled: checked => SettingsData.set("hyprlandScrollingFullscreenOneColumn", checked) } SettingsToggleRow { tags: ["hyprland", "scrolling", "follow", "focus", "scroll"] settingKey: "hyprlandScrollingFollowFocus" visible: SettingsData.hyprlandTilingLayout === "scrolling" text: I18n.tr("Follow focus") checked: SettingsData.hyprlandScrollingFollowFocus onToggled: checked => SettingsData.set("hyprlandScrollingFollowFocus", checked) } } SettingsCard { width: parent.width tags: ["hyprland", "layout", "gaps", "radius", "window", "border", "rounding"] title: I18n.tr("Layout overrides") settingKey: "hyprlandLayout" iconName: "crop_square" visible: CompositorService.isHyprland SettingsButtonGroupRow { tags: ["hyprland", "gaps", "override", "inner", "outer", "unmanaged"] settingKey: "hyprlandLayoutGapsMode" resetKeys: ["hyprlandLayoutGapsOverride"] text: I18n.tr("Gaps") model: [I18n.tr("Auto"), I18n.tr("Custom"), I18n.tr("Off")] currentIndex: { if (SettingsData.hyprlandLayoutGapsOverride === -2) return 2; return SettingsData.hyprlandLayoutGapsOverride >= 0 ? 1 : 0; } onSelectionChanged: (index, selected) => { if (!selected) return; switch (index) { case 1: SettingsData.set("hyprlandLayoutGapsOverride", Math.max(4, (SettingsData.getPrimaryBarConfig()?.spacing ?? 4))); return; case 2: SettingsData.set("hyprlandLayoutGapsOverride", -2); return; default: SettingsData.set("hyprlandLayoutGapsOverride", -1); } } } SettingsSliderRow { tags: ["hyprland", "gaps", "override", "inner", "gaps_in"] settingKey: "hyprlandLayoutGapsOverride" resetKeys: [] text: I18n.tr("Inner gaps") visible: SettingsData.hyprlandLayoutGapsOverride >= 0 value: Math.max(0, SettingsData.hyprlandLayoutGapsOverride) minimum: 0 maximum: 50 unit: "px" onSliderValueChanged: newValue => SettingsData.set("hyprlandLayoutGapsOverride", newValue) } SettingsSliderRow { tags: ["hyprland", "gaps", "override", "outer", "edge", "gaps_out"] settingKey: "hyprlandLayoutGapsOutOverride" text: I18n.tr("Outer gaps") visible: SettingsData.hyprlandLayoutGapsOverride >= 0 value: SettingsData.hyprlandLayoutGapsOutOverride >= 0 ? SettingsData.hyprlandLayoutGapsOutOverride : Math.max(0, SettingsData.hyprlandLayoutGapsOverride) minimum: 0 maximum: 50 unit: "px" onSliderValueChanged: newValue => SettingsData.set("hyprlandLayoutGapsOutOverride", newValue) } SettingsControlledBy { target: "surfaces" parentModal: root.parentModal section: "windowRadius" settingLabel: I18n.tr("Window radius") reason: Math.round(Theme.windowRadius) + "px" } SettingsToggleSliderRow { tags: ["hyprland", "border", "override", "border_size"] settingKey: "hyprlandLayoutBorderSizeEnabled" text: I18n.tr("Override border size") checked: SettingsData.hyprlandLayoutBorderSize >= 0 value: Math.max(0, SettingsData.hyprlandLayoutBorderSize) minimum: 0 maximum: 10 unit: "px" onToggled: checked => SettingsData.set("hyprlandLayoutBorderSize", checked ? 2 : -1) onSliderValueChanged: newValue => SettingsData.set("hyprlandLayoutBorderSize", newValue) } SettingsToggleSliderRow { tags: ["hyprland", "resize", "border", "mouse", "drag", "grab", "area", "extend_border_grab_area"] settingKey: "hyprlandResizeOnBorder" valueKeys: ["hyprlandBorderGrabArea"] text: I18n.tr("Resize on border") checked: SettingsData.hyprlandResizeOnBorder value: SettingsData.hyprlandBorderGrabArea minimum: 0 maximum: 100 unit: "px" onToggled: checked => SettingsData.set("hyprlandResizeOnBorder", checked) onSliderValueChanged: newValue => SettingsData.set("hyprlandBorderGrabArea", newValue) } SettingsSliderRow { tags: ["hyprland", "opacity", "transparency", "window"] settingKey: "hyprlandWindowOpacity" text: I18n.tr("Window opacity", "Hyprland opacity applied to app windows") value: SettingsData.hyprlandWindowOpacity minimum: 10 maximum: 100 unit: "%" onSliderValueChanged: newValue => SettingsData.set("hyprlandWindowOpacity", newValue) } SettingsToggleRow { visible: CompositorService.isHyprland tags: ["hyprland", "xray", "blur", "background-effect", "performance"] settingKey: "hyprlandLayoutXrayEnabled" text: I18n.tr("Xray blur") description: I18n.tr("Blurred surfaces show the wallpaper, not the windows beneath") checked: HyprlandService.layoutXrayEnabled onToggled: checked => HyprlandService.setLayoutXray(checked) } SettingsToggleRow { visible: CompositorService.isHyprland && !SettingsData.connectedFrameModeActive tags: ["hyprland", "xray", "bar", "frame", "performance"] settingKey: "hyprlandLayoutBarXrayEnabled" text: SettingsData.frameEnabled ? I18n.tr("Frame xray") : I18n.tr("Bar xray") description: I18n.tr("Blur against the wallpaper even with xray off") checked: HyprlandService.layoutBarXrayEnabled onToggled: checked => HyprlandService.setLayoutBarXray(checked) } } SettingsCard { id: hyprEffectsCard width: parent.width tags: ["hyprland", "effects", "blur", "glow", "wobble", "motion", "decoration"] title: I18n.tr("Visual effects") settingKey: "hyprlandEffects" iconName: "auto_awesome" visible: CompositorService.isHyprland && (HyprlandService.hyprSupports("decoration:blur:variant") || HyprlandService.hyprSupports("decoration:glow:enabled") || HyprlandService.hyprSupports("decoration:wobble:enabled") || HyprlandService.hyprSupports("decoration:motion_blur:enabled")) readonly property var blurVariantIds: ["kawase", "frost", "ripple", "drops", "water", "fluid_jar", "prism", "heat_shimmer", "acrylic", "aurora", "haze"] SettingsDropdownRow { tags: ["hyprland", "blur", "variant", "style", "acrylic", "aurora", "frost", "glass"] settingKey: "hyprlandBlurVariant" visible: HyprlandService.hyprSupports("decoration:blur:variant") text: I18n.tr("Blur") description: I18n.tr("Styles outside of Default use more GPU", "Hyprland blur variant dropdown description") options: [I18n.tr("Default"), I18n.tr("Frost", "Hyprland blur variant"), I18n.tr("Ripple", "Hyprland blur variant"), I18n.tr("Drops", "Hyprland blur variant"), I18n.tr("Water", "Hyprland blur variant"), I18n.tr("Fluid jar", "Hyprland blur variant"), I18n.tr("Prism", "Hyprland blur variant"), I18n.tr("Heat shimmer", "Hyprland blur variant"), I18n.tr("Acrylic", "Hyprland blur variant"), I18n.tr("Aurora", "Hyprland blur variant"), I18n.tr("Haze", "Hyprland blur variant")] currentValue: options[Math.max(0, hyprEffectsCard.blurVariantIds.indexOf(SettingsData.hyprlandBlurVariant))] onValueChanged: value => SettingsData.set("hyprlandBlurVariant", hyprEffectsCard.blurVariantIds[Math.max(0, options.indexOf(value))]) } SettingsSliderRow { tags: ["hyprland", "blur", "ripple", "strength", "refraction"] settingKey: "hyprlandBlurRippleStrength" visible: SettingsData.hyprlandBlurVariant === "ripple" text: I18n.tr("Refraction", "Hyprland blur slider, how far ripple or water waves bend the backdrop") value: SettingsData.hyprlandBlurRippleStrength minimum: 0 maximum: 32 unit: "px" onSliderValueChanged: newValue => SettingsData.set("hyprlandBlurRippleStrength", newValue) } SettingsSliderRow { tags: ["hyprland", "blur", "water", "strength", "refraction"] settingKey: "hyprlandBlurWaterStrength" visible: SettingsData.hyprlandBlurVariant === "water" text: I18n.tr("Refraction", "Hyprland blur slider, how far ripple or water waves bend the backdrop") value: SettingsData.hyprlandBlurWaterStrength minimum: 0 maximum: 32 unit: "px" onSliderValueChanged: newValue => SettingsData.set("hyprlandBlurWaterStrength", newValue) } SettingsSliderRow { tags: ["hyprland", "blur", "acrylic", "clarity"] settingKey: "hyprlandBlurAcrylicClarity" visible: SettingsData.hyprlandBlurVariant === "acrylic" text: I18n.tr("Clarity", "Hyprland acrylic blur slider, how much sharp backdrop shows through") value: SettingsData.hyprlandBlurAcrylicClarity minimum: 0 maximum: 100 unit: "%" onSliderValueChanged: newValue => SettingsData.set("hyprlandBlurAcrylicClarity", newValue) } SettingsSliderRow { tags: ["hyprland", "blur", "aurora", "intensity"] settingKey: "hyprlandBlurAuroraIntensity" visible: SettingsData.hyprlandBlurVariant === "aurora" text: I18n.tr("Intensity") value: SettingsData.hyprlandBlurAuroraIntensity minimum: 0 maximum: 100 unit: "%" onSliderValueChanged: newValue => SettingsData.set("hyprlandBlurAuroraIntensity", newValue) } SettingsSliderRow { tags: ["hyprland", "blur", "aurora", "speed", "animation"] settingKey: "hyprlandBlurAuroraSpeed" visible: SettingsData.hyprlandBlurVariant === "aurora" text: I18n.tr("Speed") value: SettingsData.hyprlandBlurAuroraSpeed minimum: 0 maximum: 10 onSliderValueChanged: newValue => SettingsData.set("hyprlandBlurAuroraSpeed", newValue) } SettingsSliderRow { tags: ["hyprland", "blur", "haze", "intensity", "sheen"] settingKey: "hyprlandBlurHazeIntensity" visible: SettingsData.hyprlandBlurVariant === "haze" text: I18n.tr("Intensity") value: SettingsData.hyprlandBlurHazeIntensity minimum: 0 maximum: 100 unit: "%" onSliderValueChanged: newValue => SettingsData.set("hyprlandBlurHazeIntensity", newValue) } SettingsSliderRow { tags: ["hyprland", "blur", "haze", "iridescence", "color"] settingKey: "hyprlandBlurHazeIridescence" visible: SettingsData.hyprlandBlurVariant === "haze" text: I18n.tr("Iridescence", "Hyprland haze blur slider, strength of the pearlescent color shift") value: SettingsData.hyprlandBlurHazeIridescence minimum: 0 maximum: 100 unit: "%" onSliderValueChanged: newValue => SettingsData.set("hyprlandBlurHazeIridescence", newValue) } SettingsToggleSliderRow { tags: ["hyprland", "glow", "inner", "range"] settingKey: "hyprlandGlowEnabled" valueKeys: ["hyprlandGlowRange"] visible: HyprlandService.hyprSupports("decoration:glow:enabled") text: I18n.tr("Glow", "Hyprland toggle, inner glow along window edges in the theme color") checked: SettingsData.hyprlandGlowEnabled value: SettingsData.hyprlandGlowRange minimum: 1 maximum: 50 unit: "px" onToggled: checked => SettingsData.set("hyprlandGlowEnabled", checked) onSliderValueChanged: newValue => SettingsData.set("hyprlandGlowRange", newValue) } SettingsSliderRow { tags: ["hyprland", "glow", "falloff", "render_power"] settingKey: "hyprlandGlowRenderPower" visible: SettingsData.hyprlandGlowEnabled && HyprlandService.hyprSupports("decoration:glow:enabled") text: I18n.tr("Glow falloff", "Hyprland slider, higher values fade the glow faster") value: SettingsData.hyprlandGlowRenderPower minimum: 1 maximum: 4 onSliderValueChanged: newValue => SettingsData.set("hyprlandGlowRenderPower", newValue) } SettingsToggleSliderRow { tags: ["hyprland", "wobble", "wobbly", "windows", "intensity"] settingKey: "hyprlandWobbleEnabled" valueKeys: ["hyprlandWobbleIntensity"] visible: HyprlandService.hyprSupports("decoration:wobble:enabled") text: I18n.tr("Wobbly windows", "Hyprland toggle, windows flex while moving and resizing") checked: SettingsData.hyprlandWobbleEnabled value: SettingsData.hyprlandWobbleIntensity minimum: 0 maximum: 200 unit: "%" onToggled: checked => SettingsData.set("hyprlandWobbleEnabled", checked) onSliderValueChanged: newValue => SettingsData.set("hyprlandWobbleIntensity", newValue) } SettingsSliderRow { tags: ["hyprland", "wobble", "stiffness", "spring"] settingKey: "hyprlandWobbleStiffness" visible: SettingsData.hyprlandWobbleEnabled && HyprlandService.hyprSupports("decoration:wobble:enabled") text: I18n.tr("Wobble stiffness", "Hyprland slider, higher values settle wobbly windows faster") value: SettingsData.hyprlandWobbleStiffness minimum: 10 maximum: 1000 onSliderValueChanged: newValue => SettingsData.set("hyprlandWobbleStiffness", newValue) } SettingsToggleSliderRow { tags: ["hyprland", "motion", "blur", "samples", "move", "resize"] settingKey: "hyprlandMotionBlurEnabled" valueKeys: ["hyprlandMotionBlurSamples"] visible: HyprlandService.hyprSupports("decoration:motion_blur:enabled") text: I18n.tr("Motion blur", "Hyprland toggle, blur windows while they move or resize") description: I18n.tr("More samples look smoother and cost more GPU", "Hyprland motion blur sample count description") checked: SettingsData.hyprlandMotionBlurEnabled value: SettingsData.hyprlandMotionBlurSamples minimum: 1 maximum: 64 onToggled: checked => SettingsData.set("hyprlandMotionBlurEnabled", checked) onSliderValueChanged: newValue => SettingsData.set("hyprlandMotionBlurSamples", newValue) } } SettingsCard { width: parent.width tags: ["hyprland", "group", "groupbar", "tabs"] title: I18n.tr("Window groups", "Hyprland settings card title, tabbed window groups") settingKey: "hyprlandGroupbar" iconName: "tab" visible: CompositorService.isHyprland SettingsToggleRow { tags: ["hyprland", "groupbar", "blur"] settingKey: "hyprlandGroupbarBlur" text: I18n.tr("Background blur") checked: SettingsData.hyprlandGroupbarBlur onToggled: checked => SettingsData.set("hyprlandGroupbarBlur", checked) } SettingsSliderRow { tags: ["hyprland", "groupbar", "text", "padding", "text_padding"] settingKey: "hyprlandGroupbarTextPadding" text: I18n.tr("Title padding", "Hyprland groupbar slider, horizontal padding around tab titles") value: SettingsData.hyprlandGroupbarTextPadding minimum: 0 maximum: 22 unit: "px" onSliderValueChanged: newValue => SettingsData.set("hyprlandGroupbarTextPadding", newValue) } SettingsToggleRow { tags: ["hyprland", "groupbar", "middle", "click", "close"] settingKey: "hyprlandGroupbarMiddleClickClose" text: I18n.tr("Middle click closes", "Hyprland groupbar toggle, middle clicking a tab closes that window") checked: SettingsData.hyprlandGroupbarMiddleClickClose onToggled: checked => SettingsData.set("hyprlandGroupbarMiddleClickClose", checked) } SettingsToggleRow { tags: ["hyprland", "groupbar", "single", "hide", "disable_when_only"] settingKey: "hyprlandGroupbarDisableWhenOnly" visible: HyprlandService.hyprSupports("group:groupbar:disable_when_only") text: I18n.tr("Hide with one window", "Hyprland groupbar toggle, no tab bar when the group holds a single window") checked: SettingsData.hyprlandGroupbarDisableWhenOnly onToggled: checked => SettingsData.set("hyprlandGroupbarDisableWhenOnly", checked) } } SettingsCard { width: parent.width tags: ["mangowc", "mango", "dwl", "layout", "gaps", "radius", "window", "border"] title: I18n.tr("Layout overrides") settingKey: "mangoLayout" iconName: "crop_square" visible: CompositorService.isMango SettingsButtonGroupRow { tags: ["mangowc", "mango", "gaps", "override", "inner", "outer", "unmanaged"] settingKey: "mangoLayoutGapsMode" resetKeys: ["mangoLayoutGapsOverride"] text: I18n.tr("Gaps") description: I18n.tr("Auto follows bar spacing, Off keeps your %1 config").arg("MangoWC") model: [I18n.tr("Auto"), I18n.tr("Custom"), I18n.tr("Off")] currentIndex: { if (SettingsData.mangoLayoutGapsOverride === -2) return 2; return SettingsData.mangoLayoutGapsOverride >= 0 ? 1 : 0; } onSelectionChanged: (index, selected) => { if (!selected) return; switch (index) { case 1: SettingsData.set("mangoLayoutGapsOverride", Math.max(4, (SettingsData.getPrimaryBarConfig()?.spacing ?? 4))); return; case 2: SettingsData.set("mangoLayoutGapsOverride", -2); return; default: SettingsData.set("mangoLayoutGapsOverride", -1); } } } SettingsSliderRow { tags: ["mangowc", "mango", "gaps", "override", "inner", "gappih", "gappiv"] settingKey: "mangoLayoutGapsOverride" resetKeys: [] text: I18n.tr("Inner gaps") visible: SettingsData.mangoLayoutGapsOverride >= 0 value: Math.max(0, SettingsData.mangoLayoutGapsOverride) minimum: 0 maximum: 50 unit: "px" onSliderValueChanged: newValue => SettingsData.set("mangoLayoutGapsOverride", newValue) } SettingsSliderRow { tags: ["mangowc", "mango", "gaps", "override", "outer", "edge", "gappoh", "gappov"] settingKey: "mangoLayoutGapsOutOverride" text: I18n.tr("Outer gaps") visible: SettingsData.mangoLayoutGapsOverride >= 0 value: SettingsData.mangoLayoutGapsOutOverride >= 0 ? SettingsData.mangoLayoutGapsOutOverride : Math.max(0, SettingsData.mangoLayoutGapsOverride) minimum: 0 maximum: 50 unit: "px" onSliderValueChanged: newValue => SettingsData.set("mangoLayoutGapsOutOverride", newValue) } SettingsControlledBy { target: "surfaces" parentModal: root.parentModal section: "windowRadius" settingLabel: I18n.tr("Window radius") reason: Math.round(Theme.windowRadius) + "px" } SettingsToggleSliderRow { tags: ["mangowc", "mango", "border", "override", "borderpx"] settingKey: "mangoLayoutBorderSizeEnabled" text: I18n.tr("Override border size") checked: SettingsData.mangoLayoutBorderSize >= 0 value: Math.max(0, SettingsData.mangoLayoutBorderSize) minimum: 0 maximum: 10 unit: "px" onToggled: checked => SettingsData.set("mangoLayoutBorderSize", checked ? 2 : -1) onSliderValueChanged: newValue => SettingsData.set("mangoLayoutBorderSize", newValue) } } } }