diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07c477a --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Binaries +remote-touchpad + +# Systemd service state +.remote-touchpad.service.state + +# Logs and run files +.rts-log + +# Environment files +.env \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d3ec422..e59454c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 1.5.4 (2026-08-02) + +* Improve X11 keyboard input +* Update dependencies + ## 1.5.3 (2025-12-24) * Update dependencies diff --git a/README.md b/README.md index fd05b7a..e039950 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,35 @@ Supports Flatpak's RemoteDesktop portal (for Wayland), Windows and X11. go install github.com/unrud/remote-touchpad@latest ``` +## Linux User Service Installation + +To install remote-touchpad as a user-specific systemd service (no root access required): + +1. Clone the repository and navigate to the project directory: + + ```sh + git clone https://github.com/Unrud/remote-touchpad.git + cd remote-touchpad + ``` + +2. Install the service using the provided wrapper script (no sudo required): + + ```sh + ./rts install + ``` + +3. Access the service: + + * View service status: `./rts status` + * Get URL: `./rts url` + * View logs: `./rts log` + * Stop service: `./rts stop` + * Start service: `./rts start` + * Restart service: `./rts restart` + * Uninstall: `./rts uninstall` + +The service will run in the background and maintain a persistent connection with URL and QR code accessible via the `url` command. + ## Screenshots ![screenshot 1](https://raw.githubusercontent.com/Unrud/remote-touchpad/master/screenshots/1.png) diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index 14b1574..113ef4d 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -23,6 +23,14 @@ Unrud + + +
    +
  • Improve X11 keyboard input
  • +
  • Update dependencies
  • +
