Skip to content

Commit 3a02963

Browse files
Add macOS-specific has_shadow and with_has_shadow to ViewportBuilder (#6850)
* [X] I have followed the instructions in the PR template This PR fixes a ghosting issue I encountered while making a native macOS transparent overlay app using egui and eframe by exposing the [existing macOS window attribute `has_shadow`](https://docs.rs/winit/latest/winit/platform/macos/trait.WindowExtMacOS.html#tymethod.has_shadow) to the `ViewportBuilder` via a new `with_has_shadow` option. ## Example of Ghosting Issue ### Before `ViewportBuilder::with_has_shadow` By default, the underlying `winit` window's `.has_shadow()` defaults to `true`. https://github.com/user-attachments/assets/c3dcc2bd-535a-4960-918e-3ae5df503b12 ### After `ViewportBuilder::with_has_shadow` https://github.com/user-attachments/assets/484462a1-ea88-43e6-85b4-0bb9724e5f14 Source code for the above example can be found here: https://github.com/gaelanmcmillan/egui-overlay-app-with-shadow-artifacts-example/blob/main/src/main.rs ### Further background By default on macOS, `winit` windows have a drop-shadow effect. When creating a fully transparent overlay GUI, this drop-shadow can create a ghosting effect, as the window content has a drop shadow which is not cleared by the app itself. This issue has been experienced by users of `bevy`, another Rust project that has an upstream dependency on `winit`: bevyengine/bevy#18673
1 parent 7d185ac commit 3a02963

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

crates/egui-winit/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,7 @@ pub fn create_winit_window_attributes(
16201620
title_shown: _title_shown,
16211621
titlebar_buttons_shown: _titlebar_buttons_shown,
16221622
titlebar_shown: _titlebar_shown,
1623+
has_shadow: _has_shadow,
16231624

16241625
// Windows:
16251626
drag_and_drop: _drag_and_drop,
@@ -1764,7 +1765,8 @@ pub fn create_winit_window_attributes(
17641765
.with_titlebar_buttons_hidden(!_titlebar_buttons_shown.unwrap_or(true))
17651766
.with_titlebar_transparent(!_titlebar_shown.unwrap_or(true))
17661767
.with_fullsize_content_view(_fullsize_content_view.unwrap_or(false))
1767-
.with_movable_by_window_background(_movable_by_window_background.unwrap_or(false));
1768+
.with_movable_by_window_background(_movable_by_window_background.unwrap_or(false))
1769+
.with_has_shadow(_has_shadow.unwrap_or(true));
17681770
}
17691771

17701772
window_attributes

crates/egui/src/viewport.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ pub struct ViewportBuilder {
294294
pub title_shown: Option<bool>,
295295
pub titlebar_buttons_shown: Option<bool>,
296296
pub titlebar_shown: Option<bool>,
297+
pub has_shadow: Option<bool>,
297298

298299
// windows:
299300
pub drag_and_drop: Option<bool>,
@@ -380,6 +381,10 @@ impl ViewportBuilder {
380381
/// The default is `false`.
381382
/// If this is not working, it's because the graphic context doesn't support transparency,
382383
/// you will need to set the transparency in the eframe!
384+
///
385+
/// ## Platform-specific
386+
///
387+
/// **macOS:** When using this feature to create an overlay-like UI, you likely want to combine this with [`Self::with_has_shadow`] set to `false` in order to avoid ghosting artifacts.
383388
#[inline]
384389
pub fn with_transparent(mut self, transparent: bool) -> Self {
385390
self.transparent = Some(transparent);
@@ -433,7 +438,6 @@ impl ViewportBuilder {
433438
}
434439

435440
/// macOS: Set to `true` to allow the window to be moved by dragging the background.
436-
///
437441
/// Enabling this feature can result in unexpected behaviour with draggable UI widgets such as sliders.
438442
#[inline]
439443
pub fn with_movable_by_background(mut self, value: bool) -> Self {
@@ -462,6 +466,19 @@ impl ViewportBuilder {
462466
self
463467
}
464468

469+
/// macOS: Set to `false` to make the window render without a drop shadow.
470+
///
471+
/// The default is `true`.
472+
///
473+
/// Disabling this feature can solve ghosting issues experienced if using [`Self::with_transparent`].
474+
///
475+
/// Look at winit for more details
476+
#[inline]
477+
pub fn with_has_shadow(mut self, has_shadow: bool) -> Self {
478+
self.has_shadow = Some(has_shadow);
479+
self
480+
}
481+
465482
/// windows: Whether show or hide the window icon in the taskbar.
466483
#[inline]
467484
pub fn with_taskbar(mut self, show: bool) -> Self {
@@ -653,6 +670,7 @@ impl ViewportBuilder {
653670
title_shown: new_title_shown,
654671
titlebar_buttons_shown: new_titlebar_buttons_shown,
655672
titlebar_shown: new_titlebar_shown,
673+
has_shadow: new_has_shadow,
656674
close_button: new_close_button,
657675
minimize_button: new_minimize_button,
658676
maximize_button: new_maximize_button,
@@ -823,6 +841,11 @@ impl ViewportBuilder {
823841
recreate_window = true;
824842
}
825843

844+
if new_has_shadow.is_some() && self.has_shadow != new_has_shadow {
845+
self.has_shadow = new_has_shadow;
846+
recreate_window = true;
847+
}
848+
826849
if new_taskbar.is_some() && self.taskbar != new_taskbar {
827850
self.taskbar = new_taskbar;
828851
recreate_window = true;

0 commit comments

Comments
 (0)