Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Build artifacts
build/
build-*/
.rpmbuild-local/

# Working/research files not for public release
gemini/
Expand Down
28 changes: 28 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ add_executable(mwb_client
src/main.cpp
src/PeerRecovery.cpp
src/SecretStore.cpp
src/TopologyModel.cpp
src/ClipboardManager.cpp
src/CryptoHelper.cpp
src/InputManager.cpp
Expand Down Expand Up @@ -85,6 +86,8 @@ include(CTest)
find_package(PkgConfig QUIET)

if (BUILD_TESTING)
find_program(PYTHON3_EXECUTABLE python3)

add_executable(mwb_client_unit_tests
tests/test_main.cpp
src/AppConfig.cpp
Expand Down Expand Up @@ -125,6 +128,14 @@ if (BUILD_TESTING)
target_compile_options(mwb_input_latency_tests PRIVATE -Wall -Wextra -Wpedantic)
mwb_apply_sanitizers(mwb_input_latency_tests)

add_executable(mwb_topology_model_tests
tests/test_topology_model.cpp
src/TopologyModel.cpp
)
target_include_directories(mwb_topology_model_tests PRIVATE src)
target_compile_options(mwb_topology_model_tests PRIVATE -Wall -Wextra -Wpedantic)
mwb_apply_sanitizers(mwb_topology_model_tests)

add_executable(mwb_mouse_trace_tests
tests/test_mouse_trace.cpp
src/InputManager.cpp
Expand Down Expand Up @@ -175,18 +186,35 @@ if (BUILD_TESTING)
add_test(NAME mwb_inject_mouse_abs_tests COMMAND mwb_inject_mouse_abs_tests)
add_test(NAME mwb_input_device_capability_tests COMMAND mwb_input_device_capability_tests)
add_test(NAME mwb_input_latency_tests COMMAND mwb_input_latency_tests)
add_test(NAME mwb_topology_model_tests COMMAND mwb_topology_model_tests)
if (PYTHON3_EXECUTABLE)
add_test(NAME mwb_topology_config_docs
COMMAND "${PYTHON3_EXECUTABLE}"
"${CMAKE_CURRENT_SOURCE_DIR}/tests/topology_config_docs_test.py"
"${CMAKE_CURRENT_SOURCE_DIR}/docs/topology.md"
)
endif()
add_test(NAME mwb_mouse_trace_tests COMMAND mwb_mouse_trace_tests)
add_test(NAME mwb_media_key_bridge_tests COMMAND mwb_media_key_bridge_tests)
add_test(NAME mwb_protocol_security_tests COMMAND mwb_protocol_security_tests)
add_test(NAME mwb_clipboard_socket_security_tests COMMAND mwb_clipboard_socket_security_tests)
add_test(NAME mwb_client_help COMMAND mwb_client --help)
add_test(NAME mwb_client_doctor COMMAND mwb_client doctor --config "${CMAKE_CURRENT_BINARY_DIR}/missing-doctor-config.ini")
add_test(NAME mwb_client_topology_explain
COMMAND mwb_client topology explain "${CMAKE_CURRENT_SOURCE_DIR}/tests/simple.topology"
)
add_test(NAME mwb_client_doctor_categories
COMMAND ${CMAKE_COMMAND}
"-DMWB_CLIENT=$<TARGET_FILE:mwb_client>"
"-DCONFIG_PATH=${CMAKE_CURRENT_BINARY_DIR}/missing-doctor-config.ini"
-P "${CMAKE_CURRENT_SOURCE_DIR}/tests/doctor_categories.cmake"
)
add_test(NAME mwb_export_windows_pair_helper
COMMAND ${CMAKE_COMMAND}
"-DMWB_CLIENT=$<TARGET_FILE:mwb_client>"
"-DTEST_DIR=${CMAKE_CURRENT_BINARY_DIR}/export_windows_pair"
-P "${CMAKE_CURRENT_SOURCE_DIR}/tests/export_windows_pair_helper.cmake"
)
add_test(NAME mwb_client_doctor_invalid_config COMMAND mwb_client doctor --config "${CMAKE_CURRENT_SOURCE_DIR}/tests/invalid_config.ini")
set_tests_properties(mwb_client_doctor_invalid_config PROPERTIES WILL_FAIL TRUE)
endif()
Expand Down
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ Recommended first-run flow for most users:
2. **Launch Setup UI:** Run `./mwb-desktop-ui.sh menu`
3. **Configure:**
- Go to **Settings** -> Enter your Windows Host IP and Security Key.
4. **Pair with Windows:**
4. **Use PowerToys layout for normal setups:**
- If this Linux/Fedora machine has one monitor, do not configure topology. Let Windows PowerToys Mouse Without Borders own the Linux/Windows machine placement.
- If topology was enabled while testing, choose **Use PowerToys Layout Only** to set `topology_enabled=false`.
5. **Pair with Windows:**
- In the same UI, use the **Export Helper** option.
- Run the exported `.ps1` script on your Windows machine to register the Linux peer.
5. **Start:** Choose **Start Service** or launch the tray with `./build/mwb_tray`.
6. **Start:** Choose **Start Service** or launch the tray with `./build/mwb_tray`.
7. **Advanced layouts only:** Open **Advanced Topology/Layout** if you have multiple Linux monitors, stacked/asymmetric edges, wrap behavior, or wrong-edge handoff problems.

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

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

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

<a name="detailed-documentation"></a>
## Detailed Documentation
Expand All @@ -109,7 +117,11 @@ User-facing beta operations:
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.

### Configuration (`config.ini`)
Supports `key_file`, `key_secret_id` (keyring), `screen_width/height` overrides, and more. Default path: `~/.config/mwb-client/config.ini`.
Supports `key_file`, `key_secret_id` (keyring), `screen_width/height` overrides, `topology_enabled`, `topology_file`, and more. Default path: `~/.config/mwb-client/config.ini`.

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.

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.

### Screen Sizing
The client detects screen size in this order:
Expand Down
25 changes: 24 additions & 1 deletion docs/beta-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ Use the desktop controller for the guided path:

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.
2. Use **Connection Behavior** to choose automatic reconnect behavior before starting the service.
3. Export a Windows helper from Linux when the UI exposes the action, or use the CLI fallback:
3. For one Linux/Fedora monitor, leave topology disabled and use the normal PowerToys layout path.
4. Optionally run **Advanced Topology/Layout** only if you have multiple Linux displays, stacked/asymmetric edges, wrap behavior, or wrong-edge handoff problems.
5. Export a Windows helper from Linux when the UI exposes the action, or use the CLI fallback:

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

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

## Advanced Topology/Layout Wizard

Open the wizard from the desktop controller only when the normal PowerToys layout is not enough:

```bash
./mwb-desktop-ui.sh layout-wizard
```

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.

Only after confirmation, the wizard writes the topology file under `~/.config/mwb-client/` and updates `config.ini`:

```ini
topology_enabled=true
topology_file=/home/example/.config/mwb-client/topology-side-by-side.topology
```

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.

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.

## Health Check

Run the built-in doctor before filing a beta issue or after changing package/service setup:
Expand Down
59 changes: 59 additions & 0 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Compatibility Guide

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.

## Compatibility Matrix

| Area | Status | Notes |
| --- | --- | --- |
| Linux on X11 | Supported beta path | Input delivery uses `/dev/uinput`. Clipboard sync needs `xclip` or `xsel` when clipboard features are enabled. |
| 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. |
| `/dev/uinput` | Required for input injection | Load the `uinput` module and grant the user access, usually through the packaged `inputflow` group and udev rule. |
| 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. |
| Barrier / Synergy / Input Leap / Deskflow | Not protocol compatible | Use the migration guide to translate concepts, not configuration files. |
| Cursr | Not protocol compatible | InputFlow does not join Cursr groups. Use MWB peer placement instead. |
| Authentication: Secret Service | Supported when available | Use `key_secret_id=` when a session bus and keyring are available. Headless sessions may not provide this. |
| Authentication: `key_file` | Supported | Good default for service usage when file permissions are managed carefully. |
| Authentication: inline `key` | Supported | Useful for quick setup, but avoid sharing configs because the key is stored directly. |
| Clipboard receive/send | Supported beta path | Requires local helpers: `wl-clipboard` on Wayland or `xclip`/`xsel` on X11. Availability is reported by `doctor`. |
| 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. |
| Network trust model | Trusted LAN/subnet | Use on a trusted local network. Do not expose MWB ports to untrusted networks or the public internet. |
| 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. |

## Linux Session Details

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.

Run the health check after setup:

```bash
./build/mwb_client doctor --config ~/.config/mwb-client/config.ini
```

Review warnings for session type, `/dev/uinput`, group membership, clipboard helpers, Secret Service availability, and authentication conflicts.

## Windows PowerToys MWB

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`.

InputFlow is independent and not affiliated with Microsoft. Compatibility is based on the open-source PowerToys MWB behavior.

## Network Assumptions

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.

Avoid:

- Forwarding MWB ports from the internet.
- Pairing across networks you do not control.
- Publishing configs or exported helper scripts that include keys or private addresses.

## Service Expectations

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.

## Topology Expectations

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.

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.
80 changes: 80 additions & 0 deletions docs/migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Migration Guide

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.

Use this guide when moving from another keyboard/mouse sharing setup, from Wine-based MWB experiments, or from an older InputFlow configuration.

## Mental Model

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.

In practice:

- The Windows machine runs PowerToys Mouse Without Borders.
- The Linux machine runs InputFlow.
- Both sides must agree on the shared key, peer names, peer addresses, and layout.
- InputFlow can export a Windows helper script that seeds the Linux peer into PowerToys MWB settings.

For the guided pairing flow, see [Public Beta Workflow](beta-workflow.md#guided-pairing-and-export-helper).

## Legacy Term Map

| Legacy term | InputFlow / PowerToys MWB concept |
| --- | --- |
| Server | A peer that currently owns the local pointer and sends input to another peer. This role is situational, not a fixed machine type. |
| Client | A peer receiving remote input. This role is also situational. |
| Screen | A machine entry in the current MWB layout. Display-level topology is a separate opt-in contract. |
| Screen name | `machine_name` / MWB peer name. Names must match what the other peer expects. |
| Configuration file | `~/.config/mwb-client/config.ini` for InputFlow; PowerToys MWB settings on Windows. |
| Shared secret / password | MWB security key. InputFlow can read it from an inline `key`, `key_file`, or Secret Service `key_secret_id`. |
| Edge transition | MWB layout adjacency between peers. |
| Clipboard sharing | InputFlow clipboard sync using local helper tools and MWB clipboard transport. |
| Barrier / Synergy protocol | Not applicable. InputFlow targets PowerToys MWB compatibility instead. |

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.

## Migrating From Barrier, Synergy, Input Leap, Deskflow, Or Cursr

Do not reuse old server/client topology files as-is. Convert the intent instead:

1. Pick the Windows PowerToys MWB machine and Linux InputFlow machine names.
2. Choose or copy the MWB security key into one InputFlow authentication source.
3. Set the Windows host IP and InputFlow local machine name in `config.ini` or the desktop UI.
4. Export the Windows pairing helper from InputFlow and run it on Windows.
5. Verify the peer layout in PowerToys MWB before starting regular use.

Common differences to expect:

- InputFlow joins a PowerToys MWB peer group, not a Synergy-family server process.
- Layout is expressed through MWB peer placement, not a separate Synergy-style screen graph.
- Input injection on Linux depends on `/dev/uinput`; Wayland may also require compositor policy or user approval.
- Clipboard support depends on installed local helpers. Install `wl-clipboard` for Wayland or `xclip`/`xsel` for X11 when needed.

## Migrating From Wine Or Windows MWB Attempts

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.

Before migrating:

- Stop any Wine-hosted MWB process so it does not compete for ports or peer names.
- Keep the PowerToys MWB security key if you want the same trusted group.
- Recreate the Linux peer through InputFlow export rather than copying Wine registry or settings files.
- Expect Linux input delivery to use `/dev/uinput`, not Windows input APIs.

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.

## Authentication Sources

Configure exactly one practical key source for normal use:

- `key=` stores the MWB security key inline in `config.ini`; simple but easiest to expose.
- `key_file=` reads the key from a local file; preferable for scripts and backups.
- `key_secret_id=` reads from Secret Service through the desktop session keyring; preferable when a session bus and keyring are available.

Avoid publishing configs, helper scripts, logs, or screenshots that expose keys, peer IPs, or Secret Service identifiers.

## Topology Roadmap

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.

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.
Loading