#![cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
#[cfg(feature = "x11")]
use std::{os::raw::c_int, sync::Arc};
#[doc(hidden)]
#[cfg(feature = "x11")]
pub use crate::platform_impl::x11;
#[cfg(feature = "x11")]
use crate::platform_impl::x11::xdisplay::XError;
pub use crate::platform_impl::EventLoop as UnixEventLoop;
use crate::{
error::{ExternalError, OsError},
event_loop::{EventLoopBuilder, EventLoopWindowTarget},
monitor::MonitorHandle,
platform_impl::{Parent, Window as UnixWindow},
window::{Window, WindowBuilder},
};
#[cfg(feature = "x11")]
use self::x11::xdisplay::XConnection;
pub trait EventLoopBuilderExtUnix {
fn with_any_thread(&mut self, any_thread: bool) -> &mut Self;
fn with_app_id<S: Into<String>>(&mut self, id: S) -> &mut Self;
}
impl<T> EventLoopBuilderExtUnix for EventLoopBuilder<T> {
#[inline]
fn with_any_thread(&mut self, any_thread: bool) -> &mut Self {
self.platform_specific.any_thread = any_thread;
self
}
fn with_app_id<S: Into<String>>(&mut self, id: S) -> &mut Self {
self.platform_specific.app_id = Some(id.into());
self
}
}
pub trait WindowExtUnix {
fn new_from_gtk_window<T: 'static>(
event_loop_window_target: &EventLoopWindowTarget<T>,
window: gtk::ApplicationWindow,
) -> Result<Window, OsError>;
fn gtk_window(&self) -> >k::ApplicationWindow;
fn default_vbox(&self) -> Option<>k::Box>;
fn set_skip_taskbar(&self, skip: bool) -> Result<(), ExternalError>;
fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>);
}
impl WindowExtUnix for Window {
fn gtk_window(&self) -> >k::ApplicationWindow {
&self.window.window
}
fn default_vbox(&self) -> Option<>k::Box> {
self.window.default_vbox.as_ref()
}
fn set_skip_taskbar(&self, skip: bool) -> Result<(), ExternalError> {
self.window.set_skip_taskbar(skip)
}
fn new_from_gtk_window<T: 'static>(
event_loop_window_target: &EventLoopWindowTarget<T>,
window: gtk::ApplicationWindow,
) -> Result<Window, OsError> {
let window = UnixWindow::new_from_gtk_window(&event_loop_window_target.p, window)?;
Ok(Window { window })
}
fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>) {
self.window.set_badge_count(count, desktop_filename);
}
}
pub trait WindowBuilderExtUnix {
fn with_skip_taskbar(self, skip: bool) -> WindowBuilder;
fn with_transient_for(self, parent: &impl gtk::glib::IsA<gtk::Window>) -> 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;
fn with_default_vbox(self, add: 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: &impl gtk::glib::IsA<gtk::Window>) -> WindowBuilder {
use gtk::glib::Cast;
self.platform_specific.parent = Parent::ChildOf(parent.clone().upcast());
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
}
fn with_default_vbox(mut self, add: bool) -> WindowBuilder {
self.platform_specific.default_vbox = add;
self
}
}
pub trait EventLoopWindowTargetExtUnix {
fn is_wayland(&self) -> bool;
#[cfg(feature = "x11")]
fn is_x11(&self) -> bool;
#[cfg(feature = "x11")]
fn xlib_xconnection(&self) -> Option<Arc<XConnection>>;
fn gtk_app(&self) -> >k::Application;
fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>);
}
impl<T> EventLoopWindowTargetExtUnix for EventLoopWindowTarget<T> {
#[inline]
fn is_wayland(&self) -> bool {
self.p.is_wayland()
}
#[cfg(feature = "x11")]
#[inline]
fn is_x11(&self) -> bool {
!self.p.is_wayland()
}
#[cfg(feature = "x11")]
#[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
}
}
#[inline]
fn gtk_app(&self) -> >k::Application {
&self.p.app
}
#[inline]
fn set_badge_count(&self, count: Option<i64>, desktop_filename: Option<String>) {
self.p.set_badge_count(count, desktop_filename);
}
}
#[cfg(feature = "x11")]
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
}
pub trait MonitorHandleExtUnix {
fn gdk_monitor(&self) -> >k::gdk::Monitor;
}
impl MonitorHandleExtUnix for MonitorHandle {
#[inline]
fn gdk_monitor(&self) -> >k::gdk::Monitor {
&self.inner.monitor
}
}