layershell_preload.go RawHistoryFolder
1package bootstrap
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7)
8
9const layerShellLibrarySubstring = "libgtk4-layer-shell"
10
11var layerShellLibraryCandidates = []string{
12 "/usr/lib/libgtk4-layer-shell.so.0",
13 "/usr/lib64/libgtk4-layer-shell.so.0",
14 "/usr/lib/aarch64-linux-gnu/libgtk4-layer-shell.so.0",
15 "/usr/lib/x86_64-linux-gnu/libgtk4-layer-shell.so.0",
16 "/lib/x86_64-linux-gnu/libgtk4-layer-shell.so.0",
17}
18
19func ShouldPreloadLayerShell(env map[string]string) bool {
20 if env["WAYLAND_DISPLAY"] == "" {
21 return false
22 }
23
24 return !LayerShellPreloadPresent(env)
25}
26
27func LayerShellPreloadPresent(env map[string]string) bool {
28 return strings.Contains(env["LD_PRELOAD"], layerShellLibrarySubstring)
29}
30
31func CurrentEnvMap() map[string]string {
32 env := make(map[string]string)
33 for _, entry := range os.Environ() {
34 key, value, ok := strings.Cut(entry, "=")
35 if !ok {
36 continue
37 }
38 env[key] = value
39 }
40 return env
41}
42
43func FindLayerShellLibrary(env map[string]string, exists func(path string) bool) string {
44 for _, path := range layerShellLibrarySearchPaths(env) {
45 if exists(path) {
46 return path
47 }
48 }
49
50 return ""
51}
52
53func LayerShellLibraryPath() string {
54 return FindLayerShellLibrary(CurrentEnvMap(), func(path string) bool {
55 info, err := os.Stat(filepath.Clean(path))
56 return err == nil && !info.IsDir()
57 })
58}
59
60func layerShellLibrarySearchPaths(env map[string]string) []string {
61 paths := make([]string, 0, len(layerShellLibraryCandidates)+4)
62 paths = append(paths, layerShellLibraryCandidates...)
63
64 seen := make(map[string]struct{}, len(paths))
65 for _, path := range paths {
66 seen[path] = struct{}{}
67 }
68
69 for _, dir := range strings.FieldsFunc(env["LD_LIBRARY_PATH"], func(r rune) bool { return r == ':' }) {
70 if dir == "" {
71 continue
72 }
73 candidate := filepath.Join(dir, "libgtk4-layer-shell.so.0")
74 if _, ok := seen[candidate]; ok {
75 continue
76 }
77 seen[candidate] = struct{}{}
78 paths = append(paths, candidate)
79 }
80
81 return paths
82}
83
84func LayerShellPreloadEnv(env map[string]string, libraryPath string) map[string]string {
85 cloned := make(map[string]string, len(env)+1)
86 for key, value := range env {
87 cloned[key] = value
88 }
89
90 if libraryPath == "" {
91 return cloned
92 }
93
94 if current := cloned["LD_PRELOAD"]; current != "" {
95 cloned["LD_PRELOAD"] = libraryPath + " " + current
96 return cloned
97 }
98
99 cloned["LD_PRELOAD"] = libraryPath
100 return cloned
101}