diff --git a/README.md b/README.md index 0ea5f21..1b001bc 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,11 @@ A macOS menu-bar utility that hands off Magic Keyboard, Magic Trackpad, and Magi This is a security-hardened fork of [HoshimuraYuto/blue-switch](https://github.com/HoshimuraYuto/blue-switch). The original ships an unauthenticated, unencrypted LAN protocol that lets anyone on the same Wi-Fi take over your Bluetooth peripherals or spoof notifications. This fork replaces that channel with a sealed, mutually-authenticated channel keyed by a 12-character pairing code you share between your two Macs — with a massively improved UI/UX over the original: a guided pairing flow, inline status feedback, per-peripheral switching, a needs-attention menu-bar icon, and safe preflight-and-rollback handoffs. +

+ The Magic Switch menu-bar dropdown
+ It lives in the menu bar: click a Mac to hand over everything, or a single peripheral to move just that one. +

+ ## Installation 1. Grab the latest build from the [releases page](https://github.com/MegaManSec/magic-switch/releases). @@ -17,46 +22,40 @@ This is a security-hardened fork of [HoshimuraYuto/blue-switch](https://github.c ## Setup -Four Settings tabs to know — two of them use the word "pair" in different senses, which can be confusing: +Magic Switch has four Settings tabs, and two of them use the word "pair" in different senses — which trips people up. **Pairing** is the cryptographic key shared between the two *Macs* (required, and set up inside Magic Switch); the Bluetooth pairing of your *peripherals* is a separate thing, done in System Settings. Do everything below on **both** Macs. -- **Peripheral** — the Bluetooth devices Magic Switch hands back and forth (Magic Keyboard / Mouse / Trackpad). -- **Device** — the *other Mac on your network* you're swapping with. -- **Pairing** — a cryptographic shared key between the two Macs. *Required.* This is **not** the Bluetooth pairing in step 1 — that's between your peripherals and each Mac, done in System Settings. This one is between the two Macs themselves, done inside Magic Switch. -- **Other** — app preferences: **Launch at Login**, two peripheral-handling toggles (**Release peripherals when this Mac sleeps** and **Reconnect peripherals if they drop** — see [Troubleshooting](#troubleshooting)), the installed version, and update notifications (see [Updates](#updates)). +### 1. Pair your peripherals to each Mac (System Settings) -

- Peripheral tab with each control labelled
- Peripheral tab — register the Magic devices you want to hand off. -

+In **System Settings → Bluetooth on each Mac**, pair your Magic Keyboard / Mouse / Trackpad to *that* Mac the normal macOS way — **each peripheral has to be paired to both Macs**. Apple's Magic devices remember multiple hosts but only connect to one at a time; Magic Switch flips which Mac currently holds a peripheral, but it doesn't create those pairings for you. (Once that's done, you won't re-pair by hand on every switch — Magic Switch handles the handoff.) + +Then launch Magic Switch, grant **Bluetooth** and **Local Network** when prompted, and right-click the menu-bar icon → **Settings**. + +### 2. Peripheral tab — choose what to manage + +Tick the Magic devices you want Magic Switch to hand back and forth. Each row's leading icon shows the detected device type; click it to override the type or reset it to Automatic.

- Device tab with each control labelled
- Device tab — pick the other Mac, sync peripherals to it, and check it's reachable. + Peripheral tab showing registered and available peripherals
+ Peripheral tab — register the Magic devices you want to hand off. Each row's leading icon shows the detected device type.

- Other tab with each control labelled
- Other tab — Launch at Login, license info, version, and a manual update check. + Peripheral tab with a row's type picker open
+ That leading icon is also a picker — Magic Switch auto-detects the type (keyboard, mouse, trackpad, headphones, AirPods, microphone), and you can override it or set it back to Automatic.

-Do this on **both** Macs. +### 3. Device tab — pick the other Mac -1. **In System Settings → Bluetooth on each Mac**, pair your Magic Keyboard / Mouse / Trackpad to *that* Mac the normal macOS way — **each peripheral has to be paired to both Macs**. Apple's Magic devices remember multiple hosts but only connect to one at a time; Magic Switch flips which Mac currently holds a peripheral, but it doesn't create those pairings for you — set them up on both Macs in System Settings first. (Once that's done, you won't re-pair by hand on every switch — Magic Switch handles the handoff.) -2. Launch Magic Switch. Grant **Bluetooth** and **Local Network** permission when prompted. -3. Right-click the menu-bar icon → Settings: - - **Peripheral** tab: tick the Magic devices you want Magic Switch to manage. - - **Device** tab: pick the other Mac from "Available Devices." -4. **Pairing** tab — *required*: - - On one Mac, click "Generate Code." A twelve-character code appears. - - On the other, click "Enter Code" and type it in. - - Both Macs should show the same eight-character fingerprint after pairing. If they don't, you typed the code wrong. -5. Sync your peripheral list to the other Mac: on the **Device** tab, find it under **Connected Devices** and click its **share button** (the box-with-an-up-arrow icon, beside **Ping**). A "Synced N peripherals to …" line appears under the row on success. The button is greyed out while that Mac is offline. +Choose the other Mac under **Available Devices**. It shows up once it's on the same network running Magic Switch; a greyed-out row means it isn't reachable right now. -Until step 4 completes, the switch action and peripheral sync refuse to talk to the peer. +

+ Device tab showing the connected Mac and available devices
+ Device tab — pick the other Mac, sync peripherals to it, and check it's reachable. +

-### The pairing flow +### 4. Pairing tab — link the two Macs (required) -Pairing all happens in the **Pairing** tab — generate a code on one Mac and enter it on the other (either direction works; both Macs derive the same key from the same code). +Generate a twelve-character code on one Mac and enter it on the other; either direction works, since both Macs derive the same key from the same code. They should then show the same eight-character fingerprint — if they differ, the code was mistyped. Until this is done, switching and peripheral sync refuse to talk to the peer.

Pairing tab before pairing
@@ -74,6 +73,19 @@ Pairing all happens in the **Pairing** tab — generate a code on one Mac and en After pairing — both Macs show the same fingerprint. If they differ, the code was mistyped.

+### 5. Sync your peripherals to the other Mac + +On the **Device** tab, find the other Mac under **Connected Devices** and click its **Share** button (the box-with-an-up-arrow, beside **Ping**). A "Synced N peripherals to …" line confirms it. The button is greyed out while that Mac is offline. + +### Other tab — preferences + +**Launch at Login**, two peripheral-handling toggles (**Release peripherals when this Mac sleeps** and **Reconnect peripherals if they drop** — see [Troubleshooting](#troubleshooting)), the installed version, and update notifications (see [Updates](#updates)). + +

+ Other tab showing app preferences
+ Other tab — Launch at Login, the sleep-release and auto-reconnect toggles, license info, version, and a manual update check. +

+ ## Usage | Action | Result | @@ -83,12 +95,7 @@ Pairing all happens in the **Pairing** tab — generate a code on one Mac and en | Menu → a peripheral | Switch just that one peripheral. Checkmark = currently on this Mac | | Menu → Settings | Open the Settings window | -The menu-bar icon also signals state: a **warning triangle** means Magic Switch needs attention (not paired, or Bluetooth off/denied) — hover for the reason; **up/down arrows** flash briefly while peripherals are moving between Macs. - -

- The menu-bar menu with actions labelled
- The menu — click a Mac to move everything, or a single peripheral to move just that one. -

+The menu-bar icon also signals state: a **warning triangle** means Magic Switch needs attention (not paired, or Bluetooth off/denied) — hover for the reason; **up/down arrows** flash briefly while peripherals are moving between Macs (the dropdown is pictured at the top of this README). ## Updates diff --git a/docs/annotate-screenshots.sh b/docs/annotate-screenshots.sh new file mode 100755 index 0000000..40b358e --- /dev/null +++ b/docs/annotate-screenshots.sh @@ -0,0 +1,123 @@ +#!/bin/bash +# Regenerate the annotated README screenshots in docs/assets/ from the raw +# captures in docs/assets/raw/. Adds numbered yellow badges + a bottom legend, +# matching the project's existing screenshot style. +# +# Repeatable: recapture a raw screenshot into docs/assets/raw/ (or tweak the +# badge/legend config below) and re-run: +# +# ./docs/annotate-screenshots.sh +# +# Requires ImageMagick v7 (`magick`) and the referenced macOS system fonts. +set -euo pipefail + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +RAW="$DIR/assets/raw" +OUT="$DIR/assets" +BADGE_DIR="$(mktemp -d)" +trap 'rm -rf "$BADGE_DIR"' EXIT + +YELLOW="#FFD60A" +LIGHT="#EAEAEA" +NUMFONT="/System/Library/Fonts/Supplemental/Arial Bold.ttf" # badge + legend numbers +TEXTFONT="/System/Library/Fonts/SFNS.ttf" # legend body (San Francisco) + +# Pre-render badge glyphs 1..6 (36px circle, centered black number). +for n in 1 2 3 4 5 6; do + magick -size 40x40 xc:none \ + -fill "$YELLOW" -draw "circle 20,20 20,2" \ + -gravity center -font "$NUMFONT" -pointsize 23 -fill black -annotate +0+0 "$n" \ + "$BADGE_DIR/$n.png" +done + +# annotate NAME BG BOTTOM_PAD LEGEND_X LEGEND_Y0 LEGEND_DY BADGES LEGEND [LEGEND_PT] +# reads $RAW/NAME.png, writes $OUT/NAME.png +# BADGES : newline-separated "num badge_cx badge_cy target_x target_y" +# LEGEND : newline-separated "num|text" (blank num => unnumbered continuation) +annotate() { + local name="$1" bg="$2" pad="$3" lx="$4" ly0="$5" ldy="$6" badges="$7" legend="$8" + local legpt="${9:-27}" + local input="$RAW/$name.png" output="$OUT/$name.png" + local W H; read W H < <(magick identify -format "%w %h\n" "$input") + + local args=( "$input" ) + # Pad below for an over-long legend; chop the window's 1px bottom edge first so + # the join to the flat background is seamless. + [ "$pad" -gt 0 ] && args+=( -gravity South -chop 0x2 -background "$bg" -gravity NorthWest -extent "${W}x$((H+pad))" ) + args+=( -gravity NorthWest ) + + # Leader lines first (the badge circle is drawn on top, hiding the stub). + args+=( -stroke "$YELLOW" -strokewidth 3 -fill none ) + while IFS= read -r b; do + [ -z "$b" ] && continue + set -- $b; args+=( -draw "line $2,$3 $4,$5" ) + done <<< "$badges" + + # Badges: composite pre-rendered glyphs on top of the leader stubs. + args+=( -stroke none ) + while IFS= read -r b; do + [ -z "$b" ] && continue + set -- $b + args+=( "(" "$BADGE_DIR/$1.png" -geometry "+$(($2-20))+$(($3-20))" ")" -composite ) + done <<< "$badges" + + # Legend (yellow number + light body text), one line per entry. + local i=0 + while IFS= read -r l; do + [ -z "$l" ] && continue + local num="${l%%|*}" text="${l#*|}" y=$((ly0 + i*ldy)) + args+=( -font "$NUMFONT" -pointsize "$legpt" -fill "$YELLOW" -annotate "+${lx}+${y}" "$num" ) + args+=( -font "$TEXTFONT" -pointsize "$legpt" -fill "$LIGHT" -annotate "+$((lx+34))+${y}" "$text" ) + i=$((i+1)) + done <<< "$legend" + + args+=( "$output" ) + magick "${args[@]}" + echo "wrote $output ($(magick identify -format '%wx%h' "$output"))" +} + +# ---- Peripheral tab ---- +annotate peripheral-tab "#292929" 0 88 583 47 \ +"2 838 205 895 205 +3 1108 352 1108 312 +1 1050 483 1092 483" \ +"1|Register a Magic device so Magic Switch can manage and hand it off +2|Release — hand this peripheral to the other Mac +3|Remove — stop managing this peripheral" + +# ---- Peripheral tab: type picker (single badge) ---- +annotate peripheral-type-picker "#292929" 0 88 730 47 \ +"1 185 158 118 200" \ +"1|Click a peripheral's icon to pick a type — or Automatic to auto-detect" + +# ---- Device tab ---- +annotate device-tab "#282828" 0 88 465 47 \ +"1 932 272 932 230 +2 1021 272 1021 230 +3 1097 272 1097 230 +4 1075 322 1102 322" \ +"1|Ping — check the other Mac is reachable +2|Share — sync your registered peripherals to that Mac +3|Remove — forget this Mac +4|Refresh — rescan the network for nearby Macs" + +# ---- Other tab (legend extends below the window) ---- +annotate other-tab "#292929" 150 88 715 47 \ +"1 1055 148 1085 148 +2 1055 240 1085 240 +3 1055 332 1085 332 +4 1078 424 1108 424 +5 160 655 160 612" \ +"1|Launch at Login — start Magic Switch when you log in +2|Release peripherals to the other Mac when this Mac sleeps +3|Reconnect peripherals automatically if they drop +4|License Information — open-source license details +5|Check for Updates — check now (status shows on the right)" + +# ---- Menu (translucent material background, smaller legend) ---- +annotate menu "#2D2D30" 150 24 405 36 \ +"1 435 72 380 72 +2 435 223 380 223" \ +"1|Click a Mac — move all peripherals there +2|Click a peripheral — move just that one + |✓ = it's on this Mac now" 20 diff --git a/docs/assets/device-tab.png b/docs/assets/device-tab.png index c5b677c..5603e75 100644 Binary files a/docs/assets/device-tab.png and b/docs/assets/device-tab.png differ diff --git a/docs/assets/menu.png b/docs/assets/menu.png index df18f83..1cb92d5 100644 Binary files a/docs/assets/menu.png and b/docs/assets/menu.png differ diff --git a/docs/assets/other-tab.png b/docs/assets/other-tab.png index 74dbf2c..1c9f706 100644 Binary files a/docs/assets/other-tab.png and b/docs/assets/other-tab.png differ diff --git a/docs/assets/peripheral-tab.png b/docs/assets/peripheral-tab.png index 4de65f0..c65e055 100644 Binary files a/docs/assets/peripheral-tab.png and b/docs/assets/peripheral-tab.png differ diff --git a/docs/assets/peripheral-type-picker.png b/docs/assets/peripheral-type-picker.png new file mode 100644 index 0000000..fca7e15 Binary files /dev/null and b/docs/assets/peripheral-type-picker.png differ