Fix dead traffic-light hit area under FullSizeContentViewWindowMask
`move_traffic_light` was framing the close / minimize / zoom NSButtons at `titlebar_height - traffic_light_position.y - button_h`. Once the window opts into `NSFullSizeContentViewWindowMask`, the content layout rectangle covers the whole frame and `titlebar_height()` returns 0 — collapsing the origin to a large negative Y. macOS still painted the buttons through its own caching layer at the title bar's natural position, but the buttons' hit-test rectangle followed the frame off screen, so clicking close / minimize / zoom did nothing. Anchor the math against the close button's actual superview frame height (the themeFrame, which equals the window height in Y-up coordinates) so the visual position and the hit area stay in lockstep no matter what mask combination the window opens with. `titlebar_height` stays available for callers that want the legacy non-full-size interpretation, with `#[allow(dead_code)]` and a docstring pointing at this fix.
This commit is contained in:
+29
-3
@@ -430,8 +430,6 @@ impl MacWindowState {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let titlebar_height = self.titlebar_height();
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let close_button: id = msg_send![
|
let close_button: id = msg_send![
|
||||||
self.native_window,
|
self.native_window,
|
||||||
@@ -449,9 +447,27 @@ impl MacWindowState {
|
|||||||
let mut close_button_frame: CGRect = msg_send![close_button, frame];
|
let mut close_button_frame: CGRect = msg_send![close_button, frame];
|
||||||
let mut min_button_frame: CGRect = msg_send![min_button, frame];
|
let mut min_button_frame: CGRect = msg_send![min_button, frame];
|
||||||
let mut zoom_button_frame: CGRect = msg_send![zoom_button, frame];
|
let mut zoom_button_frame: CGRect = msg_send![zoom_button, frame];
|
||||||
|
|
||||||
|
// The buttons live inside the window's themeFrame, which
|
||||||
|
// is Y-up and shares its height with the window itself.
|
||||||
|
// Using `self.titlebar_height()` here returns 0 once
|
||||||
|
// `NSFullSizeContentViewWindowMask` is set (the content
|
||||||
|
// layout fills the whole window), so the previous
|
||||||
|
// `titlebar_height - y - button_h` math collapsed the
|
||||||
|
// origin to a large negative number — macOS still
|
||||||
|
// painted the buttons through a separate caching layer,
|
||||||
|
// but the hit-test rectangle followed the frame off
|
||||||
|
// screen and clicks stopped reaching close / minimize /
|
||||||
|
// zoom. Anchor against the button's real superview
|
||||||
|
// instead so the frame and the visual position stay in
|
||||||
|
// lockstep.
|
||||||
|
let close_super: id = msg_send![close_button, superview];
|
||||||
|
let super_frame: CGRect = msg_send![close_super, frame];
|
||||||
|
let super_height = px(super_frame.size.height as f32);
|
||||||
|
|
||||||
let mut origin = point(
|
let mut origin = point(
|
||||||
traffic_light_position.x,
|
traffic_light_position.x,
|
||||||
titlebar_height
|
super_height
|
||||||
- traffic_light_position.y
|
- traffic_light_position.y
|
||||||
- px(close_button_frame.size.height as f32),
|
- px(close_button_frame.size.height as f32),
|
||||||
);
|
);
|
||||||
@@ -546,6 +562,16 @@ impl MacWindowState {
|
|||||||
get_scale_factor(self.native_window)
|
get_scale_factor(self.native_window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reports the height of the title bar's NSWindow chrome, i.e. the
|
||||||
|
/// vertical band that NSWindow steals from the window frame for
|
||||||
|
/// the system title and traffic-light controls. Returns 0 with
|
||||||
|
/// `NSFullSizeContentViewWindowMask` (the content layout fills the
|
||||||
|
/// whole frame), which is exactly why `move_traffic_light` cannot
|
||||||
|
/// rely on this value to position custom traffic lights — see the
|
||||||
|
/// long-form comment there. Kept for callers that want the legacy
|
||||||
|
/// "non-full-size" interpretation; do not reach for it from new
|
||||||
|
/// chrome-positioning code.
|
||||||
|
#[allow(dead_code)]
|
||||||
fn titlebar_height(&self) -> Pixels {
|
fn titlebar_height(&self) -> Pixels {
|
||||||
unsafe {
|
unsafe {
|
||||||
let frame = NSWindow::frame(self.native_window);
|
let frame = NSWindow::frame(self.native_window);
|
||||||
|
|||||||
Reference in New Issue
Block a user