api: convert Window to dyn Window

This should allow us to make future split of backends much easier.
The `Box<dyn Window>` is a _temporary_ solution, which will be
removed with the future updates when we decide on how the Window
should be stored.
This commit is contained in:
Kirill Chibisov 2024-08-23 23:40:27 +03:00 committed by GitHub
parent e716adcc0a
commit 241b7a80bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 2625 additions and 2448 deletions

View file

@ -8,7 +8,7 @@ fn main() -> Result<(), impl std::error::Error> {
use winit::event::{ElementState, KeyEvent, WindowEvent}; use winit::event::{ElementState, KeyEvent, WindowEvent};
use winit::event_loop::{ActiveEventLoop, EventLoop}; use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::raw_window_handle::HasRawWindowHandle; use winit::raw_window_handle::HasRawWindowHandle;
use winit::window::{Window, WindowId}; use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"] #[path = "util/fill.rs"]
mod fill; mod fill;
@ -16,12 +16,12 @@ fn main() -> Result<(), impl std::error::Error> {
#[derive(Default)] #[derive(Default)]
struct Application { struct Application {
parent_window_id: Option<WindowId>, parent_window_id: Option<WindowId>,
windows: HashMap<WindowId, Window>, windows: HashMap<WindowId, Box<dyn Window>>,
} }
impl ApplicationHandler for Application { impl ApplicationHandler for Application {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let attributes = Window::default_attributes() let attributes = WindowAttributes::default()
.with_title("parent window") .with_title("parent window")
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
.with_inner_size(LogicalSize::new(640.0f32, 480.0f32)); .with_inner_size(LogicalSize::new(640.0f32, 480.0f32));
@ -57,14 +57,14 @@ fn main() -> Result<(), impl std::error::Error> {
.. ..
} => { } => {
let parent_window = self.windows.get(&self.parent_window_id.unwrap()).unwrap(); let parent_window = self.windows.get(&self.parent_window_id.unwrap()).unwrap();
let child_window = spawn_child_window(parent_window, event_loop); let child_window = spawn_child_window(parent_window.as_ref(), event_loop);
let child_id = child_window.id(); let child_id = child_window.id();
println!("Child window created with id: {child_id:?}"); println!("Child window created with id: {child_id:?}");
self.windows.insert(child_id, child_window); self.windows.insert(child_id, child_window);
}, },
WindowEvent::RedrawRequested => { WindowEvent::RedrawRequested => {
if let Some(window) = self.windows.get(&window_id) { if let Some(window) = self.windows.get(&window_id) {
fill::fill_window(window); fill::fill_window(window.as_ref());
} }
}, },
_ => (), _ => (),
@ -72,9 +72,12 @@ fn main() -> Result<(), impl std::error::Error> {
} }
} }
fn spawn_child_window(parent: &Window, event_loop: &dyn ActiveEventLoop) -> Window { fn spawn_child_window(
parent: &dyn Window,
event_loop: &dyn ActiveEventLoop,
) -> Box<dyn Window> {
let parent = parent.raw_window_handle().unwrap(); let parent = parent.raw_window_handle().unwrap();
let mut window_attributes = Window::default_attributes() let mut window_attributes = WindowAttributes::default()
.with_title("child window") .with_title("child window")
.with_inner_size(LogicalSize::new(200.0f32, 200.0f32)) .with_inner_size(LogicalSize::new(200.0f32, 200.0f32))
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))

View file

@ -11,7 +11,7 @@ use winit::application::ApplicationHandler;
use winit::event::{ElementState, KeyEvent, StartCause, WindowEvent}; use winit::event::{ElementState, KeyEvent, StartCause, WindowEvent};
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop}; use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::keyboard::{Key, NamedKey}; use winit::keyboard::{Key, NamedKey};
use winit::window::{Window, WindowId}; use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"] #[path = "util/fill.rs"]
mod fill; mod fill;
@ -52,7 +52,7 @@ struct ControlFlowDemo {
request_redraw: bool, request_redraw: bool,
wait_cancelled: bool, wait_cancelled: bool,
close_requested: bool, close_requested: bool,
window: Option<Window>, window: Option<Box<dyn Window>>,
} }
impl ApplicationHandler for ControlFlowDemo { impl ApplicationHandler for ControlFlowDemo {
@ -66,7 +66,7 @@ impl ApplicationHandler for ControlFlowDemo {
} }
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes().with_title( let window_attributes = WindowAttributes::default().with_title(
"Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.", "Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.",
); );
self.window = Some(event_loop.create_window(window_attributes).unwrap()); self.window = Some(event_loop.create_window(window_attributes).unwrap());
@ -114,7 +114,7 @@ impl ApplicationHandler for ControlFlowDemo {
WindowEvent::RedrawRequested => { WindowEvent::RedrawRequested => {
let window = self.window.as_ref().unwrap(); let window = self.window.as_ref().unwrap();
window.pre_present_notify(); window.pre_present_notify();
fill::fill_window(window); fill::fill_window(window.as_ref());
}, },
_ => (), _ => (),
} }

View file

@ -11,19 +11,19 @@ fn main() -> std::process::ExitCode {
use winit::event::WindowEvent; use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop}; use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::platform::pump_events::{EventLoopExtPumpEvents, PumpStatus}; use winit::platform::pump_events::{EventLoopExtPumpEvents, PumpStatus};
use winit::window::{Window, WindowId}; use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"] #[path = "util/fill.rs"]
mod fill; mod fill;
#[derive(Default)] #[derive(Default)]
struct PumpDemo { struct PumpDemo {
window: Option<Window>, window: Option<Box<dyn Window>>,
} }
impl ApplicationHandler for PumpDemo { impl ApplicationHandler for PumpDemo {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes().with_title("A fantastic window!"); let window_attributes = WindowAttributes::default().with_title("A fantastic window!");
self.window = Some(event_loop.create_window(window_attributes).unwrap()); self.window = Some(event_loop.create_window(window_attributes).unwrap());
} }
@ -43,7 +43,7 @@ fn main() -> std::process::ExitCode {
match event { match event {
WindowEvent::CloseRequested => event_loop.exit(), WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => { WindowEvent::RedrawRequested => {
fill::fill_window(window); fill::fill_window(window.as_ref());
window.request_redraw(); window.request_redraw();
}, },
_ => (), _ => (),

View file

@ -9,7 +9,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
use winit::event::WindowEvent; use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop}; use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::platform::run_on_demand::EventLoopExtRunOnDemand; use winit::platform::run_on_demand::EventLoopExtRunOnDemand;
use winit::window::{Window, WindowId}; use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"] #[path = "util/fill.rs"]
mod fill; mod fill;
@ -18,7 +18,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
struct App { struct App {
idx: usize, idx: usize,
window_id: Option<WindowId>, window_id: Option<WindowId>,
window: Option<Window>, window: Option<Box<dyn Window>>,
} }
impl ApplicationHandler for App { impl ApplicationHandler for App {
@ -29,7 +29,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes() let window_attributes = WindowAttributes::default()
.with_title("Fantastic window number one!") .with_title("Fantastic window number one!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)); .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0));
let window = event_loop.create_window(window_attributes).unwrap(); let window = event_loop.create_window(window_attributes).unwrap();
@ -65,11 +65,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
CloseRequested", CloseRequested",
self.idx self.idx
); );
fill::cleanup_window(window); fill::cleanup_window(window.as_ref());
self.window = None; self.window = None;
}, },
WindowEvent::RedrawRequested => { WindowEvent::RedrawRequested => {
fill::fill_window(window); fill::fill_window(window.as_ref());
}, },
_ => (), _ => (),
} }

View file

