Skip to content

Commit a5ec24f

Browse files
committed
doc: Document the power menu and the clock widgets
1 parent 769ea68 commit a5ec24f

File tree

6 files changed

+204
-13
lines changed

6 files changed

+204
-13
lines changed

docs/CONFIG.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<!--
2+
SPDX-FileCopyrightText: 2024 max-ishere
3+
4+
SPDX-License-Identifier: GPL-3.0-or-later
5+
-->
6+
# ReGreet configuration docs
7+
8+
## Clock
9+
10+
The clock widget can be customized to specify the
11+
[time display format](https://docs.rs/jiff/0.1.14/jiff/fmt/strtime/index.html#conversion-specifications),
12+
how often to update the clock, overrides to the system timezone and a custom fixed label width so that the non-monospace
13+
font does not cause annoying width changes in the UI.
14+
15+
```toml
16+
[widget.clock]
17+
# strftime format argument
18+
format = "%a %H:%M"
19+
20+
# How often to update the text
21+
resolution = "500ms"
22+
23+
# Override system timezone (IANA Time Zone Database name, aka /etc/zoneinfo path)
24+
# Remove to use the system time zone.
25+
timezone = "America/Chicago"
26+
27+
# Ask GTK to make the label at least this wide. This helps keeps the parent element layout and width consistent.
28+
# Experiment with different widths, the interpretation of this value is entirely up to GTK.
29+
label_width = 150
30+
```
31+
32+
## Power menu
33+
34+
The first step in configuring the power menu is to select the backend to use. The backend is specified as part of the
35+
path under `widget.power-menu.<backend>`. Please note that only 1 backend can be active at a time.
36+
37+
For your convenience, most backends allow you to specify an action that is automatically translated into the supported
38+
languages. The correct icon is also selected. Actions that will poweroff your system will ask for confirmation before
39+
they are executed. The actions are listed in the table below.
40+
41+
| Config value | Confirmation required |
42+
|-----------------|-----------------------|
43+
| poweroff | Yes |
44+
| halt | Yes |
45+
| reboot | Yes |
46+
| reboot-firmware | Yes |
47+
| suspend | No |
48+
| hibernate | No |
49+
| hybrid-sleep | No |
50+
51+
The convention most backends' configs follow is having a single `actions` key, which is an array of actions. This simple
52+
structure allows you to easily add, remove, and reorder the buttons in the menu without having to verbosely specify all
53+
the attributes like you can do with the [custom](#custom) backend.
54+
55+
### Systemd
56+
57+
Machines using Systemd as the init system can specify the following line to use the default configuration.
58+
59+
```toml
60+
[widget.power-menu.systemd]
61+
```
62+
63+
The displayed actions can be changed using the `actions` key. [See above](#power-menu) for more details
64+
65+
```toml
66+
[widget.power-menu.systemd]
67+
actions = ["suspend", "poweroff", "reboot-firmware"]
68+
```
69+
70+
### Unix
71+
72+
This backend should work on most systems as it does not use commands shipped with any specific init system. Instead, the
73+
Linux `shutdown` command is used.
74+
75+
```toml
76+
[widget.power-menu.unix]
77+
```
78+
79+
> [!NOTE]
80+
> The only actions supported by this backend are poweroff, reboot, and halt.
81+
>
82+
> When other values are specified they are logged as warnings and silently skipped.
83+
84+
```toml
85+
[widget.power-menu.systemd]
86+
actions = ["poweroff", "reboot", "halt"]
87+
```
88+
89+
### Custom
90+
91+
The custom backend allows you to fully customize the power menu. If none of the other backends suit your needs or
92+
require additional customizations, consider using this backend.
93+
94+
It is necesary to set the `backend` key to the backend that you are implementing. The backend string can have any value
95+
and is only used as part of the label in the power menu. The actions can be specified in the `commands` key.
96+
97+
The power menu button (as well as `commands`) has the following fields:
98+
99+
- `String` Label
100+
- `String` Icon (optional)
101+
- `bool` Should this entry be confirmed?
102+
- `Vec<String>` Command to execute
103+
104+
The label, icon and confirmation can be inferred by ReGreet automatically if you set the `action` field.
105+
106+
```toml
107+
[widget.power-menu.custom]
108+
backend = "Custom" # Required value
109+
110+
[[widget.power-menu.custom.commands]]
111+
action = "poweroff"
112+
command = ["shutdown", "--now"]
113+
# `action` Infers:
114+
# label = "..." ## NOTE: label and action are mutually exclusive
115+
# icon = "..."
116+
# confirm = ...
117+
```
118+
119+
Overrides (that are different from the action defaults) can be specified for the icon and the confirm, but not the
120+
label. The logic is that if you are specifying a custom label, you are likely also specifying a custom command that
121+
ReGreet does not know how to interpret into the inferable fields.
122+
123+
The icon can be hidden altogether by setting it to an empty string.
124+
125+
```toml
126+
[[widget.power-menu.custom.commands]]
127+
action = "poweroff"
128+
command = ["shutdown", "--now"]
129+
icon = "" # no icon
130+
confirm = false
131+
# Infers:
132+
# label = Poweroff" ## NOTE: label and action are mutually exclusive
133+
```

src/gui/widget/power_menu/custom.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

5-
//! A fully customizable power menu widget.
5+
//! A fully customizable power menu backend.
66
77
use super::{Action, PowerMenuInit};
88

@@ -11,13 +11,24 @@ use super::{Action, PowerMenuInit};
1111
/// A fully-customizable power menu. You can run arbitrary commands and set labels for them. See [`Command`] for a list
1212
/// of all properties that can be configured
1313
pub struct CustomPowerMenuConfig {
14+
/// A string label in the UI that indicates the backend this menu uses.
15+
///
16+
/// For example, if you implement the power menu using `runit` commands, set the backend to Runit.
1417
backend: String,
1518
commands: Vec<Command>,
1619
}
1720

21+
/// A set of customizations that can be done to the power menu item.
22+
///
23+
/// Setting [`Self::title`] to [`Title::Action`] allows ReGreet to infer the translated label, the icon to use, and the
24+
/// need to confirm the action.
25+
///
26+
/// However, if the power menu item does not fit any of the known to ReGreet [`Action`]s, you can use the
27+
/// [`Title::Label`] variant and optionally specify the [`Self::confirm`] and the [`Self::icon`].
1828
#[derive(Deserialize, Clone)]
1929
pub struct Command {
20-
/// The title of the action.
30+
/// The title of the action. This field is flattened in the config, so instead of setting `*command*.title.action`,
31+
/// set `*command*.action`.
2132
#[serde(flatten)]
2233
title: Title,
2334

@@ -27,11 +38,17 @@ pub struct Command {
2738

2839
/// If `true`, a confirmation will be shown before the [`Self::command`] is executed.
2940
///
41+
/// The [`Option`] is handled according to these rules:
42+
///
3043
/// If [`Some`], use the value. Otherwise, try to derive the value from the [`Title::Action`], falling back to
3144
/// `false`. Actions that involve a poweroff are inferred to require confirmation.
3245
confirm: Option<bool>,
3346

3447
/// The icon name to set for this action. A list of installed icons can be looked up using the `icon-library` app.
48+
///
49+
/// If [`None`], the icon is inferred from the value of [`Title::Action`], falling back to no icon.
50+
///
51+
/// An empty string can be used to disable the icon for this item.
3552
icon: Option<String>,
3653
}
3754

src/gui/widget/power_menu/mod.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,32 @@
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

55
//! A [serde-configurable][`PowerMenuConfig`] power menu.
6+
//!
7+
//! See submodules for information on how to configure each power menu backend.
8+
//!
9+
//! ## Implementing a custom power menu backend
10+
//!
11+
//! Users of ReGreet can use the [`custom`] backend to specify arbitrary commands you want to run. Although this is not
12+
//! intended, nothing stops you from adding entries unrelated to power management.
13+
//!
14+
//! However, if you want to add support for another init system, for example, it is best to implement a custom backend.
15+
//! Fortunately, this is easy to do.
16+
//!
17+
//! You will need to create a config for this backend. Most likely, only having a single `actions: Vec<Action>` field
18+
//! will be sufficient. For forward compatibility, please do not skip creating a `struct {}` to hold the config (exactly
19+
//! the `{}` struct format). Having this struct allows future maintainers to add or rename fields more easily without
20+
//! having to deal with config structure migrations.
21+
//!
22+
//! Make sure to implement sensible defaults for the entire struct. In cases where a default value should be inferred
23+
//! after the config is parsed, use an [`Option`] to detect that the user did not set the value and generate the default
24+
//! in the [`PowerMenuInit`] implementation.
25+
//!
26+
//! Finally, implement a coversion from your custom config struct using the [`PowerMenuInit`] trait. The [`Action`] can
27+
//! be used to infer a lot of information such as the [icon](`Action::icon`) and the [translated label](`Action::fl`).
28+
//! The confirmation requirement logic defaults to checking if the action
29+
//! [involves a poweroff](`Action::is_like_poweroff`).
30+
//!
31+
//! Lastly, add your config type as a variant to the [`PowerMenuConfig`].
632
733
use custom::CustomPowerMenuConfig;
834
use relm4::{
@@ -72,8 +98,8 @@ pub enum MenuState {
7298

7399
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74100
pub enum PowerMenuMsg {
75-
/// Sent when the user selected a power menu button. If the action requires confirmation (involves a poweroff of the
76-
/// system) a confirmation screen is shown ([`PowerMenu::Confirm`] state).
101+
/// Sent when the user selected a power menu button. If the action [requires confirmation](`Command::confirm`)
102+
/// a confirmation screen is shown ([`MenuState::Confirm`] state).
77103
Request(usize),
78104

79105
/// A confirmation of a [`PowerMenuMsg::Request`] was cancelled. Has no effect if no confirmation is requested.
@@ -322,6 +348,8 @@ impl Action {
322348
}
323349
}
324350

351+
/// Returns `true` if executing this action would power off the system (meaning reboot counts). Putting the system to
352+
/// sleep does not count as it can be easily undone by waking up the system.
325353
pub const fn is_like_poweroff(&self) -> bool {
326354
matches!(
327355
self,
@@ -330,6 +358,7 @@ impl Action {
330358
}
331359
}
332360

361+
/// A convenience trait that converts any power menu config into a set of information that the generic UI can display.
333362
trait PowerMenuInit {
334363
fn backend(&self) -> String;
335364
fn commands(self) -> Vec<Command>;

src/gui/widget/power_menu/systemd.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

5-
//! A systemd-aware power menu widget.
5+
//! The Systemd power menu backend.
66
//!
77
//! See supported actions as variants of [`Action`].
88
@@ -15,8 +15,12 @@ use super::{Action, Command, PowerMenuInit};
1515
#[derive(Deserialize, Debug, Clone)]
1616
#[serde(rename_all = "snake_case")]
1717
pub struct SystemdPowerMenuConfig {
18-
/// The list of actions to show. Order is preserved. The first unique occurance is used, with duplicates discarded.
18+
/// The list of actions to show. Order is preserved.
19+
///
20+
/// The first unique occurance is used, with duplicates discarded.
1921
/// E.g. `["poweroff", "reboot", "poweroff"]` Results in this order of widgets: Poweroff, Reboot.
22+
///
23+
/// The button labels, icons and `systemctl` commands are automatically selected based on the action you specify.
2024
#[serde(default = "default_actions")]
2125
pub actions: Vec<Action>,
2226
}

src/gui/widget/power_menu/unix.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

5-
//! A power menu widget that uses the generic `man 8 shutdown` linux command.
6-
//!
7-
//! See supported actions as variants of [`Action`].
5+
//! A power menu backend that uses the generic `man 8 shutdown` linux command.
86
97
use std::collections::HashSet;
108

@@ -14,10 +12,15 @@ use super::{Action, Command, PowerMenuInit};
1412

1513
#[derive(Deserialize, Clone)]
1614
pub struct UnixPowerMenuConfig {
17-
/// The list of actions to show. Order is preserved. The first unique occurance is used, with duplicates discarded.
15+
/// The list of actions to show. Order is preserved.
16+
///
17+
/// The first unique occurance is used, with duplicates discarded.
1818
/// E.g. `["poweroff", "reboot", "poweroff"]` Results in this order of widgets: Poweroff, Reboot.
1919
///
20-
/// Please note that only `poweroff`, `reboot`, and `halt` are supported by the unix `shutdown` command.
20+
/// The button labels, icons and `systemctl` commands are automatically selected based on the action you specify.
21+
///
22+
/// Please note that only `poweroff`, `reboot`, and `halt` are supported by the unix `shutdown` command. Other
23+
/// actions are silently filtered out.
2124
#[serde(default = "default_actions")]
2225
actions: Vec<Action>,
2326
}
@@ -60,7 +63,10 @@ impl PowerMenuInit for UnixPowerMenuConfig {
6063
"--halt".to_string(),
6164
"now".to_string(),
6265
],
63-
_ => return acc,
66+
unsupported => {
67+
info!("{unsupported:?} is not supported in the Unix power menu backend.");
68+
return acc;
69+
}
6470
};
6571

6672
acc.push(Command::new(

src/i18n.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
//! # Internationalization
66
//!
7-
//! Firstly Initialize the language selection with [`init`]. Then use the [`fl`] macro to request a string by id.
7+
//! Firstly Initialize the language selection with [`init`]. Then use the [`fl!`] macro to request a string by id.
8+
//!
9+
//! [`fl!`]: crate::fl
810
911
use std::sync::LazyLock;
1012

0 commit comments

Comments
 (0)