1+ using System ;
12using System . Collections . Generic ;
23using 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 ;
47
58namespace Flow . Launcher . Plugin . ProcessKiller
69{
7- public class Main : IPlugin , IPluginI18n , IContextMenu
10+ public class Main : IPlugin , IPluginI18n , IContextMenu , ISettingProvider
811 {
9- private ProcessHelper processHelper = new ProcessHelper ( ) ;
12+ private readonly ProcessHelper processHelper = new ( ) ;
1013
1114 private static PluginInitContext _context ;
1215
16+ internal Settings Settings ;
17+
18+ private SettingsViewModel _viewModel ;
19+
1320 public void Init ( PluginInitContext context )
1421 {
1522 _context = context ;
23+ Settings = context . API . LoadSettingJsonStorage < Settings > ( ) ;
24+ _viewModel = new SettingsViewModel ( Settings ) ;
1625 }
1726
1827 public List < Result > Query ( Query query )
@@ -48,7 +57,7 @@ public List<Result> LoadContextMenus(Result result)
4857 {
4958 foreach ( var p in similarProcesses )
5059 {
51- processHelper . TryKill ( p ) ;
60+ processHelper . TryKill ( _context , p ) ;
5261 }
5362
5463 return true ;
@@ -62,45 +71,102 @@ public List<Result> LoadContextMenus(Result result)
6271
6372 private List < Result > CreateResultsFromQuery ( Query query )
6473 {
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 ( ) )
6977 {
7078 return null ;
7179 }
7280
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 ) ;
7490
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 > ( ) ;
75140 foreach ( var pr in processlist )
76141 {
77142 var p = pr . Process ;
78143 var path = processHelper . TryGetProcessFilename ( p ) ;
79144 results . Add ( new Result ( )
80145 {
81146 IcoPath = path ,
82- Title = p . ProcessName + " - " + p . Id ,
147+ Title = pr . Title ,
148+ TitleToolTip = pr . Tooltip ,
83149 SubTitle = path ,
84- TitleHighlightData = StringMatcher . FuzzySearch ( termToSearch , p . ProcessName ) . MatchData ,
150+ TitleHighlightData = pr . TitleMatch ? . MatchData ,
85151 Score = pr . Score ,
86152 ContextData = p . ProcessName ,
87153 AutoCompleteText = $ "{ _context . CurrentPluginMetadata . ActionKeyword } { Plugin . Query . TermSeparator } { p . ProcessName } ",
88154 Action = ( c ) =>
89155 {
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 ;
94159 }
95160 } ) ;
96161 }
97162
163+ // Order results by process name for processes without visible windows
98164 var sortedResults = results . OrderBy ( x => x . Title ) . ToList ( ) ;
99165
100166 // When there are multiple results AND all of them are instances of the same executable
101167 // add a quick option to kill them all at the top of the results.
102168 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 ) )
104170 {
105171 sortedResults . Insert ( 1 , new Result ( )
106172 {
@@ -112,16 +178,20 @@ private List<Result> CreateResultsFromQuery(Query query)
112178 {
113179 foreach ( var p in processlist )
114180 {
115- processHelper . TryKill ( p . Process ) ;
181+ processHelper . TryKill ( _context , p . Process ) ;
116182 }
117- // Re-query to refresh process list
118- _context . API . ChangeQuery ( query . RawQuery , true ) ;
119- return true ;
183+ _context . API . ReQuery ( ) ;
184+ return false ;
120185 }
121186 } ) ;
122187 }
123188
124189 return sortedResults ;
125190 }
191+
192+ public Control CreateSettingPanel ( )
193+ {
194+ return new SettingsControl ( _viewModel ) ;
195+ }
126196 }
127197}
0 commit comments