Skip to content

Commit 46eb9e5

Browse files
rluederlocalcc
andauthored
Update scale factor and drawable size when macOS window changes screen (#38269)
Summary Fixes UI scaling issue that occurs when starting Zed after disconnecting an external monitor on macOS. The window's scale factor and drawable size are now properly updated when the window changes screens. Problem Description When an external monitor is disconnected and Zed is started with only the built-in screen active, the UI scale becomes incorrect. This happens because: 1. macOS triggers the `window_did_change_screen` callback when a window moves between displays (including when displays are disconnected) 2. The existing implementation only restarted the display link but didn't update the window's scale factor or drawable size 3. This left the window with stale scaling information from the previous display configuration Root Cause The `window_did_change_screen` callback in `crates/gpui/src/platform/mac/window.rs` was missing the logic to update the window's scale factor and drawable size when moving between screens. This logic was only present in the `view_did_change_backing_properties callback`, which isn't triggered when external monitors are disconnected. Solution - Extracted common logic: Created a new `update_window_scale_factor()` function that encapsulates the scale factor and drawable size update logic - Added scale factor update to screen change: Modified `window_did_change_screen` to call this function after restarting the display link - Refactored existing code: Updated `view_did_change_backing_properties` to use the new shared function, reducing code duplication The fix ensures that whenever a window changes screens (due to monitor disconnect, reconnect, or manual movement), the scale factor, drawable size, and renderer state are properly synchronized. Testing - ✅ Verified that UI scaling remains correct after disconnecting external monitor - ✅ Confirmed that reconnecting external monitor works properly - ✅ Tested that manual window movement between displays updates scaling correctly - ✅ No regressions observed in normal window operations To verity my fix worked I had to copy my preview workspace over my dev workspace, once I had done this I could reproduce the issue on main consistently. After switching to the branch with this fix the issue was resolved. The fix is similar to what was done on #35686 (Windows) Closes #37245 #38229 Release Notes: - Fixed: Update scale factor and drawable size when macOS window changes screen --------- Co-authored-by: Kate <[email protected]>
1 parent cb7bd5f commit 46eb9e5

File tree

1 file changed

+27
-21
lines changed

1 file changed

+27
-21
lines changed

crates/gpui/src/platform/mac/window.rs

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,10 +1967,36 @@ extern "C" fn window_did_move(this: &Object, _: Sel, _: id) {
19671967
}
19681968
}
19691969

1970+
// Update the window scale factor and drawable size, and call the resize callback if any.
1971+
fn update_window_scale_factor(window_state: &Arc<Mutex<MacWindowState>>) {
1972+
let mut lock = window_state.as_ref().lock();
1973+
let scale_factor = lock.scale_factor();
1974+
let size = lock.content_size();
1975+
let drawable_size = size.to_device_pixels(scale_factor);
1976+
unsafe {
1977+
let _: () = msg_send![
1978+
lock.renderer.layer(),
1979+
setContentsScale: scale_factor as f64
1980+
];
1981+
}
1982+
1983+
lock.renderer.update_drawable_size(drawable_size);
1984+
1985+
if let Some(mut callback) = lock.resize_callback.take() {
1986+
let content_size = lock.content_size();
1987+
let scale_factor = lock.scale_factor();
1988+
drop(lock);
1989+
callback(content_size, scale_factor);
1990+
window_state.as_ref().lock().resize_callback = Some(callback);
1991+
};
1992+
}
1993+
19701994
extern "C" fn window_did_change_screen(this: &Object, _: Sel, _: id) {
19711995
let window_state = unsafe { get_window_state(this) };
19721996
let mut lock = window_state.as_ref().lock();
19731997
lock.start_display_link();
1998+
drop(lock);
1999+
update_window_scale_factor(&window_state);
19742000
}
19752001

19762002
extern "C" fn window_did_change_key_status(this: &Object, selector: Sel, _: id) {
@@ -2079,27 +2105,7 @@ extern "C" fn make_backing_layer(this: &Object, _: Sel) -> id {
20792105

20802106
extern "C" fn view_did_change_backing_properties(this: &Object, _: Sel) {
20812107
let window_state = unsafe { get_window_state(this) };
2082-
let mut lock = window_state.as_ref().lock();
2083-
2084-
let scale_factor = lock.scale_factor();
2085-
let size = lock.content_size();
2086-
let drawable_size = size.to_device_pixels(scale_factor);
2087-
unsafe {
2088-
let _: () = msg_send![
2089-
lock.renderer.layer(),
2090-
setContentsScale: scale_factor as f64
2091-
];
2092-
}
2093-
2094-
lock.renderer.update_drawable_size(drawable_size);
2095-
2096-
if let Some(mut callback) = lock.resize_callback.take() {
2097-
let content_size = lock.content_size();
2098-
let scale_factor = lock.scale_factor();
2099-
drop(lock);
2100-
callback(content_size, scale_factor);
2101-
window_state.as_ref().lock().resize_callback = Some(callback);
2102-
};
2108+
update_window_scale_factor(&window_state);
21032109
}
21042110

21052111
extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) {

0 commit comments

Comments
 (0)