Skip to content

Commit a74ad6d

Browse files
authored
Merge branch 'dev' into quickswitch
2 parents 3aec2a1 + 5cc3124 commit a74ad6d

File tree

7 files changed

+79
-21
lines changed

7 files changed

+79
-21
lines changed

Diff for: Flow.Launcher.Plugin/Result.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,12 @@ public string BadgeIcoPath
128128
/// <summary>
129129
/// Delegate to load an icon for this result.
130130
/// </summary>
131-
public IconDelegate Icon { get; set; }
131+
public IconDelegate Icon = null;
132132

133133
/// <summary>
134134
/// Delegate to load an icon for the badge of this result.
135135
/// </summary>
136-
public IconDelegate BadgeIcon { get; set; }
136+
public IconDelegate BadgeIcon = null;
137137

138138
/// <summary>
139139
/// Information for Glyph Icon (Prioritized than IcoPath/Icon if user enable Glyph Icons)

Diff for: Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/en.xaml

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<system:String x:Key="flowlauncher_plugin_processkiller_kill_all_count">kill {0} processes</system:String>
1111
<system:String x:Key="flowlauncher_plugin_processkiller_kill_instances">kill all instances</system:String>
1212

13+
<system:String x:Key="flowlauncher_plugin_processkiller_show_window_title">Show title for processes with visible windows</system:String>
1314
<system:String x:Key="flowlauncher_plugin_processkiller_put_visible_window_process_top">Put processes with visible windows on the top</system:String>
1415

1516
</ResourceDictionary>

Diff for: Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs

+30-8
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ private List<Result> CreateResultsFromQuery(Query query)
8181
// Filter processes based on search term
8282
var searchTerm = query.Search;
8383
var processlist = new List<ProcessResult>();
84-
var processWindowTitle = ProcessHelper.GetProcessesWithNonEmptyWindowTitle();
84+
var processWindowTitle =
85+
Settings.ShowWindowTitle || Settings.PutVisibleWindowProcessesTop ?
86+
ProcessHelper.GetProcessesWithNonEmptyWindowTitle() :
87+
new Dictionary<int, string>();
8588
if (string.IsNullOrWhiteSpace(searchTerm))
8689
{
8790
foreach (var p in allPocessList)
@@ -91,12 +94,22 @@ private List<Result> CreateResultsFromQuery(Query query)
9194
if (processWindowTitle.TryGetValue(p.Id, out var windowTitle))
9295
{
9396
// Add score to prioritize processes with visible windows
94-
// And use window title for those processes
95-
processlist.Add(new ProcessResult(p, Settings.PutVisibleWindowProcessesTop ? 200 : 0, windowTitle, null, progressNameIdTitle));
97+
// Use window title for those processes if enabled
98+
processlist.Add(new ProcessResult(
99+
p,
100+
Settings.PutVisibleWindowProcessesTop ? 200 : 0,
101+
Settings.ShowWindowTitle ? windowTitle : progressNameIdTitle,
102+
null,
103+
progressNameIdTitle));
96104
}
97105
else
98106
{
99-
processlist.Add(new ProcessResult(p, 0, progressNameIdTitle, null, progressNameIdTitle));
107+
processlist.Add(new ProcessResult(
108+
p,
109+
0,
110+
progressNameIdTitle,
111+
null,
112+
progressNameIdTitle));
100113
}
101114
}
102115
}
@@ -115,13 +128,17 @@ private List<Result> CreateResultsFromQuery(Query query)
115128
if (score > 0)
116129
{
117130
// Add score to prioritize processes with visible windows
118-
// And use window title for those processes
131+
// Use window title for those processes
119132
if (Settings.PutVisibleWindowProcessesTop)
120133
{
121134
score += 200;
122135
}
123-
processlist.Add(new ProcessResult(p, score, windowTitle,
124-
score == windowTitleMatch.Score ? windowTitleMatch : null, progressNameIdTitle));
136+
processlist.Add(new ProcessResult(
137+
p,
138+
score,
139+
Settings.ShowWindowTitle ? windowTitle : progressNameIdTitle,
140+
score == windowTitleMatch.Score ? windowTitleMatch : null,
141+
progressNameIdTitle));
125142
}
126143
}
127144
else
@@ -130,7 +147,12 @@ private List<Result> CreateResultsFromQuery(Query query)
130147
var score = processNameIdMatch.Score;
131148
if (score > 0)
132149
{
133-
processlist.Add(new ProcessResult(p, score, progressNameIdTitle, processNameIdMatch, progressNameIdTitle));
150+
processlist.Add(new ProcessResult(
151+
p,
152+
score,
153+
progressNameIdTitle,
154+
processNameIdMatch,
155+
progressNameIdTitle));
134156
}
135157
}
136158
}

