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