Do

Merge lp:~jassmith/do/wink into lp:do

Proposed by Jason Smith
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jassmith/do/wink
Merge into: lp:do
Diff against target: None lines
To merge this branch: bzr merge lp:~jassmith/do/wink
Reviewer Review Type Date Requested Status
Do Core Team Pending
Review via email: mp+4738@code.launchpad.net
To post a comment you must log in.
lp:~jassmith/do/wink updated
1108. By Jason Smith

using blocks

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Do.Interface.Linux.Docky/Do.Interface.Linux.Docky.mdp'
2--- Do.Interface.Linux.Docky/Do.Interface.Linux.Docky.mdp 2009-03-07 22:50:28 +0000
3+++ Do.Interface.Linux.Docky/Do.Interface.Linux.Docky.mdp 2009-03-20 20:43:06 +0000
4@@ -32,11 +32,9 @@
5 <File name="src/Docky.Interface/Docky.Interface.Painters/SummonModeRenderer.cs" subtype="Code" buildaction="Compile" />
6 <File name="src/Docky.Utilities/DockPreferences.cs" subtype="Code" buildaction="Compile" />
7 <File name="src/Docky.Utilities/GtkUtils.cs" subtype="Code" buildaction="Compile" />
8- <File name="src/Docky.Utilities/WindowUtils.cs" subtype="Code" buildaction="Compile" />
9 <File name="src/XLib/X11Atoms.cs" subtype="Code" buildaction="Compile" />
10 <File name="src/XLib/Xlib.cs" subtype="Code" buildaction="Compile" />
11 <File name="src/Docky.Interface/IRightClickable.cs" subtype="Code" buildaction="Compile" />
12- <File name="src/Docky.Utilities/WindowControl.cs" subtype="Code" buildaction="Compile" />
13 <File name="src/Docky.Interface/UpdateRequestArgs.cs" subtype="Code" buildaction="Compile" />
14 <File name="src/Docky.Interface/DockAnimationState.cs" subtype="Code" buildaction="Compile" />
15 <File name="src/Docky.Interface/ItemPositionProvider.cs" subtype="Code" buildaction="Compile" />
16
17=== modified file 'Do.Interface.Linux.Docky/Makefile.am'
18--- Do.Interface.Linux.Docky/Makefile.am 2009-03-07 22:50:28 +0000
19+++ Do.Interface.Linux.Docky/Makefile.am 2009-03-20 20:43:06 +0000
20@@ -66,8 +66,6 @@
21 src/Docky.Utilities/DockOrientation.cs \
22 src/Docky.Utilities/DockPreferences.cs \
23 src/Docky.Utilities/GtkUtils.cs \
24- src/Docky.Utilities/WindowControl.cs \
25- src/Docky.Utilities/WindowUtils.cs \
26 src/XLib/X11Atoms.cs \
27 src/XLib/Xlib.cs
28
29@@ -90,6 +88,7 @@
30
31 PROJECT_REFERENCES = \
32 Do.Interface.Linux \
33+ Do.Interface.Wink \
34 Do.Platform \
35 Do.Universe
36
37
38=== modified file 'Do.Interface.Linux.Docky/src/Docky.Core/Docky.Core.Default/ItemsService.cs'
39--- Do.Interface.Linux.Docky/src/Docky.Core/Docky.Core.Default/ItemsService.cs 2009-03-11 02:40:59 +0000
40+++ Do.Interface.Linux.Docky/src/Docky.Core/Docky.Core.Default/ItemsService.cs 2009-03-20 20:43:06 +0000
41@@ -26,6 +26,7 @@
42
43 using Do;
44 using Do.Interface;
45+using Do.Interface.Wink;
46 using Do.Universe;
47 using Do.Platform;
48
49
50=== modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/AbstractDockItem.cs'
51--- Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/AbstractDockItem.cs 2009-03-02 05:26:10 +0000
52+++ Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/AbstractDockItem.cs 2009-03-20 20:43:06 +0000
53@@ -24,6 +24,7 @@
54 using Gtk;
55
56 using Do.Interface;
57+using Do.Interface.Wink;
58 using Do.Platform;
59
60 using Docky.Utilities;
61
62=== modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ApplicationDockItem.cs'
63--- Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ApplicationDockItem.cs 2009-03-12 01:09:56 +0000
64+++ Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ApplicationDockItem.cs 2009-03-20 20:43:06 +0000
65@@ -27,6 +27,7 @@
66 using Mono.Unix;
67
68 using Do.Interface.CairoUtils;
69+using Do.Interface.Wink;
70 using Do.Platform;
71 using Do.Interface;
72 using Do.Universe;
73
74=== modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ItemDockItem.cs'
75--- Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ItemDockItem.cs 2009-03-08 03:26:43 +0000
76+++ Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ItemDockItem.cs 2009-03-20 20:43:06 +0000
77@@ -29,6 +29,7 @@
78 using Do.Universe;
79 using Do.Universe.Common;
80 using Do.Interface;
81+using Do.Interface.Wink;
82 using Do.Interface.CairoUtils;
83
84 using Docky.Interface.Menus;
85
86=== modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/WnckDockItem.cs'
87--- Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/WnckDockItem.cs 2009-03-10 04:35:21 +0000
88+++ Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/WnckDockItem.cs 2009-03-20 20:43:06 +0000
89@@ -26,6 +26,7 @@
90
91 using Do.Platform;
92 using Do.Universe;
93+using Do.Interface.Wink;
94 using Do.Universe.Common;
95 using Do.Interface;
96 using Do.Interface.CairoUtils;
97
98=== modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Menus/WindowMenuButtonArgs.cs'
99--- Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Menus/WindowMenuButtonArgs.cs 2009-03-07 22:50:28 +0000
100+++ Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Menus/WindowMenuButtonArgs.cs 2009-03-20 20:43:06 +0000
101@@ -17,14 +17,13 @@
102 //
103
104 using System;
105-
106 using Gdk;
107-
108 using Wnck;
109
110 using Docky.Utilities;
111
112 using Do.Interface;
113+using Do.Interface.Wink;
114
115 namespace Docky.Interface.Menus
116 {
117
118=== modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/ItemPositionProvider.cs'
119--- Do.Interface.Linux.Docky/src/Docky.Interface/ItemPositionProvider.cs 2009-03-19 04:16:01 +0000
120+++ Do.Interface.Linux.Docky/src/Docky.Interface/ItemPositionProvider.cs 2009-03-20 20:43:06 +0000
121@@ -274,7 +274,7 @@
122 // g(x) == a term used to move the ends of the zoom inward. Precalculated that the edges should be 66% of the current
123 // value. The center is 100%. (1 - offsetPercent) == 0,1 distance from center
124 // The .66 value comes from the area under the curve. Dont as me to explain it too much because it's too clever for me
125- offset = offset * (zoomInPercent - 1) * ((1 - offsetPercent) * (1 - .66) + .66);
126+ offset = offset * (zoomInPercent - 1) * (1 - offsetPercent / 3);
127 }
128
129 if (cursorOrientedPosition > centerOrientedPosition) {
130
131=== modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Util.cs'
132--- Do.Interface.Linux.Docky/src/Docky.Interface/Util.cs 2009-03-07 23:43:30 +0000
133+++ Do.Interface.Linux.Docky/src/Docky.Interface/Util.cs 2009-03-20 20:43:06 +0000
134@@ -31,12 +31,6 @@
135
136 namespace Docky.Interface
137 {
138- public enum ClickAction {
139- Focus,
140- Minimize,
141- Restore,
142- None,
143- }
144
145 public enum IconSource {
146 Statistics,
147
148=== removed file 'Do.Interface.Linux.Docky/src/Docky.Utilities/WindowControl.cs'
149--- Do.Interface.Linux.Docky/src/Docky.Utilities/WindowControl.cs 2009-03-02 06:42:16 +0000
150+++ Do.Interface.Linux.Docky/src/Docky.Utilities/WindowControl.cs 1970-01-01 00:00:00 +0000
151@@ -1,248 +0,0 @@
152-// WindowControl.cs
153-//
154-// Copyright (C) 2008 GNOME Do
155-//
156-// This program is free software: you can redistribute it and/or modify
157-// it under the terms of the GNU General Public License as published by
158-// the Free Software Foundation, either version 3 of the License, or
159-// (at your option) any later version.
160-//
161-// This program is distributed in the hope that it will be useful,
162-// but WITHOUT ANY WARRANTY; without even the implied warranty of
163-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
164-// GNU General Public License for more details.
165-//
166-// You should have received a copy of the GNU General Public License
167-// along with this program. If not, see <http://www.gnu.org/licenses/>.
168-//
169-
170-using System;
171-using System.Collections.Generic;
172-using System.Linq;
173-
174-using Wnck;
175-
176-namespace Docky.Utilities
177-{
178-
179-
180- public static class WindowControl
181- {
182-
183- const int SleepTime = 10;
184-
185- /// <summary>
186- /// Handles intelligent minimize/restoring of windows. If one or more windows is minimized, it restores
187- /// all windows. If more all are visible, it minimizes. This operation only takes into account windows
188- /// on the current workspace (by design).
189- /// </summary>
190- /// <param name="windows">
191- /// A <see cref="IEnumerable"/>
192- /// </param>
193- public static void MinimizeRestoreWindows (IEnumerable<Window> windows)
194- {
195- bool restore = false;
196- foreach (Window w in windows) {
197- if (w.IsMinimized) {
198- restore = true;
199- break;
200- }
201- }
202- if (restore)
203- RestoreWindows (windows);
204- else
205- MinimizeWindows (windows);
206- }
207-
208- /// <summary>
209- /// Minimizes every window in the list if it is not minimized
210- /// </summary>
211- /// <param name="windows">
212- /// A <see cref="IEnumerable"/>
213- /// </param>
214- public static void MinimizeWindows (IEnumerable<Window> windows)
215- {
216- foreach (Window window in windows) {
217- if (window.IsInViewport (window.Screen.ActiveWorkspace) && !window.IsMinimized) {
218- window.Minimize ();
219- System.Threading.Thread.Sleep (SleepTime);
220- }
221- }
222- }
223-
224- /// <summary>
225- /// Restores every window in the list that is minimized
226- /// </summary>
227- /// <param name="windows">
228- /// A <see cref="IEnumerable"/>
229- /// </param>
230- public static void RestoreWindows (IEnumerable<Window> windows)
231- {
232- foreach (Window window in windows.Reverse ()) {
233- if (window.IsInViewport (window.Screen.ActiveWorkspace) && window.IsMinimized) {
234- window.Unminimize (Gtk.Global.CurrentEventTime);
235- System.Threading.Thread.Sleep (SleepTime);
236- }
237- }
238- }
239-
240- public static void FocusWindows (IEnumerable<Window> windows)
241- {
242- foreach (Window window in windows.Reverse ()) {
243- if (window.IsInViewport (window.Screen.ActiveWorkspace) && !window.IsMinimized) {
244- window.CenterAndFocusWindow ();
245- System.Threading.Thread.Sleep (SleepTime);
246- }
247- }
248-
249- if (windows.Count () <= 1)
250- return;
251-
252- // we do this to make sure our active window is also at the front... Its a tricky thing to do.
253- // sometimes compiz plays badly. This hacks around it
254- uint time = Gtk.Global.CurrentEventTime + 200;
255- GLib.Timeout.Add (200, delegate {
256- windows.Where (w => w.IsInViewport (w.Screen.ActiveWorkspace) && !w.IsMinimized).First ().Activate (time);
257- return false;
258- });
259- }
260-
261- public static void FocusWindows (Window window)
262- {
263- FocusWindows (new [] {window});
264- }
265-
266- public static void IntelligentFocusOffViewportWindow (Window targetWindow, IEnumerable<Window> additionalWindows)
267- {
268- foreach (Window window in additionalWindows.Reverse ()) {
269- if (!window.IsMinimized && WindowsShareViewport (targetWindow, window)) {
270- window.CenterAndFocusWindow ();
271- System.Threading.Thread.Sleep (SleepTime);
272- }
273- }
274-
275- targetWindow.CenterAndFocusWindow ();
276-
277- if (additionalWindows.Count () <= 1)
278- return;
279-
280- // we do this to make sure our active window is also at the front... Its a tricky thing to do.
281- // sometimes compiz plays badly. This hacks around it
282- uint time = Gtk.Global.CurrentEventTime + 200;
283- GLib.Timeout.Add (200, delegate {
284- targetWindow.Activate (time);
285- return false;
286- });
287- }
288-
289- static bool WindowsShareViewport (Wnck.Window first, Wnck.Window second)
290- {
291- if (first == null || second == null) return false;
292-
293- Wnck.Workspace wksp = first.Workspace ?? second.Workspace;
294- if (wksp == null) return false;
295-
296- Gdk.Rectangle firstGeo, secondGeo;
297-
298- first.GetGeometry (out firstGeo.X, out firstGeo.Y, out firstGeo.Width, out firstGeo.Height);
299- second.GetGeometry (out secondGeo.X, out secondGeo.Y, out secondGeo.Width, out secondGeo.Height);
300-
301- firstGeo.X += wksp.ViewportX;
302- firstGeo.Y += wksp.ViewportY;
303-
304- secondGeo.X += wksp.ViewportX;
305- secondGeo.Y += wksp.ViewportY;
306-
307- int viewportWidth, viewportHeight;
308- viewportWidth = first.Screen.Width;
309- viewportHeight = first.Screen.Height;
310-
311- int firstViewportX = ((firstGeo.X + firstGeo.Width / 2) / viewportWidth) * viewportWidth;
312- int firstViewportY = ((firstGeo.Y + firstGeo.Height / 2) / viewportHeight) * viewportHeight;
313-
314- Gdk.Rectangle viewpRect = new Gdk.Rectangle (firstViewportX, firstViewportY,
315- viewportWidth, viewportHeight);
316-
317- return viewpRect.IntersectsWith (secondGeo);
318- }
319-
320- public static void CloseWindows (IEnumerable<Window> windows)
321- {
322- foreach (Window window in windows.Where (w => !w.IsSkipTasklist))
323- window.Close (Gtk.Global.CurrentEventTime);
324- }
325-
326- public static void CloseWindows (Window window)
327- {
328- CloseWindows (new [] {window});
329- }
330-
331- public static void MinimizeRestoreWindows (Window window)
332- {
333- MinimizeRestoreWindows (new [] {window});
334- }
335-
336- public static void MaximizeWindow (Window window)
337- {
338- window.Maximize ();
339- }
340-
341- /// <summary>
342- /// Moves the current viewport to the selected window and then raises it
343- /// </summary>
344- /// <param name="w">
345- /// A <see cref="Window"/>
346- /// </param>
347- public static void CenterAndFocusWindow (this Window w)
348- {
349- if (w == null)
350- return;
351-
352- if (!w.IsInViewport (w.Screen.ActiveWorkspace)) {
353- int viewX, viewY, viewW, viewH;
354- int midX, midY;
355- Screen scrn = w.Screen;
356- Workspace wsp = scrn.ActiveWorkspace;
357-
358- //get our windows geometry
359- w.GetGeometry (out viewX, out viewY, out viewW, out viewH);
360-
361- //we want to focus on where the middle of the window is
362- midX = viewX + (viewW / 2);
363- midY = viewY + (viewH / 2);
364-
365- //The positions given above are relative to the current viewport
366- //This makes them absolute
367- midX += wsp.ViewportX;
368- midY += wsp.ViewportY;
369-
370- //Check to make sure our middle didn't wrap
371- if (midX > wsp.Width) {
372- midX %= wsp.Width;
373- }
374-
375- if (midY > wsp.Height) {
376- midY %= wsp.Height;
377- }
378-
379- //take care of negative numbers (happens?)
380- while (midX < 0)
381- midX += wsp.Width;
382-
383- while (midY < 0)
384- midX += wsp.Height;
385-
386- scrn.MoveViewport (midX, midY);
387- }
388-
389- if (w.Workspace != null && w.Workspace != w.Screen.ActiveWorkspace)
390- w.Workspace.Activate (Gtk.Global.CurrentEventTime);
391-
392-
393- if (w.IsMinimized)
394- w.Unminimize (Gtk.Global.CurrentEventTime);
395-
396- w.Activate (Gtk.Global.CurrentEventTime);
397- }
398- }
399-}
400
401=== removed file 'Do.Interface.Linux.Docky/src/Docky.Utilities/WindowUtils.cs'
402--- Do.Interface.Linux.Docky/src/Docky.Utilities/WindowUtils.cs 2009-03-17 17:30:21 +0000
403+++ Do.Interface.Linux.Docky/src/Docky.Utilities/WindowUtils.cs 1970-01-01 00:00:00 +0000
404@@ -1,391 +0,0 @@
405-// WindowUtils.cs
406-//
407-// Copyright (C) 2008 GNOME Do
408-//
409-// This program is free software: you can redistribute it and/or modify
410-// it under the terms of the GNU General Public License as published by
411-// the Free Software Foundation, either version 3 of the License, or
412-// (at your option) any later version.
413-//
414-// This program is distributed in the hope that it will be useful,
415-// but WITHOUT ANY WARRANTY; without even the implied warranty of
416-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
417-// GNU General Public License for more details.
418-//
419-// You should have received a copy of the GNU General Public License
420-// along with this program. If not, see <http://www.gnu.org/licenses/>.
421-//
422-
423-using System;
424-using System.Collections.Generic;
425-using System.Diagnostics;
426-using System.IO;
427-using System.Linq;
428-using System.Text.RegularExpressions;
429-
430-using Do.Interface;
431-using Do.Universe;
432-using Do.Platform;
433-
434-using Docky.Interface;
435-
436-using Wnck;
437-
438-namespace Docky.Utilities
439-{
440-
441-
442- public static class WindowUtils
443- {
444- static string RemapFile {
445- get { return Path.Combine (Services.Paths.UserDataDirectory, "RemapFile"); }
446- }
447-
448- public static IEnumerable<string> BadPrefixes {
449- get {
450- yield return "gksu";
451- yield return "sudo";
452- yield return "java";
453- yield return "mono";
454- yield return "ruby";
455- yield return "padsp";
456- yield return "aoss";
457- yield return "python(\\d.\\d)?";
458- }
459- }
460-
461- static Dictionary<string, string> RemapDictionary { get; set; }
462-
463- static List<Application> application_list;
464- static bool application_list_update_needed;
465-
466- static Dictionary<int, string> exec_lines = new Dictionary<int, string> ();
467- static DateTime last_update = new DateTime (0);
468-
469- static WindowUtils ()
470- {
471- Wnck.Screen.Default.WindowClosed += delegate {
472- application_list_update_needed = true;
473- };
474-
475- Wnck.Screen.Default.WindowOpened += delegate {
476- application_list_update_needed = true;
477- };
478-
479- Wnck.Screen.Default.ApplicationOpened += delegate {
480- application_list_update_needed = true;
481- };
482-
483- Wnck.Screen.Default.ApplicationClosed += delegate {
484- application_list_update_needed = true;
485- };
486-
487- BuildRemapDictionary ();
488- }
489-
490- static void BuildRemapDictionary ()
491- {
492- if (!File.Exists (RemapFile)) {
493- RemapDictionary = BuildDefaultRemapDictionary ();
494-
495- StreamWriter writer = null;
496- try {
497- writer = new StreamWriter (RemapFile);
498- writer.WriteLine ("# Docky Remap File");
499- writer.WriteLine ("# Add key value pairs following dictionary syntax");
500- writer.WriteLine ("# key, value");
501- writer.WriteLine ("# key, altKey, value");
502- writer.WriteLine ("# Lines starting with # are comments, otherwise # is a valid character");
503-
504- foreach (KeyValuePair<string, string> kvp in RemapDictionary) {
505- writer.WriteLine ("{0}, {1}", kvp.Key, kvp.Value);
506- }
507- writer.Close ();
508- } finally {
509- if (writer != null)
510- writer.Dispose ();
511- }
512- } else {
513- RemapDictionary = new Dictionary<string, string> ();
514-
515- StreamReader reader = null;
516- try {
517- reader = new StreamReader (RemapFile);
518-
519- string line;
520- while (!reader.EndOfStream) {
521- line = reader.ReadLine ();
522- if (line.StartsWith ("#") || !line.Contains (","))
523- continue;
524- string [] array = line.Split (',');
525- if (array.Length < 2 || array [0].Length == 0)
526- continue;
527-
528- string val = array [array.Length - 1].Trim ().ToLower ();
529- if (string.IsNullOrEmpty (val))
530- continue;
531-
532- for (int i=0; i < array.Length - 1; i++) {
533- string key = array [i].Trim ().ToLower ();
534- if (string.IsNullOrEmpty (key))
535- continue;
536- RemapDictionary [key] = val;
537- }
538- }
539-
540- reader.Close ();
541- } catch {
542- Log.Error ("Could not read remap file");
543- RemapDictionary = BuildDefaultRemapDictionary ();
544- } finally {
545- if (reader != null)
546- reader.Dispose ();
547- }
548- }
549- }
550-
551- static Dictionary<string, string> BuildDefaultRemapDictionary ()
552- {
553- Dictionary<string, string> remapDict = new Dictionary<string, string> ();
554- remapDict ["banshee.exe"] = "banshee";
555- remapDict ["banshee-1"] = "banshee";
556- remapDict ["azureus"] = "vuze";
557- remapDict ["thunderbird-3.0"] = "thunderbird";
558- remapDict ["thunderbird-bin"] = "thunderbird";
559-
560- return remapDict;
561- }
562-
563- /// <summary>
564- /// Returns a list of all applications on the default screen
565- /// </summary>
566- /// <returns>
567- /// A <see cref="Application"/> array
568- /// </returns>
569- public static List<Application> GetApplications ()
570- {
571- if (application_list == null || application_list_update_needed) {
572- application_list = new List<Application> ();
573- foreach (Window w in Wnck.Screen.Default.Windows) {
574- if (!application_list.Contains (w.Application))
575- application_list.Add (w.Application);
576- }
577- }
578- return application_list;
579- }
580-
581- /// <summary>
582- /// Gets the command line excec string for a PID
583- /// </summary>
584- /// <param name="pid">
585- /// A <see cref="System.Int32"/>
586- /// </param>
587- /// <returns>
588- /// A <see cref="System.String"/>
589- /// </returns>
590- public static string CmdLineForPid (int pid)
591- {
592- StreamReader reader;
593- string cmdline = null;
594-
595- try {
596- string procPath = new [] { "/proc", pid.ToString (), "cmdline" }.Aggregate (Path.Combine);
597- reader = new StreamReader (procPath);
598- cmdline = reader.ReadLine ().Replace (Convert.ToChar (0x0), ' ');
599- reader.Close ();
600- reader.Dispose ();
601- } catch { }
602-
603- return cmdline;
604- }
605-
606- /// <summary>
607- /// Returns a list of applications that match an exec string
608- /// </summary>
609- /// <param name="exec">
610- /// A <see cref="System.String"/>
611- /// </param>
612- /// <returns>
613- /// A <see cref="List"/>
614- /// </returns>
615- public static List<Application> GetApplicationList (string exec)
616- {
617- List<Application> apps = new List<Application> ();
618- if (string.IsNullOrEmpty (exec))
619- return apps;
620-
621- exec = ProcessExecString (exec);
622- if (string.IsNullOrEmpty (exec))
623- return apps;
624-
625- UpdateExecList ();
626-
627- foreach (KeyValuePair<int, string> kvp in exec_lines) {
628- if (kvp.Value != null && kvp.Value.Contains (exec)) {
629- foreach (Application app in GetApplications ()) {
630- if (app == null)
631- continue;
632-
633- if (app.Pid == kvp.Key || app.Windows.Any (w => w.Pid == kvp.Key)) {
634- if (app.Windows.Any (win => !win.IsSkipTasklist))
635- apps.Add (app);
636- break;
637- }
638- }
639- }
640- }
641- return apps;
642- }
643-
644- static void UpdateExecList ()
645- {
646- if ((DateTime.UtcNow - last_update).TotalMilliseconds < 200) return;
647-
648- exec_lines.Clear ();
649-
650- foreach (string dir in Directory.GetDirectories ("/proc")) {
651- int pid;
652- try { pid = Convert.ToInt32 (Path.GetFileName (dir)); }
653- catch { continue; }
654-
655- string exec_line = CmdLineForPid (pid);
656- if (string.IsNullOrEmpty (exec_line))
657- continue;
658-
659- if (exec_line.Contains ("java") && exec_line.Contains ("jar")) {
660- foreach (Application app in GetApplications ()) {
661- if (app == null)
662- continue;
663-
664- if (app.Pid == pid || app.Windows.Any (w => w.Pid == pid)) {
665- foreach (Wnck.Window window in app.Windows.Where (win => !win.IsSkipTasklist)) {
666- exec_line = window.ClassGroup.ResClass;
667-
668- // Vuze is retarded
669- if (exec_line == "SWT")
670- exec_line = window.Name;
671- Console.WriteLine (exec_line);
672- break;
673- }
674- }
675- }
676- }
677-
678- exec_line = ProcessExecString (exec_line);
679-
680- exec_lines [pid] = exec_line;
681- }
682-
683- last_update = DateTime.UtcNow;
684- }
685-
686- public static string ProcessExecString (string exec)
687- {
688- exec = exec.ToLower ().Trim ();
689-
690- if (RemapDictionary.ContainsKey (exec))
691- return RemapDictionary [exec];
692-
693- if (exec.StartsWith ("/")) {
694- string first_part = exec.Split (' ') [0];
695- int length = first_part.Length;
696- first_part = first_part.Split ('/').Last ();
697-
698- if (length < exec.Length)
699- first_part = first_part + " " + exec.Substring (length + 1);
700-
701- if (RemapDictionary.ContainsKey (first_part)) {
702- return RemapDictionary [first_part];
703- }
704- }
705-
706- string [] parts = exec.Split (' ');
707- for (int i = 0; i < parts.Length; i++) {
708- if (parts [i].StartsWith ("-"))
709- continue;
710-
711- if (parts [i].Contains ("/"))
712- parts [i] = parts [i].Split ('/').Last ();
713-
714- Regex regex;
715- foreach (string prefix in BadPrefixes) {
716- regex = new Regex (string.Format ("^{0}$", prefix), RegexOptions.IgnoreCase);
717- if (regex.IsMatch (parts [i])) {
718- parts [i] = null;
719- break;
720- }
721- }
722-
723- if (!string.IsNullOrEmpty (parts [i])) {
724- string out_val = parts [i];
725- if (RemapDictionary.ContainsKey (out_val))
726- out_val = RemapDictionary [out_val];
727- return out_val;
728- }
729- }
730- return null;
731- }
732-
733- /// <summary>
734- /// Performs the "logical" click action on an entire group of applications
735- /// </summary>
736- /// <param name="apps">
737- /// A <see cref="IEnumerable"/>
738- /// </param>
739- public static void PerformLogicalClick (IEnumerable<Application> apps)
740- {
741- List<Window> stack = new List<Window> (Wnck.Screen.Default.WindowsStacked);
742- IEnumerable<Window> windows = apps
743- .SelectMany (app => app.Windows)
744- .OrderByDescending (w => stack.IndexOf (w));
745-
746- bool not_in_viewport = !windows.Any (w => !w.IsSkipTasklist && w.IsInViewport (w.Screen.ActiveWorkspace));
747- bool urgent = windows.Any (w => w.NeedsAttention ());
748-
749- if (not_in_viewport || urgent) {
750- foreach (Wnck.Window window in windows) {
751- if (urgent && !window.NeedsAttention ())
752- continue;
753- if (!window.IsSkipTasklist) {
754- WindowControl.IntelligentFocusOffViewportWindow (window, windows);
755- return;
756- }
757- }
758- }
759-
760- switch (GetClickAction (apps)) {
761- case ClickAction.Focus:
762- WindowControl.FocusWindows (windows);
763- break;
764- case ClickAction.Minimize:
765- WindowControl.MinimizeWindows (windows);
766- break;
767- case ClickAction.Restore:
768- WindowControl.RestoreWindows (windows);
769- break;
770- }
771- }
772-
773- static ClickAction GetClickAction (IEnumerable<Application> apps)
774- {
775- if (!apps.Any ())
776- return ClickAction.None;
777-
778- foreach (Wnck.Application app in apps) {
779- foreach (Wnck.Window window in app.Windows) {
780- if (window.IsMinimized && window.IsInViewport (Wnck.Screen.Default.ActiveWorkspace))
781- return ClickAction.Restore;
782- }
783- }
784-
785- foreach (Wnck.Application app in apps) {
786- foreach (Wnck.Window window in app.Windows) {
787- if (window.IsActive && window.IsInViewport (Wnck.Screen.Default.ActiveWorkspace))
788- return ClickAction.Minimize;
789- }
790- }
791-
792- return ClickAction.Focus;
793- }
794- }
795-}
796
797=== added directory 'Do.Interface.Wink'
798=== added file 'Do.Interface.Wink/Do.Interface.Wink.mdp'
799--- Do.Interface.Wink/Do.Interface.Wink.mdp 1970-01-01 00:00:00 +0000
800+++ Do.Interface.Wink/Do.Interface.Wink.mdp 2009-03-20 20:43:06 +0000
801@@ -0,0 +1,30 @@
802+<Project name="Do.Interface.Wink" fileversion="2.0" language="C#" targetFramework="3.5" ctype="DotNetProject">
803+ <Configurations active="Debug">
804+ <Configuration name="Debug" ctype="DotNetProjectConfiguration">
805+ <Output directory="bin/Debug" assembly="Do.Interface.Wnck" />
806+ <Build debugmode="True" target="Library" />
807+ <Execution runwithwarnings="True" consolepause="False" runtime="MsNet" />
808+ <EnvironmentVariables />
809+ <CodeGeneration compiler="Mcs" warninglevel="4" optimize="False" unsafecodeallowed="False" generateoverflowchecks="False" definesymbols="DEBUG" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
810+ </Configuration>
811+ <Configuration name="Release" ctype="DotNetProjectConfiguration">
812+ <Output directory="bin/Release" assembly="Do.Interface.Wnck" />
813+ <Build debugmode="False" target="Library" />
814+ <Execution runwithwarnings="True" consolepause="False" runtime="MsNet" />
815+ <CodeGeneration compiler="Mcs" warninglevel="4" optimize="False" unsafecodeallowed="False" generateoverflowchecks="False" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
816+ </Configuration>
817+ </Configurations>
818+ <Contents>
819+ <File name="src" subtype="Directory" buildaction="Compile" />
820+ <File name="src/Do.Interface.Wink" subtype="Directory" buildaction="Compile" />
821+ <File name="src/AssemblyInfo.cs" subtype="Code" buildaction="Compile" />
822+ <File name="src/Do.Interface.Wink/WindowControl.cs" subtype="Code" buildaction="Compile" />
823+ <File name="src/Do.Interface.Wink/WindowUtils.cs" subtype="Code" buildaction="Compile" />
824+ </Contents>
825+ <References>
826+ <ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
827+ <ProjectReference type="Gac" localcopy="True" refto="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
828+ <ProjectReference type="Gac" localcopy="True" refto="wnck-sharp, Version=2.20.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
829+ <ProjectReference type="Project" localcopy="True" refto="Do.Platform" />
830+ </References>
831+</Project>
832\ No newline at end of file
833
834=== added file 'Do.Interface.Wink/Makefile.am'
835--- Do.Interface.Wink/Makefile.am 1970-01-01 00:00:00 +0000
836+++ Do.Interface.Wink/Makefile.am 2009-03-20 23:06:10 +0000
837@@ -0,0 +1,27 @@
838+# Simple component buildsystem
839+include $(top_srcdir)/build.rules.mk
840+
841+ASSEMBLY = Do.Interface.Wink
842+TARGET = library
843+
844+PKG_CONFIG_FILES = do.interface.wink.pc
845+
846+FILES = \
847+ src/AssemblyInfo.cs \
848+ src/Do.Interface.Wink/WindowControl.cs \
849+ src/Do.Interface.Wink/WindowUtils.cs
850+
851+#RESOURCES = \
852+# Resources/Do.Interface.Wnck.addin.xml
853+
854+REFERENCES = \
855+ System \
856+ System.Core \
857+ $(GTK_SHARP_20_LIBS) \
858+ $(WNCK_SHARP_10_LIBS)
859+
860+PROJECT_REFERENCES = \
861+ Do.Platform
862+
863+#module_DATA += $(ASSEMBLY).dll.config
864+#EXTRA_DIST += $(ASSEMBLY).dll.config
865
866=== added file 'Do.Interface.Wink/do.interface.wink.pc.in'
867--- Do.Interface.Wink/do.interface.wink.pc.in 1970-01-01 00:00:00 +0000
868+++ Do.Interface.Wink/do.interface.wink.pc.in 2009-03-20 23:06:37 +0000
869@@ -0,0 +1,6 @@
870+Name: Do.Platform
871+Description: Linux specific interface to large scale interactions with windows via libwnck
872+Version: @ABI_VERSION@
873+
874+Requires: do.platform
875+Libs: -r:@expanded_libdir@/@PACKAGE@/Do.Interface.Wink.dll
876
877=== added directory 'Do.Interface.Wink/src'
878=== added file 'Do.Interface.Wink/src/AssemblyInfo.cs'
879--- Do.Interface.Wink/src/AssemblyInfo.cs 1970-01-01 00:00:00 +0000
880+++ Do.Interface.Wink/src/AssemblyInfo.cs 2009-03-20 20:43:06 +0000
881@@ -0,0 +1,42 @@
882+//
883+// Copyright (C) 2009 GNOME Do
884+//
885+// This program is free software: you can redistribute it and/or modify
886+// it under the terms of the GNU General Public License as published by
887+// the Free Software Foundation, either version 3 of the License, or
888+// (at your option) any later version.
889+//
890+// This program is distributed in the hope that it will be useful,
891+// but WITHOUT ANY WARRANTY; without even the implied warranty of
892+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
893+// GNU General Public License for more details.
894+//
895+// You should have received a copy of the GNU General Public License
896+// along with this program. If not, see <http://www.gnu.org/licenses/>.
897+//
898+using System.Reflection;
899+using System.Runtime.CompilerServices;
900+
901+// Information about this assembly is defined by the following attributes.
902+// Change them to the values specific to your project.
903+
904+[assembly: AssemblyTitle("Do.Interface.Wnck")]
905+[assembly: AssemblyDescription("")]
906+[assembly: AssemblyConfiguration("")]
907+[assembly: AssemblyCompany("")]
908+[assembly: AssemblyProduct("")]
909+[assembly: AssemblyCopyright("")]
910+[assembly: AssemblyTrademark("")]
911+[assembly: AssemblyCulture("")]
912+
913+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
914+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
915+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
916+
917+[assembly: AssemblyVersion("1.0.*")]
918+
919+// The following attributes are used to specify the signing key for the assembly,
920+// if desired. See the Mono documentation for more information about signing.
921+
922+[assembly: AssemblyDelaySign(false)]
923+[assembly: AssemblyKeyFile("")]
924
925=== added directory 'Do.Interface.Wink/src/Do.Interface.Wink'
926=== added file 'Do.Interface.Wink/src/Do.Interface.Wink/WindowControl.cs'
927--- Do.Interface.Wink/src/Do.Interface.Wink/WindowControl.cs 1970-01-01 00:00:00 +0000
928+++ Do.Interface.Wink/src/Do.Interface.Wink/WindowControl.cs 2009-03-20 20:43:06 +0000
929@@ -0,0 +1,248 @@
930+// WindowControl.cs
931+//
932+// Copyright (C) 2008 GNOME Do
933+//
934+// This program is free software: you can redistribute it and/or modify
935+// it under the terms of the GNU General Public License as published by
936+// the Free Software Foundation, either version 3 of the License, or
937+// (at your option) any later version.
938+//
939+// This program is distributed in the hope that it will be useful,
940+// but WITHOUT ANY WARRANTY; without even the implied warranty of
941+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
942+// GNU General Public License for more details.
943+//
944+// You should have received a copy of the GNU General Public License
945+// along with this program. If not, see <http://www.gnu.org/licenses/>.
946+//
947+
948+using System;
949+using System.Collections.Generic;
950+using System.Linq;
951+
952+using Wnck;
953+
954+namespace Do.Interface.Wink
955+{
956+
957+
958+ public static class WindowControl
959+ {
960+
961+ const int SleepTime = 10;
962+
963+ /// <summary>
964+ /// Handles intelligent minimize/restoring of windows. If one or more windows is minimized, it restores
965+ /// all windows. If more all are visible, it minimizes. This operation only takes into account windows
966+ /// on the current workspace (by design).
967+ /// </summary>
968+ /// <param name="windows">
969+ /// A <see cref="IEnumerable"/>
970+ /// </param>
971+ public static void MinimizeRestoreWindows (IEnumerable<Window> windows)
972+ {
973+ bool restore = false;
974+ foreach (Window w in windows) {
975+ if (w.IsMinimized) {
976+ restore = true;
977+ break;
978+ }
979+ }
980+ if (restore)
981+ RestoreWindows (windows);
982+ else
983+ MinimizeWindows (windows);
984+ }
985+
986+ /// <summary>
987+ /// Minimizes every window in the list if it is not minimized
988+ /// </summary>
989+ /// <param name="windows">
990+ /// A <see cref="IEnumerable"/>
991+ /// </param>
992+ public static void MinimizeWindows (IEnumerable<Window> windows)
993+ {
994+ foreach (Window window in windows) {
995+ if (window.IsInViewport (window.Screen.ActiveWorkspace) && !window.IsMinimized) {
996+ window.Minimize ();
997+ System.Threading.Thread.Sleep (SleepTime);
998+ }
999+ }
1000+ }
1001+
1002+ /// <summary>
1003+ /// Restores every window in the list that is minimized
1004+ /// </summary>
1005+ /// <param name="windows">
1006+ /// A <see cref="IEnumerable"/>
1007+ /// </param>
1008+ public static void RestoreWindows (IEnumerable<Window> windows)
1009+ {
1010+ foreach (Window window in windows.Reverse ()) {
1011+ if (window.IsInViewport (window.Screen.ActiveWorkspace) && window.IsMinimized) {
1012+ window.Unminimize (Gtk.Global.CurrentEventTime);
1013+ System.Threading.Thread.Sleep (SleepTime);
1014+ }
1015+ }
1016+ }
1017+
1018+ public static void FocusWindows (IEnumerable<Window> windows)
1019+ {
1020+ foreach (Window window in windows.Reverse ()) {
1021+ if (window.IsInViewport (window.Screen.ActiveWorkspace) && !window.IsMinimized) {
1022+ window.CenterAndFocusWindow ();
1023+ System.Threading.Thread.Sleep (SleepTime);
1024+ }
1025+ }
1026+
1027+ if (windows.Count () <= 1)
1028+ return;
1029+
1030+ // we do this to make sure our active window is also at the front... Its a tricky thing to do.
1031+ // sometimes compiz plays badly. This hacks around it
1032+ uint time = Gtk.Global.CurrentEventTime + 200;
1033+ GLib.Timeout.Add (200, delegate {
1034+ windows.Where (w => w.IsInViewport (w.Screen.ActiveWorkspace) && !w.IsMinimized).First ().Activate (time);
1035+ return false;
1036+ });
1037+ }
1038+
1039+ public static void FocusWindows (Window window)
1040+ {
1041+ FocusWindows (new [] {window});
1042+ }
1043+
1044+ public static void IntelligentFocusOffViewportWindow (Window targetWindow, IEnumerable<Window> additionalWindows)
1045+ {
1046+ foreach (Window window in additionalWindows.Reverse ()) {
1047+ if (!window.IsMinimized && WindowsShareViewport (targetWindow, window)) {
1048+ window.CenterAndFocusWindow ();
1049+ System.Threading.Thread.Sleep (SleepTime);
1050+ }
1051+ }
1052+
1053+ targetWindow.CenterAndFocusWindow ();
1054+
1055+ if (additionalWindows.Count () <= 1)
1056+ return;
1057+
1058+ // we do this to make sure our active window is also at the front... Its a tricky thing to do.
1059+ // sometimes compiz plays badly. This hacks around it
1060+ uint time = Gtk.Global.CurrentEventTime + 200;
1061+ GLib.Timeout.Add (200, delegate {
1062+ targetWindow.Activate (time);
1063+ return false;
1064+ });
1065+ }
1066+
1067+ static bool WindowsShareViewport (Wnck.Window first, Wnck.Window second)
1068+ {
1069+ if (first == null || second == null) return false;
1070+
1071+ Wnck.Workspace wksp = first.Workspace ?? second.Workspace;
1072+ if (wksp == null) return false;
1073+
1074+ Gdk.Rectangle firstGeo, secondGeo;
1075+
1076+ first.GetGeometry (out firstGeo.X, out firstGeo.Y, out firstGeo.Width, out firstGeo.Height);
1077+ second.GetGeometry (out secondGeo.X, out secondGeo.Y, out secondGeo.Width, out secondGeo.Height);
1078+
1079+ firstGeo.X += wksp.ViewportX;
1080+ firstGeo.Y += wksp.ViewportY;
1081+
1082+ secondGeo.X += wksp.ViewportX;
1083+ secondGeo.Y += wksp.ViewportY;
1084+
1085+ int viewportWidth, viewportHeight;
1086+ viewportWidth = first.Screen.Width;
1087+ viewportHeight = first.Screen.Height;
1088+
1089+ int firstViewportX = ((firstGeo.X + firstGeo.Width / 2) / viewportWidth) * viewportWidth;
1090+ int firstViewportY = ((firstGeo.Y + firstGeo.Height / 2) / viewportHeight) * viewportHeight;
1091+
1092+ Gdk.Rectangle viewpRect = new Gdk.Rectangle (firstViewportX, firstViewportY,
1093+ viewportWidth, viewportHeight);
1094+
1095+ return viewpRect.IntersectsWith (secondGeo);
1096+ }
1097+
1098+ public static void CloseWindows (IEnumerable<Window> windows)
1099+ {
1100+ foreach (Window window in windows.Where (w => !w.IsSkipTasklist))
1101+ window.Close (Gtk.Global.CurrentEventTime);
1102+ }
1103+
1104+ public static void CloseWindows (Window window)
1105+ {
1106+ CloseWindows (new [] {window});
1107+ }
1108+
1109+ public static void MinimizeRestoreWindows (Window window)
1110+ {
1111+ MinimizeRestoreWindows (new [] {window});
1112+ }
1113+
1114+ public static void MaximizeWindow (Window window)
1115+ {
1116+ window.Maximize ();
1117+ }
1118+
1119+ /// <summary>
1120+ /// Moves the current viewport to the selected window and then raises it
1121+ /// </summary>
1122+ /// <param name="w">
1123+ /// A <see cref="Window"/>
1124+ /// </param>
1125+ public static void CenterAndFocusWindow (this Window w)
1126+ {
1127+ if (w == null)
1128+ return;
1129+
1130+ if (!w.IsInViewport (w.Screen.ActiveWorkspace)) {
1131+ int viewX, viewY, viewW, viewH;
1132+ int midX, midY;
1133+ Screen scrn = w.Screen;
1134+ Workspace wsp = scrn.ActiveWorkspace;
1135+
1136+ //get our windows geometry
1137+ w.GetGeometry (out viewX, out viewY, out viewW, out viewH);
1138+
1139+ //we want to focus on where the middle of the window is
1140+ midX = viewX + (viewW / 2);
1141+ midY = viewY + (viewH / 2);
1142+
1143+ //The positions given above are relative to the current viewport
1144+ //This makes them absolute
1145+ midX += wsp.ViewportX;
1146+ midY += wsp.ViewportY;
1147+
1148+ //Check to make sure our middle didn't wrap
1149+ if (midX > wsp.Width) {
1150+ midX %= wsp.Width;
1151+ }
1152+
1153+ if (midY > wsp.Height) {
1154+ midY %= wsp.Height;
1155+ }
1156+
1157+ //take care of negative numbers (happens?)
1158+ while (midX < 0)
1159+ midX += wsp.Width;
1160+
1161+ while (midY < 0)
1162+ midX += wsp.Height;
1163+
1164+ scrn.MoveViewport (midX, midY);
1165+ }
1166+
1167+ if (w.Workspace != null && w.Workspace != w.Screen.ActiveWorkspace)
1168+ w.Workspace.Activate (Gtk.Global.CurrentEventTime);
1169+
1170+
1171+ if (w.IsMinimized)
1172+ w.Unminimize (Gtk.Global.CurrentEventTime);
1173+
1174+ w.Activate (Gtk.Global.CurrentEventTime);
1175+ }
1176+ }
1177+}
1178
1179=== added file 'Do.Interface.Wink/src/Do.Interface.Wink/WindowUtils.cs'
1180--- Do.Interface.Wink/src/Do.Interface.Wink/WindowUtils.cs 1970-01-01 00:00:00 +0000
1181+++ Do.Interface.Wink/src/Do.Interface.Wink/WindowUtils.cs 2009-03-20 20:43:06 +0000
1182@@ -0,0 +1,392 @@
1183+// WindowUtils.cs
1184+//
1185+// Copyright (C) 2008 GNOME Do
1186+//
1187+// This program is free software: you can redistribute it and/or modify
1188+// it under the terms of the GNU General Public License as published by
1189+// the Free Software Foundation, either version 3 of the License, or
1190+// (at your option) any later version.
1191+//
1192+// This program is distributed in the hope that it will be useful,
1193+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1194+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1195+// GNU General Public License for more details.
1196+//
1197+// You should have received a copy of the GNU General Public License
1198+// along with this program. If not, see <http://www.gnu.org/licenses/>.
1199+//
1200+
1201+using System;
1202+using System.Collections.Generic;
1203+using System.Diagnostics;
1204+using System.IO;
1205+using System.Linq;
1206+using System.Text.RegularExpressions;
1207+
1208+using Do.Platform;
1209+
1210+using Wnck;
1211+
1212+namespace Do.Interface.Wink
1213+{
1214+ public enum ClickAction {
1215+ Focus,
1216+ Minimize,
1217+ Restore,
1218+ None,
1219+ }
1220+
1221+ public static class WindowUtils
1222+ {
1223+ static string RemapFile {
1224+ get { return Path.Combine (Services.Paths.UserDataDirectory, "RemapFile"); }
1225+ }
1226+
1227+ public static IEnumerable<string> BadPrefixes {
1228+ get {
1229+ yield return "gksu";
1230+ yield return "sudo";
1231+ yield return "java";
1232+ yield return "mono";
1233+ yield return "ruby";
1234+ yield return "padsp";
1235+ yield return "aoss";
1236+ yield return "python(\\d.\\d)?";
1237+ }
1238+ }
1239+
1240+ static Dictionary<string, string> RemapDictionary { get; set; }
1241+
1242+ static List<Application> application_list;
1243+ static bool application_list_update_needed;
1244+
1245+ static Dictionary<int, string> exec_lines = new Dictionary<int, string> ();
1246+ static DateTime last_update = new DateTime (0);
1247+
1248+ static WindowUtils ()
1249+ {
1250+ Wnck.Screen.Default.WindowClosed += delegate {
1251+ application_list_update_needed = true;
1252+ };
1253+
1254+ Wnck.Screen.Default.WindowOpened += delegate {
1255+ application_list_update_needed = true;
1256+ };
1257+
1258+ Wnck.Screen.Default.ApplicationOpened += delegate {
1259+ application_list_update_needed = true;
1260+ };
1261+
1262+ Wnck.Screen.Default.ApplicationClosed += delegate {
1263+ application_list_update_needed = true;
1264+ };
1265+
1266+ BuildRemapDictionary ();
1267+ }
1268+
1269+ static void BuildRemapDictionary ()
1270+ {
1271+ if (!File.Exists (RemapFile)) {
1272+ RemapDictionary = BuildDefaultRemapDictionary ();
1273+
1274+ StreamWriter writer = null;
1275+ try {
1276+ writer = new StreamWriter (RemapFile);
1277+ writer.WriteLine ("# Docky Remap File");
1278+ writer.WriteLine ("# Add key value pairs following dictionary syntax");
1279+ writer.WriteLine ("# key, value");
1280+ writer.WriteLine ("# key, altKey, value");
1281+ writer.WriteLine ("# Lines starting with # are comments, otherwise # is a valid character");
1282+
1283+ foreach (KeyValuePair<string, string> kvp in RemapDictionary) {
1284+ writer.WriteLine ("{0}, {1}", kvp.Key, kvp.Value);
1285+ }
1286+ writer.Close ();
1287+ } finally {
1288+ if (writer != null)
1289+ writer.Dispose ();
1290+ }
1291+ } else {
1292+ RemapDictionary = new Dictionary<string, string> ();
1293+
1294+ StreamReader reader = null;
1295+ try {
1296+ reader = new StreamReader (RemapFile);
1297+
1298+ string line;
1299+ while (!reader.EndOfStream) {
1300+ line = reader.ReadLine ();
1301+ if (line.StartsWith ("#") || !line.Contains (","))
1302+ continue;
1303+ string [] array = line.Split (',');
1304+ if (array.Length < 2 || array [0].Length == 0)
1305+ continue;
1306+
1307+ string val = array [array.Length - 1].Trim ().ToLower ();
1308+ if (string.IsNullOrEmpty (val))
1309+ continue;
1310+
1311+ for (int i=0; i < array.Length - 1; i++) {
1312+ string key = array [i].Trim ().ToLower ();
1313+ if (string.IsNullOrEmpty (key))
1314+ continue;
1315+ RemapDictionary [key] = val;
1316+ }
1317+ }
1318+
1319+ reader.Close ();
1320+ } catch {
1321+ Log.Error ("Could not read remap file");
1322+ RemapDictionary = BuildDefaultRemapDictionary ();
1323+ } finally {
1324+ if (reader != null)
1325+ reader.Dispose ();
1326+ }
1327+ }
1328+ }
1329+
1330+ static Dictionary<string, string> BuildDefaultRemapDictionary ()
1331+ {
1332+ Dictionary<string, string> remapDict = new Dictionary<string, string> ();
1333+ remapDict ["banshee.exe"] = "banshee";
1334+ remapDict ["banshee-1"] = "banshee";
1335+ remapDict ["azureus"] = "vuze";
1336+ remapDict ["thunderbird-3.0"] = "thunderbird";
1337+ remapDict ["thunderbird-bin"] = "thunderbird";
1338+
1339+ return remapDict;
1340+ }
1341+
1342+ /// <summary>
1343+ /// Returns a list of all applications on the default screen
1344+ /// </summary>
1345+ /// <returns>
1346+ /// A <see cref="Application"/> array
1347+ /// </returns>
1348+ public static List<Application> GetApplications ()
1349+ {
1350+ if (application_list == null || application_list_update_needed) {
1351+ application_list = new List<Application> ();
1352+ foreach (Window w in Wnck.Screen.Default.Windows) {
1353+ if (!application_list.Contains (w.Application))
1354+ application_list.Add (w.Application);
1355+ }
1356+ }
1357+ return application_list;
1358+ }
1359+
1360+ /// <summary>
1361+ /// Gets the command line excec string for a PID
1362+ /// </summary>
1363+ /// <param name="pid">
1364+ /// A <see cref="System.Int32"/>
1365+ /// </param>
1366+ /// <returns>
1367+ /// A <see cref="System.String"/>
1368+ /// </returns>
1369+ public static string CmdLineForPid (int pid)
1370+ {
1371+ StreamReader reader;
1372+ string cmdline = null;
1373+
1374+ try {
1375+ string procPath = new [] { "/proc", pid.ToString (), "cmdline" }.Aggregate (Path.Combine);
1376+ reader = new StreamReader (procPath);
1377+ cmdline = reader.ReadLine ().Replace (Convert.ToChar (0x0), ' ');
1378+ reader.Close ();
1379+ reader.Dispose ();
1380+ } catch { }
1381+
1382+ return cmdline;
1383+ }
1384+
1385+ /// <summary>
1386+ /// Returns a list of applications that match an exec string
1387+ /// </summary>
1388+ /// <param name="exec">
1389+ /// A <see cref="System.String"/>
1390+ /// </param>
1391+ /// <returns>
1392+ /// A <see cref="List"/>
1393+ /// </returns>
1394+ public static List<Application> GetApplicationList (string exec)
1395+ {
1396+ List<Application> apps = new List<Application> ();
1397+ if (string.IsNullOrEmpty (exec))
1398+ return apps;
1399+
1400+ exec = ProcessExecString (exec);
1401+ if (string.IsNullOrEmpty (exec))
1402+ return apps;
1403+
1404+ UpdateExecList ();
1405+
1406+ foreach (KeyValuePair<int, string> kvp in exec_lines) {
1407+ if (kvp.Value != null && kvp.Value.Contains (exec)) {
1408+ foreach (Application app in GetApplications ()) {
1409+ if (app == null)
1410+ continue;
1411+
1412+ if (app.Pid == kvp.Key || app.Windows.Any (w => w.Pid == kvp.Key)) {
1413+ if (app.Windows.Any (win => !win.IsSkipTasklist))
1414+ apps.Add (app);
1415+ break;
1416+ }
1417+ }
1418+ }
1419+ }
1420+ return apps;
1421+ }
1422+
1423+ static void UpdateExecList ()
1424+ {
1425+ if ((DateTime.UtcNow - last_update).TotalMilliseconds < 200) return;
1426+
1427+ exec_lines.Clear ();
1428+
1429+ foreach (string dir in Directory.GetDirectories ("/proc")) {
1430+ int pid;
1431+ try { pid = Convert.ToInt32 (Path.GetFileName (dir)); }
1432+ catch { continue; }
1433+
1434+ string exec_line = CmdLineForPid (pid);
1435+ if (string.IsNullOrEmpty (exec_line))
1436+ continue;
1437+
1438+ if (exec_line.Contains ("java") && exec_line.Contains ("jar")) {
1439+ foreach (Application app in GetApplications ()) {
1440+ if (app == null)
1441+ continue;
1442+
1443+ if (app.Pid == pid || app.Windows.Any (w => w.Pid == pid)) {
1444+ foreach (Wnck.Window window in app.Windows.Where (win => !win.IsSkipTasklist)) {
1445+ exec_line = window.ClassGroup.ResClass;
1446+
1447+ // Vuze is retarded
1448+ if (exec_line == "SWT")
1449+ exec_line = window.Name;
1450+ Console.WriteLine (exec_line);
1451+ break;
1452+ }
1453+ }
1454+ }
1455+ }
1456+
1457+ exec_line = ProcessExecString (exec_line);
1458+
1459+ exec_lines [pid] = exec_line;
1460+ }
1461+
1462+ last_update = DateTime.UtcNow;
1463+ }
1464+
1465+ public static string ProcessExecString (string exec)
1466+ {
1467+ exec = exec.ToLower ().Trim ();
1468+
1469+ if (RemapDictionary.ContainsKey (exec))
1470+ return RemapDictionary [exec];
1471+
1472+ if (exec.StartsWith ("/")) {
1473+ string first_part = exec.Split (' ') [0];
1474+ int length = first_part.Length;
1475+ first_part = first_part.Split ('/').Last ();
1476+
1477+ if (length < exec.Length)
1478+ first_part = first_part + " " + exec.Substring (length + 1);
1479+
1480+ if (RemapDictionary.ContainsKey (first_part)) {
1481+ return RemapDictionary [first_part];
1482+ }
1483+ }
1484+
1485+ string [] parts = exec.Split (' ');
1486+ for (int i = 0; i < parts.Length; i++) {
1487+ if (parts [i].StartsWith ("-"))
1488+ continue;
1489+
1490+ if (parts [i].Contains ("/"))
1491+ parts [i] = parts [i].Split ('/').Last ();
1492+
1493+ Regex regex;
1494+ foreach (string prefix in BadPrefixes) {
1495+ regex = new Regex (string.Format ("^{0}$", prefix), RegexOptions.IgnoreCase);
1496+ if (regex.IsMatch (parts [i])) {
1497+ parts [i] = null;
1498+ break;
1499+ }
1500+ }
1501+
1502+ if (!string.IsNullOrEmpty (parts [i])) {
1503+ string out_val = parts [i];
1504+ if (RemapDictionary.ContainsKey (out_val))
1505+ out_val = RemapDictionary [out_val];
1506+ return out_val;
1507+ }
1508+ }
1509+ return null;
1510+ }
1511+
1512+ /// <summary>
1513+ /// Performs the "logical" click action on an entire group of applications
1514+ /// </summary>
1515+ /// <param name="apps">
1516+ /// A <see cref="IEnumerable"/>
1517+ /// </param>
1518+ public static void PerformLogicalClick (IEnumerable<Application> apps)
1519+ {
1520+ List<Window> stack = new List<Window> (Wnck.Screen.Default.WindowsStacked);
1521+ IEnumerable<Window> windows = apps
1522+ .SelectMany (app => app.Windows)
1523+ .OrderByDescending (w => stack.IndexOf (w));
1524+
1525+ bool not_in_viewport = !windows.Any (w => !w.IsSkipTasklist && w.IsInViewport (w.Screen.ActiveWorkspace));
1526+ bool urgent = windows.Any (w => w.NeedsAttention ());
1527+
1528+ if (not_in_viewport || urgent) {
1529+ foreach (Wnck.Window window in windows) {
1530+ if (urgent && !window.NeedsAttention ())
1531+ continue;
1532+ if (!window.IsSkipTasklist) {
1533+ WindowControl.IntelligentFocusOffViewportWindow (window, windows);
1534+ return;
1535+ }
1536+ }
1537+ }
1538+
1539+ switch (GetClickAction (apps)) {
1540+ case ClickAction.Focus:
1541+ WindowControl.FocusWindows (windows);
1542+ break;
1543+ case ClickAction.Minimize:
1544+ WindowControl.MinimizeWindows (windows);
1545+ break;
1546+ case ClickAction.Restore:
1547+ WindowControl.RestoreWindows (windows);
1548+ break;
1549+ }
1550+ }
1551+
1552+ static ClickAction GetClickAction (IEnumerable<Application> apps)
1553+ {
1554+ if (!apps.Any ())
1555+ return ClickAction.None;
1556+
1557+ foreach (Wnck.Application app in apps) {
1558+ foreach (Wnck.Window window in app.Windows) {
1559+ if (window.IsMinimized && window.IsInViewport (Wnck.Screen.Default.ActiveWorkspace))
1560+ return ClickAction.Restore;
1561+ }
1562+ }
1563+
1564+ foreach (Wnck.Application app in apps) {
1565+ foreach (Wnck.Window window in app.Windows) {
1566+ if (window.IsActive && window.IsInViewport (Wnck.Screen.Default.ActiveWorkspace))
1567+ return ClickAction.Minimize;
1568+ }
1569+ }
1570+
1571+ return ClickAction.Focus;
1572+ }
1573+ }
1574+}
1575
1576=== modified file 'Do.mds'
1577--- Do.mds 2009-02-11 08:14:54 +0000
1578+++ Do.mds 2009-03-20 20:43:06 +0000
1579@@ -1,4 +1,9 @@
1580 <Combine fileversion="2.0" outputpath="build/bin/" name="Do">
1581+ <Policies>
1582+ <ChangeLogPolicy UpdateMode="Nearest" inheritsSet="Mono">
1583+ <MessageStyle Header="" Indent="" LineAlign="0" />
1584+ </ChangeLogPolicy>
1585+ </Policies>
1586 <Configurations active="Debug">
1587 <Configuration name="Debug" ctype="CombineConfiguration">
1588 <Entry build="True" name="Do" configuration="Debug" />
1589@@ -13,6 +18,7 @@
1590 <Entry build="True" name="Do.Interface.Linux.GlassFrame" configuration="Debug" />
1591 <Entry build="True" name="Do.Interface.Linux.Mini" configuration="Debug" />
1592 <Entry build="True" name="Do.Interface.Linux.HUD" configuration="Debug" />
1593+ <Entry build="True" name="Do.Interface.Wink" configuration="Debug" />
1594 </Configuration>
1595 <Configuration name="Release" ctype="CombineConfiguration">
1596 <Entry build="True" name="Do" configuration="Release" />
1597@@ -27,6 +33,7 @@
1598 <Entry build="True" name="Do.Interface.Linux.GlassFrame" configuration="Release" />
1599 <Entry build="True" name="Do.Interface.Linux.Mini" configuration="Release" />
1600 <Entry build="True" name="Do.Interface.Linux.HUD" configuration="Release" />
1601+ <Entry build="True" name="Do.Interface.Wink" configuration="Release" />
1602 <CustomCommands>
1603 <Command type="BeforeBuild" command="autogen.sh --enable-release=YES" workingdir="${CombineDir}" />
1604 </CustomCommands>
1605@@ -45,8 +52,8 @@
1606 <Execute type="None" entry="Do.Interface.Linux.GlassFrame" />
1607 <Execute type="None" entry="Do.Interface.Linux.Mini" />
1608 <Execute type="None" entry="Do.Interface.Linux.HUD" />
1609+ <Execute type="None" entry="Do.Interface.Wink" />
1610 </StartMode>
1611- <MonoDevelop.ChangeLogAddIn.ChangeLogInfo policy="UpdateNearestChangeLog" />
1612 <Entries>
1613 <Entry filename="Do/Do.mdp" />
1614 <Entry filename="Do.Platform/Do.Platform.mdp" />
1615@@ -60,5 +67,6 @@
1616 <Entry filename="Do.Interface.Linux.GlassFrame/Do.Interface.Linux.GlassFrame.mdp" />
1617 <Entry filename="Do.Interface.Linux.Mini/Do.Interface.Linux.Mini.mdp" />
1618 <Entry filename="Do.Interface.Linux.HUD/Do.Interface.Linux.HUD.mdp" />
1619+ <Entry filename="Do.Interface.Wink/Do.Interface.Wink.mdp" />
1620 </Entries>
1621-</Combine>
1622\ No newline at end of file
1623+</Combine>
1624
1625=== modified file 'Do/Do.mdp'
1626--- Do/Do.mdp 2009-02-19 03:09:17 +0000
1627+++ Do/Do.mdp 2009-03-20 20:43:06 +0000
1628@@ -5,13 +5,13 @@
1629 <Build debugmode="True" target="Exe" />
1630 <Execution runwithwarnings="True" commandlineparameters="--debug" externalconsole="True" consolepause="True" runtime="MsNet" clr-version="Net_2_0" />
1631 <EnvironmentVariables />
1632- <CodeGeneration compiler="Mcs" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" generatexmldocumentation="False" win32Icon="../../../../../jason/do/trunk-merge/Do" ctype="CSharpCompilerParameters" />
1633+ <CodeGeneration compiler="Mcs" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
1634 </Configuration>
1635 <Configuration name="Release" ctype="DotNetProjectConfiguration">
1636 <Output directory="bin/Release" assembly="Do" />
1637 <Build debugmode="False" target="Exe" />
1638 <Execution runwithwarnings="True" consolepause="True" runtime="MsNet" clr-version="Net_2_0" />
1639- <CodeGeneration compiler="Mcs" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" generatexmldocumentation="False" win32Icon="../../../../../jason/do/trunk-merge/Do" ctype="CSharpCompilerParameters" />
1640+ <CodeGeneration compiler="Mcs" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
1641 </Configuration>
1642 </Configurations>
1643 <Contents>
1644@@ -102,6 +102,7 @@
1645 <ProjectReference type="Project" localcopy="True" refto="Do.Interface.Linux" />
1646 <ProjectReference type="Project" localcopy="True" refto="Do.Universe" />
1647 </References>
1648+ <LanguageParameters ApplicationIcon="../../../../../jason/do/trunk-merge/Do" ctype="CSharpProjectParameters" />
1649 <Deployment.LinuxDeployData scriptName="gnome-do" />
1650 <MonoDevelop.Autotools.MakefileInfo RelativeMakefileName="Makefile.am" SyncReferences="True" IsAutotoolsProject="True" RelativeConfigureInPath="../">
1651 <BuildFilesVar Sync="True" Name="FILES" />
1652
1653=== modified file 'Makefile.am'
1654--- Makefile.am 2009-02-25 22:51:59 +0000
1655+++ Makefile.am 2009-03-20 20:43:06 +0000
1656@@ -8,6 +8,7 @@
1657 data \
1658 Do.Universe \
1659 Do.Platform \
1660+ Do.Interface.Wink \
1661 Do.Interface.Linux \
1662 Do.Interface.Linux.Classic \
1663 Do.Interface.Linux.Docky \
1664
1665=== modified file 'configure.ac'
1666--- configure.ac 2009-03-17 10:17:24 +0000
1667+++ configure.ac 2009-03-20 20:43:06 +0000
1668@@ -133,6 +133,7 @@
1669 Do.Interface.Linux.GlassFrame/Makefile
1670 Do.Interface.Linux.HUD/Makefile
1671 Do.Interface.Linux.Mini/Makefile
1672+Do.Interface.Wink/Makefile
1673 Do.Platform/Makefile
1674 Do.Platform/src/AssemblyInfo.cs
1675 Do.Platform.Linux/Makefile