Skip to content

Commit

Permalink
Refactor window creation. (#485)
Browse files Browse the repository at this point in the history
* Refactor window creation to enhance comprehensibility.

# Note

The modification does not impact public API, only affects internal inteactions.

* Remove unnecessary assert.
  • Loading branch information
Sol-Ell committed Jun 3, 2024
1 parent aa80194 commit 134263c
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 125 deletions.
11 changes: 8 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,13 @@ impl Application {
self
}

/// create a new window for the application, if you want multiple windows,
/// just chain more window method to the builder
/// Create a new window for the application, if you want multiple windows,
/// just chain more window method to the builder.
///
/// # Note
///
/// Using `None` as a configuration argument is equivalent to using
/// `WindowConfig::default()`.
pub fn window<V: IntoView + 'static>(
mut self,
app_view: impl FnOnce(WindowId) -> V + 'static,
Expand All @@ -128,7 +133,7 @@ impl Application {
self.handle.as_mut().unwrap().new_window(
&self.event_loop,
Box::new(|window_id| app_view(window_id).into_any()),
config,
config.unwrap_or_default(),
);
self
}
Expand Down
190 changes: 92 additions & 98 deletions src/app_handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl ApplicationHandle {
for event in events {
match event {
AppUpdateEvent::NewWindow { view_fn, config } => {
self.new_window(event_loop, view_fn, config)
self.new_window(event_loop, view_fn, config.unwrap_or_default())
}
AppUpdateEvent::CloseWindow { window_id } => {
self.close_window(window_id, event_loop);
Expand Down Expand Up @@ -248,113 +248,107 @@ impl ApplicationHandle {
&mut self,
event_loop: &EventLoopWindowTarget<UserEvent>,
view_fn: Box<dyn FnOnce(WindowId) -> Box<dyn View>>,
config: Option<WindowConfig>,
#[allow(unused_variables)] WindowConfig {
size,
position,
show_titlebar,
transparent,
fullscreen,
window_icon,
title,
enabled_buttons,
resizable,
undecorated,
window_level,
apply_default_theme,
mac_os_config,
}: WindowConfig,
) {
let mut window_builder = floem_winit::window::WindowBuilder::new();
let transparent = config.as_ref().and_then(|c| c.transparent).unwrap_or(false);
let apply_default_theme = if let Some(config) = config {
if let Some(size) = config.size {
let size = if size.width == 0.0 || size.height == 0.0 {
Size::new(800.0, 600.0)
} else {
size
};
window_builder =
window_builder.with_inner_size(LogicalSize::new(size.width, size.height));
}
if let Some(pos) = config.position {
window_builder = window_builder.with_position(LogicalPosition::new(pos.x, pos.y));
}
if let Some(show_titlebar) = config.show_titlebar {
#[cfg(target_os = "macos")]
if !show_titlebar {
use floem_winit::platform::macos::WindowBuilderExtMacOS;
window_builder = window_builder
.with_movable(false)
.with_title_hidden(true)
.with_titlebar_transparent(true)
.with_fullsize_content_view(true)
.with_traffic_lights_offset(11.0, 16.0);
}
#[cfg(not(target_os = "macos"))]
if !show_titlebar {
window_builder = window_builder.with_decorations(false);
}
let mut window_builder = floem_winit::window::WindowBuilder::new()
.with_decorations(!undecorated)
.with_transparent(transparent)
.with_fullscreen(fullscreen)
.with_window_level(window_level)
.with_window_icon(window_icon)
.with_resizable(resizable)
.with_enabled_buttons(enabled_buttons)
.with_inner_size(LogicalSize::new(size.width, size.height));

if let Some(pos) = position {
window_builder = window_builder.with_position(LogicalPosition::new(pos.x, pos.y));
}

if let Some(title) = title {
window_builder = window_builder.with_title(title);
}

#[cfg(not(target_os = "macos"))]
if !show_titlebar {
window_builder = window_builder.with_decorations(false);
}

#[cfg(target_os = "macos")]
if !show_titlebar {
use floem_winit::platform::macos::WindowBuilderExtMacOS;
window_builder = window_builder
.with_movable(false)
.with_title_hidden(true)
.with_titlebar_transparent(true)
.with_fullsize_content_view(true)
.with_traffic_lights_offset(11.0, 16.0);
}

#[cfg(target_os = "macos")]
if undecorated {
use floem_winit::platform::macos::WindowBuilderExtMacOS;
// A palette-style window that will only obtain window focus but
// not actually propagate the first mouse click it receives is
// very unlikely to be expected behavior - these typically are
// used for something that offers a quick choice and are closed
// in a single pointer gesture.
window_builder = window_builder.with_accepts_first_mouse(true);
}

#[cfg(target_os = "macos")]
if let Some(mac) = mac_os_config {
use floem_winit::platform::macos::WindowBuilderExtMacOS;
if let Some(val) = mac.movable_by_window_background {
window_builder = window_builder.with_movable_by_window_background(val);
}
if let Some(undecorated) = config.undecorated {
window_builder = window_builder.with_decorations(!undecorated);
#[cfg(target_os = "macos")]
if undecorated {
use floem_winit::platform::macos::WindowBuilderExtMacOS;
// A palette-style window that will only obtain window focus but
// not actually propagate the first mouse click it receives is
// very unlikely to be expected behavior - these typically are
// used for something that offers a quick choice and are closed
// in a single pointer gesture.
window_builder = window_builder.with_accepts_first_mouse(true);
}
if let Some(val) = mac.titlebar_transparent {
window_builder = window_builder.with_titlebar_transparent(val);
}
if let Some(transparent) = config.transparent {
window_builder = window_builder.with_transparent(transparent);
if let Some(val) = mac.titlebar_hidden {
window_builder = window_builder.with_titlebar_hidden(val);
}
if let Some(fullscreen) = config.fullscreen {
window_builder = window_builder.with_fullscreen(Some(fullscreen));
if let Some(val) = mac.full_size_content_view {
window_builder = window_builder.with_fullsize_content_view(val);
}
if let Some(window_level) = config.window_level {
window_builder = window_builder.with_window_level(window_level);
if let Some(val) = mac.movable {
window_builder = window_builder.with_movable(val);
}
if let Some(title) = config.title {
window_builder = window_builder.with_title(title);
if let Some((x, y)) = mac.traffic_lights_offset {
window_builder = window_builder.with_traffic_lights_offset(x, y);
}
if let Some(window_icon) = config.window_icon {
window_builder = window_builder.with_window_icon(Some(window_icon));
if let Some(val) = mac.accepts_first_mouse {
window_builder = window_builder.with_accepts_first_mouse(val);
}
#[cfg(target_os = "macos")]
if let Some(mac) = config.mac_os_config {
use floem_winit::platform::macos::WindowBuilderExtMacOS;
if let Some(val) = mac.movable_by_window_background {
window_builder = window_builder.with_movable_by_window_background(val);
}
if let Some(val) = mac.titlebar_transparent {
window_builder = window_builder.with_titlebar_transparent(val);
}
if let Some(val) = mac.titlebar_hidden {
window_builder = window_builder.with_titlebar_hidden(val);
}
if let Some(val) = mac.full_size_content_view {
window_builder = window_builder.with_fullsize_content_view(val);
}
if let Some(val) = mac.movable {
window_builder = window_builder.with_movable(val);
}
if let Some((x, y)) = mac.traffic_lights_offset {
window_builder = window_builder.with_traffic_lights_offset(x, y);
}
if let Some(val) = mac.accepts_first_mouse {
window_builder = window_builder.with_accepts_first_mouse(val);
}
if let Some(val) = mac.option_as_alt {
window_builder = window_builder.with_option_as_alt(val.into());
}
if let Some(title) = mac.tabbing_identifier {
window_builder = window_builder.with_tabbing_identifier(title.as_str());
}
if let Some(disallow_hidpi) = mac.disallow_high_dpi {
window_builder = window_builder.with_disallow_hidpi(disallow_hidpi);
}
if let Some(shadow) = mac.has_shadow {
window_builder = window_builder.with_has_shadow(shadow);
}
if let Some(val) = mac.option_as_alt {
window_builder = window_builder.with_option_as_alt(val.into());
}
config.apply_default_theme.unwrap_or(true)
} else {
true
};
if let Some(title) = mac.tabbing_identifier {
window_builder = window_builder.with_tabbing_identifier(title.as_str());
}
if let Some(disallow_hidpi) = mac.disallow_high_dpi {
window_builder = window_builder.with_disallow_hidpi(disallow_hidpi);
}
if let Some(shadow) = mac.has_shadow {
window_builder = window_builder.with_has_shadow(shadow);
}
}

let result = window_builder.build(event_loop);
let window = match result {
Ok(window) => window,
Err(_) => return,
let Ok(window) = window_builder.build(event_loop) else {
return;
};
let window_id = window.id();
let window_handle = WindowHandle::new(window, view_fn, transparent, apply_default_theme);
Expand Down
8 changes: 1 addition & 7 deletions src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -967,13 +967,7 @@ pub fn capture(window_id: WindowId) {
EventPropagation::Continue
})
},
Some(WindowConfig {
size: Some(Size {
width: 1200.0,
height: 800.0,
}),
..Default::default()
}),
Some(WindowConfig::default().size((1200.0, 800.0))),
);
}

Expand Down
70 changes: 53 additions & 17 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,85 +10,121 @@ use peniko::kurbo::{Point, Size};
use crate::app::{add_app_update_event, AppUpdateEvent};
use crate::view::IntoView;

#[derive(Default, Debug)]
#[derive(Debug)]
pub struct WindowConfig {
pub(crate) size: Option<Size>,
pub(crate) size: Size,
pub(crate) position: Option<Point>,
pub(crate) show_titlebar: Option<bool>,
pub(crate) transparent: Option<bool>,
pub(crate) show_titlebar: bool,
pub(crate) transparent: bool,
pub(crate) fullscreen: Option<Fullscreen>,
pub(crate) window_icon: Option<Icon>,
pub(crate) title: Option<String>,
pub(crate) enabled_buttons: Option<WindowButtons>,
pub(crate) resizable: Option<bool>,
pub(crate) undecorated: Option<bool>,
pub(crate) window_level: Option<WindowLevel>,
pub(crate) apply_default_theme: Option<bool>,
pub(crate) enabled_buttons: WindowButtons,
pub(crate) resizable: bool,
pub(crate) undecorated: bool,
pub(crate) window_level: WindowLevel,
pub(crate) apply_default_theme: bool,
#[allow(dead_code)]
pub(crate) mac_os_config: Option<MacOSWindowConfig>,
}

impl Default for WindowConfig {
fn default() -> Self {
Self {
size: Size::new(800.0, 600.0),
position: None,
show_titlebar: true,
transparent: false,
fullscreen: None,
window_icon: None,
title: None,
enabled_buttons: WindowButtons::all(),
resizable: true,
undecorated: false,
window_level: WindowLevel::Normal,
apply_default_theme: true,
mac_os_config: None,
}
}
}

impl WindowConfig {
/// Sets new window size.
///
/// # Panics
///
/// Panics if either width or height of new size is zero.
pub fn size(mut self, size: impl Into<Size>) -> Self {
self.size = Some(size.into());
self.size = size.into();
self
}

#[inline]
pub fn position(mut self, position: Point) -> Self {
self.position = Some(position);
self
}

#[inline]
pub fn show_titlebar(mut self, show_titlebar: bool) -> Self {
self.show_titlebar = Some(show_titlebar);
self.show_titlebar = show_titlebar;
self
}

#[inline]
pub fn undecorated(mut self, undecorated: bool) -> Self {
self.undecorated = Some(undecorated);
self.undecorated = undecorated;
self
}

#[inline]
pub fn with_transparent(mut self, transparent: bool) -> Self {
self.transparent = Some(transparent);
self.transparent = transparent;
self
}

#[inline]
pub fn fullscreen(mut self, fullscreen: Fullscreen) -> Self {
self.fullscreen = Some(fullscreen);
self
}

#[inline]
pub fn window_icon(mut self, window_icon: Icon) -> Self {
self.window_icon = Some(window_icon);
self
}

#[inline]
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}

#[inline]
pub fn enabled_buttons(mut self, enabled_buttons: WindowButtons) -> Self {
self.enabled_buttons = Some(enabled_buttons);
self.enabled_buttons = enabled_buttons;
self
}

#[inline]
pub fn resizable(mut self, resizable: bool) -> Self {
self.resizable = Some(resizable);
self.resizable = resizable;
self
}

#[inline]
pub fn window_level(mut self, window_level: WindowLevel) -> Self {
self.window_level = Some(window_level);
self.window_level = window_level;
self
}

/// If set to true, the stylesheet for Floem's default theme will be
/// injected into your window. You may want to disable this when using a
/// completely custom theme.
#[inline]
pub fn apply_default_theme(mut self, apply_default_theme: bool) -> Self {
self.apply_default_theme = Some(apply_default_theme);
self.apply_default_theme = apply_default_theme;
self
}

Expand Down

0 comments on commit 134263c

Please sign in to comment.