Import the source code for Window Walker (#1177)

Import the codebase for Window Walker 

- Not loaded into the module list 
- Not added it to the installer list.
This commit is contained in:
Betsegaw Tadele 2020-01-31 15:14:37 -08:00 committed by GitHub
parent aa714f7d80
commit b4f81a0c2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 14345 additions and 0 deletions

View file

@ -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}

View file

@ -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

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
</configuration>

View file

@ -0,0 +1,16 @@
<Application x:Class="WindowWalker.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Dark.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Indigo.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Indigo.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

View file

@ -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
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View file

@ -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;
}
}
}
}

View file

@ -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
{
/// <summary>
/// Command class representing a single command
/// </summary>
public class Command
{
/// <summary>
/// Gets or sets the set of substrings to search for in the search text to figure out if the user wants this command
/// </summary>
public string[] SearchTexts { get; set; }
/// <summary>
/// Gets or sets the help tip to get displayed in the cycling display
/// </summary>
public string Tip { get; set; }
}
}

View file

@ -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
{
/// <summary>
/// A class to handle the commands entered by the user, different
/// form the user being able to search through their windows
/// </summary>
internal class Commands
{
/// <summary>
/// Initializes static members of the <see cref="Commands"/> class.
/// Constructor primarily used to enforce the creation of tips
/// and populate the enabled commands list
/// </summary>
static Commands()
{
_enabledCommands = new Dictionary<string, Command>
{
{
"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",
}
},
};
}
/// <summary>
/// Dictionary containing all the enabled commands
/// </summary>
private static readonly Dictionary<string, Command> _enabledCommands;
/// <summary>
/// Primary method which executes on the commands that are passed to it
/// </summary>
/// <param name="commandText">The search text the user has entered</param>
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");
}
}
/// <summary>
/// Gets the tips for all the enabled commands
/// </summary>
public static IEnumerable<string> GetTips()
{
return _enabledCommands.Select(x => x.Value.Tip);
}
}
}

View file

@ -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
{
/// <summary>
/// Class housing fuzzy matching methods
/// </summary>
public class FuzzyMatching
{
/// <summary>
/// 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
/// </summary>
/// <param name="text">The text to search inside of</param>
/// <param name="searchText">the text to search for</param>
/// <returns>returns the index location of each of the letters of the matches</returns>
public static List<int> 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<List<int>> allMatches = GetAllMatchIndexes(matches);
// return the score that is the max
int maxScore = allMatches.Count > 0 ? CalculateScoreForMatches(allMatches[0]) : 0;
List<int> bestMatch = allMatches.Count > 0 ? allMatches[0] : new List<int>();
foreach (var match in allMatches)
{
int score = CalculateScoreForMatches(match);
if (score > maxScore)
{
bestMatch = match;
maxScore = score;
}
}
return bestMatch;
}
/// <summary>
/// Gets all the possible matches to the search string with in the text
/// </summary>
/// <param name="matches"> 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</param>
/// <returns>a list of the possible combinations that match the search text</returns>
public static List<List<int>> GetAllMatchIndexes(bool[,] matches)
{
List<List<int>> results = new List<List<int>>();
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<int> { 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();
}
/// <summary>
/// Calculates the score for a string
/// </summary>
/// <param name="matches">the index of the matches</param>
/// <returns>an integer representing the score</returns>
public static int CalculateScoreForMatches(List<int> 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;
}
}
}

View file

@ -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<int> result = FuzzyMatching.FindBestFuzzyMatch("watsapp hellow", "hello");
List<int> expected = new List<int>() { 8, 9, 10, 11, 12 };
Assert.IsTrue(IsEqual(expected, result));
}
[TestMethod]
public void NoResult()
{
List<int> result = FuzzyMatching.FindBestFuzzyMatch("what is going on?", "whatsx goin on?");
List<int> expected = new List<int>();
Assert.IsTrue(IsEqual(expected, result));
}
[TestMethod]
public void ZeroLengthSearchString()
{
List<int> result = FuzzyMatching.FindBestFuzzyMatch("whatsapp hellow", string.Empty);
List<int> expected = new List<int>();
Assert.IsTrue(IsEqual(expected, result));
}
[TestMethod]
public void ZeroLengthText()
{
List<int> result = FuzzyMatching.FindBestFuzzyMatch(string.Empty, "hello");
List<int> expected = new List<int>();
Assert.IsTrue(IsEqual(expected, result));
}
[TestMethod]
public void ZeroLengthInputs()
{
List<int> result = FuzzyMatching.FindBestFuzzyMatch(string.Empty, string.Empty);
List<int> expected = new List<int>();
Assert.IsTrue(IsEqual(expected, result));
}
[TestMethod]
public void BestMatch()
{
List<int> result = FuzzyMatching.FindBestFuzzyMatch("aaacaab", "ab");
List<int> expected = new List<int>() { 5, 6 };
Assert.IsTrue(IsEqual(expected, result));
}
[TestMethod]
public void RealWorldProgramManager()
{
List<int> result = FuzzyMatching.FindBestFuzzyMatch("Program Manager", "pr");
List<int> expected = new List<int>() { 0, 1 };
Assert.IsTrue(IsEqual(expected, result));
}
[TestMethod]
public void BestScoreTest()
{
int score = FuzzyMatching.CalculateScoreForMatches(new List<int>() { 1, 2, 3, 4 });
Assert.IsTrue(score == -3);
}
private static bool IsEqual(List<int> list1, List<int> 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;
}
}
}

View file

@ -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
{
/// <summary>
/// Interop calls with helper layers
/// </summary>
internal class InteropAndHelpers
{
public delegate bool CallBackPtr(IntPtr hwnd, IntPtr lParam);
/// <summary>
/// Some flags for interop calls to SetWindowPosition
/// </summary>
[Flags]
public enum SetWindowPosFlags : uint
{
/// <summary>
/// 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.
/// </summary>
SWP_ASYNCWINDOWPOS = 0x4000,
/// <summary>
/// Prevents generation of the WM_SYNCPAINT message.
/// </summary>
SWP_DEFERERASE = 0x2000,
/// <summary>
/// Draws a frame (defined in the window's class description) around the window.
/// </summary>
SWP_DRAWFRAME = 0x0020,
/// <summary>
/// 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.
/// </summary>
SWP_FRAMECHANGED = 0x0020,
/// <summary>
/// Hides the window.
/// </summary>
SWP_HIDEWINDOW = 0x0080,
/// <summary>
/// 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).
/// </summary>
SWP_NOACTIVATE = 0x0010,
/// <summary>
/// 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.
/// </summary>
SWP_NOCOPYBITS = 0x0100,
/// <summary>
/// Retains the current position (ignores X and Y parameters).
/// </summary>
SWP_NOMOVE = 0x0002,
/// <summary>
/// Does not change the owner window's position in the Z order.
/// </summary>
SWP_NOOWNERZORDER = 0x0200,
/// <summary>
/// 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.
/// </summary>
SWP_NOREDRAW = 0x0008,
/// <summary>
/// Same as the SWP_NOOWNERZORDER flag.
/// </summary>
SWP_NOREPOSITION = 0x0200,
/// <summary>
/// Prevents the window from receiving the WM_WINDOWPOSCHANGING message.
/// </summary>
SWP_NOSENDCHANGING = 0x0400,
/// <summary>
/// Retains the current size (ignores the cx and cy parameters).
/// </summary>
SWP_NOSIZE = 0x0001,
/// <summary>
/// Retains the current Z order (ignores the hWndInsertAfter parameter).
/// </summary>
SWP_NOZORDER = 0x0004,
/// <summary>
/// Displays the window.
/// </summary>
SWP_SHOWWINDOW = 0x0040,
}
/// <summary>
/// Flags for setting hotkeys
/// </summary>
[Flags]
public enum Modifiers
{
NoMod = 0x0000,
Alt = 0x0001,
Ctrl = 0x0002,
Shift = 0x0004,
Win = 0x0008,
}
/// <summary>
/// Options for DwmpActivateLivePreview
/// </summary>
public enum LivePreviewTrigger
{
/// <summary>
/// Show Desktop button
/// </summary>
ShowDesktop = 1,
/// <summary>
/// WIN+SPACE hotkey
/// </summary>
WinSpace,
/// <summary>
/// Hover-over Superbar thumbnails
/// </summary>
Superbar,
/// <summary>
/// Alt-Tab
/// </summary>
AltTab,
/// <summary>
/// Press and hold on Superbar thumbnails
/// </summary>
SuperbarTouch,
/// <summary>
/// Press and hold on Show desktop
/// </summary>
ShowDesktopTouch,
}
/// <summary>
/// Show Window Enums
/// </summary>
public enum ShowWindowCommands
{
/// <summary>
/// Hides the window and activates another window.
/// </summary>
Hide = 0,
/// <summary>
/// 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.
/// </summary>
Normal = 1,
/// <summary>
/// Activates the window and displays it as a minimized window.
/// </summary>
ShowMinimized = 2,
/// <summary>
/// Maximizes the specified window.
/// </summary>
Maximize = 3, // is this the right value?
/// <summary>
/// Activates the window and displays it as a maximized window.
/// </summary>
ShowMaximized = 3,
/// <summary>
/// Displays a window in its most recent size and position. This value
/// is similar to <see cref="Win32.ShowWindowCommand.Normal"/>, except
/// the window is not activated.
/// </summary>
ShowNoActivate = 4,
/// <summary>
/// Activates the window and displays it in its current size and position.
/// </summary>
Show = 5,
/// <summary>
/// Minimizes the specified window and activates the next top-level
/// window in the Z order.
/// </summary>
Minimize = 6,
/// <summary>
/// Displays the window as a minimized window. This value is similar to
/// <see cref="Win32.ShowWindowCommand.ShowMinimized"/>, except the
/// window is not activated.
/// </summary>
ShowMinNoActive = 7,
/// <summary>
/// Displays the window in its current size and position. This value is
/// similar to <see cref="Win32.ShowWindowCommand.Show"/>, except the
/// window is not activated.
/// </summary>
ShowNA = 8,
/// <summary>
/// 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.
/// </summary>
Restore = 9,
/// <summary>
/// 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.
/// </summary>
ShowDefault = 10,
/// <summary>
/// <b>Windows 2000/XP:</b> 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.
/// </summary>
ForceMinimize = 11,
}
/// <summary>
/// The rendering policy to use for set window attribute
/// </summary>
[Flags]
public enum DwmNCRenderingPolicy
{
UseWindowStyle,
Disabled,
Enabled,
Last,
}
/// <summary>
/// Window attribute
/// </summary>
[Flags]
public enum DwmWindowAttribute
{
NCRenderingEnabled = 1,
NCRenderingPolicy,
TransitionsForceDisabled,
AllowNCPaint,
CaptionButtonBounds,
NonClientRtlLayout,
ForceIconicRepresentation,
Flip3DPolicy,
ExtendedFrameBounds,
HasIconicBitmap,
DisallowPeek,
ExcludedFromPeek,
Last,
}
/// <summary>
/// Flags for accessing the process in trying to get icon for the process
/// </summary>
[Flags]
public enum ProcessAccessFlags
{
/// <summary>
/// Required to create a thread.
/// </summary>
CreateThread = 0x0002,
/// <summary>
///
/// </summary>
SetSessionId = 0x0004,
/// <summary>
/// Required to perform an operation on the address space of a process
/// </summary>
VmOperation = 0x0008,
/// <summary>
/// Required to read memory in a process using ReadProcessMemory.
/// </summary>
VmRead = 0x0010,
/// <summary>
/// Required to write to memory in a process using WriteProcessMemory.
/// </summary>
VmWrite = 0x0020,
/// <summary>
/// Required to duplicate a handle using DuplicateHandle.
/// </summary>
DupHandle = 0x0040,
/// <summary>
/// Required to create a process.
/// </summary>
CreateProcess = 0x0080,
/// <summary>
/// Required to set memory limits using SetProcessWorkingSetSize.
/// </summary>
SetQuota = 0x0100,
/// <summary>
/// Required to set certain information about a process, such as its priority class (see SetPriorityClass).
/// </summary>
SetInformation = 0x0200,
/// <summary>
/// Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken).
/// </summary>
QueryInformation = 0x0400,
/// <summary>
/// Required to suspend or resume a process.
/// </summary>
SuspendResume = 0x0800,
/// <summary>
/// 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.
/// </summary>
QueryLimitedInformation = 0x1000,
/// <summary>
/// Required to wait for the process to terminate using the wait functions.
/// </summary>
Synchronize = 0x100000,
/// <summary>
/// Required to delete the object.
/// </summary>
Delete = 0x00010000,
/// <summary>
/// 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.
/// </summary>
ReadControl = 0x00020000,
/// <summary>
/// Required to modify the DACL in the security descriptor for the object.
/// </summary>
WriteDac = 0x00040000,
/// <summary>
/// Required to change the owner in the security descriptor for the object.
/// </summary>
WriteOwner = 0x00080000,
StandardRightsRequired = 0x000F0000,
/// <summary>
/// All possible access rights for a process object.
/// </summary>
AllAccess = StandardRightsRequired | Synchronize | 0xFFFF,
}
/// <summary>
/// Contains information about the placement of a window on the screen.
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
internal struct WINDOWPLACEMENT
{
/// <summary>
/// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT).
/// <para>
/// GetWindowPlacement and SetWindowPlacement fail if this member is not set correctly.
/// </para>
/// </summary>
public int Length;
/// <summary>
/// Specifies flags that control the position of the minimized window and the method by which the window is restored.
/// </summary>
public int Flags;
/// <summary>
/// The current show state of the window.
/// </summary>
public ShowWindowCommands ShowCmd;
/// <summary>
/// The coordinates of the window's upper-left corner when the window is minimized.
/// </summary>
public POINT MinPosition;
/// <summary>
/// The coordinates of the window's upper-left corner when the window is maximized.
/// </summary>
public POINT MaxPosition;
/// <summary>
/// The window's coordinates when the window is in the restored position.
/// </summary>
public RECT NormalPosition;
/// <summary>
/// Gets the default (empty) value.
/// </summary>
public static WINDOWPLACEMENT Default
{
get
{
WINDOWPLACEMENT result = default;
result.Length = Marshal.SizeOf(result);
return result;
}
}
}
/// <summary>
/// Required pointless variables that we don't use in making a windows show
/// </summary>
[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);
}
}
/// <summary>
/// Same as the RECT struct above
/// </summary>
[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);
}
}

View file

@ -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
{
/// <summary>
/// Class containg methods to control the live preview
/// </summary>
internal class LivePreview
{
/// <summary>
/// Makes sure that a window is excluded from the live preview
/// </summary>
/// <param name="hwnd">handle to the window to exclude</param>
public static void SetWindowExlusionFromLivePreview(IntPtr hwnd)
{
int renderPolicy = (int)InteropAndHelpers.DwmNCRenderingPolicy.Enabled;
InteropAndHelpers.DwmSetWindowAttribute(
hwnd,
12,
ref renderPolicy,
sizeof(int));
}
/// <summary>
/// Activates the live preview
/// </summary>
/// <param name="targetWindow">the window to show by making all other windows transparent</param>
/// <param name="windowToSpare">the window which should not be transparent but is not the target window</param>
public static void ActivateLivePreview(IntPtr targetWindow, IntPtr windowToSpare)
{
InteropAndHelpers.DwmpActivateLivePreview(
true,
targetWindow,
windowToSpare,
InteropAndHelpers.LivePreviewTrigger.Superbar,
IntPtr.Zero);
}
/// <summary>
/// Deactivates the live preview
/// </summary>
public static void DeactivateLivePreview()
{
InteropAndHelpers.DwmpActivateLivePreview(
false,
IntPtr.Zero,
IntPtr.Zero,
InteropAndHelpers.LivePreviewTrigger.AltTab,
IntPtr.Zero);
}
}
}

View file

@ -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
{
/// <summary>
/// Class that represents the state of the desktops windows
/// </summary>
internal class OpenWindows
{
/// <summary>
/// Delegate handler for open windows updates
/// </summary>
public delegate void OpenWindowsUpdateHandler(object sender, SearchController.SearchResultUpdateEventArgs e);
/// <summary>
/// Event raised when there is an update to the list of open windows
/// </summary>
public event OpenWindowsUpdateHandler OnOpenWindowsUpdate;
/// <summary>
/// List of all the open windows
/// </summary>
private readonly List<Window> windows = new List<Window>();
/// <summary>
/// An instance of the class OpenWindows
/// </summary>
private static OpenWindows instance;
/// <summary>
/// Gets the list of all open windows
/// </summary>
public List<Window> Windows
{
get { return new List<Window>(windows); }
}
/// <summary>
/// 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
/// </summary>
public static OpenWindows Instance
{
get
{
if (instance == null)
{
instance = new OpenWindows();
}
return instance;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="OpenWindows"/> class.
/// Private constructor to make sure there is never
/// more than one instance of this class
/// </summary>
private OpenWindows()
{
}
/// <summary>
/// Updates the list of open windows
/// </summary>
public void UpdateOpenWindowsList()
{
windows.Clear();
new Task(() =>
{
InteropAndHelpers.CallBackPtr callbackptr = new InteropAndHelpers.CallBackPtr(WindowEnumerationCallBack);
InteropAndHelpers.EnumWindows(callbackptr, 0);
}).Start();
}
/// <summary>
/// Call back method for window enumeration
/// </summary>
/// <param name="hwnd">The handle to the current window being enumerated</param>
/// <param name="lParam">Value being passed from the caller (we don't use this but might come in handy
/// in the future</param>
/// <returns>true to make sure to contiue enumeration</returns>
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;
}
}
}

View file

@ -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
{
/// <summary>
/// Custom point class to ease storing a point
/// </summary>
public class Point
{
public double X { get; set; }
public double Y { get; set; }
}
}

View file

@ -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
{
/// <summary>
/// Responsible for searching and finding matches for the strings provided.
/// Essentially the UI independent model of the application
/// </summary>
internal class SearchController
{
/// <summary>
/// the current search text
/// </summary>
private string searchText;
/// <summary>
/// Open window search results
/// </summary
private List<SearchResult> searchMatches;
/// <summary>
/// Singleton pattern
/// </summary>
private static SearchController instance;
/// <summary>
/// Delegate handler for open windows updates
/// </summary>
public delegate void SearchResultUpdateHandler(object sender, SearchResultUpdateEventArgs e);
/// <summary>
/// Event raised when there is an update to the list of open windows
/// </summary>
public event SearchResultUpdateHandler OnSearchResultUpdate;
/// <summary>
/// Gets or sets the current search text
/// </summary>
public string SearchText
{
get
{
return searchText;
}
set
{
searchText = value.ToLower().Trim();
SearchTextUpdated();
}
}
/// <summary>
/// Gets the open window search results
/// </summary>
public List<SearchResult> SearchMatches
{
get { return new List<SearchResult>(searchMatches).OrderByDescending(x => x.Score).ToList(); }
}
/// <summary>
/// Gets singleton Pattern
/// </summary>
public static SearchController Instance
{
get
{
if (instance == null)
{
instance = new SearchController();
}
return instance;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="SearchController"/> class.
/// Initializes the search controller object
/// </summary>
private SearchController()
{
searchText = string.Empty;
OpenWindows.Instance.OnOpenWindowsUpdate += OpenWindowsUpdateHandler;
}
/// <summary>
/// Event handler for when the search text has been updated
/// </summary>
public void SearchTextUpdated()
{
SyncOpenWindowsWithModelAsync();
}
/// <summary>
/// Event handler called when the OpenWindows list changes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void OpenWindowsUpdateHandler(object sender, SearchResultUpdateEventArgs e)
{
SyncOpenWindowsWithModelAsync();
}
/// <summary>
/// Syncs the open windows with the OpenWindows Model
/// </summary>
private async void SyncOpenWindowsWithModelAsync()
{
System.Diagnostics.Debug.Print("Syncing WindowSearch result with OpenWindows Model");
List<Window> snapshotOfOpenWindows = OpenWindows.Instance.Windows;
if (SearchText == string.Empty)
{
searchMatches = new List<SearchResult>();
}
else
{
searchMatches = await FuzzySearchOpenWindowsAsync(snapshotOfOpenWindows);
}
OnSearchResultUpdate?.Invoke(this, new SearchResultUpdateEventArgs());
}
/// <summary>
/// Redirecting method for Fuzzy searching
/// </summary>
/// <param name="openWindows"></param>
/// <returns>Returns search results</returns>
private Task<List<SearchResult>> FuzzySearchOpenWindowsAsync(List<Window> openWindows)
{
return Task.Run(
() =>
FuzzySearchOpenWindows(openWindows));
}
/// <summary>
/// Search method that matches the title of windows with the user search text
/// </summary>
/// <param name="openWindows"></param>
/// <returns>Returns search results</returns>
private List<SearchResult> FuzzySearchOpenWindows(List<Window> openWindows)
{
List<SearchResult> result = new List<SearchResult>();
List<SearchString> searchStrings = new List<SearchString>();
List<string> 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;
}
/// <summary>
/// Event args for a window list update event
/// </summary>
public class SearchResultUpdateEventArgs : EventArgs
{
}
}
}

View file

@ -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
{
/// <summary>
/// Contains search result windows with each window including the reason why the result was included
/// </summary>
public class SearchResult
{
/// <summary>
/// Gets the actual window reference for the search result
/// </summary>
public Window Result
{
get;
private set;
}
/// <summary>
/// Gets the list of indexes of the matching characters for the search in the title window
/// </summary>
public List<int> SearchMatchesInTitle
{
get;
private set;
}
/// <summary>
/// Gets the list of indexes of the matching characters for the search in the
/// name of the process
/// </summary>
public List<int> SearchMatchesInProcessName
{
get;
private set;
}
/// <summary>
/// Gets the type of match (shortcut, fuzzy or nothing)
/// </summary>
public SearchType SearchResultMatchType
{
get;
private set;
}
/// <summary>
/// Gets a score indicating how well this matches what we are looking for
/// </summary>
public int Score
{
get;
private set;
}
/// <summary>
/// Gets the source of where the best score was found
/// </summary>
public TextType BestScoreSource
{
get;
private set;
}
/// <summary>
/// Initializes a new instance of the <see cref="SearchResult"/> class.
/// Constructor
/// </summary>
public SearchResult(Window window, List<int> matchesInTitle, List<int> matchesInProcessName, SearchType matchType)
{
Result = window;
SearchMatchesInTitle = matchesInTitle;
SearchMatchesInProcessName = matchesInProcessName;
SearchResultMatchType = matchType;
CalculateScore();
}
/// <summary>
/// Calculates the score for how closely this window matches the search string
/// </summary>
/// <remarks>
/// Higher Score is better
/// </remarks>
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;
}
}
/// <summary>
/// The type of text that a string represents
/// </summary>
public enum TextType
{
ProcessName,
WindowTitle,
}
/// <summary>
/// The type of search
/// </summary>
public enum SearchType
{
/// <summary>
/// the search string is empty, which means all open windows are
/// going to be returned
/// </summary>
Empty,
/// <summary>
/// Regular fuzzy match search
/// </summary>
Fuzzy,
/// <summary>
/// The user has entered text that has been matched to a shortcut
/// and the shortcut is now being searched
/// </summary>
Shortcut,
}
}
}

View file

@ -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
{
/// <summary>
/// A class to represent a search string
/// </summary>
/// <remarks>Class was added inorder to be able to attach various context data to
/// a search string</remarks>
internal class SearchString
{
/// <summary>
/// Gets where is the search string coming from (is it a shortcut
/// or direct string, etc...)
/// </summary>
public SearchResult.SearchType SearchType
{
get;
private set;
}
/// <summary>
/// Gets the actual text we are searching for
/// </summary>
public string SearchText
{
get;
private set;
}
/// <summary>
/// Initializes a new instance of the <see cref="SearchString"/> class.
/// Constructor
/// </summary>
/// <param name="searchText"></param>
/// <param name="searchType"></param>
public SearchString(string searchText, SearchResult.SearchType searchType)
{
SearchText = searchText;
SearchType = searchType;
}
}
}

View file

@ -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
{
/// <summary>
/// Class that represents all the settings and
/// can be serialized into JSON for easy saving
/// </summary>
internal class Settings
{
/// <summary>
/// Gets or sets the version of the settings file
/// </summary>
public string Version { get; set; }
/// <summary>
/// Gets or sets a list of all the shortcuts
/// </summary>
public Dictionary<string, List<string>> Shortcuts { get; set; }
/// <summary>
/// Gets or sets a list of saved window locations catagorized by number of screens
/// </summary>
public Dictionary<string, Point> WindowLocations { get; set; }
/// <summary>
/// Gets or sets the location of the search windows (the top left point)
/// </summary>
[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<string, Point>();
}
WindowLocations[System.Windows.Forms.Screen.AllScreens.Length.ToString()] = value;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="Settings"/> class.
/// Constructer to initialize some default values
/// </summary>
public Settings()
{
Version = string.Empty;
Shortcuts = new Dictionary<string, List<string>>();
WindowLocation = new Point() { X = 0, Y = 0 };
WindowLocations = new Dictionary<string, Point>();
}
}
}

View file

@ -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
{
/// <summary>
/// Class for managing shortcuts
/// Example: When you type "i" we actually search for "internet"
/// </summary>
internal class SettingsManager
{
/// <summary>
/// The path to the shortcut file
/// </summary>
private static readonly string _shortcutsFile = Path.GetTempPath() + "WindowWalkerShortcuts.ini";
/// <summary>
/// Reference to a serializer for saving the settings
/// </summary>
private static readonly JavaScriptSerializer _serializer = new JavaScriptSerializer();
/// <summary>
/// An instance of the settings class representing the current settings
/// </summary>
private static readonly Settings _settingsInstance = new Settings();
/// <summary>
/// Instance of the manager itself
/// </summary>
private static SettingsManager _instance;
/// <summary>
/// Gets implements Singlton pattern
/// </summary>
public static SettingsManager Instance
{
get
{
if (_instance == null)
{
_instance = new SettingsManager();
}
return _instance;
}
}
/// <summary>
/// Initializes static members of the <see cref="SettingsManager"/> class.
/// Static constructor
/// </summary>
/// <remarks>Not sure why we have this AND a singlton pattern</remarks>
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
{
}
}
/// <summary>
/// Initializes a new instance of the <see cref="SettingsManager"/> class.
/// Contructor that does nothing?
/// </summary>
private SettingsManager()
{
return;
}
/// <summary>
/// Adds a shortcut to the settings
/// </summary>
/// <param name="before">what the user types</param>
/// <param name="after">what the resulting search string is going to be</param>
/// <returns>Returns true if it succeeds, false otherwise</returns>
/// <remarks>Proably not usefull to actually do the true/false return since
/// we can now have multiple shortcuts</remarks>
public bool AddShortcut(string before, string after)
{
if (!_settingsInstance.Shortcuts.ContainsKey(before))
{
_settingsInstance.Shortcuts.Add(before, new List<string>());
}
_settingsInstance.Shortcuts[before].Add(after);
// Write the updated shortcuts list to a file
SaveSettings();
return true;
}
/// <summary>
/// Removes a shortcut
/// </summary>
/// <param name="input">the input shortcut string</param>
/// <returns>true if it succeeds, false otherwise</returns>
/// <remarks>Probably has a bug since you can now a single input
/// mapping to multiple outputs</remarks>
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;
}
/// <summary>
/// Retrieves a shortcut and returns all possible mappings
/// </summary>
/// <param name="input">the input string for the shortcuts</param>
/// <returns>A list of all the shortcut strings that result from the user input</returns>
public List<string> GetShortcut(string input)
{
return _settingsInstance.Shortcuts.ContainsKey(input) ? _settingsInstance.Shortcuts[input] : new List<string>();
}
/// <summary>
/// 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.
/// </summary>
public void SaveSettings()
{
using (StreamWriter writer = new StreamWriter(_shortcutsFile, false))
{
writer.Write(_serializer.Serialize(_settingsInstance));
}
}
}
}

