desktop.md RawHistoryFolder

Desktop integration

Running commands

spawn binds, startup and terminal run a program directly, without a shell. The line is split on spaces: the first word is the program (from PATH or a full path), the rest are its arguments. ; separates several commands, which all start at once.

bind.ctrl+cmd+space = spawn fuzzel
startup = waybar; mako; wl-paste --watch cliphist store

Pipes, &&, redirections, $VARIABLES, ~ and quotes are passed as plain text. For those, write a script in your PATH and run it:

#!/bin/sh
# ~/.local/bin/screenshot-main
nefercap screenshot -output DP-1 -file "$HOME/Pictures/$(date +%F-%T).png"
bind.cmd+shift+p = spawn screenshot-main

Programs started by NeferWL get WAYLAND_DISPLAY, DISPLAY and NEFERWL_STATE. startup changes apply at the next session.

Clipboard

The clipboard, primary selection (middle-click paste) and clipboard managers work. A cliphist history:

startup = wl-paste --watch cliphist store
bind.cmd+v = spawn cliphist-pick
#!/bin/sh
# ~/.local/bin/cliphist-pick
cliphist list | fuzzel --dmenu | cliphist decode | wl-copy

Drag and drop works between clients: the surface under the pointer gets the offer, the drop and the chosen action (copy, move or ask, from the modifiers the clients read), and the drag icon follows the cursor. Escape, a refused drop, a dying source or the session lock cancel the drag.

Input methods

fcitx5 and IBus work through zwp_input_method_v2. Start one at session start:

startup = fcitx5 -d

Candidate popups are not drawn yet.

X11 apps

By default, X11 apps such as Steam run through xwayland-satellite 0.7+, found in PATH. NeferWL starts it when the first X11 app connects; do not start it yourself.

xwayland = off   # no X11 support

With xwayland = builtin (experimental), neferwl starts Xwayland itself and manages X11 windows: they tile, take focus and close like Wayland windows. Menus, popups and tooltips of X11 apps are shown above their window and do not take the keyboard focus. X11 apps get the cursor theme (XCURSOR_THEME), cursor size (XCURSOR_SIZE) and DPI through XSETTINGS, always announced as scale 1 (96 dpi) because X11 apps see logical sizes and neferwl upscales their windows (Gtk/CursorThemeName, Gtk/CursorThemeSize, Xft/DPI, Gdk/WindowScalingFactor, Gdk/UnscaledDPI; xwayland.xsettings = off to disable), and the X background shows the themed arrow. The clipboard and the primary selection work between X11 and Wayland apps in both directions, for text; large copies are transferred in chunks (INCR). While the session is locked, no selection data crosses.

Games with builtin:

  • Fullscreen: an X11 window can ask for fullscreen (_NET_WM_STATE_FULLSCREEN) and leave it again; toggle-fullscreen works too. A window that maps with the fullscreen state already set (games do) opens fullscreen in a column of its own, focused, even if its size is fixed. A request made within 1 second after the map is ignored, so a launcher that remembers a fullscreen size does not cover the windows it opens next. The app can ask again later.
  • Output: a window that opens exactly at one output's area opens on that output, and its fullscreen fills it.
  • Keyboard grab: an X11 app that grabs the keyboard inhibits the compositor binds only while it is focused and fullscreen; a windowed app cannot lock the binds. There is no escape bind, as with Wayland shortcut inhibitors; leave by unfullscreening from the app or switching away with the mouse.
  • Pointer: mouse-look works through relative pointer and pointer constraints.
  • App ID: Proton windows are named steam_app_<id>; match them with a window rule.
  • Bypass hint: _NET_WM_BYPASS_COMPOSITOR is read but changes nothing; direct scanout is chosen from the window state.

Session locking

NeferWL supports ext-session-lock-v1 with an external locker such as swaylock or hyprlock. The locker checks the password; NeferWL hides the desktop and blocks input.

While locked

  • Only the locker gets input. Binds, clipboard requests and new captures are refused.
  • Outputs show black and the locker's surfaces only.
  • Running captures stop.
  • Ctrl+Alt+Backspace is disabled. VT switching still works.
  • A locker that uses a screenshot as background (hyprlock screenshot, swaylock-effects --screenshots) must be in the capture allowlist.

The locker is told locked only once every output shows a protected frame or is off.

If the locker dies

The session stays locked and black. Start a new locker to take over. There is no emergency unlock key and no timeout.

A locker that exits right after unlocking must do a Wayland roundtrip first, or its exit counts as a crash and the session stays locked.

Limits

  • NeferWL does not authenticate: no PAM, no stored credentials.
  • Any process running as your user can start its own locker and unlock.
  • Clipboard data and window contents a client received before the lock stay with that client.
  • The state file is not cleared while locked.

Screen capture

nefercap, grim and screen sharing through xdg-desktop-portal-gnome work out of the box. Other tools must be added to the allowlist. See Screen capture.

Idle and screen off

