Skip to content

Commit 635320f

Browse files
committed
Expose winit always_on_top (#6527)
# Objective I needed a window which is always on top, to create a overlay app. ## Solution expose the `always_on_top` property of winit in bevy's `WindowDescriptor` as a boolean flag --- ## Changelog ### Added - add `WindowDescriptor.always_on_top` which configures a window to stay on top.
1 parent b765682 commit 635320f

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

crates/bevy_window/src/window.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ pub struct Window {
294294
fit_canvas_to_parent: bool,
295295
command_queue: Vec<WindowCommand>,
296296
alpha_mode: CompositeAlphaMode,
297+
always_on_top: bool,
297298
}
298299
/// A command to be sent to a window.
299300
///
@@ -369,6 +370,10 @@ pub enum WindowCommand {
369370
SetResizeConstraints {
370371
resize_constraints: WindowResizeConstraints,
371372
},
373+
/// Set whether the window is always on top.
374+
SetAlwaysOnTop {
375+
always_on_top: bool,
376+
},
372377
Close,
373378
}
374379

@@ -438,6 +443,7 @@ impl Window {
438443
fit_canvas_to_parent: window_descriptor.fit_canvas_to_parent,
439444
command_queue: Vec::new(),
440445
alpha_mode: window_descriptor.alpha_mode,
446+
always_on_top: window_descriptor.always_on_top,
441447
}
442448
}
443449
/// Get the window's [`WindowId`].
@@ -796,6 +802,18 @@ impl Window {
796802
resolution: UVec2::new(self.physical_width, self.physical_height),
797803
});
798804
}
805+
/// Get whether or not the window is always on top.
806+
#[inline]
807+
pub fn always_on_top(&self) -> bool {
808+
self.always_on_top
809+
}
810+
811+
/// Set whether of not the window is always on top.
812+
pub fn set_always_on_top(&mut self, always_on_top: bool) {
813+
self.always_on_top = always_on_top;
814+
self.command_queue
815+
.push(WindowCommand::SetAlwaysOnTop { always_on_top });
816+
}
799817
/// Close the operating system window corresponding to this [`Window`].
800818
///
801819
/// This will also lead to this [`Window`] being removed from the
@@ -972,6 +990,12 @@ pub struct WindowDescriptor {
972990
pub fit_canvas_to_parent: bool,
973991
/// Specifies how the alpha channel of the textures should be handled during compositing.
974992
pub alpha_mode: CompositeAlphaMode,
993+
/// Sets the window to always be on top of other windows.
994+
///
995+
/// ## Platform-specific
996+
/// - iOS / Android / Web: Unsupported.
997+
/// - Linux (Wayland): Unsupported.
998+
pub always_on_top: bool,
975999
}
9761000

9771001
impl Default for WindowDescriptor {
@@ -994,6 +1018,7 @@ impl Default for WindowDescriptor {
9941018
canvas: None,
9951019
fit_canvas_to_parent: false,
9961020
alpha_mode: CompositeAlphaMode::Auto,
1021+
always_on_top: false,
9971022
}
9981023
}
9991024
}

crates/bevy_winit/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,10 @@ fn change_window(
226226
window.set_max_inner_size(Some(max_inner_size));
227227
}
228228
}
229+
bevy_window::WindowCommand::SetAlwaysOnTop { always_on_top } => {
230+
let window = winit_windows.get_window(id).unwrap();
231+
window.set_always_on_top(always_on_top);
232+
}
229233
bevy_window::WindowCommand::Close => {
230234
// Since we have borrowed `windows` to iterate through them, we can't remove the window from it.
231235
// Add the removal requests to a queue to solve this

crates/bevy_winit/src/winit_windows.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ impl WinitWindows {
7272
}
7373
.with_resizable(window_descriptor.resizable)
7474
.with_decorations(window_descriptor.decorations)
75-
.with_transparent(window_descriptor.transparent),
75+
.with_transparent(window_descriptor.transparent)
76+
.with_always_on_top(window_descriptor.always_on_top),
7677
};
7778

7879
let constraints = window_descriptor.resize_constraints.check_constraints();

examples/window/window_settings.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ fn main() {
1515
width: 500.,
1616
height: 300.,
1717
present_mode: PresentMode::AutoVsync,
18+
always_on_top: true,
1819
..default()
1920
},
2021
..default()
@@ -25,6 +26,7 @@ fn main() {
2526
.add_system(toggle_cursor)
2627
.add_system(toggle_vsync)
2728
.add_system(cycle_cursor_icon)
29+
.add_system(toggle_always_on_top)
2830
.run();
2931
}
3032

@@ -43,6 +45,28 @@ fn toggle_vsync(input: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
4345
}
4446
}
4547

48+
/// This system toggles whether the window is always on top when pressing the T button
49+
/// You'll notice it won't be covered by other windows.
50+
///
51+
/// This feature only works on some platforms. Please check the
52+
/// [documentation](https://docs.rs/bevy/latest/bevy/prelude/struct.WindowDescriptor.html#structfield.always_on_top)
53+
/// for more details.
54+
fn toggle_always_on_top(input: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
55+
if input.just_pressed(KeyCode::T) {
56+
let window = windows.primary_mut();
57+
58+
let on_top: bool = window.always_on_top();
59+
60+
if on_top {
61+
info!("UNLOCKING WINDOW");
62+
} else {
63+
info!("LOCKING WINDOW ON TOP");
64+
}
65+
66+
window.set_always_on_top(!on_top);
67+
}
68+
}
69+
4670
/// This system will then change the title during execution
4771
fn change_title(time: Res<Time>, mut windows: ResMut<Windows>) {
4872
let window = windows.primary_mut();

0 commit comments

Comments
 (0)