1 // Copyright 2022 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 use std::cell::RefCell; 6 use std::collections::BTreeMap; 7 use std::marker::PhantomPinned; 8 use std::os::raw::c_void; 9 use std::pin::Pin; 10 use std::ptr::null_mut; 11 use std::rc::Rc; 12 13 use anyhow::bail; 14 use anyhow::Context; 15 use anyhow::Result; 16 use base::debug; 17 use base::error; 18 use base::info; 19 use linux_input_sys::virtio_input_event; 20 #[cfg(feature = "kiwi")] 21 use vm_control::ServiceSendToGpu; 22 use winapi::shared::minwindef::LRESULT; 23 use winapi::shared::windef::HWND; 24 use winapi::um::winuser::*; 25 26 use super::window::MessagePacket; 27 use super::window::Window; 28 use super::window_message_processor::*; 29 use super::ObjectId; 30 use crate::EventDevice; 31 use crate::EventDeviceKind; 32 33 /// The pointer to dispatcher will be stored with HWND using `SetPropW()` with the following name. 34 pub(crate) const DISPATCHER_PROPERTY_NAME: &str = "PROP_WND_MSG_DISPATCHER"; 35 36 /// This class is used to dispatch display events to the guest device. 37 #[derive(Clone)] 38 pub struct DisplayEventDispatcher { 39 event_devices: Rc<RefCell<BTreeMap<ObjectId, EventDevice>>>, 40 } 41 42 impl DisplayEventDispatcher { new() -> Self43 pub fn new() -> Self { 44 Self { 45 event_devices: Default::default(), 46 } 47 } 48 dispatch(&self, events: &[virtio_input_event], device_type: EventDeviceKind)49 pub fn dispatch(&self, events: &[virtio_input_event], device_type: EventDeviceKind) { 50 for event_device in self 51 .event_devices 52 .borrow_mut() 53 .values_mut() 54 .filter(|event_device| event_device.kind() == device_type) 55 { 56 if let Err(e) = event_device.send_report(events.iter().cloned()) { 57 error!("Failed to send events to event device: {}", e); 58 } 59 } 60 } 61 import_event_device(&mut self, event_device_id: ObjectId, event_device: EventDevice)62 fn import_event_device(&mut self, event_device_id: ObjectId, event_device: EventDevice) { 63 info!("Importing {:?} (ID: {:?})", event_device, event_device_id); 64 self.event_devices 65 .borrow_mut() 66 .insert(event_device_id, event_device); 67 } 68 } 69 70 /// This class is used for dispatching thread and window messages. It should be created before any 71 /// other threads start to post messages to the WndProc thread, and before the WndProc thread enters 72 /// the window message loop. Once all windows tracked by it are destroyed, it will signal exiting 73 /// the message loop and then it can be dropped. 74 pub(crate) struct WindowMessageDispatcher<T: HandleWindowMessage> { 75 message_processor: Option<WindowMessageProcessor<T>>, 76 display_event_dispatcher: DisplayEventDispatcher, 77 // The dispatcher is pinned so that its address in the memory won't change, and it is always 78 // safe to use the pointer to it stored in the window. 79 _pinned_marker: PhantomPinned, 80 } 81 82 impl<T: HandleWindowMessage> WindowMessageDispatcher<T> { 83 /// This function should only be called once from the WndProc thread. It will take the ownership 84 /// of the `Window` object, and drop it before the underlying window is completely gone. 85 /// TODO(b/238680252): This should be good enough for supporting multi-windowing, but we should 86 /// revisit it if we also want to manage some child windows of the crosvm window. create(window: Window) -> Result<Pin<Box<Self>>>87 pub fn create(window: Window) -> Result<Pin<Box<Self>>> { 88 let mut dispatcher = Box::pin(Self { 89 message_processor: Default::default(), 90 display_event_dispatcher: DisplayEventDispatcher::new(), 91 _pinned_marker: PhantomPinned, 92 }); 93 dispatcher 94 .as_mut() 95 .create_message_processor(window) 96 .context("When creating WindowMessageDispatcher")?; 97 Ok(dispatcher) 98 } 99 process_thread_message(self: Pin<&mut Self>, packet: &MessagePacket)100 pub fn process_thread_message(self: Pin<&mut Self>, packet: &MessagePacket) { 101 // Safe because we won't move the dispatcher out of it. 102 unsafe { 103 self.get_unchecked_mut() 104 .process_thread_message_internal(packet); 105 } 106 } 107 108 /// Returns `Some` if the message is processed by the targeted window. dispatch_window_message( &mut self, hwnd: HWND, packet: &MessagePacket, ) -> Option<LRESULT>109 pub fn dispatch_window_message( 110 &mut self, 111 hwnd: HWND, 112 packet: &MessagePacket, 113 ) -> Option<LRESULT> { 114 if let Some(processor) = &mut self.message_processor { 115 if processor.window().is_same_window(hwnd) { 116 let ret = processor.process_message(packet); 117 // `WM_NCDESTROY` is sent at the end of the window destruction, and is the last 118 // message the window will receive. Drop the message processor so that associated 119 // resources can be cleaned up before the window is completely gone. 120 if packet.msg == WM_NCDESTROY { 121 if let Err(e) = Self::remove_pointer_from_window(processor.window()) { 122 error!("{:?}", e); 123 } 124 self.message_processor = None; 125 Self::request_exit_message_loop(); 126 } 127 return Some(ret); 128 } 129 } 130 None 131 } 132 create_message_processor(self: Pin<&mut Self>, window: Window) -> Result<()>133 fn create_message_processor(self: Pin<&mut Self>, window: Window) -> Result<()> { 134 if !window.is_valid() { 135 bail!("Window handle is invalid!"); 136 } 137 Self::store_pointer_in_window(&*self, &window)?; 138 // Safe because we won't move the dispatcher out of it, and the dispatcher is aware of the 139 // lifecycle of the window. 140 unsafe { 141 self.get_unchecked_mut() 142 .message_processor 143 .replace(WindowMessageProcessor::<T>::new(window)); 144 } 145 Ok(()) 146 } 147 process_thread_message_internal(&mut self, packet: &MessagePacket)148 fn process_thread_message_internal(&mut self, packet: &MessagePacket) { 149 let MessagePacket { 150 msg, 151 w_param, 152 l_param, 153 } = *packet; 154 match msg { 155 #[cfg(feature = "kiwi")] 156 WM_USER_HANDLE_SERVICE_MESSAGE_INTERNAL => { 157 // Safe because the sender gives up the ownership and expects the receiver to 158 // destruct the message. 159 let message = unsafe { Box::from_raw(l_param as *mut ServiceSendToGpu) }; 160 match &mut self.message_processor { 161 Some(processor) => processor.handle_service_message(&*message), 162 None => error!( 163 "Cannot handle service message because there is no message processor!" 164 ), 165 } 166 } 167 WM_USER_HANDLE_DISPLAY_MESSAGE_INTERNAL => { 168 // Safe because the sender gives up the ownership and expects the receiver to 169 // destruct the message. 170 let message = unsafe { Box::from_raw(l_param as *mut DisplaySendToWndProc<T>) }; 171 self.handle_display_message(*message); 172 } 173 WM_USER_WNDPROC_THREAD_DROP_KILL_WINDOW_INTERNAL => match &self.message_processor { 174 Some(processor) => { 175 debug!("Destroying window on WndProc thread drop"); 176 if let Err(e) = processor.window().destroy() { 177 error!( 178 "Failed to destroy window when dropping WndProc thread: {:?}", 179 e 180 ); 181 } 182 } 183 None => debug!("No window to destroy on WndProc thread drop"), 184 }, 185 // Safe because we are processing a message targeting this thread. 186 _ => unsafe { 187 DefWindowProcW(null_mut(), msg, w_param, l_param); 188 }, 189 } 190 } 191 handle_display_message(&mut self, message: DisplaySendToWndProc<T>)192 fn handle_display_message(&mut self, message: DisplaySendToWndProc<T>) { 193 match message { 194 DisplaySendToWndProc::CreateSurface { function, callback } => { 195 callback(self.create_message_handler(function)); 196 } 197 DisplaySendToWndProc::ImportEventDevice { 198 event_device_id, 199 event_device, 200 } => { 201 self.display_event_dispatcher 202 .import_event_device(event_device_id, event_device); 203 } 204 } 205 } 206 207 /// Returns true if the window message handler is created successfully. create_message_handler( &mut self, create_handler_func: CreateMessageHandlerFunction<T>, ) -> bool208 fn create_message_handler( 209 &mut self, 210 create_handler_func: CreateMessageHandlerFunction<T>, 211 ) -> bool { 212 match &mut self.message_processor { 213 Some(processor) => match processor 214 .create_message_handler(create_handler_func, self.display_event_dispatcher.clone()) 215 { 216 Ok(_) => return true, 217 Err(e) => error!("Failed to create message handler: {:?}", e), 218 }, 219 None => { 220 error!("Cannot create message handler because there is no message processor!") 221 } 222 } 223 false 224 } 225 store_pointer_in_window(pointer: *const Self, window: &Window) -> Result<()>226 fn store_pointer_in_window(pointer: *const Self, window: &Window) -> Result<()> { 227 window 228 .set_property(DISPATCHER_PROPERTY_NAME, pointer as *mut c_void) 229 .context("When storing message dispatcher pointer") 230 } 231 232 /// When the window is being destroyed, we must remove all entries added to the property list 233 /// before `WM_NCDESTROY` returns. remove_pointer_from_window(window: &Window) -> Result<()>234 fn remove_pointer_from_window(window: &Window) -> Result<()> { 235 window 236 .remove_property(DISPATCHER_PROPERTY_NAME) 237 .context("When removing message dispatcher pointer") 238 } 239 request_exit_message_loop()240 fn request_exit_message_loop() { 241 info!("Posting WM_QUIT"); 242 // Safe because it will always succeed. 243 unsafe { 244 PostQuitMessage(0); 245 } 246 } 247 } 248