Skip to content

Add Cursor Wrap functionality to Powertoys Mouse Utils#41826

Merged
vanzue merged 14 commits intomicrosoft:mainfrom
mikehall-ms:mikehall/mousewrap
Nov 5, 2025
Merged

Add Cursor Wrap functionality to Powertoys Mouse Utils#41826
vanzue merged 14 commits intomicrosoft:mainfrom
mikehall-ms:mikehall/mousewrap

Conversation

@mikehall-ms
Copy link
Copy Markdown
Contributor

@mikehall-ms mikehall-ms commented Sep 15, 2025

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

  • Closes: CursorWrap CursorWrap #41759
  • Communication: I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected
  • Tests: Added/updated and all pass
  • Localization: All end-user-facing strings can be localized
  • Dev docs: Added/updated
  • New binaries: Added on the required places
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

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.

@mikehall-ms mikehall-ms requested a review from a team as a code owner September 15, 2025 09:56
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@niels9001 niels9001 added this to the PowerToys 0.95 milestone Sep 15, 2025
@vanzue vanzue requested a review from Copilot September 24, 2025 09:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@vanzue
Copy link
Copy Markdown
Contributor

vanzue commented Oct 30, 2025

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

@github-actions

This comment has been minimized.

@yeelam-gordon
Copy link
Copy Markdown
Contributor

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

It need to be activated by shortcut first...

@niels9001
Copy link
Copy Markdown
Collaborator

@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.

@niels9001
Copy link
Copy Markdown
Collaborator

Note to self: I need to create an utility icon for this

@yeelam-gordon
Copy link
Copy Markdown
Contributor

@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.

People can choose now:
image
While default need shortcut activation

@github-actions

This comment has been minimized.

@yeelam-gordon yeelam-gordon self-assigned this Nov 4, 2025
@yeelam-gordon
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@vanzue
Copy link
Copy Markdown
Contributor

vanzue commented Nov 4, 2025

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

It need to be activated by shortcut first...

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

@vanzue
Copy link
Copy Markdown
Contributor

vanzue commented Nov 4, 2025

And causes too many logs:
image

It's 5 minutes log, so we need to remove the logs before check in

@yeelam-gordon
Copy link
Copy Markdown
Contributor

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

It need to be activated by shortcut first...

Did you test? I surely enabled by shortcut, it's stuck and moving at a really small area, and won't leave that area

Yes, I did, that's why I can capture the screenshot. It works for me for both vertical and horizontal on my two monitors

@github-actions
Copy link
Copy Markdown

github-actions bot commented Nov 4, 2025

@check-spelling-bot Report

🔴 Please review

See the 📂 files view, the 📜action log, or 📝 job summary for details.

❌ Errors and Warnings Count
❌ forbidden-pattern 1
⚠️ ignored-expect-variant 3

See ❌ Event descriptions for more information.

These words are not needed and should be removed cabstr CIBUILD djwsxzxb icf installscopeperuser ksa rap registryroot regroot rtm suntimes TARGETDIR utm

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

@vanzue
Copy link
Copy Markdown
Contributor

vanzue commented Nov 4, 2025

wrap_cursor.mp4

Strange in my test, I'm testing in my devbox though, can't get out of the screen side

@yeelam-gordon
Copy link
Copy Markdown
Contributor

yeelam-gordon commented Nov 5, 2025

wrap_cursor.mp4
Strange 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.
I just asked GPT, looks like remote session may not be supported easily.

@vanzue, do you mind to try on physical machine? If it works at your notebook or desktop, we should able to checkin first.

@vanzue
Copy link
Copy Markdown
Contributor

vanzue commented Nov 5, 2025

Works fine in my laptop!

@vanzue vanzue merged commit cd988b7 into microsoft:main Nov 5, 2025
10 checks passed
@yeelam-gordon yeelam-gordon requested a review from Copilot November 7, 2025 01:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 30 out of 31 changed files in this pull request and generated 6 comments.

<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>
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing tab character should be removed. Line endings should be consistent with the rest of the file (spaces only).

Suggested change
</data>
</data>

Copilot uses AI. Check for mistakes.
<data name="MouseUtils_CursorWrap.Description" xml:space="preserve">
<value>Wrap the mouse cursor between monitor edges</value>
</data>

Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 2605 contains only whitespace (tab character). Remove this empty line with tab character.

Suggested change

Copilot uses AI. Check for mistakes.
<data name="MouseUtils_CursorWrap_ActivationShortcut_Button.Content" xml:space="preserve">
<value>Set shortcut</value>
</data>

Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 2615 contains only whitespace (tab character). Remove this empty line with tab character.

Suggested change

Copilot uses AI. Check for mistakes.

<data name="MouseUtils_CursorWrap_DisableWrapDuringDrag.Content" xml:space="preserve">
<value>Disable wrapping while dragging</value>
</data>
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing tab character should be removed. Line endings should be consistent with the rest of the file (spaces only).

Suggested change
</data>
</data>

Copilot uses AI. Check for mistakes.
Comment on lines +2626 to +2627
</data>

Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 2626 and 2627 have trailing tab characters. Remove the tab on line 2626 and the entire whitespace-only line 2627.

Suggested change
</data>
</data>

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +13
// 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
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
// 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>

Copilot uses AI. Check for mistakes.
@yeelam-gordon yeelam-gordon added the Product-Mouse Utilities Refers to the Mouse Utilities PowerToy label Nov 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

In for .96 Product-Mouse Utilities Refers to the Mouse Utilities PowerToy

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants