gpu_display: sync with downstream code.

Notable changes:

1. Use "W" methods during window creation and message dispatching
   to ensure unicode characters are sent to the window.
2. In DisplayEventDispatcher::dispatch(), filter() and map() will
   be ignored if we don't call collect(). We replace map() with a
   for loop to make this clearer.

Other changes are due to linter/formatter warnings, etc.

Bug=b:213150276
TEST=cargo b -p gpu_display --features win64 --no-default-features

Change-Id: I767aec208d8afd7d7cb86039d08ba8ec8369da81
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3913991
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Commit-Queue: Pujun Lun <lunpujun@google.com>
This commit is contained in:
Pujun Lun 2022-09-22 14:37:42 -07:00 committed by crosvm LUCI
parent 51f9faf3a4
commit 26d9803ccb
5 changed files with 51 additions and 62 deletions

View file

@ -209,12 +209,11 @@ impl DisplayT for DisplayWin {
} }
} }
let display_closed_event = self.display_closed_event.try_clone().map_err(|e| {
error!("Failed to clone display_closed_event: {}", e);
GpuDisplayError::Allocate
})?;
Ok(Box::new(SurfaceWin { Ok(Box::new(SurfaceWin {
display_closed_event, display_closed_event: self.display_closed_event.try_clone().map_err(|e| {
error!("Failed to clone display_closed_event: {}", e);
GpuDisplayError::Allocate
})?,
})) }))
} }
} }

View file

@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
use std::convert::From; use std::convert::From;
use std::ffi::CString;
use std::fmt; use std::fmt;
use std::mem; use std::mem;
use std::os::raw::c_int; use std::os::raw::c_int;
@ -23,6 +22,7 @@ use euclid::Size2D;
use vm_control::display::WindowVisibility; use vm_control::display::WindowVisibility;
use win_util::syscall_bail; use win_util::syscall_bail;
use win_util::win32_string; use win_util::win32_string;
use win_util::win32_wide_string;
use winapi::shared::minwindef::DWORD; use winapi::shared::minwindef::DWORD;
use winapi::shared::minwindef::FALSE; use winapi::shared::minwindef::FALSE;
use winapi::shared::minwindef::HINSTANCE; use winapi::shared::minwindef::HINSTANCE;
@ -123,10 +123,7 @@ impl Window {
info!("Creating window"); info!("Creating window");
static CONTEXT_MESSAGE: &str = "When creating Window"; static CONTEXT_MESSAGE: &str = "When creating Window";
let class_name = win32_string(class_name);
let title = win32_string(title);
let hinstance = Self::get_current_module_handle(); let hinstance = Self::get_current_module_handle();
// If we fail to load any UI element below, use NULL to let the system use the default UI // If we fail to load any UI element below, use NULL to let the system use the default UI
// rather than crash. // rather than crash.
let hicon = Self::load_custom_icon(hinstance, icon_resource_id).unwrap_or(null_mut()); let hicon = Self::load_custom_icon(hinstance, icon_resource_id).unwrap_or(null_mut());
@ -136,21 +133,16 @@ impl Window {
Self::register_window_class( Self::register_window_class(
wnd_proc, wnd_proc,
hinstance, hinstance,
&class_name, class_name,
hicon, hicon,
hcursor, hcursor,
hbrush_background, hbrush_background,
) )
.context(CONTEXT_MESSAGE)?; .context(CONTEXT_MESSAGE)?;
let hwnd = Self::create_sys_window( let hwnd =
hinstance, Self::create_sys_window(hinstance, class_name, title, dw_style, initial_window_size)
&class_name, .context(CONTEXT_MESSAGE)?;
&title,
dw_style,
initial_window_size,
)
.context(CONTEXT_MESSAGE)?;
Ok(Self { Ok(Self {
hwnd, hwnd,
@ -339,7 +331,7 @@ impl Window {
/// Calls `MonitorFromWindow()` internally. /// Calls `MonitorFromWindow()` internally.
pub fn is_on_active_display(&self) -> bool { pub fn is_on_active_display(&self) -> bool {
// Safe because `Window` object won't outlive the HWND. // Safe because `Window` object won't outlive the HWND.
unsafe { MonitorFromWindow(self.hwnd, MONITOR_DEFAULTTONULL) != null_mut() } unsafe { !MonitorFromWindow(self.hwnd, MONITOR_DEFAULTTONULL).is_null() }
} }
/// Calls `SetWindowPos()` internally. /// Calls `SetWindowPos()` internally.
@ -499,8 +491,10 @@ impl Window {
/// Calls `GetWindowPlacement()` and `SetWindowPlacement()` internally. /// Calls `GetWindowPlacement()` and `SetWindowPlacement()` internally.
pub fn set_restored_pos(&self, window_rect: &Rect) -> Result<()> { pub fn set_restored_pos(&self, window_rect: &Rect) -> Result<()> {
let mut window_placement: WINDOWPLACEMENT = Default::default(); let mut window_placement = WINDOWPLACEMENT {
window_placement.length = mem::size_of::<WINDOWPLACEMENT>().try_into().unwrap(); length: mem::size_of::<WINDOWPLACEMENT>().try_into().unwrap(),
..Default::default()
};
// Safe because `Window` object won't outlive the HWND, we know `window_placement` is valid, // Safe because `Window` object won't outlive the HWND, we know `window_placement` is valid,
// and failures are handled below. // and failures are handled below.
unsafe { unsafe {
@ -596,13 +590,13 @@ impl Window {
fn register_window_class( fn register_window_class(
wnd_proc: WNDPROC, wnd_proc: WNDPROC,
hinstance: HINSTANCE, hinstance: HINSTANCE,
class_name: &CString, class_name: &str,
hicon: HICON, hicon: HICON,
hcursor: HCURSOR, hcursor: HCURSOR,
hbrush_background: HBRUSH, hbrush_background: HBRUSH,
) -> Result<()> { ) -> Result<()> {
let window_class = WNDCLASSEXA { let window_class = WNDCLASSEXW {
cbSize: std::mem::size_of::<WNDCLASSEXA>() as u32, cbSize: std::mem::size_of::<WNDCLASSEXW>() as u32,
style: CS_OWNDC | CS_HREDRAW | CS_VREDRAW, style: CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
lpfnWndProc: wnd_proc, lpfnWndProc: wnd_proc,
cbClsExtra: 0, cbClsExtra: 0,
@ -612,14 +606,14 @@ impl Window {
hCursor: hcursor, hCursor: hcursor,
hbrBackground: hbrush_background, hbrBackground: hbrush_background,
lpszMenuName: null_mut(), lpszMenuName: null_mut(),
lpszClassName: class_name.as_ptr(), lpszClassName: win32_wide_string(class_name).as_ptr(),
hIconSm: hicon, hIconSm: hicon,
}; };
// Safe because we know the lifetime of `window_class`, and we handle failures below. // Safe because we know the lifetime of `window_class`, and we handle failures below.
unsafe { unsafe {
if RegisterClassExA(&window_class) == 0 { if RegisterClassExW(&window_class) == 0 {
syscall_bail!("Failed to call RegisterClassExA()"); syscall_bail!("Failed to call RegisterClassExW()");
} }
Ok(()) Ok(())
} }
@ -627,17 +621,17 @@ impl Window {
fn create_sys_window( fn create_sys_window(
hinstance: HINSTANCE, hinstance: HINSTANCE,
class_name: &CString, class_name: &str,
title: &CString, title: &str,
dw_style: DWORD, dw_style: DWORD,
initial_window_size: &Size2D<i32, HostWindowSpace>, initial_window_size: &Size2D<i32, HostWindowSpace>,
) -> Result<HWND> { ) -> Result<HWND> {
// Safe because we handle failures below. // Safe because we handle failures below.
unsafe { unsafe {
let hwnd = CreateWindowExA( let hwnd = CreateWindowExW(
0, 0,
class_name.as_ptr(), win32_wide_string(class_name).as_ptr(),
title.as_ptr(), win32_wide_string(title).as_ptr(),
dw_style, dw_style,
0, 0,
0, 0,
@ -648,8 +642,8 @@ impl Window {
hinstance, hinstance,
null_mut(), null_mut(),
); );
if hwnd == null_mut() { if hwnd.is_null() {
syscall_bail!("Failed to call CreateWindowExA()"); syscall_bail!("Failed to call CreateWindowExW()");
} }
Ok(hwnd) Ok(hwnd)
} }
@ -692,8 +686,10 @@ impl MonitorInfo {
/// # Safety /// # Safety
/// Caller is responsible for ensuring that `hmonitor` is a valid handle. /// Caller is responsible for ensuring that `hmonitor` is a valid handle.
unsafe fn get_monitor_info(hmonitor: HMONITOR) -> Result<MONITORINFO> { unsafe fn get_monitor_info(hmonitor: HMONITOR) -> Result<MONITORINFO> {
let mut monitor_info: MONITORINFO = Default::default(); let mut monitor_info = MONITORINFO {
monitor_info.cbSize = mem::size_of::<MONITORINFO>().try_into().unwrap(); cbSize: mem::size_of::<MONITORINFO>().try_into().unwrap(),
..Default::default()
};
if GetMonitorInfoA(hmonitor, &mut monitor_info) == 0 { if GetMonitorInfoA(hmonitor, &mut monitor_info) == 0 {
syscall_bail!("Failed to call GetMonitorInfoA()"); syscall_bail!("Failed to call GetMonitorInfoA()");
} }

View file

@ -47,16 +47,16 @@ impl DisplayEventDispatcher {
} }
pub fn dispatch(&self, events: &[virtio_input_event], device_type: EventDeviceKind) { pub fn dispatch(&self, events: &[virtio_input_event], device_type: EventDeviceKind) {
let _ = self for event_device in self
.event_devices .event_devices
.borrow_mut() .borrow_mut()
.iter_mut() .values_mut()
.filter(|(_, event_device)| event_device.kind() == device_type) .filter(|event_device| event_device.kind() == device_type)
.map(|(_, event_device)| { {
if let Err(e) = event_device.send_report(events.iter().cloned()) { if let Err(e) = event_device.send_report(events.iter().cloned()) {
error!("Failed to send events to event device: {}", e); error!("Failed to send events to event device: {}", e);
} }
}); }
} }
fn import_event_device(&mut self, event_device_id: ObjectId, event_device: EventDevice) { fn import_event_device(&mut self, event_device_id: ObjectId, event_device: EventDevice) {
@ -187,7 +187,7 @@ impl<T: HandleWindowMessage> WindowMessageDispatcher<T> {
} }
None => debug!("No window to destroy on WndProc thread drop"), None => debug!("No window to destroy on WndProc thread drop"),
}, },
// Safe because we are processing a message tageting this thread. // Safe because we are processing a message targeting this thread.
_ => unsafe { _ => unsafe {
DefWindowProcA(null_mut(), msg, w_param, l_param); DefWindowProcA(null_mut(), msg, w_param, l_param);
}, },

View file

@ -82,9 +82,6 @@ pub trait HandleWindowMessage {
/// Called when processing `WM_SETFOCUS`. /// Called when processing `WM_SETFOCUS`.
fn on_set_focus(&mut self) {} fn on_set_focus(&mut self) {}
/// Called when processing `WM_KILLFOCUS`.
fn on_kill_focus(&mut self) {}
/// Called when processing `WM_INPUT`. /// Called when processing `WM_INPUT`.
fn on_raw_input(&mut self, _window: &Window, _l_param: LPARAM) {} fn on_raw_input(&mut self, _window: &Window, _l_param: LPARAM) {}
@ -92,7 +89,7 @@ pub trait HandleWindowMessage {
fn on_mouse_move(&mut self, _w_param: WPARAM, _l_param: LPARAM) {} fn on_mouse_move(&mut self, _w_param: WPARAM, _l_param: LPARAM) {}
/// Called when processing `WM_LBUTTONDOWN` and `WM_LBUTTONUP`. /// Called when processing `WM_LBUTTONDOWN` and `WM_LBUTTONUP`.
fn on_mouse_button_left(&mut self, _is_down: bool, _l_param: LPARAM) {} fn on_mouse_button_left(&mut self, _window: &Window, _is_down: bool, _l_param: LPARAM) {}
/// Called when processing `WM_RBUTTONDOWN` and `WM_RBUTTONUP`. /// Called when processing `WM_RBUTTONDOWN` and `WM_RBUTTONUP`.
fn on_mouse_button_right(&mut self, _is_down: bool) {} fn on_mouse_button_right(&mut self, _is_down: bool) {}
@ -225,10 +222,6 @@ impl<T: HandleWindowMessage> WindowMessageProcessor<T> {
handler.on_set_focus(); handler.on_set_focus();
0 0
} }
WM_KILLFOCUS => {
handler.on_kill_focus();
0
}
WM_INPUT => { WM_INPUT => {
handler.on_raw_input(&self.window, l_param); handler.on_raw_input(&self.window, l_param);
self.window.default_process_message(packet) self.window.default_process_message(packet)
@ -238,7 +231,8 @@ impl<T: HandleWindowMessage> WindowMessageProcessor<T> {
0 0
} }
WM_LBUTTONDOWN | WM_LBUTTONUP => { WM_LBUTTONDOWN | WM_LBUTTONUP => {
handler.on_mouse_button_left(/* is_down= */ msg == WM_LBUTTONDOWN, l_param); let is_down = msg == WM_LBUTTONDOWN;
handler.on_mouse_button_left(&self.window, is_down, l_param);
0 0
} }
WM_RBUTTONDOWN | WM_RBUTTONUP => { WM_RBUTTONDOWN | WM_RBUTTONUP => {

View file

@ -175,7 +175,7 @@ impl<T: HandleWindowMessage> WindowProcedureThread<T> {
loop { loop {
let mut message = mem::MaybeUninit::uninit(); let mut message = mem::MaybeUninit::uninit();
// Safe because we know the lifetime of `message`. // Safe because we know the lifetime of `message`.
match unsafe { GetMessageA(message.as_mut_ptr(), null_mut(), 0, 0) } { match unsafe { GetMessageW(message.as_mut_ptr(), null_mut(), 0, 0) } {
0 => { 0 => {
info!("WndProc thread exiting message loop since WM_QUIT is received"); info!("WndProc thread exiting message loop since WM_QUIT is received");
message_loop_state message_loop_state
@ -184,7 +184,7 @@ impl<T: HandleWindowMessage> WindowProcedureThread<T> {
} }
-1 => { -1 => {
error!( error!(
"WndProc thread exiting message loop because GetMessageA() failed with \ "WndProc thread exiting message loop because GetMessageW() failed with \
error code {}", error code {}",
unsafe { GetLastError() } unsafe { GetLastError() }
); );
@ -195,19 +195,19 @@ impl<T: HandleWindowMessage> WindowProcedureThread<T> {
_ => (), _ => (),
} }
// Safe because `GetMessageA()` will block until `message` is populated. // Safe because `GetMessageW()` will block until `message` is populated.
let new_message = unsafe { message.assume_init() }; let new_message = unsafe { message.assume_init() };
if new_message.hwnd == null_mut() { if new_message.hwnd.is_null() {
// Thread messages don't target a specific window and `DispatchMessageA()` won't // Thread messages don't target a specific window and `DispatchMessageA()` won't
// send them to `wnd_proc()` function, hence we need to handle it as a special case. // send them to `wnd_proc()` function, hence we need to handle it as a special case.
dispatcher dispatcher
.as_mut() .as_mut()
.process_thread_message(&new_message.into()); .process_thread_message(&new_message.into());
} else { } else {
// Safe because `GetMessageA()` will block until `message` is populated. // Safe because `GetMessageW()` will block until `message` is populated.
unsafe { unsafe {
TranslateMessage(&new_message); TranslateMessage(&new_message);
DispatchMessageA(&new_message); DispatchMessageW(&new_message);
} }
} }
} }
@ -266,8 +266,8 @@ impl<T: HandleWindowMessage> WindowProcedureThread<T> {
/// processing `WM_NCDESTROY`, because the window handle will become invalid afterwards. /// processing `WM_NCDESTROY`, because the window handle will become invalid afterwards.
unsafe fn create_window() -> Result<Window> { unsafe fn create_window() -> Result<Window> {
// Gfxstream window is a child window of CrosVM window. Without WS_CLIPCHILDREN, the parent // Gfxstream window is a child window of CrosVM window. Without WS_CLIPCHILDREN, the parent
// window may use the background brush to clear the gfxstream window client area when drawing // window may use the background brush to clear the gfxstream window client area when
// occurs. This caused the screen flickering issue during resizing. // drawing occurs. This caused the screen flickering issue during resizing.
// See b/197786842 for details. // See b/197786842 for details.
let dw_style = WS_POPUP | WS_CLIPCHILDREN; let dw_style = WS_POPUP | WS_CLIPCHILDREN;
Window::new( Window::new(