From 3450168e94898317cddfca512ebc478b244403ac Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 31 Mar 2021 20:53:13 +0200 Subject: [PATCH] egui_glium: add support for transparent windows Also support non-decorated windows (without border) --- eframe/CHANGELOG.md | 7 ++----- egui_demo_lib/src/apps/demo/demo_windows.rs | 17 +++++++++------ egui_demo_lib/src/wrap_app.rs | 8 +++++++ egui_glium/CHANGELOG.md | 13 +----------- egui_glium/src/backend.rs | 23 +++++++-------------- epi/src/lib.rs | 17 ++++++++++++++- 6 files changed, 46 insertions(+), 39 deletions(-) diff --git a/eframe/CHANGELOG.md b/eframe/CHANGELOG.md index 3b4edc82..aeacb831 100644 --- a/eframe/CHANGELOG.md +++ b/eframe/CHANGELOG.md @@ -1,15 +1,15 @@ # Changelog for eframe - All notable changes to the `eframe` crate. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased +* You can now turn your window transparent with the `App::transparent` option. +* You can now disable window decorations with the `App::decorated` option. ## 0.10.0 - 2021-02-28 - * [You can now set your own app icons](https://github.com/emilk/egui/pull/193). * You can control the initial size of the native window with `App::initial_window_size`. * You can control the maximum egui web canvas size with `App::max_size_points`. @@ -17,15 +17,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## 0.9.0 - 2021-02-07 - * [Add support for HTTP body](https://github.com/emilk/egui/pull/139). ## 0.8.0 - 2021-01-17 - * Simplify `TextureAllocator` interface. ## 0.7.0 - 2021-01-04 - * Initial release of `eframe` diff --git a/egui_demo_lib/src/apps/demo/demo_windows.rs b/egui_demo_lib/src/apps/demo/demo_windows.rs index c746de69..119a0294 100644 --- a/egui_demo_lib/src/apps/demo/demo_windows.rs +++ b/egui_demo_lib/src/apps/demo/demo_windows.rs @@ -129,12 +129,17 @@ impl DemoWindows { show_menu_bar(ui); }); - // Just get a background to put the windows on instead of using whatever the clear color is - let frame = egui::Frame { - fill: ctx.style().visuals.extreme_bg_color, - ..egui::Frame::none() - }; - egui::CentralPanel::default().frame(frame).show(ctx, |_| {}); + { + let mut fill = ctx.style().visuals.extreme_bg_color; + if !cfg!(target_arch = "wasm32") { + // Native: WrapApp uses a transparent window, so let's show that off: + // NOTE: the OS compositor assumes "normal" blending, so we need to hack it: + let [r, g, b, _] = fill.to_array(); + fill = egui::Color32::from_rgba_premultiplied(r, g, b, 180); + } + let frame = egui::Frame::none().fill(fill); + egui::CentralPanel::default().frame(frame).show(ctx, |_| {}); + } self.windows(ctx); } diff --git a/egui_demo_lib/src/wrap_app.rs b/egui_demo_lib/src/wrap_app.rs index e7ef04b4..1e8c51f3 100644 --- a/egui_demo_lib/src/wrap_app.rs +++ b/egui_demo_lib/src/wrap_app.rs @@ -54,6 +54,14 @@ impl epi::App for WrapApp { self.backend_panel.max_size_points_active } + // Let's show off that we support transparent windows (on native): + fn transparent(&self) -> bool { + true + } + fn clear_color(&self) -> egui::Rgba { + egui::Rgba::TRANSPARENT // we set a `CentralPanel` fill color in `demo_windows.rs` + } + fn warm_up_enabled(&self) -> bool { // The example windows use a lot of emojis. Pre-cache them by running one frame where everything is open #[cfg(debug_assertions)] diff --git a/egui_glium/CHANGELOG.md b/egui_glium/CHANGELOG.md index d9919eaa..9add483e 100644 --- a/egui_glium/CHANGELOG.md +++ b/egui_glium/CHANGELOG.md @@ -9,18 +9,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## 0.10.0 - 2021-02-28 - * [Add shaders for GLSL 1.2, GLSL ES 1.0 and 3.0](https://github.com/emilk/egui/pull/187) - now `egui` works well on old hardware which supports OpenGL 2.1 only like Raspberry Pi 1 and Zero. ## 0.9.0 - 2021-02-07 - * Nothing new ## 0.8.0 - 2021-01-17 - ### Fixed 🐛 * Fix a bug where key releases weren't sent to egui @@ -28,39 +25,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## 0.7.0 - 2021-01-04 - ### Changed - * `http` `persistence` and `time` are now optional (and opt-in) features. ## 0.6.0 - 2020-12-26 - ### Added - * `egui_glium` will auto-save your app state every 30 seconds. * `egui_glium` can now set windows as fixed size (e.g. the user can't resize the window). See `egui::App::is_resizable()`. ### Changed - * `egui_glium` will now save you app state to [a better directory](https://docs.rs/directories-next/2.0.0/directories_next/struct.ProjectDirs.html#method.data_dir). * `egui_glium::run`: the parameter `app` now has signature `Box` (you need to add `Box::new(app)` to your code). * Window title is now passed via the `trait` function `egui::App::name()`. ### Fixed 🐛 - * Serialize window size in logical points instead of physical pixels. * Window position is now restored on restart. + ## 0.5.0 - 2020-12-13 - ### Changed - * FileStorage::from_path now takes `Into` instead of `String` ## 0.4.0 - 2020-11-28 - Started changelog. Features: * Input diff --git a/egui_glium/src/backend.rs b/egui_glium/src/backend.rs index 5795e077..0cf6e903 100644 --- a/egui_glium/src/backend.rs +++ b/egui_glium/src/backend.rs @@ -56,19 +56,19 @@ impl epi::RepaintSignal for GliumRepaintSignal { } fn create_display( - title: &str, - initial_size_points: Option, + app: &dyn epi::App, window_settings: Option, - is_resizable: bool, window_icon: Option, event_loop: &glutin::event_loop::EventLoop, ) -> glium::Display { let mut window_builder = glutin::window::WindowBuilder::new() - .with_decorations(true) - .with_resizable(is_resizable) - .with_title(title) + .with_decorations(app.decorated()) + .with_resizable(app.is_resizable()) + .with_title(app.name()) .with_window_icon(window_icon) - .with_transparent(false); + .with_transparent(app.transparent()); + + let initial_size_points = app.initial_window_size(); if let Some(window_settings) = &window_settings { window_builder = window_settings.initialize_size(window_builder); @@ -149,14 +149,7 @@ pub fn run(mut app: Box) -> ! { let window_settings = deserialize_window_settings(&storage); let event_loop = glutin::event_loop::EventLoop::with_user_event(); let icon = load_icon(app.icon_data()); - let display = create_display( - app.name(), - app.initial_window_size(), - window_settings, - app.is_resizable(), - icon, - &event_loop, - ); + let display = create_display(&*app, window_settings, icon, &event_loop); let repaint_signal = std::sync::Arc::new(GliumRepaintSignal(std::sync::Mutex::new( event_loop.create_proxy(), diff --git a/epi/src/lib.rs b/epi/src/lib.rs index 2e34b082..81616b90 100644 --- a/epi/src/lib.rs +++ b/epi/src/lib.rs @@ -130,13 +130,28 @@ pub trait App { /// This is the background of your windows if you don't set a central panel. fn clear_color(&self) -> egui::Rgba { // NOTE: a bright gray makes the shadows of the windows look weird. - egui::Color32::from_rgb(12, 12, 12).into() + // We use a bit of transparency so that if the user switches on the + // `transparent()` option they get immediate results. + egui::Color32::from_rgba_unmultiplied(12, 12, 12, 180).into() } /// The application icon, e.g. in the Windows task bar etc. fn icon_data(&self) -> Option { None } + + /// On desktop: add window decorations (i.e. a frame around your app)? + /// If false it will be difficult to move and resize the app. + fn decorated(&self) -> bool { + true + } + + /// On desktop: make the window transparent. + /// You control the transparency with [`Self::clear_color()`]. + /// You should avoid having a [`egui::CentralPanel`], or make sure its frame is also transparent. + fn transparent(&self) -> bool { + false + } } /// Image data for the icon.