Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
8aac293
bench: add Plan A 5K60 synthetic spike
oosuhada May 14, 2026
3c3809e
bench: record Windows 5K60 synthetic result
oosuhada May 14, 2026
06a0dbd
test: review Plan A spike
oosuhada May 14, 2026
b0b7597
bench: isolate receiver render costs
oosuhada May 14, 2026
921ae30
feat: add receiver benchmark HUD
oosuhada May 14, 2026
0a1b53e
test: review Windows receiver milestone
oosuhada May 14, 2026
0b9ccde
feat: add macOS primary synthetic encoder
oosuhada May 14, 2026
eac1695
test: review macOS primary milestone
oosuhada May 14, 2026
16b5600
feat: define protocol v0 parser
oosuhada May 14, 2026
31a391e
test: review protocol milestone
oosuhada May 14, 2026
1f7cf4c
bench: attempt Plan B 5K compressed transport
oosuhada May 14, 2026
db60ac6
test: review Plan B compressed attempt
oosuhada May 14, 2026
1fefb73
bench: compare Plan C scaled modes
oosuhada May 14, 2026
c19e5d6
test: review Plan C scaled modes
oosuhada May 14, 2026
85134c8
probe: add power measurement plan
oosuhada May 14, 2026
e4d827c
test: review power probe
oosuhada May 14, 2026
cca583d
docs: update current work handoff
oosuhada May 14, 2026
54c4480
feat: prepare Plan C end-to-end pipeline
oosuhada May 14, 2026
4b3b16e
bench: compare MacBook Pro primary encode
oosuhada May 15, 2026
057f6b5
research: add codec reference workspace
oosuhada May 15, 2026
1e75e7f
Analyze codec references and iMac prep
oosuhada May 15, 2026
b51cf20
Probe VideoToolbox encode properties
oosuhada May 15, 2026
5c0b549
bench: compare primary encode source strategies
oosuhada May 15, 2026
443de79
bench: investigate tiled 5K60 encode sustain
oosuhada May 15, 2026
25b4171
docs: define tiled 5K60 prototype strategy
oosuhada May 15, 2026
19cc574
bench: add sender transmission profile matrix
oosuhada May 15, 2026
aad0505
bench: isolate single stream sender stability
oosuhada May 15, 2026
b7c3eff
bench: probe encoder fallback recovery
oosuhada May 15, 2026
a1f629d
bench: record M1 Air sender profile matrix
oosuhada May 15, 2026
bcf71d5
probe: plan wired transport gate
oosuhada May 15, 2026
bbc0c74
probe: record current Tailscale network matrix
oosuhada May 15, 2026
c16379c
bench: probe encoder reset session hints
oosuhada May 15, 2026
b195a87
bench: add clean session fallback gate
oosuhada May 15, 2026
426eb13
Document multi-device iBridge test plan
oosuhada May 16, 2026
758f1ed
Record 2017 iMac LAN baseline
oosuhada May 16, 2026
b73ba9d
Record 2017 iMac iPerf matrix
oosuhada May 16, 2026
800fe64
Document 2017 iMac SSH recovery
oosuhada May 16, 2026
11d0904
Limit 2017 iMac tests to 4K
oosuhada May 16, 2026
551bcba
Add macOS receiver smoke app
oosuhada May 16, 2026
51ef6ff
Ignore macOS receiver build outputs
oosuhada May 16, 2026
2bc1fcd
bench: capture MBA to 2015 iMac Wi-Fi prep
oosuhada May 16, 2026
8093c81
bench: measure MBA to 2015 iMac Wi-Fi throughput
oosuhada May 16, 2026
601d9d4
docs: record 2015 iMac SSH prep
oosuhada May 16, 2026
93bed7c
fix: flush mac receiver diagnostics
oosuhada May 16, 2026
8f2e01a
bench: smoke MBA to 2015 iMac receiver
oosuhada May 16, 2026
85d1ec9
bench: validate 2017 iMac macOS receiver path
oosuhada May 16, 2026
2bfc617
feat: add MBA to 2015 iMac live capture scripts
oosuhada May 16, 2026
2ef0e95
feat: target virtual display for MBA live capture
oosuhada May 16, 2026
00ea8ab
bench: validate BetterDisplay virtual capture
oosuhada May 16, 2026
6838e05
feat: add one-command virtual display startup
oosuhada May 16, 2026
7aeef13
fix: hide mac receiver status overlay
oosuhada May 16, 2026
de4829c
Package macOS alpha display workflow
oosuhada May 16, 2026
2f4784a
Add wired high quality alpha profile
oosuhada May 16, 2026
a5afcab
Add capture backpressure for wired display streaming
oosuhada May 17, 2026
7d92a02
Tune wired 4K60 latency profile
oosuhada May 17, 2026
636fa97
Add immediate 2017 iMac 4K60 launch path
oosuhada May 17, 2026
9210518
Add receiver input relay MVP
oosuhada May 17, 2026
a1cbcf8
Add input relay diagnostics
oosuhada May 17, 2026
8bbdba0
Harden receiver input capture
oosuhada May 17, 2026
360734e
Hide captured cursor for receiver input
oosuhada May 17, 2026
2940382
Correct receiver pointer coordinate mapping
oosuhada May 17, 2026
414c41c
Add 2017 iMac quality profile
oosuhada May 17, 2026
83f713c
Smooth fullscreen receiver pointer edges
oosuhada May 17, 2026
7738d3c
Select virtual capture displays by name
oosuhada May 17, 2026
dda9f4e
Document 2015 iMac Ethernet smoke results
oosuhada May 17, 2026
e4c875b
Add macOS control app for iBridge sessions
oosuhada May 17, 2026
fb8b740
Remove controller build artifacts
oosuhada May 17, 2026
176d5c5
Redesign control app for multi-iMac sessions
oosuhada May 17, 2026
f42871a
Split control app sender and receiver tabs
oosuhada May 17, 2026
a790713
Polish iBridge Studio app shell
oosuhada May 17, 2026
c91aa53
Refine iBridge Studio visual layout
oosuhada May 17, 2026
36f1479
Unify app icon and receiver layout
oosuhada May 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
.DS_Store
logs/env/
logs/power/
logs/ping_*.txt
logs/iperf3_*.txt
apps/primary-macos/.build/
apps/receiver-macos/.build/
apps/controller-macos/.build/
dist/