View file

@ -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
{
/// <summary>
/// Represents a specific open window
/// </summary>
public class Window
{
/// <summary>
/// Maximum size of a file name
/// </summary>
private const int MaximumFileNameLength = 1000;
/// <summary>
/// The list of owners of a window so that we don't have to
/// constantly query for the process owning a specific window
/// </summary>
private static readonly Dictionary<IntPtr, string> _handlesToProcessCache = new Dictionary<IntPtr, string>();
/// <summary>
/// The list of icons from process so that we don't have to keep
/// loading them from disk
/// </summary>
private static readonly Dictionary<uint, ImageSource> _processIdsToIconsCache = new Dictionary<uint, ImageSource>();
/// <summary>
/// The handle to the window
/// </summary>
private readonly IntPtr hwnd;
/// <summary>
/// Gets the title of the window (the string displayed at the top of the window)
/// </summary>
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;
}
}
}
/// <summary>
/// Gets the handle to the window
/// </summary>
public IntPtr Hwnd
{
get { return hwnd; }
}
/// <summary>
/// Gets returns the name of the process
/// </summary>
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];
}
}
}
/// <summary>
/// Gets returns the name of the class for the window represented
/// </summary>
public string ClassName
{
get
{
StringBuilder windowClassName = new StringBuilder(300);
InteropAndHelpers.GetClassName(Hwnd, windowClassName, windowClassName.MaxCapacity);
return windowClassName.ToString();
}
}
/// <summary>
/// Gets represents the Window Icon for the specified window
/// </summary>
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];
}
}
}
/// <summary>
/// Gets a value indicating whether is the window visible (might return false if it is a hidden IE tab)
/// </summary>
public bool Visible
{
get
{
return InteropAndHelpers.IsWindowVisible(Hwnd);
}
}
/// <summary>
/// Gets a value indicating whether returns true if the window is minimized
/// </summary>
public bool Minimized
{
get
{
return GetWindowSizeState() == WindowSizeState.Minimized;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="Window"/> class.
/// Initializes a new Window representation
/// </summary>
/// <param name="hwnd">the handle to the window we are representing</param>
public Window(IntPtr hwnd)
{
// TODO: Add verification as to whether the window handle is valid
this.hwnd = hwnd;
}
/// <summary>
/// Highlights a window to help the user identify the window that has been selected
/// </summary>
public void HighlightWindow()
{
throw new NotImplementedException();
}
/// <summary>
/// Switches dekstop focus to the window
/// </summary>
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);
}
/// <summary>
/// Converts the window name to string along with the process name
/// </summary>
/// <returns>The title of the window</returns>
public override string ToString()
{
return Title + " (" + ProcessName.ToUpper() + ")";
}
/// <summary>
/// Returns what the window size is
/// </summary>
/// <returns>The state (minimized, maximized, etc..) of the window</returns>
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;
}
}
/// <summary>
/// Enum to simplify the state of the window
/// </summary>
public enum WindowSizeState
{
Normal,
Minimized,
Maximized,
Unknown,
}
}
}

View file

@ -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
{
/// <summary>
/// Number of letters in between constant for when
/// the result hasn't been set yet
/// </summary>
public static const int NoResult = -1;
/// <summary>
/// Properties that signify how many characters (including spaces)
/// were found when matching the results
/// </summary>
public int LettersInBetweenScore
{
get;
set;
}
/// <summary>
/// Constructor for WindowResult
/// </summary>
public WindowResult(Window window):base(window.Hwnd)
{
LettersInBetweenScore = WindowResult.NoResult;
}
}
}

View file

@ -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<object, SyncStatusEventArgs> does not allow the required notation")]
// Non general supressions
[assembly: SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "The WebBrowser is loading source code to be shown to the user. No localization required.", MessageId = "System.Windows.Controls.WebBrowser.NavigateToString(System.String)", Scope = "member", Target = "Microsoft.Templates.UI.Controls.CodeViewer.#UpdateCodeView(System.Func`2<System.String,System.String>,System.String,System.String,System.Boolean)")]
[assembly: SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "This is part of the markdown processing", MessageId = "System.Windows.Documents.Run.#ctor(System.String)", Scope = "member", Target = "Microsoft.Templates.UI.Controls.Markdown.#ImageInlineEvaluator(System.Text.RegularExpressions.Match)")]
[assembly: SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "We need to have the names of these keys in lowercase to be able to compare with the keys becoming form the template json. ContainsKey does not allow StringComparer especification to IgnoreCase", Scope = "member", Target = "Microsoft.Templates.Core.ITemplateInfoExtensions.#GetQueryableProperties(Microsoft.TemplateEngine.Abstractions.ITemplateInfo)")]
[assembly: SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "We need to have the names of these keys in lowercase to be able to compare with the keys becoming form the template json. ContainsKey does not allow StringComparer especification to IgnoreCase", Scope = "member", Target = "Microsoft.Templates.Core.Composition.CompositionQuery.#Match(System.Collections.Generic.IEnumerable`1<Microsoft.Templates.Core.Composition.QueryNode>,Microsoft.Templates.Core.Composition.QueryablePropertyDictionary)")]
[assembly: SuppressMessage("Usage", "VSTHRD103:Call async methods when in an async method", Justification = "Resource DictionaryWriter does not implement flush async", Scope = "member", Target = "~M:Microsoft.Templates.Core.PostActions.Catalog.Merge.MergeResourceDictionaryPostAction.ExecuteInternalAsync~System.Threading.Tasks.Task")]
// Threading supressions
[assembly: SuppressMessage("Microsoft.VisualStudio.Threading.Analyzers", "VSTHRD100:Avoid async void methods", Justification = "Event handlers needs async void", Scope = "member", Target = "~M:Microsoft.Templates.UI.Controls.Notification.OnClose")]
[assembly: SuppressMessage("Microsoft.VisualStudio.Threading.Analyzers", "VSTHRD100:Avoid async void methods", Justification = "Event handlers needs async void", Scope = "member", Target = "~M:Microsoft.Templates.UI.ViewModels.Common.SavedTemplateViewModel.OnDelete")]
[assembly: SuppressMessage("Microsoft.VisualStudio.Threading.Analyzers", "VSTHRD100:Avoid async void methods", Justification = "Event handlers needs async void", Scope = "member", Target = "~M:Microsoft.Templates.UI.ViewModels.Common.WizardNavigation.GoBack")]
[assembly: SuppressMessage("Microsoft.VisualStudio.Threading.Analyzers", "VSTHRD100:Avoid async void methods", Justification = "Event handlers needs async void", Scope = "member", Target = "~M:Microsoft.Templates.UI.ViewModels.Common.WizardNavigation.GoForward")]
[assembly: SuppressMessage("Microsoft.VisualStudio.Threading.Analyzers", "VSTHRD100:Avoid async void methods", Justification = "Event handlers needs async void", Scope = "member", Target = "~M:Microsoft.Templates.UI.ViewModels.Common.SavedTemplateViewModel.OnDelete(Microsoft.Templates.UI.ViewModels.Common.SavedTemplateViewModel)")]
// Localization suppressions
[assembly: SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Microsoft.Templates.Core.Locations.JunctionNativeMethods.ThrowLastWin32Error(System.String)", Scope = "member", Target = "Microsoft.Templates.Core.Locations.JunctionNativeMethods.#CreateJunction(System.String,System.String,System.Boolean)", Justification = "Only used for local generation")]
[assembly: SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Microsoft.Templates.Core.Locations.JunctionNativeMethods.ThrowLastWin32Error(System.String)", Scope = "member", Target = "Microsoft.Templates.Core.Locations.JunctionNativeMethods.#DeleteJunction(System.String)", Justification = "Only used for local generation")]
[assembly: SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Microsoft.Templates.Core.Locations.JunctionNativeMethods.ThrowLastWin32Error(System.String)", Scope = "member", Target = "Microsoft.Templates.Core.Locations.JunctionNativeMethods.#InternalGetTarget(Microsoft.Win32.SafeHandles.SafeFileHandle)", Justification = "Only used for local generation")]
[assembly: SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Microsoft.Templates.Core.Locations.JunctionNativeMethods.ThrowLastWin32Error(System.String)", Scope = "member", Target = "Microsoft.Templates.Core.Locations.JunctionNativeMethods.#OpenReparsePoint(System.String,Microsoft.Templates.Core.Locations.JunctionNativeMethods+EFileAccess)", Justification = "Only used for local generation")]
[assembly: SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Windows.Documents.InlineCollection.Add(System.String)", Scope = "member", Target = "Microsoft.Templates.UI.Extensions.TextBlockExtensions.#OnSequentialFlowStepChanged(System.Windows.DependencyObject,System.Windows.DependencyPropertyChangedEventArgs)", Justification = "No text here")]

View file

@ -0,0 +1,75 @@
// 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.Windows;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Windows.Media;
namespace WindowWalker
{
/// <summary>
/// This class handles all hotkey related activities
/// </summary>
/// <remarks>Large pieces of this class were retrived from
/// http://www.dreamincode.net/forums/topic/323708-global-hotkeys-for-wpf-applications-c%23/
/// </remarks>
internal class HotKeyHandler
{
private readonly IntPtr hwnd;
/// <summary>
/// Delegate handler for Hotkey being called
/// </summary>
public delegate void HotKeyPressedHandler(object sender, EventArgs e);
/// <summary>
/// Event raised when there is an update to the list of open windows
/// </summary>
public event HotKeyPressedHandler OnHotKeyPressed;
/// <summary>
/// Initializes a new instance of the <see cref="HotKeyHandler"/> class.
/// Constructor for the class
/// </summary>
/// <param name="hwnd">The handle to the window we are registering the key for</param>
public HotKeyHandler(Visual window)
{
hwnd = new WindowInteropHelper((Window)window).Handle;
if (!(PresentationSource.FromVisual(window) is HwndSource source))
{
throw new Exception("Could not create hWnd source from window.");
}
source.AddHook(WndProc);
bool result = Components.InteropAndHelpers.RegisterHotKey(
hwnd,
1,
(int)Components.InteropAndHelpers.Modifiers.Ctrl | (int)Components.InteropAndHelpers.Modifiers.Win,
(int)Keys.None);
}
/// <summary>
/// Call back function to detect when the hot key has been called
/// </summary>
/// <param name="hwnd"></param>
/// <param name="msg"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <param name="handled">if a key was called</param>
/// <returns>if a key was called</returns>
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == 0x0312 && OnHotKeyPressed != null)
{
OnHotKeyPressed(this, new EventArgs());
}
return IntPtr.Zero;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View file

@ -0,0 +1,18 @@
// 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.ComponentModel;
namespace WindowWalker.MVVMHelpers
{
internal class PropertyChangedBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View file

@ -0,0 +1,52 @@
// 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.Windows.Input;
namespace WindowWalker.MVVMHelpers
{
/// <summary>
/// Copy pasted from https://docs.microsoft.com/en-us/dotnet/standard/cross-platform/using-portable-class-library-with-model-view-view-model
/// </summary>
public class RelayCommand : ICommand
{
private readonly Action _handler;
private bool _isEnabled;
public RelayCommand(Action handler)
{
_handler = handler;
}
public bool IsEnabled
{
get
{
return _isEnabled;
}
set
{
if (value != _isEnabled)
{
_isEnabled = value;
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_handler();
}
}
}

View file

@ -0,0 +1,54 @@
<Window x:Class="WindowWalker.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:WindowWalker"
Title="MainWindow" Width="1000" MinHeight="10" Height="85" ResizeMode="NoResize" Topmost="True" WindowStyle="None" Loaded="Window_Loaded" WindowStartupLocation="CenterScreen" SizeToContent="Height" Visibility="{Binding WindowVisibility, Mode=TwoWay, Converter={StaticResource BoolToVis}}"
BorderBrush="{DynamicResource PrimaryHueDarkBrush}"
BorderThickness="2"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
Background="{DynamicResource MaterialDesignPaper}"
TextElement.FontWeight="Medium"
TextElement.FontSize="14"
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
Deactivated="Window_Deactivated"
ShowInTaskbar="false">
<Window.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<local:WindowSearchResultToXamlConverter x:Key="windowSearchResultToXamlConverter"/>
</ResourceDictionary>
</Window.Resources>
<Grid>
<StackPanel Margin="1" Orientation="Vertical">
<TextBox x:Name="searchBox" Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" FontSize="40" Margin="10" KeyUp="SearchBoxKeyUp" materialDesign:HintAssist.Hint="{Binding Hint}" materialDesign:HintAssist.HintOpacity="0.2"/>
<ListBox x:Name="results" ItemsSource="{Binding Results}" SelectedItem="{Binding SelectedWindowResult}" HorizontalContentAlignment="Stretch" MouseDoubleClick="Results_MouseDoubleClick">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{DynamicResource PrimaryHueMidBrush}" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<!--<TextBlock Grid.Column="0" Text="{Binding ResultWindow.Title}"/>-->
<ContentControl Grid.Column="0" Content="{Binding Converter={StaticResource windowSearchResultToXamlConverter}, Mode=OneTime}"/>
<!--<TextBlock Grid.Column="1" TextAlignment="Right" Text="{Binding ResultWindow.ProcessName}"/>-->
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<TextBox x:Name="versionDisplay" HorizontalAlignment="Right" Foreground="White" Opacity="0.1" VerticalAlignment="Top" BorderThickness="0" Margin="0,0,14,0"/>
</Grid>
</Window>

View file

@ -0,0 +1,115 @@
// 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;
using System.Windows;
using System.Windows.Input;
namespace WindowWalker
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void UpdateDisplayedVersionNumber()
{
// Since displaying version number is not critical to functionality, we don't need to do anything if it fails.
try
{
Version applicationVersion = new Version("0.0.0.0");
if (ApplicationDeployment.IsNetworkDeployed)
{
applicationVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion;
}
if (ApplicationDeployment.CurrentDeployment.UpdateLocation.Host.Contains("develop"))
{
versionDisplay.Text = "(develop) " + applicationVersion.ToString();
}
else
{
versionDisplay.Text = applicationVersion.ToString();
}
}
catch
{
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DataContext = new ViewModels.WindowWalkerViewModel(this);
searchBox.Focus();
UpdateDisplayedVersionNumber();
HideWindow();
}
private void SearchBoxKeyUp(object sender, KeyEventArgs e)
{
var viewModel = (ViewModels.WindowWalkerViewModel)DataContext;
if (e.Key == Key.Escape)
{
if (viewModel.WindowHideCommand.CanExecute(null))
{
viewModel.WindowHideCommand.Execute(null);
}
}
else if (e.Key == Key.Down)
{
if (viewModel.WindowNavigateToNextResultCommand.CanExecute(null))
{
viewModel.WindowNavigateToNextResultCommand.Execute(null);
}
}
else if (e.Key == Key.Up)
{
if (viewModel.WindowNavigateToPreviousResultCommand.CanExecute(null))
{
viewModel.WindowNavigateToPreviousResultCommand.Execute(null);
}
}
else if (e.Key == Key.Enter)
{
if (viewModel.SwitchToSelectedWindowCommand.CanExecute(null))
{
viewModel.SwitchToSelectedWindowCommand.Execute(null);
}
}
}
private void Results_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var viewModel = (ViewModels.WindowWalkerViewModel)DataContext;
if (viewModel.SwitchToSelectedWindowCommand.CanExecute(null))
{
viewModel.SwitchToSelectedWindowCommand.Execute(null);
}
}
private void Window_Deactivated(object sender, EventArgs e)
{
HideWindow();
}
private void HideWindow()
{
var viewModel = (ViewModels.WindowWalkerViewModel)DataContext;
if (viewModel.WindowHideCommand.CanExecute(null))
{
viewModel.WindowHideCommand.Execute(null);
}
}
}
}

View file

@ -0,0 +1,56 @@
// 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.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Window Walker")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Window Walker")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// In order to begin building localizable applications, set
// <UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
// inside a <PropertyGroup>. For example, if you are using US english
// in your source files, set the <UICulture> to en-US. Then uncomment
// the NeutralResourceLanguage attribute below. Update the "en-US" in
// the line below to match the UICulture setting in the project file.
// [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
// ThemeInfo.None = where theme specific resource dictionaries are located
// (used if a resource is not found in the page,
// or application resource dictionaries)
// ThemeInfo.SourceAssembly = where the generic resource dictionary is located
// (used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
[assembly: ThemeInfo(
ResourceDictionaryLocation.None,
ResourceDictionaryLocation.SourceAssembly)
]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace WindowWalker.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WindowWalker.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View file

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace WindowWalker.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View file

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View file

@ -0,0 +1,3 @@
Entypo (http://www.entypo.com/) is created by Daniel Bruce and released under the Creative Commons, Share Alike/Attribution license.
http://creativecommons.org/licenses/by-sa/3.0/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,62 @@
# License
Please carefully understand the license and download the latest icons at ModernUIIcons.com.
## Understand Your Rights
No Attribution and No Derived Works
http://creativecommons.org/licenses/by-nd/3.0/ *
- If your project is open source include this license file in the source.
- Nothing is needed in the front facing project (UNLESS you
are using any of the icons listed below in the attribution section).
- Commercial use is not only allowed but encouraged. If it is an icon
in the attribution list below, you still need to attribute those!
- Do not distribute the entire package (I've allowed this dozens of
times for open source projects, but email me first).
## Creator
- Austin Andrews (@templarian)
## Contributor**
- Jay Zawrotny (@JayZawrotny)
- A Bunch
- Oren Nachman
- appbar.chevron.down
- appbar.chevron.up
- appbar.chevron.left
- appbar.chevron.right
## Derived Works
- Alex Peattie
- Social: http://www.alexpeattie.com/projects/justvector_icons/
## Attribution***
- Kris Vandermotten (@kvandermotten)
- appbar.medical.pulse
- Constantin Kichinsky (@kichinsky)
- appbar.currency.rubles
- appbar.currency.grivna
- Massimo Savazzi (@msavazzi)
- List of missing exported icons
- Proletkult Graphik, from The Noun Project
- appbar.draw.pen (inspired)
- Olivier Guin, from The Noun Project
- appbar.draw.marker
- Gibran Bisio, from The Noun Project
- appbar.draw.bucket
Andrew Forrester, from The Noun Project
- appbar.fingerprint
* The license is for attribution, but this is not required.
** Developers and designers that emailed Templarian the source .design icons to be added into the package. PNGs also accepted, but may take longer to be added.
*** Icons I've copied so closely you want to attribute them and are also under the CC license.
Contact
- http://templarian.com/
- admin[@]templarian[.]com
* Does not apply to copyrighted logos
- Skype
- Facebook
- Twitter
- etc...

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="PowerToys Rules" Description="Based on Microsoft Minimum Recomended Rules and customized to include other required rules. These rules focus on the most critical problems in your code, including potential security holes, application crashes, and other important logic and design errors. It is recommended to include this rule set in any custom rule set you create for your projects." ToolsVersion="15.0">
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
<Rule Id="CA1001" Action="Warning" />
<Rule Id="CA1009" Action="Warning" />
<Rule Id="CA1016" Action="Warning" />
<Rule Id="CA1033" Action="Warning" />
<Rule Id="CA1049" Action="Warning" />
<Rule Id="CA1060" Action="Warning" />
<Rule Id="CA1061" Action="Warning" />
<Rule Id="CA1063" Action="Warning" />
<Rule Id="CA1065" Action="Warning" />
<Rule Id="CA1301" Action="Warning" />
<Rule Id="CA1302" Action="Warning" />
<Rule Id="CA1303" Action="Warning" />
<Rule Id="CA1304" Action="Warning" />
<Rule Id="CA1306" Action="Warning" />
<Rule Id="CA1307" Action="Warning" />
<Rule Id="CA1308" Action="Warning" />
<Rule Id="CA1309" Action="Warning" />
<Rule Id="CA1400" Action="Warning" />
<Rule Id="CA1401" Action="Warning" />
<Rule Id="CA1403" Action="Warning" />
<Rule Id="CA1404" Action="Warning" />
<Rule Id="CA1405" Action="Warning" />
<Rule Id="CA1410" Action="Warning" />
<Rule Id="CA1415" Action="Warning" />
<Rule Id="CA1821" Action="Warning" />
<Rule Id="CA1900" Action="Warning" />
<Rule Id="CA1901" Action="Warning" />
<Rule Id="CA2002" Action="Warning" />
<Rule Id="CA2100" Action="Warning" />
<Rule Id="CA2101" Action="Warning" />
<Rule Id="CA2108" Action="Warning" />
<Rule Id="CA2111" Action="Warning" />
<Rule Id="CA2112" Action="Warning" />
<Rule Id="CA2114" Action="Warning" />
<Rule Id="CA2116" Action="Warning" />
<Rule Id="CA2117" Action="Warning" />
<Rule Id="CA2122" Action="Warning" />
<Rule Id="CA2123" Action="Warning" />
<Rule Id="CA2124" Action="Warning" />
<Rule Id="CA2126" Action="Warning" />
<Rule Id="CA2131" Action="Warning" />
<Rule Id="CA2132" Action="Warning" />
<Rule Id="CA2133" Action="Warning" />
<Rule Id="CA2134" Action="Warning" />
<Rule Id="CA2137" Action="Warning" />
<Rule Id="CA2138" Action="Warning" />
<Rule Id="CA2140" Action="Warning" />
<Rule Id="CA2141" Action="Warning" />
<Rule Id="CA2146" Action="Warning" />
<Rule Id="CA2147" Action="Warning" />
<Rule Id="CA2149" Action="Warning" />
<Rule Id="CA2200" Action="Warning" />
<Rule Id="CA2202" Action="Warning" />
<Rule Id="CA2207" Action="Warning" />
<Rule Id="CA2212" Action="Warning" />
<Rule Id="CA2213" Action="Warning" />
<Rule Id="CA2214" Action="Warning" />
<Rule Id="CA2216" Action="Warning" />
<Rule Id="CA2220" Action="Warning" />
<Rule Id="CA2229" Action="Warning" />
<Rule Id="CA2231" Action="Warning" />
<Rule Id="CA2232" Action="Warning" />
<Rule Id="CA2235" Action="Warning" />
<Rule Id="CA2236" Action="Warning" />
<Rule Id="CA2237" Action="Warning" />
<Rule Id="CA2238" Action="Warning" />
<Rule Id="CA2240" Action="Warning" />
<Rule Id="CA2241" Action="Warning" />
<Rule Id="CA2242" Action="Warning" />
</Rules>
</RuleSet>

View file

@ -0,0 +1,21 @@
{
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
"settings": {
"documentationRules": {
"companyName": "Microsoft Corporation",
"copyrightText": "Copyright (c) {companyName}\r\nThe {companyName} licenses this file to you under the MIT license.\r\nSee the LICENSE file in the project root for more information. Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/",
"xmlHeader": false,
"headerDecoration": "",
"fileNamingConvention": "metadata",
"documentInterfaces": false,
"documentExposedElements": false,
"documentInternalElements": false
},
"layoutRules": {
"newlineAtEndOfFile": "require"
},
"orderingRules": {
"usingDirectivesPlacement": "outsideNamespace"
}
}
}

View file

@ -0,0 +1,283 @@
// 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.Windows.Interop;
using Microsoft.Win32;
using WindowWalker.Components;
using WindowWalker.MVVMHelpers;
namespace WindowWalker.ViewModels
{
internal class WindowWalkerViewModel : PropertyChangedBase
{
private readonly HotKeyHandler _hotKeyHandler;
private readonly List<string> _hints = new List<string>()
{
"search...",
"you can reinvoke this app using CTRL + WIN",
};
private string _searchText = string.Empty;
private List<SearchResult> _results = new List<SearchResult>();
private SearchResult _selectedWindow;
private bool _windowVisibility = true;
private string _hint = string.Empty;
private int _hintCounter = 0;
private void WireCommands()
{
SwitchToSelectedWindowCommand = new RelayCommand(SwitchToSelectedWindow)
{
IsEnabled = true,
};
WindowNavigateToNextResultCommand = new RelayCommand(WindowNavigateToNextResult)
{
IsEnabled = true,
};
WindowNavigateToPreviousResultCommand = new RelayCommand(WindowNavigateToPreviousResult)
{
IsEnabled = true,
};
WindowHideCommand = new RelayCommand(WindowHide)
{
IsEnabled = true,
};
WindowShowCommand = new RelayCommand(WindowShow)
{
IsEnabled = true,
};
}
public string SearchText
{
get => _searchText;
set
{
if (_searchText != value)
{
_searchText = value;
SearchController.Instance.SearchText = value;
NotifyPropertyChanged("SearchText");
}
}
}
public string Hint
{
get => _hint;
set
{
if (_hint != value)
{
_hint = value;
NotifyPropertyChanged("Hint");
}
}
}
public List<SearchResult> Results
{
get => _results;
set
{
if (_results != value)
{
_results = value;
NotifyPropertyChanged("Results");
}
}
}
public SearchResult SelectedWindowResult
{
get => _selectedWindow;
set
{
if (_selectedWindow != value)
{
_selectedWindow = value;
WindowResultSelected();
NotifyPropertyChanged("SelectedWindowResult");
}
}
}
public IntPtr Hwnd { get; private set; }
public bool WindowVisibility
{
get
{
return _windowVisibility;
}
set
{
if (_windowVisibility != value)
{
_windowVisibility = value;
NotifyPropertyChanged("WindowVisibility");
}
}
}
public RelayCommand SwitchToSelectedWindowCommand
{
get;
private set;
}
public RelayCommand WindowNavigateToNextResultCommand
{
get;
private set;
}
public RelayCommand WindowNavigateToPreviousResultCommand
{
get;
private set;
}
public RelayCommand WindowHideCommand
{
get;
private set;
}
public RelayCommand WindowShowCommand
{
get;
private set;
}
public WindowWalkerViewModel(System.Windows.Window mainWindow)
{
// The path to the key where Windows looks for startup applications
RegistryKey rkApp = Registry.CurrentUser.OpenSubKey(
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
// Path to launch shortcut
string startPath = Environment.GetFolderPath(Environment.SpecialFolder.Programs)
+ @"\WindowWalker\WindowWalker.appref-ms";
rkApp.SetValue("WindowWalker", startPath);
rkApp.Close();
SearchController.Instance.OnSearchResultUpdate += SearchResultUpdated;
OpenWindows.Instance.UpdateOpenWindowsList();
Hwnd = new WindowInteropHelper(mainWindow).Handle;
LivePreview.SetWindowExlusionFromLivePreview(Hwnd);
_hotKeyHandler = new HotKeyHandler(mainWindow);
_hotKeyHandler.OnHotKeyPressed += HotKeyPressedHandler;
_hints.AddRange(Commands.GetTips());
Hint = _hints[_hintCounter];
WireCommands();
}
private void HotKeyPressedHandler(object sender, EventArgs e)
{
if (SearchText == string.Empty && WindowVisibility)
{
WindowHide();
}
else
{
WindowShow();
}
}
private void WindowResultSelected()
{
if (SelectedWindowResult != null)
{
LivePreview.ActivateLivePreview(SelectedWindowResult.Result.Hwnd, Hwnd);
}
}
private void WindowNavigateToPreviousResult()
{
if (SelectedWindowResult == null && Results.Count > 0)
{
SelectedWindowResult = Results.Last();
return;
}
if (Results.Count > 0)
{
SelectedWindowResult = Results[(Results.IndexOf(SelectedWindowResult) + Results.Count - 1) % Results.Count];
}
}
private void WindowNavigateToNextResult()
{
if (SelectedWindowResult == null && Results.Count > 0)
{
SelectedWindowResult = Results.First();
return;
}
if (Results.Count > 0)
{
SelectedWindowResult = Results[(Results.IndexOf(SelectedWindowResult) + 1) % Results.Count];
}
}
private void WindowHide()
{
LivePreview.DeactivateLivePreview();
WindowVisibility = false;
ApplicationUpdates.InstallUpdateSyncWithInfo();
}
private void WindowShow()
{
_hintCounter = (_hintCounter + 1) % _hints.Count;
Hint = _hints[_hintCounter];
SearchText = string.Empty;
OpenWindows.Instance.UpdateOpenWindowsList();
LivePreview.DeactivateLivePreview();
WindowVisibility = true;
InteropAndHelpers.SetForegroundWindow(Hwnd);
}
public void SwitchToSelectedWindow()
{
if (SearchText.StartsWith(":"))
{
LivePreview.DeactivateLivePreview();
WindowHide();
Commands.ProcessCommand(SearchText);
}
else if (SelectedWindowResult != null)
{
LivePreview.DeactivateLivePreview();
SelectedWindowResult.Result.SwitchToWindow();
WindowHide();
}
else if (Results != null && Results.Count > 0)
{
LivePreview.DeactivateLivePreview();
Results.First().Result.SwitchToWindow();
WindowHide();
}
}
private void SearchResultUpdated(object sender, SearchController.SearchResultUpdateEventArgs e)
{
Results = SearchController.Instance.SearchMatches;
}
}
}

View file

@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B9BDF8BE-FED7-49B5-A7AE-DD4D1CA2D9EB}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WindowWalker</RootNamespace>
<AssemblyName>WindowWalker</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\..\..\x64\Debug\modules\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<CodeAnalysisRuleSet>..\..\..\..\codeAnalysis\Rules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\modules\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<RunCodeAnalysis>false</RunCodeAnalysis>
<CodeAnalysisRuleSet>..\..\..\..\codeAnalysis\Rules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup />
<PropertyGroup />
<PropertyGroup />
<PropertyGroup>
<ApplicationIcon>windowwalker.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="MaterialDesignColors, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\packages\MaterialDesignColors.1.2.1\lib\net45\MaterialDesignColors.dll</HintPath>
</Reference>
<Reference Include="MaterialDesignThemes.Wpf, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\packages\MaterialDesignThemes.3.0.0\lib\net45\MaterialDesignThemes.Wpf.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Components\ApplicationUpdates.cs" />
<Compile Include="Components\Command.cs" />
<Compile Include="Components\Commands.cs" />
<Compile Include="Components\FuzzyMatchingUnitTest.cs" />
<Compile Include="Components\Point.cs" />
<Compile Include="Components\SearchString.cs" />
<Compile Include="Components\Settings.cs" />
<Compile Include="Components\SettingsManager.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="MVVMHelpers\PropertyChangedBase.cs" />
<Compile Include="MVVMHelpers\RelayCommand.cs" />
<Compile Include="ViewModels\WindowWalkerViewModel.cs" />
<Compile Include="WindowSearchResultToXamlConverter.cs" />
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Components\FuzzyMatching.cs" />
<Compile Include="Components\InteropAndHelpers.cs" />
<Compile Include="Components\LivePreview.cs" />
<Compile Include="Components\OpenWindows.cs" />
<Compile Include="Components\Window.cs" />
<Compile Include="Components\SearchController.cs" />
<Compile Include="Components\SearchResult.cs" />
<Compile Include="HotKeyHandler.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="Resources\Icons.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Resources\IconsNonShared.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
<Resource Include="Resources\Entypo.ttf" />
<AdditionalFiles Include="StyleCop.json" />
<None Include="Window Walker_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\failedIcon.jpg" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Resource Include="windowwalker.ico" />
</ItemGroup>
<ItemGroup>
<PublishFile Include="WindowWalker.pdb">
<Visible>False</Visible>
<Group>
</Group>
<TargetPath>
</TargetPath>
<PublishState>Include</PublishState>
<IncludeHash>True</IncludeHash>
<FileType>File</FileType>
</PublishFile>
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\WindowsIcons-license.txt" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Entypo-license.txt" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\..\..\..\..\packages\StyleCop.Analyzers.1.1.118\analyzers\dotnet\cs\StyleCop.Analyzers.CodeFixes.dll" />
<Analyzer Include="..\..\..\..\..\packages\StyleCop.Analyzers.1.1.118\analyzers\dotnet\cs\StyleCop.Analyzers.dll" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\..\..\packages\MaterialDesignThemes.3.0.0\build\MaterialDesignThemes.targets" Condition="Exists('..\..\..\..\..\packages\MaterialDesignThemes.3.0.0\build\MaterialDesignThemes.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\..\..\packages\MaterialDesignThemes.3.0.0\build\MaterialDesignThemes.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\..\packages\MaterialDesignThemes.3.0.0\build\MaterialDesignThemes.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -0,0 +1,99 @@
// 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.Globalization;
using System.IO;
using System.Security;
using System.Windows.Data;
using System.Windows.Markup;
using System.Xml;
using WindowWalker.Components;
namespace WindowWalker
{
/// <summary>
/// Converts a string containing valid XAML into WPF objects.
/// </summary>
[ValueConversion(typeof(SearchResult), typeof(object))]
public sealed class WindowSearchResultToXamlConverter : IValueConverter
{
/// <summary>
/// Converts a string containing valid XAML into WPF objects.
/// </summary>
/// <param name="value">The string to convert.</param>
/// <param name="targetType">This parameter is not used.</param>
/// <param name="parameter">This parameter is not used.</param>
/// <param name="culture">This parameter is not used.</param>
/// <returns>A WPF object.</returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is SearchResult input)
{
string withTags;
if (input.BestScoreSource == SearchResult.TextType.ProcessName)
{
withTags = input.Result.Title;
withTags += $" ({InsertHighlightTags(input.Result.ProcessName, input.SearchMatchesInProcessName)})";
}
else
{
withTags = InsertHighlightTags(input.Result.Title, input.SearchMatchesInTitle);
withTags += $" ({input.Result.ProcessName})";
}
withTags = SecurityElement.Escape(withTags);
withTags = withTags.Replace("[[", "<Run Background=\"{DynamicResource SecondaryAccentBrush}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"{DynamicResource SecondaryAccentForegroundBrush}\">").
Replace("]]", "</Run>");
string wrappedInput = string.Format("<TextBlock xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" TextWrapping=\"Wrap\">{0}</TextBlock>", withTags);
using (StringReader stringReader = new StringReader(wrappedInput))
{
using (XmlReader xmlReader = XmlReader.Create(stringReader))
{
return XamlReader.Load(xmlReader);
}
}
}
return null;
}
/// <summary>
/// Converts WPF framework objects into a XAML string.
/// </summary>
/// <param name="value">The WPF Famework object to convert.</param>
/// <param name="targetType">This parameter is not used.</param>
/// <param name="parameter">This parameter is not used.</param>
/// <param name="culture">This parameter is not used.</param>
/// <returns>A string containg XAML.</returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException("This converter cannot be used in two-way binding.");
}
private string InsertHighlightTags(string content, List<int> indexes)
{
int offset = 0;
var result = content.Replace("[[", "**").Replace("]]", "**");
string startTag = "[[";
string stopTag = "]]";
foreach (var index in indexes)
{
result = result.Insert(index + offset, startTag);
result = result.Insert(index + offset + startTag.Length + 1, stopTag);
offset += startTag.Length + stopTag.Length;
}
return result;
}
}
}

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MaterialDesignColors" version="1.2.1" targetFramework="net472" />
<package id="MaterialDesignThemes" version="3.0.0" targetFramework="net472" />
<package id="StyleCop.Analyzers" version="1.1.118" targetFramework="net472" developmentDependency="true" />
</packages>

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View file

@ -0,0 +1,32 @@
1 VERSIONINFO
FILEVERSION 0,1,0,0
PRODUCTVERSION 0,1,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Company Name"
VALUE "FileDescription", "$projectname$ Module"
VALUE "FileVersion", "0.1.0.0"
VALUE "InternalName", "$projectname$"
VALUE "LegalCopyright", "Copyright (C) 2019 Company Name"
VALUE "OriginalFilename", "$projectname$.dll"
VALUE "ProductName", "$projectname$"
VALUE "ProductVersion", "0.1.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View file

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{51d3bd1f-07a8-48eb-b2a0-0a249cd4e1a6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>WindowWalker</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>WindowWalker</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="trace.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">pch.h</PrecompiledHeaderFile>
</ClCompile>
<ClCompile Include="trace.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)src\common\common.vcxproj">
<Project>{74485049-c722-400f-abe5-86ac52d929b3}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WindowWalker.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,204 @@
#include "pch.h"
#include <interface/powertoy_module_interface.h>
#include <interface/lowlevel_keyboard_event_data.h>
#include <interface/win_hook_event_data.h>
#include <common/settings_objects.h>
#include "trace.h"
extern "C" IMAGE_DOS_HEADER __ImageBase;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Trace::RegisterProvider();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
Trace::UnregisterProvider();
break;
}
return TRUE;
}
// The PowerToy name that will be shown in the settings.
const static wchar_t* MODULE_NAME = L"Window Walker";
// Add a description that will we shown in the module settings page.
const static wchar_t* MODULE_DESC = L"Alt+Tab but with search";
// These are the properties shown in the Settings page.
struct ModuleSettings
{
} g_settings;
// Implement the PowerToy Module Interface and all the required methods.
class WindowWalker : public PowertoyModuleIface
{
private:
// The PowerToy state.
bool m_enabled = true;
// Load initial settings from the persisted values.
void init_settings();
// Handle to the Window Walker app we launch
HANDLE m_hProcess;
public:
// Constructor
WindowWalker()
{
init_settings();
};
// Destroy the powertoy and free memory
virtual void destroy() override
{
delete this;
}
// Return the display name of the powertoy, this will be cached by the runner
virtual const wchar_t* get_name() override
{
return MODULE_NAME;
}
// Return array of the names of all events that this powertoy listens for, with
// nullptr as the last element of the array. Nullptr can also be retured for empty
// list.
virtual const wchar_t** get_events() override
{
static const wchar_t* events[] = { nullptr };
return events;
}
// Return JSON with the configuration options.
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
{
HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
// Create a Settings object.
PowerToysSettings::Settings settings(hinstance, get_name());
settings.set_description(MODULE_DESC);
return settings.serialize_to_buffer(buffer, buffer_size);
}
// Signal from the Settings editor to call a custom action.
// This can be used to spawn more complex editors.
virtual void call_custom_action(const wchar_t* action) override
{
static UINT custom_action_num_calls = 0;
try
{
// Parse the action values, including name.
PowerToysSettings::CustomActionObject action_object =
PowerToysSettings::CustomActionObject::from_json_string(action);
}
catch (std::exception&)
{
// Improper JSON.
}
}
// Called by the runner to pass the updated settings values as a serialized JSON.
virtual void set_config(const wchar_t* config) override
{
try
{
// Parse the input JSON string.
PowerToysSettings::PowerToyValues values =
PowerToysSettings::PowerToyValues::from_json_string(config);
values.save_to_settings_file();
}
catch (std::exception&)
{
// Improper JSON.
}
}
// Enable the powertoy
virtual void enable()
{
SHELLEXECUTEINFO sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
sei.lpFile = L"modules\\WindowWalker.exe";
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
m_hProcess = sei.hProcess;
m_enabled = true;
}
// Disable the powertoy
virtual void disable()
{
if (m_enabled)
{
TerminateProcess(m_hProcess, 1);
}
m_enabled = false;
}
// Returns if the powertoys is enabled
virtual bool is_enabled() override
{
return m_enabled;
}
// Handle incoming event, data is event-specific
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override
{
if (wcscmp(name, ll_keyboard) == 0)
{
auto& event = *(reinterpret_cast<LowlevelKeyboardEvent*>(data));
// Return 1 if the keypress is to be suppressed (not forwarded to Windows),
// otherwise return 0.
return 0;
}
else if (wcscmp(name, win_hook_event) == 0)
{
auto& event = *(reinterpret_cast<WinHookEvent*>(data));
// Return value is ignored
return 0;
}
return 0;
}
// This methods are part of an experimental features not fully supported yet
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override
{
}
virtual void signal_system_menu_action(const wchar_t* name) override
{
}
};
// Load the settings file.
void WindowWalker::init_settings()
{
try
{
// Load and parse the settings file for this PowerToy.
PowerToysSettings::PowerToyValues settings =
PowerToysSettings::PowerToyValues::load_from_settings_file(WindowWalker::get_name());
}
catch (std::exception&)
{
// Error while loading from the settings file. Let default values stay as they are.
}
}
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
{
return new WindowWalker();
}

View file

@ -0,0 +1,2 @@
#include "pch.h"
#pragma comment(lib, "windowsapp")

View file

@ -0,0 +1,6 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <common/common.h>
#include <ProjectTelemetry.h>
#include <shellapi.h>

View file

View file

@ -0,0 +1,29 @@
#include "pch.h"
#include "trace.h"
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
// {38e8889b-9731-53f5-e901-e8a7c1753074}
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
void Trace::RegisterProvider()
{
TraceLoggingRegister(g_hProvider);
}
void Trace::UnregisterProvider()
{
TraceLoggingUnregister(g_hProvider);
}
void Trace::MyEvent()
{
TraceLoggingWrite(
g_hProvider,
"PowerToyName_MyEvent",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
}

View file

@ -0,0 +1,9 @@
#pragma once
class Trace
{
public:
static void RegisterProvider();
static void UnregisterProvider();
static void MyEvent();
};