From fc363fe404985c0f2151c024c43e077e7619de06 Mon Sep 17 00:00:00 2001 From: Unrud Date: Sat, 27 Jan 2024 07:14:25 +0100 Subject: [PATCH 01/48] Snap: Update to core22 --- snap/snapcraft.yaml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 26fa53a..677f302 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -9,7 +9,7 @@ license: GPL-3.0+ grade: stable adopt-info: remote-touchpad -base: core20 +base: core22 confinement: strict apps: @@ -26,7 +26,7 @@ apps: - desktop - x11 common-id: com.github.unrud.RemoteTouchpad - desktop: share/applications/com.github.unrud.RemoteTouchpad.desktop + desktop: usr/share/applications/com.github.unrud.RemoteTouchpad.desktop parts: remote-touchpad: @@ -36,6 +36,8 @@ parts: - x11 source: . source-type: git + build-snaps: + - go build-packages: - gcc - libc6-dev @@ -47,13 +49,13 @@ parts: - libxrandr2 - libxtst6 override-pull: | - snapcraftctl 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: | - snapcraftctl build - install -Dm0755 -t "${SNAPCRAFT_PART_INSTALL}/bin" desktop/remote-touchpad-wait-on-error - install -Dm0644 -t "${SNAPCRAFT_PART_INSTALL}/usr/share/metainfo" desktop/com.github.unrud.RemoteTouchpad.metainfo.xml - install -Dm0644 -t "${SNAPCRAFT_PART_INSTALL}/usr/share/applications" desktop/com.github.unrud.RemoteTouchpad.desktop - install -Dm0644 -t "${SNAPCRAFT_PART_INSTALL}/usr/share/icons/hicolor/scalable/apps" desktop/com.github.unrud.RemoteTouchpad.svg + craftctl default + install -Dm0755 -t "${CRAFT_PART_INSTALL}/bin" desktop/remote-touchpad-wait-on-error + install -Dm0644 -t "${CRAFT_PART_INSTALL}/usr/share/metainfo" desktop/com.github.unrud.RemoteTouchpad.metainfo.xml + install -Dm0644 -t "${CRAFT_PART_INSTALL}/usr/share/applications" desktop/com.github.unrud.RemoteTouchpad.desktop + install -Dm0644 -t "${CRAFT_PART_INSTALL}/usr/share/icons/hicolor/scalable/apps" desktop/com.github.unrud.RemoteTouchpad.svg parse-info: [usr/share/metainfo/com.github.unrud.RemoteTouchpad.metainfo.xml] From 1985842ff0f5b829e62cfbe6309c890f82dac566 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 31 Jan 2024 09:33:09 +0100 Subject: [PATCH 02/48] Refactor CSS --- webdata/index.html | 2 +- webdata/main.css | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/webdata/index.html b/webdata/index.html index a011d0b..85bf7f9 100644 --- a/webdata/index.html +++ b/webdata/index.html @@ -1,7 +1,7 @@ - + Remote Touchpad diff --git a/webdata/main.css b/webdata/main.css index bf66d6a..3fce1b9 100644 --- a/webdata/main.css +++ b/webdata/main.css @@ -177,33 +177,37 @@ textarea { align-items: stretch; padding: 0; gap: 0; + flex-direction: row; +} + +#text-input .buttons { + flex-direction: column; } #text-input .buttons > button { - border-bottom: none; + border-top: none; border-right: none; } -#text-input .buttons > button:first-child { - border-left: none; +#text-input .buttons > button:last-child { + border-bottom: none; } -@media (min-aspect-ratio: 4/3) { +@media (max-aspect-ratio: 4/3) { #text-input { - flex-direction: row; - } - - #text-input .buttons { flex-direction: column; } - #text-input .buttons > button, - #text-input .buttons > button:first-child { + #text-input .buttons { + flex-direction: row; + } + + #text-input .buttons > button { border-top: 1px solid black; - border-left: 1px solid black; + border-bottom: none; } #text-input .buttons > button:first-child { - border-top: none; + border-left: none; } } From d502ca651ca02c59e58a04ca65aa666a9a6c12a3 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 31 Jan 2024 09:33:09 +0100 Subject: [PATCH 03/48] Disable keyboard navigation for all buttons --- webdata/app/ui.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/webdata/app/ui.mjs b/webdata/app/ui.mjs index 5441823..0812d40 100644 --- a/webdata/app/ui.mjs +++ b/webdata/app/ui.mjs @@ -63,6 +63,7 @@ export default class UI { compat.addFullscreenchangeEventListener(() => { this.#update(); }); compat.addPointerlockchangeEventListener(() => { this.#update(); }); for (const button of buttons) { + button.setAttribute("tabindex", "-1"); button.addEventListener("click", this.#handleButtonClick.bind(this)); } this.#update(); From 280a654f5936d533a73798f7f602561d2dddee2f Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 31 Jan 2024 09:33:09 +0100 Subject: [PATCH 04/48] Enable hardware keyboard input in mouse mode --- webdata/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webdata/index.html b/webdata/index.html index 85bf7f9..67f27fc 100644 --- a/webdata/index.html +++ b/webdata/index.html @@ -95,6 +95,6 @@ -
+

Mouse

