Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PT Run] WindowWalker: Refactor code, fix some bugs, hide UWP non-windows, prepare code for new features #15441

Merged
merged 36 commits into from
Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
12f1338
Import files from old PR #15329
htcfreek Jan 11, 2022
6c37d13
Improvements
htcfreek Jan 11, 2022
e29cc82
hide uwp non-windows (#13637)
htcfreek Jan 11, 2022
fd2a719
update debug tool tip
htcfreek Jan 11, 2022
5d58d32
fix spelling and comments
htcfreek Jan 11, 2022
552fefc
disable tool tip
htcfreek Jan 11, 2022
eb00d6d
fix doc links
htcfreek Jan 11, 2022
49df906
remove obsolete using
htcfreek Jan 11, 2022
6264e11
Update docs
htcfreek Jan 11, 2022
6f1e89f
fix spelling
htcfreek Jan 11, 2022
072fe14
rename elevation property and test method
htcfreek Jan 13, 2022
a53d0c9
Add property <DoesExist> to WindowProcess class
htcfreek Jan 13, 2022
18d45a3
Close process handles correctly if not used anymore
htcfreek Jan 13, 2022
f180dc8
cleanup coed
htcfreek Jan 13, 2022
e4aea0d
fix bug with sticky notes process
htcfreek Jan 13, 2022
cf94933
add window class to tool tip
htcfreek Jan 13, 2022
1a457b1
small change
htcfreek Jan 13, 2022
b65d916
make nativeMethods static class
htcfreek Jan 13, 2022
460c3ab
fix broken uwpApp property of WindowProcess class
htcfreek Jan 13, 2022
690676d
rename method
htcfreek Jan 13, 2022
93efb43
Revert making NativeMethods class static. It contains instance members.
htcfreek Jan 13, 2022
20b49a4
improve loggign
htcfreek Jan 13, 2022
41a02ef
Merge branch 'microsoft:main' into PT_ImproveWwNew
htcfreek Jan 13, 2022
55f06f9
Merge branch 'main' of https://github.com/microsoft/PowerToys into PT…
htcfreek Jan 23, 2022
f2a3fa5
fix merge mistakes
htcfreek Jan 23, 2022
ed76890
fixes
htcfreek Jan 23, 2022
6924c1c
remove obsolete delegate
htcfreek Jan 23, 2022
906267d
Improve SearchController to speed up search (#15561)
htcfreek Jan 23, 2022
d482ad2
add <IsShellProcess> property to <WindowProcess> class
htcfreek Jan 23, 2022
f76c680
reorder code
htcfreek Jan 23, 2022
dbd9a6d
disable debug tool tip
htcfreek Jan 23, 2022
f56e8e0
Update devdocs
htcfreek Jan 23, 2022
20c15e2
Merge branch 'microsoft:main' into PT_ImproveWwNew
htcfreek Jan 24, 2022
80a456c
remove obsolete event handler
htcfreek Jan 24, 2022
61170c7
Merge branch 'PT_ImproveWwNew' of https://github.com/htcfreek/PowerTo…
htcfreek Jan 24, 2022
bbfb538
update var name
htcfreek Jan 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/spell-check/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ HOLDESC
homepage
homljgmgpmcbpjbnjpfijnhipfkiclkd
HOOKPROC
Hostbackdropbrush
hostname
hotkeycontrol
hotkeys
Expand Down
19 changes: 11 additions & 8 deletions doc/devdocs/modules/launcher/plugins/windowwalker.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ The window walker plugin matches the user entered query with the open windows on

![Image of Window Walker plugin](/doc/images/launcher/plugins/windowwalker.png)

### [`OpenWindows.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs)
- The window walker plugin uses the `EnumWindows` function to enumerate all the open windows in the [`OpenWindows.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) class.
### [`OpenWindows.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs)
- The window walker plugin uses the `EnumWindows` function to enumerate all the open windows in the [`OpenWindows.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) class.

### [`SearchController.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs)
- The [`SearchController`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) encapsulates the functions needed to search and find matches.
- It is responsible for updating the search text and performing a fuzzy search on all the open windows.

### [`SearchController.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs)
- The [`SearchController`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) encapsulates the functions needed to search and find matches.
- It is responsible for updating the search text and performing a fuzzy search on all the open windows in an asynchronous manner.
### [`Window.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs)
- The [`Window`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) class represents a specific window and has functions to get the name of the window, the state of the window (whether it is visible or not), and the `SwitchTowindow` function which switches the desktop focus to the selected window. This action is performed when the user clicks on a window walker plugin result.
- The `Window` class holds a static cache with the process information of all windows we know so far and each window instance has a property which holds its process information (name, file, ...). The process data in the cache and the window property are of the type `WindowProcess`.

### [`Window.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs)
- The [`Window`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) class represents a specific window and has functions to get the name of the process, the state of the window (whether it is visible or not), and the `SwitchTowindow` function which switches the desktop focus to the selected window. This action is performed when the user clicks on a window walker plugin result.
### [`WindowProcess.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs)
- The [`WindowProcess`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs) class represents a specific process for a window. It contains static methods to query process information from the system. And it contains instance methods and properties to hold/retrieve the process information we want to know about a window's process.

### Score
The window walker plugin uses [`FuzzyMatching`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/FuzzyMatching.cs) to get the matching indices and calculates the score by creating a 2 dimensional array of the window and the query text.
The window walker plugin uses [`FuzzyMatching`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/FuzzyMatching.cs) to get the matching indices and calculates the score by creating a 2 dimensional array of the window and the query text.
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ public enum DwmNCRenderingPolicy
}

/// <summary>
/// Window attribute
/// DWM window attribute (Windows 7 and earlier: The values between ExcludedFromPeek and Last aren't supported.)
/// </summary>
[Flags]
public enum DwmWindowAttribute
Expand All @@ -266,9 +266,32 @@ public enum DwmWindowAttribute
HasIconicBitmap,
DisallowPeek,
ExcludedFromPeek,
Cloak,
Cloaked,
FreezeRepresentation,
PassiveUpdateMode,
UseHostbackdropbrush,
UseImmersiveDarkMode,
WindowCornerPreference,
BorderColor,
CaptionColor,
TextColor,
VisibleFrameBorderThickness,
Last,
}

