mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-28 23:42:51 -05:00
Fractional scaling fixes + bar border settings
This commit is contained in:
@@ -155,6 +155,14 @@ Singleton {
|
|||||||
property bool dankBarNoBackground: false
|
property bool dankBarNoBackground: false
|
||||||
property bool dankBarGothCornersEnabled: false
|
property bool dankBarGothCornersEnabled: false
|
||||||
property bool dankBarBorderEnabled: false
|
property bool dankBarBorderEnabled: false
|
||||||
|
property string dankBarBorderColor: "surfaceText"
|
||||||
|
property real dankBarBorderOpacity: 1.0
|
||||||
|
property real dankBarBorderThickness: 1
|
||||||
|
|
||||||
|
onDankBarBorderColorChanged: saveSettings()
|
||||||
|
onDankBarBorderOpacityChanged: saveSettings()
|
||||||
|
onDankBarBorderThicknessChanged: saveSettings()
|
||||||
|
|
||||||
property int dankBarPosition: SettingsData.Position.Top
|
property int dankBarPosition: SettingsData.Position.Top
|
||||||
property bool dankBarIsVertical: dankBarPosition === SettingsData.Position.Left || dankBarPosition === SettingsData.Position.Right
|
property bool dankBarIsVertical: dankBarPosition === SettingsData.Position.Left || dankBarPosition === SettingsData.Position.Right
|
||||||
property bool lockScreenShowPowerActions: true
|
property bool lockScreenShowPowerActions: true
|
||||||
@@ -407,6 +415,9 @@ Singleton {
|
|||||||
dankBarNoBackground = settings.dankBarNoBackground !== undefined ? settings.dankBarNoBackground : (settings.topBarNoBackground !== undefined ? settings.topBarNoBackground : false)
|
dankBarNoBackground = settings.dankBarNoBackground !== undefined ? settings.dankBarNoBackground : (settings.topBarNoBackground !== undefined ? settings.topBarNoBackground : false)
|
||||||
dankBarGothCornersEnabled = settings.dankBarGothCornersEnabled !== undefined ? settings.dankBarGothCornersEnabled : (settings.topBarGothCornersEnabled !== undefined ? settings.topBarGothCornersEnabled : false)
|
dankBarGothCornersEnabled = settings.dankBarGothCornersEnabled !== undefined ? settings.dankBarGothCornersEnabled : (settings.topBarGothCornersEnabled !== undefined ? settings.topBarGothCornersEnabled : false)
|
||||||
dankBarBorderEnabled = settings.dankBarBorderEnabled !== undefined ? settings.dankBarBorderEnabled : false
|
dankBarBorderEnabled = settings.dankBarBorderEnabled !== undefined ? settings.dankBarBorderEnabled : false
|
||||||
|
dankBarBorderColor = settings.dankBarBorderColor !== undefined ? settings.dankBarBorderColor : "surfaceText"
|
||||||
|
dankBarBorderOpacity = settings.dankBarBorderOpacity !== undefined ? settings.dankBarBorderOpacity : 1.0
|
||||||
|
dankBarBorderThickness = settings.dankBarBorderThickness !== undefined ? settings.dankBarBorderThickness : 1
|
||||||
dankBarPosition = settings.dankBarPosition !== undefined ? settings.dankBarPosition : (settings.dankBarAtBottom !== undefined ? (settings.dankBarAtBottom ? SettingsData.Position.Bottom : SettingsData.Position.Top) : (settings.topBarAtBottom !== undefined ? (settings.topBarAtBottom ? SettingsData.Position.Bottom : SettingsData.Position.Top) : SettingsData.Position.Top))
|
dankBarPosition = settings.dankBarPosition !== undefined ? settings.dankBarPosition : (settings.dankBarAtBottom !== undefined ? (settings.dankBarAtBottom ? SettingsData.Position.Bottom : SettingsData.Position.Top) : (settings.topBarAtBottom !== undefined ? (settings.topBarAtBottom ? SettingsData.Position.Bottom : SettingsData.Position.Top) : SettingsData.Position.Top))
|
||||||
lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true
|
lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true
|
||||||
hideBrightnessSlider = settings.hideBrightnessSlider !== undefined ? settings.hideBrightnessSlider : false
|
hideBrightnessSlider = settings.hideBrightnessSlider !== undefined ? settings.hideBrightnessSlider : false
|
||||||
@@ -533,6 +544,9 @@ Singleton {
|
|||||||
"dankBarNoBackground": dankBarNoBackground,
|
"dankBarNoBackground": dankBarNoBackground,
|
||||||
"dankBarGothCornersEnabled": dankBarGothCornersEnabled,
|
"dankBarGothCornersEnabled": dankBarGothCornersEnabled,
|
||||||
"dankBarBorderEnabled": dankBarBorderEnabled,
|
"dankBarBorderEnabled": dankBarBorderEnabled,
|
||||||
|
"dankBarBorderColor": dankBarBorderColor,
|
||||||
|
"dankBarBorderOpacity": dankBarBorderOpacity,
|
||||||
|
"dankBarBorderThickness": dankBarBorderThickness,
|
||||||
"dankBarPosition": dankBarPosition,
|
"dankBarPosition": dankBarPosition,
|
||||||
"lockScreenShowPowerActions": lockScreenShowPowerActions,
|
"lockScreenShowPowerActions": lockScreenShowPowerActions,
|
||||||
"hideBrightnessSlider": hideBrightnessSlider,
|
"hideBrightnessSlider": hideBrightnessSlider,
|
||||||
|
|||||||
@@ -685,7 +685,17 @@ Singleton {
|
|||||||
function withAlpha(c, a) { return Qt.rgba(c.r, c.g, c.b, a); }
|
function withAlpha(c, a) { return Qt.rgba(c.r, c.g, c.b, a); }
|
||||||
|
|
||||||
function snap(value, dpr) {
|
function snap(value, dpr) {
|
||||||
return Math.round(value * dpr) / dpr
|
const s = dpr || 1
|
||||||
|
return Math.round(value * s) / s
|
||||||
|
}
|
||||||
|
|
||||||
|
function px(value, dpr) {
|
||||||
|
const s = dpr || 1
|
||||||
|
return Math.round(value * s) / s
|
||||||
|
}
|
||||||
|
|
||||||
|
function hairline(dpr) {
|
||||||
|
return 1 / (dpr || 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
function invertHex(hex) {
|
function invertHex(hex) {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Hyprland
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: root
|
id: root
|
||||||
@@ -14,14 +16,16 @@ PanelWindow {
|
|||||||
property real height: 300
|
property real height: 300
|
||||||
readonly property real screenWidth: screen ? screen.width : 1920
|
readonly property real screenWidth: screen ? screen.width : 1920
|
||||||
readonly property real screenHeight: screen ? screen.height : 1080
|
readonly property real screenHeight: screen ? screen.height : 1080
|
||||||
readonly property real dpr: (screen && screen.devicePixelRatio) || 1
|
readonly property real dpr: {
|
||||||
|
if (CompositorService.isNiri && screen) {
|
||||||
function snap(v) {
|
const niriScale = NiriService.displayScales[screen.name]
|
||||||
return Math.round(v * dpr) / dpr
|
if (niriScale !== undefined) return niriScale
|
||||||
}
|
}
|
||||||
|
if (CompositorService.isHyprland && screen) {
|
||||||
function px(v) {
|
const hyprlandMonitor = Hyprland.monitors.values.find(m => m.name === screen.name)
|
||||||
return Math.round(v)
|
if (hyprlandMonitor?.scale !== undefined) return hyprlandMonitor.scale
|
||||||
|
}
|
||||||
|
return (screen?.devicePixelRatio) || 1
|
||||||
}
|
}
|
||||||
property bool showBackground: true
|
property bool showBackground: true
|
||||||
property real backgroundOpacity: 0.5
|
property real backgroundOpacity: 0.5
|
||||||
@@ -142,26 +146,26 @@ PanelWindow {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: contentContainer
|
id: contentContainer
|
||||||
|
|
||||||
width: px(root.width)
|
width: Theme.px(root.width, dpr)
|
||||||
height: px(root.height)
|
height: Theme.px(root.height, dpr)
|
||||||
anchors.centerIn: undefined
|
anchors.centerIn: undefined
|
||||||
x: {
|
x: {
|
||||||
if (positioning === "center") {
|
if (positioning === "center") {
|
||||||
return snap((root.screenWidth - width) / 2)
|
return Theme.snap((root.screenWidth - width) / 2, dpr)
|
||||||
} else if (positioning === "top-right") {
|
} else if (positioning === "top-right") {
|
||||||
return px(Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL))
|
return Theme.px(Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL), dpr)
|
||||||
} else if (positioning === "custom") {
|
} else if (positioning === "custom") {
|
||||||
return snap(root.customPosition.x)
|
return Theme.snap(root.customPosition.x, dpr)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
y: {
|
y: {
|
||||||
if (positioning === "center") {
|
if (positioning === "center") {
|
||||||
return snap((root.screenHeight - height) / 2)
|
return Theme.snap((root.screenHeight - height) / 2, dpr)
|
||||||
} else if (positioning === "top-right") {
|
} else if (positioning === "top-right") {
|
||||||
return px(Theme.barHeight + Theme.spacingXS)
|
return Theme.px(Theme.barHeight + Theme.spacingXS, dpr)
|
||||||
} else if (positioning === "custom") {
|
} else if (positioning === "custom") {
|
||||||
return snap(root.customPosition.y)
|
return Theme.snap(root.customPosition.y, dpr)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -170,6 +174,7 @@ PanelWindow {
|
|||||||
border.color: root.borderColor
|
border.color: root.borderColor
|
||||||
border.width: root.borderWidth
|
border.width: root.borderWidth
|
||||||
clip: false
|
clip: false
|
||||||
|
layer.enabled: true
|
||||||
opacity: root.shouldBeVisible ? 1 : 0
|
opacity: root.shouldBeVisible ? 1 : 0
|
||||||
transform: root.animationType === "slide" ? slideTransform : null
|
transform: root.animationType === "slide" ? slideTransform : null
|
||||||
|
|
||||||
@@ -179,8 +184,8 @@ PanelWindow {
|
|||||||
readonly property real rawX: root.shouldBeVisible ? 0 : 15
|
readonly property real rawX: root.shouldBeVisible ? 0 : 15
|
||||||
readonly property real rawY: root.shouldBeVisible ? 0 : -30
|
readonly property real rawY: root.shouldBeVisible ? 0 : -30
|
||||||
|
|
||||||
x: snap(rawX)
|
x: Theme.snap(rawX, root.dpr)
|
||||||
y: snap(rawY)
|
y: Theme.snap(rawY, root.dpr)
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Item {
|
|||||||
|
|
||||||
readonly property real correctWidth: root.width
|
readonly property real correctWidth: root.width
|
||||||
readonly property real correctHeight: root.height
|
readonly property real correctHeight: root.height
|
||||||
canvasSize: Qt.size(barWindow.px(correctWidth), barWindow.px(correctHeight))
|
canvasSize: Qt.size(Math.ceil(correctWidth), Math.ceil(correctHeight))
|
||||||
|
|
||||||
property real wing: SettingsData.dankBarGothCornersEnabled ? barWindow._wingR : 0
|
property real wing: SettingsData.dankBarGothCornersEnabled ? barWindow._wingR : 0
|
||||||
property real rt: SettingsData.dankBarSquareCorners ? 0 : Theme.cornerRadius
|
property real rt: SettingsData.dankBarSquareCorners ? 0 : Theme.cornerRadius
|
||||||
@@ -40,7 +40,6 @@ Item {
|
|||||||
Connections {
|
Connections {
|
||||||
target: barWindow
|
target: barWindow
|
||||||
function on_BgColorChanged() { barShape.requestPaint() }
|
function on_BgColorChanged() { barShape.requestPaint() }
|
||||||
function on_DprChanged() { barShape.requestPaint() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -50,19 +49,16 @@ Item {
|
|||||||
|
|
||||||
onPaint: {
|
onPaint: {
|
||||||
const ctx = getContext("2d")
|
const ctx = getContext("2d")
|
||||||
const scale = barWindow._dpr
|
const W = barWindow.isVertical ? correctHeight : correctWidth
|
||||||
const W = barWindow.px(barWindow.isVertical ? correctHeight : correctWidth)
|
const H_raw = barWindow.isVertical ? correctWidth : correctHeight
|
||||||
const H_raw = barWindow.px(barWindow.isVertical ? correctWidth : correctHeight)
|
const R = wing
|
||||||
const R = barWindow.px(wing)
|
const RT = rt
|
||||||
const RT = barWindow.px(rt)
|
|
||||||
const H = H_raw - (R > 0 ? R : 0)
|
const H = H_raw - (R > 0 ? R : 0)
|
||||||
const isTop = SettingsData.dankBarPosition === SettingsData.Position.Top
|
const isTop = SettingsData.dankBarPosition === SettingsData.Position.Top
|
||||||
const isBottom = SettingsData.dankBarPosition === SettingsData.Position.Bottom
|
const isBottom = SettingsData.dankBarPosition === SettingsData.Position.Bottom
|
||||||
const isLeft = SettingsData.dankBarPosition === SettingsData.Position.Left
|
const isLeft = SettingsData.dankBarPosition === SettingsData.Position.Left
|
||||||
const isRight = SettingsData.dankBarPosition === SettingsData.Position.Right
|
const isRight = SettingsData.dankBarPosition === SettingsData.Position.Right
|
||||||
|
|
||||||
ctx.scale(scale, scale)
|
|
||||||
|
|
||||||
function drawTopPath() {
|
function drawTopPath() {
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
ctx.moveTo(RT, 0)
|
ctx.moveTo(RT, 0)
|
||||||
@@ -89,7 +85,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.reset()
|
ctx.reset()
|
||||||
ctx.clearRect(0, 0, W, H_raw)
|
ctx.clearRect(0, 0, Math.ceil(W), Math.ceil(H_raw))
|
||||||
|
|
||||||
ctx.save()
|
ctx.save()
|
||||||
if (isBottom) {
|
if (isBottom) {
|
||||||
@@ -120,7 +116,7 @@ Item {
|
|||||||
|
|
||||||
readonly property real correctWidth: root.width
|
readonly property real correctWidth: root.width
|
||||||
readonly property real correctHeight: root.height
|
readonly property real correctHeight: root.height
|
||||||
canvasSize: Qt.size(barWindow.px(correctWidth), barWindow.px(correctHeight))
|
canvasSize: Qt.size(Math.ceil(correctWidth), Math.ceil(correctHeight))
|
||||||
|
|
||||||
property real wing: SettingsData.dankBarGothCornersEnabled ? barWindow._wingR : 0
|
property real wing: SettingsData.dankBarGothCornersEnabled ? barWindow._wingR : 0
|
||||||
property real rt: SettingsData.dankBarSquareCorners ? 0 : Theme.cornerRadius
|
property real rt: SettingsData.dankBarSquareCorners ? 0 : Theme.cornerRadius
|
||||||
@@ -137,7 +133,6 @@ Item {
|
|||||||
Connections {
|
Connections {
|
||||||
target: barWindow
|
target: barWindow
|
||||||
function on_BgColorChanged() { barTint.requestPaint() }
|
function on_BgColorChanged() { barTint.requestPaint() }
|
||||||
function on_DprChanged() { barTint.requestPaint() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -147,19 +142,16 @@ Item {
|
|||||||
|
|
||||||
onPaint: {
|
onPaint: {
|
||||||
const ctx = getContext("2d")
|
const ctx = getContext("2d")
|
||||||
const scale = barWindow._dpr
|
const W = barWindow.isVertical ? correctHeight : correctWidth
|
||||||
const W = barWindow.px(barWindow.isVertical ? correctHeight : correctWidth)
|
const H_raw = barWindow.isVertical ? correctWidth : correctHeight
|
||||||
const H_raw = barWindow.px(barWindow.isVertical ? correctWidth : correctHeight)
|
const R = wing
|
||||||
const R = barWindow.px(wing)
|
const RT = rt
|
||||||
const RT = barWindow.px(rt)
|
|
||||||
const H = H_raw - (R > 0 ? R : 0)
|
const H = H_raw - (R > 0 ? R : 0)
|
||||||
const isTop = SettingsData.dankBarPosition === SettingsData.Position.Top
|
const isTop = SettingsData.dankBarPosition === SettingsData.Position.Top
|
||||||
const isBottom = SettingsData.dankBarPosition === SettingsData.Position.Bottom
|
const isBottom = SettingsData.dankBarPosition === SettingsData.Position.Bottom
|
||||||
const isLeft = SettingsData.dankBarPosition === SettingsData.Position.Left
|
const isLeft = SettingsData.dankBarPosition === SettingsData.Position.Left
|
||||||
const isRight = SettingsData.dankBarPosition === SettingsData.Position.Right
|
const isRight = SettingsData.dankBarPosition === SettingsData.Position.Right
|
||||||
|
|
||||||
ctx.scale(scale, scale)
|
|
||||||
|
|
||||||
function drawTopPath() {
|
function drawTopPath() {
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
ctx.moveTo(RT, 0)
|
ctx.moveTo(RT, 0)
|
||||||
@@ -186,7 +178,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.reset()
|
ctx.reset()
|
||||||
ctx.clearRect(0, 0, W, H_raw)
|
ctx.clearRect(0, 0, Math.ceil(W), Math.ceil(H_raw))
|
||||||
|
|
||||||
ctx.save()
|
ctx.save()
|
||||||
if (isBottom) {
|
if (isBottom) {
|
||||||
@@ -211,14 +203,14 @@ Item {
|
|||||||
Canvas {
|
Canvas {
|
||||||
id: barBorder
|
id: barBorder
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
antialiasing: true
|
antialiasing: false
|
||||||
visible: SettingsData.dankBarBorderEnabled
|
visible: SettingsData.dankBarBorderEnabled
|
||||||
renderTarget: Canvas.FramebufferObject
|
renderTarget: Canvas.FramebufferObject
|
||||||
renderStrategy: Canvas.Cooperative
|
renderStrategy: Canvas.Cooperative
|
||||||
|
|
||||||
readonly property real correctWidth: root.width
|
readonly property real correctWidth: root.width
|
||||||
readonly property real correctHeight: root.height
|
readonly property real correctHeight: root.height
|
||||||
canvasSize: Qt.size(barWindow.px(correctWidth), barWindow.px(correctHeight))
|
canvasSize: Qt.size(Math.ceil(correctWidth), Math.ceil(correctHeight))
|
||||||
|
|
||||||
property real wing: SettingsData.dankBarGothCornersEnabled ? barWindow._wingR : 0
|
property real wing: SettingsData.dankBarGothCornersEnabled ? barWindow._wingR : 0
|
||||||
property real rt: SettingsData.dankBarSquareCorners ? 0 : Theme.cornerRadius
|
property real rt: SettingsData.dankBarSquareCorners ? 0 : Theme.cornerRadius
|
||||||
@@ -232,32 +224,28 @@ Item {
|
|||||||
onVisibleChanged: if (visible) requestPaint()
|
onVisibleChanged: if (visible) requestPaint()
|
||||||
Component.onCompleted: requestPaint()
|
Component.onCompleted: requestPaint()
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: barWindow
|
|
||||||
function on_DprChanged() { barBorder.requestPaint() }
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: Theme
|
target: Theme
|
||||||
function onSecondaryChanged() { barBorder.requestPaint() }
|
function onIsLightModeChanged() { barBorder.requestPaint() }
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: SettingsData
|
target: SettingsData
|
||||||
|
function onDankBarBorderColorChanged() { barBorder.requestPaint() }
|
||||||
|
function onDankBarBorderOpacityChanged() { barBorder.requestPaint() }
|
||||||
|
function onDankBarBorderThicknessChanged() { barBorder.requestPaint() }
|
||||||
function onDankBarSpacingChanged() { barBorder.requestPaint() }
|
function onDankBarSpacingChanged() { barBorder.requestPaint() }
|
||||||
function onDankBarSquareCornersChanged() { barBorder.requestPaint() }
|
function onDankBarSquareCornersChanged() { barBorder.requestPaint() }
|
||||||
function onCornerRadiusChanged() { barBorder.requestPaint() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPaint: {
|
onPaint: {
|
||||||
if (!borderEnabled) return
|
if (!borderEnabled) return
|
||||||
|
|
||||||
const ctx = getContext("2d")
|
const ctx = getContext("2d")
|
||||||
const scale = barWindow._dpr
|
const W = barWindow.isVertical ? correctHeight : correctWidth
|
||||||
const W = barWindow.px(barWindow.isVertical ? correctHeight : correctWidth)
|
const H_raw = barWindow.isVertical ? correctWidth : correctHeight
|
||||||
const H_raw = barWindow.px(barWindow.isVertical ? correctWidth : correctHeight)
|
const R = wing
|
||||||
const R = barWindow.px(wing)
|
const RT = rt
|
||||||
const RT = barWindow.px(rt)
|
|
||||||
const H = H_raw - (R > 0 ? R : 0)
|
const H = H_raw - (R > 0 ? R : 0)
|
||||||
const isTop = SettingsData.dankBarPosition === SettingsData.Position.Top
|
const isTop = SettingsData.dankBarPosition === SettingsData.Position.Top
|
||||||
const isBottom = SettingsData.dankBarPosition === SettingsData.Position.Bottom
|
const isBottom = SettingsData.dankBarPosition === SettingsData.Position.Bottom
|
||||||
@@ -267,8 +255,6 @@ Item {
|
|||||||
const spacing = SettingsData.dankBarSpacing
|
const spacing = SettingsData.dankBarSpacing
|
||||||
const hasEdgeGap = spacing > 0 || RT > 0
|
const hasEdgeGap = spacing > 0 || RT > 0
|
||||||
|
|
||||||
ctx.scale(scale, scale)
|
|
||||||
|
|
||||||
function drawTopBorder() {
|
function drawTopBorder() {
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
|
|
||||||
@@ -302,7 +288,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.reset()
|
ctx.reset()
|
||||||
ctx.clearRect(0, 0, W, H_raw)
|
ctx.clearRect(0, 0, Math.ceil(W), Math.ceil(H_raw))
|
||||||
|
|
||||||
ctx.save()
|
ctx.save()
|
||||||
if (isBottom) {
|
if (isBottom) {
|
||||||
@@ -319,9 +305,17 @@ Item {
|
|||||||
drawTopBorder()
|
drawTopBorder()
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
|
|
||||||
ctx.lineWidth = 1
|
const key = SettingsData.dankBarBorderColor || "surfaceText"
|
||||||
ctx.strokeStyle = Theme.secondary
|
const base = (key === "surfaceText") ? Theme.surfaceText
|
||||||
|
: (key === "primary") ? Theme.primary
|
||||||
|
: Theme.secondary
|
||||||
|
const color = Theme.withAlpha(base, SettingsData.dankBarBorderOpacity ?? 1.0)
|
||||||
|
const thickness = Math.max(1, SettingsData.dankBarBorderThickness ?? 1)
|
||||||
|
|
||||||
|
ctx.globalCompositeOperation = "source-over"
|
||||||
|
ctx.lineWidth = thickness
|
||||||
|
ctx.strokeStyle = color
|
||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import QtQuick.Controls
|
|||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import QtQuick.Shapes
|
import QtQuick.Shapes
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Hyprland
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import Quickshell.Services.Mpris
|
import Quickshell.Services.Mpris
|
||||||
import Quickshell.Services.Notifications
|
import Quickshell.Services.Notifications
|
||||||
@@ -61,8 +62,17 @@ Item {
|
|||||||
property real wingtipsRadius: Theme.cornerRadius
|
property real wingtipsRadius: Theme.cornerRadius
|
||||||
readonly property real _wingR: Math.max(0, wingtipsRadius)
|
readonly property real _wingR: Math.max(0, wingtipsRadius)
|
||||||
readonly property color _bgColor: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, topBarCore?.backgroundTransparency ?? SettingsData.dankBarTransparency)
|
readonly property color _bgColor: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, topBarCore?.backgroundTransparency ?? SettingsData.dankBarTransparency)
|
||||||
readonly property real _dpr: (barWindow.screen && barWindow.screen.devicePixelRatio) ? barWindow.screen.devicePixelRatio : 1
|
readonly property real _dpr: {
|
||||||
function px(v) { return Math.round(v * _dpr) / _dpr }
|
if (CompositorService.isNiri && barWindow.screen) {
|
||||||
|
const niriScale = NiriService.displayScales[barWindow.screen.name]
|
||||||
|
if (niriScale !== undefined) return niriScale
|
||||||
|
}
|
||||||
|
if (CompositorService.isHyprland && barWindow.screen) {
|
||||||
|
const hyprlandMonitor = Hyprland.monitors.values.find(m => m.name === barWindow.screen.name)
|
||||||
|
if (hyprlandMonitor?.scale !== undefined) return hyprlandMonitor.scale
|
||||||
|
}
|
||||||
|
return (barWindow.screen?.devicePixelRatio) || 1
|
||||||
|
}
|
||||||
|
|
||||||
property string screenName: modelData.name
|
property string screenName: modelData.name
|
||||||
readonly property int notificationCount: NotificationService.notifications.length
|
readonly property int notificationCount: NotificationService.notifications.length
|
||||||
@@ -70,8 +80,8 @@ Item {
|
|||||||
readonly property real widgetThickness: Math.max(20, 26 + SettingsData.dankBarInnerPadding * 0.6)
|
readonly property real widgetThickness: Math.max(20, 26 + SettingsData.dankBarInnerPadding * 0.6)
|
||||||
|
|
||||||
screen: modelData
|
screen: modelData
|
||||||
implicitHeight: !isVertical ? px(effectiveBarThickness + SettingsData.dankBarSpacing + (SettingsData.dankBarGothCornersEnabled ? _wingR : 0)) : 0
|
implicitHeight: !isVertical ? Theme.px(effectiveBarThickness + SettingsData.dankBarSpacing + (SettingsData.dankBarGothCornersEnabled ? _wingR : 0), _dpr) : 0
|
||||||
implicitWidth: isVertical ? px(effectiveBarThickness + SettingsData.dankBarSpacing + (SettingsData.dankBarGothCornersEnabled ? _wingR : 0)) : 0
|
implicitWidth: isVertical ? Theme.px(effectiveBarThickness + SettingsData.dankBarSpacing + (SettingsData.dankBarGothCornersEnabled ? _wingR : 0), _dpr) : 0
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
property var nativeInhibitor: null
|
property var nativeInhibitor: null
|
||||||
@@ -234,7 +244,7 @@ Item {
|
|||||||
Item {
|
Item {
|
||||||
id: inputMask
|
id: inputMask
|
||||||
|
|
||||||
readonly property int barThickness: px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing)
|
readonly property int barThickness: Theme.px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing, barWindow._dpr)
|
||||||
|
|
||||||
readonly property bool inOverviewWithShow: CompositorService.isNiri && NiriService.inOverview && SettingsData.dankBarOpenOnOverview
|
readonly property bool inOverviewWithShow: CompositorService.isNiri && NiriService.inOverview && SettingsData.dankBarOpenOnOverview
|
||||||
readonly property bool effectiveVisible: SettingsData.dankBarVisible || inOverviewWithShow
|
readonly property bool effectiveVisible: SettingsData.dankBarVisible || inOverviewWithShow
|
||||||
@@ -367,8 +377,8 @@ Item {
|
|||||||
id: topBarMouseArea
|
id: topBarMouseArea
|
||||||
y: !barWindow.isVertical ? (SettingsData.dankBarPosition === SettingsData.Position.Bottom ? parent.height - height : 0) : 0
|
y: !barWindow.isVertical ? (SettingsData.dankBarPosition === SettingsData.Position.Bottom ? parent.height - height : 0) : 0
|
||||||
x: barWindow.isVertical ? (SettingsData.dankBarPosition === SettingsData.Position.Right ? parent.width - width : 0) : 0
|
x: barWindow.isVertical ? (SettingsData.dankBarPosition === SettingsData.Position.Right ? parent.width - width : 0) : 0
|
||||||
height: !barWindow.isVertical ? px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing) : undefined
|
height: !barWindow.isVertical ? Theme.px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing, barWindow._dpr) : undefined
|
||||||
width: barWindow.isVertical ? px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing) : undefined
|
width: barWindow.isVertical ? Theme.px(barWindow.effectiveBarThickness + SettingsData.dankBarSpacing, barWindow._dpr) : undefined
|
||||||
anchors {
|
anchors {
|
||||||
left: !barWindow.isVertical ? parent.left : (SettingsData.dankBarPosition === SettingsData.Position.Left ? parent.left : undefined)
|
left: !barWindow.isVertical ? parent.left : (SettingsData.dankBarPosition === SettingsData.Position.Left ? parent.left : undefined)
|
||||||
right: !barWindow.isVertical ? parent.right : (SettingsData.dankBarPosition === SettingsData.Position.Right ? parent.right : undefined)
|
right: !barWindow.isVertical ? parent.right : (SettingsData.dankBarPosition === SettingsData.Position.Right ? parent.right : undefined)
|
||||||
@@ -387,8 +397,8 @@ Item {
|
|||||||
|
|
||||||
transform: Translate {
|
transform: Translate {
|
||||||
id: topBarSlide
|
id: topBarSlide
|
||||||
x: barWindow.isVertical ? px(topBarCore.reveal ? 0 : (SettingsData.dankBarPosition === SettingsData.Position.Right ? barWindow.implicitWidth : -barWindow.implicitWidth)) : 0
|
x: barWindow.isVertical ? Theme.snap(topBarCore.reveal ? 0 : (SettingsData.dankBarPosition === SettingsData.Position.Right ? barWindow.implicitWidth : -barWindow.implicitWidth), barWindow._dpr) : 0
|
||||||
y: !barWindow.isVertical ? px(topBarCore.reveal ? 0 : (SettingsData.dankBarPosition === SettingsData.Position.Bottom ? barWindow.implicitHeight : -barWindow.implicitHeight)) : 0
|
y: !barWindow.isVertical ? Theme.snap(topBarCore.reveal ? 0 : (SettingsData.dankBarPosition === SettingsData.Position.Bottom ? barWindow.implicitHeight : -barWindow.implicitHeight), barWindow._dpr) : 0
|
||||||
|
|
||||||
Behavior on x {
|
Behavior on x {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
@@ -408,10 +418,10 @@ Item {
|
|||||||
Item {
|
Item {
|
||||||
id: barUnitInset
|
id: barUnitInset
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: !barWindow.isVertical ? px(SettingsData.dankBarSpacing) : (axis.edge === "left" ? px(SettingsData.dankBarSpacing) : 0)
|
anchors.leftMargin: !barWindow.isVertical ? Theme.px(SettingsData.dankBarSpacing, barWindow._dpr) : (axis.edge === "left" ? Theme.px(SettingsData.dankBarSpacing, barWindow._dpr) : 0)
|
||||||
anchors.rightMargin: !barWindow.isVertical ? px(SettingsData.dankBarSpacing) : (axis.edge === "right" ? px(SettingsData.dankBarSpacing) : 0)
|
anchors.rightMargin: !barWindow.isVertical ? Theme.px(SettingsData.dankBarSpacing, barWindow._dpr) : (axis.edge === "right" ? Theme.px(SettingsData.dankBarSpacing, barWindow._dpr) : 0)
|
||||||
anchors.topMargin: barWindow.isVertical ? px(SettingsData.dankBarSpacing) : (axis.outerVisualEdge() === "bottom" ? 0 : px(SettingsData.dankBarSpacing))
|
anchors.topMargin: barWindow.isVertical ? Theme.px(SettingsData.dankBarSpacing, barWindow._dpr) : (axis.outerVisualEdge() === "bottom" ? 0 : Theme.px(SettingsData.dankBarSpacing, barWindow._dpr))
|
||||||
anchors.bottomMargin: barWindow.isVertical ? px(SettingsData.dankBarSpacing) : (axis.outerVisualEdge() === "bottom" ? px(SettingsData.dankBarSpacing) : 0)
|
anchors.bottomMargin: barWindow.isVertical ? Theme.px(SettingsData.dankBarSpacing, barWindow._dpr) : (axis.outerVisualEdge() === "bottom" ? Theme.px(SettingsData.dankBarSpacing, barWindow._dpr) : 0)
|
||||||
|
|
||||||
BarCanvas {
|
BarCanvas {
|
||||||
id: barBackground
|
id: barBackground
|
||||||
|
|||||||
@@ -942,14 +942,51 @@ Item {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
StyledText {
|
Row {
|
||||||
text: I18n.tr("Edge Spacing (0 = edge-to-edge)")
|
width: parent.width
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
spacing: Theme.spacingS
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
StyledText {
|
||||||
|
text: I18n.tr("Edge Spacing (0 = edge-to-edge)")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width - edgeSpacingText.implicitWidth - resetEdgeSpacingBtn.width - Theme.spacingS - Theme.spacingM
|
||||||
|
height: 1
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: edgeSpacingText
|
||||||
|
visible: false
|
||||||
|
text: I18n.tr("Edge Spacing (0 = edge-to-edge)")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: resetEdgeSpacingBtn
|
||||||
|
buttonSize: 20
|
||||||
|
iconName: "refresh"
|
||||||
|
iconSize: 12
|
||||||
|
backgroundColor: Theme.surfaceContainerHigh
|
||||||
|
iconColor: Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
SettingsData.setDankBarSpacing(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: Theme.spacingS
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankSlider {
|
DankSlider {
|
||||||
|
id: edgeSpacingSlider
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 24
|
height: 24
|
||||||
value: SettingsData.dankBarSpacing
|
value: SettingsData.dankBarSpacing
|
||||||
@@ -963,6 +1000,13 @@ Item {
|
|||||||
SettingsData.setDankBarSpacing(
|
SettingsData.setDankBarSpacing(
|
||||||
newValue)
|
newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
target: edgeSpacingSlider
|
||||||
|
property: "value"
|
||||||
|
value: SettingsData.dankBarSpacing
|
||||||
|
restoreMode: Binding.RestoreBinding
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -970,19 +1014,56 @@ Item {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
StyledText {
|
Row {
|
||||||
text: I18n.tr("Exclusive Zone Offset")
|
width: parent.width
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
spacing: Theme.spacingS
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
StyledText {
|
||||||
|
text: I18n.tr("Exclusive Zone Offset")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width - exclusiveZoneText.implicitWidth - resetExclusiveZoneBtn.width - Theme.spacingS - Theme.spacingM
|
||||||
|
height: 1
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: exclusiveZoneText
|
||||||
|
visible: false
|
||||||
|
text: I18n.tr("Exclusive Zone Offset")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: resetExclusiveZoneBtn
|
||||||
|
buttonSize: 20
|
||||||
|
iconName: "refresh"
|
||||||
|
iconSize: 12
|
||||||
|
backgroundColor: Theme.surfaceContainerHigh
|
||||||
|
iconColor: Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
SettingsData.setDankBarBottomGap(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: Theme.spacingS
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankSlider {
|
DankSlider {
|
||||||
|
id: exclusiveZoneSlider
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 24
|
height: 24
|
||||||
value: SettingsData.dankBarBottomGap
|
value: SettingsData.dankBarBottomGap
|
||||||
minimum: -100
|
minimum: -50
|
||||||
maximum: 100
|
maximum: 50
|
||||||
unit: ""
|
unit: ""
|
||||||
showValue: true
|
showValue: true
|
||||||
wheelEnabled: false
|
wheelEnabled: false
|
||||||
@@ -991,6 +1072,13 @@ Item {
|
|||||||
SettingsData.setDankBarBottomGap(
|
SettingsData.setDankBarBottomGap(
|
||||||
newValue)
|
newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
target: exclusiveZoneSlider
|
||||||
|
property: "value"
|
||||||
|
value: SettingsData.dankBarBottomGap
|
||||||
|
restoreMode: Binding.RestoreBinding
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -998,14 +1086,51 @@ Item {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
StyledText {
|
Row {
|
||||||
text: I18n.tr("Size")
|
width: parent.width
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
spacing: Theme.spacingS
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
StyledText {
|
||||||
|
text: I18n.tr("Size")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width - sizeText.implicitWidth - resetSizeBtn.width - Theme.spacingS - Theme.spacingM
|
||||||
|
height: 1
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: sizeText
|
||||||
|
visible: false
|
||||||
|
text: I18n.tr("Size")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: resetSizeBtn
|
||||||
|
buttonSize: 20
|
||||||
|
iconName: "refresh"
|
||||||
|
iconSize: 12
|
||||||
|
backgroundColor: Theme.surfaceContainerHigh
|
||||||
|
iconColor: Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
SettingsData.setDankBarInnerPadding(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: Theme.spacingS
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankSlider {
|
DankSlider {
|
||||||
|
id: sizeSlider
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 24
|
height: 24
|
||||||
value: SettingsData.dankBarInnerPadding
|
value: SettingsData.dankBarInnerPadding
|
||||||
@@ -1019,6 +1144,13 @@ Item {
|
|||||||
SettingsData.setDankBarInnerPadding(
|
SettingsData.setDankBarInnerPadding(
|
||||||
newValue)
|
newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
target: sizeSlider
|
||||||
|
property: "value"
|
||||||
|
value: SettingsData.dankBarInnerPadding
|
||||||
|
restoreMode: Binding.RestoreBinding
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1056,14 +1188,227 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankToggle {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
text: I18n.tr("Border")
|
spacing: Theme.spacingM
|
||||||
description: "Add a 1px border to the bar. Smart edge detection only shows border on exposed sides."
|
|
||||||
checked: SettingsData.dankBarBorderEnabled
|
DankToggle {
|
||||||
onToggled: checked => {
|
width: parent.width
|
||||||
SettingsData.setDankBarBorderEnabled(checked)
|
text: I18n.tr("Border")
|
||||||
}
|
description: "Add a 1px border to the bar. Smart edge detection only shows border on exposed sides."
|
||||||
|
checked: SettingsData.dankBarBorderEnabled
|
||||||
|
onToggled: checked => {
|
||||||
|
SettingsData.setDankBarBorderEnabled(checked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
leftPadding: Theme.spacingM
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
visible: SettingsData.dankBarBorderEnabled
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width - parent.leftPadding
|
||||||
|
height: 1
|
||||||
|
color: Theme.outline
|
||||||
|
opacity: 0.2
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width - parent.leftPadding
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width - borderColorGroup.width - Theme.spacingM
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Border Color")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Choose the border accent color")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankButtonGroup {
|
||||||
|
id: borderColorGroup
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
model: ["Surface", "Secondary", "Primary"]
|
||||||
|
currentIndex: {
|
||||||
|
const colorOption = SettingsData.dankBarBorderColor || "surfaceText"
|
||||||
|
switch (colorOption) {
|
||||||
|
case "surfaceText": return 0
|
||||||
|
case "secondary": return 1
|
||||||
|
case "primary": return 2
|
||||||
|
default: return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onSelectionChanged: (index, selected) => {
|
||||||
|
if (selected) {
|
||||||
|
let newColor = "surfaceText"
|
||||||
|
switch (index) {
|
||||||
|
case 0: newColor = "surfaceText"; break
|
||||||
|
case 1: newColor = "secondary"; break
|
||||||
|
case 2: newColor = "primary"; break
|
||||||
|
}
|
||||||
|
if (SettingsData.dankBarBorderColor !== newColor) {
|
||||||
|
SettingsData.dankBarBorderColor = newColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width - parent.leftPadding
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Border Opacity")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width - borderOpacityText.implicitWidth - resetBorderOpacityBtn.width - Theme.spacingS - Theme.spacingM
|
||||||
|
height: 1
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: borderOpacityText
|
||||||
|
visible: false
|
||||||
|
text: I18n.tr("Border Opacity")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: resetBorderOpacityBtn
|
||||||
|
buttonSize: 20
|
||||||
|
iconName: "refresh"
|
||||||
|
iconSize: 12
|
||||||
|
backgroundColor: Theme.surfaceContainerHigh
|
||||||
|
iconColor: Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
SettingsData.dankBarBorderOpacity = 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: Theme.spacingS
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankSlider {
|
||||||
|
id: borderOpacitySlider
|
||||||
|
width: parent.width
|
||||||
|
height: 24
|
||||||
|
value: (SettingsData.dankBarBorderOpacity ?? 1.0) * 100
|
||||||
|
minimum: 0
|
||||||
|
maximum: 100
|
||||||
|
unit: "%"
|
||||||
|
showValue: true
|
||||||
|
wheelEnabled: false
|
||||||
|
thumbOutlineColor: Theme.surfaceContainerHigh
|
||||||
|
onSliderValueChanged: newValue => {
|
||||||
|
SettingsData.dankBarBorderOpacity = newValue / 100
|
||||||
|
}
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
target: borderOpacitySlider
|
||||||
|
property: "value"
|
||||||
|
value: (SettingsData.dankBarBorderOpacity ?? 1.0) * 100
|
||||||
|
restoreMode: Binding.RestoreBinding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width - parent.leftPadding
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Border Thickness")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width - borderThicknessText.implicitWidth - resetBorderThicknessBtn.width - Theme.spacingS - Theme.spacingM
|
||||||
|
height: 1
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: borderThicknessText
|
||||||
|
visible: false
|
||||||
|
text: I18n.tr("Border Thickness")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: resetBorderThicknessBtn
|
||||||
|
buttonSize: 20
|
||||||
|
iconName: "refresh"
|
||||||
|
iconSize: 12
|
||||||
|
backgroundColor: Theme.surfaceContainerHigh
|
||||||
|
iconColor: Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
onClicked: {
|
||||||
|
SettingsData.dankBarBorderThickness = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: Theme.spacingS
|
||||||
|
height: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankSlider {
|
||||||
|
id: borderThicknessSlider
|
||||||
|
width: parent.width
|
||||||
|
height: 24
|
||||||
|
value: SettingsData.dankBarBorderThickness ?? 1
|
||||||
|
minimum: 1
|
||||||
|
maximum: 10
|
||||||
|
unit: "px"
|
||||||
|
showValue: true
|
||||||
|
wheelEnabled: false
|
||||||
|
thumbOutlineColor: Theme.surfaceContainerHigh
|
||||||
|
onSliderValueChanged: newValue => {
|
||||||
|
SettingsData.dankBarBorderThickness = newValue
|
||||||
|
}
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
target: borderThicknessSlider
|
||||||
|
property: "value"
|
||||||
|
value: SettingsData.dankBarBorderThickness ?? 1
|
||||||
|
restoreMode: Binding.RestoreBinding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ Singleton {
|
|||||||
|
|
||||||
property var outputs: ({})
|
property var outputs: ({})
|
||||||
property var windows: []
|
property var windows: []
|
||||||
|
property var displayScales: ({})
|
||||||
|
|
||||||
property bool inOverview: false
|
property bool inOverview: false
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ Singleton {
|
|||||||
const outputsData = JSON.parse(text)
|
const outputsData = JSON.parse(text)
|
||||||
outputs = outputsData
|
outputs = outputsData
|
||||||
console.log("NiriService: Loaded", Object.keys(outputsData).length, "outputs")
|
console.log("NiriService: Loaded", Object.keys(outputsData).length, "outputs")
|
||||||
|
updateDisplayScales()
|
||||||
if (windows.length > 0) {
|
if (windows.length > 0) {
|
||||||
windows = sortWindowsByLayout(windows)
|
windows = sortWindowsByLayout(windows)
|
||||||
}
|
}
|
||||||
@@ -169,6 +171,20 @@ Singleton {
|
|||||||
outputsProcess.running = true
|
outputsProcess.running = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateDisplayScales() {
|
||||||
|
if (!outputs || Object.keys(outputs).length === 0) return
|
||||||
|
|
||||||
|
const scales = {}
|
||||||
|
for (const outputName in outputs) {
|
||||||
|
const output = outputs[outputName]
|
||||||
|
if (output.logical && output.logical.scale !== undefined) {
|
||||||
|
scales[outputName] = output.logical.scale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
displayScales = scales
|
||||||
|
}
|
||||||
|
|
||||||
function sortWindowsByLayout(windowList) {
|
function sortWindowsByLayout(windowList) {
|
||||||
return [...windowList].sort((a, b) => {
|
return [...windowList].sort((a, b) => {
|
||||||
const aWorkspace = workspaces[a.workspace_id]
|
const aWorkspace = workspaces[a.workspace_id]
|
||||||
@@ -395,6 +411,7 @@ Singleton {
|
|||||||
function handleOutputsChanged(data) {
|
function handleOutputsChanged(data) {
|
||||||
if (!data.outputs) return
|
if (!data.outputs) return
|
||||||
outputs = data.outputs
|
outputs = data.outputs
|
||||||
|
updateDisplayScales()
|
||||||
windows = sortWindowsByLayout(windows)
|
windows = sortWindowsByLayout(windows)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,6 +427,7 @@ Singleton {
|
|||||||
if (ToastService.toastVisible && ToastService.currentLevel === ToastService.levelError) {
|
if (ToastService.toastVisible && ToastService.currentLevel === ToastService.levelError) {
|
||||||
ToastService.hideToast()
|
ToastService.hideToast()
|
||||||
}
|
}
|
||||||
|
fetchOutputs()
|
||||||
if (hasInitialConnection && !suppressConfigToast && !suppressNextConfigToast && !matugenSuppression) {
|
if (hasInitialConnection && !suppressConfigToast && !suppressNextConfigToast && !matugenSuppression) {
|
||||||
ToastService.showInfo("niri: config reloaded")
|
ToastService.showInfo("niri: config reloaded")
|
||||||
} else if (suppressNextConfigToast) {
|
} else if (suppressNextConfigToast) {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Hyprland
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: root
|
id: root
|
||||||
@@ -69,9 +71,21 @@ PanelWindow {
|
|||||||
|
|
||||||
readonly property real screenWidth: root.screen.width
|
readonly property real screenWidth: root.screen.width
|
||||||
readonly property real screenHeight: root.screen.height
|
readonly property real screenHeight: root.screen.height
|
||||||
readonly property real dpr: root.screen.devicePixelRatio
|
readonly property real dpr: {
|
||||||
|
if (CompositorService.isNiri && root.screen) {
|
||||||
|
const niriScale = NiriService.displayScales[root.screen.name]
|
||||||
|
if (niriScale !== undefined) return niriScale
|
||||||
|
}
|
||||||
|
if (CompositorService.isHyprland && root.screen) {
|
||||||
|
const hyprlandMonitor = Hyprland.monitors.values.find(m => m.name === root.screen.name)
|
||||||
|
if (hyprlandMonitor?.scale !== undefined) return hyprlandMonitor.scale
|
||||||
|
}
|
||||||
|
return root.screen?.devicePixelRatio || 1
|
||||||
|
}
|
||||||
|
|
||||||
readonly property real calculatedX: {
|
readonly property real alignedWidth: Theme.px(popupWidth, dpr)
|
||||||
|
readonly property real alignedHeight: Theme.px(popupHeight, dpr)
|
||||||
|
readonly property real alignedX: Theme.snap((() => {
|
||||||
if (SettingsData.dankBarPosition === SettingsData.Position.Left) {
|
if (SettingsData.dankBarPosition === SettingsData.Position.Left) {
|
||||||
return triggerY
|
return triggerY
|
||||||
} else if (SettingsData.dankBarPosition === SettingsData.Position.Right) {
|
} else if (SettingsData.dankBarPosition === SettingsData.Position.Right) {
|
||||||
@@ -80,8 +94,8 @@ PanelWindow {
|
|||||||
const centerX = triggerX + (triggerWidth / 2) - (popupWidth / 2)
|
const centerX = triggerX + (triggerWidth / 2) - (popupWidth / 2)
|
||||||
return Math.max(Theme.popupDistance, Math.min(screenWidth - popupWidth - Theme.popupDistance, centerX))
|
return Math.max(Theme.popupDistance, Math.min(screenWidth - popupWidth - Theme.popupDistance, centerX))
|
||||||
}
|
}
|
||||||
}
|
})(), dpr)
|
||||||
readonly property real calculatedY: {
|
readonly property real alignedY: Theme.snap((() => {
|
||||||
if (SettingsData.dankBarPosition === SettingsData.Position.Left || SettingsData.dankBarPosition === SettingsData.Position.Right) {
|
if (SettingsData.dankBarPosition === SettingsData.Position.Left || SettingsData.dankBarPosition === SettingsData.Position.Right) {
|
||||||
const centerY = triggerX + (triggerWidth / 2) - (popupHeight / 2)
|
const centerY = triggerX + (triggerWidth / 2) - (popupHeight / 2)
|
||||||
return Math.max(Theme.popupDistance, Math.min(screenHeight - popupHeight - Theme.popupDistance, centerY))
|
return Math.max(Theme.popupDistance, Math.min(screenHeight - popupHeight - Theme.popupDistance, centerY))
|
||||||
@@ -90,12 +104,7 @@ PanelWindow {
|
|||||||
} else {
|
} else {
|
||||||
return Math.max(Theme.popupDistance, Math.min(screenHeight - popupHeight - Theme.popupDistance, triggerY + Theme.popupDistance))
|
return Math.max(Theme.popupDistance, Math.min(screenHeight - popupHeight - Theme.popupDistance, triggerY + Theme.popupDistance))
|
||||||
}
|
}
|
||||||
}
|
})(), dpr)
|
||||||
|
|
||||||
readonly property real alignedWidth: Theme.snap(popupWidth, dpr)
|
|
||||||
readonly property real alignedHeight: Theme.snap(popupHeight, dpr)
|
|
||||||
readonly property real alignedX: Theme.snap(calculatedX, dpr)
|
|
||||||
readonly property real alignedY: Theme.snap(calculatedY, dpr)
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -117,6 +126,7 @@ PanelWindow {
|
|||||||
height: alignedHeight
|
height: alignedHeight
|
||||||
active: root.visible
|
active: root.visible
|
||||||
asynchronous: false
|
asynchronous: false
|
||||||
|
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true"
|
||||||
opacity: shouldBeVisible ? 1 : 0
|
opacity: shouldBeVisible ? 1 : 0
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
|
|||||||
Reference in New Issue
Block a user