Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
ebcad4b
fix(input): preserve receiver-master click count
freebo Jul 28, 2026
4c78e89
Merge pull request #150 from freebo/codex/fix-receiver-master-double-…
swellweb Jul 28, 2026
40af3c3
Release 3.3.1
swellweb Jul 28, 2026
9589f1f
feat(sender): add brightness & volume sliders to the menu bar
aalpgiray Jul 26, 2026
7d09729
feat(menubar): Night Shift and True Tone for the receiver's display
aalpgiray Jul 29, 2026
be11162
Fix receiver identity after wake and color metadata
swellweb Jul 31, 2026
6c7c696
Merge remote-tracking branch 'origin/pr/152' into codex/verify-pr152
swellweb Aug 1, 2026
df57d7a
Build and publish Sender for x86_64
preggocl Aug 2, 2026
a900826
Fix Sender architecture artifact paths
preggocl Aug 2, 2026
d8ec334
Merge pull request #155 from preggocl/upstream-intel-ci-release
swellweb Aug 2, 2026
57c9228
release: prepare v3.4.2
swellweb Aug 2, 2026
14afe68
feat: measure and select direct USB4 network paths
Betafer Aug 7, 2026
6a382e1
perf: add stable Retina 4K 60 fps capture
Betafer Aug 7, 2026
62c9790
feat: make monitor sessions headless and stoppable
Betafer Aug 7, 2026
11a10af
fix(receiver): keep fullscreen video above notifications
Betafer Aug 7, 2026
8fafbe9
Merge pull request #162 from Betafer/codex/receiver-notification-shield
swellweb Aug 9, 2026
8c1b7dd
Merge pull request #160 from Betafer/codex/retina-4k60
swellweb Aug 9, 2026
434a3ed
fix(sender): refresh discovered receiver addresses
swellweb Aug 9, 2026
a2c5860
Merge remote-tracking branch 'origin/dev-3.4.0' into dev-3.4.0
swellweb Aug 9, 2026
6d7da90
fix(audio): support interleaved screen capture buffers
swellweb Aug 9, 2026
b5c49b9
chore: prepare 3.4.3 Intel test build
swellweb Aug 9, 2026
dcb9b1d
fix(audio): preserve relay preference across profiles
swellweb Aug 10, 2026
27c208e
feat(network): select the fastest measured connection path
swellweb Aug 10, 2026
3469d6f
feat(automation): support headless lifecycle and persistent stop
swellweb Aug 10, 2026
b59d68f
chore: prepare 3.5.0 release
swellweb Aug 10, 2026
c1b3d40
TargetBridge 3.5.0: measured paths and resilient automation
swellweb Aug 10, 2026
92f930b
fix(receiver): preserve input releases under queue pressure
Betafer Aug 10, 2026
47de0a1
fix(sender): avoid duplicate receiver-master cursor
Betafer Aug 10, 2026
0ce99bf
fix(receiver): advertise the physical display profile
preggocl Aug 15, 2026
ee3e17b
fix(receiver): fall back to software video decode
preggocl Aug 15, 2026
65f3a0f
Merge remote-tracking branch 'origin/pr-165' into maint-3.5
swellweb Aug 18, 2026
4ee00d3
Merge remote-tracking branch 'origin/pr-166' into maint-3.5
swellweb Aug 18, 2026
75a389f
Merge remote-tracking branch 'origin/pr-169' into maint-3.5
swellweb Aug 18, 2026
222e30a
Merge remote-tracking branch 'origin/pr-170' into maint-3.5
swellweb Aug 18, 2026
13f8fd3
ci: validate maintenance 3.5 patches
swellweb Aug 18, 2026
ec96fa3
chore: prepare 3.5.1 maintenance release
swellweb Aug 19, 2026
b9045f1
fix(input): keep receiver master cursor normal by default
swellweb Aug 19, 2026
c842ade
fix(display): preserve native 5K profile and cursor shapes
swellweb Aug 19, 2026
b761ee6
feat: expose privacy permission probes
Betafer Aug 19, 2026
42eee3b
fix(build): package SDL runtimes safely (#189)
swellweb Aug 29, 2026
7620113
fix(receiver): allow display sleep before first session
Betafer Aug 21, 2026
563d0f4
fix(receiver): release audio device while idle
Betafer Aug 19, 2026
60555c3
fix(receiver): guard idle watchdog clock underflow
Betafer Aug 19, 2026
53cfc7e
build: support reproducible app variants
Betafer Aug 19, 2026
7070dec
fix(receiver): keep local login alerts behind monitor
Betafer Aug 21, 2026
9d04f39
test(receiver): cover monitor shield lifecycle and repeated activation
swellweb Sep 5, 2026
25a3374
docs: prepare complete 3.5.1 maintenance release notes
swellweb Sep 5, 2026
fb45b5f
Merge pull request #191 from swellweb/codex/maint-3.5-integration
swellweb Sep 5, 2026
4ec4807
fix(sender): reserve video capacity before encoding reference frames
Betafer Sep 12, 2026
d7bf6e2
fix(sender): distinguish idle capture from a stalled pipeline
Betafer Sep 12, 2026
7532d62
Merge PR #194: preserve encoded video references
swellweb Sep 13, 2026
402ef8e
Merge PR #195: distinguish idle capture from stalls
swellweb Sep 13, 2026
8f734d4
Merge PR #177: expose read-only permission status
swellweb Sep 13, 2026
126141a
test: guard combined capture fixes and permission probes
swellweb Sep 13, 2026
ffc43f3
fix(input): preserve receiver modifiers on relayed pointer events
swellweb Sep 14, 2026
4f67b12
fix(input): apply remote modifiers to local pointer clicks
swellweb Sep 14, 2026
b952c98
release: prepare TargetBridge 3.5.2
swellweb Sep 14, 2026
8ab5c3a
Merge pull request #200 from swellweb/codex/maint-3.5-video-permissions
swellweb Sep 14, 2026
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
25 changes: 21 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ name: CI Build Verification

on:
push:
branches: [ main, 3.1-maint, 3.2-dev, dev-3.3.0 ]
branches: [ main, 3.1-maint, maint-3.5, 3.2-dev, dev-3.3.0, dev-3.4.0 ]
pull_request:
branches: [ main, 3.1-maint, 3.2-dev, dev-3.3.0 ]
branches: [ main, 3.1-maint, maint-3.5, 3.2-dev, dev-3.3.0, dev-3.4.0 ]

jobs:
build-sender:
name: Build Sender (macOS 15 - Apple Silicon)
runs-on: macos-15
name: Build Sender (${{ matrix.os }} - ${{ matrix.arch }})
strategy:
matrix:
include:
- os: macos-15-intel
arch: x86_64
- os: macos-15
arch: arm64
runs-on: ${{ matrix.os }}
steps:
- name: Checkout Code
uses: actions/checkout@v6
Expand All @@ -26,12 +33,19 @@ jobs:
run: |
cd TargetBridge-Sender
./scripts/build_targetbridge_sender_app.sh
file ../build/TargetBridge.app/Contents/MacOS/TargetBridge | grep -q "${{ matrix.arch }}"

- name: Run Sender Unit Tests
run: |
cd TargetBridge-Sender
xcodebuild test -project TargetBridge.xcodeproj -scheme TBDisplaySender -destination 'platform=macOS' -derivedDataPath .build/DerivedData

- name: Check Integrated Video Queue Guards
run: ruby TargetBridge-Sender/scripts/test_video_queue_budget.rb

- name: Check Sender Permission Probe
run: ruby TargetBridge-Sender/scripts/test_permission_status.rb sender build/TargetBridge.app/Contents/MacOS/TargetBridge

build-receiver:
name: Build Receiver (${{ matrix.os }} - ${{ matrix.arch }})
strategy:
Expand Down Expand Up @@ -63,3 +77,6 @@ jobs:
run: |
cd TargetBridge-Receiver
./scripts/build_tbreceiver_c_app.sh

- name: Check Receiver Permission Probe
run: ruby TargetBridge-Sender/scripts/test_permission_status.rb receiver 'build/TargetBridge Receiver.app/Contents/MacOS/TargetBridgeReceiver'
27 changes: 21 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@ permissions:

jobs:
build-sender:
name: Build Sender (Apple Silicon)
runs-on: macos-15
name: Build Sender (${{ matrix.os }} - ${{ matrix.arch }})
strategy:
matrix:
include:
- os: macos-15-intel
arch: x86_64
- os: macos-15
arch: arm64
runs-on: ${{ matrix.os }}
steps:
- name: Checkout Code
uses: actions/checkout@v6
Expand All @@ -26,22 +33,23 @@ jobs:
run: |
cd TargetBridge-Sender
./scripts/build_targetbridge_sender_app.sh
file ../build/TargetBridge.app/Contents/MacOS/TargetBridge | grep -q "${{ matrix.arch }}"

- name: Zip App Bundle
run: |
cd build
zip -r TargetBridge-arm64.app.zip TargetBridge.app
zip -r TargetBridge-${{ matrix.arch }}.app.zip TargetBridge.app

- name: Generate build provenance attestation
uses: actions/attest@v4
with:
subject-path: build/TargetBridge-arm64.app.zip
subject-path: build/TargetBridge-${{ matrix.arch }}.app.zip

- name: Upload Sender Artifact
uses: actions/upload-artifact@v7
with:
name: TargetBridge-arm64.app.zip
path: build/TargetBridge-arm64.app.zip
name: TargetBridge-${{ matrix.arch }}.app.zip
path: build/TargetBridge-${{ matrix.arch }}.app.zip
retention-days: 1

build-receiver:
Expand Down Expand Up @@ -93,6 +101,12 @@ jobs:
uses: actions/checkout@v6

- name: Download Sender Artifact
uses: actions/download-artifact@v8
with:
name: TargetBridge-x86_64.app.zip
path: ./artifacts

- name: Download Sender Artifact (arm64)
uses: actions/download-artifact@v8
with:
name: TargetBridge-arm64.app.zip
Expand All @@ -115,6 +129,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ github.ref_name }}" \
./artifacts/TargetBridge-x86_64.app.zip \
./artifacts/TargetBridge-arm64.app.zip \
./artifacts/TargetBridge-Receiver-x86_64.app.zip \
./artifacts/TargetBridge-Receiver-arm64.app.zip \
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ tbreceiver