/// <summary>
/// Flags for describing the window cloak state (Windows 7 and earlier: This value is not supported.)
/// </summary>
[Flags]
public enum DwmWindowCloakState
{
None = 0,
CloakedApp = 1,
CloakedShell = 2,
CloakedInherited = 4,
}

/// <summary>
/// Flags for accessing the process in trying to get icon for the process
/// </summary>
Expand Down Expand Up @@ -869,7 +892,7 @@ public enum ExtendedWindowStyles : uint
[DllImport("user32.dll", SetLastError = true, BestFitMapping = false)]
public static extern IntPtr GetProp(IntPtr hWnd, string lpString);

[DllImport("kernel32.dll")]
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);

[DllImport("dwmapi.dll", EntryPoint = "#113", CallingConvention = CallingConvention.StdCall)]
Expand All @@ -890,5 +913,37 @@ public enum ExtendedWindowStyles : uint

[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam);

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);

[DllImport("user32.dll")]
public static extern IntPtr GetShellWindow();

/// <summary>
/// Returns the last Win32 Error code thrown by a native method if enabled for this method.
/// </summary>
/// <returns>The error code as int value.</returns>
public static int GetLastWin32Error()
{
return Marshal.GetLastWin32Error();
}

/// <summary>
/// Validate that the handle is not null and close it.
/// </summary>
/// <param name="handle">Handle to close.</param>
/// <returns>Zero if native method fails and nonzero if the native method succeeds.</returns>
public static bool CloseHandleIfNotNull(IntPtr handle)
{
if (handle == IntPtr.Zero)
{
// Return true if there is nothing to close.
return true;
}

return CloseHandle(handle);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ internal class OpenWindows
/// </summary>
private static readonly string _powerLauncherExe = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);

