macOS: add WindowEvent::PointerButton::is_macos_activation_click

Apps need per-click decisions to follow the macOS convention of accepting
first mouse for low-risk actions (selection, scrolling) but rejecting it
for buttons and destructive actions. Motivated by slint-ui/slint#10451.

Always return `true` from `acceptsFirstMouse:`, and tag the resulting
`PointerButton` events with `is_macos_activation_click: true` (on both
the activating left press and its matching release) so the app can
short-circuit the whole gesture with a single check:

    WindowEvent::PointerButton { is_macos_activation_click: true, .. } => return,

Replaces an earlier callback-based design (`accepts_first_mouse` on
`ApplicationHandlerExtMacOS`) that mapped more closely to AppKit but
didn't fit winit's event-driven model and required re-entrancy handling.

Also removes `WindowAttributesMacOS::with_accepts_first_mouse`, which is
now redundant — apps that want to reject activation clicks check the
flag on the per-event instead.
This commit is contained in:
Till Adam
2026-06-18 22:39:35 +02:00
committed by Simon Hausmann
parent 92b643c3f1
commit 6a8a334426
15 changed files with 95 additions and 21 deletions

View File

@@ -1873,6 +1873,7 @@ unsafe fn public_window_callback_inner(
_ => unreachable!(),
}
.into(),
is_macos_activation_click: false,
});
result = ProcResult::Value(0);
},
@@ -1902,6 +1903,7 @@ unsafe fn public_window_callback_inner(
_ => unreachable!(),
}
.into(),
is_macos_activation_click: false,
});
result = ProcResult::Value(0);
},
@@ -1930,6 +1932,7 @@ unsafe fn public_window_callback_inner(
position,
// 1 is defined as back, 2 as forward; other codes are unexpected.
button: MouseButton::try_from_u8(b).unwrap().into(),
is_macos_activation_click: false,
});
result = ProcResult::Value(0);
},
@@ -1959,6 +1962,7 @@ unsafe fn public_window_callback_inner(
position,
// 1 is defined as back, 2 as forward; other codes are unexpected.
button: MouseButton::try_from_u8(b).unwrap().into(),
is_macos_activation_click: false,
});
result = ProcResult::Value(0);
},
@@ -2018,6 +2022,7 @@ unsafe fn public_window_callback_inner(
state: Pressed,
position,
button: Touch { finger_id, force: None },
is_macos_activation_click: false,
});
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_UP) {
userdata.send_window_event(window, WindowEvent::PointerButton {
@@ -2026,6 +2031,7 @@ unsafe fn public_window_callback_inner(
state: Released,
position,
button: Touch { finger_id, force: None },
is_macos_activation_click: false,
});
userdata.send_window_event(window, WindowEvent::PointerLeft {
device_id: None,
@@ -2187,6 +2193,7 @@ unsafe fn public_window_callback_inner(
state: Pressed,
position,
button,
is_macos_activation_click: false,
});
} else {
userdata.send_window_event(window, WindowEvent::PointerButton {
@@ -2195,6 +2202,7 @@ unsafe fn public_window_callback_inner(
state: Released,
position,
button,
is_macos_activation_click: false,
});
userdata.send_window_event(window, WindowEvent::PointerLeft {
device_id: None,