1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-03 02:52:07 -04:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Artem
24e3024b57 fix(brightness): refresh sysfs cache on hotplug (#1674)
* fix(brightness): refresh sysfs cache on hotplug

The SysfsBackend used a cache that was never refreshed on display hot plug, causing new backlight devices to not appear in IPC until restart.

This adds Rescan() to SysfsBackend and calls it in Manager.Rescan(), matching the behavior of DDCBackend.

Fixes: hotplugged external monitor brightness control via IPC

* make fmt

---------

Co-authored-by: bbedward <bbedward@gmail.com>
2026-02-14 14:00:01 -05:00
bbedward
52d5af11ba dankdash: fix triggering when clock widget isnt present on bar
fixes #1601
2026-02-14 13:54:51 -05:00
bbedward
44a45b00cf widgets: cleanup rectangles across popouts, modals, OSDs 2026-02-14 11:15:26 -05:00
bbedward
2b78fe5b9f popout: remove double rectangle artifact 2026-02-14 10:45:50 -05:00
bbedward
14f92669c6 doctor: add cups-pk-helper 2026-02-14 10:38:03 -05:00
22 changed files with 146 additions and 271 deletions

View File

@@ -689,6 +689,19 @@ func checkOptionalDependencies() []checkResult {
logindStatus, logindMsg := getOptionalDBusStatus("org.freedesktop.login1")
results = append(results, checkResult{catOptionalFeatures, "logind", logindStatus, logindMsg, "Session management", optionalFeaturesURL})
cupsPkHelperBus := "org.opensuse.CupsPkHelper.Mechanism"
var cupsPkStatus status
var cupsPkMsg string
switch {
case utils.IsDBusServiceAvailable(cupsPkHelperBus):
cupsPkStatus, cupsPkMsg = statusOK, "Running"
case utils.IsDBusServiceActivatable(cupsPkHelperBus):
cupsPkStatus, cupsPkMsg = statusOK, "Available"
default:
cupsPkStatus, cupsPkMsg = statusWarn, "Not available (install cups-pk-helper)"
}
results = append(results, checkResult{catOptionalFeatures, "cups-pk-helper", cupsPkStatus, cupsPkMsg, "Printer management", optionalFeaturesURL})
results = append(results, checkI2CAvailability())
terminals := []string{"ghostty", "kitty", "alacritty", "foot", "wezterm"}

View File

@@ -96,6 +96,12 @@ func (m *Manager) Rescan() {
}
}
if m.sysfsReady && m.sysfsBackend != nil {
if err := m.sysfsBackend.Rescan(); err != nil {
log.Debugf("Sysfs rescan failed: %v", err)
}
}
m.updateState()
}

View File

@@ -101,6 +101,10 @@ func shouldSuppressDevice(name string) bool {
return false
}
func (b *SysfsBackend) Rescan() error {
return b.scanDevices()
}
func (b *SysfsBackend) GetDevices() ([]Device, error) {
devices := make([]Device, 0)

View File

@@ -1,6 +1,8 @@
package utils
import (
"slices"
"github.com/godbus/dbus/v5"
)
@@ -18,3 +20,18 @@ func IsDBusServiceAvailable(busName string) bool {
}
return owned
}
func IsDBusServiceActivatable(busName string) bool {
conn, err := dbus.ConnectSystemBus()
if err != nil {
return false
}
defer conn.Close()
obj := conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
var activatable []string
if err := obj.Call("org.freedesktop.DBus.ListActivatableNames", 0).Store(&activatable); err != nil {
return false
}
return slices.Contains(activatable, busName)
}

View File

@@ -251,13 +251,20 @@ Item {
active: false
asynchronous: false
Component.onCompleted: {
PopoutService.dankDashPopoutLoader = dankDashPopoutLoader;
}
onLoaded: {
if (item) {
PopoutService.dankDashPopout = item;
PopoutService._onDankDashPopoutLoaded();
}
}
sourceComponent: Component {
DankDashPopout {
id: dankDashPopout
Component.onCompleted: {
PopoutService.dankDashPopout = dankDashPopout;
}
}
}
}

View File

@@ -3,7 +3,6 @@ import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
@@ -378,11 +377,11 @@ Item {
}
}
DankRectangle {
Rectangle {
anchors.fill: parent
color: root.backgroundColor
borderColor: root.borderColor
borderWidth: root.borderWidth
border.color: root.borderColor
border.width: root.borderWidth
radius: root.cornerRadius
}

View File

@@ -357,11 +357,11 @@ Item {
}
}
DankRectangle {
Rectangle {
anchors.fill: parent
color: root.backgroundColor
borderColor: root.borderColor
borderWidth: root.borderWidth
border.color: root.borderColor
border.width: root.borderWidth
radius: root.cornerRadius
}

View File

@@ -54,9 +54,6 @@ DankPopout {
property alias launcherContent: launcherContent
color: "transparent"
radius: Theme.cornerRadius
antialiasing: true
smooth: true
QtObject {
id: modalAdapter
@@ -68,35 +65,6 @@ DankPopout {
}
}
Repeater {
model: [
{
"margin": -3,
"color": Qt.rgba(0, 0, 0, 0.05),
"z": -3
},
{
"margin": -2,
"color": Qt.rgba(0, 0, 0, 0.08),
"z": -2
},
{
"margin": 0,
"color": Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12),
"z": -1
}
]
Rectangle {
anchors.fill: parent
anchors.margins: modelData.margin
color: "transparent"
radius: parent.radius + Math.abs(modelData.margin)
border.color: modelData.color
border.width: 0
z: modelData.z
}
}
FocusScope {
anchors.fill: parent
focus: true

View File

@@ -115,11 +115,6 @@ DankPopout {
property alias bluetoothCodecSelector: bluetoothCodecSelector
color: "transparent"
radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
antialiasing: true
smooth: true
Rectangle {
anchors.fill: parent

View File

@@ -48,11 +48,6 @@ DankPopout {
implicitHeight: contentColumn.implicitHeight + Theme.spacingL * 2
color: "transparent"
radius: Theme.cornerRadius
border.color: Theme.outlineMedium
border.width: 0
antialiasing: true
smooth: true
focus: true
Component.onCompleted: {
if (root.shouldBeVisible) {
@@ -78,35 +73,6 @@ DankPopout {
target: root
}
Rectangle {
anchors.fill: parent
anchors.margins: -3
color: "transparent"
radius: parent.radius + 3
border.color: Qt.rgba(0, 0, 0, 0.05)
border.width: 0
z: -3
}
Rectangle {
anchors.fill: parent
anchors.margins: -2
color: "transparent"
radius: parent.radius + 2
border.color: Theme.shadowMedium
border.width: 0
z: -2
}
Rectangle {
anchors.fill: parent
color: "transparent"
border.color: Theme.outlineStrong
border.width: 0
radius: parent.radius
z: -1
}
Column {
id: contentColumn

View File

@@ -111,11 +111,6 @@ DankPopout {
implicitHeight: contentColumn.implicitHeight + Theme.spacingL * 2
color: "transparent"
radius: Theme.cornerRadius
border.color: Theme.outlineMedium
border.width: 0
antialiasing: true
smooth: true
focus: true
Component.onCompleted: {
@@ -142,15 +137,6 @@ DankPopout {
}
}
Rectangle {
anchors.fill: parent
color: "transparent"
border.color: Theme.outlineStrong
border.width: 0
radius: parent.radius
z: -1
}
Column {
id: contentColumn

View File

@@ -37,9 +37,6 @@ DankPopout {
implicitHeight: contentColumn.height + Theme.spacingL * 2
color: "transparent"
radius: Theme.cornerRadius
border.color: Theme.outlineMedium
border.width: 0
focus: true
Keys.onPressed: event => {

View File

@@ -170,7 +170,6 @@ DankPopout {
implicitHeight: contentColumn.height + Theme.spacingM * 2
color: "transparent"
radius: Theme.cornerRadius
focus: true
Component.onCompleted: {

View File

@@ -551,10 +551,18 @@ Variants {
layer.enabled: true
clip: false
DankRectangle {
Rectangle {
anchors.fill: parent
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, backgroundTransparency)
overlayColor: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
border.color: Theme.outlineMedium
border.width: 1
radius: Theme.cornerRadius
}
Rectangle {
anchors.fill: parent
color: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04)
radius: Theme.cornerRadius
}
}

View File

@@ -132,9 +132,6 @@ DankPopout {
}
color: "transparent"
radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
focus: true
Component.onCompleted: {

View File

@@ -1,7 +1,6 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
import QtQuick.Shapes
import Quickshell
import Quickshell.Wayland
import Quickshell.Services.Notifications
@@ -268,65 +267,13 @@ PanelWindow {
}
}
Shape {
Rectangle {
id: backgroundShape
anchors.fill: parent
preferredRendererType: Shape.CurveRenderer
readonly property real radius: Theme.cornerRadius
readonly property color fillColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
readonly property color strokeColor: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.outline, 0.08)
readonly property real strokeWidth: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
ShapePath {
fillColor: backgroundShape.fillColor
strokeColor: backgroundShape.strokeColor
strokeWidth: backgroundShape.strokeWidth
startX: backgroundShape.radius
startY: 0
PathLine {
x: backgroundShape.width - backgroundShape.radius
y: 0
}
PathQuad {
x: backgroundShape.width
y: backgroundShape.radius
controlX: backgroundShape.width
controlY: 0
}
PathLine {
x: backgroundShape.width
y: backgroundShape.height - backgroundShape.radius
}
PathQuad {
x: backgroundShape.width - backgroundShape.radius
y: backgroundShape.height
controlX: backgroundShape.width
controlY: backgroundShape.height
}
PathLine {
x: backgroundShape.radius
y: backgroundShape.height
}
PathQuad {
x: 0
y: backgroundShape.height - backgroundShape.radius
controlX: 0
controlY: backgroundShape.height
}
PathLine {
x: 0
y: backgroundShape.radius
}
PathQuad {
x: backgroundShape.radius
y: 0
controlX: 0
controlY: 0
}
}
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.outline, 0.08)
border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
}
Rectangle {

View File

@@ -25,10 +25,6 @@ DankPopout {
implicitHeight: popoutColumn.implicitHeight + Theme.spacingL * 2
color: "transparent"
radius: Theme.cornerRadius
border.width: 0
antialiasing: true
smooth: true
focus: true
Component.onCompleted: {

View File

@@ -37,38 +37,6 @@ DankPopout {
id: updaterPanel
color: "transparent"
radius: Theme.cornerRadius
antialiasing: true
smooth: true
Repeater {
model: [
{
"margin": -3,
"color": Qt.rgba(0, 0, 0, 0.05),
"z": -3
},
{
"margin": -2,
"color": Qt.rgba(0, 0, 0, 0.08),
"z": -2
},
{
"margin": 0,
"color": Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12),
"z": -1
}
]
Rectangle {
anchors.fill: parent
anchors.margins: modelData.margin
color: "transparent"
radius: parent.radius + Math.abs(modelData.margin)
border.color: modelData.color
border.width: 0
z: modelData.z
}
}
Column {
width: parent.width - Theme.spacingL * 2

View File

@@ -13,6 +13,7 @@ Singleton {
property var appDrawerPopout: null
property var processListPopout: null
property var dankDashPopout: null
property var dankDashPopoutLoader: null
property var batteryPopout: null
property var vpnPopout: null
property var systemUpdatePopout: null
@@ -119,31 +120,87 @@ Singleton {
}
}
property bool _dankDashWantsOpen: false
property bool _dankDashWantsToggle: false
property int _dankDashPendingTab: 0
property real _dankDashPendingX: 0
property real _dankDashPendingY: 0
property real _dankDashPendingWidth: 0
property string _dankDashPendingSection: ""
property var _dankDashPendingScreen: null
property bool _dankDashHasPosition: false
function _storeDankDashPosition(x, y, width, section, screen, hasPos) {
_dankDashPendingX = x;
_dankDashPendingY = y;
_dankDashPendingWidth = width;
_dankDashPendingSection = section;
_dankDashPendingScreen = screen;
_dankDashHasPosition = hasPos;
}
function openDankDash(tabIndex, x, y, width, section, screen) {
_dankDashPendingTab = tabIndex || 0;
if (dankDashPopout) {
if (arguments.length >= 6) {
if (arguments.length >= 6)
setPosition(dankDashPopout, x, y, width, section, screen);
}
dankDashPopout.currentTabIndex = tabIndex || 0;
dankDashPopout.currentTabIndex = _dankDashPendingTab;
dankDashPopout.dashVisible = true;
return;
}
if (!dankDashPopoutLoader)
return;
_storeDankDashPosition(x, y, width, section, screen, arguments.length >= 6);
_dankDashWantsOpen = true;
_dankDashWantsToggle = false;
dankDashPopoutLoader.active = true;
}
function closeDankDash() {
if (dankDashPopout) {
if (dankDashPopout)
dankDashPopout.dashVisible = false;
}
}
function toggleDankDash(tabIndex, x, y, width, section, screen) {
_dankDashPendingTab = tabIndex || 0;
if (dankDashPopout) {
if (arguments.length >= 6) {
if (arguments.length >= 6)
setPosition(dankDashPopout, x, y, width, section, screen);
}
if (dankDashPopout.dashVisible) {
dankDashPopout.dashVisible = false;
} else {
dankDashPopout.currentTabIndex = tabIndex || 0;
dankDashPopout.currentTabIndex = _dankDashPendingTab;
dankDashPopout.dashVisible = true;
}
return;
}
if (!dankDashPopoutLoader)
return;
_storeDankDashPosition(x, y, width, section, screen, arguments.length >= 6);
_dankDashWantsToggle = true;
_dankDashWantsOpen = false;
dankDashPopoutLoader.active = true;
}
function _onDankDashPopoutLoaded() {
if (!dankDashPopout)
return;
if (_dankDashHasPosition)
setPosition(dankDashPopout, _dankDashPendingX, _dankDashPendingY, _dankDashPendingWidth, _dankDashPendingSection, _dankDashPendingScreen);
if (_dankDashWantsOpen) {
_dankDashWantsOpen = false;
dankDashPopout.currentTabIndex = _dankDashPendingTab;
dankDashPopout.dashVisible = true;
return;
}
if (_dankDashWantsToggle) {
_dankDashWantsToggle = false;
if (dankDashPopout.dashVisible) {
dankDashPopout.dashVisible = false;
} else {
dankDashPopout.currentTabIndex = _dankDashPendingTab;
dankDashPopout.dashVisible = true;
}
}

View File

@@ -4,7 +4,6 @@ import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Services
import qs.Widgets
PanelWindow {
id: root
@@ -260,11 +259,13 @@ PanelWindow {
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha * osdContainer.opacity))
DankRectangle {
Rectangle {
id: background
anchors.fill: parent
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, osdContainer.popupSurfaceAlpha)
border.color: Theme.outlineMedium
border.width: 1
z: -1
}
@@ -293,9 +294,12 @@ PanelWindow {
}
}
DankRectangle {
Rectangle {
anchors.fill: parent
radius: Theme.cornerRadius
color: Theme.surfaceContainer
border.color: Theme.outlineMedium
border.width: 1
}
}

View File

@@ -4,7 +4,6 @@ import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
@@ -471,12 +470,8 @@ Item {
anchors.fill: parent
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
}
DankRectangle {
anchors.fill: parent
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
border.color: Theme.outlineMedium
border.width: 1
}
Loader {

View File

@@ -1,54 +0,0 @@
import QtQuick
import QtQuick.Shapes
import qs.Common
Item {
id: root
property color color: Theme.surfaceContainer
property color borderColor: Theme.outlineMedium
property real borderWidth: 1
property real radius: Theme.cornerRadius
property color overlayColor: "transparent"
Shape {
anchors.fill: parent
preferredRendererType: Shape.CurveRenderer
ShapePath {
fillColor: root.color
strokeColor: root.borderColor
strokeWidth: root.borderWidth
startX: root.radius
startY: 0
PathLine { x: root.width - root.radius; y: 0 }
PathQuad { x: root.width; y: root.radius; controlX: root.width; controlY: 0 }
PathLine { x: root.width; y: root.height - root.radius }
PathQuad { x: root.width - root.radius; y: root.height; controlX: root.width; controlY: root.height }
PathLine { x: root.radius; y: root.height }
PathQuad { x: 0; y: root.height - root.radius; controlX: 0; controlY: root.height }
PathLine { x: 0; y: root.radius }
PathQuad { x: root.radius; y: 0; controlX: 0; controlY: 0 }
}
ShapePath {
fillColor: root.overlayColor
strokeColor: "transparent"
strokeWidth: 0
startX: root.radius
startY: 0
PathLine { x: root.width - root.radius; y: 0 }
PathQuad { x: root.width; y: root.radius; controlX: root.width; controlY: 0 }
PathLine { x: root.width; y: root.height - root.radius }
PathQuad { x: root.width - root.radius; y: root.height; controlX: root.width; controlY: root.height }
PathLine { x: root.radius; y: root.height }
PathQuad { x: 0; y: root.height - root.radius; controlX: 0; controlY: root.height }
PathLine { x: 0; y: root.radius }
PathQuad { x: root.radius; y: 0; controlX: 0; controlY: 0 }
}
}
}