mirror of
https://github.com/danbulant/cushy
synced 2026-07-08 04:30:34 +00:00
app_name, fullscreen, focused
Finally finished removing WindowAttributes.
This commit is contained in:
parent
8d653c2d6c
commit
0f866009b8
2 changed files with 108 additions and 53 deletions
|
|
@ -26,6 +26,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
`KeyboardEvent`. Because of this change, `KeyboardEvent` no longer implements
|
`KeyboardEvent`. Because of this change, `KeyboardEvent` no longer implements
|
||||||
`From<winit::event::KeyEvent>`. Instead, a new api `KeyEvent::from_winit`
|
`From<winit::event::KeyEvent>`. Instead, a new api `KeyEvent::from_winit`
|
||||||
allows constructing from both the modifiers and key event.
|
allows constructing from both the modifiers and key event.
|
||||||
|
- The type alias `WindowAttributes` has been removed. This type is no longer
|
||||||
|
used in Cushy's public API.
|
||||||
|
- `Window::attributes` has been made private. All functionality available from
|
||||||
|
this field should be available directly via functions on `Window`, and when
|
||||||
|
possible, the attributes are be able to be dynamically updated as well.
|
||||||
|
- `Window::focused` now accepts an `IntoValue` implementor instead of
|
||||||
|
`IntoDynamic`. Additionally, the initial value is now used to control whether
|
||||||
|
the OS should initially activate the window when it is opened.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
@ -85,6 +93,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `Window::cursor_position`
|
- `Window::cursor_position`
|
||||||
- `Window::cursor_visible`
|
- `Window::cursor_visible`
|
||||||
- `Window::decorated`
|
- `Window::decorated`
|
||||||
|
- `Window::enabled_buttons`
|
||||||
- `Window::icon`
|
- `Window::icon`
|
||||||
- `Window::inner_position`
|
- `Window::inner_position`
|
||||||
- `Window::maximized`
|
- `Window::maximized`
|
||||||
|
|
|
||||||
152
src/window.rs
152
src/window.rs
|
|
@ -31,8 +31,8 @@ use kludgine::app::winit::event::{
|
||||||
use kludgine::app::winit::keyboard::{
|
use kludgine::app::winit::keyboard::{
|
||||||
Key, KeyLocation, NamedKey, NativeKeyCode, PhysicalKey, SmolStr,
|
Key, KeyLocation, NamedKey, NativeKeyCode, PhysicalKey, SmolStr,
|
||||||
};
|
};
|
||||||
use kludgine::app::winit::window::{self, Cursor, Icon, WindowLevel};
|
use kludgine::app::winit::window::{self, Cursor, Fullscreen, Icon, WindowButtons, WindowLevel};
|
||||||
use kludgine::app::{winit, WindowBehavior as _};
|
use kludgine::app::{winit, WindowAttributes, WindowBehavior as _};
|
||||||
use kludgine::cosmic_text::{fontdb, Family, FamilyOwned};
|
use kludgine::cosmic_text::{fontdb, Family, FamilyOwned};
|
||||||
use kludgine::drawing::Drawing;
|
use kludgine::drawing::Drawing;
|
||||||
use kludgine::shapes::Shape;
|
use kludgine::shapes::Shape;
|
||||||
|
|
@ -477,19 +477,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The attributes of a Cushy window.
|
|
||||||
pub type WindowAttributes = kludgine::app::WindowAttributes;
|
|
||||||
|
|
||||||
/// A Cushy window that is not yet running.
|
/// A Cushy window that is not yet running.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct Window<Behavior = WidgetInstance>
|
pub struct Window<Behavior = WidgetInstance>
|
||||||
where
|
where
|
||||||
Behavior: WindowBehavior,
|
Behavior: WindowBehavior,
|
||||||
{
|
{
|
||||||
context: Behavior::Context,
|
|
||||||
pending: PendingWindow,
|
|
||||||
/// The attributes of this window.
|
|
||||||
pub attributes: WindowAttributes,
|
|
||||||
/// The title to display in the title bar of the window.
|
/// The title to display in the title bar of the window.
|
||||||
pub title: Value<String>,
|
pub title: Value<String>,
|
||||||
/// The colors to use to theme the user interface.
|
/// The colors to use to theme the user interface.
|
||||||
|
|
@ -527,6 +520,9 @@ where
|
||||||
/// Resizes the window to fit the contents if true.
|
/// Resizes the window to fit the contents if true.
|
||||||
pub resize_to_fit: Value<bool>,
|
pub resize_to_fit: Value<bool>,
|
||||||
|
|
||||||
|
context: Behavior::Context,
|
||||||
|
pending: PendingWindow,
|
||||||
|
attributes: WindowAttributes,
|
||||||
on_closed: Option<OnceCallback>,
|
on_closed: Option<OnceCallback>,
|
||||||
on_open: Option<OnceCallback<WindowHandle>>,
|
on_open: Option<OnceCallback<WindowHandle>>,
|
||||||
inner_size: Option<Dynamic<Size<UPx>>>,
|
inner_size: Option<Dynamic<Size<UPx>>>,
|
||||||
|
|
@ -551,6 +547,8 @@ where
|
||||||
close_requested: Option<Callback<(), bool>>,
|
close_requested: Option<Callback<(), bool>>,
|
||||||
icon: Option<Value<Option<RgbaImage>>>,
|
icon: Option<Value<Option<RgbaImage>>>,
|
||||||
modifiers: Option<Dynamic<Modifiers>>,
|
modifiers: Option<Dynamic<Modifiers>>,
|
||||||
|
enabled_buttons: Option<Value<WindowButtons>>,
|
||||||
|
fullscreen: Option<Value<Option<Fullscreen>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Behavior> Default for Window<Behavior>
|
impl<Behavior> Default for Window<Behavior>
|
||||||
|
|
@ -644,6 +642,8 @@ where
|
||||||
outer_position: None,
|
outer_position: None,
|
||||||
icon: None,
|
icon: None,
|
||||||
modifiers: None,
|
modifiers: None,
|
||||||
|
enabled_buttons: None,
|
||||||
|
fullscreen: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -713,12 +713,17 @@ where
|
||||||
/// When the window is focused for user input, the dynamic will contain
|
/// When the window is focused for user input, the dynamic will contain
|
||||||
/// `true`.
|
/// `true`.
|
||||||
///
|
///
|
||||||
/// `focused` will be initialized with an initial state
|
/// The current value of `focused` will inform the OS whether the window
|
||||||
/// of `false`.
|
/// should be activated upon opening. To prevent state mismatches, if
|
||||||
pub fn focused(mut self, focused: impl IntoDynamic<bool>) -> Self {
|
/// `focused` is a dynamic, it will be initialized with `false` so that the
|
||||||
let focused = focused.into_dynamic();
|
/// transition to focused can be observed.
|
||||||
focused.set(false);
|
pub fn focused(mut self, focused: impl IntoValue<bool>) -> Self {
|
||||||
self.focused = Some(focused);
|
let focused = focused.into_value();
|
||||||
|
self.attributes.active = focused.get();
|
||||||
|
if let Value::Dynamic(focused) = focused {
|
||||||
|
focused.set(false);
|
||||||
|
self.focused = Some(focused);
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -737,6 +742,14 @@ where
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the full screen mode for this window.
|
||||||
|
pub fn fullscreen(mut self, fullscreen: impl IntoValue<Option<Fullscreen>>) -> Self {
|
||||||
|
let fullscreen = fullscreen.into_value();
|
||||||
|
self.attributes.fullscreen = fullscreen.get();
|
||||||
|
self.fullscreen = Some(fullscreen);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets `inner_size` to be the dynamic synchronized with this window's
|
/// Sets `inner_size` to be the dynamic synchronized with this window's
|
||||||
/// inner size.
|
/// inner size.
|
||||||
///
|
///
|
||||||
|
|
@ -848,6 +861,14 @@ where
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the enabled buttons for this window.
|
||||||
|
pub fn enabled_buttons(mut self, buttons: impl IntoValue<WindowButtons>) -> Self {
|
||||||
|
let buttons = buttons.into_value();
|
||||||
|
self.attributes.enabled_buttons = buttons.get();
|
||||||
|
self.enabled_buttons = Some(buttons);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Controls the level of this window.
|
/// Controls the level of this window.
|
||||||
pub fn window_level(mut self, window_level: impl IntoValue<WindowLevel>) -> Self {
|
pub fn window_level(mut self, window_level: impl IntoValue<WindowLevel>) -> Self {
|
||||||
let window_level = window_level.into_value();
|
let window_level = window_level.into_value();
|
||||||
|
|
@ -991,6 +1012,16 @@ where
|
||||||
self.modifiers = Some(modifiers.into_dynamic());
|
self.modifiers = Some(modifiers.into_dynamic());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the name of the application.
|
||||||
|
///
|
||||||
|
/// - `WM_CLASS` on X11
|
||||||
|
/// - application ID on wayland
|
||||||
|
/// - class name on windows
|
||||||
|
pub fn app_name(mut self, name: String) -> Self {
|
||||||
|
self.attributes.app_name = Some(name);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Behavior> Run for Window<Behavior>
|
impl<Behavior> Run for Window<Behavior>
|
||||||
|
|
@ -1060,6 +1091,10 @@ where
|
||||||
outer_size: this.outer_size.unwrap_or_default(),
|
outer_size: this.outer_size.unwrap_or_default(),
|
||||||
window_icon: this.icon.unwrap_or_default(),
|
window_icon: this.icon.unwrap_or_default(),
|
||||||
modifiers: this.modifiers.unwrap_or_default(),
|
modifiers: this.modifiers.unwrap_or_default(),
|
||||||
|
enabled_buttons: this
|
||||||
|
.enabled_buttons
|
||||||
|
.unwrap_or(Value::Constant(WindowButtons::all())),
|
||||||
|
fullscreen: this.fullscreen.unwrap_or_default(),
|
||||||
}),
|
}),
|
||||||
pending: this.pending,
|
pending: this.pending,
|
||||||
},
|
},
|
||||||
|
|
@ -1217,6 +1252,8 @@ struct OpenWindow<T> {
|
||||||
outer_position: Tracked<Dynamic<Point<Px>>>,
|
outer_position: Tracked<Dynamic<Point<Px>>>,
|
||||||
inner_position: Dynamic<Point<Px>>,
|
inner_position: Dynamic<Point<Px>>,
|
||||||
window_icon: Tracked<Value<Option<RgbaImage>>>,
|
window_icon: Tracked<Value<Option<RgbaImage>>>,
|
||||||
|
enabled_buttons: Tracked<Value<WindowButtons>>,
|
||||||
|
fullscreen: Tracked<Value<Option<Fullscreen>>>,
|
||||||
modifiers: Dynamic<Modifiers>,
|
modifiers: Dynamic<Modifiers>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1655,6 +1692,8 @@ where
|
||||||
outer_position: Tracked::from(settings.outer_position).ignoring_first(),
|
outer_position: Tracked::from(settings.outer_position).ignoring_first(),
|
||||||
window_icon: Tracked::from(settings.window_icon),
|
window_icon: Tracked::from(settings.window_icon),
|
||||||
modifiers: settings.modifiers,
|
modifiers: settings.modifiers,
|
||||||
|
enabled_buttons: Tracked::from(settings.enabled_buttons).ignoring_first(),
|
||||||
|
fullscreen: Tracked::from(settings.fullscreen).ignoring_first(),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.synchronize_platform_window(&mut window);
|
this.synchronize_platform_window(&mut window);
|
||||||
|
|
@ -1843,39 +1882,39 @@ where
|
||||||
where
|
where
|
||||||
W: PlatformWindowImplementation,
|
W: PlatformWindowImplementation,
|
||||||
{
|
{
|
||||||
|
macro_rules! when_updated {
|
||||||
|
($prop:ident, $handle:ident, $block:expr) => {
|
||||||
|
self.$prop.inner_sync_when_changed($handle.clone());
|
||||||
|
if let Some($prop) = self.$prop.updated() {
|
||||||
|
$block
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
self.redraw_status.sync_received();
|
self.redraw_status.sync_received();
|
||||||
self.update_ized(window);
|
self.update_ized(window);
|
||||||
if let Some(winit) = window.winit() {
|
if let Some(winit) = window.winit() {
|
||||||
let mut redraw = false;
|
let mut redraw = false;
|
||||||
let handle = window.handle(self.redraw_status.clone());
|
let handle = window.handle(self.redraw_status.clone());
|
||||||
self.outer_position.inner_sync_when_changed(handle.clone());
|
|
||||||
if let Some(position) = self.outer_position.updated() {
|
when_updated!(outer_position, handle, {
|
||||||
winit.set_outer_position(PhysicalPosition::<i32>::from(*position));
|
winit.set_outer_position(PhysicalPosition::<i32>::from(*outer_position));
|
||||||
}
|
});
|
||||||
self.content_protected
|
when_updated!(content_protected, handle, {
|
||||||
.inner_sync_when_changed(handle.clone());
|
winit.set_content_protected(*content_protected);
|
||||||
if let Some(protected) = self.content_protected.updated() {
|
});
|
||||||
winit.set_content_protected(*protected);
|
when_updated!(cursor_hittest, handle, {
|
||||||
}
|
let _ = winit.set_cursor_hittest(*cursor_hittest);
|
||||||
self.cursor_hittest.inner_sync_when_changed(handle.clone());
|
});
|
||||||
if let Some(hit) = self.cursor_hittest.updated() {
|
when_updated!(cursor_visible, handle, {
|
||||||
let _ = winit.set_cursor_hittest(*hit);
|
winit.set_cursor_visible(*cursor_visible);
|
||||||
}
|
});
|
||||||
self.cursor_visible.inner_sync_when_changed(handle.clone());
|
when_updated!(window_level, handle, {
|
||||||
if let Some(visible) = self.cursor_visible.updated() {
|
|
||||||
winit.set_cursor_visible(*visible);
|
|
||||||
}
|
|
||||||
self.window_level.inner_sync_when_changed(handle.clone());
|
|
||||||
if let Some(window_level) = self.window_level.updated() {
|
|
||||||
winit.set_window_level(*window_level);
|
winit.set_window_level(*window_level);
|
||||||
}
|
});
|
||||||
self.decorated.inner_sync_when_changed(handle.clone());
|
when_updated!(decorated, handle, {
|
||||||
if let Some(decorated) = self.decorated.updated() {
|
|
||||||
winit.set_decorations(*decorated);
|
winit.set_decorations(*decorated);
|
||||||
}
|
});
|
||||||
self.resize_increments
|
when_updated!(resize_increments, handle, {
|
||||||
.inner_sync_when_changed(handle.clone());
|
|
||||||
if let Some(resize_increments) = self.resize_increments.updated() {
|
|
||||||
let increments: Option<PhysicalSize<f32>> =
|
let increments: Option<PhysicalSize<f32>> =
|
||||||
if resize_increments.width > 0 || resize_increments.height > 0 {
|
if resize_increments.width > 0 || resize_increments.height > 0 {
|
||||||
Some(PhysicalSize::new(
|
Some(PhysicalSize::new(
|
||||||
|
|
@ -1886,24 +1925,27 @@ where
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
winit.set_resize_increments(increments);
|
winit.set_resize_increments(increments);
|
||||||
}
|
});
|
||||||
self.visible.inner_sync_when_changed(handle.clone());
|
when_updated!(visible, handle, {
|
||||||
if let Some(visible) = self.visible.updated() {
|
|
||||||
winit.set_visible(*visible);
|
winit.set_visible(*visible);
|
||||||
}
|
});
|
||||||
self.resizable.inner_sync_when_changed(handle.clone());
|
when_updated!(resizable, handle, {
|
||||||
if let Some(resizable) = self.resizable.updated() {
|
|
||||||
winit.set_resizable(*resizable);
|
winit.set_resizable(*resizable);
|
||||||
redraw = true;
|
redraw = true;
|
||||||
}
|
});
|
||||||
self.window_icon.inner_sync_when_changed(handle.clone());
|
when_updated!(window_icon, handle, {
|
||||||
if let Some(icon) = self.window_icon.updated() {
|
let icon = window_icon.as_ref().map(|icon| {
|
||||||
let icon = icon.as_ref().map(|icon| {
|
|
||||||
Icon::from_rgba(icon.as_raw().clone(), icon.width(), icon.height())
|
Icon::from_rgba(icon.as_raw().clone(), icon.width(), icon.height())
|
||||||
.expect("valid image")
|
.expect("valid image")
|
||||||
});
|
});
|
||||||
winit.set_window_icon(icon);
|
winit.set_window_icon(icon);
|
||||||
}
|
});
|
||||||
|
when_updated!(enabled_buttons, handle, {
|
||||||
|
winit.set_enabled_buttons(*enabled_buttons);
|
||||||
|
});
|
||||||
|
when_updated!(fullscreen, handle, {
|
||||||
|
winit.set_fullscreen(fullscreen.clone());
|
||||||
|
});
|
||||||
|
|
||||||
if redraw {
|
if redraw {
|
||||||
window.set_needs_redraw();
|
window.set_needs_redraw();
|
||||||
|
|
@ -2687,7 +2729,7 @@ pub(crate) mod sealed {
|
||||||
use figures::{Fraction, Point, Size};
|
use figures::{Fraction, Point, Size};
|
||||||
use image::{DynamicImage, RgbaImage};
|
use image::{DynamicImage, RgbaImage};
|
||||||
use kludgine::app::winit::event::Modifiers;
|
use kludgine::app::winit::event::Modifiers;
|
||||||
use kludgine::app::winit::window::{UserAttentionType, WindowLevel};
|
use kludgine::app::winit::window::{Fullscreen, UserAttentionType, WindowButtons, WindowLevel};
|
||||||
use kludgine::Color;
|
use kludgine::Color;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
|
|
@ -2746,6 +2788,8 @@ pub(crate) mod sealed {
|
||||||
pub outer_size: Dynamic<Size<UPx>>,
|
pub outer_size: Dynamic<Size<UPx>>,
|
||||||
pub window_icon: Value<Option<RgbaImage>>,
|
pub window_icon: Value<Option<RgbaImage>>,
|
||||||
pub modifiers: Dynamic<Modifiers>,
|
pub modifiers: Dynamic<Modifiers>,
|
||||||
|
pub enabled_buttons: Value<WindowButtons>,
|
||||||
|
pub fullscreen: Value<Option<Fullscreen>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -3359,6 +3403,8 @@ impl StandaloneWindowBuilder {
|
||||||
outer_size: Dynamic::default(),
|
outer_size: Dynamic::default(),
|
||||||
window_icon: Value::Constant(None),
|
window_icon: Value::Constant(None),
|
||||||
modifiers: Dynamic::default(),
|
modifiers: Dynamic::default(),
|
||||||
|
enabled_buttons: Value::dynamic(WindowButtons::all()),
|
||||||
|
fullscreen: Value::default(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue