diff --git a/PowerToys.sln b/PowerToys.sln
index 70785dc18669..a1fb9fc4cf66 100644
--- a/PowerToys.sln
+++ b/PowerToys.sln
@@ -6,7 +6,9 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runner", "src\runner\runner.vcxproj", "{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}"
ProjectSection(ProjectDependencies) = postProject
{48804216-2A0E-4168-A6D8-9CD068D14227} = {48804216-2A0E-4168-A6D8-9CD068D14227}
+ {51D3BD1F-07A8-48EB-B2A0-0A249CD4E1A6} = {51D3BD1F-07A8-48EB-B2A0-0A249CD4E1A6}
{74485049-C722-400F-ABE5-86AC52D929B3} = {74485049-C722-400F-ABE5-86AC52D929B3}
+ {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB} = {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}
{A46629C4-1A6C-40FA-A8B6-10E5102BB0BA} = {A46629C4-1A6C-40FA-A8B6-10E5102BB0BA}
{07C389E3-6BC8-41CF-923E-307B1265FA2D} = {07C389E3-6BC8-41CF-923E-307B1265FA2D}
EndProjectSection
@@ -86,6 +88,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUWPUI", "src\mod
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
EndProjectSection
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "windowwalker", "windowwalker", "{8DC78AF7-DC3E-4C57-A8FB-7E347DE74A03}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Window Walker", "src\modules\windowwalker\app\Window Walker\Window Walker.csproj", "{B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowWalker", "src\modules\windowwalker\dll\WindowWalker.vcxproj", "{51D3BD1F-07A8-48EB-B2A0-0A249CD4E1A6}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -160,6 +168,14 @@ Global
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Debug|x64.Build.0 = Debug|x64
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Release|x64.ActiveCfg = Release|x64
{0485F45C-EA7A-4BB5-804B-3E8D14699387}.Release|x64.Build.0 = Release|x64
+ {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}.Debug|x64.ActiveCfg = Debug|x64
+ {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}.Debug|x64.Build.0 = Debug|x64
+ {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}.Release|x64.ActiveCfg = Release|x64
+ {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}.Release|x64.Build.0 = Release|x64
+ {51D3BD1F-07A8-48EB-B2A0-0A249CD4E1A6}.Debug|x64.ActiveCfg = Debug|x64
+ {51D3BD1F-07A8-48EB-B2A0-0A249CD4E1A6}.Debug|x64.Build.0 = Debug|x64
+ {51D3BD1F-07A8-48EB-B2A0-0A249CD4E1A6}.Release|x64.ActiveCfg = Release|x64
+ {51D3BD1F-07A8-48EB-B2A0-0A249CD4E1A6}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -183,6 +199,9 @@ Global
{2151F984-E006-4A9F-92EF-C6DDE3DC8413} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{64A80062-4D8B-4229-8A38-DFA1D7497749} = {BEEAB7F2-FFF6-45AB-9CDB-B04CC0734B88}
{0485F45C-EA7A-4BB5-804B-3E8D14699387} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
+ {8DC78AF7-DC3E-4C57-A8FB-7E347DE74A03} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
+ {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB} = {8DC78AF7-DC3E-4C57-A8FB-7E347DE74A03}
+ {51D3BD1F-07A8-48EB-B2A0-0A249CD4E1A6} = {8DC78AF7-DC3E-4C57-A8FB-7E347DE74A03}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
diff --git a/src/modules/windowwalker/app/Window Walker.sln b/src/modules/windowwalker/app/Window Walker.sln
new file mode 100644
index 000000000000..8dd54bcba847
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26430.6
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Window Walker", "Window Walker\Window Walker.csproj", "{B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}"
+EndProject
+Global
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/modules/windowwalker/app/Window Walker/App.config b/src/modules/windowwalker/app/Window Walker/App.config
new file mode 100644
index 000000000000..de277144ee45
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/modules/windowwalker/app/Window Walker/App.xaml b/src/modules/windowwalker/app/Window Walker/App.xaml
new file mode 100644
index 000000000000..f238d2ecf0bc
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/App.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/modules/windowwalker/app/Window Walker/App.xaml.cs b/src/modules/windowwalker/app/Window Walker/App.xaml.cs
new file mode 100644
index 000000000000..787aa56e74dd
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/App.xaml.cs
@@ -0,0 +1,15 @@
+// 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.Windows;
+
+namespace WindowWalker
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/ApplicationUpdates.cs b/src/modules/windowwalker/app/Window Walker/Components/ApplicationUpdates.cs
new file mode 100644
index 000000000000..cbe0549e29df
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/ApplicationUpdates.cs
@@ -0,0 +1,90 @@
+// 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.Deployment.Application;
+
+namespace WindowWalker.Components
+{
+ public class ApplicationUpdates
+ {
+ private static DateTime _lastUpdateCheck = DateTime.Now;
+ private static bool alreadyCheckingForUpdate = false;
+
+ private static bool updateAvailable = false;
+
+ public static void InstallUpdateSyncWithInfo()
+ {
+ if (alreadyCheckingForUpdate)
+ {
+ return;
+ }
+ else
+ {
+ alreadyCheckingForUpdate = true;
+ }
+
+ var daysSinceLastUpdate = (DateTime.Now - _lastUpdateCheck).Days;
+
+ if (ApplicationDeployment.IsNetworkDeployed)
+ {
+ if (updateAvailable)
+ {
+ UpdateCheckInfo info = null;
+ ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
+
+ try
+ {
+ info = ad.CheckForDetailedUpdate();
+ }
+ catch
+ {
+ return;
+ }
+ finally
+ {
+ _lastUpdateCheck = DateTime.Now;
+ }
+
+ if (info.UpdateAvailable || true)
+ {
+ try
+ {
+ ad.Update();
+ System.Windows.Application.Current.Shutdown();
+ System.Windows.Forms.Application.Restart();
+ }
+ catch
+ {
+ return;
+ }
+ }
+ }
+ else
+ {
+ ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
+
+ ad.CheckForUpdateCompleted += new CheckForUpdateCompletedEventHandler(CheckForUpdateCompleted);
+ ad.CheckForUpdateAsync();
+
+ _lastUpdateCheck = DateTime.Now;
+ }
+ }
+ }
+
+ private static void CheckForUpdateCompleted(object sender, CheckForUpdateCompletedEventArgs e)
+ {
+ if (e.Error != null || !e.UpdateAvailable)
+ {
+ alreadyCheckingForUpdate = false;
+ return;
+ }
+ else
+ {
+ updateAvailable = true;
+ alreadyCheckingForUpdate = false;
+ }
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/Command.cs b/src/modules/windowwalker/app/Window Walker/Components/Command.cs
new file mode 100644
index 000000000000..6d368b95c33c
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/Command.cs
@@ -0,0 +1,22 @@
+// 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/
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Command class representing a single command
+ ///
+ public class Command
+ {
+ ///
+ /// Gets or sets the set of substrings to search for in the search text to figure out if the user wants this command
+ ///
+ public string[] SearchTexts { get; set; }
+
+ ///
+ /// Gets or sets the help tip to get displayed in the cycling display
+ ///
+ public string Tip { get; set; }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/Commands.cs b/src/modules/windowwalker/app/Window Walker/Components/Commands.cs
new file mode 100644
index 000000000000..3c44dee77158
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/Commands.cs
@@ -0,0 +1,104 @@
+// 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.Diagnostics;
+using System.Linq;
+
+namespace WindowWalker.Components
+{
+ ///
+ /// A class to handle the commands entered by the user, different
+ /// form the user being able to search through their windows
+ ///
+ internal class Commands
+ {
+ ///
+ /// Initializes static members of the class.
+ /// Constructor primarily used to enforce the creation of tips
+ /// and populate the enabled commands list
+ ///
+ static Commands()
+ {
+ _enabledCommands = new Dictionary
+ {
+ {
+ "quit",
+ new Command()
+ {
+ SearchTexts = new string[]
+ {
+ ":quit",
+ ":q",
+ },
+ Tip = "type \":quit\" to exit",
+ }
+ },
+ {
+ "launchTerminal",
+ new Command()
+ {
+ SearchTexts = new string[]
+ {
+ ":lterminal",
+ ":lcmd",
+ ":lterm",
+ ":lt",
+ },
+ Tip = "type \":lt\" or \":lcmd\"to launch a new terminal window",
+ }
+ },
+ {
+ "launchVSCode",
+ new Command()
+ {
+ SearchTexts = new string[]
+ {
+ ":lvscode",
+ ":lcode",
+ },
+ Tip = "type \":lvscode\" or \":lcode\"to launch a new instance of VSCode",
+ }
+ },
+ };
+ }
+
+ ///
+ /// Dictionary containing all the enabled commands
+ ///
+ private static readonly Dictionary _enabledCommands;
+
+ ///
+ /// Primary method which executes on the commands that are passed to it
+ ///
+ /// The search text the user has entered
+ public static void ProcessCommand(string commandText)
+ {
+ LivePreview.DeactivateLivePreview();
+
+ if (_enabledCommands["quit"].SearchTexts.Contains(commandText))
+ {
+ System.Windows.Application.Current.Shutdown();
+ }
+ else if (_enabledCommands["launchTerminal"].SearchTexts.Contains(commandText))
+ {
+ Process.Start(new ProcessStartInfo("cmd.exe")
+ { WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) });
+ }
+ else if (_enabledCommands["launchVSCode"].SearchTexts.Contains(commandText))
+ {
+ Process.Start("code");
+ }
+ }
+
+ ///
+ /// Gets the tips for all the enabled commands
+ ///
+ public static IEnumerable GetTips()
+ {
+ return _enabledCommands.Select(x => x.Value.Tip);
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/FuzzyMatching.cs b/src/modules/windowwalker/app/Window Walker/Components/FuzzyMatching.cs
new file mode 100644
index 000000000000..78cf1048757a
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/FuzzyMatching.cs
@@ -0,0 +1,123 @@
+// 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.Collections.Generic;
+using System.Linq;
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Class housing fuzzy matching methods
+ ///
+ public class FuzzyMatching
+ {
+ ///
+ /// Finds the best match (the one with the most
+ /// number of letters adjecent to each other) and
+ /// returns the index location of each of the letters
+ /// of the matches
+ ///
+ /// The text to search inside of
+ /// the text to search for
+ /// returns the index location of each of the letters of the matches
+ public static List FindBestFuzzyMatch(string text, string searchText)
+ {
+ searchText = searchText.ToLower();
+ text = text.ToLower();
+
+ // Create a grid to march matches like
+ // eg.
+ // a b c a d e c f g
+ // a x x
+ // c x x
+ bool[,] matches = new bool[text.Length, searchText.Length];
+ for (int firstIndex = 0; firstIndex < text.Length; firstIndex++)
+ {
+ for (int secondIndex = 0; secondIndex < searchText.Length; secondIndex++)
+ {
+ matches[firstIndex, secondIndex] =
+ searchText[secondIndex] == text[firstIndex] ?
+ true :
+ false;
+ }
+ }
+
+ // use this table to get all the possible matches
+ List> allMatches = GetAllMatchIndexes(matches);
+
+ // return the score that is the max
+ int maxScore = allMatches.Count > 0 ? CalculateScoreForMatches(allMatches[0]) : 0;
+ List bestMatch = allMatches.Count > 0 ? allMatches[0] : new List();
+
+ foreach (var match in allMatches)
+ {
+ int score = CalculateScoreForMatches(match);
+ if (score > maxScore)
+ {
+ bestMatch = match;
+ maxScore = score;
+ }
+ }
+
+ return bestMatch;
+ }
+
+ ///
+ /// Gets all the possible matches to the search string with in the text
+ ///
+ /// a table showing the matches as generated by
+ /// a two dimentional array with the first dimention the text and the second
+ /// one the search string and each cell marked as an intersection between the two
+ /// a list of the possible combinations that match the search text
+ public static List> GetAllMatchIndexes(bool[,] matches)
+ {
+ List> results = new List>();
+
+ for (int secondIndex = 0; secondIndex < matches.GetLength(1); secondIndex++)
+ {
+ for (int firstIndex = 0; firstIndex < matches.GetLength(0); firstIndex++)
+ {
+ if (secondIndex == 0 && matches[firstIndex, secondIndex])
+ {
+ results.Add(new List { firstIndex });
+ }
+ else if (matches[firstIndex, secondIndex])
+ {
+ var tempList = results.Where(x => x.Count == secondIndex && x[x.Count - 1] < firstIndex).Select(x => x.ToList()).ToList();
+
+ foreach (var pathSofar in tempList)
+ {
+ pathSofar.Add(firstIndex);
+ }
+
+ results.AddRange(tempList);
+ }
+ }
+
+ results = results.Where(x => x.Count == secondIndex + 1).ToList();
+ }
+
+ return results.Where(x => x.Count == matches.GetLength(1)).ToList();
+ }
+
+ ///
+ /// Calculates the score for a string
+ ///
+ /// the index of the matches
+ /// an integer representing the score
+ public static int CalculateScoreForMatches(List matches)
+ {
+ var score = 0;
+
+ for (int currentIndex = 1; currentIndex < matches.Count; currentIndex++)
+ {
+ var previousIndex = currentIndex - 1;
+
+ score -= matches[currentIndex] - matches[previousIndex];
+ }
+
+ return score == 0 ? -10000 : score;
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/FuzzyMatchingUnitTest.cs b/src/modules/windowwalker/app/Window Walker/Components/FuzzyMatchingUnitTest.cs
new file mode 100644
index 000000000000..d0664cace97d
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/FuzzyMatchingUnitTest.cs
@@ -0,0 +1,102 @@
+// 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.Collections.Generic;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace WindowWalker.Components
+{
+ [TestClass]
+ public class FuzzyMatchingUnitTest
+ {
+ [TestMethod]
+ public void SimpleMatching()
+ {
+ List result = FuzzyMatching.FindBestFuzzyMatch("watsapp hellow", "hello");
+ List expected = new List() { 8, 9, 10, 11, 12 };
+
+ Assert.IsTrue(IsEqual(expected, result));
+ }
+
+ [TestMethod]
+ public void NoResult()
+ {
+ List result = FuzzyMatching.FindBestFuzzyMatch("what is going on?", "whatsx goin on?");
+ List expected = new List();
+
+ Assert.IsTrue(IsEqual(expected, result));
+ }
+
+ [TestMethod]
+ public void ZeroLengthSearchString()
+ {
+ List result = FuzzyMatching.FindBestFuzzyMatch("whatsapp hellow", string.Empty);
+ List expected = new List();
+
+ Assert.IsTrue(IsEqual(expected, result));
+ }
+
+ [TestMethod]
+ public void ZeroLengthText()
+ {
+ List result = FuzzyMatching.FindBestFuzzyMatch(string.Empty, "hello");
+ List expected = new List();
+
+ Assert.IsTrue(IsEqual(expected, result));
+ }
+
+ [TestMethod]
+ public void ZeroLengthInputs()
+ {
+ List result = FuzzyMatching.FindBestFuzzyMatch(string.Empty, string.Empty);
+ List expected = new List();
+
+ Assert.IsTrue(IsEqual(expected, result));
+ }
+
+ [TestMethod]
+ public void BestMatch()
+ {
+ List result = FuzzyMatching.FindBestFuzzyMatch("aaacaab", "ab");
+ List expected = new List() { 5, 6 };
+
+ Assert.IsTrue(IsEqual(expected, result));
+ }
+
+ [TestMethod]
+ public void RealWorldProgramManager()
+ {
+ List result = FuzzyMatching.FindBestFuzzyMatch("Program Manager", "pr");
+ List expected = new List() { 0, 1 };
+
+ Assert.IsTrue(IsEqual(expected, result));
+ }
+
+ [TestMethod]
+ public void BestScoreTest()
+ {
+ int score = FuzzyMatching.CalculateScoreForMatches(new List() { 1, 2, 3, 4 });
+ Assert.IsTrue(score == -3);
+ }
+
+ private static bool IsEqual(List list1, List list2)
+ {
+ if (list1.Count != list2.Count)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < list1.Count; i++)
+ {
+ if (list1[i] != list2[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/InteropAndHelpers.cs b/src/modules/windowwalker/app/Window Walker/Components/InteropAndHelpers.cs
new file mode 100644
index 000000000000..3ebe543fb1d9
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/InteropAndHelpers.cs
@@ -0,0 +1,652 @@
+// 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.Runtime.InteropServices;
+using System.Text;
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Interop calls with helper layers
+ ///
+ internal class InteropAndHelpers
+ {
+ public delegate bool CallBackPtr(IntPtr hwnd, IntPtr lParam);
+
+ ///
+ /// Some flags for interop calls to SetWindowPosition
+ ///
+ [Flags]
+ public enum SetWindowPosFlags : uint
+ {
+ ///
+ /// If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request.
+ ///
+ SWP_ASYNCWINDOWPOS = 0x4000,
+
+ ///
+ /// Prevents generation of the WM_SYNCPAINT message.
+ ///
+ SWP_DEFERERASE = 0x2000,
+
+ ///
+ /// Draws a frame (defined in the window's class description) around the window.
+ ///
+ SWP_DRAWFRAME = 0x0020,
+
+ ///
+ /// Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window's size is being changed.
+ ///
+ SWP_FRAMECHANGED = 0x0020,
+
+ ///
+ /// Hides the window.
+ ///
+ SWP_HIDEWINDOW = 0x0080,
+
+ ///
+ /// Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter).
+ ///
+ SWP_NOACTIVATE = 0x0010,
+
+ ///
+ /// Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the window is sized or repositioned.
+ ///
+ SWP_NOCOPYBITS = 0x0100,
+
+ ///
+ /// Retains the current position (ignores X and Y parameters).
+ ///
+ SWP_NOMOVE = 0x0002,
+
+ ///
+ /// Does not change the owner window's position in the Z order.
+ ///
+ SWP_NOOWNERZORDER = 0x0200,
+
+ ///
+ /// Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.
+ ///
+ SWP_NOREDRAW = 0x0008,
+
+ ///
+ /// Same as the SWP_NOOWNERZORDER flag.
+ ///
+ SWP_NOREPOSITION = 0x0200,
+
+ ///
+ /// Prevents the window from receiving the WM_WINDOWPOSCHANGING message.
+ ///
+ SWP_NOSENDCHANGING = 0x0400,
+
+ ///
+ /// Retains the current size (ignores the cx and cy parameters).
+ ///
+ SWP_NOSIZE = 0x0001,
+
+ ///
+ /// Retains the current Z order (ignores the hWndInsertAfter parameter).
+ ///
+ SWP_NOZORDER = 0x0004,
+
+ ///
+ /// Displays the window.
+ ///
+ SWP_SHOWWINDOW = 0x0040,
+ }
+
+ ///
+ /// Flags for setting hotkeys
+ ///
+ [Flags]
+ public enum Modifiers
+ {
+ NoMod = 0x0000,
+ Alt = 0x0001,
+ Ctrl = 0x0002,
+ Shift = 0x0004,
+ Win = 0x0008,
+ }
+
+ ///
+ /// Options for DwmpActivateLivePreview
+ ///
+ public enum LivePreviewTrigger
+ {
+ ///
+ /// Show Desktop button
+ ///
+ ShowDesktop = 1,
+
+ ///
+ /// WIN+SPACE hotkey
+ ///
+ WinSpace,
+
+ ///
+ /// Hover-over Superbar thumbnails
+ ///
+ Superbar,
+
+ ///
+ /// Alt-Tab
+ ///
+ AltTab,
+
+ ///
+ /// Press and hold on Superbar thumbnails
+ ///
+ SuperbarTouch,
+
+ ///
+ /// Press and hold on Show desktop
+ ///
+ ShowDesktopTouch,
+ }
+
+ ///
+ /// Show Window Enums
+ ///
+ public enum ShowWindowCommands
+ {
+ ///
+ /// Hides the window and activates another window.
+ ///
+ Hide = 0,
+
+ ///
+ /// Activates and displays a window. If the window is minimized or
+ /// maximized, the system restores it to its original size and position.
+ /// An application should specify this flag when displaying the window
+ /// for the first time.
+ ///
+ Normal = 1,
+
+ ///
+ /// Activates the window and displays it as a minimized window.
+ ///
+ ShowMinimized = 2,
+
+ ///
+ /// Maximizes the specified window.
+ ///
+ Maximize = 3, // is this the right value?
+
+ ///
+ /// Activates the window and displays it as a maximized window.
+ ///
+ ShowMaximized = 3,
+
+ ///
+ /// Displays a window in its most recent size and position. This value
+ /// is similar to , except
+ /// the window is not activated.
+ ///
+ ShowNoActivate = 4,
+
+ ///
+ /// Activates the window and displays it in its current size and position.
+ ///
+ Show = 5,
+
+ ///
+ /// Minimizes the specified window and activates the next top-level
+ /// window in the Z order.
+ ///
+ Minimize = 6,
+
+ ///
+ /// Displays the window as a minimized window. This value is similar to
+ /// , except the
+ /// window is not activated.
+ ///
+ ShowMinNoActive = 7,
+
+ ///
+ /// Displays the window in its current size and position. This value is
+ /// similar to , except the
+ /// window is not activated.
+ ///
+ ShowNA = 8,
+
+ ///
+ /// Activates and displays the window. If the window is minimized or
+ /// maximized, the system restores it to its original size and position.
+ /// An application should specify this flag when restoring a minimized window.
+ ///
+ Restore = 9,
+
+ ///
+ /// Sets the show state based on the SW_* value specified in the
+ /// STARTUPINFO structure passed to the CreateProcess function by the
+ /// program that started the application.
+ ///
+ ShowDefault = 10,
+
+ ///
+ /// Windows 2000/XP: Minimizes a window, even if the thread
+ /// that owns the window is not responding. This flag should only be
+ /// used when minimizing windows from a different thread.
+ ///
+ ForceMinimize = 11,
+ }
+
+ ///
+ /// The rendering policy to use for set window attribute
+ ///
+ [Flags]
+ public enum DwmNCRenderingPolicy
+ {
+ UseWindowStyle,
+ Disabled,
+ Enabled,
+ Last,
+ }
+
+ ///
+ /// Window attribute
+ ///
+ [Flags]
+ public enum DwmWindowAttribute
+ {
+ NCRenderingEnabled = 1,
+ NCRenderingPolicy,
+ TransitionsForceDisabled,
+ AllowNCPaint,
+ CaptionButtonBounds,
+ NonClientRtlLayout,
+ ForceIconicRepresentation,
+ Flip3DPolicy,
+ ExtendedFrameBounds,
+ HasIconicBitmap,
+ DisallowPeek,
+ ExcludedFromPeek,
+ Last,
+ }
+
+ ///
+ /// Flags for accessing the process in trying to get icon for the process
+ ///
+ [Flags]
+ public enum ProcessAccessFlags
+ {
+ ///
+ /// Required to create a thread.
+ ///
+ CreateThread = 0x0002,
+
+ ///
+ ///
+ ///
+ SetSessionId = 0x0004,
+
+ ///
+ /// Required to perform an operation on the address space of a process
+ ///
+ VmOperation = 0x0008,
+
+ ///
+ /// Required to read memory in a process using ReadProcessMemory.
+ ///
+ VmRead = 0x0010,
+
+ ///
+ /// Required to write to memory in a process using WriteProcessMemory.
+ ///
+ VmWrite = 0x0020,
+
+ ///
+ /// Required to duplicate a handle using DuplicateHandle.
+ ///
+ DupHandle = 0x0040,
+
+ ///
+ /// Required to create a process.
+ ///
+ CreateProcess = 0x0080,
+
+ ///
+ /// Required to set memory limits using SetProcessWorkingSetSize.
+ ///
+ SetQuota = 0x0100,
+
+ ///
+ /// Required to set certain information about a process, such as its priority class (see SetPriorityClass).
+ ///
+ SetInformation = 0x0200,
+
+ ///
+ /// Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken).
+ ///
+ QueryInformation = 0x0400,
+
+ ///
+ /// Required to suspend or resume a process.
+ ///
+ SuspendResume = 0x0800,
+
+ ///
+ /// Required to retrieve certain information about a process (see GetExitCodeProcess, GetPriorityClass, IsProcessInJob, QueryFullProcessImageName).
+ /// A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION.
+ ///
+ QueryLimitedInformation = 0x1000,
+
+ ///
+ /// Required to wait for the process to terminate using the wait functions.
+ ///
+ Synchronize = 0x100000,
+
+ ///
+ /// Required to delete the object.
+ ///
+ Delete = 0x00010000,
+
+ ///
+ /// Required to read information in the security descriptor for the object, not including the information in the SACL.
+ /// To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. For more information, see SACL Access Right.
+ ///
+ ReadControl = 0x00020000,
+
+ ///
+ /// Required to modify the DACL in the security descriptor for the object.
+ ///
+ WriteDac = 0x00040000,
+
+ ///
+ /// Required to change the owner in the security descriptor for the object.
+ ///
+ WriteOwner = 0x00080000,
+
+ StandardRightsRequired = 0x000F0000,
+
+ ///
+ /// All possible access rights for a process object.
+ ///
+ AllAccess = StandardRightsRequired | Synchronize | 0xFFFF,
+ }
+
+ ///
+ /// Contains information about the placement of a window on the screen.
+ ///
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct WINDOWPLACEMENT
+ {
+ ///
+ /// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT).
+ ///
+ /// GetWindowPlacement and SetWindowPlacement fail if this member is not set correctly.
+ ///
+ ///
+ public int Length;
+
+ ///
+ /// Specifies flags that control the position of the minimized window and the method by which the window is restored.
+ ///
+ public int Flags;
+
+ ///
+ /// The current show state of the window.
+ ///
+ public ShowWindowCommands ShowCmd;
+
+ ///
+ /// The coordinates of the window's upper-left corner when the window is minimized.
+ ///
+ public POINT MinPosition;
+
+ ///
+ /// The coordinates of the window's upper-left corner when the window is maximized.
+ ///
+ public POINT MaxPosition;
+
+ ///
+ /// The window's coordinates when the window is in the restored position.
+ ///
+ public RECT NormalPosition;
+
+ ///
+ /// Gets the default (empty) value.
+ ///
+ public static WINDOWPLACEMENT Default
+ {
+ get
+ {
+ WINDOWPLACEMENT result = default;
+ result.Length = Marshal.SizeOf(result);
+ return result;
+ }
+ }
+ }
+
+ ///
+ /// Required pointless variables that we don't use in making a windows show
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RECT
+ {
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+
+ public RECT(int left, int top, int right, int bottom)
+ {
+ Left = left;
+ Top = top;
+ Right = right;
+ Bottom = bottom;
+ }
+
+ public RECT(System.Drawing.Rectangle r)
+ : this(r.Left, r.Top, r.Right, r.Bottom)
+ {
+ }
+
+ public int X
+ {
+ get
+ {
+ return Left;
+ }
+
+ set
+ {
+ Right -= Left - value;
+ Left = value;
+ }
+ }
+
+ public int Y
+ {
+ get
+ {
+ return Top;
+ }
+
+ set
+ {
+ Bottom -= Top - value;
+ Top = value;
+ }
+ }
+
+ public int Height
+ {
+ get { return Bottom - Top; }
+ set { Bottom = value + Top; }
+ }
+
+ public int Width
+ {
+ get { return Right - Left; }
+ set { Right = value + Left; }
+ }
+
+ public System.Drawing.Point Location
+ {
+ get
+ {
+ return new System.Drawing.Point(Left, Top);
+ }
+
+ set
+ {
+ X = value.X;
+ Y = value.Y;
+ }
+ }
+
+ public System.Drawing.Size Size
+ {
+ get
+ {
+ return new System.Drawing.Size(Width, Height);
+ }
+
+ set
+ {
+ Width = value.Width;
+ Height = value.Height;
+ }
+ }
+
+ public static implicit operator System.Drawing.Rectangle(RECT r)
+ {
+ return new System.Drawing.Rectangle(r.Left, r.Top, r.Width, r.Height);
+ }
+
+ public static implicit operator RECT(System.Drawing.Rectangle r)
+ {
+ return new RECT(r);
+ }
+
+ public static bool operator ==(RECT r1, RECT r2)
+ {
+ return r1.Equals(r2);
+ }
+
+ public static bool operator !=(RECT r1, RECT r2)
+ {
+ return !r1.Equals(r2);
+ }
+
+ public bool Equals(RECT r)
+ {
+ return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is RECT)
+ {
+ return Equals((RECT)obj);
+ }
+ else if (obj is System.Drawing.Rectangle)
+ {
+ return Equals(new RECT((System.Drawing.Rectangle)obj));
+ }
+
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return ((System.Drawing.Rectangle)this).GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top, Right, Bottom);
+ }
+ }
+
+ ///
+ /// Same as the RECT struct above
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct POINT
+ {
+ public int X;
+ public int Y;
+
+ public POINT(int x, int y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public POINT(System.Drawing.Point pt)
+ : this(pt.X, pt.Y)
+ {
+ }
+
+ public static implicit operator System.Drawing.Point(POINT p)
+ {
+ return new System.Drawing.Point(p.X, p.Y);
+ }
+
+ public static implicit operator POINT(System.Drawing.Point p)
+ {
+ return new POINT(p.X, p.Y);
+ }
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
+ public static extern int EnumWindows(CallBackPtr callPtr, int lPar);
+
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
+ public static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
+
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
+ public static extern int GetWindowTextLength(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ public static extern bool IsWindowVisible(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags uFlags);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool SetForegroundWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
+
+ [DllImport("user32.dll")]
+ public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
+
+ [DllImport("user32.dll")]
+ public static extern bool FlashWindow(IntPtr hwnd, bool bInvert);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
+
+ [DllImport("psapi.dll")]
+ public static extern uint GetProcessImageFileName(IntPtr hProcess, [Out] StringBuilder lpImageFileName, [In] [MarshalAs(UnmanagedType.U4)] int nSize);
+
+ [DllImport("kernel32.dll")]
+ public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
+
+ [DllImport("dwmapi.dll", EntryPoint = "#113", CallingConvention = CallingConvention.StdCall)]
+ public static extern int DwmpActivateLivePreview([MarshalAs(UnmanagedType.Bool)]bool fActivate, IntPtr hWndExclude, IntPtr hWndInsertBefore, LivePreviewTrigger lpt, IntPtr prcFinalRect);
+
+ [DllImport("dwmapi.dll", PreserveSig = false)]
+ public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
+
+ [DllImport("user32.dll")]
+ public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/LivePreview.cs b/src/modules/windowwalker/app/Window Walker/Components/LivePreview.cs
new file mode 100644
index 000000000000..08f9feefc6f2
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/LivePreview.cs
@@ -0,0 +1,57 @@
+// 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;
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Class containg methods to control the live preview
+ ///
+ internal class LivePreview
+ {
+ ///
+ /// Makes sure that a window is excluded from the live preview
+ ///
+ /// handle to the window to exclude
+ public static void SetWindowExlusionFromLivePreview(IntPtr hwnd)
+ {
+ int renderPolicy = (int)InteropAndHelpers.DwmNCRenderingPolicy.Enabled;
+
+ InteropAndHelpers.DwmSetWindowAttribute(
+ hwnd,
+ 12,
+ ref renderPolicy,
+ sizeof(int));
+ }
+
+ ///
+ /// Activates the live preview
+ ///
+ /// the window to show by making all other windows transparent
+ /// the window which should not be transparent but is not the target window
+ public static void ActivateLivePreview(IntPtr targetWindow, IntPtr windowToSpare)
+ {
+ InteropAndHelpers.DwmpActivateLivePreview(
+ true,
+ targetWindow,
+ windowToSpare,
+ InteropAndHelpers.LivePreviewTrigger.Superbar,
+ IntPtr.Zero);
+ }
+
+ ///
+ /// Deactivates the live preview
+ ///
+ public static void DeactivateLivePreview()
+ {
+ InteropAndHelpers.DwmpActivateLivePreview(
+ false,
+ IntPtr.Zero,
+ IntPtr.Zero,
+ InteropAndHelpers.LivePreviewTrigger.AltTab,
+ IntPtr.Zero);
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/OpenWindows.cs b/src/modules/windowwalker/app/Window Walker/Components/OpenWindows.cs
new file mode 100644
index 000000000000..968089401b83
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/OpenWindows.cs
@@ -0,0 +1,118 @@
+// 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.Linq;
+using System.Threading.Tasks;
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Class that represents the state of the desktops windows
+ ///
+ internal class OpenWindows
+ {
+ ///
+ /// Delegate handler for open windows updates
+ ///
+ public delegate void OpenWindowsUpdateHandler(object sender, SearchController.SearchResultUpdateEventArgs e);
+
+ ///
+ /// Event raised when there is an update to the list of open windows
+ ///
+ public event OpenWindowsUpdateHandler OnOpenWindowsUpdate;
+
+ ///
+ /// 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
+ ///
+ public List Windows
+ {
+ get { return 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
+ ///
+ public 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
+ ///
+ public void UpdateOpenWindowsList()
+ {
+ windows.Clear();
+
+ new Task(() =>
+ {
+ InteropAndHelpers.CallBackPtr callbackptr = new InteropAndHelpers.CallBackPtr(WindowEnumerationCallBack);
+ InteropAndHelpers.EnumWindows(callbackptr, 0);
+ }).Start();
+ }
+
+ ///
+ /// 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 contiue enumeration
+ public bool WindowEnumerationCallBack(IntPtr hwnd, IntPtr lParam)
+ {
+ Window newWindow = new Window(hwnd);
+
+ if (windows.Select(x => x.Title).Contains(newWindow.Title))
+ {
+ if (newWindow.ProcessName.ToLower().Equals("applicationframehost.exe"))
+ {
+ windows.Remove(windows.Where(x => x.Title == newWindow.Title).First());
+ }
+
+ return true;
+ }
+
+ if ((newWindow.Visible && !newWindow.ProcessName.ToLower().Equals("iexplore.exe")) ||
+ (newWindow.ProcessName.ToLower().Equals("iexplore.exe") && newWindow.ClassName == "TabThumbnailWindow"))
+ {
+ windows.Add(newWindow);
+
+ OnOpenWindowsUpdate?.Invoke(this, new SearchController.SearchResultUpdateEventArgs());
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/Point.cs b/src/modules/windowwalker/app/Window Walker/Components/Point.cs
new file mode 100644
index 000000000000..c91de3f5537e
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/Point.cs
@@ -0,0 +1,16 @@
+// 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/
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Custom point class to ease storing a point
+ ///
+ public class Point
+ {
+ public double X { get; set; }
+
+ public double Y { get; set; }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/SearchController.cs b/src/modules/windowwalker/app/Window Walker/Components/SearchController.cs
new file mode 100644
index 000000000000..1764071cea2f
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/SearchController.cs
@@ -0,0 +1,192 @@
+// 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.Linq;
+using System.Threading.Tasks;
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Responsible for searching and finding matches for the strings provided.
+ /// Essentially the UI independent model of the application
+ ///
+ internal class SearchController
+ {
+ ///
+ /// the current search text
+ ///
+ private string searchText;
+
+ ///
+ /// Open window search results
+ /// searchMatches;
+
+ ///
+ /// Singleton pattern
+ ///
+ private static SearchController instance;
+
+ ///
+ /// Delegate handler for open windows updates
+ ///
+ public delegate void SearchResultUpdateHandler(object sender, SearchResultUpdateEventArgs e);
+
+ ///
+ /// Event raised when there is an update to the list of open windows
+ ///
+ public event SearchResultUpdateHandler OnSearchResultUpdate;
+
+ ///
+ /// Gets or sets the current search text
+ ///
+ public string SearchText
+ {
+ get
+ {
+ return searchText;
+ }
+
+ set
+ {
+ searchText = value.ToLower().Trim();
+ SearchTextUpdated();
+ }
+ }
+
+ ///
+ /// Gets the open window search results
+ ///
+ public List SearchMatches
+ {
+ get { return new List(searchMatches).OrderByDescending(x => x.Score).ToList(); }
+ }
+
+ ///
+ /// Gets singleton Pattern
+ ///
+ public static SearchController Instance
+ {
+ get
+ {
+ if (instance == null)
+ {
+ instance = new SearchController();
+ }
+
+ return instance;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Initializes the search controller object
+ ///
+ private SearchController()
+ {
+ searchText = string.Empty;
+ OpenWindows.Instance.OnOpenWindowsUpdate += OpenWindowsUpdateHandler;
+ }
+
+ ///
+ /// Event handler for when the search text has been updated
+ ///
+ public void SearchTextUpdated()
+ {
+ SyncOpenWindowsWithModelAsync();
+ }
+
+ ///
+ /// Event handler called when the OpenWindows list changes
+ ///
+ ///
+ ///
+ public void OpenWindowsUpdateHandler(object sender, SearchResultUpdateEventArgs e)
+ {
+ SyncOpenWindowsWithModelAsync();
+ }
+
+ ///
+ /// Syncs the open windows with the OpenWindows Model
+ ///
+ private async void SyncOpenWindowsWithModelAsync()
+ {
+ System.Diagnostics.Debug.Print("Syncing WindowSearch result with OpenWindows Model");
+
+ List snapshotOfOpenWindows = OpenWindows.Instance.Windows;
+
+ if (SearchText == string.Empty)
+ {
+ searchMatches = new List();
+ }
+ else
+ {
+ searchMatches = await FuzzySearchOpenWindowsAsync(snapshotOfOpenWindows);
+ }
+
+ OnSearchResultUpdate?.Invoke(this, new SearchResultUpdateEventArgs());
+ }
+
+ ///
+ /// Redirecting method for Fuzzy searching
+ ///
+ ///
+ /// Returns search results
+ private Task> FuzzySearchOpenWindowsAsync(List openWindows)
+ {
+ return Task.Run(
+ () =>
+ FuzzySearchOpenWindows(openWindows));
+ }
+
+ ///
+ /// Search method that matches the title of windows with the user search text
+ ///
+ ///
+ /// Returns search results
+ private List FuzzySearchOpenWindows(List openWindows)
+ {
+ List result = new List();
+ List searchStrings = new List();
+
+ List shortcuts = SettingsManager.Instance.GetShortcut(SearchText);
+
+ foreach (var shortcut in shortcuts)
+ {
+ searchStrings.Add(new SearchString(shortcut, SearchResult.SearchType.Shortcut));
+ }
+
+ searchStrings.Add(new SearchString(searchText, SearchResult.SearchType.Fuzzy));
+
+ foreach (var searchString in searchStrings)
+ {
+ foreach (var window in openWindows)
+ {
+ var titleMatch = FuzzyMatching.FindBestFuzzyMatch(window.Title, searchString.SearchText);
+ var processMatch = FuzzyMatching.FindBestFuzzyMatch(window.ProcessName, searchString.SearchText);
+
+ if ((titleMatch.Count != 0 || processMatch.Count != 0) &&
+ window.Title.Length != 0)
+ {
+ var temp = new SearchResult(window, titleMatch, processMatch, searchString.SearchType);
+ result.Add(temp);
+ }
+ }
+ }
+
+ System.Diagnostics.Debug.Print("Found " + result.Count + " windows that match the search text");
+
+ return result;
+ }
+
+ ///
+ /// Event args for a window list update event
+ ///
+ public class SearchResultUpdateEventArgs : EventArgs
+ {
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/SearchResult.cs b/src/modules/windowwalker/app/Window Walker/Components/SearchResult.cs
new file mode 100644
index 000000000000..2dbeb4db58e6
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/SearchResult.cs
@@ -0,0 +1,135 @@
+// 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.Collections.Generic;
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Contains search result windows with each window including the reason why the result was included
+ ///
+ public class SearchResult
+ {
+ ///
+ /// Gets the actual window reference for the search result
+ ///
+ public Window Result
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets the list of indexes of the matching characters for the search in the title window
+ ///
+ public List SearchMatchesInTitle
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets the list of indexes of the matching characters for the search in the
+ /// name of the process
+ ///
+ public List SearchMatchesInProcessName
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets the type of match (shortcut, fuzzy or nothing)
+ ///
+ public SearchType SearchResultMatchType
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets a score indicating how well this matches what we are looking for
+ ///
+ public int Score
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets the source of where the best score was found
+ ///
+ public TextType BestScoreSource
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Constructor
+ ///
+ public SearchResult(Window window, List matchesInTitle, List matchesInProcessName, SearchType matchType)
+ {
+ Result = window;
+ SearchMatchesInTitle = matchesInTitle;
+ SearchMatchesInProcessName = matchesInProcessName;
+ SearchResultMatchType = matchType;
+ CalculateScore();
+ }
+
+ ///
+ /// Calculates the score for how closely this window matches the search string
+ ///
+ ///
+ /// Higher Score is better
+ ///
+ private void CalculateScore()
+ {
+ if (FuzzyMatching.CalculateScoreForMatches(SearchMatchesInProcessName) >
+ FuzzyMatching.CalculateScoreForMatches(SearchMatchesInTitle))
+ {
+ Score = FuzzyMatching.CalculateScoreForMatches(SearchMatchesInProcessName);
+ BestScoreSource = TextType.ProcessName;
+ }
+ else
+ {
+ Score = FuzzyMatching.CalculateScoreForMatches(SearchMatchesInTitle);
+ BestScoreSource = TextType.WindowTitle;
+ }
+ }
+
+ ///
+ /// The type of text that a string represents
+ ///
+ public enum TextType
+ {
+ ProcessName,
+ WindowTitle,
+ }
+
+ ///
+ /// The type of search
+ ///
+ public enum SearchType
+ {
+ ///
+ /// the search string is empty, which means all open windows are
+ /// going to be returned
+ ///
+ Empty,
+
+ ///
+ /// Regular fuzzy match search
+ ///
+ Fuzzy,
+
+ ///
+ /// The user has entered text that has been matched to a shortcut
+ /// and the shortcut is now being searched
+ ///
+ Shortcut,
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/SearchString.cs b/src/modules/windowwalker/app/Window Walker/Components/SearchString.cs
new file mode 100644
index 000000000000..125bdc97da1a
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/SearchString.cs
@@ -0,0 +1,45 @@
+// 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/
+
+namespace WindowWalker.Components
+{
+ ///
+ /// A class to represent a search string
+ ///
+ /// Class was added inorder to be able to attach various context data to
+ /// a search string
+ internal class SearchString
+ {
+ ///
+ /// Gets where is the search string coming from (is it a shortcut
+ /// or direct string, etc...)
+ ///
+ public SearchResult.SearchType SearchType
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets the actual text we are searching for
+ ///
+ public string SearchText
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Constructor
+ ///
+ ///
+ ///
+ public SearchString(string searchText, SearchResult.SearchType searchType)
+ {
+ SearchText = searchText;
+ SearchType = searchType;
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/Settings.cs b/src/modules/windowwalker/app/Window Walker/Components/Settings.cs
new file mode 100644
index 000000000000..ff4f24272c19
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/Settings.cs
@@ -0,0 +1,72 @@
+// 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.Collections.Generic;
+using System.Web.Script.Serialization;
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Class that represents all the settings and
+ /// can be serialized into JSON for easy saving
+ ///
+ internal class Settings
+ {
+ ///
+ /// Gets or sets the version of the settings file
+ ///
+ public string Version { get; set; }
+
+ ///
+ /// Gets or sets a list of all the shortcuts
+ ///
+ public Dictionary> Shortcuts { get; set; }
+
+ ///
+ /// Gets or sets a list of saved window locations catagorized by number of screens
+ ///
+ public Dictionary WindowLocations { get; set; }
+
+ ///
+ /// Gets or sets the location of the search windows (the top left point)
+ ///
+ [ScriptIgnore]
+ public Point WindowLocation
+ {
+ get
+ {
+ if (WindowLocations.ContainsKey(System.Windows.Forms.Screen.AllScreens.Length.ToString()))
+ {
+ return WindowLocations[System.Windows.Forms.Screen.AllScreens.Length.ToString()];
+ }
+ else
+ {
+ return new Point() { X = 0, Y = 0 };
+ }
+ }
+
+ set
+ {
+ if (WindowLocations == null)
+ {
+ WindowLocations = new Dictionary();
+ }
+
+ WindowLocations[System.Windows.Forms.Screen.AllScreens.Length.ToString()] = value;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Constructer to initialize some default values
+ ///
+ public Settings()
+ {
+ Version = string.Empty;
+ Shortcuts = new Dictionary>();
+ WindowLocation = new Point() { X = 0, Y = 0 };
+ WindowLocations = new Dictionary();
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/SettingsManager.cs b/src/modules/windowwalker/app/Window Walker/Components/SettingsManager.cs
new file mode 100644
index 000000000000..3f88d5e31b68
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/SettingsManager.cs
@@ -0,0 +1,153 @@
+// 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.Collections.Generic;
+using System.IO;
+using System.Web.Script.Serialization;
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Class for managing shortcuts
+ /// Example: When you type "i" we actually search for "internet"
+ ///
+ internal class SettingsManager
+ {
+ ///
+ /// The path to the shortcut file
+ ///
+ private static readonly string _shortcutsFile = Path.GetTempPath() + "WindowWalkerShortcuts.ini";
+
+ ///
+ /// Reference to a serializer for saving the settings
+ ///
+ private static readonly JavaScriptSerializer _serializer = new JavaScriptSerializer();
+
+ ///
+ /// An instance of the settings class representing the current settings
+ ///
+ private static readonly Settings _settingsInstance = new Settings();
+
+ ///
+ /// Instance of the manager itself
+ ///
+ private static SettingsManager _instance;
+
+ ///
+ /// Gets implements Singlton pattern
+ ///
+ public static SettingsManager Instance
+ {
+ get
+ {
+ if (_instance == null)
+ {
+ _instance = new SettingsManager();
+ }
+
+ return _instance;
+ }
+ }
+
+ ///
+ /// Initializes static members of the class.
+ /// Static constructor
+ ///
+ /// Not sure why we have this AND a singlton pattern
+ static SettingsManager()
+ {
+ try
+ {
+ if (File.Exists(_shortcutsFile))
+ {
+ using (StreamReader reader = new StreamReader(_shortcutsFile))
+ {
+ string jsonString = reader.ReadToEnd();
+ _settingsInstance = (Settings)_serializer.Deserialize(jsonString, typeof(Settings));
+ }
+ }
+ }
+ catch
+ {
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Contructor that does nothing?
+ ///
+ private SettingsManager()
+ {
+ return;
+ }
+
+ ///
+ /// Adds a shortcut to the settings
+ ///
+ /// what the user types
+ /// what the resulting search string is going to be
+ /// Returns true if it succeeds, false otherwise
+ /// Proably not usefull to actually do the true/false return since
+ /// we can now have multiple shortcuts
+ public bool AddShortcut(string before, string after)
+ {
+ if (!_settingsInstance.Shortcuts.ContainsKey(before))
+ {
+ _settingsInstance.Shortcuts.Add(before, new List());
+ }
+
+ _settingsInstance.Shortcuts[before].Add(after);
+
+ // Write the updated shortcuts list to a file
+ SaveSettings();
+
+ return true;
+ }
+
+ ///
+ /// Removes a shortcut
+ ///
+ /// the input shortcut string
+ /// true if it succeeds, false otherwise
+ /// Probably has a bug since you can now a single input
+ /// mapping to multiple outputs
+ public bool RemoveShortcut(string input)
+ {
+ if (!_settingsInstance.Shortcuts.ContainsKey(input))
+ {
+ return false;
+ }
+
+ _settingsInstance.Shortcuts.Remove(input);
+
+ // Write the updated shortcuts list to a file
+ SaveSettings();
+
+ return true;
+ }
+
+ ///
+ /// Retrieves a shortcut and returns all possible mappings
+ ///
+ /// the input string for the shortcuts
+ /// A list of all the shortcut strings that result from the user input
+ public List GetShortcut(string input)
+ {
+ return _settingsInstance.Shortcuts.ContainsKey(input) ? _settingsInstance.Shortcuts[input] : new List();
+ }
+
+ ///
+ /// Writes the current shortcuts to the shortcuts file.
+ /// Note: We are writing the file even if there are no shortcuts. This handles
+ /// the case where the user deletes their last shortcut.
+ ///
+ public void SaveSettings()
+ {
+ using (StreamWriter writer = new StreamWriter(_shortcutsFile, false))
+ {
+ writer.Write(_serializer.Serialize(_settingsInstance));
+ }
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/Window.cs b/src/modules/windowwalker/app/Window Walker/Components/Window.cs
new file mode 100644
index 000000000000..ea7f73c53ed8
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/Window.cs
@@ -0,0 +1,265 @@
+// 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.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Interop;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace WindowWalker.Components
+{
+ ///
+ /// Represents a specific open window
+ ///
+ public class Window
+ {
+ ///
+ /// Maximum size of a file name
+ ///
+ private const int MaximumFileNameLength = 1000;
+
+ ///
+ /// The list of owners of a window so that we don't have to
+ /// constantly query for the process owning a specific window
+ ///
+ private static readonly Dictionary _handlesToProcessCache = new Dictionary();
+
+ ///
+ /// The list of icons from process so that we don't have to keep
+ /// loading them from disk
+ ///
+ private static readonly Dictionary _processIdsToIconsCache = new Dictionary();
+
+ ///
+ /// The handle to the window
+ ///
+ private readonly IntPtr hwnd;
+
+ ///
+ /// Gets the title of the window (the string displayed at the top of the window)
+ ///
+ public string Title
+ {
+ get
+ {
+ int sizeOfTitle = InteropAndHelpers.GetWindowTextLength(hwnd);
+ if (sizeOfTitle++ > 0)
+ {
+ StringBuilder titleBuffer = new StringBuilder(sizeOfTitle);
+ InteropAndHelpers.GetWindowText(hwnd, titleBuffer, sizeOfTitle);
+ return titleBuffer.ToString();
+ }
+ else
+ {
+ return string.Empty;
+ }
+ }
+ }
+
+ ///
+ /// Gets the handle to the window
+ ///
+ public IntPtr Hwnd
+ {
+ get { return hwnd; }
+ }
+
+ ///
+ /// Gets returns the name of the process
+ ///
+ public string ProcessName
+ {
+ get
+ {
+ lock (_handlesToProcessCache)
+ {
+ if (_handlesToProcessCache.Count > 7000)
+ {
+ Debug.Print("Clearing Process Cache because it's size is " + _handlesToProcessCache.Count);
+ _handlesToProcessCache.Clear();
+ }
+
+ if (!_handlesToProcessCache.ContainsKey(Hwnd))
+ {
+ InteropAndHelpers.GetWindowThreadProcessId(Hwnd, out uint processId);
+ IntPtr processHandle = InteropAndHelpers.OpenProcess(InteropAndHelpers.ProcessAccessFlags.AllAccess, true, (int)processId);
+ StringBuilder processName = new StringBuilder(MaximumFileNameLength);
+
+ if (InteropAndHelpers.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0)
+ {
+ _handlesToProcessCache.Add(
+ Hwnd,
+ processName.ToString().Split('\\').Reverse().ToArray()[0]);
+ }
+ else
+ {
+ _handlesToProcessCache.Add(Hwnd, string.Empty);
+ }
+ }
+
+ return _handlesToProcessCache[hwnd];
+ }
+ }
+ }
+
+ ///
+ /// Gets returns the name of the class for the window represented
+ ///
+ public string ClassName
+ {
+ get
+ {
+ StringBuilder windowClassName = new StringBuilder(300);
+ InteropAndHelpers.GetClassName(Hwnd, windowClassName, windowClassName.MaxCapacity);
+
+ return windowClassName.ToString();
+ }
+ }
+
+ ///
+ /// Gets represents the Window Icon for the specified window
+ ///
+ public ImageSource WindowIcon
+ {
+ get
+ {
+ lock (_processIdsToIconsCache)
+ {
+ InteropAndHelpers.GetWindowThreadProcessId(Hwnd, out uint processId);
+
+ if (!_processIdsToIconsCache.ContainsKey(processId))
+ {
+ try
+ {
+ Process process = Process.GetProcessById((int)processId);
+ Icon tempIcon = Icon.ExtractAssociatedIcon(process.Modules[0].FileName);
+ _processIdsToIconsCache.Add(processId, Imaging.CreateBitmapSourceFromHIcon(
+ tempIcon.Handle,
+ Int32Rect.Empty,
+ BitmapSizeOptions.FromEmptyOptions()));
+ }
+ catch
+ {
+ BitmapImage failedImage = new BitmapImage(new Uri(@"Images\failedIcon.jpg", UriKind.Relative));
+ _processIdsToIconsCache.Add(processId, failedImage);
+ }
+ }
+
+ return _processIdsToIconsCache[processId];
+ }
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether is the window visible (might return false if it is a hidden IE tab)
+ ///
+ public bool Visible
+ {
+ get
+ {
+ return InteropAndHelpers.IsWindowVisible(Hwnd);
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether returns true if the window is minimized
+ ///
+ public bool Minimized
+ {
+ get
+ {
+ return GetWindowSizeState() == WindowSizeState.Minimized;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Initializes a new Window representation
+ ///
+ /// the handle to the window we are representing
+ public Window(IntPtr hwnd)
+ {
+ // TODO: Add verification as to whether the window handle is valid
+ this.hwnd = hwnd;
+ }
+
+ ///
+ /// Highlights a window to help the user identify the window that has been selected
+ ///
+ public void HighlightWindow()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Switches dekstop focus to the window
+ ///
+ public void SwitchToWindow()
+ {
+ // The following block is necessary because
+ // 1) There is a weird flashing behaviour when trying
+ // to use ShowWindow for switching tabs in IE
+ // 2) SetForegroundWindow fails on minimized windows
+ if (ProcessName.ToLower().Equals("iexplore.exe") || !Minimized)
+ {
+ InteropAndHelpers.SetForegroundWindow(Hwnd);
+ }
+ else
+ {
+ InteropAndHelpers.ShowWindow(Hwnd, InteropAndHelpers.ShowWindowCommands.Restore);
+ }
+
+ InteropAndHelpers.FlashWindow(Hwnd, true);
+ }
+
+ ///
+ /// Converts the window name to string along with the process name
+ ///
+ /// The title of the window
+ public override string ToString()
+ {
+ return Title + " (" + ProcessName.ToUpper() + ")";
+ }
+
+ ///
+ /// Returns what the window size is
+ ///
+ /// The state (minimized, maximized, etc..) of the window
+ public WindowSizeState GetWindowSizeState()
+ {
+ InteropAndHelpers.GetWindowPlacement(Hwnd, out InteropAndHelpers.WINDOWPLACEMENT placement);
+
+ switch (placement.ShowCmd)
+ {
+ case InteropAndHelpers.ShowWindowCommands.Normal:
+ return WindowSizeState.Normal;
+ case InteropAndHelpers.ShowWindowCommands.Minimize:
+ case InteropAndHelpers.ShowWindowCommands.ShowMinimized:
+ return WindowSizeState.Minimized;
+ case InteropAndHelpers.ShowWindowCommands.Maximize: // No need for ShowMaximized here since its also of value 3
+ return WindowSizeState.Maximized;
+ default:
+ // throw new Exception("Don't know how to handle window state = " + placement.ShowCmd);
+ return WindowSizeState.Unknown;
+ }
+ }
+
+ ///
+ /// Enum to simplify the state of the window
+ ///
+ public enum WindowSizeState
+ {
+ Normal,
+ Minimized,
+ Maximized,
+ Unknown,
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/Components/WindowResult.cs b/src/modules/windowwalker/app/Window Walker/Components/WindowResult.cs
new file mode 100644
index 000000000000..e0a4dd2615ed
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/Components/WindowResult.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WindowWalker.Components
+{
+ class WindowResult:Window
+ {
+ ///
+ /// Number of letters in between constant for when
+ /// the result hasn't been set yet
+ ///
+ public static const int NoResult = -1;
+
+ ///
+ /// Properties that signify how many characters (including spaces)
+ /// were found when matching the results
+ ///
+ public int LettersInBetweenScore
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Constructor for WindowResult
+ ///
+ public WindowResult(Window window):base(window.Hwnd)
+ {
+ LettersInBetweenScore = WindowResult.NoResult;
+ }
+ }
+}
diff --git a/src/modules/windowwalker/app/Window Walker/GlobalSuppressions.cs b/src/modules/windowwalker/app/Window Walker/GlobalSuppressions.cs
new file mode 100644
index 000000000000..37063f3c9adf
--- /dev/null
+++ b/src/modules/windowwalker/app/Window Walker/GlobalSuppressions.cs
@@ -0,0 +1,49 @@
+// 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/
+
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1009:ClosingParenthesisMustBeSpacedCorrectly", Justification = "All current violations are due to Tuple shorthand and so valid.")]
+
+[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:PrefixLocalCallsWithThis", Justification = "We follow the C# Core Coding Style which avoids using `this` unless absolutely necessary.")]
+
+[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:UsingDirectivesMustBePlacedWithinNamespace", Justification = "We follow the C# Core Coding Style which puts using statements outside the namespace.")]
+[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:ElementsMustAppearInTheCorrectOrder", Justification = "It is not a priority and have hight impact in code changes.")]
+[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "It is not a priority and have hight impact in code changes.")]
+[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1203:ConstantsMustAppearBeforeFields", Justification = "It is not a priority and have hight impact in code changes.")]
+[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:StaticElementsMustAppearBeforeInstanceElements", Justification = "It is not a priority and have hight impact in code changes.")]
+
+[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1309:FieldNamesMustNotBeginWithUnderscore", Justification = "We follow the C# Core Coding Style which uses underscores as prefixes rather than using `this.`.")]
+
+[assembly: SuppressMessage("StyleCop.CSharp.SpecialRules", "SA0001:XmlCommentAnalysisDisabled", Justification = "Not enabled as we don't want or need XML documentation.")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1629:DocumentationTextMustEndWithAPeriod", Justification = "Not enabled as we don't want or need XML documentation.")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1625:ElementDocumentationMustNotBeCopiedAndPasted", Justification = "Reviewed.")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1614:ElementParameterDocumentationMustHaveText", Justification = "Reviewed.")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1616:ElementReturnValueDocumentationMustHaveText", Justification = "Reviewed.")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly", Scope = "member", Target = "Microsoft.Templates.Core.Locations.TemplatesSynchronization.#SyncStatusChanged", Justification = "Using an Action