mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
On Unix, add option to pick backends
Add features 'x11' and 'wayland' to pick backends on Linux/BSD, with both enabled by default. Fixes #774.
This commit is contained in:
parent
5a6cfc314e
commit
c1ea0dde92
|
@ -1,4 +1,5 @@
|
|||
# Unreleased
|
||||
- On Unix, X11 and Wayland are now optional features (enabled by default)
|
||||
- On X11, fix deadlock when calling `set_fullscreen_inner`.
|
||||
- On Web, prevent the webpage from scrolling when the user is focused on a winit canvas
|
||||
|
||||
|
|
|
@ -17,8 +17,11 @@ default-target = "x86_64-unknown-linux-gnu"
|
|||
targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "wasm32-unknown-unknown"]
|
||||
|
||||
[features]
|
||||
default = ["x11", "wayland"]
|
||||
web-sys = ["web_sys", "wasm-bindgen", "instant/wasm-bindgen"]
|
||||
stdweb = ["std_web", "instant/stdweb"]
|
||||
x11 = ["x11-dl"]
|
||||
wayland = ["wayland-client", "smithay-client-toolkit"]
|
||||
|
||||
[dependencies]
|
||||
instant = "0.1"
|
||||
|
@ -78,11 +81,11 @@ features = [
|
|||
]
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies]
|
||||
wayland-client = { version = "0.23.0", features = [ "dlopen", "egl", "cursor", "eventloop"] }
|
||||
wayland-client = { version = "0.23.0", features = [ "dlopen", "egl", "cursor", "eventloop"] , optional = true }
|
||||
mio = "0.6"
|
||||
mio-extras = "2.0"
|
||||
smithay-client-toolkit = "^0.6.6"
|
||||
x11-dl = "2.18.5"
|
||||
smithay-client-toolkit = { version = "^0.6.6", optional = true }
|
||||
x11-dl = { version = "2.18.5", optional = true }
|
||||
percent-encoding = "2.0"
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "windows"))'.dependencies.parking_lot]
|
||||
|
|
|
@ -64,6 +64,8 @@ Winit is only officially supported on the latest stable version of the Rust comp
|
|||
|
||||
Winit provides the following features, which can be enabled in your `Cargo.toml` file:
|
||||
* `serde`: Enables serialization/deserialization of certain types with [Serde](https://crates.io/crates/serde).
|
||||
* `x11` (enabled by default): On Unix platform, compiles with the X11 backend
|
||||
* `wayland` (enabled by default): On Unix platform, compiles with the Wayland backend
|
||||
|
||||
### Platform-specific usage
|
||||
|
||||
|
|
21
build.rs
Normal file
21
build.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
#[cfg(all(
|
||||
any(
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
),
|
||||
not(feature = "x11"),
|
||||
not(feature = "wayland")
|
||||
))]
|
||||
compile_error!("at least one of the \"x11\"/\"wayland\" features must be enabled");
|
||||
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
not(feature = "web-sys"),
|
||||
not(feature = "stdweb")
|
||||
))]
|
||||
compile_error!("at least one of the \"web-sys\"/\"stdweb\" features must be enabled");
|
||||
|
||||
fn main() {}
|
|
@ -1,37 +1,46 @@
|
|||
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
|
||||
|
||||
use std::{os::raw, ptr, sync::Arc};
|
||||
use std::os::raw;
|
||||
#[cfg(feature = "x11")]
|
||||
use std::{ptr, sync::Arc};
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
use smithay_client_toolkit::window::{ButtonState as SCTKButtonState, Theme as SCTKTheme};
|
||||
|
||||
use crate::{
|
||||
dpi::Size,
|
||||
event_loop::{EventLoop, EventLoopWindowTarget},
|
||||
monitor::MonitorHandle,
|
||||
window::{Window, WindowBuilder},
|
||||
};
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
use crate::dpi::Size;
|
||||
#[cfg(feature = "x11")]
|
||||
use crate::platform_impl::x11::{ffi::XVisualInfo, XConnection};
|
||||
use crate::platform_impl::{
|
||||
x11::{ffi::XVisualInfo, XConnection},
|
||||
EventLoop as LinuxEventLoop, EventLoopWindowTarget as LinuxEventLoopWindowTarget,
|
||||
Window as LinuxWindow,
|
||||
};
|
||||
|
||||
// TODO: stupid hack so that glutin can do its work
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "x11")]
|
||||
pub use crate::platform_impl::x11;
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported};
|
||||
|
||||
/// Additional methods on `EventLoopWindowTarget` that are specific to Unix.
|
||||
pub trait EventLoopWindowTargetExtUnix {
|
||||
/// True if the `EventLoopWindowTarget` uses Wayland.
|
||||
#[cfg(feature = "wayland")]
|
||||
fn is_wayland(&self) -> bool;
|
||||
///
|
||||
|
||||
/// True if the `EventLoopWindowTarget` uses X11.
|
||||
#[cfg(feature = "x11")]
|
||||
fn is_x11(&self) -> bool;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "x11")]
|
||||
fn xlib_xconnection(&self) -> Option<Arc<XConnection>>;
|
||||
|
||||
/// Returns a pointer to the `wl_display` object of wayland that is used by this
|
||||
|
@ -40,35 +49,42 @@ pub trait EventLoopWindowTargetExtUnix {
|
|||
/// Returns `None` if the `EventLoop` doesn't use wayland (if it uses xlib for example).
|
||||
///
|
||||
/// The pointer will become invalid when the winit `EventLoop` is destroyed.
|
||||
#[cfg(feature = "wayland")]
|
||||
fn wayland_display(&self) -> Option<*mut raw::c_void>;
|
||||
}
|
||||
|
||||
impl<T> EventLoopWindowTargetExtUnix for EventLoopWindowTarget<T> {
|
||||
#[inline]
|
||||
#[cfg(feature = "wayland")]
|
||||
fn is_wayland(&self) -> bool {
|
||||
self.p.is_wayland()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn is_x11(&self) -> bool {
|
||||
!self.p.is_wayland()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "x11")]
|
||||
fn xlib_xconnection(&self) -> Option<Arc<XConnection>> {
|
||||
match self.p {
|
||||
LinuxEventLoopWindowTarget::X(ref e) => Some(e.x_connection().clone()),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "wayland")]
|
||||
fn wayland_display(&self) -> Option<*mut raw::c_void> {
|
||||
match self.p {
|
||||
LinuxEventLoopWindowTarget::Wayland(ref p) => {
|
||||
Some(p.display().get_display_ptr() as *mut _)
|
||||
}
|
||||
#[cfg(feature = "x11")]
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -82,6 +98,7 @@ pub trait EventLoopExtUnix {
|
|||
///
|
||||
/// If called outside the main thread. To initialize an X11 event loop outside
|
||||
/// the main thread, use [`new_x11_any_thread`](#tymethod.new_x11_any_thread).
|
||||
#[cfg(feature = "x11")]
|
||||
fn new_x11() -> Result<Self, XNotSupported>
|
||||
where
|
||||
Self: Sized;
|
||||
|
@ -92,6 +109,7 @@ pub trait EventLoopExtUnix {
|
|||
///
|
||||
/// If called outside the main thread. To initialize a Wayland event loop outside
|
||||
/// the main thread, use [`new_wayland_any_thread`](#tymethod.new_wayland_any_thread).
|
||||
#[cfg(feature = "wayland")]
|
||||
fn new_wayland() -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
|
@ -108,6 +126,7 @@ pub trait EventLoopExtUnix {
|
|||
///
|
||||
/// This method bypasses the cross-platform compatibility requirement
|
||||
/// that `EventLoop` be created on the main thread.
|
||||
#[cfg(feature = "x11")]
|
||||
fn new_x11_any_thread() -> Result<Self, XNotSupported>
|
||||
where
|
||||
Self: Sized;
|
||||
|
@ -116,6 +135,7 @@ pub trait EventLoopExtUnix {
|
|||
///
|
||||
/// This method bypasses the cross-platform compatibility requirement
|
||||
/// that `EventLoop` be created on the main thread.
|
||||
#[cfg(feature = "wayland")]
|
||||
fn new_wayland_any_thread() -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
|
@ -135,11 +155,13 @@ impl<T> EventLoopExtUnix for EventLoop<T> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn new_x11_any_thread() -> Result<Self, XNotSupported> {
|
||||
LinuxEventLoop::new_x11_any_thread().map(wrap_ev)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "wayland")]
|
||||
fn new_wayland_any_thread() -> Self {
|
||||
wrap_ev(
|
||||
LinuxEventLoop::new_wayland_any_thread()
|
||||
|
@ -149,11 +171,13 @@ impl<T> EventLoopExtUnix for EventLoop<T> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn new_x11() -> Result<Self, XNotSupported> {
|
||||
LinuxEventLoop::new_x11().map(wrap_ev)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "wayland")]
|
||||
fn new_wayland() -> Self {
|
||||
wrap_ev(
|
||||
LinuxEventLoop::new_wayland()
|
||||
|
@ -168,6 +192,7 @@ pub trait WindowExtUnix {
|
|||
/// Returns the ID of the `Window` xlib object that is used by this window.
|
||||
///
|
||||
/// Returns `None` if the window doesn't use xlib (if it uses wayland for example).
|
||||
#[cfg(feature = "x11")]
|
||||
fn xlib_window(&self) -> Option<raw::c_ulong>;
|
||||
|
||||
/// Returns a pointer to the `Display` object of xlib that is used by this window.
|
||||
|
@ -175,14 +200,18 @@ pub trait WindowExtUnix {
|
|||
/// Returns `None` if the window doesn't use xlib (if it uses wayland for example).
|
||||
///
|
||||
/// The pointer will become invalid when the glutin `Window` is destroyed.
|
||||
#[cfg(feature = "x11")]
|
||||
fn xlib_display(&self) -> Option<*mut raw::c_void>;
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
fn xlib_screen_id(&self) -> Option<raw::c_int>;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "x11")]
|
||||
fn xlib_xconnection(&self) -> Option<Arc<XConnection>>;
|
||||
|
||||
/// Set window urgency hint (`XUrgencyHint`). Only relevant on X.
|
||||
#[cfg(feature = "x11")]
|
||||
fn set_urgent(&self, is_urgent: bool);
|
||||
|
||||
/// This function returns the underlying `xcb_connection_t` of an xlib `Display`.
|
||||
|
@ -190,6 +219,7 @@ pub trait WindowExtUnix {
|
|||
/// Returns `None` if the window doesn't use xlib (if it uses wayland for example).
|
||||
///
|
||||
/// The pointer will become invalid when the glutin `Window` is destroyed.
|
||||
#[cfg(feature = "x11")]
|
||||
fn xcb_connection(&self) -> Option<*mut raw::c_void>;
|
||||
|
||||
/// Returns a pointer to the `wl_surface` object of wayland that is used by this window.
|
||||
|
@ -197,6 +227,7 @@ pub trait WindowExtUnix {
|
|||
/// Returns `None` if the window doesn't use wayland (if it uses xlib for example).
|
||||
///
|
||||
/// The pointer will become invalid when the glutin `Window` is destroyed.
|
||||
#[cfg(feature = "wayland")]
|
||||
fn wayland_surface(&self) -> Option<*mut raw::c_void>;
|
||||
|
||||
/// Returns a pointer to the `wl_display` object of wayland that is used by this window.
|
||||
|
@ -204,9 +235,11 @@ pub trait WindowExtUnix {
|
|||
/// Returns `None` if the window doesn't use wayland (if it uses xlib for example).
|
||||
///
|
||||
/// The pointer will become invalid when the glutin `Window` is destroyed.
|
||||
#[cfg(feature = "wayland")]
|
||||
fn wayland_display(&self) -> Option<*mut raw::c_void>;
|
||||
|
||||
/// Sets the color theme of the client side window decorations on wayland
|
||||
#[cfg(feature = "wayland")]
|
||||
fn set_wayland_theme<T: Theme>(&self, theme: T);
|
||||
|
||||
/// Check if the window is ready for drawing
|
||||
|
@ -221,73 +254,92 @@ pub trait WindowExtUnix {
|
|||
|
||||
impl WindowExtUnix for Window {
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn xlib_window(&self) -> Option<raw::c_ulong> {
|
||||
match self.window {
|
||||
LinuxWindow::X(ref w) => Some(w.xlib_window()),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn xlib_display(&self) -> Option<*mut raw::c_void> {
|
||||
match self.window {
|
||||
LinuxWindow::X(ref w) => Some(w.xlib_display()),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn xlib_screen_id(&self) -> Option<raw::c_int> {
|
||||
match self.window {
|
||||
LinuxWindow::X(ref w) => Some(w.xlib_screen_id()),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "x11")]
|
||||
fn xlib_xconnection(&self) -> Option<Arc<XConnection>> {
|
||||
match self.window {
|
||||
LinuxWindow::X(ref w) => Some(w.xlib_xconnection()),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn set_urgent(&self, is_urgent: bool) {
|
||||
if let LinuxWindow::X(ref w) = self.window {
|
||||
w.set_urgent(is_urgent);
|
||||
match self.window {
|
||||
LinuxWindow::X(ref w) => w.set_urgent(is_urgent),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn xcb_connection(&self) -> Option<*mut raw::c_void> {
|
||||
match self.window {
|
||||
LinuxWindow::X(ref w) => Some(w.xcb_connection()),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "wayland")]
|
||||
fn wayland_surface(&self) -> Option<*mut raw::c_void> {
|
||||
match self.window {
|
||||
LinuxWindow::Wayland(ref w) => Some(w.surface().as_ref().c_ptr() as *mut _),
|
||||
#[cfg(feature = "x11")]
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "wayland")]
|
||||
fn wayland_display(&self) -> Option<*mut raw::c_void> {
|
||||
match self.window {
|
||||
LinuxWindow::Wayland(ref w) => Some(w.display().as_ref().c_ptr() as *mut _),
|
||||
#[cfg(feature = "x11")]
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "wayland")]
|
||||
fn set_wayland_theme<T: Theme>(&self, theme: T) {
|
||||
match self.window {
|
||||
LinuxWindow::Wayland(ref w) => w.set_theme(WaylandTheme(theme)),
|
||||
#[cfg(feature = "x11")]
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -300,20 +352,28 @@ impl WindowExtUnix for Window {
|
|||
|
||||
/// Additional methods on `WindowBuilder` that are specific to Unix.
|
||||
pub trait WindowBuilderExtUnix {
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_x11_visual<T>(self, visual_infos: *const T) -> Self;
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_x11_screen(self, screen_id: i32) -> Self;
|
||||
|
||||
/// Build window with `WM_CLASS` hint; defaults to the name of the binary. Only relevant on X11.
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_class(self, class: String, instance: String) -> Self;
|
||||
/// Build window with override-redirect flag; defaults to false. Only relevant on X11.
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_override_redirect(self, override_redirect: bool) -> Self;
|
||||
/// Build window with `_NET_WM_WINDOW_TYPE` hints; defaults to `Normal`. Only relevant on X11.
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_x11_window_type(self, x11_window_type: Vec<XWindowType>) -> Self;
|
||||
/// Build window with `_GTK_THEME_VARIANT` hint set to the specified value. Currently only relevant on X11.
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_gtk_theme_variant(self, variant: String) -> Self;
|
||||
/// Build window with resize increment hint. Only implemented on X11.
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_resize_increments<S: Into<Size>>(self, increments: S) -> Self;
|
||||
/// Build window with base size hint. Only implemented on X11.
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_base_size<S: Into<Size>>(self, base_size: S) -> Self;
|
||||
|
||||
/// Build window with a given application ID. It should match the `.desktop` file distributed with
|
||||
|
@ -321,60 +381,72 @@ pub trait WindowBuilderExtUnix {
|
|||
///
|
||||
/// For details about application ID conventions, see the
|
||||
/// [Desktop Entry Spec](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id)
|
||||
#[cfg(feature = "wayland")]
|
||||
fn with_app_id(self, app_id: String) -> Self;
|
||||
}
|
||||
|
||||
impl WindowBuilderExtUnix for WindowBuilder {
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_x11_visual<T>(mut self, visual_infos: *const T) -> Self {
|
||||
self.platform_specific.visual_infos =
|
||||
Some(unsafe { ptr::read(visual_infos as *const XVisualInfo) });
|
||||
{
|
||||
self.platform_specific.visual_infos =
|
||||
Some(unsafe { ptr::read(visual_infos as *const XVisualInfo) });
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_x11_screen(mut self, screen_id: i32) -> Self {
|
||||
self.platform_specific.screen_id = Some(screen_id);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_class(mut self, instance: String, class: String) -> Self {
|
||||
self.platform_specific.class = Some((instance, class));
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_override_redirect(mut self, override_redirect: bool) -> Self {
|
||||
self.platform_specific.override_redirect = override_redirect;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_x11_window_type(mut self, x11_window_types: Vec<XWindowType>) -> Self {
|
||||
self.platform_specific.x11_window_types = x11_window_types;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_gtk_theme_variant(mut self, variant: String) -> Self {
|
||||
self.platform_specific.gtk_theme_variant = Some(variant);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_resize_increments<S: Into<Size>>(mut self, increments: S) -> Self {
|
||||
self.platform_specific.resize_increments = Some(increments.into());
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_base_size<S: Into<Size>>(mut self, base_size: S) -> Self {
|
||||
self.platform_specific.base_size = Some(base_size.into());
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "wayland")]
|
||||
fn with_app_id(mut self, app_id: String) -> Self {
|
||||
self.platform_specific.app_id = Some(app_id);
|
||||
self
|
||||
|
@ -395,6 +467,7 @@ impl MonitorHandleExtUnix for MonitorHandle {
|
|||
}
|
||||
|
||||
/// Wrapper for implementing SCTK's theme trait.
|
||||
#[cfg(feature = "wayland")]
|
||||
struct WaylandTheme<T: Theme>(T);
|
||||
|
||||
pub trait Theme: Send + 'static {
|
||||
|
@ -432,6 +505,7 @@ pub trait Theme: Send + 'static {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
impl<T: Theme> SCTKTheme for WaylandTheme<T> {
|
||||
fn get_primary_color(&self, active: bool) -> [u8; 4] {
|
||||
self.0.primary_color(active)
|
||||
|
@ -478,6 +552,7 @@ pub enum ButtonState {
|
|||
Disabled,
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
impl ButtonState {
|
||||
fn from_sctk(button_state: SCTKButtonState) -> Self {
|
||||
match button_state {
|
||||
|
|
|
@ -1,12 +1,27 @@
|
|||
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
|
||||
#![cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
|
||||
use std::{collections::VecDeque, env, ffi::CStr, fmt, mem::MaybeUninit, os::raw::*, sync::Arc};
|
||||
#[cfg(all(not(feature = "x11"), not(feature = "wayland")))]
|
||||
compile_error!("Please select a feature to build for unix: `x11`, `wayland`");
|
||||
|
||||
use std::{collections::VecDeque, env, fmt};
|
||||
#[cfg(feature = "x11")]
|
||||
use std::{ffi::CStr, mem::MaybeUninit, os::raw::*, sync::Arc};
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
use parking_lot::Mutex;
|
||||
use raw_window_handle::RawWindowHandle;
|
||||
#[cfg(feature = "wayland")]
|
||||
use smithay_client_toolkit::reexports::client::ConnectError;
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
pub use self::x11::XNotSupported;
|
||||
#[cfg(feature = "x11")]
|
||||
use self::x11::{ffi::XVisualInfo, util::WindowType as XWindowType, XConnection, XError};
|
||||
use crate::{
|
||||
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||
|
@ -20,7 +35,9 @@ use crate::{
|
|||
|
||||
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
pub mod wayland;
|
||||
#[cfg(feature = "x11")]
|
||||
pub mod x11;
|
||||
|
||||
/// Environment variable specifying which backend should be used on unix platform.
|
||||
|
@ -34,33 +51,52 @@ const BACKEND_PREFERENCE_ENV_VAR: &str = "WINIT_UNIX_BACKEND";
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct PlatformSpecificWindowBuilderAttributes {
|
||||
#[cfg(feature = "x11")]
|
||||
pub visual_infos: Option<XVisualInfo>,
|
||||
#[cfg(feature = "x11")]
|
||||
pub screen_id: Option<i32>,
|
||||
#[cfg(feature = "x11")]
|
||||
pub resize_increments: Option<Size>,
|
||||
#[cfg(feature = "x11")]
|
||||
pub base_size: Option<Size>,
|
||||
#[cfg(feature = "x11")]
|
||||
pub class: Option<(String, String)>,
|
||||
#[cfg(feature = "x11")]
|
||||
pub override_redirect: bool,
|
||||
#[cfg(feature = "x11")]
|
||||
pub x11_window_types: Vec<XWindowType>,
|
||||
#[cfg(feature = "x11")]
|
||||
pub gtk_theme_variant: Option<String>,
|
||||
#[cfg(feature = "wayland")]
|
||||
pub app_id: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
#[cfg(feature = "x11")]
|
||||
visual_infos: None,
|
||||
#[cfg(feature = "x11")]
|
||||
screen_id: None,
|
||||
#[cfg(feature = "x11")]
|
||||
resize_increments: None,
|
||||
#[cfg(feature = "x11")]
|
||||
base_size: None,
|
||||
#[cfg(feature = "x11")]
|
||||
class: None,
|
||||
#[cfg(feature = "x11")]
|
||||
override_redirect: false,
|
||||
#[cfg(feature = "x11")]
|
||||
x11_window_types: vec![XWindowType::Normal],
|
||||
#[cfg(feature = "x11")]
|
||||
gtk_theme_variant: None,
|
||||
#[cfg(feature = "wayland")]
|
||||
app_id: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
lazy_static! {
|
||||
pub static ref X11_BACKEND: Mutex<Result<Arc<XConnection>, XNotSupported>> =
|
||||
Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new));
|
||||
|
@ -68,141 +104,159 @@ lazy_static! {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum OsError {
|
||||
#[cfg(feature = "x11")]
|
||||
XError(XError),
|
||||
#[cfg(feature = "x11")]
|
||||
XMisc(&'static str),
|
||||
}
|
||||
|
||||
impl fmt::Display for OsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
OsError::XError(e) => f.pad(&e.description),
|
||||
OsError::XMisc(e) => f.pad(e),
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
#[cfg(feature = "x11")]
|
||||
OsError::XError(ref e) => _f.pad(&e.description),
|
||||
#[cfg(feature = "x11")]
|
||||
OsError::XMisc(ref e) => _f.pad(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Window {
|
||||
#[cfg(feature = "x11")]
|
||||
X(x11::Window),
|
||||
#[cfg(feature = "wayland")]
|
||||
Wayland(wayland::Window),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum WindowId {
|
||||
#[cfg(feature = "x11")]
|
||||
X(x11::WindowId),
|
||||
#[cfg(feature = "wayland")]
|
||||
Wayland(wayland::WindowId),
|
||||
}
|
||||
|
||||
impl WindowId {
|
||||
pub unsafe fn dummy() -> Self {
|
||||
WindowId::Wayland(wayland::WindowId::dummy())
|
||||
#[cfg(feature = "wayland")]
|
||||
return WindowId::Wayland(wayland::WindowId::dummy());
|
||||
#[cfg(all(not(feature = "wayland"), feature = "x11"))]
|
||||
return WindowId::X(x11::WindowId::dummy());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum DeviceId {
|
||||
#[cfg(feature = "x11")]
|
||||
X(x11::DeviceId),
|
||||
#[cfg(feature = "wayland")]
|
||||
Wayland(wayland::DeviceId),
|
||||
}
|
||||
|
||||
impl DeviceId {
|
||||
pub unsafe fn dummy() -> Self {
|
||||
DeviceId::Wayland(wayland::DeviceId::dummy())
|
||||
#[cfg(feature = "wayland")]
|
||||
return DeviceId::Wayland(wayland::DeviceId::dummy());
|
||||
#[cfg(all(not(feature = "wayland"), feature = "x11"))]
|
||||
return DeviceId::X(x11::DeviceId::dummy());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum MonitorHandle {
|
||||
#[cfg(feature = "x11")]
|
||||
X(x11::MonitorHandle),
|
||||
#[cfg(feature = "wayland")]
|
||||
Wayland(wayland::MonitorHandle),
|
||||
}
|
||||
|
||||
/// `x11_or_wayland!(match expr; Enum(foo) => foo.something())`
|
||||
/// expands to the equivalent of
|
||||
/// ```ignore
|
||||
/// match self {
|
||||
/// Enum::X(foo) => foo.something(),
|
||||
/// Enum::Wayland(foo) => foo.something(),
|
||||
/// }
|
||||
/// ```
|
||||
/// The result can be converted to another enum by adding `; as AnotherEnum`
|
||||
macro_rules! x11_or_wayland {
|
||||
(match $what:expr; $enum:ident ( $($c1:tt)* ) => $x:expr; as $enum2:ident ) => {
|
||||
match $what {
|
||||
#[cfg(feature = "x11")]
|
||||
$enum::X($($c1)*) => $enum2::X($x),
|
||||
#[cfg(feature = "wayland")]
|
||||
$enum::Wayland($($c1)*) => $enum2::Wayland($x),
|
||||
}
|
||||
};
|
||||
(match $what:expr; $enum:ident ( $($c1:tt)* ) => $x:expr) => {
|
||||
match $what {
|
||||
#[cfg(feature = "x11")]
|
||||
$enum::X($($c1)*) => $x,
|
||||
#[cfg(feature = "wayland")]
|
||||
$enum::Wayland($($c1)*) => $x,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl MonitorHandle {
|
||||
#[inline]
|
||||
pub fn name(&self) -> Option<String> {
|
||||
match self {
|
||||
&MonitorHandle::X(ref m) => m.name(),
|
||||
&MonitorHandle::Wayland(ref m) => m.name(),
|
||||
}
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.name())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn native_identifier(&self) -> u32 {
|
||||
match self {
|
||||
&MonitorHandle::X(ref m) => m.native_identifier(),
|
||||
&MonitorHandle::Wayland(ref m) => m.native_identifier(),
|
||||
}
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.native_identifier())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn size(&self) -> PhysicalSize<u32> {
|
||||
match self {
|
||||
&MonitorHandle::X(ref m) => m.size(),
|
||||
&MonitorHandle::Wayland(ref m) => m.size(),
|
||||
}
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.size())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn position(&self) -> PhysicalPosition<i32> {
|
||||
match self {
|
||||
&MonitorHandle::X(ref m) => m.position(),
|
||||
&MonitorHandle::Wayland(ref m) => m.position(),
|
||||
}
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.position())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
match self {
|
||||
&MonitorHandle::X(ref m) => m.scale_factor(),
|
||||
&MonitorHandle::Wayland(ref m) => m.scale_factor() as f64,
|
||||
}
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.scale_factor() as f64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn video_modes(&self) -> Box<dyn Iterator<Item = RootVideoMode>> {
|
||||
match self {
|
||||
MonitorHandle::X(m) => Box::new(m.video_modes()),
|
||||
MonitorHandle::Wayland(m) => Box::new(m.video_modes()),
|
||||
}
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => Box::new(m.video_modes()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum VideoMode {
|
||||
#[cfg(feature = "x11")]
|
||||
X(x11::VideoMode),
|
||||
#[cfg(feature = "wayland")]
|
||||
Wayland(wayland::VideoMode),
|
||||
}
|
||||
|
||||
impl VideoMode {
|
||||
#[inline]
|
||||
pub fn size(&self) -> PhysicalSize<u32> {
|
||||
match self {
|
||||
&VideoMode::X(ref m) => m.size(),
|
||||
&VideoMode::Wayland(ref m) => m.size(),
|
||||
}
|
||||
x11_or_wayland!(match self; VideoMode(m) => m.size())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bit_depth(&self) -> u16 {
|
||||
match self {
|
||||
&VideoMode::X(ref m) => m.bit_depth(),
|
||||
&VideoMode::Wayland(ref m) => m.bit_depth(),
|
||||
}
|
||||
x11_or_wayland!(match self; VideoMode(m) => m.bit_depth())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn refresh_rate(&self) -> u16 {
|
||||
match self {
|
||||
&VideoMode::X(ref m) => m.refresh_rate(),
|
||||
&VideoMode::Wayland(ref m) => m.refresh_rate(),
|
||||
}
|
||||
x11_or_wayland!(match self; VideoMode(m) => m.refresh_rate())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn monitor(&self) -> RootMonitorHandle {
|
||||
match self {
|
||||
&VideoMode::X(ref m) => m.monitor(),
|
||||
&VideoMode::Wayland(ref m) => m.monitor(),
|
||||
}
|
||||
x11_or_wayland!(match self; VideoMode(m) => m.monitor())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,9 +268,11 @@ impl Window {
|
|||
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
||||
) -> Result<Self, RootOsError> {
|
||||
match *window_target {
|
||||
#[cfg(feature = "wayland")]
|
||||
EventLoopWindowTarget::Wayland(ref window_target) => {
|
||||
wayland::Window::new(window_target, attribs, pl_attribs).map(Window::Wayland)
|
||||
}
|
||||
#[cfg(feature = "x11")]
|
||||
EventLoopWindowTarget::X(ref window_target) => {
|
||||
x11::Window::new(window_target, attribs, pl_attribs).map(Window::X)
|
||||
}
|
||||
|
@ -225,232 +281,166 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn id(&self) -> WindowId {
|
||||
match self {
|
||||
&Window::X(ref w) => WindowId::X(w.id()),
|
||||
&Window::Wayland(ref w) => WindowId::Wayland(w.id()),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.id(); as WindowId)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_title(&self, title: &str) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_title(title),
|
||||
&Window::Wayland(ref w) => w.set_title(title),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_title(title));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_visible(&self, visible: bool) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_visible(visible),
|
||||
&Window::Wayland(ref w) => w.set_visible(visible),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_visible(visible))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
|
||||
match self {
|
||||
&Window::X(ref w) => w.outer_position(),
|
||||
&Window::Wayland(ref w) => w.outer_position(),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.outer_position())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
|
||||
match self {
|
||||
&Window::X(ref m) => m.inner_position(),
|
||||
&Window::Wayland(ref m) => m.inner_position(),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.inner_position())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_outer_position(&self, position: Position) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_outer_position(position),
|
||||
&Window::Wayland(ref w) => w.set_outer_position(position),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_outer_position(position))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn inner_size(&self) -> PhysicalSize<u32> {
|
||||
match self {
|
||||
&Window::X(ref w) => w.inner_size(),
|
||||
&Window::Wayland(ref w) => w.inner_size(),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.inner_size())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn outer_size(&self) -> PhysicalSize<u32> {
|
||||
match self {
|
||||
&Window::X(ref w) => w.outer_size(),
|
||||
&Window::Wayland(ref w) => w.outer_size(),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.outer_size())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_inner_size(&self, size: Size) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_inner_size(size),
|
||||
&Window::Wayland(ref w) => w.set_inner_size(size),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_inner_size(size))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_min_inner_size(&self, dimensions: Option<Size>) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_min_inner_size(dimensions),
|
||||
&Window::Wayland(ref w) => w.set_min_inner_size(dimensions),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_min_inner_size(dimensions))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_max_inner_size(&self, dimensions: Option<Size>) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_max_inner_size(dimensions),
|
||||
&Window::Wayland(ref w) => w.set_max_inner_size(dimensions),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_max_inner_size(dimensions))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_resizable(&self, resizable: bool) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_resizable(resizable),
|
||||
&Window::Wayland(ref w) => w.set_resizable(resizable),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_resizable(resizable))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_cursor_icon(&self, cursor: CursorIcon) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_cursor_icon(cursor),
|
||||
&Window::Wayland(ref w) => w.set_cursor_icon(cursor),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_cursor_icon(cursor))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> {
|
||||
match self {
|
||||
&Window::X(ref window) => window.set_cursor_grab(grab),
|
||||
&Window::Wayland(ref window) => window.set_cursor_grab(grab),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(window) => window.set_cursor_grab(grab))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_cursor_visible(&self, visible: bool) {
|
||||
match self {
|
||||
&Window::X(ref window) => window.set_cursor_visible(visible),
|
||||
&Window::Wayland(ref window) => window.set_cursor_visible(visible),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(window) => window.set_cursor_visible(visible))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
match self {
|
||||
&Window::X(ref w) => w.scale_factor(),
|
||||
&Window::Wayland(ref w) => w.scale_factor() as f64,
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.scale_factor() as f64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_cursor_position(&self, position: Position) -> Result<(), ExternalError> {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_cursor_position(position),
|
||||
&Window::Wayland(ref w) => w.set_cursor_position(position),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_cursor_position(position))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_maximized(&self, maximized: bool) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_maximized(maximized),
|
||||
&Window::Wayland(ref w) => w.set_maximized(maximized),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_maximized(maximized))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_minimized(&self, minimized: bool) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_minimized(minimized),
|
||||
&Window::Wayland(ref w) => w.set_minimized(minimized),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.set_minimized(minimized))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fullscreen(&self) -> Option<Fullscreen> {
|
||||
match self {
|
||||
&Window::X(ref w) => w.fullscreen(),
|
||||
&Window::Wayland(ref w) => w.fullscreen(),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.fullscreen())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_fullscreen(&self, monitor: Option<Fullscreen>) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_fullscreen(monitor),
|
||||
&Window::Wayland(ref w) => w.set_fullscreen(monitor),
|
||||
}
|
||||
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 set_always_on_top(&self, _always_on_top: bool) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_decorations(decorations),
|
||||
&Window::Wayland(ref w) => w.set_decorations(decorations),
|
||||
#[cfg(feature = "x11")]
|
||||
&Window::X(ref w) => w.set_always_on_top(_always_on_top),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_always_on_top(&self, always_on_top: bool) {
|
||||
pub fn set_window_icon(&self, _window_icon: Option<Icon>) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_always_on_top(always_on_top),
|
||||
&Window::Wayland(_) => (),
|
||||
#[cfg(feature = "x11")]
|
||||
&Window::X(ref w) => w.set_window_icon(_window_icon),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_window_icon(&self, window_icon: Option<Icon>) {
|
||||
pub fn set_ime_position(&self, _position: Position) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_window_icon(window_icon),
|
||||
&Window::Wayland(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_ime_position(&self, position: Position) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.set_ime_position(position),
|
||||
&Window::Wayland(_) => (),
|
||||
#[cfg(feature = "x11")]
|
||||
&Window::X(ref w) => w.set_ime_position(_position),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn request_redraw(&self) {
|
||||
match self {
|
||||
&Window::X(ref w) => w.request_redraw(),
|
||||
&Window::Wayland(ref w) => w.request_redraw(),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(w) => w.request_redraw())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn current_monitor(&self) -> RootMonitorHandle {
|
||||
match self {
|
||||
&Window::X(ref window) => RootMonitorHandle {
|
||||
inner: MonitorHandle::X(window.current_monitor()),
|
||||
},
|
||||
&Window::Wayland(ref window) => RootMonitorHandle {
|
||||
inner: MonitorHandle::Wayland(window.current_monitor()),
|
||||
},
|
||||
RootMonitorHandle {
|
||||
inner: x11_or_wayland!(match self; Window(window) => window.current_monitor(); as MonitorHandle),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
|
||||
match self {
|
||||
#[cfg(feature = "x11")]
|
||||
&Window::X(ref window) => window
|
||||
.available_monitors()
|
||||
.into_iter()
|
||||
.map(MonitorHandle::X)
|
||||
.collect(),
|
||||
#[cfg(feature = "wayland")]
|
||||
&Window::Wayland(ref window) => window
|
||||
.available_monitors()
|
||||
.into_iter()
|
||||
|
@ -461,20 +451,20 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn primary_monitor(&self) -> MonitorHandle {
|
||||
match self {
|
||||
&Window::X(ref window) => MonitorHandle::X(window.primary_monitor()),
|
||||
&Window::Wayland(ref window) => MonitorHandle::Wayland(window.primary_monitor()),
|
||||
}
|
||||
x11_or_wayland!(match self; Window(window) => window.primary_monitor(); as MonitorHandle)
|
||||
}
|
||||
|
||||
pub fn raw_window_handle(&self) -> RawWindowHandle {
|
||||
match self {
|
||||
#[cfg(feature = "x11")]
|
||||
&Window::X(ref window) => RawWindowHandle::Xlib(window.raw_window_handle()),
|
||||
#[cfg(feature = "wayland")]
|
||||
&Window::Wayland(ref window) => RawWindowHandle::Wayland(window.raw_window_handle()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
unsafe extern "C" fn x_error_callback(
|
||||
display: *mut x11::ffi::Display,
|
||||
event: *mut x11::ffi::XErrorEvent,
|
||||
|
@ -508,21 +498,22 @@ unsafe extern "C" fn x_error_callback(
|
|||
}
|
||||
|
||||
pub enum EventLoop<T: 'static> {
|
||||
#[cfg(feature = "wayland")]
|
||||
Wayland(wayland::EventLoop<T>),
|
||||
#[cfg(feature = "x11")]
|
||||
X(x11::EventLoop<T>),
|
||||
}
|
||||
|
||||
pub enum EventLoopProxy<T: 'static> {
|
||||
#[cfg(feature = "x11")]
|
||||
X(x11::EventLoopProxy<T>),
|
||||
#[cfg(feature = "wayland")]
|
||||
Wayland(wayland::EventLoopProxy<T>),
|
||||
}
|
||||
|
||||
impl<T: 'static> Clone for EventLoopProxy<T> {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
EventLoopProxy::X(proxy) => EventLoopProxy::X(proxy.clone()),
|
||||
EventLoopProxy::Wayland(proxy) => EventLoopProxy::Wayland(proxy.clone()),
|
||||
}
|
||||
x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.clone(); as EventLoopProxy)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -538,12 +529,18 @@ impl<T: 'static> EventLoop<T> {
|
|||
match env_var.as_str() {
|
||||
"x11" => {
|
||||
// TODO: propagate
|
||||
#[cfg(feature = "x11")]
|
||||
return EventLoop::new_x11_any_thread()
|
||||
.expect("Failed to initialize X11 backend");
|
||||
#[cfg(not(feature = "x11"))]
|
||||
panic!("x11 feature is not enabled")
|
||||
}
|
||||
"wayland" => {
|
||||
#[cfg(feature = "wayland")]
|
||||
return EventLoop::new_wayland_any_thread()
|
||||
.expect("Failed to initialize Wayland backend");
|
||||
#[cfg(not(feature = "wayland"))]
|
||||
panic!("wayland feature is not enabled");
|
||||
}
|
||||
_ => panic!(
|
||||
"Unknown environment variable value for {}, try one of `x11`,`wayland`",
|
||||
|
@ -552,16 +549,23 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
let wayland_err = match EventLoop::new_wayland_any_thread() {
|
||||
Ok(event_loop) => return event_loop,
|
||||
Err(err) => err,
|
||||
};
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
let x11_err = match EventLoop::new_x11_any_thread() {
|
||||
Ok(event_loop) => return event_loop,
|
||||
Err(err) => err,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "wayland"))]
|
||||
let wayland_err = "backend disabled";
|
||||
#[cfg(not(feature = "x11"))]
|
||||
let x11_err = "backend disabled";
|
||||
|
||||
let err_string = format!(
|
||||
"Failed to initialize any backend! Wayland status: {:?} X11 status: {:?}",
|
||||
wayland_err, x11_err,
|
||||
|
@ -569,22 +573,26 @@ impl<T: 'static> EventLoop<T> {
|
|||
panic!(err_string);
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
pub fn new_wayland() -> Result<EventLoop<T>, ConnectError> {
|
||||
assert_is_main_thread("new_wayland_any_thread");
|
||||
|
||||
EventLoop::new_wayland_any_thread()
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
pub fn new_wayland_any_thread() -> Result<EventLoop<T>, ConnectError> {
|
||||
wayland::EventLoop::new().map(EventLoop::Wayland)
|
||||
}
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
pub fn new_x11() -> Result<EventLoop<T>, XNotSupported> {
|
||||
assert_is_main_thread("new_x11_any_thread");
|
||||
|
||||
EventLoop::new_x11_any_thread()
|
||||
}
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
pub fn new_x11_any_thread() -> Result<EventLoop<T>, XNotSupported> {
|
||||
let xconn = match X11_BACKEND.lock().as_ref() {
|
||||
Ok(xconn) => xconn.clone(),
|
||||
|
@ -597,11 +605,13 @@ impl<T: 'static> EventLoop<T> {
|
|||
#[inline]
|
||||
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
|
||||
match *self {
|
||||
#[cfg(feature = "wayland")]
|
||||
EventLoop::Wayland(ref evlp) => evlp
|
||||
.available_monitors()
|
||||
.into_iter()
|
||||
.map(MonitorHandle::Wayland)
|
||||
.collect(),
|
||||
#[cfg(feature = "x11")]
|
||||
EventLoop::X(ref evlp) => evlp
|
||||
.x_connection()
|
||||
.available_monitors()
|
||||
|
@ -614,57 +624,46 @@ impl<T: 'static> EventLoop<T> {
|
|||
#[inline]
|
||||
pub fn primary_monitor(&self) -> MonitorHandle {
|
||||
match *self {
|
||||
#[cfg(feature = "wayland")]
|
||||
EventLoop::Wayland(ref evlp) => MonitorHandle::Wayland(evlp.primary_monitor()),
|
||||
#[cfg(feature = "x11")]
|
||||
EventLoop::X(ref evlp) => MonitorHandle::X(evlp.x_connection().primary_monitor()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
||||
match *self {
|
||||
EventLoop::Wayland(ref evlp) => EventLoopProxy::Wayland(evlp.create_proxy()),
|
||||
EventLoop::X(ref evlp) => EventLoopProxy::X(evlp.create_proxy()),
|
||||
}
|
||||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy)
|
||||
}
|
||||
|
||||
pub fn run_return<F>(&mut self, callback: F)
|
||||
where
|
||||
F: FnMut(crate::event::Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
match *self {
|
||||
EventLoop::Wayland(ref mut evlp) => evlp.run_return(callback),
|
||||
EventLoop::X(ref mut evlp) => evlp.run_return(callback),
|
||||
}
|
||||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_return(callback))
|
||||
}
|
||||
|
||||
pub fn run<F>(self, callback: F) -> !
|
||||
where
|
||||
F: 'static + FnMut(crate::event::Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
match self {
|
||||
EventLoop::Wayland(evlp) => evlp.run(callback),
|
||||
EventLoop::X(evlp) => evlp.run(callback),
|
||||
}
|
||||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.run(callback))
|
||||
}
|
||||
|
||||
pub fn window_target(&self) -> &crate::event_loop::EventLoopWindowTarget<T> {
|
||||
match *self {
|
||||
EventLoop::Wayland(ref evl) => evl.window_target(),
|
||||
EventLoop::X(ref evl) => evl.window_target(),
|
||||
}
|
||||
x11_or_wayland!(match self; EventLoop(evl) => evl.window_target())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> EventLoopProxy<T> {
|
||||
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
|
||||
match *self {
|
||||
EventLoopProxy::Wayland(ref proxy) => proxy.send_event(event),
|
||||
EventLoopProxy::X(ref proxy) => proxy.send_event(event),
|
||||
}
|
||||
x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.send_event(event))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum EventLoopWindowTarget<T> {
|
||||
#[cfg(feature = "wayland")]
|
||||
Wayland(wayland::EventLoopWindowTarget<T>),
|
||||
#[cfg(feature = "x11")]
|
||||
X(x11::EventLoopWindowTarget<T>),
|
||||
}
|
||||
|
||||
|
@ -672,8 +671,10 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
#[inline]
|
||||
pub fn is_wayland(&self) -> bool {
|
||||
match *self {
|
||||
#[cfg(feature = "wayland")]
|
||||
EventLoopWindowTarget::Wayland(_) => true,
|
||||
EventLoopWindowTarget::X(_) => false,
|
||||
#[cfg(feature = "x11")]
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -554,6 +554,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
let instant_wakeup = {
|
||||
let window_target = match self.window_target.p {
|
||||
crate::platform_impl::EventLoopWindowTarget::Wayland(ref wt) => wt,
|
||||
#[cfg(feature = "x11")]
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let dispatched = window_target
|
||||
|
@ -662,6 +663,7 @@ impl<T> EventLoop<T> {
|
|||
{
|
||||
let window_target = match self.window_target.p {
|
||||
crate::platform_impl::EventLoopWindowTarget::Wayland(ref wt) => wt,
|
||||
#[cfg(feature = "x11")]
|
||||
_ => unreachable!(),
|
||||
};
|
||||
window_target.store.lock().unwrap().for_each_redraw_trigger(
|
||||
|
@ -689,6 +691,7 @@ impl<T> EventLoop<T> {
|
|||
{
|
||||
let window_target = match self.window_target.p {
|
||||
crate::platform_impl::EventLoopWindowTarget::Wayland(ref wt) => wt,
|
||||
#[cfg(feature = "x11")]
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
@ -803,6 +806,7 @@ impl<T> EventLoop<T> {
|
|||
fn get_target<T>(target: &RootELW<T>) -> &EventLoopWindowTarget<T> {
|
||||
match target.p {
|
||||
crate::platform_impl::EventLoopWindowTarget::Wayland(ref wt) => wt,
|
||||
#[cfg(feature = "x11")]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,6 +158,7 @@ impl Window {
|
|||
Some(Fullscreen::Borderless(RootMonitorHandle {
|
||||
inner: PlatformMonitorHandle::Wayland(ref monitor_id),
|
||||
})) => frame.set_fullscreen(Some(&monitor_id.proxy)),
|
||||
#[cfg(feature = "x11")]
|
||||
Some(Fullscreen::Borderless(_)) => unreachable!(),
|
||||
None => {
|
||||
if attributes.maximized {
|
||||
|
@ -354,6 +355,7 @@ impl Window {
|
|||
.unwrap()
|
||||
.set_fullscreen(Some(&monitor_id.proxy));
|
||||
}
|
||||
#[cfg(feature = "x11")]
|
||||
Some(Fullscreen::Borderless(_)) => unreachable!(),
|
||||
None => self.frame.lock().unwrap().unset_fullscreen(),
|
||||
}
|
||||
|
|
|
@ -426,6 +426,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
pub(crate) fn get_xtarget<T>(target: &RootELW<T>) -> &EventLoopWindowTarget<T> {
|
||||
match target.p {
|
||||
super::EventLoopWindowTarget::X(ref target) => target,
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -493,9 +494,21 @@ impl<'a> Deref for DeviceInfo<'a> {
|
|||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct WindowId(ffi::Window);
|
||||
|
||||
impl WindowId {
|
||||
pub unsafe fn dummy() -> Self {
|
||||
WindowId(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId(c_int);
|
||||
|
||||
impl DeviceId {
|
||||
pub unsafe fn dummy() -> Self {
|
||||
DeviceId(0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Window(Arc<UnownedWindow>);
|
||||
|
||||
impl Deref for Window {
|
||||
|
|
|
@ -653,6 +653,7 @@ impl UnownedWindow {
|
|||
Fullscreen::Borderless(RootMonitorHandle {
|
||||
inner: PlatformMonitorHandle::X(ref monitor),
|
||||
}) => (None, monitor),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue