1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-07 19:59:14 -04:00

feat(FocusedWindow): Improve content width calculation and add size options (#2444)

* use RowLayout in focusedapp widget for better width calculation

* Add context menu with additional size options for focused app widget
This commit is contained in:
Lichie
2026-05-20 08:43:14 -07:00
committed by GitHub
parent 548c2305fb
commit 0990b43a43
5 changed files with 266 additions and 30 deletions
+1
View File
@@ -394,6 +394,7 @@ Singleton {
property string audioScrollMode: "volume"
property int audioWheelScrollAmount: 5
property bool clockCompactMode: false
property int focusedWindowSize: 1
property bool focusedWindowCompactMode: false
property bool runningAppsCompactMode: true
property int barMaxVisibleApps: 0
@@ -153,6 +153,7 @@ var SPEC = {
audioWheelScrollAmount: { def: 5 },
clockCompactMode: { def: false },
focusedWindowCompactMode: { def: false },
focusedWindowSize: { def: 1 },
runningAppsCompactMode: { def: true },
barMaxVisibleApps: { def: 0 },
barMaxVisibleRunningApps: { def: 0 },
@@ -1,5 +1,6 @@
import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell
import Quickshell.Wayland
import Quickshell.Widgets
@@ -14,9 +15,20 @@ BasePill {
property var widgetData: null
property bool compactMode: widgetData?.focusedWindowCompactMode !== undefined ? widgetData.focusedWindowCompactMode : SettingsData.focusedWindowCompactMode
property int availableWidth: 400
readonly property int maxNormalWidth: 456
readonly property int maxCompactWidth: 288
readonly property int maxWidth: {
const size = widgetData?.focusedWindowSize !== undefined ? widgetData.focusedWindowSize : SettingsData.focusedWindowSize;
switch (size) {
case 0:
return 288;
case 2:
return 656;
case 3:
return 856;
default:
return 456;
}
}
property int availableWidth: maxWidth
property Toplevel activeWindow: null
property var activeDesktopEntry: null
property bool isHovered: mouseArea.containsMouse
@@ -171,8 +183,7 @@ BasePill {
return 0;
if (root.isVerticalOrientation)
return root.widgetThickness - root.horizontalPadding * 2;
const baseWidth = contentRow.implicitWidth;
return compactMode ? Math.min(baseWidth, maxCompactWidth - root.horizontalPadding * 2) : Math.min(baseWidth, maxNormalWidth - root.horizontalPadding * 2);
return contentRow.implicitWidth;
}
implicitHeight: root.widgetThickness - root.horizontalPadding * 2
clip: false
@@ -222,7 +233,7 @@ BasePill {
color: Theme.widgetTextColor
}
Row {
RowLayout {
id: contentRow
anchors.centerIn: parent
spacing: Theme.spacingS
@@ -231,24 +242,23 @@ BasePill {
StyledText {
id: appText
text: {
if (!activeWindow || !activeWindow.appId)
if (compactMode || !activeWindow || !activeWindow.appId)
return "";
return Paths.getAppName(activeWindow.appId, activeDesktopEntry);
}
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
maximumLineCount: 1
width: Math.min(implicitWidth, compactMode ? 80 : 180)
visible: !compactMode && text.length > 0
Layout.maximumWidth: compactMode ? 80 : 180
visible: text.length > 0
}
StyledText {
text: "•"
id: appSeparator
text: compactMode ? "" : "•"
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
color: Theme.outlineButton
anchors.verticalCenter: parent.verticalCenter
visible: !compactMode && appText.text && titleText.text
}
@@ -276,10 +286,9 @@ BasePill {
}
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
maximumLineCount: 1
width: Math.min(implicitWidth, compactMode ? 280 : 250)
Layout.maximumWidth: maxWidth - appText.implicitWidth - appSeparator.implicitWidth
visible: text.length > 0
}
}
+35 -4
View File
@@ -431,7 +431,7 @@ Item {
"id": widget.id,
"enabled": widget.enabled
};
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "diskUsageMode", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "controlCenterGroupOrder", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge", "trayUseInlineExpansion", "hideWhenIdle"];
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "diskUsageMode", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowSize", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "controlCenterGroupOrder", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge", "trayUseInlineExpansion", "hideWhenIdle"];
for (var i = 0; i < keys.length; i++) {
if (widget[keys[i]] !== undefined)
result[keys[i]] = widget[keys[i]];
@@ -625,9 +625,6 @@ Item {
var newWidget = cloneWidgetData(widget);
switch (widgetId) {
case "music":
newWidget.mediaSize = value;
break;
case "clock":
newWidget.clockCompactMode = value;
break;
@@ -647,6 +644,29 @@ Item {
setWidgetsForSection(sectionId, widgets);
}
function handleWidgetSizeChanged(sectionId, widgetId, value) {
var widgets = getWidgetsForSection(sectionId).slice();
for (var i = 0; i < widgets.length; i++) {
var widget = widgets[i];
var currentId = typeof widget === "string" ? widget : widget.id;
if (currentId !== widgetId)
continue;
var newWidget = cloneWidgetData(widget);
switch (widgetId) {
case "music":
newWidget.mediaSize = value;
break;
case "focusedWindow":
newWidget.focusedWindowSize = value;
break;
}
widgets[i] = newWidget;
break;
}
setWidgetsForSection(sectionId, widgets);
}
function getItemsForSection(sectionId) {
var widgets = [];
var widgetData = getWidgetsForSection(sectionId);
@@ -708,6 +728,8 @@ Item {
item.clockCompactMode = widget.clockCompactMode;
if (widget.focusedWindowCompactMode !== undefined)
item.focusedWindowCompactMode = widget.focusedWindowCompactMode;
if (widget.focusedWindowSize !== undefined)
item.focusedWindowSize = widget.focusedWindowSize;
if (widget.runningAppsCompactMode !== undefined)
item.runningAppsCompactMode = widget.runningAppsCompactMode;
if (widget.runningAppsGroupByApp !== undefined)
@@ -1014,6 +1036,9 @@ Item {
onCompactModeChanged: (widgetId, value) => {
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
}
onWidgetSizeChanged: (widgetId, value) => {
widgetsTab.handleWidgetSizeChanged(sectionId, widgetId, value);
}
onOverflowSettingChanged: (sectionId, widgetIndex, settingName, value) => {
widgetsTab.handleOverflowSettingChanged(sectionId, widgetIndex, settingName, value);
}
@@ -1084,6 +1109,9 @@ Item {
onCompactModeChanged: (widgetId, value) => {
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
}
onWidgetSizeChanged: (widgetId, value) => {
widgetsTab.handleWidgetSizeChanged(sectionId, widgetId, value);
}
onOverflowSettingChanged: (sectionId, widgetIndex, settingName, value) => {
widgetsTab.handleOverflowSettingChanged(sectionId, widgetIndex, settingName, value);
}
@@ -1154,6 +1182,9 @@ Item {
onCompactModeChanged: (widgetId, value) => {
widgetsTab.handleCompactModeChanged(sectionId, widgetId, value);
}
onWidgetSizeChanged: (widgetId, value) => {
widgetsTab.handleWidgetSizeChanged(sectionId, widgetId, value);
}
onOverflowSettingChanged: (sectionId, widgetIndex, settingName, value) => {
widgetsTab.handleOverflowSettingChanged(sectionId, widgetIndex, settingName, value);
}
+206 -12
View File
@@ -24,6 +24,7 @@ Column {
signal removeWidget(string sectionId, int widgetIndex)
signal spacerSizeChanged(string sectionId, int widgetIndex, int newSize)
signal compactModeChanged(string widgetId, var value)
signal widgetSizeChanged(string widgetId, var value)
signal gpuSelectionChanged(string sectionId, int widgetIndex, int selectedIndex)
signal diskMountSelectionChanged(string sectionId, int widgetIndex, string mountPath)
signal controlCenterSettingChanged(string sectionId, int widgetIndex, string settingName, bool value)
@@ -41,7 +42,7 @@ Column {
"id": widget.id,
"enabled": widget.enabled
};
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "diskUsageMode", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "controlCenterGroupOrder", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge", "trayUseInlineExpansion"];
var keys = ["size", "selectedGpuIndex", "pciId", "mountPath", "diskUsageMode", "minimumWidth", "showSwap", "showInGb", "mediaSize", "clockCompactMode", "focusedWindowSize", "focusedWindowCompactMode", "runningAppsCompactMode", "keyboardLayoutNameCompactMode", "runningAppsGroupByApp", "runningAppsCurrentWorkspace", "runningAppsCurrentMonitor", "showNetworkIcon", "showBluetoothIcon", "showAudioIcon", "showAudioPercent", "showVpnIcon", "showBrightnessIcon", "showBrightnessPercent", "showMicIcon", "showMicPercent", "showBatteryIcon", "showPrinterIcon", "showScreenSharingIcon", "controlCenterGroupOrder", "barMaxVisibleApps", "barMaxVisibleRunningApps", "barShowOverflowBadge", "trayUseInlineExpansion"];
for (var i = 0; i < keys.length; i++) {
if (widget[keys[i]] !== undefined)
result[keys[i]] = widget[keys[i]];
@@ -390,6 +391,39 @@ Column {
}
}
DankActionButton {
id: focusedWindowMenuButton
buttonSize: 32
visible: modelData.id === "focusedWindow"
iconName: "more_vert"
iconSize: 18
iconColor: Theme.outline
onClicked: {
focusedWindowContextMenu.widgetData = modelData;
focusedWindowContextMenu.sectionId = root.sectionId;
focusedWindowContextMenu.widgetIndex = index;
var buttonPos = focusedWindowMenuButton.mapToItem(root, 0, 0);
var popupWidth = focusedWindowContextMenu.width;
var popupHeight = focusedWindowContextMenu.height;
var xPos = buttonPos.x - popupWidth - Theme.spacingS;
if (xPos < 0)
xPos = buttonPos.x + focusedWindowMenuButton.width + Theme.spacingS;
var yPos = buttonPos.y - popupHeight / 2 + focusedWindowMenuButton.height / 2;
if (yPos < 0) {
yPos = Theme.spacingS;
} else if (yPos + popupHeight > root.height) {
yPos = root.height - popupHeight - Theme.spacingS;
}
focusedWindowContextMenu.x = xPos;
focusedWindowContextMenu.y = yPos;
focusedWindowContextMenu.open();
}
}
DankActionButton {
id: musicMenuButton
visible: modelData.id === "music"
@@ -458,19 +492,17 @@ Column {
Row {
spacing: Theme.spacingXS
visible: modelData.id === "clock" || modelData.id === "focusedWindow" || modelData.id === "keyboard_layout_name" || modelData.id === "appsDock" || modelData.id === "systemTray"
visible: modelData.id === "clock" || modelData.id === "keyboard_layout_name" || modelData.id === "appsDock" || modelData.id === "systemTray"
DankActionButton {
id: compactModeButton
buttonSize: 28
visible: modelData.id === "clock" || modelData.id === "focusedWindow" || modelData.id === "keyboard_layout_name"
visible: modelData.id === "clock" || modelData.id === "keyboard_layout_name"
iconName: {
const isCompact = (() => {
switch (modelData.id) {
case "clock":
return modelData.clockCompactMode !== undefined ? modelData.clockCompactMode : SettingsData.clockCompactMode;
case "focusedWindow":
return modelData.focusedWindowCompactMode !== undefined ? modelData.focusedWindowCompactMode : SettingsData.focusedWindowCompactMode;
case "keyboard_layout_name":
return modelData.keyboardLayoutNameCompactMode !== undefined ? modelData.keyboardLayoutNameCompactMode : SettingsData.keyboardLayoutNameCompactMode;
default:
@@ -485,8 +517,6 @@ Column {
switch (modelData.id) {
case "clock":
return modelData.clockCompactMode !== undefined ? modelData.clockCompactMode : SettingsData.clockCompactMode;
case "focusedWindow":
return modelData.focusedWindowCompactMode !== undefined ? modelData.focusedWindowCompactMode : SettingsData.focusedWindowCompactMode;
case "keyboard_layout_name":
return modelData.keyboardLayoutNameCompactMode !== undefined ? modelData.keyboardLayoutNameCompactMode : SettingsData.keyboardLayoutNameCompactMode;
default:
@@ -500,8 +530,6 @@ Column {
switch (modelData.id) {
case "clock":
return modelData.clockCompactMode !== undefined ? modelData.clockCompactMode : SettingsData.clockCompactMode;
case "focusedWindow":
return modelData.focusedWindowCompactMode !== undefined ? modelData.focusedWindowCompactMode : SettingsData.focusedWindowCompactMode;
case "keyboard_layout_name":
return modelData.keyboardLayoutNameCompactMode !== undefined ? modelData.keyboardLayoutNameCompactMode : SettingsData.keyboardLayoutNameCompactMode;
default:
@@ -515,8 +543,6 @@ Column {
switch (modelData.id) {
case "clock":
return modelData.clockCompactMode !== undefined ? modelData.clockCompactMode : SettingsData.clockCompactMode;
case "focusedWindow":
return modelData.focusedWindowCompactMode !== undefined ? modelData.focusedWindowCompactMode : SettingsData.focusedWindowCompactMode;
case "keyboard_layout_name":
return modelData.keyboardLayoutNameCompactMode !== undefined ? modelData.keyboardLayoutNameCompactMode : SettingsData.keyboardLayoutNameCompactMode;
default:
@@ -1067,6 +1093,174 @@ Column {
}
}
Popup {
id: focusedWindowContextMenu
property var widgetData: null
property string sectionId: ""
property int widgetIndex: -1
width: 180
height: focusedWindowMenuColumn.implicitHeight + Theme.spacingS * 2
padding: 0
modal: true
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
background: Rectangle {
color: Theme.surfaceContainer
radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
}
contentItem: Item {
Column {
id: focusedWindowMenuColumn
anchors.fill: parent
anchors.margins: Theme.spacingS
spacing: 2
Rectangle {
width: parent.width
height: 32
radius: Theme.cornerRadius
color: fwCompactArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: "zoom_in"
size: 16
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Compact")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
anchors.verticalCenter: parent.verticalCenter
}
}
DankToggle {
id: fwCompactToggle
anchors.right: parent.right
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
width: 40
height: 20
checked: focusedWindowContextMenu.currentWidgetData?.focusedWindowCompactMode ?? SettingsData.focusedWindowCompactMode
onToggled: {
root.overflowSettingChanged(focusedWindowContextMenu.sectionId, focusedWindowContextMenu.widgetIndex, "focuswedWindowCompactMode", toggled);
}
}
MouseArea {
id: fwCompactArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: {
fwCompactToggle.checked = !fwCompactToggle.checked;
root.overflowSettingChanged(focusedWindowContextMenu.sectionId, focusedWindowContextMenu.widgetIndex, "focusedWindowCompactMode", fwCompactToggle.checked);
}
}
}
Repeater {
model: [
{
icon: "photo_size_select_small",
label: I18n.tr("Small"),
sizeValue: 0
},
{
icon: "photo_size_select_actual",
label: I18n.tr("Medium"),
sizeValue: 1
},
{
icon: "photo_size_select_large",
label: I18n.tr("Large"),
sizeValue: 2
},
{
icon: "fit_screen",
label: I18n.tr("Largest"),
sizeValue: 3
}
]
delegate: Rectangle {
required property var modelData
required property int index
function isSelected() {
var wd = focusedWindowContextMenu.widgetData;
var currentSize = wd?.focusedWindowSize ?? SettingsData.focusedWindowSize;
return currentSize === modelData.sizeValue;
}
width: focusedWindowMenuColumn.width
height: Math.max(18, Theme.fontSizeSmall) + Theme.spacingM * 2
radius: Theme.cornerRadius
color: focusedWindowOptionArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: modelData.icon
size: 18
color: isSelected() ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: modelData.label
font.pixelSize: Theme.fontSizeSmall
font.weight: isSelected() ? Font.Medium : Font.Normal
color: isSelected() ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankIcon {
anchors.right: parent.right
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
name: "check"
size: 16
color: Theme.primary
visible: isSelected()
}
MouseArea {
id: focusedWindowOptionArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.widgetSizeChanged("focusedWindow", modelData.sizeValue);
focusedWindowContextMenu.close();
}
}
}
}
}
}
}
Popup {
id: diskUsageContextMenu
@@ -2144,7 +2338,7 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.compactModeChanged("music", modelData.sizeValue);
root.widgetSizeChanged("music", modelData.sizeValue);
musicContextMenu.close();
}
}