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