Skip to content

Commit

Permalink
Add option to toggle window control buttons (#9083)
Browse files Browse the repository at this point in the history
# 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.
  • Loading branch information
aleksa2808 authored Jul 23, 2023
1 parent 453bd05 commit 5e8ee10
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 7 deletions.
3 changes: 2 additions & 1 deletion crates/bevy_window/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ impl Plugin for WindowPlugin {
.register_type::<InternalWindowState>()
.register_type::<MonitorSelection>()
.register_type::<WindowResizeConstraints>()
.register_type::<WindowTheme>();
.register_type::<WindowTheme>()
.register_type::<EnabledButtons>();

// Register `PathBuf` as it's used by `FileDragAndDrop`
app.register_type::<PathBuf>();
Expand Down
54 changes: 51 additions & 3 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,21 @@ pub struct Window {
/// Note: This does not stop the program from fullscreening/setting
/// the size programmatically.
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?
///
/// (Decorations are the minimize, maximize, and close buttons on desktop apps)
///
// ## Platform-specific
//
// **`iOS`**, **`Android`**, and the **`Web`** do not have decorations.
/// ## Platform-specific
///
/// **`iOS`**, **`Android`**, and the **`Web`** do not have decorations.
pub decorations: bool,
/// Should the window be transparent?
///
Expand Down Expand Up @@ -221,6 +229,7 @@ impl Default for Window {
ime_enabled: Default::default(),
ime_position: Default::default(),
resizable: true,
enabled_buttons: Default::default(),
decorations: true,
transparent: false,
focused: true,
Expand Down Expand Up @@ -1001,3 +1010,42 @@ pub enum WindowTheme {
/// Use the dark variant.
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,
}
}
}
16 changes: 15 additions & 1 deletion crates/bevy_winit/src/converters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use bevy_input::{
ButtonState,
};
use bevy_math::Vec2;
use bevy_window::{CursorIcon, WindowLevel, WindowTheme};
use bevy_window::{CursorIcon, EnabledButtons, WindowLevel, WindowTheme};

pub fn convert_keyboard_input(
keyboard_input: &winit::event::KeyboardInput,
Expand Down Expand Up @@ -293,3 +293,17 @@ pub fn convert_window_theme(theme: WindowTheme) -> winit::window::Theme {
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
}
9 changes: 8 additions & 1 deletion crates/bevy_winit/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ use winit::{
use crate::web_resize::{CanvasParentResizeEventChannel, WINIT_CANVAS_SELECTOR};
use crate::{
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,
};

Expand Down Expand Up @@ -222,6 +225,10 @@ pub(crate) fn changed_window(
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 {
let constraints = window.resize_constraints.check_constraints();
let min_inner_size = LogicalSize {
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_winit/src/winit_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use winit::{

use crate::{
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.
Expand Down Expand Up @@ -94,6 +94,7 @@ impl WinitWindows {
.with_window_level(convert_window_level(window.window_level))
.with_theme(window.window_theme.map(convert_window_theme))
.with_resizable(window.resizable)
.with_enabled_buttons(convert_enabled_buttons(window.enabled_buttons))
.with_decorations(window.decorations)
.with_transparent(window.transparent);

Expand Down
30 changes: 30 additions & 0 deletions examples/window/window_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ fn main() {
// Tells wasm not to override default event handling, like F5, Ctrl+R etc.
prevent_default_event_handling: false,
window_theme: Some(WindowTheme::Dark),
enabled_buttons: bevy::window::EnabledButtons {
maximize: false,
..Default::default()
},
..default()
}),
..default()
Expand All @@ -34,6 +38,7 @@ fn main() {
toggle_theme,
toggle_cursor,
toggle_vsync,
toggle_window_controls,
cycle_cursor_icon,
switch_level,
),
Expand Down Expand Up @@ -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
fn change_title(mut windows: Query<&mut Window>, time: Res<Time>) {
let mut window = windows.single_mut();
Expand Down

0 comments on commit 5e8ee10

Please sign in to comment.