+
+
    @@ -365,16 +373,16 @@ - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.3/screenshots/1.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.4/screenshots/1.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.3/screenshots/2.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.4/screenshots/2.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.3/screenshots/3.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.4/screenshots/3.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.3/screenshots/4.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.4/screenshots/4.png diff --git a/flatpak/com.github.unrud.RemoteTouchpad.yaml b/flatpak/com.github.unrud.RemoteTouchpad.yaml index 48eef40..239160e 100644 --- a/flatpak/com.github.unrud.RemoteTouchpad.yaml +++ b/flatpak/com.github.unrud.RemoteTouchpad.yaml @@ -17,8 +17,8 @@ modules: path: .. - type: git url: https://github.com/godbus/dbus - tag: v5.2.1 - commit: 20d95a3d9a57a5cb72cbdafb3fd9ecb6d2ccd038 + tag: v5.2.2 + commit: a8ac15ba63645f02ffd57f4b443203279ab40b30 dest: vendor/github.com/godbus/dbus/v5 - type: git url: https://github.com/skip2/go-qrcode @@ -26,13 +26,13 @@ modules: dest: vendor/github.com/skip2/go-qrcode - type: git url: https://github.com/golang/net - tag: v0.48.0 - commit: 35e1306bddd863f360fb94480c5fed84229953f0 + tag: v0.57.0 + commit: b8f09f6f062ceb4531b7af4bd17a5c8fe9c4b2b5 dest: vendor/golang.org/x/net - type: git url: https://github.com/golang/sys - tag: v0.39.0 - commit: 08e54827f6706016347e1e4f4866b84126842b20 + tag: v0.47.0 + commit: 9e7e939dcafac07e8ab4cffa6e5fc74908413f00 dest: vendor/golang.org/x/sys - type: file path: modules.txt diff --git a/flatpak/modules.txt b/flatpak/modules.txt index fec832d..6092904 100644 --- a/flatpak/modules.txt +++ b/flatpak/modules.txt @@ -1,7 +1,7 @@ # github.com/bendahl/uinput v1.7.0 ## explicit; go 1.13 github.com/bendahl/uinput -# github.com/godbus/dbus/v5 v5.2.1 +# github.com/godbus/dbus/v5 v5.2.2 ## explicit; go 1.20 github.com/godbus/dbus/v5 # github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e @@ -9,9 +9,9 @@ github.com/godbus/dbus/v5 github.com/skip2/go-qrcode github.com/skip2/go-qrcode/bitset github.com/skip2/go-qrcode/reedsolomon -# golang.org/x/net v0.48.0 -## explicit; go 1.24.0 +# golang.org/x/net v0.57.0 +## explicit; go 1.25.0 golang.org/x/net/websocket -# golang.org/x/sys v0.39.0 -## explicit; go 1.24.0 +# golang.org/x/sys v0.47.0 +## explicit; go 1.25.0 golang.org/x/sys/unix diff --git a/go.mod b/go.mod index ea1c480..5afd19d 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,9 @@ go 1.25.5 require ( github.com/bendahl/uinput v1.7.0 - github.com/godbus/dbus/v5 v5.2.1 + github.com/godbus/dbus/v5 v5.2.2 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - golang.org/x/net v0.48.0 + golang.org/x/net v0.57.0 ) -require golang.org/x/sys v0.39.0 // indirect +require golang.org/x/sys v0.47.0 // indirect diff --git a/go.sum b/go.sum index 801ae05..783b4df 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,10 @@ github.com/bendahl/uinput v1.7.0 h1:nA4fm8Wu8UYNOPykIZm66nkWEyvxzfmJ8YC02PM40jg= github.com/bendahl/uinput v1.7.0/go.mod h1:Np7w3DINc9wB83p12fTAM3DPPhFnAKP0WTXRqCQJ6Z8= -github.com/godbus/dbus/v5 v5.2.1 h1:I4wwMdWSkmI57ewd+elNGwLRf2/dtSaFz1DujfWYvOk= -github.com/godbus/dbus/v5 v5.2.1/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= +github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= +github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= +golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= diff --git a/host.go b/host.go index 54874e5..622b3bf 100644 --- a/host.go +++ b/host.go @@ -74,7 +74,8 @@ func findDefaultHost() string { continue } for _, linkLocalPrefix := range []string{ - "169.254.", "fe8", "fe9", "fea", "feb"} { + "169.254.", "fe8", "fe9", "fea", "feb", + } { if strings.HasPrefix(ip.String(), linkLocalPrefix) { addIP(20, ip) continue addrs diff --git a/inputcontrol/controller.go b/inputcontrol/controller.go index 06ed8e4..111e937 100644 --- a/inputcontrol/controller.go +++ b/inputcontrol/controller.go @@ -21,8 +21,10 @@ package inputcontrol import "sort" -type PointerButton int -type Key int +type ( + PointerButton int + Key int +) const ( PointerButtonLeft PointerButton = iota diff --git a/inputcontrol/controller_portal.go b/inputcontrol/controller_portal.go index 6f38407..99ecf8b 100644 --- a/inputcontrol/controller_portal.go +++ b/inputcontrol/controller_portal.go @@ -88,12 +88,14 @@ func InitPortalController() (Controller, error) { "org.freedesktop.portal.RemoteDesktop.version") if err != nil { return nil, &UnsupportedPlatformError{ - fmt.Errorf("getting 'version' failed: %w", err)} + fmt.Errorf("getting 'version' failed: %w", err), + } } remoteDesktopVersion, ok := remoteDesktopVersionV.Value().(uint32) if !ok { return nil, &UnsupportedPlatformError{ - errors.New("unexpected 'version' type")} + errors.New("unexpected 'version' type"), + } } restoreTokenStore, err := func() (*secretStore, error) { if remoteDesktopVersion < 2 { @@ -103,7 +105,7 @@ func InitPortalController() (Controller, error) { if err != nil { return nil, err } - if err := os.MkdirAll(cacheDirectory, 0700); err != nil { + if err := os.MkdirAll(cacheDirectory, 0o700); err != nil { return nil, err } secret, err := retrieveSecret(bus) @@ -120,17 +122,20 @@ func InitPortalController() (Controller, error) { "org.freedesktop.portal.RemoteDesktop.AvailableDeviceTypes") if err != nil { return nil, &UnsupportedPlatformError{ - fmt.Errorf("getting 'AvailableDeviceTypes' failed: %w", err)} + fmt.Errorf("getting 'AvailableDeviceTypes' failed: %w", err), + } } availableDeviceTypes, ok := availableDeviceTypesV.Value().(uint32) if !ok { return nil, &UnsupportedPlatformError{ - errors.New("unexpected 'AvailableDeviceTypes' return type")} + errors.New("unexpected 'AvailableDeviceTypes' return type"), + } } if availableDeviceTypes&deviceKeyboard == 0 || availableDeviceTypes&devicePointer == 0 { return nil, &UnsupportedPlatformError{ - errors.New("keyboard or pointer source type not supported")} + errors.New("keyboard or pointer source type not supported"), + } } createSessionResults, err := checkResponse(getResponse(bus, portalDesktop, "org.freedesktop.portal.RemoteDesktop.CreateSession", 0, @@ -138,12 +143,14 @@ func InitPortalController() (Controller, error) { )) if err != nil { return nil, &UnsupportedPlatformError{ - fmt.Errorf("calling 'CreateSession' failed: %w", err)} + fmt.Errorf("calling 'CreateSession' failed: %w", err), + } } sessionHandleString, ok := createSessionResults["session_handle"].Value().(string) if !ok { return nil, &UnsupportedPlatformError{ - errors.New("unexpected 'session_handle' type in 'CreateSession' return value")} + errors.New("unexpected 'session_handle' type in 'CreateSession' return value"), + } } sessionHandle := dbus.ObjectPath(sessionHandleString) selectDevicesOptions := map[string]dbus.Variant{ @@ -165,7 +172,8 @@ func InitPortalController() (Controller, error) { )) if err != nil { return nil, &UnsupportedPlatformError{ - fmt.Errorf("calling 'SelectDevices' failed: %w", err)} + fmt.Errorf("calling 'SelectDevices' failed: %w", err), + } } startResponseStatus, startResults, err := getResponse(bus, portalDesktop, "org.freedesktop.portal.RemoteDesktop.Start", 0, @@ -173,7 +181,8 @@ func InitPortalController() (Controller, error) { ) if err != nil { return nil, &UnsupportedPlatformError{ - fmt.Errorf("calling 'Start' failed: %w", err)} + fmt.Errorf("calling 'Start' failed: %w", err), + } } if startResponseStatus != 0 { return nil, errors.New("keyboard or pointer access denied") @@ -186,14 +195,17 @@ func InitPortalController() (Controller, error) { devices, ok := startResults["devices"].Value().(uint32) if !ok { return nil, &UnsupportedPlatformError{ - errors.New("unexpected 'devices' type in 'Start' return value")} + errors.New("unexpected 'devices' type in 'Start' return value"), + } } if devices&deviceKeyboard == 0 || devices&devicePointer == 0 { return nil, errors.New("keyboard or pointer access denied") } cleanupBus = false - return &portalController{bus: bus, portalDesktop: portalDesktop, - sessionHandle: sessionHandle}, nil + return &portalController{ + bus: bus, portalDesktop: portalDesktop, + sessionHandle: sessionHandle, + }, nil } func retrieveSecret(bus *dbus.Conn) ([]byte, error) { @@ -267,11 +279,12 @@ func (s *secretStore) Store(data []byte) error { return err } ciphertext := s.aesgcm.Seal(nil, nonce, data, nil) - return os.WriteFile(s.filename, slices.Concat(nonce, ciphertext), 0600) + return os.WriteFile(s.filename, slices.Concat(nonce, ciphertext), 0o600) } func getResponse(bus *dbus.Conn, object dbus.BusObject, method string, - flags dbus.Flags, args ...interface{}) (uint32, map[string]dbus.Variant, error) { + flags dbus.Flags, args ...interface{}, +) (uint32, map[string]dbus.Variant, error) { ch := make(chan *dbus.Signal, 512) bus.Signal(ch) defer bus.RemoveSignal(ch) diff --git a/inputcontrol/controller_uinput.go b/inputcontrol/controller_uinput.go index df51e65..2dd9bab 100644 --- a/inputcontrol/controller_uinput.go +++ b/inputcontrol/controller_uinput.go @@ -25,10 +25,11 @@ package inputcontrol import ( "errors" "fmt" - "github.com/bendahl/uinput" "log" "os" "time" + + "github.com/bendahl/uinput" ) const shiftKeysDelay time.Duration = 50 * time.Millisecond diff --git a/inputcontrol/controller_x11.go b/inputcontrol/controller_x11.go index bb37d37..f45b75b 100644 --- a/inputcontrol/controller_x11.go +++ b/inputcontrol/controller_x11.go @@ -32,9 +32,12 @@ package inputcontrol // return DefaultRootWindow(dpy); // } import "C" + import ( "errors" "fmt" + "maps" + "slices" "strings" "sync" "time" @@ -42,12 +45,18 @@ import ( ) const ( - keyboardMappingDelay time.Duration = 500 * time.Millisecond + keyboardMappingDelay time.Duration = 200 * time.Millisecond scrollDiv int = 20 ) -var modifierIndices [6]uint = [...]uint{C.ShiftMapIndex, C.Mod1MapIndex, - C.Mod2MapIndex, C.Mod3MapIndex, C.Mod4MapIndex, C.Mod5MapIndex} +var modifierIndexes = [...]int{ + C.ShiftMapIndex, + C.Mod1MapIndex, + C.Mod2MapIndex, + C.Mod3MapIndex, + C.Mod4MapIndex, + C.Mod5MapIndex, +} type x11Controller struct { display *C.Display @@ -63,13 +72,15 @@ func InitX11Controller() (Controller, error) { display := C.XOpenDisplay(nil) if display == nil { return nil, &UnsupportedPlatformError{ - errors.New("failed to connect to X server")} + errors.New("failed to connect to X server"), + } } p := &x11Controller{display: display} if p.xIsXwayland() { p.Close() return nil, &UnsupportedPlatformError{ - errors.New("X server is Xwayland")} + errors.New("X server is Xwayland"), + } } return p, nil } @@ -113,53 +124,68 @@ func (p *x11Controller) Close() error { return nil } -func (p *x11Controller) findEmptyKeycodeLocked() (C.KeyCode, C.int, error) { +func (p *x11Controller) findEmptyKeycodeLocked() (keycode C.KeyCode, keysymsPerKeycode int, err error) { var minKeycodes, maxKeycodes C.int C.XDisplayKeycodes(p.display, &minKeycodes, &maxKeycodes) - var keysymsPerKeycode C.int - keysyms := C.XGetKeyboardMapping(p.display, C.KeyCode(minKeycodes), - maxKeycodes-minKeycodes+1, &keysymsPerKeycode) + var keysymsPerKeycodeC C.int + keysyms := C.XGetKeyboardMapping( + p.display, + C.KeyCode(minKeycodes), + maxKeycodes-minKeycodes+1, + &keysymsPerKeycodeC, + ) if keysyms == nil { return 0, 0, errors.New("failed to get keyboard mapping") } defer C.XFree(unsafe.Pointer(keysyms)) + keysymsPerKeycode = int(keysymsPerKeycodeC) keycodes: - for keycode := C.KeyCode(minKeycodes); keycode <= C.KeyCode(maxKeycodes); keycode++ { - for i := 0; i < int(keysymsPerKeycode); i++ { - keysymsIndex := int(keycode- - C.KeyCode(minKeycodes))*int(keysymsPerKeycode) + i - keysym := *(*C.KeySym)(unsafe.Pointer(uintptr(unsafe.Pointer(keysyms)) + - uintptr(keysymsIndex)*unsafe.Sizeof(*keysyms))) + for keycode := int(minKeycodes); keycode <= int(maxKeycodes); keycode++ { + for i := range keysymsPerKeycode { + keysymsIndex := (keycode-int(minKeycodes))*keysymsPerKeycode + i + keysym := *(*C.KeySym)(unsafe.Pointer( + uintptr(unsafe.Pointer(keysyms)) + + uintptr(keysymsIndex)*unsafe.Sizeof(*keysyms), + )) if keysym != 0 { continue keycodes } } - return keycode, keysymsPerKeycode, nil + return C.KeyCode(keycode), keysymsPerKeycode, nil } return 0, 0, errors.New("no empty keycode found") } -func (p *x11Controller) changeKeyMappingLocked(keysymsPerKeycode C.int, - keycode C.KeyCode, keysym Keysym) { +func (p *x11Controller) changeKeyMappingLocked( + keycode C.KeyCode, keysymsPerKeycode int, keysym Keysym, +) { keycodeMapping := make([]C.KeySym, keysymsPerKeycode) for i := range keycodeMapping { keycodeMapping[i] = C.KeySym(keysym) } - C.XChangeKeyboardMapping(p.display, C.int(keycode), keysymsPerKeycode, - (*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])), 1) - C.XFlush(p.display) + C.XChangeKeyboardMapping( + p.display, + C.int(keycode), + C.int(keysymsPerKeycode), + (*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])), + 1, + ) + C.XSync(p.display, C.False) } func (p *x11Controller) getModKeycodesLocked() map[uint]C.KeyCode { modKeymap := C.XGetModifierMapping(p.display) defer C.XFreeModifiermap(modKeymap) modKeycodes := make(map[uint]C.KeyCode) - for _, modIndex := range modifierIndices { - for i := 0; i < int(modKeymap.max_keypermod); i++ { - keycode := *(*C.KeyCode)(unsafe.Pointer(uintptr(unsafe.Pointer(modKeymap.modifiermap)) + - uintptr(uint(modIndex)*uint(modKeymap.max_keypermod)+uint(i)))) + for _, modIndex := range modifierIndexes { + for i := range int(modKeymap.max_keypermod) { + keycodeIndex := modIndex*int(modKeymap.max_keypermod) + i + keycode := *(*C.KeyCode)(unsafe.Pointer( + uintptr(unsafe.Pointer(modKeymap.modifiermap)) + + uintptr(keycodeIndex)*unsafe.Sizeof(*modKeymap.modifiermap), + )) if keycode != 0 { - modKeycodes[1< /dev/null; then + echo "Error: Go is not installed. Please install Go first." + return 1 + fi + + echo "Building remote-touchpad binary..." + go build -tags portal,uinput,x11 -o remote-touchpad + + if [ ! -f "remote-touchpad" ]; then + echo "Error: Failed to build remote-touchpad binary" + return 1 + fi + + # Setup directories + mkdir -p ~/.local/bin ~/.config/systemd/user + + echo "Installing service files..." + cp remote-touchpad ~/.local/bin/ || echo "Error: cp to ~/.local/bin failed" + cp remote-touchpad.service ~/.config/systemd/user/ || echo "Error: cp to ~/.config/systemd/user failed" + + echo "Enabling and starting service..." + systemctl --user daemon-reload + systemctl --user enable --now ${SERVICE_NAME}.service + + echo "✓ remote-touchpad user service installed and started" + echo "" + echo "Use './rts status' to check the service" + echo "Use './rts url' to get the connection URL" +} + +start() { + systemctl --user start ${SERVICE_NAME}.service + echo "Started remote-touchpad service" +} + +stop() { + systemctl --user stop ${SERVICE_NAME}.service + echo "Stopped remote-touchpad service" +} + +status() { + systemctl --user status ${SERVICE_NAME}.service --no-pager +} + +restart() { + systemctl --user restart ${SERVICE_NAME}.service + echo "Restarted remote-touchpad service" +} + +url() { + # Extract URL from service logs + echo "Fetching remote-touchpad URL..." + local url=$(journalctl --user -u ${SERVICE_NAME}.service -n 100 --no-pager 2>/dev/null | grep -oE "http://[^ ]+|https://[^ ]+" | tail -1) + if [ -n "$url" ]; then + echo "Remote Touchpad URL: $url" + # Generate QR code if qrencode is available + if command -v qrencode &> /dev/null; then + echo "Generating QR code..." + echo "$url" | qrencode -t ansiutf8 + else + echo "QR code generation requires qrencode. Install it with:" + echo " sudo apt-get install qrencode # Debian/Ubuntu" + echo " sudo dnf install qrencode # Fedora" + echo " brew install qrencode # macOS" + fi + else + echo "Could not find URL in service logs. Is the service running?" + fi +} + +log() { + echo "Viewing remote-touchpad service logs..." + journalctl --user -u ${SERVICE_NAME}.service --no-pager +} + +uninstall() { + echo "Uninstalling remote-touchpad..." + systemctl --user stop ${SERVICE_NAME}.service + systemctl --user disable ${SERVICE_NAME}.service + rm -f ~/.config/systemd/user/${SERVICE_NAME}.service + rm -f ~/.local/bin/remote-touchpad + systemctl --user daemon-reload + echo "✓ remote-touchpad uninstalled" +} + +help() { + echo "Remote Touchpad CLI Wrapper" + echo "" + echo "Usage: rts [command]" + echo "" + echo "Commands:" + echo " install - Install remote-touchpad as a systemd user service" + echo " start - Start the remote-touchpad service" + echo " stop - Stop the remote-touchpad service" + echo " status - Check service status" + echo " restart - Restart the service" + echo " url - Show the remote-touchpad URL" + echo " log - View service logs" + echo " uninstall - Uninstall the service" + echo " help - Show this help message" +} + +# Main command handler +case "$1" in + install) + install + ;; + start) + start + ;; + stop) + stop + ;; + status) + status + ;; + restart) + restart + ;; + url) + url + ;; + log) + log + ;; + uninstall) + uninstall + ;; + help|--help|-h|"") + help + ;; + *) + echo "Unknown command: $1" + help + exit 1 + ;; +esac diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 677f302..6d23326 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,17 +1,21 @@ -# Build by running "snapcraft". +# Build by running `snapcraft`. # WARNING: # Snapcraft uses caching for already build steps but it's buggy and can cause strange problems. -# Clean the cache by running "snapcraft clean". +# Clean the cache by running `snapcraft clean`. name: remote-touchpad license: GPL-3.0+ grade: stable adopt-info: remote-touchpad -base: core22 +base: core24 confinement: strict +platforms: + amd64: + arm64: + apps: remote-touchpad: command: bin/remote-touchpad @@ -48,10 +52,6 @@ parts: - libxt6 - libxrandr2 - libxtst6 - override-pull: | - craftctl default - # WORKAROUND: Point icon directly to SVG otherwise snapcraft can't find it - sed -e 's|Icon=com.github.unrud.RemoteTouchpad|Icon=/usr/share/icons/hicolor/scalable/apps/com.github.unrud.RemoteTouchpad.svg|' -i desktop/com.github.unrud.RemoteTouchpad.desktop override-build: | craftctl default install -Dm0755 -t "${CRAFT_PART_INSTALL}/bin" desktop/remote-touchpad-wait-on-error