mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 09:46:54 +02:00
CmdPal: Remove dead code from Window Walker and cleanup (#45570)
## Summary of the Pull Request This PR is a light cleanup on Window Walker built-in extension: - Removes unused types - Removes redundant code - Fixes inconsistent naming conventions - De-LINQ-ify - Fixes XML doc - Updates language constructs to the latest (use of System.Threading.Lock, Collection expressions) - Updates types and members visibility and makes static classes static ⚠️ Trickiest part are44ac1c1and26c946cthat removes redundant null checks.
This commit is contained in:
@@ -3,15 +3,10 @@
|
||||
// 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.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Ext.WindowWalker.Helpers;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.WindowWalker.Components;
|
||||
|
||||
@@ -20,26 +15,11 @@ namespace Microsoft.CmdPal.Ext.WindowWalker.Components;
|
||||
/// </summary>
|
||||
internal sealed class Window
|
||||
{
|
||||
/// <summary>
|
||||
/// The handle to the window
|
||||
/// </summary>
|
||||
private readonly IntPtr hwnd;
|
||||
|
||||
/// <summary>
|
||||
/// A static cache for the process data of all known windows
|
||||
/// that we don't have to query the data every time
|
||||
/// </summary>
|
||||
private static readonly Dictionary<IntPtr, WindowProcess> _handlesToProcessCache = new();
|
||||
|
||||
/// <summary>
|
||||
/// An instance of <see cref="WindowProcess"/> that contains the process information for the window
|
||||
/// </summary>
|
||||
private readonly WindowProcess processInfo;
|
||||
|
||||
/// <summary>
|
||||
/// An instance of <see cref="VDesktop"/> that contains the desktop information for the window
|
||||
/// </summary>
|
||||
private readonly VDesktop desktopInfo;
|
||||
private static readonly Dictionary<IntPtr, WindowProcess> HandlesToProcessCache = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the title of the window (the string displayed at the top of the window)
|
||||
@@ -48,11 +28,11 @@ internal sealed class Window
|
||||
{
|
||||
get
|
||||
{
|
||||
var sizeOfTitle = NativeMethods.GetWindowTextLength(hwnd);
|
||||
var sizeOfTitle = NativeMethods.GetWindowTextLength(Hwnd);
|
||||
if (sizeOfTitle++ > 0)
|
||||
{
|
||||
StringBuilder titleBuffer = new StringBuilder(sizeOfTitle);
|
||||
var numCharactersWritten = NativeMethods.GetWindowText(hwnd, titleBuffer, sizeOfTitle);
|
||||
var titleBuffer = new StringBuilder(sizeOfTitle);
|
||||
var numCharactersWritten = NativeMethods.GetWindowText(Hwnd, titleBuffer, sizeOfTitle);
|
||||
if (numCharactersWritten == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
@@ -70,17 +50,17 @@ internal sealed class Window
|
||||
/// <summary>
|
||||
/// Gets the handle to the window
|
||||
/// </summary>
|
||||
internal IntPtr Hwnd => hwnd;
|
||||
internal IntPtr Hwnd { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the object of with the process information of the window
|
||||
/// </summary>
|
||||
internal WindowProcess Process => processInfo;
|
||||
internal WindowProcess Process { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the object of with the desktop information of the window
|
||||
/// </summary>
|
||||
internal VDesktop Desktop => desktopInfo;
|
||||
internal VDesktop Desktop { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the class for the window represented
|
||||
@@ -130,7 +110,7 @@ internal sealed class Window
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the window is minimized
|
||||
/// </summary>
|
||||
internal bool Minimized => GetWindowSizeState() == WindowSizeState.Minimized;
|
||||
private bool Minimized => GetWindowSizeState() == WindowSizeState.Minimized;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Window"/> class.
|
||||
@@ -140,9 +120,9 @@ internal sealed class Window
|
||||
internal Window(IntPtr hwnd)
|
||||
{
|
||||
// TODO: Add verification as to whether the window handle is valid
|
||||
this.hwnd = hwnd;
|
||||
processInfo = CreateWindowProcessInstance(hwnd);
|
||||
desktopInfo = WindowWalkerCommandsProvider.VirtualDesktopHelperInstance.GetWindowDesktop(hwnd);
|
||||
Hwnd = hwnd;
|
||||
Process = CreateWindowProcessInstance(hwnd);
|
||||
Desktop = WindowWalkerCommandsProvider.VirtualDesktopHelperInstance.GetWindowDesktop(hwnd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -155,7 +135,7 @@ internal sealed class Window
|
||||
// to use ShowWindow for switching tabs in IE
|
||||
// 2) SetForegroundWindow fails on minimized windows
|
||||
// Using Ordinal since this is internal
|
||||
if (processInfo.Name?.ToUpperInvariant().Equals("IEXPLORE.EXE", StringComparison.Ordinal) == true || !Minimized)
|
||||
if (Process.Name?.ToUpperInvariant().Equals("IEXPLORE.EXE", StringComparison.Ordinal) == true || !Minimized)
|
||||
{
|
||||
NativeMethods.SetForegroundWindow(Hwnd);
|
||||
}
|
||||
@@ -174,7 +154,7 @@ internal sealed class Window
|
||||
/// <summary>
|
||||
/// Helper function to close the window
|
||||
/// </summary>
|
||||
internal void CloseThisWindowHelper()
|
||||
private void CloseThisWindowHelper()
|
||||
{
|
||||
_ = NativeMethods.SendMessageTimeout(Hwnd, Win32Constants.WM_SYSCOMMAND, Win32Constants.SC_CLOSE, 0, 0x0000, 5000, out _);
|
||||
}
|
||||
@@ -184,7 +164,7 @@ internal sealed class Window
|
||||
/// </summary>
|
||||
internal void CloseThisWindow()
|
||||
{
|
||||
Thread thread = new(new ThreadStart(CloseThisWindowHelper));
|
||||
Thread thread = new(CloseThisWindowHelper);
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
@@ -197,47 +177,47 @@ internal sealed class Window
|
||||
{
|
||||
icon = null;
|
||||
|
||||
if (hwnd == IntPtr.Zero)
|
||||
if (Hwnd == IntPtr.Zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try WM_GETICON with SendMessageTimeout
|
||||
if (NativeMethods.SendMessageTimeout(hwnd, Win32Constants.WM_GETICON, (UIntPtr)Win32Constants.ICON_BIG, IntPtr.Zero, Win32Constants.SMTO_ABORTIFHUNG, 100, out var result) != 0 && result != 0)
|
||||
if (NativeMethods.SendMessageTimeout(Hwnd, Win32Constants.WM_GETICON, Win32Constants.ICON_BIG, IntPtr.Zero, Win32Constants.SMTO_ABORTIFHUNG, 100, out var result) != 0 && result != 0)
|
||||
{
|
||||
icon = System.Drawing.Icon.FromHandle((IntPtr)result);
|
||||
NativeMethods.DestroyIcon((IntPtr)result);
|
||||
icon = System.Drawing.Icon.FromHandle(result);
|
||||
NativeMethods.DestroyIcon(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NativeMethods.SendMessageTimeout(hwnd, Win32Constants.WM_GETICON, (UIntPtr)Win32Constants.ICON_SMALL, IntPtr.Zero, Win32Constants.SMTO_ABORTIFHUNG, 100, out result) != 0 && result != 0)
|
||||
if (NativeMethods.SendMessageTimeout(Hwnd, Win32Constants.WM_GETICON, Win32Constants.ICON_SMALL, IntPtr.Zero, Win32Constants.SMTO_ABORTIFHUNG, 100, out result) != 0 && result != 0)
|
||||
{
|
||||
icon = System.Drawing.Icon.FromHandle((IntPtr)result);
|
||||
NativeMethods.DestroyIcon((IntPtr)result);
|
||||
icon = System.Drawing.Icon.FromHandle(result);
|
||||
NativeMethods.DestroyIcon(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NativeMethods.SendMessageTimeout(hwnd, Win32Constants.WM_GETICON, (UIntPtr)Win32Constants.ICON_SMALL2, IntPtr.Zero, Win32Constants.SMTO_ABORTIFHUNG, 100, out result) != 0 && result != 0)
|
||||
if (NativeMethods.SendMessageTimeout(Hwnd, Win32Constants.WM_GETICON, Win32Constants.ICON_SMALL2, IntPtr.Zero, Win32Constants.SMTO_ABORTIFHUNG, 100, out result) != 0 && result != 0)
|
||||
{
|
||||
icon = System.Drawing.Icon.FromHandle((IntPtr)result);
|
||||
NativeMethods.DestroyIcon((IntPtr)result);
|
||||
icon = System.Drawing.Icon.FromHandle(result);
|
||||
NativeMethods.DestroyIcon(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback to GetClassLongPtr
|
||||
var iconHandle = NativeMethods.GetClassLongPtr(hwnd, Win32Constants.GCLP_HICON);
|
||||
var iconHandle = NativeMethods.GetClassLongPtr(Hwnd, Win32Constants.GCLP_HICON);
|
||||
if (iconHandle != IntPtr.Zero)
|
||||
{
|
||||
icon = System.Drawing.Icon.FromHandle(iconHandle);
|
||||
NativeMethods.DestroyIcon((IntPtr)iconHandle);
|
||||
NativeMethods.DestroyIcon(iconHandle);
|
||||
return true;
|
||||
}
|
||||
|
||||
iconHandle = NativeMethods.GetClassLongPtr(hwnd, Win32Constants.GCLP_HICONSM);
|
||||
iconHandle = NativeMethods.GetClassLongPtr(Hwnd, Win32Constants.GCLP_HICONSM);
|
||||
if (iconHandle != IntPtr.Zero)
|
||||
{
|
||||
icon = System.Drawing.Icon.FromHandle(iconHandle);
|
||||
NativeMethods.DestroyIcon((IntPtr)iconHandle);
|
||||
NativeMethods.DestroyIcon(iconHandle);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -251,16 +231,16 @@ internal sealed class Window
|
||||
public override string ToString()
|
||||
{
|
||||
// Using CurrentCulture since this is user facing
|
||||
return Title + " (" + processInfo.Name?.ToUpper(CultureInfo.CurrentCulture) + ")";
|
||||
return Title + " (" + Process.Name?.ToUpper(CultureInfo.CurrentCulture) + ")";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns what the window size is
|
||||
/// </summary>
|
||||
/// <returns>The state (minimized, maximized, etc..) of the window</returns>
|
||||
internal WindowSizeState GetWindowSizeState()
|
||||
/// <returns>The state (minimized, maximized, etc...) of the window</returns>
|
||||
private WindowSizeState GetWindowSizeState()
|
||||
{
|
||||
NativeMethods.GetWindowPlacement(Hwnd, out WINDOWPLACEMENT placement);
|
||||
NativeMethods.GetWindowPlacement(Hwnd, out var placement);
|
||||
|
||||
switch (placement.ShowCmd)
|
||||
{
|
||||
@@ -304,7 +284,7 @@ internal sealed class Window
|
||||
case (int)DwmWindowCloakStates.CloakedApp:
|
||||
return WindowCloakState.App;
|
||||
case (int)DwmWindowCloakStates.CloakedShell:
|
||||
return WindowWalkerCommandsProvider.VirtualDesktopHelperInstance.IsWindowCloakedByVirtualDesktopManager(hwnd, Desktop.Id) ? WindowCloakState.OtherDesktop : WindowCloakState.Shell;
|
||||
return WindowWalkerCommandsProvider.VirtualDesktopHelperInstance.IsWindowCloakedByVirtualDesktopManager(Hwnd, Desktop.Id) ? WindowCloakState.OtherDesktop : WindowCloakState.Shell;
|
||||
case (int)DwmWindowCloakStates.CloakedInherited:
|
||||
return WindowCloakState.Inherited;
|
||||
default:
|
||||
@@ -332,7 +312,7 @@ internal sealed class Window
|
||||
/// <returns>Class name</returns>
|
||||
private static string GetWindowClassName(IntPtr hwnd)
|
||||
{
|
||||
StringBuilder windowClassName = new StringBuilder(300);
|
||||
var windowClassName = new StringBuilder(300);
|
||||
var numCharactersWritten = NativeMethods.GetClassName(hwnd, windowClassName, windowClassName.MaxCapacity);
|
||||
|
||||
if (numCharactersWritten == 0)
|
||||
@@ -350,16 +330,16 @@ internal sealed class Window
|
||||
/// <returns>A new Instance of type <see cref="WindowProcess"/></returns>
|
||||
private static WindowProcess CreateWindowProcessInstance(IntPtr hWindow)
|
||||
{
|
||||
lock (_handlesToProcessCache)
|
||||
lock (HandlesToProcessCache)
|
||||
{
|
||||
if (_handlesToProcessCache.Count > 7000)
|
||||
if (HandlesToProcessCache.Count > 7000)
|
||||
{
|
||||
Debug.Print("Clearing Process Cache because it's size is " + _handlesToProcessCache.Count);
|
||||
_handlesToProcessCache.Clear();
|
||||
Debug.Print("Clearing Process Cache because it's size is " + HandlesToProcessCache.Count);
|
||||
HandlesToProcessCache.Clear();
|
||||
}
|
||||
|
||||
// Add window's process to cache if missing
|
||||
if (!_handlesToProcessCache.ContainsKey(hWindow))
|
||||
if (!HandlesToProcessCache.ContainsKey(hWindow))
|
||||
{
|
||||
// Get process ID and name
|
||||
var processId = WindowProcess.GetProcessIDFromWindowHandle(hWindow);
|
||||
@@ -368,23 +348,23 @@ internal sealed class Window
|
||||
|
||||
if (processName.Length != 0)
|
||||
{
|
||||
_handlesToProcessCache.Add(hWindow, new WindowProcess(processId, threadId, processName));
|
||||
HandlesToProcessCache.Add(hWindow, new WindowProcess(processId, threadId, processName));
|
||||
}
|
||||
else
|
||||
{
|
||||
// For the dwm process we cannot receive the name. This is no problem because the window isn't part of result list.
|
||||
ExtensionHost.LogMessage(new LogMessage() { Message = $"Invalid process {processId} ({processName}) for window handle {hWindow}." });
|
||||
_handlesToProcessCache.Add(hWindow, new WindowProcess(0, 0, string.Empty));
|
||||
ExtensionHost.LogMessage(new LogMessage { Message = $"Invalid process {processId} ({processName}) for window handle {hWindow}." });
|
||||
HandlesToProcessCache.Add(hWindow, new WindowProcess(0, 0, string.Empty));
|
||||
}
|
||||
}
|
||||
|
||||
// Correct the process data if the window belongs to a uwp app hosted by 'ApplicationFrameHost.exe'
|
||||
// (This only works if the window isn't minimized. For minimized windows the required child window isn't assigned.)
|
||||
if (_handlesToProcessCache[hWindow].IsUwpAppFrameHost)
|
||||
if (HandlesToProcessCache[hWindow].IsUwpAppFrameHost)
|
||||
{
|
||||
new Task(() =>
|
||||
{
|
||||
EnumWindowsProc callbackptr = new EnumWindowsProc((IntPtr hwnd, IntPtr lParam) =>
|
||||
var callbackptr = new EnumWindowsProc((hwnd, _) =>
|
||||
{
|
||||
// Every uwp app main window has at least three child windows. Only the one we are interested in has a class starting with "Windows.UI.Core." and is assigned to the real app process.
|
||||
// (The other ones have a class name that begins with the string "ApplicationFrame".)
|
||||
@@ -395,9 +375,9 @@ internal sealed class Window
|
||||
var childProcessName = WindowProcess.GetProcessNameFromProcessID(childProcessId);
|
||||
|
||||
// Update process info in cache
|
||||
lock (_handlesToProcessCache)
|
||||
lock (HandlesToProcessCache)
|
||||
{
|
||||
_handlesToProcessCache[hWindow].UpdateProcessInfo(childProcessId, childThreadId, childProcessName);
|
||||
HandlesToProcessCache[hWindow].UpdateProcessInfo(childProcessId, childThreadId, childProcessName);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -411,7 +391,7 @@ internal sealed class Window
|
||||
}).Start();
|
||||
}
|
||||
|
||||
return _handlesToProcessCache[hWindow];
|
||||
return HandlesToProcessCache[hWindow];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user