@ -34,18 +34,20 @@ mod platform {
/// The graphics context used to draw to a window. /// The graphics context used to draw to a window.
struct GraphicsContext { struct GraphicsContext {
/// The global softbuffer context. /// The global softbuffer context.
context: RefCell<Context<&'static Window>>, context: RefCell<Context<&'static dyn Window>>,
/// The hash map of window IDs to surfaces. /// The hash map of window IDs to surfaces.
surfaces: HashMap<WindowId, Surface<&'static Window, &'static Window>>, surfaces: HashMap<WindowId, Surface<&'static dyn Window, &'static dyn Window>>,
} }
impl GraphicsContext { impl GraphicsContext {
fn new(w: &Window) -> Self { fn new(w: &dyn Window) -> Self {
Self { Self {
context: RefCell::new( context: RefCell::new(
Context::new(unsafe { mem::transmute::<&'_ Window, &'static Window>(w) }) Context::new(unsafe {
.expect("Failed to create a softbuffer context"), mem::transmute::<&'_ dyn Window, &'static dyn Window>(w)
})
.expect("Failed to create a softbuffer context"),
), ),
surfaces: HashMap::new(), surfaces: HashMap::new(),
} }
@ -53,22 +55,22 @@ mod platform {
fn create_surface( fn create_surface(
&mut self, &mut self,
window: &Window, window: &dyn Window,
) -> &mut Surface<&'static Window, &'static Window> { ) -> &mut Surface<&'static dyn Window, &'static dyn Window> {
self.surfaces.entry(window.id()).or_insert_with(|| { self.surfaces.entry(window.id()).or_insert_with(|| {
Surface::new(&self.context.borrow(), unsafe { Surface::new(&self.context.borrow(), unsafe {
mem::transmute::<&'_ Window, &'static Window>(window) mem::transmute::<&'_ dyn Window, &'static dyn Window>(window)
}) })
.expect("Failed to create a softbuffer surface") .expect("Failed to create a softbuffer surface")
}) })
} }
fn destroy_surface(&mut self, window: &Window) { fn destroy_surface(&mut self, window: &dyn Window) {
self.surfaces.remove(&window.id()); self.surfaces.remove(&window.id());
} }
} }
pub fn fill_window(window: &Window) { pub fn fill_window(window: &dyn Window) {
GC.with(|gc| { GC.with(|gc| {
let size = window.inner_size(); let size = window.inner_size();
let (Some(width), Some(height)) = let (Some(width), Some(height)) =
@ -94,7 +96,7 @@ mod platform {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn cleanup_window(window: &Window) { pub fn cleanup_window(window: &dyn Window) {
GC.with(|gc| { GC.with(|gc| {
let mut gc = gc.borrow_mut(); let mut gc = gc.borrow_mut();
if let Some(context) = gc.as_mut() { if let Some(context) = gc.as_mut() {
@ -106,12 +108,12 @@ mod platform {
#[cfg(not(all(feature = "rwh_06", not(any(target_os = "android", target_os = "ios")))))] #[cfg(not(all(feature = "rwh_06", not(any(target_os = "android", target_os = "ios")))))]
mod platform { mod platform {
pub fn fill_window(_window: &winit::window::Window) { pub fn fill_window(_window: &dyn winit::window::Window) {
// No-op on mobile platforms. // No-op on mobile platforms.
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn cleanup_window(_window: &winit::window::Window) { pub fn cleanup_window(_window: &dyn winit::window::Window) {
// No-op on mobile platforms. // No-op on mobile platforms.
} }
} }

View file

@ -31,7 +31,7 @@ use winit::platform::startup_notify::{
use winit::platform::web::{ActiveEventLoopExtWeb, CustomCursorExtWeb, WindowAttributesExtWeb}; use winit::platform::web::{ActiveEventLoopExtWeb, CustomCursorExtWeb, WindowAttributesExtWeb};
use winit::window::{ use winit::window::{
Cursor, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, Icon, ResizeDirection, Cursor, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, Icon, ResizeDirection,
Theme, Window, WindowId, Theme, Window, WindowAttributes, WindowId,
}; };
#[path = "util/tracing.rs"] #[path = "util/tracing.rs"]
@ -135,7 +135,7 @@ impl Application {
// TODO read-out activation token. // TODO read-out activation token.
#[allow(unused_mut)] #[allow(unused_mut)]
let mut window_attributes = Window::default_attributes() let mut window_attributes = WindowAttributes::default()
.with_title("Winit window") .with_title("Winit window")
.with_transparent(true) .with_transparent(true)
.with_window_icon(Some(self.icon.clone())); .with_window_icon(Some(self.icon.clone()));
@ -560,9 +560,9 @@ struct WindowState {
/// ///
/// NOTE: This surface must be dropped before the `Window`. /// NOTE: This surface must be dropped before the `Window`.
#[cfg(not(any(android_platform, ios_platform)))] #[cfg(not(any(android_platform, ios_platform)))]
surface: Surface<DisplayHandle<'static>, Arc<Window>>, surface: Surface<DisplayHandle<'static>, Arc<dyn Window>>,
/// The actual winit Window. /// The actual winit Window.
window: Arc<Window>, window: Arc<dyn Window>,
/// The window theme we're drawing with. /// The window theme we're drawing with.
theme: Theme, theme: Theme,
/// Cursor position over the window. /// Cursor position over the window.
@ -590,8 +590,8 @@ struct WindowState {
} }
impl WindowState { impl WindowState {
fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> { fn new(app: &Application, window: Box<dyn Window>) -> Result<Self, Box<dyn Error>> {
let window = Arc::new(window); let window: Arc<dyn Window> = Arc::from(window);
// SAFETY: the surface is dropped before the `window` which provided it with handle, thus // SAFETY: the surface is dropped before the `window` which provided it with handle, thus
// it doesn't outlive it. // it doesn't outlive it.
@ -601,7 +601,7 @@ impl WindowState {
let theme = window.theme().unwrap_or(Theme::Dark); let theme = window.theme().unwrap_or(Theme::Dark);
info!("Theme: {theme:?}"); info!("Theme: {theme:?}");
let named_idx = 0; let named_idx = 0;
window.set_cursor(CURSORS[named_idx]); window.set_cursor(CURSORS[named_idx].into());
// Allow IME out of the box. // Allow IME out of the box.
let ime = true; let ime = true;
@ -636,7 +636,7 @@ impl WindowState {
self.ime = !self.ime; self.ime = !self.ime;
self.window.set_ime_allowed(self.ime); self.window.set_ime_allowed(self.ime);
if let Some(position) = self.ime.then_some(self.cursor_position).flatten() { if let Some(position) = self.ime.then_some(self.cursor_position).flatten() {
self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20)); self.window.set_ime_cursor_area(position.into(), PhysicalSize::new(20, 20).into());
} }
} }
@ -647,7 +647,7 @@ impl WindowState {
pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) { pub fn cursor_moved(&mut self, position: PhysicalPosition<f64>) {
self.cursor_position = Some(position); self.cursor_position = Some(position);
if self.ime { if self.ime {
self.window.set_ime_cursor_area(position, PhysicalSize::new(20, 20)); self.window.set_ime_cursor_area(position.into(), PhysicalSize::new(20, 20).into());
} }
} }
@ -683,7 +683,7 @@ impl WindowState {
fn toggle_resize_increments(&mut self) { fn toggle_resize_increments(&mut self) {
let new_increments = match self.window.resize_increments() { let new_increments = match self.window.resize_increments() {
Some(_) => None, Some(_) => None,
None => Some(LogicalSize::new(25.0, 25.0)), None => Some(LogicalSize::new(25.0, 25.0).into()),
}; };
info!("Had increments: {}", new_increments.is_none()); info!("Had increments: {}", new_increments.is_none());
self.window.set_resize_increments(new_increments); self.window.set_resize_increments(new_increments);
@ -733,7 +733,7 @@ impl WindowState {
mem::swap(&mut inner_size.width, &mut inner_size.height); mem::swap(&mut inner_size.width, &mut inner_size.height);
info!("Requesting resize from {old_inner_size:?} to {inner_size:?}"); info!("Requesting resize from {old_inner_size:?} to {inner_size:?}");
if let Some(new_inner_size) = self.window.request_inner_size(inner_size) { if let Some(new_inner_size) = self.window.request_inner_size(inner_size.into()) {
if old_inner_size == new_inner_size { if old_inner_size == new_inner_size {
info!("Inner size change got ignored"); info!("Inner size change got ignored");
} else { } else {
@ -766,7 +766,7 @@ impl WindowState {
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
let cursor = event_loop.create_custom_cursor(url_custom_cursor())?; let cursor = event_loop.create_custom_cursor(url_custom_cursor())?;
self.window.set_cursor(cursor); self.window.set_cursor(cursor.into());
Ok(()) Ok(())
} }
@ -788,7 +788,7 @@ impl WindowState {
let cursor = CustomCursor::from_animation(Duration::from_secs(3), cursors).unwrap(); let cursor = CustomCursor::from_animation(Duration::from_secs(3), cursors).unwrap();
let cursor = event_loop.create_custom_cursor(cursor)?; let cursor = event_loop.create_custom_cursor(cursor)?;
self.window.set_cursor(cursor); self.window.set_cursor(cursor.into());
Ok(()) Ok(())
} }
@ -817,7 +817,7 @@ impl WindowState {
/// Show window menu. /// Show window menu.
fn show_menu(&self) { fn show_menu(&self) {
if let Some(position) = self.cursor_position { if let Some(position) = self.cursor_position {
self.window.show_window_menu(position); self.window.show_window_menu(position.into());
} }
} }

View file

@ -7,19 +7,19 @@ fn main() -> Result<(), Box<dyn Error>> {
use winit::event::WindowEvent; use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop}; use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::platform::x11::WindowAttributesExtX11; use winit::platform::x11::WindowAttributesExtX11;
use winit::window::{Window, WindowId}; use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"] #[path = "util/fill.rs"]
mod fill; mod fill;
pub struct XEmbedDemo { pub struct XEmbedDemo {
parent_window_id: u32, parent_window_id: u32,
window: Option<Window>, window: Option<Box<dyn Window>>,
} }
impl ApplicationHandler for XEmbedDemo { impl ApplicationHandler for XEmbedDemo {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = Window::default_attributes() let window_attributes = WindowAttributes::default()
.with_title("An embedded window!") .with_title("An embedded window!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
.with_embed_parent_window(self.parent_window_id); .with_embed_parent_window(self.parent_window_id);
@ -38,7 +38,7 @@ fn main() -> Result<(), Box<dyn Error>> {
WindowEvent::CloseRequested => event_loop.exit(), WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => { WindowEvent::RedrawRequested => {
window.pre_present_notify(); window.pre_present_notify();
fill::fill_window(window); fill::fill_window(window.as_ref());
}, },
_ => (), _ => (),
} }

View file

@ -67,6 +67,8 @@ changelog entry.
### Changed ### Changed
- Change `ActiveEventLoop` to be a trait. - Change `ActiveEventLoop` to be a trait.
- Change `Window` to be a trait.
- `ActiveEventLoop::create_window` now returns `Box<dyn Window>`.
- `ApplicationHandler` now uses `dyn ActiveEventLoop`. - `ApplicationHandler` now uses `dyn ActiveEventLoop`.
- On Web, let events wake up event loop immediately when using `ControlFlow::Poll`. - On Web, let events wake up event loop immediately when using `ControlFlow::Poll`.
- Bump MSRV from `1.70` to `1.73`. - Bump MSRV from `1.70` to `1.73`.

View file

@ -50,7 +50,7 @@ impl From<CustomCursor> for Cursor {
/// ```no_run /// ```no_run
/// # use winit::event_loop::ActiveEventLoop; /// # use winit::event_loop::ActiveEventLoop;
/// # use winit::window::Window; /// # use winit::window::Window;
/// # fn scope(event_loop: &dyn ActiveEventLoop, window: &Window) { /// # fn scope(event_loop: &dyn ActiveEventLoop, window: &dyn Window) {
/// use winit::window::CustomCursor; /// use winit::window::CustomCursor;
/// ///
/// let w = 10; /// let w = 10;
@ -67,7 +67,7 @@ impl From<CustomCursor> for Cursor {
/// }; /// };
/// ///
/// if let Ok(custom_cursor) = event_loop.create_custom_cursor(source) { /// if let Ok(custom_cursor) = event_loop.create_custom_cursor(source) {
/// window.set_cursor(custom_cursor.clone()); /// window.set_cursor(custom_cursor.clone().into());
/// } /// }
/// # } /// # }
/// ``` /// ```

View file

@ -321,7 +321,10 @@ pub trait ActiveEventLoop: AsAny {
/// ///
/// - **Web:** The window is created but not inserted into the Web page automatically. Please /// - **Web:** The window is created but not inserted into the Web page automatically. Please
/// see the Web platform module for more information. /// see the Web platform module for more information.
fn create_window(&self, window_attributes: WindowAttributes) -> Result<Window, OsError>; fn create_window(
&self,
window_attributes: WindowAttributes,
) -> Result<Box<dyn Window>, OsError>;
/// Create custom cursor. /// Create custom cursor.
/// ///

View file

@ -44,16 +44,16 @@
//! use winit::application::ApplicationHandler; //! use winit::application::ApplicationHandler;
//! use winit::event::WindowEvent; //! use winit::event::WindowEvent;
//! use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop}; //! use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
//! use winit::window::{Window, WindowId}; //! use winit::window::{Window, WindowId, WindowAttributes};
//! //!
//! #[derive(Default)] //! #[derive(Default)]
//! struct App { //! struct App {
//! window: Option<Window>, //! window: Option<Box<dyn Window>>,
//! } //! }
//! //!
//! impl ApplicationHandler for App { //! impl ApplicationHandler for App {
//! fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { //! fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
//! self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap()); //! self.window = Some(event_loop.create_window(WindowAttributes::default()).unwrap());
//! } //! }
//! //!
//! fn window_event(&mut self, event_loop: &dyn ActiveEventLoop, id: WindowId, event: WindowEvent) { //! fn window_event(&mut self, event_loop: &dyn ActiveEventLoop, id: WindowId, event: WindowEvent) {

View file

@ -99,13 +99,15 @@ pub trait WindowExtAndroid {
fn config(&self) -> ConfigurationRef; fn config(&self) -> ConfigurationRef;
} }
impl WindowExtAndroid for Window { impl WindowExtAndroid for dyn Window + '_ {
fn content_rect(&self) -> Rect { fn content_rect(&self) -> Rect {
self.window.content_rect() let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.content_rect()
} }
fn config(&self) -> ConfigurationRef { fn config(&self) -> ConfigurationRef {
self.window.config() let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.config()
} }
} }

View file

@ -209,42 +209,49 @@ pub trait WindowExtIOS {
fn recognize_rotation_gesture(&self, should_recognize: bool); fn recognize_rotation_gesture(&self, should_recognize: bool);
} }
impl WindowExtIOS for Window { impl WindowExtIOS for dyn Window + '_ {
#[inline] #[inline]
fn set_scale_factor(&self, scale_factor: f64) { fn set_scale_factor(&self, scale_factor: f64) {
self.window.maybe_queue_on_main(move |w| w.set_scale_factor(scale_factor)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.set_scale_factor(scale_factor));
} }
#[inline] #[inline]
fn set_valid_orientations(&self, valid_orientations: ValidOrientations) { fn set_valid_orientations(&self, valid_orientations: ValidOrientations) {
self.window.maybe_queue_on_main(move |w| w.set_valid_orientations(valid_orientations)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.set_valid_orientations(valid_orientations));
} }
#[inline] #[inline]
fn set_prefers_home_indicator_hidden(&self, hidden: bool) { fn set_prefers_home_indicator_hidden(&self, hidden: bool) {
self.window.maybe_queue_on_main(move |w| w.set_prefers_home_indicator_hidden(hidden)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.set_prefers_home_indicator_hidden(hidden));
} }
#[inline] #[inline]
fn set_preferred_screen_edges_deferring_system_gestures(&self, edges: ScreenEdge) { fn set_preferred_screen_edges_deferring_system_gestures(&self, edges: ScreenEdge) {
self.window.maybe_queue_on_main(move |w| { let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| {
w.set_preferred_screen_edges_deferring_system_gestures(edges) w.set_preferred_screen_edges_deferring_system_gestures(edges)
}) });
} }
#[inline] #[inline]
fn set_prefers_status_bar_hidden(&self, hidden: bool) { fn set_prefers_status_bar_hidden(&self, hidden: bool) {
self.window.maybe_queue_on_main(move |w| w.set_prefers_status_bar_hidden(hidden)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.set_prefers_status_bar_hidden(hidden));
} }
#[inline] #[inline]
fn set_preferred_status_bar_style(&self, status_bar_style: StatusBarStyle) { fn set_preferred_status_bar_style(&self, status_bar_style: StatusBarStyle) {
self.window.maybe_queue_on_main(move |w| w.set_preferred_status_bar_style(status_bar_style)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.set_preferred_status_bar_style(status_bar_style))
} }
#[inline] #[inline]
fn recognize_pinch_gesture(&self, should_recognize: bool) { fn recognize_pinch_gesture(&self, should_recognize: bool) {
self.window.maybe_queue_on_main(move |w| w.recognize_pinch_gesture(should_recognize)); let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.recognize_pinch_gesture(should_recognize));
} }
#[inline] #[inline]
@ -254,7 +261,8 @@ impl WindowExtIOS for Window {
minimum_number_of_touches: u8, minimum_number_of_touches: u8,
maximum_number_of_touches: u8, maximum_number_of_touches: u8,
) { ) {
self.window.maybe_queue_on_main(move |w| { let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| {
w.recognize_pan_gesture( w.recognize_pan_gesture(
should_recognize, should_recognize,
minimum_number_of_touches, minimum_number_of_touches,
@ -265,12 +273,14 @@ impl WindowExtIOS for Window {
#[inline] #[inline]
fn recognize_doubletap_gesture(&self, should_recognize: bool) { fn recognize_doubletap_gesture(&self, should_recognize: bool) {
self.window.maybe_queue_on_main(move |w| w.recognize_doubletap_gesture(should_recognize)); let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.recognize_doubletap_gesture(should_recognize));
} }
#[inline] #[inline]
fn recognize_rotation_gesture(&self, should_recognize: bool) { fn recognize_rotation_gesture(&self, should_recognize: bool) {
self.window.maybe_queue_on_main(move |w| w.recognize_rotation_gesture(should_recognize)); let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.recognize_rotation_gesture(should_recognize));
} }
} }

View file

@ -152,75 +152,89 @@ pub trait WindowExtMacOS {
fn option_as_alt(&self) -> OptionAsAlt; fn option_as_alt(&self) -> OptionAsAlt;
} }
impl WindowExtMacOS for Window { impl WindowExtMacOS for dyn Window + '_ {
#[inline] #[inline]
fn simple_fullscreen(&self) -> bool { fn simple_fullscreen(&self) -> bool {
self.window.maybe_wait_on_main(|w| w.simple_fullscreen()) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(|w| w.simple_fullscreen())
} }
#[inline] #[inline]
fn set_simple_fullscreen(&self, fullscreen: bool) -> bool { fn set_simple_fullscreen(&self, fullscreen: bool) -> bool {
self.window.maybe_wait_on_main(move |w| w.set_simple_fullscreen(fullscreen)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.set_simple_fullscreen(fullscreen))
} }
#[inline] #[inline]
fn has_shadow(&self) -> bool { fn has_shadow(&self) -> bool {
self.window.maybe_wait_on_main(|w| w.has_shadow()) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(|w| w.has_shadow())
} }
#[inline] #[inline]
fn set_has_shadow(&self, has_shadow: bool) { fn set_has_shadow(&self, has_shadow: bool) {
self.window.maybe_queue_on_main(move |w| w.set_has_shadow(has_shadow)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.set_has_shadow(has_shadow));
} }
#[inline] #[inline]
fn set_tabbing_identifier(&self, identifier: &str) { fn set_tabbing_identifier(&self, identifier: &str) {
self.window.maybe_wait_on_main(|w| w.set_tabbing_identifier(identifier)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(|w| w.set_tabbing_identifier(identifier))
} }
#[inline] #[inline]
fn tabbing_identifier(&self) -> String { fn tabbing_identifier(&self) -> String {
self.window.maybe_wait_on_main(|w| w.tabbing_identifier()) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(|w| w.tabbing_identifier())
} }
#[inline] #[inline]
fn select_next_tab(&self) { fn select_next_tab(&self) {
self.window.maybe_queue_on_main(|w| w.select_next_tab()) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(|w| w.select_next_tab());
} }
#[inline] #[inline]
fn select_previous_tab(&self) { fn select_previous_tab(&self) {
self.window.maybe_queue_on_main(|w| w.select_previous_tab()) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(|w| w.select_previous_tab());
} }
#[inline] #[inline]
fn select_tab_at_index(&self, index: usize) { fn select_tab_at_index(&self, index: usize) {
self.window.maybe_queue_on_main(move |w| w.select_tab_at_index(index)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.select_tab_at_index(index));
} }
#[inline] #[inline]
fn num_tabs(&self) -> usize { fn num_tabs(&self) -> usize {
self.window.maybe_wait_on_main(|w| w.num_tabs()) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(|w| w.num_tabs())
} }
#[inline] #[inline]
fn is_document_edited(&self) -> bool { fn is_document_edited(&self) -> bool {
self.window.maybe_wait_on_main(|w| w.is_document_edited()) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(|w| w.is_document_edited())
} }
#[inline] #[inline]
fn set_document_edited(&self, edited: bool) { fn set_document_edited(&self, edited: bool) {
self.window.maybe_queue_on_main(move |w| w.set_document_edited(edited)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.set_document_edited(edited));
} }
#[inline] #[inline]
fn set_option_as_alt(&self, option_as_alt: OptionAsAlt) { fn set_option_as_alt(&self, option_as_alt: OptionAsAlt) {
self.window.maybe_queue_on_main(move |w| w.set_option_as_alt(option_as_alt)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(move |w| w.set_option_as_alt(option_as_alt));
} }
#[inline] #[inline]
fn option_as_alt(&self) -> OptionAsAlt { fn option_as_alt(&self) -> OptionAsAlt {
self.window.maybe_wait_on_main(|w| w.option_as_alt()) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.maybe_wait_on_main(|w| w.option_as_alt())
} }
} }

View file

@ -72,9 +72,22 @@ impl EventLoopExtStartupNotify for dyn ActiveEventLoop + '_ {
} }
} }
impl WindowExtStartupNotify for Window { impl WindowExtStartupNotify for dyn Window + '_ {
fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError> { fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError> {
self.window.request_activation_token() #[cfg(wayland_platform)]
if let Some(window) = self.as_any().downcast_ref::<crate::platform_impl::wayland::Window>()
{
return window.request_activation_token();
}
#[cfg(x11_platform)]
if let Some(window) =
self.as_any().downcast_ref::<crate::platform_impl::x11::window::Window>()
{
return window.request_activation_token();
}
Err(NotSupportedError::new())
} }
} }

View file

@ -16,7 +16,7 @@
use crate::event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder}; use crate::event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder};
use crate::monitor::MonitorHandle; use crate::monitor::MonitorHandle;
pub use crate::window::Theme; pub use crate::window::Theme;
use crate::window::{Window, WindowAttributes}; use crate::window::{Window as CoreWindow, WindowAttributes};
/// Additional methods on [`ActiveEventLoop`] that are specific to Wayland. /// Additional methods on [`ActiveEventLoop`] that are specific to Wayland.
pub trait ActiveEventLoopExtWayland { pub trait ActiveEventLoopExtWayland {
@ -71,9 +71,11 @@ impl EventLoopBuilderExtWayland for EventLoopBuilder {
} }
/// Additional methods on [`Window`] that are specific to Wayland. /// Additional methods on [`Window`] that are specific to Wayland.
///
/// [`Window`]: crate::window::Window
pub trait WindowExtWayland {} pub trait WindowExtWayland {}
impl WindowExtWayland for Window {} impl WindowExtWayland for dyn CoreWindow + '_ {}
/// Additional methods on [`WindowAttributes`] that are specific to Wayland. /// Additional methods on [`WindowAttributes`] that are specific to Wayland.
pub trait WindowAttributesExtWayland { pub trait WindowAttributesExtWayland {

View file

@ -82,7 +82,7 @@ pub trait WindowExtWeb {
/// Returns [`true`] if calling `event.preventDefault()` is enabled. /// Returns [`true`] if calling `event.preventDefault()` is enabled.
/// ///
/// See [`Window::set_prevent_default()`] for more details. /// See [`WindowExtWeb::set_prevent_default()`] for more details.
fn prevent_default(&self) -> bool; fn prevent_default(&self) -> bool;
/// Sets whether `event.preventDefault()` should be called on events on the /// Sets whether `event.preventDefault()` should be called on events on the
@ -104,22 +104,34 @@ pub trait WindowExtWeb {
fn is_cursor_lock_raw(&self) -> bool; fn is_cursor_lock_raw(&self) -> bool;
} }
impl WindowExtWeb for Window { impl WindowExtWeb for dyn Window + '_ {
#[inline] #[inline]
fn canvas(&self) -> Option<Ref<'_, HtmlCanvasElement>> { fn canvas(&self) -> Option<Ref<'_, HtmlCanvasElement>> {
self.window.canvas() self.as_any()
.downcast_ref::<crate::platform_impl::Window>()
.expect("non Web window on Web")
.canvas()
} }
fn prevent_default(&self) -> bool { fn prevent_default(&self) -> bool {
self.window.prevent_default() self.as_any()
.downcast_ref::<crate::platform_impl::Window>()
.expect("non Web window on Web")
.prevent_default()
} }
fn set_prevent_default(&self, prevent_default: bool) { fn set_prevent_default(&self, prevent_default: bool) {
self.window.set_prevent_default(prevent_default) self.as_any()
.downcast_ref::<crate::platform_impl::Window>()
.expect("non Web window on Web")
.set_prevent_default(prevent_default)
} }
fn is_cursor_lock_raw(&self) -> bool { fn is_cursor_lock_raw(&self) -> bool {
self.window.is_cursor_lock_raw() self.as_any()
.downcast_ref::<crate::platform_impl::Window>()
.expect("non Web window on Web")
.is_cursor_lock_raw()
} }
} }
@ -136,7 +148,7 @@ pub trait WindowAttributesExtWeb {
/// Sets whether `event.preventDefault()` should be called on events on the /// Sets whether `event.preventDefault()` should be called on events on the
/// canvas that have side effects. /// canvas that have side effects.
/// ///
/// See [`Window::set_prevent_default()`] for more details. /// See [`WindowExtWeb::set_prevent_default()`] for more details.
/// ///
/// Enabled by default. /// Enabled by default.
fn with_prevent_default(self, prevent_default: bool) -> Self; fn with_prevent_default(self, prevent_default: bool) -> Self;

View file

@ -4,6 +4,7 @@
//! tested regularly. //! tested regularly.
use std::borrow::Borrow; use std::borrow::Borrow;
use std::ffi::c_void; use std::ffi::c_void;
use std::ops::Deref;
use std::path::Path; use std::path::Path;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
@ -115,50 +116,25 @@ pub enum CornerPreference {
/// ///
/// See [`WindowBorrowExtWindows::any_thread`] for more information. /// See [`WindowBorrowExtWindows::any_thread`] for more information.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct AnyThread<W>(W); pub struct AnyThread<W: Window>(W);
impl<W: Borrow<Window>> AnyThread<W> { impl<W: Window> AnyThread<W> {
/// Get a reference to the inner window. /// Get a reference to the inner window.
#[inline] #[inline]
pub fn get_ref(&self) -> &Window { pub fn get_ref(&self) -> &dyn Window {
self.0.borrow()
}
/// Get a reference to the inner object.
#[inline]
pub fn inner(&self) -> &W {
&self.0 &self.0
} }
/// Unwrap and get the inner window.
#[inline]
pub fn into_inner(self) -> W {
self.0
}
} }
impl<W: Borrow<Window>> AsRef<Window> for AnyThread<W> { impl<W: Window> Deref for AnyThread<W> {
fn as_ref(&self) -> &Window { type Target = W;
self.get_ref()
}
}
impl<W: Borrow<Window>> Borrow<Window> for AnyThread<W> {
fn borrow(&self) -> &Window {
self.get_ref()
}
}
impl<W: Borrow<Window>> std::ops::Deref for AnyThread<W> {
type Target = Window;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
self.get_ref() &self.0
} }
} }
#[cfg(feature = "rwh_06")] #[cfg(feature = "rwh_06")]
impl<W: Borrow<Window>> rwh_06::HasWindowHandle for AnyThread<W> { impl<W: Window> rwh_06::HasWindowHandle for AnyThread<W> {
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> { fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
// SAFETY: The top level user has asserted this is only used safely. // SAFETY: The top level user has asserted this is only used safely.
unsafe { self.get_ref().window_handle_any_thread() } unsafe { self.get_ref().window_handle_any_thread() }
@ -341,7 +317,7 @@ pub trait WindowExtWindows {
/// ///
/// ```no_run /// ```no_run
/// # use winit::window::Window; /// # use winit::window::Window;
/// # fn scope(window: Window) { /// # fn scope(window: Box<dyn Window>) {
/// use std::thread; /// use std::thread;
/// ///
/// use winit::platform::windows::WindowExtWindows; /// use winit::platform::windows::WindowExtWindows;
@ -365,35 +341,41 @@ pub trait WindowExtWindows {
) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError>; ) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError>;
} }
impl WindowExtWindows for Window { impl WindowExtWindows for dyn Window + '_ {
#[inline] #[inline]
fn set_enable(&self, enabled: bool) { fn set_enable(&self, enabled: bool) {
self.window.set_enable(enabled) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.set_enable(enabled)
} }
#[inline] #[inline]
fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>) { fn set_taskbar_icon(&self, taskbar_icon: Option<Icon>) {
self.window.set_taskbar_icon(taskbar_icon) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.set_taskbar_icon(taskbar_icon)
} }
#[inline] #[inline]
fn set_skip_taskbar(&self, skip: bool) { fn set_skip_taskbar(&self, skip: bool) {
self.window.set_skip_taskbar(skip) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.set_skip_taskbar(skip)
} }
#[inline] #[inline]
fn set_undecorated_shadow(&self, shadow: bool) { fn set_undecorated_shadow(&self, shadow: bool) {
self.window.set_undecorated_shadow(shadow) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.set_undecorated_shadow(shadow)
} }
#[inline] #[inline]
fn set_system_backdrop(&self, backdrop_type: BackdropType) { fn set_system_backdrop(&self, backdrop_type: BackdropType) {
self.window.set_system_backdrop(backdrop_type) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.set_system_backdrop(backdrop_type)
} }
#[inline] #[inline]
fn set_border_color(&self, color: Option<Color>) { fn set_border_color(&self, color: Option<Color>) {
self.window.set_border_color(color.unwrap_or(Color::NONE)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.set_border_color(color.unwrap_or(Color::NONE))
} }
#[inline] #[inline]
@ -401,25 +383,29 @@ impl WindowExtWindows for Window {
// The windows docs don't mention NONE as a valid options but it works in practice and is // The windows docs don't mention NONE as a valid options but it works in practice and is
// useful to circumvent the Windows option "Show accent color on title bars and // useful to circumvent the Windows option "Show accent color on title bars and
// window borders" // window borders"
self.window.set_title_background_color(color.unwrap_or(Color::NONE)) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.set_title_background_color(color.unwrap_or(Color::NONE))
} }
#[inline] #[inline]
fn set_title_text_color(&self, color: Color) { fn set_title_text_color(&self, color: Color) {
self.window.set_title_text_color(color) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.set_title_text_color(color)
} }
#[inline] #[inline]
fn set_corner_preference(&self, preference: CornerPreference) { fn set_corner_preference(&self, preference: CornerPreference) {
self.window.set_corner_preference(preference) let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
window.set_corner_preference(preference)
} }
#[cfg(feature = "rwh_06")] #[cfg(feature = "rwh_06")]
unsafe fn window_handle_any_thread( unsafe fn window_handle_any_thread(
&self, &self,
) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> { ) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
unsafe { unsafe {
let handle = self.window.rwh_06_no_thread_check()?; let handle = window.rwh_06_no_thread_check()?;
// SAFETY: The handle is valid in this context. // SAFETY: The handle is valid in this context.
Ok(rwh_06::WindowHandle::borrow_raw(handle)) Ok(rwh_06::WindowHandle::borrow_raw(handle))
@ -430,7 +416,7 @@ impl WindowExtWindows for Window {
/// Additional methods for anything that dereference to [`Window`]. /// Additional methods for anything that dereference to [`Window`].
/// ///
/// [`Window`]: crate::window::Window /// [`Window`]: crate::window::Window
pub trait WindowBorrowExtWindows: Borrow<Window> + Sized { pub trait WindowBorrowExtWindows: Borrow<dyn Window> + Sized {
/// Create an object that allows accessing the inner window handle in a thread-unsafe way. /// Create an object that allows accessing the inner window handle in a thread-unsafe way.
/// ///
/// It is possible to call [`window_handle_any_thread`] to get around Windows's thread /// It is possible to call [`window_handle_any_thread`] to get around Windows's thread
@ -457,12 +443,15 @@ pub trait WindowBorrowExtWindows: Borrow<Window> + Sized {
doc = "[`HasWindowHandle`]: #only-available-with-rwh_06", doc = "[`HasWindowHandle`]: #only-available-with-rwh_06",
doc = "[`window_handle_any_thread`]: #only-available-with-rwh_06" doc = "[`window_handle_any_thread`]: #only-available-with-rwh_06"
)] )]
unsafe fn any_thread(self) -> AnyThread<Self> { unsafe fn any_thread(self) -> AnyThread<Self>
where
Self: Window,
{
AnyThread(self) AnyThread(self)
} }
} }
impl<W: Borrow<Window> + Sized> WindowBorrowExtWindows for W {} impl<W: Borrow<dyn Window> + Sized> WindowBorrowExtWindows for W {}
/// Additional methods on `WindowAttributes` that are specific to Windows. /// Additional methods on `WindowAttributes` that are specific to Windows.
#[allow(rustdoc::broken_intra_doc_links)] #[allow(rustdoc::broken_intra_doc_links)]

View file

@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use crate::dpi::Size; use crate::dpi::Size;
use crate::event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder}; use crate::event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder};
use crate::monitor::MonitorHandle; use crate::monitor::MonitorHandle;
use crate::window::{Window, WindowAttributes}; use crate::window::{Window as CoreWindow, WindowAttributes};
/// X window type. Maps directly to /// X window type. Maps directly to
/// [`_NET_WM_WINDOW_TYPE`](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html). /// [`_NET_WM_WINDOW_TYPE`](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html).
@ -138,9 +138,11 @@ impl EventLoopBuilderExtX11 for EventLoopBuilder {
} }
/// Additional methods on [`Window`] that are specific to X11. /// Additional methods on [`Window`] that are specific to X11.
///
/// [`Window`]: crate::window::Window
pub trait WindowExtX11 {} pub trait WindowExtX11 {}
impl WindowExtX11 for Window {} impl WindowExtX11 for dyn CoreWindow {}
/// Additional methods on [`WindowAttributes`] that are specific to X11. /// Additional methods on [`WindowAttributes`] that are specific to X11.
pub trait WindowAttributesExtX11 { pub trait WindowAttributesExtX11 {
@ -169,13 +171,13 @@ pub trait WindowAttributesExtX11 {
/// ///
/// ``` /// ```
/// # use winit::dpi::{LogicalSize, PhysicalSize}; /// # use winit::dpi::{LogicalSize, PhysicalSize};
/// # use winit::window::Window; /// # use winit::window::{Window, WindowAttributes};
/// # use winit::platform::x11::WindowAttributesExtX11; /// # use winit::platform::x11::WindowAttributesExtX11;
/// // Specify the size in logical dimensions like this: /// // Specify the size in logical dimensions like this:
/// Window::default_attributes().with_base_size(LogicalSize::new(400.0, 200.0)); /// WindowAttributes::default().with_base_size(LogicalSize::new(400.0, 200.0));
/// ///
/// // Or specify the size in physical dimensions like this: /// // Or specify the size in physical dimensions like this:
/// Window::default_attributes().with_base_size(PhysicalSize::new(400, 200)); /// WindowAttributes::default().with_base_size(PhysicalSize::new(400, 200));
/// ``` /// ```
fn with_base_size<S: Into<Size>>(self, base_size: S) -> Self; fn with_base_size<S: Into<Size>>(self, base_size: S) -> Self;
@ -184,12 +186,12 @@ pub trait WindowAttributesExtX11 {
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
/// use winit::window::Window; /// use winit::window::{Window, WindowAttributes};
/// use winit::event_loop::ActiveEventLoop; /// use winit::event_loop::ActiveEventLoop;
/// use winit::platform::x11::{XWindow, WindowAttributesExtX11}; /// use winit::platform::x11::{XWindow, WindowAttributesExtX11};
/// # fn create_window(event_loop: &dyn ActiveEventLoop) -> Result<(), Box<dyn std::error::Error>> { /// # fn create_window(event_loop: &dyn ActiveEventLoop) -> Result<(), Box<dyn std::error::Error>> {
/// let parent_window_id = std::env::args().nth(1).unwrap().parse::<XWindow>()?; /// let parent_window_id = std::env::args().nth(1).unwrap().parse::<XWindow>()?;
/// let window_attributes = Window::default_attributes().with_embed_parent_window(parent_window_id); /// let window_attributes = WindowAttributes::default().with_embed_parent_window(parent_window_id);
/// let window = event_loop.create_window(window_attributes)?; /// let window = event_loop.create_window(window_attributes)?;
/// # Ok(()) } /// # Ok(()) }
/// ``` /// ```

View file

@ -22,10 +22,9 @@ use crate::event_loop::{
}; };
use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::pump_events::PumpStatus; use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::Fullscreen;
use crate::window::{ use crate::window::{
self, CursorGrabMode, CustomCursor, CustomCursorSource, ImePurpose, ResizeDirection, Theme, self, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, ImePurpose,
Window as RootWindow, WindowAttributes, WindowButtons, WindowLevel, ResizeDirection, Theme, Window as CoreWindow, WindowAttributes, WindowButtons, WindowLevel,
}; };
mod keycodes; mod keycodes;
@ -593,9 +592,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window( fn create_window(
&self, &self,
window_attributes: WindowAttributes, window_attributes: WindowAttributes,
) -> Result<RootWindow, error::OsError> { ) -> Result<Box<dyn CoreWindow>, error::OsError> {
let window = Window::new(self, window_attributes)?; Ok(Box::new(Window::new(self, window_attributes)?))
Ok(RootWindow { window })
} }
fn create_custom_cursor( fn create_custom_cursor(
@ -723,172 +721,18 @@ impl Window {
Ok(Self { app: el.app.clone(), redraw_requester: el.redraw_requester.clone() }) Ok(Self { app: el.app.clone(), redraw_requester: el.redraw_requester.clone() })
} }
pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&Self) + Send + 'static) { pub fn config(&self) -> ConfigurationRef {
f(self) self.app.config()
} }
pub(crate) fn maybe_wait_on_main<R: Send>(&self, f: impl FnOnce(&Self) -> R + Send) -> R { pub fn content_rect(&self) -> Rect {
f(self) self.app.content_rect()
}
pub fn id(&self) -> WindowId {
WindowId
}
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
None
}
pub fn available_monitors(&self) -> Option<MonitorHandle> {
None
}
pub fn current_monitor(&self) -> Option<MonitorHandle> {
None
}
pub fn scale_factor(&self) -> f64 {
scale_factor(&self.app)
}
pub fn request_redraw(&self) {
self.redraw_requester.request_redraw()
}
pub fn pre_present_notify(&self) {}
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, error::NotSupportedError> {
Err(error::NotSupportedError::new())
}
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, error::NotSupportedError> {
Err(error::NotSupportedError::new())
}
pub fn set_outer_position(&self, _position: Position) {
// no effect
}
pub fn inner_size(&self) -> PhysicalSize<u32> {
self.outer_size()
}
pub fn request_inner_size(&self, _size: Size) -> Option<PhysicalSize<u32>> {
Some(self.inner_size())
}
pub fn outer_size(&self) -> PhysicalSize<u32> {
screen_size(&self.app)
}
pub fn set_min_inner_size(&self, _: Option<Size>) {}
pub fn set_max_inner_size(&self, _: Option<Size>) {}
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
None
}
pub fn set_resize_increments(&self, _increments: Option<Size>) {}
pub fn set_title(&self, _title: &str) {}
pub fn set_transparent(&self, _transparent: bool) {}
pub fn set_blur(&self, _blur: bool) {}
pub fn set_visible(&self, _visibility: bool) {}
pub fn is_visible(&self) -> Option<bool> {
None
}
pub fn set_resizable(&self, _resizeable: bool) {}
pub fn is_resizable(&self) -> bool {
false
}
pub fn set_enabled_buttons(&self, _buttons: WindowButtons) {}
pub fn enabled_buttons(&self) -> WindowButtons {
WindowButtons::all()
}
pub fn set_minimized(&self, _minimized: bool) {}
pub fn is_minimized(&self) -> Option<bool> {
None
}
pub fn set_maximized(&self, _maximized: bool) {}
pub fn is_maximized(&self) -> bool {
false
}
pub fn set_fullscreen(&self, _monitor: Option<Fullscreen>) {
warn!("Cannot set fullscreen on Android");
}
pub fn fullscreen(&self) -> Option<Fullscreen> {
None
}
pub fn set_decorations(&self, _decorations: bool) {}
pub fn is_decorated(&self) -> bool {
true
}
pub fn set_window_level(&self, _level: WindowLevel) {}
pub fn set_window_icon(&self, _window_icon: Option<crate::icon::Icon>) {}
pub fn set_ime_cursor_area(&self, _position: Position, _size: Size) {}
pub fn set_ime_allowed(&self, _allowed: bool) {}
pub fn set_ime_purpose(&self, _purpose: ImePurpose) {}
pub fn focus_window(&self) {}
pub fn request_user_attention(&self, _request_type: Option<window::UserAttentionType>) {}
pub fn set_cursor(&self, _: Cursor) {}
pub fn set_cursor_position(&self, _: Position) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
}
pub fn set_cursor_grab(&self, _: CursorGrabMode) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
}
pub fn set_cursor_visible(&self, _: bool) {}
pub fn drag_window(&self) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
}
pub fn drag_resize_window(
&self,
_direction: ResizeDirection,
) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
}
#[inline]
pub fn show_window_menu(&self, _position: Position) {}
pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
} }
#[cfg(feature = "rwh_06")] #[cfg(feature = "rwh_06")]
// Allow the usage of HasRawWindowHandle inside this function // Allow the usage of HasRawWindowHandle inside this function
#[allow(deprecated)] #[allow(deprecated)]
pub fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> { fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> {
use rwh_06::HasRawWindowHandle; use rwh_06::HasRawWindowHandle;
if let Some(native_window) = self.app.native_window().as_ref() { if let Some(native_window) = self.app.native_window().as_ref() {
@ -904,37 +748,206 @@ impl Window {
} }
#[cfg(feature = "rwh_06")] #[cfg(feature = "rwh_06")]
pub fn raw_display_handle_rwh_06( fn raw_display_handle_rwh_06(&self) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Android(rwh_06::AndroidDisplayHandle::new())) Ok(rwh_06::RawDisplayHandle::Android(rwh_06::AndroidDisplayHandle::new()))
} }
}
pub fn config(&self) -> ConfigurationRef { #[cfg(feature = "rwh_06")]
self.app.config() impl rwh_06::HasDisplayHandle for Window {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
let raw = self.raw_display_handle_rwh_06()?;
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasWindowHandle for Window {
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
let raw = self.raw_window_handle_rwh_06()?;
unsafe { Ok(rwh_06::WindowHandle::borrow_raw(raw)) }
}
}
impl CoreWindow for Window {
fn id(&self) -> window::WindowId {
window::WindowId(WindowId)
} }
pub fn content_rect(&self) -> Rect { fn primary_monitor(&self) -> Option<RootMonitorHandle> {
self.app.content_rect()
}
pub fn set_theme(&self, _theme: Option<Theme>) {}
pub fn theme(&self) -> Option<Theme> {
None None
} }
pub fn set_content_protected(&self, _protected: bool) {} fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
Box::new(std::iter::empty())
}
pub fn has_focus(&self) -> bool { fn current_monitor(&self) -> Option<RootMonitorHandle> {
None
}
fn scale_factor(&self) -> f64 {
scale_factor(&self.app)
}
fn request_redraw(&self) {
self.redraw_requester.request_redraw()
}
fn pre_present_notify(&self) {}
fn inner_position(&self) -> Result<PhysicalPosition<i32>, error::NotSupportedError> {
Err(error::NotSupportedError::new())
}
fn outer_position(&self) -> Result<PhysicalPosition<i32>, error::NotSupportedError> {
Err(error::NotSupportedError::new())
}
fn set_outer_position(&self, _position: Position) {
// no effect
}
fn inner_size(&self) -> PhysicalSize<u32> {
self.outer_size()
}
fn request_inner_size(&self, _size: Size) -> Option<PhysicalSize<u32>> {
Some(self.inner_size())
}
fn outer_size(&self) -> PhysicalSize<u32> {
screen_size(&self.app)
}
fn set_min_inner_size(&self, _: Option<Size>) {}
fn set_max_inner_size(&self, _: Option<Size>) {}
fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
None
}
fn set_resize_increments(&self, _increments: Option<Size>) {}
fn set_title(&self, _title: &str) {}
fn set_transparent(&self, _transparent: bool) {}
fn set_blur(&self, _blur: bool) {}
fn set_visible(&self, _visibility: bool) {}
fn is_visible(&self) -> Option<bool> {
None
}
fn set_resizable(&self, _resizeable: bool) {}
fn is_resizable(&self) -> bool {
false
}
fn set_enabled_buttons(&self, _buttons: WindowButtons) {}
fn enabled_buttons(&self) -> WindowButtons {
WindowButtons::all()
}
fn set_minimized(&self, _minimized: bool) {}
fn is_minimized(&self) -> Option<bool> {
None
}
fn set_maximized(&self, _maximized: bool) {}
fn is_maximized(&self) -> bool {
false
}
fn set_fullscreen(&self, _monitor: Option<Fullscreen>) {
warn!("Cannot set fullscreen on Android");
}
fn fullscreen(&self) -> Option<Fullscreen> {
None
}
fn set_decorations(&self, _decorations: bool) {}
fn is_decorated(&self) -> bool {
true
}
fn set_window_level(&self, _level: WindowLevel) {}
fn set_window_icon(&self, _window_icon: Option<crate::icon::Icon>) {}
fn set_ime_cursor_area(&self, _position: Position, _size: Size) {}
fn set_ime_allowed(&self, _allowed: bool) {}
fn set_ime_purpose(&self, _purpose: ImePurpose) {}
fn focus_window(&self) {}
fn request_user_attention(&self, _request_type: Option<window::UserAttentionType>) {}
fn set_cursor(&self, _: Cursor) {}
fn set_cursor_position(&self, _: Position) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
}
fn set_cursor_grab(&self, _: CursorGrabMode) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
}
fn set_cursor_visible(&self, _: bool) {}
fn drag_window(&self) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
}
fn drag_resize_window(&self, _direction: ResizeDirection) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
}
#[inline]
fn show_window_menu(&self, _position: Position) {}
fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
}
fn set_theme(&self, _theme: Option<Theme>) {}
fn theme(&self) -> Option<Theme> {
None
}
fn set_content_protected(&self, _protected: bool) {}
fn has_focus(&self) -> bool {
HAS_FOCUS.load(Ordering::Relaxed) HAS_FOCUS.load(Ordering::Relaxed)
} }
pub fn title(&self) -> String { fn title(&self) -> String {
String::new() String::new()
} }
pub fn reset_dead_keys(&self) {} fn reset_dead_keys(&self) {}
#[cfg(feature = "rwh_06")]
fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
self
}
#[cfg(feature = "rwh_06")]
fn rwh_06_window_handle(&self) -> &dyn rwh_06::HasWindowHandle {
self
}
} }
#[derive(Default, Clone, Debug)] #[derive(Default, Clone, Debug)]

View file

@ -38,9 +38,7 @@ use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::macos::ActivationPolicy; use crate::platform::macos::ActivationPolicy;
use crate::platform::pump_events::PumpStatus; use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::Window; use crate::platform_impl::Window;
use crate::window::{ use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme};
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow,
};
#[derive(Default)] #[derive(Default)]
pub struct PanicInfo { pub struct PanicInfo {
@ -105,9 +103,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window( fn create_window(
&self, &self,
window_attributes: crate::window::WindowAttributes, window_attributes: crate::window::WindowAttributes,
) -> Result<crate::window::Window, crate::error::OsError> { ) -> Result<Box<dyn crate::window::Window>, crate::error::OsError> {
let window = Window::new(self, window_attributes)?; Ok(Box::new(Window::new(self, window_attributes)?))
Ok(RootWindow { window })
} }
fn create_custom_cursor( fn create_custom_cursor(

View file

@ -1,5 +1,6 @@
#![allow(clippy::unnecessary_cast)] #![allow(clippy::unnecessary_cast)]
use dpi::{Position, Size};
use objc2::rc::{autoreleasepool, Retained}; use objc2::rc::{autoreleasepool, Retained};
use objc2::{declare_class, mutability, ClassType, DeclaredClass}; use objc2::{declare_class, mutability, ClassType, DeclaredClass};
use objc2_app_kit::{NSResponder, NSWindow}; use objc2_app_kit::{NSResponder, NSWindow};
@ -8,7 +9,11 @@ use objc2_foundation::{MainThreadBound, MainThreadMarker, NSObject};
use super::event_loop::ActiveEventLoop; use super::event_loop::ActiveEventLoop;
use super::window_delegate::WindowDelegate; use super::window_delegate::WindowDelegate;
use crate::error::OsError as RootOsError; use crate::error::OsError as RootOsError;
use crate::window::WindowAttributes; use crate::monitor::MonitorHandle as CoreMonitorHandle;
use crate::window::{
Cursor, Fullscreen, Icon, ImePurpose, Theme, UserAttentionType, Window as CoreWindow,
WindowAttributes, WindowButtons, WindowLevel,
};
pub(crate) struct Window { pub(crate) struct Window {
window: MainThreadBound<Retained<WinitWindow>>, window: MainThreadBound<Retained<WinitWindow>>,
@ -16,12 +21,6 @@ pub(crate) struct Window {
delegate: MainThreadBound<Retained<WindowDelegate>>, delegate: MainThreadBound<Retained<WindowDelegate>>,
} }
impl Drop for Window {
fn drop(&mut self) {
self.window.get_on_main(|window| autoreleasepool(|_| window.close()))
}
}
impl Window { impl Window {
pub(crate) fn new( pub(crate) fn new(
window_target: &ActiveEventLoop, window_target: &ActiveEventLoop,
@ -36,11 +35,6 @@ impl Window {
}) })
} }
pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&WindowDelegate) + Send + 'static) {
// For now, don't actually do queuing, since it may be less predictable
self.maybe_wait_on_main(f)
}
pub(crate) fn maybe_wait_on_main<R: Send>( pub(crate) fn maybe_wait_on_main<R: Send>(
&self, &self,
f: impl FnOnce(&WindowDelegate) -> R + Send, f: impl FnOnce(&WindowDelegate) -> R + Send,
@ -69,6 +63,283 @@ impl Window {
} }
} }
impl Drop for Window {
fn drop(&mut self) {
// Restore the video mode.
if matches!(self.fullscreen(), Some(Fullscreen::Exclusive(_))) {
self.set_fullscreen(None);
}
self.window.get_on_main(|window| autoreleasepool(|_| window.close()))
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for Window {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
let raw = self.raw_display_handle_rwh_06()?;
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasWindowHandle for Window {
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
let raw = self.raw_window_handle_rwh_06()?;
unsafe { Ok(rwh_06::WindowHandle::borrow_raw(raw)) }
}
}
impl CoreWindow for Window {
fn id(&self) -> crate::window::WindowId {
self.maybe_wait_on_main(|delegate| crate::window::WindowId(delegate.id()))
}
fn scale_factor(&self) -> f64 {
self.maybe_wait_on_main(|delegate| delegate.scale_factor())
}
fn request_redraw(&self) {
self.maybe_wait_on_main(|delegate| delegate.request_redraw());
}
fn pre_present_notify(&self) {
self.maybe_wait_on_main(|delegate| delegate.pre_present_notify());
}
fn reset_dead_keys(&self) {
self.maybe_wait_on_main(|delegate| delegate.reset_dead_keys());
}
fn inner_position(
&self,
) -> Result<dpi::PhysicalPosition<i32>, crate::error::NotSupportedError> {
self.maybe_wait_on_main(|delegate| delegate.inner_position())
}
fn outer_position(
&self,
) -> Result<dpi::PhysicalPosition<i32>, crate::error::NotSupportedError> {
self.maybe_wait_on_main(|delegate| delegate.outer_position())
}
fn set_outer_position(&self, position: Position) {
self.maybe_wait_on_main(|delegate| delegate.set_outer_position(position));
}
fn inner_size(&self) -> dpi::PhysicalSize<u32> {
self.maybe_wait_on_main(|delegate| delegate.inner_size())
}
fn request_inner_size(&self, size: Size) -> Option<dpi::PhysicalSize<u32>> {
self.maybe_wait_on_main(|delegate| delegate.request_inner_size(size))
}
fn outer_size(&self) -> dpi::PhysicalSize<u32> {
self.maybe_wait_on_main(|delegate| delegate.outer_size())
}
fn set_min_inner_size(&self, min_size: Option<Size>) {
self.maybe_wait_on_main(|delegate| delegate.set_min_inner_size(min_size))
}
fn set_max_inner_size(&self, max_size: Option<Size>) {
self.maybe_wait_on_main(|delegate| delegate.set_max_inner_size(max_size));
}
fn resize_increments(&self) -> Option<dpi::PhysicalSize<u32>> {
self.maybe_wait_on_main(|delegate| delegate.resize_increments())
}
fn set_resize_increments(&self, increments: Option<Size>) {
self.maybe_wait_on_main(|delegate| delegate.set_resize_increments(increments));
}
fn set_title(&self, title: &str) {
self.maybe_wait_on_main(|delegate| delegate.set_title(title));
}
fn set_transparent(&self, transparent: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_transparent(transparent));
}
fn set_blur(&self, blur: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_blur(blur));
}
fn set_visible(&self, visible: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_visible(visible));
}
fn is_visible(&self) -> Option<bool> {
self.maybe_wait_on_main(|delegate| delegate.is_visible())
}
fn set_resizable(&self, resizable: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_resizable(resizable))
}
fn is_resizable(&self) -> bool {
self.maybe_wait_on_main(|delegate| delegate.is_resizable())
}
fn set_enabled_buttons(&self, buttons: WindowButtons) {
self.maybe_wait_on_main(|delegate| delegate.set_enabled_buttons(buttons))
}
fn enabled_buttons(&self) -> WindowButtons {
self.maybe_wait_on_main(|delegate| delegate.enabled_buttons())
}
fn set_minimized(&self, minimized: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_minimized(minimized));
}
fn is_minimized(&self) -> Option<bool> {
self.maybe_wait_on_main(|delegate| delegate.is_minimized())
}
fn set_maximized(&self, maximized: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_maximized(maximized));
}
fn is_maximized(&self) -> bool {
self.maybe_wait_on_main(|delegate| delegate.is_maximized())
}
fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
self.maybe_wait_on_main(|delegate| delegate.set_fullscreen(fullscreen.map(Into::into)))
}
fn fullscreen(&self) -> Option<Fullscreen> {
self.maybe_wait_on_main(|delegate| delegate.fullscreen().map(Into::into))
}
fn set_decorations(&self, decorations: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_decorations(decorations));
}
fn is_decorated(&self) -> bool {
self.maybe_wait_on_main(|delegate| delegate.is_decorated())
}
fn set_window_level(&self, level: WindowLevel) {
self.maybe_wait_on_main(|delegate| delegate.set_window_level(level));
}
fn set_window_icon(&self, window_icon: Option<Icon>) {
self.maybe_wait_on_main(|delegate| delegate.set_window_icon(window_icon));
}
fn set_ime_cursor_area(&self, position: Position, size: Size) {
self.maybe_wait_on_main(|delegate| delegate.set_ime_cursor_area(position, size));
}
fn set_ime_allowed(&self, allowed: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_ime_allowed(allowed));
}
fn set_ime_purpose(&self, purpose: ImePurpose) {
self.maybe_wait_on_main(|delegate| delegate.set_ime_purpose(purpose));
}
fn focus_window(&self) {
self.maybe_wait_on_main(|delegate| delegate.focus_window());
}
fn has_focus(&self) -> bool {
self.maybe_wait_on_main(|delegate| delegate.has_focus())
}
fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
self.maybe_wait_on_main(|delegate| delegate.request_user_attention(request_type));
}
fn set_theme(&self, theme: Option<Theme>) {
self.maybe_wait_on_main(|delegate| delegate.set_theme(theme));
}
fn theme(&self) -> Option<Theme> {
self.maybe_wait_on_main(|delegate| delegate.theme())
}
fn set_content_protected(&self, protected: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_content_protected(protected));
}
fn title(&self) -> String {
self.maybe_wait_on_main(|delegate| delegate.title())
}
fn set_cursor(&self, cursor: Cursor) {
self.maybe_wait_on_main(|delegate| delegate.set_cursor(cursor));
}
fn set_cursor_position(&self, position: Position) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_position(position))
}
fn set_cursor_grab(
&self,
mode: crate::window::CursorGrabMode,
) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_grab(mode))
}
fn set_cursor_visible(&self, visible: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_visible(visible))
}
fn drag_window(&self) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.drag_window())
}
fn drag_resize_window(
&self,
direction: crate::window::ResizeDirection,
) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.drag_resize_window(direction))
}
fn show_window_menu(&self, position: Position) {
self.maybe_wait_on_main(|delegate| delegate.show_window_menu(position))
}
fn set_cursor_hittest(&self, hittest: bool) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_hittest(hittest))
}
fn current_monitor(&self) -> Option<CoreMonitorHandle> {
self.maybe_wait_on_main(|delegate| {
delegate.current_monitor().map(|inner| CoreMonitorHandle { inner })
})
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
self.maybe_wait_on_main(|delegate| {
Box::new(
delegate.available_monitors().into_iter().map(|inner| CoreMonitorHandle { inner }),
)
})
}
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
self.maybe_wait_on_main(|delegate| {
delegate.primary_monitor().map(|inner| CoreMonitorHandle { inner })
})
}
#[cfg(feature = "rwh_06")]
fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
self
}
#[cfg(feature = "rwh_06")]
fn rwh_06_window_handle(&self) -> &dyn rwh_06::HasWindowHandle {
self
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId(pub usize); pub struct WindowId(pub usize);

View file

@ -33,7 +33,7 @@ use crate::event_loop::{
}; };
use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform_impl::Window; use crate::platform_impl::Window;
use crate::window::{CustomCursor, CustomCursorSource, Theme, Window as RootWindow}; use crate::window::{CustomCursor, CustomCursorSource, Theme, Window as CoreWindow};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct ActiveEventLoop { pub(crate) struct ActiveEventLoop {
@ -49,9 +49,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window( fn create_window(
&self, &self,
window_attributes: crate::window::WindowAttributes, window_attributes: crate::window::WindowAttributes,
) -> Result<RootWindow, OsError> { ) -> Result<Box<dyn CoreWindow>, OsError> {
let window = Window::new(self, window_attributes)?; Ok(Box::new(Window::new(self, window_attributes)?))
Ok(RootWindow { window })
} }
fn create_custom_cursor( fn create_custom_cursor(

View file

@ -23,10 +23,11 @@ use crate::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, P
use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError}; use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError};
use crate::event::{Event, WindowEvent}; use crate::event::{Event, WindowEvent};
use crate::icon::Icon; use crate::icon::Icon;
use crate::monitor::MonitorHandle as CoreMonitorHandle;
use crate::platform::ios::{ScreenEdge, StatusBarStyle, ValidOrientations}; use crate::platform::ios::{ScreenEdge, StatusBarStyle, ValidOrientations};
use crate::window::{ use crate::window::{
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
WindowButtons, WindowId as RootWindowId, WindowLevel, WindowAttributes, WindowButtons, WindowId as CoreWindowId, WindowLevel,
}; };
declare_class!( declare_class!(
@ -49,7 +50,7 @@ declare_class!(
app_state::handle_nonuser_event( app_state::handle_nonuser_event(
mtm, mtm,
EventWrapper::StaticEvent(Event::WindowEvent { EventWrapper::StaticEvent(Event::WindowEvent {
window_id: RootWindowId(self.id()), window_id: CoreWindowId(self.id()),
event: WindowEvent::Focused(true), event: WindowEvent::Focused(true),
}), }),
); );
@ -62,7 +63,7 @@ declare_class!(
app_state::handle_nonuser_event( app_state::handle_nonuser_event(
mtm, mtm,
EventWrapper::StaticEvent(Event::WindowEvent { EventWrapper::StaticEvent(Event::WindowEvent {
window_id: RootWindowId(self.id()), window_id: CoreWindowId(self.id()),
event: WindowEvent::Focused(false), event: WindowEvent::Focused(false),
}), }),
); );
@ -522,7 +523,7 @@ impl Window {
width: screen_frame.size.width as f64, width: screen_frame.size.width as f64,
height: screen_frame.size.height as f64, height: screen_frame.size.height as f64,
}; };
let window_id = RootWindowId(window.id()); let window_id = CoreWindowId(window.id());
app_state::handle_nonuser_events( app_state::handle_nonuser_events(
mtm, mtm,
std::iter::once(EventWrapper::ScaleFactorChanged(app_state::ScaleFactorChanged { std::iter::once(EventWrapper::ScaleFactorChanged(app_state::ScaleFactorChanged {
@ -543,11 +544,6 @@ impl Window {
Ok(Window { inner: MainThreadBound::new(inner, mtm) }) Ok(Window { inner: MainThreadBound::new(inner, mtm) })
} }
pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&Inner) + Send + 'static) {
// For now, don't actually do queuing, since it may be less predictable
self.maybe_wait_on_main(f)
}
pub(crate) fn maybe_wait_on_main<R: Send>(&self, f: impl FnOnce(&Inner) -> R + Send) -> R { pub(crate) fn maybe_wait_on_main<R: Send>(&self, f: impl FnOnce(&Inner) -> R + Send) -> R {
self.inner.get_on_main(|inner| f(inner)) self.inner.get_on_main(|inner| f(inner))
} }
@ -573,6 +569,272 @@ impl Window {
} }
} }
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for Window {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
let raw = self.raw_display_handle_rwh_06()?;
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasWindowHandle for Window {
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
let raw = self.raw_window_handle_rwh_06()?;
unsafe { Ok(rwh_06::WindowHandle::borrow_raw(raw)) }
}
}
impl CoreWindow for Window {
fn id(&self) -> crate::window::WindowId {
self.maybe_wait_on_main(|delegate| crate::window::WindowId(delegate.id()))
}
fn scale_factor(&self) -> f64 {
self.maybe_wait_on_main(|delegate| delegate.scale_factor())
}
fn request_redraw(&self) {
self.maybe_wait_on_main(|delegate| delegate.request_redraw());
}
fn pre_present_notify(&self) {
self.maybe_wait_on_main(|delegate| delegate.pre_present_notify());
}
fn reset_dead_keys(&self) {
self.maybe_wait_on_main(|delegate| delegate.reset_dead_keys());
}
fn inner_position(
&self,
) -> Result<dpi::PhysicalPosition<i32>, crate::error::NotSupportedError> {
self.maybe_wait_on_main(|delegate| delegate.inner_position())
}
fn outer_position(
&self,
) -> Result<dpi::PhysicalPosition<i32>, crate::error::NotSupportedError> {
self.maybe_wait_on_main(|delegate| delegate.outer_position())
}
fn set_outer_position(&self, position: Position) {
self.maybe_wait_on_main(|delegate| delegate.set_outer_position(position));
}
fn inner_size(&self) -> dpi::PhysicalSize<u32> {
self.maybe_wait_on_main(|delegate| delegate.inner_size())
}
fn request_inner_size(&self, size: Size) -> Option<dpi::PhysicalSize<u32>> {
self.maybe_wait_on_main(|delegate| delegate.request_inner_size(size))
}
fn outer_size(&self) -> dpi::PhysicalSize<u32> {
self.maybe_wait_on_main(|delegate| delegate.outer_size())
}
fn set_min_inner_size(&self, min_size: Option<Size>) {
self.maybe_wait_on_main(|delegate| delegate.set_min_inner_size(min_size))
}
fn set_max_inner_size(&self, max_size: Option<Size>) {
self.maybe_wait_on_main(|delegate| delegate.set_max_inner_size(max_size));
}
fn resize_increments(&self) -> Option<dpi::PhysicalSize<u32>> {
self.maybe_wait_on_main(|delegate| delegate.resize_increments())
}
fn set_resize_increments(&self, increments: Option<Size>) {
self.maybe_wait_on_main(|delegate| delegate.set_resize_increments(increments));
}
fn set_title(&self, title: &str) {
self.maybe_wait_on_main(|delegate| delegate.set_title(title));
}
fn set_transparent(&self, transparent: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_transparent(transparent));
}
fn set_blur(&self, blur: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_blur(blur));
}
fn set_visible(&self, visible: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_visible(visible));
}
fn is_visible(&self) -> Option<bool> {
self.maybe_wait_on_main(|delegate| delegate.is_visible())
}
fn set_resizable(&self, resizable: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_resizable(resizable))
}
fn is_resizable(&self) -> bool {
self.maybe_wait_on_main(|delegate| delegate.is_resizable())
}
fn set_enabled_buttons(&self, buttons: WindowButtons) {
self.maybe_wait_on_main(|delegate| delegate.set_enabled_buttons(buttons))
}
fn enabled_buttons(&self) -> WindowButtons {
self.maybe_wait_on_main(|delegate| delegate.enabled_buttons())
}
fn set_minimized(&self, minimized: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_minimized(minimized));
}
fn is_minimized(&self) -> Option<bool> {
self.maybe_wait_on_main(|delegate| delegate.is_minimized())
}
fn set_maximized(&self, maximized: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_maximized(maximized));
}
fn is_maximized(&self) -> bool {
self.maybe_wait_on_main(|delegate| delegate.is_maximized())
}
fn set_fullscreen(&self, fullscreen: Option<crate::window::Fullscreen>) {
self.maybe_wait_on_main(|delegate| delegate.set_fullscreen(fullscreen.map(Into::into)))
}
fn fullscreen(&self) -> Option<crate::window::Fullscreen> {
self.maybe_wait_on_main(|delegate| delegate.fullscreen().map(Into::into))
}
fn set_decorations(&self, decorations: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_decorations(decorations));
}
fn is_decorated(&self) -> bool {
self.maybe_wait_on_main(|delegate| delegate.is_decorated())
}
fn set_window_level(&self, level: WindowLevel) {
self.maybe_wait_on_main(|delegate| delegate.set_window_level(level));
}
fn set_window_icon(&self, window_icon: Option<Icon>) {
self.maybe_wait_on_main(|delegate| delegate.set_window_icon(window_icon));
}
fn set_ime_cursor_area(&self, position: Position, size: Size) {
self.maybe_wait_on_main(|delegate| delegate.set_ime_cursor_area(position, size));
}
fn set_ime_allowed(&self, allowed: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_ime_allowed(allowed));
}
fn set_ime_purpose(&self, purpose: ImePurpose) {
self.maybe_wait_on_main(|delegate| delegate.set_ime_purpose(purpose));
}
fn focus_window(&self) {
self.maybe_wait_on_main(|delegate| delegate.focus_window());
}
fn has_focus(&self) -> bool {
self.maybe_wait_on_main(|delegate| delegate.has_focus())
}
fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
self.maybe_wait_on_main(|delegate| delegate.request_user_attention(request_type));
}
fn set_theme(&self, theme: Option<Theme>) {
self.maybe_wait_on_main(|delegate| delegate.set_theme(theme));
}
fn theme(&self) -> Option<Theme> {
self.maybe_wait_on_main(|delegate| delegate.theme())
}
fn set_content_protected(&self, protected: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_content_protected(protected));
}
fn title(&self) -> String {
self.maybe_wait_on_main(|delegate| delegate.title())
}
fn set_cursor(&self, cursor: Cursor) {
self.maybe_wait_on_main(|delegate| delegate.set_cursor(cursor));
}
fn set_cursor_position(&self, position: Position) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_position(position))
}
fn set_cursor_grab(
&self,
mode: crate::window::CursorGrabMode,
) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_grab(mode))
}
fn set_cursor_visible(&self, visible: bool) {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_visible(visible))
}
fn drag_window(&self) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.drag_window())
}
fn drag_resize_window(
&self,
direction: crate::window::ResizeDirection,
) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.drag_resize_window(direction))
}
fn show_window_menu(&self, position: Position) {
self.maybe_wait_on_main(|delegate| delegate.show_window_menu(position))
}
fn set_cursor_hittest(&self, hittest: bool) -> Result<(), crate::error::ExternalError> {
self.maybe_wait_on_main(|delegate| delegate.set_cursor_hittest(hittest))
}
fn current_monitor(&self) -> Option<CoreMonitorHandle> {
self.maybe_wait_on_main(|delegate| {
delegate.current_monitor().map(|inner| CoreMonitorHandle { inner })
})
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
self.maybe_wait_on_main(|delegate| {
Box::new(
delegate.available_monitors().into_iter().map(|inner| CoreMonitorHandle { inner }),
)
})
}
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
self.maybe_wait_on_main(|delegate| {
delegate.primary_monitor().map(|inner| CoreMonitorHandle { inner })
})
}
#[cfg(feature = "rwh_06")]
fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
self
}
#[cfg(feature = "rwh_06")]
fn rwh_06_window_handle(&self) -> &dyn rwh_06::HasWindowHandle {
self
}
}
// WindowExtIOS // WindowExtIOS
impl Inner { impl Inner {
pub fn set_scale_factor(&self, scale_factor: f64) { pub fn set_scale_factor(&self, scale_factor: f64) {

View file

@ -3,7 +3,6 @@
#[cfg(all(not(x11_platform), not(wayland_platform)))] #[cfg(all(not(x11_platform), not(wayland_platform)))]
compile_error!("Please select a feature to build for unix: `x11`, `wayland`"); compile_error!("Please select a feature to build for unix: `x11`, `wayland`");
use std::collections::VecDeque;
use std::num::{NonZeroU16, NonZeroU32}; use std::num::{NonZeroU16, NonZeroU32};
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
use std::sync::Arc; use std::sync::Arc;
@ -19,22 +18,19 @@ pub(crate) use self::common::xkb::{physicalkey_to_scancode, scancode_to_physical
use self::x11::{X11Error, XConnection, XError, XNotSupported}; use self::x11::{X11Error, XConnection, XError, XNotSupported};
use crate::application::ApplicationHandler; use crate::application::ApplicationHandler;
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource; pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size}; #[cfg(x11_platform)]
use crate::error::{EventLoopError, ExternalError, NotSupportedError}; use crate::dpi::Size;
use crate::event_loop::{ActiveEventLoop, AsyncRequestSerial}; use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::icon::Icon; use crate::error::EventLoopError;
use crate::event_loop::ActiveEventLoop;
pub(crate) use crate::icon::RgbaIcon as PlatformIcon; pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
use crate::keyboard::Key; use crate::keyboard::Key;
use crate::platform::pump_events::PumpStatus; use crate::platform::pump_events::PumpStatus;
#[cfg(x11_platform)] #[cfg(x11_platform)]
use crate::platform::x11::{WindowType as XWindowType, XlibErrorHook}; use crate::platform::x11::{WindowType as XWindowType, XlibErrorHook};
pub(crate) use crate::platform_impl::Fullscreen;
#[cfg(x11_platform)] #[cfg(x11_platform)]
use crate::utils::Lazy; use crate::utils::Lazy;
use crate::window::{ use crate::window::ActivationToken;
ActivationToken, Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType,
WindowButtons, WindowLevel,
};
pub(crate) mod common; pub(crate) mod common;
#[cfg(wayland_platform)] #[cfg(wayland_platform)]
@ -137,13 +133,6 @@ impl fmt::Display for OsError {
} }
} }
pub(crate) enum Window {
#[cfg(x11_platform)]
X(x11::Window),
#[cfg(wayland_platform)]
Wayland(wayland::Window),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId(u64); pub struct WindowId(u64);
@ -297,316 +286,6 @@ impl VideoModeHandle {
} }
} }
impl Window {
pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&Self) + Send + 'static) {
f(self)
}
pub(crate) fn maybe_wait_on_main<R: Send>(&self, f: impl FnOnce(&Self) -> R + Send) -> R {
f(self)
}
#[inline]
pub fn id(&self) -> WindowId {
x11_or_wayland!(match self; Window(w) => w.id())
}
#[inline]
pub fn set_title(&self, title: &str) {
x11_or_wayland!(match self; Window(w) => w.set_title(title));
}
#[inline]
pub fn set_transparent(&self, transparent: bool) {
x11_or_wayland!(match self; Window(w) => w.set_transparent(transparent));
}
#[inline]
pub fn set_blur(&self, blur: bool) {
x11_or_wayland!(match self; Window(w) => w.set_blur(blur));
}
#[inline]
pub fn set_visible(&self, visible: bool) {
x11_or_wayland!(match self; Window(w) => w.set_visible(visible))
}
#[inline]
pub fn is_visible(&self) -> Option<bool> {
x11_or_wayland!(match self; Window(w) => w.is_visible())
}
#[inline]
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
x11_or_wayland!(match self; Window(w) => w.outer_position())
}
#[inline]
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
x11_or_wayland!(match self; Window(w) => w.inner_position())
}
#[inline]
pub fn set_outer_position(&self, position: Position) {
x11_or_wayland!(match self; Window(w) => w.set_outer_position(position))
}
#[inline]
pub fn inner_size(&self) -> PhysicalSize<u32> {
x11_or_wayland!(match self; Window(w) => w.inner_size())
}
#[inline]
pub fn outer_size(&self) -> PhysicalSize<u32> {
x11_or_wayland!(match self; Window(w) => w.outer_size())
}
#[inline]
pub fn request_inner_size(&self, size: Size) -> Option<PhysicalSize<u32>> {
x11_or_wayland!(match self; Window(w) => w.request_inner_size(size))
}
#[inline]
pub(crate) fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError> {
x11_or_wayland!(match self; Window(w) => w.request_activation_token())
}
#[inline]
pub fn set_min_inner_size(&self, dimensions: Option<Size>) {
x11_or_wayland!(match self; Window(w) => w.set_min_inner_size(dimensions))
}
#[inline]
pub fn set_max_inner_size(&self, dimensions: Option<Size>) {
x11_or_wayland!(match self; Window(w) => w.set_max_inner_size(dimensions))
}
#[inline]
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
x11_or_wayland!(match self; Window(w) => w.resize_increments())
}
#[inline]
pub fn set_resize_increments(&self, increments: Option<Size>) {
x11_or_wayland!(match self; Window(w) => w.set_resize_increments(increments))
}
#[inline]
pub fn set_resizable(&self, resizable: bool) {
x11_or_wayland!(match self; Window(w) => w.set_resizable(resizable))
}
#[inline]
pub fn is_resizable(&self) -> bool {
x11_or_wayland!(match self; Window(w) => w.is_resizable())
}
#[inline]
pub fn set_enabled_buttons(&self, buttons: WindowButtons) {
x11_or_wayland!(match self; Window(w) => w.set_enabled_buttons(buttons))
}
#[inline]
pub fn enabled_buttons(&self) -> WindowButtons {
x11_or_wayland!(match self; Window(w) => w.enabled_buttons())
}
#[inline]
pub fn set_cursor(&self, cursor: Cursor) {
x11_or_wayland!(match self; Window(w) => w.set_cursor(cursor))
}
#[inline]
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
x11_or_wayland!(match self; Window(window) => window.set_cursor_grab(mode))
}
#[inline]
pub fn set_cursor_visible(&self, visible: bool) {
x11_or_wayland!(match self; Window(window) => window.set_cursor_visible(visible))
}
#[inline]
pub fn drag_window(&self) -> Result<(), ExternalError> {
x11_or_wayland!(match self; Window(window) => window.drag_window())
}
#[inline]
pub fn drag_resize_window(&self, direction: ResizeDirection) -> Result<(), ExternalError> {
x11_or_wayland!(match self; Window(window) => window.drag_resize_window(direction))
}
#[inline]
pub fn show_window_menu(&self, position: Position) {
x11_or_wayland!(match self; Window(w) => w.show_window_menu(position))
}
#[inline]
pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
x11_or_wayland!(match self; Window(w) => w.set_cursor_hittest(hittest))
}
#[inline]
pub fn scale_factor(&self) -> f64 {
x11_or_wayland!(match self; Window(w) => w.scale_factor())
}
#[inline]
pub fn set_cursor_position(&self, position: Position) -> Result<(), ExternalError> {
x11_or_wayland!(match self; Window(w) => w.set_cursor_position(position))
}
#[inline]
pub fn set_maximized(&self, maximized: bool) {
x11_or_wayland!(match self; Window(w) => w.set_maximized(maximized))
}
#[inline]
pub fn is_maximized(&self) -> bool {
x11_or_wayland!(match self; Window(w) => w.is_maximized())
}
#[inline]
pub fn set_minimized(&self, minimized: bool) {
x11_or_wayland!(match self; Window(w) => w.set_minimized(minimized))
}
#[inline]
pub fn is_minimized(&self) -> Option<bool> {
x11_or_wayland!(match self; Window(w) => w.is_minimized())
}
#[inline]
pub(crate) fn fullscreen(&self) -> Option<Fullscreen> {
x11_or_wayland!(match self; Window(w) => w.fullscreen())
}
#[inline]
pub(crate) fn set_fullscreen(&self, monitor: Option<Fullscreen>) {
x11_or_wayland!(match self; Window(w) => w.set_fullscreen(monitor))
}
#[inline]
pub fn set_decorations(&self, decorations: bool) {
x11_or_wayland!(match self; Window(w) => w.set_decorations(decorations))
}
#[inline]
pub fn is_decorated(&self) -> bool {
x11_or_wayland!(match self; Window(w) => w.is_decorated())
}
#[inline]
pub fn set_window_level(&self, level: WindowLevel) {
x11_or_wayland!(match self; Window(w) => w.set_window_level(level))
}
#[inline]
pub fn set_window_icon(&self, window_icon: Option<Icon>) {
x11_or_wayland!(match self; Window(w) => w.set_window_icon(window_icon.map(|icon| icon.inner)))
}
#[inline]
pub fn set_ime_cursor_area(&self, position: Position, size: Size) {
x11_or_wayland!(match self; Window(w) => w.set_ime_cursor_area(position, size))
}
#[inline]
pub fn reset_dead_keys(&self) {
common::xkb::reset_dead_keys()
}
#[inline]
pub fn set_ime_allowed(&self, allowed: bool) {
x11_or_wayland!(match self; Window(w) => w.set_ime_allowed(allowed))
}
#[inline]
pub fn set_ime_purpose(&self, purpose: ImePurpose) {
x11_or_wayland!(match self; Window(w) => w.set_ime_purpose(purpose))
}
#[inline]
pub fn focus_window(&self) {
x11_or_wayland!(match self; Window(w) => w.focus_window())
}
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
x11_or_wayland!(match self; Window(w) => w.request_user_attention(request_type))
}
#[inline]
pub fn request_redraw(&self) {
x11_or_wayland!(match self; Window(w) => w.request_redraw())
}
#[inline]
pub fn pre_present_notify(&self) {
x11_or_wayland!(match self; Window(w) => w.pre_present_notify())
}
#[inline]
pub fn current_monitor(&self) -> Option<MonitorHandle> {
Some(x11_or_wayland!(match self; Window(w) => w.current_monitor()?; as MonitorHandle))
}
#[inline]
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
match self {
#[cfg(x11_platform)]
Window::X(ref window) => {
window.available_monitors().into_iter().map(MonitorHandle::X).collect()
},
#[cfg(wayland_platform)]
Window::Wayland(ref window) => {
window.available_monitors().into_iter().map(MonitorHandle::Wayland).collect()
},
}
}
#[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
Some(x11_or_wayland!(match self; Window(w) => w.primary_monitor()?; as MonitorHandle))
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> {
x11_or_wayland!(match self; Window(window) => window.raw_window_handle_rwh_06())
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
x11_or_wayland!(match self; Window(window) => window.raw_display_handle_rwh_06())
}
#[inline]
pub fn set_theme(&self, theme: Option<Theme>) {
x11_or_wayland!(match self; Window(window) => window.set_theme(theme))
}
#[inline]
pub fn theme(&self) -> Option<Theme> {
x11_or_wayland!(match self; Window(window) => window.theme())
}
pub fn set_content_protected(&self, protected: bool) {
x11_or_wayland!(match self; Window(window) => window.set_content_protected(protected))
}
#[inline]
pub fn has_focus(&self) -> bool {
x11_or_wayland!(match self; Window(window) => window.has_focus())
}
pub fn title(&self) -> String {
x11_or_wayland!(match self; Window(window) => window.title())
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct KeyEventExtra { pub struct KeyEventExtra {
pub text_with_all_modifiers: Option<SmolStr>, pub text_with_all_modifiers: Option<SmolStr>,

View file

@ -628,10 +628,9 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window( fn create_window(
&self, &self,
window_attributes: crate::window::WindowAttributes, window_attributes: crate::window::WindowAttributes,
) -> Result<crate::window::Window, RootOsError> { ) -> Result<Box<dyn crate::window::Window>, RootOsError> {
let window = crate::platform_impl::wayland::Window::new(self, window_attributes)?; let window = crate::platform_impl::wayland::Window::new(self, window_attributes)?;
let window = crate::platform_impl::Window::Wayland(window); Ok(Box::new(window))
Ok(crate::window::Window { window })
} }
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> { fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {

View file

@ -21,12 +21,12 @@ use crate::dpi::{LogicalSize, PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError}; use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError};
use crate::event::{Ime, WindowEvent}; use crate::event::{Ime, WindowEvent};
use crate::event_loop::AsyncRequestSerial; use crate::event_loop::AsyncRequestSerial;
use crate::platform_impl::{ use crate::monitor::MonitorHandle as CoreMonitorHandle;
Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformIcon, use crate::platform_impl::{Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError};
};
use crate::window::{ use crate::window::{
Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Cursor, CursorGrabMode, Fullscreen as CoreFullscreen, ImePurpose, ResizeDirection, Theme,
WindowAttributes, WindowButtons, WindowLevel, UserAttentionType, Window as CoreWindow, WindowAttributes, WindowButtons,
WindowId as CoreWindowId, WindowLevel,
}; };
pub(crate) mod state; pub(crate) mod state;
@ -223,51 +223,65 @@ impl Window {
} }
impl Window { impl Window {
#[inline] pub fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError> {
pub fn id(&self) -> WindowId { let xdg_activation = match self.xdg_activation.as_ref() {
self.window_id Some(xdg_activation) => xdg_activation,
None => return Err(NotSupportedError::new()),
};
let serial = AsyncRequestSerial::get();
let data = XdgActivationTokenData::Obtain((self.window_id, serial));
let xdg_activation_token = xdg_activation.get_activation_token(&self.queue_handle, data);
xdg_activation_token.set_surface(self.surface());
xdg_activation_token.commit();
Ok(serial)
} }
#[inline] #[inline]
pub fn set_title(&self, title: impl ToString) { pub fn surface(&self) -> &WlSurface {
let new_title = title.to_string(); self.window.wl_surface()
self.window_state.lock().unwrap().set_title(new_title); }
}
impl Drop for Window {
fn drop(&mut self) {
self.window_requests.closed.store(true, Ordering::Relaxed);
self.event_loop_awakener.ping();
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasWindowHandle for Window {
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
let raw = rwh_06::WaylandWindowHandle::new({
let ptr = self.window.wl_surface().id().as_ptr();
std::ptr::NonNull::new(ptr as *mut _).expect("wl_surface will never be null")
});
unsafe { Ok(rwh_06::WindowHandle::borrow_raw(raw.into())) }
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for Window {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
let raw = rwh_06::WaylandDisplayHandle::new({
let ptr = self.display.id().as_ptr();
std::ptr::NonNull::new(ptr as *mut _).expect("wl_proxy should never be null")
});
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw.into())) }
}
}
impl CoreWindow for Window {
fn id(&self) -> CoreWindowId {
CoreWindowId(self.window_id)
} }
#[inline] fn request_redraw(&self) {
pub fn set_visible(&self, _visible: bool) {
// Not possible on Wayland.
}
#[inline]
pub fn is_visible(&self) -> Option<bool> {
None
}
#[inline]
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
Err(NotSupportedError::new())
}
#[inline]
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
Err(NotSupportedError::new())
}
#[inline]
pub fn set_outer_position(&self, _: Position) {
// Not possible on Wayland.
}
#[inline]
pub fn inner_size(&self) -> PhysicalSize<u32> {
let window_state = self.window_state.lock().unwrap();
let scale_factor = window_state.scale_factor();
super::logical_to_physical_rounded(window_state.inner_size(), scale_factor)
}
#[inline]
pub fn request_redraw(&self) {
// NOTE: try to not wake up the loop when the event was already scheduled and not yet // NOTE: try to not wake up the loop when the event was already scheduled and not yet
// processed by the loop, because if at this point the value was `true` it could only // processed by the loop, because if at this point the value was `true` it could only
// mean that the loop still haven't dispatched the value to the client and will do // mean that the loop still haven't dispatched the value to the client and will do
@ -283,28 +297,50 @@ impl Window {
} }
#[inline] #[inline]
pub fn pre_present_notify(&self) { fn title(&self) -> String {
self.window_state.lock().unwrap().title().to_owned()
}
fn pre_present_notify(&self) {
self.window_state.lock().unwrap().request_frame_callback(); self.window_state.lock().unwrap().request_frame_callback();
} }
#[inline] fn reset_dead_keys(&self) {
pub fn outer_size(&self) -> PhysicalSize<u32> { crate::platform_impl::common::xkb::reset_dead_keys()
let window_state = self.window_state.lock().unwrap();
let scale_factor = window_state.scale_factor();
super::logical_to_physical_rounded(window_state.outer_size(), scale_factor)
} }
#[inline] fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
pub fn request_inner_size(&self, size: Size) -> Option<PhysicalSize<u32>> { Err(NotSupportedError::new())
}
fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
Err(NotSupportedError::new())
}
fn set_outer_position(&self, _position: Position) {
// Not possible.
}
fn inner_size(&self) -> PhysicalSize<u32> {
let window_state = self.window_state.lock().unwrap();
let scale_factor = window_state.scale_factor();
super::logical_to_physical_rounded(window_state.inner_size(), scale_factor)
}
fn request_inner_size(&self, size: Size) -> Option<PhysicalSize<u32>> {
let mut window_state = self.window_state.lock().unwrap(); let mut window_state = self.window_state.lock().unwrap();
let new_size = window_state.request_inner_size(size); let new_size = window_state.request_inner_size(size);
self.request_redraw(); self.request_redraw();
Some(new_size) Some(new_size)
} }
/// Set the minimum inner size for the window. fn outer_size(&self) -> PhysicalSize<u32> {
#[inline] let window_state = self.window_state.lock().unwrap();
pub fn set_min_inner_size(&self, min_size: Option<Size>) { let scale_factor = window_state.scale_factor();
super::logical_to_physical_rounded(window_state.outer_size(), scale_factor)
}
fn set_min_inner_size(&self, min_size: Option<Size>) {
let scale_factor = self.scale_factor(); let scale_factor = self.scale_factor();
let min_size = min_size.map(|size| size.to_logical(scale_factor)); let min_size = min_size.map(|size| size.to_logical(scale_factor));
self.window_state.lock().unwrap().set_min_inner_size(min_size); self.window_state.lock().unwrap().set_min_inner_size(min_size);
@ -314,7 +350,7 @@ impl Window {
/// Set the maximum inner size for the window. /// Set the maximum inner size for the window.
#[inline] #[inline]
pub fn set_max_inner_size(&self, max_size: Option<Size>) { fn set_max_inner_size(&self, max_size: Option<Size>) {
let scale_factor = self.scale_factor(); let scale_factor = self.scale_factor();
let max_size = max_size.map(|size| size.to_logical(scale_factor)); let max_size = max_size.map(|size| size.to_logical(scale_factor));
self.window_state.lock().unwrap().set_max_inner_size(max_size); self.window_state.lock().unwrap().set_max_inner_size(max_size);
@ -322,96 +358,53 @@ impl Window {
self.request_redraw(); self.request_redraw();
} }
#[inline] fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
None None
} }
#[inline] fn set_resize_increments(&self, _increments: Option<Size>) {
pub fn set_resize_increments(&self, _increments: Option<Size>) {
warn!("`set_resize_increments` is not implemented for Wayland"); warn!("`set_resize_increments` is not implemented for Wayland");
} }
fn set_title(&self, title: &str) {
let new_title = title.to_string();
self.window_state.lock().unwrap().set_title(new_title);
}
#[inline] #[inline]
pub fn set_transparent(&self, transparent: bool) { fn set_transparent(&self, transparent: bool) {
self.window_state.lock().unwrap().set_transparent(transparent); self.window_state.lock().unwrap().set_transparent(transparent);
} }
#[inline] fn set_visible(&self, _visible: bool) {
pub fn has_focus(&self) -> bool { // Not possible on Wayland.
self.window_state.lock().unwrap().has_focus()
} }
#[inline] fn is_visible(&self) -> Option<bool> {
pub fn is_minimized(&self) -> Option<bool> {
// XXX clients don't know whether they are minimized or not.
None None
} }
#[inline] fn set_resizable(&self, resizable: bool) {
pub fn show_window_menu(&self, position: Position) {
let scale_factor = self.scale_factor();
let position = position.to_logical(scale_factor);
self.window_state.lock().unwrap().show_window_menu(position);
}
#[inline]
pub fn drag_resize_window(&self, direction: ResizeDirection) -> Result<(), ExternalError> {
self.window_state.lock().unwrap().drag_resize_window(direction)
}
#[inline]
pub fn set_resizable(&self, resizable: bool) {
if self.window_state.lock().unwrap().set_resizable(resizable) { if self.window_state.lock().unwrap().set_resizable(resizable) {
// NOTE: Requires commit to be applied. // NOTE: Requires commit to be applied.
self.request_redraw(); self.request_redraw();
} }
} }
#[inline] fn is_resizable(&self) -> bool {
pub fn is_resizable(&self) -> bool {
self.window_state.lock().unwrap().resizable() self.window_state.lock().unwrap().resizable()
} }
#[inline] fn set_enabled_buttons(&self, _buttons: WindowButtons) {
pub fn set_enabled_buttons(&self, _buttons: WindowButtons) {
// TODO(kchibisov) v5 of the xdg_shell allows that. // TODO(kchibisov) v5 of the xdg_shell allows that.
} }
#[inline] fn enabled_buttons(&self) -> WindowButtons {
pub fn enabled_buttons(&self) -> WindowButtons {
// TODO(kchibisov) v5 of the xdg_shell allows that. // TODO(kchibisov) v5 of the xdg_shell allows that.
WindowButtons::all() WindowButtons::all()
} }
#[inline] fn set_minimized(&self, minimized: bool) {
pub fn scale_factor(&self) -> f64 {
self.window_state.lock().unwrap().scale_factor()
}
#[inline]
pub fn set_blur(&self, blur: bool) {
self.window_state.lock().unwrap().set_blur(blur);
}
#[inline]
pub fn set_decorations(&self, decorate: bool) {
self.window_state.lock().unwrap().set_decorate(decorate)
}
#[inline]
pub fn is_decorated(&self) -> bool {
self.window_state.lock().unwrap().is_decorated()
}
#[inline]
pub fn set_window_level(&self, _level: WindowLevel) {}
#[inline]
pub(crate) fn set_window_icon(&self, _window_icon: Option<PlatformIcon>) {}
#[inline]
pub fn set_minimized(&self, minimized: bool) {
// You can't unminimize the window on Wayland. // You can't unminimize the window on Wayland.
if !minimized { if !minimized {
warn!("Unminimizing is ignored on Wayland."); warn!("Unminimizing is ignored on Wayland.");
@ -421,8 +414,20 @@ impl Window {
self.window.set_minimized(); self.window.set_minimized();
} }
#[inline] fn is_minimized(&self) -> Option<bool> {
pub fn is_maximized(&self) -> bool { // XXX clients don't know whether they are minimized or not.
None
}
fn set_maximized(&self, maximized: bool) {
if maximized {
self.window.set_maximized()
} else {
self.window.unset_maximized()
}
}
fn is_maximized(&self) -> bool {
self.window_state self.window_state
.lock() .lock()
.unwrap() .unwrap()
@ -432,43 +437,14 @@ impl Window {
.unwrap_or_default() .unwrap_or_default()
} }
#[inline] fn set_fullscreen(&self, fullscreen: Option<CoreFullscreen>) {
pub fn set_maximized(&self, maximized: bool) {
if maximized {
self.window.set_maximized()
} else {
self.window.unset_maximized()
}
}
#[inline]
pub(crate) fn fullscreen(&self) -> Option<Fullscreen> {
let is_fullscreen = self
.window_state
.lock()
.unwrap()
.last_configure
.as_ref()
.map(|last_configure| last_configure.is_fullscreen())
.unwrap_or_default();
if is_fullscreen {
let current_monitor = self.current_monitor().map(PlatformMonitorHandle::Wayland);
Some(Fullscreen::Borderless(current_monitor))
} else {
None
}
}
#[inline]
pub(crate) fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
match fullscreen { match fullscreen {
Some(Fullscreen::Exclusive(_)) => { Some(CoreFullscreen::Exclusive(_)) => {
warn!("`Fullscreen::Exclusive` is ignored on Wayland"); warn!("`Fullscreen::Exclusive` is ignored on Wayland");
}, },
#[cfg_attr(not(x11_platform), allow(clippy::bind_instead_of_map))] #[cfg_attr(not(x11_platform), allow(clippy::bind_instead_of_map))]
Some(Fullscreen::Borderless(monitor)) => { Some(CoreFullscreen::Borderless(monitor)) => {
let output = monitor.and_then(|monitor| match monitor { let output = monitor.and_then(|monitor| match monitor.inner {
PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy), PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy),
#[cfg(x11_platform)] #[cfg(x11_platform)]
PlatformMonitorHandle::X(_) => None, PlatformMonitorHandle::X(_) => None,
@ -480,22 +456,82 @@ impl Window {
} }
} }
#[inline] fn fullscreen(&self) -> Option<CoreFullscreen> {
pub fn set_cursor(&self, cursor: Cursor) { let is_fullscreen = self
let window_state = &mut self.window_state.lock().unwrap(); .window_state
.lock()
.unwrap()
.last_configure
.as_ref()
.map(|last_configure| last_configure.is_fullscreen())
.unwrap_or_default();
match cursor { if is_fullscreen {
Cursor::Icon(icon) => window_state.set_cursor(icon), let current_monitor = self.current_monitor();
Cursor::Custom(cursor) => window_state.set_custom_cursor(cursor), Some(CoreFullscreen::Borderless(current_monitor))
} else {
None
} }
} }
#[inline] #[inline]
pub fn set_cursor_visible(&self, visible: bool) { fn scale_factor(&self) -> f64 {
self.window_state.lock().unwrap().set_cursor_visible(visible); self.window_state.lock().unwrap().scale_factor()
} }
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) { #[inline]
fn set_blur(&self, blur: bool) {
self.window_state.lock().unwrap().set_blur(blur);
}
#[inline]
fn set_decorations(&self, decorate: bool) {
self.window_state.lock().unwrap().set_decorate(decorate)
}
#[inline]
fn is_decorated(&self) -> bool {
self.window_state.lock().unwrap().is_decorated()
}
fn set_window_level(&self, _level: WindowLevel) {}
fn set_window_icon(&self, _window_icon: Option<crate::window::Icon>) {}
#[inline]
fn set_ime_cursor_area(&self, position: Position, size: Size) {
let window_state = self.window_state.lock().unwrap();
if window_state.ime_allowed() {
let scale_factor = window_state.scale_factor();
let position = position.to_logical(scale_factor);
let size = size.to_logical(scale_factor);
window_state.set_ime_cursor_area(position, size);
}
}
#[inline]
fn set_ime_allowed(&self, allowed: bool) {
let mut window_state = self.window_state.lock().unwrap();
if window_state.ime_allowed() != allowed && window_state.set_ime_allowed(allowed) {
let event = WindowEvent::Ime(if allowed { Ime::Enabled } else { Ime::Disabled });
self.window_events_sink.lock().unwrap().push_window_event(event, self.window_id);
self.event_loop_awakener.ping();
}
}
#[inline]
fn set_ime_purpose(&self, purpose: ImePurpose) {
self.window_state.lock().unwrap().set_ime_purpose(purpose);
}
fn focus_window(&self) {}
fn has_focus(&self) -> bool {
self.window_state.lock().unwrap().has_focus()
}
fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
let xdg_activation = match self.xdg_activation.as_ref() { let xdg_activation = match self.xdg_activation.as_ref() {
Some(xdg_activation) => xdg_activation, Some(xdg_activation) => xdg_activation,
None => { None => {
@ -521,29 +557,26 @@ impl Window {
xdg_activation_token.commit(); xdg_activation_token.commit();
} }
pub fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError> { fn set_theme(&self, theme: Option<Theme>) {
let xdg_activation = match self.xdg_activation.as_ref() { self.window_state.lock().unwrap().set_theme(theme)
Some(xdg_activation) => xdg_activation,
None => return Err(NotSupportedError::new()),
};
let serial = AsyncRequestSerial::get();
let data = XdgActivationTokenData::Obtain((self.window_id, serial));
let xdg_activation_token = xdg_activation.get_activation_token(&self.queue_handle, data);
xdg_activation_token.set_surface(self.surface());
xdg_activation_token.commit();
Ok(serial)
} }
#[inline] fn theme(&self) -> Option<Theme> {
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> { self.window_state.lock().unwrap().theme()
self.window_state.lock().unwrap().set_cursor_grab(mode)
} }
#[inline] fn set_content_protected(&self, _protected: bool) {}
pub fn set_cursor_position(&self, position: Position) -> Result<(), ExternalError> {
fn set_cursor(&self, cursor: Cursor) {
let window_state = &mut self.window_state.lock().unwrap();
match cursor {
Cursor::Icon(icon) => window_state.set_cursor(icon),
Cursor::Custom(cursor) => window_state.set_custom_cursor(cursor),
}
}
fn set_cursor_position(&self, position: Position) -> Result<(), ExternalError> {
let scale_factor = self.scale_factor(); let scale_factor = self.scale_factor();
let position = position.to_logical(scale_factor); let position = position.to_logical(scale_factor);
self.window_state self.window_state
@ -554,13 +587,29 @@ impl Window {
.map(|_| self.request_redraw()) .map(|_| self.request_redraw())
} }
#[inline] fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
pub fn drag_window(&self) -> Result<(), ExternalError> { self.window_state.lock().unwrap().set_cursor_grab(mode)
}
fn set_cursor_visible(&self, visible: bool) {
self.window_state.lock().unwrap().set_cursor_visible(visible);
}
fn drag_window(&self) -> Result<(), ExternalError> {
self.window_state.lock().unwrap().drag_window() self.window_state.lock().unwrap().drag_window()
} }
#[inline] fn drag_resize_window(&self, direction: ResizeDirection) -> Result<(), ExternalError> {
pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> { self.window_state.lock().unwrap().drag_resize_window(direction)
}
fn show_window_menu(&self, position: Position) {
let scale_factor = self.scale_factor();
let position = position.to_logical(scale_factor);
self.window_state.lock().unwrap().show_window_menu(position);
}
fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
let surface = self.window.wl_surface(); let surface = self.window.wl_surface();
if hittest { if hittest {
@ -576,102 +625,42 @@ impl Window {
} }
} }
#[inline] fn current_monitor(&self) -> Option<CoreMonitorHandle> {
pub fn set_ime_cursor_area(&self, position: Position, size: Size) {
let window_state = self.window_state.lock().unwrap();
if window_state.ime_allowed() {
let scale_factor = window_state.scale_factor();
let position = position.to_logical(scale_factor);
let size = size.to_logical(scale_factor);
window_state.set_ime_cursor_area(position, size);
}
}
#[inline]
pub fn set_ime_allowed(&self, allowed: bool) {
let mut window_state = self.window_state.lock().unwrap();
if window_state.ime_allowed() != allowed && window_state.set_ime_allowed(allowed) {
let event = WindowEvent::Ime(if allowed { Ime::Enabled } else { Ime::Disabled });
self.window_events_sink.lock().unwrap().push_window_event(event, self.window_id);
self.event_loop_awakener.ping();
}
}
#[inline]
pub fn set_ime_purpose(&self, purpose: ImePurpose) {
self.window_state.lock().unwrap().set_ime_purpose(purpose);
}
#[inline]
pub fn focus_window(&self) {}
#[inline]
pub fn surface(&self) -> &WlSurface {
self.window.wl_surface()
}
#[inline]
pub fn current_monitor(&self) -> Option<MonitorHandle> {
let data = self.window.wl_surface().data::<SurfaceData>()?; let data = self.window.wl_surface().data::<SurfaceData>()?;
data.outputs().next().map(MonitorHandle::new) data.outputs()
.next()
.map(MonitorHandle::new)
.map(crate::platform_impl::MonitorHandle::Wayland)
.map(|inner| CoreMonitorHandle { inner })
} }
#[inline] fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
pub fn available_monitors(&self) -> Vec<MonitorHandle> { Box::new(
self.monitors.lock().unwrap().clone() self.monitors
.lock()
.unwrap()
.clone()
.into_iter()
.map(crate::platform_impl::MonitorHandle::Wayland)
.map(|inner| CoreMonitorHandle { inner }),
)
} }
#[inline] fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
pub fn primary_monitor(&self) -> Option<MonitorHandle> { // NOTE: There's no such concept on Wayland.
// XXX there's no such concept on Wayland.
None None
} }
/// Get the raw-window-handle v0.6 display handle.
#[cfg(feature = "rwh_06")] #[cfg(feature = "rwh_06")]
#[inline] fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
pub fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> { self
Ok(rwh_06::WaylandWindowHandle::new({
let ptr = self.window.wl_surface().id().as_ptr();
std::ptr::NonNull::new(ptr as *mut _).expect("wl_surface will never be null")
})
.into())
} }
/// Get the raw-window-handle v0.6 window handle.
#[cfg(feature = "rwh_06")] #[cfg(feature = "rwh_06")]
#[inline] fn rwh_06_window_handle(&self) -> &dyn rwh_06::HasWindowHandle {
pub fn raw_display_handle_rwh_06( self
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::WaylandDisplayHandle::new({
let ptr = self.display.id().as_ptr();
std::ptr::NonNull::new(ptr as *mut _).expect("wl_proxy should never be null")
})
.into())
}
#[inline]
pub fn set_theme(&self, theme: Option<Theme>) {
self.window_state.lock().unwrap().set_theme(theme)
}
#[inline]
pub fn theme(&self) -> Option<Theme> {
self.window_state.lock().unwrap().theme()
}
pub fn set_content_protected(&self, _protected: bool) {}
#[inline]
pub fn title(&self) -> String {
self.window_state.lock().unwrap().title().to_owned()
}
}
impl Drop for Window {
fn drop(&mut self) {
self.window_requests.closed.store(true, Ordering::Relaxed);
self.event_loop_awakener.ping();
} }
} }

