detached a5764bd

feat(captureallow): allow xdg-desktop-portal-gnome instead of the wlr portal

commit
a5764bdc8540ac73589a21d8649ca9055415f2d4
author
brice · · 2026-10-14 20:37 UTC
committer
brice · · 2026-10-14 21:39 UTC
parent
c050b9a
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
6 files · +14 -12
M examples/capture-allow +4 -4
@@ -5,8 +5,8 @@
55 #
66 # /usr/bin/grim
77 # /usr/bin/nefercap
8-# /usr/lib/xdg-desktop-portal-wlr
9-# /usr/libexec/xdg-desktop-portal-wlr
8+# /usr/lib/xdg-desktop-portal-gnome
9+# /usr/libexec/xdg-desktop-portal-gnome
1010 #
1111 # To allow a tool installed elsewhere, copy this file to
1212 # /etc/neferwl/capture-allow as root and add its path. The file REPLACES the
@@ -27,5 +27,5 @@
2727 # would then be allowed to capture.
2828 /usr/bin/grim
2929 /usr/bin/nefercap
30-/usr/lib/xdg-desktop-portal-wlr
31-/usr/libexec/xdg-desktop-portal-wlr
30+/usr/lib/xdg-desktop-portal-gnome
31+/usr/libexec/xdg-desktop-portal-gnome
@@ -5,8 +5,8 @@
5 #5 #
6 # /usr/bin/grim6 # /usr/bin/grim
7 # /usr/bin/nefercap7 # /usr/bin/nefercap
8-# /usr/lib/xdg-desktop-portal-wlr8+# /usr/lib/xdg-desktop-portal-gnome
9-# /usr/libexec/xdg-desktop-portal-wlr9+# /usr/libexec/xdg-desktop-portal-gnome
10 #10 #
11 # To allow a tool installed elsewhere, copy this file to11 # To allow a tool installed elsewhere, copy this file to
12 # /etc/neferwl/capture-allow as root and add its path. The file REPLACES the12 # /etc/neferwl/capture-allow as root and add its path. The file REPLACES the
@@ -27,5 +27,5 @@
27 # would then be allowed to capture.27 # would then be allowed to capture.
28 /usr/bin/grim28 /usr/bin/grim
29 /usr/bin/nefercap29 /usr/bin/nefercap
30-/usr/lib/xdg-desktop-portal-wlr30+/usr/lib/xdg-desktop-portal-gnome
31-/usr/libexec/xdg-desktop-portal-wlr31+/usr/libexec/xdg-desktop-portal-gnome
M internal/adapters/captureallow/policy.go +2 -2
@@ -45,8 +45,8 @@ func Builtin() *Policy {
4545 builtin := [...]string{
4646 "/usr/bin/grim",
4747 "/usr/bin/nefercap",
48- "/usr/lib/xdg-desktop-portal-wlr",
49- "/usr/libexec/xdg-desktop-portal-wlr",
48+ "/usr/lib/xdg-desktop-portal-gnome",
49+ "/usr/libexec/xdg-desktop-portal-gnome",
5050 }
5151 p := &Policy{mode: ModeList, exes: make(map[string]struct{}, len(builtin))}
5252 for _, e := range builtin {
@@ -45,8 +45,8 @@ func Builtin() *Policy {
45 builtin := [...]string{45 builtin := [...]string{
46 "/usr/bin/grim",46 "/usr/bin/grim",
47 "/usr/bin/nefercap",47 "/usr/bin/nefercap",
48- "/usr/lib/xdg-desktop-portal-wlr",48+ "/usr/lib/xdg-desktop-portal-gnome",
49- "/usr/libexec/xdg-desktop-portal-wlr",49+ "/usr/libexec/xdg-desktop-portal-gnome",
50 }50 }
51 p := &Policy{mode: ModeList, exes: make(map[string]struct{}, len(builtin))}51 p := &Policy{mode: ModeList, exes: make(map[string]struct{}, len(builtin))}
52 for _, e := range builtin {52 for _, e := range builtin {
M internal/adapters/captureallow/policy_test.go +3 -3
@@ -16,8 +16,8 @@ func TestParse(t *testing.T) {
1616 errLine int
1717 wantFail bool
1818 }{
19- {name: "paths comments blanks", in: "# header\n\n/usr/bin/grim\n /usr/lib/xdg-desktop-portal-wlr \n\t# indented comment\n/opt/a#b\n",
20- mode: ModeList, allowed: []string{"/usr/bin/grim", "/usr/lib/xdg-desktop-portal-wlr", "/opt/a#b"}, refused: []string{"/usr/bin/grim2", "/usr/bin", "grim", ""}},
19+ {name: "paths comments blanks", in: "# header\n\n/usr/bin/grim\n /usr/lib/xdg-desktop-portal-gnome \n\t# indented comment\n/opt/a#b\n",
20+ mode: ModeList, allowed: []string{"/usr/bin/grim", "/usr/lib/xdg-desktop-portal-gnome", "/opt/a#b"}, refused: []string{"/usr/bin/grim2", "/usr/bin", "grim", ""}},
2121 {name: "cleaned", in: "/usr//bin/../bin/grim\n", mode: ModeList, allowed: []string{"/usr/bin/grim"}},
2222 {name: "no trailing newline", in: "/a/b", mode: ModeList, allowed: []string{"/a/b"}},
2323 {name: "empty file allows nothing", in: "", mode: ModeList, refused: []string{"/usr/bin/grim"}},
@@ -75,7 +75,7 @@ func TestParseTooLarge(t *testing.T) {
7575
7676 func TestBuiltin(t *testing.T) {
7777 p := Builtin()
78- want := []string{"/usr/bin/grim", "/usr/bin/nefercap", "/usr/lib/xdg-desktop-portal-wlr", "/usr/libexec/xdg-desktop-portal-wlr"}
78+ want := []string{"/usr/bin/grim", "/usr/bin/nefercap", "/usr/lib/xdg-desktop-portal-gnome", "/usr/libexec/xdg-desktop-portal-gnome"}
7979 if p.Mode() != ModeList || p.Len() != len(want) {
8080 t.Fatalf("mode %v, len %d", p.Mode(), p.Len())
8181 }
@@ -16,8 +16,8 @@ func TestParse(t *testing.T) {
16 errLine int16 errLine int
17 wantFail bool17 wantFail bool
18 }{18 }{
19- {name: "paths comments blanks", in: "# header\n\n/usr/bin/grim\n /usr/lib/xdg-desktop-portal-wlr \n\t# indented comment\n/opt/a#b\n",19+ {name: "paths comments blanks", in: "# header\n\n/usr/bin/grim\n /usr/lib/xdg-desktop-portal-gnome \n\t# indented comment\n/opt/a#b\n",
20- mode: ModeList, allowed: []string{"/usr/bin/grim", "/usr/lib/xdg-desktop-portal-wlr", "/opt/a#b"}, refused: []string{"/usr/bin/grim2", "/usr/bin", "grim", ""}},20+ mode: ModeList, allowed: []string{"/usr/bin/grim", "/usr/lib/xdg-desktop-portal-gnome", "/opt/a#b"}, refused: []string{"/usr/bin/grim2", "/usr/bin", "grim", ""}},
21 {name: "cleaned", in: "/usr//bin/../bin/grim\n", mode: ModeList, allowed: []string{"/usr/bin/grim"}},21 {name: "cleaned", in: "/usr//bin/../bin/grim\n", mode: ModeList, allowed: []string{"/usr/bin/grim"}},
22 {name: "no trailing newline", in: "/a/b", mode: ModeList, allowed: []string{"/a/b"}},22 {name: "no trailing newline", in: "/a/b", mode: ModeList, allowed: []string{"/a/b"}},
23 {name: "empty file allows nothing", in: "", mode: ModeList, refused: []string{"/usr/bin/grim"}},23 {name: "empty file allows nothing", in: "", mode: ModeList, refused: []string{"/usr/bin/grim"}},
@@ -75,7 +75,7 @@ func TestParseTooLarge(t *testing.T) {
75 75
76 func TestBuiltin(t *testing.T) {76 func TestBuiltin(t *testing.T) {
77 p := Builtin()77 p := Builtin()
78- want := []string{"/usr/bin/grim", "/usr/bin/nefercap", "/usr/lib/xdg-desktop-portal-wlr", "/usr/libexec/xdg-desktop-portal-wlr"}78+ want := []string{"/usr/bin/grim", "/usr/bin/nefercap", "/usr/lib/xdg-desktop-portal-gnome", "/usr/libexec/xdg-desktop-portal-gnome"}
79 if p.Mode() != ModeList || p.Len() != len(want) {79 if p.Mode() != ModeList || p.Len() != len(want) {
80 t.Fatalf("mode %v, len %d", p.Mode(), p.Len())80 t.Fatalf("mode %v, len %d", p.Mode(), p.Len())
81 }81 }
M internal/adapters/wayland/captureauth.go +3 -1
@@ -14,7 +14,9 @@ import (
1414 // capture sessions and frames, whatever their source (output, output region
1515 // or workspace), and the attach of a layer surface to a capture exclusion. A
1616 // refused client gets the failure its protocol defines (failed, or stopped
17-// for a session) and nothing is captured or flashed. In order:
17+// for a session) and nothing is captured or flashed. The same executable
18+// allowlist also gates the D-Bus screencast callers (adapters/screencast). In
19+// order:
1820 //
1921 // 1. While the session is protected (ext-session-lock) no client may
2022 // capture, so nothing of the locked session reaches a buffer.
@@ -14,7 +14,9 @@ import (
14 // capture sessions and frames, whatever their source (output, output region14 // capture sessions and frames, whatever their source (output, output region
15 // or workspace), and the attach of a layer surface to a capture exclusion. A15 // or workspace), and the attach of a layer surface to a capture exclusion. A
16 // refused client gets the failure its protocol defines (failed, or stopped16 // refused client gets the failure its protocol defines (failed, or stopped
17-// for a session) and nothing is captured or flashed. In order:17+// for a session) and nothing is captured or flashed. The same executable
18+// allowlist also gates the D-Bus screencast callers (adapters/screencast). In
19+// order:
18 //20 //
19 // 1. While the session is protected (ext-session-lock) no client may21 // 1. While the session is protected (ext-session-lock) no client may
20 // capture, so nothing of the locked session reaches a buffer.22 // capture, so nothing of the locked session reaches a buffer.
M internal/adapters/wayland/extforeigntoplevel.go +1 -1
@@ -10,7 +10,7 @@ import (
1010 )
1111
1212 // ext-foreign-toplevel-list lists mapped toplevels, read-only: title, app_id
13-// and a stable identifier. xdg-desktop-portal-wlr lists the windows it can
13+// and a stable identifier. Screen-sharing portals list the windows they can
1414 // share with it, and ext_foreign_toplevel_image_capture_source_manager_v1
1515 // takes its handles (window capture, imagecopy.go). It follows the same
1616 // window state and session-protection rules as wlr-foreign-toplevel.
@@ -10,7 +10,7 @@ import (
10 )10 )
11 11
12 // ext-foreign-toplevel-list lists mapped toplevels, read-only: title, app_id12 // ext-foreign-toplevel-list lists mapped toplevels, read-only: title, app_id
13-// and a stable identifier. xdg-desktop-portal-wlr lists the windows it can13+// and a stable identifier. Screen-sharing portals list the windows they can
14 // share with it, and ext_foreign_toplevel_image_capture_source_manager_v114 // share with it, and ext_foreign_toplevel_image_capture_source_manager_v1
15 // takes its handles (window capture, imagecopy.go). It follows the same15 // takes its handles (window capture, imagecopy.go). It follows the same
16 // window state and session-protection rules as wlr-foreign-toplevel.16 // window state and session-protection rules as wlr-foreign-toplevel.
M internal/adapters/wayland/imagecopy.go +1 -1
@@ -587,7 +587,7 @@ type captureExtFrame struct {
587587 // A frame whose target is briefly unavailable (not active yet, rendered off
588588 // screen by another session, its indicator or exclusion not on screen yet,
589589 // a renderer slot busy) is tried again rather than failed: failed(unknown)
590-// ends the whole screencast in clients such as xdg-desktop-portal-wlr. Only
590+// ends the whole screencast in screen-sharing clients. Only
591591 // a stopped session, a refused client or a wrong buffer fail at once.
592592 const (
593593 captureRetryEvery = 16 * time.Millisecond
@@ -587,7 +587,7 @@ type captureExtFrame struct {
587 // A frame whose target is briefly unavailable (not active yet, rendered off587 // A frame whose target is briefly unavailable (not active yet, rendered off
588 // screen by another session, its indicator or exclusion not on screen yet,588 // screen by another session, its indicator or exclusion not on screen yet,
589 // a renderer slot busy) is tried again rather than failed: failed(unknown)589 // a renderer slot busy) is tried again rather than failed: failed(unknown)
590-// ends the whole screencast in clients such as xdg-desktop-portal-wlr. Only590+// ends the whole screencast in screen-sharing clients. Only
591 // a stopped session, a refused client or a wrong buffer fail at once.591 // a stopped session, a refused client or a wrong buffer fail at once.
592 const (592 const (
593 captureRetryEvery = 16 * time.Millisecond593 captureRetryEvery = 16 * time.Millisecond

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 25

Tags 10

↑↓ moveenter openesc close