Add Cursor Wrap functionality to Powertoys Mouse Utils#41826
Add Cursor Wrap functionality to Powertoys Mouse Utils#41826vanzue merged 14 commits intomicrosoft:mainfrom
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull Request Overview
A new PowerToys Mouse Utils module called "CursorWrap" that enables cursor wrapping between monitor edges. The implementation allows the mouse cursor to wrap from one edge of a display to the opposite edge of the display stack - supporting both single and multi-monitor setups.
Key Changes
- Added complete CursorWrap module with C++ implementation for mouse hook functionality
- Integrated CursorWrap into PowerToys Settings UI with configuration options
- Added GPO policy support and telemetry tracking for the new module
Reviewed Changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs | Added CursorWrap settings integration to MouseUtils view model |
| src/settings-ui/Settings.UI/Strings/en-us/Resources.resw | Added localization strings for CursorWrap UI elements |
| src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml | Added CursorWrap settings UI controls to Mouse Utils page |
| src/settings-ui/Settings.UI.Library/*.cs | Added CursorWrap settings data models and properties |
| src/modules/MouseUtils/CursorWrap/*.cpp/.h | Core CursorWrap module implementation with mouse hook and wrapping logic |
| src/runner/main.cpp | Added CursorWrap DLL to module loading list |
| src/common/utils/gpo.h | Added GPO policy support for CursorWrap |
| PowerToys.sln | Added CursorWrap project to solution |
|
I merged main and gave a test locally(a dev box), looks like if I enable it and move my cursor to my screen edge, it will stuck there |
This comment has been minimized.
This comment has been minimized.
It need to be activated by shortcut first... |
|
@yeelam-gordon @mikehall-ms I think we don't even need the shortcut, and can just enable the functionality whenever the toggleswitch is on? By default it should be turned off. |
|
Note to self: I need to create an utility icon for this |
People can choose now: |
This comment has been minimized.
This comment has been minimized.
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Did you test? I surely enabled by shortcut, it's stuck at corner and moving at a really small area, and won't leave that area no matter how I move my mouse |
Yes, I did, that's why I can capture the screenshot. It works for me for both vertical and horizontal on my two monitors |
@check-spelling-bot Report🔴 Please reviewSee the 📂 files view, the 📜action log, or 📝 job summary for details.
See ❌ Event descriptions for more information. These words are not needed and should be removedcabstr CIBUILD djwsxzxb icf installscopeperuser ksa rap registryroot regroot rtm suntimes TARGETDIR utmIf the flagged items are 🤯 false positivesIf items relate to a ...
|
wrap_cursor.mp4Strange in my test, I'm testing in my devbox though, can't get out of the screen side |
May be... remote desktop is different? I am using physical machine. @vanzue, do you mind to try on physical machine? If it works at your notebook or desktop, we should able to checkin first. |
|
Works fine in my laptop! |
| <data name="Oobe_MouseUtils_MouseHighlighter_Description.Text" xml:space="preserve"> | ||
| <value>Use a keyboard shortcut to highlight left and right mouse clicks.</value> | ||
| <comment>Mouse as in the hardware peripheral.</comment> | ||
| </data> |
There was a problem hiding this comment.
Trailing tab character should be removed. Line endings should be consistent with the rest of the file (spaces only).
| </data> | |
| </data> |
| <data name="MouseUtils_CursorWrap.Description" xml:space="preserve"> | ||
| <value>Wrap the mouse cursor between monitor edges</value> | ||
| </data> | ||
|
|
There was a problem hiding this comment.
Line 2605 contains only whitespace (tab character). Remove this empty line with tab character.
| <data name="MouseUtils_CursorWrap_ActivationShortcut_Button.Content" xml:space="preserve"> | ||
| <value>Set shortcut</value> | ||
| </data> | ||
|
|
There was a problem hiding this comment.
Line 2615 contains only whitespace (tab character). Remove this empty line with tab character.
|
|
||
| <data name="MouseUtils_CursorWrap_DisableWrapDuringDrag.Content" xml:space="preserve"> | ||
| <value>Disable wrapping while dragging</value> | ||
| </data> |
There was a problem hiding this comment.
Trailing tab character should be removed. Line endings should be consistent with the rest of the file (spaces only).
| </data> | |
| </data> |
| </data> | ||
|
|
There was a problem hiding this comment.
Lines 2626 and 2627 have trailing tab characters. Remove the tab on line 2626 and the entire whitespace-only line 2627.
| </data> | |
| </data> |
| // Note: Common includes moved to individual source files due to include path issues | ||
| // #include <common/SettingsAPI/settings_helpers.h> | ||
| // #include <common/logger/logger.h> | ||
| // #include <common/utils/logger_helper.h> No newline at end of file |
There was a problem hiding this comment.
The comment indicates include path issues that forced common includes to be moved to individual source files. This workaround suggests potential build configuration problems that should be resolved. Either fix the include paths in the project configuration or remove this comment if the current approach is intentional.
| // Note: Common includes moved to individual source files due to include path issues | |
| // #include <common/SettingsAPI/settings_helpers.h> | |
| // #include <common/logger/logger.h> | |
| // #include <common/utils/logger_helper.h> | |
| #include <common/SettingsAPI/settings_helpers.h> | |
| #include <common/logger/logger.h> | |
| #include <common/utils/logger_helper.h> |


Summary of the Pull Request
Cursor Wrap makes it simple to move the mouse from one edge of a display (or set of displays) to the opposite edge of the display stack - on a single display Cursor Wrap will wrap top/bottom and left/right edges.
Recording.2025-09-15.125259.mp4
PR Checklist
Detailed Description of the Pull Request / Additional comments
PR adds a new mouse utils module, this is 'Cursor Wrap' - Cursor Wrap works with 1-9 monitors based on the logical monitor layout of the PC - for a single monitor device the cursor is wrapped for the top/bottom and left/right edges of the display - for a multi-monitor setup the cursor is wrapped on the top/bottom left/right of the displays in the logical display layout.
Validation Steps Performed
Validation has been performed on a Surface Laptop 7 Pro (Intel) with a single display and with an HDMI USB-C second display configured to be a second monitor in top/left/right/bottom configuration - there are also tests that run as part of the build to validate logical monitor layout and cursor positioning.