1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 05:25:41 -05:00

displays: allow choosing logarithmic mode for backlight devices

This commit is contained in:
bbedward
2025-11-04 17:01:50 -05:00
parent cd51eb25ce
commit 1ac95f0d14
4 changed files with 259 additions and 80 deletions

View File

@@ -60,6 +60,8 @@ Singleton {
property bool showThirdPartyPlugins: false
property string launchPrefix: ""
property string lastBrightnessDevice: ""
property var brightnessLogarithmicDevices: ({})
property var brightnessUserSetValues: ({})
property int selectedGpuIndex: 0
property bool nvidiaGpuTempEnabled: false
@@ -107,6 +109,8 @@ Singleton {
wallpaperPathDark = settings.wallpaperPathDark !== undefined ? settings.wallpaperPathDark : ""
monitorWallpapersLight = settings.monitorWallpapersLight !== undefined ? settings.monitorWallpapersLight : {}
monitorWallpapersDark = settings.monitorWallpapersDark !== undefined ? settings.monitorWallpapersDark : {}
brightnessLogarithmicDevices = settings.brightnessLogarithmicDevices !== undefined ? settings.brightnessLogarithmicDevices : {}
brightnessUserSetValues = settings.brightnessUserSetValues !== undefined ? settings.brightnessUserSetValues : {}
doNotDisturb = settings.doNotDisturb !== undefined ? settings.doNotDisturb : false
nightModeEnabled = settings.nightModeEnabled !== undefined ? settings.nightModeEnabled : false
nightModeTemperature = settings.nightModeTemperature !== undefined ? settings.nightModeTemperature : 4500
@@ -185,6 +189,8 @@ Singleton {
"wallpaperPathDark": wallpaperPathDark,
"monitorWallpapersLight": monitorWallpapersLight,
"monitorWallpapersDark": monitorWallpapersDark,
"brightnessLogarithmicDevices": brightnessLogarithmicDevices,
"brightnessUserSetValues": brightnessUserSetValues,
"doNotDisturb": doNotDisturb,
"nightModeEnabled": nightModeEnabled,
"nightModeTemperature": nightModeTemperature,
@@ -268,7 +274,7 @@ Singleton {
}
function cleanupUnusedKeys() {
const validKeys = ["isLightMode", "wallpaperPath", "perMonitorWallpaper", "monitorWallpapers", "perModeWallpaper", "wallpaperPathLight", "wallpaperPathDark", "monitorWallpapersLight", "monitorWallpapersDark", "doNotDisturb", "nightModeEnabled", "nightModeTemperature", "nightModeHighTemperature", "nightModeAutoEnabled", "nightModeAutoMode", "nightModeStartHour", "nightModeStartMinute", "nightModeEndHour", "nightModeEndMinute", "latitude", "longitude", "nightModeUseIPLocation", "nightModeLocationProvider", "pinnedApps", "selectedGpuIndex", "nvidiaGpuTempEnabled", "nonNvidiaGpuTempEnabled", "enabledGpuPciIds", "wallpaperCyclingEnabled", "wallpaperCyclingMode", "wallpaperCyclingInterval", "wallpaperCyclingTime", "monitorCyclingSettings", "lastBrightnessDevice", "launchPrefix", "wallpaperTransition", "includedTransitions", "recentColors", "showThirdPartyPlugins", "configVersion"]
const validKeys = ["isLightMode", "wallpaperPath", "perMonitorWallpaper", "monitorWallpapers", "perModeWallpaper", "wallpaperPathLight", "wallpaperPathDark", "monitorWallpapersLight", "monitorWallpapersDark", "doNotDisturb", "nightModeEnabled", "nightModeTemperature", "nightModeHighTemperature", "nightModeAutoEnabled", "nightModeAutoMode", "nightModeStartHour", "nightModeStartMinute", "nightModeEndHour", "nightModeEndMinute", "latitude", "longitude", "nightModeUseIPLocation", "nightModeLocationProvider", "pinnedApps", "selectedGpuIndex", "nvidiaGpuTempEnabled", "nonNvidiaGpuTempEnabled", "enabledGpuPciIds", "wallpaperCyclingEnabled", "wallpaperCyclingMode", "wallpaperCyclingInterval", "wallpaperCyclingTime", "monitorCyclingSettings", "lastBrightnessDevice", "brightnessLogarithmicDevices", "brightnessUserSetValues", "launchPrefix", "wallpaperTransition", "includedTransitions", "recentColors", "showThirdPartyPlugins", "configVersion"]
try {
const content = settingsFile.text()
@@ -656,6 +662,36 @@ Singleton {
saveSettings()
}
function setBrightnessLogarithmic(deviceName, enabled) {
var newSettings = Object.assign({}, brightnessLogarithmicDevices)
if (enabled) {
newSettings[deviceName] = true
} else {
delete newSettings[deviceName]
}
brightnessLogarithmicDevices = newSettings
saveSettings()
if (typeof DisplayService !== "undefined") {
DisplayService.updateDeviceBrightnessDisplay(deviceName)
}
}
function getBrightnessLogarithmic(deviceName) {
return brightnessLogarithmicDevices[deviceName] === true
}
function setBrightnessUserSetValue(deviceName, value) {
var newValues = Object.assign({}, brightnessUserSetValues)
newValues[deviceName] = value
brightnessUserSetValues = newValues
saveSettings()
}
function getBrightnessUserSetValue(deviceName) {
return brightnessUserSetValues[deviceName]
}
function setSelectedGpuIndex(index) {
selectedGpuIndex = index
saveSettings()

View File

@@ -210,103 +210,147 @@ Rectangle {
required property var modelData
required property int index
property real deviceBrightness: {
DisplayService.brightnessVersion
return DisplayService.getDeviceBrightness(modelData.name)
}
width: parent.width
height: 80
height: 100
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
border.color: modelData.name === currentDeviceName ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: modelData.name === currentDeviceName ? 2 : 0
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Theme.spacingM
spacing: Theme.spacingM
Column {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: 2
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: {
const deviceClass = modelData.class || ""
const deviceName = modelData.name || ""
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: 2
if (deviceClass === "backlight" || deviceClass === "ddc") {
const brightness = DisplayService.getDeviceBrightness(modelData.name)
if (brightness <= 33)
return "brightness_low"
if (brightness <= 66)
return "brightness_medium"
return "brightness_high"
} else if (deviceName.includes("kbd")) {
return "keyboard"
} else {
return "lightbulb"
DankIcon {
name: {
const deviceClass = modelData.class || ""
const deviceName = modelData.name || ""
if (deviceClass === "backlight" || deviceClass === "ddc") {
if (deviceBrightness <= 33)
return "brightness_low"
if (deviceBrightness <= 66)
return "brightness_medium"
return "brightness_high"
} else if (deviceName.includes("kbd")) {
return "keyboard"
} else {
return "lightbulb"
}
}
size: Theme.iconSize
color: modelData.name === currentDeviceName ? Theme.primary : Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: Math.round(deviceBrightness) + "%"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
size: Theme.iconSize
color: modelData.name === currentDeviceName ? Theme.primary : Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: Math.round(DisplayService.getDeviceBrightness(modelData.name)) + "%"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.width - parent.spacing - 50
StyledText {
text: {
const name = modelData.name || ""
const deviceClass = modelData.class || ""
if (deviceClass === "backlight") {
return name.replace("_", " ").replace(/\b\w/g, c => c.toUpperCase())
}
return name
}
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: modelData.name === currentDeviceName ? Font.Medium : Font.Normal
elide: Text.ElideRight
width: parent.width
}
StyledText {
text: modelData.name
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideRight
width: parent.width
}
StyledText {
text: {
const deviceClass = modelData.class || ""
if (deviceClass === "backlight")
return "Backlight device"
if (deviceClass === "ddc")
return "DDC/CI monitor"
if (deviceClass === "leds")
return "LED device"
return deviceClass
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideRight
width: parent.width
}
}
}
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.parent.width - parent.parent.anchors.leftMargin - parent.spacing - 50 - Theme.spacingM
Rectangle {
width: parent.width
height: 24
radius: height / 2
color: SessionData.getBrightnessLogarithmic(modelData.name) ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05)
StyledText {
text: {
const name = modelData.name || ""
const deviceClass = modelData.class || ""
if (deviceClass === "backlight") {
return name.replace("_", " ").replace(/\b\w/g, c => c.toUpperCase())
}
return name
Row {
anchors.centerIn: parent
spacing: 4
DankIcon {
name: "show_chart"
size: 14
color: SessionData.getBrightnessLogarithmic(modelData.name) ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: SessionData.getBrightnessLogarithmic(modelData.name) ? "Logarithmic" : "Linear"
font.pixelSize: Theme.fontSizeSmall
color: SessionData.getBrightnessLogarithmic(modelData.name) ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: modelData.name === currentDeviceName ? Font.Medium : Font.Normal
elide: Text.ElideRight
width: parent.width
}
StyledText {
text: modelData.name
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideRight
width: parent.width
}
StyledText {
text: {
const deviceClass = modelData.class || ""
if (deviceClass === "backlight")
return "Backlight device"
if (deviceClass === "ddc")
return "DDC/CI monitor"
if (deviceClass === "leds")
return "LED device"
return deviceClass
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
const currentState = SessionData.getBrightnessLogarithmic(modelData.name)
SessionData.setBrightnessLogarithmic(modelData.name, !currentState)
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideRight
width: parent.width
}
}
}
MouseArea {
anchors.fill: parent
anchors.bottomMargin: 28
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {

View File

@@ -71,6 +71,7 @@ Row {
}
property real targetBrightness: {
DisplayService.brightnessVersion
if (!targetDeviceName) {
return 0
}

View File

@@ -1,6 +1,6 @@
pragma Singleton
pragma ComponentBehavior
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
@@ -13,9 +13,12 @@ Singleton {
property bool brightnessAvailable: devices.length > 0
property var devices: []
property var deviceBrightness: ({})
property var deviceBrightnessUserSet: ({})
property int brightnessVersion: 0
property string currentDevice: ""
property string lastIpcDevice: ""
property int brightnessLevel: {
brightnessVersion
const deviceToUse = lastIpcDevice === "" ? getDefaultDevice() : (lastIpcDevice || currentDevice)
if (!deviceToUse) {
return 50
@@ -52,17 +55,30 @@ Singleton {
devices = newDevices
}
const isLogarithmic = SessionData.getBrightnessLogarithmic(device.id)
const userSetValue = deviceBrightnessUserSet[device.id]
let displayValue = device.currentPercent
if (isLogarithmic) {
if (userSetValue !== undefined) {
displayValue = userSetValue
} else {
displayValue = linearToLogarithmic(device.currentPercent)
}
}
const oldValue = deviceBrightness[device.id]
const newBrightness = Object.assign({}, deviceBrightness)
newBrightness[device.id] = device.currentPercent
newBrightness[device.id] = displayValue
deviceBrightness = newBrightness
brightnessVersion++
const shouldSuppress = suppressSignal || suppressNextOsd
if (suppressNextOsd) {
suppressNextOsd = false
}
if (!shouldSuppress && oldValue !== device.currentPercent) {
if (!shouldSuppress && oldValue !== displayValue) {
brightnessChanged()
}
}
@@ -84,9 +100,21 @@ Singleton {
const newBrightness = {}
for (const device of state.devices) {
newBrightness[device.id] = device.currentPercent
const isLogarithmic = SessionData.getBrightnessLogarithmic(device.id)
const userSetValue = deviceBrightnessUserSet[device.id]
if (isLogarithmic) {
if (userSetValue !== undefined) {
newBrightness[device.id] = userSetValue
} else {
newBrightness[device.id] = linearToLogarithmic(device.currentPercent)
}
} else {
newBrightness[device.id] = device.currentPercent
}
}
deviceBrightness = newBrightness
brightnessVersion++
brightnessAvailable = devices.length > 0
@@ -129,10 +157,24 @@ Singleton {
suppressNextOsd = true
}
DMSService.sendRequest("brightness.setBrightness", {
"device": actualDevice,
"percent": clampedValue
}, response => {
const isLogarithmic = SessionData.getBrightnessLogarithmic(actualDevice)
if (isLogarithmic) {
const newUserSet = Object.assign({}, deviceBrightnessUserSet)
newUserSet[actualDevice] = clampedValue
deviceBrightnessUserSet = newUserSet
SessionData.setBrightnessUserSetValue(actualDevice, clampedValue)
}
const params = {
"device": actualDevice,
"percent": clampedValue
}
if (isLogarithmic) {
params.logarithmic = true
}
DMSService.sendRequest("brightness.setBrightness", params, response => {
if (response.error) {
console.error("DisplayService: Failed to set brightness:", response.error)
ToastService.showError("Failed to set brightness: " + response.error)
@@ -167,6 +209,12 @@ Singleton {
return 50
}
function linearToLogarithmic(linearPercent) {
const normalized = linearPercent / 100.0
const logPercent = Math.pow(normalized, 2.0) * 100.0
return Math.round(logPercent)
}
function getDefaultDevice() {
for (const device of devices) {
if (device.class === "backlight") {
@@ -504,8 +552,14 @@ Singleton {
})
}
function updateDeviceBrightnessDisplay(deviceName) {
brightnessVersion++
brightnessChanged()
}
Component.onCompleted: {
nightModeEnabled = SessionData.nightModeEnabled
deviceBrightnessUserSet = Object.assign({}, SessionData.brightnessUserSetValues)
if (DMSService.isConnected) {
checkGammaControlAvailability()
}
@@ -717,11 +771,55 @@ Singleton {
let result = "Available devices:\n"
for (const device of root.devices) {
result += device.id + " (" + device.class + ")\n"
const isLog = SessionData.getBrightnessLogarithmic(device.id)
result += device.id + " (" + device.class + ")" + (isLog ? " [logarithmic]" : "") + "\n"
}
return result
}
function enableLogarithmic(device: string): string {
const targetDevice = device || root.currentDevice
if (!targetDevice) {
return "No device specified"
}
if (!root.devices.some(d => d.id === targetDevice)) {
return "Device not found: " + targetDevice
}
SessionData.setBrightnessLogarithmic(targetDevice, true)
return "Logarithmic mode enabled for " + targetDevice
}
function disableLogarithmic(device: string): string {
const targetDevice = device || root.currentDevice
if (!targetDevice) {
return "No device specified"
}
if (!root.devices.some(d => d.id === targetDevice)) {
return "Device not found: " + targetDevice
}
SessionData.setBrightnessLogarithmic(targetDevice, false)
return "Logarithmic mode disabled for " + targetDevice
}
function toggleLogarithmic(device: string): string {
const targetDevice = device || root.currentDevice
if (!targetDevice) {
return "No device specified"
}
if (!root.devices.some(d => d.id === targetDevice)) {
return "Device not found: " + targetDevice
}
const currentState = SessionData.getBrightnessLogarithmic(targetDevice)
SessionData.setBrightnessLogarithmic(targetDevice, !currentState)
return "Logarithmic mode " + (!currentState ? "enabled" : "disabled") + " for " + targetDevice
}
target: "brightness"
}