View file

@ -18,8 +18,7 @@ use tracing::warn;
use x11rb::connection::RequestConnection; use x11rb::connection::RequestConnection;
use x11rb::errors::{ConnectError, ConnectionError, IdsExhausted, ReplyError}; use x11rb::errors::{ConnectError, ConnectionError, IdsExhausted, ReplyError};
use x11rb::protocol::xinput::{self, ConnectionExt as _}; use x11rb::protocol::xinput::{self, ConnectionExt as _};
use x11rb::protocol::xkb; use x11rb::protocol::{xkb, xproto};
use x11rb::protocol::xproto::{self, ConnectionExt as _};
use x11rb::x11_utils::X11Error as LogicalError; use x11rb::x11_utils::X11Error as LogicalError;
use x11rb::xcb_ffi::ReplyOrIdError; use x11rb::xcb_ffi::ReplyOrIdError;
@ -33,9 +32,11 @@ use crate::event_loop::{
use crate::platform::pump_events::PumpStatus; use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::common::xkb::Context; use crate::platform_impl::common::xkb::Context;
use crate::platform_impl::platform::{min_timeout, WindowId}; use crate::platform_impl::platform::{min_timeout, WindowId};
use crate::platform_impl::x11::window::Window;
use crate::platform_impl::{OsError, OwnedDisplayHandle, PlatformCustomCursor}; use crate::platform_impl::{OsError, OwnedDisplayHandle, PlatformCustomCursor};
use crate::window::{ use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowAttributes, CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as CoreWindow,
WindowAttributes,
}; };
mod activation; mod activation;
@ -46,7 +47,7 @@ pub mod ffi;
mod ime; mod ime;
mod monitor; mod monitor;
mod util; mod util;
mod window; pub(crate) mod window;
mod xdisplay; mod xdisplay;
mod xsettings; mod xsettings;
@ -687,10 +688,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window( fn create_window(
&self, &self,
window_attributes: WindowAttributes, window_attributes: WindowAttributes,
) -> Result<crate::window::Window, RootOsError> { ) -> Result<Box<dyn CoreWindow>, RootOsError> {
let window = crate::platform_impl::x11::Window::new(self, window_attributes)?; Ok(Box::new(Window::new(self, window_attributes)?))
let window = crate::platform_impl::Window::X(window);
Ok(crate::window::Window { window })
} }
fn create_custom_cursor( fn create_custom_cursor(
@ -827,39 +826,6 @@ impl FingerId {
} }
} }
pub(crate) struct Window(Arc<UnownedWindow>);
impl Deref for Window {
type Target = UnownedWindow;
#[inline]
fn deref(&self) -> &UnownedWindow {
&self.0
}
}
impl Window {
pub(crate) fn new(
event_loop: &ActiveEventLoop,
attribs: WindowAttributes,
) -> Result<Self, RootOsError> {
let window = Arc::new(UnownedWindow::new(event_loop, attribs)?);
event_loop.windows.borrow_mut().insert(window.id(), Arc::downgrade(&window));
Ok(Window(window))
}
}
impl Drop for Window {
fn drop(&mut self) {
let window = self.deref();
let xconn = &window.xconn;
if let Ok(c) = xconn.xcb_connection().destroy_window(window.id().0 as xproto::Window) {
c.ignore_error();
}
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct EventLoopProxy { pub struct EventLoopProxy {
ping: Ping, ping: Ping,

View file

@ -1,6 +1,7 @@
use std::ffi::CString; use std::ffi::CString;
use std::mem::replace; use std::mem::replace;
use std::num::NonZeroU32; use std::num::NonZeroU32;
use std::ops::Deref;
use std::os::raw::*; use std::os::raw::*;
use std::path::Path; use std::path::Path;
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
@ -30,14 +31,312 @@ use crate::platform_impl::x11::{
xinput_fp1616_to_float, MonitorHandle as X11MonitorHandle, WakeSender, X11Error, xinput_fp1616_to_float, MonitorHandle as X11MonitorHandle, WakeSender, X11Error,
}; };
use crate::platform_impl::{ use crate::platform_impl::{
Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformCustomCursor, common, Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformCustomCursor,
PlatformIcon, VideoModeHandle as PlatformVideoModeHandle, PlatformIcon, VideoModeHandle as PlatformVideoModeHandle,
}; };
use crate::window::{ use crate::window::{
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
WindowButtons, WindowLevel, WindowAttributes, WindowButtons, WindowLevel,
}; };
pub(crate) struct Window(Arc<UnownedWindow>);
impl Deref for Window {
type Target = UnownedWindow;
#[inline]
fn deref(&self) -> &UnownedWindow {
&self.0
}
}
impl Window {
pub(crate) fn new(
event_loop: &ActiveEventLoop,
attribs: WindowAttributes,
) -> Result<Self, RootOsError> {
let window = Arc::new(UnownedWindow::new(event_loop, attribs)?);
event_loop.windows.borrow_mut().insert(window.id(), Arc::downgrade(&window));
Ok(Window(window))
}
}
impl CoreWindow for Window {
fn id(&self) -> crate::window::WindowId {
crate::window::WindowId(self.0.id())
}
fn scale_factor(&self) -> f64 {
self.0.scale_factor()
}
fn request_redraw(&self) {
self.0.request_redraw()
}
fn pre_present_notify(&self) {
self.0.pre_present_notify()
}
fn reset_dead_keys(&self) {
common::xkb::reset_dead_keys();
}
fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
self.0.inner_position()
}
fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
self.0.outer_position()
}
fn set_outer_position(&self, position: Position) {
self.0.set_outer_position(position)
}
fn inner_size(&self) -> PhysicalSize<u32> {
self.0.inner_size()
}
fn request_inner_size(&self, size: Size) -> Option<PhysicalSize<u32>> {
self.0.request_inner_size(size)
}
fn outer_size(&self) -> PhysicalSize<u32> {
self.0.outer_size()
}
fn set_min_inner_size(&self, min_size: Option<Size>) {
self.0.set_min_inner_size(min_size)
}
fn set_max_inner_size(&self, max_size: Option<Size>) {
self.0.set_max_inner_size(max_size)
}
fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
self.0.resize_increments()
}
fn set_resize_increments(&self, increments: Option<Size>) {
self.0.set_resize_increments(increments)
}
fn set_title(&self, title: &str) {
self.0.set_title(title);
}
fn set_transparent(&self, transparent: bool) {
self.0.set_transparent(transparent);
}
fn set_blur(&self, blur: bool) {
self.0.set_blur(blur);
}
fn set_visible(&self, visible: bool) {
self.0.set_visible(visible);
}
fn is_visible(&self) -> Option<bool> {
self.0.is_visible()
}
fn set_resizable(&self, resizable: bool) {
self.0.set_resizable(resizable);
}
fn is_resizable(&self) -> bool {
self.0.is_resizable()
}
fn set_enabled_buttons(&self, buttons: WindowButtons) {
self.0.set_enabled_buttons(buttons)
}
fn enabled_buttons(&self) -> WindowButtons {
self.0.enabled_buttons()
}
fn set_minimized(&self, minimized: bool) {
self.0.set_minimized(minimized)
}
fn is_minimized(&self) -> Option<bool> {
self.0.is_minimized()
}
fn set_maximized(&self, maximized: bool) {
self.0.set_maximized(maximized)
}
fn is_maximized(&self) -> bool {
self.0.is_maximized()
}
fn set_fullscreen(&self, fullscreen: Option<crate::window::Fullscreen>) {
self.0.set_fullscreen(fullscreen.map(Into::into))
}
fn fullscreen(&self) -> Option<crate::window::Fullscreen> {
self.0.fullscreen().map(Into::into)
}
fn set_decorations(&self, decorations: bool) {
self.0.set_decorations(decorations);
}
fn is_decorated(&self) -> bool {
self.0.is_decorated()
}
fn set_window_level(&self, level: WindowLevel) {
self.0.set_window_level(level);
}
fn set_window_icon(&self, window_icon: Option<crate::window::Icon>) {
self.0.set_window_icon(window_icon.map(|inner| inner.inner))
}
fn set_ime_cursor_area(&self, position: Position, size: Size) {
self.0.set_ime_cursor_area(position, size);
}
fn set_ime_allowed(&self, allowed: bool) {
self.0.set_ime_allowed(allowed);
}
fn set_ime_purpose(&self, purpose: ImePurpose) {
self.0.set_ime_purpose(purpose);
}
fn focus_window(&self) {
self.0.focus_window();
}
fn has_focus(&self) -> bool {
self.0.has_focus()
}
fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
self.0.request_user_attention(request_type);
}
fn set_theme(&self, theme: Option<Theme>) {
self.0.set_theme(theme);
}
fn theme(&self) -> Option<Theme> {
self.0.theme()
}
fn set_content_protected(&self, protected: bool) {
self.0.set_content_protected(protected);
}
fn title(&self) -> String {
self.0.title()
}
fn set_cursor(&self, cursor: Cursor) {
self.0.set_cursor(cursor);
}
fn set_cursor_position(&self, position: Position) -> Result<(), ExternalError> {
self.0.set_cursor_position(position)
}
fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
self.0.set_cursor_grab(mode)
}
fn set_cursor_visible(&self, visible: bool) {
self.0.set_cursor_visible(visible);
}
fn drag_window(&self) -> Result<(), ExternalError> {
self.0.drag_window()
}
fn drag_resize_window(&self, direction: ResizeDirection) -> Result<(), ExternalError> {
self.0.drag_resize_window(direction)
}
fn show_window_menu(&self, position: Position) {
self.0.show_window_menu(position);
}
fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
self.0.set_cursor_hittest(hittest)
}
fn current_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
self.0
.current_monitor()
.map(crate::platform_impl::MonitorHandle::X)
.map(|inner| crate::monitor::MonitorHandle { inner })
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
Box::new(
self.0
.available_monitors()
.into_iter()
.map(crate::platform_impl::MonitorHandle::X)
.map(|inner| crate::monitor::MonitorHandle { inner }),
)
}
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
self.0
.primary_monitor()
.map(crate::platform_impl::MonitorHandle::X)
.map(|inner| crate::monitor::MonitorHandle { inner })
}
#[cfg(feature = "rwh_06")]
fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
self
}
#[cfg(feature = "rwh_06")]
fn rwh_06_window_handle(&self) -> &dyn rwh_06::HasWindowHandle {
self
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for Window {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
let raw = self.0.raw_display_handle_rwh_06()?;
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasWindowHandle for Window {
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
let raw = self.0.raw_window_handle_rwh_06()?;
unsafe { Ok(rwh_06::WindowHandle::borrow_raw(raw)) }
}
}
impl Drop for Window {
fn drop(&mut self) {
let window = &self.0;
let xconn = &window.xconn;
// Restore the video mode on drop.
if let Some(Fullscreen::Exclusive(_)) = window.fullscreen() {
window.set_fullscreen(None);
}
if let Ok(c) = xconn.xcb_connection().destroy_window(window.id().0 as xproto::Window) {
c.ignore_error();
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct SharedState { pub struct SharedState {
pub cursor_pos: Option<(f64, f64)>, pub cursor_pos: Option<(f64, f64)>,

View file

@ -23,8 +23,10 @@ use crate::keyboard::{
Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NamedKey, NativeKey, NativeKeyCode, Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NamedKey, NativeKey, NativeKeyCode,
PhysicalKey, PhysicalKey,
}; };
use crate::platform_impl::Window;
use crate::window::{ use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId as RootWindowId, CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as CoreWindow,
WindowId as RootWindowId,
}; };
fn convert_scancode(scancode: u8) -> (PhysicalKey, Option<NamedKey>) { fn convert_scancode(scancode: u8) -> (PhysicalKey, Option<NamedKey>) {
@ -729,9 +731,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window( fn create_window(
&self, &self,
window_attributes: crate::window::WindowAttributes, window_attributes: crate::window::WindowAttributes,
) -> Result<crate::window::Window, crate::error::OsError> { ) -> Result<Box<dyn CoreWindow>, crate::error::OsError> {
let window = crate::platform_impl::Window::new(self, window_attributes)?; Ok(Box::new(Window::new(self, window_attributes)?))
Ok(crate::window::Window { window })
} }
fn create_custom_cursor( fn create_custom_cursor(

View file

@ -6,9 +6,9 @@ use super::{
}; };
use crate::cursor::Cursor; use crate::cursor::Cursor;
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size}; use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
use crate::platform_impl::Fullscreen; use crate::error;
use crate::window::ImePurpose; use crate::monitor::MonitorHandle as CoreMonitorHandle;
use crate::{error, window}; use crate::window::{self, Fullscreen, ImePurpose, Window as CoreWindow, WindowId as CoreWindowId};
// These values match the values uses in the `window_new` function in orbital: // These values match the values uses in the `window_new` function in orbital:
// https://gitlab.redox-os.org/redox-os/orbital/-/blob/master/src/scheme.rs // https://gitlab.redox-os.org/redox-os/orbital/-/blob/master/src/scheme.rs
@ -125,14 +125,6 @@ impl Window {
}) })
} }
pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&Self) + Send + 'static) {
f(self)
}
pub(crate) fn maybe_wait_on_main<R: Send>(&self, f: impl FnOnce(&Self) -> R + Send) -> R {
f(self)
}
fn get_flag(&self, flag: char) -> Result<bool, error::ExternalError> { fn get_flag(&self, flag: char) -> Result<bool, error::ExternalError> {
let mut buf: [u8; 4096] = [0; 4096]; let mut buf: [u8; 4096] = [0; 4096];
let path = self let path = self
@ -150,36 +142,51 @@ impl Window {
Ok(()) Ok(())
} }
#[cfg(feature = "rwh_06")]
#[inline] #[inline]
pub fn id(&self) -> WindowId { fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> {
WindowId { fd: self.window_socket.fd as u64 } let handle = rwh_06::OrbitalWindowHandle::new({
let window = self.window_socket.fd as *mut _;
std::ptr::NonNull::new(window).expect("orbital fd should never be null")
});
Ok(rwh_06::RawWindowHandle::Orbital(handle))
}
#[cfg(feature = "rwh_06")]
#[inline]
fn raw_display_handle_rwh_06(&self) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Orbital(rwh_06::OrbitalDisplayHandle::new()))
}
}
impl CoreWindow for Window {
fn id(&self) -> CoreWindowId {
CoreWindowId(WindowId { fd: self.window_socket.fd as u64 })
} }
#[inline] #[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> { fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
Some(MonitorHandle) Some(CoreMonitorHandle { inner: MonitorHandle })
} }
#[inline] #[inline]
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> { fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
let mut v = VecDeque::with_capacity(1); Box::new(vec![CoreMonitorHandle { inner: MonitorHandle }].into_iter())
v.push_back(MonitorHandle);
v
} }
#[inline] #[inline]
pub fn current_monitor(&self) -> Option<MonitorHandle> { fn current_monitor(&self) -> Option<CoreMonitorHandle> {
Some(MonitorHandle) Some(CoreMonitorHandle { inner: MonitorHandle })
} }
#[inline] #[inline]
pub fn scale_factor(&self) -> f64 { fn scale_factor(&self) -> f64 {
MonitorHandle.scale_factor() MonitorHandle.scale_factor()
} }
#[inline] #[inline]
pub fn request_redraw(&self) { fn request_redraw(&self) {
let window_id = self.id(); let window_id = self.id().0;
let mut redraws = self.redraws.lock().unwrap(); let mut redraws = self.redraws.lock().unwrap();
if !redraws.contains(&window_id) { if !redraws.contains(&window_id) {
redraws.push_back(window_id); redraws.push_back(window_id);
@ -189,15 +196,15 @@ impl Window {
} }
#[inline] #[inline]
pub fn pre_present_notify(&self) {} fn pre_present_notify(&self) {}
#[inline] #[inline]
pub fn reset_dead_keys(&self) { fn reset_dead_keys(&self) {
// TODO? // TODO?
} }
#[inline] #[inline]
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, error::NotSupportedError> { fn inner_position(&self) -> Result<PhysicalPosition<i32>, error::NotSupportedError> {
let mut buf: [u8; 4096] = [0; 4096]; let mut buf: [u8; 4096] = [0; 4096];
let path = self.window_socket.fpath(&mut buf).expect("failed to read properties"); let path = self.window_socket.fpath(&mut buf).expect("failed to read properties");
let properties = WindowProperties::new(path); let properties = WindowProperties::new(path);
@ -205,20 +212,20 @@ impl Window {
} }
#[inline] #[inline]
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, error::NotSupportedError> { fn outer_position(&self) -> Result<PhysicalPosition<i32>, error::NotSupportedError> {
// TODO: adjust for window decorations // TODO: adjust for window decorations
self.inner_position() self.inner_position()
} }
#[inline] #[inline]
pub fn set_outer_position(&self, position: Position) { fn set_outer_position(&self, position: Position) {
// TODO: adjust for window decorations // TODO: adjust for window decorations
let (x, y): (i32, i32) = position.to_physical::<i32>(self.scale_factor()).into(); let (x, y): (i32, i32) = position.to_physical::<i32>(self.scale_factor()).into();
self.window_socket.write(format!("P,{x},{y}").as_bytes()).expect("failed to set position"); self.window_socket.write(format!("P,{x},{y}").as_bytes()).expect("failed to set position");
} }
#[inline] #[inline]
pub fn inner_size(&self) -> PhysicalSize<u32> { fn inner_size(&self) -> PhysicalSize<u32> {
let mut buf: [u8; 4096] = [0; 4096]; let mut buf: [u8; 4096] = [0; 4096];
let path = self.window_socket.fpath(&mut buf).expect("failed to read properties"); let path = self.window_socket.fpath(&mut buf).expect("failed to read properties");
let properties = WindowProperties::new(path); let properties = WindowProperties::new(path);
@ -226,26 +233,26 @@ impl Window {
} }
#[inline] #[inline]
pub fn request_inner_size(&self, size: Size) -> Option<PhysicalSize<u32>> { fn request_inner_size(&self, size: Size) -> Option<PhysicalSize<u32>> {
let (w, h): (u32, u32) = size.to_physical::<u32>(self.scale_factor()).into(); let (w, h): (u32, u32) = size.to_physical::<u32>(self.scale_factor()).into();
self.window_socket.write(format!("S,{w},{h}").as_bytes()).expect("failed to set size"); self.window_socket.write(format!("S,{w},{h}").as_bytes()).expect("failed to set size");
None None
} }
#[inline] #[inline]
pub fn outer_size(&self) -> PhysicalSize<u32> { fn outer_size(&self) -> PhysicalSize<u32> {
// TODO: adjust for window decorations // TODO: adjust for window decorations
self.inner_size() self.inner_size()
} }
#[inline] #[inline]
pub fn set_min_inner_size(&self, _: Option<Size>) {} fn set_min_inner_size(&self, _: Option<Size>) {}
#[inline] #[inline]
pub fn set_max_inner_size(&self, _: Option<Size>) {} fn set_max_inner_size(&self, _: Option<Size>) {}
#[inline] #[inline]
pub fn title(&self) -> String { fn title(&self) -> String {
let mut buf: [u8; 4096] = [0; 4096]; let mut buf: [u8; 4096] = [0; 4096];
let path = self.window_socket.fpath(&mut buf).expect("failed to read properties"); let path = self.window_socket.fpath(&mut buf).expect("failed to read properties");
let properties = WindowProperties::new(path); let properties = WindowProperties::new(path);
@ -253,84 +260,82 @@ impl Window {
} }
#[inline] #[inline]
pub fn set_title(&self, title: &str) { fn set_title(&self, title: &str) {
self.window_socket.write(format!("T,{title}").as_bytes()).expect("failed to set title"); self.window_socket.write(format!("T,{title}").as_bytes()).expect("failed to set title");
} }
#[inline] #[inline]
pub fn set_transparent(&self, transparent: bool) { fn set_transparent(&self, transparent: bool) {
let _ = self.set_flag(ORBITAL_FLAG_TRANSPARENT, transparent); let _ = self.set_flag(ORBITAL_FLAG_TRANSPARENT, transparent);
} }
#[inline] #[inline]
pub fn set_blur(&self, _blur: bool) {} fn set_blur(&self, _blur: bool) {}
#[inline] #[inline]
pub fn set_visible(&self, visible: bool) { fn set_visible(&self, visible: bool) {
let _ = self.set_flag(ORBITAL_FLAG_HIDDEN, !visible); let _ = self.set_flag(ORBITAL_FLAG_HIDDEN, !visible);
} }
#[inline] #[inline]
pub fn is_visible(&self) -> Option<bool> { fn is_visible(&self) -> Option<bool> {
Some(!self.get_flag(ORBITAL_FLAG_HIDDEN).unwrap_or(false)) Some(!self.get_flag(ORBITAL_FLAG_HIDDEN).unwrap_or(false))
} }
#[inline] #[inline]
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> { fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
None None
} }
#[inline] #[inline]
pub fn set_resize_increments(&self, _increments: Option<Size>) {} fn set_resize_increments(&self, _increments: Option<Size>) {}
#[inline] #[inline]
pub fn set_resizable(&self, resizeable: bool) { fn set_resizable(&self, resizeable: bool) {
let _ = self.set_flag(ORBITAL_FLAG_RESIZABLE, resizeable); let _ = self.set_flag(ORBITAL_FLAG_RESIZABLE, resizeable);
} }
#[inline] #[inline]
pub fn is_resizable(&self) -> bool { fn is_resizable(&self) -> bool {
self.get_flag(ORBITAL_FLAG_RESIZABLE).unwrap_or(false) self.get_flag(ORBITAL_FLAG_RESIZABLE).unwrap_or(false)
} }
#[inline] #[inline]
pub fn set_minimized(&self, _minimized: bool) {} fn set_minimized(&self, _minimized: bool) {}
#[inline] #[inline]
pub fn is_minimized(&self) -> Option<bool> { fn is_minimized(&self) -> Option<bool> {
None None
} }
#[inline] #[inline]
pub fn set_maximized(&self, maximized: bool) { fn set_maximized(&self, maximized: bool) {
let _ = self.set_flag(ORBITAL_FLAG_MAXIMIZED, maximized); let _ = self.set_flag(ORBITAL_FLAG_MAXIMIZED, maximized);
} }
#[inline] #[inline]
pub fn is_maximized(&self) -> bool { fn is_maximized(&self) -> bool {
self.get_flag(ORBITAL_FLAG_MAXIMIZED).unwrap_or(false) self.get_flag(ORBITAL_FLAG_MAXIMIZED).unwrap_or(false)
} }
#[inline] fn set_fullscreen(&self, _monitor: Option<Fullscreen>) {}
pub(crate) fn set_fullscreen(&self, _monitor: Option<Fullscreen>) {}
#[inline] fn fullscreen(&self) -> Option<Fullscreen> {
pub(crate) fn fullscreen(&self) -> Option<Fullscreen> {
None None
} }
#[inline] #[inline]
pub fn set_decorations(&self, decorations: bool) { fn set_decorations(&self, decorations: bool) {
let _ = self.set_flag(ORBITAL_FLAG_BORDERLESS, !decorations); let _ = self.set_flag(ORBITAL_FLAG_BORDERLESS, !decorations);
} }
#[inline] #[inline]
pub fn is_decorated(&self) -> bool { fn is_decorated(&self) -> bool {
!self.get_flag(ORBITAL_FLAG_BORDERLESS).unwrap_or(false) !self.get_flag(ORBITAL_FLAG_BORDERLESS).unwrap_or(false)
} }
#[inline] #[inline]
pub fn set_window_level(&self, level: window::WindowLevel) { fn set_window_level(&self, level: window::WindowLevel) {
match level { match level {
window::WindowLevel::AlwaysOnBottom => { window::WindowLevel::AlwaysOnBottom => {
let _ = self.set_flag(ORBITAL_FLAG_BACK, true); let _ = self.set_flag(ORBITAL_FLAG_BACK, true);
@ -346,36 +351,33 @@ impl Window {
} }
#[inline] #[inline]
pub fn set_window_icon(&self, _window_icon: Option<crate::icon::Icon>) {} fn set_window_icon(&self, _window_icon: Option<crate::icon::Icon>) {}
#[inline] #[inline]
pub fn set_ime_cursor_area(&self, _position: Position, _size: Size) {} fn set_ime_cursor_area(&self, _position: Position, _size: Size) {}
#[inline] #[inline]
pub fn set_ime_allowed(&self, _allowed: bool) {} fn set_ime_allowed(&self, _allowed: bool) {}
#[inline] #[inline]
pub fn set_ime_purpose(&self, _purpose: ImePurpose) {} fn set_ime_purpose(&self, _purpose: ImePurpose) {}
#[inline] #[inline]
pub fn focus_window(&self) {} fn focus_window(&self) {}
#[inline] #[inline]
pub fn request_user_attention(&self, _request_type: Option<window::UserAttentionType>) {} fn request_user_attention(&self, _request_type: Option<window::UserAttentionType>) {}
#[inline] #[inline]
pub fn set_cursor(&self, _: Cursor) {} fn set_cursor(&self, _: Cursor) {}
#[inline] #[inline]
pub fn set_cursor_position(&self, _: Position) -> Result<(), error::ExternalError> { fn set_cursor_position(&self, _: Position) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new())) Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
} }
#[inline] #[inline]
pub fn set_cursor_grab( fn set_cursor_grab(&self, mode: window::CursorGrabMode) -> Result<(), error::ExternalError> {
&self,
mode: window::CursorGrabMode,
) -> Result<(), error::ExternalError> {
let (grab, relative) = match mode { let (grab, relative) = match mode {
window::CursorGrabMode::None => (false, false), window::CursorGrabMode::None => (false, false),
window::CursorGrabMode::Confined => (true, false), window::CursorGrabMode::Confined => (true, false),
@ -391,12 +393,12 @@ impl Window {
} }
#[inline] #[inline]
pub fn set_cursor_visible(&self, visible: bool) { fn set_cursor_visible(&self, visible: bool) {
let _ = self.window_socket.write(format!("M,C,{}", if visible { 1 } else { 0 }).as_bytes()); let _ = self.window_socket.write(format!("M,C,{}", if visible { 1 } else { 0 }).as_bytes());
} }
#[inline] #[inline]
pub fn drag_window(&self) -> Result<(), error::ExternalError> { fn drag_window(&self) -> Result<(), error::ExternalError> {
self.window_socket self.window_socket
.write(b"D") .write(b"D")
.map_err(|err| error::ExternalError::Os(os_error!(OsError::new(err))))?; .map_err(|err| error::ExternalError::Os(os_error!(OsError::new(err))))?;
@ -404,7 +406,7 @@ impl Window {
} }
#[inline] #[inline]
pub fn drag_resize_window( fn drag_resize_window(
&self, &self,
direction: window::ResizeDirection, direction: window::ResizeDirection,
) -> Result<(), error::ExternalError> { ) -> Result<(), error::ExternalError> {
@ -425,60 +427,68 @@ impl Window {
} }
#[inline] #[inline]
pub fn show_window_menu(&self, _position: Position) {} fn show_window_menu(&self, _position: Position) {}
#[inline] #[inline]
pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), error::ExternalError> { fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), error::ExternalError> {
Err(error::ExternalError::NotSupported(error::NotSupportedError::new())) Err(error::ExternalError::NotSupported(error::NotSupportedError::new()))
} }
#[cfg(feature = "rwh_06")]
#[inline] #[inline]
pub fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> { fn set_enabled_buttons(&self, _buttons: window::WindowButtons) {}
let handle = rwh_06::OrbitalWindowHandle::new({
let window = self.window_socket.fd as *mut _;
std::ptr::NonNull::new(window).expect("orbital fd should never be null")
});
Ok(rwh_06::RawWindowHandle::Orbital(handle))
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Orbital(rwh_06::OrbitalDisplayHandle::new()))
}
#[inline] #[inline]
pub fn set_enabled_buttons(&self, _buttons: window::WindowButtons) {} fn enabled_buttons(&self) -> window::WindowButtons {
#[inline]
pub fn enabled_buttons(&self) -> window::WindowButtons {
window::WindowButtons::all() window::WindowButtons::all()
} }
#[inline] #[inline]
pub fn theme(&self) -> Option<window::Theme> { fn theme(&self) -> Option<window::Theme> {
None None
} }
#[inline] #[inline]
pub fn has_focus(&self) -> bool { fn has_focus(&self) -> bool {
false false
} }
#[inline] #[inline]
pub fn set_theme(&self, _theme: Option<window::Theme>) {} fn set_theme(&self, _theme: Option<window::Theme>) {}
pub fn set_content_protected(&self, _protected: bool) {} fn set_content_protected(&self, _protected: bool) {}
#[cfg(feature = "rwh_06")]
fn rwh_06_window_handle(&self) -> &dyn rwh_06::HasWindowHandle {
self
}
#[cfg(feature = "rwh_06")]
fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
self
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasWindowHandle for Window {
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
let raw = self.raw_window_handle_rwh_06()?;
unsafe { Ok(rwh_06::WindowHandle::borrow_raw(raw)) }
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for Window {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
let raw = self.raw_display_handle_rwh_06()?;
unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) }
}
} }
impl Drop for Window { impl Drop for Window {
fn drop(&mut self) { fn drop(&mut self) {
{ {
let mut destroys = self.destroys.lock().unwrap(); let mut destroys = self.destroys.lock().unwrap();
destroys.push_back(self.id()); destroys.push_back(self.id().0);
} }
self.wake_socket.wake().unwrap(); self.wake_socket.wake().unwrap();

View file

@ -27,8 +27,7 @@ use crate::platform_impl::platform::cursor::CustomCursor;
use crate::platform_impl::platform::r#async::Waker; use crate::platform_impl::platform::r#async::Waker;
use crate::platform_impl::Window; use crate::platform_impl::Window;
use crate::window::{ use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow, CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId as RootWindowId,
WindowId as RootWindowId,
}; };
#[derive(Default)] #[derive(Default)]
@ -632,9 +631,9 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window( fn create_window(
&self, &self,
window_attributes: crate::window::WindowAttributes, window_attributes: crate::window::WindowAttributes,
) -> Result<crate::window::Window, crate::error::OsError> { ) -> Result<Box<dyn crate::window::Window>, crate::error::OsError> {
let window = Window::new(self, window_attributes)?; let window = Window::new(self, window_attributes)?;
Ok(RootWindow { window }) Ok(Box::new(window))
} }
fn create_custom_cursor( fn create_custom_cursor(

View file

@ -51,4 +51,3 @@ pub(crate) use self::monitor::{
use self::web_sys as backend; use self::web_sys as backend;
pub use self::window::{PlatformSpecificWindowAttributes, Window, WindowId}; pub use self::window::{PlatformSpecificWindowAttributes, Window, WindowId};
pub(crate) use crate::icon::NoIcon as PlatformIcon; pub(crate) use crate::icon::NoIcon as PlatformIcon;
pub(crate) use crate::platform_impl::Fullscreen;

View file

@ -29,6 +29,7 @@ use super::main_thread::MainThreadMarker;
use super::r#async::{Dispatcher, Notified, Notifier}; use super::r#async::{Dispatcher, Notified, Notifier};
use super::web_sys::{Engine, EventListenerHandle}; use super::web_sys::{Engine, EventListenerHandle};
use crate::dpi::{PhysicalPosition, PhysicalSize}; use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::web::{ use crate::platform::web::{
MonitorPermissionError, Orientation, OrientationData, OrientationLock, OrientationLockError, MonitorPermissionError, Orientation, OrientationData, OrientationLock, OrientationLockError,
}; };
@ -188,6 +189,12 @@ impl PartialOrd for MonitorHandle {
} }
} }
impl From<MonitorHandle> for RootMonitorHandle {
fn from(inner: MonitorHandle) -> Self {
RootMonitorHandle { inner }
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum OrientationLockFuture { pub enum OrientationLockFuture {
Future(Notified<Result<(), OrientationLockError>>), Future(Notified<Result<(), OrientationLockError>>),

View file

@ -5,15 +5,17 @@ use std::sync::Arc;
use web_sys::HtmlCanvasElement; use web_sys::HtmlCanvasElement;
use super::main_thread::{MainThreadMarker, MainThreadSafe}; use super::main_thread::{MainThreadMarker, MainThreadSafe};
use super::monitor::{MonitorHandle, MonitorHandler}; use super::monitor::MonitorHandler;
use super::r#async::Dispatcher; use super::r#async::Dispatcher;
use super::{backend, lock, ActiveEventLoop, Fullscreen}; use super::{backend, lock, ActiveEventLoop};
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size}; use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{ExternalError, NotSupportedError, OsError as RootOE}; use crate::error::{ExternalError, NotSupportedError, OsError as RootOE};
use crate::icon::Icon; use crate::icon::Icon;
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::window::{ use crate::window::{
Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Cursor, CursorGrabMode, Fullscreen as RootFullscreen, ImePurpose, ResizeDirection, Theme,
WindowAttributes, WindowButtons, WindowId as RootWI, WindowLevel, UserAttentionType, Window as RootWindow, WindowAttributes, WindowButtons, WindowId as RootWI,
WindowLevel,
}; };
pub struct Window { pub struct Window {
@ -65,14 +67,6 @@ impl Window {
Ok(Window { inner: dispatcher }) Ok(Window { inner: dispatcher })
} }
pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&Inner) + Send + 'static) {
self.inner.dispatch(f)
}
pub(crate) fn maybe_wait_on_main<R: Send>(&self, f: impl FnOnce(&Inner) -> R + Send) -> R {
self.inner.queue(f)
}
pub fn canvas(&self) -> Option<Ref<'_, HtmlCanvasElement>> { pub fn canvas(&self) -> Option<Ref<'_, HtmlCanvasElement>> {
MainThreadMarker::new() MainThreadMarker::new()
.map(|main_thread| Ref::map(self.inner.value(main_thread), |inner| inner.canvas.raw())) .map(|main_thread| Ref::map(self.inner.value(main_thread), |inner| inner.canvas.raw()))
@ -91,10 +85,307 @@ impl Window {
lock::is_cursor_lock_raw(inner.canvas.navigator(), inner.canvas.document()) lock::is_cursor_lock_raw(inner.canvas.navigator(), inner.canvas.document())
}) })
} }
}
impl RootWindow for Window {
fn id(&self) -> RootWI {
RootWI(self.inner.queue(|inner| inner.id))
}
fn scale_factor(&self) -> f64 {
self.inner.queue(Inner::scale_factor)
}
fn request_redraw(&self) {
self.inner.dispatch(|inner| inner.canvas.request_animation_frame())
}
fn pre_present_notify(&self) {}
fn reset_dead_keys(&self) {
// Not supported
}
fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
// Note: the canvas element has no window decorations, so this is equal to `outer_position`.
self.outer_position()
}
fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
self.inner.queue(|inner| Ok(inner.canvas.position().to_physical(inner.scale_factor())))
}
fn set_outer_position(&self, position: Position) {
self.inner.dispatch(move |inner| {
let position = position.to_logical::<f64>(inner.scale_factor());
backend::set_canvas_position(
inner.canvas.document(),
inner.canvas.raw(),
inner.canvas.style(),
position,
)
})
}
fn inner_size(&self) -> PhysicalSize<u32> {
self.inner.queue(|inner| inner.canvas.inner_size())
}
fn request_inner_size(&self, size: Size) -> Option<PhysicalSize<u32>> {
self.inner.queue(|inner| {
let size = size.to_logical(self.scale_factor());
backend::set_canvas_size(
inner.canvas.document(),
inner.canvas.raw(),
inner.canvas.style(),
size,
);
None
})
}
fn outer_size(&self) -> PhysicalSize<u32> {
// Note: the canvas element has no window decorations, so this is equal to `inner_size`.
self.inner_size()
}
fn set_min_inner_size(&self, min_size: Option<Size>) {
self.inner.dispatch(move |inner| {
let dimensions = min_size.map(|min_size| min_size.to_logical(inner.scale_factor()));
backend::set_canvas_min_size(
inner.canvas.document(),
inner.canvas.raw(),
inner.canvas.style(),
dimensions,
)
})
}
fn set_max_inner_size(&self, max_size: Option<Size>) {
self.inner.dispatch(move |inner| {
let dimensions = max_size.map(|dimensions| dimensions.to_logical(inner.scale_factor()));
backend::set_canvas_max_size(
inner.canvas.document(),
inner.canvas.raw(),
inner.canvas.style(),
dimensions,
)
})
}
fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
None
}
fn set_resize_increments(&self, _: Option<Size>) {
// Intentionally a no-op: users can't resize canvas elements
}
fn set_title(&self, title: &str) {
self.inner.queue(|inner| inner.canvas.set_attribute("alt", title))
}
fn set_transparent(&self, _: bool) {}
fn set_blur(&self, _: bool) {}
fn set_visible(&self, _: bool) {
// Intentionally a no-op
}
fn is_visible(&self) -> Option<bool> {
None
}
fn set_resizable(&self, _: bool) {
// Intentionally a no-op: users can't resize canvas elements
}
fn is_resizable(&self) -> bool {
true
}
fn set_enabled_buttons(&self, _: WindowButtons) {}
fn enabled_buttons(&self) -> WindowButtons {
WindowButtons::all()
}
fn set_minimized(&self, _: bool) {
// Intentionally a no-op, as canvases cannot be 'minimized'
}
fn is_minimized(&self) -> Option<bool> {
// Canvas cannot be 'minimized'
Some(false)
}
fn set_maximized(&self, _: bool) {
// Intentionally a no-op, as canvases cannot be 'maximized'
}
fn is_maximized(&self) -> bool {
// Canvas cannot be 'maximized'
false
}
fn set_fullscreen(&self, fullscreen: Option<RootFullscreen>) {
self.inner.dispatch(move |inner| {
if let Some(fullscreen) = fullscreen {
inner.canvas.request_fullscreen(fullscreen.into());
} else {
inner.canvas.exit_fullscreen()
}
})
}
fn fullscreen(&self) -> Option<RootFullscreen> {
self.inner.queue(|inner| {
if inner.canvas.is_fullscreen() {
Some(RootFullscreen::Borderless(None))
} else {
None
}
})
}
fn set_decorations(&self, _: bool) {
// Intentionally a no-op, no canvas decorations
}
fn is_decorated(&self) -> bool {
true
}
fn set_window_level(&self, _: WindowLevel) {
// Intentionally a no-op, no window ordering
}
fn set_window_icon(&self, _: Option<Icon>) {
// Currently an intentional no-op
}
fn set_ime_cursor_area(&self, _: Position, _: Size) {
// Currently not implemented
}
fn set_ime_allowed(&self, _: bool) {
// Currently not implemented
}
fn set_ime_purpose(&self, _: ImePurpose) {
// Currently not implemented
}
fn focus_window(&self) {
self.inner.dispatch(|inner| {
let _ = inner.canvas.raw().focus();
})
}
fn has_focus(&self) -> bool {
self.inner.queue(|inner| inner.canvas.has_focus.get())
}
fn request_user_attention(&self, _: Option<UserAttentionType>) {
// Currently an intentional no-op
}
fn set_theme(&self, _: Option<Theme>) {}
fn theme(&self) -> Option<Theme> {
self.inner.queue(|inner| {
backend::is_dark_mode(&inner.window).map(|is_dark_mode| {
if is_dark_mode {
Theme::Dark
} else {
Theme::Light
}
})
})
}
fn set_content_protected(&self, _: bool) {}
fn title(&self) -> String {
String::new()
}
fn set_cursor(&self, cursor: Cursor) {
self.inner.dispatch(move |inner| inner.canvas.cursor.set_cursor(cursor))
}
fn set_cursor_position(&self, _: Position) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
self.inner.queue(|inner| {
match mode {
CursorGrabMode::None => inner.canvas.document().exit_pointer_lock(),
CursorGrabMode::Locked => lock::request_pointer_lock(
inner.canvas.navigator(),
inner.canvas.document(),
inner.canvas.raw(),
),
CursorGrabMode::Confined => {
return Err(ExternalError::NotSupported(NotSupportedError::new()))
},
}
Ok(())
})
}
fn set_cursor_visible(&self, visible: bool) {
self.inner.dispatch(move |inner| inner.canvas.cursor.set_cursor_visible(visible))
}
fn drag_window(&self) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
fn drag_resize_window(&self, _: ResizeDirection) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
fn show_window_menu(&self, _: Position) {}
fn set_cursor_hittest(&self, _: bool) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
fn current_monitor(&self) -> Option<RootMonitorHandle> {
Some(self.inner.queue(|inner| inner.monitor.current_monitor()).into())
}
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
Box::new(
self.inner
.queue(|inner| inner.monitor.available_monitors())
.into_iter()
.map(RootMonitorHandle::from),
)
}
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
self.inner.queue(|inner| inner.monitor.primary_monitor()).map(RootMonitorHandle::from)
}
#[cfg(feature = "rwh_06")] #[cfg(feature = "rwh_06")]
#[inline] fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
pub fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> { self
}
#[cfg(feature = "rwh_06")]
fn rwh_06_window_handle(&self) -> &dyn rwh_06::HasWindowHandle {
self
}
}
#[cfg(feature = "rwh_06")]
impl rwh_06::HasWindowHandle for Window {
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
MainThreadMarker::new() MainThreadMarker::new()
.map(|main_thread| { .map(|main_thread| {
let inner = self.inner.value(main_thread); let inner = self.inner.value(main_thread);
@ -102,323 +393,30 @@ impl Window {
let canvas: &wasm_bindgen::JsValue = inner.canvas.raw(); let canvas: &wasm_bindgen::JsValue = inner.canvas.raw();
let window_handle = let window_handle =
rwh_06::WebCanvasWindowHandle::new(std::ptr::NonNull::from(canvas).cast()); rwh_06::WebCanvasWindowHandle::new(std::ptr::NonNull::from(canvas).cast());
rwh_06::RawWindowHandle::WebCanvas(window_handle) // SAFETY: The pointer won't be invalidated as long as `Window` lives, which the
// lifetime is bound to.
unsafe {
rwh_06::WindowHandle::borrow_raw(rwh_06::RawWindowHandle::WebCanvas(
window_handle,
))
}
}) })
.ok_or(rwh_06::HandleError::Unavailable) .ok_or(rwh_06::HandleError::Unavailable)
} }
}
#[cfg(feature = "rwh_06")] #[cfg(feature = "rwh_06")]
#[inline] impl rwh_06::HasDisplayHandle for Window {
pub(crate) fn raw_display_handle_rwh_06( fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
&self, Ok(rwh_06::DisplayHandle::web())
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Web(rwh_06::WebDisplayHandle::new()))
} }
} }
impl Inner { impl Inner {
pub fn set_title(&self, title: &str) {
self.canvas.set_attribute("alt", title)
}
pub fn set_transparent(&self, _transparent: bool) {}
pub fn set_blur(&self, _blur: bool) {}
pub fn set_visible(&self, _visible: bool) {
// Intentionally a no-op
}
#[inline]
pub fn is_visible(&self) -> Option<bool> {
None
}
pub fn request_redraw(&self) {
self.canvas.request_animation_frame();
}
pub fn pre_present_notify(&self) {}
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
Ok(self.canvas.position().to_physical(self.scale_factor()))
}
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
// Note: the canvas element has no window decorations, so this is equal to `outer_position`.
self.outer_position()
}
pub fn set_outer_position(&self, position: Position) {
let position = position.to_logical::<f64>(self.scale_factor());
backend::set_canvas_position(
self.canvas.document(),
self.canvas.raw(),
self.canvas.style(),
position,
)
}
#[inline]
pub fn inner_size(&self) -> PhysicalSize<u32> {
self.canvas.inner_size()
}
#[inline]
pub fn outer_size(&self) -> PhysicalSize<u32> {
// Note: the canvas element has no window decorations, so this is equal to `inner_size`.
self.inner_size()
}
#[inline]
pub fn request_inner_size(&self, size: Size) -> Option<PhysicalSize<u32>> {
let size = size.to_logical(self.scale_factor());
backend::set_canvas_size(
self.canvas.document(),
self.canvas.raw(),
self.canvas.style(),
size,
);
None
}
#[inline]
pub fn set_min_inner_size(&self, dimensions: Option<Size>) {
let dimensions = dimensions.map(|dimensions| dimensions.to_logical(self.scale_factor()));
backend::set_canvas_min_size(
self.canvas.document(),
self.canvas.raw(),
self.canvas.style(),
dimensions,
)
}
#[inline]
pub fn set_max_inner_size(&self, dimensions: Option<Size>) {
let dimensions = dimensions.map(|dimensions| dimensions.to_logical(self.scale_factor()));
backend::set_canvas_max_size(
self.canvas.document(),
self.canvas.raw(),
self.canvas.style(),
dimensions,
)
}
#[inline]
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
None
}
#[inline]
pub fn set_resize_increments(&self, _increments: Option<Size>) {
// Intentionally a no-op: users can't resize canvas elements
}
#[inline]
pub fn set_resizable(&self, _resizable: bool) {
// Intentionally a no-op: users can't resize canvas elements
}
pub fn is_resizable(&self) -> bool {
true
}
#[inline]
pub fn set_enabled_buttons(&self, _buttons: WindowButtons) {}
#[inline]
pub fn enabled_buttons(&self) -> WindowButtons {
WindowButtons::all()
}
#[inline] #[inline]
pub fn scale_factor(&self) -> f64 { pub fn scale_factor(&self) -> f64 {
super::backend::scale_factor(&self.window) super::backend::scale_factor(&self.window)
} }
#[inline]
pub fn set_cursor(&self, cursor: Cursor) {
self.canvas.cursor.set_cursor(cursor)
}
#[inline]
pub fn set_cursor_position(&self, _position: Position) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
#[inline]
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
match mode {
CursorGrabMode::None => self.canvas.document().exit_pointer_lock(),
CursorGrabMode::Locked => lock::request_pointer_lock(
self.canvas.navigator(),
self.canvas.document(),
self.canvas.raw(),
),
CursorGrabMode::Confined => {
return Err(ExternalError::NotSupported(NotSupportedError::new()))
},
}
Ok(())
}
#[inline]
pub fn set_cursor_visible(&self, visible: bool) {
self.canvas.cursor.set_cursor_visible(visible)
}
#[inline]
pub fn drag_window(&self) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
#[inline]
pub fn drag_resize_window(&self, _direction: ResizeDirection) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
#[inline]
pub fn show_window_menu(&self, _position: Position) {}
#[inline]
pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
#[inline]
pub fn set_minimized(&self, _minimized: bool) {
// Intentionally a no-op, as canvases cannot be 'minimized'
}
#[inline]
pub fn is_minimized(&self) -> Option<bool> {
// Canvas cannot be 'minimized'
Some(false)
}
#[inline]
pub fn set_maximized(&self, _maximized: bool) {
// Intentionally a no-op, as canvases cannot be 'maximized'
}
#[inline]
pub fn is_maximized(&self) -> bool {
// Canvas cannot be 'maximized'
false
}
#[inline]
pub(crate) fn fullscreen(&self) -> Option<Fullscreen> {
if self.canvas.is_fullscreen() {
Some(Fullscreen::Borderless(Some(self.monitor.current_monitor())))
} else {
None
}
}
#[inline]
pub(crate) fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
if let Some(fullscreen) = fullscreen {
self.canvas.request_fullscreen(fullscreen);
} else {
self.canvas.exit_fullscreen()
}
}
#[inline]
pub fn set_decorations(&self, _decorations: bool) {
// Intentionally a no-op, no canvas decorations
}
pub fn is_decorated(&self) -> bool {
true
}
#[inline]
pub fn set_window_level(&self, _level: WindowLevel) {
// Intentionally a no-op, no window ordering
}
#[inline]
pub fn set_window_icon(&self, _window_icon: Option<Icon>) {
// Currently an intentional no-op
}
#[inline]
pub fn set_ime_cursor_area(&self, _position: Position, _size: Size) {
// Currently not implemented
}
#[inline]
pub fn set_ime_allowed(&self, _allowed: bool) {
// Currently not implemented
}
#[inline]
pub fn set_ime_purpose(&self, _purpose: ImePurpose) {
// Currently not implemented
}
#[inline]
pub fn focus_window(&self) {
let _ = self.canvas.raw().focus();
}
#[inline]
pub fn request_user_attention(&self, _request_type: Option<UserAttentionType>) {
// Currently an intentional no-op
}
#[inline]
pub fn current_monitor(&self) -> Option<MonitorHandle> {
Some(self.monitor.current_monitor())
}
#[inline]
pub fn available_monitors(&self) -> Vec<MonitorHandle> {
self.monitor.available_monitors()
}
#[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
self.monitor.primary_monitor()
}
#[inline]
pub fn id(&self) -> WindowId {
self.id
}
#[inline]
pub fn set_theme(&self, _theme: Option<Theme>) {}
#[inline]
pub fn theme(&self) -> Option<Theme> {
backend::is_dark_mode(&self.window).map(|is_dark_mode| {
if is_dark_mode {
Theme::Dark
} else {
Theme::Light
}
})
}
pub fn set_content_protected(&self, _protected: bool) {}
#[inline]
pub fn has_focus(&self) -> bool {
self.canvas.has_focus.get()
}
pub fn title(&self) -> String {
String::new()
}
pub fn reset_dead_keys(&self) {
// Not supported
}
} }
impl Drop for Inner { impl Drop for Inner {

View file

@ -86,8 +86,8 @@ use crate::platform_impl::platform::{
use crate::platform_impl::Window; use crate::platform_impl::Window;
use crate::utils::Lazy; use crate::utils::Lazy;
use crate::window::{ use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow, CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as CoreWindow,
WindowAttributes, WindowId as RootWindowId, WindowAttributes, WindowId as CoreWindowId,
}; };
pub(crate) struct WindowData { pub(crate) struct WindowData {
@ -518,9 +518,11 @@ impl RootActiveEventLoop for ActiveEventLoop {
RootEventLoopProxy { event_loop_proxy } RootEventLoopProxy { event_loop_proxy }
} }
fn create_window(&self, window_attributes: WindowAttributes) -> Result<RootWindow, OsError> { fn create_window(
let window = Window::new(self, window_attributes)?; &self,
Ok(RootWindow { window }) window_attributes: WindowAttributes,
) -> Result<Box<dyn CoreWindow>, OsError> {
Ok(Box::new(Window::new(self, window_attributes)?))
} }
fn create_custom_cursor( fn create_custom_cursor(
@ -918,7 +920,7 @@ fn update_modifiers(window: HWND, userdata: &WindowData) {
drop(window_state); drop(window_state);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: ModifiersChanged(modifiers.into()), event: ModifiersChanged(modifiers.into()),
}); });
} }
@ -930,7 +932,7 @@ unsafe fn gain_active_focus(window: HWND, userdata: &WindowData) {
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: Focused(true), event: Focused(true),
}); });
} }
@ -940,12 +942,12 @@ unsafe fn lose_active_focus(window: HWND, userdata: &WindowData) {
userdata.window_state_lock().modifiers_state = ModifiersState::empty(); userdata.window_state_lock().modifiers_state = ModifiersState::empty();
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: ModifiersChanged(ModifiersState::empty().into()), event: ModifiersChanged(ModifiersState::empty().into()),
}); });
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: Focused(false), event: Focused(false),
}); });
} }
@ -1043,7 +1045,7 @@ unsafe fn public_window_callback_inner(
userdata.key_event_builder.process_message(window, msg, wparam, lparam, &mut result); userdata.key_event_builder.process_message(window, msg, wparam, lparam, &mut result);
for event in events { for event in events {
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: KeyboardInput { event: KeyboardInput {
device_id: DEVICE_ID, device_id: DEVICE_ID,
event: event.event, event: event.event,
@ -1128,7 +1130,7 @@ unsafe fn public_window_callback_inner(
WM_CLOSE => { WM_CLOSE => {
use crate::event::WindowEvent::CloseRequested; use crate::event::WindowEvent::CloseRequested;
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: CloseRequested, event: CloseRequested,
}); });
result = ProcResult::Value(0); result = ProcResult::Value(0);
@ -1138,7 +1140,7 @@ unsafe fn public_window_callback_inner(
use crate::event::WindowEvent::Destroyed; use crate::event::WindowEvent::Destroyed;
unsafe { RevokeDragDrop(window) }; unsafe { RevokeDragDrop(window) };
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: Destroyed, event: Destroyed,
}); });
result = ProcResult::Value(0); result = ProcResult::Value(0);
@ -1159,7 +1161,7 @@ unsafe fn public_window_callback_inner(
// and request a normal redraw with `RedrawWindow`. // and request a normal redraw with `RedrawWindow`.
if !userdata.event_loop_runner.should_buffer() { if !userdata.event_loop_runner.should_buffer() {
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::RedrawRequested, event: WindowEvent::RedrawRequested,
}); });
} }
@ -1262,7 +1264,7 @@ unsafe fn public_window_callback_inner(
let physical_position = let physical_position =
unsafe { PhysicalPosition::new((*windowpos).x, (*windowpos).y) }; unsafe { PhysicalPosition::new((*windowpos).x, (*windowpos).y) };
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: Moved(physical_position), event: Moved(physical_position),
}); });
} }
@ -1278,7 +1280,7 @@ unsafe fn public_window_callback_inner(
let physical_size = PhysicalSize::new(w, h); let physical_size = PhysicalSize::new(w, h);
let event = Event::WindowEvent { let event = Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: Resized(physical_size), event: Resized(physical_size),
}; };
@ -1393,7 +1395,7 @@ unsafe fn public_window_callback_inner(
userdata.window_state_lock().ime_state = ImeState::Enabled; userdata.window_state_lock().ime_state = ImeState::Enabled;
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::Ime(Ime::Enabled), event: WindowEvent::Ime(Ime::Enabled),
}); });
} }
@ -1413,7 +1415,7 @@ unsafe fn public_window_callback_inner(
if lparam == 0 { if lparam == 0 {
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::Ime(Ime::Preedit(String::new(), None)), event: WindowEvent::Ime(Ime::Preedit(String::new(), None)),
}); });
} }
@ -1425,11 +1427,11 @@ unsafe fn public_window_callback_inner(
userdata.window_state_lock().ime_state = ImeState::Enabled; userdata.window_state_lock().ime_state = ImeState::Enabled;
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::Ime(Ime::Preedit(String::new(), None)), event: WindowEvent::Ime(Ime::Preedit(String::new(), None)),
}); });
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::Ime(Ime::Commit(text)), event: WindowEvent::Ime(Ime::Commit(text)),
}); });
} }
@ -1444,7 +1446,7 @@ unsafe fn public_window_callback_inner(
let cursor_range = first.map(|f| (f, last.unwrap_or(f))); let cursor_range = first.map(|f| (f, last.unwrap_or(f)));
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::Ime(Ime::Preedit(text, cursor_range)), event: WindowEvent::Ime(Ime::Preedit(text, cursor_range)),
}); });
} }
@ -1467,11 +1469,11 @@ unsafe fn public_window_callback_inner(
let ime_context = unsafe { ImeContext::current(window) }; let ime_context = unsafe { ImeContext::current(window) };
if let Some(text) = unsafe { ime_context.get_composed_text() } { if let Some(text) = unsafe { ime_context.get_composed_text() } {
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::Ime(Ime::Preedit(String::new(), None)), event: WindowEvent::Ime(Ime::Preedit(String::new(), None)),
}); });
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::Ime(Ime::Commit(text)), event: WindowEvent::Ime(Ime::Commit(text)),
}); });
} }
@ -1480,7 +1482,7 @@ unsafe fn public_window_callback_inner(
userdata.window_state_lock().ime_state = ImeState::Disabled; userdata.window_state_lock().ime_state = ImeState::Disabled;
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::Ime(Ime::Disabled), event: WindowEvent::Ime(Ime::Disabled),
}); });
} }
@ -1538,7 +1540,7 @@ unsafe fn public_window_callback_inner(
drop(w); drop(w);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: CursorEntered { device_id: DEVICE_ID }, event: CursorEntered { device_id: DEVICE_ID },
}); });
@ -1559,7 +1561,7 @@ unsafe fn public_window_callback_inner(
drop(w); drop(w);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: CursorLeft { device_id: DEVICE_ID }, event: CursorLeft { device_id: DEVICE_ID },
}); });
}, },
@ -1578,7 +1580,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: CursorMoved { device_id: DEVICE_ID, position }, event: CursorMoved { device_id: DEVICE_ID, position },
}); });
} }
@ -1594,7 +1596,7 @@ unsafe fn public_window_callback_inner(
} }
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: CursorLeft { device_id: DEVICE_ID }, event: CursorLeft { device_id: DEVICE_ID },
}); });
@ -1610,7 +1612,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::MouseWheel { event: WindowEvent::MouseWheel {
device_id: DEVICE_ID, device_id: DEVICE_ID,
delta: LineDelta(0.0, value), delta: LineDelta(0.0, value),
@ -1630,7 +1632,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::MouseWheel { event: WindowEvent::MouseWheel {
device_id: DEVICE_ID, device_id: DEVICE_ID,
delta: LineDelta(value, 0.0), delta: LineDelta(value, 0.0),
@ -1665,7 +1667,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Left }, event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Left },
}); });
result = ProcResult::Value(0); result = ProcResult::Value(0);
@ -1681,7 +1683,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: MouseInput { device_id: DEVICE_ID, state: Released, button: Left }, event: MouseInput { device_id: DEVICE_ID, state: Released, button: Left },
}); });
result = ProcResult::Value(0); result = ProcResult::Value(0);
@ -1697,7 +1699,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Right }, event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Right },
}); });
result = ProcResult::Value(0); result = ProcResult::Value(0);
@ -1713,7 +1715,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: MouseInput { device_id: DEVICE_ID, state: Released, button: Right }, event: MouseInput { device_id: DEVICE_ID, state: Released, button: Right },
}); });
result = ProcResult::Value(0); result = ProcResult::Value(0);
@ -1729,7 +1731,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Middle }, event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Middle },
}); });
result = ProcResult::Value(0); result = ProcResult::Value(0);
@ -1745,7 +1747,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: MouseInput { device_id: DEVICE_ID, state: Released, button: Middle }, event: MouseInput { device_id: DEVICE_ID, state: Released, button: Middle },
}); });
result = ProcResult::Value(0); result = ProcResult::Value(0);
@ -1762,7 +1764,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: MouseInput { event: MouseInput {
device_id: DEVICE_ID, device_id: DEVICE_ID,
state: Pressed, state: Pressed,
@ -1787,7 +1789,7 @@ unsafe fn public_window_callback_inner(
update_modifiers(window, userdata); update_modifiers(window, userdata);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: MouseInput { event: MouseInput {
device_id: DEVICE_ID, device_id: DEVICE_ID,
state: Released, state: Released,
@ -1836,7 +1838,7 @@ unsafe fn public_window_callback_inner(
let y = location.y as f64 + (input.y % 100) as f64 / 100f64; let y = location.y as f64 + (input.y % 100) as f64 / 100f64;
let location = PhysicalPosition::new(x, y); let location = PhysicalPosition::new(x, y);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::Touch(Touch { event: WindowEvent::Touch(Touch {
phase: if util::has_flag(input.dwFlags, TOUCHEVENTF_DOWN) { phase: if util::has_flag(input.dwFlags, TOUCHEVENTF_DOWN) {
TouchPhase::Started TouchPhase::Started
@ -1984,7 +1986,7 @@ unsafe fn public_window_callback_inner(
let y = location.y as f64 + y.fract(); let y = location.y as f64 + y.fract();
let location = PhysicalPosition::new(x, y); let location = PhysicalPosition::new(x, y);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: WindowEvent::Touch(Touch { event: WindowEvent::Touch(Touch {
phase: if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_DOWN) { phase: if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_DOWN) {
TouchPhase::Started TouchPhase::Started
@ -2167,7 +2169,7 @@ unsafe fn public_window_callback_inner(
let new_inner_size = Arc::new(Mutex::new(new_physical_inner_size)); let new_inner_size = Arc::new(Mutex::new(new_physical_inner_size));
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: ScaleFactorChanged { event: ScaleFactorChanged {
scale_factor: new_scale_factor, scale_factor: new_scale_factor,
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)), inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)),
@ -2319,7 +2321,7 @@ unsafe fn public_window_callback_inner(
window_state.current_theme = new_theme; window_state.current_theme = new_theme;
drop(window_state); drop(window_state);
userdata.send_event(Event::WindowEvent { userdata.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window)), window_id: CoreWindowId(WindowId(window)),
event: ThemeChanged(new_theme), event: ThemeChanged(new_theme),
}); });
} }

View file

@ -16,7 +16,6 @@ use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::monitor::VideoModeHandle as RootVideoModeHandle; use crate::monitor::VideoModeHandle as RootVideoModeHandle;
use crate::platform_impl::platform::dpi::{dpi_to_scale_factor, get_monitor_dpi}; use crate::platform_impl::platform::dpi::{dpi_to_scale_factor, get_monitor_dpi};
use crate::platform_impl::platform::util::has_flag; use crate::platform_impl::platform::util::has_flag;
use crate::platform_impl::platform::window::Window;
#[derive(Clone)] #[derive(Clone)]
pub struct VideoModeHandle { pub struct VideoModeHandle {
@ -136,17 +135,6 @@ pub fn current_monitor(hwnd: HWND) -> MonitorHandle {
MonitorHandle::new(hmonitor) MonitorHandle::new(hmonitor)
} }
impl Window {
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
available_monitors()
}
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
let monitor = primary_monitor();
Some(monitor)
}
}
pub(crate) fn get_monitor_info(hmonitor: HMONITOR) -> Result<MONITORINFOEXW, io::Error> { pub(crate) fn get_monitor_info(hmonitor: HMONITOR) -> Result<MONITORINFOEXW, io::Error> {
let mut monitor_info: MONITORINFOEXW = unsafe { mem::zeroed() }; let mut monitor_info: MONITORINFOEXW = unsafe { mem::zeroed() };
monitor_info.monitorInfo.cbSize = mem::size_of::<MONITORINFOEXW>() as u32; monitor_info.monitorInfo.cbSize = mem::size_of::<MONITORINFOEXW>() as u32;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
#[allow(dead_code)] #[allow(dead_code)]
fn needs_send<T: Send>() {} fn needs_send<T: Send + ?Sized>() {}
#[test] #[test]
fn event_loop_proxy_send() { fn event_loop_proxy_send() {
@ -8,7 +8,7 @@ fn event_loop_proxy_send() {
#[test] #[test]
fn window_send() { fn window_send() {
needs_send::<winit::window::Window>(); needs_send::<dyn winit::window::Window>();
} }
#[test] #[test]

View file

@ -1,5 +1,5 @@
#[allow(dead_code)] #[allow(dead_code)]
fn needs_sync<T: Sync>() {} fn needs_sync<T: Sync + ?Sized>() {}
#[test] #[test]
fn event_loop_proxy_send() { fn event_loop_proxy_send() {
@ -8,7 +8,7 @@ fn event_loop_proxy_send() {
#[test] #[test]
fn window_sync() { fn window_sync() {
needs_sync::<winit::window::Window>(); needs_sync::<dyn winit::window::Window>();
} }
#[test] #[test]