Diff for: Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs

+32-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
using Microsoft.Win32.SafeHandles;
2-
using System;
1+
using System;
2+
using System.Collections.Concurrent;
33
using System.Collections.Generic;
44
using System.Diagnostics;
55
using System.Linq;
66
using System.Text;
7+
using System.Threading.Tasks;
8+
using Microsoft.Win32.SafeHandles;
79
using Windows.Win32;
810
using Windows.Win32.Foundation;
911
using Windows.Win32.System.Threading;
@@ -72,8 +74,21 @@ public List<Process> GetMatchingProcesses()
7274
/// </summary>
7375
public static unsafe Dictionary<int, string> GetProcessesWithNonEmptyWindowTitle()
7476
{
75-
var processDict = new Dictionary<int, string>();
77+
// Collect all window handles
78+
var windowHandles = new List<HWND>();
7679
PInvoke.EnumWindows((hWnd, _) =>
80+
{
81+
if (PInvoke.IsWindowVisible(hWnd))
82+
{
83+
windowHandles.Add(hWnd);
84+
}
85+
return true;
86+
}, IntPtr.Zero);
87+
88+
// Concurrently process each window handle
89+
var processDict = new ConcurrentDictionary<int, string>();
90+
var processedProcessIds = new ConcurrentDictionary<int, byte>();
91+
Parallel.ForEach(windowHandles, hWnd =>
7792
{
7893
var windowTitle = GetWindowTitle(hWnd);
7994
if (!string.IsNullOrWhiteSpace(windowTitle) && PInvoke.IsWindowVisible(hWnd))
@@ -82,20 +97,26 @@ public static unsafe Dictionary<int, string> GetProcessesWithNonEmptyWindowTitle
8297
var result = PInvoke.GetWindowThreadProcessId(hWnd, &processId);
8398
if (result == 0u || processId == 0u)
8499
{
85-
return false;
100+
return;
86101
}
87102

88-
var process = Process.GetProcessById((int)processId);
89-
if (!processDict.ContainsKey((int)processId))
103+
// Ensure each process ID is processed only once
104+
if (processedProcessIds.TryAdd((int)processId, 0))
90105
{
91-
processDict.Add((int)processId, windowTitle);
106+
try
107+
{
108+
var process = Process.GetProcessById((int)processId);
109+
processDict.TryAdd((int)processId, windowTitle);
110+
}
111+
catch
112+
{
113+
// Handle exceptions (e.g., process exited)
114+
}
92115
}
93116
}
117+
});
94118

95-
return true;
96-
}, IntPtr.Zero);
97-
98-
return processDict;
119+
return new Dictionary<int, string>(processDict);
99120
}
100121

101122
private static unsafe string GetWindowTitle(HWND hwnd)

Diff for: Plugins/Flow.Launcher.Plugin.ProcessKiller/Settings.cs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
{
33
public class Settings
44
{
5+
public bool ShowWindowTitle { get; set; } = true;
6+
57
public bool PutVisibleWindowProcessesTop { get; set; } = false;
68
}
79
}

Diff for: Plugins/Flow.Launcher.Plugin.ProcessKiller/ViewModels/SettingsViewModel.cs

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ public SettingsViewModel(Settings settings)
99
Settings = settings;
1010
}
1111

12+
public bool ShowWindowTitle
13+
{
14+
get => Settings.ShowWindowTitle;
15+
set => Settings.ShowWindowTitle = value;
16+
}
17+
1218
public bool PutVisibleWindowProcessesTop
1319
{
1420
get => Settings.PutVisibleWindowProcessesTop;

Diff for: Plugins/Flow.Launcher.Plugin.ProcessKiller/Views/SettingsControl.xaml

+6
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@
1212
<Grid.ColumnDefinitions />
1313
<Grid.RowDefinitions>
1414
<RowDefinition Height="auto" />
15+
<RowDefinition Height="auto" />
1516
</Grid.RowDefinitions>
1617
<CheckBox
1718
Grid.Row="0"
1819
Margin="{StaticResource SettingPanelItemRightTopBottomMargin}"
20+
Content="{DynamicResource flowlauncher_plugin_processkiller_show_window_title}"
21+
IsChecked="{Binding ShowWindowTitle}" />
22+
<CheckBox
23+
Grid.Row="1"
24+
Margin="{StaticResource SettingPanelItemRightTopBottomMargin}"
1925
Content="{DynamicResource flowlauncher_plugin_processkiller_put_visible_window_process_top}"
2026
IsChecked="{Binding PutVisibleWindowProcessesTop}" />
2127
</Grid>

0 commit comments

Comments
 (0)