Simplify documentation and website; expand shortcut guides
This commit is contained in:
1 parent
46509f880a
commit
4d60c296a7
26 files changed
+1060
-1032
No files matched your search
+1
-7
@@ -3,14 +3,8 @@
|
||||
*.log
|
||||
ChatGPT Image*.png
|
||||
|
||||
# Local implementation notes and validation plans
|
||||
# Local architecture decision notes
|
||||
/docs/adr/
|
||||
/docs/animation-validation.md
|
||||
/docs/nested-resize-testing.md
|
||||
/docs/native-soak-testing.md
|
||||
/docs/ferese-window-manager-spec.md
|
||||
/docs/ferese-theme-ui-spec.md
|
||||
/docs/ferese-shell-design.md
|
||||
|
||||
# Generated GitHub Pages site
|
||||
/build/site/
|
||||
|
||||
@@ -2,60 +2,35 @@
|
||||
<img src="docs/images/ferese-lockup.svg" width="300" alt="Ferese">
|
||||
</p>
|
||||
|
||||
<p align="center"><strong>A beautiful, fluid Wayland desktop made to feel like yours.</strong></p>
|
||||
<p align="center"><strong>A Wayland desktop with scrolling layouts and a shared theme.</strong></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="docs/installation.md">Install</a> ·
|
||||
<a href="docs/configuration.md">Configure</a> ·
|
||||
<a href="docs/desktop-widgets.md">Widgets</a> ·
|
||||
<a href="docs/notifications.md">Notifications</a>
|
||||
<a href="docs/README.md">Documentation</a>
|
||||
</p>
|
||||
|
||||
Ferese is a complete Wayland desktop built around personalization. Its custom
|
||||
shell, native settings, live-reloading themes and wallpapers, desktop widgets,
|
||||
fluid animations, and scrolling and tiling layouts work together as one
|
||||
cohesive experience—beautiful by default and unmistakably yours.
|
||||
Ferese is a Linux desktop with scrolling columns, tree tiling, and floating
|
||||
windows. It includes a top bar, Settings, notifications, desktop widgets, a
|
||||
lock screen, and screen sharing. Change themes and settings without restarting.
|
||||
|
||||

|
||||
|
||||
## Why Ferese
|
||||
## Features
|
||||
|
||||
- **Flexible layouts:** scrolling columns, tree tiling, floating windows and a
|
||||
workspace overview.
|
||||
- **A native shell:** menu bar, control center, settings, notifications and
|
||||
desktop widgets designed to belong together, including themed authentication prompts.
|
||||
Native apps share the [Ferese theme components](crates/ferese-theme/README.md).
|
||||
- **Personal by design:** themes, wallpapers, accent colors, blur, borders and
|
||||
motion that update without restarting your session.
|
||||
- **Ready for real setups:** gestures, multi-monitor support, fractional
|
||||
scaling, screenshots, background services and session locking.
|
||||
- **Screen sharing:** a native display picker and PipeWire video streams for
|
||||
portal-compatible recording and conferencing apps.
|
||||
- Scrolling and tree layouts, floating windows, and a workspace overview.
|
||||
- Configurable keyboard shortcuts and touchpad gestures.
|
||||
- Multiple monitors with fractional scaling.
|
||||
- Six theme presets, wallpapers, blur, and adjustable corners.
|
||||
- Clock and sticky-note widgets.
|
||||
- Screenshots with Satty editing, screen sharing, and top-bar recording.
|
||||
|
||||

|
||||
|
||||
The overview brings windows and workspaces into one view. Read more about
|
||||
[why Ferese builds the compositor and shell together](docs/why-ferese.md).
|
||||
|
||||
## Make it yours
|
||||
|
||||
Use the native Settings app for everyday customization, or edit
|
||||
`~/.config/ferese/config.kdl` when you want complete control. Ferese reloads
|
||||
changes as you make them and keeps the last working configuration if an edit is
|
||||
invalid.
|
||||
|
||||

|
||||
|
||||
Choose a preset or build your own look. Window behavior, gestures, shortcuts,
|
||||
rules, displays, widgets and login items are configurable too. Start with the
|
||||
[configuration guide](docs/configuration.md) or the
|
||||
[example config](packaging/config.kdl).
|
||||

