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

Merge branch 'master' of github.com:bbedward/DankMaterialShell

This commit is contained in:
bbedward
2025-11-09 13:54:02 -05:00
8 changed files with 91 additions and 136 deletions

View File

@@ -21,21 +21,27 @@ Item {
property real barThickness: 48
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
property Item windowRoot: (Window.window ? Window.window.contentItem : null)
property int _workspaceUpdateTrigger: 0
property int _desktopEntriesUpdateTrigger: 0
property int _toplevelsUpdateTrigger: 0
readonly property var sortedToplevels: {
_workspaceUpdateTrigger
_toplevelsUpdateTrigger
const toplevels = CompositorService.sortedToplevels
if (!toplevels || toplevels.length === 0)
return []
if (!toplevels || toplevels.length === 0) return []
if (SettingsData.runningAppsCurrentWorkspace) {
const filtered = CompositorService.filterCurrentWorkspace(toplevels, parentScreen?.name)
return filtered || []
return CompositorService.filterCurrentWorkspace(toplevels, parentScreen?.name) || []
}
return toplevels
}
Connections {
target: CompositorService
function onToplevelsChanged() {
_toplevelsUpdateTrigger++
}
}
Connections {
target: DesktopEntries
function onApplicationsChanged() {
@@ -89,36 +95,6 @@ Item {
height: isVertical ? calculatedSize : barThickness
visible: windowCount > 0
Connections {
target: NiriService
function onAllWorkspacesChanged() {
_workspaceUpdateTrigger++
}
function onWindowsChanged() {
_workspaceUpdateTrigger++
}
}
Connections {
target: Hyprland
function onFocusedWorkspaceChanged() {
_workspaceUpdateTrigger++
}
}
Connections {
target: Hyprland.workspaces
function onValuesChanged() {
_workspaceUpdateTrigger++
}
}
Connections {
target: Hyprland.toplevels
function onValuesChanged() {
_workspaceUpdateTrigger++
}
}
Rectangle {
id: visualBackground
@@ -241,7 +217,10 @@ Item {
Repeater {
id: windowRepeater
model: SettingsData.runningAppsGroupByApp ? groupedWindows : sortedToplevels
model: ScriptModel {
values: SettingsData.runningAppsGroupByApp ? groupedWindows : sortedToplevels
objectProp: SettingsData.runningAppsGroupByApp ? "appId" : "address"
}
delegate: Item {
id: delegateItem
@@ -470,7 +449,10 @@ Item {
Repeater {
id: windowRepeater
model: SettingsData.runningAppsGroupByApp ? groupedWindows : sortedToplevels
model: ScriptModel {
values: SettingsData.runningAppsGroupByApp ? groupedWindows : sortedToplevels
objectProp: SettingsData.runningAppsGroupByApp ? "appId" : "address"
}
delegate: Item {
id: delegateItem

View File

@@ -238,7 +238,7 @@ Item {
Connections {
target: CompositorService
function onSortedToplevelsChanged() {
function onToplevelsChanged() {
dockModel.updateModel()
}
}

View File

@@ -20,6 +20,7 @@ Item {
property real popoutWidth: 400
property real popoutHeight: 0
property var pillClickAction: null
property var pillRightClickAction: null
property Component controlCenterWidget: null
property string ccWidgetIcon: ""
@@ -120,6 +121,18 @@ Item {
pluginPopout.toggle()
}
}
onRightClicked: {
if (pillRightClickAction) {
if (pillRightClickAction.length === 0) {
pillRightClickAction()
} else {
const globalPos = mapToGlobal(0, 0)
const currentScreen = parentScreen || Screen
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
pillRightClickAction(pos.x, pos.y, pos.width, section, currentScreen)
}
}
}
}
BasePill {
@@ -147,6 +160,18 @@ Item {
pluginPopout.toggle()
}
}
onRightClicked: {
if (pillRightClickAction) {
if (pillRightClickAction.length === 0) {
pillRightClickAction()
} else {
const globalPos = mapToGlobal(0, 0)
const currentScreen = parentScreen || Screen
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
pillRightClickAction(pos.x, pos.y, pos.width, section, currentScreen)
}
}
}
}
function closePopout() {

View File

@@ -177,6 +177,7 @@ PluginComponent {
- `popoutWidth`: Popout window width
- `popoutHeight`: Popout window height
- `pillClickAction`: Custom click handler function (overrides popout)
- `pillRightClickAction`: Custom right click handler function
### Control Center Integration
@@ -227,7 +228,7 @@ PluginComponent {
**Custom Click Actions:**
Override default popout with `pillClickAction`:
Override default popout with `pillClickAction` and `pillRightClickAction`:
```qml
pillClickAction: () => {
@@ -238,6 +239,14 @@ pillClickAction: () => {
pillClickAction: (x, y, width, section, screen) => {
popoutService?.toggleControlCenter(x, y, width, section, screen)
}
pillRightClickAction: () => {
Process.exec("bash", ["-c", "notify-send 'Right clicked!'"])
}
pillRightClickAction: (x, y, width, section, screen) => {
popoutService?.toggleControlCenter(x, y, width, section, screen)
}
```
The PluginComponent automatically handles:

View File

@@ -21,17 +21,10 @@ Singleton {
readonly property string swaySocket: Quickshell.env("SWAYSOCK")
property bool useNiriSorting: isNiri && NiriService
property var sortedToplevels: sortedToplevelsCache
property var sortedToplevelsCache: []
property var sortedToplevels: []
property bool _sortScheduled: false
property bool _refreshScheduled: false
property bool _hasRefreshedOnce: false
property var _coordCache: ({})
property int _refreshCount: 0
property real _refreshWindowStart: 0
readonly property int _maxRefreshesPerSecond: 3
signal toplevelsChanged()
function getScreenScale(screen) {
if (!screen) return 1
@@ -59,46 +52,20 @@ Singleton {
}
Timer {
id: refreshTimer
interval: 40
id: sortDebounceTimer
interval: 100
repeat: false
onTriggered: {
try {
Hyprland.refreshToplevels()
} catch(e) {}
_refreshScheduled = false
_hasRefreshedOnce = true
scheduleSort()
_sortScheduled = false
sortedToplevels = computeSortedToplevels()
toplevelsChanged()
}
}
function scheduleSort() {
if (_sortScheduled) return
_sortScheduled = true
Qt.callLater(function() {
_sortScheduled = false
sortedToplevelsCache = computeSortedToplevels()
})
}
function scheduleRefresh() {
if (!isHyprland) return
if (_refreshScheduled) return
const now = Date.now()
if (now - _refreshWindowStart > 1000) {
_refreshCount = 0
_refreshWindowStart = now
}
if (_refreshCount >= _maxRefreshesPerSecond) {
console.warn("CompositorService: Refresh rate limit exceeded, skipping refresh")
return
}
_refreshCount++
_refreshScheduled = true
refreshTimer.restart()
sortDebounceTimer.restart()
}
Connections {
@@ -106,19 +73,31 @@ Singleton {
function onValuesChanged() { root.scheduleSort() }
}
Connections {
target: Hyprland.toplevels
function onValuesChanged() {
root.scheduleSort()
target: isHyprland ? Hyprland : null
enabled: isHyprland
function onRawEvent(event) {
if (event.name === "openwindow" ||
event.name === "closewindow" ||
event.name === "movewindow" ||
event.name === "movewindowv2" ||
event.name === "workspace" ||
event.name === "workspacev2" ||
event.name === "focusedmon" ||
event.name === "focusedmonv2" ||
event.name === "activewindow" ||
event.name === "activewindowv2" ||
event.name === "changefloatingmode" ||
event.name === "fullscreen" ||
event.name === "moveintogroup" ||
event.name === "moveoutofgroup") {
try {
Hyprland.refreshToplevels()
} catch(e) {}
root.scheduleSort()
}
}
}
Connections {
target: Hyprland.workspaces
function onValuesChanged() { root.scheduleSort() }
}
Connections {
target: Hyprland
function onFocusedWorkspaceChanged() { root.scheduleSort() }
}
Connections {
target: NiriService
function onWindowsChanged() { root.scheduleSort() }
@@ -165,7 +144,6 @@ Singleton {
function sortHyprlandToplevelsSafe() {
if (!Hyprland.toplevels || !Hyprland.toplevels.values) return []
if (_refreshScheduled && sortedToplevelsCache.length > 0) return sortedToplevelsCache
const items = Array.from(Hyprland.toplevels.values)
@@ -177,21 +155,7 @@ Singleton {
} catch(e) { return fb }
}
let currentAddresses = new Set()
for (let i = 0; i < items.length; i++) {
const addr = items[i]?.address
if (addr) currentAddresses.add(addr)
}
for (let cachedAddr in _coordCache) {
if (!currentAddresses.has(cachedAddr)) {
delete _coordCache[cachedAddr]
}
}
let snap = []
let missingAnyPosition = false
let hasNewWindow = false
for (let i = 0; i < items.length; i++) {
const t = items[i]
if (!t) continue
@@ -208,23 +172,8 @@ Singleton {
const wsId = _get(li, ["workspace", "id"], null) ?? _get(t, ["workspace", "id"], Number.MAX_SAFE_INTEGER)
const at = _get(li, ["at"], null)
let atX = (at !== null && at !== undefined && typeof at[0] === "number") ? at[0] : NaN
let atY = (at !== null && at !== undefined && typeof at[1] === "number") ? at[1] : NaN
if (!(atX === atX) || !(atY === atY)) {
const cached = _coordCache[addr]
if (cached) {
atX = cached.x
atY = cached.y
} else {
if (addr) hasNewWindow = true
missingAnyPosition = true
atX = 1e9
atY = 1e9
}
} else if (addr) {
_coordCache[addr] = { x: atX, y: atY }
}
let atX = (at !== null && at !== undefined && typeof at[0] === "number") ? at[0] : 1e9
let atY = (at !== null && at !== undefined && typeof at[1] === "number") ? at[1] : 1e9
const relX = Number.isFinite(monX) ? (atX - monX) : atX
const relY = Number.isFinite(monY) ? (atY - monY) : atY
@@ -242,10 +191,6 @@ Singleton {
})
}
if (missingAnyPosition && hasNewWindow && !_hasRefreshedOnce) {
scheduleRefresh()
}
const groups = new Map()
for (const it of snap) {
const key = it.monKey + "::" + it.wsId
@@ -400,9 +345,6 @@ Singleton {
isSway = false
compositor = "hyprland"
console.info("CompositorService: Detected Hyprland")
try {
Hyprland.refreshToplevels()
} catch(e) {}
return
}

View File

@@ -32,11 +32,9 @@ Singleton {
}
for (const appId of appIds){
let icon = Quickshell.iconPath(entry?.icon, true)
console.log(icon)
if (icon && icon !== "") return icon
let execPath = entry?.execString?.replace(/\/bin.*/, "")
console.log(execPath)
if (!execPath) continue
//Check that the app is installed with nix/guix
@@ -46,13 +44,11 @@ Singleton {
let iconPath = `${basePath}/share/icons/hicolor/scalable/apps/${appId}.svg`
icon = Quickshell.iconPath(iconPath, true)
console.log(icon)
if (icon && icon !== "") return icon
for (const size of sizes) {
iconPath = `${basePath}/share/icons/hicolor/${size}/apps/${appId}.png`
icon = Quickshell.iconPath(iconPath, true)
console.log(icon)
if (icon && icon !== "") return icon
}
}

View File

@@ -3,6 +3,7 @@ import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Services
import qs.Widgets
pragma ComponentBehavior: Bound

View File

@@ -692,7 +692,7 @@
{
"term": "Close",
"context": "Close",
"reference": "Modules/SystemUpdatePopout.qml:335, Modals/NetworkWiredInfoModal.qml:131, Modals/NetworkInfoModal.qml:131, Modules/DankBar/Widgets/RunningApps.qml:788",
"reference": "Modules/SystemUpdatePopout.qml:335, Modals/NetworkWiredInfoModal.qml:131, Modals/NetworkInfoModal.qml:131, Modules/DankBar/Widgets/RunningApps.qml:770",
"comment": ""
},
{