mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 03:37:59 +01:00
Cursor wrap command
This commit is contained in:
@@ -99,6 +99,10 @@ namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
return CommonSharedConstants::MOUSE_CROSSHAIRS_TRIGGER_EVENT;
|
||||
}
|
||||
hstring Constants::CursorWrapTriggerEvent()
|
||||
{
|
||||
return CommonSharedConstants::CURSOR_WRAP_TRIGGER_EVENT;
|
||||
}
|
||||
hstring Constants::LightSwitchToggleEvent()
|
||||
{
|
||||
return CommonSharedConstants::LIGHTSWITCH_TOGGLE_EVENT;
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace winrt::PowerToys::Interop::implementation
|
||||
static hstring FindMyMouseTriggerEvent();
|
||||
static hstring MouseHighlighterTriggerEvent();
|
||||
static hstring MouseCrosshairsTriggerEvent();
|
||||
static hstring CursorWrapTriggerEvent();
|
||||
static hstring LightSwitchToggleEvent();
|
||||
static hstring ZoomItZoomEvent();
|
||||
static hstring ZoomItDrawEvent();
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace PowerToys
|
||||
static String FindMyMouseTriggerEvent();
|
||||
static String MouseHighlighterTriggerEvent();
|
||||
static String MouseCrosshairsTriggerEvent();
|
||||
static String CursorWrapTriggerEvent();
|
||||
static String LightSwitchToggleEvent();
|
||||
static String ZoomItZoomEvent();
|
||||
static String ZoomItDrawEvent();
|
||||
|
||||
@@ -89,6 +89,7 @@ namespace CommonSharedConstants
|
||||
const wchar_t FIND_MY_MOUSE_TRIGGER_EVENT[] = L"Local\\FindMyMouseTriggerEvent-5a9dc5f4-1c74-4f2f-a66f-1b9b6a2f9b23";
|
||||
const wchar_t MOUSE_HIGHLIGHTER_TRIGGER_EVENT[] = L"Local\\MouseHighlighterTriggerEvent-1e3c9c3d-3fdf-4f9a-9a52-31c9b3c3a8f4";
|
||||
const wchar_t MOUSE_CROSSHAIRS_TRIGGER_EVENT[] = L"Local\\MouseCrosshairsTriggerEvent-0d4c7f92-0a5c-4f5c-b64b-8a2a2f7e0b21";
|
||||
const wchar_t CURSOR_WRAP_TRIGGER_EVENT[] = L"Local\\CursorWrapTriggerEvent-1f8452b5-4e6e-45b3-8b09-13f14a5900c9";
|
||||
|
||||
// Path to the event used by RegistryPreview
|
||||
const wchar_t REGISTRY_PREVIEW_TRIGGER_EVENT[] = L"Local\\RegistryPreviewEvent-4C559468-F75A-4E7F-BC4F-9C9688316687";
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "../../../common/utils/resources.h"
|
||||
#include "../../../common/logger/logger.h"
|
||||
#include "../../../common/utils/logger_helper.h"
|
||||
#include "../../../common/interop/shared_constants.h"
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
@@ -108,6 +109,12 @@ private:
|
||||
// Hotkey
|
||||
Hotkey m_activationHotkey{};
|
||||
|
||||
// Event-driven trigger support (for CmdPal/automation)
|
||||
HANDLE m_triggerEventHandle = nullptr;
|
||||
HANDLE m_terminateEventHandle = nullptr;
|
||||
std::thread m_eventThread;
|
||||
std::atomic_bool m_listening{ false };
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
CursorWrap()
|
||||
@@ -121,7 +128,8 @@ public:
|
||||
// Destroy the powertoy and free memory
|
||||
virtual void destroy() override
|
||||
{
|
||||
StopMouseHook();
|
||||
// Ensure hooks/threads/handles are torn down before deletion
|
||||
disable();
|
||||
g_cursorWrapInstance = nullptr; // Clear global instance pointer
|
||||
delete this;
|
||||
}
|
||||
@@ -200,6 +208,34 @@ public:
|
||||
// This ensures cursor wrapping is active immediately after enabling
|
||||
StartMouseHook();
|
||||
Logger::info("CursorWrap enabled - mouse hook started");
|
||||
|
||||
// Start listening for external trigger event so we can invoke the same logic as the activation hotkey.
|
||||
m_triggerEventHandle = CreateEventW(nullptr, false, false, CommonSharedConstants::CURSOR_WRAP_TRIGGER_EVENT);
|
||||
m_terminateEventHandle = CreateEventW(nullptr, false, false, nullptr);
|
||||
if (m_triggerEventHandle && m_terminateEventHandle)
|
||||
{
|
||||
m_listening = true;
|
||||
m_eventThread = std::thread([this]() {
|
||||
HANDLE handles[2] = { m_triggerEventHandle, m_terminateEventHandle };
|
||||
while (m_listening)
|
||||
{
|
||||
auto res = WaitForMultipleObjects(2, handles, false, INFINITE);
|
||||
if (!m_listening)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == WAIT_OBJECT_0)
|
||||
{
|
||||
on_hotkey(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Disable the powertoy
|
||||
@@ -209,6 +245,26 @@ public:
|
||||
Trace::EnableCursorWrap(false);
|
||||
StopMouseHook();
|
||||
Logger::info("CursorWrap disabled - mouse hook stopped");
|
||||
|
||||
m_listening = false;
|
||||
if (m_terminateEventHandle)
|
||||
{
|
||||
SetEvent(m_terminateEventHandle);
|
||||
}
|
||||
if (m_eventThread.joinable())
|
||||
{
|
||||
m_eventThread.join();
|
||||
}
|
||||
if (m_triggerEventHandle)
|
||||
{
|
||||
CloseHandle(m_triggerEventHandle);
|
||||
m_triggerEventHandle = nullptr;
|
||||
}
|
||||
if (m_terminateEventHandle)
|
||||
{
|
||||
CloseHandle(m_terminateEventHandle);
|
||||
m_terminateEventHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns if the powertoys is enabled
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToys.Interop;
|
||||
|
||||
namespace PowerToysExtension.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Toggles Cursor Wrap via the shared trigger event.
|
||||
/// </summary>
|
||||
internal sealed partial class ToggleCursorWrapCommand : InvokableCommand
|
||||
{
|
||||
public ToggleCursorWrapCommand()
|
||||
{
|
||||
Name = "Toggle Cursor Wrap";
|
||||
}
|
||||
|
||||
public override CommandResult Invoke()
|
||||
{
|
||||
try
|
||||
{
|
||||
using var evt = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.CursorWrapTriggerEvent());
|
||||
evt.Set();
|
||||
return CommandResult.Dismiss();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return CommandResult.ShowToast($"Failed to toggle Cursor Wrap: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,13 @@ internal sealed class MouseUtilsModuleCommandProvider : ModuleCommandProvider
|
||||
Icon = icon,
|
||||
};
|
||||
|
||||
yield return new ListItem(new ToggleCursorWrapCommand())
|
||||
{
|
||||
Title = "Toggle Cursor Wrap",
|
||||
Subtitle = "Wrap the cursor across monitor edges",
|
||||
Icon = icon,
|
||||
};
|
||||
|
||||
yield return new ListItem(new ShowMouseJumpPreviewCommand())
|
||||
{
|
||||
Title = "Show Mouse Jump Preview",
|
||||
|
||||
Reference in New Issue
Block a user