/
githubmirror
/
PowerToys
Обзор
Документация
Войти
/
githubmirror
/
PowerToys
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/modules/MouseUtils/MouseJump.WinUI3/Helpers/MouseJumpEventLoop.cs
150 строк
6 KB
Michael Clayton
Ready for Review - [Mouse Jump] - port upstream WinUI3 code to Mouse Jump (microsoft#48290) (#48393)
07 авг 2026, 08:34
Не верифицирован
07 авг 2026, 08:34
e0010c5
Код
Авторство
О чём код?
// 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 ManagedCommon; using Microsoft.UI.Dispatching; namespace MouseJump.WinUI3.Helpers; internal static class MouseJumpEventLoop { /// <summary> /// Based on NativeEventWaiter.WaitForEventLoop. /// </summary> public static void RunEventHandler(string eventName, Action callback, DispatcherQueue dispatcherQueue, CancellationToken cancel) { Logger.LogDebug($"starting event handler for event '{eventName}'"); var thread = new Thread(() => { using var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName); var waitHandles = new WaitHandle[] { cancel.WaitHandle, eventHandle }; while (true) { Logger.LogDebug($"[{eventName}] - entering event handler loop"); if (WaitHandle.WaitAny(waitHandles) == 1) { try { Logger.LogDebug($"[{eventName}] - invoking callback"); var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); if (!dispatcherQueue.TryEnqueue(() => { try { callback(); tcs.SetResult(); } catch (Exception ex) { tcs.SetException(ex); } })) { tcs.SetException(new InvalidOperationException("DispatcherQueue is not accepting work items.")); } tcs.Task.GetAwaiter().GetResult(); } catch (Exception ex) { // if something went wrong the application could be in an unstable state. // the main MouseJump module will restart the background process the next // time the hotkey is invoked, so just rethrow the exception here. Logger.LogDebug($"[{eventName}] - error occurred"); Logger.LogError(ex.ToString()); throw; } } else { Logger.LogDebug($"[{eventName}] - exiting event handler loop"); return; } } }); thread.Name = "MouseJumpEventLoopThread"; thread.IsBackground = true; thread.Start(); } /// <summary> /// Based on NativeEventWaiter.WaitForEventLoop, /// but takes an async callback. /// </summary> public static void RunAsyncEventHandler(string eventName, Func<Task> callback, DispatcherQueue dispatcherQueue, CancellationToken cancel) { Logger.LogDebug($"starting event handler for event '{eventName}'"); var thread = new Thread(() => { using var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName); var waitHandles = new WaitHandle[] { cancel.WaitHandle, eventHandle }; while (true) { Logger.LogDebug($"[{eventName}] - entering event handler loop"); if (WaitHandle.WaitAny(waitHandles) == 1) { try { Logger.LogDebug($"[{eventName}] - invoking callback"); var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); if (!dispatcherQueue.TryEnqueue(() => { try { _ = callback().ContinueWith( t => { if (t.IsFaulted) { tcs.SetException(t.Exception!.InnerExceptions); } else if (t.IsCanceled) { tcs.SetCanceled(); } else { tcs.SetResult(); } }, TaskScheduler.Default); } catch (Exception ex) { tcs.SetException(ex); } })) { tcs.SetException(new InvalidOperationException("DispatcherQueue is not accepting work items.")); } tcs.Task.GetAwaiter().GetResult(); // block until callback completes } catch (Exception ex) { // if something went wrong the application could be in an unstable state. // the main MouseJump module will restart the background process the next // time the hotkey is invoked, so just rethrow the exception here. Logger.LogDebug($"[{eventName}] - error occurred"); Logger.LogError(ex.ToString()); throw; } } else { Logger.LogDebug($"[{eventName}] - exiting event handler loop"); return; } } }); thread.Name = "MouseJumpEventLoopThread"; thread.IsBackground = true; thread.Start(); } }