diff --git a/crates/ui/src/docking/native_tests.rs b/crates/ui/src/docking/native_tests.rs
--- a/crates/ui/src/docking/native_tests.rs
+++ b/crates/ui/src/docking/native_tests.rs
@@ -664,6 +664,23 @@ fn unused_keys_in_a_native_window_reach_the_app() {
     assert!(out.forwarded_events.is_empty());
 }
 
+#[test]
+fn the_key_that_ends_a_fields_editing_is_not_forwarded() {
+    // Enter ends a text field's editing in a native window and takes its focus in the same frame:
+    // the main window must not also act on it (VectorCraft opened its Move dialog).
+    let mut d = driver(layout(true));
+    let id = window(&d, 5).id;
+    d.content.text = Some(5);
+    d.content.focus_text = true;
+    d.step(vec![]);
+    let enter = Event::Key { key: Key::Enter, physical_key: None, pressed: true, repeat: false, modifiers: Modifiers::NONE };
+    let out = d.window_step(id, vec![enter]);
+    assert!(out.forwarded_events.is_empty(), "{:?}", out.forwarded_events);
+    // With the field done, the window's keys are the app's again.
+    let out = d.window_step(id, vec![Event::Text("v".into())]);
+    assert_eq!(out.forwarded_events, vec![Event::Text("v".into())]);
+}
+
 #[cfg(feature = "serde")]
 #[test]
 fn a_native_window_saves_its_id_place_and_monitor() {
diff --git a/crates/ui/src/docking/render/native.rs b/crates/ui/src/docking/render/native.rs
--- a/crates/ui/src/docking/render/native.rs
+++ b/crates/ui/src/docking/render/native.rs
@@ -654,6 +654,9 @@ impl<P: Clone + Eq + Hash + Debug + Send + Sync + 'static> Renderer<'_, P> {
             if own {
                 crate::ime::window::begin_window(ui.ctx());
             }
+            // A field that had the keyboard as the frame began took this frame's keys, even if
+            // they ended its editing (Enter): they are not forwarded.
+            let had_focus = ui.memory(|m| m.focused().is_some());
             self.floating_body(ui, window, body, full);
             if own {
                 self.content.window_drawn(ui);
@@ -695,7 +698,9 @@ impl<P: Clone + Eq + Hash + Debug + Send + Sync + 'static> Renderer<'_, P> {
             } else {
                 self.paint_cross(ui, &mut surface);
                 self.route_body_drag(ui.ctx(), Some(window.id));
-                self.forward_events(ui);
+                if !had_focus {
+                    self.forward_events(ui);
+                }
                 self.report_files(ui, window, viewport);
             }
             ui.input(|i| Report {
diff --git a/docs/ui-docking.md b/docs/ui-docking.md
--- a/docs/ui-docking.md
+++ b/docs/ui-docking.md
@@ -573,7 +573,8 @@ windows from the first frame. `DockArea::native_windows(bool)` overrides the cho
   `DockOutput::forwarded_events`, with the modifiers held in that window in
   `DockOutput::forwarded_modifiers` (egui-winit sends Cmd/Ctrl+C, X and V as `Copy`, `Cut` and
   `Paste` without the key). The app feeds them to the shortcut handling it runs on the main
-  window. A window where any widget has keyboard focus forwards nothing, and an Escape that
+  window. A window where any widget has keyboard focus forwards nothing, nor does a frame that
+  began with one: the Enter that ends a text field's editing is the field's. An Escape that
   cancels a drag is not forwarded.
 - **Input methods.** egui's IME descriptor (`PlatformOutput::ime`) goes out from the pass of
   the window whose editor has the keyboard. A `craft_ui::ime::Composer` in a panel body of a
