#![cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
use std::{os::raw::c_int, sync::Arc};
#[doc(hidden)]
pub use crate::platform_impl::x11;
pub use crate::platform_impl::{hit_test, EventLoop as UnixEventLoop};
use crate::{
event_loop::{EventLoop, EventLoopWindowTarget},
platform_impl::{x11::xdisplay::XError, Parent},
window::{Window, WindowBuilder},
};
use self::x11::xdisplay::XConnection;
pub trait WindowExtUnix {
fn gtk_window(&self) -> >k::ApplicationWindow;
fn set_skip_taskbar(&self, skip: bool);
}
impl WindowExtUnix for Window {
fn gtk_window(&self) -> >k::ApplicationWindow {
&self.window.window
}
fn set_skip_taskbar(&self, skip: bool) {
self.window.set_skip_taskbar(skip);
}
}
pub trait WindowBuilderExtUnix {
fn with_skip_taskbar(self, skip: bool) -> WindowBuilder;
fn with_transient_for(self, parent: gtk::ApplicationWindow) -> WindowBuilder;
fn with_transparent_draw(self, draw: bool) -> WindowBuilder;
fn with_double_buffered(self, double_buffered: bool) -> WindowBuilder;
fn with_rgba_visual(self, rgba_visual: bool) -> WindowBuilder;
fn with_app_paintable(self, app_paintable: bool) -> WindowBuilder;
fn with_cursor_moved_event(self, cursor_moved: bool) -> WindowBuilder;
}
impl WindowBuilderExtUnix for WindowBuilder {
fn with_skip_taskbar(mut self, skip: bool) -> WindowBuilder {
self.platform_specific.skip_taskbar = skip;
self
}
fn with_transient_for(mut self, parent: gtk::ApplicationWindow) -> WindowBuilder {
self.platform_specific.parent = Parent::ChildOf(parent);
self
}
fn with_transparent_draw(mut self, draw: bool) -> WindowBuilder {
self.platform_specific.auto_transparent = draw;
self
}
fn with_double_buffered(mut self, double_buffered: bool) -> WindowBuilder {
self.platform_specific.double_buffered = double_buffered;
self
}
fn with_rgba_visual(mut self, rgba_visual: bool) -> WindowBuilder {
self.platform_specific.rgba_visual = rgba_visual;
self
}
fn with_app_paintable(mut self, app_paintable: bool) -> WindowBuilder {
self.platform_specific.app_paintable = app_paintable;
self
}
fn with_cursor_moved_event(mut self, cursor_moved: bool) -> WindowBuilder {
self.platform_specific.cursor_moved = cursor_moved;
self
}
}
pub trait EventLoopExtUnix {
fn new_any_thread() -> Self
where
Self: Sized;
}
fn wrap_ev<T>(event_loop: UnixEventLoop<T>) -> EventLoop<T> {
EventLoop {
event_loop,
_marker: std::marker::PhantomData,
}
}
impl<T> EventLoopExtUnix for EventLoop<T> {
#[inline]
fn new_any_thread() -> Self {
wrap_ev(UnixEventLoop::new_any_thread())
}
}
pub trait EventLoopWindowTargetExtUnix {
fn is_wayland(&self) -> bool;
fn is_x11(&self) -> bool;
fn xlib_xconnection(&self) -> Option<Arc<XConnection>>;
}
impl<T> EventLoopWindowTargetExtUnix for EventLoopWindowTarget<T> {
#[inline]
fn is_wayland(&self) -> bool {
self.p.is_wayland()
}
#[inline]
fn is_x11(&self) -> bool {
!self.p.is_wayland()
}
#[inline]
fn xlib_xconnection(&self) -> Option<Arc<XConnection>> {
if self.is_x11() {
if let Ok(xconn) = XConnection::new(Some(x_error_callback)) {
Some(Arc::new(xconn))
} else {
None
}
} else {
None
}
}
}
unsafe extern "C" fn x_error_callback(
_display: *mut x11::ffi::Display,
event: *mut x11::ffi::XErrorEvent,
) -> c_int {
let error = XError {
description: String::new(),
error_code: (*event).error_code,
request_code: (*event).request_code,
minor_code: (*event).minor_code,
};
error!("X11 error: {:#?}", error);
0
}