1use {
2 std::{
3 collections::HashMap,
4 mem,
5 rc::Rc,
6 cell::{Cell, RefCell},
7 os::raw::{c_char, c_int, c_uint, c_ulong, c_void, c_uchar, c_long},
8 ptr,
9 },
10 self::super::{
11 x11_sys,
12 xlib_event::XlibEvent,
13 xlib_window::*,
14 super::select_timer::SelectTimers,
15 },
16 crate::{
17 makepad_math::DVec2,
18 event::*,
19 cursor::MouseCursor,
20 os::cx_native::EventFlow,
21 },
22};
23
24static mut XLIB_APP: *mut XlibApp = 0 as *mut _;
25
26pub fn get_xlib_app_global() -> &'static mut XlibApp {
27 unsafe {
28 &mut *(XLIB_APP)
29 }
30}
31
32pub fn init_xlib_app_global(event_callback: Box<dyn FnMut(&mut XlibApp, XlibEvent) -> EventFlow>) {
33 unsafe {
34 XLIB_APP = Box::into_raw(Box::new(XlibApp::new(event_callback)));
35 }
36}
37
38pub struct XlibApp {
39 pub display: *mut x11_sys::Display,
40 event_loop_running: bool,
41 pub xim: x11_sys::XIM,
42 pub clipboard: String,
43 pub display_fd: c_int,
44 pub window_map: HashMap<c_ulong, *mut XlibWindow>,
46
47 pub timers: SelectTimers,
48
49 pub last_scroll_time: f64,
50 pub last_click_time: f64,
51 pub last_click_pos: (i32, i32),
52 pub event_callback: Option<Box<dyn FnMut(&mut XlibApp, XlibEvent) -> EventFlow >>,
53 pub event_flow: EventFlow,
55 pub current_cursor: MouseCursor,
56 pub internal_cursor: MouseCursor,
57 pub atoms: XlibAtoms,
58 pub dnd: Dnd,
59 pub next_keypress_is_repeat: bool,
60}
61
62impl XlibApp {
63 pub fn new(event_callback: Box<dyn FnMut(&mut XlibApp, XlibEvent) -> EventFlow>) -> XlibApp {
64 unsafe {
65 let display = x11_sys::XOpenDisplay(ptr::null());
66 let display_fd = x11_sys::XConnectionNumber(display);
67 let xim = x11_sys::XOpenIM(display, ptr::null_mut(), ptr::null_mut(), ptr::null_mut());
68 x11_sys::XrmInitialize();
71 XlibApp {
72 event_loop_running: true,
73 event_callback: Some(event_callback),
74 atoms: XlibAtoms::new(display),
75 xim,
76 display,
77 display_fd,
78 clipboard: String::new(),
80 last_scroll_time: 0.0,
81 last_click_time: 0.0,
82 last_click_pos: (0, 0),
83 window_map: HashMap::new(),
84 timers: SelectTimers::new(),
85 event_flow: EventFlow::Poll,
86 current_cursor: MouseCursor::Default,
88 internal_cursor: MouseCursor::Default,
89 dnd: Dnd::new(display),
90 next_keypress_is_repeat: false,
91 }
92 }
93 }
94
95 pub unsafe fn event_loop_poll(&mut self) {
96 while self.display != ptr::null_mut() && x11_sys::XPending(self.display) != 0 {
99 let mut event = mem::MaybeUninit::uninit();
100 x11_sys::XNextEvent(self.display, event.as_mut_ptr());
101 let mut event = event.assume_init();
102 match event.type_ as u32 {
103 x11_sys::SelectionNotify => {
104 let selection = event.xselection;
105 if selection.property == self.dnd.atoms.selection {
106 self.dnd.handle_selection_event(&selection);
107 } else {
108 let mut actual_type = mem::MaybeUninit::uninit();
110 let mut actual_format = mem::MaybeUninit::uninit();
111 let mut n_items = mem::MaybeUninit::uninit();
112 let mut bytes_to_read = mem::MaybeUninit::uninit();
113 let mut ret = mem::MaybeUninit::uninit();
114 x11_sys::XGetWindowProperty(
115 self.display,
116 selection.requestor,
117 selection.property,
118 0,
119 0,
120 0,
121 x11_sys::AnyPropertyType as c_ulong,
122 actual_type.as_mut_ptr(),
123 actual_format.as_mut_ptr(),
124 n_items.as_mut_ptr(),
125 bytes_to_read.as_mut_ptr(),
126 ret.as_mut_ptr()
127 );
128 let bytes_to_read = bytes_to_read.assume_init();
132 let mut bytes_after = mem::MaybeUninit::uninit();
134 x11_sys::XGetWindowProperty(
135 self.display,
136 selection.requestor,
137 selection.property,
138 0,
139 bytes_to_read as c_long,
140 0,
141 x11_sys::AnyPropertyType as c_ulong,
142 actual_type.as_mut_ptr(),
143 actual_format.as_mut_ptr(),
144 n_items.as_mut_ptr(),
145 bytes_after.as_mut_ptr(),
146 ret.as_mut_ptr()
147 );
148 let ret = ret.assume_init();
149 if ret != ptr::null_mut() && bytes_to_read > 0 {
151 let utf8_slice = std::slice::from_raw_parts::<u8>(ret as *const _ as *const u8, bytes_to_read as usize);
152 if let Ok(utf8_string) = String::from_utf8(utf8_slice.to_vec()) {
153 self.do_callback(XlibEvent::TextInput(TextInputEvent {
154 input: utf8_string,
155 was_paste: true,
156 replace_last: false
157 }));
158 }
159 x11_sys::XFree(ret as *mut _ as *mut c_void);
160 }
161 }
162 },
163 x11_sys::SelectionRequest => {
164 let request = event.xselectionrequest;
165 let mut response = x11_sys::XSelectionEvent {
166 type_: x11_sys::SelectionNotify as i32,
167 serial: 0,
168 send_event: 0,
169 display: self.display,
170 requestor: request.requestor,
171 selection: request.selection,
172 target: request.target,
173 time: request.time,
174 property: request.property,
175 };
176 if request.target == self.atoms.targets {
177 let mut targets = [self.atoms.utf8_string];
178 x11_sys::XChangeProperty(
179 self.display,
180 request.requestor,
181 request.property,
182 4,
183 32,
184 x11_sys::PropModeReplace as i32,
185 targets.as_mut() as *mut _ as *mut c_uchar,
186 targets.len() as i32
187 );
188 }
189 else if request.target == self.atoms.utf8_string {
190 x11_sys::XChangeProperty(
191 self.display,
192 request.requestor,
193 request.property,
194 self.atoms.utf8_string,
195 8,
196 x11_sys::PropModeReplace as i32,
197 self.clipboard.as_ptr() as *const _ as *const c_uchar,
198 self.clipboard.len() as i32
199 );
200 }
201 else {
202 response.property = 0;
203 }
204 x11_sys::XSendEvent(self.display, request.requestor, 1, 0, &mut response as *mut _ as *mut x11_sys::XEvent);
205 },
206 x11_sys::DestroyNotify => { let destroy_window = event.xdestroywindow;
208 if let Some(window_ptr) = self.window_map.get(&destroy_window.window) {
209 let window = &mut (**window_ptr);
210 window.do_callback(XlibEvent::WindowClosed(WindowClosedEvent {
211 window_id: window.window_id,
212 }));
213 }
214 },
215 x11_sys::ConfigureNotify => {
216 let cfg = event.xconfigure;
217 if let Some(window_ptr) = self.window_map.get(&cfg.window) {
218 let window = &mut (**window_ptr);
219 if cfg.window == window.window.unwrap() {
220 window.send_change_event();
221 }
222 }
223 },
224 x11_sys::EnterNotify => {},
225 x11_sys::LeaveNotify => {
226 let crossing = event.xcrossing;
227 if crossing.detail == 4 {
228 if let Some(_window_ptr) = self.window_map.get(&crossing.window) {
229 }
246 }
247 },
248 x11_sys::MotionNotify => { let motion = event.xmotion;
250 if let Some(window_ptr) = self.window_map.get(&motion.window) {
251 let window = &mut (**window_ptr);
252 let x = motion.x;
253 let y = motion.y;
254 if window.window.is_none() {
255 return; }
257 if motion.window != window.window.unwrap() {
258 }
268
269 let pos = DVec2 {x: x as f64 / window.last_window_geom.dpi_factor, y: y as f64 / window.last_window_geom.dpi_factor};
270
271 let response = Rc::new(Cell::new(WindowDragQueryResponse::NoAnswer));
273 window.do_callback(XlibEvent::WindowDragQuery(WindowDragQueryEvent {
274 window_id: window.window_id,
275 abs: window.last_mouse_pos,
276 response: response.clone()
277 }));
278 window.send_mouse_move(pos, KeyModifiers::default());
281 let window_size = window.last_window_geom.inner_size;
282 if pos.x >= 0.0 && pos.x < 10.0 && pos.y >= 0.0 && pos.y < 10.0 {
283 window.last_nc_mode = Some(_NET_WM_MOVERESIZE_SIZE_TOPLEFT);
284 self.set_internal_mouse_cursor(MouseCursor::NwResize);
285 }
286 else if pos.x >= 0.0 && pos.x < 10.0 && pos.y >= window_size.y - 10.0 {
287 window.last_nc_mode = Some(_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT);
288 self.set_internal_mouse_cursor(MouseCursor::SwResize);
289 }
290 else if pos.x >= 0.0 && pos.x < 5.0 {
291 window.last_nc_mode = Some(_NET_WM_MOVERESIZE_SIZE_LEFT);
292 self.set_internal_mouse_cursor(MouseCursor::WResize);
293 }
294 else if pos.x >= window_size.x - 10.0 && pos.y >= 0.0 && pos.y < 10.0 {
295 window.last_nc_mode = Some(_NET_WM_MOVERESIZE_SIZE_TOPRIGHT);
296 self.set_internal_mouse_cursor(MouseCursor::NeResize);
297 }
298 else if pos.x >= window_size.x - 10.0 && pos.y >= window_size.y - 10.0 {
299 window.last_nc_mode = Some(_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT);
300 self.set_internal_mouse_cursor(MouseCursor::SeResize);
301 }
302 else if pos.x >= window_size.x - 5.0 {
303 window.last_nc_mode = Some(_NET_WM_MOVERESIZE_SIZE_RIGHT);
304 self.set_internal_mouse_cursor(MouseCursor::EResize);
305 }
306 else if pos.y <= 5.0 {
307 window.last_nc_mode = Some(_NET_WM_MOVERESIZE_SIZE_TOP);
308 self.set_internal_mouse_cursor(MouseCursor::NResize);
309 }
310 else if pos.y > window_size.y - 5.0 {
311 window.last_nc_mode = Some(_NET_WM_MOVERESIZE_SIZE_BOTTOM);
312 self.set_internal_mouse_cursor(MouseCursor::SResize);
313 }
314 else {
315 match response.get() {
316 WindowDragQueryResponse::Caption => {
317 window.last_nc_mode = Some(_NET_WM_MOVERESIZE_MOVE);
318 },
319 _ => {
320 window.last_nc_mode = None;
321 }
322 }
323 self.restore_mouse_cursor(self.current_cursor);
324 }
325 }
326 },
327 x11_sys::ButtonPress => { let button = event.xbutton;
329 let time_now = self.time_now();
330 if let Some(window_ptr) = self.window_map.get(&button.window) {
331 let window = &mut (**window_ptr);
332 x11_sys::XSetInputFocus(
333 self.display,
334 window.window.unwrap(),
335 x11_sys::None as i32,
336 x11_sys::CurrentTime as c_ulong
337 );
338
339 if button.button >= 4 && button.button <= 7 {
340 let last_scroll_time = self.last_scroll_time;
341 self.last_scroll_time = time_now;
342 let speed = 1200.0 * (0.2 - 2. * (self.last_scroll_time - last_scroll_time)).max(0.01);
344
345 self.do_callback(XlibEvent::Scroll(ScrollEvent {
346 window_id: window.window_id,
347 scroll: DVec2 {
348 x: if button.button == 6 {-speed} else if button.button == 7 {speed} else {0.},
349 y: if button.button == 4 {-speed} else if button.button == 5 {speed} else {0.}
350 },
351 abs: window.last_mouse_pos,
352 modifiers: self.xkeystate_to_modifiers(button.state),
353 is_mouse: true,
354 handled_x: Cell::new(false),
355 handled_y: Cell::new(false),
356 time: self.last_scroll_time
357 }))
358
359 }
360 else {
361 if let Some(last_nc_mode) = window.last_nc_mode {
363 if (time_now - self.last_click_time) < 0.35
364 && (button.x_root - self.last_click_pos.0).abs() < 5
365 && (button.y_root - self.last_click_pos.1).abs() < 5
366 && last_nc_mode == _NET_WM_MOVERESIZE_MOVE {
367 if window.get_is_maximized() {
368 window.restore();
369 }
370 else {
371 window.maximize();
372 }
373 }
374 else {
375
376 let default_screen = x11_sys::XDefaultScreen(self.display);
377 let root_window = x11_sys::XRootWindow(self.display, default_screen);
378 x11_sys::XUngrabPointer(self.display, 0);
379 x11_sys::XFlush(self.display);
380 let mut xclient = x11_sys::XClientMessageEvent {
381 type_: x11_sys::ClientMessage as i32,
382 serial: 0,
383 send_event: 0,
384 display: self.display,
385 window: window.window.unwrap(),
386 message_type: self.atoms.net_wm_moveresize,
387 format: 32,
388 data: {
389 let mut msg = mem::zeroed::<x11_sys::XClientMessageEvent__bindgen_ty_1>();
390 msg.l[0] = button.x_root as c_long;
391 msg.l[1] = button.y_root as c_long;
392 msg.l[2] = last_nc_mode;
393 msg
394 }
395 };
396 x11_sys::XSendEvent(
397 self.display,
398 root_window,
399 0,
400 (x11_sys::SubstructureRedirectMask | x11_sys::SubstructureNotifyMask) as c_long,
401 &mut xclient as *mut _ as *mut x11_sys::XEvent
402 );
403 }
404 }
405 else {
406 window.send_mouse_down(
407 self.xbutton_to_mouse_button(button.button),
408 self.xkeystate_to_modifiers(button.state)
409 );
410 }
411 }
412 }
413 self.last_click_time = time_now;
414 self.last_click_pos = (button.x_root, button.y_root);
415 },
416 x11_sys::ButtonRelease => { let button = event.xbutton;
418 if let Some(window_ptr) = self.window_map.get(&button.window) {
419 let window = &mut (**window_ptr);
420 window.send_mouse_up(
421 self.xbutton_to_mouse_button(button.button),
422 self.xkeystate_to_modifiers(button.state),
423 );
424 }
425 },
426 x11_sys::KeyPress => {
427 if let Some(window_ptr) = self.window_map.get(&event.xkey.window) {
428 let window = &mut (**window_ptr);
429 let block_text = if event.xkey.keycode != 0 {
430 let key_code = self.xkeyevent_to_keycode(&mut event.xkey);
431 let modifiers = self.xkeystate_to_modifiers(event.xkey.state);
432
433 if modifiers.control || modifiers.logo {
434 match key_code {
435 KeyCode::KeyV => { x11_sys::XConvertSelection(
438 self.display,
439 self.atoms.clipboard,
440 self.atoms.utf8_string,
441 self.atoms.clipboard,
442 window.window.unwrap(),
443 event.xkey.time
444 );
445 }
455 KeyCode::KeyC => {
456 let response = Rc::new(RefCell::new(None));
457 self.do_callback(XlibEvent::TextCopy(TextClipboardEvent {
458 response: response.clone()
459 }));
460 let response = response.borrow();
461 if let Some(response) = response.as_ref() {
462 self.copy_to_clipboard(response, window.window.unwrap(), event.xkey.time);
463 }
464 }
465 KeyCode::KeyX => {
466 let response = Rc::new(RefCell::new(None));
467 self.do_callback(XlibEvent::TextCut(TextClipboardEvent {
468 response: response.clone()
469 }));
470 let response = response.borrow();
471 if let Some(response) = response.as_ref() {
472 self.copy_to_clipboard(response, window.window.unwrap(), event.xkey.time);
473 }
474 }
475 _ => ()
476 }
477 }
478
479 let block_text = modifiers.control || modifiers.logo || modifiers.alt;
480 self.do_callback(XlibEvent::KeyDown(KeyEvent {
481 key_code: key_code,
482 is_repeat: self.next_keypress_is_repeat,
483 modifiers: modifiers,
484 time: self.time_now()
485 }));
486 self.next_keypress_is_repeat = false;
487 block_text
488 }else {false};
489
490 if !block_text {
491 let mut buffer = [0u8; 32];
493 let mut keysym = mem::MaybeUninit::uninit();
494 let mut status = mem::MaybeUninit::uninit();
495 let count = x11_sys::Xutf8LookupString(
496 window.xic.unwrap(),
497 &mut event.xkey,
498 buffer.as_mut_ptr() as *mut c_char,
499 buffer.len() as c_int,
500 keysym.as_mut_ptr(),
501 status.as_mut_ptr(),
502 );
503 let status = status.assume_init();
505 if status != x11_sys::XBufferOverflow {
506 let utf8 = std::str::from_utf8(&buffer[..count as usize]).unwrap_or("").to_string();
507 let char_code = utf8.chars().next().unwrap_or('\0');
508 if char_code >= ' ' && char_code != 127 as char {
509 self.do_callback(XlibEvent::TextInput(TextInputEvent {
510 input: utf8,
511 was_paste: false,
512 replace_last: false
513 }));
514 }
515 }
516 }
517 }
518 },
519 x11_sys::KeyRelease => {
520 if x11_sys::XEventsQueued(self.display, x11_sys::QueuedAfterReading) > 0 {
523 let mut nev = mem::MaybeUninit::uninit();
524 x11_sys::XPeekEvent(self.display, nev.as_mut_ptr());
525 let nev = nev.assume_init();
526 if nev.type_ as u32 == x11_sys::KeyPress
527 && nev.xkey.time == event.xkey.time
528 && nev.xkey.keycode == event.xkey.keycode {
529 self.next_keypress_is_repeat = true;
530 }
531 }
532 if !self.next_keypress_is_repeat {
533 self.do_callback(XlibEvent::KeyUp(KeyEvent {
534 key_code: self.xkeyevent_to_keycode(&mut event.xkey),
535 is_repeat: false,
536 modifiers: self.xkeystate_to_modifiers(event.xkey.state),
537 time: self.time_now()
538 }));
539 }
540 },
541 x11_sys::ClientMessage => {
542 let event = event.xclient;
543 if event.message_type == self.atoms.wm_protocols {
544 if let Some(window_ptr) = self.window_map.get(&event.window) {
545 let window = &mut (**window_ptr);
546 window.close_window();
547 }
548 }
549 if event.message_type == self.dnd.atoms.enter {
550 self.dnd.handle_enter_event(&event);
551 } else if event.message_type == self.dnd.atoms.drop {
552 self.dnd.handle_drop_event(&event);
553 } else if event.message_type == self.dnd.atoms.leave {
554 self.dnd.handle_leave_event(&event);
555 } else if event.message_type == self.dnd.atoms.position {
556 self.dnd.handle_position_event(&event);
557 }
558 },
559 x11_sys::Expose => {
560 },
567 x11_sys::VisibilityNotify => {
568 let event = event.xvisibility;
569 if event.state != x11_sys::VisibilityFullyObscured {
570 if let Some(window_ptr) = self.window_map.get(&event.window) {
571 let window = &mut (**window_ptr);
572 window.send_focus_event();
573 }
574 }
575 }
576
577 _ => {}
578 }
579 }
580 self.do_callback(XlibEvent::Paint);
581 }
582
583 pub fn event_loop(&mut self) {
584 unsafe {
585
586 self.do_callback(XlibEvent::Paint);
587
588 let mut timer_ids = Vec::new();
589 while self.event_loop_running {
590 match self.event_flow {
591 EventFlow::Exit => {
592 break;
593 }
594 EventFlow::Wait => {
595 let time = self.time_now();
596 self.timers.update_timers(&mut timer_ids);
597 for timer_id in &timer_ids{
598 self.do_callback(
599 XlibEvent::Timer(TimerEvent {
600 timer_id:*timer_id,
601 time: Some(time)
602 })
603 );
604 }
605 self.timers.select(self.display_fd);
606 self.event_flow = EventFlow::Poll;
607 }
608 EventFlow::Poll => {
609 let time = self.time_now();
610 self.timers.update_timers(&mut timer_ids);
611 for timer_id in &timer_ids{
612 self.do_callback(
613 XlibEvent::Timer(TimerEvent {
614 timer_id:*timer_id,
615 time: Some(time)
616 })
617 );
618 }
619 self.event_loop_poll();
620 }
621 }
622 }
623 }
624 }
625
626 pub fn do_callback(&mut self, event: XlibEvent) {
627 if let Some(mut callback) = self.event_callback.take() {
628 self.event_flow = callback(self, event);
629 if let EventFlow::Exit = self.event_flow {
630 self.terminate_event_loop();
631 }
632 self.event_callback = Some(callback);
633 }
634 }
635
636 pub fn terminate_event_loop(&mut self) {
637 self.event_loop_running = false;
638 if !self.xim.is_null() {
639 unsafe {x11_sys::XCloseIM(self.xim)};
640 self.xim = ptr::null_mut();
641 }
642 if !self.display.is_null() {
643 unsafe {x11_sys::XCloseDisplay(self.display)};
644 self.display = ptr::null_mut();
645 }
646 }
647
648 pub fn start_timer(&mut self, id: u64, timeout: f64, repeats: bool) {
649 self.timers.start_timer(id, timeout, repeats);
650 }
651
652 pub fn stop_timer(&mut self, id: u64) {
653 self.timers.stop_timer(id);
654 }
655
656 pub fn time_now(&self) -> f64 {
657 self.timers.time_now()
658 }
659
660 pub fn load_first_cursor(&self, names: &[&[u8]]) -> Option<c_ulong> {
661 unsafe {
662 for name in names {
663 let cursor = x11_sys::XcursorLibraryLoadCursor(
664 self.display,
665 name.as_ptr() as *const c_char,
666 );
667 if cursor != 0 {
668 return Some(cursor)
669 }
670 }
671 }
672 return None
673 }
674
675 pub fn set_internal_mouse_cursor(&mut self, cursor: MouseCursor) {
676 if self.internal_cursor != cursor {
677 self.internal_cursor = cursor.clone();
678 self.set_mouse_cursor_(cursor);
679 }
680 }
681
682 pub fn restore_mouse_cursor(&mut self, cursor: MouseCursor) {
683 self.set_mouse_cursor_(cursor);
684 }
685
686 pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) {
687 if self.current_cursor != cursor {
688 self.current_cursor = cursor.clone();
689 self.set_mouse_cursor_(cursor);
690 }
691 }
692
693 fn set_mouse_cursor_(&mut self, cursor: MouseCursor) {
694 let x11_cursor = match cursor {
695 MouseCursor::Hidden => {
696 return;
697 },
698 MouseCursor::EResize => self.load_first_cursor(&[b"right_side\0"]),
699 MouseCursor::NResize => self.load_first_cursor(&[b"top_side\0"]),
700 MouseCursor::NeResize => self.load_first_cursor(&[b"top_right_corner\0"]),
701 MouseCursor::NwResize => self.load_first_cursor(&[b"top_left_corner\0"]),
702 MouseCursor::SResize => self.load_first_cursor(&[b"bottom_side\0"]),
703 MouseCursor::SeResize => self.load_first_cursor(&[b"bottom_right_corner\0"]),
704 MouseCursor::SwResize => self.load_first_cursor(&[b"bottom_left_corner\0"]),
705 MouseCursor::WResize => self.load_first_cursor(&[b"left_side\0"]),
706
707 MouseCursor::Default => self.load_first_cursor(&[b"left_ptr\0"]),
708 MouseCursor::Crosshair => self.load_first_cursor(&[b"crosshair\0"]),
709 MouseCursor::Hand => self.load_first_cursor(&[b"hand2\0", b"left_ptr\0"]),
710 MouseCursor::Arrow => self.load_first_cursor(&[b"left_ptr\0\0"]),
711 MouseCursor::Move => self.load_first_cursor(&[b"move\0"]),
712 MouseCursor::NotAllowed => self.load_first_cursor(&[b"crossed_circle\0"]),
713 MouseCursor::Text => self.load_first_cursor(&[b"text\0", b"xterm\0"]),
714 MouseCursor::Wait => self.load_first_cursor(&[b"watch\0"]),
715 MouseCursor::Help => self.load_first_cursor(&[b"question_arrow\0"]),
716 MouseCursor::NsResize => self.load_first_cursor(&[b"v_double_arrow\0"]),
717 MouseCursor::NeswResize => self.load_first_cursor(&[b"fd_double_arrow\0", b"size_fdiag\0"]),
718 MouseCursor::EwResize => self.load_first_cursor(&[b"h_double_arrow\0"]),
719 MouseCursor::NwseResize => self.load_first_cursor(&[b"bd_double_arrow\0", b"size_bdiag\0"]),
720 MouseCursor::ColResize => self.load_first_cursor(&[b"split_h\0", b"h_double_arrow\0"]),
721 MouseCursor::RowResize => self.load_first_cursor(&[b"split_v\0", b"v_double_arrow\0"]),
722 MouseCursor::Grab => self.load_first_cursor(&[b"grab\0"]),
723 MouseCursor::Grabbing => self.load_first_cursor(&[b"grabbing\0"]),
724 };
725 if let Some(x11_cursor) = x11_cursor {
726 unsafe {
727 for (k, v) in &self.window_map {
728 if !(**v).window.is_none() {
729 x11_sys::XDefineCursor(self.display, *k, x11_cursor);
730 }
731 }
732 x11_sys::XFreeCursor(self.display, x11_cursor);
733 }
734 }
735 }
736
737 fn xbutton_to_mouse_button(&self, button: u32) -> MouseButton {
738 match button {
739 0 => MouseButton::empty(),
740 1 => MouseButton::PRIMARY,
741 2 => MouseButton::MIDDLE,
742 3 => MouseButton::SECONDARY,
743 4..=7 => MouseButton::empty(),
745 8 => MouseButton::BACK,
746 9 => MouseButton::FORWARD,
747 10.. => MouseButton::from_raw_button(button as usize - 4),
748 }
749 }
750
751 fn xkeystate_to_modifiers(&self, state: c_uint) -> KeyModifiers {
752 KeyModifiers {
753 alt: state & x11_sys::Mod1Mask != 0,
754 shift: state & x11_sys::ShiftMask != 0,
755 control: state & x11_sys::ControlMask != 0,
756 logo: state & x11_sys::Mod4Mask != 0,
757 }
758 }
759
760 fn xkeyevent_to_keycode(&self, key_event: &mut x11_sys::XKeyEvent) -> KeyCode {
761 let mut keysym = 0;
762 unsafe {
763 x11_sys::XLookupString(
764 key_event,
765 ptr::null_mut(),
766 0,
767 &mut keysym,
768 ptr::null_mut(),
769 );
770 }
771 match keysym as u32 {
772 x11_sys::XK_a => KeyCode::KeyA,
773 x11_sys::XK_A => KeyCode::KeyA,
774 x11_sys::XK_b => KeyCode::KeyB,
775 x11_sys::XK_B => KeyCode::KeyB,
776 x11_sys::XK_c => KeyCode::KeyC,
777 x11_sys::XK_C => KeyCode::KeyC,
778 x11_sys::XK_d => KeyCode::KeyD,
779 x11_sys::XK_D => KeyCode::KeyD,
780 x11_sys::XK_e => KeyCode::KeyE,
781 x11_sys::XK_E => KeyCode::KeyE,
782 x11_sys::XK_f => KeyCode::KeyF,
783 x11_sys::XK_F => KeyCode::KeyF,
784 x11_sys::XK_g => KeyCode::KeyG,
785 x11_sys::XK_G => KeyCode::KeyG,
786 x11_sys::XK_h => KeyCode::KeyH,
787 x11_sys::XK_H => KeyCode::KeyH,
788 x11_sys::XK_i => KeyCode::KeyI,
789 x11_sys::XK_I => KeyCode::KeyI,
790 x11_sys::XK_j => KeyCode::KeyJ,
791 x11_sys::XK_J => KeyCode::KeyJ,
792 x11_sys::XK_k => KeyCode::KeyK,
793 x11_sys::XK_K => KeyCode::KeyK,
794 x11_sys::XK_l => KeyCode::KeyL,
795 x11_sys::XK_L => KeyCode::KeyL,
796 x11_sys::XK_m => KeyCode::KeyM,
797 x11_sys::XK_M => KeyCode::KeyM,
798 x11_sys::XK_n => KeyCode::KeyN,
799 x11_sys::XK_N => KeyCode::KeyN,
800 x11_sys::XK_o => KeyCode::KeyO,
801 x11_sys::XK_O => KeyCode::KeyO,
802 x11_sys::XK_p => KeyCode::KeyP,
803 x11_sys::XK_P => KeyCode::KeyP,
804 x11_sys::XK_q => KeyCode::KeyQ,
805 x11_sys::XK_Q => KeyCode::KeyQ,
806 x11_sys::XK_r => KeyCode::KeyR,
807 x11_sys::XK_R => KeyCode::KeyR,
808 x11_sys::XK_s => KeyCode::KeyS,
809 x11_sys::XK_S => KeyCode::KeyS,
810 x11_sys::XK_t => KeyCode::KeyT,
811 x11_sys::XK_T => KeyCode::KeyT,
812 x11_sys::XK_u => KeyCode::KeyU,
813 x11_sys::XK_U => KeyCode::KeyU,
814 x11_sys::XK_v => KeyCode::KeyV,
815 x11_sys::XK_V => KeyCode::KeyV,
816 x11_sys::XK_w => KeyCode::KeyW,
817 x11_sys::XK_W => KeyCode::KeyW,
818 x11_sys::XK_x => KeyCode::KeyX,
819 x11_sys::XK_X => KeyCode::KeyX,
820 x11_sys::XK_y => KeyCode::KeyY,
821 x11_sys::XK_Y => KeyCode::KeyY,
822 x11_sys::XK_z => KeyCode::KeyZ,
823 x11_sys::XK_Z => KeyCode::KeyZ,
824
825 x11_sys::XK_0 => KeyCode::Key0,
826 x11_sys::XK_1 => KeyCode::Key1,
827 x11_sys::XK_2 => KeyCode::Key2,
828 x11_sys::XK_3 => KeyCode::Key3,
829 x11_sys::XK_4 => KeyCode::Key4,
830 x11_sys::XK_5 => KeyCode::Key5,
831 x11_sys::XK_6 => KeyCode::Key6,
832 x11_sys::XK_7 => KeyCode::Key7,
833 x11_sys::XK_8 => KeyCode::Key8,
834 x11_sys::XK_9 => KeyCode::Key9,
835
836 x11_sys::XK_Alt_L => KeyCode::Alt,
837 x11_sys::XK_Alt_R => KeyCode::Alt,
838 x11_sys::XK_Meta_L => KeyCode::Logo,
839 x11_sys::XK_Meta_R => KeyCode::Logo,
840 x11_sys::XK_Shift_L => KeyCode::Shift,
841 x11_sys::XK_Shift_R => KeyCode::Shift,
842 x11_sys::XK_Control_L => KeyCode::Control,
843 x11_sys::XK_Control_R => KeyCode::Control,
844
845 x11_sys::XK_equal => KeyCode::Equals,
846 x11_sys::XK_minus => KeyCode::Minus,
847 x11_sys::XK_bracketright => KeyCode::RBracket,
848 x11_sys::XK_bracketleft => KeyCode::LBracket,
849 x11_sys::XK_Return => KeyCode::ReturnKey,
850 x11_sys::XK_grave => KeyCode::Backtick,
851 x11_sys::XK_semicolon => KeyCode::Semicolon,
852 x11_sys::XK_backslash => KeyCode::Backslash,
853 x11_sys::XK_comma => KeyCode::Comma,
854 x11_sys::XK_slash => KeyCode::Slash,
855 x11_sys::XK_period => KeyCode::Period,
856 x11_sys::XK_Tab => KeyCode::Tab,
857 x11_sys::XK_ISO_Left_Tab => KeyCode::Tab,
858 x11_sys::XK_space => KeyCode::Space,
859 x11_sys::XK_BackSpace => KeyCode::Backspace,
860 x11_sys::XK_Escape => KeyCode::Escape,
861 x11_sys::XK_Caps_Lock => KeyCode::Capslock,
862 x11_sys::XK_KP_Decimal => KeyCode::NumpadDecimal,
863 x11_sys::XK_KP_Multiply => KeyCode::NumpadMultiply,
864 x11_sys::XK_KP_Add => KeyCode::NumpadAdd,
865 x11_sys::XK_Num_Lock => KeyCode::Numlock,
866 x11_sys::XK_KP_Divide => KeyCode::NumpadDivide,
867 x11_sys::XK_KP_Enter => KeyCode::NumpadEnter,
868 x11_sys::XK_KP_Subtract => KeyCode::NumpadSubtract,
869 x11_sys::XK_KP_0 => KeyCode::Numpad0,
871 x11_sys::XK_KP_1 => KeyCode::Numpad1,
872 x11_sys::XK_KP_2 => KeyCode::Numpad2,
873 x11_sys::XK_KP_3 => KeyCode::Numpad3,
874 x11_sys::XK_KP_4 => KeyCode::Numpad4,
875 x11_sys::XK_KP_5 => KeyCode::Numpad5,
876 x11_sys::XK_KP_6 => KeyCode::Numpad6,
877 x11_sys::XK_KP_7 => KeyCode::Numpad7,
878 x11_sys::XK_KP_8 => KeyCode::Numpad8,
879 x11_sys::XK_KP_9 => KeyCode::Numpad9,
880
881 x11_sys::XK_F1 => KeyCode::F1,
882 x11_sys::XK_F2 => KeyCode::F2,
883 x11_sys::XK_F3 => KeyCode::F3,
884 x11_sys::XK_F4 => KeyCode::F4,
885 x11_sys::XK_F5 => KeyCode::F5,
886 x11_sys::XK_F6 => KeyCode::F6,
887 x11_sys::XK_F7 => KeyCode::F7,
888 x11_sys::XK_F8 => KeyCode::F8,
889 x11_sys::XK_F9 => KeyCode::F9,
890 x11_sys::XK_F10 => KeyCode::F10,
891 x11_sys::XK_F11 => KeyCode::F11,
892 x11_sys::XK_F12 => KeyCode::F12,
893
894 x11_sys::XK_Print => KeyCode::PrintScreen,
895 x11_sys::XK_Home => KeyCode::Home,
896 x11_sys::XK_Page_Up => KeyCode::PageUp,
897 x11_sys::XK_Delete => KeyCode::Delete,
898 x11_sys::XK_End => KeyCode::End,
899 x11_sys::XK_Page_Down => KeyCode::PageDown,
900 x11_sys::XK_Left => KeyCode::ArrowLeft,
901 x11_sys::XK_Right => KeyCode::ArrowRight,
902 x11_sys::XK_Down => KeyCode::ArrowDown,
903 x11_sys::XK_Up => KeyCode::ArrowUp,
904 _ => KeyCode::Unknown,
905 }
906 }
907
908 pub unsafe fn copy_to_clipboard(&mut self, text: &String, window_id: c_ulong, time: u64) {
909 self.clipboard = text.clone();
911 x11_sys::XSetSelectionOwner(
913 self.display,
914 self.atoms.clipboard,
915 window_id,
916 time
917 );
918 x11_sys::XFlush(self.display);
919 }
920}
921
922pub struct XlibAtoms {
923 pub clipboard: x11_sys::Atom,
924 pub net_wm_moveresize: x11_sys::Atom,
925 pub wm_delete_window: x11_sys::Atom,
926 pub wm_protocols: x11_sys::Atom,
927 pub wm_class: x11_sys::Atom,
928 pub motif_wm_hints: x11_sys::Atom,
929 pub net_wm_state: x11_sys::Atom,
930 pub new_wm_state_maximized_horz: x11_sys::Atom,
931 pub new_wm_state_maximized_vert: x11_sys::Atom,
932 pub targets: x11_sys::Atom,
933 pub string: x11_sys::Atom,
934 pub utf8_string: x11_sys::Atom,
935 pub text: x11_sys::Atom,
936 pub multiple: x11_sys::Atom,
937 pub text_plain: x11_sys::Atom,
938 pub atom: x11_sys::Atom,
939}
940
941impl XlibAtoms {
942 fn new(display: *mut x11_sys::Display) -> Self {
943 unsafe {Self {
944 clipboard: x11_sys::XInternAtom(display, "CLIPBOARD\0".as_ptr() as *const _, 0),
945 net_wm_moveresize: x11_sys::XInternAtom(display, "_NET_WM_MOVERESIZE\0".as_ptr() as *const _, 0),
946 wm_delete_window: x11_sys::XInternAtom(display, "WM_DELETE_WINDOW\0".as_ptr() as *const _, 0),
947 wm_protocols: x11_sys::XInternAtom(display, "WM_PROTOCOLS\0".as_ptr() as *const _, 0),
948 wm_class: x11_sys::XInternAtom(display, "WM_CLASS\0".as_ptr() as *const _, 0),
949 motif_wm_hints: x11_sys::XInternAtom(display, "_MOTIF_WM_HINTS\0".as_ptr() as *const _, 0),
950 net_wm_state: x11_sys::XInternAtom(display, "_NET_WM_STATE\0".as_ptr() as *const _, 0),
951 new_wm_state_maximized_horz: x11_sys::XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_HORZ\0".as_ptr() as *const _, 0),
952 new_wm_state_maximized_vert: x11_sys::XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_VERT\0".as_ptr() as *const _, 0),
953 targets: x11_sys::XInternAtom(display, "TARGETS\0".as_ptr() as *const _, 0),
954 string: x11_sys::XInternAtom(display, "STRING\0".as_ptr() as *const _, 0),
955 utf8_string: x11_sys::XInternAtom(display, "UTF8_STRING\0".as_ptr() as *const _, 1),
956 atom: x11_sys::XInternAtom(display, "ATOM\0".as_ptr() as *const _, 0),
957 text: x11_sys::XInternAtom(display, "TEXT\0".as_ptr() as *const _, 0),
958 text_plain: x11_sys::XInternAtom(display, "text/plain\0".as_ptr() as *const _, 0),
959 multiple: x11_sys::XInternAtom(display, "MULTIPLE\0".as_ptr() as *const _, 0),
960 }}
961 }
962}
963