Repository: electron/electron
Pull request: feat: support `mouse-move` event of Tray API on Windows

#### Description of Change
Adds support for the `mouse-move` event of Tray API on Windows. Due to Win32-API limitations* it currently isn't possible to port `mouse-enter/leave` as well. Their behavior can be emulated by using `mouse-move` and a timer.

*In order to detect when the mouse leaves the icon, we need to listen for `WM_MOUSELEAVE` messages. This message will only be fired after creating a tracking request using [TrackMouseEvent](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-trackmouseevent). Apparently, `NotifyIcon` (Win32 API used to display the tray icon) doesn't work with this method. If I missed sth, feel free to add the other events in a new PR.

cc @nornagon @erickzhao 

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [x] relevant documentation is changed or added
- [x] PR title follows semantic [commit guidelines](https://github.com/electron/electron/blob/master/docs/development/pull-requests.md#commit-message-guidelines)
- [x] [PR release notes](https://github.com/electron/clerk/blob/master/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/master/README.md#examples).

#### Release Notes

Notes: Added support for `mouse-move` event of Tray API on Windows.


Changed files:
filename: docs/api/tray.md
patch: @@ -161,7 +161,7 @@ Returns:
 
 Emitted when the mouse exits the tray icon.
 
-#### Event: 'mouse-move' _macOS_
+#### Event: 'mouse-move' _macOS_ _Windows_
 
 Returns:
 

filename: shell/browser/ui/win/notify_icon.cc
patch: @@ -65,6 +65,13 @@ void NotifyIcon::HandleClickEvent(int modifiers,
   }
 }
 
+void NotifyIcon::HandleMouseMoveEvent(int modifiers) {
+  gfx::Point cursorPos = display::Screen::GetScreen()->GetCursorScreenPoint();
+  // Omit event fired when tray icon is created but cursor is outside of it.
+  if (GetBounds().Contains(cursorPos))
+    NotifyMouseMoved(cursorPos, modifiers);
+}
+
 void NotifyIcon::ResetIcon() {
   NOTIFYICONDATA icon_data;
   InitIconData(&icon_data);

filename: shell/browser/ui/win/notify_icon.h
patch: @@ -44,6 +44,9 @@ class NotifyIcon : public TrayIcon {
                         bool left_button_click,
                         bool double_button_click);
 
+  // Handles a mouse move event from the user.
+  void HandleMouseMoveEvent(int modifiers);
+
   // Re-creates the status tray icon now after the taskbar has been created.
   void ResetIcon();
 

filename: shell/browser/ui/win/notify_icon_host.cc
patch: @@ -170,6 +170,10 @@ LRESULT CALLBACK NotifyIconHost::WndProc(HWND hwnd,
             (lparam == WM_LBUTTONDOWN || lparam == WM_LBUTTONDBLCLK),
             (lparam == WM_LBUTTONDBLCLK || lparam == WM_RBUTTONDBLCLK));
         return TRUE;
+
+      case WM_MOUSEMOVE:
+        win_icon->HandleMouseMoveEvent(GetKeyboardModifers());
+        return TRUE;
     }
   }
   return ::DefWindowProc(hwnd, message, wparam, lparam);