# Local display captures can contain private screen contents.
benchmarks/runs/**/*display_*.png

# Local third-party source references are analysis inputs, not vendored code.
reference/*
!reference/README.md
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "reference/BetterDisplay"]
path = reference/BetterDisplay
url = https://github.com/waydabber/BetterDisplay.git
branch = opensource
1 change: 1 addition & 0 deletions apps/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
This directory contains the actual software, not just harness docs.

- `primary-macos`: MacBook-side capture/encode/transport app.
- `receiver-macos`: iMac macOS receiver spike for live 4K TCP HEVC/H.264 display.
- `receiver-windows`: iMac Windows receiver app.
- `shared-protocol`: shared protocol definitions/tests.

Expand Down
22 changes: 22 additions & 0 deletions apps/controller-macos/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// swift-tools-version: 6.0

import PackageDescription

let package = Package(
name: "iBridgeController",
platforms: [
.macOS(.v14)
],
products: [
.executable(name: "iBridgeController", targets: ["iBridgeController"])
],
targets: [
.executableTarget(
name: "iBridgeController",
linkerSettings: [
.linkedFramework("AppKit"),
.linkedFramework("SwiftUI")
]
)
]
)
19 changes: 19 additions & 0 deletions apps/controller-macos/Sources/iBridgeController/App.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import SwiftUI

@main
struct IBridgeControllerApp: App {
@StateObject private var model = ControllerModel()

var body: some Scene {
WindowGroup("iBridge Studio", id: "main") {
ContentView()
.environmentObject(model)
}
.windowResizability(.contentMinSize)

MenuBarExtra("iBridge Studio", systemImage: "display.2") {
MenuBarView()
.environmentObject(model)
}
}
}
142 changes: 142 additions & 0 deletions apps/controller-macos/Sources/iBridgeController/Components.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import AppKit
import SwiftUI

struct StudioBackdrop: View {
var body: some View {
ZStack {
Color(nsColor: .windowBackgroundColor)
LinearGradient(
colors: [
Color.blue.opacity(0.08),
Color.teal.opacity(0.05),
Color.clear
],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.ignoresSafeArea()
LinearGradient(
colors: [
Color.white.opacity(0.045),
Color.clear
],
startPoint: .top,
endPoint: .center
)
.ignoresSafeArea()
}
}
}

struct AppIconMark: View {
var body: some View {
Image(nsImage: NSApplication.shared.applicationIconImage)
.resizable()
.aspectRatio(contentMode: .fit)
}
}

struct WindowChromeConfigurator: NSViewRepresentable {
func makeNSView(context: Context) -> NSView {
let view = NSView()
DispatchQueue.main.async {
configure(window: view.window)
}
return view
}

func updateNSView(_ nsView: NSView, context: Context) {
DispatchQueue.main.async {
configure(window: nsView.window)
}
}

private func configure(window: NSWindow?) {
guard let window else { return }
window.titlebarAppearsTransparent = true
window.isOpaque = true
window.backgroundColor = .windowBackgroundColor
window.styleMask.insert(.fullSizeContentView)
}
}

struct GlassPanel<Content: View>: View {
let content: Content

init(@ViewBuilder content: () -> Content) {
self.content = content()
}

var body: some View {
content
.padding(14)
.background(Color(nsColor: .controlBackgroundColor), in: RoundedRectangle(cornerRadius: 8))
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(Color.primary.opacity(0.10), lineWidth: 1)
)
}
}

struct HeaderButton: View {
let title: String
let systemImage: String
let role: ButtonRole?
let action: () -> Void

init(
_ title: String,
systemImage: String,
role: ButtonRole? = nil,
action: @escaping () -> Void
) {
self.title = title
self.systemImage = systemImage
self.role = role
self.action = action
}

var body: some View {
Button(role: role, action: action) {
Label(title, systemImage: systemImage)
}
.controlSize(.large)
}
}

struct StatusPill: View {
let title: String
let color: Color

var body: some View {
HStack(spacing: 6) {
Circle()
.fill(color)
.frame(width: 8, height: 8)
Text(title)
.font(.caption.weight(.medium))
}
.padding(.horizontal, 9)
.padding(.vertical, 5)
.background(color.opacity(0.14), in: Capsule())
}
}

struct LabeledField<Content: View>: View {
let title: String
let content: Content

init(_ title: String, @ViewBuilder content: () -> Content) {
self.title = title
self.content = content()
}

var body: some View {
VStack(alignment: .leading, spacing: 5) {
Text(title)
.font(.caption.weight(.semibold))
.foregroundStyle(.secondary)
content
}
}
}
151 changes: 151 additions & 0 deletions apps/controller-macos/Sources/iBridgeController/ContentView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import AppKit
import SwiftUI

struct ContentView: View {
@EnvironmentObject private var model: ControllerModel

var body: some View {
ZStack {
StudioBackdrop()
VStack(spacing: 0) {
HeaderView()
Divider().opacity(0.6)
StudioTabPicker()
Divider().opacity(0.45)
Group {
switch model.selectedTab {
case .sender:
SenderTab()
case .receiver:
ReceiverTab()
case .logs:
LogTab()
}
}
}
}
.background(WindowChromeConfigurator())
.frame(minWidth: 760, minHeight: 720)
}
}

struct StudioTabPicker: View {
@EnvironmentObject private var model: ControllerModel

var body: some View {
HStack {
Spacer()

Picker("Mode", selection: $model.selectedTab) {
ForEach(StudioTab.allCases) { tab in
Label(tab.rawValue, systemImage: tab.systemImage)
.tag(tab)
}
}
.pickerStyle(.segmented)
.frame(width: 360)
.labelsHidden()

Spacer()
}
.padding(.horizontal, 20)
.padding(.vertical, 12)
.background(.thinMaterial)
}
}

struct HeaderView: View {
@EnvironmentObject private var model: ControllerModel

var body: some View {
HStack(spacing: 14) {
AppIconMark()
.frame(width: 54, height: 54)
.accessibilityHidden(true)

VStack(alignment: .leading, spacing: 2) {
Text("iBridge Studio")
.font(.title3.weight(.semibold))
Text("Turn your retired iMacs into Retina monitors")
.font(.caption)
.foregroundStyle(.secondary)
}

Spacer()

HeaderButton("Refresh Displays", systemImage: "display.2") {
model.listDisplays()
}
.disabled(model.isListingDisplays)

HeaderButton("Restore Windows", systemImage: "rectangle.on.rectangle") {
model.restoreWindowsToMacBook()
}

HeaderButton("Stop All", systemImage: "stop.fill", role: .destructive) {
model.stopAllSenders()
}
}
.padding(.horizontal, 20)
.padding(.vertical, 16)
.background {
Rectangle()
.fill(Color(nsColor: .controlBackgroundColor))
.overlay(
LinearGradient(
colors: [
Color.white.opacity(0.07),
Color.white.opacity(0.02),
Color.clear
],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
)
}
}
}

struct MenuBarView: View {
@EnvironmentObject private var model: ControllerModel
@Environment(\.openWindow) private var openWindow

var body: some View {
Button("Show iBridge Studio") {
openWindow(id: "main")
NSApp.activate(ignoringOtherApps: true)
}

Divider()

Button("Refresh Displays") {
model.listDisplays()
}

Button("Restore Windows to MacBook") {
model.restoreWindowsToMacBook()
}

Divider()

Menu("Add Sender") {
ForEach(presets) { preset in
Button(preset.name) {
model.addSession(preset: preset)
openWindow(id: "main")
NSApp.activate(ignoringOtherApps: true)
}
}
}

Button("Stop All Senders") {
model.stopAllSenders()
}

Divider()

Button("Quit iBridge Studio") {
NSApp.terminate(nil)
}
}
}
Loading