Skip to content

Commit 8097f90

Browse files
committed
Refine Apple HP live-view scaling
1 parent 319c0a9 commit 8097f90

2 files changed

Lines changed: 89 additions & 29 deletions

File tree

examples/client/applehp_protocol.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,15 +351,12 @@ apple_hp_make_set_display_message(uint8_t combine_all_displays, uint32_t display
351351
}
352352

353353
static inline struct apple_hp_scale_factor_message
354-
apple_hp_make_native_scale_factor_message(void) {
354+
apple_hp_make_scale_factor_message(double scale) {
355355
struct apple_hp_scale_factor_message msg;
356-
static const uint8_t kNativeScaleFactorBe[8] = {
357-
0x3f, 0xea, 0x75, 0x92, 0x03, 0xca, 0xe7, 0x59,
358-
};
359356

360357
memset(&msg, 0, sizeof(msg));
361358
msg.type = APPLE_HP_MSG_SCALE_FACTOR;
362-
memcpy(msg.scale_be, kNativeScaleFactorBe, sizeof(msg.scale_be));
359+
apple_hp_store_be_double(msg.scale_be, scale);
363360
return msg;
364361
}
365362

examples/client/applehpdebug.c

Lines changed: 87 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,10 @@ static int env_flag_default_true(const char *name) {
606606
return env_flag_enabled(name);
607607
}
608608

609+
static int env_flag_default_false(const char *name) {
610+
return env_flag_enabled(name);
611+
}
612+
609613
static const char *apple_hp_getenv_first(const char *a, const char *b) {
610614
const char *s = NULL;
611615
if (a) {
@@ -907,10 +911,11 @@ static uint32_t apple_hp_visible_content_pad(void) {
907911
}
908912

909913
static int apple_hp_visible_crop_enabled(void) {
910-
/* Dynamic-resolution backing surfaces can carry trailing black padding
911-
* after the server downsizes the virtual display. Crop detection is
912-
* therefore on by default for the HP live-view path, with an env opt-out. */
913-
return env_flag_default_true("VNC_APPLE_HP_VISIBLE_CROP");
914+
/* HP backing/layout sizes are authoritative for rendering. Heuristic crop
915+
* detection can misclassify legitimate dark regions during startup and after
916+
* layout changes, which distorts the live-view aspect. Keep cropping opt-in
917+
* for debugging and edge cases instead of enabling it by default. */
918+
return env_flag_default_false("VNC_APPLE_HP_VISIBLE_CROP");
914919
}
915920

916921
static int apple_hp_dynamic_target_materially_diff(uint16_t a_w, uint16_t a_h,
@@ -1210,8 +1215,37 @@ static int send_set_display_message(rfbClient *client) {
12101215
return send_blob(client, &msg, sizeof(msg), "apple-hp post-rekey hello");
12111216
}
12121217

1218+
static double apple_hp_runtime_scale_factor(void) {
1219+
#if defined(APPLEHPDEBUG_HAS_SDL)
1220+
int window_w = 0;
1221+
int window_h = 0;
1222+
int output_w = 0;
1223+
int output_h = 0;
1224+
double scale_x;
1225+
double scale_y;
1226+
double scale;
1227+
1228+
if (!g_runtime.live_view || !g_live.window || !g_live.renderer) return 1.0;
1229+
SDL_GetWindowSize(g_live.window, &window_w, &window_h);
1230+
if (window_w <= 0 || window_h <= 0) return 1.0;
1231+
if (SDL_GetRendererOutputSize(g_live.renderer, &output_w, &output_h) < 0) return 1.0;
1232+
if (output_w <= 0 || output_h <= 0) return 1.0;
1233+
scale_x = (double)output_w / (double)window_w;
1234+
scale_y = (double)output_h / (double)window_h;
1235+
scale = ((scale_x > scale_y) ? scale_x : scale_y) * 0.5;
1236+
if (scale > 0.95 && scale < 1.05) scale = 1.0;
1237+
if (scale < 0.5) scale = 0.5;
1238+
if (scale > 2.0) scale = 2.0;
1239+
return scale;
1240+
#else
1241+
return 1.0;
1242+
#endif
1243+
}
1244+
12131245
static int send_native_scale_factor_message(rfbClient *client) {
1214-
struct apple_hp_scale_factor_message msg = apple_hp_make_native_scale_factor_message();
1246+
double scale = apple_hp_runtime_scale_factor();
1247+
struct apple_hp_scale_factor_message msg = apple_hp_make_scale_factor_message(scale);
1248+
rfbClientLog("apple-hp: using scale factor %.6f\n", scale);
12151249
return send_blob(client, &msg, sizeof(msg), "apple-hp scale factor");
12161250
}
12171251

@@ -1964,34 +1998,52 @@ static int live_view_runtime_display_size(rfbClient *client, uint16_t *out_w, ui
19641998
#if defined(APPLEHPDEBUG_HAS_SDL)
19651999
int window_w = 0;
19662000
int window_h = 0;
2001+
int output_w = 0;
2002+
int output_h = 0;
19672003
int display_index = 0;
19682004
int w = 0;
19692005
int h = 0;
19702006
Uint32 window_flags = 0;
19712007
SDL_Rect bounds;
19722008

19732009
if (!client || !out_w || !out_h) return 0;
1974-
if (g_live.runtime_size_valid &&
1975-
g_live.cached_runtime_w > 0 &&
1976-
g_live.cached_runtime_h > 0) {
1977-
*out_w = g_live.cached_runtime_w;
1978-
*out_h = g_live.cached_runtime_h;
1979-
return 1;
1980-
}
19812010
memset(&bounds, 0, sizeof(bounds));
19822011
if (g_live.window) {
19832012
window_flags = SDL_GetWindowFlags(g_live.window);
19842013
display_index = SDL_GetWindowDisplayIndex(g_live.window);
19852014
if (display_index < 0) display_index = 0;
19862015
SDL_GetWindowSize(g_live.window, &window_w, &window_h);
19872016
}
2017+
if (g_live.renderer) {
2018+
if (SDL_GetRendererOutputSize(g_live.renderer, &output_w, &output_h) < 0) {
2019+
output_w = 0;
2020+
output_h = 0;
2021+
}
2022+
}
2023+
if (output_w > 0 && output_h > 0) {
2024+
int hidpi_scale = 1;
2025+
if (window_w > 0) {
2026+
int inferred = (output_w + (window_w / 2)) / window_w;
2027+
if (inferred > hidpi_scale) hidpi_scale = inferred;
2028+
}
2029+
if (window_h > 0) {
2030+
int inferred = (output_h + (window_h / 2)) / window_h;
2031+
if (inferred > hidpi_scale) hidpi_scale = inferred;
2032+
}
2033+
if (hidpi_scale < 1) hidpi_scale = 1;
2034+
w = output_w / hidpi_scale;
2035+
h = output_h / hidpi_scale;
2036+
}
19882037
if ((window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0 ||
19892038
(window_flags & SDL_WINDOW_FULLSCREEN) != 0) {
19902039
/* Dynamic-resolution requests should follow the logical fullscreen window
19912040
* size in points, not the HiDPI drawable size in pixels. On macOS the
19922041
* actual fullscreen window size tracks the drawable area more reliably
19932042
* than display bounds, which can include extra space and produce bars. */
1994-
if (window_w > 0 && window_h > 0) {
2043+
if (w > 0 && h > 0) {
2044+
/* Prefer normalized drawable size when available; it reflects the
2045+
* actual fullscreen content area more accurately than window chrome. */
2046+
} else if (window_w > 0 && window_h > 0) {
19952047
w = window_w;
19962048
h = window_h;
19972049
} else if (SDL_GetDisplayUsableBounds(display_index, &bounds) == 0 &&
@@ -2235,17 +2287,13 @@ static int compute_live_view_geometry(rfbClient *client, struct apple_hp_live_vi
22352287
geom->src.h = client->height > 0 ? client->height : 1;
22362288
}
22372289
if (g_runtime.apple_hp_mode && geom->src.w > 0 && geom->src.h > 0) {
2238-
if (g_hp.visible_content_valid &&
2239-
geom->src.x == g_hp.visible_content_x &&
2240-
geom->src.y == g_hp.visible_content_y &&
2241-
geom->src.w == g_hp.visible_content_w &&
2242-
geom->src.h == g_hp.visible_content_h) {
2243-
fit_src_w = geom->src.w;
2244-
fit_src_h = geom->src.h;
2245-
} else {
2246-
fit_src_w = display_w > 0 ? display_w : geom->src.w;
2247-
fit_src_h = display_h > 0 ? display_h : geom->src.h;
2248-
}
2290+
/* Fit using the actual sampled backing/source rectangle. Apple HP often
2291+
* reports logical display dimensions that differ slightly from the backing
2292+
* it actually returns (for example 1616x1010 vs 3211x2007). Using the
2293+
* logical size for presentation introduces small bars and makes the source
2294+
* overlay appear larger than the destination box. */
2295+
fit_src_w = geom->src.w;
2296+
fit_src_h = geom->src.h;
22492297
fit_w = geom->output_w;
22502298
fit_h = (int)(((long long)fit_w * (long long)fit_src_h) / (long long)fit_src_w);
22512299
if (fit_h > geom->output_h) {
@@ -3229,6 +3277,21 @@ static rfbBool handle_hp_probe_encoding(rfbClient *client, rfbFramebufferUpdateR
32293277
}
32303278
g_hp.initial_full_refresh_done = 0;
32313279
g_hp.initial_full_refresh_retries = 0;
3280+
if (!g_live.window_user_sized) {
3281+
uint16_t startup_target_w = 0;
3282+
uint16_t startup_target_h = 0;
3283+
if (apple_hp_compute_dynamic_resolution_target(client, &startup_target_w, &startup_target_h) &&
3284+
startup_target_w != 0 && startup_target_h != 0 &&
3285+
apple_hp_dynamic_target_materially_diff(startup_target_w, startup_target_h,
3286+
scaled_w, scaled_h)) {
3287+
g_live.last_runtime_w = startup_target_w;
3288+
g_live.last_runtime_h = startup_target_h;
3289+
if (!maybe_send_dynamic_resolution_update(client, "startup-layout", TRUE)) {
3290+
free(payload);
3291+
return FALSE;
3292+
}
3293+
}
3294+
}
32323295
}
32333296
if (client && scaled_w != 0 && scaled_h != 0 &&
32343297
(scaled_w != prev_display_w || scaled_h != prev_display_h ||

0 commit comments

Comments
 (0)