# C test outputs
test_net_parser
test_input_queue
test_idle_watchdog
test_receiver_profile
test_monitor_shield
*.dSYM/
47 changes: 42 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,44 @@ contributions help keep the project moving forward.

[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-pink?logo=github)](https://github.com/sponsors/swellweb)

## TargetBridge 3.3
## Contributors

TargetBridge 3.3 improves the reliability of the display connection while
keeping the established multi-Mac workspace features:
Thank you to everyone who tests TargetBridge on real hardware, reports issues,
and improves the project. A special thank-you for this release goes to:

- [@aalpgiray](https://github.com/aalpgiray) for receiver brightness, volume, Night Shift, and True Tone controls.
- [@preggocl](https://github.com/preggocl) for the physical Receiver display profile and the software decode fallback.
- [@Betafer](https://github.com/Betafer) for input-queue safety, cursor work, idle audio/display handling, watchdog protection, monitor shielding, and build improvements.

## TargetBridge 3.5.2

TargetBridge 3.5.2 is a focused maintenance update to the Input Dockstation.
When the Receiver is the input master, Shift and Command now remain active for
multi-file selection even when the keyboard is connected to the Receiver and
the mouse or trackpad is used locally on the Sender. This fixes Finder range
selection and non-contiguous selection without changing ordinary local input.

It also includes the video queue, capture-health and permission-status fixes
prepared for this maintenance line. For the wider 3.5.1 maintenance work,
including Receiver display profiles, idle resource handling, and compatibility
with older Macs:

- preserve keyboard and mouse release events when the Receiver input queue is under pressure
- preserve native macOS cursor shapes by default, including the screenshot crosshair; the custom overlay is reserved for the explicit large-cursor option
- advertise the Receiver's actual panel geometry instead of always reporting a fixed 5K profile
- preserve native 5K panel dimensions when macOS uses a scaled HiDPI desktop
- fall back safely to software video decode when VideoToolbox cannot decode a stream on older hardware
- allow display sleep while the Receiver is waiting, including before the first session
- open audio output only when audio arrives and release it when the session ends
- handle watchdog clock underflow without incorrectly dropping the connection
- keep local notification banners behind the active monitor surface across display/fullscreen transitions
- package SDL runtimes safely and support explicit build/version overrides

See the [full 3.5.2 release notes](docs/releases/3.5.2.md), the
[3.5.1 release notes](docs/releases/3.5.1.md), and the
[testing guide](docs/Testing.md), including the new monitor-shield lifecycle test.

It also keeps the established multi-Mac workspace features:

- mirror mode and extended desktop mode
- multiple receivers from one sender
Expand Down Expand Up @@ -54,8 +88,9 @@ keeping the established multi-Mac workspace features:
- Network Link (experimental): [docs/Features.md#network-link-experimental](docs/Features.md#network-link-experimental)
- Audio Relay: [docs/Features.md#audio-relay](docs/Features.md#audio-relay)
- Input Dockstation, clipboard sync, master/slave roles, and Receiver Master shortcuts: [docs/Features.md#input-dockstation](docs/Features.md#input-dockstation)
- Remote brightness control: [docs/Features.md#remote-brightness-control](docs/Features.md#remote-brightness-control)
- Receiver device controls (brightness, volume, Night Shift, True Tone): [docs/Features.md#receiver-device-controls](docs/Features.md#receiver-device-controls)
- Remote connection & automation (URL scheme, launch args, SSH, login/wake): [docs/Automation.md](docs/Automation.md)
- Measured connection-path selection (Thunderbolt, USB/USB4, Ethernet, Wi-Fi): [docs/Automation.md#1-targetbridge-cli](docs/Automation.md#1-targetbridge-cli)
- Shared translations (English, Italian, German, French, and Chinese): [docs/Features.md#shared-translations](docs/Features.md#shared-translations)
- Thunderbolt networking extras (SSH/SFTP, file sharing, Internet Sharing): [docs/Features.md#thunderbolt-networking-extras](docs/Features.md#thunderbolt-networking-extras)

Expand All @@ -66,6 +101,7 @@ keeping the established multi-Mac workspace features:
- Stream profiles range from `2560 x 1440` to `5120 x 2880` with H.264/HEVC selection based on capability. `5K 60` is an experimental profile for recent Apple Silicon; `5K 48` remains recommended for reliable daily work. See [Display Modes](docs/Features.md#display-modes).
- Receiver discovery is automatic over Bonjour. Extended-display arrangement is remembered per receiver when possible. See [Display Modes](docs/Features.md#display-modes).
- Thunderbolt Bridge remains the primary low-latency path, with `Network Link` available as an experimental addon-gated transport. See [Network Link](docs/Features.md#network-link-experimental).
- The Sender menu can control a connected receiver's brightness, volume, Night Shift, and True Tone when supported. See [Receiver Device Controls](docs/Features.md#receiver-device-controls).

## Official Addons

Expand All @@ -77,7 +113,7 @@ TargetBridge now has a conservative manifest-based addon system. Official manife

## Requirements

- Sender: Apple Silicon Mac (M1 or later), macOS 14 Sonoma or later
- Sender: Apple Silicon Mac (M1 or later) or Intel Mac, macOS 14 Sonoma or later. Apple Silicon remains the primary tested path; Intel Sender builds are available for broader testing.
- Receiver: Intel or Apple Silicon Mac, macOS 11 Big Sur or later
- Thunderbolt cable
- See also [docs/Hardware.md](docs/Hardware.md) for hardware details, tested cables, adapters, and Thunderbolt networking ideas.
Expand All @@ -87,6 +123,7 @@ TargetBridge now has a conservative manifest-based addon system. Official manife
**[→ Download latest release (pre-built apps, no Xcode needed)](https://github.com/swellweb/targetBridge/releases/latest)**

- `TargetBridge-arm64.app.zip` — Sender (for Apple Silicon Macs)
- `TargetBridge-x86_64.app.zip` — Sender (for Intel Macs)
- `TargetBridge-Receiver-arm64.app.zip` — Apple Silicon Receiver (use machine as monitor for sender)
- `TargetBridge-Receiver-x86_64.app.zip` — Intel Receiver (use machine as monitor for sender)

Expand Down
48 changes: 37 additions & 11 deletions TargetBridge-Receiver/TBReceiverC/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@

CC ?= clang
PKG ?= pkgconf
APP_VERSION ?= 3.2.0
APP_VERSION ?= 3.5.2
APP_BUILD ?= dev

MACOSX_DEPLOYMENT_TARGET ?= 11.0
export MACOSX_DEPLOYMENT_TARGET

CFLAGS += -O2 -g -Wall -Wextra -Wno-unused-parameter -std=c11
CFLAGS += $(shell $(PKG) --cflags libavcodec libavutil sdl2)
CFLAGS += $(shell $(PKG) --cflags libavcodec libavutil libswscale sdl2)
CFLAGS += -DTB_RECEIVER_VERSION=\"$(APP_VERSION)\" -DTB_RECEIVER_BUILD=\"$(APP_BUILD)\"
CFLAGS += -DTB_LANGUAGE_SOURCE_DIR=\"$(abspath ../../TargetBridge-Shared/Languages)\"

LDFLAGS += $(shell $(PKG) --libs libavcodec libavutil sdl2)
LDFLAGS += $(shell $(PKG) --libs libavcodec libavutil libswscale sdl2)

UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
LDFLAGS += -framework ApplicationServices -framework AppKit -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework VideoToolbox -framework CoreMedia -framework CoreVideo -framework IOSurface -framework CoreServices -framework CoreAudio
LDFLAGS += -framework ApplicationServices -framework AppKit -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework VideoToolbox -framework CoreMedia -framework CoreVideo -framework IOSurface -framework CoreServices -framework CoreAudio -framework SystemConfiguration
endif

C_SRC = src/main.c src/net.c src/decoder.c src/display.c src/tb_i18n.c
OBJC_SRC = src/tb_gesture_bridge.m
C_SRC = src/main.c src/net.c src/decoder.c src/display.c src/input_queue.c src/idle_watchdog.c src/receiver_profile.c src/tb_i18n.c
OBJC_SRC = src/tb_gesture_bridge.m src/tb_display_tweaks.m
OBJ = $(C_SRC:.c=.o) $(OBJC_SRC:.m=.o)
BIN = tbreceiver

Expand All @@ -51,17 +51,43 @@ $(BIN): $(OBJ)
$(CC) $(CFLAGS) -fobjc-arc -c -o $@ $<

clean:
rm -f $(OBJ) $(BIN) $(TEST_BIN)
rm -f $(OBJ) $(BIN) $(TEST_BIN) $(TEST_INPUT_QUEUE_BIN) $(TEST_IDLE_WATCHDOG_BIN) $(TEST_RECEIVER_PROFILE_BIN) test_monitor_shield

# Unit tests for the packet parser. net.c is pure POSIX, so this needs no
# ffmpeg/SDL/pkgconf — it runs anywhere, including CI, with no hardware.
TEST_CFLAGS = -O2 -g -Wall -Wextra -Wno-unused-parameter -std=c11
TEST_LDFLAGS =
ifeq ($(UNAME_S),Darwin)
TEST_LDFLAGS += -framework CoreFoundation -framework SystemConfiguration
endif
TEST_BIN = test_net_parser
TEST_INPUT_QUEUE_BIN = test_input_queue
TEST_IDLE_WATCHDOG_BIN = test_idle_watchdog
TEST_RECEIVER_PROFILE_BIN = test_receiver_profile

test_net_parser: tests/test_net_parser.c src/net.c src/net.h src/proto.h
$(CC) $(TEST_CFLAGS) -Isrc tests/test_net_parser.c src/net.c $(TEST_LDFLAGS) -o $@

$(TEST_INPUT_QUEUE_BIN): tests/test_input_queue.c src/input_queue.c src/input_queue.h
$(CC) $(TEST_CFLAGS) -Isrc tests/test_input_queue.c src/input_queue.c -o $@

$(TEST_BIN): tests/test_net_parser.c src/net.c src/net.h src/proto.h
$(CC) $(TEST_CFLAGS) -Isrc tests/test_net_parser.c src/net.c -o $@
$(TEST_IDLE_WATCHDOG_BIN): tests/test_idle_watchdog.c src/idle_watchdog.c src/idle_watchdog.h
$(CC) $(TEST_CFLAGS) -Isrc tests/test_idle_watchdog.c src/idle_watchdog.c -o $@

test: $(TEST_BIN)
$(TEST_RECEIVER_PROFILE_BIN): tests/test_receiver_profile.c src/receiver_profile.c src/receiver_profile.h
$(CC) $(TEST_CFLAGS) -Isrc tests/test_receiver_profile.c src/receiver_profile.c -o $@

test: $(TEST_BIN) $(TEST_INPUT_QUEUE_BIN) $(TEST_IDLE_WATCHDOG_BIN) $(TEST_RECEIVER_PROFILE_BIN)
./$(TEST_BIN)
./$(TEST_INPUT_QUEUE_BIN)
./$(TEST_IDLE_WATCHDOG_BIN)
./$(TEST_RECEIVER_PROFILE_BIN)

# AppKit lifecycle coverage requires a logged-in macOS GUI session.
test_monitor_shield: tests/test_monitor_shield.m src/tb_gesture_bridge.m src/tb_gesture_bridge.h
$(CC) -fobjc-arc -framework AppKit -framework CoreGraphics tests/test_monitor_shield.m -o $@

test-monitor-shield: test_monitor_shield
./test_monitor_shield

.PHONY: all clean test
.PHONY: all clean test test-monitor-shield
Loading
Loading