gpu_display: send mouse position w/ Kiwi scroll events.

Bug: 262705211
Test: ran emulator & verified scroll position is sent to the guest &
that the bug no longer repros.

Change-Id: Iaa8e748aeaa8faea361e7d6deb94fe152824c850
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4804795
Reviewed-by: Vikram Auradkar <auradkar@google.com>
diff --git a/gpu_display/src/gpu_display_win/math_util.rs b/gpu_display/src/gpu_display_win/math_util.rs
index eefcadd..93ce401 100644
--- a/gpu_display/src/gpu_display_win/math_util.rs
+++ b/gpu_display/src/gpu_display_win/math_util.rs
@@ -9,6 +9,7 @@
 use euclid::size2;
 use euclid::Size2D;
 use num_traits::NumCast;
+use winapi::shared::windef::LPPOINT;
 use winapi::shared::windef::POINT;
 use winapi::shared::windef::RECT;
 
@@ -136,6 +137,7 @@
 
 pub trait SysPointExtension {
     fn to_point(&self) -> Point;
+    fn as_mut_ptr(&mut self) -> LPPOINT;
 }
 
 impl SysPointExtension for POINT {
@@ -143,6 +145,11 @@
     fn to_point(&self) -> Point {
         point2(self.x, self.y)
     }
+
+    #[inline]
+    fn as_mut_ptr(&mut self) -> LPPOINT {
+        self as LPPOINT
+    }
 }
 
 pub trait Size2DCheckedCast<U>: Sized {
diff --git a/gpu_display/src/gpu_display_win/window.rs b/gpu_display/src/gpu_display_win/window.rs
index ba54053..8f7d042 100644
--- a/gpu_display/src/gpu_display_win/window.rs
+++ b/gpu_display/src/gpu_display_win/window.rs
@@ -19,6 +19,7 @@
 use euclid::point2;
 use euclid::size2;
 use euclid::Box2D;
+use euclid::Point2D;
 use euclid::Size2D;
 use win_util::syscall_bail;
 use win_util::win32_wide_string;
@@ -410,6 +411,24 @@
         Ok(point.to_point())
     }
 
+    /// Calls `ScreenToClient()` internally. Converts the screen coordinates to window client area
+    /// coordinates.
+    pub fn screen_to_client(&self, point: Point) -> Result<Point> {
+        let mut point = point.to_sys_point();
+
+        // Safe because:
+        // 1. point is stack allocated & lives as long as the function call.
+        // 2. the window handle is guaranteed valid by self.
+        // 3. we check the error before using the output data.
+        unsafe {
+            let res = ScreenToClient(self.hwnd, point.as_mut_ptr());
+            if res == 0 {
+                syscall_bail!("failed to convert cursor position to client coordinates");
+            }
+        }
+        Ok(Point2D::new(point.x, point.y))
+    }
+
     /// Calls `MonitorFromWindow()` internally. If the window is not on any active display monitor,
     /// returns the handle to the closest one.
     pub fn get_nearest_monitor_handle(&self) -> HMONITOR {
diff --git a/gpu_display/src/gpu_display_win/window_message_processor.rs b/gpu_display/src/gpu_display_win/window_message_processor.rs
index 395f1a7..5cf1c5f 100644
--- a/gpu_display/src/gpu_display_win/window_message_processor.rs
+++ b/gpu_display/src/gpu_display_win/window_message_processor.rs
@@ -109,7 +109,7 @@
     fn on_mouse_button_right(&mut self, _is_down: bool) {}
 
     /// Called when processing `WM_MOUSEWHEEL`.
-    fn on_mouse_wheel(&mut self, _w_param: WPARAM) {}
+    fn on_mouse_wheel(&mut self, _window: &Window, _w_param: WPARAM, _l_param: LPARAM) {}
 
     /// Called when processing `WM_SETCURSOR`. It should return true if the cursor has been handled
     /// and the default processing should be skipped.
@@ -276,7 +276,7 @@
                 0
             }
             WM_MOUSEWHEEL => {
-                handler.on_mouse_wheel(w_param);
+                handler.on_mouse_wheel(&self.window, w_param, l_param);
                 0
             }
             WM_SETCURSOR => {