[Run][WindowWalker]Improve EnumWindows synchronization (#27490)

This commit is contained in:
Davide Giacometti 2023-07-25 15:15:34 +02:00 committed by GitHub
parent 082c312325
commit e02ceaa8d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 16 deletions

View File

@ -6,6 +6,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using Wox.Plugin.Common.Win32;
namespace Microsoft.Plugin.WindowWalker.Components
@ -15,6 +17,11 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// </summary>
internal class OpenWindows
{
/// <summary>
/// Used to enforce single execution of EnumWindows
/// </summary>
private static readonly object _enumWindowsLock = new();
/// <summary>
/// PowerLauncher main executable
/// </summary>
@ -33,10 +40,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <summary>
/// Gets the list of all open windows
/// </summary>
internal List<Window> Windows
{
get { return new List<Window>(windows); }
}
internal List<Window> Windows => windows;
/// <summary>
/// Gets an instance property of this class that makes sure that
@ -68,11 +72,26 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <summary>
/// Updates the list of open windows
/// </summary>
internal void UpdateOpenWindowsList()
internal void UpdateOpenWindowsList(CancellationToken cancellationToken)
{
windows.Clear();
EnumWindowsProc callbackptr = new EnumWindowsProc(WindowEnumerationCallBack);
_ = NativeMethods.EnumWindows(callbackptr, 0);
var tokenHandle = GCHandle.Alloc(cancellationToken);
try
{
var tokenHandleParam = GCHandle.ToIntPtr(tokenHandle);
lock (_enumWindowsLock)
{
windows.Clear();
EnumWindowsProc callbackptr = new EnumWindowsProc(WindowEnumerationCallBack);
_ = NativeMethods.EnumWindows(callbackptr, tokenHandleParam);
}
}
finally
{
if (tokenHandle.IsAllocated)
{
tokenHandle.Free();
}
}
}
/// <summary>
@ -84,6 +103,14 @@ namespace Microsoft.Plugin.WindowWalker.Components
/// <returns>true to make sure to continue enumeration</returns>
internal bool WindowEnumerationCallBack(IntPtr hwnd, IntPtr lParam)
{
var tokenHandle = GCHandle.FromIntPtr(lParam);
var cancellationToken = (CancellationToken)tokenHandle.Target;
if (cancellationToken.IsCancellationRequested)
{
// Stop enumeration
return false;
}
Window newWindow = new Window(hwnd);
if (newWindow.IsWindow && newWindow.Visible && newWindow.IsOwner &&

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Controls;
using ManagedCommon;
using Microsoft.Plugin.WindowWalker.Components;
@ -13,8 +14,11 @@ using Wox.Plugin.Common.VirtualDesktop.Helper;
namespace Microsoft.Plugin.WindowWalker
{
public class Main : IPlugin, IPluginI18n, ISettingProvider, IContextMenu
public class Main : IPlugin, IPluginI18n, ISettingProvider, IContextMenu, IDisposable
{
private CancellationTokenSource _cancellationTokenSource = new();
private bool _disposed;
private string IconPath { get; set; }
private string InfoIconPath { get; set; }
@ -27,11 +31,6 @@ namespace Microsoft.Plugin.WindowWalker
internal static readonly VirtualDesktopHelper VirtualDesktopHelperInstance = new VirtualDesktopHelper();
static Main()
{
OpenWindows.Instance.UpdateOpenWindowsList();
}
public List<Result> Query(Query query)
{
if (query == null)
@ -39,8 +38,12 @@ namespace Microsoft.Plugin.WindowWalker
throw new ArgumentNullException(nameof(query));
}
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = new CancellationTokenSource();
VirtualDesktopHelperInstance.UpdateDesktopList();
OpenWindows.Instance.UpdateOpenWindowsList();
OpenWindows.Instance.UpdateOpenWindowsList(_cancellationTokenSource.Token);
SearchController.Instance.UpdateSearchText(query.Search);
List<SearchResult> searchControllerResults = SearchController.Instance.SearchMatches;
@ -103,5 +106,23 @@ namespace Microsoft.Plugin.WindowWalker
{
WindowWalkerSettings.Instance.UpdateSettings(settings);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_cancellationTokenSource?.Dispose();
_disposed = true;
}
}
}
}
}

View File

@ -16,7 +16,7 @@ namespace Wox.Plugin.Common.Win32
public static class NativeMethods
{
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int EnumWindows(EnumWindowsProc callPtr, int lPar);
public static extern int EnumWindows(EnumWindowsProc callPtr, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCmd uCmd);