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_loop::{ActiveEventLoop, EventLoop};
use winit::raw_window_handle::HasRawWindowHandle;
use winit::window::{Window, WindowId};
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
@ -16,12 +16,12 @@ fn main() -> Result<(), impl std::error::Error> {
#[derive(Default)]
struct Application {
parent_window_id: Option<WindowId>,
windows: HashMap<WindowId, Window>,
windows: HashMap<WindowId, Box<dyn Window>>,
}
impl ApplicationHandler for Application {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let attributes = Window::default_attributes()
let attributes = WindowAttributes::default()
.with_title("parent window")
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
.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 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();
println!("Child window created with id: {child_id:?}");
self.windows.insert(child_id, child_window);
},
WindowEvent::RedrawRequested => {
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 mut window_attributes = Window::default_attributes()
let mut window_attributes = WindowAttributes::default()
.with_title("child window")
.with_inner_size(LogicalSize::new(200.0f32, 200.0f32))
.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_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::keyboard::{Key, NamedKey};
use winit::window::{Window, WindowId};
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
@ -52,7 +52,7 @@ struct ControlFlowDemo {
request_redraw: bool,
wait_cancelled: bool,
close_requested: bool,
window: Option<Window>,
window: Option<Box<dyn Window>>,
}
impl ApplicationHandler for ControlFlowDemo {
@ -66,7 +66,7 @@ impl ApplicationHandler for ControlFlowDemo {
}
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.",
);
self.window = Some(event_loop.create_window(window_attributes).unwrap());
@ -114,7 +114,7 @@ impl ApplicationHandler for ControlFlowDemo {
WindowEvent::RedrawRequested => {
let window = self.window.as_ref().unwrap();
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_loop::{ActiveEventLoop, EventLoop};
use winit::platform::pump_events::{EventLoopExtPumpEvents, PumpStatus};
use winit::window::{Window, WindowId};
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
#[derive(Default)]
struct PumpDemo {
window: Option<Window>,
window: Option<Box<dyn Window>>,
}
impl ApplicationHandler for PumpDemo {
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());
}
@ -43,7 +43,7 @@ fn main() -> std::process::ExitCode {
match event {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => {
fill::fill_window(window);
fill::fill_window(window.as_ref());
window.request_redraw();
},
_ => (),

View file

@ -9,7 +9,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::platform::run_on_demand::EventLoopExtRunOnDemand;
use winit::window::{Window, WindowId};
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
@ -18,7 +18,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
struct App {
idx: usize,
window_id: Option<WindowId>,
window: Option<Window>,
window: Option<Box<dyn Window>>,
}
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) {
let window_attributes = Window::default_attributes()
let window_attributes = WindowAttributes::default()
.with_title("Fantastic window number one!")
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0));
let window = event_loop.create_window(window_attributes).unwrap();
@ -65,11 +65,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
CloseRequested",
self.idx
);
fill::cleanup_window(window);
fill::cleanup_window(window.as_ref());
self.window = None;
},
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.
struct GraphicsContext {
/// The global softbuffer context.
context: RefCell<Context<&'static Window>>,
context: RefCell<Context<&'static dyn Window>>,
/// 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 {
fn new(w: &Window) -> Self {
fn new(w: &dyn Window) -> Self {
Self {
context: RefCell::new(
Context::new(unsafe { mem::transmute::<&'_ Window, &'static Window>(w) })
.expect("Failed to create a softbuffer context"),
Context::new(unsafe {
mem::transmute::<&'_ dyn Window, &'static dyn Window>(w)
})
.expect("Failed to create a softbuffer context"),
),
surfaces: HashMap::new(),
}
@ -53,22 +55,22 @@ mod platform {
fn create_surface(
&mut self,
window: &Window,
) -> &mut Surface<&'static Window, &'static Window> {
window: &dyn Window,
) -> &mut Surface<&'static dyn Window, &'static dyn Window> {
self.surfaces.entry(window.id()).or_insert_with(|| {
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")
})
}
fn destroy_surface(&mut self, window: &Window) {
fn destroy_surface(&mut self, window: &dyn Window) {
self.surfaces.remove(&window.id());
}
}
pub fn fill_window(window: &Window) {
pub fn fill_window(window: &dyn Window) {
GC.with(|gc| {
let size = window.inner_size();
let (Some(width), Some(height)) =
@ -94,7 +96,7 @@ mod platform {
}
#[allow(dead_code)]
pub fn cleanup_window(window: &Window) {
pub fn cleanup_window(window: &dyn Window) {
GC.with(|gc| {
let mut gc = gc.borrow_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")))))]
mod platform {
pub fn fill_window(_window: &winit::window::Window) {
pub fn fill_window(_window: &dyn winit::window::Window) {
// No-op on mobile platforms.
}
#[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.
}
}

View file

@ -31,7 +31,7 @@ use winit::platform::startup_notify::{
use winit::platform::web::{ActiveEventLoopExtWeb, CustomCursorExtWeb, WindowAttributesExtWeb};
use winit::window::{
Cursor, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, Icon, ResizeDirection,
Theme, Window, WindowId,
Theme, Window, WindowAttributes, WindowId,
};
#[path = "util/tracing.rs"]
@ -135,7 +135,7 @@ impl Application {
// TODO read-out activation token.
#[allow(unused_mut)]
let mut window_attributes = Window::default_attributes()
let mut window_attributes = WindowAttributes::default()
.with_title("Winit window")
.with_transparent(true)
.with_window_icon(Some(self.icon.clone()));
@ -560,9 +560,9 @@ struct WindowState {
///
/// NOTE: This surface must be dropped before the `Window`.
#[cfg(not(any(android_platform, ios_platform)))]
surface: Surface<DisplayHandle<'static>, Arc<Window>>,
surface: Surface<DisplayHandle<'static>, Arc<dyn Window>>,
/// The actual winit Window.
window: Arc<Window>,
window: Arc<dyn Window>,
/// The window theme we're drawing with.
theme: Theme,
/// Cursor position over the window.
@ -590,8 +590,8 @@ struct WindowState {
}
impl WindowState {
fn new(app: &Application, window: Window) -> Result<Self, Box<dyn Error>> {
let window = Arc::new(window);
fn new(app: &Application, window: Box<dyn Window>) -> Result<Self, Box<dyn Error>> {
let window: Arc<dyn Window> = Arc::from(window);
// SAFETY: the surface is dropped before the `window` which provided it with handle, thus
// it doesn't outlive it.
@ -601,7 +601,7 @@ impl WindowState {
let theme = window.theme().unwrap_or(Theme::Dark);
info!("Theme: {theme:?}");
let named_idx = 0;
window.set_cursor(CURSORS[named_idx]);
window.set_cursor(CURSORS[named_idx].into());
// Allow IME out of the box.
let ime = true;
@ -636,7 +636,7 @@ impl WindowState {
self.ime = !self.ime;
self.window.set_ime_allowed(self.ime);
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>) {
self.cursor_position = Some(position);
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) {
let new_increments = match self.window.resize_increments() {
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());
self.window.set_resize_increments(new_increments);
@ -733,7 +733,7 @@ impl WindowState {
mem::swap(&mut inner_size.width, &mut inner_size.height);
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 {
info!("Inner size change got ignored");
} else {
@ -766,7 +766,7 @@ impl WindowState {
) -> Result<(), Box<dyn Error>> {
let cursor = event_loop.create_custom_cursor(url_custom_cursor())?;
self.window.set_cursor(cursor);
self.window.set_cursor(cursor.into());
Ok(())
}
@ -788,7 +788,7 @@ impl WindowState {
let cursor = CustomCursor::from_animation(Duration::from_secs(3), cursors).unwrap();
let cursor = event_loop.create_custom_cursor(cursor)?;
self.window.set_cursor(cursor);
self.window.set_cursor(cursor.into());
Ok(())
}
@ -817,7 +817,7 @@ impl WindowState {
/// Show window menu.
fn show_menu(&self) {
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_loop::{ActiveEventLoop, EventLoop};
use winit::platform::x11::WindowAttributesExtX11;
use winit::window::{Window, WindowId};
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
pub struct XEmbedDemo {
parent_window_id: u32,
window: Option<Window>,
window: Option<Box<dyn Window>>,
}
impl ApplicationHandler for XEmbedDemo {
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_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
.with_embed_parent_window(self.parent_window_id);
@ -38,7 +38,7 @@ fn main() -> Result<(), Box<dyn Error>> {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => {
window.pre_present_notify();
fill::fill_window(window);
fill::fill_window(window.as_ref());
},
_ => (),
}

View file

@ -67,6 +67,8 @@ changelog entry.
### Changed
- 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`.
- On Web, let events wake up event loop immediately when using `ControlFlow::Poll`.
- Bump MSRV from `1.70` to `1.73`.

View file

@ -50,7 +50,7 @@ impl From<CustomCursor> for Cursor {
/// ```no_run
/// # use winit::event_loop::ActiveEventLoop;
/// # 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;
///
/// let w = 10;
@ -67,7 +67,7 @@ impl From<CustomCursor> for Cursor {
/// };
///
/// 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
/// 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.
///

View file

@ -44,16 +44,16 @@
//! use winit::application::ApplicationHandler;
//! use winit::event::WindowEvent;
//! use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
//! use winit::window::{Window, WindowId};
//! use winit::window::{Window, WindowId, WindowAttributes};
//!
//! #[derive(Default)]
//! struct App {
//! window: Option<Window>,
//! window: Option<Box<dyn Window>>,
//! }
//!
//! impl ApplicationHandler for App {
//! 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) {

View file

@ -99,13 +99,15 @@ pub trait WindowExtAndroid {
fn config(&self) -> ConfigurationRef;
}
impl WindowExtAndroid for Window {
impl WindowExtAndroid for dyn Window + '_ {
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 {
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);
}
impl WindowExtIOS for Window {
impl WindowExtIOS for dyn Window + '_ {
#[inline]
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]
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]
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]
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)
})
});
}
#[inline]
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]
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]
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]
@ -254,7 +261,8 @@ impl WindowExtIOS for Window {
minimum_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(
should_recognize,
minimum_number_of_touches,
@ -265,12 +273,14 @@ impl WindowExtIOS for Window {
#[inline]
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]
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;
}
impl WindowExtMacOS for Window {
impl WindowExtMacOS for dyn Window + '_ {
#[inline]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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> {
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::monitor::MonitorHandle;
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.
pub trait ActiveEventLoopExtWayland {
@ -71,9 +71,11 @@ impl EventLoopBuilderExtWayland for EventLoopBuilder {
}
/// Additional methods on [`Window`] that are specific to Wayland.
///
/// [`Window`]: crate::window::Window
pub trait WindowExtWayland {}
impl WindowExtWayland for Window {}
impl WindowExtWayland for dyn CoreWindow + '_ {}
/// Additional methods on [`WindowAttributes`] that are specific to Wayland.
pub trait WindowAttributesExtWayland {

View file

@ -82,7 +82,7 @@ pub trait WindowExtWeb {
/// 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;
/// 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;
}
impl WindowExtWeb for Window {
impl WindowExtWeb for dyn Window + '_ {
#[inline]
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 {
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) {
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 {
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
/// canvas that have side effects.
///
/// See [`Window::set_prevent_default()`] for more details.
/// See [`WindowExtWeb::set_prevent_default()`] for more details.
///
/// Enabled by default.
fn with_prevent_default(self, prevent_default: bool) -> Self;

View file

@ -4,6 +4,7 @@
//! tested regularly.
use std::borrow::Borrow;
use std::ffi::c_void;
use std::ops::Deref;
use std::path::Path;
#[cfg(feature = "serde")]
@ -115,50 +116,25 @@ pub enum CornerPreference {
///
/// See [`WindowBorrowExtWindows::any_thread`] for more information.
#[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.
#[inline]
pub fn get_ref(&self) -> &Window {
self.0.borrow()
}
/// Get a reference to the inner object.
#[inline]
pub fn inner(&self) -> &W {
pub fn get_ref(&self) -> &dyn Window {
&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> {
fn as_ref(&self) -> &Window {
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;
impl<W: Window> Deref for AnyThread<W> {
type Target = W;
fn deref(&self) -> &Self::Target {
self.get_ref()
&self.0
}
}
#[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> {
// SAFETY: The top level user has asserted this is only used safely.
unsafe { self.get_ref().window_handle_any_thread() }
@ -341,7 +317,7 @@ pub trait WindowExtWindows {
///
/// ```no_run
/// # use winit::window::Window;
/// # fn scope(window: Window) {
/// # fn scope(window: Box<dyn Window>) {
/// use std::thread;
///
/// use winit::platform::windows::WindowExtWindows;
@ -365,35 +341,41 @@ pub trait WindowExtWindows {
) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError>;
}
impl WindowExtWindows for Window {
impl WindowExtWindows for dyn Window + '_ {
#[inline]
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]
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]
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]
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]
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]
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]
@ -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
// useful to circumvent the Windows option "Show accent color on title bars and
// 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]
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]
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")]
unsafe fn window_handle_any_thread(
&self,
) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
let window = self.as_any().downcast_ref::<crate::platform_impl::Window>().unwrap();
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.
Ok(rwh_06::WindowHandle::borrow_raw(handle))
@ -430,7 +416,7 @@ impl WindowExtWindows for Window {
/// Additional methods for anything that dereference to [`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.
///
/// 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 = "[`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)
}
}
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.
#[allow(rustdoc::broken_intra_doc_links)]

View file

@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use crate::dpi::Size;
use crate::event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder};
use crate::monitor::MonitorHandle;
use crate::window::{Window, WindowAttributes};
use crate::window::{Window as CoreWindow, WindowAttributes};
/// X window type. Maps directly to
/// [`_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.
///
/// [`Window`]: crate::window::Window
pub trait WindowExtX11 {}
impl WindowExtX11 for Window {}
impl WindowExtX11 for dyn CoreWindow {}
/// Additional methods on [`WindowAttributes`] that are specific to X11.
pub trait WindowAttributesExtX11 {
@ -169,13 +171,13 @@ pub trait WindowAttributesExtX11 {
///
/// ```
/// # use winit::dpi::{LogicalSize, PhysicalSize};
/// # use winit::window::Window;
/// # use winit::window::{Window, WindowAttributes};
/// # use winit::platform::x11::WindowAttributesExtX11;
/// // 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:
/// 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;
@ -184,12 +186,12 @@ pub trait WindowAttributesExtX11 {
/// # Example
///
/// ```no_run
/// use winit::window::Window;
/// use winit::window::{Window, WindowAttributes};
/// use winit::event_loop::ActiveEventLoop;
/// use winit::platform::x11::{XWindow, WindowAttributesExtX11};
/// # 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 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)?;
/// # Ok(()) }
/// ```

View file

@ -22,10 +22,9 @@ use crate::event_loop::{
};
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::Fullscreen;
use crate::window::{
self, CursorGrabMode, CustomCursor, CustomCursorSource, ImePurpose, ResizeDirection, Theme,
Window as RootWindow, WindowAttributes, WindowButtons, WindowLevel,
self, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, ImePurpose,
ResizeDirection, Theme, Window as CoreWindow, WindowAttributes, WindowButtons, WindowLevel,
};
mod keycodes;
@ -593,9 +592,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window(
&self,
window_attributes: WindowAttributes,
) -> Result<RootWindow, error::OsError> {
let window = Window::new(self, window_attributes)?;
Ok(RootWindow { window })
) -> Result<Box<dyn CoreWindow>, error::OsError> {
Ok(Box::new(Window::new(self, window_attributes)?))
}
fn create_custom_cursor(
@ -723,172 +721,18 @@ impl Window {
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) {
f(self)
pub fn config(&self) -> ConfigurationRef {
self.app.config()
}
pub(crate) fn maybe_wait_on_main<R: Send>(&self, f: impl FnOnce(&Self) -> R + Send) -> R {
f(self)
}
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()))
pub fn content_rect(&self) -> Rect {
self.app.content_rect()
}
#[cfg(feature = "rwh_06")]
// Allow the usage of HasRawWindowHandle inside this function
#[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;
if let Some(native_window) = self.app.native_window().as_ref() {
@ -904,37 +748,206 @@ impl Window {
}
#[cfg(feature = "rwh_06")]
pub fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
fn raw_display_handle_rwh_06(&self) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Android(rwh_06::AndroidDisplayHandle::new()))
}
}
pub fn config(&self) -> ConfigurationRef {
self.app.config()
#[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) -> window::WindowId {
window::WindowId(WindowId)
}
pub fn content_rect(&self) -> Rect {
self.app.content_rect()
}
pub fn set_theme(&self, _theme: Option<Theme>) {}
pub fn theme(&self) -> Option<Theme> {
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
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)
}
pub fn title(&self) -> String {
fn title(&self) -> String {
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)]

View file

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

View file

@ -1,5 +1,6 @@
#![allow(clippy::unnecessary_cast)]
use dpi::{Position, Size};
use objc2::rc::{autoreleasepool, Retained};
use objc2::{declare_class, mutability, ClassType, DeclaredClass};
use objc2_app_kit::{NSResponder, NSWindow};
@ -8,7 +9,11 @@ use objc2_foundation::{MainThreadBound, MainThreadMarker, NSObject};
use super::event_loop::ActiveEventLoop;
use super::window_delegate::WindowDelegate;
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 {
window: MainThreadBound<Retained<WinitWindow>>,
@ -16,12 +21,6 @@ pub(crate) struct Window {
delegate: MainThreadBound<Retained<WindowDelegate>>,
}
impl Drop for Window {
fn drop(&mut self) {
self.window.get_on_main(|window| autoreleasepool(|_| window.close()))
}
}
impl Window {
pub(crate) fn new(
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>(
&self,
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)]
pub struct WindowId(pub usize);

View file

@ -33,7 +33,7 @@ use crate::event_loop::{
};
use crate::monitor::MonitorHandle as RootMonitorHandle;
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)]
pub(crate) struct ActiveEventLoop {
@ -49,9 +49,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window(
&self,
window_attributes: crate::window::WindowAttributes,
) -> Result<RootWindow, OsError> {
let window = Window::new(self, window_attributes)?;
Ok(RootWindow { window })
) -> Result<Box<dyn CoreWindow>, OsError> {
Ok(Box::new(Window::new(self, window_attributes)?))
}
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::event::{Event, WindowEvent};
use crate::icon::Icon;
use crate::monitor::MonitorHandle as CoreMonitorHandle;
use crate::platform::ios::{ScreenEdge, StatusBarStyle, ValidOrientations};
use crate::window::{
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
WindowButtons, WindowId as RootWindowId, WindowLevel,
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
WindowAttributes, WindowButtons, WindowId as CoreWindowId, WindowLevel,
};
declare_class!(
@ -49,7 +50,7 @@ declare_class!(
app_state::handle_nonuser_event(
mtm,
EventWrapper::StaticEvent(Event::WindowEvent {
window_id: RootWindowId(self.id()),
window_id: CoreWindowId(self.id()),
event: WindowEvent::Focused(true),
}),
);
@ -62,7 +63,7 @@ declare_class!(
app_state::handle_nonuser_event(
mtm,
EventWrapper::StaticEvent(Event::WindowEvent {
window_id: RootWindowId(self.id()),
window_id: CoreWindowId(self.id()),
event: WindowEvent::Focused(false),
}),
);
@ -522,7 +523,7 @@ impl Window {
width: screen_frame.size.width 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(
mtm,
std::iter::once(EventWrapper::ScaleFactorChanged(app_state::ScaleFactorChanged {
@ -543,11 +544,6 @@ impl Window {
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 {
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
impl Inner {
pub fn set_scale_factor(&self, scale_factor: f64) {

View file

@ -3,7 +3,6 @@
#[cfg(all(not(x11_platform), not(wayland_platform)))]
compile_error!("Please select a feature to build for unix: `x11`, `wayland`");
use std::collections::VecDeque;
use std::num::{NonZeroU16, NonZeroU32};
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
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 crate::application::ApplicationHandler;
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
use crate::error::{EventLoopError, ExternalError, NotSupportedError};
use crate::event_loop::{ActiveEventLoop, AsyncRequestSerial};
use crate::icon::Icon;
#[cfg(x11_platform)]
use crate::dpi::Size;
use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::error::EventLoopError;
use crate::event_loop::ActiveEventLoop;
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
use crate::keyboard::Key;
use crate::platform::pump_events::PumpStatus;
#[cfg(x11_platform)]
use crate::platform::x11::{WindowType as XWindowType, XlibErrorHook};
pub(crate) use crate::platform_impl::Fullscreen;
#[cfg(x11_platform)]
use crate::utils::Lazy;
use crate::window::{
ActivationToken, Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType,
WindowButtons, WindowLevel,
};
use crate::window::ActivationToken;
pub(crate) mod common;
#[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)]
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)]
pub struct KeyEventExtra {
pub text_with_all_modifiers: Option<SmolStr>,

View file

@ -628,10 +628,9 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window(
&self,
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::Window::Wayland(window);
Ok(crate::window::Window { window })
Ok(Box::new(window))
}
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::event::{Ime, WindowEvent};
use crate::event_loop::AsyncRequestSerial;
use crate::platform_impl::{
Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformIcon,
};
use crate::monitor::MonitorHandle as CoreMonitorHandle;
use crate::platform_impl::{Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError};
use crate::window::{
Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType,
WindowAttributes, WindowButtons, WindowLevel,
Cursor, CursorGrabMode, Fullscreen as CoreFullscreen, ImePurpose, ResizeDirection, Theme,
UserAttentionType, Window as CoreWindow, WindowAttributes, WindowButtons,
WindowId as CoreWindowId, WindowLevel,
};
pub(crate) mod state;
@ -223,51 +223,65 @@ impl Window {
}
impl Window {
#[inline]
pub fn id(&self) -> WindowId {
self.window_id
pub fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError> {
let xdg_activation = match self.xdg_activation.as_ref() {
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]
pub fn set_title(&self, title: impl ToString) {
let new_title = title.to_string();
self.window_state.lock().unwrap().set_title(new_title);
pub fn surface(&self) -> &WlSurface {
self.window.wl_surface()
}
}
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]
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) {
fn request_redraw(&self) {
// 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
// mean that the loop still haven't dispatched the value to the client and will do
@ -283,28 +297,50 @@ impl Window {
}
#[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();
}
#[inline]
pub fn outer_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.outer_size(), scale_factor)
fn reset_dead_keys(&self) {
crate::platform_impl::common::xkb::reset_dead_keys()
}
#[inline]
pub fn request_inner_size(&self, size: Size) -> Option<PhysicalSize<u32>> {
fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
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 new_size = window_state.request_inner_size(size);
self.request_redraw();
Some(new_size)
}
/// Set the minimum inner size for the window.
#[inline]
pub fn set_min_inner_size(&self, min_size: Option<Size>) {
fn outer_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.outer_size(), scale_factor)
}
fn set_min_inner_size(&self, min_size: Option<Size>) {
let scale_factor = self.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);
@ -314,7 +350,7 @@ impl Window {
/// Set the maximum inner size for the window.
#[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 max_size = max_size.map(|size| size.to_logical(scale_factor));
self.window_state.lock().unwrap().set_max_inner_size(max_size);
@ -322,96 +358,53 @@ impl Window {
self.request_redraw();
}
#[inline]
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
None
}
#[inline]
pub fn set_resize_increments(&self, _increments: Option<Size>) {
fn set_resize_increments(&self, _increments: Option<Size>) {
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]
pub fn set_transparent(&self, transparent: bool) {
fn set_transparent(&self, transparent: bool) {
self.window_state.lock().unwrap().set_transparent(transparent);
}
#[inline]
pub fn has_focus(&self) -> bool {
self.window_state.lock().unwrap().has_focus()
fn set_visible(&self, _visible: bool) {
// Not possible on Wayland.
}
#[inline]
pub fn is_minimized(&self) -> Option<bool> {
// XXX clients don't know whether they are minimized or not.
fn is_visible(&self) -> Option<bool> {
None
}
#[inline]
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) {
fn set_resizable(&self, resizable: bool) {
if self.window_state.lock().unwrap().set_resizable(resizable) {
// NOTE: Requires commit to be applied.
self.request_redraw();
}
}
#[inline]
pub fn is_resizable(&self) -> bool {
fn is_resizable(&self) -> bool {
self.window_state.lock().unwrap().resizable()
}
#[inline]
pub fn set_enabled_buttons(&self, _buttons: WindowButtons) {
fn set_enabled_buttons(&self, _buttons: WindowButtons) {
// TODO(kchibisov) v5 of the xdg_shell allows that.
}
#[inline]
pub fn enabled_buttons(&self) -> WindowButtons {
fn enabled_buttons(&self) -> WindowButtons {
// TODO(kchibisov) v5 of the xdg_shell allows that.
WindowButtons::all()
}
#[inline]
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) {
fn set_minimized(&self, minimized: bool) {
// You can't unminimize the window on Wayland.
if !minimized {
warn!("Unminimizing is ignored on Wayland.");
@ -421,8 +414,20 @@ impl Window {
self.window.set_minimized();
}
#[inline]
pub fn is_maximized(&self) -> bool {
fn is_minimized(&self) -> Option<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
.lock()
.unwrap()
@ -432,43 +437,14 @@ impl Window {
.unwrap_or_default()
}
#[inline]
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>) {
fn set_fullscreen(&self, fullscreen: Option<CoreFullscreen>) {
match fullscreen {
Some(Fullscreen::Exclusive(_)) => {
Some(CoreFullscreen::Exclusive(_)) => {
warn!("`Fullscreen::Exclusive` is ignored on Wayland");
},
#[cfg_attr(not(x11_platform), allow(clippy::bind_instead_of_map))]
Some(Fullscreen::Borderless(monitor)) => {
let output = monitor.and_then(|monitor| match monitor {
Some(CoreFullscreen::Borderless(monitor)) => {
let output = monitor.and_then(|monitor| match monitor.inner {
PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy),
#[cfg(x11_platform)]
PlatformMonitorHandle::X(_) => None,
@ -480,22 +456,82 @@ impl Window {
}
}
#[inline]
pub fn set_cursor(&self, cursor: Cursor) {
let window_state = &mut self.window_state.lock().unwrap();
fn fullscreen(&self) -> Option<CoreFullscreen> {
let is_fullscreen = self
.window_state
.lock()
.unwrap()
.last_configure
.as_ref()
.map(|last_configure| last_configure.is_fullscreen())
.unwrap_or_default();
match cursor {
Cursor::Icon(icon) => window_state.set_cursor(icon),
Cursor::Custom(cursor) => window_state.set_custom_cursor(cursor),
if is_fullscreen {
let current_monitor = self.current_monitor();
Some(CoreFullscreen::Borderless(current_monitor))
} else {
None
}
}
#[inline]
pub fn set_cursor_visible(&self, visible: bool) {
self.window_state.lock().unwrap().set_cursor_visible(visible);
fn scale_factor(&self) -> f64 {
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() {
Some(xdg_activation) => xdg_activation,
None => {
@ -521,29 +557,26 @@ impl Window {
xdg_activation_token.commit();
}
pub fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError> {
let xdg_activation = match self.xdg_activation.as_ref() {
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)
fn set_theme(&self, theme: Option<Theme>) {
self.window_state.lock().unwrap().set_theme(theme)
}
#[inline]
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
self.window_state.lock().unwrap().set_cursor_grab(mode)
fn theme(&self) -> Option<Theme> {
self.window_state.lock().unwrap().theme()
}
#[inline]
pub fn set_cursor_position(&self, position: Position) -> Result<(), ExternalError> {
fn set_content_protected(&self, _protected: bool) {}
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 position = position.to_logical(scale_factor);
self.window_state
@ -554,13 +587,29 @@ impl Window {
.map(|_| self.request_redraw())
}
#[inline]
pub fn drag_window(&self) -> Result<(), ExternalError> {
fn set_cursor_grab(&self, mode: CursorGrabMode) -> 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()
}
#[inline]
pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> {
fn drag_resize_window(&self, direction: ResizeDirection) -> 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();
if hittest {
@ -576,102 +625,42 @@ impl Window {
}
}
#[inline]
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> {
fn current_monitor(&self) -> Option<CoreMonitorHandle> {
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]
pub fn available_monitors(&self) -> Vec<MonitorHandle> {
self.monitors.lock().unwrap().clone()
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
Box::new(
self.monitors
.lock()
.unwrap()
.clone()
.into_iter()
.map(crate::platform_impl::MonitorHandle::Wayland)
.map(|inner| CoreMonitorHandle { inner }),
)
}
#[inline]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
// XXX there's no such concept on Wayland.
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
// NOTE: There's no such concept on Wayland.
None
}
/// Get the raw-window-handle v0.6 display handle.
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> {
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())
fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
self
}
/// Get the raw-window-handle v0.6 window handle.
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_display_handle_rwh_06(
&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();
fn rwh_06_window_handle(&self) -> &dyn rwh_06::HasWindowHandle {
self
}
}

View file

@ -18,8 +18,7 @@ use tracing::warn;
use x11rb::connection::RequestConnection;
use x11rb::errors::{ConnectError, ConnectionError, IdsExhausted, ReplyError};
use x11rb::protocol::xinput::{self, ConnectionExt as _};
use x11rb::protocol::xkb;
use x11rb::protocol::xproto::{self, ConnectionExt as _};
use x11rb::protocol::{xkb, xproto};
use x11rb::x11_utils::X11Error as LogicalError;
use x11rb::xcb_ffi::ReplyOrIdError;
@ -33,9 +32,11 @@ use crate::event_loop::{
use crate::platform::pump_events::PumpStatus;
use crate::platform_impl::common::xkb::Context;
use crate::platform_impl::platform::{min_timeout, WindowId};
use crate::platform_impl::x11::window::Window;
use crate::platform_impl::{OsError, OwnedDisplayHandle, PlatformCustomCursor};
use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowAttributes,
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as CoreWindow,
WindowAttributes,
};
mod activation;
@ -46,7 +47,7 @@ pub mod ffi;
mod ime;
mod monitor;
mod util;
mod window;
pub(crate) mod window;
mod xdisplay;
mod xsettings;
@ -687,10 +688,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window(
&self,
window_attributes: WindowAttributes,
) -> Result<crate::window::Window, RootOsError> {
let window = crate::platform_impl::x11::Window::new(self, window_attributes)?;
let window = crate::platform_impl::Window::X(window);
Ok(crate::window::Window { window })
) -> Result<Box<dyn CoreWindow>, RootOsError> {
Ok(Box::new(Window::new(self, window_attributes)?))
}
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)]
pub struct EventLoopProxy {
ping: Ping,

View file

@ -1,6 +1,7 @@
use std::ffi::CString;
use std::mem::replace;
use std::num::NonZeroU32;
use std::ops::Deref;
use std::os::raw::*;
use std::path::Path;
use std::sync::{Arc, Mutex, MutexGuard};
@ -30,14 +31,312 @@ use crate::platform_impl::x11::{
xinput_fp1616_to_float, MonitorHandle as X11MonitorHandle, WakeSender, X11Error,
};
use crate::platform_impl::{
Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformCustomCursor,
common, Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError, PlatformCustomCursor,
PlatformIcon, VideoModeHandle as PlatformVideoModeHandle,
};
use crate::window::{
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
WindowButtons, WindowLevel,
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
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)]
pub struct SharedState {
pub cursor_pos: Option<(f64, f64)>,

View file

@ -23,8 +23,10 @@ use crate::keyboard::{
Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NamedKey, NativeKey, NativeKeyCode,
PhysicalKey,
};
use crate::platform_impl::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>) {
@ -729,9 +731,8 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window(
&self,
window_attributes: crate::window::WindowAttributes,
) -> Result<crate::window::Window, crate::error::OsError> {
let window = crate::platform_impl::Window::new(self, window_attributes)?;
Ok(crate::window::Window { window })
) -> Result<Box<dyn CoreWindow>, crate::error::OsError> {
Ok(Box::new(Window::new(self, window_attributes)?))
}
fn create_custom_cursor(

View file

@ -6,9 +6,9 @@ use super::{
};
use crate::cursor::Cursor;
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
use crate::platform_impl::Fullscreen;
use crate::window::ImePurpose;
use crate::{error, window};
use crate::error;
use crate::monitor::MonitorHandle as CoreMonitorHandle;
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:
// 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> {
let mut buf: [u8; 4096] = [0; 4096];
let path = self
@ -150,36 +142,51 @@ impl Window {
Ok(())
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn id(&self) -> WindowId {
WindowId { fd: self.window_socket.fd as u64 }
fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> {
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]
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
Some(MonitorHandle)
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
Some(CoreMonitorHandle { inner: MonitorHandle })
}
#[inline]
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
let mut v = VecDeque::with_capacity(1);
v.push_back(MonitorHandle);
v
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
Box::new(vec![CoreMonitorHandle { inner: MonitorHandle }].into_iter())
}
#[inline]
pub fn current_monitor(&self) -> Option<MonitorHandle> {
Some(MonitorHandle)
fn current_monitor(&self) -> Option<CoreMonitorHandle> {
Some(CoreMonitorHandle { inner: MonitorHandle })
}
#[inline]
pub fn scale_factor(&self) -> f64 {
fn scale_factor(&self) -> f64 {
MonitorHandle.scale_factor()
}
#[inline]
pub fn request_redraw(&self) {
let window_id = self.id();
fn request_redraw(&self) {
let window_id = self.id().0;
let mut redraws = self.redraws.lock().unwrap();
if !redraws.contains(&window_id) {
redraws.push_back(window_id);
@ -189,15 +196,15 @@ impl Window {
}
#[inline]
pub fn pre_present_notify(&self) {}
fn pre_present_notify(&self) {}
#[inline]
pub fn reset_dead_keys(&self) {
fn reset_dead_keys(&self) {
// TODO?
}
#[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 path = self.window_socket.fpath(&mut buf).expect("failed to read properties");
let properties = WindowProperties::new(path);
@ -205,20 +212,20 @@ impl Window {
}
#[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
self.inner_position()
}
#[inline]
pub fn set_outer_position(&self, position: Position) {
fn set_outer_position(&self, position: Position) {
// TODO: adjust for window decorations
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");
}
#[inline]
pub fn inner_size(&self) -> PhysicalSize<u32> {
fn inner_size(&self) -> PhysicalSize<u32> {
let mut buf: [u8; 4096] = [0; 4096];
let path = self.window_socket.fpath(&mut buf).expect("failed to read properties");
let properties = WindowProperties::new(path);
@ -226,26 +233,26 @@ impl Window {
}
#[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();
self.window_socket.write(format!("S,{w},{h}").as_bytes()).expect("failed to set size");
None
}
#[inline]
pub fn outer_size(&self) -> PhysicalSize<u32> {
fn outer_size(&self) -> PhysicalSize<u32> {
// TODO: adjust for window decorations
self.inner_size()
}
#[inline]
pub fn set_min_inner_size(&self, _: Option<Size>) {}
fn set_min_inner_size(&self, _: Option<Size>) {}
#[inline]
pub fn set_max_inner_size(&self, _: Option<Size>) {}
fn set_max_inner_size(&self, _: Option<Size>) {}
#[inline]
pub fn title(&self) -> String {
fn title(&self) -> String {
let mut buf: [u8; 4096] = [0; 4096];
let path = self.window_socket.fpath(&mut buf).expect("failed to read properties");
let properties = WindowProperties::new(path);
@ -253,84 +260,82 @@ impl Window {
}
#[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");
}
#[inline]
pub fn set_transparent(&self, transparent: bool) {
fn set_transparent(&self, transparent: bool) {
let _ = self.set_flag(ORBITAL_FLAG_TRANSPARENT, transparent);
}
#[inline]
pub fn set_blur(&self, _blur: bool) {}
fn set_blur(&self, _blur: bool) {}
#[inline]
pub fn set_visible(&self, visible: bool) {
fn set_visible(&self, visible: bool) {
let _ = self.set_flag(ORBITAL_FLAG_HIDDEN, !visible);
}
#[inline]
pub fn is_visible(&self) -> Option<bool> {
fn is_visible(&self) -> Option<bool> {
Some(!self.get_flag(ORBITAL_FLAG_HIDDEN).unwrap_or(false))
}
#[inline]
pub fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
fn resize_increments(&self) -> Option<PhysicalSize<u32>> {
None
}
#[inline]
pub fn set_resize_increments(&self, _increments: Option<Size>) {}
fn set_resize_increments(&self, _increments: Option<Size>) {}
#[inline]
pub fn set_resizable(&self, resizeable: bool) {
fn set_resizable(&self, resizeable: bool) {
let _ = self.set_flag(ORBITAL_FLAG_RESIZABLE, resizeable);
}
#[inline]
pub fn is_resizable(&self) -> bool {
fn is_resizable(&self) -> bool {
self.get_flag(ORBITAL_FLAG_RESIZABLE).unwrap_or(false)
}
#[inline]
pub fn set_minimized(&self, _minimized: bool) {}
fn set_minimized(&self, _minimized: bool) {}
#[inline]
pub fn is_minimized(&self) -> Option<bool> {
fn is_minimized(&self) -> Option<bool> {
None
}
#[inline]
pub fn set_maximized(&self, maximized: bool) {
fn set_maximized(&self, maximized: bool) {
let _ = self.set_flag(ORBITAL_FLAG_MAXIMIZED, maximized);
}
#[inline]
pub fn is_maximized(&self) -> bool {
fn is_maximized(&self) -> bool {
self.get_flag(ORBITAL_FLAG_MAXIMIZED).unwrap_or(false)
}
#[inline]
pub(crate) fn set_fullscreen(&self, _monitor: Option<Fullscreen>) {}
fn set_fullscreen(&self, _monitor: Option<Fullscreen>) {}
#[inline]
pub(crate) fn fullscreen(&self) -> Option<Fullscreen> {
fn fullscreen(&self) -> Option<Fullscreen> {
None
}
#[inline]
pub fn set_decorations(&self, decorations: bool) {
fn set_decorations(&self, decorations: bool) {
let _ = self.set_flag(ORBITAL_FLAG_BORDERLESS, !decorations);
}
#[inline]
pub fn is_decorated(&self) -> bool {
fn is_decorated(&self) -> bool {
!self.get_flag(ORBITAL_FLAG_BORDERLESS).unwrap_or(false)
}
#[inline]
pub fn set_window_level(&self, level: window::WindowLevel) {
fn set_window_level(&self, level: window::WindowLevel) {
match level {
window::WindowLevel::AlwaysOnBottom => {
let _ = self.set_flag(ORBITAL_FLAG_BACK, true);
@ -346,36 +351,33 @@ impl Window {
}
#[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]
pub fn set_ime_cursor_area(&self, _position: Position, _size: Size) {}
fn set_ime_cursor_area(&self, _position: Position, _size: Size) {}
#[inline]
pub fn set_ime_allowed(&self, _allowed: bool) {}
fn set_ime_allowed(&self, _allowed: bool) {}
#[inline]
pub fn set_ime_purpose(&self, _purpose: ImePurpose) {}
fn set_ime_purpose(&self, _purpose: ImePurpose) {}
#[inline]
pub fn focus_window(&self) {}
fn focus_window(&self) {}
#[inline]
pub fn request_user_attention(&self, _request_type: Option<window::UserAttentionType>) {}
fn request_user_attention(&self, _request_type: Option<window::UserAttentionType>) {}
#[inline]
pub fn set_cursor(&self, _: Cursor) {}
fn set_cursor(&self, _: Cursor) {}
#[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()))
}
#[inline]
pub fn set_cursor_grab(
&self,
mode: window::CursorGrabMode,
) -> Result<(), error::ExternalError> {
fn set_cursor_grab(&self, mode: window::CursorGrabMode) -> Result<(), error::ExternalError> {
let (grab, relative) = match mode {
window::CursorGrabMode::None => (false, false),
window::CursorGrabMode::Confined => (true, false),
@ -391,12 +393,12 @@ impl Window {
}
#[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());
}
#[inline]
pub fn drag_window(&self) -> Result<(), error::ExternalError> {
fn drag_window(&self) -> Result<(), error::ExternalError> {
self.window_socket
.write(b"D")
.map_err(|err| error::ExternalError::Os(os_error!(OsError::new(err))))?;
@ -404,7 +406,7 @@ impl Window {
}
#[inline]
pub fn drag_resize_window(
fn drag_resize_window(
&self,
direction: window::ResizeDirection,
) -> Result<(), error::ExternalError> {
@ -425,60 +427,68 @@ impl Window {
}
#[inline]
pub fn show_window_menu(&self, _position: Position) {}
fn show_window_menu(&self, _position: Position) {}
#[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()))
}
#[cfg(feature = "rwh_06")]
#[inline]
pub fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> {
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()))
}
fn set_enabled_buttons(&self, _buttons: window::WindowButtons) {}
#[inline]
pub fn set_enabled_buttons(&self, _buttons: window::WindowButtons) {}
#[inline]
pub fn enabled_buttons(&self) -> window::WindowButtons {
fn enabled_buttons(&self) -> window::WindowButtons {
window::WindowButtons::all()
}
#[inline]
pub fn theme(&self) -> Option<window::Theme> {
fn theme(&self) -> Option<window::Theme> {
None
}
#[inline]
pub fn has_focus(&self) -> bool {
fn has_focus(&self) -> bool {
false
}
#[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 {
fn drop(&mut self) {
{
let mut destroys = self.destroys.lock().unwrap();
destroys.push_back(self.id());
destroys.push_back(self.id().0);
}
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::Window;
use crate::window::{
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow,
WindowId as RootWindowId,
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId as RootWindowId,
};
#[derive(Default)]
@ -632,9 +631,9 @@ impl RootActiveEventLoop for ActiveEventLoop {
fn create_window(
&self,
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(RootWindow { window })
Ok(Box::new(window))
}
fn create_custom_cursor(

View file

@ -51,4 +51,3 @@ pub(crate) use self::monitor::{
use self::web_sys as backend;
pub use self::window::{PlatformSpecificWindowAttributes, Window, WindowId};
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::web_sys::{Engine, EventListenerHandle};
use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::platform::web::{
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)]
pub enum OrientationLockFuture {
Future(Notified<Result<(), OrientationLockError>>),

View file

@ -5,15 +5,17 @@ use std::sync::Arc;
use web_sys::HtmlCanvasElement;
use super::main_thread::{MainThreadMarker, MainThreadSafe};
use super::monitor::{MonitorHandle, MonitorHandler};
use super::monitor::MonitorHandler;
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::error::{ExternalError, NotSupportedError, OsError as RootOE};
use crate::icon::Icon;
use crate::monitor::MonitorHandle as RootMonitorHandle;
use crate::window::{
Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType,
WindowAttributes, WindowButtons, WindowId as RootWI, WindowLevel,
Cursor, CursorGrabMode, Fullscreen as RootFullscreen, ImePurpose, ResizeDirection, Theme,
UserAttentionType, Window as RootWindow, WindowAttributes, WindowButtons, WindowId as RootWI,
WindowLevel,
};
pub struct Window {
@ -65,14 +67,6 @@ impl Window {
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>> {
MainThreadMarker::new()
.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())
})
}
}
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")]
#[inline]
pub fn raw_window_handle_rwh_06(&self) -> Result<rwh_06::RawWindowHandle, rwh_06::HandleError> {
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::HasWindowHandle for Window {
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
MainThreadMarker::new()
.map(|main_thread| {
let inner = self.inner.value(main_thread);
@ -102,323 +393,30 @@ impl Window {
let canvas: &wasm_bindgen::JsValue = inner.canvas.raw();
let window_handle =
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)
}
}
#[cfg(feature = "rwh_06")]
#[inline]
pub(crate) fn raw_display_handle_rwh_06(
&self,
) -> Result<rwh_06::RawDisplayHandle, rwh_06::HandleError> {
Ok(rwh_06::RawDisplayHandle::Web(rwh_06::WebDisplayHandle::new()))
#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for Window {
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
Ok(rwh_06::DisplayHandle::web())
}
}
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]
pub fn scale_factor(&self) -> f64 {
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 {

View file

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

View file

@ -16,7 +16,6 @@ use crate::dpi::{PhysicalPosition, PhysicalSize};
use crate::monitor::VideoModeHandle as RootVideoModeHandle;
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::window::Window;
#[derive(Clone)]
pub struct VideoModeHandle {
@ -136,17 +135,6 @@ pub fn current_monitor(hwnd: HWND) -> MonitorHandle {
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> {
let mut monitor_info: MONITORINFOEXW = unsafe { mem::zeroed() };
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)]
fn needs_send<T: Send>() {}
fn needs_send<T: Send + ?Sized>() {}
#[test]
fn event_loop_proxy_send() {
@ -8,7 +8,7 @@ fn event_loop_proxy_send() {
#[test]
fn window_send() {
needs_send::<winit::window::Window>();
needs_send::<dyn winit::window::Window>();
}
#[test]

View file

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