diff --git a/doc/devdocs/modules/mouseutils/findmymouse.md b/doc/devdocs/modules/mouseutils/findmymouse.md new file mode 100644 index 0000000000..e4bc51a513 --- /dev/null +++ b/doc/devdocs/modules/mouseutils/findmymouse.md @@ -0,0 +1,95 @@ +# Find My Mouse + +Find My Mouse is a utility that helps users locate their mouse pointer by creating a spotlight effect when activated. It is based on Raymond Chen's SuperSonar utility. + +## Implementation + +Find My Mouse displays a spotlight effect centered on the cursor location when activated via a keyboard shortcut (typically a double-press of the Ctrl key). + +### Key Files +- `src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp` - Contains the main implementation +- Key function: `s_WndProc` - Handles window messages for the utility + +### Enabling Process + +When the utility is enabled: + +1. A background thread is created to run the Find My Mouse logic asynchronously: + ```cpp + // Enable the PowerToy + virtual void enable() + { + m_enabled = true; // Mark the module as enabled + Trace::EnableFindMyMouse(true); // Enable telemetry + std::thread([=]() { FindMyMouseMain(m_hModule, m_findMyMouseSettings); }).detach(); // Run main logic in background + } + ``` + +2. The `CompositionSpotlight` instance is initialized with user settings: + ```cpp + CompositionSpotlight sonar; + sonar.ApplySettings(settings, false); // Apply settings + if (!sonar.Initialize(hinst)) + { + Logger::error("Couldn't initialize a sonar instance."); + return 0; + } + + m_sonar = &sonar; + ``` + +3. The utility listens for raw input events using `WM_INPUT`, which provides more precise and responsive input detection than standard mouse events. + +### Activation Process + +The activation process works as follows: + +1. **Keyboard Hook Detects Shortcut** + - A global low-level keyboard hook is set up during initialization + - The hook monitors for the specific activation pattern (double Ctrl press) + - Once matched, it sends a `WM_PRIV_SHORTCUT` message to the sonar window: + ```cpp + virtual void OnHotkeyEx() override + { + Logger::trace("OnHotkeyEx()"); + HWND hwnd = GetSonarHwnd(); + if (hwnd != nullptr) + { + PostMessageW(hwnd, WM_PRIV_SHORTCUT, NULL, NULL); + } + } + ``` + +2. **Message Handler Triggers Action** + - The custom message is routed to `BaseWndProc()` + - The handler toggles the sonar animation: + ```cpp + if (message == WM_PRIV_SHORTCUT) + { + if (m_sonarStart == NoSonar) + StartSonar(); // Trigger sonar animation + else + StopSonar(); // Cancel if already running + } + ``` + +3. **Sonar Animation** + - `StartSonar()` uses `CompositionSpotlight` to display a highlight (ripple/pulse) centered on the mouse pointer + - The animation is temporary and fades automatically or can be cancelled by user input + +### Event Handling + +The Find My Mouse utility handles several types of events: + +- **Mouse Events**: Trigger sonar animations (e.g., after a shake or shortcut) +- **Keyboard Events**: May cancel or toggle the effect +- **Custom Shortcut Messages**: Handled to allow toggling Find My Mouse using a user-defined hotkey + +When the main window receives a `WM_DESTROY` message (on shutdown or disable), the sonar instance is properly cleaned up, and the message loop ends gracefully. + +## Debugging + +To debug Find My Mouse: +- Attach to the PowerToys Runner process directly +- Set breakpoints in the `FindMyMouse.cpp` file +- When debugging the spotlight effect, visual artifacts may occur due to the debugger's overhead diff --git a/doc/devdocs/modules/mouseutils/mousehighlighter.md b/doc/devdocs/modules/mouseutils/mousehighlighter.md new file mode 100644 index 0000000000..c9413f1bc8 --- /dev/null +++ b/doc/devdocs/modules/mouseutils/mousehighlighter.md @@ -0,0 +1,92 @@ +# Mouse Highlighter + +Mouse Highlighter is a utility that visualizes mouse clicks by displaying a highlight effect around the cursor when clicked. + +## Implementation + +Mouse Highlighter runs within the PowerToys Runner process and draws visual indicators (typically circles) around the mouse cursor when the user clicks. + +### Key Files +- `src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.cpp` - Contains the main implementation +- Key function: `WndProc` - Handles window messages and mouse events + +### Enabling Process + +When the utility is enabled: + +1. A background thread is created to run the mouse highlighter logic asynchronously: + ```cpp + std::thread([=]() { MouseHighlighterMain(m_hModule, m_highlightSettings); }).detach(); + ``` + +2. The Highlighter instance is initialized and configured with user settings: + ```cpp + Highlighter highlighter; + Highlighter::instance = &highlighter; + highlighter.ApplySettings(settings); + highlighter.MyRegisterClass(hInstance); + ``` + +3. A highlighter window is created: + ```cpp + instance->CreateHighlighter(); + ``` + +4. The utility: + - Registers a custom window class + - Creates a transparent window for drawing visuals + - Handles the `WM_CREATE` message to initialize the Windows Composition API (Compositor, visuals, and target) + +### Activation Process + +The activation process works as follows: + +1. **Shortcut Detection** + - The system detects when the activation shortcut is pressed + - A global hotkey listener (registered with `RegisterHotKey` or similar hook) detects the shortcut + +2. **Message Transmission** + - A message (like `WM_SWITCH_ACTIVATION_MODE`) is sent to the highlighter window via `PostMessage()` or `SendMessage()` + +3. **Window Procedure Handling** + - The `WndProc` of the highlighter window receives the message and toggles between start and stop drawing modes: + ```cpp + case WM_SWITCH_ACTIVATION_MODE: + if (instance->m_visible) + instance->StopDrawing(); + else + instance->StartDrawing(); + ``` + +4. **Drawing Activation** + - If turning ON, `StartDrawing()` is called, which: + - Moves the highlighter window to the topmost position + - Slightly offsets the size to avoid transparency bugs + - Shows the transparent drawing window + - Hooks into global mouse events + - Starts drawing visual feedback around the mouse + + - If turning OFF, `StopDrawing()` is called, which: + - Hides the drawing window + - Removes the mouse hook + - Stops rendering highlighter visuals + +### Drawing Process + +When the mouse highlighter is active: +1. A low-level mouse hook detects mouse button events +2. On click, the highlighter draws a circle (or other configured visual) at the cursor position +3. The visual effect fades over time according to user settings +4. Each click can be configured to show different colors based on the mouse button used + +## Debugging + +To debug Mouse Highlighter: +- Attach to the PowerToys Runner process directly +- Set breakpoints in the `MouseHighlighter.cpp` file +- Be aware that visual effects may appear different or stuttery during debugging due to the debugger's overhead + +## Known Issues + +- There is a reported bug where the highlight color stays on after toggling opacity to 0 +- This issue has been present for more than six months and can still be reproduced in recent PowerToys releases diff --git a/doc/devdocs/modules/mouseutils/mousejump.md b/doc/devdocs/modules/mouseutils/mousejump.md new file mode 100644 index 0000000000..6a362d5110 --- /dev/null +++ b/doc/devdocs/modules/mouseutils/mousejump.md @@ -0,0 +1,90 @@ +# Mouse Jump + +Mouse Jump is a utility that allows users to quickly move their cursor to any location on screen using a grid-based overlay interface. + +## Implementation + +Unlike the other Mouse Utilities that run within the PowerToys Runner process, Mouse Jump operates as a separate process that communicates with the Runner via events. + +### Key Files +- `src/modules/MouseUtils/MouseJump` - Contains the Runner interface for Mouse Jump +- `src/modules/MouseUtils/MouseJumpUI` - Contains the UI implementation +- `src/modules/MouseUtils/MouseJumpUI/MainForm.cs` - Main UI form implementation +- `src/modules/MouseUtils/MouseJump.Common` - Shared code between the Runner and UI components + +### Enabling Process + +When the utility is enabled: + +1. A separate UI process is launched for Mouse Jump: + ```cpp + void launch_process() + { + Logger::trace(L"Starting MouseJump process"); + unsigned long powertoys_pid = GetCurrentProcessId(); + + std::wstring executable_args = L""; + executable_args.append(std::to_wstring(powertoys_pid)); + + SHELLEXECUTEINFOW sei{ sizeof(sei) }; + sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; + sei.lpFile = L"PowerToys.MouseJumpUI.exe"; + sei.nShow = SW_SHOWNORMAL; + sei.lpParameters = executable_args.data(); + if (ShellExecuteExW(&sei)) + { + Logger::trace("Successfully started the Mouse Jump process"); + } + else + { + Logger::error(L"Mouse Jump failed to start. {}", get_last_error_or_default(GetLastError())); + } + + m_hProcess = sei.hProcess; + } + ``` + +2. The Runner creates shared events for communication with the UI process: + ```cpp + m_hInvokeEvent = CreateDefaultEvent(CommonSharedConstants::MOUSE_JUMP_SHOW_PREVIEW_EVENT); + m_hTerminateEvent = CreateDefaultEvent(CommonSharedConstants::TERMINATE_MOUSE_JUMP_SHARED_EVENT); + ``` + +### Activation Process + +The activation process works as follows: + +1. **Shortcut Detection** + - When the activation shortcut is pressed, the Runner signals the shared event `MOUSE_JUMP_SHOW_PREVIEW_EVENT` + +2. **UI Display** + - The MouseJumpUI process listens for this event and displays a screen overlay when triggered + - The overlay shows a grid or other visual aid to help select a destination point + +3. **Mouse Movement** + - User selects a destination point on the overlay + - The UI process moves the mouse cursor to the selected position + +4. **Termination** + - When the utility needs to be disabled or PowerToys is shutting down, the Runner signals the `TERMINATE_MOUSE_JUMP_SHARED_EVENT` + - The UI process responds by cleaning up and exiting + +### User Interface + +The Mouse Jump UI is implemented in C# using Windows Forms: +- Displays a semi-transparent overlay over the entire screen +- May include grid lines, quadrant divisions, or other visual aids to help with precision selection +- Captures mouse and keyboard input to allow for selection and cancellation +- Moves the mouse cursor to the selected location upon confirmation + +## Debugging + +To debug Mouse Jump: + +1. Start by debugging the Runner process directly +2. Then attach the debugger to the MouseJumpUI process when it launches +3. Note: Debugging MouseJumpUI directly is challenging because it requires the Runner's process ID to be passed as a parameter at launch + +## Community Contributions + +Mouse Jump was initially contributed by Michael Clayton (@mikeclayton) and is based on his FancyMouse utility. diff --git a/doc/devdocs/modules/mouseutils/mousepointer.md b/doc/devdocs/modules/mouseutils/mousepointer.md new file mode 100644 index 0000000000..37ae7ecf33 --- /dev/null +++ b/doc/devdocs/modules/mouseutils/mousepointer.md @@ -0,0 +1,114 @@ +# Mouse Pointer Crosshairs + +Mouse Pointer Crosshairs is a utility that displays horizontal and vertical lines that intersect at the mouse cursor position, making it easier to track the cursor location on screen. + +## Implementation + +Mouse Pointer Crosshairs runs within the PowerToys Runner process and draws crosshair lines that follow the cursor in real-time. + +### Key Files +- `src/modules/MouseUtils/MousePointerCrosshairs/InclusiveCrosshairs.cpp` - Contains the main implementation +- Key function: `WndProc` - Handles window messages and mouse events + +### Enabling Process + +When the utility is enabled: + +1. A background thread is created to run the crosshairs logic asynchronously: + ```cpp + std::thread([=]() { InclusiveCrosshairsMain(hInstance, settings); }).detach(); + ``` + +2. The InclusiveCrosshairs instance is initialized and configured with user settings: + ```cpp + InclusiveCrosshairs crosshairs; + InclusiveCrosshairs::instance = &crosshairs; + crosshairs.ApplySettings(settings, false); + crosshairs.MyRegisterClass(hInstance); + ``` + +3. The utility: + - Creates the crosshairs visuals using Windows Composition API inside `CreateInclusiveCrosshairs()` + - Handles the `WM_CREATE` message to initialize the Windows Composition API (Compositor, visuals, and target) + - Creates a transparent, layered window for drawing the crosshairs with specific extended window styles (e.g., `WS_EX_LAYERED`, `WS_EX_TRANSPARENT`) + +### Activation Process + +The activation process works as follows: + +1. **Shortcut Detection** + - When the activation shortcut is pressed, the window procedure (`WndProc`) receives a custom message `WM_SWITCH_ACTIVATION_MODE` + +2. **Toggle Drawing State** + ```cpp + case WM_SWITCH_ACTIVATION_MODE: + if (instance->m_drawing) + { + instance->StopDrawing(); + } + else + { + instance->StartDrawing(); + } + break; + ``` + +3. **Start Drawing Function** + - The `StartDrawing()` function is called to: + - Log the start of drawing + - Update the crosshairs position + - Check if the cursor should be auto-hidden, and set a timer for auto-hide if enabled + - Show the crosshairs window if the cursor is visible + - Set a low-level mouse hook to track mouse movements asynchronously + + ```cpp + void InclusiveCrosshairs::StartDrawing() + { + Logger::info("Start drawing crosshairs."); + UpdateCrosshairsPosition(); + + m_hiddenCursor = false; + if (m_crosshairs_auto_hide) + { + CURSORINFO cursorInfo{}; + cursorInfo.cbSize = sizeof(cursorInfo); + if (GetCursorInfo(&cursorInfo)) + { + m_hiddenCursor = !(cursorInfo.flags & CURSOR_SHOWING); + } + + SetAutoHideTimer(); + } + + if (!m_hiddenCursor) + { + ShowWindow(m_hwnd, SW_SHOWNOACTIVATE); + } + + m_drawing = true; + m_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, m_hinstance, 0); + } + ``` + +4. **Stop Drawing Function** + - The `StopDrawing()` function is called to: + - Remove the mouse hook + - Kill the auto-hide timer + - Hide the crosshairs window + - Log the stop of drawing + +### Cursor Tracking + +While active, the utility: +1. Uses a low-level mouse hook (`WH_MOUSE_LL`) to track cursor movement +2. Updates crosshair positions in real-time as the mouse moves +3. Supports auto-hiding functionality when the cursor is inactive for a specified period + +## Debugging + +To debug Mouse Pointer Crosshairs: +- Attach to the PowerToys Runner process directly +- Set breakpoints in the `InclusiveCrosshairs.cpp` file +- Be aware that during debugging, moving the mouse may cause unexpected or "strange" visual behavior because: + - The mouse hook (`MouseHookProc`) updates the crosshairs position on every `WM_MOUSEMOVE` event + - This frequent update combined with the debugger's overhead or breakpoints can cause visual glitches or stutters diff --git a/doc/devdocs/modules/mouseutils/readme.md b/doc/devdocs/modules/mouseutils/readme.md new file mode 100644 index 0000000000..f25840a141 --- /dev/null +++ b/doc/devdocs/modules/mouseutils/readme.md @@ -0,0 +1,113 @@ +# Mouse Utilities + +Mouse Utilities is a collection of tools designed to enhance mouse and cursor functionality on Windows. The module contains four sub-utilities that provide different mouse-related features. + +## Overview + +Mouse Utilities includes the following sub-modules: + +- **[Find My Mouse](findmymouse.md)**: Helps locate the mouse pointer by creating a visual spotlight effect when activated +- **[Mouse Highlighter](mousehighlighter.md)**: Visualizes mouse clicks with customizable highlights +- **[Mouse Jump](mousejump.md)**: Allows quick cursor movement to specific screen locations +- **[Mouse Pointer Crosshairs](mousepointer.md)**: Displays crosshair lines that follow the mouse cursor + +## Architecture + +Most of the sub-modules (Find My Mouse, Mouse Highlighter, and Mouse Pointer Crosshairs) run within the PowerToys Runner process as separate threads. Mouse Jump is more complex and runs as a separate process that communicates with the Runner via events. + +### Code Structure + +#### Settings UI +- [MouseUtilsPage.xaml](/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml) +- [MouseJumpPanel.xaml](/src/settings-ui/Settings.UI/SettingsXAML/Panels/MouseJumpPanel.xaml) +- [MouseJumpPanel.xaml.cs](/src/settings-ui/Settings.UI/SettingsXAML/Panels/MouseJumpPanel.xaml.cs) +- [MouseUtilsViewModel.cs](/src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs) +- [MouseUtilsViewModel_MouseJump.cs](/src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel_MouseJump.cs) + +#### Runner and Module Implementation +- [FindMyMouse](/src/modules/MouseUtils/FindMyMouse) +- [MouseHighlighter](/src/modules/MouseUtils/MouseHighlighter) +- [MousePointerCrosshairs](/src/modules/MouseUtils/MousePointerCrosshairs) +- [MouseJump](/src/modules/MouseUtils/MouseJump) +- [MouseJumpUI](/src/modules/MouseUtils/MouseJumpUI) +- [MouseJump.Common](/src/modules/MouseUtils/MouseJump.Common) + +## Community Contributors + +- **Michael Clayton (@mikeclayton)**: Contributed the initial version of the Mouse Jump tool and several updates based on his FancyMouse utility +- **Raymond Chen (@oldnewthing)**: Find My Mouse is based on Raymond Chen's SuperSonar + +## Known Issues + +- Mouse Highlighter has a reported bug where the highlight color stays on after toggling opacity to 0 + +## See Also + +For more detailed implementation information, please refer to the individual utility documentation pages linked above. +#### Activation Process +1. A keyboard hook detects the activation shortcut (typically double-press of Ctrl) +2. A `WM_PRIV_SHORTCUT` message is sent to the sonar window +3. `StartSonar()` is called to display a spotlight animation centered on the mouse pointer +4. The animation automatically fades or can be cancelled by user input + +### Mouse Highlighter + +Mouse Highlighter visualizes mouse clicks by displaying a highlight effect around the cursor when clicked. + +#### Key Components +- Uses Windows Composition API for rendering +- Main implementation in `MouseHighlighter.cpp` +- Core logic handled by the `WndProc` function + +#### Activation Process +1. When activated, it creates a transparent overlay window +2. A mouse hook monitors for click events +3. On click detection, the highlighter draws a circle or other visual indicator +4. The highlight effect fades over time based on user settings + +### Mouse Pointer Crosshairs + +Displays horizontal and vertical lines that intersect at the mouse cursor position. + +#### Key Components +- Uses Windows Composition API for rendering +- Core implementation in `InclusiveCrosshairs.cpp` +- Main logic handled by the `WndProc` function + +#### Activation Process +1. Creates a transparent, layered window for drawing crosshairs +2. When activated via shortcut, calls `StartDrawing()` +3. Sets a low-level mouse hook to track cursor movement +4. Updates crosshairs position on every mouse movement +5. Includes auto-hide functionality for cursor inactivity + +### Mouse Jump + +Allows quick mouse cursor repositioning to any screen location through a grid-based UI. + +#### Key Components +- Runs as a separate process (`PowerToys.MouseJumpUI.exe`) +- Communicates with Runner process via events +- UI implemented in `MainForm.cs` + +#### Activation Process +1. When shortcut is pressed, Runner triggers the shared event `MOUSE_JUMP_SHOW_PREVIEW_EVENT` +2. The MouseJumpUI process displays a screen overlay +3. User selects a destination point on the overlay +4. Mouse cursor is moved to the selected position +5. The UI process can be terminated via the `TERMINATE_MOUSE_JUMP_SHARED_EVENT` + +## Debugging + +### Find My Mouse, Mouse Highlighter, and Mouse Pointer Crosshairs +- Debug by attaching to the Runner process directly +- During debugging, visual effects may appear glitchy due to the debugger's overhead + +### Mouse Jump +- Start by debugging the Runner process +- Then attach the debugger to the MouseJumpUI process +- Note: Debugging MouseJumpUI directly is challenging as it requires the Runner's process ID as a parameter + +## Known Issues + +- Mouse Highlighter has a reported bug where the highlight color stays on after toggling opacity to 0 diff --git a/doc/devdocs/modules/readme.md b/doc/devdocs/modules/readme.md index 2895451a02..26de2cd9d4 100644 --- a/doc/devdocs/modules/readme.md +++ b/doc/devdocs/modules/readme.md @@ -4,19 +4,20 @@ This section contains documentation for individual PowerToys modules, including ## Available Modules -| Module | Description | Documentation | -|--------|-------------|---------------| -| Environment Variables | Tool for managing user and system environment variables | [Architecture & Implementation](environmentvariables.md) | -| FancyZones | Window manager utility for custom window layouts | [Architecture & Implementation](fancyzones.md), [Debugging Tools](fancyzones-tools.md) | -| File Locksmith | Tool for finding processes that lock files | [Architecture & Implementation](filelocksmith.md) | -| Hosts File Editor | Tool for managing the system hosts file | [Architecture & Implementation](hostsfileeditor.md) | -| Keyboard Manager | Tool for remapping keys and keyboard shortcuts | [Documentation](keyboardmanager/README.md) | -| NewPlus | Context menu extension for creating new files in File Explorer | [Architecture & Implementation](newplus.md) | -| Quick Accent | Tool for quickly inserting accented characters and special symbols | [Architecture & Implementation](quickaccent.md) | -| Registry Preview | Tool for visualizing and editing Registry files | [Architecture & Implementation](registrypreview.md) | -| Screen Ruler | Tool for measuring pixel distances and color boundaries on screen | [Architecture & Implementation](screenruler.md) | -| Shortcut Guide | Tool for displaying Windows keyboard shortcuts when holding the Windows key | [Architecture & Implementation](shortcut_guide.md) | -| ZoomIt | Screen zoom and annotation tool | [Architecture & Implementation](zoomit.md) | +| Module | Description | +|--------|-------------| +| [Environment Variables](environmentvariables.md) | Tool for managing user and system environment variables | +| [FancyZones](fancyzones.md) ([debugging tools](fancyzones-tools.md)) | Window manager utility for custom window layouts | +| [File Locksmith](filelocksmith.md) | Tool for finding processes that lock files | +| [Hosts File Editor](hostsfileeditor.md) | Tool for managing the system hosts file | +| [Keyboard Manager](keyboardmanager/README.md) | Tool for remapping keys and keyboard shortcuts | +| [Mouse Utilities](mouseutils/readme.md) | Collection of tools to enhance mouse and cursor functionality | +| [NewPlus](newplus.md) | Context menu extension for creating new files in File Explorer | +| [Quick Accent](quickaccent.md) | Tool for quickly inserting accented characters and special symbols | +| [Registry Preview](registrypreview.md) | Tool for visualizing and editing Registry files | +| [Screen Ruler](screenruler.md) | Tool for measuring pixel distances and color boundaries on screen | +| [Shortcut Guide](shortcut_guide.md) | Tool for displaying Windows keyboard shortcuts when holding the Windows key | +| [ZoomIt](zoomit.md) | Screen zoom and annotation tool | ## Adding New Module Documentation