swayidle and wlopm turn the screens off after a delay:

startup = swayidle -w timeout 300 wlopm-off resume wlopm-on
#!/bin/sh
# ~/.local/bin/wlopm-off (wlopm-on is the same with --on)
exec wlopm --off '*'

Video players, games and browsers keep the screens on while they ask to, through Wayland or D-Bus (org.freedesktop.ScreenSaver).

Power keys

NeferWL stops logind from acting on the power, suspend, hibernate and reboot keys. They do nothing unless you bind them:

bind.XF86PowerOff = spawn systemctl suspend
bind.XF86Suspend = spawn systemctl hibernate
Key Bind name
Power XF86PowerOff
Sleep XF86Sleep
Suspend XF86Suspend
Reboot code:408

The lid switch is still handled by logind.

Bars

Waybar 0.13+ (ext/workspaces) and ironbar show and switch workspaces. Taskbars can list, focus and close windows.

Workspace IDs are name:<name> for named workspaces, stable across launches. Numbered workspaces get a random prefix per launch, so do not save settings keyed on them.

State for scripts

NeferWL writes its state as JSON to $XDG_RUNTIME_DIR/neferwl/<wayland socket>.json, also given to started programs as $NEFERWL_STATE. It lists outputs, workspaces, the focused window, and every window with its app ID, PID, workspace, column and row.

The workspaces list holds every workspace with its visible flag, its columns and the windows in them, each with x, y, width and height in logical pixels of its output. The file is written at most once per second.

