From 105cb4b8f218048300d7e8125475d65594f4ce46 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 29 Jul 2022 14:21:23 +0200 Subject: [PATCH] eframe: add function to set, query and toggle fullscreen mode (#1866) Closes https://github.com/emilk/egui/pull/674 Adds `NativeOptions:fullscreen`, `Frame::set_fullscreen` and `WindowInfo::fullscreen`. --- eframe/CHANGELOG.md | 1 + eframe/src/epi.rs | 18 ++++++++++++++++++ eframe/src/native/epi_integration.rs | 10 +++++++++- eframe/src/web/backend.rs | 1 + egui-winit/src/window_settings.rs | 19 +++++++++++++++---- egui_demo_app/src/backend_panel.rs | 28 +++++++++++++++++++--------- 6 files changed, 63 insertions(+), 14 deletions(-) diff --git a/eframe/CHANGELOG.md b/eframe/CHANGELOG.md index 8a58f3fe..3cdffbea 100644 --- a/eframe/CHANGELOG.md +++ b/eframe/CHANGELOG.md @@ -23,6 +23,7 @@ NOTE: [`egui-winit`](../egui-winit/CHANGELOG.md), [`egui_glium`](../egui_glium/C * `dark-light` (dark mode detection) is now enabled by default on Mac and Windows ([#1726](https://github.com/emilk/egui/pull/1726)). * Fixed mouse cursor change on Linux ([#1747](https://github.com/emilk/egui/pull/1747)). * Added `Frame::set_visible` ([#1808](https://github.com/emilk/egui/pull/1808)). +* Added fullscreen support ([#1866](https://github.com/emilk/egui/pull/1866)). #### Web: * Added option to select WebGL version ([#1803](https://github.com/emilk/egui/pull/1803)). diff --git a/eframe/src/epi.rs b/eframe/src/epi.rs index 88f48d8f..7d7ac8e8 100644 --- a/eframe/src/epi.rs +++ b/eframe/src/epi.rs @@ -180,6 +180,11 @@ pub struct NativeOptions { /// If false it will be difficult to move and resize the app. pub decorated: bool, + /// Start in (borderless) fullscreen? + /// + /// Default: `false`. + pub fullscreen: bool, + /// On Windows: enable drag and drop support. Drag and drop can /// not be disabled on other platforms. /// @@ -270,6 +275,7 @@ impl Default for NativeOptions { always_on_top: false, maximized: false, decorated: true, + fullscreen: false, drag_and_drop_support: true, icon_data: None, initial_window_pos: None, @@ -547,11 +553,17 @@ impl Frame { } /// Set whether to show window decorations (i.e. a frame around you app). + /// /// If false it will be difficult to move and resize the app. pub fn set_decorations(&mut self, decorated: bool) { self.output.decorated = Some(decorated); } + /// Turn borderless fullscreen on/off (native only). + pub fn set_fullscreen(&mut self, fullscreen: bool) { + self.output.fullscreen = Some(fullscreen); + } + /// set the position of the outer window pub fn set_window_pos(&mut self, pos: egui::Pos2) { self.output.window_pos = Some(pos); @@ -591,6 +603,9 @@ pub struct WindowInfo { /// Unit: egui points (logical pixels). pub position: egui::Pos2, + /// Are we in fullscreen mode? + pub fullscreen: bool, + /// Window inner size in egui points (logical pixels). pub size: egui::Vec2, } @@ -740,6 +755,9 @@ pub mod backend { /// Set to some bool to change window decorations. pub decorated: Option, + /// Set to some bool to change window fullscreen. + pub fullscreen: Option, + /// Set to true to drag window while primary mouse button is down. pub drag_window: bool, diff --git a/eframe/src/native/epi_integration.rs b/eframe/src/native/epi_integration.rs index a6a6d6e0..0c4ae5ad 100644 --- a/eframe/src/native/epi_integration.rs +++ b/eframe/src/native/epi_integration.rs @@ -21,6 +21,7 @@ pub fn read_window_info( .to_logical::(pixels_per_point.into()); Some(WindowInfo { position: egui::Pos2 { x: pos.x, y: pos.y }, + fullscreen: window.fullscreen().is_some(), size: egui::Vec2 { x: size.width, y: size.height, @@ -39,6 +40,7 @@ pub fn window_builder( always_on_top, maximized, decorated, + fullscreen, drag_and_drop_support, icon_data, initial_window_pos, @@ -54,8 +56,9 @@ pub fn window_builder( let mut window_builder = winit::window::WindowBuilder::new() .with_always_on_top(*always_on_top) - .with_maximized(*maximized) .with_decorations(*decorated) + .with_fullscreen(fullscreen.then(|| winit::window::Fullscreen::Borderless(None))) + .with_maximized(*maximized) .with_resizable(*resizable) .with_transparent(*transparent) .with_window_icon(window_icon); @@ -118,6 +121,7 @@ pub fn handle_app_output( window_size, window_title, decorated, + fullscreen, drag_window, window_pos, visible, @@ -137,6 +141,10 @@ pub fn handle_app_output( ); } + if let Some(fullscreen) = fullscreen { + window.set_fullscreen(fullscreen.then(|| winit::window::Fullscreen::Borderless(None))); + } + if let Some(window_title) = window_title { window.set_title(&window_title); } diff --git a/eframe/src/web/backend.rs b/eframe/src/web/backend.rs index ecca55cb..4c445d29 100644 --- a/eframe/src/web/backend.rs +++ b/eframe/src/web/backend.rs @@ -298,6 +298,7 @@ impl AppRunner { window_size: _, // Can't resize a web page window_title: _, // TODO(emilk): change title of window decorated: _, // Can't toggle decorations + fullscreen: _, // TODO(emilk): fullscreen web window drag_window: _, // Can't be dragged window_pos: _, // Can't set position of a web page visible: _, // Can't hide a web page diff --git a/egui-winit/src/window_settings.rs b/egui-winit/src/window_settings.rs index ece4d006..651a4e86 100644 --- a/egui-winit/src/window_settings.rs +++ b/egui-winit/src/window_settings.rs @@ -6,6 +6,9 @@ pub struct WindowSettings { /// the inner or outer position depending on the platform. /// See [`winit::window::WindowAttributes`] for details. position: Option, + + fullscreen: bool, + /// Inner size of window in logical pixels inner_size_points: Option, } @@ -29,6 +32,9 @@ impl WindowSettings { Self { position, + + fullscreen: window.fullscreen().is_some(), + inner_size_points: Some(egui::vec2( inner_size_points.width, inner_size_points.height, @@ -55,10 +61,15 @@ impl WindowSettings { } if let Some(inner_size_points) = self.inner_size_points { - window.with_inner_size(winit::dpi::LogicalSize { - width: inner_size_points.x as f64, - height: inner_size_points.y as f64, - }) + window + .with_inner_size(winit::dpi::LogicalSize { + width: inner_size_points.x as f64, + height: inner_size_points.y as f64, + }) + .with_fullscreen( + self.fullscreen + .then(|| winit::window::Fullscreen::Borderless(None)), + ) } else { window } diff --git a/egui_demo_app/src/backend_panel.rs b/egui_demo_app/src/backend_panel.rs index 17a60c7e..bb9e9a02 100644 --- a/egui_demo_app/src/backend_panel.rs +++ b/egui_demo_app/src/backend_panel.rs @@ -174,15 +174,25 @@ impl BackendPanel { } } - if !frame.is_web() - && ui - .button("📱 Phone Size") - .on_hover_text("Resize the window to be small like a phone.") - .clicked() - { - // frame.set_window_size(egui::Vec2::new(375.0, 812.0)); // iPhone 12 mini - frame.set_window_size(egui::Vec2::new(375.0, 667.0)); // iPhone SE 2nd gen - ui.close_menu(); + if !frame.is_web() { + ui.horizontal(|ui| { + if let Some(window_info) = &frame.info().window_info { + let mut fullscreen = window_info.fullscreen; + ui.checkbox(&mut fullscreen, "🗖 Fullscreen") + .on_hover_text("Fullscreen the window"); + frame.set_fullscreen(fullscreen); + } + + if ui + .button("📱 Phone Size") + .on_hover_text("Resize the window to be small like a phone.") + .clicked() + { + // frame.set_window_size(egui::Vec2::new(375.0, 812.0)); // iPhone 12 mini + frame.set_window_size(egui::Vec2::new(375.0, 667.0)); // iPhone SE 2nd gen + ui.close_menu(); + } + }); } }