36
38
public static class WindowUtils
38
static IEnumerable<string> BadPrefixes {
40
static string RemapFile {
41
get { return Path.Combine (Services.Paths.UserDataDirectory, "RemapFile"); }
44
public static IEnumerable<string> BadPrefixes {
42
yield return "python ";
53
yield return "python(\\d.\\d)?";
57
static Dictionary<string, string> RemapDictionary { get; set; }
46
59
static List<Application> application_list;
47
60
static bool application_list_update_needed;
62
static Dictionary<int, string> exec_lines = new Dictionary<int, string> ();
63
static DateTime last_update = new DateTime (0);
49
65
static WindowUtils ()
51
67
Wnck.Screen.Default.WindowClosed += delegate {
63
79
Wnck.Screen.Default.ApplicationClosed += delegate {
64
80
application_list_update_needed = true;
83
BuildRemapDictionary ();
86
static void BuildRemapDictionary ()
88
if (!File.Exists (RemapFile)) {
89
RemapDictionary = BuildDefaultRemapDictionary ();
91
StreamWriter writer = null;
93
writer = new StreamWriter (RemapFile);
94
writer.WriteLine ("# Docky Remap File");
95
writer.WriteLine ("# Add key value pairs following dictionary syntax");
96
writer.WriteLine ("# key, value");
97
writer.WriteLine ("# key, altKey, value");
98
writer.WriteLine ("# Lines starting with # are comments, otherwise # is a valid character");
100
foreach (KeyValuePair<string, string> kvp in RemapDictionary) {
101
writer.WriteLine ("{0}, {1}", kvp.Key, kvp.Value);
109
RemapDictionary = new Dictionary<string, string> ();
111
StreamReader reader = null;
113
reader = new StreamReader (RemapFile);
116
while (!reader.EndOfStream) {
117
line = reader.ReadLine ();
118
if (line.StartsWith ("#") || !line.Contains (","))
120
string [] array = line.Split (',');
121
if (array.Length < 2 || array [0].Length == 0)
124
string val = array [array.Length - 1].Trim ().ToLower ();
125
if (string.IsNullOrEmpty (val))
128
for (int i=0; i < array.Length - 1; i++) {
129
string key = array [i].Trim ().ToLower ();
130
if (string.IsNullOrEmpty (key))
132
RemapDictionary [key] = val;
138
Log.Error ("Could not read remap file");
139
RemapDictionary = BuildDefaultRemapDictionary ();
147
static Dictionary<string, string> BuildDefaultRemapDictionary ()
149
Dictionary<string, string> remapDict = new Dictionary<string, string> ();
150
remapDict ["banshee.exe"] = "banshee";
151
remapDict ["banshee-1"] = "banshee";
152
remapDict ["azureus"] = "vuze";
153
remapDict ["thunderbird-3.0"] = "thunderbird";
154
remapDict ["thunderbird-bin"] = "thunderbird";
95
186
public static string CmdLineForPid (int pid)
97
188
StreamReader reader;
189
string cmdline = null;
100
192
string procPath = new [] { "/proc", pid.ToString (), "cmdline" }.Aggregate (Path.Combine);
101
193
reader = new StreamReader (procPath);
102
cmdline = reader.ReadLine ();
194
cmdline = reader.ReadLine ().Replace (Convert.ToChar (0x0), ' ');
104
196
reader.Dispose ();
105
} catch { return null; }
122
214
if (string.IsNullOrEmpty (exec))
125
foreach (string s in BadPrefixes) {
126
if (exec.StartsWith (s)) {
127
exec = exec.Substring (s.Length);
217
exec = ProcessExecString (exec);
218
if (string.IsNullOrEmpty (exec))
223
foreach (KeyValuePair<int, string> kvp in exec_lines) {
224
if (kvp.Value != null && kvp.Value.Contains (exec)) {
225
foreach (Application app in GetApplications ()) {
229
if (app.Pid == kvp.Key || app.Windows.Any (w => w.Pid == kvp.Key)) {
230
if (app.Windows.Any (win => !win.IsSkipTasklist))
131
exec = exec.Split (' ')[0];
133
Application out_app = null;
240
static void UpdateExecList ()
242
if ((DateTime.UtcNow - last_update).TotalMilliseconds < 200) return;
134
246
foreach (string dir in Directory.GetDirectories ("/proc")) {
137
248
try { pid = Convert.ToInt32 (Path.GetFileName (dir)); }
138
249
catch { continue; }
141
252
if (string.IsNullOrEmpty (exec_line))
144
if (exec_line.Contains (exec)) {
255
if (exec_line.Contains ("java") && exec_line.Contains ("jar")) {
145
256
foreach (Application app in GetApplications ()) {
149
if (app.Pid == pid) {
150
if (app.Windows.Select (win => !win.IsSkipTasklist).Any ())
260
if (app.Pid == pid || app.Windows.Any (w => w.Pid == pid)) {
261
foreach (Wnck.Window window in app.Windows.Where (win => !win.IsSkipTasklist)) {
262
exec_line = window.ClassGroup.ResClass;
265
if (exec_line == "SWT")
266
exec_line = window.Name;
267
Console.WriteLine (exec_line);
274
exec_line = ProcessExecString (exec_line);
276
exec_lines [pid] = exec_line;
279
last_update = DateTime.UtcNow;
282
public static string ProcessExecString (string exec)
284
exec = exec.ToLower ().Trim ();
286
if (RemapDictionary.ContainsKey (exec))
287
return RemapDictionary [exec];
289
if (exec.StartsWith ("/")) {
290
string first_part = exec.Split (' ') [0];
291
int length = first_part.Length;
292
first_part = first_part.Split ('/').Last ();
294
if (length < exec.Length)
295
first_part = first_part + " " + exec.Substring (length + 1);
297
if (RemapDictionary.ContainsKey (first_part)) {
298
return RemapDictionary [first_part];
302
string [] parts = exec.Split (' ');
303
for (int i = 0; i < parts.Length; i++) {
304
if (parts [i].StartsWith ("-"))
307
if (parts [i].Contains ("/"))
308
parts [i] = parts [i].Split ('/').Last ();
311
foreach (string prefix in BadPrefixes) {
312
regex = new Regex (string.Format ("^{0}$", prefix), RegexOptions.IgnoreCase);
313
if (regex.IsMatch (parts [i])) {
319
if (!string.IsNullOrEmpty (parts [i])) {
320
string out_val = parts [i];
321
if (RemapDictionary.ContainsKey (out_val))
322
out_val = RemapDictionary [out_val];
169
335
public static void PerformLogicalClick (IEnumerable<Application> apps)
171
bool not_in_viewport = !apps.Any (app => app.Windows
172
.Any (w => !w.IsSkipTasklist && w.IsInViewport (Wnck.Screen.Default.ActiveWorkspace)));
173
bool urgent = apps.Any (app => app.Windows.Any (w => w.NeedsAttention ()));
337
List<Window> stack = new List<Window> (Wnck.Screen.Default.WindowsStacked);
338
IEnumerable<Window> windows = apps
339
.SelectMany (app => app.Windows)
340
.OrderByDescending (w => stack.IndexOf (w));
342
bool not_in_viewport = !windows.Any (w => !w.IsSkipTasklist && w.IsInViewport (w.Screen.ActiveWorkspace));
343
bool urgent = windows.Any (w => w.NeedsAttention ());
175
345
if (not_in_viewport || urgent) {
176
foreach (Wnck.Application application in apps) {
177
foreach (Wnck.Window window in application.Windows) {
178
if (urgent && !window.NeedsAttention ())
180
if (!window.IsSkipTasklist) {
181
window.CenterAndFocusWindow ();
346
foreach (Wnck.Window window in windows) {
347
if (urgent && !window.NeedsAttention ())
349
if (!window.IsSkipTasklist) {
350
WindowControl.IntelligentFocusOffViewportWindow (window, windows);
188
List<Window> windows = new List<Window> ();
189
foreach (Wnck.Application app in apps)
190
windows.AddRange (app.Windows);
192
356
switch (GetClickAction (apps)) {
193
357
case ClickAction.Focus:
194
358
WindowControl.FocusWindows (windows);