From 7cff8286c84cc5576a7b9fecda2c75397a3b3d29 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 31 Jan 2024 09:33:10 +0100 Subject: [PATCH 05/48] Hide focus outline for textarea --- webdata/main.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webdata/main.css b/webdata/main.css index 3fce1b9..9e65a7c 100644 --- a/webdata/main.css +++ b/webdata/main.css @@ -153,6 +153,10 @@ textarea { padding: 0 0.5rem; } +textarea:focus { + outline: none; +} + #keys { padding: 0; justify-content: end; From f11cefc74ce27414506182af5f3c3286dae4ce63 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 31 Jan 2024 09:33:10 +0100 Subject: [PATCH 06/48] Keep text input open after sending --- webdata/app/ui.mjs | 18 +++++++++++------- webdata/index.html | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/webdata/app/ui.mjs b/webdata/app/ui.mjs index 0812d40..a21ddf1 100644 --- a/webdata/app/ui.mjs +++ b/webdata/app/ui.mjs @@ -57,7 +57,7 @@ export default class UI { (target) => target.classList.contains("touch-input")); document.addEventListener("mousedown", this.#handleMousedown.bind(this)); document.addEventListener("touchend", this.#handleTouchend.bind(this)); - textInput.addEventListener("input", this.#handleTextInput.bind(this)); + textInput.addEventListener("input", () => { this.#updateTextInput(); }); sendText.addEventListener("click", this.#handleSendText.bind(this)); window.addEventListener("popstate", () => { this.#update(); }); compat.addFullscreenchangeEventListener(() => { this.#update(); }); @@ -98,8 +98,13 @@ export default class UI { } } - #handleTextInput() { + #updateTextInput(newValue = null) { + if (newValue != null) { + textInput.value = newValue; + } sessionStorage.setItem("text-input", textInput.value); + sendText.textContent = sendText.getAttribute(`data-${textInput.value ? "send" : "back"}-content`); + textInput.focus(); } #handleButtonClick(event) { @@ -113,10 +118,10 @@ export default class UI { // normalize line endings const text = textInput.value.replace(/\r\n?/g, "\n"); this.#inputController.keyboardText(text); - textInput.value = ""; - this.#handleTextInput(); + this.#updateTextInput(""); + } else { + history.back(); } - history.back(); } #showScene(scene) { @@ -160,8 +165,7 @@ export default class UI { showTextInput() { this.#showScene(textInputScene); - textInput.value = sessionStorage.getItem("text-input") || ""; - textInput.focus(); + this.#updateTextInput(sessionStorage.getItem("text-input") || ""); if (history.state != "text-input") { history.pushState("text-input", ""); } diff --git a/webdata/index.html b/webdata/index.html index 67f27fc..68c24a6 100644 --- a/webdata/index.html +++ b/webdata/index.html @@ -28,7 +28,7 @@
- +
From 6a812607fefd3659eb495daa57356f4cd5c30fb6 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 31 Jan 2024 09:33:11 +0100 Subject: [PATCH 07/48] Fix virtual keyboard covering buttons in Chromium --- webdata/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webdata/index.html b/webdata/index.html index 68c24a6..52fb46f 100644 --- a/webdata/index.html +++ b/webdata/index.html @@ -1,7 +1,7 @@ - + Remote Touchpad From 88fd6e731408e51bf301ea7d28a7c7e63bcfae74 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 31 Jan 2024 09:33:11 +0100 Subject: [PATCH 08/48] Workaround for virtual keyboard covering buttons for Safari on iOS --- webdata/main.css | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/webdata/main.css b/webdata/main.css index 9e65a7c..6b9907f 100644 --- a/webdata/main.css +++ b/webdata/main.css @@ -197,7 +197,18 @@ textarea:focus { border-bottom: none; } -@media (max-aspect-ratio: 4/3) { +/* Only Safari for iOS */ +@supports (-webkit-touch-callout: none) { + /* Virtual keyboard can overlay content */ + #text-input .buttons > button:last-child { + display: flex; + padding-top: 0.2em; + justify-content: center; + } +} + +/* Portrait orientation (not for Safari on iOS) */ +@supports not (-webkit-touch-callout: none) { @media (max-aspect-ratio: 4/3) { #text-input { flex-direction: column; } @@ -214,4 +225,4 @@ textarea:focus { #text-input .buttons > button:first-child { border-left: none; } -} +} } From 652ee5aa6c590ad7eb27752445a6c094d1ccb04d Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 31 Jan 2024 14:59:38 +0100 Subject: [PATCH 09/48] Bump version to 1.4.5 --- CHANGELOG.md | 6 ++++++ ...com.github.unrud.RemoteTouchpad.metainfo.xml | 17 +++++++++++++---- main.go | 2 +- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f83fcc2..4116ca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 1.4.5 (2024-01-31) + +* Keep text input open after sending +* Workaround for virtual keyboard covering buttons (Chromium & iOS) +* Enable hardware keyboard input in mouse mode + ## 1.4.4 (2024-01-23) * Fix Xwayland detection on newer servers diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index f684a9b..a677665 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -19,6 +19,15 @@ https://github.com/Unrud/remote-touchpad Unrud + + +
    +
  • Keep text input open after sending
  • +
  • Workaround for virtual keyboard covering buttons (Chromium & iOS)
  • +
  • Enable hardware keyboard input in mouse mode
  • +
+
+
    @@ -309,16 +318,16 @@ - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.4/screenshots/1.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.5/screenshots/1.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.4/screenshots/2.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.5/screenshots/2.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.4/screenshots/3.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.5/screenshots/3.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.4/screenshots/4.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.5/screenshots/4.png diff --git a/main.go b/main.go index a56a52b..a96a958 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,7 @@ const ( authenticationRateBurst int = 10 challengeLength int = 8 defaultBind string = ":0" - version string = "1.4.4" + version string = "1.4.5" prettyAppName string = "Remote Touchpad" ) From 0184dcb22f456daec5cbc2b4efb7e69f802316fc Mon Sep 17 00:00:00 2001 From: Unrud Date: Tue, 6 Feb 2024 11:26:34 +0100 Subject: [PATCH 10/48] Set MIME types explicitly Fixes #61 Fixes #70 --- webdata.go | 33 +++++++++++++++++++++++++++++++++ webdata_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 webdata_test.go diff --git a/webdata.go b/webdata.go index 4d07131..1b816b6 100644 --- a/webdata.go +++ b/webdata.go @@ -1,19 +1,52 @@ +/* + * Copyright (c) 2024 Unrud + * + * This file is part of Remote-Touchpad. + * + * Remote-Touchpad is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Remote-Touchpad. If not, see . + */ + package main import ( "embed" "io/fs" "log" + "mime" ) //go:embed webdata/* var webdataFSWithPrefix embed.FS var webdataFS fs.FS +var webdataTypes = map[string]string{ + ".css": "text/css; charset=utf-8", + ".html": "text/html; charset=utf-8", + ".mjs": "text/javascript; charset=utf-8", + ".png": "image/png", + ".woff": "font/woff", +} + func init() { var err error webdataFS, err = fs.Sub(webdataFSWithPrefix, "webdata") if err != nil { log.Fatal(err) } + for ext, typ := range webdataTypes { + if err := mime.AddExtensionType(ext, typ); err != nil { + log.Fatal(err) + } + } } diff --git a/webdata_test.go b/webdata_test.go new file mode 100644 index 0000000..7ce8e8b --- /dev/null +++ b/webdata_test.go @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Unrud + * + * This file is part of Remote-Touchpad. + * + * Remote-Touchpad is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Remote-Touchpad is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Remote-Touchpad. If not, see . + */ + +package main + +import ( + "fmt" + "io/fs" + "path/filepath" + "testing" +) + +func TestWebdataTypesCompleteness(t *testing.T) { + if err := fs.WalkDir(webdataFS, ".", func(_ string, d fs.DirEntry, err error) error { + if err != nil || d.IsDir() { + return err + } + ext := filepath.Ext(d.Name()) + if _, haveType := webdataTypes[ext]; !haveType { + return fmt.Errorf("missing mime type for extension %#v", ext) + } + return nil + }); err != nil { + t.Fatal(err) + } +} From 632578205860a3262c57a0b11471f50ed36b4249 Mon Sep 17 00:00:00 2001 From: Unrud Date: Tue, 6 Feb 2024 11:33:40 +0100 Subject: [PATCH 11/48] Fix CI test --- .github/workflows/test.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d76fa6a..c1ed46d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -38,10 +38,6 @@ jobs: - name: Go Build run: go build ./... - - name: Go Test - run: go test ./... - if: ${{ matrix.os != 'linux' }} - - name: Go Test (with data race detection) run: go test -race ./... if: ${{ matrix.os == 'linux' }} From 016351e9d2dd9311a38768e8f0bfb618c9fe0032 Mon Sep 17 00:00:00 2001 From: Unrud Date: Tue, 6 Feb 2024 11:33:41 +0100 Subject: [PATCH 12/48] Bump version to 1.4.6 --- CHANGELOG.md | 4 ++++ .../com.github.unrud.RemoteTouchpad.metainfo.xml | 15 +++++++++++---- main.go | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4116ca2..9172f94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.4.6 (2024-02-06) + +* Prevent incorrect MIME types + ## 1.4.5 (2024-01-31) * Keep text input open after sending diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index a677665..9a7da69 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -19,6 +19,13 @@ https://github.com/Unrud/remote-touchpad Unrud + + +
      +
    • Prevent incorrect MIME types
    • +
    +
    +
      @@ -318,16 +325,16 @@ - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.5/screenshots/1.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.6/screenshots/1.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.5/screenshots/2.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.6/screenshots/2.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.5/screenshots/3.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.6/screenshots/3.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.5/screenshots/4.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.6/screenshots/4.png diff --git a/main.go b/main.go index a96a958..15195d6 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,7 @@ const ( authenticationRateBurst int = 10 challengeLength int = 8 defaultBind string = ":0" - version string = "1.4.5" + version string = "1.4.6" prettyAppName string = "Remote Touchpad" ) From 6996fbf958fb71a4557b0ca06146f8eed1231a24 Mon Sep 17 00:00:00 2001 From: Unrud Date: Fri, 5 Apr 2024 22:37:48 +0200 Subject: [PATCH 13/48] appdata: Add developer ID --- desktop/com.github.unrud.RemoteTouchpad.metainfo.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index 9a7da69..0fb3444 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -17,7 +17,9 @@ com.github.unrud.RemoteTouchpad.desktop https://github.com/Unrud/remote-touchpad/issues https://github.com/Unrud/remote-touchpad - Unrud + + Unrud + From 064c3cd242b93970bf979eaace3c671c9baea7eb Mon Sep 17 00:00:00 2001 From: Unrud Date: Fri, 5 Apr 2024 22:38:15 +0200 Subject: [PATCH 14/48] appdata: Add vcs-browser URL --- desktop/com.github.unrud.RemoteTouchpad.metainfo.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index 0fb3444..8986625 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -17,6 +17,7 @@ com.github.unrud.RemoteTouchpad.desktop https://github.com/Unrud/remote-touchpad/issues https://github.com/Unrud/remote-touchpad + https://github.com/Unrud/remote-touchpad Unrud From 4916fc59db7a8430e68def9f2668653a5c849de3 Mon Sep 17 00:00:00 2001 From: Unrud Date: Sat, 6 Apr 2024 17:22:46 +0200 Subject: [PATCH 15/48] Update dependencies --- flatpak/com.github.unrud.RemoteTouchpad.yaml | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flatpak/com.github.unrud.RemoteTouchpad.yaml b/flatpak/com.github.unrud.RemoteTouchpad.yaml index 0a89b54..91989eb 100644 --- a/flatpak/com.github.unrud.RemoteTouchpad.yaml +++ b/flatpak/com.github.unrud.RemoteTouchpad.yaml @@ -28,8 +28,8 @@ modules: dest: vendor/github.com/skip2/go-qrcode - type: git url: https://github.com/golang/net - tag: v0.20.0 - commit: cb5b10f0bbc51089bf49030ce3bd43bbfee08c23 + tag: v0.24.0 + commit: 7bbe32058aba7159e4d273710e6f4f1c16c627fb dest: vendor/golang.org/x/net buildsystem: simple build-commands: diff --git a/go.mod b/go.mod index b4ebadb..be58f22 100644 --- a/go.mod +++ b/go.mod @@ -6,5 +6,5 @@ require ( github.com/bendahl/uinput v1.7.0 github.com/godbus/dbus/v5 v5.1.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - golang.org/x/net v0.20.0 + golang.org/x/net v0.24.0 ) diff --git a/go.sum b/go.sum index 430ee54..8a1a094 100644 --- a/go.sum +++ b/go.sum @@ -4,5 +4,5 @@ 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.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= From dd510bc4a0d181c9a220e97f8f0c78ed425c13d3 Mon Sep 17 00:00:00 2001 From: Unrud Date: Sat, 13 Apr 2024 19:03:36 +0200 Subject: [PATCH 16/48] Update appdata --- desktop/com.github.unrud.RemoteTouchpad.metainfo.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index 8986625..1d672a7 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -18,6 +18,7 @@ https://github.com/Unrud/remote-touchpad/issues https://github.com/Unrud/remote-touchpad https://github.com/Unrud/remote-touchpad + Unrud Unrud From b4ecfad31689cacee2c9692203da68cd99059dbc Mon Sep 17 00:00:00 2001 From: Unrud Date: Fri, 30 Aug 2024 23:41:45 +0200 Subject: [PATCH 17/48] Update dependencies --- flatpak/com.github.unrud.RemoteTouchpad.yaml | 4 ++-- go.mod | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flatpak/com.github.unrud.RemoteTouchpad.yaml b/flatpak/com.github.unrud.RemoteTouchpad.yaml index 91989eb..0413e96 100644 --- a/flatpak/com.github.unrud.RemoteTouchpad.yaml +++ b/flatpak/com.github.unrud.RemoteTouchpad.yaml @@ -28,8 +28,8 @@ modules: dest: vendor/github.com/skip2/go-qrcode - type: git url: https://github.com/golang/net - tag: v0.24.0 - commit: 7bbe32058aba7159e4d273710e6f4f1c16c627fb + tag: v0.28.0 + commit: 4542a42604cd159f1adb93c58368079ae37b3bf6 dest: vendor/golang.org/x/net buildsystem: simple build-commands: diff --git a/go.mod b/go.mod index be58f22..50d9d86 100644 --- a/go.mod +++ b/go.mod @@ -6,5 +6,5 @@ require ( github.com/bendahl/uinput v1.7.0 github.com/godbus/dbus/v5 v5.1.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - golang.org/x/net v0.24.0 + golang.org/x/net v0.28.0 ) From 288345b5d32b5d994005671fb082b6aaa6ae34d1 Mon Sep 17 00:00:00 2001 From: Unrud Date: Fri, 30 Aug 2024 23:45:18 +0200 Subject: [PATCH 18/48] Bump version to 1.4.7 --- CHANGELOG.md | 4 ++++ .../com.github.unrud.RemoteTouchpad.metainfo.xml | 15 +++++++++++---- main.go | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9172f94..bc0a1d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.4.7 (2024-08-30) + +* Update dependencies + ## 1.4.6 (2024-02-06) * Prevent incorrect MIME types diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index 1d672a7..4618317 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -23,6 +23,13 @@ Unrud + + +
        +
      • Update dependencies
      • +
      +
      +
        @@ -329,16 +336,16 @@ - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.6/screenshots/1.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.7/screenshots/1.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.6/screenshots/2.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.7/screenshots/2.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.6/screenshots/3.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.7/screenshots/3.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.6/screenshots/4.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.7/screenshots/4.png diff --git a/main.go b/main.go index 15195d6..0e24287 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,7 @@ const ( authenticationRateBurst int = 10 challengeLength int = 8 defaultBind string = ":0" - version string = "1.4.6" + version string = "1.4.7" prettyAppName string = "Remote Touchpad" ) From 30cfff86b0c517ba33de7af70582642fa6d408ee Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 1 Sep 2024 17:09:23 +0200 Subject: [PATCH 19/48] Update go.sum --- go.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index 8a1a094..0f9b239 100644 --- a/go.sum +++ b/go.sum @@ -4,5 +4,5 @@ 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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= From c71e5c4b8b2d8b4ed3137f3e553a532a318f1570 Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 1 Sep 2024 17:12:02 +0200 Subject: [PATCH 20/48] Flatpak: Add IPC to fix linting error --- flatpak/com.github.unrud.RemoteTouchpad.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/flatpak/com.github.unrud.RemoteTouchpad.yaml b/flatpak/com.github.unrud.RemoteTouchpad.yaml index 0413e96..2f298a1 100644 --- a/flatpak/com.github.unrud.RemoteTouchpad.yaml +++ b/flatpak/com.github.unrud.RemoteTouchpad.yaml @@ -8,6 +8,7 @@ sdk-extensions: finish-args: - --socket=fallback-x11 - --socket=wayland + - --share=ipc # Required by Flathub linter - --share=network modules: - name: remote-touchpad From 4fb452c5427aeaefdf8da50aadf6ec30136096bd Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 1 Sep 2024 17:15:32 +0200 Subject: [PATCH 21/48] Bump version to 1.4.8 --- CHANGELOG.md | 4 ++++ .../com.github.unrud.RemoteTouchpad.metainfo.xml | 15 +++++++++++---- main.go | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc0a1d8..8d03509 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.4.8 (2024-09-01) + +* Update dependencies + ## 1.4.7 (2024-08-30) * Update dependencies diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index 4618317..116e8d6 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -23,6 +23,13 @@ Unrud + + +
          +
        • Update dependencies
        • +
        +
        +
          @@ -336,16 +343,16 @@ - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.7/screenshots/1.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.8/screenshots/1.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.7/screenshots/2.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.8/screenshots/2.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.7/screenshots/3.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.8/screenshots/3.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.7/screenshots/4.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.8/screenshots/4.png diff --git a/main.go b/main.go index 0e24287..3d05c7e 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,7 @@ const ( authenticationRateBurst int = 10 challengeLength int = 8 defaultBind string = ":0" - version string = "1.4.7" + version string = "1.4.8" prettyAppName string = "Remote Touchpad" ) From 7a806f7b009c59821a6725f2b4f531253690d12a Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 17 Nov 2024 21:33:51 +0100 Subject: [PATCH 22/48] Flatpak: Update runtime --- flatpak/com.github.unrud.RemoteTouchpad.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flatpak/com.github.unrud.RemoteTouchpad.yaml b/flatpak/com.github.unrud.RemoteTouchpad.yaml index 2f298a1..cc261a6 100644 --- a/flatpak/com.github.unrud.RemoteTouchpad.yaml +++ b/flatpak/com.github.unrud.RemoteTouchpad.yaml @@ -1,6 +1,6 @@ app-id: com.github.unrud.RemoteTouchpad runtime: org.freedesktop.Platform -runtime-version: '23.08' +runtime-version: '24.08' sdk: org.freedesktop.Sdk command: remote-touchpad sdk-extensions: From c6c54c77a7e3a985233695e3c16a0223d07c0930 Mon Sep 17 00:00:00 2001 From: godalming Date: Sat, 15 Mar 2025 12:05:29 +0000 Subject: [PATCH 23/48] Add support for session restore on the linux portals backend, fixing #77 --- README.md | 12 +++++-- inputcontrol/controller.go | 4 +-- inputcontrol/controller_null.go | 2 +- inputcontrol/controller_portal.go | 54 ++++++++++++++++++++++++++++-- inputcontrol/controller_uinput.go | 2 +- inputcontrol/controller_windows.go | 2 +- inputcontrol/controller_x11.go | 2 +- main.go | 5 +-- 8 files changed, 70 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2740e73..fd05b7a 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,16 @@ Supports Flatpak's RemoteDesktop portal (for Wayland), Windows and X11. * [Snap](https://snapcraft.io/remote-touchpad) * [Windows](https://github.com/Unrud/remote-touchpad/releases/latest) * Golang: - * Portal & uinput & X11: `go install -tags portal,uinput,x11 github.com/unrud/remote-touchpad@latest` - * Windows: `go install github.com/unrud/remote-touchpad@latest` + * Portal & uinput & X11: + + ```sh + go install -tags portal,uinput,x11 github.com/unrud/remote-touchpad@latest + ``` + * Windows: + + ```sh + go install github.com/unrud/remote-touchpad@latest + ``` ## Screenshots diff --git a/inputcontrol/controller.go b/inputcontrol/controller.go index 06ed8e4..3a64df0 100644 --- a/inputcontrol/controller.go +++ b/inputcontrol/controller.go @@ -55,14 +55,14 @@ const ( type ControllerInfo struct { Name string - Init func() (Controller, error) + Init func(bool) (Controller, error) priority int } var Controllers []ControllerInfo -func RegisterController(name string, init func() (Controller, error), priority int) { +func RegisterController(name string, init func(bool) (Controller, error), priority int) { Controllers = append(Controllers, ControllerInfo{name, init, priority}) sort.SliceStable(Controllers, func(i, j int) bool { return Controllers[i].priority < Controllers[j].priority diff --git a/inputcontrol/controller_null.go b/inputcontrol/controller_null.go index 6188cce..8b1ba67 100644 --- a/inputcontrol/controller_null.go +++ b/inputcontrol/controller_null.go @@ -31,7 +31,7 @@ func init() { RegisterController("null", InitNullController, 1000) } -func InitNullController() (Controller, error) { +func InitNullController(saveRestoreToken bool) (Controller, error) { return &nullController{}, nil } diff --git a/inputcontrol/controller_portal.go b/inputcontrol/controller_portal.go index 7d19efc..62512c6 100644 --- a/inputcontrol/controller_portal.go +++ b/inputcontrol/controller_portal.go @@ -25,6 +25,8 @@ import ( "errors" "fmt" "github.com/godbus/dbus/v5" + "os" + "path/filepath" ) const ( @@ -34,6 +36,8 @@ const ( btnReleased uint32 = 0 btnPressed uint32 = 1 + untilRevoked uint32 = 2 + // linux/input-event-codes.h btnLeft int32 = 0x110 btnRight int32 = 0x111 @@ -50,7 +54,26 @@ func init() { RegisterController("RemoteDesktop portal", InitPortalController, 1) } -func InitPortalController() (Controller, error) { +func InitPortalController(saveRestoreToken bool) (Controller, error) { + cacheDirectory, err := os.UserCacheDir() + var restoreTokenFilePath string + var restoreToken string + if err != nil { + err = errors.Join(errors.New("Cannot get user cache directory, therefore cannot get restore token file path in order to read or save the restore token. "), err) + if saveRestoreToken == true { + return nil, err + } else { + fmt.Println(err.Error()) + } + } else { + restoreTokenFilePath = filepath.Join(cacheDirectory, "remote_touchpad_portals_restore_token") + restoreTokenBytes, err := os.ReadFile(restoreTokenFilePath) + if err != nil { + fmt.Printf("Failed to read restore token file: %s\n", err) + } else { + restoreToken = string(restoreTokenBytes) + } + } bus, err := dbus.SessionBusPrivate() if err != nil { return nil, &UnsupportedPlatformError{err} @@ -81,10 +104,18 @@ func InitPortalController() (Controller, error) { return nil, &UnsupportedPlatformError{ errors.New("unexpected 'AvailableDeviceTypes' return type")} } - if availableDeviceTypes&deviceKeyboard == 0 || + if availableDeviceTypes&deviceKeyboard == 0 && availableDeviceTypes&devicePointer == 0 { return nil, &UnsupportedPlatformError{ - errors.New("keyboard or pointer source type not supported")} + errors.New("keyboard and pointer source type not supported")} + } + if availableDeviceTypes&deviceKeyboard == 0 { + return nil, &UnsupportedPlatformError{ + errors.New("keyboard source type not supported")} + } + if availableDeviceTypes&devicePointer == 0 { + return nil, &UnsupportedPlatformError{ + errors.New("pointer source type not supported")} } inVardict := make(map[string]dbus.Variant) inVardict["session_handle_token"] = dbus.MakeVariant("t") @@ -110,6 +141,12 @@ func InitPortalController() (Controller, error) { sessionHandle := dbus.ObjectPath(sessionHandleS) inVardict = make(map[string]dbus.Variant) inVardict["types"] = dbus.MakeVariant(deviceKeyboard | devicePointer) + if restoreToken != "" { + inVardict["restore_token"] = dbus.MakeVariant(restoreToken) + } + if saveRestoreToken { + inVardict["persist_mode"] = dbus.MakeVariant(untilRevoked) + } result, outVardict, err = getResponse(bus, remoteDesktop, "org.freedesktop.portal.RemoteDesktop.SelectDevices", 0, sessionHandle, inVardict) if err != nil { @@ -128,6 +165,17 @@ func InitPortalController() (Controller, error) { if result != 0 { return nil, errors.New("keyboard or pointer access denied") } + if saveRestoreToken { + restoreToken, ok := outVardict["restore_token"].Value().(string) + if !ok { + return nil, errors.New("Failed to get new restore token") + } else { + err := os.WriteFile(restoreTokenFilePath, []byte(restoreToken), 0644) + if err != nil { + return nil, errors.Join(errors.New("Failed to write restore token: "), err) + } + } + } devicesV, ok := outVardict["devices"] if !ok { return nil, &UnsupportedPlatformError{ diff --git a/inputcontrol/controller_uinput.go b/inputcontrol/controller_uinput.go index df51e65..b9723a2 100644 --- a/inputcontrol/controller_uinput.go +++ b/inputcontrol/controller_uinput.go @@ -43,7 +43,7 @@ func init() { RegisterController("uinput", InitUinputController, 10) } -func InitUinputController() (Controller, error) { +func InitUinputController(saveRestoreToken bool) (Controller, error) { keymapName, keymapSet := os.LookupEnv("REMOTE_TOUCHPAD_UINPUT_KEYMAP") if !keymapSet { keymapName = "defkeymap" diff --git a/inputcontrol/controller_windows.go b/inputcontrol/controller_windows.go index 58b5e9a..0a19556 100644 --- a/inputcontrol/controller_windows.go +++ b/inputcontrol/controller_windows.go @@ -95,7 +95,7 @@ func init() { RegisterController("Windows", InitWindowsController, 0) } -func InitWindowsController() (Controller, error) { +func InitWindowsController(saveRestoreToken bool) (Controller, error) { p := &windowsController{} if err := sendInputProc.Find(); err != nil { return nil, &UnsupportedPlatformError{err} diff --git a/inputcontrol/controller_x11.go b/inputcontrol/controller_x11.go index bb37d37..98fcbc4 100644 --- a/inputcontrol/controller_x11.go +++ b/inputcontrol/controller_x11.go @@ -59,7 +59,7 @@ func init() { RegisterController("X11", InitX11Controller, 0) } -func InitX11Controller() (Controller, error) { +func InitX11Controller(saveRestoreToken bool) (Controller, error) { display := C.XOpenDisplay(nil) if display == nil { return nil, &UnsupportedPlatformError{ diff --git a/main.go b/main.go index 3d05c7e..44cf381 100644 --- a/main.go +++ b/main.go @@ -152,7 +152,7 @@ func secureRandBase64(length int) string { func main() { terminal.SetTitle(prettyAppName) var bind, certFile, keyFile, secret string - var showVersion bool + var showVersion, savePlaintextRestoreToken bool var config config flag.BoolVar(&showVersion, "version", false, "show program's version number and exit") flag.StringVar(&bind, "bind", defaultBind, "bind server to [HOSTNAME]:PORT") @@ -164,6 +164,7 @@ func main() { flag.Float64Var(&config.ScrollSpeed, "scroll-speed", 1, "scroll speed multiplier") flag.Float64Var(&config.MouseMoveSpeed, "mouse-move-speed", 1, "mouse move speed multiplier") flag.Float64Var(&config.MouseScrollSpeed, "mouse-scroll-speed", 1, "mouse scroll speed multiplier") + flag.BoolVar(&savePlaintextRestoreToken, "save-plaintext-restore-token", false, "save a restore token in plaintext in order to avoid the confirmation dialogue that appears with some implementations of the portals backend on wayland on linux from appearing on the next run of remote-touchpad") flag.Parse() if showVersion { fmt.Println(version) @@ -188,7 +189,7 @@ func main() { for _, controllerInfo := range inputcontrol.Controllers { controllerName = controllerInfo.Name var err error - controller, err = controllerInfo.Init() + controller, err = controllerInfo.Init(savePlaintextRestoreToken) if err == nil { break } else { From 21461d9a766fe09c3adfe1195b425266de57ce14 Mon Sep 17 00:00:00 2001 From: godalming Date: Sun, 16 Mar 2025 17:48:29 +0000 Subject: [PATCH 24/48] Fix file permisions. Detect if restore tokens are not supported (version <= 1). Always log and continue if it is not possible to use a restore token rather than exit the program or log using fmt. --- inputcontrol/controller_portal.go | 66 +++++++++++++++++-------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/inputcontrol/controller_portal.go b/inputcontrol/controller_portal.go index 62512c6..dd07e6c 100644 --- a/inputcontrol/controller_portal.go +++ b/inputcontrol/controller_portal.go @@ -25,6 +25,7 @@ import ( "errors" "fmt" "github.com/godbus/dbus/v5" + "log" "os" "path/filepath" ) @@ -55,25 +56,6 @@ func init() { } func InitPortalController(saveRestoreToken bool) (Controller, error) { - cacheDirectory, err := os.UserCacheDir() - var restoreTokenFilePath string - var restoreToken string - if err != nil { - err = errors.Join(errors.New("Cannot get user cache directory, therefore cannot get restore token file path in order to read or save the restore token. "), err) - if saveRestoreToken == true { - return nil, err - } else { - fmt.Println(err.Error()) - } - } else { - restoreTokenFilePath = filepath.Join(cacheDirectory, "remote_touchpad_portals_restore_token") - restoreTokenBytes, err := os.ReadFile(restoreTokenFilePath) - if err != nil { - fmt.Printf("Failed to read restore token file: %s\n", err) - } else { - restoreToken = string(restoreTokenBytes) - } - } bus, err := dbus.SessionBusPrivate() if err != nil { return nil, &UnsupportedPlatformError{err} @@ -94,6 +76,30 @@ func InitPortalController(saveRestoreToken bool) (Controller, error) { } remoteDesktop := bus.Object("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop") + version, err := remoteDesktop.GetProperty( + "org.freedesktop.portal.RemoteDesktop.version") + if err != nil { + return nil, &UnsupportedPlatformError{err} + } + supportsRestoreTokens := version.Value().(uint32) >= 2 + var restoreTokenFilePath string + var restoreToken string + if supportsRestoreTokens { + cacheDirectory, err := os.UserCacheDir() + if err != nil { + log.Printf("Cannot get user cache directory: %s. Therefore cannot get restore token file path in order to read or save the restore token.\n", err) + } else { + restoreTokenFilePath = filepath.Join(cacheDirectory, "remote_touchpad_portals_restore_token") + restoreTokenBytes, err := os.ReadFile(restoreTokenFilePath) + if err != nil { + log.Printf("Failed to read restore token file: %s\n", err) + } else { + restoreToken = string(restoreTokenBytes) + } + } + } else { + log.Println("Portals implementation does not support restore tokens") + } availableDeviceTypesV, err := remoteDesktop.GetProperty( "org.freedesktop.portal.RemoteDesktop.AvailableDeviceTypes") if err != nil { @@ -141,11 +147,13 @@ func InitPortalController(saveRestoreToken bool) (Controller, error) { sessionHandle := dbus.ObjectPath(sessionHandleS) inVardict = make(map[string]dbus.Variant) inVardict["types"] = dbus.MakeVariant(deviceKeyboard | devicePointer) - if restoreToken != "" { - inVardict["restore_token"] = dbus.MakeVariant(restoreToken) - } - if saveRestoreToken { - inVardict["persist_mode"] = dbus.MakeVariant(untilRevoked) + if supportsRestoreTokens { + if restoreToken != "" { + inVardict["restore_token"] = dbus.MakeVariant(restoreToken) + } + if saveRestoreToken { + inVardict["persist_mode"] = dbus.MakeVariant(untilRevoked) + } } result, outVardict, err = getResponse(bus, remoteDesktop, "org.freedesktop.portal.RemoteDesktop.SelectDevices", 0, sessionHandle, inVardict) @@ -165,14 +173,14 @@ func InitPortalController(saveRestoreToken bool) (Controller, error) { if result != 0 { return nil, errors.New("keyboard or pointer access denied") } - if saveRestoreToken { + if supportsRestoreTokens && saveRestoreToken { restoreToken, ok := outVardict["restore_token"].Value().(string) if !ok { - return nil, errors.New("Failed to get new restore token") - } else { - err := os.WriteFile(restoreTokenFilePath, []byte(restoreToken), 0644) + log.Println("Failed to get new restore token") + } else if restoreTokenFilePath != "" { + err := os.WriteFile(restoreTokenFilePath, []byte(restoreToken), 0600) if err != nil { - return nil, errors.Join(errors.New("Failed to write restore token: "), err) + log.Printf("Failed to write restore token: %s", err) } } } From 0fe41d0b15b3bf61fdc035f052c428ad20f6b058 Mon Sep 17 00:00:00 2001 From: godalming Date: Mon, 17 Mar 2025 18:51:12 +0000 Subject: [PATCH 25/48] Fix not being able to create restore token on snap because the cache directory does not exist --- inputcontrol/controller_portal.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/inputcontrol/controller_portal.go b/inputcontrol/controller_portal.go index dd07e6c..439a7c5 100644 --- a/inputcontrol/controller_portal.go +++ b/inputcontrol/controller_portal.go @@ -83,9 +83,10 @@ func InitPortalController(saveRestoreToken bool) (Controller, error) { } supportsRestoreTokens := version.Value().(uint32) >= 2 var restoreTokenFilePath string + var cacheDirectory string var restoreToken string if supportsRestoreTokens { - cacheDirectory, err := os.UserCacheDir() + cacheDirectory, err = os.UserCacheDir() if err != nil { log.Printf("Cannot get user cache directory: %s. Therefore cannot get restore token file path in order to read or save the restore token.\n", err) } else { @@ -178,9 +179,14 @@ func InitPortalController(saveRestoreToken bool) (Controller, error) { if !ok { log.Println("Failed to get new restore token") } else if restoreTokenFilePath != "" { - err := os.WriteFile(restoreTokenFilePath, []byte(restoreToken), 0600) + err := os.MkdirAll(cacheDirectory, 0700) if err != nil { - log.Printf("Failed to write restore token: %s", err) + log.Printf("Failed to create cache directory for restore token: %s\n", err) + } else { + err := os.WriteFile(restoreTokenFilePath, []byte(restoreToken), 0600) + if err != nil { + log.Printf("Failed to write restore token: %s\n", err) + } } } } From 7c1652e9ddc9d35ea3bcd773f36b3a01789f814b Mon Sep 17 00:00:00 2001 From: Unrud Date: Mon, 17 Mar 2025 20:24:25 +0100 Subject: [PATCH 26/48] CI: Install missing package --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c1ed46d..9f3768a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -23,7 +23,7 @@ jobs: with: go-version: stable check-latest: true - - run: sudo apt install libxrandr-dev libxtst-dev + - run: sudo apt install libxrandr-dev libxtst-dev libxt-dev if: ${{ contains(matrix.tags, 'x11') }} - name: Go Format From abd9fd4773830f4ed4300a5b7c62fc51a23304a5 Mon Sep 17 00:00:00 2001 From: Unrud Date: Mon, 17 Mar 2025 20:32:36 +0100 Subject: [PATCH 27/48] Update dependencies --- flatpak/com.github.unrud.RemoteTouchpad.yaml | 10 +++++----- flatpak/modules.txt | 14 ++++++++++++++ go.mod | 6 ++++-- go.sum | 4 ++-- 4 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 flatpak/modules.txt diff --git a/flatpak/com.github.unrud.RemoteTouchpad.yaml b/flatpak/com.github.unrud.RemoteTouchpad.yaml index cc261a6..08934d7 100644 --- a/flatpak/com.github.unrud.RemoteTouchpad.yaml +++ b/flatpak/com.github.unrud.RemoteTouchpad.yaml @@ -15,9 +15,6 @@ modules: sources: - type: git path: .. - - type: shell - commands: - - . /usr/lib/sdk/golang/enable.sh; go mod vendor -e - type: git url: https://github.com/godbus/dbus tag: v5.1.0 @@ -29,9 +26,12 @@ modules: dest: vendor/github.com/skip2/go-qrcode - type: git url: https://github.com/golang/net - tag: v0.28.0 - commit: 4542a42604cd159f1adb93c58368079ae37b3bf6 + tag: v0.37.0 + commit: 99b3ae0643f9a2f9d820fcbba5f9e4c83b23bd48 dest: vendor/golang.org/x/net + - type: file + path: modules.txt + dest: vendor buildsystem: simple build-commands: - . /usr/lib/sdk/golang/enable.sh; go build -tags portal,x11 diff --git a/flatpak/modules.txt b/flatpak/modules.txt new file mode 100644 index 0000000..1ac92b8 --- /dev/null +++ b/flatpak/modules.txt @@ -0,0 +1,14 @@ +# github.com/bendahl/uinput v1.7.0 +## explicit; go 1.13 +github.com/bendahl/uinput +# 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.37.0 +## explicit; go 1.23.0 +golang.org/x/net/websocket diff --git a/go.mod b/go.mod index 50d9d86..c99d2aa 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,12 @@ module github.com/unrud/remote-touchpad -go 1.20 +go 1.23.0 + +toolchain go1.23.7 require ( github.com/bendahl/uinput v1.7.0 github.com/godbus/dbus/v5 v5.1.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - golang.org/x/net v0.28.0 + golang.org/x/net v0.37.0 ) diff --git a/go.sum b/go.sum index 0f9b239..9cf18b6 100644 --- a/go.sum +++ b/go.sum @@ -4,5 +4,5 @@ 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.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= From 16dc47b5708bf0e526c175cea30b22da988dfc47 Mon Sep 17 00:00:00 2001 From: Unrud Date: Tue, 18 Mar 2025 09:18:15 +0100 Subject: [PATCH 28/48] Encrypt restore token --- flatpak/com.github.unrud.RemoteTouchpad.yaml | 5 + flatpak/modules.txt | 3 + go.mod | 1 + go.sum | 2 + inputcontrol/controller.go | 4 +- inputcontrol/controller_null.go | 2 +- inputcontrol/controller_portal.go | 158 ++++++++++++++----- inputcontrol/controller_uinput.go | 2 +- inputcontrol/controller_windows.go | 2 +- inputcontrol/controller_x11.go | 2 +- main.go | 5 +- 11 files changed, 137 insertions(+), 49 deletions(-) diff --git a/flatpak/com.github.unrud.RemoteTouchpad.yaml b/flatpak/com.github.unrud.RemoteTouchpad.yaml index 08934d7..55bb828 100644 --- a/flatpak/com.github.unrud.RemoteTouchpad.yaml +++ b/flatpak/com.github.unrud.RemoteTouchpad.yaml @@ -29,6 +29,11 @@ modules: tag: v0.37.0 commit: 99b3ae0643f9a2f9d820fcbba5f9e4c83b23bd48 dest: vendor/golang.org/x/net + - type: git + url: https://github.com/golang/crypto + tag: v0.36.0 + commit: 49bf5b80c8108983f588ecabd7bf996e6e63a515 + dest: vendor/golang.org/x/crypto - type: file path: modules.txt dest: vendor diff --git a/flatpak/modules.txt b/flatpak/modules.txt index 1ac92b8..6662b65 100644 --- a/flatpak/modules.txt +++ b/flatpak/modules.txt @@ -9,6 +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/crypto v0.36.0 +## explicit; go 1.23.0 +golang.org/x/crypto/hkdf # golang.org/x/net v0.37.0 ## explicit; go 1.23.0 golang.org/x/net/websocket diff --git a/go.mod b/go.mod index c99d2aa..1f2549c 100644 --- a/go.mod +++ b/go.mod @@ -8,5 +8,6 @@ require ( github.com/bendahl/uinput v1.7.0 github.com/godbus/dbus/v5 v5.1.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e + golang.org/x/crypto v0.36.0 golang.org/x/net v0.37.0 ) diff --git a/go.sum b/go.sum index 9cf18b6..a03440b 100644 --- a/go.sum +++ b/go.sum @@ -4,5 +4,7 @@ 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/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= diff --git a/inputcontrol/controller.go b/inputcontrol/controller.go index 3a64df0..06ed8e4 100644 --- a/inputcontrol/controller.go +++ b/inputcontrol/controller.go @@ -55,14 +55,14 @@ const ( type ControllerInfo struct { Name string - Init func(bool) (Controller, error) + Init func() (Controller, error) priority int } var Controllers []ControllerInfo -func RegisterController(name string, init func(bool) (Controller, error), priority int) { +func RegisterController(name string, init func() (Controller, error), priority int) { Controllers = append(Controllers, ControllerInfo{name, init, priority}) sort.SliceStable(Controllers, func(i, j int) bool { return Controllers[i].priority < Controllers[j].priority diff --git a/inputcontrol/controller_null.go b/inputcontrol/controller_null.go index 8b1ba67..6188cce 100644 --- a/inputcontrol/controller_null.go +++ b/inputcontrol/controller_null.go @@ -31,7 +31,7 @@ func init() { RegisterController("null", InitNullController, 1000) } -func InitNullController(saveRestoreToken bool) (Controller, error) { +func InitNullController() (Controller, error) { return &nullController{}, nil } diff --git a/inputcontrol/controller_portal.go b/inputcontrol/controller_portal.go index 439a7c5..b5a59d2 100644 --- a/inputcontrol/controller_portal.go +++ b/inputcontrol/controller_portal.go @@ -22,12 +22,20 @@ package inputcontrol import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/sha256" "errors" "fmt" - "github.com/godbus/dbus/v5" + "io" "log" "os" "path/filepath" + "slices" + + "github.com/godbus/dbus/v5" + "golang.org/x/crypto/hkdf" ) const ( @@ -55,7 +63,7 @@ func init() { RegisterController("RemoteDesktop portal", InitPortalController, 1) } -func InitPortalController(saveRestoreToken bool) (Controller, error) { +func InitPortalController() (Controller, error) { bus, err := dbus.SessionBusPrivate() if err != nil { return nil, &UnsupportedPlatformError{err} @@ -81,25 +89,26 @@ func InitPortalController(saveRestoreToken bool) (Controller, error) { if err != nil { return nil, &UnsupportedPlatformError{err} } - supportsRestoreTokens := version.Value().(uint32) >= 2 - var restoreTokenFilePath string - var cacheDirectory string - var restoreToken string - if supportsRestoreTokens { - cacheDirectory, err = os.UserCacheDir() - if err != nil { - log.Printf("Cannot get user cache directory: %s. Therefore cannot get restore token file path in order to read or save the restore token.\n", err) - } else { - restoreTokenFilePath = filepath.Join(cacheDirectory, "remote_touchpad_portals_restore_token") - restoreTokenBytes, err := os.ReadFile(restoreTokenFilePath) - if err != nil { - log.Printf("Failed to read restore token file: %s\n", err) - } else { - restoreToken = string(restoreTokenBytes) - } + restoreTokenStore, err := func() (*secretStore, error) { + if version.Value().(uint32) < 2 { + return nil, nil } - } else { - log.Println("Portals implementation does not support restore tokens") + cacheDirectory, err := os.UserCacheDir() + if err != nil { + return nil, err + } + if err := os.MkdirAll(cacheDirectory, 0700); err != nil { + return nil, err + } + secret, err := retrieveSecret(bus) + if err != nil { + return nil, err + } + return newSecretStore(secret, + filepath.Join(cacheDirectory, "remote-touchpad.portal-restore-token.bin")) + }() + if err != nil { + log.Printf("Skipping restore token: %v", err) } availableDeviceTypesV, err := remoteDesktop.GetProperty( "org.freedesktop.portal.RemoteDesktop.AvailableDeviceTypes") @@ -148,13 +157,15 @@ func InitPortalController(saveRestoreToken bool) (Controller, error) { sessionHandle := dbus.ObjectPath(sessionHandleS) inVardict = make(map[string]dbus.Variant) inVardict["types"] = dbus.MakeVariant(deviceKeyboard | devicePointer) - if supportsRestoreTokens { - if restoreToken != "" { - inVardict["restore_token"] = dbus.MakeVariant(restoreToken) - } - if saveRestoreToken { - inVardict["persist_mode"] = dbus.MakeVariant(untilRevoked) + if restoreTokenStore != nil { + if restoreToken, err := restoreTokenStore.Load(); err != nil { + if !errors.Is(err, os.ErrNotExist) { + log.Printf("Failed to load restore token: %v", err) + } + } else if len(restoreToken) > 0 { + inVardict["restore_token"] = dbus.MakeVariant(string(restoreToken)) } + inVardict["persist_mode"] = dbus.MakeVariant(untilRevoked) } result, outVardict, err = getResponse(bus, remoteDesktop, "org.freedesktop.portal.RemoteDesktop.SelectDevices", 0, sessionHandle, inVardict) @@ -174,20 +185,9 @@ func InitPortalController(saveRestoreToken bool) (Controller, error) { if result != 0 { return nil, errors.New("keyboard or pointer access denied") } - if supportsRestoreTokens && saveRestoreToken { - restoreToken, ok := outVardict["restore_token"].Value().(string) - if !ok { - log.Println("Failed to get new restore token") - } else if restoreTokenFilePath != "" { - err := os.MkdirAll(cacheDirectory, 0700) - if err != nil { - log.Printf("Failed to create cache directory for restore token: %s\n", err) - } else { - err := os.WriteFile(restoreTokenFilePath, []byte(restoreToken), 0600) - if err != nil { - log.Printf("Failed to write restore token: %s\n", err) - } - } + if restoreToken, _ := outVardict["restore_token"].Value().(string); restoreTokenStore != nil { + if err := restoreTokenStore.Store([]byte(restoreToken)); err != nil { + log.Printf("Failed to store restore token: %v", err) } } devicesV, ok := outVardict["devices"] @@ -208,6 +208,84 @@ func InitPortalController(saveRestoreToken bool) (Controller, error) { sessionHandle: sessionHandle}, nil } +func retrieveSecret(bus *dbus.Conn) ([]byte, error) { + portalDesktop := bus.Object("org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop") + secretReader, secretWriter, err := os.Pipe() + if err != nil { + return nil, err + } + defer secretReader.Close() + defer secretWriter.Close() + if result, _, err := getResponse(bus, portalDesktop, + "org.freedesktop.portal.Secret.RetrieveSecret", 0, + dbus.UnixFD(secretWriter.Fd()), + map[string]dbus.Variant{}, + ); err != nil { + return nil, err + } else if result != 0 { + return nil, fmt.Errorf("calling 'RetrieveSecret' failed (%v)", result) + } + if err := secretWriter.Close(); err != nil { + return nil, err + } + secret, err := io.ReadAll(secretReader) + if err != nil { + return nil, err + } + if len(secret) < 16 { + return nil, fmt.Errorf("'RetrieveSecret' returned too few bytes (%d)", len(secret)) + } + return secret, err +} + +type secretStore struct { + aesgcm cipher.AEAD + filename string +} + +func newSecretStore(key []byte, filename string) (*secretStore, error) { + 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) + if err != nil { + return nil, err + } + aesgcm, err := cipher.NewGCM(block) + if err != nil { + return nil, err + } + return &secretStore{ + aesgcm: aesgcm, + filename: filename, + }, nil +} + +func (s *secretStore) Load() ([]byte, error) { + data, err := os.ReadFile(s.filename) + if err != nil { + return nil, err + } + if len(data) < s.aesgcm.NonceSize() { + return nil, errors.New("invalid ciphertext") + } + nonce := data[:s.aesgcm.NonceSize()] + ciphertext := data[len(nonce):] + return s.aesgcm.Open(nil, nonce, ciphertext, nil) +} + +func (s *secretStore) Store(data []byte) error { + nonce := make([]byte, s.aesgcm.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return err + } + ciphertext := s.aesgcm.Seal(nil, nonce, data, nil) + 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) { ch := make(chan *dbus.Signal, 512) diff --git a/inputcontrol/controller_uinput.go b/inputcontrol/controller_uinput.go index b9723a2..df51e65 100644 --- a/inputcontrol/controller_uinput.go +++ b/inputcontrol/controller_uinput.go @@ -43,7 +43,7 @@ func init() { RegisterController("uinput", InitUinputController, 10) } -func InitUinputController(saveRestoreToken bool) (Controller, error) { +func InitUinputController() (Controller, error) { keymapName, keymapSet := os.LookupEnv("REMOTE_TOUCHPAD_UINPUT_KEYMAP") if !keymapSet { keymapName = "defkeymap" diff --git a/inputcontrol/controller_windows.go b/inputcontrol/controller_windows.go index 0a19556..58b5e9a 100644 --- a/inputcontrol/controller_windows.go +++ b/inputcontrol/controller_windows.go @@ -95,7 +95,7 @@ func init() { RegisterController("Windows", InitWindowsController, 0) } -func InitWindowsController(saveRestoreToken bool) (Controller, error) { +func InitWindowsController() (Controller, error) { p := &windowsController{} if err := sendInputProc.Find(); err != nil { return nil, &UnsupportedPlatformError{err} diff --git a/inputcontrol/controller_x11.go b/inputcontrol/controller_x11.go index 98fcbc4..bb37d37 100644 --- a/inputcontrol/controller_x11.go +++ b/inputcontrol/controller_x11.go @@ -59,7 +59,7 @@ func init() { RegisterController("X11", InitX11Controller, 0) } -func InitX11Controller(saveRestoreToken bool) (Controller, error) { +func InitX11Controller() (Controller, error) { display := C.XOpenDisplay(nil) if display == nil { return nil, &UnsupportedPlatformError{ diff --git a/main.go b/main.go index 44cf381..3d05c7e 100644 --- a/main.go +++ b/main.go @@ -152,7 +152,7 @@ func secureRandBase64(length int) string { func main() { terminal.SetTitle(prettyAppName) var bind, certFile, keyFile, secret string - var showVersion, savePlaintextRestoreToken bool + var showVersion bool var config config flag.BoolVar(&showVersion, "version", false, "show program's version number and exit") flag.StringVar(&bind, "bind", defaultBind, "bind server to [HOSTNAME]:PORT") @@ -164,7 +164,6 @@ func main() { flag.Float64Var(&config.ScrollSpeed, "scroll-speed", 1, "scroll speed multiplier") flag.Float64Var(&config.MouseMoveSpeed, "mouse-move-speed", 1, "mouse move speed multiplier") flag.Float64Var(&config.MouseScrollSpeed, "mouse-scroll-speed", 1, "mouse scroll speed multiplier") - flag.BoolVar(&savePlaintextRestoreToken, "save-plaintext-restore-token", false, "save a restore token in plaintext in order to avoid the confirmation dialogue that appears with some implementations of the portals backend on wayland on linux from appearing on the next run of remote-touchpad") flag.Parse() if showVersion { fmt.Println(version) @@ -189,7 +188,7 @@ func main() { for _, controllerInfo := range inputcontrol.Controllers { controllerName = controllerInfo.Name var err error - controller, err = controllerInfo.Init(savePlaintextRestoreToken) + controller, err = controllerInfo.Init() if err == nil { break } else { From 5771f44b0e5951146f39965bbdb429f671339979 Mon Sep 17 00:00:00 2001 From: Unrud Date: Tue, 18 Mar 2025 09:18:16 +0100 Subject: [PATCH 29/48] Cleanup portal controller --- inputcontrol/controller_portal.go | 151 ++++++++++++++---------------- 1 file changed, 71 insertions(+), 80 deletions(-) diff --git a/inputcontrol/controller_portal.go b/inputcontrol/controller_portal.go index b5a59d2..7ee2f81 100644 --- a/inputcontrol/controller_portal.go +++ b/inputcontrol/controller_portal.go @@ -55,7 +55,7 @@ const ( type portalController struct { bus *dbus.Conn - remoteDesktop dbus.BusObject + portalDesktop dbus.BusObject sessionHandle dbus.ObjectPath } @@ -82,15 +82,21 @@ func InitPortalController() (Controller, error) { if err != nil { return nil, &UnsupportedPlatformError{err} } - remoteDesktop := bus.Object("org.freedesktop.portal.Desktop", + portalDesktop := bus.Object("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop") - version, err := remoteDesktop.GetProperty( + remoteDesktopVersionV, err := portalDesktop.GetProperty( "org.freedesktop.portal.RemoteDesktop.version") if err != nil { - return nil, &UnsupportedPlatformError{err} + return nil, &UnsupportedPlatformError{ + fmt.Errorf("getting 'version' failed: %w", err)} + } + remoteDesktopVersion, ok := remoteDesktopVersionV.Value().(uint32) + if !ok { + return nil, &UnsupportedPlatformError{ + errors.New("unexpected 'version' type")} } restoreTokenStore, err := func() (*secretStore, error) { - if version.Value().(uint32) < 2 { + if remoteDesktopVersion < 2 { return nil, nil } cacheDirectory, err := os.UserCacheDir() @@ -110,92 +116,74 @@ func InitPortalController() (Controller, error) { if err != nil { log.Printf("Skipping restore token: %v", err) } - availableDeviceTypesV, err := remoteDesktop.GetProperty( + availableDeviceTypesV, err := portalDesktop.GetProperty( "org.freedesktop.portal.RemoteDesktop.AvailableDeviceTypes") if err != nil { - return nil, &UnsupportedPlatformError{err} + return nil, &UnsupportedPlatformError{ + fmt.Errorf("getting 'AvailableDeviceTypes' failed: %w", err)} } availableDeviceTypes, ok := availableDeviceTypesV.Value().(uint32) if !ok { return nil, &UnsupportedPlatformError{ errors.New("unexpected 'AvailableDeviceTypes' return type")} } - if availableDeviceTypes&deviceKeyboard == 0 && + if availableDeviceTypes&deviceKeyboard == 0 || availableDeviceTypes&devicePointer == 0 { return nil, &UnsupportedPlatformError{ - errors.New("keyboard and pointer source type not supported")} + errors.New("keyboard or pointer source type not supported")} } - if availableDeviceTypes&deviceKeyboard == 0 { - return nil, &UnsupportedPlatformError{ - errors.New("keyboard source type not supported")} - } - if availableDeviceTypes&devicePointer == 0 { - return nil, &UnsupportedPlatformError{ - errors.New("pointer source type not supported")} - } - inVardict := make(map[string]dbus.Variant) - inVardict["session_handle_token"] = dbus.MakeVariant("t") - result, outVardict, err := getResponse(bus, remoteDesktop, - "org.freedesktop.portal.RemoteDesktop.CreateSession", 0, inVardict) + createSessionResults, err := checkResponse(getResponse(bus, portalDesktop, + "org.freedesktop.portal.RemoteDesktop.CreateSession", 0, + map[string]dbus.Variant{"session_handle_token": dbus.MakeVariant("t")}, + )) if err != nil { - return nil, &UnsupportedPlatformError{err} - } - if result != 0 { return nil, &UnsupportedPlatformError{ - fmt.Errorf("Calling 'CreateSession' failed (%v)", result)} + fmt.Errorf("calling 'CreateSession' failed: %w", err)} } - sessionHandleV, ok := outVardict["session_handle"] - if !ok { - return nil, &UnsupportedPlatformError{ - errors.New("'session_handle' missing from 'CreateSession' return value")} - } - sessionHandleS, ok := sessionHandleV.Value().(string) + sessionHandleString, ok := createSessionResults["session_handle"].Value().(string) if !ok { return nil, &UnsupportedPlatformError{ errors.New("unexpected 'session_handle' type in 'CreateSession' return value")} } - sessionHandle := dbus.ObjectPath(sessionHandleS) - inVardict = make(map[string]dbus.Variant) - inVardict["types"] = dbus.MakeVariant(deviceKeyboard | devicePointer) + sessionHandle := dbus.ObjectPath(sessionHandleString) + selectDevicesOptions := map[string]dbus.Variant{ + "types": dbus.MakeVariant(deviceKeyboard | devicePointer), + } if restoreTokenStore != nil { if restoreToken, err := restoreTokenStore.Load(); err != nil { if !errors.Is(err, os.ErrNotExist) { log.Printf("Failed to load restore token: %v", err) } } else if len(restoreToken) > 0 { - inVardict["restore_token"] = dbus.MakeVariant(string(restoreToken)) + selectDevicesOptions["restore_token"] = dbus.MakeVariant(string(restoreToken)) } - inVardict["persist_mode"] = dbus.MakeVariant(untilRevoked) + selectDevicesOptions["persist_mode"] = dbus.MakeVariant(untilRevoked) } - result, outVardict, err = getResponse(bus, remoteDesktop, - "org.freedesktop.portal.RemoteDesktop.SelectDevices", 0, sessionHandle, inVardict) + _, err = checkResponse(getResponse(bus, portalDesktop, + "org.freedesktop.portal.RemoteDesktop.SelectDevices", 0, + sessionHandle, selectDevicesOptions, + )) if err != nil { - return nil, &UnsupportedPlatformError{err} - } - if result != 0 { return nil, &UnsupportedPlatformError{ - fmt.Errorf("Calling 'SelectDevices' failed (%v)", result)} + fmt.Errorf("calling 'SelectDevices' failed: %w", err)} } - inVardict = make(map[string]dbus.Variant) - result, outVardict, err = getResponse(bus, remoteDesktop, - "org.freedesktop.portal.RemoteDesktop.Start", 0, sessionHandle, "", inVardict) + startResponseStatus, startResults, err := getResponse(bus, portalDesktop, + "org.freedesktop.portal.RemoteDesktop.Start", 0, + sessionHandle, "", map[string]dbus.Variant{}, + ) if err != nil { - return nil, &UnsupportedPlatformError{err} + return nil, &UnsupportedPlatformError{ + fmt.Errorf("calling 'Start' failed: %w", err)} } - if result != 0 { + if startResponseStatus != 0 { return nil, errors.New("keyboard or pointer access denied") } - if restoreToken, _ := outVardict["restore_token"].Value().(string); restoreTokenStore != nil { + if restoreToken, _ := startResults["restore_token"].Value().(string); restoreTokenStore != nil { if err := restoreTokenStore.Store([]byte(restoreToken)); err != nil { log.Printf("Failed to store restore token: %v", err) } } - devicesV, ok := outVardict["devices"] - if !ok { - return nil, &UnsupportedPlatformError{ - errors.New("'devices' missing from 'Start' return value")} - } - devices, ok := devicesV.Value().(uint32) + devices, ok := startResults["devices"].Value().(uint32) if !ok { return nil, &UnsupportedPlatformError{ errors.New("unexpected 'devices' type in 'Start' return value")} @@ -204,7 +192,7 @@ func InitPortalController() (Controller, error) { return nil, errors.New("keyboard or pointer access denied") } cleanupBus = false - return &portalController{bus: bus, remoteDesktop: remoteDesktop, + return &portalController{bus: bus, portalDesktop: portalDesktop, sessionHandle: sessionHandle}, nil } @@ -217,14 +205,11 @@ func retrieveSecret(bus *dbus.Conn) ([]byte, error) { } defer secretReader.Close() defer secretWriter.Close() - if result, _, err := getResponse(bus, portalDesktop, + if _, err := checkResponse(getResponse(bus, portalDesktop, "org.freedesktop.portal.Secret.RetrieveSecret", 0, - dbus.UnixFD(secretWriter.Fd()), - map[string]dbus.Variant{}, - ); err != nil { - return nil, err - } else if result != 0 { - return nil, fmt.Errorf("calling 'RetrieveSecret' failed (%v)", result) + dbus.UnixFD(secretWriter.Fd()), map[string]dbus.Variant{}, + )); err != nil { + return nil, fmt.Errorf("calling 'RetrieveSecret' failed: %w", err) } if err := secretWriter.Close(); err != nil { return nil, err @@ -299,32 +284,39 @@ func getResponse(bus *dbus.Conn, object dbus.BusObject, method string, s := <-ch if s.Path == requestPath && s.Name == "org.freedesktop.portal.Request.Response" { if len(s.Body) != 2 { - return 0, nil, errors.New("unexpected 'Response' return length") + return 0, nil, fmt.Errorf("unexpected 'Response' return length (%d)", len(s.Body)) } - result, ok := s.Body[0].(uint32) + responseStatus, ok := s.Body[0].(uint32) if !ok { return 0, nil, errors.New("unexpected 'Response' return type") } - outVardict, ok := s.Body[1].(map[string]dbus.Variant) + results, ok := s.Body[1].(map[string]dbus.Variant) if !ok { return 0, nil, errors.New("unexpected 'Response' return type") } - return result, outVardict, nil + return responseStatus, results, nil } } } +func checkResponse(responseStatus uint32, results map[string]dbus.Variant, err error) (map[string]dbus.Variant, error) { + if err == nil && responseStatus != 0 { + err = fmt.Errorf("unexpected 'Response' status (%d)", responseStatus) + } + return results, err +} + func (p *portalController) Close() error { return p.bus.Close() } func (p *portalController) keyboardKeys(keys []Keysym) error { - inVardict := make(map[string]dbus.Variant) for _, keysym := range keys { for _, state := range [...]uint32{btnPressed, btnReleased} { - if err := p.remoteDesktop.Call( - "org.freedesktop.portal.RemoteDesktop.NotifyKeyboardKeysym", - 0, p.sessionHandle, inVardict, keysym, state).Store(); err != nil { + if err := p.portalDesktop.Call( + "org.freedesktop.portal.RemoteDesktop.NotifyKeyboardKeysym", 0, + p.sessionHandle, map[string]dbus.Variant{}, keysym, state, + ).Store(); err != nil { return err } } @@ -369,28 +361,27 @@ func (p *portalController) PointerButton(button PointerButton, press bool) error if press { state = btnPressed } - inVardict := make(map[string]dbus.Variant) - if err := p.remoteDesktop.Call("org.freedesktop.portal.RemoteDesktop.NotifyPointerButton", - 0, p.sessionHandle, inVardict, btn, state).Store(); err != nil { + if err := p.portalDesktop.Call("org.freedesktop.portal.RemoteDesktop.NotifyPointerButton", 0, + p.sessionHandle, map[string]dbus.Variant{}, btn, state, + ).Store(); err != nil { return err } return nil } func (p *portalController) PointerMove(deltaX, deltaY int) error { - inVardict := make(map[string]dbus.Variant) - if err := p.remoteDesktop.Call("org.freedesktop.portal.RemoteDesktop.NotifyPointerMotion", - 0, p.sessionHandle, inVardict, float64(deltaX), float64(deltaY)).Store(); err != nil { + if err := p.portalDesktop.Call("org.freedesktop.portal.RemoteDesktop.NotifyPointerMotion", 0, + p.sessionHandle, map[string]dbus.Variant{}, float64(deltaX), float64(deltaY), + ).Store(); err != nil { return err } return nil } func (p *portalController) PointerScroll(deltaHorizontal, deltaVertical int, finish bool) error { - inVardict := make(map[string]dbus.Variant) - inVardict["finish"] = dbus.MakeVariant(finish) - if err := p.remoteDesktop.Call("org.freedesktop.portal.RemoteDesktop.NotifyPointerAxis", - 0, p.sessionHandle, inVardict, float64(deltaHorizontal), float64(deltaVertical)).Store(); err != nil { + if err := p.portalDesktop.Call("org.freedesktop.portal.RemoteDesktop.NotifyPointerAxis", 0, + p.sessionHandle, map[string]dbus.Variant{"finish": dbus.MakeVariant(finish)}, float64(deltaHorizontal), float64(deltaVertical), + ).Store(); err != nil { return err } return nil From d48d9aed3da33cbbd70f0eaf2c752490d8b72ee5 Mon Sep 17 00:00:00 2001 From: Unrud Date: Tue, 18 Mar 2025 22:02:15 +0100 Subject: [PATCH 30/48] Bump version to 1.5.0 --- CHANGELOG.md | 5 +++++ .../com.github.unrud.RemoteTouchpad.metainfo.xml | 16 ++++++++++++---- main.go | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d03509..6e06388 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 1.5.0 (2025-03-18) + +* Add restore token support for the remote desktop portal +* Update dependencies + ## 1.4.8 (2024-09-01) * Update dependencies diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index 116e8d6..f8affb0 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -23,6 +23,14 @@ Unrud + + +
            +
          • Add restore token support for the remote desktop portal
          • +
          • Update dependencies
          • +
          +
          +
            @@ -343,16 +351,16 @@ - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.8/screenshots/1.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.0/screenshots/1.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.8/screenshots/2.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.0/screenshots/2.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.8/screenshots/3.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.0/screenshots/3.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.4.8/screenshots/4.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.0/screenshots/4.png diff --git a/main.go b/main.go index 3d05c7e..a70e488 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,7 @@ const ( authenticationRateBurst int = 10 challengeLength int = 8 defaultBind string = ":0" - version string = "1.4.8" + version string = "1.5.0" prettyAppName string = "Remote Touchpad" ) From 06674b224f6f1b012a3c30533130843eed907eab Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 12 Oct 2025 06:26:11 +0200 Subject: [PATCH 31/48] Update dependencies --- flatpak/com.github.unrud.RemoteTouchpad.yaml | 10 +++++----- go.mod | 8 ++++---- go.sum | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/flatpak/com.github.unrud.RemoteTouchpad.yaml b/flatpak/com.github.unrud.RemoteTouchpad.yaml index 55bb828..54e8e97 100644 --- a/flatpak/com.github.unrud.RemoteTouchpad.yaml +++ b/flatpak/com.github.unrud.RemoteTouchpad.yaml @@ -1,6 +1,6 @@ app-id: com.github.unrud.RemoteTouchpad runtime: org.freedesktop.Platform -runtime-version: '24.08' +runtime-version: '25.08' sdk: org.freedesktop.Sdk command: remote-touchpad sdk-extensions: @@ -26,13 +26,13 @@ modules: dest: vendor/github.com/skip2/go-qrcode - type: git url: https://github.com/golang/net - tag: v0.37.0 - commit: 99b3ae0643f9a2f9d820fcbba5f9e4c83b23bd48 + tag: v0.46.0 + commit: 2002a064a49010d8b881673c73f04e0b741e7c32 dest: vendor/golang.org/x/net - type: git url: https://github.com/golang/crypto - tag: v0.36.0 - commit: 49bf5b80c8108983f588ecabd7bf996e6e63a515 + tag: v0.43.0 + commit: 627cb894b6b2021e34c4ad4af4c0a963127491e4 dest: vendor/golang.org/x/crypto - type: file path: modules.txt diff --git a/go.mod b/go.mod index 1f2549c..75e1e34 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,13 @@ module github.com/unrud/remote-touchpad -go 1.23.0 +go 1.24.0 -toolchain go1.23.7 +toolchain go1.24.8 require ( github.com/bendahl/uinput v1.7.0 github.com/godbus/dbus/v5 v5.1.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - golang.org/x/crypto v0.36.0 - golang.org/x/net v0.37.0 + golang.org/x/crypto v0.43.0 + golang.org/x/net v0.46.0 ) diff --git a/go.sum b/go.sum index a03440b..736cffa 100644 --- a/go.sum +++ b/go.sum @@ -4,7 +4,7 @@ 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/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +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= From 1add8e4cb8c204020fa0a3f1f6267c5edc3a5bcb Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 12 Oct 2025 06:26:29 +0200 Subject: [PATCH 32/48] Bump version to 1.5.1 --- .../com.github.unrud.RemoteTouchpad.metainfo.xml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index f8affb0..9e2c36b 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -23,6 +23,13 @@ Unrud + + +
              +
            • Update dependencies
            • +
            +
            +
              @@ -351,16 +358,16 @@ - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.0/screenshots/1.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.1/screenshots/1.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.0/screenshots/2.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.1/screenshots/2.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.0/screenshots/3.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.1/screenshots/3.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.0/screenshots/4.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.1/screenshots/4.png From 2b3d5c5bf318fc41b0b54aa2864056572d56b779 Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 12 Oct 2025 06:42:46 +0200 Subject: [PATCH 33/48] Flatpak: Update modules.txt --- flatpak/modules.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flatpak/modules.txt b/flatpak/modules.txt index 6662b65..cb7ea3f 100644 --- a/flatpak/modules.txt +++ b/flatpak/modules.txt @@ -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/crypto v0.36.0 -## explicit; go 1.23.0 +# golang.org/x/crypto v0.43.0 +## explicit; go 1.24.0 golang.org/x/crypto/hkdf -# golang.org/x/net v0.37.0 -## explicit; go 1.23.0 +# golang.org/x/net v0.46.0 +## explicit; go 1.24.0 golang.org/x/net/websocket From 800171efdd86160d4676967459101155ff053faa Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 12 Oct 2025 06:45:35 +0200 Subject: [PATCH 34/48] Bump version to 1.5.2 --- CHANGELOG.md | 4 ++++ desktop/com.github.unrud.RemoteTouchpad.metainfo.xml | 10 +++++----- main.go | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e06388..8df847c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.5.2 (2025-10-12) + +* Update dependencies + ## 1.5.0 (2025-03-18) * Add restore token support for the remote desktop portal diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index 9e2c36b..9c85e89 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -23,7 +23,7 @@ Unrud - +
              • Update dependencies
              • @@ -358,16 +358,16 @@ - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.1/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.1/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.1/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.1/screenshots/4.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.2/screenshots/4.png diff --git a/main.go b/main.go index a70e488..5a6da17 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,7 @@ const ( authenticationRateBurst int = 10 challengeLength int = 8 defaultBind string = ":0" - version string = "1.5.0" + version string = "1.5.2" prettyAppName string = "Remote Touchpad" ) From eebde588268253d0789081ec851820664bb891cf Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 24 Dec 2025 22:57:01 +0100 Subject: [PATCH 35/48] Update dependencies --- flatpak/com.github.unrud.RemoteTouchpad.yaml | 16 ++++++++-------- flatpak/modules.txt | 12 ++++++------ go.mod | 11 +++++------ go.sum | 12 ++++++------ inputcontrol/controller_portal.go | 7 +++---- 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/flatpak/com.github.unrud.RemoteTouchpad.yaml b/flatpak/com.github.unrud.RemoteTouchpad.yaml index 54e8e97..48eef40 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.1.0 - commit: e523abc905595cf17fb0001a7d77eaaddfaa216d + tag: v5.2.1 + commit: 20d95a3d9a57a5cb72cbdafb3fd9ecb6d2ccd038 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.46.0 - commit: 2002a064a49010d8b881673c73f04e0b741e7c32 + tag: v0.48.0 + commit: 35e1306bddd863f360fb94480c5fed84229953f0 dest: vendor/golang.org/x/net - type: git - url: https://github.com/golang/crypto - tag: v0.43.0 - commit: 627cb894b6b2021e34c4ad4af4c0a963127491e4 - dest: vendor/golang.org/x/crypto + url: https://github.com/golang/sys + tag: v0.39.0 + commit: 08e54827f6706016347e1e4f4866b84126842b20 + dest: vendor/golang.org/x/sys - type: file path: modules.txt dest: vendor diff --git a/flatpak/modules.txt b/flatpak/modules.txt index cb7ea3f..fec832d 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.1.0 -## explicit; go 1.12 +# github.com/godbus/dbus/v5 v5.2.1 +## explicit; go 1.20 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/crypto v0.43.0 -## explicit; go 1.24.0 -golang.org/x/crypto/hkdf -# golang.org/x/net v0.46.0 +# golang.org/x/net v0.48.0 ## explicit; go 1.24.0 golang.org/x/net/websocket +# golang.org/x/sys v0.39.0 +## explicit; go 1.24.0 +golang.org/x/sys/unix diff --git a/go.mod b/go.mod index 75e1e34..ea1c480 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,12 @@ module github.com/unrud/remote-touchpad -go 1.24.0 - -toolchain go1.24.8 +go 1.25.5 require ( github.com/bendahl/uinput v1.7.0 - github.com/godbus/dbus/v5 v5.1.0 + github.com/godbus/dbus/v5 v5.2.1 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - golang.org/x/crypto v0.43.0 - golang.org/x/net v0.46.0 + golang.org/x/net v0.48.0 ) + +require golang.org/x/sys v0.39.0 // indirect diff --git a/go.sum b/go.sum index 736cffa..801ae05 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.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +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/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/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= +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= diff --git a/inputcontrol/controller_portal.go b/inputcontrol/controller_portal.go index 7ee2f81..6f38407 100644 --- a/inputcontrol/controller_portal.go +++ b/inputcontrol/controller_portal.go @@ -24,6 +24,7 @@ package inputcontrol import ( "crypto/aes" "crypto/cipher" + "crypto/hkdf" "crypto/rand" "crypto/sha256" "errors" @@ -35,7 +36,6 @@ import ( "slices" "github.com/godbus/dbus/v5" - "golang.org/x/crypto/hkdf" ) const ( @@ -230,9 +230,8 @@ type secretStore struct { } func newSecretStore(key []byte, filename string) (*secretStore, error) { - hkdf := hkdf.New(sha256.New, key, nil, nil) - derivedKey := make([]byte, 32) - if _, err := io.ReadFull(hkdf, derivedKey); err != nil { + derivedKey, err := hkdf.Key(sha256.New, key, nil, "", 32) + if err != nil { return nil, err } block, err := aes.NewCipher(derivedKey) From a2dfa7ac47b5f050e5e066b46f1eb6e64213c867 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 24 Dec 2025 22:59:32 +0100 Subject: [PATCH 36/48] Bump version to 1.5.3 --- CHANGELOG.md | 4 ++++ .../com.github.unrud.RemoteTouchpad.metainfo.xml | 15 +++++++++++---- main.go | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8df847c..d3ec422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.5.3 (2025-12-24) + +* Update dependencies + ## 1.5.2 (2025-10-12) * Update dependencies diff --git a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml index 9c85e89..14b1574 100644 --- a/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml +++ b/desktop/com.github.unrud.RemoteTouchpad.metainfo.xml @@ -23,6 +23,13 @@ Unrud + + +
                  +
                • Update dependencies
                • +
                +
                +
                  @@ -358,16 +365,16 @@ - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.2/screenshots/1.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.3/screenshots/1.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.2/screenshots/2.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.3/screenshots/2.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.2/screenshots/3.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.3/screenshots/3.png - https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.2/screenshots/4.png + https://raw.githubusercontent.com/Unrud/remote-touchpad/v1.5.3/screenshots/4.png diff --git a/main.go b/main.go index 5a6da17..d4d43e9 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,7 @@ const ( authenticationRateBurst int = 10 challengeLength int = 8 defaultBind string = ":0" - version string = "1.5.2" + version string = "1.5.3" prettyAppName string = "Remote Touchpad" ) From a30bed46242a15c0219b09b353568e2d1be8e323 Mon Sep 17 00:00:00 2001 From: Unrud Date: Sat, 11 Jul 2026 20:20:03 +0200 Subject: [PATCH 37/48] Snap: Update to core24 --- snap/snapcraft.yaml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 677f302..8cecb86 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,15 +1,15 @@ -# 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 apps: @@ -48,10 +48,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 From 996edb05017136ab0a72e6b364b60dccfadf8a33 Mon Sep 17 00:00:00 2001 From: Unrud Date: Sat, 11 Jul 2026 20:59:03 +0200 Subject: [PATCH 38/48] Snap: Specifiy supported platforms --- snap/snapcraft.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 8cecb86..6d23326 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -12,6 +12,10 @@ adopt-info: remote-touchpad base: core24 confinement: strict +platforms: + amd64: + arm64: + apps: remote-touchpad: command: bin/remote-touchpad From 1aa8f92cc8755dc55b4bbc584129d0b3567100b7 Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 2 Aug 2026 11:15:23 +0200 Subject: [PATCH 39/48] Use range over integers --- inputcontrol/controller_x11.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/inputcontrol/controller_x11.go b/inputcontrol/controller_x11.go index bb37d37..093ea2b 100644 --- a/inputcontrol/controller_x11.go +++ b/inputcontrol/controller_x11.go @@ -125,7 +125,7 @@ func (p *x11Controller) findEmptyKeycodeLocked() (C.KeyCode, C.int, error) { defer C.XFree(unsafe.Pointer(keysyms)) keycodes: for keycode := C.KeyCode(minKeycodes); keycode <= C.KeyCode(maxKeycodes); keycode++ { - for i := 0; i < int(keysymsPerKeycode); i++ { + for i := range int(keysymsPerKeycode) { keysymsIndex := int(keycode- C.KeyCode(minKeycodes))*int(keysymsPerKeycode) + i keysym := *(*C.KeySym)(unsafe.Pointer(uintptr(unsafe.Pointer(keysyms)) + @@ -155,7 +155,7 @@ func (p *x11Controller) getModKeycodesLocked() map[uint]C.KeyCode { defer C.XFreeModifiermap(modKeymap) modKeycodes := make(map[uint]C.KeyCode) for _, modIndex := range modifierIndices { - for i := 0; i < int(modKeymap.max_keypermod); i++ { + for i := range int(modKeymap.max_keypermod) { keycode := *(*C.KeyCode)(unsafe.Pointer(uintptr(unsafe.Pointer(modKeymap.modifiermap)) + uintptr(uint(modIndex)*uint(modKeymap.max_keypermod)+uint(i)))) if keycode != 0 { @@ -354,7 +354,7 @@ func (p *x11Controller) PointerScroll(deltaHorizontal, deltaVertical int, finish buttonHorizontal = 6 stepsHorizontal = -stepsHorizontal } - for i := 0; i < stepsHorizontal; i++ { + for range stepsHorizontal { if err := p.sendButton(buttonHorizontal, true); err != nil { return err } @@ -367,7 +367,7 @@ func (p *x11Controller) PointerScroll(deltaHorizontal, deltaVertical int, finish buttonVertical = 4 stepsVertical = -stepsVertical } - for i := 0; i < stepsVertical; i++ { + for range stepsVertical { if err := p.sendButton(buttonVertical, true); err != nil { return err } From 85b6d6ea9d6669d0eac240db50a2b45df37450f9 Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 2 Aug 2026 12:40:05 +0200 Subject: [PATCH 40/48] X11: Use XSync to improve reliability --- inputcontrol/controller_x11.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/inputcontrol/controller_x11.go b/inputcontrol/controller_x11.go index 093ea2b..5ba9179 100644 --- a/inputcontrol/controller_x11.go +++ b/inputcontrol/controller_x11.go @@ -147,7 +147,7 @@ func (p *x11Controller) changeKeyMappingLocked(keysymsPerKeycode C.int, } C.XChangeKeyboardMapping(p.display, C.int(keycode), keysymsPerKeycode, (*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])), 1) - C.XFlush(p.display) + C.XSync(p.display, C.False) } func (p *x11Controller) getModKeycodesLocked() map[uint]C.KeyCode { @@ -236,7 +236,6 @@ func (p *x11Controller) keyboardKeys(keys []Keysym) error { var root, child C.Window var rootX, rootY, x, y C.int var activeMods C.uint - C.XSync(p.display, C.False) C.XQueryPointer(p.display, rootWindow, &root, &child, &rootX, &rootY, &x, &y, &activeMods) keycode, mods := p.findKeycodeLocked(keyboard, modKeycodes, activeMods, @@ -265,7 +264,7 @@ func (p *x11Controller) keyboardKeys(keys []Keysym) error { C.XTestFakeKeyEvent(p.display, C.uint(keycode), C.False, 0) p.sendModsLocked(modKeycodes, pressMods, false) p.sendModsLocked(modKeycodes, releaseMods, true) - C.XFlush(p.display) + C.XSync(p.display, C.False) if keycode == emptyKeycode { // race condition! time.Sleep(keyboardMappingDelay) @@ -309,7 +308,7 @@ func (p *x11Controller) sendButton(button uint, press bool) error { pressC = C.True } C.XTestFakeButtonEvent(p.display, C.uint(button), pressC, 0) - C.XFlush(p.display) + C.XSync(p.display, C.False) return nil } @@ -333,7 +332,7 @@ func (p *x11Controller) PointerMove(deltaX, deltaY int) error { return errors.New("X server connection closed") } C.XTestFakeRelativeMotionEvent(p.display, C.int(deltaX), C.int(deltaY), 0) - C.XFlush(p.display) + C.XSync(p.display, C.False) return nil } From 6ef2be87767de56e6465f742d3eeb9033c0aa405 Mon Sep 17 00:00:00 2001 From: Unrud Date: Sun, 2 Aug 2026 22:12:27 +0200 Subject: [PATCH 41/48] Format code --- host.go | 3 ++- inputcontrol/controller.go | 6 +++-- inputcontrol/controller_portal.go | 43 ++++++++++++++++++++----------- inputcontrol/controller_uinput.go | 3 ++- inputcontrol/controller_x11.go | 22 +++++++++++----- main.go | 7 ++--- 6 files changed, 55 insertions(+), 29 deletions(-) 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 5ba9179..179eafc 100644 --- a/inputcontrol/controller_x11.go +++ b/inputcontrol/controller_x11.go @@ -32,6 +32,7 @@ package inputcontrol // return DefaultRootWindow(dpy); // } import "C" + import ( "errors" "fmt" @@ -46,8 +47,10 @@ const ( scrollDiv int = 20 ) -var modifierIndices [6]uint = [...]uint{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 @@ -63,13 +66,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 } @@ -140,7 +145,8 @@ keycodes: } func (p *x11Controller) changeKeyMappingLocked(keysymsPerKeycode C.int, - keycode C.KeyCode, keysym Keysym) { + keycode C.KeyCode, keysym Keysym, +) { keycodeMapping := make([]C.KeySym, keysymsPerKeycode) for i := range keycodeMapping { keycodeMapping[i] = C.KeySym(keysym) @@ -169,7 +175,8 @@ func (p *x11Controller) getModKeycodesLocked() map[uint]C.KeyCode { func (p *x11Controller) findKeycodeLocked(keyboard C.XkbDescPtr, modKeycodes map[uint]C.KeyCode, activeMods C.uint, - keysym Keysym) (C.KeyCode, C.uint) { + keysym Keysym, +) (C.KeyCode, C.uint) { keycode := C.XKeysymToKeycode(p.display, C.KeySym(keysym)) if keycode == 0 { return 0, 0 @@ -204,7 +211,8 @@ func (p *x11Controller) findKeycodeLocked(keyboard C.XkbDescPtr, } func (p *x11Controller) sendModsLocked(modKeycodes map[uint]C.KeyCode, mods C.uint, - press bool) { + press bool, +) { var pressC C.int = C.False if press { pressC = C.True diff --git a/main.go b/main.go index d4d43e9..dc6ad1a 100644 --- a/main.go +++ b/main.go @@ -27,9 +27,6 @@ import ( "errors" "flag" "fmt" - "github.com/unrud/remote-touchpad/inputcontrol" - "github.com/unrud/remote-touchpad/terminal" - "golang.org/x/net/websocket" "log" mathrand "math/rand" "net" @@ -39,6 +36,10 @@ import ( "strings" "time" "unicode/utf8" + + "github.com/unrud/remote-touchpad/inputcontrol" + "github.com/unrud/remote-touchpad/terminal" + "golang.org/x/net/websocket" ) const ( From 346d9cf3752e1dca5546eb59e860a85ddf215f7f Mon Sep 17 00:00:00 2001 From: Unrud Date: Mon, 3 Aug 2026 00:32:33 +0200 Subject: [PATCH 42/48] X11: Cleanup code --- inputcontrol/controller_x11.go | 115 ++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 46 deletions(-) diff --git a/inputcontrol/controller_x11.go b/inputcontrol/controller_x11.go index 179eafc..8e40c5c 100644 --- a/inputcontrol/controller_x11.go +++ b/inputcontrol/controller_x11.go @@ -47,9 +47,13 @@ const ( 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 { @@ -118,41 +122,52 @@ 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 := range int(keysymsPerKeycode) { - 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.XChangeKeyboardMapping( + p.display, + C.int(keycode), + C.int(keysymsPerKeycode), + (*C.KeySym)(unsafe.Pointer(&keycodeMapping[0])), + 1, + ) C.XSync(p.display, C.False) } @@ -160,12 +175,15 @@ 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 _, modIndex := range modifierIndexes { for i := range int(modKeymap.max_keypermod) { - keycode := *(*C.KeyCode)(unsafe.Pointer(uintptr(unsafe.Pointer(modKeymap.modifiermap)) + - uintptr(uint(modIndex)*uint(modKeymap.max_keypermod)+uint(i)))) + 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< Date: Mon, 3 Aug 2026 00:32:34 +0200 Subject: [PATCH 43/48] X11: Minimize mod changes --- inputcontrol/controller_x11.go | 36 ++++++++++++---------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/inputcontrol/controller_x11.go b/inputcontrol/controller_x11.go index 8e40c5c..2206df4 100644 --- a/inputcontrol/controller_x11.go +++ b/inputcontrol/controller_x11.go @@ -36,6 +36,8 @@ import "C" import ( "errors" "fmt" + "maps" + "slices" "strings" "sync" "time" @@ -198,31 +200,19 @@ func (p *x11Controller) findKeycodeLocked( if keycode == 0 { return 0, 0 } - var alwaysActiveMods uint - for _, modIndex := range modifierIndexes { - mod := uint(1) << modIndex - if _, modAvailable := modKeycodes[mod]; !modAvailable { - alwaysActiveMods |= activeMods & mod - } - } - _, shiftModAvailable := modKeycodes[C.ShiftMask] - for _, modIndex := range modifierIndexes { - var mod uint - if modIndex != C.ShiftMapIndex { - mod = 1 << modIndex - } - for _, shiftMod := range [...]uint{0, C.ShiftMask} { - if shiftMod != 0 && !shiftModAvailable { - continue - } - mods := alwaysActiveMods | shiftMod | mod - var retMods C.uint - var retKeysym C.KeySym - C.XkbTranslateKeyCode(keyboard, keycode, C.uint(mods), &retMods, &retKeysym) - if retKeysym == C.KeySym(keysym) { - return keycode, mods + for activeModBitmap := range uint(1) << len(modKeycodes) { + mods := activeMods + for i, mod := range slices.Sorted(maps.Keys(modKeycodes)) { + if activeModBitmap&(1< Date: Mon, 3 Aug 2026 00:32:34 +0200 Subject: [PATCH 44/48] X11: Reduce delay when mapping new keys Reliability is improved by XSync --- inputcontrol/controller_x11.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/inputcontrol/controller_x11.go b/inputcontrol/controller_x11.go index 2206df4..f45b75b 100644 --- a/inputcontrol/controller_x11.go +++ b/inputcontrol/controller_x11.go @@ -45,7 +45,7 @@ import ( ) const ( - keyboardMappingDelay time.Duration = 500 * time.Millisecond + keyboardMappingDelay time.Duration = 200 * time.Millisecond scrollDiv int = 20 ) @@ -273,8 +273,6 @@ func (p *x11Controller) keyboardKeys(keys []Keysym) error { } keycode = emptyKeycode p.changeKeyMappingLocked(keycode, keysymsPerKeycode, keysym) - // race condition! - time.Sleep(keyboardMappingDelay) } else { pressMods = mods & ^activeMods releaseMods = activeMods & ^mods From 9764d1975d9aa68e77510105117c543b4350f944 Mon Sep 17 00:00:00 2001 From: Unrud Date: Mon, 3 Aug 2026 00:32:34 +0200 Subject: [PATCH 45/48] Update dependencies --- flatpak/com.github.unrud.RemoteTouchpad.yaml | 12 ++++++------ flatpak/modules.txt | 10 +++++----- go.mod | 6 +++--- go.sum | 12 ++++++------ 4 files changed, 20 insertions(+), 20 deletions(-) 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= From a77f3aa8ecf8b38f789d7a8ddefcb9cc4407d0fc Mon Sep 17 00:00:00 2001 From: Unrud Date: Mon, 3 Aug 2026 00:32:35 +0200 Subject: [PATCH 46/48] Bump version to 1.5.4 --- CHANGELOG.md | 5 +++++ .../com.github.unrud.RemoteTouchpad.metainfo.xml | 16 ++++++++++++---- main.go | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) 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/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/main.go b/main.go index dc6ad1a..f8db693 100644 --- a/main.go +++ b/main.go @@ -48,7 +48,7 @@ const ( authenticationRateBurst int = 10 challengeLength int = 8 defaultBind string = ":0" - version string = "1.5.3" + version string = "1.5.4" prettyAppName string = "Remote Touchpad" ) From ed7e8bae543324bdd6faf0fa614142b471eb5770 Mon Sep 17 00:00:00 2001 From: Luka Jankovic Date: Fri, 14 Aug 2026 21:59:58 +0200 Subject: [PATCH 47/48] Add systemd user service and CLI wrapper for remote-touchpad This commit introduces a complete systemd user service setup for remote-touchpad, eliminating the need for users to manually manage the binary process. Key additions: - New rts CLI wrapper script providing a user-friendly interface for service management without requiring root access - Systemd service file for proper background operation with restart policies and dependency management - Service management commands: install, start, stop, status, restart, and uninstall - URL extraction and QR code generation via the url command - Service log viewing via the log command The installation process now: 1. Verifies Go is installed 2. Builds the remote-touchpad binary with appropriate tags 3. Installs service files to ~/.config/systemd/user/ 4. Installs the binary to ~/.local/bin/ 5. Enables and starts the service automatically The README has been updated with comprehensive installation instructions for the new user service approach. --- README.md | 29 ++++++++ remote-touchpad.service | 12 ++++ rts | 149 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 remote-touchpad.service create mode 100755 rts 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/remote-touchpad.service b/remote-touchpad.service new file mode 100644 index 0000000..76f5a74 --- /dev/null +++ b/remote-touchpad.service @@ -0,0 +1,12 @@ +[Unit] +Description=Remote Touchpad Service +After=network.target + +[Service] +Type=simple +ExecStart=%h/.local/bin/remote-touchpad +Restart=always +RestartSec=5s + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/rts b/rts new file mode 100755 index 0000000..84fbe46 --- /dev/null +++ b/rts @@ -0,0 +1,149 @@ +#!/bin/bash + +# Remote Touchpad CLI Wrapper +# Provides easy access to remote-touchpad service + +SERVICE_NAME="remote-touchpad" +SERVICE_USER="$USER" + +install() { + echo "Installing remote-touchpad as a user systemd service..." + + # Check if Go is installed + if ! command -v go &> /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 From 2ac00c3b483720085e7fb686967490f9089c9e62 Mon Sep 17 00:00:00 2001 From: Luka Jankovic Date: Fri, 14 Aug 2026 22:01:02 +0200 Subject: [PATCH 48/48] Updated gitignore --- .gitignore | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .gitignore 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