maolan_plugin_host/
gui_x11.rs1#[cfg(all(unix, not(target_os = "macos")))]
4pub mod x11 {
5 use std::os::raw::{c_char, c_int, c_uint, c_ulong};
6
7 pub type Display = std::ffi::c_void;
8 pub type Window = c_ulong;
9
10 #[link(name = "X11")]
11 unsafe extern "C" {
12 pub fn XOpenDisplay(display_name: *const c_char) -> *mut Display;
13 pub fn XCloseDisplay(display: *mut Display) -> c_int;
14 pub fn XDefaultScreen(display: *mut Display) -> c_int;
15 pub fn XRootWindow(display: *mut Display, screen: c_int) -> Window;
16 pub fn XBlackPixel(display: *mut Display, screen: c_int) -> c_ulong;
17 pub fn XWhitePixel(display: *mut Display, screen: c_int) -> c_ulong;
18 pub fn XCreateSimpleWindow(
19 display: *mut Display,
20 parent: Window,
21 x: c_int,
22 y: c_int,
23 width: c_uint,
24 height: c_uint,
25 border_width: c_uint,
26 border: c_ulong,
27 background: c_ulong,
28 ) -> Window;
29 pub fn XStoreName(display: *mut Display, w: Window, name: *const c_char) -> c_int;
30 pub fn XMapWindow(display: *mut Display, w: Window) -> c_int;
31 pub fn XUnmapWindow(display: *mut Display, w: Window) -> c_int;
32 pub fn XDestroyWindow(display: *mut Display, w: Window) -> c_int;
33 pub fn XResizeWindow(
34 display: *mut Display,
35 w: Window,
36 width: c_uint,
37 height: c_uint,
38 ) -> c_int;
39 pub fn XFlush(display: *mut Display) -> c_int;
40 }
41
42 pub struct ContainerWindow {
43 display: *mut Display,
44 window: Window,
45 }
46
47 unsafe impl Send for ContainerWindow {}
48
49 impl ContainerWindow {
50 pub fn window(&self) -> Window {
51 self.window
52 }
53
54 pub fn map(&self) {
55 unsafe {
56 XMapWindow(self.display, self.window);
57 XFlush(self.display);
58 }
59 }
60
61 pub fn unmap(&self) {
62 unsafe {
63 XUnmapWindow(self.display, self.window);
64 XFlush(self.display);
65 }
66 }
67
68 pub fn resize(&self, width: u32, height: u32) {
69 unsafe {
70 XResizeWindow(self.display, self.window, width, height);
71 XFlush(self.display);
72 }
73 }
74 }
75
76 impl Drop for ContainerWindow {
77 fn drop(&mut self) {
78 unsafe {
79 XDestroyWindow(self.display, self.window);
80 XFlush(self.display);
81 XCloseDisplay(self.display);
82 }
83 }
84 }
85
86 pub fn create_container_window(
87 display_name: Option<&str>,
88 parent: Option<Window>,
89 title: &str,
90 width: u32,
91 height: u32,
92 ) -> Result<ContainerWindow, String> {
93 let display_name_c = display_name.and_then(|s| std::ffi::CString::new(s).ok());
94 let display_name_ptr = display_name_c
95 .as_ref()
96 .map(|s| s.as_ptr())
97 .unwrap_or(std::ptr::null());
98
99 let display = unsafe { XOpenDisplay(display_name_ptr) };
100 if display.is_null() {
101 return Err("failed to open X11 display".to_string());
102 }
103
104 let screen = unsafe { XDefaultScreen(display) };
105 let root = unsafe { XRootWindow(display, screen) };
106 let black = unsafe { XBlackPixel(display, screen) };
107 let white = unsafe { XWhitePixel(display, screen) };
108
109 let parent = parent.unwrap_or(root);
110
111 let window =
112 unsafe { XCreateSimpleWindow(display, parent, 0, 0, width, height, 1, black, white) };
113 if window == 0 {
114 unsafe { XCloseDisplay(display) };
115 return Err("failed to create X11 container window".to_string());
116 }
117
118 if let Ok(cstr) = std::ffi::CString::new(title) {
119 unsafe {
120 XStoreName(display, window, cstr.as_ptr());
121 }
122 }
123
124 Ok(ContainerWindow { display, window })
125 }
126}