Add option to toggle window control buttons (#9083)
# Objective Implements #9082 but with an option to toggle minimize and close buttons too. ## Solution - Added an `enabled_buttons` member to the `Window` struct through which users can enable or disable specific window control buttons. --- ## Changelog - Added an `enabled_buttons` member to the `Window` struct through which users can enable or disable specific window control buttons. - Added a new system to the `window_settings` example which demonstrates the toggling functionality. --- ## Migration guide - Added an `enabled_buttons` member to the `Window` struct through which users can enable or disable specific window control buttons.
This commit is contained in:
parent
453bd058fe
commit
5e8ee108cb
@ -141,7 +141,8 @@ impl Plugin for WindowPlugin {
|
|||||||
.register_type::<InternalWindowState>()
|
.register_type::<InternalWindowState>()
|
||||||
.register_type::<MonitorSelection>()
|
.register_type::<MonitorSelection>()
|
||||||
.register_type::<WindowResizeConstraints>()
|
.register_type::<WindowResizeConstraints>()
|
||||||
.register_type::<WindowTheme>();
|
.register_type::<WindowTheme>()
|
||||||
|
.register_type::<EnabledButtons>();
|
||||||
|
|
||||||
// Register `PathBuf` as it's used by `FileDragAndDrop`
|
// Register `PathBuf` as it's used by `FileDragAndDrop`
|
||||||
app.register_type::<PathBuf>();
|
app.register_type::<PathBuf>();
|
||||||
|
@ -126,13 +126,21 @@ pub struct Window {
|
|||||||
/// Note: This does not stop the program from fullscreening/setting
|
/// Note: This does not stop the program from fullscreening/setting
|
||||||
/// the size programmatically.
|
/// the size programmatically.
|
||||||
pub resizable: bool,
|
pub resizable: bool,
|
||||||
|
/// Specifies which window control buttons should be enabled.
|
||||||
|
///
|
||||||
|
/// ## Platform-specific
|
||||||
|
///
|
||||||
|
/// **`iOS`**, **`Android`**, and the **`Web`** do not have window control buttons.
|
||||||
|
///
|
||||||
|
/// On some **`Linux`** environments these values have no effect.
|
||||||
|
pub enabled_buttons: EnabledButtons,
|
||||||
/// Should the window have decorations enabled?
|
/// Should the window have decorations enabled?
|
||||||
///
|
///
|
||||||
/// (Decorations are the minimize, maximize, and close buttons on desktop apps)
|
/// (Decorations are the minimize, maximize, and close buttons on desktop apps)
|
||||||
///
|
///
|
||||||
// ## Platform-specific
|
/// ## Platform-specific
|
||||||
//
|
///
|
||||||
// **`iOS`**, **`Android`**, and the **`Web`** do not have decorations.
|
/// **`iOS`**, **`Android`**, and the **`Web`** do not have decorations.
|
||||||
pub decorations: bool,
|
pub decorations: bool,
|
||||||
/// Should the window be transparent?
|
/// Should the window be transparent?
|
||||||
///
|
///
|
||||||
@ -221,6 +229,7 @@ impl Default for Window {
|
|||||||
ime_enabled: Default::default(),
|
ime_enabled: Default::default(),
|
||||||
ime_position: Default::default(),
|
ime_position: Default::default(),
|
||||||
resizable: true,
|
resizable: true,
|
||||||
|
enabled_buttons: Default::default(),
|
||||||
decorations: true,
|
decorations: true,
|
||||||
transparent: false,
|
transparent: false,
|
||||||
focused: true,
|
focused: true,
|
||||||
@ -1001,3 +1010,42 @@ pub enum WindowTheme {
|
|||||||
/// Use the dark variant.
|
/// Use the dark variant.
|
||||||
Dark,
|
Dark,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Specifies which [`Window`] control buttons should be enabled.
|
||||||
|
///
|
||||||
|
/// ## Platform-specific
|
||||||
|
///
|
||||||
|
/// **`iOS`**, **`Android`**, and the **`Web`** do not have window control buttons.
|
||||||
|
///
|
||||||
|
/// On some **`Linux`** environments these values have no effect.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Reflect)]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "serialize",
|
||||||
|
derive(serde::Serialize, serde::Deserialize),
|
||||||
|
reflect(Serialize, Deserialize)
|
||||||
|
)]
|
||||||
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
pub struct EnabledButtons {
|
||||||
|
/// Enables the functionality of the minimize button.
|
||||||
|
pub minimize: bool,
|
||||||
|
/// Enables the functionality of the maximize button.
|
||||||
|
///
|
||||||
|
/// macOS note: When [`Window`] `resizable` member is set to `false`
|
||||||
|
/// the maximize button will be disabled regardless of this value.
|
||||||
|
/// Additionaly, when `resizable` is set to `true` the window will
|
||||||
|
/// be maximized when its bar is double-clicked regardless of whether
|
||||||
|
/// the maximize button is enabled or not.
|
||||||
|
pub maximize: bool,
|
||||||
|
/// Enables the functionality of the close button.
|
||||||
|
pub close: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EnabledButtons {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
minimize: true,
|
||||||
|
maximize: true,
|
||||||
|
close: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@ use bevy_input::{
|
|||||||
ButtonState,
|
ButtonState,
|
||||||
};
|
};
|
||||||
use bevy_math::Vec2;
|
use bevy_math::Vec2;
|
||||||
use bevy_window::{CursorIcon, WindowLevel, WindowTheme};
|
use bevy_window::{CursorIcon, EnabledButtons, WindowLevel, WindowTheme};
|
||||||
|
|
||||||
pub fn convert_keyboard_input(
|
pub fn convert_keyboard_input(
|
||||||
keyboard_input: &winit::event::KeyboardInput,
|
keyboard_input: &winit::event::KeyboardInput,
|
||||||
@ -293,3 +293,17 @@ pub fn convert_window_theme(theme: WindowTheme) -> winit::window::Theme {
|
|||||||
WindowTheme::Dark => winit::window::Theme::Dark,
|
WindowTheme::Dark => winit::window::Theme::Dark,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn convert_enabled_buttons(enabled_buttons: EnabledButtons) -> winit::window::WindowButtons {
|
||||||
|
let mut window_buttons = winit::window::WindowButtons::empty();
|
||||||
|
if enabled_buttons.minimize {
|
||||||
|
window_buttons.insert(winit::window::WindowButtons::MINIMIZE);
|
||||||
|
}
|
||||||
|
if enabled_buttons.maximize {
|
||||||
|
window_buttons.insert(winit::window::WindowButtons::MAXIMIZE);
|
||||||
|
}
|
||||||
|
if enabled_buttons.close {
|
||||||
|
window_buttons.insert(winit::window::WindowButtons::CLOSE);
|
||||||
|
}
|
||||||
|
window_buttons
|
||||||
|
}
|
||||||
|
@ -23,7 +23,10 @@ use winit::{
|
|||||||
use crate::web_resize::{CanvasParentResizeEventChannel, WINIT_CANVAS_SELECTOR};
|
use crate::web_resize::{CanvasParentResizeEventChannel, WINIT_CANVAS_SELECTOR};
|
||||||
use crate::{
|
use crate::{
|
||||||
accessibility::{AccessKitAdapters, WinitActionHandlers},
|
accessibility::{AccessKitAdapters, WinitActionHandlers},
|
||||||
converters::{self, convert_window_level, convert_window_theme, convert_winit_theme},
|
converters::{
|
||||||
|
self, convert_enabled_buttons, convert_window_level, convert_window_theme,
|
||||||
|
convert_winit_theme,
|
||||||
|
},
|
||||||
get_best_videomode, get_fitting_videomode, WinitWindows,
|
get_best_videomode, get_fitting_videomode, WinitWindows,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -222,6 +225,10 @@ pub(crate) fn changed_window(
|
|||||||
winit_window.set_resizable(window.resizable);
|
winit_window.set_resizable(window.resizable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if window.enabled_buttons != cache.window.enabled_buttons {
|
||||||
|
winit_window.set_enabled_buttons(convert_enabled_buttons(window.enabled_buttons));
|
||||||
|
}
|
||||||
|
|
||||||
if window.resize_constraints != cache.window.resize_constraints {
|
if window.resize_constraints != cache.window.resize_constraints {
|
||||||
let constraints = window.resize_constraints.check_constraints();
|
let constraints = window.resize_constraints.check_constraints();
|
||||||
let min_inner_size = LogicalSize {
|
let min_inner_size = LogicalSize {
|
||||||
|
@ -18,7 +18,7 @@ use winit::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
accessibility::{AccessKitAdapters, WinitActionHandler, WinitActionHandlers},
|
accessibility::{AccessKitAdapters, WinitActionHandler, WinitActionHandlers},
|
||||||
converters::{convert_window_level, convert_window_theme},
|
converters::{convert_enabled_buttons, convert_window_level, convert_window_theme},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A resource which maps window entities to [`winit`] library windows.
|
/// A resource which maps window entities to [`winit`] library windows.
|
||||||
@ -94,6 +94,7 @@ impl WinitWindows {
|
|||||||
.with_window_level(convert_window_level(window.window_level))
|
.with_window_level(convert_window_level(window.window_level))
|
||||||
.with_theme(window.window_theme.map(convert_window_theme))
|
.with_theme(window.window_theme.map(convert_window_theme))
|
||||||
.with_resizable(window.resizable)
|
.with_resizable(window.resizable)
|
||||||
|
.with_enabled_buttons(convert_enabled_buttons(window.enabled_buttons))
|
||||||
.with_decorations(window.decorations)
|
.with_decorations(window.decorations)
|
||||||
.with_transparent(window.transparent);
|
.with_transparent(window.transparent);
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@ fn main() {
|
|||||||
// Tells wasm not to override default event handling, like F5, Ctrl+R etc.
|
// Tells wasm not to override default event handling, like F5, Ctrl+R etc.
|
||||||
prevent_default_event_handling: false,
|
prevent_default_event_handling: false,
|
||||||
window_theme: Some(WindowTheme::Dark),
|
window_theme: Some(WindowTheme::Dark),
|
||||||
|
enabled_buttons: bevy::window::EnabledButtons {
|
||||||
|
maximize: false,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
..default()
|
..default()
|
||||||
@ -34,6 +38,7 @@ fn main() {
|
|||||||
toggle_theme,
|
toggle_theme,
|
||||||
toggle_cursor,
|
toggle_cursor,
|
||||||
toggle_vsync,
|
toggle_vsync,
|
||||||
|
toggle_window_controls,
|
||||||
cycle_cursor_icon,
|
cycle_cursor_icon,
|
||||||
switch_level,
|
switch_level,
|
||||||
),
|
),
|
||||||
@ -76,6 +81,31 @@ fn switch_level(input: Res<Input<KeyCode>>, mut windows: Query<&mut Window>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This system toggles the window controls when pressing buttons 1, 2 and 3
|
||||||
|
///
|
||||||
|
/// This feature only works on some platforms. Please check the
|
||||||
|
/// [documentation](https://docs.rs/bevy/latest/bevy/prelude/struct.Window.html#structfield.enabled_buttons)
|
||||||
|
/// for more details.
|
||||||
|
fn toggle_window_controls(input: Res<Input<KeyCode>>, mut windows: Query<&mut Window>) {
|
||||||
|
let toggle_minimize = input.just_pressed(KeyCode::Key1);
|
||||||
|
let toggle_maximize = input.just_pressed(KeyCode::Key2);
|
||||||
|
let toggle_close = input.just_pressed(KeyCode::Key3);
|
||||||
|
|
||||||
|
if toggle_minimize || toggle_maximize || toggle_close {
|
||||||
|
let mut window = windows.single_mut();
|
||||||
|
|
||||||
|
if toggle_minimize {
|
||||||
|
window.enabled_buttons.minimize = !window.enabled_buttons.minimize;
|
||||||
|
}
|
||||||
|
if toggle_maximize {
|
||||||
|
window.enabled_buttons.maximize = !window.enabled_buttons.maximize;
|
||||||
|
}
|
||||||
|
if toggle_close {
|
||||||
|
window.enabled_buttons.close = !window.enabled_buttons.close;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This system will then change the title during execution
|
/// This system will then change the title during execution
|
||||||
fn change_title(mut windows: Query<&mut Window>, time: Res<Time>) {
|
fn change_title(mut windows: Query<&mut Window>, time: Res<Time>) {
|
||||||
let mut window = windows.single_mut();
|
let mut window = windows.single_mut();
|
||||||
|
Loading…
Reference in New Issue
Block a user