// 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. // Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/ 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 { /// /// Class that represents the state of the desktops windows /// internal class OpenWindows { /// /// Used to enforce single execution of EnumWindows /// private static readonly Lock _enumWindowsLock = new(); /// /// PowerLauncher main executable /// private static readonly string _powerLauncherExe = Path.GetFileName(Environment.ProcessPath); /// /// List of all the open windows /// private readonly List windows = new List(); /// /// An instance of the class OpenWindows /// private static OpenWindows instance; /// /// Gets the list of all open windows /// internal List Windows => new List(windows); /// /// Gets an instance property of this class that makes sure that /// the first instance gets created and that all the requests /// end up at that one instance /// internal static OpenWindows Instance { get { if (instance == null) { instance = new OpenWindows(); } return instance; } } /// /// Initializes a new instance of the class. /// Private constructor to make sure there is never /// more than one instance of this class /// private OpenWindows() { } /// /// Updates the list of open windows /// internal void UpdateOpenWindowsList(CancellationToken cancellationToken) { 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(); } } } /// /// Call back method for window enumeration /// /// The handle to the current window being enumerated /// Value being passed from the caller (we don't use this but might come in handy /// in the future /// true to make sure to continue enumeration 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 && (!newWindow.IsToolWindow || newWindow.IsAppWindow) && !newWindow.TaskListDeleted && (newWindow.Desktop.IsVisible || !WindowWalkerSettings.Instance.ResultsFromVisibleDesktopOnly || Main.VirtualDesktopHelperInstance.GetDesktopCount() < 2) && newWindow.ClassName != "Windows.UI.Core.CoreWindow" && newWindow.Process.Name != _powerLauncherExe) { // To hide (not add) preloaded uwp app windows that are invisible to the user and other cloaked windows, we check the cloak state. (Issue #13637.) // (If user asking to see cloaked uwp app windows again we can add an optional plugin setting in the future.) if (!newWindow.IsCloaked || newWindow.GetWindowCloakState() == Window.WindowCloakState.OtherDesktop) { windows.Add(newWindow); } } return true; } } }