mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +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;
|
return CommonSharedConstants::MOUSE_CROSSHAIRS_TRIGGER_EVENT;
|
||||||
}
|
}
|
||||||
|
hstring Constants::CursorWrapTriggerEvent()
|
||||||
|
{
|
||||||
|
return CommonSharedConstants::CURSOR_WRAP_TRIGGER_EVENT;
|
||||||
|
}
|
||||||
hstring Constants::LightSwitchToggleEvent()
|
hstring Constants::LightSwitchToggleEvent()
|
||||||
{
|
{
|
||||||
return CommonSharedConstants::LIGHTSWITCH_TOGGLE_EVENT;
|
return CommonSharedConstants::LIGHTSWITCH_TOGGLE_EVENT;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace winrt::PowerToys::Interop::implementation
|
|||||||
static hstring FindMyMouseTriggerEvent();
|
static hstring FindMyMouseTriggerEvent();
|
||||||
static hstring MouseHighlighterTriggerEvent();
|
static hstring MouseHighlighterTriggerEvent();
|
||||||
static hstring MouseCrosshairsTriggerEvent();
|
static hstring MouseCrosshairsTriggerEvent();
|
||||||
|
static hstring CursorWrapTriggerEvent();
|
||||||
static hstring LightSwitchToggleEvent();
|
static hstring LightSwitchToggleEvent();
|
||||||
static hstring ZoomItZoomEvent();
|
static hstring ZoomItZoomEvent();
|
||||||
static hstring ZoomItDrawEvent();
|
static hstring ZoomItDrawEvent();
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace PowerToys
|
|||||||
static String FindMyMouseTriggerEvent();
|
static String FindMyMouseTriggerEvent();
|
||||||
static String MouseHighlighterTriggerEvent();
|
static String MouseHighlighterTriggerEvent();
|
||||||
static String MouseCrosshairsTriggerEvent();
|
static String MouseCrosshairsTriggerEvent();
|
||||||
|
static String CursorWrapTriggerEvent();
|
||||||
static String LightSwitchToggleEvent();
|
static String LightSwitchToggleEvent();
|
||||||
static String ZoomItZoomEvent();
|
static String ZoomItZoomEvent();
|
||||||
static String ZoomItDrawEvent();
|
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 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_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 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
|
// Path to the event used by RegistryPreview
|
||||||
const wchar_t REGISTRY_PREVIEW_TRIGGER_EVENT[] = L"Local\\RegistryPreviewEvent-4C559468-F75A-4E7F-BC4F-9C9688316687";
|
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/utils/resources.h"
|
||||||
#include "../../../common/logger/logger.h"
|
#include "../../../common/logger/logger.h"
|
||||||
#include "../../../common/utils/logger_helper.h"
|
#include "../../../common/utils/logger_helper.h"
|
||||||
|
#include "../../../common/interop/shared_constants.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -108,6 +109,12 @@ private:
|
|||||||
// Hotkey
|
// Hotkey
|
||||||
Hotkey m_activationHotkey{};
|
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:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
CursorWrap()
|
CursorWrap()
|
||||||
@@ -121,7 +128,8 @@ public:
|
|||||||
// Destroy the powertoy and free memory
|
// Destroy the powertoy and free memory
|
||||||
virtual void destroy() override
|
virtual void destroy() override
|
||||||
{
|
{
|
||||||
StopMouseHook();
|
// Ensure hooks/threads/handles are torn down before deletion
|
||||||
|
disable();
|
||||||
g_cursorWrapInstance = nullptr; // Clear global instance pointer
|
g_cursorWrapInstance = nullptr; // Clear global instance pointer
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
@@ -200,6 +208,34 @@ public:
|
|||||||
// This ensures cursor wrapping is active immediately after enabling
|
// This ensures cursor wrapping is active immediately after enabling
|
||||||
StartMouseHook();
|
StartMouseHook();
|
||||||
Logger::info("CursorWrap enabled - mouse hook started");
|
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
|
// Disable the powertoy
|
||||||
@@ -209,6 +245,26 @@ public:
|
|||||||
Trace::EnableCursorWrap(false);
|
Trace::EnableCursorWrap(false);
|
||||||
StopMouseHook();
|
StopMouseHook();
|
||||||
Logger::info("CursorWrap disabled - mouse hook stopped");
|
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
|
// 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,
|
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())
|
yield return new ListItem(new ShowMouseJumpPreviewCommand())
|
||||||
{
|
{
|
||||||
Title = "Show Mouse Jump Preview",
|
Title = "Show Mouse Jump Preview",
|
||||||
|
|||||||
Reference in New Issue
Block a user