Merge #244: a native window moved by its only tab joins a body's center

This commit is contained in:
aiongg committed 2026-10-24 04:49:51 +00:00
commit 85c8cf1cd5
3 files changed
+47 -6

No files matched your search

+37
View File
@@ -859,6 +859,43 @@ fn the_only_tab_of_a_native_window_docks_it_with_title_bar_docks_off() {
assert!(!in_root(&d, 7));
}
#[test]
fn the_only_tab_of_a_native_window_fills_and_joins_a_frame_bodys_center() {
let mut layout = layout(false);
layout.floating.push(Floating::single(vec![7], 0, [300.0, 80.0, 240.0, 200.0]));
let style = |s: &mut super::DockStyle| {
s.side_edge_zones = true;
s.title_bar_docks = false;
s.float_hint = false;
};
let mut d = DockDriver::new(layout, Content::default()).with_style(style).with_native_host(ORIGIN);
let id = window(&d, 7).id;
// The middle of frame [3, 4], in the main window.
let middle = pos2(600.0, 300.0);
let from = pos2(15.0, TAB_ROW);
d.window_step(id, vec![Event::PointerMoved(from), button(from, true)]);
d.window_step(id, vec![Event::PointerMoved(from + vec2(8.0, 6.0))]);
for _ in 0..2 {
let local = d.window_local(id, ORIGIN + middle.to_vec2()).unwrap();
d.window_step(id, vec![Event::PointerMoved(local)]);
}
// The center rectangle is the only zone around the pointer: outlined and filled.
let zone = |filled: bool| {
d.shapes().iter().any(|clipped| match &clipped.shape {
egui::Shape::Path(path) => {
path.closed && (path.fill != Color32::TRANSPARENT) == filled && Rect::from_points(&path.points).contains(middle)
}
_ => false,
})
};
assert!(zone(false), "outlined");
assert!(zone(true), "filled");
let local = d.window_local(id, ORIGIN + middle.to_vec2()).unwrap();
let out = d.window_step(id, vec![button(local, false)]);
assert!(matches!(window_move(&out), Some(Target::At { anchor: 3 | 4, placement: Placement::Split(super::Zone::Center) })), "{:?}", out.actions);
assert!(in_root(&d, 7));
}
#[test]
fn a_native_window_forwards_no_keys_while_one_of_its_widgets_has_focus() {
let mut d = driver(layout(true));
+8 -5
View File
@@ -116,7 +116,8 @@ impl<P: Clone + Eq + Hash + Debug + Send + Sync + 'static> Renderer<'_, P> {
/// The valid target under the pointer for a whole group. A target holding the group
/// itself is a no-op proposal; a target the model would reject is no target. A window
/// moving live looks through itself and does not split frames or join a body's center.
/// moving live looks through itself and does not split frames or, moved by its bar, join
/// a body's center.
pub(super) fn group_proposal(&self, drag: &GroupDrag<P>, pointer: Pos2) -> Option<DropProposal<P>> {
let window = drag.gesture == GroupGesture::Window;
if let Some(proposal) = self.extra_proposal(&drag.members, pointer, window) {
@@ -148,14 +149,16 @@ impl<P: Clone + Eq + Hash + Debug + Send + Sync + 'static> Renderer<'_, P> {
}
let proposal = self.resolve_roomy(&drag.panel, pointer, std::slice::from_ref(target), |to| group_action(drag, to))?;
// A window moving live splits only groups of other floating windows. A native
// window's bar also takes the main window's frame edges, but not a body's center.
// window's bar also takes the main window's frame edges, but not a body's center. A
// native window moved by its only tab or group joins a body's center too, as that tab
// or group drag would.
let into_window = matches!(self.place(&proposal.anchor), Some(Place::Floating { .. }));
#[cfg(feature = "native-windows")]
let edges = self.cross.bar;
let (edges, joins) = (self.cross.bar, self.cross.docks);
#[cfg(not(feature = "native-windows"))]
let edges = false;
let (edges, joins) = (false, false);
let split = match proposal.placement {
Placement::Split(Zone::Center) => true,
Placement::Split(Zone::Center) => !joins,
Placement::Split(_) => !edges,
_ => false,
};
+2 -1
View File
@@ -439,7 +439,8 @@ that is not floatable, stays in-window. Floating windows get no taskbar or Alt-T
`DockStyle::title_bar_docks`; the only tab or group docks either way, since it is the way
back in with that flag off. Targets: in the
main window a dock line, a frame's tab row or edge zone, or the layout's outer edge; in a
floating window a frame zone or tab row. A frame body's center takes no whole window. Over
floating window a frame zone or tab row. A frame body's center takes a window moved by its
only tab or group, as that tab or group drag would, but not one moved by its bar. Over
the desktop, or with Ctrl/Cmd held, it stays where it was moved, and the layout takes its
place once, at the release. Escape puts it back. An
in-window floating window's title bar still splits only groups of other floating windows.