macOS `ViewportBuilder` tweaks (#3613)
This commit is contained in:
parent
85489dc1dd
commit
a2b15b23ad
|
|
@ -6,6 +6,9 @@ NOTE: [`egui-winit`](../egui-winit/CHANGELOG.md), [`egui_glium`](../egui_glium/C
|
|||
This file is updated upon each release.
|
||||
Changes since the last release can be found by running the `scripts/generate_changelog.py` script.
|
||||
|
||||
## Unreleased
|
||||
* `NativeOptions::fullsize_content` has been replaced with four settings: `ViewportBuilder::with_fullsize_content_view`, `with_title_shown`, `with_titlebar_shown`, `with_titlebar_buttons_shown`
|
||||
|
||||
## 0.23.0 - 2023-09-27
|
||||
* Update MSRV to Rust 1.70.0 [#3310](https://github.com/emilk/egui/pull/3310)
|
||||
* Update to puffin 0.16 [#3144](https://github.com/emilk/egui/pull/3144)
|
||||
|
|
|
|||
|
|
@ -1224,13 +1224,13 @@ fn initialize_or_update_viewport<'vp>(
|
|||
viewport.class = class;
|
||||
viewport.viewport_ui_cb = viewport_ui_cb;
|
||||
|
||||
let (delta_commands, recreate) = viewport.builder.patch(&builder);
|
||||
let (delta_commands, recreate) = viewport.builder.patch(builder);
|
||||
|
||||
if recreate {
|
||||
log::debug!(
|
||||
"Recreating window for viewport {:?} ({:?})",
|
||||
ids.this,
|
||||
builder.title
|
||||
viewport.builder.title
|
||||
);
|
||||
viewport.window = None;
|
||||
viewport.egui_winit = None;
|
||||
|
|
|
|||
|
|
@ -1037,13 +1037,13 @@ fn initialize_or_update_viewport<'vp>(
|
|||
viewport.ids.parent = ids.parent;
|
||||
viewport.viewport_ui_cb = viewport_ui_cb;
|
||||
|
||||
let (delta_commands, recreate) = viewport.builder.patch(&builder);
|
||||
let (delta_commands, recreate) = viewport.builder.patch(builder);
|
||||
|
||||
if recreate {
|
||||
log::debug!(
|
||||
"Recreating window for viewport {:?} ({:?})",
|
||||
ids.this,
|
||||
builder.title
|
||||
viewport.builder.title
|
||||
);
|
||||
viewport.window = None;
|
||||
viewport.egui_winit = None;
|
||||
|
|
|
|||
|
|
@ -1292,13 +1292,18 @@ pub fn create_winit_window_builder<T>(
|
|||
maximize_button,
|
||||
window_level,
|
||||
|
||||
// only handled on some platforms:
|
||||
title_hidden: _title_hidden,
|
||||
titlebar_transparent: _titlebar_transparent,
|
||||
// macOS:
|
||||
fullsize_content_view: _fullsize_content_view,
|
||||
app_id: _app_id,
|
||||
title_shown: _title_shown,
|
||||
titlebar_buttons_shown: _titlebar_buttons_shown,
|
||||
titlebar_shown: _titlebar_shown,
|
||||
|
||||
// Windows:
|
||||
drag_and_drop: _drag_and_drop,
|
||||
|
||||
// wayland:
|
||||
app_id: _app_id,
|
||||
|
||||
mouse_passthrough: _, // handled in `apply_viewport_builder_to_new_window`
|
||||
} = viewport_builder;
|
||||
|
||||
|
|
@ -1309,7 +1314,7 @@ pub fn create_winit_window_builder<T>(
|
|||
.with_resizable(resizable.unwrap_or(true))
|
||||
.with_visible(visible.unwrap_or(true))
|
||||
.with_maximized(maximized.unwrap_or(false))
|
||||
.with_window_level(match window_level {
|
||||
.with_window_level(match window_level.unwrap_or_default() {
|
||||
egui::viewport::WindowLevel::AlwaysOnBottom => WindowLevel::AlwaysOnBottom,
|
||||
egui::viewport::WindowLevel::AlwaysOnTop => WindowLevel::AlwaysOnTop,
|
||||
egui::viewport::WindowLevel::Normal => WindowLevel::Normal,
|
||||
|
|
@ -1383,8 +1388,9 @@ pub fn create_winit_window_builder<T>(
|
|||
{
|
||||
use winit::platform::macos::WindowBuilderExtMacOS as _;
|
||||
window_builder = window_builder
|
||||
.with_title_hidden(_title_hidden.unwrap_or(false))
|
||||
.with_titlebar_transparent(_titlebar_transparent.unwrap_or(false))
|
||||
.with_title_hidden(!_title_shown.unwrap_or(true))
|
||||
.with_titlebar_buttons_hidden(!_titlebar_buttons_shown.unwrap_or(true))
|
||||
.with_titlebar_transparent(!_titlebar_shown.unwrap_or(true))
|
||||
.with_fullsize_content_view(_fullsize_content_view.unwrap_or(false));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -275,16 +275,19 @@ pub struct ViewportBuilder {
|
|||
pub icon: Option<Arc<IconData>>,
|
||||
pub active: Option<bool>,
|
||||
pub visible: Option<bool>,
|
||||
pub title_hidden: Option<bool>,
|
||||
pub titlebar_transparent: Option<bool>,
|
||||
pub fullsize_content_view: Option<bool>,
|
||||
pub drag_and_drop: Option<bool>,
|
||||
|
||||
// macOS:
|
||||
pub fullsize_content_view: Option<bool>,
|
||||
pub title_shown: Option<bool>,
|
||||
pub titlebar_buttons_shown: Option<bool>,
|
||||
pub titlebar_shown: Option<bool>,
|
||||
|
||||
pub close_button: Option<bool>,
|
||||
pub minimize_button: Option<bool>,
|
||||
pub maximize_button: Option<bool>,
|
||||
|
||||
pub window_level: WindowLevel,
|
||||
pub window_level: Option<WindowLevel>,
|
||||
|
||||
pub mouse_passthrough: Option<bool>,
|
||||
}
|
||||
|
|
@ -400,35 +403,37 @@ impl ViewportBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
/// Hides the window title.
|
||||
/// macOS: Makes the window content appear behind the titlebar.
|
||||
///
|
||||
/// Mac Os only.
|
||||
#[inline]
|
||||
pub fn with_title_hidden(mut self, title_hidden: bool) -> Self {
|
||||
self.title_hidden = Some(title_hidden);
|
||||
self
|
||||
}
|
||||
|
||||
/// Makes the titlebar transparent and allows the content to appear behind it.
|
||||
///
|
||||
/// Mac Os only.
|
||||
#[inline]
|
||||
pub fn with_titlebar_transparent(mut self, value: bool) -> Self {
|
||||
self.titlebar_transparent = Some(value);
|
||||
self
|
||||
}
|
||||
|
||||
/// On Mac: the window doesn't have a titlebar, but floating window buttons.
|
||||
///
|
||||
/// See [winit's documentation][with_fullsize_content_view] for information on Mac-specific options.
|
||||
///
|
||||
/// [with_fullsize_content_view]: https://docs.rs/winit/latest/x86_64-apple-darwin/winit/platform/macos/trait.WindowBuilderExtMacOS.html#tymethod.with_fullsize_content_view
|
||||
/// You often want to combine this with [`Self::with_titlebar_shown`]
|
||||
/// and [`Self::with_title_shown`].
|
||||
#[inline]
|
||||
pub fn with_fullsize_content_view(mut self, value: bool) -> Self {
|
||||
self.fullsize_content_view = Some(value);
|
||||
self
|
||||
}
|
||||
|
||||
/// macOS: Set to `false` to hide the window title.
|
||||
#[inline]
|
||||
pub fn with_title_shown(mut self, title_shown: bool) -> Self {
|
||||
self.title_shown = Some(title_shown);
|
||||
self
|
||||
}
|
||||
|
||||
/// macOS: Set to `false` to hide the titlebar button (close, minimize, maximize)
|
||||
#[inline]
|
||||
pub fn with_titlebar_buttons_shown(mut self, titlebar_buttons_shown: bool) -> Self {
|
||||
self.titlebar_buttons_shown = Some(titlebar_buttons_shown);
|
||||
self
|
||||
}
|
||||
|
||||
/// macOS: Set to `false` to make the titlebar transparent, allowing the content to appear behind it.
|
||||
#[inline]
|
||||
pub fn with_titlebar_shown(mut self, shown: bool) -> Self {
|
||||
self.titlebar_shown = Some(shown);
|
||||
self
|
||||
}
|
||||
|
||||
/// Requests the window to be of specific dimensions.
|
||||
///
|
||||
/// If this is not set, some platform-specific dimensions will be used.
|
||||
|
|
@ -539,7 +544,7 @@ impl ViewportBuilder {
|
|||
/// Control if window i always-on-top, always-on-bottom, or neither.
|
||||
#[inline]
|
||||
pub fn with_window_level(mut self, level: WindowLevel) -> Self {
|
||||
self.window_level = level;
|
||||
self.window_level = Some(level);
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -561,156 +566,199 @@ impl ViewportBuilder {
|
|||
|
||||
/// Update this `ViewportBuilder` with a delta,
|
||||
/// returning a list of commands and a bool intdicating if the window needs to be recreated.
|
||||
pub fn patch(&mut self, new: &ViewportBuilder) -> (Vec<ViewportCommand>, bool) {
|
||||
#[must_use]
|
||||
pub fn patch(&mut self, new_vp_builder: ViewportBuilder) -> (Vec<ViewportCommand>, bool) {
|
||||
let ViewportBuilder {
|
||||
title: new_title,
|
||||
app_id: new_app_id,
|
||||
position: new_position,
|
||||
inner_size: new_inner_size,
|
||||
min_inner_size: new_min_inner_size,
|
||||
max_inner_size: new_max_inner_size,
|
||||
fullscreen: new_fullscreen,
|
||||
maximized: new_maximized,
|
||||
resizable: new_resizable,
|
||||
transparent: new_transparent,
|
||||
decorations: new_decorations,
|
||||
icon: new_icon,
|
||||
active: new_active,
|
||||
visible: new_visible,
|
||||
drag_and_drop: new_drag_and_drop,
|
||||
fullsize_content_view: new_fullsize_content_view,
|
||||
title_shown: new_title_shown,
|
||||
titlebar_buttons_shown: new_titlebar_buttons_shown,
|
||||
titlebar_shown: new_titlebar_shown,
|
||||
close_button: new_close_button,
|
||||
minimize_button: new_minimize_button,
|
||||
maximize_button: new_maximize_button,
|
||||
window_level: new_window_level,
|
||||
mouse_passthrough: new_mouse_passthrough,
|
||||
} = new_vp_builder;
|
||||
|
||||
let mut commands = Vec::new();
|
||||
|
||||
if let Some(new_title) = &new.title {
|
||||
if Some(new_title) != self.title.as_ref() {
|
||||
if let Some(new_title) = new_title {
|
||||
if Some(&new_title) != self.title.as_ref() {
|
||||
self.title = Some(new_title.clone());
|
||||
commands.push(ViewportCommand::Title(new_title.clone()));
|
||||
commands.push(ViewportCommand::Title(new_title));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_position) = new.position {
|
||||
if let Some(new_position) = new_position {
|
||||
if Some(new_position) != self.position {
|
||||
self.position = Some(new_position);
|
||||
commands.push(ViewportCommand::OuterPosition(new_position));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_inner_size) = new.inner_size {
|
||||
if let Some(new_inner_size) = new_inner_size {
|
||||
if Some(new_inner_size) != self.inner_size {
|
||||
self.inner_size = Some(new_inner_size);
|
||||
commands.push(ViewportCommand::InnerSize(new_inner_size));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_min_inner_size) = new.min_inner_size {
|
||||
if let Some(new_min_inner_size) = new_min_inner_size {
|
||||
if Some(new_min_inner_size) != self.min_inner_size {
|
||||
self.min_inner_size = Some(new_min_inner_size);
|
||||
commands.push(ViewportCommand::MinInnerSize(new_min_inner_size));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_max_inner_size) = new.max_inner_size {
|
||||
if let Some(new_max_inner_size) = new_max_inner_size {
|
||||
if Some(new_max_inner_size) != self.max_inner_size {
|
||||
self.max_inner_size = Some(new_max_inner_size);
|
||||
commands.push(ViewportCommand::MaxInnerSize(new_max_inner_size));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_fullscreen) = new.fullscreen {
|
||||
if let Some(new_fullscreen) = new_fullscreen {
|
||||
if Some(new_fullscreen) != self.fullscreen {
|
||||
self.fullscreen = Some(new_fullscreen);
|
||||
commands.push(ViewportCommand::Fullscreen(new_fullscreen));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_maximized) = new.maximized {
|
||||
if let Some(new_maximized) = new_maximized {
|
||||
if Some(new_maximized) != self.maximized {
|
||||
self.maximized = Some(new_maximized);
|
||||
commands.push(ViewportCommand::Maximized(new_maximized));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_resizable) = new.resizable {
|
||||
if let Some(new_resizable) = new_resizable {
|
||||
if Some(new_resizable) != self.resizable {
|
||||
self.resizable = Some(new_resizable);
|
||||
commands.push(ViewportCommand::Resizable(new_resizable));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_transparent) = new.transparent {
|
||||
if let Some(new_transparent) = new_transparent {
|
||||
if Some(new_transparent) != self.transparent {
|
||||
self.transparent = Some(new_transparent);
|
||||
commands.push(ViewportCommand::Transparent(new_transparent));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_decorations) = new.decorations {
|
||||
if let Some(new_decorations) = new_decorations {
|
||||
if Some(new_decorations) != self.decorations {
|
||||
self.decorations = Some(new_decorations);
|
||||
commands.push(ViewportCommand::Decorations(new_decorations));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_icon) = &new.icon {
|
||||
if let Some(new_icon) = new_icon {
|
||||
let is_new = match &self.icon {
|
||||
Some(existing) => !Arc::ptr_eq(new_icon, existing),
|
||||
Some(existing) => !Arc::ptr_eq(&new_icon, existing),
|
||||
None => true,
|
||||
};
|
||||
|
||||
if is_new {
|
||||
commands.push(ViewportCommand::Icon(Some(new_icon.clone())));
|
||||
self.icon = Some(new_icon.clone());
|
||||
self.icon = Some(new_icon);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_visible) = new.visible {
|
||||
if let Some(new_visible) = new_visible {
|
||||
if Some(new_visible) != self.active {
|
||||
self.visible = Some(new_visible);
|
||||
commands.push(ViewportCommand::Visible(new_visible));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(new_mouse_passthrough) = new.mouse_passthrough {
|
||||
if let Some(new_mouse_passthrough) = new_mouse_passthrough {
|
||||
if Some(new_mouse_passthrough) != self.mouse_passthrough {
|
||||
self.mouse_passthrough = Some(new_mouse_passthrough);
|
||||
commands.push(ViewportCommand::MousePassthrough(new_mouse_passthrough));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement compare for windows buttons
|
||||
if let Some(new_window_level) = new_window_level {
|
||||
if Some(new_window_level) != self.window_level {
|
||||
self.window_level = Some(new_window_level);
|
||||
commands.push(ViewportCommand::WindowLevel(new_window_level));
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Things we don't have commands for require a full window recreation.
|
||||
// The reason we don't have commands for them is that `winit` doesn't support
|
||||
// changing them without recreating the window.
|
||||
|
||||
let mut recreate_window = false;
|
||||
|
||||
if let Some(new_active) = new.active {
|
||||
if Some(new_active) != self.active {
|
||||
self.active = Some(new_active);
|
||||
recreate_window = true;
|
||||
}
|
||||
if new_active.is_some() && self.active != new_active {
|
||||
self.active = new_active;
|
||||
recreate_window = true;
|
||||
}
|
||||
|
||||
if let Some(new_close_button) = new.close_button {
|
||||
if Some(new_close_button) != self.close_button {
|
||||
self.close_button = Some(new_close_button);
|
||||
recreate_window = true;
|
||||
}
|
||||
if new_app_id.is_some() && self.app_id != new_app_id {
|
||||
self.app_id = new_app_id;
|
||||
recreate_window = true;
|
||||
}
|
||||
|
||||
if let Some(new_minimize_button) = new.minimize_button {
|
||||
if Some(new_minimize_button) != self.minimize_button {
|
||||
self.minimize_button = Some(new_minimize_button);
|
||||
recreate_window = true;
|
||||
}
|
||||
if new_close_button.is_some() && self.close_button != new_close_button {
|
||||
self.close_button = new_close_button;
|
||||
recreate_window = true;
|
||||
}
|
||||
|
||||
if let Some(new_maximized_button) = new.maximize_button {
|
||||
if Some(new_maximized_button) != self.maximize_button {
|
||||
self.maximize_button = Some(new_maximized_button);
|
||||
recreate_window = true;
|
||||
}
|
||||
if new_minimize_button.is_some() && self.minimize_button != new_minimize_button {
|
||||
self.minimize_button = new_minimize_button;
|
||||
recreate_window = true;
|
||||
}
|
||||
|
||||
if let Some(new_title_hidden) = new.title_hidden {
|
||||
if Some(new_title_hidden) != self.title_hidden {
|
||||
self.title_hidden = Some(new_title_hidden);
|
||||
recreate_window = true;
|
||||
}
|
||||
if new_maximize_button.is_some() && self.maximize_button != new_maximize_button {
|
||||
self.maximize_button = new_maximize_button;
|
||||
recreate_window = true;
|
||||
}
|
||||
|
||||
if let Some(new_titlebar_transparent) = new.titlebar_transparent {
|
||||
if Some(new_titlebar_transparent) != self.titlebar_transparent {
|
||||
self.titlebar_transparent = Some(new_titlebar_transparent);
|
||||
recreate_window = true;
|
||||
}
|
||||
if new_title_shown.is_some() && self.title_shown != new_title_shown {
|
||||
self.title_shown = new_title_shown;
|
||||
recreate_window = true;
|
||||
}
|
||||
|
||||
if let Some(new_fullsize_content_view) = new.fullsize_content_view {
|
||||
if Some(new_fullsize_content_view) != self.fullsize_content_view {
|
||||
self.fullsize_content_view = Some(new_fullsize_content_view);
|
||||
recreate_window = true;
|
||||
}
|
||||
if new_titlebar_buttons_shown.is_some()
|
||||
&& self.titlebar_buttons_shown != new_titlebar_buttons_shown
|
||||
{
|
||||
self.titlebar_buttons_shown = new_titlebar_buttons_shown;
|
||||
recreate_window = true;
|
||||
}
|
||||
|
||||
if new_titlebar_shown.is_some() && self.titlebar_shown != new_titlebar_shown {
|
||||
self.titlebar_shown = new_titlebar_shown;
|
||||
recreate_window = true;
|
||||
}
|
||||
|
||||
if new_fullsize_content_view.is_some()
|
||||
&& self.fullsize_content_view != new_fullsize_content_view
|
||||
{
|
||||
self.fullsize_content_view = new_fullsize_content_view;
|
||||
recreate_window = true;
|
||||
}
|
||||
|
||||
if new_drag_and_drop.is_some() && self.drag_and_drop != new_drag_and_drop {
|
||||
self.drag_and_drop = new_drag_and_drop;
|
||||
recreate_window = true;
|
||||
}
|
||||
|
||||
(commands, recreate_window)
|
||||
|
|
@ -958,7 +1006,7 @@ impl ViewportOutput {
|
|||
|
||||
self.parent = parent;
|
||||
self.class = class;
|
||||
self.builder.patch(&builder);
|
||||
let _ = self.builder.patch(builder); // we ignore the returned command, because `self.builder` will be the basis of a new patch
|
||||
self.viewport_ui_cb = viewport_ui_cb;
|
||||
self.commands.append(&mut commands);
|
||||
self.repaint_delay = self.repaint_delay.min(repaint_delay);
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ fn main() -> Result<(), eframe::Error> {
|
|||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||
let options = eframe::NativeOptions {
|
||||
viewport: egui::ViewportBuilder::default()
|
||||
.with_decorations(false) // Hide the OS-specific "chrome" around the window
|
||||
.with_inner_size([400.0, 100.0])
|
||||
.with_min_inner_size([400.0, 100.0])
|
||||
.with_decorations(false) // Hide the OS-specific "chrome" around the window
|
||||
.with_transparent(true), // To have rounded corners we need transparency
|
||||
|
||||
..Default::default()
|
||||
|
|
|
|||
Loading…
Reference in New Issue