• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #[path = "generated/xlib.rs"]
6 #[allow(
7     dead_code,
8     non_snake_case,
9     non_camel_case_types,
10     non_upper_case_globals
11 )]
12 mod xlib;
13 
14 use std::cmp::max;
15 use std::ffi::c_void;
16 use std::ffi::CStr;
17 use std::ffi::CString;
18 use std::mem::transmute_copy;
19 use std::mem::zeroed;
20 use std::os::raw::c_ulong;
21 use std::ptr::null;
22 use std::ptr::null_mut;
23 use std::ptr::NonNull;
24 use std::rc::Rc;
25 
26 use base::AsRawDescriptor;
27 use base::RawDescriptor;
28 use data_model::VolatileSlice;
29 use libc::shmat;
30 use libc::shmctl;
31 use libc::shmdt;
32 use libc::shmget;
33 use libc::IPC_CREAT;
34 use libc::IPC_PRIVATE;
35 use libc::IPC_RMID;
36 use linux_input_sys::virtio_input_event;
37 
38 use crate::keycode_converter::KeycodeTranslator;
39 use crate::keycode_converter::KeycodeTypes;
40 use crate::DisplayT;
41 use crate::EventDeviceKind;
42 use crate::GpuDisplayError;
43 use crate::GpuDisplayEvents;
44 use crate::GpuDisplayFramebuffer;
45 use crate::GpuDisplayResult;
46 use crate::GpuDisplaySurface;
47 use crate::SurfaceType;
48 use crate::SysDisplayT;
49 
50 const BUFFER_COUNT: usize = 2;
51 
52 /// A wrapper for XFree that takes any type.
x_free<T>(t: *mut T)53 unsafe fn x_free<T>(t: *mut T) {
54     xlib::XFree(t as *mut c_void);
55 }
56 
57 #[derive(Clone)]
58 struct XDisplay(Rc<NonNull<xlib::Display>>);
59 impl Drop for XDisplay {
drop(&mut self)60     fn drop(&mut self) {
61         if Rc::strong_count(&self.0) == 1 {
62             unsafe {
63                 xlib::XCloseDisplay(self.as_ptr());
64             }
65         }
66     }
67 }
68 
69 impl XDisplay {
70     /// Returns a pointer to the X display object.
as_ptr(&self) -> *mut xlib::Display71     fn as_ptr(&self) -> *mut xlib::Display {
72         self.0.as_ptr()
73     }
74 
75     /// Sends any pending commands to the X server.
flush(&self)76     fn flush(&self) {
77         unsafe {
78             xlib::XFlush(self.as_ptr());
79         }
80     }
81 
82     /// Returns true of the XShm extension is supported on this display.
supports_shm(&self) -> bool83     fn supports_shm(&self) -> bool {
84         unsafe { xlib::XShmQueryExtension(self.as_ptr()) != 0 }
85     }
86 
87     /// Gets the default screen of this display.
default_screen(&self) -> Option<XScreen>88     fn default_screen(&self) -> Option<XScreen> {
89         Some(XScreen(NonNull::new(unsafe {
90             xlib::XDefaultScreenOfDisplay(self.as_ptr())
91         })?))
92     }
93 
94     /// Blocks until the next event from the display is received and returns that event.
95     ///
96     /// Always flush before using this if any X commands where issued.
next_event(&self) -> XEvent97     fn next_event(&self) -> XEvent {
98         unsafe {
99             let mut ev = zeroed();
100             xlib::XNextEvent(self.as_ptr(), &mut ev);
101             ev.into()
102         }
103     }
104 }
105 
106 impl AsRawDescriptor for XDisplay {
as_raw_descriptor(&self) -> RawDescriptor107     fn as_raw_descriptor(&self) -> RawDescriptor {
108         unsafe { xlib::XConnectionNumber(self.as_ptr()) }
109     }
110 }
111 
112 struct XEvent(xlib::XEvent);
113 impl From<xlib::XEvent> for XEvent {
from(ev: xlib::XEvent) -> XEvent114     fn from(ev: xlib::XEvent) -> XEvent {
115         XEvent(ev)
116     }
117 }
118 
119 impl XEvent {
any(&self) -> xlib::XAnyEvent120     fn any(&self) -> xlib::XAnyEvent {
121         // All events have the same xany field.
122         unsafe { self.0.xany }
123     }
124 
type_(&self) -> u32125     fn type_(&self) -> u32 {
126         // All events have the same type_ field.
127         unsafe { self.0.type_ as u32 }
128     }
129 
window(&self) -> xlib::Window130     fn window(&self) -> xlib::Window {
131         self.any().window
132     }
133 
134     // Some of the event types are dynamic so they need to be passed in.
as_enum(&self, shm_complete_type: u32) -> XEventEnum135     fn as_enum(&self, shm_complete_type: u32) -> XEventEnum {
136         match self.type_() {
137             xlib::KeyPress | xlib::KeyRelease => XEventEnum::KeyEvent(unsafe { self.0.xkey }),
138             xlib::ButtonPress => XEventEnum::ButtonEvent {
139                 event: unsafe { self.0.xbutton },
140                 pressed: true,
141             },
142             xlib::ButtonRelease => XEventEnum::ButtonEvent {
143                 event: unsafe { self.0.xbutton },
144                 pressed: false,
145             },
146             xlib::MotionNotify => XEventEnum::Motion(unsafe { self.0.xmotion }),
147             xlib::Expose => XEventEnum::Expose,
148             xlib::ClientMessage => {
149                 XEventEnum::ClientMessage(unsafe { self.0.xclient.data.l[0] as u64 })
150             }
151             t if t == shm_complete_type => {
152                 // Because XShmCompletionEvent is not part of the XEvent union, simulate a union
153                 // with transmute_copy. If the shm_complete_type turns out to be bogus, some of the
154                 // data would be incorrect, but the common event fields would still be valid.
155                 let ev_completion: xlib::XShmCompletionEvent = unsafe { transmute_copy(&self.0) };
156                 XEventEnum::ShmCompletionEvent(ev_completion.shmseg)
157             }
158             _ => XEventEnum::Unhandled,
159         }
160     }
161 }
162 
163 enum XEventEnum {
164     KeyEvent(xlib::XKeyEvent),
165     ButtonEvent {
166         event: xlib::XButtonEvent,
167         pressed: bool,
168     },
169     Motion(xlib::XMotionEvent),
170     Expose,
171     ClientMessage(u64),
172     ShmCompletionEvent(xlib::ShmSeg),
173     // We don't care about most kinds of events,
174     Unhandled,
175 }
176 
177 struct XScreen(NonNull<xlib::Screen>);
178 
179 impl XScreen {
as_ptr(&self) -> *mut xlib::Screen180     fn as_ptr(&self) -> *mut xlib::Screen {
181         self.0.as_ptr()
182     }
183 
184     /// Gets the screen number of this screen.
get_number(&self) -> i32185     fn get_number(&self) -> i32 {
186         unsafe { xlib::XScreenNumberOfScreen(self.as_ptr()) }
187     }
188 }
189 
190 struct Buffer {
191     display: XDisplay,
192     image: *mut xlib::XImage,
193     /// The documentation says XShmSegmentInfo must last at least as long as the XImage, which
194     /// probably precludes moving it as well.
195     segment_info: Box<xlib::XShmSegmentInfo>,
196     size: usize,
197     in_use: bool,
198 }
199 
200 impl Drop for Buffer {
drop(&mut self)201     fn drop(&mut self) {
202         unsafe {
203             xlib::XShmDetach(self.display.as_ptr(), self.segment_info.as_mut());
204             xlib::XDestroyImage(self.image);
205             shmdt(self.segment_info.shmaddr as *const _);
206             shmctl(self.segment_info.shmid, IPC_RMID, null_mut());
207         }
208     }
209 }
210 
211 impl Buffer {
as_volatile_slice(&self) -> VolatileSlice212     fn as_volatile_slice(&self) -> VolatileSlice {
213         unsafe { VolatileSlice::from_raw_parts(self.segment_info.shmaddr as *mut _, self.size) }
214     }
215 
stride(&self) -> usize216     fn stride(&self) -> usize {
217         unsafe { (*self.image).bytes_per_line as usize }
218     }
219 
bytes_per_pixel(&self) -> usize220     fn bytes_per_pixel(&self) -> usize {
221         let bytes_per_pixel = unsafe { (*self.image).bits_per_pixel / 8 };
222         bytes_per_pixel as usize
223     }
224 }
225 
226 // Surfaces here are equivalent to XWindows.
227 struct XSurface {
228     display: XDisplay,
229     visual: *mut xlib::Visual,
230     depth: u32,
231     window: xlib::Window,
232     gc: xlib::GC,
233     width: u32,
234     height: u32,
235 
236     // Fields for handling the buffer swap chain.
237     buffers: [Option<Buffer>; BUFFER_COUNT],
238     buffer_next: usize,
239     buffer_completion_type: u32,
240 
241     // Fields for handling window close requests
242     delete_window_atom: c_ulong,
243     close_requested: bool,
244 }
245 
246 impl XSurface {
247     /// Returns index of the current (on-screen) buffer, or 0 if there are no buffers.
current_buffer(&self) -> usize248     fn current_buffer(&self) -> usize {
249         match self.buffer_next.checked_sub(1) {
250             Some(i) => i,
251             None => self.buffers.len() - 1,
252         }
253     }
254 
255     /// Draws the indicated buffer onto the screen.
draw_buffer(&mut self, buffer_index: usize)256     fn draw_buffer(&mut self, buffer_index: usize) {
257         let buffer = match self.buffers.get_mut(buffer_index) {
258             Some(Some(b)) => b,
259             _ => {
260                 // If there is no buffer, that means the framebuffer was never set and we should
261                 // simply blank the window with arbitrary contents.
262                 unsafe {
263                     xlib::XClearWindow(self.display.as_ptr(), self.window);
264                 }
265                 return;
266             }
267         };
268         // Mark the buffer as in use. When the XShmCompletionEvent occurs, this will get marked
269         // false.
270         buffer.in_use = true;
271         unsafe {
272             xlib::XShmPutImage(
273                 self.display.as_ptr(),
274                 self.window,
275                 self.gc,
276                 buffer.image,
277                 0, // src x
278                 0, // src y
279                 0, // dst x
280                 0, // dst y
281                 self.width,
282                 self.height,
283                 true as i32, /* send XShmCompletionEvent event */
284             );
285             self.display.flush();
286         }
287     }
288 
289     /// Gets the buffer at buffer_index, allocating it if necessary.
lazily_allocate_buffer(&mut self, buffer_index: usize) -> Option<&Buffer>290     fn lazily_allocate_buffer(&mut self, buffer_index: usize) -> Option<&Buffer> {
291         if buffer_index >= self.buffers.len() {
292             return None;
293         }
294 
295         if self.buffers[buffer_index].is_some() {
296             return self.buffers[buffer_index].as_ref();
297         }
298         // The buffer_index is valid and the buffer was never created, so we create it now.
299         unsafe {
300             // The docs for XShmCreateImage imply that XShmSegmentInfo must be allocated to live at
301             // least as long as the XImage, which probably means it can't move either. Use a Box in
302             // order to fulfill those requirements.
303             let mut segment_info: Box<xlib::XShmSegmentInfo> = Box::new(zeroed());
304             let image = xlib::XShmCreateImage(
305                 self.display.as_ptr(),
306                 self.visual,
307                 self.depth,
308                 xlib::ZPixmap as i32,
309                 null_mut(),
310                 segment_info.as_mut(),
311                 self.width,
312                 self.height,
313             );
314             if image.is_null() {
315                 return None;
316             }
317             let size = (*image)
318                 .bytes_per_line
319                 .checked_mul((*image).height)
320                 .unwrap();
321             segment_info.shmid = shmget(IPC_PRIVATE, size as usize, IPC_CREAT | 0o777);
322             if segment_info.shmid == -1 {
323                 xlib::XDestroyImage(image);
324                 return None;
325             }
326             segment_info.shmaddr = shmat(segment_info.shmid, null_mut(), 0) as *mut _;
327             if segment_info.shmaddr == (-1isize) as *mut _ {
328                 xlib::XDestroyImage(image);
329                 shmctl(segment_info.shmid, IPC_RMID, null_mut());
330                 return None;
331             }
332             (*image).data = segment_info.shmaddr;
333             segment_info.readOnly = true as i32;
334             xlib::XShmAttach(self.display.as_ptr(), segment_info.as_mut());
335             self.buffers[buffer_index] = Some(Buffer {
336                 display: self.display.clone(),
337                 image,
338                 segment_info,
339                 size: size as usize,
340                 in_use: false,
341             });
342             self.buffers[buffer_index].as_ref()
343         }
344     }
345 }
346 
347 impl GpuDisplaySurface for XSurface {
surface_descriptor(&self) -> u64348     fn surface_descriptor(&self) -> u64 {
349         self.window as u64
350     }
351 
framebuffer(&mut self) -> Option<GpuDisplayFramebuffer>352     fn framebuffer(&mut self) -> Option<GpuDisplayFramebuffer> {
353         // Framebuffers are lazily allocated. If the next buffer is not in self.buffers, add it
354         // using push_new_buffer and then get its memory.
355         let framebuffer = self.lazily_allocate_buffer(self.buffer_next)?;
356         let bytes_per_pixel = framebuffer.bytes_per_pixel() as u32;
357         Some(GpuDisplayFramebuffer::new(
358             framebuffer.as_volatile_slice(),
359             framebuffer.stride() as u32,
360             bytes_per_pixel,
361         ))
362     }
363 
next_buffer_in_use(&self) -> bool364     fn next_buffer_in_use(&self) -> bool {
365         // Buffers that have not yet been made are not in use, hence unwrap_or(false).
366         self.buffers
367             .get(self.buffer_next)
368             .and_then(|b| Some(b.as_ref()?.in_use))
369             .unwrap_or(false)
370     }
371 
close_requested(&self) -> bool372     fn close_requested(&self) -> bool {
373         self.close_requested
374     }
375 
flip(&mut self)376     fn flip(&mut self) {
377         let current_buffer_index = self.buffer_next;
378         self.buffer_next = (self.buffer_next + 1) % self.buffers.len();
379         self.draw_buffer(current_buffer_index);
380     }
381 
buffer_completion_type(&self) -> u32382     fn buffer_completion_type(&self) -> u32 {
383         self.buffer_completion_type
384     }
385 
draw_current_buffer(&mut self)386     fn draw_current_buffer(&mut self) {
387         self.draw_buffer(self.current_buffer())
388     }
389 
on_client_message(&mut self, client_data: u64)390     fn on_client_message(&mut self, client_data: u64) {
391         if client_data == self.delete_window_atom {
392             self.close_requested = true;
393         }
394     }
395 
on_shm_completion(&mut self, shm_complete: u64)396     fn on_shm_completion(&mut self, shm_complete: u64) {
397         for buffer in self.buffers.iter_mut().flatten() {
398             if buffer.segment_info.shmseg == shm_complete {
399                 buffer.in_use = false;
400             }
401         }
402     }
403 }
404 
405 impl Drop for XSurface {
drop(&mut self)406     fn drop(&mut self) {
407         // Safe given it should always be of the correct type.
408         unsafe {
409             xlib::XFreeGC(self.display.as_ptr(), self.gc);
410             xlib::XDestroyWindow(self.display.as_ptr(), self.window);
411         }
412     }
413 }
414 
415 pub struct DisplayX {
416     display: XDisplay,
417     screen: XScreen,
418     visual: *mut xlib::Visual,
419     keycode_translator: KeycodeTranslator,
420     current_event: Option<XEvent>,
421     mt_tracking_id: u16,
422 }
423 
424 impl DisplayX {
open_display(display: Option<&str>) -> GpuDisplayResult<DisplayX>425     pub fn open_display(display: Option<&str>) -> GpuDisplayResult<DisplayX> {
426         let display_cstr = match display.map(CString::new) {
427             Some(Ok(s)) => Some(s),
428             Some(Err(_)) => return Err(GpuDisplayError::InvalidPath),
429             None => None,
430         };
431 
432         let keycode_translator = KeycodeTranslator::new(KeycodeTypes::XkbScancode);
433 
434         unsafe {
435             // Open the display
436             let display = match NonNull::new(xlib::XOpenDisplay(
437                 display_cstr
438                     .as_ref()
439                     .map(|s| CStr::as_ptr(s))
440                     .unwrap_or(null()),
441             )) {
442                 Some(display_ptr) => XDisplay(Rc::new(display_ptr)),
443                 None => return Err(GpuDisplayError::Connect),
444             };
445 
446             // Check for required extension.
447             if !display.supports_shm() {
448                 return Err(GpuDisplayError::RequiredFeature("xshm extension"));
449             }
450 
451             let screen = display
452                 .default_screen()
453                 .ok_or(GpuDisplayError::Connect)
454                 .unwrap();
455             let screen_number = screen.get_number();
456 
457             // Check for and save required visual (24-bit BGR for the default screen).
458             let mut visual_info_template = xlib::XVisualInfo {
459                 visual: null_mut(),
460                 visualid: 0,
461                 screen: screen_number,
462                 depth: 24,
463                 class: 0,
464                 red_mask: 0x00ff0000,
465                 green_mask: 0x0000ff00,
466                 blue_mask: 0x000000ff,
467                 colormap_size: 0,
468                 bits_per_rgb: 0,
469             };
470             let visual_info = xlib::XGetVisualInfo(
471                 display.as_ptr(),
472                 (xlib::VisualScreenMask
473                     | xlib::VisualDepthMask
474                     | xlib::VisualRedMaskMask
475                     | xlib::VisualGreenMaskMask
476                     | xlib::VisualBlueMaskMask) as i64,
477                 &mut visual_info_template,
478                 &mut 0,
479             );
480             if visual_info.is_null() {
481                 return Err(GpuDisplayError::RequiredFeature("no matching visual"));
482             }
483             let visual = (*visual_info).visual;
484             x_free(visual_info);
485 
486             Ok(DisplayX {
487                 display,
488                 screen,
489                 visual,
490                 keycode_translator,
491                 current_event: None,
492                 mt_tracking_id: 0,
493             })
494         }
495     }
496 
next_tracking_id(&mut self) -> i32497     pub fn next_tracking_id(&mut self) -> i32 {
498         let cur_id: i32 = self.mt_tracking_id as i32;
499         self.mt_tracking_id = self.mt_tracking_id.wrapping_add(1);
500         cur_id
501     }
502 
current_tracking_id(&self) -> i32503     pub fn current_tracking_id(&self) -> i32 {
504         self.mt_tracking_id as i32
505     }
506 }
507 
508 impl DisplayT for DisplayX {
pending_events(&self) -> bool509     fn pending_events(&self) -> bool {
510         unsafe { xlib::XPending(self.display.as_ptr()) != 0 }
511     }
512 
flush(&self)513     fn flush(&self) {
514         self.display.flush();
515     }
516 
next_event(&mut self) -> GpuDisplayResult<u64>517     fn next_event(&mut self) -> GpuDisplayResult<u64> {
518         let ev = self.display.next_event();
519         let descriptor = ev.window() as u64;
520         self.current_event = Some(ev);
521         Ok(descriptor)
522     }
523 
handle_next_event( &mut self, surface: &mut Box<dyn GpuDisplaySurface>, ) -> Option<GpuDisplayEvents>524     fn handle_next_event(
525         &mut self,
526         surface: &mut Box<dyn GpuDisplaySurface>,
527     ) -> Option<GpuDisplayEvents> {
528         // Should not panic since the common layer only calls this when an event exists.
529         let ev = self.current_event.take().unwrap();
530 
531         match ev.as_enum(surface.buffer_completion_type()) {
532             XEventEnum::KeyEvent(key) => {
533                 if let Some(linux_keycode) = self.keycode_translator.translate(key.keycode) {
534                     let events = vec![virtio_input_event::key(
535                         linux_keycode,
536                         key.type_ == xlib::KeyPress as i32,
537                     )];
538 
539                     return Some(GpuDisplayEvents {
540                         events,
541                         device_type: EventDeviceKind::Keyboard,
542                     });
543                 }
544             }
545             XEventEnum::ButtonEvent {
546                 event: button_event,
547                 pressed,
548             } => {
549                 // We only support a single touch from button 1 (left mouse button).
550                 // TODO(tutankhamen): slot is always 0, because all the input
551                 // events come from mouse device, i.e. only one touch is possible at a time.
552                 // Full MT protocol has to be implemented and properly wired later.
553                 if button_event.button & xlib::Button1 != 0 {
554                     // The touch event *must* be first per the Linux input subsystem's guidance.
555                     let mut events = vec![virtio_input_event::multitouch_slot(0)];
556 
557                     if pressed {
558                         events.push(virtio_input_event::multitouch_tracking_id(
559                             self.next_tracking_id(),
560                         ));
561                         events.push(virtio_input_event::multitouch_absolute_x(max(
562                             0,
563                             button_event.x,
564                         )));
565                         events.push(virtio_input_event::multitouch_absolute_y(max(
566                             0,
567                             button_event.y,
568                         )));
569                     } else {
570                         events.push(virtio_input_event::multitouch_tracking_id(-1));
571                     }
572 
573                     return Some(GpuDisplayEvents {
574                         events,
575                         device_type: EventDeviceKind::Touchscreen,
576                     });
577                 }
578             }
579             XEventEnum::Motion(motion) => {
580                 if motion.state & xlib::Button1Mask != 0 {
581                     let events = vec![
582                         virtio_input_event::multitouch_slot(0),
583                         virtio_input_event::multitouch_tracking_id(self.current_tracking_id()),
584                         virtio_input_event::multitouch_absolute_x(max(0, motion.x)),
585                         virtio_input_event::multitouch_absolute_y(max(0, motion.y)),
586                     ];
587 
588                     return Some(GpuDisplayEvents {
589                         events,
590                         device_type: EventDeviceKind::Touchscreen,
591                     });
592                 }
593             }
594             XEventEnum::Expose => surface.draw_current_buffer(),
595             XEventEnum::ClientMessage(xclient_data) => {
596                 surface.on_client_message(xclient_data);
597                 return None;
598             }
599             XEventEnum::ShmCompletionEvent(shmseg) => {
600                 surface.on_shm_completion(shmseg);
601                 return None;
602             }
603             XEventEnum::Unhandled => return None,
604         }
605 
606         None
607     }
608 
create_surface( &mut self, parent_surface_id: Option<u32>, _surface_id: u32, width: u32, height: u32, _surf_type: SurfaceType, ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>>609     fn create_surface(
610         &mut self,
611         parent_surface_id: Option<u32>,
612         _surface_id: u32,
613         width: u32,
614         height: u32,
615         _surf_type: SurfaceType,
616     ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>> {
617         if parent_surface_id.is_some() {
618             return Err(GpuDisplayError::Unsupported);
619         }
620 
621         unsafe {
622             let depth = xlib::XDefaultDepthOfScreen(self.screen.as_ptr()) as u32;
623 
624             let black_pixel = xlib::XBlackPixelOfScreen(self.screen.as_ptr());
625 
626             let window = xlib::XCreateSimpleWindow(
627                 self.display.as_ptr(),
628                 xlib::XRootWindowOfScreen(self.screen.as_ptr()),
629                 0,
630                 0,
631                 width,
632                 height,
633                 1,
634                 black_pixel,
635                 black_pixel,
636             );
637 
638             let gc = xlib::XCreateGC(self.display.as_ptr(), window, 0, null_mut());
639 
640             // Because the event is from an extension, its type must be calculated dynamically.
641             let buffer_completion_type =
642                 xlib::XShmGetEventBase(self.display.as_ptr()) as u32 + xlib::ShmCompletion;
643 
644             // Mark this window as responding to close requests.
645             let mut delete_window_atom = xlib::XInternAtom(
646                 self.display.as_ptr(),
647                 CStr::from_bytes_with_nul(b"WM_DELETE_WINDOW\0")
648                     .unwrap()
649                     .as_ptr(),
650                 0,
651             );
652             xlib::XSetWMProtocols(self.display.as_ptr(), window, &mut delete_window_atom, 1);
653 
654             let size_hints = xlib::XAllocSizeHints();
655             (*size_hints).flags = (xlib::PMinSize | xlib::PMaxSize) as i64;
656             (*size_hints).max_width = width as i32;
657             (*size_hints).min_width = width as i32;
658             (*size_hints).max_height = height as i32;
659             (*size_hints).min_height = height as i32;
660             xlib::XSetWMNormalHints(self.display.as_ptr(), window, size_hints);
661             x_free(size_hints);
662 
663             // We will use redraw the buffer when we are exposed.
664             xlib::XSelectInput(
665                 self.display.as_ptr(),
666                 window,
667                 (xlib::ExposureMask
668                     | xlib::KeyPressMask
669                     | xlib::KeyReleaseMask
670                     | xlib::ButtonPressMask
671                     | xlib::ButtonReleaseMask
672                     | xlib::PointerMotionMask) as i64,
673             );
674 
675             xlib::XClearWindow(self.display.as_ptr(), window);
676             xlib::XMapRaised(self.display.as_ptr(), window);
677 
678             // Flush everything so that the window is visible immediately.
679             self.display.flush();
680 
681             Ok(Box::new(XSurface {
682                 display: self.display.clone(),
683                 visual: self.visual,
684                 depth,
685                 window,
686                 gc,
687                 width,
688                 height,
689                 buffers: Default::default(),
690                 buffer_next: 0,
691                 buffer_completion_type,
692                 delete_window_atom,
693                 close_requested: false,
694             }))
695         }
696     }
697 }
698 
699 impl SysDisplayT for DisplayX {}
700 
701 impl AsRawDescriptor for DisplayX {
as_raw_descriptor(&self) -> RawDescriptor702     fn as_raw_descriptor(&self) -> RawDescriptor {
703         self.display.as_raw_descriptor()
704     }
705 }
706