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