1use {
2 std::{
3 mem,
4 cell::Cell,
5 rc::Rc,
6 os::raw::{c_ulong, c_long, c_void, c_char},
7 ptr,
8 ffi::{CStr, CString, OsStr},
9 },
10 self::super::{
11 x11_sys,
12 xlib_event::XlibEvent,
13 xlib_app::*,
14 },
15 crate::{
16 area::Area,
17 window::WindowId,
18 makepad_math::DVec2,
19 event::*,
20 cursor::MouseCursor,
21 },
22};
23
24#[derive(Clone)]
25pub struct XlibWindow {
26 pub window: Option<c_ulong>,
27 pub xic: Option<x11_sys::XIC>,
28 pub attributes: Option<x11_sys::XSetWindowAttributes>,
29 pub visual_info: Option<x11_sys::XVisualInfo>,
30 pub last_nc_mode: Option<c_long>,
33 pub window_id: WindowId,
34 pub last_window_geom: WindowGeom,
35
36 pub ime_spot: DVec2,
37 pub current_cursor: MouseCursor,
38 pub last_mouse_pos: DVec2,
39}
40impl XlibWindow {
52
53 pub fn new(window_id: WindowId) -> XlibWindow {
54
55 XlibWindow {
56 window: None,
57 xic: None,
58 attributes: None,
59 visual_info: None,
60 window_id,
62 last_window_geom: WindowGeom::default(),
63 last_nc_mode: None,
64 ime_spot: DVec2::default(),
65 current_cursor: MouseCursor::Default,
66 last_mouse_pos: DVec2::default(),
67 }
68 }
69
70 pub fn init(&mut self, title: &str, size: DVec2, position: Option<DVec2>, visual_info: x11_sys::XVisualInfo, custom_window_chrome: bool) {
71 unsafe {
72 let display = get_xlib_app_global().display;
73
74 let default_screen = x11_sys::XDefaultScreen(display);
76
77 let root_window = x11_sys::XRootWindow(display, default_screen);
79
80 let mut attributes = mem::zeroed::<x11_sys::XSetWindowAttributes>();
81
82 attributes.border_pixel = 0;
83 attributes.colormap =
85 x11_sys::XCreateColormap(display, root_window, visual_info.visual, x11_sys::AllocNone as i32);
86 attributes.event_mask = (
87 x11_sys::ExposureMask
88 | x11_sys::StructureNotifyMask
89 | x11_sys::ButtonMotionMask
90 | x11_sys::PointerMotionMask
91 | x11_sys::ButtonPressMask
92 | x11_sys::ButtonReleaseMask
93 | x11_sys::KeyPressMask
94 | x11_sys::KeyReleaseMask
95 | x11_sys::VisibilityChangeMask
96 | x11_sys::FocusChangeMask
97 | x11_sys::EnterWindowMask
98 | x11_sys::LeaveWindowMask
99 ) as c_long;
100
101 let dpi_factor = self.get_dpi_factor();
102 let window = x11_sys::XCreateWindow(
104 display,
105 root_window,
106 if position.is_some() {position.unwrap().x}else {150.0} as i32,
107 if position.is_some() {position.unwrap().y}else {60.0} as i32,
108 (size.x * dpi_factor) as u32,
109 (size.y * dpi_factor) as u32,
110 0,
111 visual_info.depth,
112 x11_sys::InputOutput as u32,
113 visual_info.visual,
114 (x11_sys::CWBorderPixel | x11_sys::CWColormap | x11_sys::CWEventMask) as c_ulong, &mut attributes,
116 );
117
118 x11_sys::XSetWMProtocols(display, window, &mut get_xlib_app_global().atoms.wm_delete_window, 1);
120
121 if custom_window_chrome {
122 let hints = MwmHints {
123 flags: MWM_HINTS_DECORATIONS,
124 functions: 0,
125 decorations: 0,
126 input_mode: 0,
127 status: 0,
128 };
129
130 let atom_motif_wm_hints = get_xlib_app_global().atoms.motif_wm_hints;
131
132 x11_sys::XChangeProperty(
133 display,
134 window,
135 atom_motif_wm_hints,
136 atom_motif_wm_hints,
137 32,
138 x11_sys::PropModeReplace as i32,
139 &hints as *const _ as *const u8,
140 5
141 );
142 }
143
144 get_xlib_app_global().dnd.enable_for_window(window);
145
146 let title_bytes = format!("{}\0", title);
148 x11_sys::XStoreName(display, window, title_bytes.as_bytes().as_ptr() as *const c_char);
149
150 {
153 let class = std::env::args_os().next().as_ref()
155 .and_then(|arg0| std::path::Path::new(arg0).file_name())
156 .and_then(OsStr::to_str)
157 .map(ToOwned::to_owned)
158 .unwrap_or_else(|| String::from("Makepad"));
159 let instance = std::env::var("RESOURCE_NAME").ok()
160 .unwrap_or_else(|| class.clone());
161 let wm_class = format!("{instance}\0{class}\0");
162
163 x11_sys::XChangeProperty(
164 display,
165 window,
166 get_xlib_app_global().atoms.wm_class,
167 get_xlib_app_global().atoms.string,
168 (core::mem::size_of::<u8>() * 8) as i32,
170 x11_sys::PropModeReplace as i32,
171 wm_class.as_ptr(),
172 wm_class.len() as i32
173 );
174
175 }
176
177 x11_sys::XMapWindow(display, window);
179 x11_sys::XFlush(display);
180
181 if let Some(pos) = position {
185 x11_sys::XMoveWindow(display, window, pos.x as i32, pos.y as i32);
186 x11_sys::XFlush(display);
187 }
188
189 let xic = x11_sys::XCreateIC(
190 get_xlib_app_global().xim,
191 x11_sys::XNInputStyle.as_ptr(),
192 (x11_sys::XIMPreeditNothing | x11_sys::XIMStatusNothing) as i32,
193 x11_sys::XNClientWindow.as_ptr(),
194 window,
195 x11_sys::XNFocusWindow.as_ptr(),
196 window,
197 ptr::null_mut() as *mut c_void
198 );
199
200 get_xlib_app_global().window_map.insert(window, self);
202
203 self.attributes = Some(attributes);
204 self.visual_info = Some(visual_info);
205 self.window = Some(window);
206 self.xic = Some(xic);
207 self.last_window_geom = self.get_window_geom();
208
209 let new_geom = self.get_window_geom();
210 self.do_callback(XlibEvent::WindowGeomChange(WindowGeomChangeEvent {
211 window_id: self.window_id,
212 old_geom: new_geom.clone(),
213 new_geom: new_geom
214 })
215 );
216 }
217 }
218
219 fn restore_or_maximize(&self, add_remove: c_long) {
220 unsafe {
221 let default_screen = x11_sys::XDefaultScreen(get_xlib_app_global().display);
222 let root_window = x11_sys::XRootWindow(get_xlib_app_global().display, default_screen);
223 let mut xclient = x11_sys::XClientMessageEvent {
224 type_: x11_sys::ClientMessage as i32,
225 serial: 0,
226 send_event: 0,
227 display: get_xlib_app_global().display,
228 window: self.window.unwrap(),
229 message_type: get_xlib_app_global().atoms.net_wm_state,
230 format: 32,
231 data: {
232 let mut msg = mem::zeroed::<x11_sys::XClientMessageEvent__bindgen_ty_1>();
233 msg.l[0] = add_remove;
234 msg.l[1] = get_xlib_app_global().atoms.new_wm_state_maximized_horz as c_long;
235 msg.l[2] = get_xlib_app_global().atoms.new_wm_state_maximized_vert as c_long;
236 msg
237 }
238 };
239 x11_sys::XSendEvent(
240 get_xlib_app_global().display,
241 root_window,
242 0,
243 (x11_sys::SubstructureNotifyMask | x11_sys::SubstructureRedirectMask) as c_long,
244 &mut xclient as *mut _ as *mut x11_sys::XEvent
245 );
246 }
247 }
248
249 pub fn restore(&self) {
250 self.restore_or_maximize(_NET_WM_STATE_REMOVE);
251 }
252
253 pub fn maximize(&self) {
254 self.restore_or_maximize(_NET_WM_STATE_ADD);
255 }
256
257 pub fn close_window(&mut self) {
258 unsafe {
259 x11_sys::XDestroyWindow(get_xlib_app_global().display, self.window.unwrap());
260 self.window = None;
261 }
264 }
265
266 pub fn minimize(&self) {
267 unsafe {
268 let default_screen = x11_sys::XDefaultScreen(get_xlib_app_global().display);
269 x11_sys::XIconifyWindow(get_xlib_app_global().display, self.window.unwrap(), default_screen);
270 x11_sys::XFlush(get_xlib_app_global().display);
271 }
272 }
273
274 pub fn set_topmost(&self, _topmost: bool) {
275 }
276
277 pub fn get_is_topmost(&self) -> bool {
278 false
279 }
280
281 pub fn get_window_geom(&self) -> WindowGeom {
282 WindowGeom {
283 xr_is_presenting: false,
284 can_fullscreen: false,
285 is_topmost: self.get_is_topmost(),
286 is_fullscreen: self.get_is_maximized(),
287 inner_size: self.get_inner_size(),
288 outer_size: self.get_outer_size(),
289 dpi_factor: self.get_dpi_factor(),
290 position: self.get_position()
291 }
292 }
293
294 pub fn get_is_maximized(&self) -> bool {
295 let mut maximized = false;
296 unsafe {
297 let mut prop_type = mem::MaybeUninit::uninit();
298 let mut format = mem::MaybeUninit::uninit();
299 let mut n_item = mem::MaybeUninit::uninit();
300 let mut bytes_after = mem::MaybeUninit::uninit();
301 let mut properties = mem::MaybeUninit::uninit();
302 let result = x11_sys::XGetWindowProperty(
303 get_xlib_app_global().display,
304 self.window.unwrap(),
305 get_xlib_app_global().atoms.net_wm_state,
306 0,
307 !0,
308 0,
309 x11_sys::AnyPropertyType as c_ulong,
310 prop_type.as_mut_ptr(),
311 format.as_mut_ptr(),
312 n_item.as_mut_ptr(),
313 bytes_after.as_mut_ptr(),
314 properties.as_mut_ptr()
315 );
316 let n_item = n_item.assume_init();
319 let properties = properties.assume_init();
321 if result == 0 && properties != ptr::null_mut() {
322 let items = std::slice::from_raw_parts::<c_ulong>(properties as *mut _, n_item as usize);
323 for item in items {
324 if *item == get_xlib_app_global().atoms.new_wm_state_maximized_horz
325 || *item == get_xlib_app_global().atoms.new_wm_state_maximized_vert {
326 maximized = true;
327 break;
328 }
329 }
330 x11_sys::XFree(properties as *mut _);
331 }
332 }
333 maximized
334 }
335
336 pub fn set_ime_spot(&mut self, spot: DVec2) {
337 self.ime_spot = spot;
338 }
339
340 pub fn get_position(&self) -> DVec2 {
341 unsafe {
342 let mut xwa = mem::MaybeUninit::uninit();
343 let display = get_xlib_app_global().display;
344 x11_sys::XGetWindowAttributes(
345 display,
346 self.window.unwrap(),
347 xwa.as_mut_ptr()
348 );
349 let xwa = xwa.assume_init();
350 return DVec2 {x: xwa.x as f64, y: xwa.y as f64}
351 }
360 }
361
362 pub fn get_inner_size(&self) -> DVec2 {
363 let dpi_factor = self.get_dpi_factor();
364 unsafe {
365 let mut xwa = mem::MaybeUninit::uninit();
366 let display = get_xlib_app_global().display;
367 x11_sys::XGetWindowAttributes(display, self.window.unwrap(), xwa.as_mut_ptr());
368 let xwa = xwa.assume_init();
369 return DVec2 {x: xwa.width as f64 / dpi_factor, y: xwa.height as f64 / dpi_factor}
370 }
371 }
372
373 pub fn get_outer_size(&self) -> DVec2 {
374 unsafe {
375 let mut xwa = mem::MaybeUninit::uninit();
376 let display = get_xlib_app_global().display;
377 x11_sys::XGetWindowAttributes(display, self.window.unwrap(), xwa.as_mut_ptr());
378 let xwa = xwa.assume_init();
379 return DVec2 {x: xwa.width as f64, y: xwa.height as f64}
380 }
381 }
382
383 pub fn set_position(&mut self, _pos: DVec2) {
384 }
385
386 pub fn set_outer_size(&self, _size: DVec2) {
387 }
388
389 pub fn set_inner_size(&self, _size: DVec2) {
390 }
391
392 pub fn get_dpi_factor(&self) -> f64 {
393 unsafe {
394 let display = get_xlib_app_global().display;
396 let resource_string = x11_sys::XResourceManagerString(display);
397 if resource_string == std::ptr::null_mut() {
398 return 1.0
399 }
400 let db = x11_sys::XrmGetStringDatabase(resource_string);
401 let mut ty = mem::MaybeUninit::uninit();
402 let mut value = mem::MaybeUninit::uninit();
403 x11_sys::XrmGetResource(
404 db,
405 "Xft.dpi\0".as_ptr() as * const _,
406 "String\0".as_ptr() as * const _,
407 ty.as_mut_ptr(),
408 value.as_mut_ptr()
409 );
410 let value = value.assume_init();
412 if value.addr == std::ptr::null_mut() {
413 return 1.0; }
415 else {
416 let dpi: f64 = CStr::from_ptr(value.addr).to_str().unwrap().parse().unwrap();
417 return dpi / 96.0;
418 }
419 }
420 }
421
422 pub fn time_now(&self) -> f64 {
423 get_xlib_app_global().time_now()
424 }
425
426 pub fn do_callback(&mut self, event: XlibEvent) {
427 get_xlib_app_global().do_callback(event);
428 }
429
430 pub fn send_change_event(&mut self) {
431
432 let mut new_geom = self.get_window_geom();
433 if new_geom.inner_size.x < self.last_window_geom.inner_size.x ||
434 new_geom.inner_size.y < self.last_window_geom.inner_size.y {
435 new_geom.is_fullscreen = false;
436 }
437 let old_geom = self.last_window_geom.clone();
438 self.last_window_geom = new_geom.clone();
439
440 self.do_callback(XlibEvent::WindowGeomChange(WindowGeomChangeEvent {
441 window_id: self.window_id,
442 old_geom: old_geom,
443 new_geom: new_geom
444 }));
445 self.do_callback(XlibEvent::Paint);
446 }
447
448 pub fn send_focus_event(&mut self) {
449 self.do_callback(XlibEvent::AppGotFocus);
450 }
451
452 pub fn send_focus_lost_event(&mut self) {
453 self.do_callback(XlibEvent::AppLostFocus);
454 }
455
456 pub fn send_mouse_down(&mut self, button: MouseButton, modifiers: KeyModifiers) {
457 self.do_callback(XlibEvent::MouseDown(MouseDownEvent {
458 button,
459 modifiers,
460 window_id: self.window_id,
461 abs: self.last_mouse_pos,
462 time: self.time_now(),
463 handled: Cell::new(Area::Empty),
464 }));
465 }
466
467 pub fn send_mouse_up(&mut self, button: MouseButton, modifiers: KeyModifiers) {
468 self.do_callback(XlibEvent::MouseUp(MouseUpEvent {
469 button,
470 modifiers,
471 window_id: self.window_id,
472 abs: self.last_mouse_pos,
473 time: self.time_now()
474 }));
475 }
476
477 pub fn send_mouse_move(&mut self, pos: DVec2, modifiers: KeyModifiers) {
478 self.last_mouse_pos = pos;
479 self.do_callback(XlibEvent::MouseMove(MouseMoveEvent {
480 window_id: self.window_id,
481 abs: pos,
482 modifiers,
483 time: self.time_now(),
484 handled: Cell::new(Area::Empty),
485 }));
486
487 }
488
489 pub fn send_close_requested_event(&mut self) -> bool {
490 let accept_close = Rc::new(Cell::new(true));
491 self.do_callback(XlibEvent::WindowCloseRequested(WindowCloseRequestedEvent {
492 window_id: self.window_id,
493 accept_close: accept_close.clone()
494 }));
495 if !accept_close.get() {
496 return false
497 }
498 true
499 }
500
501 pub fn send_text_input(&mut self, input: String, replace_last: bool) {
502 self.do_callback(XlibEvent::TextInput(TextInputEvent {
503 input,
504 was_paste: false,
505 replace_last,
506 }))
507 }
508
509}
510
511
512#[derive(Clone, Copy, PartialEq)]
513#[repr(C)]
514struct MwmHints {
515 pub flags: c_ulong,
516 pub functions: c_ulong,
517 pub decorations: c_ulong,
518 pub input_mode: c_long,
519 pub status: c_ulong,
520}
521
522pub const MWM_HINTS_FUNCTIONS: c_ulong = 1 << 0;
523pub const MWM_HINTS_DECORATIONS: c_ulong = 1 << 1;
524
525pub const MWM_FUNC_ALL: c_ulong = 1 << 0;
526pub const MWM_FUNC_RESIZE: c_ulong = 1 << 1;
527pub const MWM_FUNC_MOVE: c_ulong = 1 << 2;
528pub const MWM_FUNC_MINIMIZE: c_ulong = 1 << 3;
529pub const MWM_FUNC_MAXIMIZE: c_ulong = 1 << 4;
530pub const MWM_FUNC_CLOSE: c_ulong = 1 << 5;
531pub const _NET_WM_MOVERESIZE_SIZE_TOPLEFT: c_long = 0;
532pub const _NET_WM_MOVERESIZE_SIZE_TOP: c_long = 1;
533pub const _NET_WM_MOVERESIZE_SIZE_TOPRIGHT: c_long = 2;
534pub const _NET_WM_MOVERESIZE_SIZE_RIGHT: c_long = 3;
535pub const _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT: c_long = 4;
536pub const _NET_WM_MOVERESIZE_SIZE_BOTTOM: c_long = 5;
537pub const _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT: c_long = 6;
538pub const _NET_WM_MOVERESIZE_SIZE_LEFT: c_long = 7;
539pub const _NET_WM_MOVERESIZE_MOVE: c_long = 8;pub const _NET_WM_MOVERESIZE_SIZE_KEYBOARD: c_long = 9;pub const _NET_WM_MOVERESIZE_MOVE_KEYBOARD: c_long = 10;
542
543pub const _NET_WM_STATE_REMOVE: c_long = 0;pub const _NET_WM_STATE_ADD: c_long = 1;pub const _NET_WM_STATE_TOGGLE: c_long = 2;pub struct Dnd {
550 pub atoms: DndAtoms,
551 pub display: *mut x11_sys::Display,
552 pub type_list: Option<Vec<x11_sys::Atom >>,
553 pub selection: Option<CString>,
554}
555
556impl Dnd {
557 pub unsafe fn new(display: *mut x11_sys::Display) -> Dnd {
558 Dnd {
559 atoms: DndAtoms::new(display),
560 display,
561 type_list: None,
562 selection: None,
563 }
564 }
565
566 pub unsafe fn enable_for_window(&mut self, window: x11_sys::Window) {
568 let version = 5 as c_ulong;
574
575 x11_sys::XChangeProperty(
576 self.display,
577 window,
578 self.atoms.aware,
579 4, 32,
581 x11_sys::PropModeReplace as std::os::raw::c_int,
582 &version as *const c_ulong as *const std::os::raw::c_uchar,
583 1
584 );
585 }
586
587 pub unsafe fn handle_enter_event(&mut self, event: &x11_sys::XClientMessageEvent) {
589 let source_window = event.data.l[0] as x11_sys::Window;
594 let has_more_types = event.data.l[1] & (1 << 0) != 0;
595
596 self.type_list = Some(if has_more_types {
600 self.get_type_list_property(source_window)
601 } else {
602 event.data.l[2..4]
603 .iter()
604 .map( | &l | l as x11_sys::Atom)
605 .filter( | &atom | atom != x11_sys::None as x11_sys::Atom)
606 .collect()
607 });
608 }
609
610 pub unsafe fn handle_drop_event(&mut self, event: &x11_sys::XClientMessageEvent) {
612 let target_window = event.window as x11_sys::Window;
620 self.convert_selection(target_window);
621 self.type_list = None;
622 }
623
624 pub unsafe fn handle_leave_event(&mut self, _event: &x11_sys::XClientMessageEvent) {
626 self.type_list = None;
631 }
632
633 pub unsafe fn handle_position_event(&mut self, event: &x11_sys::XClientMessageEvent) {
635 let target_window = event.window as x11_sys::Window;
640 let source_window = event.data.l[0] as x11_sys::Window;
641
642 let accepted = self.type_list.as_ref().map_or(false, | type_list | type_list.contains(&self.atoms.uri_list));
647
648 self.send_status_event(source_window, target_window, accepted);
650
651 if accepted && self.selection.is_none() {
659 }
660 }
661
662 pub unsafe fn handle_selection_event(&mut self, _event: &x11_sys::XSelectionEvent) {
664 }
674
675 pub unsafe fn get_selection_property(&mut self, source_window: x11_sys::Window) -> Vec< std::os::raw::c_uchar> {
677 let mut selection = Vec::new();
678 let mut offset = 0;
679 let length = 1024;
680 let mut actual_type = 0;
681 let mut actual_format = 0;
682 let mut nitems = 0;
683 let mut bytes_after = 0;
684 let mut prop = ptr::null_mut();
685 loop {
686 x11_sys::XGetWindowProperty(
687 self.display,
688 source_window,
689 self.atoms.selection,
690 offset,
691 length,
692 x11_sys::False as std::os::raw::c_int,
693 self.atoms.uri_list,
694 &mut actual_type,
695 &mut actual_format,
696 &mut nitems,
697 &mut bytes_after,
698 &mut prop,
699 );
700 selection.extend_from_slice(std::slice::from_raw_parts(prop as *mut std::os::raw::c_uchar, nitems as usize));
701 x11_sys::XFree(prop as *mut c_void);
702 if bytes_after == 0 {
703 break;
704 }
705 offset += length;
706 };
707 selection
708 }
709
710 pub unsafe fn get_type_list_property(&mut self, source_window: x11_sys::Window) -> Vec<x11_sys::Atom> {
712 let mut type_list = Vec::new();
713 let mut offset = 0;
714 let length = 1024;
715 let mut actual_type = 0;
716 let mut actual_format = 0;
717 let mut nitems = 0;
718 let mut bytes_after = 0;
719 let mut prop = ptr::null_mut();
720 loop {
721 x11_sys::XGetWindowProperty(
722 self.display,
723 source_window,
724 self.atoms.type_list,
725 offset,
726 length,
727 x11_sys::False as std::os::raw::c_int,
728 4, &mut actual_type,
730 &mut actual_format,
731 &mut nitems,
732 &mut bytes_after,
733 &mut prop,
734 );
735 type_list.extend_from_slice(std::slice::from_raw_parts(prop as *mut x11_sys::Atom, nitems as usize));
736 x11_sys::XFree(prop as *mut c_void);
737 if bytes_after == 0 {
738 break;
739 }
740 offset += length;
741 };
742 type_list
743 }
744
745 pub unsafe fn send_status_event(&mut self, source_window: x11_sys::Window, target_window: x11_sys::Window, accepted: bool) {
747 x11_sys::XSendEvent(
748 self.display,
749 source_window,
750 x11_sys::False as std::os::raw::c_int,
751 x11_sys::NoEventMask as std::os::raw::c_long,
752 &mut x11_sys::XClientMessageEvent {
753 type_: x11_sys::ClientMessage as std::os::raw::c_int,
754 serial: 0,
755 send_event: 0,
756 display: self.display,
757 window: source_window,
758 message_type: self.atoms.status,
759 format: 32,
760 data: {
761 let mut data = mem::zeroed::<x11_sys::XClientMessageEvent__bindgen_ty_1>();
762 data.l[0] = target_window as c_long;
763 data.l[1] = if accepted {1 << 0} else {0};
764 data.l[2] = 0;
765 data.l[3] = 0;
766 data.l[4] = if accepted {self.atoms.action_private} else {self.atoms.none} as c_long;
767 data
768 }
769 } as *mut x11_sys::XClientMessageEvent as *mut x11_sys::XEvent
770 );
771 x11_sys::XFlush(self.display);
772 }
773
774 pub unsafe fn convert_selection(&self, target_window: x11_sys::Window) {
777 x11_sys::XConvertSelection(
778 self.display,
779 self.atoms.selection,
780 self.atoms.uri_list,
781 self.atoms.selection,
782 target_window,
783 x11_sys::CurrentTime as x11_sys::Time,
784 );
785 }
786}
787
788pub struct DndAtoms {
789 pub action_private: x11_sys::Atom,
790 pub aware: x11_sys::Atom,
791 pub drop: x11_sys::Atom,
792 pub enter: x11_sys::Atom,
793 pub leave: x11_sys::Atom,
794 pub none: x11_sys::Atom,
795 pub position: x11_sys::Atom,
796 pub selection: x11_sys::Atom,
797 pub status: x11_sys::Atom,
798 pub type_list: x11_sys::Atom,
799 pub uri_list: x11_sys::Atom,
800}
801
802impl DndAtoms {
803 pub unsafe fn new(display: *mut x11_sys::Display) -> DndAtoms {
804 DndAtoms {
805 action_private: x11_sys::XInternAtom(display, "XdndActionPrivate\0".as_ptr() as *const _, 0),
806 aware: x11_sys::XInternAtom(display, "XdndAware\0".as_ptr() as *const _, 0),
807 drop: x11_sys::XInternAtom(display, "XdndDrop\0".as_ptr() as *const _, 0),
808 enter: x11_sys::XInternAtom(display, "XdndEnter\0".as_ptr() as *const _, 0),
809 leave: x11_sys::XInternAtom(display, "XdndLeave\0".as_ptr() as *const _, 0),
810 none: x11_sys::XInternAtom(display, "None\0".as_ptr() as *const _, 0),
811 position: x11_sys::XInternAtom(display, "XdndPosition\0".as_ptr() as *const _, 0),
812 selection: x11_sys::XInternAtom(display, "XdndSelection\0".as_ptr() as *const _, 0),
813 status: x11_sys::XInternAtom(display, "XdndStatus\0".as_ptr() as *const _, 0),
814 type_list: x11_sys::XInternAtom(display, "XdndTypeList\0".as_ptr() as *const _, 0),
815 uri_list: x11_sys::XInternAtom(display, "text/uri-list\0".as_ptr() as *const _, 0),
816 }
817 }
818}