{"id":50840561,"url":"https://github.com/eondcom/kensington-trackball-linux","last_synced_at":"2026-06-14T06:32:13.185Z","repository":{"id":361620837,"uuid":"1255151126","full_name":"eondcom/kensington-trackball-linux","owner":"eondcom","description":"Kensington trackball button mapper for Linux/Wayland (Pop!_OS COSMIC) — remap buttons to browser back/forward, key combos, commands, chords, ball-speed; evdev/uinput daemon + GTK GUI","archived":false,"fork":false,"pushed_at":"2026-05-31T13:32:01.000Z","size":147,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T15:16:34.555Z","etag":null,"topics":["cosmic","evdev","gtk","input-remapper","kensington","linux","popos","trackball","uinput","wayland"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eondcom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-31T13:23:59.000Z","updated_at":"2026-05-31T13:32:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/eondcom/kensington-trackball-linux","commit_stats":null,"previous_names":["eondcom/kensington-trackball-linux"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/eondcom/kensington-trackball-linux","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eondcom%2Fkensington-trackball-linux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eondcom%2Fkensington-trackball-linux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eondcom%2Fkensington-trackball-linux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eondcom%2Fkensington-trackball-linux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eondcom","download_url":"https://codeload.github.com/eondcom/kensington-trackball-linux/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eondcom%2Fkensington-trackball-linux/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34312071,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-14T02:00:07.365Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cosmic","evdev","gtk","input-remapper","kensington","linux","popos","trackball","uinput","wayland"],"created_at":"2026-06-14T06:32:12.490Z","updated_at":"2026-06-14T06:32:13.180Z","avatar_url":"https://github.com/eondcom.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ktrackball — Kensington trackball button mapper (Pop!_OS / Wayland)\n\nA lightweight `evdev`/`uinput` daemon that remaps the buttons of a Kensington\ntrackball to actions — browser **Back/Forward**, key combos, commands, ball-scroll,\nor a precision mode. It works at the kernel level, so it runs under **Wayland**\n(Pop!_OS COSMIC) where X11 tools like `xinput`/`xdotool` do not.\n\nBuilt for: `Kensington Expert Wireless Trackball (047d:8018)` on Pop!_OS 24.04 COSMIC.\n\n![ktrackball GUI](docs/screenshot.png)\n\n## How it works\n\n1. Grabs the trackball's pointer event device **exclusively** (`EVIOCGRAB`).\n2. Creates a virtual `uinput` device that forwards normal motion + scrolling.\n3. Each configured physical button is translated into an action instead of (or\n   in addition to) its normal click.\n\nBecause actions like *Back* are sent as kernel-level keystrokes (`Alt+Left`),\nthey work in any app/compositor.\n\n## Install\n\n```bash\ncd ~/kensington-trackball\nsudo ./install.sh\n```\n\nThe installer: installs `python3-evdev`, loads `uinput`, copies the daemon to\n`/opt/ktrackball`, the config to `/etc/ktrackball/config.toml`, and enables a\nsystemd service that starts at boot.\n\n## Map your buttons\n\nThe 4 corner buttons may not be the codes you expect — confirm them:\n\n```bash\nsudo systemctl stop ktrackball          # release the device\nsudo python3 /opt/ktrackball/trackball_mapper.py learn \\\n     --config /etc/ktrackball/config.toml\n# press each corner button; note the printed names (BTN_SIDE, BTN_EXTRA, ...)\n```\n\nEdit the map and restart:\n\n```bash\nsudoedit /etc/ktrackball/config.toml\nsudo systemctl restart ktrackball\njournalctl -u ktrackball -f             # watch it work\n```\n\n## Action types\n\n| type             | example                                                     | effect                          |\n|------------------|-------------------------------------------------------------|---------------------------------|\n| `passthrough`    | `{ type = \"passthrough\" }`                                  | normal click                    |\n| `key`            | `{ type = \"key\", keys = [\"KEY_LEFTALT\",\"KEY_LEFT\"] }`       | inject a key combo (Back)       |\n| `command`        | `{ type = \"command\", command = \"firefox\" }`                 | launch a program (as your user) |\n| `scroll_hold`    | `{ type = \"scroll_hold\" }`                                  | hold + roll ball = scroll       |\n| `precision_hold` | `{ type = \"precision_hold\" }`                               | hold for slow/precise pointer   |\n\nTuning keys in `config.toml`: `precision_factor`, `scroll_divisor`, `scroll_invert`.\n\n## Useful commands\n\n```bash\npython3 trackball_mapper.py list           # list input devices + their names\npython3 trackball_mapper.py check-config   # validate config, resolve names\npython3 trackball_mapper.py learn          # identify button codes\n```\n\n## Uninstall\n\n```bash\nsudo systemctl disable --now ktrackball\nsudo rm -rf /opt/ktrackball /etc/ktrackball /etc/systemd/system/ktrackball.service\nsudo systemctl daemon-reload\n```\n\n## GUI\n\nA GTK3 app lets you assign actions without editing the file:\n\n```bash\npython3 /opt/ktrackball/ktrackball_gui.py     # or launch \"Kensington Trackball Settings\"\n```\n\nIt maps six **positions**: 좌측 상단 / 우측 상단 / 상단(좌+우 동시) / 좌측 하단 /\n우측 하단 / 하단(좌+우 동시). Click **버튼 감지 / Detect** on each single position\nto identify the physical button, pick an action (Back, Forward, Home, End,\nscroll mode, custom key combo / command…), then **저장 후 적용 / Save**. The GUI\nruns as your user; detecting a button and saving use `pkexec` (you authenticate).\nA **볼 스피드 / ball-speed** slider scales pointer movement like a mouse-speed\nsetting (`pointer_speed`, 1.0 = unchanged).\n\n## Chords (두 버튼 동시 누르기)\n\nPressing two buttons together within `chord_window_ms` (default 40) fires a\nsingle chord action and suppresses the individual button actions — so the two\ntop buttons or two bottom buttons become extra mappable inputs. Chords accept\n**key** or **command** actions only. Buttons that take part in a chord get a\ntiny press delay (the chord window) so clicks/drags still work normally.\n\n```toml\n[[chords]]\nbuttons = [\"BTN_SIDE\", \"BTN_MIDDLE\"]   # both top buttons\ntype = \"key\"\nkeys = [\"KEY_LEFTCTRL\", \"KEY_T\"]       # -\u003e new tab\n```\n\n## Security model\n\nThis is an input-remapping daemon, so by design it has powerful access. If you\naudit or fork it, note:\n\n- The daemon runs **as root** because it must read `/dev/input` (raw input\n  events) and write `/dev/uinput` (synthetic input). Reading raw input means it\n  *can* see all keystrokes — same capability as any remapper (input-remapper,\n  keyd). Run only code you trust.\n- `/etc/ktrackball/config.toml` is installed **root-owned, mode 0644**. Keep it\n  that way: a non-root-writable config is what stops a local user from injecting\n  a malicious `command` action into the root daemon.\n- The `command` action runs an arbitrary shell command (dropped to your desktop\n  user). That's intended, and safe only because the config is root-controlled.\n- The GUI never runs as root. It calls `pkexec` for the two privileged steps,\n  which **require authentication each time**. Do **not** add a passwordless\n  polkit rule for the helper — that would let any local process install a config\n  (and thus run arbitrary `command` actions) without authorization.\n- No secrets, credentials, or telemetry are present in this repo.\n\n## Notes\n\n- The scroll ring already works natively as a wheel — no mapping needed.\n- The service runs as root (needs `/dev/input` + `/dev/uinput`); `command`\n  actions are dropped to your desktop user with a Wayland-capable environment.\n- Wireless reconnects are handled automatically (the daemon re-grabs the device).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feondcom%2Fkensington-trackball-linux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feondcom%2Fkensington-trackball-linux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feondcom%2Fkensington-trackball-linux/lists"}