Skip to content

Repository files navigation

KVM Switch

Мгновенное переключение клавиатуры и трекпада между двумя Mac по локальной сети (software KVM). Девайсы остаются спарены по Bluetooth с одним Mac — Bluetooth не трогается вообще. Ввод форвардится по TCP, переключение по хоткею мгновенное.

Симметрично: на обоих Mac стоит одно и то же приложение, каждый может и отдавать ввод, и принимать. Всё управление — из иконки в меню-баре, без терминала.

Почему не Bluetooth-свитчер

Apple Magic Trackpad/Keyboard хранят бонд только с одним хостом — любой свитчер переспаривает девайс на каждом переключении (10–15 с и отвалы). KVM это обходит.

Сборка (на обоих Mac)

./build.sh        # нужен Xcode CLT: xcode-select --install
open "KVM Switch.app"

Права (System Settings → Privacy & Security)

Перетащи KVM Switch.app и включи:

  • Accessibility — обязательно (и для перехвата, и для воспроизведения ввода)
  • Input Monitoring — обязательно (перехват клавиатуры)
  • Локальная сеть — macOS спросит при первом запуске (для авто-поиска)

build.sh использует сертификат «KVM Switch Signing», если он установлен. С ним подпись остаётся стабильной. При fallback на ad-hoc после пересборки может понадобиться заново выдать права. Сертификат создаётся через ./setup-signing.sh. Для существующей другой подписи можно передать KVM_SIGNING_IDENTITY="имя сертификата" ./build.sh; это позволяет сохранить identity, уже разрешённую на конкретном Mac.

Иконка в меню-баре

  • 🔴 связи нет
  • 🟢 связь есть, ввод на этом Mac
  • 🔵 связь есть, ввод уходит на второй Mac

Клик по иконке показывает: имя/IP этого Mac, состояние исходящей связи (→) и входящей (←), порт, хоткей.

Настройка (всё из приложения)

Иконка → Настройки…:

  • Второй Mac — выбор из найденных в сети (Bonjour) либо вручную IP/host + порт
  • Хоткей — нажми кнопку и набери свою комбинацию (по умолчанию ⌃⌥⌘S)
  • Край экрана — тумблер + направление (где стоит второй Mac). Курсор уходит на второй Mac, когда упрёшься в крайнее ребро ВСЕХ твоих экранов (внутренние стыки мониторов не триггерят — между своими экранами ходишь свободно). Возврат — упереться в обратный край на втором Mac. Нужен непрерывный push (~120 px): набор текста, остановка/смена направления и пауза между движениями более 250 мс сбрасывают накопленное движение к краю.
  • Автозапуск — тумблер «запускать при логине»

Выбрать второй Mac можно и быстро: иконка → Второй Mac → клик по имени.

Как пользоваться

  1. Запусти приложение на обоих Mac, выдай права.
  2. При первой настройке единственный найденный Mac выбирается автоматически. Если найдено несколько, выбери второй в подменю «Второй Mac». Существующий выбор сохраняется.
  3. Иконка станет 🟢 — связь есть.
  4. Жми хоткей (⌃⌥⌘S) — ввод мгновенно уходит на второй Mac (🔵), ещё раз — назад (🟢). Можно и через иконку → «Переключить ввод».

Экстренный возврат: ⌃⌥⌘Esc на ноутбуке, к которому подключена клавиатура. Это сочетание фиксировано и не зависит от настроенного хоткея.

Подключать клавиатуру и мышь можно к любому из двух Mac: роли сервера и клиента не назначаются. Физический ввод на принимающем Mac прекращает текущую удалённую сессию; следующий переход через край или хоткей может передавать ввод в обратную сторону. Программные события от приложений (например, вставка текста) и события мыши без движения не прекращают удалённую сессию. Приложение не переключает Bluetooth-сопряжение устройств само.

Надёжность (версия 1.1.3)