|
||||
|
||||
## Install
|
||||
|
||||
Install Ferese on Linux with any Wayland-capable login manager, a command-based
|
||||
greeter, or a local TTY. Start with the [installation guide](docs/installation.md)
|
||||
for system dependencies and Rust 1.95 or newer, then build as your normal user:
|
||||
Install the [dependencies](docs/installation.md#requirements), then build as your
|
||||
normal user:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/ferese-wm/ferese.git
|
||||
@@ -63,59 +38,48 @@ cd ferese
|
||||
./scripts/install.sh
|
||||
```
|
||||
|
||||
Log out and select **Ferese** at your login screen. For greeters that take a
|
||||
session command, use `/usr/local/bin/ferese-session`. The installer preserves
|
||||
your configuration and other sessions, and retains the previous release for
|
||||
rollback. The guide covers [all startup methods](docs/installation.md#start-a-session),
|
||||
optional tools, updates, and recovery.
|
||||
Log out, select **Ferese** at your login screen, and sign in. For a TTY or a
|
||||
greeter that accepts a command, run `ferese-session`.
|
||||
See [Installation](docs/installation.md) for previews, updates, and recovery.
|
||||
|
||||
To preview Ferese inside your current Wayland desktop instead:
|
||||
## Configure
|
||||
|
||||
```sh
|
||||
cargo build --release --locked -p ferese -p ferese-shell -p ferese-settings -p feresectl -p ferese-lock
|
||||
target/release/ferese --backend nested --grant-effects --grant-shell-control -- \
|
||||
target/release/ferese-shell
|
||||
```
|
||||
Open **Control Center → Settings**, or edit `~/.config/ferese/config.kdl`.
|
||||
Changes reload automatically; invalid edits keep the last working configuration.
|
||||
|
||||
## Get around
|
||||

|
||||
|
||||
These are the built-in defaults; every shortcut and gesture can be changed.
|
||||
The login guide shows your active shortcuts. Disable it in **Settings → Shortcuts**
|
||||
when you no longer need it.
|
||||
See the [configuration reference](docs/configuration.md) and
|
||||
[example config](packaging/config.kdl).
|
||||
|
||||
## Default shortcuts
|
||||
|
||||
`Super` is usually the Windows key. Change shortcuts and gestures in
|
||||
**Settings → Shortcuts**.
|
||||
|
||||
| Shortcut | Action |
|
||||
| --- | --- |
|
||||
| Super + Enter | Open a terminal |
|
||||
| Super + H / J / K / L | Focus a window |
|
||||
| Super + H / J / K / L | Focus left / down / up / right |
|
||||
| Super + F | Maximize the window |
|
||||
| Super + Shift + F | Toggle fullscreen |
|
||||
| Super + R | Cycle column width |
|
||||
| Super + Tab | Open workspace and window overview |
|
||||
| Super + Tab | Open overview |
|
||||
| Super + M | Switch scrolling / tree layout |
|
||||
| Print Screen | Capture the active monitor and open Satty |
|
||||
| Super + Shift + S | Select a screenshot area |
|
||||
| Super + Shift + E | Ask to log out |
|
||||
|
||||
Click the bar date for a calendar. Click the battery for power modes and
|
||||
confirmed Restart, Power off and Suspend actions.
|
||||
See [all shortcuts and mouse actions](docs/shortcuts.md), including Super-drag
|
||||
to move and Super-right-drag to resize floating windows.
|
||||
|
||||
Three-finger swipes move between workspaces and windows. Open **Control Center →
|
||||
Settings → Shortcuts** to change them or assign gestures to other actions.
|
||||
Three-finger swipes up/down switch workspaces; left/right focus windows.
|
||||
The shortcut guide appears at login until disabled in Settings.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Why Ferese](docs/why-ferese.md)
|
||||
- [Installation and recovery](docs/installation.md)
|
||||
- [Configuration reference](docs/configuration.md)
|
||||
- [Desktop widgets](docs/desktop-widgets.md)
|
||||
- [Notifications](docs/notifications.md)
|
||||
- [Native locker](docs/locking.md)
|
||||
- [Desktop portals and compatibility](docs/portals.md)
|
||||
- [Screen sharing and recording](docs/screen-sharing.md)
|
||||
Start with the [documentation index](docs/README.md) for user guides and
|
||||
[development instructions](docs/development.md) for builds and testing.
|
||||
|
||||
## Development
|
||||
|
||||
```sh
|
||||
cargo test --workspace --locked
|
||||
cargo fmt --all --check
|
||||
```
|
||||
|
||||
Ferese is built in Rust on Smithay. Use release builds when evaluating motion
|
||||
and startup performance, and keep another desktop session available while
|
||||
testing hardware behavior.
|
||||
Ferese is written in Rust using Smithay. Report bugs on
|
||||
[GitHub](https://github.com/ferese-wm/ferese/issues) with reproduction steps and logs.
|
||||
+17
-13
@@ -65,7 +65,7 @@ use smithay::wayland::xdg_toplevel_icon::XdgToplevelIconManager;
|
||||
|
||||
use crate::backends::direct::DirectBackendState;
|
||||
use crate::config::{Binding, DaemonConfig, InputSettings, OutputProfile, ThemeSettings};
|
||||
use crate::cursor::NamedCursor;
|
||||
use crate::cursor::{NamedCursor, cursor_theme, load_named_cursor};
|
||||
use crate::dimming::DimAnimation;
|
||||
use crate::gestures::{Swipe, SwipeDirection};
|
||||
use crate::handlers::screencopy::PendingScreencopy;
|
||||
@@ -74,13 +74,14 @@ use crate::handlers::screenshot_worker::Worker;
|
||||
use crate::input::LockedPointerHint;
|
||||
use crate::input_capture::InputCapture;
|
||||
use crate::ipc::IpcSocketGuard;
|
||||
use crate::overview::OverviewState;
|
||||
use crate::portal_session::PortalSession;
|
||||
use crate::portal_shortcuts::PortalShortcuts;
|
||||
use crate::resize_transaction::ResizeTransaction;
|
||||
use crate::session_lock::{IdleSettings, Lock};
|
||||
use crate::shell_control::ShellSnapshot;
|
||||
use crate::stacking::WindowStack;
|
||||
use crate::wallpaper::WallpaperState;
|
||||
use crate::wallpaper::{WallpaperConfig, WallpaperState};
|
||||
use crate::window_rules::{WindowRule, resolve as resolve_window_rules};
|
||||
use crate::winit::{
|
||||
BlurProgram, MaterialBuffers, MaterialProgram, NestedBackend, OverviewScrim, ResizeSnapshot, RoundedClipPrograms,
|
||||
@@ -344,10 +345,10 @@ pub struct Ferese {
|
||||
}
|
||||
|
||||
pub struct RuntimeConfig {
|
||||
pub(crate) lock_idle: crate::session_lock::IdleSettings,
|
||||
pub(crate) autostart: Vec<crate::config::DaemonConfig>,
|
||||
pub(crate) lock_idle: IdleSettings,
|
||||
pub(crate) autostart: Vec<DaemonConfig>,
|
||||
pub(crate) overview_font_family: String,
|
||||
pub(crate) wallpaper: crate::wallpaper::WallpaperConfig,
|
||||
pub(crate) wallpaper: WallpaperConfig,
|
||||
pub layout_mode: LayoutMode,
|
||||
pub gap_config: GapConfig,
|
||||
pub input_settings: InputSettings,
|
||||
@@ -371,9 +372,11 @@ impl Ferese {
|
||||
config: RuntimeConfig,
|
||||
) -> Result<Self, Box<dyn Error>> {
|
||||
let display_handle = display.handle();
|
||||
|
||||
crate::handlers::screencopy::init_global(&display_handle);
|
||||
crate::effects::init_global(&display_handle);
|
||||
crate::shell_control::init_global(&display_handle);
|
||||
|
||||
let alpha_modifier_state = AlphaModifierState::new::<Self>(&display_handle);
|
||||
let compositor_state = CompositorState::new::<Self>(&display_handle);
|
||||
let cursor_shape_state = CursorShapeManagerState::new::<Self>(&display_handle);
|
||||
@@ -427,8 +430,8 @@ impl Ferese {
|
||||
let socket_name = Self::init_wayland_listener(display, event_loop)?;
|
||||
|
||||
let start_time = Instant::now();
|
||||
let cursor_theme = crate::cursor::cursor_theme();
|
||||
let default_cursor = crate::cursor::load_named_cursor(&cursor_theme, CursorIcon::Default);
|
||||
let cursor_theme = cursor_theme();
|
||||
let default_cursor = load_named_cursor(&cursor_theme, CursorIcon::Default);
|
||||
let named_cursors = HashMap::from([(CursorIcon::Default, default_cursor)]);
|
||||
|
||||
let mut state = Self {
|
||||
@@ -457,10 +460,10 @@ impl Ferese {
|
||||
resize_transactions: HashMap::new(),
|
||||
resize_snapshots: HashMap::new(),
|
||||
nested_backend: None,
|
||||
wallpaper: crate::wallpaper::WallpaperState::with_wakeup(config.wallpaper, Some(event_loop.get_signal())),
|
||||
wallpaper: WallpaperState::with_wakeup(config.wallpaper, Some(event_loop.get_signal())),
|
||||
maximized_windows: HashSet::new(),
|
||||
maximized_column_widths: HashMap::new(),
|
||||
window_stack: crate::stacking::WindowStack::default(),
|
||||
window_stack: WindowStack::default(),
|
||||
floating_above_fullscreen: HashMap::new(),
|
||||
natural_floating_pending: HashSet::new(),
|
||||
window_borders: HashMap::new(),
|
||||
@@ -473,7 +476,7 @@ impl Ferese {
|
||||
overview_scrims: HashMap::new(),
|
||||
material_programs: HashMap::new(),
|
||||
material_buffers: HashMap::new(),
|
||||
portal_shortcuts: crate::portal_shortcuts::PortalShortcuts::default(),
|
||||
portal_shortcuts: PortalShortcuts::default(),
|
||||
pending_logout: None,
|
||||
logout_query: None,
|
||||
logout_owner: None,
|
||||
@@ -506,20 +509,20 @@ impl Ferese {
|
||||
cursor_theme,
|
||||
named_cursors,
|
||||
intercepted_keys: HashSet::new(),
|
||||
swipe: crate::gestures::Swipe::default(),
|
||||
swipe: Swipe::default(),
|
||||
idle_inhibitors: HashMap::new(),
|
||||
active_shortcuts_inhibitor: None,
|
||||
direct_backend: None,
|
||||
_ipc_socket: None,
|
||||
pending_dmabuf_imports: Vec::new(),
|
||||
pending_screencopies: Vec::new(),
|
||||
screenshot: crate::handlers::screenshot::Coordinator::new(),
|
||||
screenshot: Coordinator::new(),
|
||||
screenshot_parts: None,
|
||||
screenshot_worker: None,
|
||||
shell_resources: Vec::new(),
|
||||
shell_snapshot_serial: 0,
|
||||
last_shell_snapshot: None,
|
||||
overview: crate::overview::OverviewState::with_font_family(config.overview_font_family),
|
||||
overview: OverviewState::with_font_family(config.overview_font_family),
|
||||
next_window_id: 1,
|
||||
next_output_id: 1,
|
||||
last_animation_tick: start_time,
|
||||
@@ -557,6 +560,7 @@ impl Ferese {
|
||||
state.screenshot_parts = Some(screenshot.parts);
|
||||
state.screenshot_worker = Some(screenshot.worker);
|
||||
state._ipc_socket = Some(screenshot._guard);
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ prompt and screen-sharing/recording chooser.
|
||||
|
||||
- `Palette` resolves KDL colors and corners and builds the native toolkit theme.
|
||||
- `PRESETS` defines the six built-in color schemes.
|
||||
- `font` and `text` share bounded font-name storage and explicit font selection.
|
||||
- `font` and `text` provide shared font selection and text.
|
||||
- `controls` supplies surfaces, navigation, font-aware text buttons and input styles.
|
||||
- `menus` supplies headings, rows, sections, separators, switches and slider styles.
|
||||
- `calendar` supplies date/time labels, stacked clock digits and calendar grids.
|
||||
@@ -16,9 +16,8 @@ prompt and screen-sharing/recording chooser.
|
||||
Keep the attachment alive with its window and make the client background
|
||||
transparent after attachment succeeds. Other compositors retain the client fill.
|
||||
|
||||
Applications own layout, data, actions and animation timing. Pass their current
|
||||
palette and animation progress into the shared components; do not build another
|
||||
native theme or copy a common control style into an application.
|
||||
Applications supply layout, data, actions, and animation progress. Extend shared
|
||||
components when a style is needed across apps.
|
||||
|
||||
```rust
|
||||
let palette = ferese_theme::Palette::from_document(Some(&document));
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Documentation
|
||||
|
||||
## Get started
|
||||
|
||||
- [Installation](installation.md): dependencies, login, previews, updates, and recovery.
|
||||
- [Configuration](configuration.md): KDL syntax, layouts, input, shortcuts, and displays.
|
||||
- [Why Ferese](why-ferese.md): layouts and the shared desktop theme.
|
||||
|
||||
## Use the desktop
|
||||
|
||||
- [Shortcuts and gestures](shortcuts.md): keyboard navigation, Super-drag, resize, and window grouping.
|
||||
|
||||
- [Desktop widgets](desktop-widgets.md): clocks and sticky notes.
|
||||
- [Notifications](notifications.md): popups, history, and Do Not Disturb.
|
||||
- [Lock screen](locking.md): appearance, automatic locking, and display sleep.
|
||||
- [Screen sharing and recording](screen-sharing.md): choosing sources and stopping a session.
|
||||
- [Desktop portals](portals.md): application integration and supported services.
|
||||
|
||||
## Develop Ferese
|
||||
|
||||
- [Development](development.md): builds, tests, and portal checks.
|
||||
- [Compositor architecture](ferese-window-manager-spec.md).
|
||||
- [Shell behavior](ferese-shell-design.md).
|
||||
- [Theme components](ferese-theme-ui-spec.md).
|
||||
- [Animation checks](animation-validation.md).
|
||||
- [Nested resize checks](nested-resize-testing.md).
|
||||
- [Client soak testing](native-soak-testing.md).
|
||||
- [Performance measurements](performance-baseline.md).
|
||||
- [Website development](../site/README.md).
|
||||
@@ -0,0 +1,26 @@
|
||||
# Animation regression checks
|
||||
|
||||
Run `cargo test -p ferese-animation -p ferese --offline` for transition,
|
||||
resize requests, reduced motion, stacking, and refresh-rate regression tests.
|
||||
|
||||
For visual validation, use a disposable Ferese session with three tiled windows
|
||||
containing text and at least one floating window. Test both the nested and DRM
|
||||
backends. Record the session at its native refresh rate when comparing builds;
|
||||
single screenshots cannot establish smoothness.
|
||||
|
||||
| Scenario | Expected result |
|
||||
| --- | --- |
|
||||
| Super+F on the middle column, then exit | Neighbours remain behind the expanding window. The shrinking window stays above them until the transition finishes. |
|
||||
| Toggle Super+F repeatedly at 40–80 ms intervals | Every reversal starts at the presented frame. Corners, border and shadow follow the same zoom progress. The final state matches the last input. |
|
||||
| Cycle width, then immediately Super+F | The old column-width spring cannot override maximized width. |
|
||||
| Exit maximize or fullscreen and immediately resize or scroll | The current frame is retained when the target changes; scrolling resumes without a position jump. |
|
||||
| Drag a floating window; resize from its top-left corner | The window follows the pointer directly. The opposite edge stays anchored. Delayed client commits do not move or raise it. |
|
||||
| Zoom responsive and slow-redrawing clients | Each zoom requests the destination size once. Client redraws do not generate intermediate resize requests or restart the motion. |
|
||||
| Zoom the leftmost and rightmost columns in and out | Each outer edge moves monotonically toward its destination; neither side trembles or reverses near the screen edge. |
|
||||
| Disable borders and shadows, then zoom | Rounded corner pixels repaint through the final frame; no corner remnants remain. |
|
||||
| Repeat on 60 Hz and 144 Hz outputs; move focus between them | Similar elapsed-time motion with no double advancement. Check frame timing on actual DRM hardware. |
|
||||
| Enable reduced motion | Geometry and decorations reach their final values together. |
|
||||
|
||||
Zoom requests the destination client size once and scales the available buffer
|
||||
along the transition. This avoids repeated content reflow during motion. It is
|
||||
not a buffer snapshot or a guarantee of perfectly sharp intermediate text.
|
||||
+81
-106
@@ -2,8 +2,9 @@
|
||||
|
||||
Edit `~/.config/ferese/config.kdl` (or `$XDG_CONFIG_HOME/ferese/config.kdl`),
|
||||
or open **Control Center → Settings**. Start with the [example](../packaging/config.kdl).
|
||||
All supported configuration sections are listed below; [desktop widgets](desktop-widgets.md)
|
||||
covers the complete clock and sticky-note fields separately.
|
||||
This reference covers layouts, appearance, input, and desktop behavior.
|
||||
See [Desktop widgets](desktop-widgets.md), [Notifications](notifications.md),
|
||||
and [Desktop portals](portals.md) for their additional options.
|
||||
|
||||
## KDL syntax
|
||||
|
||||
@@ -44,8 +45,7 @@ its command as positional arguments. Duplicate fields are rejected.
|
||||
The dotted paths in the reference tables below describe nested sections.
|
||||
|
||||
Settings preserves comments and custom fields when editing, while normalizing
|
||||
indentation. Runtime configuration uses KDL only. KDL parsing requires Rust 1.95
|
||||
or newer to build.
|
||||
indentation. Configuration uses KDL.
|
||||
|
||||
## Saving and validation
|
||||
|
||||
@@ -74,15 +74,15 @@ Live config is limited to 60 KiB.
|
||||
| `layout` key | Type / values | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `mode` | `"scrolling"`, `"tree"` | `"scrolling"` | Workspace layout |
|
||||
| `inner_gap` | number ≥ 0 | `10` | Between windows |
|
||||
| `outer_gap` | number ≥ 0 | `4` | Around workspace edges |
|
||||
| `smart_gaps` | boolean | `false` | Remove outer gaps for one tiled window |
|
||||
| `inner-gap` | number ≥ 0 | `10` | Between windows |
|
||||
| `outer-gap` | number ≥ 0 | `4` | Around workspace edges |
|
||||
| `smart-gaps` | boolean | `false` | Remove outer gaps for one tiled window |
|
||||
|
||||
| `scrolling` key | Type / values | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `default_column_width` | proportion > 0; or `"full"` | `0.5` | Width of new columns |
|
||||
| `focus_strategy` | `"minimal"`, `"center_on_focus"`, `"paged"` | `"minimal"` | Viewport movement on focus |
|
||||
| `width_presets` | array of widths | `[0.3333333333333333, 0.5, 0.6666666666666666, "full"]` | Super+R cycle; empty uses defaults |
|
||||
| `default-column-width` | proportion > 0; or `"full"` | `0.5` | Width of new columns |
|
||||
| `focus-strategy` | `"minimal"`, `"center_on_focus"`, `"paged"` | `"minimal"` | Viewport movement on focus |
|
||||
| `width-presets` | array of widths | `[0.3333333333333333, 0.5, 0.6666666666666666, "full"]` | Super+R cycle; empty uses defaults |
|
||||
|
||||
`minimal` scrolls only to reveal the focused window. `center_on_focus` centers
|
||||
it. `paged` packs columns into viewport-sized pages: halves form pairs, thirds
|
||||
@@ -94,95 +94,73 @@ Changing default width preserves manually resized columns.
|
||||
| Section / key | Type | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `animations.enabled` | boolean | `true` | Enable motion |
|
||||
| `animations.reduced_motion` | boolean | `false` | Disable animated motion |
|
||||
| `animations.reduced-motion` | boolean | `false` | Disable animated motion |
|
||||
| `animations.speed` | number > 0 | `1` | Higher is faster; `0.75` is slower |
|
||||
| `animations.spring.mass` | number > 0 | `1` | Window-motion spring mass |
|
||||
| `animations.spring.stiffness` | number > 0 | `700` | Spring stiffness |
|
||||
| `animations.spring.damping` | number ≥ 0 | `53` | Spring damping |
|
||||
| `animations.viewport_spring.mass` | number > 0 | `1` | Scrolling spring mass |
|
||||
| `animations.viewport_spring.stiffness` | number > 0 | `320` | Scrolling stiffness |
|
||||
| `animations.viewport_spring.damping_ratio` | number > 0 | `1` | `1` is critically damped |
|
||||
| `animations.viewport-spring.mass` | number > 0 | `1` | Scrolling spring mass |
|
||||
| `animations.viewport-spring.stiffness` | number > 0 | `320` | Scrolling stiffness |
|
||||
| `animations.viewport-spring.damping-ratio` | number > 0 | `1` | `1` is critically damped |
|
||||
|
||||
## Appearance
|
||||
|
||||
Settings → Appearance offers six presets: **Ferese Blue** (default),
|
||||
**Monochrome**, **Gruvbox**, **Dracula**, **Ayu Light**, and **Monokai**.
|
||||
The two-row gallery previews each palette on a miniature desktop; a checkmark
|
||||
identifies the active preset.
|
||||
Ferese Blue uses the README logo's `#3D7BE6`. Each preset coordinates surfaces,
|
||||
text, menu-bar colors, borders and the focus ring. Ayu Light also switches native
|
||||
Settings controls to light styling. Presets preserve wallpaper, typography,
|
||||
geometry and opacity settings; colors remain individually editable.
|
||||
|
||||
The community palettes are desktop adaptations with text shades adjusted for
|
||||
readability. Sources: [Gruvbox](https://github.com/morhetz/gruvbox),
|
||||
[Dracula](https://github.com/dracula/visual-studio-code),
|
||||
[Ayu](https://github.com/ayu-theme/ayu-colors), and
|
||||
[classic Monokai](https://github.com/microsoft/vscode/blob/main/extensions/theme-monokai/themes/monokai-color-theme.json).
|
||||
Marketplace install counts informed the shortlist; they are not a measurement
|
||||
of desktop users. Monochrome and Gruvbox replace similar blue palettes to keep
|
||||
these six visually distinct.
|
||||
|
||||
Ferese Blue uses the logo accent, `#3D7BE6`. Presets update colors and preserve
|
||||
wallpaper, fonts, corners, and opacity. Colors remain individually editable.
|
||||
|
||||
| Section / key | Type | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `appearance.corner_radius` | number ≥ 0 | unset | Legacy fallback for shell radius |
|
||||
| `appearance.inactive_dim.enabled` | boolean | `false` | Dim unfocused windows |
|
||||
| `appearance.inactive_dim.amount` | number 0–1 | `0.15` | Darkening strength |
|
||||
| `appearance.inactive_dim.duration_ms` | number ≥ 0 | `150` | Dimming and focus-ring transition; 0 snaps |
|
||||
| `theme.typography.font_family` | string | system sans-serif | Shell, Settings and overview font |
|
||||
| `appearance.corner-radius` | number ≥ 0 | unset | Legacy fallback for shell radius |
|
||||
| `appearance.inactive-dim.enabled` | boolean | `false` | Dim unfocused windows |
|
||||
| `appearance.inactive-dim.amount` | number 0–1 | `0.15` | Darkening strength |
|
||||
| `appearance.inactive-dim.duration-ms` | number ≥ 0 | `150` | Dimming and focus-ring transition; 0 snaps |
|
||||
| `theme.typography.font-family` | string | system sans-serif | Shell, Settings and overview font |
|
||||
| `theme.background.path` | string | bundled Ferese wallpaper | Wallpaper image path; an existing selection overrides the default |
|
||||
| `theme.background.mode` | `"fill"`, `"fit"` | `"fill"` | Crop or letterbox |
|
||||
| `theme.material.style` | `"solid"`, `"translucent"` | `"solid"` | Shell background material |
|
||||
| `theme.material.opacity` | number 0–1 | `0.78` | Shared shell background opacity for bars, menus, popovers, notifications and themed dialogs. Text/icons stay opaque; 0 hides the material. Solid mode is always opaque |
|
||||
| `theme.material.blur_radius` | number ≥ 0 | `12` | Translucent backdrop blur, capped at 32; 0 disables |
|
||||
| `theme.material.blur-radius` | number ≥ 0 | `12` | Translucent backdrop blur, capped at 32; 0 disables |
|
||||
|
||||
| `theme.colors` key | Default | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `surface_base` | `"#111821"` | Material/card base color |
|
||||
| `text_primary` | `"#F4F7FB"` | Main text |
|
||||
| `text_muted` | `"#8793A2"` | Secondary text |
|
||||
| `surface-base` | `"#111821"` | Material/card base color |
|
||||
| `text-primary` | `"#F4F7FB"` | Main text |
|
||||
| `text-muted` | `"#8793A2"` | Secondary text |
|
||||
| `accent` | `"#3D7BE6"` | Active controls and solid focus ring |
|
||||
| `border` | `"#FFFFFF18"` | Unfocused window border |
|
||||
| `shadow` | `"#00000055"` | Window shadow color |
|
||||
|
||||
Ferese derives the text and icon color for filled accent controls from the
|
||||
configured theme. It keeps the configured text color and, when necessary, shades
|
||||
the accent fill slightly to reach a 4.5:1 contrast ratio. If that would require a
|
||||
large color change, it chooses black or white instead. The same rule is shared by
|
||||
native dialogs, settings selections, and notification badges. Hover, pressed,
|
||||
and disabled accent-button states use the same policy. Small filled controls
|
||||
resolve accent transparency against their theme surface so wallpaper cannot
|
||||
make their labels unreadable. No separate per-application color setting is needed.
|
||||
The target follows [normal-text contrast guidance](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html).
|
||||
Filled controls choose a contrasting text color automatically.
|
||||
|
||||
| `theme.geometry` key | Type | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `border_width` | number ≥ 0 | `1` | Window border thickness |
|
||||
| `focus_ring_width` | number ≥ 0 | `2` | Focused border thickness |
|
||||
| `window_radius` | number ≥ 0 | `14` | Managed-window corners, independent of the shell |
|
||||
| `shell_radius` | number ≥ 0 | `14` | All shell surfaces, cards, widgets and interaction backgrounds; 0 makes them square |
|
||||
| `top_bar_height` | number > 0 | `28` | Menu-bar height |
|
||||
| `top_bar_margin_top` | integer ≥ 0 | `0` | Space above bar |
|
||||
| `top_bar_window_gap` | integer ≥ 0 | `0` | Clearance below bar |
|
||||
| `top_bar_margin_horizontal` | integer ≥ 0 | `0` | Bar side margins |
|
||||
| `top_bar_radius` | number ≥ 0 | unset | Legacy fallback for shell radius |
|
||||
| `panel_padding` | number ≥ 0 | `12` | Bar inner padding |
|
||||
| `control_gap` | number ≥ 0 | `12` | Right-side control spacing |
|
||||
| `border-width` | number ≥ 0 | `1` | Window border thickness |
|
||||
| `focus-ring-width` | number ≥ 0 | `2` | Focused border thickness |
|
||||
| `window-radius` | number ≥ 0 | `14` | Managed-window corners, independent of the shell |
|
||||
| `shell-radius` | number ≥ 0 | `14` | All shell surfaces, cards, widgets and interaction backgrounds; 0 makes them square |
|
||||
| `top-bar-height` | number > 0 | `28` | Menu-bar height |
|
||||
| `top-bar-margin-top` | integer ≥ 0 | `0` | Space above bar |
|
||||
| `top-bar-window-gap` | integer ≥ 0 | `0` | Clearance below bar |
|
||||
| `top-bar-margin-horizontal` | integer ≥ 0 | `0` | Bar side margins |
|
||||
| `top-bar-radius` | number ≥ 0 | unset | Legacy fallback for shell radius |
|
||||
| `panel-padding` | number ≥ 0 | `12` | Bar inner padding |
|
||||
| `control-gap` | number ≥ 0 | `12` | Right-side control spacing |
|
||||
|
||||
| Section / key | Type | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `theme.surface.bar.background` | color | `"#1C202EF2"` | Shell fallback background; compositor materials use `surface_base` |
|
||||
| `theme.surface.bar.text_primary` | color | `"#F0F3FA"` | Bar text/icons |
|
||||
| `theme.surface.bar.text_muted` | color | `"#AAB4C7"` | Inactive bar foreground |
|
||||
| `theme.shadow.soft.offset_y` | number | `4` | Window shadow vertical offset |
|
||||
| `theme.surface.bar.background` | color | `"#1C202EF2"` | Shell fallback background; compositor materials use `surface-base` |
|
||||
| `theme.surface.bar.text-primary` | color | `"#F0F3FA"` | Bar text/icons |
|
||||
| `theme.surface.bar.text-muted` | color | `"#AAB4C7"` | Inactive bar foreground |
|
||||
| `theme.shadow.soft.offset-y` | number | `4` | Window shadow vertical offset |
|
||||
| `theme.shadow.soft.blur` | number ≥ 0 | `18` | Window shadow softness |
|
||||
| `theme.shadow.soft.opacity` | number 0–1 | `0.20` | Window shadow strength |
|
||||
|
||||
Solid materials omit blur; translucent materials blur behind the surface color.
|
||||
True fullscreen removes decorations. Focus transitions never scale the content.
|
||||
|
||||
Optional `theme.focus_ring.gradient` and `theme.border.gradient` use the same
|
||||
Optional `theme.focus-ring.gradient` and `theme.border.gradient` use the same
|
||||
keys: required `from` and `to` colors, and `angle` (number, default `0`). Angles
|
||||
are clockwise: 0 is left-to-right, 90 top-to-bottom. Omit the gradient section
|
||||
for solid `accent` or `border` colors.
|
||||
@@ -199,16 +177,25 @@ theme {
|
||||
}
|
||||
```
|
||||
|
||||
## Workspaces
|
||||
|
||||
A single-output session starts with workspace 1. Numbered workspace shortcuts create
|
||||
workspaces on demand; switching forward past the last workspace also creates the
|
||||
next one when the current workspace contains windows. Empty workspaces are
|
||||
cleaned up automatically, keeping at most one empty workspace in addition to
|
||||
any empty workspace currently shown on another display. Additional displays
|
||||
receive their own workspace.
|
||||
|
||||
## Input
|
||||
|
||||
| `input` key | Type | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `focus_follows_mouse` | boolean | `false` | Focus visible windows under the pointer without raising them or scrolling; click or use keyboard focus to reveal a window |
|
||||
| `xkb_layout` | nonempty string | `"us"` | XKB layout |
|
||||
| `xkb_variant` | string | `""` | XKB variant |
|
||||
| `xkb_options` | string array | `[]` | XKB options |
|
||||
| `repeat_rate` | integer > 0 | `25` | Repeats per second |
|
||||
| `repeat_delay_ms` | integer ≥ 0 | `600` | Delay before repeat |
|
||||
| `focus-follows-mouse` | boolean | `false` | Focus visible windows under the pointer without raising them or scrolling; click or use keyboard focus to reveal a window |
|
||||
| `xkb-layout` | nonempty string | `"us"` | XKB layout |
|
||||
| `xkb-variant` | string | `""` | XKB variant |
|
||||
| `xkb-options` | string array | `[]` | XKB options |
|
||||
| `repeat-rate` | integer > 0 | `25` | Repeats per second |
|
||||
| `repeat-delay-ms` | integer ≥ 0 | `600` | Delay before repeat |
|
||||
|
||||
With focus-follows-mouse enabled, hovering a visible part of a window changes
|
||||
keyboard focus without raising it or moving the scrolling viewport. Clicking or
|
||||
@@ -221,7 +208,7 @@ Clicking a workspace card's background switches workspaces while keeping Overvie
|
||||
open. Previews follow layout order and use the configured shell font and colors.
|
||||
|
||||
The touchpad device keys are booleans, all defaulting to `true`: `tap`,
|
||||
`natural_scroll` and `disable_while_typing`. These apply to DRM devices; nested
|
||||
`natural-scroll` and `disable-while-typing`. These apply to DRM devices; nested
|
||||
previews use the host's physical input settings.
|
||||
|
||||
Three-finger swipes navigate on release: up goes to the next workspace on the
|
||||
@@ -254,6 +241,8 @@ Adjust recognition distance in **Settings → Keyboard & mouse**, or with
|
||||
|
||||
## Commands and bindings
|
||||
|
||||
See [Shortcuts and gestures](shortcuts.md) for the full default keymap and mouse actions.
|
||||
|
||||
`commands` maps arbitrary names to nonempty argument arrays. The built-in
|
||||
`terminal "foot"` can be overridden. Commands run directly, without a shell.
|
||||
|
||||
@@ -292,7 +281,7 @@ Super+Shift+1–9 move to workspace; Super+R width cycle; Super+C center;
|
||||
Super+[/] consume/expel; Super+F maximize; Super+Shift+F fullscreen;
|
||||
Super+M layout; Super+Shift+Space floating; Super+Tab overview;
|
||||
Super+Shift+S area screenshot; Print Screen whole-screen screenshot;
|
||||
Super+Shift+E immediate logout.
|
||||
Super+Shift+E logout confirmation.
|
||||
|
||||
Hold Super and drag a floating window with the left mouse button to move it.
|
||||
Hold Super and drag with the right mouse button to resize it from the nearest
|
||||
@@ -314,19 +303,8 @@ the same save and copy workflow.
|
||||
|
||||
`ferese-screenshot --all` captures every enabled output as one image.
|
||||
|
||||
The editor window is sized from the captured image rather than the output, so a
|
||||
small area selection does not open a large window. Sizing is advisory: the
|
||||
compositor floats the editor at whatever size Satty requests, clamped to the
|
||||
workspace.
|
||||
|
||||
A capture is assembled from the readback each output produces when it is next
|
||||
redrawn, so a request is abandoned if an output has not been redrawn within 30
|
||||
seconds. That is reported as an error rather than a partial or empty image, and
|
||||
the request holds no resources once it is abandoned. Nothing is left in the
|
||||
runtime directory: `feresctl screenshot` writes a private file that the caller
|
||||
opens and unlinks, and any file a dead client leaves behind is reclaimed after
|
||||
an hour.
|
||||
|
||||
Satty opens as a floating window sized for the captured image and constrained
|
||||
to the workspace.
|
||||
|
||||
## Window rules
|
||||
|
||||
@@ -335,7 +313,7 @@ window rules can override that behavior.
|
||||
|
||||
| `window-rule` key | Type | Default / meaning |
|
||||
| --- | --- | --- |
|
||||
| `app_id` | nonempty string | Optional exact match; case-insensitive, `.desktop` suffix ignored |
|
||||
| `app-id` | nonempty string | Optional exact match; case-insensitive, `.desktop` suffix ignored |
|
||||
| `title` | nonempty string | Optional exact, case-sensitive match |
|
||||
| `transient` | boolean | Optional parent-dialog match |
|
||||
| `workspace` | integer > 0 | Leave placement unchanged |
|
||||
@@ -369,8 +347,8 @@ are connected wins. Find connector names and persistent identities using
|
||||
| `transform` | enum below | `"normal"` |
|
||||
| `position` | `[integer, integer]` | Automatic horizontal placement |
|
||||
|
||||
Transforms: `normal`, `rotate_90`, `rotate_180`, `rotate_270`, `flipped`,
|
||||
`flipped_90`, `flipped_180`, `flipped_270`. Unspecified connected displays stay
|
||||
Transforms: `normal`, `rotate-90`, `rotate-180`, `rotate-270`, `flipped`,
|
||||
`flipped-90`, `flipped-180`, `flipped-270`. Unspecified connected displays stay
|
||||
enabled with defaults. Disabling every usable output is rejected.
|
||||
|
||||
```kdl
|
||||
@@ -390,10 +368,10 @@ returns. Ferese does not change the system's suspend policy.
|
||||
| `status` key | Type | Default | Meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| `keybinding-guide` | boolean | `true` | Show the active shortcut guide at login until disabled in Settings → Shortcuts. |
|
||||
| `window_title` | boolean | `true` | Focused window title in the bar center when space allows |
|
||||
| `battery_percentage` | boolean | `true` | Show percentage beside icon |
|
||||
| `low_battery_threshold` | integer 0–100 | `20` | Warning-color threshold |
|
||||
| `settings_command` | argument array | `["ferese-settings"]` | Settings launcher; `[]` hides the action |
|
||||
| `window-title` | boolean | `true` | Focused window title in the bar center when space allows |
|
||||
| `battery-percentage` | boolean | `true` | Show percentage beside icon |
|
||||
| `low-battery-threshold` | integer 0–100 | `20` | Warning-color threshold |
|
||||
| `settings-command` | argument array | `["ferese-settings"]` | Settings launcher; `[]` hides the action |
|
||||
|
||||
## Login items and locking
|
||||
|
||||
@@ -443,22 +421,19 @@ environment for screenshots to work.
|
||||
Text input is available by default; Ctrl+Alt+Escape releases an active shortcut
|
||||
inhibitor. Use `feresectl --help` for runtime control commands.
|
||||
|
||||
## Notifications
|
||||
|
||||
Settings → Notifications controls popups, Do Not Disturb, and the default timeout. See [Notifications](notifications.md) for KDL options and app behavior.
|
||||
|
||||
A single-output session starts with workspace 1. Numbered workspace shortcuts create
|
||||
workspaces on demand; switching forward past the last workspace also creates the
|
||||
next one when the current workspace contains windows. Empty workspaces are
|
||||
cleaned up automatically, keeping at most one empty workspace in addition to
|
||||
any empty workspace currently shown on another display. Additional displays
|
||||
receive their own workspace.
|
||||
|
||||
Shell rounding is controlled in Settings → Appearance → Shell corner radius.
|
||||
Small controls cap the radius to fit their size. Window rounding remains under
|
||||
Settings → Windows. `theme.geometry.shell_radius` takes precedence over the old
|
||||
`appearance.corner_radius` and then `theme.geometry.top_bar_radius` keys; when
|
||||
Settings → Windows. `theme.geometry.shell-radius` takes precedence over the old
|
||||
`appearance.corner-radius` and then `theme.geometry.top-bar-radius` keys; when
|
||||
none are set, the shell uses 14 px. Legacy clock/note radius fields no longer
|
||||
override shell rounding.
|
||||
|
||||
Power actions use a centered system confirmation. The `exit` key binding (Super+Shift+E by default) requests logout confirmation; `feresectl request-logout` does the same. `feresectl exit` remains an immediate administrative exit.
|
||||
## Power and logout
|
||||
|
||||
Power actions use a centered confirmation. **Super+Shift+E** and
|
||||
`feresectl request-logout` ask to log out. `feresectl exit` ends the session
|
||||
immediately.
|
||||
|
||||
## Notifications
|
||||
|
||||
See [Notifications](notifications.md) for popups, Do Not Disturb, and timeout options.
|
||||
+25
-33
@@ -1,13 +1,8 @@
|
||||
# Desktop widgets
|
||||
|
||||
The shell's desktop clock sits above the wallpaper and behind normal windows.
|
||||
Drag the clock to reposition it; it reserves no workspace space.
|
||||
All desktop widgets share dragging: grab the clock or a note's title. Release
|
||||
to save the position, or press Escape to cancel.
|
||||
Dragging stops at other visible widgets on the same output; edges can slide
|
||||
along each other. Disabled widgets and widgets on other outputs do not block it.
|
||||
Each matching output gets a small, transparent surface—not a full-screen canvas.
|
||||
Lock-screen rendering remains separate and does not expose the desktop clock.
|
||||
Clock and sticky-note widgets sit above the wallpaper and behind windows.
|
||||
Drag the clock or a note's title to move it. Release to save, or press Escape to
|
||||
cancel. Widgets stop at each other's edges on the same display.
|
||||
|
||||
Enable it in Settings → Desktop widgets or in your Ferese config:
|
||||
|
||||
@@ -42,42 +37,40 @@ desktop-widgets {
|
||||
Positions: `top_left`, `top_center`, `top_right`, `center_left`, `center`,
|
||||
`center_right`, `bottom_left`, `bottom_center`, `bottom_right`.
|
||||
Margins affect anchored axes only: a centered horizontal position ignores
|
||||
`margin_x`; a centered vertical position ignores `margin_y`.
|
||||
`margin-x`; a centered vertical position ignores `margin-y`.
|
||||
All geometry and text sizes use logical pixels and follow the output's scale.
|
||||
Increase the widget width/height for longer formats or larger text.
|
||||
|
||||
Pixel is the default clock style: heavy hours above minutes, alternating theme colors, and a small plain date above. Its bundled Cantarell display font can be replaced with the font selector. Minimal retains the plain time/date layout. Pixel zero-pads hours and hides am/pm for the stacked display. Formats with seconds or additional text retain their full formatted label on one line. Both styles shrink time text to fit smaller widget dimensions; an explicit text color overrides the alternating colors.
|
||||
Choose **Pixel** for stacked hours and minutes with alternating theme colors,
|
||||
or **Minimal** for a plain time/date layout. Pixel zero-pads hours and hides am/pm.
|
||||
Formats containing seconds or extra text use a single line. Both styles shrink
|
||||
time text to fit. Select a different font in Settings, or set `font-family`.
|
||||
|
||||
Saving reloads appearance and labels live. Placement, size, output filters and
|
||||
enable/disable changes recreate only clock surfaces; normal windows and the bar
|
||||
remain intact. Disconnecting an output destroys its clock; reconnecting creates
|
||||
one if its name matches the filter. Invalid configuration keeps the last working
|
||||
configuration. Theme changes apply to colors/fonts that have no explicit override.
|
||||
|
||||
Formatting uses [Jiff's strftime-compatible formats](https://docs.rs/jiff/latest/jiff/fmt/strtime/index.html).
|
||||
Seconds update on the shell's existing timer. Without seconds, unchanged labels
|
||||
produce no additional clock buffer damage; there is no widget animation loop.
|
||||
Widget placement can be changed by dragging or through Settings and KDL.
|
||||
Sticky notes also support editing directly on the desktop.
|
||||
Changes apply live. Colors and fonts follow the theme unless overridden.
|
||||
Formatting uses [strftime-compatible formats](https://docs.rs/jiff/latest/jiff/fmt/strtime/index.html).
|
||||
Use `%H:%M` for 24-hour time or `%-I:%M %p` for 12-hour time.
|
||||
|
||||
## Clock limits
|
||||
|
||||
Clock and note corners follow the shared shell radius. Their `radius` fields
|
||||
are accepted for compatibility but do not override it.
|
||||
|
||||
All clock keys are optional. The example enables the clock (disabled by default);
|
||||
the other values illustrate defaults or their empty-string equivalents.
|
||||
`outputs` is an array of strings; `enabled`, `bold`, `show_date`, `lowercase` are
|
||||
`outputs` is an array of strings; `enabled`, `bold`, `show-date`, `lowercase` are
|
||||
booleans; `width`, `height`, and margins are integers. Other sizes/opacity are numbers.
|
||||
|
||||
| Fields | Accepted range |
|
||||
| --- | --- |
|
||||
| `width`, `height` | 64–1600, 32–800 |
|
||||
| `margin_x`, `margin_y` | 0–8192 |
|
||||
| `time_size`, `date_size` | 8–240, 8–96 |
|
||||
| `margin-x`, `margin-y` | 0–8192 |
|
||||
| `time-size`, `date-size` | 8–240, 8–96 |
|
||||
| `opacity` | 0–1 |
|
||||
| `gap`, `padding`, `radius` | 0–64, 0–64, 0–128 |
|
||||
| `font_family`, `time_format`, `date_format` | At most 128 bytes each |
|
||||
| `font-family`, `time-format`, `date-format` | At most 128 bytes each |
|
||||
| `outputs` | At most 32 exact output names, each 1–128 bytes |
|
||||
|
||||
Formats must be valid; `time_zone` must be empty or a recognized IANA name.
|
||||
Formats must be valid; `time-zone` must be empty or a recognized IANA name.
|
||||
Colors are empty (inherit), `#RRGGBB` or `#RRGGBBAA`; all numeric values must be finite.
|
||||
|
||||
## Sticky notes
|
||||
@@ -87,7 +80,8 @@ click Edit for its multiline editor, then Done to finish. Text autosaves after
|
||||
500 ms without typing. Escape cancels a drag or finishes editing. Position saves
|
||||
on release; dragging changes the anchor to `top_left` and saves pixel margins.
|
||||
Title, size and style are also editable in Settings. Notes persist in the config.
|
||||
Choose each note’s font in Settings using the installed-font dropdown or enter a family name manually. Default font inherits the interface font. In KDL, use `font-family "Comfortaa"` inside the `note` node.
|
||||
Choose a note’s font in Settings or set `font-family "Comfortaa"` in its `note`
|
||||
node. Without an override, notes use the interface font.
|
||||
|
||||
These are plain-text notes, not Markdown or HTML.
|
||||
|
||||
@@ -99,9 +93,7 @@ desktop-widgets {
|
||||
|
||||
Repeat the `note` node for additional notes; IDs must be unique. Cards stay behind windows
|
||||
and take keyboard focus only when clicked. Set `interactive #false` for a fully
|
||||
click-through card. Long text wraps; increase height if needed. Notes have no idle
|
||||
animation loop. Clock and notes share a compact drag preview moved by the
|
||||
compositor, not an output-sized canvas. It is released when dragging ends.
|
||||
click-through card. Long text wraps; increase height if needed.
|
||||
|
||||
| Key | Type | Default / accepted values |
|
||||
| --- | --- | --- |
|
||||
@@ -112,10 +104,10 @@ compositor, not an output-sized canvas. It is released when dragging ends.
|
||||
| `text` | string | `""`; multiline plain text, maximum 16 KiB |
|
||||
| `outputs` | string array | `[]` means all; at most 32 exact names, each 1–128 bytes |
|
||||
| `anchor` | string | `"top_right"`; same nine positions as clock |
|
||||
| `margin_x`, `margin_y` | integer | `48`, `80`; 0–8192; anchored edges only |
|
||||
| `margin-x`, `margin-y` | integer | `48`, `80`; 0–8192; anchored edges only |
|
||||
| `width`, `height` | integer | `320`, `240`; 120–1200, 80–1200 |
|
||||
| `font_family` | string | omitted/empty follows desktop font; maximum 128 bytes |
|
||||
| `text_size`, `title_size` | number | `16`, `18`; 8–96 |
|
||||
| `font-family` | string | omitted/empty follows desktop font; maximum 128 bytes |
|
||||
| `text-size`, `title-size` | number | `16`, `18`; 8–96 |
|
||||
| `color` | string | omitted/empty/`"theme"` follows primary text; or hex color |
|
||||
| `background` | string | omitted/`"theme"` follows surface base; empty is transparent; or hex color |
|
||||
| `opacity` | number | `0.9`; 0–1, multiplies text/background alpha |
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# Development
|
||||
|
||||
Install the [build dependencies](installation.md#requirements), then run:
|
||||
|
||||
```sh
|
||||
cargo build --release --locked --workspace
|
||||
cargo test --workspace --locked
|
||||
cargo fmt --all --check
|
||||
```
|
||||
|
||||
Use release builds for performance and animation checks. Preview changes in a
|
||||
[nested session](installation.md#preview-and-logs) before testing hardware behavior.
|
||||
Keep another desktop available for direct-session recovery.
|
||||
|
||||
## Test guides
|
||||
|
||||
- [Animation checks](animation-validation.md): transitions, interruption, and hit testing.
|
||||
- [Nested resize checks](nested-resize-testing.md): wallpaper and bar responsiveness.
|
||||
- [Client soak testing](native-soak-testing.md): repeated client lifecycle and resource growth.
|
||||
- [Performance measurements](performance-baseline.md): sampling and historical results.
|
||||
|
||||
The [compositor](ferese-window-manager-spec.md), [shell](ferese-shell-design.md),
|
||||
and [theme](ferese-theme-ui-spec.md) references describe the main code boundaries.
|
||||
|
||||
## Portal checks
|
||||
|
||||
Run backend unit tests and compare D-Bus contracts against installed portal XML:
|
||||
|
||||
```sh
|
||||
cargo test --locked -p xdg-desktop-portal-ferese
|
||||
python3 scripts/tests/test_portal_contracts.py
|
||||
```
|
||||
|
||||
The contract test uses a private bus. It checks signatures, appearance changes,
|
||||
invalid-config retention, and caller authorization. It does not prove complete
|
||||
compatibility with every app or open consent dialogs.
|
||||
|
||||
With release binaries built, run isolated integration checks:
|
||||
|
||||
```sh
|
||||
FERESE_TEST_SHORTCUTS=1 python3 scripts/tests/test_shortcuts_isolated.py
|
||||
FERESE_TEST_WINDOW_CAPTURE=1 python3 scripts/tests/test_window_capture_isolated.py
|
||||
FERESE_TEST_INHIBIT=1 python3 scripts/tests/test_inhibit_isolated.py
|
||||
FERESE_TEST_RESTORE=1 python3 scripts/tests/test_restore_isolated.py
|
||||
FERESE_TEST_WINDOW_STREAM=1 python3 scripts/tests/test_window_stream_isolated.py
|
||||
```
|
||||
|
||||
These cover shortcut cleanup, window capture, inhibitors, restored permissions,
|
||||
and live window streams. Check each script's dependencies before running it.
|
||||
They use disposable nested sessions or private buses.
|
||||
|
||||
For monitor streaming and lock revocation, install Python GI/GStreamer with
|
||||
`pipewiresrc`, `dbus-daemon`, `xdg-desktop-portal`, and `bwrap`, then run:
|
||||
|
||||
```sh
|
||||
FERESE_TEST_PORTAL=1 \
|
||||
FERESE_TEST_PORTAL_BINARY=target/release/xdg-desktop-portal-ferese \
|
||||
python3 scripts/tests/test_portal_isolated.py
|
||||
```
|
||||
|
||||
Add `FERESE_TEST_PORTAL_CONSENT=1` to exercise the picker. Choose the temporary
|
||||
display and click **Share**. Tests must target the nested preview, not the host desktop.
|
||||
|
||||
Check real encoding and the private InputCapture transport:
|
||||
|
||||
```sh
|
||||
cargo test --locked -p xdg-desktop-portal-ferese --bin ferese-record encoder_finishes_a_real_webm -- --ignored
|
||||
cargo test --locked -p ferese input_capture::tests
|
||||
cargo test --locked -p xdg-desktop-portal-ferese eis::tests -- --ignored
|
||||
```
|
||||
|
||||
Encoding needs the recorder's GStreamer plugins. The transport test needs libei
|
||||
and uses synthetic input over a private socket pair. Hardware pointer barriers,
|
||||
multiple monitors, display sleep, and live authentication still need session tests.
|
||||
|
||||
## Report a bug
|
||||
|
||||
Include the commit or installed release, reproduction steps, backend (nested or
|
||||
direct), monitor scales/transforms, and relevant logs. Avoid publishing passwords,
|
||||
access tokens, or private window content.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Shell behavior
|
||||
|
||||
This is a maintainer reference. User options are documented in
|
||||
[Configuration](configuration.md). Common UI belongs in
|
||||
[ferese-theme](../crates/ferese-theme/README.md).
|
||||
|
||||
## Bar and popovers
|
||||
|
||||
The shell creates a bar for each output. Workspace buttons use compositor state
|
||||
and appear in numeric order. The active window title occupies the center when
|
||||
space allows. Date and time form one calendar button. Right-side controls open
|
||||
sound, battery, notifications, recording, and Control Center popovers.
|
||||
|
||||
A popover is anchored to its control and constrained to the same output.
|
||||
Opening another primary popover replaces the current one. Popovers reserve no
|
||||
workspace space; the bar reserves its configured height and margins.
|
||||
True fullscreen hides the bar without changing the preserved tiled layout.
|
||||
|
||||
Use real service availability for controls. Handle missing services and failed
|
||||
actions without blocking the UI. Settings opens as a separate application.
|
||||
|
||||
## Overview
|
||||
|
||||
The compositor presents window previews; the shell supplies labels and workspace
|
||||
controls. Do not continuously copy windows into the shell process.
|
||||
|
||||
Clicking a workspace background selects that workspace and keeps overview open
|
||||
so its windows can be selected. Clicking a window activates that exact window.
|
||||
Directional keys change selection, Enter activates it, and Escape dismisses.
|
||||
Activation must use the selected window ID, not the window focused before overview.
|
||||
|
||||
## Focus and dialogs
|
||||
|
||||
The bar and notification popups do not normally take keyboard focus. Interactive
|
||||
shell surfaces restore the previous valid app focus when dismissed.
|
||||
|
||||
Power actions and logout use a centered system confirmation, including blockers
|
||||
when present. Input outside the confirmation must not reach applications.
|
||||
Authentication, screen-sharing, and recording dialogs are separate themed windows.
|
||||
Use one visible frame, content-sized height, and an output-sized height limit.
|
||||
Scrollable lists must leave headings and action buttons accessible.
|
||||
|
||||
Attach dialog material to the content card using the shared theme helper.
|
||||
Match blur regions to the displayed card throughout opening and resize; do not
|
||||
paint an opaque window behind a translucent card.
|
||||
|
||||
## Notifications and widgets
|
||||
|
||||
The shell provides the standard notification service. Normal popups respect
|
||||
Do Not Disturb; critical messages bypass it. History is held in memory and clears
|
||||
when the shell exits. See [Notifications](notifications.md).
|
||||
|
||||
Clock and note widgets sit behind application windows, reserve no workspace space,
|
||||
and save positions after dragging. Only interactive notes take keyboard focus.
|
||||
See [Desktop widgets](desktop-widgets.md).
|
||||
|
||||
## Lifecycle
|
||||
|
||||
Shell failure must not destroy managed windows or workspace state. Reconstruct
|
||||
bars and controls from compositor state after reconnecting, and clear dead shell
|
||||
focus. Notification history is not reconstructed from disk.
|
||||
|
||||
Keep slow service queries, image loading, and filesystem work away from UI event
|
||||
handling. Stop animation work once the UI settles. Validate popover placement,
|
||||
fullscreen transitions, dialog dismissal, and shell restart in a nested session.
|
||||
@@ -0,0 +1,81 @@
|
||||
# Theme components
|
||||
|
||||
Ferese's native apps use [ferese-theme](../crates/ferese-theme/README.md) for
|
||||
colors, fonts, controls, menus, icons, calendar elements, and dialog materials.
|
||||
Use [Configuration → Appearance](configuration.md#appearance) for supported keys
|
||||
and defaults.
|
||||
|
||||
## Shared appearance
|
||||
|
||||
The six presets are Ferese Blue, Monochrome, Gruvbox, Dracula, Ayu Light, and
|
||||
Monokai. Ferese Blue uses the logo accent, `#3D7BE6`. Presets change colors while
|
||||
preserving wallpaper, typography, corners, and opacity.
|
||||
|
||||
The interface font applies to shell text and native dialogs. Clock and note
|
||||
widgets can override it. Managed-window corners and shell corners are separate
|
||||
settings; small controls cap their corners to fit their size.
|
||||
|
||||
## Materials
|
||||
|
||||
Two material styles are supported:
|
||||
|
||||
| Style | Background |
|
||||
| --- | --- |
|
||||
| `solid` | Opaque theme surface |
|
||||
| `translucent` | Theme tint over blurred background content |
|
||||
|
||||
Bars, popovers, notifications, and themed dialogs share `theme.material.opacity`
|
||||
and `blur-radius`. Text and icons stay opaque. An opacity of zero hides the
|
||||
material; blur radius zero disables blur. Solid mode stays opaque.
|
||||
|
||||
```kdl
|
||||
theme {
|
||||
colors {
|
||||
accent "#3D7BE6"
|
||||
}
|
||||
material {
|
||||
style "translucent"
|
||||
opacity 0.78
|
||||
blur-radius 12
|
||||
}
|
||||
geometry {
|
||||
shell-radius 14
|
||||
window-radius 14
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The compositor owns blur and tint. `material::ModalMaterial` attaches native
|
||||
dialogs to that rendering path. Keep the attachment alive with the window and
|
||||
make the attached client background transparent. Outside Ferese, retain a client
|
||||
background so the dialog remains usable.
|
||||
|
||||
## Components
|
||||
|
||||
| Module | Use |
|
||||
| --- | --- |
|
||||
| `palette` | Resolve configuration colors and build the native toolkit theme |
|
||||
| `controls` | Surfaces, navigation, text buttons, and input styles |
|
||||
| `menus` | Rows, headings, sections, separators, switches, and sliders |
|
||||
| `calendar` | Date/time labels, clock digits, and calendar grids |
|
||||
| `icons` | Shared SVG assets, sizing, and tint |
|
||||
| `typography` | Shared font selection and text |
|
||||
| `contrast` | Readable labels on filled controls |
|
||||
| `material` | Attach modal cards to compositor materials |
|
||||
|
||||
Applications provide data, layout, actions, and animation progress. Extend shared
|
||||
components when a style is needed in multiple apps. Avoid hardcoded app-specific
|
||||
fonts, foreground colors, or opacity values.
|
||||
|
||||
## UI checks
|
||||
|
||||
- Check text and icons in all six presets, including Ayu Light.
|
||||
- Check rest, hover, pressed, focused, selected, and disabled controls.
|
||||
- Keep accent-button labels readable after typing or changing focus.
|
||||
- Keep controls usable with solid materials and blur disabled.
|
||||
- Align material regions with the visible card at every output scale.
|
||||
- Give dialogs one frame; cap their height and scroll their content, preserving actions.
|
||||
- Respect reduced motion and stop requesting animation frames after settling.
|
||||
|
||||
Theme changes affect appearance; they do not change focus, workspace ownership,
|
||||
input permissions, or authentication policy.
|
||||
@@ -0,0 +1,109 @@
|
||||
# Compositor architecture
|
||||
|
||||
This is a maintainer reference. For supported configuration and shortcuts, use
|
||||
[Configuration](configuration.md); for builds and checks, use [Development](development.md).
|
||||
|
||||
## Processes and crates
|
||||
|
||||
| Component | Responsibility |
|
||||
| --- | --- |
|
||||
| `ferese` | Wayland clients, windows, workspaces, input, outputs, and rendering |
|
||||
| `ferese-shell` | Bar, popovers, notifications, widgets, and system confirmations |
|
||||
| `ferese-settings` | Configuration editor |
|
||||
| `feresectl` | Command-line control |
|
||||
| `ferese-lock` | Lock-screen UI and PAM authentication |
|
||||
| `ferese-polkit-agent` | System authentication prompts |
|
||||
| `xdg-desktop-portal-ferese` | Desktop portal requests and PipeWire streams |
|
||||
| `ferese-record` | Video encoding and saving |
|
||||
|
||||
The compositor uses Smithay and calloop. The direct backend renders through
|
||||
DRM/KMS; the nested backend renders into a window on another Wayland desktop.
|
||||
Native UIs use libcosmic. Layout, animation, configuration, IPC, protocols, and
|
||||
[theme components](../crates/ferese-theme/README.md) live in separate crates.
|
||||
|
||||
## State and ownership
|
||||
|
||||
The event loop owns compositor state and Wayland objects. Background workers
|
||||
return results through bounded channels; results must be checked against current
|
||||
window, output, and request identities before application.
|
||||
|
||||
Keep these relationships valid after a state change:
|
||||
|
||||
- Each window belongs to one workspace and appears once in its layout or floating list.
|
||||
- Each attached workspace belongs to one output; each output has one active workspace.
|
||||
- A window's output follows workspace ownership.
|
||||
- Fullscreen preserves the underlying layout or floating placement.
|
||||
- Focus points to a live window or authorized shell surface.
|
||||
- Workspace focus history is distinct from current keyboard focus.
|
||||
|
||||
Monitor removal migrates workspaces to a remaining output. Returning monitors
|
||||
restore eligible workspaces; explicit user moves take priority. Selecting a
|
||||
workspace visible on another monitor focuses that monitor.
|
||||
|
||||
## Layout and presentation
|
||||
|
||||
Scrolling layouts arrange columns horizontally. Windows within a column divide
|
||||
its height. A workspace owns its viewport; presentation subtracts that viewport
|
||||
from window positions. Tree layouts use nested splits and stacks. Layout changes
|
||||
preserve window membership and floating placement.
|
||||
|
||||
Keep layout targets, animated rectangles, and committed client sizes separate.
|
||||
A layout transition requests the destination client size rather than sending
|
||||
one configure per animation frame. Available content is scaled and clipped until
|
||||
the matching client buffer arrives. Hit testing uses the same presented geometry.
|
||||
Interrupted animations continue from their current position.
|
||||
|
||||
Input and layout use logical pixels. Rendering converts them using the output's
|
||||
scale and transform. Application popups use their parent's output and presented
|
||||
position when calculating bounds.
|
||||
|
||||
## Rendering and frame delivery
|
||||
|
||||
Render damage from client commits, animations, effects, cursor motion, and output
|
||||
changes. Movement damages both old and new bounds, including shadows and blur.
|
||||
Output-specific callbacks follow window ownership. Presentation feedback is
|
||||
collected only for surfaces the renderer actually displayed on that output.
|
||||
An unchanged frame still permits paced client callbacks without submitting a
|
||||
new display buffer.
|
||||
|
||||
Animations use elapsed time across outputs, with a timer while transitions remain
|
||||
active. An idle focused monitor must not stall another monitor's animation.
|
||||
|
||||
The compositor renders blur from content behind the requesting surface. Material
|
||||
regions and client content must share coordinates during placement, scaling,
|
||||
and animation. See [Theme components](ferese-theme-ui-spec.md).
|
||||
|
||||
## Input
|
||||
|
||||
Use milliseconds for keyboard, pointer, touch, and gesture protocol events;
|
||||
relative-motion timestamps retain microseconds. Keep keyboard focus, pointer
|
||||
focus, and window stacking separate. Hover focus does not scroll or raise windows.
|
||||
|
||||
Pointer grabs and constraints must end cleanly when their surface disappears.
|
||||
A locked pointer's position hint is stored while locked, then resolved against
|
||||
current surface geometry and clamped to an output when the lock is released.
|
||||
|
||||
## IPC and private protocols
|
||||
|
||||
User control uses `$XDG_RUNTIME_DIR/ferese/control.sock`, restricted to the
|
||||
session user. The parent directory is private and peers are checked by UID.
|
||||
IPC frames are length-prefixed JSON with bounded message sizes, workers, and queues.
|
||||
See `feresectl --help` for commands.
|
||||
|
||||
Private Wayland capabilities grant shell control or material effects to trusted
|
||||
components. Public layer-shell access alone grants neither. Trusted connections
|
||||
and descriptors must not leak to launched applications. Capture paths check
|
||||
session policy and reject capture while locked.
|
||||
|
||||
Session locking must protect every output, including hotplug, and remain secure
|
||||
if the lock UI crashes. [Portal integration](portals.md) documents application
|
||||
consent and the currently supported services.
|
||||
|
||||
## Review and testing
|
||||
|
||||
Check output ownership, presented geometry, focus restoration, request lifetimes,
|
||||
and bounded work whenever changing a protocol or rendering path. Test both
|
||||
backends; a nested result does not establish hardware behavior.
|
||||
|
||||
Use the [animation](animation-validation.md), [resize](nested-resize-testing.md),
|
||||
and [soak](native-soak-testing.md) checks alongside the workspace tests.
|
||||
+24
-58
@@ -6,23 +6,12 @@ TTY. You do not need to replace your existing login manager or desktop.
|
||||
|
||||
## Requirements
|
||||
|
||||
You need a working graphics driver with DRM/KMS and EGL support, an authenticated
|
||||
local login session with seat access through logind or seatd, D-Bus, and
|
||||
Linux-PAM for the native locker. A nested preview needs an existing Wayland
|
||||
desktop instead of direct access to the graphics device.
|
||||
Use a Wayland-capable graphics driver and a local user session with seat access
|
||||
through logind or seatd. A nested preview runs inside an existing Wayland desktop.
|
||||
|
||||
Build with **Rust 1.95 or newer**, a C/C++ toolchain, CMake, pkg-config, and the
|
||||
native development libraries below. The installer builds Ferese, its shell,
|
||||
Settings, command-line tools, locker, polkit agent, and desktop portal backend together. It does not install system
|
||||
packages or enable background services at boot. On systemd systems, the installed
|
||||
session helper activates `ferese-session.target` after exporting the compositor's
|
||||
Wayland display, and stops it when the shell exits. This keeps
|
||||
`graphical-session.target` active so desktop portals can start. The native portal
|
||||
is D-Bus activated and supervised by systemd; it stops with the session so a
|
||||
previous release cannot remain running after logout. Session startup also refreshes
|
||||
an already-running native portal after importing the current display environment.
|
||||
Nested previews
|
||||
do not alter the host's activation environment or session targets.
|
||||
Building requires **Rust 1.95 or newer**, a C/C++ toolchain, CMake, pkg-config,
|
||||
and the libraries below. The installer builds all Ferese components; install
|
||||
system packages separately.
|
||||
|
||||
### Fedora
|
||||
|
||||
@@ -60,11 +49,9 @@ sudo apt install build-essential git curl cmake pkg-config libwayland-dev \
|
||||
gstreamer1.0-plugins-good
|
||||
```
|
||||
|
||||
These are package recipes, not a claim that every distribution release has been
|
||||
tested. Fedora is the currently exercised installation path. Older releases
|
||||
may need newer packages or additional repositories. For other distributions,
|
||||
install the equivalent libraries; see the upstream
|
||||
[Smithay dependencies](https://github.com/Smithay/smithay#system-dependencies).
|
||||
Fedora is the tested installation path. Package names and versions may differ
|
||||
on other distributions. See [Smithay dependencies](https://github.com/Smithay/smithay#system-dependencies)
|
||||
for equivalent libraries.
|
||||
|
||||
### Rust toolchain
|
||||
|
||||
@@ -98,32 +85,17 @@ The script builds locked release binaries, then requests administrator access
|
||||
through `sudo` or `pkexec` for installation. Do not run the whole build as root.
|
||||
The first build needs network access to fetch Rust dependencies.
|
||||
|
||||
The installer adds:
|
||||
The installer adds the session launcher, desktop tools, portal backend, login
|
||||
entry, icons, default wallpaper, and example config. Releases live under
|
||||
`/usr/local/lib/ferese/releases/`; commands live under `/usr/local/bin/`.
|
||||
The `current` and `previous` links support updates and rollback.
|
||||
|
||||
- Versioned releases under `/usr/local/lib/ferese/releases/`, with `current` and
|
||||
`previous` links for upgrades and rollback.
|
||||
- Commands under `/usr/local/bin/`, including `ferese-session`, `ferese-settings`,
|
||||
`feresectl`, `ferese-lock`, `ferese-polkit-agent`, `ferese-screenshot`, and
|
||||
`xdg-desktop-portal-ferese`, and `ferese-record`.
|
||||
- D-Bus activation and Ferese-specific desktop portal registration.
|
||||
- A Wayland session entry at `/usr/share/wayland-sessions/ferese.desktop`.
|
||||
- A Settings application entry, icons, the default wallpaper, and an example config.
|
||||
- `/etc/pam.d/ferese-lock`, using your distribution's authentication stack.
|
||||
An existing administrator-supplied policy is preserved.
|
||||
|
||||
Your existing configuration and other desktop sessions are preserved. The
|
||||
installer does not change your default session or login manager.
|
||||
|
||||
Ferese starts its own polkit authentication agent with the shell. Password
|
||||
prompts follow the configured font, accent, surface color, and corner radius.
|
||||
Authentication still uses polkit's system helper and policy. The agent starts
|
||||
only inside a Ferese session; logging into another desktop leaves its agent
|
||||
unchanged. Restart your Ferese session after upgrading to use the new prompt.
|
||||
Your configuration, other desktop sessions, and existing PAM policy are preserved.
|
||||
Ferese starts its authentication agent and portal services with the session.
|
||||
|
||||
### Initial configuration
|
||||
|
||||
Ferese has built-in defaults. To start from the example without replacing an
|
||||
existing config:
|
||||
Ferese has built-in defaults. To start from the example without replacing your config:
|
||||
|
||||
```sh
|
||||
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/ferese"
|
||||
@@ -144,9 +116,7 @@ command in Settings if you prefer another terminal.
|
||||
|
||||
Save your work and log out. Open your login screen's session selector, choose
|
||||
**Ferese**, and sign in. Any manager that supports Wayland sessions and reads
|
||||
`/usr/share/wayland-sessions/` can discover the installed entry. The selector's
|
||||
location and whether it appears before or after choosing your account depend
|
||||
on the login manager.
|
||||
`/usr/share/wayland-sessions/` can discover the installed entry.
|
||||
|
||||
If Ferese is missing, confirm that the session entry exists and its launcher is
|
||||
executable:
|
||||
@@ -169,15 +139,9 @@ If your greeter asks for a session command instead of reading desktop files, use
|
||||
/usr/local/bin/ferese-session
|
||||
```
|
||||
|
||||
For a setup such as greetd, configure that as the command launched **after user
|
||||
authentication**, using your greeter's session-command option. Preserve the
|
||||
existing authentication and greeter configuration. Do not set Ferese itself as
|
||||
the privileged greeter process. See the
|
||||
[greetd documentation](https://sr.ht/~kennylevinsen/greetd/) for your chosen frontend.
|
||||
|
||||
The launcher starts the compositor and shell together, sets the desktop
|
||||
environment variables, and starts a D-Bus session when one is not already
|
||||
available. Launch it instead of the bare compositor for a complete desktop.
|
||||
For greetd, use this as the session command after authentication; see the
|
||||
[greetd documentation](https://sr.ht/~kennylevinsen/greetd/).
|
||||
The launcher starts the compositor, shell, and session services together.
|
||||
|
||||
### From a TTY
|
||||
|
||||
@@ -229,7 +193,8 @@ inside an existing Wayland desktop:
|
||||
|
||||
```sh
|
||||
cargo build --release --locked -p ferese -p ferese-shell -p ferese-settings -p feresectl -p ferese-lock -p xdg-desktop-portal-ferese
|
||||
target/release/ferese --backend nested --grant-effects --grant-shell-control -- \
|
||||
FERESE_ENABLE_SCREENCOPY=1 target/release/ferese --backend nested \
|
||||
--grant-effects --grant-shell-control -- \
|
||||
target/release/ferese-shell
|
||||
```
|
||||
|
||||
@@ -283,12 +248,13 @@ Installer options:
|
||||
|
||||
`--dry-run` prints the planned commands. `--offline` requires dependencies to be
|
||||
cached already. `--skip-build` installs the binaries already in `target/release/`;
|
||||
use it only after building all six components from the intended revision.
|
||||
use it only after building all components from the intended revision.
|
||||
Run `./scripts/install.sh --help` for all options.
|
||||
|
||||
## Logout and recovery
|
||||
|
||||
Save your work before **Super+Shift+E** or `feresectl exit`: logout is immediate.
|
||||
Use **Super+Shift+E** or `feresectl request-logout` to ask for logout confirmation.
|
||||
`feresectl exit` ends the session immediately; save your work first.
|
||||
If Ferese freezes, switch to another TTY with **Ctrl+Alt+F1–F12**, sign in, and
|
||||
identify the affected compositor process:
|
||||
|
||||
|
||||
+38
-83
@@ -1,79 +1,43 @@
|
||||
# Native locker
|
||||
# Lock screen
|
||||
|
||||
Ferese Lock uses `ext-session-lock-v1`, not a fullscreen application overlay.
|
||||
Each output receives its own surface, including outputs added while locked.
|
||||
The compositor protects the desktop if the client exits or crashes.
|
||||
Ferese Lock follows your desktop wallpaper, colors, font, and shell corners.
|
||||
Open **Settings → Lock screen** to change its clock, date, wallpaper softness,
|
||||
and inactivity delays.
|
||||
|
||||
## Preview
|
||||
## Preview and lock
|
||||
|
||||
```sh
|
||||
cargo build --release --locked -p ferese-lock
|
||||
target/release/ferese-lock --preview
|
||||
ferese-lock --preview # ordinary window; does not lock or check passwords
|
||||
ferese-lock # lock; returns after compositor confirmation
|
||||
ferese-lock --foreground # stay attached until unlock
|
||||
```
|
||||
|
||||
This is an ordinary, closable window. Submitting the field does not call PAM,
|
||||
lock, or unlock anything. Do not type your actual password into a visual preview.
|
||||
Do not enter your real password in a preview. The account picture comes from
|
||||
AccountsService or `~/.face`; a silhouette is used when neither is available.
|
||||
|
||||
Settings → Lock screen provides clock visibility, date visibility, time format,
|
||||
wallpaper dimming and softness, inactivity delays, and a safe preview button. Your account picture is loaded from
|
||||
AccountsService or `~/.face`, with a user silhouette as a fallback.
|
||||
Escape clears the password. Caps Lock is shown beside authentication status.
|
||||
Failed attempts show an error and delay retries. Authentication uses the system's
|
||||
PAM policy; both password and account validation must succeed.
|
||||
|
||||
The locker reads Ferese's wallpaper, theme colors, typography, and shell radius
|
||||
at startup. The wallpaper is softened once and shared across displays. Set softness
|
||||
to zero to keep it sharp. Escape clears the password. Caps Lock is shown above authentication
|
||||
status. Password verification runs on a worker, and repeated attempts are held
|
||||
for two seconds after failure, in addition to delays enforced by PAM.
|
||||
## Automatic locking
|
||||
|
||||
## Installation and locking
|
||||
Install `swayidle`, then add this to `~/.config/ferese/config.kdl` to lock after
|
||||
five minutes and before system sleep:
|
||||
|
||||
The normal `scripts/install.sh` includes the native binary and installs
|
||||
`/etc/pam.d/ferese-lock` if absent. Existing administrator policies are preserved.
|
||||
Fedora/Arch installations use `system-auth`; Debian-family installations use
|
||||
`common-auth` and `common-account`; the fallback uses the system `login` stack.
|
||||
There is no setuid binary, password command argument, or shadow-file reader.
|
||||
Both authentication and account validation must succeed. Expired credentials
|
||||
must be updated outside the locker. Interactive multi-factor enrollment and
|
||||
password changes are not supported by this initial password UI.
|
||||
|
||||
```sh
|
||||
ferese-lock # returns after confirmation, UI stays running
|
||||
ferese-lock --foreground # stays attached until unlock
|
||||
```kdl
|
||||
autostart {
|
||||
command "swayidle" "-w" "timeout" "300" "ferese-lock" "before-sleep" "ferese-lock" "lock" "ferese-lock"
|
||||
}
|
||||
```
|
||||
|
||||
The `swayidle -w` example in [Configuration](configuration.md#login-items-and-locking)
|
||||
can invoke the default command. Auto-locking is opt-in. This change does not
|
||||
install or start an idle daemon, replace your login manager, or change the Control Center's
|
||||
suspend action. Test real password authentication inside a nested Ferese session
|
||||
before enabling this on your desktop.
|
||||
|
||||
## Security and recovery
|
||||
|
||||
Never interpret the preview as proof of a locked desktop. A missing PAM policy
|
||||
or unsupported compositor produces an error before a lock request. A failure
|
||||
or authentication-worker panic never authorizes unlock. A crash after the lock
|
||||
request may leave the session permanently locked; end that session from another
|
||||
TTY if necessary. Do not restart the compositor to test crash behavior on a live
|
||||
session with unsaved work.
|
||||
|
||||
The pinned libcosmic backend emits `Locked` twice: once when requesting a lock
|
||||
and once on the actual protocol callback. The startup handshake waits for the
|
||||
second notification. Re-audit this behavior whenever upgrading libcosmic. The
|
||||
parent times out with an error after 15 seconds and leaves the UI running; it
|
||||
never reports success merely because the window appeared.
|
||||
|
||||
Validation references: [session-lock protocol](https://wayland.app/protocols/ext-session-lock-v1),
|
||||
[PAM authentication](https://man7.org/linux/man-pages/man3/pam_authenticate.3.html),
|
||||
and [PAM account checks](https://man7.org/linux/man-pages/man3/pam_acct_mgmt.3.html).
|
||||
Test password unlocking before enabling automatic locking. The installer provides
|
||||
`/etc/pam.d/ferese-lock` and preserves an existing administrator policy.
|
||||
|
||||
## Inactivity and display sleep
|
||||
|
||||
A locked display dims after 30 seconds without input and sleeps after 120 seconds.
|
||||
Dimming fades over half a second. Any keyboard, pointer or touch activity restores
|
||||
brightness and wakes the display while keeping the session locked. The compositor
|
||||
owns this policy, so it remains effective if the locker crashes. Sleep starts only
|
||||
after the compositor has confirmed that every display is protected.
|
||||
|
||||
Settings → Lock screen adjusts both delays. Zero disables that action:
|
||||
Locked displays dim after 30 seconds without input and sleep after 120 seconds.
|
||||
Keyboard, pointer, or touch activity wakes them without unlocking. Set either
|
||||
delay to zero to disable it, in Settings or KDL:
|
||||
|
||||
```kdl
|
||||
lock-screen {
|
||||
@@ -82,28 +46,19 @@ lock-screen {
|
||||
}
|
||||
```
|
||||
|
||||
These delays are independent of automatic locking. Existing idle inhibitors from
|
||||
apps cannot keep an already locked display awake. In a direct session, display
|
||||
sleep uses DRM DPMS without removing outputs or rearranging workspaces; nested
|
||||
previews show black instead of powering off the host display. This puts displays
|
||||
to sleep, not the computer. Suspend remains a separate system power action.
|
||||
These delays start after locking, independently of the automatic-lock timer.
|
||||
Display sleep does not suspend the computer. A nested preview shows black
|
||||
instead of powering off the host display.
|
||||
|
||||
## Practical swaylock comparison
|
||||
## Recovery and limits
|
||||
|
||||
| Behavior | Ferese Lock |
|
||||
| --- | --- |
|
||||
| Secure Wayland locking and protection after a locker crash | Session-lock protocol, compositor-owned fallback |
|
||||
| All displays, including hotplug | Separate lock surface for each display |
|
||||
| Readiness before an idle manager permits suspend | Default command waits for compositor confirmation |
|
||||
| Password verification | PAM authentication and account checks on a worker |
|
||||
| Password clearing and Caps Lock feedback | Escape clears; Caps Lock indicator |
|
||||
| Authentication failure feedback and retry delay | Error message and bounded retry delay |
|
||||
| Wallpaper, font and color customization | Shared Ferese theme and Settings |
|
||||
| Inactivity and display power | Compositor dimming and DPMS; input restores brightness |
|
||||
The lock covers all displays, including newly connected ones. If the lock UI
|
||||
crashes, the compositor keeps the session protected. Recovery may require ending
|
||||
that session from another TTY; see [Recovery](installation.md#logout-and-recovery).
|
||||
|
||||
[Swaylock](https://github.com/swaywm/swaylock/blob/master/swaylock.1.scd) provides
|
||||
additional appearance flags, layout indicators and readiness-FD CLI options.
|
||||
Ferese uses its shared configuration and existing startup acknowledgement instead.
|
||||
Like the [swayidle example](https://github.com/swaywm/swayidle/blob/master/swayidle.1.scd),
|
||||
locking and display sleep are separate from system suspend. Password changes and
|
||||
interactive multi-factor prompts remain outside this password-only interface.
|
||||
The password interface does not support password changes or interactive
|
||||
multi-factor prompts. Update expired credentials outside the locker.
|
||||
|
||||
Developers should validate locking and readiness against
|
||||
[ext-session-lock-v1](https://wayland.app/protocols/ext-session-lock-v1).
|
||||
See [Development](development.md) for tests.
|
||||
@@ -0,0 +1,67 @@
|
||||
# Native-client soak testing
|
||||
|
||||
The soak runner repeatedly creates and destroys native Wayland clients while
|
||||
exercising focus, resize, column width, fullscreen, floating, and workspace
|
||||
paths. Every tenth iteration also terminates a client abruptly. If a local
|
||||
malformed-client probe is available, it opens three isolated connections that
|
||||
send malformed Wayland messages. The runner requires
|
||||
Ferese to disconnect each malformed client and then checks that the compositor
|
||||
and authenticated IPC socket remain responsive. It also records compositor RSS
|
||||
growth.
|
||||
|
||||
Build `ferese` and `feresectl` and start a disposable
|
||||
[nested session](installation.md#preview-and-logs). Select its Wayland socket and
|
||||
compositor PID explicitly, then run:
|
||||
|
||||
```sh
|
||||
WAYLAND_DISPLAY=wayland-N FERESE_PID=PID ./scripts/soak-native.sh
|
||||
```
|
||||
|
||||
Replace `wayland-N` and `PID` with the preview's values. Do not use the host socket
|
||||
or rely on automatic PID selection when multiple sessions are running.
|
||||
|
||||
The default duration is 24 hours. A shorter validation run is:
|
||||
|
||||
```bash
|
||||
WAYLAND_DISPLAY=wayland-N \
|
||||
FERESE_PID=PID \
|
||||
FERESE_SOAK_SECONDS=300 \
|
||||
./scripts/soak-native.sh
|
||||
```
|
||||
|
||||
Development probes are local-only, not distributed in the Cargo workspace.
|
||||
Supply an existing executable with `FERESE_MALFORMED_CLIENT` to enable protocol
|
||||
checks. An explicitly configured missing probe is an error; without a probe,
|
||||
the runner reports that protocol checks are skipped.
|
||||
|
||||
The local probe can also be run independently against a disposable Ferese session:
|
||||
|
||||
```bash
|
||||
WAYLAND_DISPLAY=wayland-1 /path/to/ferese-malformed-client
|
||||
target/debug/feresectl get-outputs
|
||||
```
|
||||
|
||||
Do not point the malformed-client probe at the host compositor socket.
|
||||
|
||||
Environment controls:
|
||||
|
||||
- `FERESE_SOAK_SECONDS`: run duration, default `86400`;
|
||||
- `FERESE_SOAK_DELAY`: delay between operations, default `0.15` seconds;
|
||||
- `FERESE_SOAK_CLIENT`: native client executable, default `foot`;
|
||||
- `FERESECTL`: path to `feresectl`, default `target/debug/feresectl`;
|
||||
- `FERESE_MALFORMED_CLIENT`: path to the malformed protocol probe, default
|
||||
`target/debug/ferese-malformed-client`;
|
||||
- `FERESE_PID`: compositor PID; automatic lookup is only a fallback;
|
||||
- `FERESE_SOAK_LOG`: result log, default `/tmp/ferese-soak-<pid>.log`.
|
||||
- `FERESE_SOAK_MAX_RSS_GROWTH_KIB`: maximum RSS growth, default `131072`
|
||||
(128 MiB);
|
||||
- `FERESE_SOAK_MAX_FD_GROWTH`: maximum open-file-descriptor growth, default
|
||||
`32`;
|
||||
- `FERESE_SOAK_MAX_THREAD_GROWTH`: maximum thread growth, default `8`.
|
||||
|
||||
Run the same workload once with the nested backend and once from a direct DRM
|
||||
session. Samples are taken after spawned clients are reaped. A passing run
|
||||
requires the compositor to remain alive, IPC queries to succeed, and RSS, file
|
||||
descriptor, and thread growth to stay within the declared budgets. Tighten the
|
||||
defaults for release hardware when its normal cache behavior is known. Preserve
|
||||
the soak log and the `ferese::render` summaries with the release artifacts.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Nested resize checks
|
||||
|
||||
Build and launch a preview with protocol and render logging:
|
||||
|
||||
```sh
|
||||
cargo build --release --locked -p ferese -p ferese-shell
|
||||
WAYLAND_DEBUG=1 FERESE_TRACE_PERFORMANCE=1 \
|
||||
target/release/ferese --backend nested --grant-effects --grant-shell-control -- \
|
||||
target/release/ferese-shell 2>/tmp/ferese-resize.log
|
||||
```
|
||||
|
||||
Use a wallpaper, drag each edge of the host window, and repeatedly maximize and
|
||||
restore it. Check that the wallpaper and bar follow without long stalls, including
|
||||
at fractional scaling.
|
||||
|
||||
## Compare renderers
|
||||
|
||||
Repeat with `ICED_BACKEND=wgpu` and `ICED_BACKEND=tiny-skia`. The shell enables
|
||||
wgpu; software fallback can be slower when resampling wallpaper.
|
||||
|
||||
Trace the whole sequence: host resize, layer configure, client acknowledgement,
|
||||
new buffer commit, then compositor rendering. A quick acknowledgement does not
|
||||
mean the client has finished drawing. `FERESE_TRACE_PERFORMANCE` measures compositor
|
||||
work, not shell rasterization.
|
||||
|
||||
## Historical check
|
||||
|
||||
A KDE Wayland check at 175% scale used debug binaries and protocol tracing.
|
||||
Median configure acknowledgement was 1.35 ms with tiny-skia and 2.27 ms with
|
||||
wgpu. Wallpaper buffer intervals were 5919 ms with tiny-skia (only two buffers)
|
||||
and 9.85 ms median with wgpu. Capture durations differed, so these are diagnostic
|
||||
observations rather than throughput benchmarks. GPU intervals also had stalls
|
||||
up to about 200 ms.
|
||||
|
||||
Repeat on the current build. A nested result does not establish direct-session
|
||||
resize or frame-pacing behavior.
|
||||
+28
-38
@@ -1,37 +1,24 @@
|
||||
# Notifications
|
||||
|
||||
Ferese Shell provides themed notification cards and an in-session history panel.
|
||||
Cards appear beneath the bar on the focused output and follow the selected theme.
|
||||
Click the notification icon in the bar to open history, toggle Do Not Disturb, or
|
||||
clear notifications. Escape, clicking outside, or the close button closes the history panel.
|
||||
The center uses the same anchored popup and animation as the other bar menus.
|
||||
Both the center and popup cards follow the shell material: translucent mode uses
|
||||
the compositor’s blur and tint, while solid mode stays opaque.
|
||||
|
||||
## Send a notification
|
||||
|
||||
Notifications use the standard `org.freedesktop.Notifications` D-Bus interface.
|
||||
Existing apps and `notify-send` work without Ferese-specific commands:
|
||||
|
||||
```sh
|
||||
notify-send --app-name=Ferese --icon=dialog-information "Hello" "Your desktop notification"
|
||||
```
|
||||
Ferese shows compact notification popups and a history panel opened from the bar.
|
||||
Their colors, font, corners, and background follow the shell theme.
|
||||
|
||||
## Popups and history
|
||||
|
||||
Up to three popup cards are visible at once. History keeps the most recent 100
|
||||
notifications in memory and clears when the shell exits. Hovering a popup pauses
|
||||
its timer. Critical notifications bypass Do Not Disturb and do not expire unless
|
||||
the sender supplies a timeout. App action buttons emit the standard action signal;
|
||||
a replacement updates the same notification ID. Transient messages are removed
|
||||
from history when they close.
|
||||
Up to three popups are visible at once. Hovering pauses a popup's timer.
|
||||
History keeps the latest 100 notifications and clears when the shell exits.
|
||||
App action buttons work when provided by the sender. Transient messages leave
|
||||
history when closed.
|
||||
|
||||
## Settings and Do Not Disturb
|
||||
Critical notifications bypass Do Not Disturb and remain visible unless the app
|
||||
provides a timeout. Other apps can also request a timeout or no timeout.
|
||||
|
||||
Settings → Notifications controls popup visibility, the initial Do Not Disturb
|
||||
state, and the default timeout. The bar's Do Not Disturb toggle is temporary;
|
||||
changing the Settings option saves the preference for future sessions. Apps can
|
||||
request their own timeout, including no timeout.
|
||||
## Settings
|
||||
|
||||
**Settings → Notifications** controls popup visibility, the default timeout, and
|
||||
the Do Not Disturb preference. The bar toggle changes Do Not Disturb for the
|
||||
current session; Settings saves it for future sessions. Hidden popups still enter
|
||||
history.
|
||||
|
||||
```kdl
|
||||
notifications {
|
||||
@@ -41,17 +28,20 @@ notifications {
|
||||
}
|
||||
```
|
||||
|
||||
The timeout must be between 1000 and 30000 milliseconds. Hiding popups still
|
||||
records notifications in history. Appearance follows the Ferese theme.
|
||||
The default timeout accepts 1000–30000 milliseconds.
|
||||
|
||||
## Session integration
|
||||
## Send a test notification
|
||||
|
||||
Only one notification server can own the D-Bus interface. The Ferese session
|
||||
launcher stops the SwayNotificationCenter user service before starting its shell.
|
||||
For a manually started shell, stop that service with `systemctl --user stop
|
||||
swaync.service`. If another server already owns the interface, Ferese leaves it
|
||||
running and logs that native notifications are unavailable.
|
||||
```sh
|
||||
notify-send --app-name=Ferese --icon=dialog-information "Hello" "Your desktop notification"
|
||||
```
|
||||
|
||||
This implementation supports plain text, app icons, urgency, transient/resident
|
||||
hints, actions, replacements, and close signals. It does not advertise rich body
|
||||
markup, embedded image data, notification sounds, or history persistence.
|
||||
## Troubleshooting
|
||||
|
||||
Only one notification server can run on the session bus. The session launcher
|
||||
stops `swaync.service` before starting the shell. When launching the shell manually,
|
||||
stop any existing notification server first. If another server owns the interface,
|
||||
Ferese logs that native notifications are unavailable.
|
||||
|
||||
Ferese supports plain text, app icons, actions, replacement, and urgency. Rich
|
||||
markup, embedded images, sounds, and saved notification history are not supported.
|
||||
+39
-206
@@ -1,217 +1,50 @@
|
||||
# Release performance baseline
|
||||
# Performance measurements
|
||||
|
||||
Measured 2026-09-27 at commit `08a5866`, using
|
||||
`cargo build --release --locked -p ferese -p ferese-shell -p feresectl`.
|
||||
Use release builds and a fixed workload when comparing performance. Record the
|
||||
commit, output size, scale, refresh rate, graphics driver, and whether the session
|
||||
is nested or direct. Keep the nested preview visible: host occlusion changes
|
||||
rendering behavior.
|
||||
|
||||
Two disposable nested sessions used separate runtime/config directories, default
|
||||
configuration, the bundled wallpaper, and the release shell. Performance logging
|
||||
was enabled with `FERESE_TRACE_PERFORMANCE=1`. The nested output reported
|
||||
1422 × 1696 physical pixels, 2× scale and 60 Hz. The parent DRM output was a
|
||||
2880 × 1800 eDP panel at 120 Hz and 2× scale.
|
||||
## Collect a sample
|
||||
|
||||
## Measurements
|
||||
```sh
|
||||
cargo build --release --locked -p ferese -p ferese-shell -p feresectl
|
||||
FERESE_TRACE_PERFORMANCE=1 target/release/ferese --backend nested \
|
||||
--grant-effects --grant-shell-control -- target/release/ferese-shell
|
||||
```
|
||||
|
||||
CPU is process CPU time from `/proc/PID/stat` divided by elapsed monotonic time,
|
||||
expressed as a percentage of one core. First-run samples lasted 10 seconds;
|
||||
second-run samples lasted 5 seconds. These are short observational samples,
|
||||
not statistically established improvements or before/after comparisons.
|
||||
Compare idle, several windows, overview, Settings navigation, translucent
|
||||
popovers, and screen capture separately. Allow startup to settle and repeat each
|
||||
sample. Record process CPU, child-process CPU, RSS, render attempts, and damaged
|
||||
frames. Keep build work and unrelated activity outside the sampling interval.
|
||||
|
||||
| Scenario | Compositor CPU, run 1 / run 2 | Shell CPU, run 1 / run 2 |
|
||||
CPU percentages below use one core as 100%. Short samples are observations,
|
||||
not guarantees or hardware-session benchmarks.
|
||||
|
||||
## Historical results
|
||||
|
||||
On 2026-09-27 at `08a5866`, two nested runs used a 1422 × 1696 output at 2× scale,
|
||||
reporting 60 Hz on a 120 Hz host. Samples lasted 5–10 seconds.
|
||||
|
||||
| Scenario | Compositor CPU, two runs | Shell CPU, two runs |
|
||||
| --- | --- | --- |
|
||||
| Idle shell, no application window | 5.3% / 5.8% | 1.5% / 1.6% |
|
||||
| Idle, no application window | 5.3% / 5.8% | 1.5% / 1.6% |
|
||||
| Overview with one terminal | 18.6% / 16.2% | 1.3% / 1.4% |
|
||||
| After window transitions, terminal still open | 6.6% / 6.4% | 1.5% / 1.4% |
|
||||
| After transitions | 6.6% / 6.4% | 1.5% / 1.4% |
|
||||
|
||||
Compositor RSS was approximately 81–82 MiB initially and 91–92 MiB after the
|
||||
short exercise. This does not establish a leak or long-term memory stability.
|
||||
Main-thread voluntary context switches were approximately 162–165/s at idle
|
||||
and 498–505/s in overview; these are scheduling proxies, not hardware wakeups.
|
||||
Compositor RSS increased from about 81–82 MiB to 91–92 MiB during the exercise.
|
||||
These samples do not establish a leak or long-term stability. A follow-up had
|
||||
lower rendering rates, so the original observations did not prove duplicate scheduling.
|
||||
|
||||
A five-second idle log interval contained 60 damaged frames and 531 no-damage
|
||||
attempts, approximately 118 attempts/s. A later overview interval contained
|
||||
591 damaged frames in 5001 ms. Nested frame scheduling and overview damage
|
||||
therefore deserve investigation first. The parent runs at 120 Hz, so the
|
||||
mismatch with the nested output's reported 60 Hz must be understood before
|
||||
attributing these counts to duplicate scheduling.
|
||||
A 20-second status-worker comparison removed five commands per poll (15 to 10).
|
||||
Total measured CPU time including child processes fell from 2.41 to 1.90 seconds.
|
||||
The timing wrapper was included, and this was one comparison.
|
||||
|
||||
## Behavioral exercise
|
||||
For push status delivery (`4bf0757` to `b0583eb`), a synthetic transport test
|
||||
measured median delivery delay of 129.398 ms before and 0.130 ms after. It excluded
|
||||
queries, UI dispatch, and painting. Visible shell samples suggested lower typical
|
||||
CPU, but an after-run spike raised the mean; they did not establish a robust
|
||||
average CPU saving.
|
||||
|
||||
Both sessions exited with status 0. The probes created a terminal, entered and
|
||||
left overview, and toggled maximize, fullscreen and floating twice each.
|
||||
The second session exercised `theme.typography.font_family`, wallpaper fit/fill,
|
||||
and replacement image paths through filesystem-driven reloads. Logs confirmed
|
||||
accepted reloads and replacement wallpaper decoding. This verifies execution
|
||||
and liveness, not pixel-perfect appearance or GPU allocation-failure recovery.
|
||||
The first probe used an incorrect font key; only the second probe counts as
|
||||
font reload coverage.
|
||||
|
||||
Raw local artifacts:
|
||||
|
||||
- `/tmp/ferese-profile-7cbrpopn/{results.json,session.log}`
|
||||
- `/tmp/ferese-profile-h2ypepn6/{results.json,session.log}`
|
||||
- Probe scripts: `/tmp/ferese-profile.py` and `/tmp/ferese-profile-reloads.py`
|
||||
|
||||
## Limits and next work
|
||||
|
||||
The installed DRM compositor is release `20260927-042025-168287`; its binary hash
|
||||
differs from the tested release build. A read-only host sample measured 9.8%
|
||||
compositor CPU and 1.7% shell CPU, but overlapped the nested workload and is not
|
||||
an idle baseline or validation of the new DRM code. No session was replaced.
|
||||
Only one monitor was connected, so multi-monitor behavior remains untested.
|
||||
|
||||
Next investigate nested refresh scheduling and repeated overview damage, using
|
||||
these scenarios for before/after measurements. Preserve client frame callbacks,
|
||||
animation pacing and idle responsiveness. Status command polling remains a
|
||||
secondary target; blur invalidation needs a separate translucent-material
|
||||
workload before ranking its cost. New-build DRM and multi-monitor validation
|
||||
remain necessary before claiming hardware performance improvements.
|
||||
|
||||
## Follow-up investigation
|
||||
|
||||
A repeat baseline (`/tmp/ferese-profile-n8437l1i`) confirmed 60 Hz after startup
|
||||
but ran near 60 attempts/s rather than 118. Compositor CPU was 3.0% idle, 9.2%
|
||||
in overview and 4.6% after transitions. The earlier high-rate behavior is not
|
||||
consistently reproduced, so it is not sufficient evidence of duplicate redraws.
|
||||
The candidate refresh-period guard was discarded after testing.
|
||||
|
||||
The guard run (`/tmp/ferese-profile-llcrkvm5`) measured 4.0% idle, 8.6% overview,
|
||||
and 3.6% after transitions. Render attempts fell slightly below the nominal
|
||||
cadence. This did not establish a benefit, so no frame-pacing change was kept.
|
||||
The next investigation is unconditional thumbnail damage in overview.
|
||||
|
||||
## Broader profiling (visible preview)
|
||||
|
||||
Artifacts: `/tmp/ferese-profile-all-0lhodit4/`; script:
|
||||
`/tmp/ferese-profile-all.py`. This run used the unchanged release compositor,
|
||||
release shell and release Settings. The user kept the preview visible after an
|
||||
earlier hidden-window run proved that host occlusion invalidated render samples.
|
||||
Six-second samples are exploratory, not statistically stable benchmarks.
|
||||
The captured output was 2856 × 1696 pixels; the preview was resized during the
|
||||
session, so these workloads must not be compared as if output size were fixed.
|
||||
|
||||
| Scenario | Compositor CPU | Shell CPU | Shell waited-child CPU | Settings CPU |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| Idle shell | 4.33% | 1.33% | 7.50% | — |
|
||||
| Three terminals | 6.67% | 1.50% | 11.33% | — |
|
||||
| Overview, three terminals | 17.50% | 1.17% | 8.17% | — |
|
||||
| Settings open, idle | 6.17% | 1.50% | 10.83% | 0.00% |
|
||||
| After capture/window transitions | 8.50% | 1.33% | 11.00% | 2.50% |
|
||||
|
||||
Percentages use one CPU core as 100%. Child CPU is Linux's accumulated CPU time
|
||||
for reaped children, separate from the shell process. This includes the timing
|
||||
wrapper: a PATH-local `timeout` wrapper invokes GNU time and the real timeout
|
||||
command. Read-only PipeWire queries use the host runtime socket; no status
|
||||
control actions were sent. The native installed shell cross-check, without
|
||||
instrumentation, measured 2.0% self CPU plus 8.8% waited-child CPU over ten
|
||||
seconds. It is an older binary and a different scene, so this corroborates the
|
||||
existence of subprocess overhead rather than providing an exact comparison.
|
||||
|
||||
The preview recorded 273 successful status command invocations across 21 polls:
|
||||
13 per poll. The three login1 capability calls consumed 1.88 seconds total wall
|
||||
time, about 90 ms/poll. Three nmcli queries consumed 1.35 seconds total; two wpctl
|
||||
queries consumed 0.80 seconds. GNU time's hundredth-second granularity makes
|
||||
per-command CPU totals unsuitable for precise attribution. Stable capability
|
||||
queries, device metadata and frequently changing values currently share one
|
||||
poll cycle. Separate refresh policies or service subscriptions deserve priority.
|
||||
|
||||
Settings mapped in 109 ms, measured from process launch until IPC reported it
|
||||
focused (not first completed paint). Idle Settings RSS was 108068 KiB, with 38
|
||||
threads and 65 descriptors. Zero measured CPU over six seconds means below this
|
||||
sample's resolution, not a guarantee of zero work. Startup font enumeration was
|
||||
not isolated separately. Settings interaction/search/page-switch profiling is
|
||||
still outstanding.
|
||||
|
||||
Twenty `feresectl get-outputs` calls had median process-inclusive latency of
|
||||
3.05 ms and maximum 3.95 ms. Five captures took 1.13 seconds total, including
|
||||
client startup, transfer and PNG encoding. Capture was enabled only in the
|
||||
isolated compositor with `FERESE_ENABLE_SCREENCOPY=1`. The first screenshot was
|
||||
visually inspected and showed the shell and Settings rendered. It does not
|
||||
measure GPU readback independently. Window maximize/fullscreen/layout toggles
|
||||
completed, but there was no instrumented input-to-photon latency measurement.
|
||||
|
||||
The four-second visible overview perf recording (`cpu-clock:u`, 999 Hz) collected
|
||||
471 samples with no lost samples. Shared-object attribution: 47.77% Ferese
|
||||
executable (including statically linked dependencies), 30.36% Mesa Gallium,
|
||||
14.23% libc, 2.97% Wayland client library. Approximately 96.4% of samples were in
|
||||
the main compositor thread. Texture upload/memory-copy paths appear in the
|
||||
sampled stacks. This is user-space CPU sampling, not GPU timing; short samples
|
||||
and incomplete frame-pointer unwinding limit function-level attribution.
|
||||
|
||||
The earlier broad run (`/tmp/ferese-profile-all-boiq_r30`) had a 37-second render
|
||||
reporting gap while hidden, no usable perf samples, and a disabled screencopy
|
||||
protocol. Its render/overview and capture results are excluded. Its bare idle
|
||||
sample was 1.0% CPU, but visibility differences preclude subtracting it from the
|
||||
visible shell run.
|
||||
|
||||
Next priority: shell status subprocesses. Then investigate sustained overview
|
||||
damage and texture uploads with controlled window visibility and dimensions.
|
||||
Control-center interaction, widgets, translucent-material workloads, long-term
|
||||
memory growth, new-build DRM and multi-monitor runs remain unprofiled. No source
|
||||
changes or profiling-note commits were made during this profiling pass.
|
||||
|
||||
## Status-worker optimization comparison
|
||||
|
||||
Compared the production status module at `08a5866` with the new single-command
|
||||
brightness reader and reusable native D-Bus connections. A standalone harness
|
||||
started `Service::start(None)`, consumed updates every 250 ms, and ran for 20
|
||||
seconds without a UI. Both variants used the same host runtime/services and
|
||||
command timing wrapper. Artifacts: `/tmp/ferese-status-compare/`.
|
||||
|
||||
Both completed nine polls. Notifications were available in this comparison, so
|
||||
the original worker launched 15 commands/poll and the new one launched 10:
|
||||
135 versus 90 invocations. Four busctl launches and one brightnessctl launch per
|
||||
poll were removed. When notifications are absent, the equivalent counts are
|
||||
13 versus 8. Poll frequency, fresh capability queries and post-action generation
|
||||
handling remain unchanged; no status-value caching was introduced.
|
||||
|
||||
GNU time measured total user+system CPU, including waited children: 2.41 seconds
|
||||
before, 1.90 seconds after over 20.01 seconds each (about 21% lower in this single
|
||||
comparison). Timing-wrapper overhead is included, so this is not a precise
|
||||
uninstrumented CPU improvement estimate. Native D-Bus adds persistent sockets
|
||||
and a runtime thread pool; UI samples observed roughly 26–28 shell threads and
|
||||
48 descriptors versus roughly 18 threads and 42 descriptors previously.
|
||||
|
||||
One UI run showed a transient self-CPU spike; a subsequent perf recording
|
||||
identified tiny-skia raster work rather than D-Bus queries among its hot paths.
|
||||
The UI-free comparison avoids treating variable UI activity as polling cost.
|
||||
|
||||
Validation: workspace suite and explicit private-dbus-daemon test passed. The
|
||||
private bus exercised live capability changes, yes/challenge/no/na handling,
|
||||
notification-owner appearance/disappearance, error replies, missing methods,
|
||||
and a reply delayed past the configured timeout. Brightness parser tests cover
|
||||
rounding, zero brightness, invalid classes and malformed/nonfinite values.
|
||||
|
||||
### Push status delivery measurement (b0583eb)
|
||||
|
||||
Compared release binaries for 4bf0757 and b0583eb with the same nested compositor,
|
||||
empty isolated config and a visible preview. Binary SHA-256 hashes differ and
|
||||
were checked after forcing a shell rebuild to avoid shared-target artifact reuse.
|
||||
No status-command timing wrappers were active. Discarded an initial baseline
|
||||
that overlapped compilation. Retained after/before/after runs, each with three
|
||||
10-second samples following a three-second startup settle. Artifacts and harness:
|
||||
`/tmp/ferese-status-push-measure/` (`summary.json`, `ui.py`, `latency.rs`).
|
||||
|
||||
Shell CPU percentages of one core:
|
||||
- Before: 1.5, 1.4, 1.6 (median 1.5).
|
||||
- After run 1: 0.8, 1.1, 1.1.
|
||||
- After run 2: 1.0, 1.1, 7.5 (combined after median 1.1).
|
||||
|
||||
The 7.5% sample coincided with a large damaged-pixel burst (44.3 million in a
|
||||
five-second interval), higher RSS and two additional descriptors. Its cause was
|
||||
not isolated; it is retained, not silently excluded. Combined after mean is
|
||||
2.1%, versus 1.5% before, so these short runs do not establish a robust average
|
||||
CPU saving. Typical steady-state samples suggest a 0.4 percentage-point reduction.
|
||||
Status child CPU remained roughly 6–8% of one core, dominating shell self CPU.
|
||||
|
||||
Steady-state damaged frames were about 12/s before versus 6.6–7.6/s in the first
|
||||
after run. The repeat had similar quiet intervals plus bursts at 15.6 and 22.7/s.
|
||||
Total render attempts stayed around 60/s, confirming active rather than hidden
|
||||
preview sampling. No claim is made about DRM-session CPU or total idle wakeups.
|
||||
|
||||
An isolated transport harness used the old bounded mpsc + 250ms polling path and
|
||||
an extracted copy of the new Updates::stream implementation, with 40 synthetic
|
||||
updates per path at 317ms intervals. Worker-to-consumer delay:
|
||||
- Before: median 129.398ms, p95 239.957ms, maximum 245.881ms.
|
||||
- After: median 0.130ms, p95 0.330ms, maximum 0.425ms.
|
||||
This measures delivery only, excluding status queries, UI dispatch and painting.
|
||||
The preview processes exited and the temporary source worktree was removed.
|
||||
These results predate later changes. Run fresh comparisons for current claims,
|
||||
and validate direct rendering and multiple monitors separately.
|
||||
+45
-159
@@ -1,174 +1,60 @@
|
||||
# Desktop portals
|
||||
|
||||
Applications call the standard `org.freedesktop.portal.Desktop` frontend. Ferese's
|
||||
native backend implements desktop integration; GTK remains the fallback for
|
||||
standard file, print and application dialogs. Install both backends.
|
||||
Desktop portals let applications request screen sharing, screenshots, wallpaper
|
||||
changes, and other desktop services. Ferese provides themed consent dialogs;
|
||||
GTK supplies file, print, and other standard dialogs.
|
||||
|
||||
## Native services
|
||||
Install `xdg-desktop-portal`, `xdg-desktop-portal-gtk`, and Ferese's backend through
|
||||
[Installation](installation.md). The session launcher starts the services with
|
||||
the correct display environment.
|
||||
|
||||
- **Settings:** Ferese's color scheme, accent color, contrast preference and
|
||||
reduced-motion setting. Changes are signalled after valid KDL appearance
|
||||
changes; malformed saves leave the last valid preferences intact.
|
||||
- **Screenshot:** screen, selected-area, selected-window and active-window PNG
|
||||
captures, plus a screen color picker. Window captures render the selected
|
||||
toplevel and its subsurfaces in isolation, preserving transparency; occluding
|
||||
windows, separate popups, shell layers and compositor borders are excluded.
|
||||
The native window picker lists window titles and application IDs. Every capture
|
||||
asks for consent. Interactive requests offer area selection; area and color
|
||||
selection use `slurp`. Captures use Ferese's bounded screenshot IPC.
|
||||
The helper must disappear from the compositor before capture starts.
|
||||
- **Wallpaper:** a preview and confirmation, then an atomic configuration update.
|
||||
Desktop and lock-screen wallpaper can be set independently, or together.
|
||||
Ferese copies accepted local images into its own private data directory so
|
||||
temporary portal files can disappear safely. Image bytes and decoded dimensions
|
||||
are bounded. `theme.background.lock-path` overrides the lock-screen image;
|
||||
without it the lock screen follows `theme.background.path`.
|
||||
- **Background:** native open-window/app state, change signals and per-instance
|
||||
background consent. Legacy autostart requests create managed XDG desktop entries;
|
||||
current frontends manage those files themselves. Direct sessions launch standard
|
||||
XDG autostart entries after importing the display environment. User overrides,
|
||||
Hidden, OnlyShowIn, NotShowIn and TryExec are respected; previews skip autostart.
|
||||
- **Lockdown:** standard printing, save-to-disk, application-handler, location,
|
||||
camera, microphone and sound-output restrictions. All default to unrestricted.
|
||||
Configure boolean `disable-*` fields under `portals { lockdown { ... } }`;
|
||||
changes are signalled to the frontend. Invalid policy types retain the current
|
||||
policy. Only the portal frontend may write backend policy properties.
|
||||
- **USB:** native confirmation showing device vendor/model and requested read-only
|
||||
or read/write access. The portal frontend handles device enumeration and opening.
|
||||
- **GlobalShortcuts:** session-scoped keyboard shortcuts with native trigger
|
||||
selection, conflict checking, activation/release signals and reconfiguration.
|
||||
Applications cannot replace Ferese bindings or reserved escape/VT shortcuts.
|
||||
Closing a session or losing its compositor connection releases its shortcuts;
|
||||
shortcuts do not activate on the lock screen. Saved choices are offered for
|
||||
future sessions, with explicit approval before registering them.
|
||||
- **Inhibit:** connection-scoped logout, suspend and idle inhibitors, backed by
|
||||
logind descriptors and compositor idle inhibition. Native session monitors
|
||||
report lock state and Running/QueryEnd/Ending transitions. Ending queries wait
|
||||
for acknowledgements for up to one second. Power confirmations list blockers
|
||||
and recheck them before acting; authentication failure cancels the query.
|
||||
UserSwitch is recorded, but Ferese currently has no user-switch operation.
|
||||
- **InputCapture:** approved keyboard and pointer capture over a private EIS
|
||||
connection, with standard screen zones and pointer barriers on outside display
|
||||
edges. Capture begins at a configured barrier; releasing it restores local
|
||||
input. Ctrl+Alt+Escape returns control immediately. Locking, topology/keymap
|
||||
changes, receiver disconnects and stalled consumers stop capture. Permission
|
||||
is requested for every session; touch capture and remembered grants are not
|
||||
offered. This is an input receiver, not remote input injection.
|
||||
- **ScreenCast:** monitor and isolated window sharing with a native picker, PipeWire streams and explicit opt-in
|
||||
saved permissions. The frontend stores and revokes saved choices. Invalid
|
||||
restore data or changed display identity requires fresh consent.
|
||||
See [screen sharing](screen-sharing.md) for lifetime and recording details.
|
||||
## Supported services
|
||||
|
||||
Native request dialogs use Ferese's theme and are floating windows. Screenshot,
|
||||
PickColor, Wallpaper, USB, InputCapture and ScreenCast consent dialogs use Wayland parent identifiers to establish
|
||||
a transient relationship with the requesting window.
|
||||
Cancelling a request or losing the portal frontend terminates its pending helper.
|
||||
|
||||
The packaged `ferese-portals.conf` selects these interfaces explicitly. Existing
|
||||
user overrides in `~/.config/xdg-desktop-portal/` may take precedence. Install the
|
||||
new compositor, backend and preference files together; screenshot synchronization
|
||||
requires the updated compositor IPC.
|
||||
|
||||
## GNOME compatibility audit
|
||||
|
||||
The audit compares the [GNOME backend's registered interfaces](https://github.com/GNOME/xdg-desktop-portal-gnome/blob/main/data/meson.build)
|
||||
with the [standard backend D-Bus contracts](https://flatpak.github.io/xdg-desktop-portal/docs/impl-dbus-interfaces.html).
|
||||
Matching D-Bus signatures does not establish complete feature parity.
|
||||
|
||||
| Interface | Ferese integration |
|
||||
| Service | Behavior |
|
||||
| --- | --- |
|
||||
| Settings | Native, including appearance change signals |
|
||||
| Screenshot | Native screen/area/window/active-window capture and PickColor |
|
||||
| Wallpaper | Native desktop, lock-screen and combined targets |
|
||||
| ScreenCast | Native v4 monitors and isolated windows, logical geometry, live window resizing and opt-in saved display permissions |
|
||||
| Access, Account, AppChooser, DynamicLauncher, FileChooser, Notification, Print | Delegated to GTK |
|
||||
| Background | Native application state, per-instance consent and XDG autostart |
|
||||
| Usb | Native consent; standard frontend handles enumeration and device descriptors |
|
||||
| GlobalShortcuts | Native sessions, configurable keyboard triggers, conflict checks and activation/release signals |
|
||||
| RemoteDesktop | Deferred: authorized input injection and EIS transport |
|
||||
| Clipboard | Deferred with RemoteDesktop |
|
||||
| InputCapture | Native v2 keyboard/pointer consent, zones, outside-edge barriers and private EIS receiver transport |
|
||||
| Lockdown | Native seven-property policy provider with persisted configuration and change signals |
|
||||
| Inhibit | Native inhibitors and session monitors; UserSwitch recorded until a switch operation exists |
|
||||
| Settings | Color scheme, accent, contrast, and reduced-motion preferences |
|
||||
| Screenshot | Screen, area, window, active-window capture, and color picking |
|
||||
| Wallpaper | Preview and approval for desktop, lock screen, or both |
|
||||
| ScreenCast | Display and window sharing through PipeWire |
|
||||
| Background | Permission to run in the background and startup integration |
|
||||
| USB | Device information and approval for requested access |
|
||||
| GlobalShortcuts | App shortcut selection, conflict checks, and activation |
|
||||
| Inhibit | App requests to delay logout, suspend, or idle actions |
|
||||
| InputCapture | Approved keyboard/pointer capture for input-sharing applications |
|
||||
| Lockdown | Administrator restrictions on printing, saving, handlers, location, camera, microphone, and sound |
|
||||
| FileChooser, Print, Access, Account, AppChooser, DynamicLauncher, Notification | GTK backend |
|
||||
|
||||
The frontend supplies additional APIs such as OpenURI, network monitoring,
|
||||
document export and permission storage. Adding a similarly named backend service
|
||||
is neither required nor sufficient for those APIs.
|
||||
RemoteDesktop and its session Clipboard integration are not implemented.
|
||||
This does not affect ordinary application clipboard use.
|
||||
|
||||
Window streams render only the selected toplevel and its subsurfaces, including
|
||||
on an inactive workspace. Overlapping apps, shell layers, separate popup windows
|
||||
and compositor decorations are excluded. The private capture protocol is available
|
||||
only to the native portal executable and checks session opt-in and locking.
|
||||
Window resizing renegotiates PipeWire video dimensions. Closing the selected
|
||||
window ends sharing; its lifetime ID cannot select a replacement app. Window
|
||||
selections require fresh consent and are not saved as display permissions.
|
||||
RemoteDesktop and its Clipboard integration remain deferred.
|
||||
## Consent and capture
|
||||
|
||||
## Validation
|
||||
Screenshot and screen-sharing requests ask for approval. Screen sharing can
|
||||
remember display permissions when the application requests it and the user opts
|
||||
in. Window sharing always asks again. See [Screen sharing](screen-sharing.md).
|
||||
Window captures contain the selected app and its subsurfaces; separate popups,
|
||||
other apps, shell layers, and compositor decorations are excluded.
|
||||
|
||||
Build the backend and run unit tests, then check its contracts on a private bus:
|
||||
InputCapture starts at an approved display-edge barrier. **Ctrl+Alt+Escape**
|
||||
returns local control. Locking, disconnecting the receiver, or changing displays
|
||||
or the keyboard layout stops capture. Touch and remembered InputCapture grants
|
||||
are not supported. InputCapture forwards local input; it does not inject remote input.
|
||||
|
||||
```sh
|
||||
cargo build --locked -p xdg-desktop-portal-ferese
|
||||
cargo test --locked -p xdg-desktop-portal-ferese
|
||||
python3 scripts/tests/test_portal_contracts.py
|
||||
```
|
||||
Wallpaper approval copies the image into Ferese's data directory and updates the
|
||||
config. Set `theme.background.lock-path` for a separate lock-screen image; otherwise
|
||||
it follows the desktop wallpaper.
|
||||
|
||||
With a Wayland host and a built compositor, check shortcut connection cleanup
|
||||
and configuration conflicts in an isolated nested compositor:
|
||||
Global shortcuts cannot replace Ferese bindings or reserved escape/console keys.
|
||||
They stop when the app session closes and never activate on the lock screen.
|
||||
Power confirmations show app inhibitors before proceeding. Ferese has no
|
||||
user-switch operation.
|
||||
|
||||
```sh
|
||||
FERESE_TEST_SHORTCUTS=1 python3 scripts/tests/test_shortcuts_isolated.py
|
||||
```
|
||||
## Portal selection
|
||||
|
||||
Check window capture isolation, transparency and orientation with overlapping
|
||||
clients in a temporary nested compositor:
|
||||
The installer writes `/usr/share/xdg-desktop-portal/ferese-portals.conf`.
|
||||
Overrides in `~/.config/xdg-desktop-portal/` may take precedence. If a request opens
|
||||
the wrong dialog or no source appears, check those overrides and confirm that
|
||||
`XDG_CURRENT_DESKTOP` includes `Ferese`.
|
||||
|
||||
```sh
|
||||
FERESE_TEST_WINDOW_CAPTURE=1 python3 scripts/tests/test_window_capture_isolated.py
|
||||
```
|
||||
|
||||
Capture a managed window directly from the CLI with `feresectl screenshot-window
|
||||
<window-id> > capture.png`; `feresectl get-windows` lists IDs.
|
||||
|
||||
The contract test compares introspection against the installed official backend
|
||||
XML, verifies appearance changes and invalid-save retention, and checks that
|
||||
sensitive methods reject callers outside the portal frontend. It does not open
|
||||
consent dialogs or capture the host desktop. Interactive consent, fractional-scale
|
||||
capture, polkit and hotplug still require a live session test.
|
||||
|
||||
Check native inhibitor lifetimes, acknowledgement generations and session-ending
|
||||
transitions against a mock logind in an isolated nested compositor:
|
||||
|
||||
```sh
|
||||
FERESE_TEST_INHIBIT=1 python3 scripts/tests/test_inhibit_isolated.py
|
||||
```
|
||||
|
||||
The shell now requires version 4 of Ferese's shell protocol; rebuild the shell
|
||||
and compositor together when upgrading.
|
||||
|
||||
Check restored sharing, mode downgrade, stale-data fallback, output-generation
|
||||
validation and frontend-disconnect cleanup with synthetic monitor identities on
|
||||
an isolated bus and nested compositor:
|
||||
|
||||
```sh
|
||||
FERESE_TEST_RESTORE=1 python3 scripts/tests/test_restore_isolated.py
|
||||
```
|
||||
|
||||
Check live window pixels, overlap isolation, inactive workspaces, resizing and
|
||||
closure using a disposable nested compositor and a real PipeWire consumer:
|
||||
|
||||
```sh
|
||||
FERESE_TEST_WINDOW_STREAM=1 python3 scripts/tests/test_window_stream_isolated.py
|
||||
```
|
||||
|
||||
Check InputCapture state and its transport against an installed libei receiver:
|
||||
|
||||
```sh
|
||||
cargo test --locked -p ferese input_capture::tests
|
||||
cargo test --locked -p xdg-desktop-portal-ferese eis::tests -- --ignored
|
||||
```
|
||||
|
||||
The receiver test uses a private socket pair and synthetic input; it never
|
||||
captures the host keyboard or changes host focus. Real pointer-barrier crossings
|
||||
and interactive consent still need a live session check.
|
||||
For capture issues, see [screen-sharing troubleshooting](screen-sharing.md#troubleshooting).
|
||||
For backend contracts and integration checks, see [Development](development.md#portal-checks).
|
||||
+50
-120
@@ -1,142 +1,73 @@
|
||||
# Screen sharing and recording
|
||||
|
||||
Ferese includes a ScreenCast portal backend, `xdg-desktop-portal-ferese`.
|
||||
Applications use the standard desktop portal to request a display or window, then receive
|
||||
video through PipeWire. A recorder or conferencing application handles encoding,
|
||||
saving files, or sending video; those tasks do not run inside the compositor.
|
||||
Share a monitor or window from a Wayland-compatible recording or conferencing app,
|
||||
or save a video using the top bar. [Installation](installation.md) includes the
|
||||
portal and PipeWire dependencies.
|
||||
|
||||
## Record from the top bar
|
||||
|
||||
1. Click the screen-recording icon in the top bar to open the display picker.
|
||||
2. Choose a monitor in the native picker and click **Share**.
|
||||
3. The icon changes to a stop square and shows elapsed time. Click it to stop.
|
||||
1. Click the recording icon.
|
||||
2. Select a monitor and click **Share**.
|
||||
3. Click the stop square to finish.
|
||||
|
||||
The recorder finishes the video before sending a notification with its saved
|
||||
path. Videos are saved as VP8 WebM files under
|
||||
`Videos/Ferese` (using your configured XDG Videos folder). Audio is off.
|
||||
The icon uses the same theme accent, hover effect, and corner radius as the
|
||||
other bar controls.
|
||||
|
||||
Encoding runs in a separate native `ferese-record` process using GStreamer.
|
||||
The shell remains responsive while a file is recorded or finalized. If saving
|
||||
fails, an error appears in the notification center; an unfinished `.webm.part` file
|
||||
may remain at the path shown in the error.
|
||||
Videos are saved as VP8 WebM files in your XDG Videos folder under `Ferese`.
|
||||
A notification shows the saved path. Audio and region recording are not supported
|
||||
by the built-in recorder; other recording apps can handle audio separately.
|
||||
If recording fails, a notification reports the error and any unfinished
|
||||
`.webm.part` file.
|
||||
|
||||
## Start sharing
|
||||
|
||||
Use a Wayland screen-sharing or recording source in your application. Ferese
|
||||
opens a native source picker. Depending on what the application requests, choose
|
||||
from displays, windows, or both and press **Share**. Nothing is selected by default.
|
||||
Applications that request multiple sources can select up to eight. Display and
|
||||
window choices are grouped separately. Windows show their title and application.
|
||||
Window streams capture only the selected app's toplevel and subsurfaces, even
|
||||
when covered or on another workspace. Separate popups and compositor decorations
|
||||
are excluded. Resizing a shared window updates the video size without ending the
|
||||
session. Closing that window ends sharing.
|
||||
The picker uses your Ferese theme colors, font, and shell corner radius. Its
|
||||
background uses the same compositor material as popovers and authentication
|
||||
prompts: opaque in solid mode, or blurred and translucent using the shared
|
||||
**Appearance → Shell opacity** and blur settings. Text and icons remain opaque.
|
||||
Select a Wayland screen-sharing source in your application. In Ferese's picker,
|
||||
choose a display or window and click **Share**. Nothing is selected initially.
|
||||
Apps requesting multiple sources can select up to eight.
|
||||
|
||||
Other applications keep a **screen sharing** window with a **Stop sharing** button.
|
||||
Ferese’s built-in recorder uses the top-bar stop control instead, leaving your
|
||||
windows accessible after display selection. The command-line recorder keeps the
|
||||
sharing window when it is not launched by the shell. Press **Stop sharing** or
|
||||
close the sharing window to revoke an ordinary application’s session. Closing the requesting application,
|
||||
locking Ferese, disconnecting the selected display, or changing a monitor's capture
|
||||
size also ends sharing. By default, each request asks for consent. If an application requests saved
|
||||
permissions, the picker offers an **Allow without asking** switch, off by default.
|
||||
Permissions can last while the application runs or until revoked, as requested
|
||||
by the app. The standard portal frontend owns permission storage and revocation.
|
||||
A changed or missing display, different app, or changed cursor options asks again.
|
||||
Displays without a reliable EDID identity, including nested previews, always need
|
||||
fresh consent. Window selections also require fresh consent and cannot enable saved
|
||||
display permissions. Stopping a stream ends that stream; it does not erase a previously
|
||||
saved permission.
|
||||
Everything visible on a shared display, including notifications, is included.
|
||||
A shared display includes everything visible on it, including notifications.
|
||||
A shared window includes only that app's content and subsurfaces, even when
|
||||
covered or on another workspace. Separate popups and compositor decorations are
|
||||
excluded. Resizing a shared window updates its video size; closing it ends sharing.
|
||||
|
||||
## Installation
|
||||
The picker follows your shell colors, font, corners, opacity, and blur.
|
||||
|
||||
The [standard installer](installation.md) builds and installs the backend, its
|
||||
D-Bus activation entry, and a Ferese-specific portal preference file. Install
|
||||
`pipewire`, a PipeWire session manager such as `wireplumber`,
|
||||
`xdg-desktop-portal`, and `xdg-desktop-portal-gtk` using your distribution's package
|
||||
manager. The GTK backend supplies standard dialogs such as file selection. Ferese also
|
||||
provides native Settings, Screenshot and Wallpaper services; see
|
||||
[desktop portals](portals.md).
|
||||
The built-in recorder also needs GStreamer’s PipeWire, base, and good plugins
|
||||
(`pipewiresrc`, `videoconvert`, `vp8enc`, and `webmmux`). The installation guide
|
||||
includes these packages.
|
||||
## Stop sharing
|
||||
|
||||
Log into a new Ferese session after installation. The session launcher imports
|
||||
its Wayland display into the D-Bus activation environment. Nested previews leave
|
||||
the host activation environment alone.
|
||||
Click **Stop sharing** in the sharing window, or close that window. The built-in
|
||||
recorder uses the top-bar stop button instead. Sharing also ends when the app
|
||||
closes or Ferese locks. Disconnecting a shared monitor or changing its capture
|
||||
size ends its stream; start sharing again afterward.
|
||||
|
||||
Existing custom window rules can float the picker and sharing indicator:
|
||||
## Remember permissions
|
||||
|
||||
```kdl
|
||||
window-rule app-id="dev.ferese.ScreenShare" floating=#true
|
||||
```
|
||||
When an app requests saved display permissions, the picker offers **Allow without
|
||||
asking**, off by default. Approval lasts for the duration requested by the app.
|
||||
The portal manages stored permissions and revocation.
|
||||
|
||||
The packaged example configuration already includes this rule. Existing user
|
||||
configuration is preserved during installation.
|
||||
A different app, changed display, or changed cursor option needs approval again.
|
||||
Nested previews and displays without a reliable identity always ask. Window
|
||||
permissions are not saved. Stopping a stream does not erase a saved permission.
|
||||
|
||||
## Current capabilities
|
||||
## Requirements and limits
|
||||
|
||||
- Monitor and isolated window capture, one PipeWire stream per source, up to 30 fps.
|
||||
- Window streams keep working across workspace switches and renegotiate on resize.
|
||||
- Hidden or embedded pointer, as requested by the application.
|
||||
- Logical stream position and size, including fractional output scales.
|
||||
- Wayland parent-window relationships for the consent picker.
|
||||
- Bounded frame storage and reusable shared-memory buffers.
|
||||
- Cancellation during selection, an explicit stop control, and process cleanup.
|
||||
- ScreenCast backend version 4 with explicit opt-in saved display permissions.
|
||||
Install PipeWire, WirePlumber, `xdg-desktop-portal`, and `xdg-desktop-portal-gtk`.
|
||||
The built-in recorder also needs GStreamer's PipeWire, base, and good plugins;
|
||||
see the [package lists](installation.md#requirements).
|
||||
|
||||
Region selection and audio capture in Ferese’s recorder are not implemented yet.
|
||||
The top-bar recorder currently requests monitors. Other recording applications can handle audio separately.
|
||||
Video currently uses CPU copies through the compositor's shared-memory screencopy path, not DMA-BUF zero-copy. High-resolution
|
||||
or multiple-display recording can therefore use significant CPU and memory
|
||||
bandwidth. A paused stream checks capture availability once per second so locking
|
||||
also ends sessions without an active consumer.
|
||||
The installer supplies Ferese's portal backend and selects it for screen sharing.
|
||||
Log into a new Ferese session after installation.
|
||||
|
||||
## Development checks
|
||||
|
||||
Build the backend after installing the native dependencies in the
|
||||
[installation guide](installation.md#requirements):
|
||||
|
||||
```sh
|
||||
cargo build --release --locked -p xdg-desktop-portal-ferese
|
||||
cargo test --locked -p xdg-desktop-portal-ferese
|
||||
# Exercise real video encoding and playback (requires the plugins above):
|
||||
cargo test --locked -p xdg-desktop-portal-ferese --bin ferese-record encoder_finishes_a_real_webm -- --ignored
|
||||
```
|
||||
|
||||
The opt-in integration test opens a temporary nested compositor and uses a
|
||||
private D-Bus session. It requires built Ferese and locker binaries, Python
|
||||
GI/GStreamer with `pipewiresrc`, `dbus-daemon`, `xdg-desktop-portal`, and `bwrap`.
|
||||
It checks capture delivery and timestamps, cancellation, frontend loss, and lock
|
||||
revocation:
|
||||
|
||||
```sh
|
||||
FERESE_TEST_PORTAL=1 \
|
||||
FERESE_TEST_PORTAL_BINARY=target/release/xdg-desktop-portal-ferese \
|
||||
python3 scripts/tests/test_portal_isolated.py
|
||||
```
|
||||
|
||||
Add `FERESE_TEST_PORTAL_CONSENT=1` to exercise the native picker and restricted
|
||||
PipeWire connection. Select the temporary display and click **Share** when
|
||||
prompted. Tests capture only the nested preview and leave host PAM policies and
|
||||
D-Bus activation unchanged.
|
||||
Streams run at up to 30 fps and support hidden or embedded cursors. Capture copies
|
||||
frames through CPU-accessible buffers, so large or multiple streams can use
|
||||
substantial CPU and memory bandwidth.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Confirm that `XDG_CURRENT_DESKTOP` contains `Ferese`, PipeWire is running, and
|
||||
`FERESE_ENABLE_SCREENCOPY` was not set to `0` before launching the session.
|
||||
- Confirm PipeWire and WirePlumber are running.
|
||||
- Confirm `XDG_CURRENT_DESKTOP` includes `Ferese`.
|
||||
- Check that `FERESE_ENABLE_SCREENCOPY` was not set to `0` before session startup.
|
||||
- Check for portal overrides in `~/.config/xdg-desktop-portal/`.
|
||||
|
||||
The installed preference is
|
||||
`/usr/share/xdg-desktop-portal/ferese-portals.conf`. A user override under
|
||||
`~/.config/xdg-desktop-portal/` can take precedence. Its ScreenCast preference
|
||||
should name `ferese`:
|
||||
The installed preference is `/usr/share/xdg-desktop-portal/ferese-portals.conf`.
|
||||
Its ScreenCast entry should select Ferese:
|
||||
|
||||
```ini
|
||||
[preferred]
|
||||
@@ -144,8 +75,7 @@ default=gtk;
|
||||
org.freedesktop.impl.portal.ScreenCast=ferese;
|
||||
```
|
||||
|
||||
If capture dimensions change, stop and start sharing again. Ferese ends the old
|
||||
session instead of feeding incorrectly sized frames to the application.
|
||||
|
||||
For development, `xdg-desktop-portal-ferese --sources` lists displays available
|
||||
on the current `WAYLAND_DISPLAY`. This command does not start a stream.
|
||||
`xdg-desktop-portal-ferese --sources` lists displays on the current
|
||||
`WAYLAND_DISPLAY` without starting a stream. Nested previews do not replace the
|
||||
host desktop's portal environment. See [Development](development.md#portal-checks)
|
||||
for isolated sharing tests.
|
||||
@@ -0,0 +1,106 @@
|
||||
# Shortcuts and gestures
|
||||
|
||||
`Super` is usually the Windows key. These are the built-in defaults. Open
|
||||
**Settings → Shortcuts** to change bindings and gestures or disable the login
|
||||
guide. Your saved bindings can override these defaults.
|
||||
|
||||
## Move and resize with the mouse
|
||||
|
||||
| Action | Result |
|
||||
| --- | --- |
|
||||
| Super + left-button drag on a floating window | Move the window |
|
||||
| Super + right-button drag on a floating window | Resize from the nearest corner |
|
||||
| Super + Shift + Space | Switch the focused window between tiled and floating |
|
||||
|
||||
You can drag from inside the window; a title bar or resize border is not required.
|
||||
To place an app freely, toggle it to floating, then Super-drag it.
|
||||
|
||||
## Focus, move, and resize
|
||||
|
||||
`H`, `J`, `K`, and `L` mean left, down, up, and right.
|
||||
|
||||
| Shortcut | Action |
|
||||
| --- | --- |
|
||||
| Super + H / J / K / L | Focus in that direction |
|
||||
| Super + Shift + H / J / K / L | Move the focused window in that direction |
|
||||
| Super + Ctrl + H / J / K / L | Resize in that direction |
|
||||
| Super + Q | Close the focused window |
|
||||
| Super + F | Maximize or restore the window |
|
||||
| Super + Shift + F | Enter or leave fullscreen |
|
||||
|
||||
Maximize fills the available workspace. Fullscreen also hides the bar and window
|
||||
decorations.
|
||||
|
||||
## Columns and layouts
|
||||
|
||||
| Shortcut | Action |
|
||||
| --- | --- |
|
||||
| Super + R | Cycle column width |
|
||||
| Super + C | Center the focused column |
|
||||
| Super + [ | Place the window in a neighbouring column |
|
||||
| Super + ] | Extract the window into its own column |
|
||||
| Super + M | Switch scrolling / tree layout |
|
||||
| Super + Tab | Open or close overview |
|
||||
|
||||
In scrolling mode, **Super + [** uses the left neighbour when available, otherwise
|
||||
the right. Try it with two terminals to place them vertically in one column.
|
||||
**Super + ]** separates the focused window again.
|
||||
|
||||
In overview, select a workspace to see its windows, then click the window you
|
||||
want. Directional focus keys move selection; Enter activates it and Escape closes
|
||||
overview.
|
||||
|
||||
## Workspaces
|
||||
|
||||
| Shortcut | Action |
|
||||
| --- | --- |
|
||||
| Super + 1–9 | Switch to that workspace |
|
||||
| Super + Shift + 1–9 | Move the window to that workspace |
|
||||
|
||||
Workspaces are created as needed. Selecting one visible on another monitor focuses
|
||||
that monitor.
|
||||
|
||||
## Desktop actions
|
||||
|
||||
| Shortcut | Action |
|
||||
| --- | --- |
|
||||
| Super + Enter | Open the configured terminal (`foot` by default) |
|
||||
| Print Screen | Capture the active monitor and open Satty |
|
||||
| Super + Shift + S | Select a screenshot area and open Satty |
|
||||
| Super + Shift + E | Ask to log out |
|
||||
|
||||
In Satty, Enter saves the edited screenshot and copies it to the clipboard;
|
||||
Escape discards it. See [Configuration](configuration.md#commands-and-bindings)
|
||||
for dependencies and custom screenshot commands.
|
||||
|
||||
## Touchpad gestures
|
||||
|
||||
| Three-finger swipe | Action on release |
|
||||
| --- | --- |
|
||||
| Up / down | Next / previous workspace on this monitor |
|
||||
| Left / right | Focus the window to the right / left |
|
||||
|
||||
Short, diagonal, or cancelled swipes do nothing. Gestures can use the same actions
|
||||
as keyboard bindings, including overview or moving a window. Four- and five-finger
|
||||
bindings are supported too.
|
||||
|
||||
## Add a shortcut
|
||||
|
||||
For example, bind a lock command and use a swipe to open overview:
|
||||
|
||||
```kdl
|
||||
commands {
|
||||
lock "ferese-lock"
|
||||
}
|
||||
binding "Super+Alt+L" "spawn" "lock"
|
||||
binding "Swipe3Up" "toggle-overview"
|
||||
```
|
||||
|
||||
These are examples, not defaults. To disable a built-in binding:
|
||||
|
||||
```kdl
|
||||
binding "Super+Q" disabled=#true
|
||||
```
|
||||
|
||||
See [Commands and bindings](configuration.md#commands-and-bindings) for action
|
||||
names, arguments, and physical-key matching.
|
||||
+16
-60
@@ -1,34 +1,26 @@
|
||||
# Why Ferese
|
||||
|
||||
Omarchy and Ferese come from two different ideas about how a desktop should be
|
||||
built. Omarchy brings existing Linux tools together and configures them as one
|
||||
environment, which gives it access to mature components that already do their
|
||||
jobs well.
|
||||
Ferese combines window management and a desktop shell with one configuration.
|
||||
Settings, the bar, notifications, widgets, authentication prompts, and the lock
|
||||
screen share colors and fonts.
|
||||
|
||||
A setup like that might combine:
|
||||
## Choose how windows fit
|
||||
|
||||
```text
|
||||
Hyprland + bar + launcher + notifications + lock screen + theme scripts
|
||||
```
|
||||
Scrolling columns let you keep windows at useful widths and move through them
|
||||
horizontally. Tree tiling divides the screen into nested splits. Floating windows
|
||||
work alongside either layout, and overview shows windows across workspaces.
|
||||
|
||||
There is nothing wrong with this approach, and being able to replace each part
|
||||
is useful, but those parts still have their own configuration, state, rendering,
|
||||
and lifecycle. Matching their themes can make them look related, while keeping
|
||||
their behavior in sync remains an ongoing part of maintaining the desktop.
|
||||

|
||||
|
||||
With Ferese, we are building the compositor and shell together, so workspaces,
|
||||
layout, focus, outputs, input, and materials all come from the same desktop
|
||||
state. The shell and Settings use first-party interfaces to work with that state
|
||||
instead of reading separate versions of it from several external tools.
|
||||
## Change the desktop together
|
||||
|
||||
This does not mean every Ferese component has to run in one process. It means
|
||||
that the components share the same concepts, configuration, and protocols, so a
|
||||
workspace or surface means the same thing everywhere it appears.
|
||||
Choose a theme in Settings, then adjust the wallpaper, colors, font, corners,
|
||||
and motion. Changes apply live. Window corners and shell corners can be set
|
||||
independently.
|
||||
|
||||
## What this means in practice
|
||||

|
||||
|
||||
You can see the difference in something as simple as corner radius. Ferese has a
|
||||
shared setting for shell surfaces:
|
||||
For example, this changes shell corners:
|
||||
|
||||
```kdl
|
||||
theme {
|
||||
@@ -38,41 +30,5 @@ theme {
|
||||
}
|
||||
```
|
||||
|
||||
Changing that value updates the bar, Control Center, popovers, notifications,
|
||||
widgets, and native lock screen together. Managed windows have their own radius
|
||||
because they are a different kind of surface, but each value still has one clear
|
||||
meaning wherever it is used.
|
||||
|
||||

|
||||
|
||||
In an assembled desktop, making the same visual change may mean editing the
|
||||
window manager, bar CSS, launcher theme, notification daemon, and lock screen
|
||||
config separately, then keeping those values aligned as the setup changes.
|
||||
|
||||
The same difference shows up in how the desktop behaves. Ferese implements
|
||||
scrolling as part of its workspace model, renders blur behind shell surfaces in
|
||||
the compositor, and builds the overview from the real window scene. Focus,
|
||||
fullscreen, workspace geometry, and input all work from the same state rather
|
||||
than waiting for separate tools to catch up with one another.
|
||||
|
||||

|
||||
|
||||
When a window opens, Ferese can handle the result as one transition:
|
||||
|
||||
```text
|
||||
window opens → layout updates → viewport moves → input follows
|
||||
```
|
||||
|
||||
An assembled environment may need to publish a window-manager event, pass it
|
||||
through IPC, run a script, update the bar, and start another animation before
|
||||
the rest of the desktop reflects the change. Each step can be fast, but it is
|
||||
still another boundary that has to be maintained.
|
||||
|
||||
## The tradeoff we are making
|
||||
|
||||
Building more of the desktop ourselves gives Ferese tighter control over how its
|
||||
parts work together, but it also leaves us responsible for more code. Omarchy
|
||||
can rely on mature components from across the Linux desktop ecosystem, while
|
||||
Ferese has to build that same level of maturity over time, and that is a tradeoff
|
||||
we are willing to make to keep the desktop consistent in both behavior and
|
||||
configuration.
|
||||
See [Configuration](configuration.md) for all options, or
|
||||
[Installation](installation.md) to try Ferese in a nested preview.
|
||||
@@ -16,10 +16,13 @@ PAGES = [
|
||||
('why-ferese', 'Why Ferese', ROOT / 'docs/why-ferese.md'),
|
||||
('installation', 'Installation', ROOT / 'docs/installation.md'),
|
||||
('configuration', 'Configuration', ROOT / 'docs/configuration.md'),
|
||||
('shortcuts', 'Shortcuts and gestures', ROOT / 'docs/shortcuts.md'),
|
||||
('desktop-widgets', 'Desktop widgets', ROOT / 'docs/desktop-widgets.md'),
|
||||
('notifications', 'Notifications', ROOT / 'docs/notifications.md'),
|
||||
('locking', 'Native locker', ROOT / 'docs/locking.md'),
|
||||
('locking', 'Lock screen', ROOT / 'docs/locking.md'),
|
||||
('screen-sharing', 'Screen sharing', ROOT / 'docs/screen-sharing.md'),
|
||||
('portals', 'Desktop portals', ROOT / 'docs/portals.md'),
|
||||
('development', 'Development', ROOT / 'docs/development.md'),
|
||||
]
|
||||
md = MarkdownIt('commonmark', {'html': False}).enable('table')
|
||||
OUTPUT.mkdir(parents=True, exist_ok=True)
|
||||
@@ -101,7 +104,7 @@ for page_number, (slug, title, source) in enumerate(PAGES):
|
||||
<div class="docs-layout"><aside class="docs-sidebar"><div class="docs-search" hidden><label class="sr-only" for="docs-search">Search the handbook</label><input id="docs-search" type="search" placeholder="Search the handbook…" autocomplete="off" aria-controls="search-results"><div class="search-results" id="search-results" hidden></div><p class="sr-only" id="search-status" role="status"></p></div><details open><summary>FERESE HANDBOOK</summary><nav aria-label="Documentation">{navigation}</nav></details><div class="sidebar-links"><a href="{REPO}/issues">Report an issue <svg class="link-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M7 17 17 7M7 7h10v10"/></svg></a><a href="../">Back to Ferese ←</a></div></aside>
|
||||
<main class="docs-article" id="main"><div class="breadcrumb"><a href="./">Handbook</a><span aria-hidden="true">/</span><span>{escape(title)}</span></div><article class="prose">{body}</article><a class="edit-link" href="{REPO}/blob/main/{source.relative_to(ROOT)}">View this guide on GitHub <svg class="link-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M7 17 17 7M7 7h10v10"/></svg></a><nav class="docs-pager" aria-label="Previous and next guide">{pager}</nav></main>
|
||||
<aside class="docs-toc" aria-label="On this page">{'<p>ON THIS PAGE</p><nav>' + contents + '</nav>' if contents else ''}</aside></div>
|
||||
<footer class="site-footer page-width"><a class="wordmark" href="../">ferese</a><p>A beautiful, fluid Wayland desktop.</p><a href="{REPO}">Built in the open <svg class="link-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M7 17 17 7M7 7h10v10"/></svg></a></footer></body></html>'''
|
||||
<footer class="site-footer page-width"><a class="wordmark" href="../">ferese</a><p>A Wayland desktop with scrolling layouts.</p><a href="{REPO}">Built in the open <svg class="link-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M7 17 17 7M7 7h10v10"/></svg></a></footer></body></html>'''
|
||||
(OUTPUT / 'docs' / f'{slug}.html').write_text(doc)
|
||||
(OUTPUT / 'docs/search-index.json').write_text(json.dumps(search_index, ensure_ascii=False))
|
||||
print(f'Built website and {len(PAGES)} handbook pages at {OUTPUT}')
|
||||
+1
-3
@@ -2,7 +2,6 @@
|
||||
|
||||
The public site is static HTML and CSS. The handbook is generated from the
|
||||
project's Markdown guides, so website and repository documentation stay in sync.
|
||||
There are no client frameworks, external fonts, or tracking scripts.
|
||||
|
||||
## Local preview
|
||||
|
||||
@@ -18,8 +17,7 @@ site sources or Markdown guides, then refresh the browser.
|
||||
|
||||
- `site/index.html` and `site/styles.css`: homepage and shared visual design.
|
||||
- `site/content/index.md`: handbook introduction.
|
||||
- `docs/{why-ferese,installation,configuration,desktop-widgets,notifications,locking,screen-sharing}.md`:
|
||||
source guides.
|
||||
- `docs/*.md`: guides; published pages are listed in `scripts/build-site.py`.
|
||||
- `scripts/build-site.py`: renders Markdown, resolves links, generates section
|
||||
navigation, previous/next links, and the search index.
|
||||
- `site/app.js`: handbook search and code copying. Reading and navigation work
|
||||
|
||||
+33
-49
@@ -1,69 +1,53 @@
|
||||
# The Ferese handbook
|
||||
# Ferese handbook
|
||||
|
||||
Ferese is a complete Wayland desktop built around personalization. Its custom shell, native Settings, live themes, and flexible layouts work together as one cohesive experience.
|
||||
Ferese is a Linux Wayland desktop with scrolling columns, tree tiling, floating
|
||||
windows, and a shared theme for its desktop tools.
|
||||
|
||||
This handbook covers installing Ferese, finding your way around, and making the desktop your own.
|
||||
## Get started
|
||||
|
||||
[Why Ferese](why-ferese.md) explains why the desktop is designed as one integrated system rather than assembled from separately configured tools.
|
||||
|
||||
## Start with your first session
|
||||
|
||||
1. Read [Installation](installation.md) for dependencies, building, login-manager or TTY startup, and recovery.
|
||||
1. [Install Ferese](installation.md), or try a [nested preview](installation.md#preview-and-logs).
|
||||
2. Open **Control Center → Settings** to choose a theme and configure your desktop.
|
||||
3. Explore the [configuration reference](configuration.md) for layouts, shortcuts, window rules, and displays.
|
||||
3. Use the [configuration reference](configuration.md) for shortcuts, gestures, window rules, and displays.
|
||||
|
||||
Want to try it before switching desktops? The [preview instructions](installation.md#preview-and-logs) cover running Ferese inside an existing Wayland session.
|
||||
## Default shortcuts
|
||||
|
||||
## Find your way around
|
||||
|
||||
Ferese supports scrolling columns, tree tiling, floating windows, and a workspace overview. These are the built-in keyboard shortcuts; all can be changed in Settings.
|
||||
`Super` is usually the Windows key. All these shortcuts can be changed in Settings.
|
||||
|
||||
| Shortcut | Action |
|
||||
| --- | --- |
|
||||
| Super + Enter | Open a terminal |
|
||||
| Super + H / J / K / L | Focus a window |
|
||||
| Super + R | Cycle column width |
|
||||
| Super + Tab | Open workspace and window overview |
|
||||
| Super + H / J / K / L | Focus left / down / up / right |
|
||||
| Super + F | Maximize the window |
|
||||
| Super + Shift + F | Toggle fullscreen |
|
||||
| Super + Tab | Open overview |
|
||||
| Super + M | Switch scrolling / tree layout |
|
||||
| Print Screen | Capture the active monitor and open Satty |
|
||||
| Super + Shift + S | Select a screenshot area |
|
||||
| Super + Shift + E | Ask to log out |
|
||||
|
||||
Three-finger swipes move between workspaces and windows. Open **Control Center → Settings → Shortcuts** to change the defaults or assign gestures to other actions.
|
||||
See [all shortcuts and mouse actions](shortcuts.md), including Super-drag to move
|
||||
and Super-right-drag to resize floating windows.
|
||||
|
||||
## Make it feel like yours
|
||||
Three-finger swipes up/down switch workspaces; left/right focus windows.
|
||||
Change gestures in **Settings → Shortcuts**. The login shortcut guide can be
|
||||
disabled there too.
|
||||
|
||||
Use **Settings** for everyday customization. Choose an appearance preset, change the wallpaper, adjust shell and window corners, or add a clock and sticky notes through [Desktop widgets](desktop-widgets.md).
|
||||
## Desktop guides
|
||||
|
||||
[Native locker](locking.md) covers lock-screen appearance, authentication, and idle locking.
|
||||
- [Desktop widgets](desktop-widgets.md): clocks and sticky notes.
|
||||
- [Notifications](notifications.md): history and Do Not Disturb.
|
||||
- [Lock screen](locking.md): appearance, automatic locking, and display sleep.
|
||||
- [Screen sharing and recording](screen-sharing.md): share an app or display, or save a video.
|
||||
- [Desktop portals](portals.md): integration with applications.
|
||||
|
||||
[Notifications](notifications.md) explains popup cards, history, Do Not Disturb, and app actions.
|
||||
Use Settings or edit `~/.config/ferese/config.kdl`. Changes reload automatically;
|
||||
invalid edits keep the last working configuration.
|
||||
|
||||
If you prefer a text editor, your configuration lives at:
|
||||
## Troubleshooting
|
||||
|
||||
```text
|
||||
~/.config/ferese/config.kdl
|
||||
```
|
||||
See [logs and recovery](installation.md#logout-and-recovery). `feresectl exit`
|
||||
ends the session immediately; `feresectl request-logout` asks for confirmation.
|
||||
|
||||
Ferese reloads changes as you make them. An invalid edit keeps the last working configuration. Settings also preserves a backup of your previous save. See [Saving and validation](configuration.md#saving-and-validation).
|
||||
|
||||
## Share your screen
|
||||
|
||||
Use Ferese’s native display picker to share a monitor with a portal-compatible
|
||||
recording or conferencing app. To save a video directly, click the recording
|
||||
icon in the top bar. See [Screen sharing and recording](screen-sharing.md) for setup, stopping a session, and supported sources.
|
||||
|
||||
## Keep a recovery path
|
||||
|
||||
Keep another desktop session available while testing hardware behavior. Save your work before logging out: `feresectl exit` and **Super + Shift + E** end the current session immediately.
|
||||
|
||||
The [recovery guide](installation.md#logout-and-recovery) explains logs, installed releases, and rollback.
|
||||
|
||||
## Work on Ferese
|
||||
|
||||
Ferese is built in Rust on Smithay. Use release builds when evaluating motion and startup performance. From the repository checkout:
|
||||
|
||||
```sh
|
||||
cargo test --workspace --locked
|
||||
cargo fmt --all --check
|
||||
```
|
||||
|
||||
The [source repository](https://github.com/ferese-wm/ferese) is the place to explore implementation details and report issues. When reporting a problem, include how to reproduce it, whether you used the nested or DRM backend, and relevant logs.
|
||||
Report problems in the [issue tracker](https://github.com/ferese-wm/ferese/issues).
|
||||
Include reproduction steps, whether Ferese ran as a nested preview or a direct
|
||||
session, and relevant logs. Contributors can start with [Development](development.md).
|
||||
+12
-12
@@ -6,15 +6,15 @@
|
||||
<meta name="theme-color" content="#10151c" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Ferese is a beautiful, fluid Wayland desktop made to feel like yours. Explore the desktop, then get started with the documentation."
|
||||
content="Ferese is a Linux Wayland desktop with scrolling layouts, native Settings, and a shared theme."
|
||||
/>
|
||||
<meta
|
||||
property="og:title"
|
||||
content="Ferese — A desktop that feels like yours"
|
||||
content="Ferese — Wayland desktop"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content="A complete Wayland desktop built around personalization."
|
||||
content="A Wayland desktop with scrolling layouts and a shared theme."
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta
|
||||
@@ -22,7 +22,7 @@
|
||||
content="https://ferese-wm.github.io/ferese/assets/ferese-desktop.png"
|
||||
/>
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<title>Ferese — A desktop that feels like yours</title>
|
||||
<title>Ferese — Wayland desktop</title>
|
||||
<link rel="icon" href="assets/ferese.svg" type="image/svg+xml" />
|
||||
<link rel="stylesheet" href="styles.css?v=jetbrains" />
|
||||
</head>
|
||||
@@ -47,11 +47,11 @@
|
||||
<main id="main" class="simple-home">
|
||||
<section class="product-intro page-width">
|
||||
<h1 class="product-tagline">
|
||||
A beautiful, fluid Wayland desktop made to feel like yours.
|
||||
A Wayland desktop with scrolling layouts and a shared theme.
|
||||
</h1>
|
||||
<p class="product-description">
|
||||
A complete Linux desktop with a custom shell, native settings,
|
||||
scrolling and tiling layouts, and live-reloading themes.
|
||||
A Linux desktop with a top bar, Settings,
|
||||
scrolling and tiling layouts, and themes that update live.
|
||||
</p>
|
||||
<div class="product-links">
|
||||
<a class="button" href="docs/installation.html">Install Ferese</a>
|
||||
@@ -93,7 +93,7 @@
|
||||
A menu bar, Control Center, Settings, notifications, and desktop
|
||||
widgets, designed to work together.
|
||||
</p>
|
||||
<a href="docs/why-ferese.html">Why integration matters →</a>
|
||||
<a href="docs/why-ferese.html">Explore Ferese →</a>
|
||||
</article>
|
||||
<article>
|
||||
<h2>Make it yours</h2>
|
||||
@@ -108,7 +108,7 @@
|
||||
<h2>Getting started</h2>
|
||||
<p>
|
||||
The <a href="docs/installation.html">installation guide</a> covers
|
||||
dependencies, setup with any Wayland-capable login manager, and TTY startup. You can also
|
||||
dependencies, login, updates, and recovery. You can also
|
||||
<a href="docs/installation.html#preview-and-logs">preview Ferese</a>
|
||||
inside an existing Wayland session before installing.
|
||||
</p>
|
||||
@@ -116,17 +116,17 @@
|
||||
Share a display with recording and conferencing apps through Ferese’s
|
||||
native screen-sharing portal. Choose what to share and stop at any time.
|
||||
See <a href="docs/screen-sharing.html">screen sharing and recording</a>
|
||||
for setup and current capabilities.
|
||||
for setup and limits.
|
||||
</p>
|
||||
<p>
|
||||
Built in Rust on Smithay. Development happens
|
||||
Find <a href="docs/shortcuts.html">shortcuts and mouse actions</a> in the handbook. Development happens
|
||||
<a href="https://github.com/ferese-wm/ferese">on GitHub</a>.
|
||||
</p>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="site-footer page-width">
|
||||
<a class="wordmark" href="./">ferese</a>
|
||||
<p>A beautiful, fluid Wayland desktop.</p>
|
||||
<p>A Wayland desktop with scrolling layouts.</p>
|
||||
<a href="docs/">Read the handbook <svg class="link-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M7 17 17 7M7 7h10v10"/></svg></a>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
Reference in new issue
Block a user