shell: general date and time format. applied to lockscreen and control center

This commit is contained in:
Lemmy
2026-05-09 01:30:39 -04:00
parent 3696fb58b9
commit 72ae75eab3
14 changed files with 82 additions and 18 deletions
+11 -2
View File
@@ -201,8 +201,8 @@
"nightlight": "Night Light",
"nightlight-states": {
"off": "Night Light",
"scheduled-day": "Scheduled — day",
"scheduled-night": "Night Light",
"scheduled-day": "Scheduled",
"scheduled-night": "Running",
"forced": "Always on"
},
"notification": "DND",
@@ -729,6 +729,7 @@
"directories": "Directories",
"effects": "Effects",
"focus-styling": "Focus Styling",
"formats": "Formats",
"general": "General",
"grouping": "Grouping",
"lifecycle": "Lifecycle",
@@ -1252,6 +1253,14 @@
"label": "Middle Click Opens Widget Settings",
"description": "Open a bar widget's settings from the bar with middle click"
},
"time-format": {
"label": "Time Format",
"description": "Default time format for shell UI without its own setting"
},
"date-format": {
"label": "Date Format",
"description": "Default date format for shell UI without its own setting"
},
"show-location": {
"label": "Show Location",
"description": "Show location name in weather widgets"
+2
View File
@@ -7,6 +7,8 @@
[shell]
ui_scale = 1.0
font_family = "sans-serif"
time_format = "{:%H:%M}" # default shell UI time format
date_format = "%A, %x" # default shell UI date format
offline_mode = false # block all outgoing HTTP when true
telemetry_enabled = false # send an anonymous usage ping on startup
polkit_agent = false
+5 -4
View File
@@ -285,10 +285,11 @@ namespace {
bool shellConfigEqual(const ShellConfig& a, const ShellConfig& b) {
return nearlyEqual(a.uiScale, b.uiScale) && a.fontFamily == b.fontFamily && a.lang == b.lang &&
a.offlineMode == b.offlineMode && a.telemetryEnabled == b.telemetryEnabled &&
a.polkitAgent == b.polkitAgent && a.passwordMaskStyle == b.passwordMaskStyle &&
a.animation.enabled == b.animation.enabled && nearlyEqual(a.animation.speed, b.animation.speed) &&
a.avatarPath == b.avatarPath && a.settingsShowAdvanced == b.settingsShowAdvanced &&
a.timeFormat == b.timeFormat && a.dateFormat == b.dateFormat && a.offlineMode == b.offlineMode &&
a.telemetryEnabled == b.telemetryEnabled && a.polkitAgent == b.polkitAgent &&
a.passwordMaskStyle == b.passwordMaskStyle && a.animation.enabled == b.animation.enabled &&
nearlyEqual(a.animation.speed, b.animation.speed) && a.avatarPath == b.avatarPath &&
a.settingsShowAdvanced == b.settingsShowAdvanced &&
a.middleClickOpensWidgetSettings == b.middleClickOpensWidgetSettings && a.showLocation == b.showLocation &&
a.clipboardAutoPaste == b.clipboardAutoPaste && a.shadow.blur == b.shadow.blur &&
a.shadow.offsetX == b.shadow.offsetX && a.shadow.offsetY == b.shadow.offsetY &&
+6
View File
@@ -1181,6 +1181,12 @@ void ConfigService::parseTableInto(const toml::table& tbl, Config& config, bool
if (auto v = (*shellTbl)["lang"].value<std::string>()) {
shell.lang = *v;
}
if (auto v = (*shellTbl)["time_format"].value<std::string>()) {
shell.timeFormat = *v;
}
if (auto v = (*shellTbl)["date_format"].value<std::string>()) {
shell.dateFormat = *v;
}
if (auto v = (*shellTbl)["offline_mode"].value<bool>()) {
shell.offlineMode = *v;
}
+2
View File
@@ -370,6 +370,8 @@ struct ShellConfig {
float uiScale = 1.0f;
std::string fontFamily = "sans-serif";
std::string lang; // empty = auto-detect from $LC_ALL/$LC_MESSAGES/$LANG
std::string timeFormat = "{:%H:%M}";
std::string dateFormat = "%A, %x";
bool offlineMode = false;
bool telemetryEnabled = false;
bool polkitAgent = false;
+17 -2
View File
@@ -1,5 +1,6 @@
#include "shell/control_center/calendar_tab.h"
#include "config/config_service.h"
#include "core/ui_phase.h"
#include "i18n/i18n.h"
#include "render/core/renderer.h"
@@ -84,8 +85,15 @@ namespace {
return state;
}
std::string formatShellDate(const ConfigService* config) {
const char* format = config != nullptr ? config->config().shell.dateFormat.c_str() : "%A, %x";
return formatLocalTime(format);
}
} // namespace
CalendarTab::CalendarTab(ConfigService* config) : m_config(config) {}
std::unique_ptr<Flex> CalendarTab::create() {
const float scale = contentScale();
@@ -159,7 +167,7 @@ std::unique_ptr<Flex> CalendarTab::create() {
monthWrap->addChild(std::move(month));
auto monthSub = std::make_unique<Label>();
monthSub->setText(i18n::tr("control-center.calendar.today"));
monthSub->setText(formatShellDate(m_config));
monthSub->setCaptionStyle();
monthSub->setFontSize(Style::fontSizeCaption * scale);
monthSub->setColor(colorSpecFromRole(ColorRole::OnSurfaceVariant));
@@ -257,6 +265,13 @@ void CalendarTab::doLayout(Renderer& renderer, float contentWidth, float bodyHei
m_rootLayout->layout(renderer);
}
void CalendarTab::doUpdate(Renderer& renderer) {
(void)renderer;
if (m_monthSubLabel != nullptr) {
m_monthSubLabel->setText(formatShellDate(m_config));
}
}
void CalendarTab::onClose() {
m_rootLayout = nullptr;
m_calendarArea = nullptr;
@@ -328,7 +343,7 @@ void CalendarTab::rebuild() {
m_monthLabel->setText(monthName(month) + " " + std::to_string(year));
m_monthLabel->setMaxWidth(monthWidth);
if (m_monthSubLabel != nullptr) {
m_monthSubLabel->setText(formatCurrentDate());
m_monthSubLabel->setText(formatShellDate(m_config));
m_monthSubLabel->setMaxWidth(monthWidth);
}
+5
View File
@@ -5,18 +5,23 @@
#include <limits>
class Button;
class ConfigService;
class InputArea;
class Label;
class CalendarTab : public Tab {
public:
explicit CalendarTab(ConfigService* config = nullptr);
std::unique_ptr<Flex> create() override;
void onClose() override;
private:
void doLayout(Renderer& renderer, float contentWidth, float bodyHeight) override;
void doUpdate(Renderer& renderer) override;
void rebuild();
ConfigService* m_config = nullptr;
Flex* m_rootLayout = nullptr;
InputArea* m_calendarArea = nullptr;
Flex* m_card = nullptr;
@@ -34,7 +34,7 @@ ControlCenterPanel::ControlCenterPanel(
m_tabs[tabIndex(TabId::Audio)] =
std::make_unique<AudioTab>(audio, mpris, config, wayland, PanelManager::instance().renderContext());
m_tabs[tabIndex(TabId::Weather)] = std::make_unique<WeatherTab>(weather, config);
m_tabs[tabIndex(TabId::Calendar)] = std::make_unique<CalendarTab>();
m_tabs[tabIndex(TabId::Calendar)] = std::make_unique<CalendarTab>(config);
m_tabs[tabIndex(TabId::Notifications)] = std::make_unique<NotificationsTab>(notifications);
m_tabs[tabIndex(TabId::Network)] = std::make_unique<NetworkTab>(network, networkSecrets);
m_tabs[tabIndex(TabId::Bluetooth)] = std::make_unique<BluetoothTab>(bluetooth, bluetoothAgent);
+14 -4
View File
@@ -45,6 +45,16 @@ namespace {
float dashboardAvatarSize(float scale) { return Style::controlHeightLg * kDashboardAvatarScale * scale; }
std::string formatShellTime(const ConfigService* config) {
const char* format = config != nullptr ? config->config().shell.timeFormat.c_str() : "{:%H:%M}";
return formatLocalTime(format);
}
std::string formatShellDate(const ConfigService* config) {
const char* format = config != nullptr ? config->config().shell.dateFormat.c_str() : "%A, %x";
return formatLocalTime(format);
}
void applyDashboardCardStyle(Flex& card, float scale) {
applySectionCardStyle(card, scale);
card.setGap(Style::spaceSm * scale);
@@ -262,7 +272,7 @@ std::unique_ptr<Flex> DashboardTab::create() {
m_dateTimeCard = dateTimeCard.get();
auto timeLabel = std::make_unique<Label>();
timeLabel->setText(formatLocalTime("{:%H:%M}"));
timeLabel->setText(formatShellTime(m_config));
timeLabel->setBold(true);
timeLabel->setFontSize(Style::fontSizeTitle * 1.7f * scale);
timeLabel->setColor(colorSpecFromRole(ColorRole::Primary));
@@ -276,7 +286,7 @@ std::unique_ptr<Flex> DashboardTab::create() {
dateTimeRight->setGap(Style::spaceXs * 0.5f * scale);
auto dateLabel = std::make_unique<Label>();
dateLabel->setText(formatCurrentDate());
dateLabel->setText(formatShellDate(m_config));
dateLabel->setFontSize(Style::fontSizeBody * 0.9f * scale);
dateLabel->setColor(colorSpecFromRole(ColorRole::OnSurface));
m_dateLabel = dateLabel.get();
@@ -744,10 +754,10 @@ void DashboardTab::sync(Renderer& renderer) {
syncShortcuts();
if (m_timeLabel != nullptr) {
m_timeLabel->setText(formatLocalTime("{:%H:%M}"));
m_timeLabel->setText(formatShellTime(m_config));
}
if (m_dateLabel != nullptr) {
m_dateLabel->setText(formatCurrentDate());
m_dateLabel->setText(formatShellDate(m_config));
}
syncWallpaperBackground(renderer);
+1 -1
View File
@@ -329,7 +329,7 @@ void LockScreen::syncInstances() {
}
void LockScreen::createInstance(const WaylandOutput& output) {
auto surface = std::make_unique<LockSurface>(*m_wayland);
auto surface = std::make_unique<LockSurface>(*m_wayland, m_configService);
surface->setRenderContext(m_renderContext);
surface->setTextureCache(m_textureCache);
surface->setLockedState(m_locked);
+7 -3
View File
@@ -37,9 +37,13 @@ namespace {
return tryParseHexColor(path.substr(kPrefix.size()), out);
}
const char* shellTimeFormat(const ConfigService* config) {
return config != nullptr ? config->config().shell.timeFormat.c_str() : "{:%H:%M}";
}
} // namespace
LockSurface::LockSurface(WaylandConnection& connection) : Surface(connection) {
LockSurface::LockSurface(WaylandConnection& connection, ConfigService* config) : Surface(connection), m_config(config) {
auto wallpaper = std::make_unique<WallpaperNode>();
m_wallpaper = static_cast<WallpaperNode*>(m_root.addChild(std::move(wallpaper)));
m_wallpaper->setZIndex(0);
@@ -254,7 +258,7 @@ void LockSurface::onPointerEvent(const PointerEvent& event) {
}
void LockSurface::onSecondTick() {
const auto text = formatLocalTime("{:%H:%M}");
const auto text = formatLocalTime(shellTimeFormat(m_config));
if (m_clock != nullptr && m_clock->text() != text) {
requestUpdate();
}
@@ -405,4 +409,4 @@ void LockSurface::applyWallpaperTexture() {
m_wallpaperDirty = false;
}
void LockSurface::updateClockText() { m_clock->setText(formatLocalTime("{:%H:%M}")); }
void LockSurface::updateClockText() { m_clock->setText(formatLocalTime(shellTimeFormat(m_config))); }
+2 -1
View File
@@ -27,7 +27,7 @@ struct PointerEvent;
class LockSurface : public Surface {
public:
explicit LockSurface(WaylandConnection& connection);
explicit LockSurface(WaylandConnection& connection, ConfigService* config = nullptr);
~LockSurface() override;
using Surface::initialize;
@@ -61,6 +61,7 @@ private:
ext_session_lock_surface_v1* m_lockSurface = nullptr;
wl_output* m_output = nullptr;
ConfigService* m_config = nullptr;
Node m_root;
WallpaperNode* m_wallpaper = nullptr;
Box* m_backdrop = nullptr;
+3
View File
@@ -1309,6 +1309,9 @@ void PanelManager::onConfigReloaded() {
// Re-apply compositor blur for any open panel — covers both attached and layer-shell
// panels reacting to shell.panel.background_blur changes.
applyPanelCompositorBlur();
if (m_surface != nullptr) {
m_surface->requestUpdate();
}
// The remaining work is bar-config-driven and only applies to attached panels.
if (!isAttachedOpen() || m_output == nullptr) {
+6
View File
@@ -569,6 +569,12 @@ namespace settings {
tr("settings.schema.shell.middle-click-opens-widget-settings.description"),
{"shell", "middle_click_opens_widget_settings"}, ToggleSetting{cfg.shell.middleClickOpensWidgetSettings},
"bar widget settings middle click configure"));
entries.push_back(makeEntry("shell", "formats", tr("settings.schema.shell.time-format.label"),
tr("settings.schema.shell.time-format.description"), {"shell", "time_format"},
TextSetting{cfg.shell.timeFormat, "{:%H:%M}"}, "clock time format strftime chrono"));
entries.push_back(makeEntry("shell", "formats", tr("settings.schema.shell.date-format.label"),
tr("settings.schema.shell.date-format.description"), {"shell", "date_format"},
TextSetting{cfg.shell.dateFormat, "%A, %x"}, "calendar date format strftime chrono"));
entries.push_back(makeEntry("shell", "location", tr("settings.schema.shell.show-location.label"),
tr("settings.schema.shell.show-location.description"), {"shell", "show_location"},
ToggleSetting{cfg.shell.showLocation}, "weather"));