1
+ using System ;
1
2
using System . Collections . Generic ;
2
3
using System . Linq ;
3
- using Flow . Launcher . Infrastructure ;
4
+ using System . Windows . Controls ;
5
+ using Flow . Launcher . Plugin . ProcessKiller . ViewModels ;
6
+ using Flow . Launcher . Plugin . ProcessKiller . Views ;
4
7
5
8
namespace Flow . Launcher . Plugin . ProcessKiller
6
9
{
7
- public class Main : IPlugin , IPluginI18n , IContextMenu
10
+ public class Main : IPlugin , IPluginI18n , IContextMenu , ISettingProvider
8
11
{
9
- private ProcessHelper processHelper = new ProcessHelper ( ) ;
12
+ private readonly ProcessHelper processHelper = new ( ) ;
10
13
11
14
private static PluginInitContext _context ;
12
15
16
+ internal Settings Settings ;
17
+
18
+ private SettingsViewModel _viewModel ;
19
+
13
20
public void Init ( PluginInitContext context )
14
21
{
15
22
_context = context ;
23
+ Settings = context . API . LoadSettingJsonStorage < Settings > ( ) ;
24
+ _viewModel = new SettingsViewModel ( Settings ) ;
16
25
}
17
26
18
27
public List < Result > Query ( Query query )
@@ -48,7 +57,7 @@ public List<Result> LoadContextMenus(Result result)
48
57
{
49
58
foreach ( var p in similarProcesses )
50
59
{
51
- processHelper . TryKill ( p ) ;
60
+ processHelper . TryKill ( _context , p ) ;
52
61
}
53
62
54
63
return true ;
@@ -62,45 +71,102 @@ public List<Result> LoadContextMenus(Result result)
62
71
63
72
private List < Result > CreateResultsFromQuery ( Query query )
64
73
{
65
- string termToSearch = query . Search ;
66
- var processlist = processHelper . GetMatchingProcesses ( termToSearch ) ;
67
-
68
- if ( ! processlist . Any ( ) )
74
+ // Get all non-system processes
75
+ var allPocessList = processHelper . GetMatchingProcesses ( ) ;
76
+ if ( ! allPocessList . Any ( ) )
69
77
{
70
78
return null ;
71
79
}
72
80
73
- var results = new List < Result > ( ) ;
81
+ // Filter processes based on search term
82
+ var searchTerm = query . Search ;
83
+ var processlist = new List < ProcessResult > ( ) ;
84
+ var processWindowTitle = ProcessHelper . GetProcessesWithNonEmptyWindowTitle ( ) ;
85
+ if ( string . IsNullOrWhiteSpace ( searchTerm ) )
86
+ {
87
+ foreach ( var p in allPocessList )
88
+ {
89
+ var progressNameIdTitle = ProcessHelper . GetProcessNameIdTitle ( p ) ;
74
90
91
+ if ( processWindowTitle . TryGetValue ( p . Id , out var windowTitle ) )
92
+ {
93
+ // 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 ) ) ;
96
+ }
97
+ else
98
+ {
99
+ processlist . Add ( new ProcessResult ( p , 0 , progressNameIdTitle , null , progressNameIdTitle ) ) ;
100
+ }
101
+ }
102
+ }
103
+ else
104
+ {
105
+ foreach ( var p in allPocessList )
106
+ {
107
+ var progressNameIdTitle = ProcessHelper . GetProcessNameIdTitle ( p ) ;
108
+
109
+ if ( processWindowTitle . TryGetValue ( p . Id , out var windowTitle ) )
110
+ {
111
+ // Get max score from searching process name, window title and process id
112
+ var windowTitleMatch = _context . API . FuzzySearch ( searchTerm , windowTitle ) ;
113
+ var processNameIdMatch = _context . API . FuzzySearch ( searchTerm , progressNameIdTitle ) ;
114
+ var score = Math . Max ( windowTitleMatch . Score , processNameIdMatch . Score ) ;
115
+ if ( score > 0 )
116
+ {
117
+ // Add score to prioritize processes with visible windows
118
+ // And use window title for those processes
119
+ if ( Settings . PutVisibleWindowProcessesTop )
120
+ {
121
+ score += 200 ;
122
+ }
123
+ processlist . Add ( new ProcessResult ( p , score , windowTitle ,
124
+ score == windowTitleMatch . Score ? windowTitleMatch : null , progressNameIdTitle ) ) ;
125
+ }
126
+ }
127
+ else
128
+ {
129
+ var processNameIdMatch = _context . API . FuzzySearch ( searchTerm , progressNameIdTitle ) ;
130
+ var score = processNameIdMatch . Score ;
131
+ if ( score > 0 )
132
+ {
133
+ processlist . Add ( new ProcessResult ( p , score , progressNameIdTitle , processNameIdMatch , progressNameIdTitle ) ) ;
134
+ }
135
+ }
136
+ }
137
+ }
138
+
139
+ var results = new List < Result > ( ) ;
75
140
foreach ( var pr in processlist )
76
141
{
77
142
var p = pr . Process ;
78
143
var path = processHelper . TryGetProcessFilename ( p ) ;
79
144
results . Add ( new Result ( )
80
145
{
81
146
IcoPath = path ,
82
- Title = p . ProcessName + " - " + p . Id ,
147
+ Title = pr . Title ,
148
+ TitleToolTip = pr . Tooltip ,
83
149
SubTitle = path ,
84
- TitleHighlightData = StringMatcher . FuzzySearch ( termToSearch , p . ProcessName ) . MatchData ,
150
+ TitleHighlightData = pr . TitleMatch ? . MatchData ,
85
151
Score = pr . Score ,
86
152
ContextData = p . ProcessName ,
87
153
AutoCompleteText = $ "{ _context . CurrentPluginMetadata . ActionKeyword } { Plugin . Query . TermSeparator } { p . ProcessName } ",
88
154
Action = ( c ) =>
89
155
{
90
- processHelper . TryKill ( p ) ;
91
- // Re-query to refresh process list
92
- _context . API . ChangeQuery ( query . RawQuery , true ) ;
93
- return true ;
156
+ processHelper . TryKill ( _context , p ) ;
157
+ _context . API . ReQuery ( ) ;
158
+ return false ;
94
159
}
95
160
} ) ;
96
161
}
97
162
163
+ // Order results by process name for processes without visible windows
98
164
var sortedResults = results . OrderBy ( x => x . Title ) . ToList ( ) ;
99
165
100
166
// When there are multiple results AND all of them are instances of the same executable
101
167
// add a quick option to kill them all at the top of the results.
102
168
var firstResult = sortedResults . FirstOrDefault ( x => ! string . IsNullOrEmpty ( x . SubTitle ) ) ;
103
- if ( processlist . Count > 1 && ! string . IsNullOrEmpty ( termToSearch ) && sortedResults . All ( r => r . SubTitle == firstResult ? . SubTitle ) )
169
+ if ( processlist . Count > 1 && ! string . IsNullOrEmpty ( searchTerm ) && sortedResults . All ( r => r . SubTitle == firstResult ? . SubTitle ) )
104
170
{
105
171
sortedResults . Insert ( 1 , new Result ( )
106
172
{
@@ -112,16 +178,20 @@ private List<Result> CreateResultsFromQuery(Query query)
112
178
{
113
179
foreach ( var p in processlist )
114
180
{
115
- processHelper . TryKill ( p . Process ) ;
181
+ processHelper . TryKill ( _context , p . Process ) ;
116
182
}
117
- // Re-query to refresh process list
118
- _context . API . ChangeQuery ( query . RawQuery , true ) ;
119
- return true ;
183
+ _context . API . ReQuery ( ) ;
184
+ return false ;
120
185
}
121
186
} ) ;
122
187
}
123
188
124
189
return sortedResults ;
125
190
}
191
+
192
+ public Control CreateSettingPanel ( )
193
+ {
194
+ return new SettingsControl ( _viewModel ) ;
195
+ }
126
196
}
127
197
}
0 commit comments