diff --git a/assets/translations/en.json b/assets/translations/en.json index 5de9c57697..9185a9ec9e 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -3307,6 +3307,11 @@ "label": "Labels Only When Occupied", "workspaces-description": "Show workspace ID or name labels on workspaces with open windows and on the active workspace even when it is empty; other empty tags stay unlabeled" }, + "use-custom-workspace-ids":{ + "description": "Use Custom workspace IDs", + "label": "Custom Workspace IDs", + "workspaces-description": "Set a custom ID for each numerical workspace to be displayed on the widget" + }, "length": { "description": "Spacer length in pixels", "label": "Length" diff --git a/src/shell/bar/widget_factory.cpp b/src/shell/bar/widget_factory.cpp index b896002b72..710fd11c49 100644 --- a/src/shell/bar/widget_factory.cpp +++ b/src/shell/bar/widget_factory.cpp @@ -13,6 +13,7 @@ #include "shell/bar/widgets/clock_widget.h" #include "shell/bar/widgets/control_center_widget.h" #include "shell/bar/widgets/custom_button_widget.h" + #ifndef NDEBUG #include "shell/bar/widgets/debug_indicator_widget.h" #endif @@ -690,7 +691,17 @@ std::unique_ptr WidgetFactory::create( const ColorSpec urgentColor = wc != nullptr ? wc->getColorSpec("urgent_color", colorSpecFromRole(ColorRole::Error), "widget." + name + ".urgent_color") : colorSpecFromRole(ColorRole::Error); + const bool useCustomWorkspaceIDs = wc != nullptr ? wc->getBool("use_custom_workspace_ids") : false; WorkspacesWidget::DisplayMode displayMode = WorkspacesWidget::DisplayMode::Id; + std::unordered_map workspaceLabelMap{}; + for (int i = 1; i <= 10; i++) { + auto id = std::format("workspace_{}_id", i); + if (wc == nullptr) + break; + if (wc->hasSetting(id)) { + workspaceLabelMap[i] = wc->getString(id); + } + } if (display == "id") { displayMode = WorkspacesWidget::DisplayMode::Id; } else if (display == "name") { @@ -719,6 +730,8 @@ std::unique_ptr WidgetFactory::create( .focusedPill = workspaceStyle == "focus_hint", .focusedOutputOnly = wc != nullptr ? wc->getBool("focused_output_only", false) : false, .enableScroll = wc != nullptr ? wc->getBool("enable_scroll", true) : true, + .useCustomWorkspaceIds = useCustomWorkspaceIDs, + .workspaceIdMap = std::move(workspaceLabelMap) }; auto widget = std::make_unique(m_platform, m_configService, output, options); widget->setContentScale(contentScale); diff --git a/src/shell/bar/widgets/workspaces_widget.cpp b/src/shell/bar/widgets/workspaces_widget.cpp index 2b1d609e35..a42cacd439 100644 --- a/src/shell/bar/widgets/workspaces_widget.cpp +++ b/src/shell/bar/widgets/workspaces_widget.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -78,7 +79,8 @@ WorkspacesWidget::WorkspacesWidget( m_activePillSize(std::clamp(options.activePillSize, 0.25f, 8.0f)), m_inactivePillSize(std::clamp(options.inactivePillSize, 0.25f, 8.0f)), m_minimal(options.minimal), m_focusedPill(options.focusedPill), m_focusedOutputOnly(options.focusedOutputOnly), - m_enableScroll(options.enableScroll), m_focusedColor(options.focusedColor), + m_enableScroll(options.enableScroll), m_useCustomWorkspaceIds(options.useCustomWorkspaceIds), + m_workspaceIdMap(std::move(options.workspaceIdMap)), m_focusedColor(options.focusedColor), m_occupiedColor(options.occupiedColor), m_emptyColor(options.emptyColor), m_urgentColor(options.urgentColor) { buildDesktopIconIndex(); } @@ -1418,10 +1420,18 @@ std::string WorkspacesWidget::workspaceLabel(const Workspace& workspace, std::si const DisplayMode displayMode = effectiveDisplayMode(); std::string label; if (displayMode == DisplayMode::Id) { + if (m_useCustomWorkspaceIds && m_workspaceIdMap.contains(static_cast(workspace.index))) { + return m_workspaceIdMap.at(static_cast(workspace.index)); + } + if (workspace.index > 0) { label = std::to_string(workspace.index); } else if (const auto numericId = numericWorkspaceId(workspace); numericId.has_value()) { - label = std::to_string(*numericId); + if (m_useCustomWorkspaceIds && m_workspaceIdMap.contains(static_cast(*numericId))) { + label = m_workspaceIdMap.at(static_cast(*numericId)); + } else { + label = std::to_string(*numericId); + } } else { label = std::to_string(displayIndex + 1); } diff --git a/src/shell/bar/widgets/workspaces_widget.h b/src/shell/bar/widgets/workspaces_widget.h index 7f5f13198e..f2fc9ed224 100644 --- a/src/shell/bar/widgets/workspaces_widget.h +++ b/src/shell/bar/widgets/workspaces_widget.h @@ -44,6 +44,8 @@ class WorkspacesWidget : public Widget { bool focusedPill = false; bool focusedOutputOnly = false; bool enableScroll = true; + bool useCustomWorkspaceIds = false; + std::unordered_map workspaceIdMap; }; WorkspacesWidget(CompositorPlatform& platform, ConfigService& config, wl_output* output, Options options); @@ -157,6 +159,8 @@ class WorkspacesWidget : public Widget { bool m_enableScroll = true; bool m_wasFocusedOutput = true; bool m_activeUsesFocusedColor = true; + bool m_useCustomWorkspaceIds = false; + std::unordered_map m_workspaceIdMap; std::string m_cachedActiveWindowAppId; IconResolver m_iconResolver; std::unordered_map m_appIcons; diff --git a/src/shell/settings/widget_settings_registry.cpp b/src/shell/settings/widget_settings_registry.cpp index 4990123957..7692af6ccd 100644 --- a/src/shell/settings/widget_settings_registry.cpp +++ b/src/shell/settings/widget_settings_registry.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1093,6 +1094,27 @@ namespace settings { "settings.widgets.settings.labels-only-when-occupied.workspaces-description"; add(std::move(labelsOnlyWhenOccupied)); } + { + auto useCustomWorkspaceIds = withGroup(boolSpec("use_custom_workspace_ids", false), "workspaces.list"); + useCustomWorkspaceIds.descriptionKey = + "settings.widgets.settings.use-custom-workspace-ids.workspaces-description"; + add(std::move(useCustomWorkspaceIds)); + } + { + WidgetSettingVisibility workspaceIdVisibility; + workspaceIdVisibility.all = { + WidgetSettingVisibilityCondition{"use_custom_workspace_ids", {"true"}}, + }; + + for (int i = 1; i <= 10; i++) { + auto spec = stringSpec(std::format("workspace_{}_id", i), std::to_string(i)); + spec.literalLabel = std::format("Workspace {} ID", i); + auto workspace_id = withGroup(std::move(spec), "workspaces.list"); + workspace_id.literalDescription = std::format("Display ID for workspace {}", i); + workspace_id.visibleWhen = workspaceIdVisibility; + add(std::move(workspace_id)); + } + } { auto maxLabelChars = withGroup(intSpec("max_label_chars", 1, 1.0, 20.0, 1.0), "workspaces.list"); maxLabelChars.descriptionKey = "settings.widgets.settings.max-label-chars.workspaces-description";