Skip to content

Commit 3295ad8

Browse files
authored
Add topology foundation and safer Windows helper (#12)
* Add beta diagnostics summary and issue template * Add topology foundation and safer Windows helper * Wire topology preview and layout wizard (#13)
1 parent 82608a4 commit 3295ad8

27 files changed

Lines changed: 2972 additions & 54 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Build artifacts
22
build/
33
build-*/
4+
.rpmbuild-local/
45

56
# Working/research files not for public release
67
gemini/

CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ add_executable(mwb_client
4646
src/main.cpp
4747
src/PeerRecovery.cpp
4848
src/SecretStore.cpp
49+
src/TopologyModel.cpp
4950
src/ClipboardManager.cpp
5051
src/CryptoHelper.cpp
5152
src/InputManager.cpp
@@ -85,6 +86,8 @@ include(CTest)
8586
find_package(PkgConfig QUIET)
8687

8788
if (BUILD_TESTING)
89+
find_program(PYTHON3_EXECUTABLE python3)
90+
8891
add_executable(mwb_client_unit_tests
8992
tests/test_main.cpp
9093
src/AppConfig.cpp
@@ -125,6 +128,14 @@ if (BUILD_TESTING)
125128
target_compile_options(mwb_input_latency_tests PRIVATE -Wall -Wextra -Wpedantic)
126129
mwb_apply_sanitizers(mwb_input_latency_tests)
127130

131+
add_executable(mwb_topology_model_tests
132+
tests/test_topology_model.cpp
133+
src/TopologyModel.cpp
134+
)
135+
target_include_directories(mwb_topology_model_tests PRIVATE src)
136+
target_compile_options(mwb_topology_model_tests PRIVATE -Wall -Wextra -Wpedantic)
137+
mwb_apply_sanitizers(mwb_topology_model_tests)
138+
128139
add_executable(mwb_mouse_trace_tests
129140
tests/test_mouse_trace.cpp
130141
src/InputManager.cpp
@@ -175,18 +186,35 @@ if (BUILD_TESTING)
175186
add_test(NAME mwb_inject_mouse_abs_tests COMMAND mwb_inject_mouse_abs_tests)
176187
add_test(NAME mwb_input_device_capability_tests COMMAND mwb_input_device_capability_tests)
177188
add_test(NAME mwb_input_latency_tests COMMAND mwb_input_latency_tests)
189+
add_test(NAME mwb_topology_model_tests COMMAND mwb_topology_model_tests)
190+
if (PYTHON3_EXECUTABLE)
191+
add_test(NAME mwb_topology_config_docs
192+
COMMAND "${PYTHON3_EXECUTABLE}"
193+
"${CMAKE_CURRENT_SOURCE_DIR}/tests/topology_config_docs_test.py"
194+
"${CMAKE_CURRENT_SOURCE_DIR}/docs/topology.md"
195+
)
196+
endif()
178197
add_test(NAME mwb_mouse_trace_tests COMMAND mwb_mouse_trace_tests)
179198
add_test(NAME mwb_media_key_bridge_tests COMMAND mwb_media_key_bridge_tests)
180199
add_test(NAME mwb_protocol_security_tests COMMAND mwb_protocol_security_tests)
181200
add_test(NAME mwb_clipboard_socket_security_tests COMMAND mwb_clipboard_socket_security_tests)
182201
add_test(NAME mwb_client_help COMMAND mwb_client --help)
183202
add_test(NAME mwb_client_doctor COMMAND mwb_client doctor --config "${CMAKE_CURRENT_BINARY_DIR}/missing-doctor-config.ini")
203+
add_test(NAME mwb_client_topology_explain
204+
COMMAND mwb_client topology explain "${CMAKE_CURRENT_SOURCE_DIR}/tests/simple.topology"
205+
)
184206
add_test(NAME mwb_client_doctor_categories
185207
COMMAND ${CMAKE_COMMAND}
186208
"-DMWB_CLIENT=$<TARGET_FILE:mwb_client>"
187209
"-DCONFIG_PATH=${CMAKE_CURRENT_BINARY_DIR}/missing-doctor-config.ini"
188210
-P "${CMAKE_CURRENT_SOURCE_DIR}/tests/doctor_categories.cmake"
189211
)
212+
add_test(NAME mwb_export_windows_pair_helper
213+
COMMAND ${CMAKE_COMMAND}
214+
"-DMWB_CLIENT=$<TARGET_FILE:mwb_client>"
215+
"-DTEST_DIR=${CMAKE_CURRENT_BINARY_DIR}/export_windows_pair"
216+
-P "${CMAKE_CURRENT_SOURCE_DIR}/tests/export_windows_pair_helper.cmake"
217+
)
190218
add_test(NAME mwb_client_doctor_invalid_config COMMAND mwb_client doctor --config "${CMAKE_CURRENT_SOURCE_DIR}/tests/invalid_config.ini")
191219
set_tests_properties(mwb_client_doctor_invalid_config PROPERTIES WILL_FAIL TRUE)
192220
endif()

README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@ Recommended first-run flow for most users:
1515
2. **Launch Setup UI:** Run `./mwb-desktop-ui.sh menu`
1616
3. **Configure:**
1717
- Go to **Settings** -> Enter your Windows Host IP and Security Key.
18-
4. **Pair with Windows:**
18+
4. **Use PowerToys layout for normal setups:**
19+
- If this Linux/Fedora machine has one monitor, do not configure topology. Let Windows PowerToys Mouse Without Borders own the Linux/Windows machine placement.
20+
- If topology was enabled while testing, choose **Use PowerToys Layout Only** to set `topology_enabled=false`.
21+
5. **Pair with Windows:**
1922
- In the same UI, use the **Export Helper** option.
2023
- Run the exported `.ps1` script on your Windows machine to register the Linux peer.
21-
5. **Start:** Choose **Start Service** or launch the tray with `./build/mwb_tray`.
24+
6. **Start:** Choose **Start Service** or launch the tray with `./build/mwb_tray`.
25+
7. **Advanced layouts only:** Open **Advanced Topology/Layout** if you have multiple Linux monitors, stacked/asymmetric edges, wrap behavior, or wrong-edge handoff problems.
2226

2327
For the full beta setup, health-check, diagnostics, connection-quality, and packaging-verification workflow, see [docs/beta-workflow.md](docs/beta-workflow.md).
2428

@@ -98,9 +102,13 @@ See the full [documentation section](#detailed-documentation) for environment va
98102
User-facing beta operations:
99103

100104
- [Guided Windows pairing and export helper](docs/beta-workflow.md#guided-pairing-and-export-helper)
105+
- [Topology/layout wizard](docs/beta-workflow.md#topologylayout-wizard)
101106
- [Health checks and diagnostics bundle](docs/beta-workflow.md#health-check)
102107
- [Connection quality and latency reporting](docs/beta-workflow.md#connection-quality)
103108
- [Packaging verification](docs/beta-workflow.md#packaging-verification)
109+
- [Topology config contract and layout wizard expectations](docs/topology.md)
110+
- [Migration from other keyboard/mouse sharing tools](docs/migration.md)
111+
- [Compatibility matrix and platform caveats](docs/compatibility.md)
104112

105113
<a name="detailed-documentation"></a>
106114
## Detailed Documentation
@@ -109,7 +117,11 @@ User-facing beta operations:
109117
This repository started as a fork of [chrischip/mwb-client-linux](https://github.com/chrischip/mwb-client-linux) and has been substantially expanded with service management, rich clipboard support, and recovery tooling.
110118

111119
### Configuration (`config.ini`)
112-
Supports `key_file`, `key_secret_id` (keyring), `screen_width/height` overrides, and more. Default path: `~/.config/mwb-client/config.ini`.
120+
Supports `key_file`, `key_secret_id` (keyring), `screen_width/height` overrides, `topology_enabled`, `topology_file`, and more. Default path: `~/.config/mwb-client/config.ini`.
121+
122+
Display-level topology is a separate opt-in contract. The default runtime remains MWB-compatible machine placement unless topology is explicitly enabled; see [docs/topology.md](docs/topology.md) for examples, wrap policies, validation, and cross-machine handoff behavior.
123+
124+
Windows PowerToys still owns the Windows-side machine layout. InputFlow topology does not edit PowerToys per-display geometry; it only tells Linux which local display edge should hand off back to Windows. Keep the PowerToys machine position and the InputFlow topology links consistent.
113125

114126
### Screen Sizing
115127
The client detects screen size in this order:

docs/beta-workflow.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ Use the desktop controller for the guided path:
1212

1313
1. Open **Settings** and enter the Windows host IP, local machine name, port, and exactly one authentication source: inline key, `key_file`, or Secret Service key ID.
1414
2. Use **Connection Behavior** to choose automatic reconnect behavior before starting the service.
15-
3. Export a Windows helper from Linux when the UI exposes the action, or use the CLI fallback:
15+
3. For one Linux/Fedora monitor, leave topology disabled and use the normal PowerToys layout path.
16+
4. Optionally run **Advanced Topology/Layout** only if you have multiple Linux displays, stacked/asymmetric edges, wrap behavior, or wrong-edge handoff problems.
17+
5. Export a Windows helper from Linux when the UI exposes the action, or use the CLI fallback:
1618

1719
```bash
1820
./build/mwb_client export-windows-pair \
@@ -31,6 +33,27 @@ Keep the exported `.ps1` private because it contains pairing material. Delete it
3133

3234
![Pairing helper walkthrough](screenshots/pairing-helper.svg)
3335

36+
## Advanced Topology/Layout Wizard
37+
38+
Open the wizard from the desktop controller only when the normal PowerToys layout is not enough:
39+
40+
```bash
41+
./mwb-desktop-ui.sh layout-wizard
42+
```
43+
44+
The wizard asks for a plain-language layout, Linux/Windows machine names, display size, wrap policy, and output file name. It shows a preview of the exact topology file before making changes. For one Linux monitor, prefer **Use PowerToys Layout Only** instead.
45+
46+
Only after confirmation, the wizard writes the topology file under `~/.config/mwb-client/` and updates `config.ini`:
47+
48+
```ini
49+
topology_enabled=true
50+
topology_file=/home/example/.config/mwb-client/topology-side-by-side.topology
51+
```
52+
53+
When topology is enabled, configured cross-machine edge transitions are enforced at runtime. Same-machine transitions remain local, and invalid topology falls back to the existing behavior with a warning.
54+
55+
Use **Explain Current Topology** after saving. It translates the topology into English and reminds users that Windows PowerToys still owns the Windows-side machine layout. Keep the PowerToys machine placement and the InputFlow topology edges consistent.
56+
3457
## Health Check
3558

3659
Run the built-in doctor before filing a beta issue or after changing package/service setup:

docs/compatibility.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Compatibility Guide
2+
3+
InputFlow is a native Linux peer for Microsoft PowerToys Mouse Without Borders (MWB). It targets PowerToys MWB interoperability with Linux input, clipboard, service, and configuration integration. It is not a Barrier, Synergy, Input Leap, Deskflow, or Cursr protocol implementation.
4+
5+
## Compatibility Matrix
6+
7+
| Area | Status | Notes |
8+
| --- | --- | --- |
9+
| Linux on X11 | Supported beta path | Input delivery uses `/dev/uinput`. Clipboard sync needs `xclip` or `xsel` when clipboard features are enabled. |
10+
| Linux on Wayland | Supported with caveats | Input delivery still needs writable `/dev/uinput`. Some compositors may apply extra policy, prompts, or restrictions for synthetic input. Clipboard sync needs `wl-clipboard`, and polling may be needed in some sessions. |
11+
| `/dev/uinput` | Required for input injection | Load the `uinput` module and grant the user access, usually through the packaged `inputflow` group and udev rule. |
12+
| PowerToys MWB on Windows | Target peer | Pair InputFlow with the PowerToys Mouse Without Borders feature on Windows. Exported helpers seed `MachinePool`, `MachineMatrixString`, `Name2IP`, peer name, address, layout, and key material. |
13+
| Barrier / Synergy / Input Leap / Deskflow | Not protocol compatible | Use the migration guide to translate concepts, not configuration files. |
14+
| Cursr | Not protocol compatible | InputFlow does not join Cursr groups. Use MWB peer placement instead. |
15+
| Authentication: Secret Service | Supported when available | Use `key_secret_id=` when a session bus and keyring are available. Headless sessions may not provide this. |
16+
| Authentication: `key_file` | Supported | Good default for service usage when file permissions are managed carefully. |
17+
| Authentication: inline `key` | Supported | Useful for quick setup, but avoid sharing configs because the key is stored directly. |
18+
| Clipboard receive/send | Supported beta path | Requires local helpers: `wl-clipboard` on Wayland or `xclip`/`xsel` on X11. Availability is reported by `doctor`. |
19+
| systemd user service | Opt-in | Packaging includes a user unit, but users should enable/start it only after validating config, key source, and `/dev/uinput` access. |
20+
| Network trust model | Trusted LAN/subnet | Use on a trusted local network. Do not expose MWB ports to untrusted networks or the public internet. |
21+
| Display-level topology config | Opt-in | The contract is documented in [Topology Config Contract](topology.md), and the default runtime remains MWB-compatible machine placement unless topology is enabled. |
22+
23+
## Linux Session Details
24+
25+
X11 is the simpler path because clipboard helpers and desktop automation policy are more predictable. Wayland can work, but compositor policy matters: even with `/dev/uinput` access, the compositor or desktop environment may restrict, gate, or prompt around synthetic input behavior.
26+
27+
Run the health check after setup:
28+
29+
```bash
30+
./build/mwb_client doctor --config ~/.config/mwb-client/config.ini
31+
```
32+
33+
Review warnings for session type, `/dev/uinput`, group membership, clipboard helpers, Secret Service availability, and authentication conflicts.
34+
35+
## Windows PowerToys MWB
36+
37+
InputFlow is intended to pair with the Windows PowerToys MWB implementation. Use the exported Windows helper when possible because it writes the MWB settings that are easy to mistype by hand: peer name, address, shared key, `MachinePool`, `MachineMatrixString`, and `Name2IP`.
38+
39+
InputFlow is independent and not affiliated with Microsoft. Compatibility is based on the open-source PowerToys MWB behavior.
40+
41+
## Network Assumptions
42+
43+
InputFlow assumes a trusted local network where peers can reach each other directly by IP or resolvable host name. Keep MWB traffic on a private LAN, VPN, or otherwise trusted subnet.
44+
45+
Avoid:
46+
47+
- Forwarding MWB ports from the internet.
48+
- Pairing across networks you do not control.
49+
- Publishing configs or exported helper scripts that include keys or private addresses.
50+
51+
## Service Expectations
52+
53+
The systemd user service is a convenience, not a required first step. During migration or first setup, run the desktop UI or CLI manually, confirm `doctor` output, and verify Windows pairing. Enable the user service only after those checks pass.
54+
55+
## Topology Expectations
56+
57+
Current default compatibility is machine-level MWB placement. Display-level topology is intentionally gated and opt-in so InputFlow can remain compatible with PowerToys MWB unless the user enables explicit machine/display links.
58+
59+
The topology contract separates machines from displays and supports configurable wrap policies, AAB/BAA/ABA layouts, stacked layouts, asymmetric layouts, and cross-machine edge handoff. See [Topology Config Contract](topology.md) for the file format and validation expectations.

docs/migration.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Migration Guide
2+
3+
InputFlow is a native Linux peer for PowerToys Mouse Without Borders (MWB). It is built to interoperate with the Windows PowerToys MWB implementation; it is not a generic Synergy-family protocol clone and should not be expected to join Barrier, Synergy, Input Leap, Deskflow, or Cursr groups directly.
4+
5+
Use this guide when moving from another keyboard/mouse sharing setup, from Wine-based MWB experiments, or from an older InputFlow configuration.
6+
7+
## Mental Model
8+
9+
PowerToys MWB and InputFlow use a peer model. Each machine has a name, address, shared security key, and layout position. There is no permanent "server" machine that owns every other client in the way Synergy-family tools commonly describe the topology.
10+
11+
In practice:
12+
13+
- The Windows machine runs PowerToys Mouse Without Borders.
14+
- The Linux machine runs InputFlow.
15+
- Both sides must agree on the shared key, peer names, peer addresses, and layout.
16+
- InputFlow can export a Windows helper script that seeds the Linux peer into PowerToys MWB settings.
17+
18+
For the guided pairing flow, see [Public Beta Workflow](beta-workflow.md#guided-pairing-and-export-helper).
19+
20+
## Legacy Term Map
21+
22+
| Legacy term | InputFlow / PowerToys MWB concept |
23+
| --- | --- |
24+
| Server | A peer that currently owns the local pointer and sends input to another peer. This role is situational, not a fixed machine type. |
25+
| Client | A peer receiving remote input. This role is also situational. |
26+
| Screen | A machine entry in the current MWB layout. Display-level topology is a separate opt-in contract. |
27+
| Screen name | `machine_name` / MWB peer name. Names must match what the other peer expects. |
28+
| Configuration file | `~/.config/mwb-client/config.ini` for InputFlow; PowerToys MWB settings on Windows. |
29+
| Shared secret / password | MWB security key. InputFlow can read it from an inline `key`, `key_file`, or Secret Service `key_secret_id`. |
30+
| Edge transition | MWB layout adjacency between peers. |
31+
| Clipboard sharing | InputFlow clipboard sync using local helper tools and MWB clipboard transport. |
32+
| Barrier / Synergy protocol | Not applicable. InputFlow targets PowerToys MWB compatibility instead. |
33+
34+
This map is only a vocabulary bridge. It does not claim that the named projects are maintained, unmaintained, compatible, or incompatible beyond the protocol distinction above.
35+
36+
## Migrating From Barrier, Synergy, Input Leap, Deskflow, Or Cursr
37+
38+
Do not reuse old server/client topology files as-is. Convert the intent instead:
39+
40+
1. Pick the Windows PowerToys MWB machine and Linux InputFlow machine names.
41+
2. Choose or copy the MWB security key into one InputFlow authentication source.
42+
3. Set the Windows host IP and InputFlow local machine name in `config.ini` or the desktop UI.
43+
4. Export the Windows pairing helper from InputFlow and run it on Windows.
44+
5. Verify the peer layout in PowerToys MWB before starting regular use.
45+
46+
Common differences to expect:
47+
48+
- InputFlow joins a PowerToys MWB peer group, not a Synergy-family server process.
49+
- Layout is expressed through MWB peer placement, not a separate Synergy-style screen graph.
50+
- Input injection on Linux depends on `/dev/uinput`; Wayland may also require compositor policy or user approval.
51+
- Clipboard support depends on installed local helpers. Install `wl-clipboard` for Wayland or `xclip`/`xsel` for X11 when needed.
52+
53+
## Migrating From Wine Or Windows MWB Attempts
54+
55+
Running Windows PowerToys MWB through Wine is not the intended Linux path. InputFlow replaces that approach with a native Linux peer that talks to PowerToys MWB on Windows.
56+
57+
Before migrating:
58+
59+
- Stop any Wine-hosted MWB process so it does not compete for ports or peer names.
60+
- Keep the PowerToys MWB security key if you want the same trusted group.
61+
- Recreate the Linux peer through InputFlow export rather than copying Wine registry or settings files.
62+
- Expect Linux input delivery to use `/dev/uinput`, not Windows input APIs.
63+
64+
If a previous Wine setup used the same Linux machine name, remove stale duplicate peer entries from PowerToys MWB or overwrite them with the exported helper.
65+
66+
## Authentication Sources
67+
68+
Configure exactly one practical key source for normal use:
69+
70+
- `key=` stores the MWB security key inline in `config.ini`; simple but easiest to expose.
71+
- `key_file=` reads the key from a local file; preferable for scripts and backups.
72+
- `key_secret_id=` reads from Secret Service through the desktop session keyring; preferable when a session bus and keyring are available.
73+
74+
Avoid publishing configs, helper scripts, logs, or screenshots that expose keys, peer IPs, or Secret Service identifiers.
75+
76+
## Topology Roadmap
77+
78+
InputFlow defaults to MWB-compatible machine placement. Optional topology adds a cleaner machine/display split, explicit wrap policies, AAB/BAA/ABA layouts, stacked layouts, asymmetric layouts, and configured cross-machine edge handoff.
79+
80+
Until the runtime topology feature gate is enabled and validated for your setup, treat topology as machine-level MWB placement and verify changes in PowerToys MWB after exporting. If you are testing the layout wizard or runtime topology branch, use the [Topology Config Contract](topology.md) and keep `wrap=none` with explicit links until validation output matches the intended handoff behavior.

0 commit comments

Comments
 (0)