• 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::collections::BTreeMap;
17 use std::ffi::{c_void, CStr, CString};
18 use std::mem::{transmute_copy, zeroed};
19 use std::num::NonZeroU32;
20 use std::os::raw::c_ulong;
21 use std::ptr::{null, null_mut, NonNull};
22 use std::rc::Rc;
23 use std::time::Duration;
24 
25 use libc::{shmat, shmctl, shmdt, shmget, IPC_CREAT, IPC_PRIVATE, IPC_RMID};
26 
27 use crate::{
28     keycode_converter::KeycodeTranslator, keycode_converter::KeycodeTypes, DisplayT, EventDevice,
29     EventDeviceKind, GpuDisplayError, GpuDisplayFramebuffer,
30 };
31 
32 use base::{error, AsRawDescriptor, EventType, PollToken, RawDescriptor, WaitContext};
33 use data_model::VolatileSlice;
34 
35 const BUFFER_COUNT: usize = 2;
36 
37 type ObjectId = NonZeroU32;
38 
39 /// A wrapper for XFree that takes any type.
x_free<T>(t: *mut T)40 unsafe fn x_free<T>(t: *mut T) {
41     xlib::XFree(t as *mut c_void);
42 }
43 
44 #[derive(Clone)]
45 struct XDisplay(Rc<NonNull<xlib::Display>>);
46 impl Drop for XDisplay {
drop(&mut self)47     fn drop(&mut self) {
48         if Rc::strong_count(&self.0) == 1 {
49             unsafe {
50                 xlib::XCloseDisplay(self.as_ptr());
51             }
52         }
53     }
54 }
55 
56 impl XDisplay {
as_ptr(&self) -> *mut xlib::Display57     fn as_ptr(&self) -> *mut xlib::Display {
58         self.0.as_ptr()
59     }
60 
61     /// Returns true of the XShm extension is supported on this display.
supports_shm(&self) -> bool62     fn supports_shm(&self) -> bool {
63         unsafe { xlib::XShmQueryExtension(self.as_ptr()) != 0 }
64     }
65 
66     /// Gets the default screen of this display.
default_screen(&self) -> Option<XScreen>67     fn default_screen(&self) -> Option<XScreen> {
68         Some(XScreen(NonNull::new(unsafe {
69             xlib::XDefaultScreenOfDisplay(self.as_ptr())
70         })?))
71     }
72 
73     /// Returns true if there are events that are on the queue.
pending_events(&self) -> bool74     fn pending_events(&self) -> bool {
75         unsafe { xlib::XPending(self.as_ptr()) != 0 }
76     }
77 
78     /// Sends any pending commands to the X server.
flush(&self)79     fn flush(&self) {
80         unsafe {
81             xlib::XFlush(self.as_ptr());
82         }
83     }
84 
85     /// Blocks until the next event from the display is received and returns that event.
86     ///
87     /// Always flush before using this if any X commands where issued.
next_event(&self) -> XEvent88     fn next_event(&self) -> XEvent {
89         unsafe {
90             let mut ev = zeroed();
91             xlib::XNextEvent(self.as_ptr(), &mut ev);
92             ev.into()
93         }
94     }
95 }
96 
97 impl AsRawDescriptor for XDisplay {
as_raw_descriptor(&self) -> RawDescriptor98     fn as_raw_descriptor(&self) -> RawDescriptor {
99         unsafe { xlib::XConnectionNumber(self.as_ptr()) }
100     }
101 }
102 
103 struct XEvent(xlib::XEvent);
104 impl From<xlib::XEvent> for XEvent {
from(ev: xlib::XEvent) -> XEvent105     fn from(ev: xlib::XEvent) -> XEvent {
106         XEvent(ev)
107     }
108 }
109 
110 impl XEvent {
any(&self) -> xlib::XAnyEvent111     fn any(&self) -> xlib::XAnyEvent {
112         // All events have the same xany field.
113         unsafe { self.0.xany }
114     }
115 
type_(&self) -> u32116     fn type_(&self) -> u32 {
117         // All events have the same type_ field.
118         unsafe { self.0.type_ as u32 }
119     }
120 
window(&self) -> xlib::Window121     fn window(&self) -> xlib::Window {
122         self.any().window
123     }
124 
125     // Some of the event types are dynamic so they need to be passed in.
as_enum(&self, shm_complete_type: u32) -> XEventEnum126     fn as_enum(&self, shm_complete_type: u32) -> XEventEnum {
127         match self.type_() {
128             xlib::KeyPress | xlib::KeyRelease => XEventEnum::KeyEvent(unsafe { self.0.xkey }),
129             xlib::ButtonPress => XEventEnum::ButtonEvent {
130                 event: unsafe { self.0.xbutton },
131                 pressed: true,
132             },
133             xlib::ButtonRelease => XEventEnum::ButtonEvent {
134                 event: unsafe { self.0.xbutton },
135                 pressed: false,
136             },
137             xlib::MotionNotify => XEventEnum::Motion(unsafe { self.0.xmotion }),
138             xlib::Expose => XEventEnum::Expose,
139             xlib::ClientMessage => {
140                 XEventEnum::ClientMessage(unsafe { self.0.xclient.data.l[0] as u64 })
141             }
142             t if t == shm_complete_type => {
143                 // Because XShmCompletionEvent is not part of the XEvent union, simulate a union
144                 // with transmute_copy. If the shm_complete_type turns out to be bogus, some of the
145                 // data would be incorrect, but the common event fields would still be valid.
146                 let ev_completion: xlib::XShmCompletionEvent = unsafe { transmute_copy(&self.0) };
147                 XEventEnum::ShmCompletionEvent(ev_completion.shmseg)
148             }
149             _ => XEventEnum::Unhandled,
150         }
151     }
152 }
153 
154 enum XEventEnum {
155     KeyEvent(xlib::XKeyEvent),
156     ButtonEvent {
157         event: xlib::XButtonEvent,
158         pressed: bool,
159     },
160     Motion(xlib::XMotionEvent),
161     Expose,
162     ClientMessage(u64),
163     ShmCompletionEvent(xlib::ShmSeg),
164     // We don't care about most kinds of events,
165     Unhandled,
166 }
167 
168 struct XScreen(NonNull<xlib::Screen>);
169 
170 impl XScreen {
as_ptr(&self) -> *mut xlib::Screen171     fn as_ptr(&self) -> *mut xlib::Screen {
172         self.0.as_ptr()
173     }
174 
175     /// Gets the screen number of this screen.
get_number(&self) -> i32176     fn get_number(&self) -> i32 {
177         unsafe { xlib::XScreenNumberOfScreen(self.as_ptr()) }
178     }
179 }
180 
181 struct Buffer {
182     display: XDisplay,
183     image: *mut xlib::XImage,
184     /// The documentation says XShmSegmentInfo must last at least as long as the XImage, which
185     /// probably precludes moving it as well.
186     segment_info: Box<xlib::XShmSegmentInfo>,
187     size: usize,
188     in_use: bool,
189 }
190 
191 impl Drop for Buffer {
drop(&mut self)192     fn drop(&mut self) {
193         unsafe {
194             xlib::XShmDetach(self.display.as_ptr(), self.segment_info.as_mut());
195             xlib::XDestroyImage(self.image);
196             shmdt(self.segment_info.shmaddr as *const _);
197             shmctl(self.segment_info.shmid, IPC_RMID, null_mut());
198         }
199     }
200 }
201 
202 impl Buffer {
as_volatile_slice(&self) -> VolatileSlice203     fn as_volatile_slice(&self) -> VolatileSlice {
204         unsafe { VolatileSlice::from_raw_parts(self.segment_info.shmaddr as *mut _, self.size) }
205     }
206 
stride(&self) -> usize207     fn stride(&self) -> usize {
208         unsafe { (*self.image).bytes_per_line as usize }
209     }
210 
bytes_per_pixel(&self) -> usize211     fn bytes_per_pixel(&self) -> usize {
212         let bytes_per_pixel = unsafe { (*self.image).bits_per_pixel / 8 };
213         bytes_per_pixel as usize
214     }
215 }
216 
217 // Surfaces here are equivalent to XWindows.
218 struct Surface {
219     display: XDisplay,
220     visual: *mut xlib::Visual,
221     depth: u32,
222     window: xlib::Window,
223     gc: xlib::GC,
224     width: u32,
225     height: u32,
226     event_devices: BTreeMap<ObjectId, EventDevice>,
227     keycode_translator: KeycodeTranslator,
228 
229     // Fields for handling the buffer swap chain.
230     buffers: [Option<Buffer>; BUFFER_COUNT],
231     buffer_next: usize,
232     buffer_completion_type: u32,
233 
234     // Fields for handling window close requests
235     delete_window_atom: c_ulong,
236     close_requested: bool,
237 }
238 
239 impl Surface {
create( display: XDisplay, screen: &XScreen, visual: *mut xlib::Visual, width: u32, height: u32, ) -> Surface240     fn create(
241         display: XDisplay,
242         screen: &XScreen,
243         visual: *mut xlib::Visual,
244         width: u32,
245         height: u32,
246     ) -> Surface {
247         let keycode_translator = KeycodeTranslator::new(KeycodeTypes::XkbScancode);
248         unsafe {
249             let depth = xlib::XDefaultDepthOfScreen(screen.as_ptr()) as u32;
250 
251             let black_pixel = xlib::XBlackPixelOfScreen(screen.as_ptr());
252 
253             let window = xlib::XCreateSimpleWindow(
254                 display.as_ptr(),
255                 xlib::XRootWindowOfScreen(screen.as_ptr()),
256                 0,
257                 0,
258                 width,
259                 height,
260                 1,
261                 black_pixel,
262                 black_pixel,
263             );
264 
265             let gc = xlib::XCreateGC(display.as_ptr(), window, 0, null_mut());
266 
267             // Because the event is from an extension, its type must be calculated dynamically.
268             let buffer_completion_type =
269                 xlib::XShmGetEventBase(display.as_ptr()) as u32 + xlib::ShmCompletion;
270 
271             // Mark this window as responding to close requests.
272             let mut delete_window_atom = xlib::XInternAtom(
273                 display.as_ptr(),
274                 CStr::from_bytes_with_nul(b"WM_DELETE_WINDOW\0")
275                     .unwrap()
276                     .as_ptr(),
277                 0,
278             );
279             xlib::XSetWMProtocols(display.as_ptr(), window, &mut delete_window_atom, 1);
280 
281             let size_hints = xlib::XAllocSizeHints();
282             (*size_hints).flags = (xlib::PMinSize | xlib::PMaxSize) as i64;
283             (*size_hints).max_width = width as i32;
284             (*size_hints).min_width = width as i32;
285             (*size_hints).max_height = height as i32;
286             (*size_hints).min_height = height as i32;
287             xlib::XSetWMNormalHints(display.as_ptr(), window, size_hints);
288             x_free(size_hints);
289 
290             // We will use redraw the buffer when we are exposed.
291             xlib::XSelectInput(
292                 display.as_ptr(),
293                 window,
294                 (xlib::ExposureMask
295                     | xlib::KeyPressMask
296                     | xlib::KeyReleaseMask
297                     | xlib::ButtonPressMask
298                     | xlib::ButtonReleaseMask
299                     | xlib::PointerMotionMask) as i64,
300             );
301 
302             xlib::XClearWindow(display.as_ptr(), window);
303             xlib::XMapRaised(display.as_ptr(), window);
304 
305             // Flush everything so that the window is visible immediately.
306             display.flush();
307 
308             Surface {
309                 display,
310                 visual,
311                 depth,
312                 window,
313                 gc,
314                 width,
315                 height,
316                 event_devices: Default::default(),
317                 keycode_translator,
318                 buffers: Default::default(),
319                 buffer_next: 0,
320                 buffer_completion_type,
321                 delete_window_atom,
322                 close_requested: false,
323             }
324         }
325     }
326 
327     /// Returns index of the current (on-screen) buffer, or 0 if there are no buffers.
current_buffer(&self) -> usize328     fn current_buffer(&self) -> usize {
329         match self.buffer_next.checked_sub(1) {
330             Some(i) => i,
331             None => self.buffers.len() - 1,
332         }
333     }
334 
dispatch_to_event_devices( &mut self, events: &[virtio_input_event], device_type: EventDeviceKind, )335     fn dispatch_to_event_devices(
336         &mut self,
337         events: &[virtio_input_event],
338         device_type: EventDeviceKind,
339     ) {
340         for event_device in self.event_devices.values_mut() {
341             if event_device.kind() != device_type {
342                 continue;
343             }
344             if let Err(e) = event_device.send_report(events.iter().cloned()) {
345                 error!("error sending events to event device: {}", e);
346             }
347         }
348     }
349 
handle_event(&mut self, ev: XEvent)350     fn handle_event(&mut self, ev: XEvent) {
351         match ev.as_enum(self.buffer_completion_type) {
352             XEventEnum::KeyEvent(key) => {
353                 if let Some(linux_keycode) = self.keycode_translator.translate(key.keycode) {
354                     let events = &[virtio_input_event::key(
355                         linux_keycode,
356                         key.type_ == xlib::KeyPress as i32,
357                     )];
358                     self.dispatch_to_event_devices(events, EventDeviceKind::Keyboard);
359                 }
360             }
361             XEventEnum::ButtonEvent {
362                 event: button_event,
363                 pressed,
364             } => {
365                 // We only support a single touch from button 1 (left mouse button).
366                 if button_event.button & xlib::Button1 != 0 {
367                     // The touch event *must* be first per the Linux input subsystem's guidance.
368                     let events = &[
369                         virtio_input_event::touch(pressed),
370                         virtio_input_event::absolute_x(max(0, button_event.x)),
371                         virtio_input_event::absolute_y(max(0, button_event.y)),
372                     ];
373                     self.dispatch_to_event_devices(events, EventDeviceKind::Touchscreen);
374                 }
375             }
376             XEventEnum::Motion(motion) => {
377                 if motion.state & xlib::Button1Mask != 0 {
378                     let events = &[
379                         virtio_input_event::touch(true),
380                         virtio_input_event::absolute_x(max(0, motion.x)),
381                         virtio_input_event::absolute_y(max(0, motion.y)),
382                     ];
383                     self.dispatch_to_event_devices(events, EventDeviceKind::Touchscreen);
384                 }
385             }
386             XEventEnum::Expose => self.draw_buffer(self.current_buffer()),
387             XEventEnum::ClientMessage(xclient_data) => {
388                 if xclient_data == self.delete_window_atom {
389                     self.close_requested = true;
390                 }
391             }
392             XEventEnum::ShmCompletionEvent(shmseg) => {
393                 // Find the buffer associated with this event and mark it as not in use.
394                 for buffer_opt in self.buffers.iter_mut() {
395                     if let Some(buffer) = buffer_opt {
396                         if buffer.segment_info.shmseg == shmseg {
397                             buffer.in_use = false;
398                         }
399                     }
400                 }
401             }
402             XEventEnum::Unhandled => {}
403         }
404     }
405 
406     /// Draws the indicated buffer onto the screen.
draw_buffer(&mut self, buffer_index: usize)407     fn draw_buffer(&mut self, buffer_index: usize) {
408         let buffer = match self.buffers.get_mut(buffer_index) {
409             Some(Some(b)) => b,
410             _ => {
411                 // If there is no buffer, that means the framebuffer was never set and we should
412                 // simply blank the window with arbitrary contents.
413                 unsafe {
414                     xlib::XClearWindow(self.display.as_ptr(), self.window);
415                 }
416                 return;
417             }
418         };
419         // Mark the buffer as in use. When the XShmCompletionEvent occurs, this will get marked
420         // false.
421         buffer.in_use = true;
422         unsafe {
423             xlib::XShmPutImage(
424                 self.display.as_ptr(),
425                 self.window,
426                 self.gc,
427                 buffer.image,
428                 0, // src x
429                 0, // src y
430                 0, // dst x
431                 0, // dst y
432                 self.width,
433                 self.height,
434                 true as i32, /* send XShmCompletionEvent event */
435             );
436             self.display.flush();
437         }
438     }
439 
440     /// Gets the buffer at buffer_index, allocating it if necessary.
lazily_allocate_buffer(&mut self, buffer_index: usize) -> Option<&Buffer>441     fn lazily_allocate_buffer(&mut self, buffer_index: usize) -> Option<&Buffer> {
442         if buffer_index >= self.buffers.len() {
443             return None;
444         }
445 
446         if self.buffers[buffer_index].is_some() {
447             return self.buffers[buffer_index].as_ref();
448         }
449         // The buffer_index is valid and the buffer was never created, so we create it now.
450         unsafe {
451             // The docs for XShmCreateImage imply that XShmSegmentInfo must be allocated to live at
452             // least as long as the XImage, which probably means it can't move either. Use a Box in
453             // order to fulfill those requirements.
454             let mut segment_info: Box<xlib::XShmSegmentInfo> = Box::new(zeroed());
455             let image = xlib::XShmCreateImage(
456                 self.display.as_ptr(),
457                 self.visual,
458                 self.depth,
459                 xlib::ZPixmap as i32,
460                 null_mut(),
461                 segment_info.as_mut(),
462                 self.width,
463                 self.height,
464             );
465             if image.is_null() {
466                 return None;
467             }
468             let size = (*image)
469                 .bytes_per_line
470                 .checked_mul((*image).height)
471                 .unwrap();
472             segment_info.shmid = shmget(IPC_PRIVATE, size as usize, IPC_CREAT | 0o777);
473             if segment_info.shmid == -1 {
474                 xlib::XDestroyImage(image);
475                 return None;
476             }
477             segment_info.shmaddr = shmat(segment_info.shmid, null_mut(), 0) as *mut _;
478             if segment_info.shmaddr == (-1isize) as *mut _ {
479                 xlib::XDestroyImage(image);
480                 shmctl(segment_info.shmid, IPC_RMID, null_mut());
481                 return None;
482             }
483             (*image).data = segment_info.shmaddr;
484             segment_info.readOnly = true as i32;
485             xlib::XShmAttach(self.display.as_ptr(), segment_info.as_mut());
486             self.buffers[buffer_index] = Some(Buffer {
487                 display: self.display.clone(),
488                 image,
489                 segment_info,
490                 size: size as usize,
491                 in_use: false,
492             });
493             self.buffers[buffer_index].as_ref()
494         }
495     }
496 
497     /// Gets the next framebuffer, allocating if necessary.
framebuffer(&mut self) -> Option<GpuDisplayFramebuffer>498     fn framebuffer(&mut self) -> Option<GpuDisplayFramebuffer> {
499         // Framebuffers are lazily allocated. If the next buffer is not in self.buffers, add it
500         // using push_new_buffer and then get its memory.
501         let framebuffer = self.lazily_allocate_buffer(self.buffer_next)?;
502         let bytes_per_pixel = framebuffer.bytes_per_pixel() as u32;
503         Some(GpuDisplayFramebuffer::new(
504             framebuffer.as_volatile_slice(),
505             framebuffer.stride() as u32,
506             bytes_per_pixel,
507         ))
508     }
509 
510     /// True if the next buffer is in use because of an XShmPutImage call.
next_buffer_in_use(&self) -> bool511     fn next_buffer_in_use(&self) -> bool {
512         // Buffers that have not yet been made are not in use, hence unwrap_or(false).
513         self.buffers
514             .get(self.buffer_next)
515             .and_then(|b| Some(b.as_ref()?.in_use))
516             .unwrap_or(false)
517     }
518 
519     /// Puts the next buffer onto the screen and sets the next buffer in the swap chain.
flip(&mut self)520     fn flip(&mut self) {
521         let current_buffer_index = self.buffer_next;
522         self.buffer_next = (self.buffer_next + 1) % self.buffers.len();
523         self.draw_buffer(current_buffer_index);
524     }
525 }
526 
527 impl Drop for Surface {
drop(&mut self)528     fn drop(&mut self) {
529         // Safe given it should always be of the correct type.
530         unsafe {
531             xlib::XFreeGC(self.display.as_ptr(), self.gc);
532             xlib::XDestroyWindow(self.display.as_ptr(), self.window);
533         }
534     }
535 }
536 
537 #[derive(PollToken)]
538 enum DisplayXPollToken {
539     Display,
540     EventDevice { event_device_id: u32 },
541 }
542 
543 pub struct DisplayX {
544     wait_ctx: WaitContext<DisplayXPollToken>,
545     display: XDisplay,
546     screen: XScreen,
547     visual: *mut xlib::Visual,
548     next_id: ObjectId,
549     surfaces: BTreeMap<ObjectId, Surface>,
550     event_devices: BTreeMap<ObjectId, EventDevice>,
551 }
552 
553 impl DisplayX {
open_display(display: Option<&str>) -> Result<DisplayX, GpuDisplayError>554     pub fn open_display(display: Option<&str>) -> Result<DisplayX, GpuDisplayError> {
555         let wait_ctx = WaitContext::new().map_err(|_| GpuDisplayError::Allocate)?;
556 
557         let display_cstr = match display.map(CString::new) {
558             Some(Ok(s)) => Some(s),
559             Some(Err(_)) => return Err(GpuDisplayError::InvalidPath),
560             None => None,
561         };
562 
563         unsafe {
564             // Open the display
565             let display = match NonNull::new(xlib::XOpenDisplay(
566                 display_cstr
567                     .as_ref()
568                     .map(|s| CStr::as_ptr(s))
569                     .unwrap_or(null()),
570             )) {
571                 Some(display_ptr) => XDisplay(Rc::new(display_ptr)),
572                 None => return Err(GpuDisplayError::Connect),
573             };
574 
575             wait_ctx
576                 .add(&display, DisplayXPollToken::Display)
577                 .map_err(|_| GpuDisplayError::Allocate)?;
578 
579             // Check for required extension.
580             if !display.supports_shm() {
581                 return Err(GpuDisplayError::RequiredFeature("xshm extension"));
582             }
583 
584             let screen = display
585                 .default_screen()
586                 .ok_or(GpuDisplayError::Connect)
587                 .unwrap();
588             let screen_number = screen.get_number();
589 
590             // Check for and save required visual (24-bit BGR for the default screen).
591             let mut visual_info_template = xlib::XVisualInfo {
592                 visual: null_mut(),
593                 visualid: 0,
594                 screen: screen_number,
595                 depth: 24,
596                 class: 0,
597                 red_mask: 0x00ff0000,
598                 green_mask: 0x0000ff00,
599                 blue_mask: 0x000000ff,
600                 colormap_size: 0,
601                 bits_per_rgb: 0,
602             };
603             let visual_info = xlib::XGetVisualInfo(
604                 display.as_ptr(),
605                 (xlib::VisualScreenMask
606                     | xlib::VisualDepthMask
607                     | xlib::VisualRedMaskMask
608                     | xlib::VisualGreenMaskMask
609                     | xlib::VisualBlueMaskMask) as i64,
610                 &mut visual_info_template,
611                 &mut 0,
612             );
613             if visual_info.is_null() {
614                 return Err(GpuDisplayError::RequiredFeature("no matching visual"));
615             }
616             let visual = (*visual_info).visual;
617             x_free(visual_info);
618 
619             Ok(DisplayX {
620                 wait_ctx,
621                 display,
622                 screen,
623                 visual,
624                 next_id: ObjectId::new(1).unwrap(),
625                 surfaces: Default::default(),
626                 event_devices: Default::default(),
627             })
628         }
629     }
630 
surface_ref(&self, surface_id: u32) -> Option<&Surface>631     fn surface_ref(&self, surface_id: u32) -> Option<&Surface> {
632         ObjectId::new(surface_id).and_then(move |id| self.surfaces.get(&id))
633     }
634 
surface_mut(&mut self, surface_id: u32) -> Option<&mut Surface>635     fn surface_mut(&mut self, surface_id: u32) -> Option<&mut Surface> {
636         ObjectId::new(surface_id).and_then(move |id| self.surfaces.get_mut(&id))
637     }
638 
event_device(&self, event_device_id: u32) -> Option<&EventDevice>639     fn event_device(&self, event_device_id: u32) -> Option<&EventDevice> {
640         ObjectId::new(event_device_id).and_then(move |id| self.event_devices.get(&id))
641     }
642 
event_device_mut(&mut self, event_device_id: u32) -> Option<&mut EventDevice>643     fn event_device_mut(&mut self, event_device_id: u32) -> Option<&mut EventDevice> {
644         ObjectId::new(event_device_id).and_then(move |id| self.event_devices.get_mut(&id))
645     }
646 
handle_event(&mut self, ev: XEvent)647     fn handle_event(&mut self, ev: XEvent) {
648         let window = ev.window();
649         for surface in self.surfaces.values_mut() {
650             if surface.window != window {
651                 continue;
652             }
653             surface.handle_event(ev);
654             return;
655         }
656     }
657 
dispatch_display_events(&mut self)658     fn dispatch_display_events(&mut self) {
659         loop {
660             self.display.flush();
661             if !self.display.pending_events() {
662                 break;
663             }
664             let ev = self.display.next_event();
665             self.handle_event(ev);
666         }
667     }
668 
handle_event_device(&mut self, event_device_id: u32)669     fn handle_event_device(&mut self, event_device_id: u32) {
670         if let Some(event_device) = self.event_device(event_device_id) {
671             // TODO(zachr): decode the event and forward to the device.
672             let _ = event_device.recv_event_encoded();
673         }
674     }
675 
handle_poll_ctx(&mut self) -> base::Result<()>676     fn handle_poll_ctx(&mut self) -> base::Result<()> {
677         let wait_events = self.wait_ctx.wait_timeout(Duration::default())?;
678         for wait_event in wait_events.iter().filter(|e| e.is_writable) {
679             if let DisplayXPollToken::EventDevice { event_device_id } = wait_event.token {
680                 if let Some(event_device) = self.event_device_mut(event_device_id) {
681                     if !event_device.flush_buffered_events()? {
682                         continue;
683                     }
684                 }
685                 // Although this looks exactly like the previous if-block, we need to reborrow self
686                 // as immutable in order to make use of self.wait_ctx.
687                 if let Some(event_device) = self.event_device(event_device_id) {
688                     self.wait_ctx.modify(
689                         event_device,
690                         EventType::Read,
691                         DisplayXPollToken::EventDevice { event_device_id },
692                     )?;
693                 }
694             }
695         }
696 
697         for wait_event in wait_events.iter().filter(|e| e.is_readable) {
698             match wait_event.token {
699                 DisplayXPollToken::Display => self.dispatch_display_events(),
700                 DisplayXPollToken::EventDevice { event_device_id } => {
701                     self.handle_event_device(event_device_id)
702                 }
703             }
704         }
705 
706         Ok(())
707     }
708 }
709 
710 impl DisplayT for DisplayX {
dispatch_events(&mut self)711     fn dispatch_events(&mut self) {
712         if let Err(e) = self.handle_poll_ctx() {
713             error!("failed to dispatch events: {}", e);
714         }
715     }
716 
create_surface( &mut self, parent_surface_id: Option<u32>, width: u32, height: u32, ) -> Result<u32, GpuDisplayError>717     fn create_surface(
718         &mut self,
719         parent_surface_id: Option<u32>,
720         width: u32,
721         height: u32,
722     ) -> Result<u32, GpuDisplayError> {
723         if parent_surface_id.is_some() {
724             return Err(GpuDisplayError::Unsupported);
725         }
726 
727         let new_surface = Surface::create(
728             self.display.clone(),
729             &self.screen,
730             self.visual,
731             width,
732             height,
733         );
734         let new_surface_id = self.next_id;
735         self.surfaces.insert(new_surface_id, new_surface);
736         self.next_id = ObjectId::new(self.next_id.get() + 1).unwrap();
737 
738         Ok(new_surface_id.get())
739     }
740 
release_surface(&mut self, surface_id: u32)741     fn release_surface(&mut self, surface_id: u32) {
742         if let Some(mut surface) =
743             ObjectId::new(surface_id).and_then(|id| self.surfaces.remove(&id))
744         {
745             self.event_devices.append(&mut surface.event_devices);
746         }
747     }
748 
framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer>749     fn framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer> {
750         self.surface_mut(surface_id).and_then(|s| s.framebuffer())
751     }
752 
next_buffer_in_use(&self, surface_id: u32) -> bool753     fn next_buffer_in_use(&self, surface_id: u32) -> bool {
754         self.surface_ref(surface_id)
755             .map(|s| s.next_buffer_in_use())
756             .unwrap_or(false)
757     }
758 
flip(&mut self, surface_id: u32)759     fn flip(&mut self, surface_id: u32) {
760         if let Some(surface) = self.surface_mut(surface_id) {
761             surface.flip()
762         }
763     }
764 
close_requested(&self, surface_id: u32) -> bool765     fn close_requested(&self, surface_id: u32) -> bool {
766         self.surface_ref(surface_id)
767             .map(|s| s.close_requested)
768             .unwrap_or(true)
769     }
770 
771     #[allow(unused_variables)]
import_dmabuf( &mut self, fd: RawDescriptor, offset: u32, stride: u32, modifiers: u64, width: u32, height: u32, fourcc: u32, ) -> Result<u32, GpuDisplayError>772     fn import_dmabuf(
773         &mut self,
774         fd: RawDescriptor,
775         offset: u32,
776         stride: u32,
777         modifiers: u64,
778         width: u32,
779         height: u32,
780         fourcc: u32,
781     ) -> Result<u32, GpuDisplayError> {
782         Err(GpuDisplayError::Unsupported)
783     }
784     #[allow(unused_variables)]
release_import(&mut self, import_id: u32)785     fn release_import(&mut self, import_id: u32) {
786         // unsupported
787     }
788     #[allow(unused_variables)]
commit(&mut self, surface_id: u32)789     fn commit(&mut self, surface_id: u32) {
790         // unsupported
791     }
792     #[allow(unused_variables)]
flip_to(&mut self, surface_id: u32, import_id: u32)793     fn flip_to(&mut self, surface_id: u32, import_id: u32) {
794         // unsupported
795     }
796     #[allow(unused_variables)]
set_position(&mut self, surface_id: u32, x: u32, y: u32)797     fn set_position(&mut self, surface_id: u32, x: u32, y: u32) {
798         // unsupported
799     }
800 
import_event_device(&mut self, event_device: EventDevice) -> Result<u32, GpuDisplayError>801     fn import_event_device(&mut self, event_device: EventDevice) -> Result<u32, GpuDisplayError> {
802         let new_event_device_id = self.next_id;
803 
804         self.wait_ctx
805             .add(
806                 &event_device,
807                 DisplayXPollToken::EventDevice {
808                     event_device_id: new_event_device_id.get(),
809                 },
810             )
811             .map_err(|_| GpuDisplayError::Allocate)?;
812 
813         self.event_devices.insert(new_event_device_id, event_device);
814         self.next_id = ObjectId::new(self.next_id.get() + 1).unwrap();
815 
816         Ok(new_event_device_id.get())
817     }
818 
release_event_device(&mut self, event_device_id: u32)819     fn release_event_device(&mut self, event_device_id: u32) {
820         ObjectId::new(event_device_id).and_then(|id| self.event_devices.remove(&id));
821     }
822 
attach_event_device(&mut self, surface_id: u32, event_device_id: u32)823     fn attach_event_device(&mut self, surface_id: u32, event_device_id: u32) {
824         let event_device_id = match ObjectId::new(event_device_id) {
825             Some(id) => id,
826             None => return,
827         };
828         let surface_id = match ObjectId::new(surface_id) {
829             Some(id) => id,
830             None => return,
831         };
832         let surface = self.surfaces.get_mut(&surface_id).unwrap();
833         let event_device = self.event_devices.remove(&event_device_id).unwrap();
834         surface.event_devices.insert(event_device_id, event_device);
835     }
836 }
837 
838 impl AsRawDescriptor for DisplayX {
as_raw_descriptor(&self) -> RawDescriptor839     fn as_raw_descriptor(&self) -> RawDescriptor {
840         self.wait_ctx.as_raw_descriptor()
841     }
842 }
843