/// <summary>
/// Delegate handler for open windows updates
/// </summary>
public delegate void OpenWindowsUpdateEventHandler(object sender, SearchController.SearchResultUpdateEventArgs e);

/// <summary>
/// List of all the open windows
/// </summary>
Expand Down Expand Up @@ -93,9 +88,14 @@ public bool WindowEnumerationCallBack(IntPtr hwnd, IntPtr lParam)

if (newWindow.IsWindow && newWindow.Visible && newWindow.IsOwner &&
(!newWindow.IsToolWindow || newWindow.IsAppWindow) && !newWindow.TaskListDeleted &&
newWindow.ClassName != "Windows.UI.Core.CoreWindow" && newWindow.ProcessName != _powerLauncherExe)
newWindow.ClassName != "Windows.UI.Core.CoreWindow" && newWindow.ProcessInfo.Name != _powerLauncherExe)
{
windows.Add(newWindow);
// To hide (not add) preloaded uwp app windows that are invisible to the user we check the cloak state in DWM to be "none". (Issue #13637.)
// (If user asking to see these windows again we can add an optional plugin setting in the future.)
if (!newWindow.IsCloaked)
{
windows.Add(newWindow);
}
}

return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;

namespace Microsoft.Plugin.WindowWalker.Components
{
Expand All @@ -24,24 +23,14 @@ internal class SearchController

/// <summary>
/// Open window search results
/// </summary
/// </summary>
private List<SearchResult> searchMatches;

/// <summary>
/// Singleton pattern
/// </summary>
private static SearchController instance;

/// <summary>
/// Delegate handler for open windows updates
/// </summary>
public delegate void SearchResultUpdateEventHandler(object sender, SearchResultUpdateEventArgs e);

/// <summary>
/// Event raised when there is an update to the list of open windows
/// </summary>
public event SearchResultUpdateEventHandler OnSearchResultUpdateEventHandler;

/// <summary>
/// Gets or sets the current search text
/// </summary>
Expand Down Expand Up @@ -95,16 +84,16 @@ private SearchController()
/// <summary>
/// Event handler for when the search text has been updated
/// </summary>
public async Task UpdateSearchText(string searchText)
public void UpdateSearchText(string searchText)
{
SearchText = searchText;
await SyncOpenWindowsWithModelAsync().ConfigureAwait(false);
SyncOpenWindowsWithModel();
}

/// <summary>
/// Syncs the open windows with the OpenWindows Model
/// </summary>
public async Task SyncOpenWindowsWithModelAsync()
public void SyncOpenWindowsWithModel()
{
System.Diagnostics.Debug.Print("Syncing WindowSearch result with OpenWindows Model");

Expand All @@ -116,22 +105,8 @@ public async Task SyncOpenWindowsWithModelAsync()
}
else
{
searchMatches = await FuzzySearchOpenWindowsAsync(snapshotOfOpenWindows).ConfigureAwait(false);
searchMatches = FuzzySearchOpenWindows(snapshotOfOpenWindows);
}

OnSearchResultUpdateEventHandler?.Invoke(this, new SearchResultUpdateEventArgs());
}

/// <summary>
/// Redirecting method for Fuzzy searching
/// </summary>
/// <param name="openWindows">what windows are open</param>
/// <returns>Returns search results</returns>
private Task<List<SearchResult>> FuzzySearchOpenWindowsAsync(List<Window> openWindows)
{
return Task.Run(
() =>
FuzzySearchOpenWindows(openWindows));
}

/// <summary>
Expand All @@ -151,7 +126,7 @@ private List<SearchResult> FuzzySearchOpenWindows(List<Window> openWindows)
foreach (var window in openWindows)
{
var titleMatch = FuzzyMatching.FindBestFuzzyMatch(window.Title, searchString.SearchText);
var processMatch = FuzzyMatching.FindBestFuzzyMatch(window.ProcessName, searchString.SearchText);
var processMatch = FuzzyMatching.FindBestFuzzyMatch(window.ProcessInfo.Name, searchString.SearchText);

if ((titleMatch.Count != 0 || processMatch.Count != 0) &&
window.Title.Length != 0)
Expand Down
Loading