diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 07c477a..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-# 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 e59454c..8df847c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,14 +1,5 @@
# Changelog
-## 1.5.4 (2026-08-02)
-
-* Improve X11 keyboard input
-* Update dependencies
-
-## 1.5.3 (2025-12-24)
-
-* Update dependencies
-
## 1.5.2 (2025-10-12)
* Update dependencies
diff --git a/README.md b/README.md
index e039950..fd05b7a 100644
--- a/README.md
+++ b/README.md
@@ -23,35 +23,6 @@ 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

diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml
index 113ef4d..9c85e89 100644
--- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml
+++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml
@@ -23,21 +23,6 @@
Unrud
-
-
-
- - Improve X11 keyboard input
- - Update dependencies
-
-
-
-
-
-
-
-
- https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.4/screenshots/1.png
+ https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.2/screenshots/1.png
- https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.4/screenshots/2.png
+ https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.2/screenshots/2.png
- https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.4/screenshots/3.png
+ https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.2/screenshots/3.png
- https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.4/screenshots/4.png
+ https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.2/screenshots/4.png
diff --git a/flatpak/com.github.unrud.RemoteTouchpad.yaml b/flatpak/com.github.unrud.RemoteTouchpad.yaml
index 239160e..54e8e97 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.2
- commit: a8ac15ba63645f02ffd57f4b443203279ab40b30
+ tag: v5.1.0
+ commit: e523abc905595cf17fb0001a7d77eaaddfaa216d
dest: vendor/github.com/godbus/dbus/v5
- type: git
url: https://github.com/skip2/go-qrcode
@@ -26,14 +26,14 @@ modules:
dest: vendor/github.com/skip2/go-qrcode
- type: git
url: https://github.com/golang/net
- tag: v0.57.0
- commit: b8f09f6f062ceb4531b7af4bd17a5c8fe9c4b2b5
+ tag: v0.46.0
+ commit: 2002a064a49010d8b881673c73f04e0b741e7c32
dest: vendor/golang.org/x/net
- type: git
- url: https://github.com/golang/sys
- tag: v0.47.0
- commit: 9e7e939dcafac07e8ab4cffa6e5fc74908413f00
- dest: vendor/golang.org/x/sys
+ url: https://github.com/golang/crypto
+ tag: v0.43.0
+ commit: 627cb894b6b2021e34c4ad4af4c0a963127491e4
+ dest: vendor/golang.org/x/crypto
- type: file
path: modules.txt
dest: vendor
diff --git a/flatpak/modules.txt b/flatpak/modules.txt
index 6092904..cb7ea3f 100644
--- a/flatpak/modules.txt
+++ b/flatpak/modules.txt
@@ -1,17 +1,17 @@
# github.com/bendahl/uinput v1.7.0
## explicit; go 1.13
github.com/bendahl/uinput
-# github.com/godbus/dbus/v5 v5.2.2
-## explicit; go 1.20
+# github.com/godbus/dbus/v5 v5.1.0
+## explicit; go 1.12
github.com/godbus/dbus/v5
# github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
## explicit; go 1.13
github.com/skip2/go-qrcode
github.com/skip2/go-qrcode/bitset
github.com/skip2/go-qrcode/reedsolomon
-# golang.org/x/net v0.57.0
-## explicit; go 1.25.0
+# golang.org/x/crypto v0.43.0
+## explicit; go 1.24.0
+golang.org/x/crypto/hkdf
+# golang.org/x/net v0.46.0
+## explicit; go 1.24.0
golang.org/x/net/websocket
-# 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 5afd19d..75e1e34 100644
--- a/go.mod
+++ b/go.mod
@@ -1,12 +1,13 @@
module github.com/unrud/remote-touchpad
-go 1.25.5
+go 1.24.0
+
+toolchain go1.24.8
require (
github.com/bendahl/uinput v1.7.0
- github.com/godbus/dbus/v5 v5.2.2
+ github.com/godbus/dbus/v5 v5.1.0
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
- golang.org/x/net v0.57.0
+ golang.org/x/crypto v0.43.0
+ golang.org/x/net v0.46.0
)
-
-require golang.org/x/sys v0.47.0 // indirect
diff --git a/go.sum b/go.sum
index 783b4df..736cffa 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.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
-github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
+github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
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.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=
+golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
+golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
+golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
+golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
diff --git a/host.go b/host.go
index 622b3bf..54874e5 100644
--- a/host.go
+++ b/host.go
@@ -74,8 +74,7 @@ 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 111e937..06ed8e4 100644
--- a/inputcontrol/controller.go
+++ b/inputcontrol/controller.go
@@ -21,10 +21,8 @@ package inputcontrol
import "sort"
-type (
- PointerButton int
- Key int
-)
+type PointerButton int
+type Key int
const (
PointerButtonLeft PointerButton = iota
diff --git a/inputcontrol/controller_portal.go b/inputcontrol/controller_portal.go
index 99ecf8b..7ee2f81 100644
--- a/inputcontrol/controller_portal.go
+++ b/inputcontrol/controller_portal.go
@@ -24,7 +24,6 @@ package inputcontrol
import (
"crypto/aes"
"crypto/cipher"
- "crypto/hkdf"
"crypto/rand"
"crypto/sha256"
"errors"
@@ -36,6 +35,7 @@ import (
"slices"
"github.com/godbus/dbus/v5"
+ "golang.org/x/crypto/hkdf"
)
const (
@@ -88,14 +88,12 @@ 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 {
@@ -105,7 +103,7 @@ func InitPortalController() (Controller, error) {
if err != nil {
return nil, err
}
- if err := os.MkdirAll(cacheDirectory, 0o700); err != nil {
+ if err := os.MkdirAll(cacheDirectory, 0700); err != nil {
return nil, err
}
secret, err := retrieveSecret(bus)
@@ -122,20 +120,17 @@ 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,
@@ -143,14 +138,12 @@ 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{
@@ -172,8 +165,7 @@ 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,
@@ -181,8 +173,7 @@ 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")
@@ -195,17 +186,14 @@ 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) {
@@ -242,8 +230,9 @@ type secretStore struct {
}
func newSecretStore(key []byte, filename string) (*secretStore, error) {
- derivedKey, err := hkdf.Key(sha256.New, key, nil, "", 32)
- if err != nil {
+ hkdf := hkdf.New(sha256.New, key, nil, nil)
+ derivedKey := make([]byte, 32)
+ if _, err := io.ReadFull(hkdf, derivedKey); err != nil {
return nil, err
}
block, err := aes.NewCipher(derivedKey)
@@ -279,12 +268,11 @@ 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), 0o600)
+ return os.WriteFile(s.filename, slices.Concat(nonce, ciphertext), 0600)
}
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 2dd9bab..df51e65 100644
--- a/inputcontrol/controller_uinput.go
+++ b/inputcontrol/controller_uinput.go
@@ -25,11 +25,10 @@ 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 f45b75b..bb37d37 100644
--- a/inputcontrol/controller_x11.go
+++ b/inputcontrol/controller_x11.go
@@ -32,12 +32,9 @@ package inputcontrol
// return DefaultRootWindow(dpy);
// }
import "C"
-
import (
"errors"
"fmt"
- "maps"
- "slices"
"strings"
"sync"
"time"
@@ -45,18 +42,12 @@ import (
)
const (
- keyboardMappingDelay time.Duration = 200 * time.Millisecond
+ keyboardMappingDelay time.Duration = 500 * time.Millisecond
scrollDiv int = 20
)
-var modifierIndexes = [...]int{
- C.ShiftMapIndex,
- C.Mod1MapIndex,
- C.Mod2MapIndex,
- C.Mod3MapIndex,
- C.Mod4MapIndex,
- C.Mod5MapIndex,
-}
+var modifierIndices [6]uint = [...]uint{C.ShiftMapIndex, C.Mod1MapIndex,
+ C.Mod2MapIndex, C.Mod3MapIndex, C.Mod4MapIndex, C.Mod5MapIndex}
type x11Controller struct {
display *C.Display
@@ -72,15 +63,13 @@ 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
}
@@ -124,68 +113,53 @@ func (p *x11Controller) Close() error {
return nil
}
-func (p *x11Controller) findEmptyKeycodeLocked() (keycode C.KeyCode, keysymsPerKeycode int, err error) {
+func (p *x11Controller) findEmptyKeycodeLocked() (C.KeyCode, C.int, error) {
var minKeycodes, maxKeycodes C.int
C.XDisplayKeycodes(p.display, &minKeycodes, &maxKeycodes)
- var keysymsPerKeycodeC C.int
- keysyms := C.XGetKeyboardMapping(
- p.display,
- C.KeyCode(minKeycodes),
- maxKeycodes-minKeycodes+1,
- &keysymsPerKeycodeC,
- )
+ var keysymsPerKeycode C.int
+ keysyms := C.XGetKeyboardMapping(p.display, C.KeyCode(minKeycodes),
+ maxKeycodes-minKeycodes+1, &keysymsPerKeycode)
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 := 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),
- ))
+ 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)))
if keysym != 0 {
continue keycodes
}
}
- return C.KeyCode(keycode), keysymsPerKeycode, nil
+ return keycode, keysymsPerKeycode, nil
}
return 0, 0, errors.New("no empty keycode found")
}
-func (p *x11Controller) changeKeyMappingLocked(
- keycode C.KeyCode, keysymsPerKeycode int, keysym Keysym,
-) {
+func (p *x11Controller) changeKeyMappingLocked(keysymsPerKeycode C.int,
+ keycode C.KeyCode, keysym Keysym) {
keycodeMapping := make([]C.KeySym, keysymsPerKeycode)
for i := range keycodeMapping {
keycodeMapping[i] = C.KeySym(keysym)
}
- C.XChangeKeyboardMapping(
- p.display,
- C.int(keycode),
- C.int(keysymsPerKeycode),
- (*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])),
- 1,
- )
- C.XSync(p.display, C.False)
+ C.XChangeKeyboardMapping(p.display, C.int(keycode), keysymsPerKeycode,
+ (*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])), 1)
+ C.XFlush(p.display)
}
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 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),
- ))
+ 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))))
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 6d23326..677f302 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -1,21 +1,17 @@
-# 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: core24
+base: core22
confinement: strict
-platforms:
- amd64:
- arm64:
-
apps:
remote-touchpad:
command: bin/remote-touchpad
@@ -52,6 +48,10 @@ 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