neferwl state                        # the whole state
neferwl state output-of "$PID"       # the output showing that process's window
neferwl state | jq '[.windows[] | select(.hidden)] | length'   # windows in hidden stashes
neferwl state | jq '.workspaces[] | select(.visible) | .columns[] | .width'   # column widths on screen
source
1# Desktop integration
2
3## Running commands
4
5`spawn` binds, `startup` and `terminal` run a program directly, **without a shell**. The line is split on spaces: the first word is the program (from `PATH` or a full path), the rest are its arguments. `;` separates several commands, which all start at once.
6
7```text
8bind.ctrl+cmd+space = spawn fuzzel
9startup = waybar; mako; wl-paste --watch cliphist store
10```
11
12Pipes, `&&`, redirections, `$VARIABLES`, `~` and quotes are passed as plain text. For those, write a script in your `PATH` and run it:
13
14```sh
15#!/bin/sh
16# ~/.local/bin/screenshot-main
17nefercap screenshot -output DP-1 -file "$HOME/Pictures/$(date +%F-%T).png"
18```
19
20```text
21bind.cmd+shift+p = spawn screenshot-main
22```
23
24Programs started by NeferWL get `WAYLAND_DISPLAY`, `DISPLAY` and `NEFERWL_STATE`. `startup` changes apply at the next session.
25
26## Clipboard
27
28The clipboard, primary selection (middle-click paste) and clipboard managers work. A [cliphist](https://github.com/sentriz/cliphist) history:
29
30```text
31startup = wl-paste --watch cliphist store
32bind.cmd+v = spawn cliphist-pick
33```
34
35```sh
36#!/bin/sh
37# ~/.local/bin/cliphist-pick
38cliphist list | fuzzel --dmenu | cliphist decode | wl-copy
39```
40
41Drag and drop works between clients: the surface under the pointer gets the offer, the drop and the chosen action (copy, move or ask, from the modifiers the clients read), and the drag icon follows the cursor. Escape, a refused drop, a dying source or the session lock cancel the drag.
42
43## Input methods
44
45[fcitx5](https://fcitx-im.org) and IBus work through `zwp_input_method_v2`. Start one at session start:
46
47```text
48startup = fcitx5 -d
49```
50
51Candidate popups are not drawn yet.
52
53## X11 apps
54
55By default, X11 apps such as Steam run through [xwayland-satellite](https://github.com/Supreeeme/xwayland-satellite) 0.7+, found in `PATH`. NeferWL starts it when the first X11 app connects; do not start it yourself.
56
57```text
58xwayland = off   # no X11 support
59```
60
61With `xwayland = builtin` (experimental), neferwl starts `Xwayland` itself and manages X11 windows: they tile, take focus and close like Wayland windows. Menus, popups and tooltips of X11 apps are shown above their window and do not take the keyboard focus. X11 apps get the cursor theme (`XCURSOR_THEME`), cursor size (`XCURSOR_SIZE`) and DPI through XSETTINGS, always announced as scale 1 (96 dpi) because X11 apps see logical sizes and neferwl upscales their windows (`Gtk/CursorThemeName`, `Gtk/CursorThemeSize`, `Xft/DPI`, `Gdk/WindowScalingFactor`, `Gdk/UnscaledDPI`; `xwayland.xsettings = off` to disable), and the X background shows the themed arrow. The clipboard and the primary selection work between X11 and Wayland apps in both directions, for text; large copies are transferred in chunks (INCR). While the session is locked, no selection data crosses.
62
63Games with `builtin`:
64
65- **Fullscreen:** an X11 window can ask for fullscreen (`_NET_WM_STATE_FULLSCREEN`) and leave it again; `toggle-fullscreen` works too. A window that maps with the fullscreen state already set (games do) opens fullscreen in a column of its own, focused, even if its size is fixed. A request made within 1 second *after* the map is ignored, so a launcher that remembers a fullscreen size does not cover the windows it opens next. The app can ask again later.
66- **Output:** a window that opens exactly at one output's area opens on that output, and its fullscreen fills it.
67- **Keyboard grab:** an X11 app that grabs the keyboard inhibits the compositor binds only while it is focused and fullscreen; a windowed app cannot lock the binds. There is no escape bind, as with Wayland shortcut inhibitors; leave by unfullscreening from the app or switching away with the mouse.
68- **Pointer:** mouse-look works through relative pointer and pointer constraints.
69- **App ID:** Proton windows are named `steam_app_<id>`; match them with a [window rule](config.md#window-rules).
70- **Bypass hint:** `_NET_WM_BYPASS_COMPOSITOR` is read but changes nothing; direct scanout is chosen from the window state.
71
72## Session locking
73
74NeferWL supports `ext-session-lock-v1` with an external locker such as swaylock or hyprlock. The locker checks the password; NeferWL hides the desktop and blocks input.
75
76### While locked
77
78- Only the locker gets input. Binds, clipboard requests and new captures are refused.
79- Outputs show black and the locker's surfaces only.
80- Running captures stop.
81- `Ctrl+Alt+Backspace` is disabled. VT switching still works.
82- A locker that uses a screenshot as background (hyprlock `screenshot`, swaylock-effects `--screenshots`) must be in the [capture allowlist](capture.md#the-allowlist).
83
84The locker is told `locked` only once every output shows a protected frame or is off.
85
86### If the locker dies
87
88The session stays locked and black. Start a new locker to take over. There is no emergency unlock key and no timeout.
89
90A locker that exits right after unlocking must do a Wayland roundtrip first, or its exit counts as a crash and the session stays locked.
91
92### Limits
93
94- NeferWL does not authenticate: no PAM, no stored credentials.
95- Any process running as your user can start its own locker and unlock.
96- Clipboard data and window contents a client received before the lock stay with that client.
97- The [state file](desktop.md#state-for-scripts) is not cleared while locked.
98
99## Screen capture
100
101nefercap, `grim` and screen sharing through `xdg-desktop-portal-gnome` work out of the box. Other tools must be added to the allowlist. See [Screen capture](capture.md).
102
103## Idle and screen off
104
105[swayidle](https://github.com/swaywm/swayidle) and [wlopm](https://git.sr.ht/~leon_plickat/wlopm) turn the screens off after a delay:
106
107```text
108startup = swayidle -w timeout 300 wlopm-off resume wlopm-on
109```
110
111```sh
112#!/bin/sh
113# ~/.local/bin/wlopm-off (wlopm-on is the same with --on)
114exec wlopm --off '*'
115```
116
117Video players, games and browsers keep the screens on while they ask to, through Wayland or D-Bus (`org.freedesktop.ScreenSaver`).
118
119## Power keys
120
121NeferWL stops logind from acting on the power, suspend, hibernate and reboot keys. They do nothing unless you bind them:
122
123```text
124bind.XF86PowerOff = spawn systemctl suspend
125bind.XF86Suspend = spawn systemctl hibernate
126```
127
128| Key | Bind name |
129|---|---|
130| Power | `XF86PowerOff` |
131| Sleep | `XF86Sleep` |
132| Suspend | `XF86Suspend` |
133| Reboot | `code:408` |
134
135The lid switch is still handled by logind.
136
137## Bars
138
139Waybar 0.13+ (`ext/workspaces`) and ironbar show and switch workspaces. Taskbars can list, focus and close windows.
140
141Workspace IDs are `name:<name>` for named workspaces, stable across launches. Numbered workspaces get a random prefix per launch, so do not save settings keyed on them.
142
143## State for scripts
144
145NeferWL writes its state as JSON to `$XDG_RUNTIME_DIR/neferwl/<wayland socket>.json`, also given to started programs as `$NEFERWL_STATE`. It lists outputs, workspaces, the focused window, and every window with its app ID, PID, workspace, column and row.
146
147The `workspaces` list holds every workspace with its `visible` flag, its columns and the windows in them, each with `x`, `y`, `width` and `height` in logical pixels of its output. The file is written at most once per second.
148
149```sh
150neferwl state                        # the whole state
151neferwl state output-of "$PID"       # the output showing that process's window
152neferwl state | jq '[.windows[] | select(.hidden)] | length'   # windows in hidden stashes
153neferwl state | jq '.workspaces[] | select(.visible) | .columns[] | .width'   # column widths on screen
154```

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 23

Tags 10

↑↓ moveenter openesc close