1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-04 19:42:08 -04:00

refactor: (Framemode) Added DeferredAction for dbar/dock state handling

This commit is contained in:
purian23
2026-05-04 10:43:07 -04:00
parent cc47703d48
commit 19c561da14
7 changed files with 245 additions and 84 deletions

View File

@@ -0,0 +1,55 @@
import QtQuick
Item {
id: root
visible: false
width: 0
height: 0
property int interval: 0
property bool pending: false
signal triggered
function schedule() {
if (!root.enabled || root.pending)
return;
root.pending = true;
deferTimer.restart();
}
function restart() {
if (!root.enabled)
return;
root.pending = true;
deferTimer.restart();
}
function flush() {
if (!root.pending)
return;
deferTimer.stop();
root.pending = false;
root.triggered();
}
function cancel() {
deferTimer.stop();
root.pending = false;
}
onEnabledChanged: {
if (!enabled)
cancel();
}
Timer {
id: deferTimer
interval: root.interval
repeat: false
onTriggered: root.flush()
}
Component.onDestruction: cancel()
}

View File

@@ -164,7 +164,22 @@ Item {
}
}
property bool barSurfacesLoaded: true
function recreateBarSurfaces() {
if (barSurfacesLoaded)
barSurfacesLoaded = false;
barSurfaceReloadAction.schedule();
}
DeferredAction {
id: barSurfaceReloadAction
onTriggered: root.barSurfacesLoaded = true
}
property string _barLayoutStateJson: {
if (!barSurfacesLoaded)
return "[]";
const configs = SettingsData.barConfigs;
const mapped = configs.map(c => ({
id: c.id,
@@ -188,6 +203,19 @@ Item {
}
}
Connections {
target: SettingsData
function onFrameEnabledChanged() {
root.recreateBarSurfaces();
}
function onConnectedFrameModeActiveChanged() {
root.recreateBarSurfaces();
}
function onForceDankBarLayoutRefresh() {
root.recreateBarSurfaces();
}
}
Frame {}
Repeater {
@@ -203,7 +231,7 @@ Item {
id: barLoader
required property var modelData
property var barConfig: SettingsData.barConfigs.find(cfg => cfg.id === modelData.id) || null
active: barConfig?.enabled ?? false
active: root.barSurfacesLoaded && (barConfig?.enabled ?? false)
asynchronous: false
sourceComponent: DankBar {

View File

@@ -19,33 +19,52 @@ Item {
property var leftWidgetsModel
property var centerWidgetsModel
property var rightWidgetsModel
property bool _animateFrameInsets: false
readonly property real innerPadding: barConfig?.innerPadding ?? 4
readonly property real outlineThickness: (barConfig?.widgetOutlineEnabled ?? false) ? (barConfig?.widgetOutlineThickness ?? 1) : 0
readonly property real _edgeBaseMargin: Math.max(Theme.spacingXS, innerPadding * 0.8)
readonly property real _frameEdgeFloorInset: SettingsData.frameEnabled ? Math.max(0, SettingsData.frameThickness - _edgeBaseMargin) : 0
readonly property bool _hasBarWindow: barWindow !== undefined && barWindow !== null
readonly property bool _barIsVertical: _hasBarWindow ? barWindow.isVertical : false
readonly property string _barScreenName: _hasBarWindow ? (barWindow.screenName || "") : ""
readonly property bool hasAdjacentTopBarLive: _hasBarWindow && barWindow.hasAdjacentTopBar
readonly property bool hasAdjacentBottomBarLive: _hasBarWindow && barWindow.hasAdjacentBottomBar
readonly property bool hasAdjacentLeftBarLive: _hasBarWindow && barWindow.hasAdjacentLeftBar
readonly property bool hasAdjacentRightBarLive: _hasBarWindow && barWindow.hasAdjacentRightBar
property bool _hadAdjacentTopBar: false
property bool _hadAdjacentBottomBar: false
property bool _hadAdjacentLeftBar: false
property bool _hadAdjacentRightBar: false
onHasAdjacentTopBarLiveChanged: if (hasAdjacentTopBarLive) _hadAdjacentTopBar = true
onHasAdjacentBottomBarLiveChanged: if (hasAdjacentBottomBarLive) _hadAdjacentBottomBar = true
onHasAdjacentLeftBarLiveChanged: if (hasAdjacentLeftBarLive) _hadAdjacentLeftBar = true
onHasAdjacentRightBarLiveChanged: if (hasAdjacentRightBarLive) _hadAdjacentRightBar = true
readonly property real _frameLeftInset: {
if (!SettingsData.frameEnabled || barWindow.isVertical) return 0
return barWindow.hasAdjacentLeftBar
if (!_hasBarWindow || !SettingsData.frameEnabled || _barIsVertical) return 0
return hasAdjacentLeftBarLive
? SettingsData.frameBarSize
: 0
: (_hadAdjacentLeftBar ? _frameEdgeFloorInset : 0)
}
readonly property real _frameRightInset: {
if (!SettingsData.frameEnabled || barWindow.isVertical) return 0
return barWindow.hasAdjacentRightBar
if (!_hasBarWindow || !SettingsData.frameEnabled || _barIsVertical) return 0
return hasAdjacentRightBarLive
? SettingsData.frameBarSize
: 0
: (_hadAdjacentRightBar ? _frameEdgeFloorInset : 0)
}
readonly property real _frameTopInset: {
if (!SettingsData.frameEnabled || !barWindow.isVertical) return 0
return barWindow.hasAdjacentTopBar
if (!_hasBarWindow || !SettingsData.frameEnabled || !_barIsVertical) return 0
return hasAdjacentTopBarLive
? SettingsData.frameThickness
: 0
: (_hadAdjacentTopBar ? _frameEdgeFloorInset : 0)
}
readonly property real _frameBottomInset: {
if (!SettingsData.frameEnabled || !barWindow.isVertical) return 0
return barWindow.hasAdjacentBottomBar
if (!_hasBarWindow || !SettingsData.frameEnabled || !_barIsVertical) return 0
return hasAdjacentBottomBarLive
? SettingsData.frameThickness
: 0
: (_hadAdjacentBottomBar ? _frameEdgeFloorInset : 0)
}
property alias hLeftSection: hLeftSection
@@ -56,16 +75,61 @@ Item {
property alias vRightSection: vRightSection
anchors.fill: parent
anchors.leftMargin: Math.max(Theme.spacingXS, innerPadding * 0.8) + _frameLeftInset
anchors.rightMargin: Math.max(Theme.spacingXS, innerPadding * 0.8) + _frameRightInset
anchors.topMargin: (barWindow.isVertical
? (barWindow.hasAdjacentTopBar ? outlineThickness : Theme.spacingXS)
anchors.leftMargin: _edgeBaseMargin + _frameLeftInset
anchors.rightMargin: _edgeBaseMargin + _frameRightInset
anchors.topMargin: (_barIsVertical
? (hasAdjacentTopBarLive ? outlineThickness : Theme.spacingXS)
: 0) + _frameTopInset
anchors.bottomMargin: (barWindow.isVertical
? (barWindow.hasAdjacentBottomBar ? outlineThickness : Theme.spacingXS)
anchors.bottomMargin: (_barIsVertical
? (hasAdjacentBottomBarLive ? outlineThickness : Theme.spacingXS)
: 0) + _frameBottomInset
clip: false
DeferredAction {
id: enableFrameInsetAnimation
onTriggered: topBarContent._animateFrameInsets = true
}
Component.onCompleted: {
_hadAdjacentTopBar = hasAdjacentTopBarLive;
_hadAdjacentBottomBar = hasAdjacentBottomBarLive;
_hadAdjacentLeftBar = hasAdjacentLeftBarLive;
_hadAdjacentRightBar = hasAdjacentRightBarLive;
enableFrameInsetAnimation.schedule();
}
Behavior on anchors.leftMargin {
enabled: _animateFrameInsets && SettingsData.frameEnabled
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
Behavior on anchors.rightMargin {
enabled: _animateFrameInsets && SettingsData.frameEnabled
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
Behavior on anchors.topMargin {
enabled: _animateFrameInsets && SettingsData.frameEnabled
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
Behavior on anchors.bottomMargin {
enabled: _animateFrameInsets && SettingsData.frameEnabled
NumberAnimation {
duration: Theme.shortDuration
easing.type: Easing.OutCubic
}
}
property int componentMapRevision: 0
function updateComponentMap() {
@@ -73,10 +137,14 @@ Item {
}
readonly property var sortedToplevels: {
return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, barWindow.screenName);
if (!_hasBarWindow) {
return [];
}
return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, _barScreenName);
}
function getRealWorkspaces() {
const screenName = _barScreenName;
if (CompositorService.isNiri) {
const fallbackWorkspaces = [
{
@@ -90,16 +158,16 @@ Item {
"name": ""
}
];
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
if (!screenName || SettingsData.workspaceFollowFocus) {
const currentWorkspaces = NiriService.getCurrentOutputWorkspaces();
return currentWorkspaces.length > 0 ? currentWorkspaces : fallbackWorkspaces;
}
const workspaces = NiriService.allWorkspaces.filter(ws => ws.output === barWindow.screenName);
const workspaces = NiriService.allWorkspaces.filter(ws => ws.output === screenName);
return workspaces.length > 0 ? workspaces : fallbackWorkspaces;
} else if (CompositorService.isHyprland) {
const workspaces = Hyprland.workspaces?.values || [];
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
if (!screenName || SettingsData.workspaceFollowFocus) {
const sorted = workspaces.slice().sort((a, b) => a.id - b.id);
const filtered = sorted.filter(ws => ws.id > -1);
return filtered.length > 0 ? filtered : [
@@ -111,7 +179,7 @@ Item {
}
const monitorWorkspaces = workspaces.filter(ws => {
return ws.lastIpcObject && ws.lastIpcObject.monitor === barWindow.screenName && ws.id > -1;
return ws.lastIpcObject && ws.lastIpcObject.monitor === screenName && ws.id > -1;
});
if (monitorWorkspaces.length === 0) {
@@ -133,7 +201,7 @@ Item {
length: DwlService.tagCount
}, (_, i) => i);
}
return DwlService.getVisibleTags(barWindow.screenName);
return DwlService.getVisibleTags(screenName);
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
const workspaces = I3.workspaces?.values || [];
if (workspaces.length === 0)
@@ -143,11 +211,11 @@ Item {
}
];
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
if (!screenName || SettingsData.workspaceFollowFocus) {
return workspaces.slice().sort((a, b) => a.num - b.num);
}
const monitorWorkspaces = workspaces.filter(ws => ws.monitor?.name === barWindow.screenName);
const monitorWorkspaces = workspaces.filter(ws => ws.monitor?.name === screenName);
return monitorWorkspaces.length > 0 ? monitorWorkspaces.sort((a, b) => a.num - b.num) : [
{
"num": 1
@@ -158,31 +226,32 @@ Item {
}
function getCurrentWorkspace() {
const screenName = _barScreenName;
if (CompositorService.isNiri) {
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
if (!screenName || SettingsData.workspaceFollowFocus) {
return NiriService.getCurrentWorkspaceNumber();
}
const activeWs = NiriService.allWorkspaces.find(ws => ws.output === barWindow.screenName && ws.is_active);
const activeWs = NiriService.allWorkspaces.find(ws => ws.output === screenName && ws.is_active);
return activeWs ? activeWs.idx : 1;
} else if (CompositorService.isHyprland) {
const monitors = Hyprland.monitors?.values || [];
const currentMonitor = monitors.find(monitor => monitor.name === barWindow.screenName);
const currentMonitor = monitors.find(monitor => monitor.name === screenName);
return currentMonitor?.activeWorkspace?.id ?? 1;
} else if (CompositorService.isDwl) {
if (!DwlService.dwlAvailable)
return 0;
const outputState = DwlService.getOutputState(barWindow.screenName);
const outputState = DwlService.getOutputState(screenName);
if (!outputState || !outputState.tags)
return 0;
const activeTags = DwlService.getActiveTags(barWindow.screenName);
const activeTags = DwlService.getActiveTags(screenName);
return activeTags.length > 0 ? activeTags[0] : 0;
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
if (!screenName || SettingsData.workspaceFollowFocus) {
const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true);
return focusedWs ? focusedWs.num : 1;
}
const focusedWs = I3.workspaces?.values?.find(ws => ws.monitor?.name === barWindow.screenName && ws.focused === true);
const focusedWs = I3.workspaces?.values?.find(ws => ws.monitor?.name === screenName && ws.focused === true);
return focusedWs ? focusedWs.num : 1;
}
return 1;
@@ -223,7 +292,7 @@ Item {
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
if (nextIndex !== validIndex) {
DwlService.switchToTag(barWindow.screenName, realWorkspaces[nextIndex]);
DwlService.switchToTag(_barScreenName, realWorkspaces[nextIndex]);
}
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
const currentWs = getCurrentWorkspace();
@@ -290,8 +359,8 @@ Item {
readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(0, mediaLeftEdge - leftSectionRightEdge) : leftToClockGap
readonly property int mediaToClockGap: mediaMaxWidth > 0 ? Theme.spacingS : 0
readonly property int clockToRightGap: validLayout ? Math.max(0, rightSectionLeftEdge - clockRightEdge) : 1000
readonly property bool spacingTight: !barWindow.isVertical && validLayout && (leftToMediaGap < 150 || clockToRightGap < 100)
readonly property bool overlapping: !barWindow.isVertical && validLayout && (leftToMediaGap < 100 || clockToRightGap < 50)
readonly property bool spacingTight: !_barIsVertical && validLayout && (leftToMediaGap < 150 || clockToRightGap < 100)
readonly property bool overlapping: !_barIsVertical && validLayout && (leftToMediaGap < 100 || clockToRightGap < 50)
function getWidgetEnabled(enabled) {
return enabled !== false;
@@ -761,7 +830,7 @@ Item {
WorkspaceSwitcher {
axis: barWindow.axis
screenName: barWindow.screenName
screenName: _barScreenName
widgetHeight: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
parentScreen: barWindow.screen
@@ -1378,8 +1447,8 @@ Item {
id: spacerComponent
Item {
width: barWindow.isVertical ? barWindow.widgetThickness : (parent.spacerSize || 20)
height: barWindow.isVertical ? (parent.spacerSize || 20) : barWindow.widgetThickness
width: _barIsVertical ? barWindow.widgetThickness : (parent.spacerSize || 20)
height: _barIsVertical ? (parent.spacerSize || 20) : barWindow.widgetThickness
implicitWidth: width
implicitHeight: height
@@ -1408,14 +1477,14 @@ Item {
id: separatorComponent
Item {
width: barWindow.isVertical ? parent.barThickness : 1
height: barWindow.isVertical ? 1 : parent.barThickness
width: _barIsVertical ? parent.barThickness : 1
height: _barIsVertical ? 1 : parent.barThickness
implicitWidth: width
implicitHeight: height
Rectangle {
width: barWindow.isVertical ? parent.width * 0.6 : 1
height: barWindow.isVertical ? 1 : parent.height * 0.6
width: _barIsVertical ? parent.width * 0.6 : 1
height: _barIsVertical ? 1 : parent.height * 0.6
anchors.centerIn: parent
color: Theme.outline
opacity: 0.3

View File

@@ -510,17 +510,6 @@ PanelWindow {
property var nativeInhibitor: null
Component.onCompleted: {
if (SettingsData.forceStatusBarLayoutRefresh) {
SettingsData.forceStatusBarLayoutRefresh.connect(() => {
Qt.callLater(() => {
stackContainer.visible = false;
Qt.callLater(() => {
stackContainer.visible = true;
});
});
});
}
updateGpuTempConfig();
_updateBackgroundAlpha();
_updateHasMaximizedToplevel();

View File

@@ -202,18 +202,21 @@ Variants {
ConnectedModeState.setDockSlide(dock._dockScreenName, dockSlide.x, dockSlide.y);
}
property bool _slideSyncPending: false
DeferredAction {
id: dockSlideSync
enabled: SettingsData.connectedFrameModeActive
onTriggered: dock._syncDockSlide()
}
function _queueSlideSync() {
if (!SettingsData.connectedFrameModeActive)
return;
if (_slideSyncPending)
return;
_slideSyncPending = true;
Qt.callLater(dock._flushSlideSync);
dockSlideSync.schedule();
}
function _flushSlideSync() {
_slideSyncPending = false;
dock._syncDockSlide();
DeferredAction {
id: dockChromeSync
onTriggered: dock._syncDockChromeState()
}
property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData)
@@ -390,8 +393,12 @@ Variants {
}
}
Component.onCompleted: Qt.callLater(() => dock._syncDockChromeState())
Component.onDestruction: ConnectedModeState.clearDockState(dock._dockScreenName)
Component.onCompleted: dockChromeSync.schedule()
Component.onDestruction: {
dockChromeSync.cancel();
dockSlideSync.cancel();
ConnectedModeState.clearDockState(dock._dockScreenName);
}
onRevealChanged: dock._syncDockChromeState()
onWidthChanged: dock._syncDockChromeState()
@@ -404,6 +411,7 @@ Variants {
Connections {
target: SettingsData
function onConnectedFrameModeActiveChanged() {
dockSlideSync.cancel();
dock._syncDockChromeState();
}
}

View File

@@ -1195,16 +1195,16 @@ PanelWindow {
// Coalesce bursts of settings-change signals into a single _buildBlur() call
// on the next event loop tick.
property bool _blurRebuildPending: false
DeferredAction {
id: blurRebuildAction
onTriggered: win._runBlurRebuild()
}
function _scheduleBlurRebuild() {
if (_blurRebuildPending)
return;
_blurRebuildPending = true;
Qt.callLater(_runBlurRebuild);
blurRebuildAction.schedule();
}
function _runBlurRebuild() {
_blurRebuildPending = false;
win._buildBlur();
_buildBlur();
}
Connections {
@@ -1257,7 +1257,10 @@ PanelWindow {
}
Component.onCompleted: win._scheduleBlurRebuild()
Component.onDestruction: win._teardownBlur()
Component.onDestruction: {
blurRebuildAction.cancel();
win._teardownBlur();
}
FrameBorder {
anchors.fill: parent

View File

@@ -18,13 +18,12 @@ Singleton {
function registerWidget(widgetId, screenName, widgetRef) {
if (!widgetId || !screenName || !widgetRef)
return;
if (typeof widgetRegistry !== "object" || widgetRegistry === null)
widgetRegistry = ({});
if (!widgetRegistry[widgetId])
widgetRegistry[widgetId] = {};
widgetRegistry[widgetId][screenName] = widgetRef;
const nextRegistry = (typeof widgetRegistry === "object" && widgetRegistry !== null) ? Object.assign({}, widgetRegistry) : {};
const screenMap = (typeof nextRegistry[widgetId] === "object" && nextRegistry[widgetId] !== null) ? Object.assign({}, nextRegistry[widgetId]) : {};
screenMap[screenName] = widgetRef;
nextRegistry[widgetId] = screenMap;
widgetRegistry = nextRegistry;
widgetRegistered(widgetId, screenName);
}
@@ -36,15 +35,21 @@ Singleton {
if (!widgetRegistry[widgetId])
return;
delete widgetRegistry[widgetId][screenName];
if (Object.keys(widgetRegistry[widgetId]).length === 0)
delete widgetRegistry[widgetId];
const nextRegistry = Object.assign({}, widgetRegistry);
const screenMap = (typeof nextRegistry[widgetId] === "object" && nextRegistry[widgetId] !== null) ? Object.assign({}, nextRegistry[widgetId]) : {};
delete screenMap[screenName];
if (Object.keys(screenMap).length === 0) {
delete nextRegistry[widgetId];
} else {
nextRegistry[widgetId] = screenMap;
}
widgetRegistry = nextRegistry;
widgetUnregistered(widgetId, screenName);
}
function getWidget(widgetId, screenName) {
if (!widgetRegistry[widgetId])
if (typeof widgetRegistry !== "object" || widgetRegistry === null || !widgetRegistry[widgetId])
return null;
if (screenName)
return widgetRegistry[widgetId][screenName] || null;
@@ -54,7 +59,7 @@ Singleton {
}
function getWidgetOnFocusedScreen(widgetId) {
if (!widgetRegistry[widgetId])
if (typeof widgetRegistry !== "object" || widgetRegistry === null || !widgetRegistry[widgetId])
return null;
const focusedScreen = getFocusedScreenName();
@@ -78,10 +83,14 @@ Singleton {
}
function getRegisteredWidgetIds() {
if (typeof widgetRegistry !== "object" || widgetRegistry === null)
return [];
return Object.keys(widgetRegistry);
}
function hasWidget(widgetId) {
if (typeof widgetRegistry !== "object" || widgetRegistry === null)
return false;
return widgetRegistry[widgetId] && Object.keys(widgetRegistry[widgetId]).length > 0;
}