Обновить нужно оба Mac. Старый peer не отвечает на новый протокол проверки работоспособности: с ним новая версия оставляет ввод локальным.

  • Каждые 250 мс запрашивается ответ от потока приложения, обрабатывающего ввод. Без свежего ответа передача прекращается: проверка выполняется на каждом физическом событии и таймером. Срок ответа — 1,5 с; планировщик ОС может задержать выполнение таймера. Одного открытого TCP-соединения недостаточно.
  • Перехват начинается только после подтверждения сессии вторым Mac. Пока ответ не пришёл, обычные события проходят локально. Просроченные подтверждения игнорируются.
  • Ошибки отправки, EOF, смена настроек и отключение event tap возвращают локальный режим. Старые callbacks соединений не могут отменить новое соединение.
  • При удалённом управлении локальный курсор скрывает отдельный помощник. Он не удерживает курсор и не отключает связь мыши с курсором. Основной процесс продлевает разрешение на скрытие каждые 250 мс только при здоровой связи; без продления через 1 секунду помощник показывает курсор и завершает работу. Остановка всего основного процесса не останавливает этот таймер.
  • Перехват начинается после подтверждения и второго Mac, и помощника курсора. Если помощник завис, основное приложение возвращается в local и завершает именно свой дочерний процесс; его скрытие снимается WindowServer.
  • Для скрытия курсора из фонового menu-bar приложения используется свойство WindowServer SetsCursorInBackground, как в распространённых macOS KVM. Это частный API: при отсутствии нужных символов передача остаётся выключенной. После крупных обновлений macOS скрытие и восстановление требуют перепроверки.
  • При завершении сессии, разрыве связи и физическом перехвате управления освобождаются клавиши, модификаторы и кнопки мыши, нажатые через приложение.
  • После задержки главного потока или сна старые сессии закрываются. Возобновление соединения само по себе не включает перехват: нужен новый переход/хоткей.
  • Инжектируемые события помечаются и не возвращаются в сеть.

Проверка изменений

python3 tests/run.py
./build.sh

Автоматические проверки подменяют вывод событий, чтобы не нажимать клавиши и не двигать курсор пользователя. Они не заменяют проверку на двух Mac с реальными правами Accessibility/Input Monitoring. План такой проверки — в VALIDATION.md.

Ограничения

Передаются курсор, клики, drag, прокрутка и жесты трекпада, обычные клавиши macOS, F1–F20, навигация, цифровой блок и левые/правые модификаторы. Сохраняются автоповтор и тип клавиатуры. Мультимедийные и специальные клавиши передаются как события systemDefined subtype 8; поддержаны документированные коды IOKit 0–23, кроме Power (6), а также Menu (25). Их фактическое действие зависит от оборудования и настроек принимающего Mac. Caps Lock не считается постоянно зажатой клавишей; нажатия хоткея переключения зарезервированы до отпускания.

Touch ID, Power, неизвестные системные события и функции, которые macOS не выдаёт event tap, остаются локальными. Защищённый ввод macOS не обходится. Раскладку определяет принимающий Mac. Прокрутка трекпада передаётся вместе с фазами, инерцией и дробными дельтами, а мультитач-жесты приложений (pinch, поворот, smart zoom, свайп между страницами, force click) — как сериализованное событие CG type 29, которое второй Mac воспроизводит у своего курсора. Жесты Dock (свайпы Spaces/Mission Control, Launchpad) обрабатывает не event tap, а служба мультитача, поэтому они остаются локальными.

Для активной передачи запрашивается точность таймеров и I/O, а для TCP — приоритет интерактивного трафика. Геометрия экранов обновляется при изменении конфигурации дисплеев вместо запроса на каждом движении. Это уменьшает работу в пути обработки событий, но не устраняет задержки и потери Wi-Fi.

Плавность курсора (1.1.3)

Приложение ищет второй Mac через Bonjour в общей Wi-Fi/Ethernet сети. includePeerToPeer выключен для поиска, приёма и исходящей связи: KVM больше не запрашивает прямое радиообнаружение Apple. Системные AirDrop/Continuity и настройки Wi-Fi не изменяются. Для соединения обоим Mac нужна общая LAN; прямой режим без общей сети в этой версии не используется.

Последовательные движения без нажатой кнопки, уже пришедшие одной пачкой, объединяются в одно обновление курсора. Геометрия и возврат через край считаются для каждого движения. Клики, перетаскивание, клавиши, модификаторы и управляющие сообщения разделяют пачки. Дополнительного таймера сглаживания или задержки нет. Это сокращает воспроизведение накопившихся движений, но не скрывает сетевые паузы.

Apple о диагностике задержек и peer-to-peer Wi-Fi.

About

Instant keyboard/trackpad sharing between two Macs over TCP (software KVM) — menu-bar app, hotkey or edge-of-screen switching, no Bluetooth re-pairing

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages