|
|
|
|
@@ -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,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|