Merge lp:~jassmith/do/glitch-free-docky into lp:do
- glitch-free-docky
- Merge into trunk
Proposed by
Jason Smith
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~jassmith/do/glitch-free-docky |
Merge into: | lp:do |
Diff against target: | None lines |
To merge this branch: | bzr merge lp:~jassmith/do/glitch-free-docky |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alex Launi (community) | Approve | ||
Review via email: mp+5092@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 1135. By Jason Smith
-
remove debug
- 1136. By Jason Smith
-
Fix issues found in review
- 1137. By Jason Smith
-
merge trunk
- 1138. By Jason Smith
-
Implement tiling code
- 1139. By Jason Smith
-
Add show desktop command
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === removed file 'Do.Interface.Linux.Docky/Do.Interface.Linux.Docky.dll.config' |
2 | --- Do.Interface.Linux.Docky/Do.Interface.Linux.Docky.dll.config 2009-01-11 20:30:50 +0000 |
3 | +++ Do.Interface.Linux.Docky/Do.Interface.Linux.Docky.dll.config 1970-01-01 00:00:00 +0000 |
4 | @@ -1,4 +0,0 @@ |
5 | -<configuration> |
6 | - <dllmap dll="X11" target="libX11.so.6"/> |
7 | - <dllmap dll="libgdk-x11" target="libgdk-x11-2.0.so.0"/> |
8 | -</configuration> |
9 | |
10 | === modified file 'Do.Interface.Linux.Docky/Do.Interface.Linux.Docky.mdp' |
11 | --- Do.Interface.Linux.Docky/Do.Interface.Linux.Docky.mdp 2009-03-20 20:43:06 +0000 |
12 | +++ Do.Interface.Linux.Docky/Do.Interface.Linux.Docky.mdp 2009-03-31 03:39:44 +0000 |
13 | @@ -19,7 +19,6 @@ |
14 | <File name="src" subtype="Directory" buildaction="Compile" /> |
15 | <File name="Resources" subtype="Directory" buildaction="Compile" /> |
16 | <File name="Resources/Do.Interface.Linux.Docky.addin.xml" subtype="Code" buildaction="EmbedAsResource" /> |
17 | - <File name="src/XLib" subtype="Directory" buildaction="Compile" /> |
18 | <File name="src/Docky.Interface" subtype="Directory" buildaction="Compile" /> |
19 | <File name="src/Docky.Utilities" subtype="Directory" buildaction="Compile" /> |
20 | <File name="src/Docky.Interface/DockArea.cs" subtype="Code" buildaction="Compile" /> |
21 | @@ -32,8 +31,6 @@ |
22 | <File name="src/Docky.Interface/Docky.Interface.Painters/SummonModeRenderer.cs" subtype="Code" buildaction="Compile" /> |
23 | <File name="src/Docky.Utilities/DockPreferences.cs" subtype="Code" buildaction="Compile" /> |
24 | <File name="src/Docky.Utilities/GtkUtils.cs" subtype="Code" buildaction="Compile" /> |
25 | - <File name="src/XLib/X11Atoms.cs" subtype="Code" buildaction="Compile" /> |
26 | - <File name="src/XLib/Xlib.cs" subtype="Code" buildaction="Compile" /> |
27 | <File name="src/Docky.Interface/IRightClickable.cs" subtype="Code" buildaction="Compile" /> |
28 | <File name="src/Docky.Interface/UpdateRequestArgs.cs" subtype="Code" buildaction="Compile" /> |
29 | <File name="src/Docky.Interface/DockAnimationState.cs" subtype="Code" buildaction="Compile" /> |
30 | |
31 | === modified file 'Do.Interface.Linux.Docky/Makefile.am' |
32 | --- Do.Interface.Linux.Docky/Makefile.am 2009-03-20 20:43:06 +0000 |
33 | +++ Do.Interface.Linux.Docky/Makefile.am 2009-03-31 16:33:58 +0000 |
34 | @@ -65,9 +65,7 @@ |
35 | src/Docky.Interface/Util.cs \ |
36 | src/Docky.Utilities/DockOrientation.cs \ |
37 | src/Docky.Utilities/DockPreferences.cs \ |
38 | - src/Docky.Utilities/GtkUtils.cs \ |
39 | - src/XLib/X11Atoms.cs \ |
40 | - src/XLib/Xlib.cs |
41 | + src/Docky.Utilities/GtkUtils.cs |
42 | |
43 | RESOURCES = \ |
44 | Resources/Do.Interface.Linux.Docky.addin.xml \ |
45 | @@ -91,6 +89,3 @@ |
46 | Do.Interface.Wink \ |
47 | Do.Platform \ |
48 | Do.Universe |
49 | - |
50 | -module_DATA += $(ASSEMBLY).dll.config |
51 | -EXTRA_DIST += $(ASSEMBLY).dll.config |
52 | |
53 | === modified file 'Do.Interface.Linux.Docky/src/Docky.Core/Docky.Core.Default/ItemsService.cs' |
54 | --- Do.Interface.Linux.Docky/src/Docky.Core/Docky.Core.Default/ItemsService.cs 2009-03-20 20:43:06 +0000 |
55 | +++ Do.Interface.Linux.Docky/src/Docky.Core/Docky.Core.Default/ItemsService.cs 2009-04-01 01:08:07 +0000 |
56 | @@ -199,14 +199,15 @@ |
57 | |
58 | void HandleWindowOpened(object o, WindowOpenedArgs args) |
59 | { |
60 | + // we do a delayed update so that we allow a small gap for wnck to catch up |
61 | if (!args.Window.IsSkipTasklist) |
62 | - UpdateItems (); |
63 | + DelayUpdateItems (); |
64 | } |
65 | |
66 | void HandleWindowClosed(object o, WindowClosedArgs args) |
67 | { |
68 | if (!args.Window.IsSkipTasklist) |
69 | - UpdateItems (); |
70 | + DelayUpdateItems (); |
71 | } |
72 | |
73 | void HandleUniverseInitialized(object sender, EventArgs e) |
74 | @@ -259,17 +260,25 @@ |
75 | item.Position = i++; |
76 | } |
77 | |
78 | + void DelayUpdateItems () |
79 | + { |
80 | + GLib.Timeout.Add (20, delegate { |
81 | + UpdateItems (); |
82 | + return false; |
83 | + }); |
84 | + } |
85 | + |
86 | void UpdateItems () |
87 | { |
88 | if (!UpdatesEnabled) |
89 | return; |
90 | |
91 | - UpdateStatItems (); |
92 | - |
93 | if (!CustomItemsRead) { |
94 | foreach (string s in ReadCustomItems ()) |
95 | InternalAddItemToDock (s, LastPosition + 1); |
96 | |
97 | + UpdateStatItems (); |
98 | + |
99 | Dictionary<string, int> sortDictionary = ReadSortDictionary (); |
100 | foreach (ItemDockItem item in OrderedItems.Where (di => di is ItemDockItem)) { |
101 | if (sortDictionary.ContainsKey (item.Element.UniqueId)) |
102 | @@ -277,6 +286,8 @@ |
103 | } |
104 | |
105 | CustomItemsRead = true; |
106 | + } else { |
107 | + UpdateStatItems (); |
108 | } |
109 | |
110 | UpdateTaskItems (); |
111 | @@ -329,24 +340,22 @@ |
112 | |
113 | void UpdateTaskItems () |
114 | { |
115 | - foreach (ItemDockItem item in OrderedItems.Where (di => di is ItemDockItem)) { |
116 | + foreach (ItemDockItem item in OrderedItems.Where (di => di is ItemDockItem)) |
117 | item.UpdateApplication (); |
118 | - } |
119 | |
120 | List<ApplicationDockItem> out_items = new List<ApplicationDockItem> (); |
121 | |
122 | - IEnumerable<int> knownPids = OrderedItems |
123 | + IEnumerable<Window> knownWindows = OrderedItems |
124 | .Where (di => di is ItemDockItem) |
125 | .Cast<ItemDockItem> () |
126 | - .SelectMany (di => di.Pids); |
127 | - |
128 | - IEnumerable<Application> prunedApps = WindowUtils.GetApplications () |
129 | - .Where (app => app.Windows.Any (w => !w.IsSkipTasklist)) |
130 | - .Where (app => !knownPids.Contains (app.Pid) && app.Windows.Any ()); |
131 | - |
132 | - foreach (IEnumerable<Wnck.Application> apps in prunedApps |
133 | - .GroupBy (app => (app as Wnck.Application).Windows [0].ClassGroup.ResClass)) { |
134 | - ApplicationDockItem api = new ApplicationDockItem (apps); |
135 | + .SelectMany (di => di.Windows); |
136 | + |
137 | + var prunedWindows = WindowUtils.GetWindows () |
138 | + .Where (w => !w.IsSkipTasklist && !knownWindows.Contains (w)) |
139 | + .GroupBy (w => SafeResClass (w)); |
140 | + |
141 | + foreach (IEnumerable<Wnck.Window> windows in prunedWindows) { |
142 | + ApplicationDockItem api = new ApplicationDockItem (windows); |
143 | |
144 | if (task_items.Any (di => di.Equals (api))) { |
145 | AbstractDockItem match = task_items.Where (di => di.Equals (api)).First (); |
146 | @@ -374,6 +383,13 @@ |
147 | task_items.AddRange (out_items.Cast<AbstractDockItem> ()); |
148 | } |
149 | |
150 | + string SafeResClass (Wnck.Window window) |
151 | + { |
152 | + if (window.ClassGroup != null && window.ClassGroup.ResClass != null) |
153 | + return window.ClassGroup.ResClass; |
154 | + return string.Empty; |
155 | + } |
156 | + |
157 | void OnDockItemsChanged () |
158 | { |
159 | output_items.Clear (); |
160 | @@ -506,15 +522,6 @@ |
161 | return DockItems.Contains (item) && 0 <= position && position < DockItems.Count; |
162 | } |
163 | |
164 | - int LastNonTaskItemPosition () |
165 | - { |
166 | - if (!OrderedItems.Any (di => !(di is ApplicationDockItem))) |
167 | - return 0; |
168 | - return OrderedItems |
169 | - .Where (di => !(di is ApplicationDockItem)) |
170 | - .Max ((Func<AbstractDockItem, int>) (di => di.Position)); |
171 | - } |
172 | - |
173 | /// <summary> |
174 | /// Returns the most used items out of GNOME Do and does a tiny bit of filtering and sorting on them |
175 | /// This is mostly to encourage a better first run experience, but overall this can be improved |
176 | @@ -616,19 +623,22 @@ |
177 | continue; |
178 | } |
179 | |
180 | - if (item is ApplicationDockItem && position <= LastNonTaskItemPosition ()) { |
181 | + if (item is ApplicationDockItem) { |
182 | ApplicationDockItem api = item as ApplicationDockItem; |
183 | - string desktop_file = api.DesktopFile; |
184 | - |
185 | - if (string.IsNullOrEmpty (desktop_file)) continue; |
186 | - |
187 | - AbstractDockItem newItem = MaybeCreateCustomItem (desktop_file); |
188 | - |
189 | - if (newItem == null) continue; |
190 | + |
191 | + if (api.Launcher == null) continue; |
192 | + |
193 | + Item launcher = api.Launcher as Item; |
194 | + if (launcher == null) |
195 | + continue; |
196 | + |
197 | + AbstractDockItem newItem = new ItemDockItem (launcher); |
198 | |
199 | newItem.Position = item.Position; |
200 | newItem.DockAddItem = item.DockAddItem; |
201 | - custom_items [desktop_file] = newItem; |
202 | + custom_items [launcher.UniqueId] = newItem; |
203 | + |
204 | + RegisterDockItem (newItem); |
205 | UpdateItems (); |
206 | WriteData (); |
207 | } |
208 | |
209 | === modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/DockArea.cs' |
210 | --- Do.Interface.Linux.Docky/src/Docky.Interface/DockArea.cs 2009-03-15 17:41:40 +0000 |
211 | +++ Do.Interface.Linux.Docky/src/Docky.Interface/DockArea.cs 2009-04-01 01:08:07 +0000 |
212 | @@ -26,6 +26,7 @@ |
213 | using Gtk; |
214 | |
215 | using Do.Platform; |
216 | +using Do.Interface.Xlib; |
217 | |
218 | using Docky.Core; |
219 | using Docky.Utilities; |
220 | @@ -99,14 +100,14 @@ |
221 | |
222 | switch (DockPreferences.Orientation) { |
223 | case DockOrientation.Bottom: |
224 | - values [(int) XLib.Struts.Bottom] = (uint) (DockHeight + (Screen.Height - (geo.Y + geo.Height))); |
225 | - values [(int) XLib.Struts.BottomStart] = (uint) geo.X; |
226 | - values [(int) XLib.Struts.BottomEnd] = (uint) (geo.X + geo.Width - 1); |
227 | + values [(int) Struts.Bottom] = (uint) (DockHeight + (Screen.Height - (geo.Y + geo.Height))); |
228 | + values [(int) Struts.BottomStart] = (uint) geo.X; |
229 | + values [(int) Struts.BottomEnd] = (uint) (geo.X + geo.Width - 1); |
230 | break; |
231 | case DockOrientation.Top: |
232 | - values [(int) XLib.Struts.Top] = (uint) (DockHeight + geo.Y); |
233 | - values [(int) XLib.Struts.TopStart] = (uint) geo.X; |
234 | - values [(int) XLib.Struts.TopEnd] = (uint) (geo.X + geo.Width - 1); |
235 | + values [(int) Struts.Top] = (uint) (DockHeight + geo.Y); |
236 | + values [(int) Struts.TopStart] = (uint) geo.X; |
237 | + values [(int) Struts.TopEnd] = (uint) (geo.X + geo.Width - 1); |
238 | break; |
239 | } |
240 | return values; |
241 | @@ -175,8 +176,11 @@ |
242 | break; |
243 | } |
244 | } |
245 | + |
246 | CursorIsOverDockArea = dockRegion.Contains (cursor); |
247 | } |
248 | + Console.WriteLine (cursor); |
249 | + Console.WriteLine (dockRegion); |
250 | |
251 | // When we change over this boundry, it will normally trigger an animation, we need to be sure to catch it |
252 | if (CursorIsOverDockArea != cursorIsOverDockArea) { |
253 | |
254 | === modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/DockArea_Rendering.cs' |
255 | --- Do.Interface.Linux.Docky/src/Docky.Interface/DockArea_Rendering.cs 2009-03-11 16:29:55 +0000 |
256 | +++ Do.Interface.Linux.Docky/src/Docky.Interface/DockArea_Rendering.cs 2009-04-01 01:08:07 +0000 |
257 | @@ -207,6 +207,8 @@ |
258 | |
259 | void DrawDrock (Context cr) |
260 | { |
261 | + Console.WriteLine (VerticalOffset); |
262 | + Console.WriteLine (CursorIsOverDockArea); |
263 | Gdk.Rectangle dockArea = GetDockArea (); |
264 | DockBackgroundRenderer.RenderDockBackground (cr, dockArea); |
265 | |
266 | |
267 | === modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/DockWindow.cs' |
268 | --- Do.Interface.Linux.Docky/src/Docky.Interface/DockWindow.cs 2009-03-15 18:30:41 +0000 |
269 | +++ Do.Interface.Linux.Docky/src/Docky.Interface/DockWindow.cs 2009-04-01 01:09:29 +0000 |
270 | @@ -25,11 +25,11 @@ |
271 | using Cairo; |
272 | |
273 | using Docky.Utilities; |
274 | -using Docky.XLib; |
275 | |
276 | using Do.Universe; |
277 | using Do.Platform; |
278 | using Do.Interface; |
279 | +using Do.Interface.Xlib; |
280 | using Do.Interface.CairoUtils; |
281 | using Do.Interface.AnimationBase; |
282 | |
283 | @@ -243,7 +243,9 @@ |
284 | results_window.Move ((geo.X + geo.Width / 2) - res.Width / 2, geo.Y + dock_area.DockHeight); |
285 | break; |
286 | } |
287 | - Display.Sync (); |
288 | + |
289 | + if (Display != null) |
290 | + Display.Sync (); |
291 | |
292 | is_repositioned_hidden = false; |
293 | } |
294 | @@ -264,7 +266,8 @@ |
295 | break; |
296 | } |
297 | |
298 | - Display.Sync (); |
299 | + if (Display != null) |
300 | + Display.Sync (); |
301 | |
302 | is_repositioned_hidden = true; |
303 | } |
304 | @@ -272,20 +275,21 @@ |
305 | public void WindowHideOffset (out int x, out int y) |
306 | { |
307 | x = y = 0; |
308 | - |
309 | - if (!is_repositioned_hidden) { |
310 | - return; |
311 | - } |
312 | - |
313 | - Gdk.Rectangle main; |
314 | - GetSize (out main.Width, out main.Height); |
315 | + |
316 | + Gdk.Rectangle main, geo; |
317 | + main.Width = dock_area.Width; |
318 | + main.Height = dock_area.Height; |
319 | + GetBufferedPosition (out main.X, out main.Y); |
320 | + geo = LayoutUtils.MonitorGemonetry (); |
321 | + |
322 | + |
323 | switch (DockPreferences.Orientation) { |
324 | case DockOrientation.Bottom: |
325 | - y = main.Height; |
326 | - break; |
327 | + y = main.Y - ((geo.Y + geo.Height) - main.Height); |
328 | + return; |
329 | case DockOrientation.Top: |
330 | - y = 0 - main.Height; |
331 | - break; |
332 | + y = main.Y - geo.Y; |
333 | + return; |
334 | } |
335 | } |
336 | |
337 | @@ -308,7 +312,7 @@ |
338 | |
339 | public bool SetStruts () |
340 | { |
341 | - X11Atoms atoms = new X11Atoms (GdkWindow); |
342 | + X11Atoms atoms = X11Atoms.Instance; |
343 | |
344 | uint [] struts = dock_area.StrutRequest; |
345 | uint [] first_struts = new [] { struts [0], struts [1], struts [2], struts [3] }; |
346 | @@ -318,10 +322,10 @@ |
347 | if (!IsRealized) |
348 | return false; |
349 | Xlib.XChangeProperty (GdkWindow, atoms._NET_WM_STRUT_PARTIAL, atoms.XA_CARDINAL, |
350 | - (int) XLib.PropertyMode.PropModeReplace, struts); |
351 | + (int) PropertyMode.PropModeReplace, struts); |
352 | |
353 | Xlib.XChangeProperty (GdkWindow, atoms._NET_WM_STRUT, atoms.XA_CARDINAL, |
354 | - (int) XLib.PropertyMode.PropModeReplace, first_struts); |
355 | + (int) PropertyMode.PropModeReplace, first_struts); |
356 | |
357 | return false; |
358 | } |
359 | |
360 | === modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ApplicationDockItem.cs' |
361 | --- Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ApplicationDockItem.cs 2009-03-20 20:43:06 +0000 |
362 | +++ Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ApplicationDockItem.cs 2009-04-01 02:13:22 +0000 |
363 | @@ -43,16 +43,6 @@ |
364 | { |
365 | public event EventHandler RemoveClicked; |
366 | |
367 | - static readonly IEnumerable<string> DesktopFilesDirectories = new [] { |
368 | - "~/.local/share/applications/wine", |
369 | - "~/.local/share/applications", |
370 | - "/usr/share/applications", |
371 | - "/usr/share/applications/kde", |
372 | - "/usr/share/applications/kde4", |
373 | - "/usr/share/gdm/applications", |
374 | - "/usr/local/share/applications", |
375 | - }; |
376 | - |
377 | string MinimizeRestoreText = Catalog.GetString ("Minimize") + "/" + Catalog.GetString ("Restore"); |
378 | string MaximizeText = Catalog.GetString ("Maximize"); |
379 | string CloseText = Catalog.GetString ("Close All"); |
380 | @@ -77,33 +67,23 @@ |
381 | Gdk.Rectangle icon_region; |
382 | Gdk.Pixbuf drag_pixbuf; |
383 | |
384 | - IEnumerable<Wnck.Application> applications; |
385 | - |
386 | - string desktop_file; |
387 | - bool checked_desktop_file; |
388 | - |
389 | - public string DesktopFile { |
390 | + IEnumerable<Wnck.Window> windows; |
391 | + |
392 | + IApplicationItem launcher; |
393 | + |
394 | + public IApplicationItem Launcher { |
395 | get { |
396 | - if (desktop_file == null && !checked_desktop_file) { |
397 | - checked_desktop_file = true; |
398 | - foreach (string s in GetIconGuesses ()) { |
399 | - desktop_file = GetDesktopFile (s); |
400 | - if (desktop_file != null) |
401 | - break; |
402 | - } |
403 | + if (launcher == null && Exec != null) { |
404 | + string command = WindowUtils.ProcessExecString (Exec); |
405 | + launcher = Services.UniverseFactory.MaybeApplicationItemFromCommand (command); |
406 | } |
407 | - return desktop_file; |
408 | + return launcher; |
409 | } |
410 | } |
411 | |
412 | string Exec { |
413 | get { |
414 | string exec; |
415 | - foreach (Wnck.Application app in Applications) { |
416 | - exec = MaybeGetExecStringForPID (app.Pid); |
417 | - if (exec != null) |
418 | - return exec; |
419 | - } |
420 | |
421 | foreach (Wnck.Window win in VisibleWindows) { |
422 | exec = MaybeGetExecStringForPID (win.Pid); |
423 | @@ -130,34 +110,23 @@ |
424 | protected override Gdk.Pixbuf GetSurfacePixbuf (int size) |
425 | { |
426 | Gdk.Pixbuf pbuf = null; |
427 | - foreach (string guess in GetIconGuesses ()) { |
428 | - if (pbuf != null) { |
429 | + |
430 | + if (Launcher == null) { |
431 | + foreach (string guess in GetIconGuesses ()) { |
432 | + bool found = IconProvider.PixbufFromIconName (guess, size, out pbuf); |
433 | + if (found && (pbuf.Width == size || pbuf.Height == size)) |
434 | + break; |
435 | + |
436 | pbuf.Dispose (); |
437 | pbuf = null; |
438 | } |
439 | - |
440 | - bool found = IconProvider.PixbufFromIconName (guess, size, out pbuf); |
441 | - if (found && (pbuf.Width == size || pbuf.Height == size)) |
442 | - break; |
443 | - |
444 | - pbuf.Dispose (); |
445 | - pbuf = null; |
446 | - |
447 | - string desktopPath = GetDesktopFile (guess); |
448 | - if (!string.IsNullOrEmpty (desktopPath)) { |
449 | - try { |
450 | - string icon = Services.UniverseFactory.NewApplicationItem (desktopPath).Icon; |
451 | - pbuf = IconProvider.PixbufFromIconName (icon, size); |
452 | - break; |
453 | - } catch { |
454 | - continue; |
455 | - } |
456 | - } |
457 | + } else { |
458 | + IconProvider.PixbufFromIconName (Launcher.Icon, size, out pbuf); |
459 | } |
460 | |
461 | // we failed to find an icon, lets use an uggggly one |
462 | if (pbuf == null) |
463 | - pbuf = Applications.First ().Icon; |
464 | + pbuf = Windows.First ().Icon; |
465 | |
466 | if (pbuf.Height != size && pbuf.Width != size ) { |
467 | double scale = (double)size / Math.Max (pbuf.Width, pbuf.Height); |
468 | @@ -170,14 +139,16 @@ |
469 | |
470 | string Name { |
471 | get { |
472 | - foreach (Wnck.Application application in Applications) { |
473 | - if (StringIsValidName (application.IconName)) |
474 | - return application.IconName; |
475 | - else if (StringIsValidName (application.Name)) |
476 | - return application.Name; |
477 | - } |
478 | - |
479 | + if (NeedsAttention) { |
480 | + return VisibleWindows.Where (w => w.NeedsAttention ()).First ().Name; |
481 | + } |
482 | + if (VisibleWindows.Any () && VisibleWindows.Count () == 1) { |
483 | + return VisibleWindows.First ().Name; |
484 | + } |
485 | + |
486 | foreach (Wnck.Window window in VisibleWindows) { |
487 | + if (StringIsValidName (window.ClassGroup.ResClass)) |
488 | + return window.ClassGroup.ResClass; |
489 | if (StringIsValidName (window.IconName)) |
490 | return window.IconName; |
491 | else if (StringIsValidName (window.Name)) |
492 | @@ -191,13 +162,13 @@ |
493 | get { return windowCount; } |
494 | } |
495 | |
496 | - protected override IEnumerable<Wnck.Application> Applications { |
497 | - get { return applications; } |
498 | + public override IEnumerable<Wnck.Window> Windows { |
499 | + get { return windows; } |
500 | } |
501 | |
502 | - public ApplicationDockItem (IEnumerable<Wnck.Application> applications) : base () |
503 | + public ApplicationDockItem (IEnumerable<Wnck.Window> windows) : base () |
504 | { |
505 | - this.applications = applications; |
506 | + this.windows = windows; |
507 | windowCount = VisibleWindows.Count (); |
508 | |
509 | foreach (Wnck.Window w in VisibleWindows) { |
510 | @@ -227,41 +198,49 @@ |
511 | if (VisibleWindows.Count () == 0) |
512 | Core.DockServices.ItemsService.ForceUpdate (); |
513 | } |
514 | + |
515 | + SetText (Name); |
516 | } |
517 | |
518 | IEnumerable<string> GetIconGuesses () |
519 | { |
520 | List<string> guesses = new List<string> (); |
521 | |
522 | - if (!string.IsNullOrEmpty (Exec)) { |
523 | - yield return Exec; |
524 | - yield return Exec.Split ('-')[0]; |
525 | + // open office hack... |
526 | + if (VisibleWindows.Any () && |
527 | + VisibleWindows.First ().ClassGroup != null && |
528 | + VisibleWindows.First ().ClassGroup.ResClass.ToLower ().Contains ("openoffice")) { |
529 | + yield return "openoffice"; |
530 | + yield break; |
531 | } |
532 | |
533 | - foreach (Wnck.Application app in Applications) { |
534 | - if (!guesses.Contains (PrepName (app.Name))) |
535 | - guesses.Add (PrepName (app.Name)); |
536 | - if (!guesses.Contains (PrepName (app.IconName))) |
537 | - guesses.Add (PrepName (app.IconName)); |
538 | + string exec = Exec; |
539 | + if (!string.IsNullOrEmpty (exec)) { |
540 | + yield return exec; |
541 | + yield return exec.Split ('-')[0]; |
542 | + yield return WindowUtils.ProcessExecString (exec); |
543 | } |
544 | |
545 | foreach (Wnck.Window win in VisibleWindows) { |
546 | if (!guesses.Contains (PrepName (win.Name))) |
547 | guesses.Add (PrepName (win.Name)); |
548 | + |
549 | if (!guesses.Contains (PrepName (win.IconName))) |
550 | guesses.Add (PrepName (win.IconName)); |
551 | + |
552 | + if (win.ClassGroup == null) |
553 | + continue; |
554 | + |
555 | if (!guesses.Contains (PrepName (win.ClassGroup.ResClass))) |
556 | guesses.Add (PrepName (win.ClassGroup.ResClass)); |
557 | + |
558 | + if (!guesses.Contains (PrepName (win.ClassGroup.Name))) |
559 | + guesses.Add (PrepName (win.ClassGroup.Name)); |
560 | } |
561 | |
562 | - foreach (string s in guesses) |
563 | + foreach (string s in guesses) { |
564 | yield return s; |
565 | - |
566 | - foreach (string s in guesses) |
567 | - yield return "gnome-" + s; |
568 | - |
569 | - if (Name.Length > 4 && Name.Contains (" ")) |
570 | - yield return Name.Split (' ') [0].ToLower (); |
571 | + } |
572 | } |
573 | |
574 | string PrepName (string s) |
575 | @@ -283,27 +262,14 @@ |
576 | return exec; |
577 | } |
578 | |
579 | - string GetDesktopFile (string base_name) |
580 | - { |
581 | - foreach (string dir in DesktopFilesDirectories) { |
582 | - try { |
583 | - if (File.Exists (System.IO.Path.Combine (dir, base_name+".desktop"))) |
584 | - return System.IO.Path.Combine (dir, base_name+".desktop"); |
585 | - if (File.Exists (System.IO.Path.Combine (dir, "gnome-"+base_name+".desktop"))) |
586 | - return System.IO.Path.Combine (dir, "gnome-"+base_name+".desktop"); |
587 | - } catch { return null; } |
588 | - } |
589 | - return null; |
590 | - } |
591 | - |
592 | bool StringIsValidName (string s) |
593 | { |
594 | s = s.Trim (); |
595 | if (string.IsNullOrEmpty (s) || s == "<unknown>") |
596 | return false; |
597 | |
598 | - foreach (string prefix in WindowUtils.BadPrefixes) { |
599 | - if (string.Compare (s, prefix, true) == 0) |
600 | + foreach (System.Text.RegularExpressions.Regex prefix in WindowUtils.BadPrefixes) { |
601 | + if (prefix.IsMatch (s)) |
602 | return false; |
603 | } |
604 | |
605 | @@ -324,14 +290,15 @@ |
606 | if (!(other is ApplicationDockItem)) |
607 | return false; |
608 | |
609 | - return Applications.Any (app => (other as ApplicationDockItem).Applications.Contains (app)); |
610 | + return Windows.Any (w => (other as ApplicationDockItem).Windows.Contains (w)); |
611 | } |
612 | |
613 | public IEnumerable<AbstractMenuArgs> GetMenuItems () |
614 | { |
615 | yield return new SeparatorMenuButtonArgs (); |
616 | |
617 | - if (DesktopFile == null) { |
618 | + Item item = Launcher as Item; |
619 | + if (item == null) { |
620 | yield return new SimpleMenuButtonArgs (() => WindowControl.MinimizeRestoreWindows (VisibleWindows), |
621 | MinimizeRestoreText, MinimizeIcon).AsDark (); |
622 | |
623 | @@ -341,8 +308,6 @@ |
624 | yield return new SimpleMenuButtonArgs (() => WindowControl.CloseWindows (VisibleWindows), |
625 | CloseText, CloseIcon).AsDark (); |
626 | } else { |
627 | - Item item = Services.UniverseFactory.NewApplicationItem (DesktopFile) as Item; |
628 | - |
629 | foreach (Act act in ActionsForItem (item)) |
630 | yield return new LaunchMenuButtonArgs (act, item, act.Name, act.Icon).AsDark (); |
631 | } |
632 | @@ -352,6 +317,12 @@ |
633 | yield return new WindowMenuButtonArgs (window, window.Name, WindowIcon); |
634 | } |
635 | } |
636 | + |
637 | + protected override void Launch () |
638 | + { |
639 | + if (Launcher != null) |
640 | + Launcher.Run (); |
641 | + } |
642 | |
643 | public override void Dispose () |
644 | { |
645 | |
646 | === modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ItemDockItem.cs' |
647 | --- Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ItemDockItem.cs 2009-03-20 20:43:06 +0000 |
648 | +++ Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/ItemDockItem.cs 2009-03-25 03:40:59 +0000 |
649 | @@ -52,7 +52,7 @@ |
650 | bool accepting_drops; |
651 | Gdk.Pixbuf drag_pixbuf; |
652 | Gdk.Rectangle icon_region; |
653 | - List<Wnck.Application> apps; |
654 | + List<Wnck.Window> windows; |
655 | |
656 | public event EventHandler RemoveClicked; |
657 | |
658 | @@ -64,16 +64,32 @@ |
659 | get { return element.Icon; } |
660 | } |
661 | |
662 | + string Name { |
663 | + get { |
664 | + if (NeedsAttention && AttentionWindows.Any ()) |
665 | + return AttentionWindows.First ().Name; |
666 | + |
667 | + if (VisibleWindows.Any () && WindowCount == 1) |
668 | + return VisibleWindows.First ().Name; |
669 | + |
670 | + return Element.Name; |
671 | + } |
672 | + } |
673 | + |
674 | public Item Element { |
675 | get { return element; } |
676 | } |
677 | |
678 | - protected override IEnumerable<Wnck.Application> Applications { |
679 | - get { return apps; } |
680 | + public override IEnumerable<Wnck.Window> Windows { |
681 | + get { return windows; } |
682 | + } |
683 | + |
684 | + IEnumerable<Wnck.Window> AttentionWindows { |
685 | + get { return VisibleWindows.Where (w => w.NeedsAttention ()); } |
686 | } |
687 | |
688 | public IEnumerable<int> Pids { |
689 | - get { return apps.Select (win => win.Pid).ToArray (); } |
690 | + get { return windows.Select (win => win.Pid).ToArray (); } |
691 | } |
692 | |
693 | public override int WindowCount { |
694 | @@ -84,9 +100,7 @@ |
695 | { |
696 | Position = -1; |
697 | this.element = element; |
698 | - apps = new List<Wnck.Application> (); |
699 | - |
700 | - SetText (element.Name); |
701 | + windows = new List<Wnck.Window> (); |
702 | |
703 | UpdateApplication (); |
704 | NeedsAttention = DetermineUrgencyStatus (); |
705 | @@ -95,6 +109,8 @@ |
706 | accepting_drops = true; |
707 | else |
708 | accepting_drops = false; |
709 | + |
710 | + SetText (Name); |
711 | } |
712 | |
713 | public override bool ReceiveItem (string item) |
714 | @@ -126,46 +142,49 @@ |
715 | |
716 | public void UpdateApplication () |
717 | { |
718 | - UnregisterStateChangeEvents (); |
719 | + UnregisterWindowEvents (); |
720 | |
721 | if (element is IApplicationItem) { |
722 | - apps = WindowUtils.GetApplicationList ((element as IApplicationItem).Exec); |
723 | - window_count = Applications.SelectMany (a => a.Windows).Where (w => !w.IsSkipTasklist).Count (); |
724 | + windows = WindowUtils.WindowListForCmd ((element as IApplicationItem).Exec); |
725 | + window_count = windows.Where (w => !w.IsSkipTasklist).Count (); |
726 | } |
727 | |
728 | - RegisterStateChangeEvents (); |
729 | - } |
730 | - |
731 | - void RegisterStateChangeEvents () |
732 | - { |
733 | - foreach (Application app in Applications) { |
734 | - foreach (Wnck.Window w in app.Windows) { |
735 | - if (!w.IsSkipTasklist) |
736 | - w.StateChanged += OnWindowStateChanged; |
737 | - } |
738 | - } |
739 | - } |
740 | - |
741 | - void UnregisterStateChangeEvents () |
742 | - { |
743 | - foreach (Application app in Applications) { |
744 | - foreach (Wnck.Window w in app.Windows) { |
745 | - try { |
746 | - w.StateChanged -= OnWindowStateChanged; |
747 | - } catch {} |
748 | - } |
749 | - } |
750 | - } |
751 | - |
752 | - void OnWindowStateChanged (object o, StateChangedArgs args) |
753 | + RegisterWindowEvents (); |
754 | + SetText (Name); |
755 | + } |
756 | + |
757 | + void RegisterWindowEvents () |
758 | + { |
759 | + foreach (Wnck.Window w in VisibleWindows) { |
760 | + w.StateChanged += HandleStateChanged; |
761 | + w.NameChanged += HandleNameChanged; |
762 | + } |
763 | + } |
764 | + |
765 | + void UnregisterWindowEvents () |
766 | + { |
767 | + foreach (Wnck.Window w in Windows) { |
768 | + try { |
769 | + w.StateChanged -= HandleStateChanged; |
770 | + w.NameChanged += HandleNameChanged; |
771 | + } catch {} |
772 | + } |
773 | + } |
774 | + |
775 | + void HandleStateChanged (object o, StateChangedArgs args) |
776 | { |
777 | if (handle_timer > 0) return; |
778 | // we do this delayed so that we dont get a flood of these events. Certain windows behave badly. |
779 | handle_timer = GLib.Timeout.Add (100, HandleUpdate); |
780 | - window_count = Applications.SelectMany (a => a.Windows).Where (w => !w.IsSkipTasklist).Count (); |
781 | + window_count = VisibleWindows.Count (); |
782 | SetIconRegionFromCache (); |
783 | } |
784 | |
785 | + void HandleNameChanged(object sender, EventArgs e) |
786 | + { |
787 | + SetText (Name); |
788 | + } |
789 | + |
790 | bool HandleUpdate () |
791 | { |
792 | bool needed_attention = NeedsAttention; |
793 | @@ -180,6 +199,7 @@ |
794 | OnUpdateNeeded (new UpdateRequestArgs (this, req)); |
795 | } |
796 | |
797 | + SetText (Name); |
798 | handle_timer = 0; |
799 | return false; |
800 | } |
801 | @@ -250,9 +270,9 @@ |
802 | |
803 | public override void Dispose () |
804 | { |
805 | - UnregisterStateChangeEvents (); |
806 | + UnregisterWindowEvents (); |
807 | element = null; |
808 | - apps.Clear (); |
809 | + windows.Clear (); |
810 | |
811 | if (drag_pixbuf != null) |
812 | drag_pixbuf.Dispose (); |
813 | |
814 | === modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/WnckDockItem.cs' |
815 | --- Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/WnckDockItem.cs 2009-03-20 20:43:06 +0000 |
816 | +++ Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Items/WnckDockItem.cs 2009-04-01 01:08:07 +0000 |
817 | @@ -42,20 +42,26 @@ |
818 | |
819 | public abstract class WnckDockItem : AbstractDockItem |
820 | { |
821 | + // a bad hack, but it works |
822 | + static string [] blacklist = new [] { |
823 | + "CopyToClipboardAction", |
824 | + "WindowFocusAction", |
825 | + }; |
826 | + |
827 | int last_raised; |
828 | |
829 | DateTime last_scroll = new DateTime (0); |
830 | TimeSpan scroll_rate = new TimeSpan (0, 0, 0, 0, 300); |
831 | |
832 | - protected abstract IEnumerable<Wnck.Application> Applications { get; } |
833 | + public abstract IEnumerable<Wnck.Window> Windows { get; } |
834 | |
835 | protected IEnumerable<Wnck.Window> VisibleWindows { |
836 | - get { return Applications.SelectMany (a => a.Windows).Where (w => !w.IsSkipTasklist); } |
837 | + get { return Windows.Where (w => !w.IsSkipTasklist); } |
838 | } |
839 | |
840 | protected bool HasVisibleApps { |
841 | get { |
842 | - if (Applications == null) |
843 | + if (Windows == null) |
844 | return false; |
845 | return VisibleWindows.Any (); |
846 | } |
847 | @@ -69,7 +75,7 @@ |
848 | protected IEnumerable<Act> ActionsForItem (Item item) |
849 | { |
850 | return Services.Core.GetActionsForItemOrderedByRelevance (item, false) |
851 | - .Where (act => act.GetType ().Name != "CopyToClipboardAction") |
852 | + .Where (act => !blacklist.Contains (act.GetType ().Name)) |
853 | .OrderByDescending (act => act.GetType ().Name != "WindowCloseAction") |
854 | .ThenByDescending (act => act.GetType ().Name != "WindowMaximizeAction") |
855 | .ThenByDescending (act => act.GetType ().Name != "WindowMinimizeAction") |
856 | @@ -77,10 +83,7 @@ |
857 | .ThenBy (act => act.Name); |
858 | } |
859 | |
860 | - protected virtual void Launch () |
861 | - { |
862 | - return; |
863 | - } |
864 | + protected abstract void Launch (); |
865 | |
866 | public override void Scrolled (Gdk.ScrollDirection direction) |
867 | { |
868 | @@ -115,12 +118,12 @@ |
869 | |
870 | public override void Clicked (uint button, Gdk.ModifierType state, Gdk.Point position) |
871 | { |
872 | - if (!Applications.Any () || !HasVisibleApps || button == 2) { |
873 | + if (!Windows.Any () || !HasVisibleApps || button == 2) { |
874 | AnimationType = ClickAnimationType.Bounce; |
875 | Launch (); |
876 | } else if (button == 1) { |
877 | AnimationType = ClickAnimationType.Darken; |
878 | - WindowUtils.PerformLogicalClick (Applications); |
879 | + WindowUtils.PerformLogicalClick (Windows); |
880 | } else { |
881 | AnimationType = ClickAnimationType.None; |
882 | } |
883 | |
884 | === modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Menus/AbstractMenuButtonArgs.cs' |
885 | --- Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Menus/AbstractMenuButtonArgs.cs 2009-03-07 22:50:28 +0000 |
886 | +++ Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Menus/AbstractMenuButtonArgs.cs 2009-03-26 14:42:21 +0000 |
887 | @@ -39,7 +39,8 @@ |
888 | const int Height = 22; |
889 | |
890 | Gtk.Widget widget; |
891 | - bool hovered; |
892 | + bool hovered, tooltip; |
893 | + string description, icon; |
894 | |
895 | public bool Dark { get; set; } |
896 | |
897 | @@ -47,33 +48,60 @@ |
898 | get { return 1; } |
899 | } |
900 | |
901 | - public override Gtk.Widget Widget { |
902 | - get { |
903 | - if (widget == null) |
904 | - widget = BuildWidget (); |
905 | - return widget; |
906 | - } |
907 | - } |
908 | - |
909 | - protected virtual string Description { get; set; } |
910 | - |
911 | - protected virtual string Icon { get; set; } |
912 | - |
913 | - protected virtual bool UseTooltip { get; set; } |
914 | + public override Gtk.Widget Widget { |
915 | + get { return widget; } |
916 | + } |
917 | + |
918 | + private Gdk.Pixbuf Pixbuf { get; set; } |
919 | + |
920 | + protected string Description { |
921 | + get { |
922 | + return description; |
923 | + } |
924 | + set { |
925 | + description = value; |
926 | + BuildWidget (); |
927 | + } |
928 | + } |
929 | + |
930 | + protected string Icon { |
931 | + get { |
932 | + return icon; |
933 | + } |
934 | + set { |
935 | + icon = value; |
936 | + BuildWidget (); |
937 | + } |
938 | + } |
939 | + |
940 | + protected bool UseTooltip { |
941 | + get { |
942 | + return tooltip; |
943 | + } |
944 | + set { |
945 | + |
946 | + tooltip = value; |
947 | + BuildWidget (); |
948 | + } |
949 | + } |
950 | |
951 | public AbstractMenuButtonArgs () |
952 | { |
953 | - |
954 | } |
955 | |
956 | public AbstractMenuButtonArgs (string description, string icon) |
957 | { |
958 | - Description = GLib.Markup.EscapeText (Catalog.GetString (description)); |
959 | - Icon = icon; |
960 | + this.description = GLib.Markup.EscapeText (Catalog.GetString (description)); |
961 | + this.icon = icon; |
962 | + |
963 | + BuildWidget (); |
964 | } |
965 | |
966 | - Widget BuildWidget () |
967 | + void BuildWidget () |
968 | { |
969 | + if (widget != null) |
970 | + widget.Destroy (); |
971 | + |
972 | DrawingArea button = new DrawingArea (); |
973 | |
974 | button.ExposeEvent += HandleExposeEvent; |
975 | @@ -88,7 +116,12 @@ |
976 | if (UseTooltip) |
977 | button.TooltipText = Description; |
978 | |
979 | - return button; |
980 | + widget = button; |
981 | + |
982 | + if (Pixbuf != null) |
983 | + Pixbuf.Dispose (); |
984 | + |
985 | + Pixbuf = GetPixbuf (Height - 8); |
986 | } |
987 | |
988 | void HandleButtonReleaseEvent(object o, ButtonReleaseEventArgs args) |
989 | @@ -135,27 +168,31 @@ |
990 | |
991 | int width = area.Width - WidthBuffer * 2 - 25; |
992 | |
993 | - TextRenderContext renderContext = new TextRenderContext (cr, string.Format (FormatString, Description), width); |
994 | - |
995 | - renderContext.LeftCenteredPoint = new Gdk.Point (area.X + WidthBuffer + 25, area.Y + area.Height / 2); |
996 | - renderContext.Alignment = Pango.Alignment.Left; |
997 | - renderContext.EllipsizeMode = Pango.EllipsizeMode.End; |
998 | - |
999 | - DockServices.DrawingService.TextPathAtPoint (renderContext); |
1000 | - |
1001 | - cr.Color = new Cairo.Color (1, 1, 1); |
1002 | - cr.Fill (); |
1003 | - |
1004 | - Gdk.Pixbuf pbuf = GetPixbuf (Height - 8); |
1005 | - CairoHelper.SetSourcePixbuf (cr, pbuf, WidthBuffer, (Height - pbuf.Height) / 2); |
1006 | - cr.PaintWithAlpha (IconOpacity); |
1007 | - pbuf.Dispose (); |
1008 | + if (!string.IsNullOrEmpty (Description)) { |
1009 | + TextRenderContext renderContext = new TextRenderContext (cr, string.Format (FormatString, Description), width); |
1010 | + |
1011 | + renderContext.LeftCenteredPoint = new Gdk.Point (area.X + WidthBuffer + 25, area.Y + area.Height / 2); |
1012 | + renderContext.Alignment = Pango.Alignment.Left; |
1013 | + renderContext.EllipsizeMode = Pango.EllipsizeMode.End; |
1014 | + |
1015 | + DockServices.DrawingService.TextPathAtPoint (renderContext); |
1016 | + |
1017 | + cr.Color = new Cairo.Color (1, 1, 1); |
1018 | + cr.Fill (); |
1019 | + } |
1020 | + |
1021 | + if (Pixbuf != null) { |
1022 | + CairoHelper.SetSourcePixbuf (cr, Pixbuf, WidthBuffer, (Height - Pixbuf.Height) / 2); |
1023 | + cr.PaintWithAlpha (IconOpacity); |
1024 | + } |
1025 | } |
1026 | } |
1027 | |
1028 | protected virtual Gdk.Pixbuf GetPixbuf (int size) |
1029 | { |
1030 | - return IconProvider.PixbufFromIconName (Icon, size); |
1031 | + if (!string.IsNullOrEmpty (Icon)) |
1032 | + return IconProvider.PixbufFromIconName (Icon, size); |
1033 | + return null; |
1034 | } |
1035 | |
1036 | public abstract void Action (); |
1037 | @@ -169,6 +206,7 @@ |
1038 | public override void Dispose () |
1039 | { |
1040 | Widget.Destroy (); |
1041 | + Pixbuf.Dispose (); |
1042 | base.Dispose (); |
1043 | } |
1044 | |
1045 | |
1046 | === modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Menus/WindowMenuButtonArgs.cs' |
1047 | --- Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Menus/WindowMenuButtonArgs.cs 2009-03-20 20:43:06 +0000 |
1048 | +++ Do.Interface.Linux.Docky/src/Docky.Interface/Docky.Interface.Menus/WindowMenuButtonArgs.cs 2009-03-26 04:33:12 +0000 |
1049 | @@ -38,7 +38,6 @@ |
1050 | return (window.IsMinimized) ? .5 : base.IconOpacity; |
1051 | } |
1052 | } |
1053 | - |
1054 | |
1055 | public WindowMenuButtonArgs (Wnck.Window window, string description, string icon) : base (description, icon) |
1056 | { |
1057 | |
1058 | === modified file 'Do.Interface.Linux.Docky/src/Docky.Interface/Util.cs' |
1059 | --- Do.Interface.Linux.Docky/src/Docky.Interface/Util.cs 2009-03-20 20:43:06 +0000 |
1060 | +++ Do.Interface.Linux.Docky/src/Docky.Interface/Util.cs 2009-03-24 16:08:07 +0000 |
1061 | @@ -78,7 +78,8 @@ |
1062 | DockOrientation orientation) |
1063 | { |
1064 | Surface sr; |
1065 | - sr = similar.CreateSimilar (similar.Content, maxWidth, Height); |
1066 | + // we are going to give ourselves a bit of a buffer due to pango weirdness |
1067 | + sr = similar.CreateSimilar (similar.Content, maxWidth + 5, Height); |
1068 | |
1069 | Context cr = new Context (sr); |
1070 | |
1071 | @@ -89,7 +90,7 @@ |
1072 | cr.NewPath (); |
1073 | |
1074 | int localHeight = textArea.Height; |
1075 | - cr.SetRoundedRectanglePath (textArea.X + .5, .5, textArea.Width + 20 - 1, localHeight + 10 - 1, 5); |
1076 | + cr.SetRoundedRectanglePath (textArea.X + .5, .5, textArea.Width + 20 - 1, localHeight + 10 - 1, 5); |
1077 | |
1078 | cr.Color = new Cairo.Color (0.1, 0.1, 0.1, .75); |
1079 | cr.FillPreserve (); |
1080 | |
1081 | === modified file 'Do.Interface.Wink/Do.Interface.Wink.mdp' |
1082 | --- Do.Interface.Wink/Do.Interface.Wink.mdp 2009-03-20 20:43:06 +0000 |
1083 | +++ Do.Interface.Wink/Do.Interface.Wink.mdp 2009-03-31 03:39:44 +0000 |
1084 | @@ -20,11 +20,20 @@ |
1085 | <File name="src/AssemblyInfo.cs" subtype="Code" buildaction="Compile" /> |
1086 | <File name="src/Do.Interface.Wink/WindowControl.cs" subtype="Code" buildaction="Compile" /> |
1087 | <File name="src/Do.Interface.Wink/WindowUtils.cs" subtype="Code" buildaction="Compile" /> |
1088 | + <File name="src/Do.Interface.Wink/ClickAction.cs" subtype="Code" buildaction="Compile" /> |
1089 | + <File name="src/Do.Interface.Wink/ScreenUtils.cs" subtype="Code" buildaction="Compile" /> |
1090 | + <File name="src/Do.Interface.Wink/Viewport.cs" subtype="Code" buildaction="Compile" /> |
1091 | + <File name="src/Do.Interface.Xlib" subtype="Directory" buildaction="Compile" /> |
1092 | + <File name="src/Do.Interface.Xlib/X11Atoms.cs" subtype="Code" buildaction="Compile" /> |
1093 | + <File name="src/Do.Interface.Xlib/Xlib.cs" subtype="Code" buildaction="Compile" /> |
1094 | </Contents> |
1095 | <References> |
1096 | <ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> |
1097 | <ProjectReference type="Gac" localcopy="True" refto="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> |
1098 | <ProjectReference type="Gac" localcopy="True" refto="wnck-sharp, Version=2.20.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" /> |
1099 | <ProjectReference type="Project" localcopy="True" refto="Do.Platform" /> |
1100 | + <ProjectReference type="Gac" localcopy="True" refto="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" /> |
1101 | + <ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" /> |
1102 | + <ProjectReference type="Gac" localcopy="True" refto="Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" /> |
1103 | </References> |
1104 | </Project> |
1105 | \ No newline at end of file |
1106 | |
1107 | === modified file 'Do.Interface.Wink/Makefile.am' |
1108 | --- Do.Interface.Wink/Makefile.am 2009-03-20 23:06:10 +0000 |
1109 | +++ Do.Interface.Wink/Makefile.am 2009-03-31 16:23:23 +0000 |
1110 | @@ -8,8 +8,13 @@ |
1111 | |
1112 | FILES = \ |
1113 | src/AssemblyInfo.cs \ |
1114 | + src/Do.Interface.Xlib/Xlib.cs \ |
1115 | + src/Do.Interface.Xlib/X11Atoms.cs \ |
1116 | + src/Do.Interface.Wink/ClickAction.cs \ |
1117 | src/Do.Interface.Wink/WindowControl.cs \ |
1118 | - src/Do.Interface.Wink/WindowUtils.cs |
1119 | + src/Do.Interface.Wink/WindowUtils.cs \ |
1120 | + src/Do.Interface.Wink/ScreenUtils.cs \ |
1121 | + src/Do.Interface.Wink/Viewport.cs |
1122 | |
1123 | #RESOURCES = \ |
1124 | # Resources/Do.Interface.Wnck.addin.xml |
1125 | @@ -17,11 +22,12 @@ |
1126 | REFERENCES = \ |
1127 | System \ |
1128 | System.Core \ |
1129 | + Mono.Posix \ |
1130 | $(GTK_SHARP_20_LIBS) \ |
1131 | $(WNCK_SHARP_10_LIBS) |
1132 | |
1133 | PROJECT_REFERENCES = \ |
1134 | Do.Platform |
1135 | |
1136 | -#module_DATA += $(ASSEMBLY).dll.config |
1137 | -#EXTRA_DIST += $(ASSEMBLY).dll.config |
1138 | +module_DATA += $(ASSEMBLY).dll.config |
1139 | +EXTRA_DIST += $(ASSEMBLY).dll.config |
1140 | |
1141 | === added file 'Do.Interface.Wink/src/Do.Interface.Wink/ClickAction.cs' |
1142 | --- Do.Interface.Wink/src/Do.Interface.Wink/ClickAction.cs 1970-01-01 00:00:00 +0000 |
1143 | +++ Do.Interface.Wink/src/Do.Interface.Wink/ClickAction.cs 2009-03-25 19:49:42 +0000 |
1144 | @@ -0,0 +1,31 @@ |
1145 | +// |
1146 | +// Copyright (C) 2009 GNOME Do |
1147 | +// |
1148 | +// This program is free software: you can redistribute it and/or modify |
1149 | +// it under the terms of the GNU General Public License as published by |
1150 | +// the Free Software Foundation, either version 3 of the License, or |
1151 | +// (at your option) any later version. |
1152 | +// |
1153 | +// This program is distributed in the hope that it will be useful, |
1154 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
1155 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1156 | +// GNU General Public License for more details. |
1157 | +// |
1158 | +// You should have received a copy of the GNU General Public License |
1159 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1160 | +// |
1161 | + |
1162 | +using System; |
1163 | + |
1164 | +namespace Do.Interface.Wink |
1165 | +{ |
1166 | + |
1167 | + |
1168 | + public enum ClickAction |
1169 | + { |
1170 | + Focus, |
1171 | + Minimize, |
1172 | + Restore, |
1173 | + None, |
1174 | + } |
1175 | +} |
1176 | |
1177 | === added file 'Do.Interface.Wink/src/Do.Interface.Wink/ScreenUtils.cs' |
1178 | --- Do.Interface.Wink/src/Do.Interface.Wink/ScreenUtils.cs 1970-01-01 00:00:00 +0000 |
1179 | +++ Do.Interface.Wink/src/Do.Interface.Wink/ScreenUtils.cs 2009-04-01 01:08:07 +0000 |
1180 | @@ -0,0 +1,138 @@ |
1181 | +// |
1182 | +// Copyright (C) 2009 GNOME Do |
1183 | +// |
1184 | +// This program is free software: you can redistribute it and/or modify |
1185 | +// it under the terms of the GNU General Public License as published by |
1186 | +// the Free Software Foundation, either version 3 of the License, or |
1187 | +// (at your option) any later version. |
1188 | +// |
1189 | +// This program is distributed in the hope that it will be useful, |
1190 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
1191 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1192 | +// GNU General Public License for more details. |
1193 | +// |
1194 | +// You should have received a copy of the GNU General Public License |
1195 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1196 | +// |
1197 | + |
1198 | +using System; |
1199 | +using System.Collections.Generic; |
1200 | +using System.Linq; |
1201 | + |
1202 | +using Mono.Unix; |
1203 | + |
1204 | +using Wnck; |
1205 | + |
1206 | +namespace Do.Interface.Wink |
1207 | +{ |
1208 | + |
1209 | + |
1210 | + public static class ScreenUtils |
1211 | + { |
1212 | + static string ViewportFormatString = Catalog.GetString ("Desktop") + " {0}"; |
1213 | + static List<Viewport> viewports; |
1214 | + |
1215 | + public static Viewport ActiveViewport { |
1216 | + get { |
1217 | + Workspace wsp = Wnck.Screen.Default.ActiveWorkspace; |
1218 | + Gdk.Rectangle geo = new Gdk.Rectangle (wsp.ViewportX, wsp.ViewportY, wsp.Screen.Width, wsp.Screen.Height); |
1219 | + if (viewports.Any (vp => vp.Area == geo)) |
1220 | + return viewports.First (vp => vp.Area == geo); |
1221 | + return null; |
1222 | + } |
1223 | + } |
1224 | + |
1225 | + public static IEnumerable<Viewport> Viewports { |
1226 | + get { return viewports.AsEnumerable (); } |
1227 | + } |
1228 | + |
1229 | + static ScreenUtils () |
1230 | + { |
1231 | + Wnck.Screen.Default.ViewportsChanged += HandleViewportsChanged; |
1232 | + Wnck.Screen.Default.WorkspaceCreated += HandleWorkspaceCreated; |
1233 | + Wnck.Screen.Default.WorkspaceDestroyed += HandleWorkspaceDestroyed; |
1234 | + |
1235 | +// Wnck.Screen.Default.ForceUpdate (); |
1236 | + UpdateViewports (); |
1237 | + } |
1238 | + |
1239 | + static void HandleWorkspaceDestroyed(object o, WorkspaceDestroyedArgs args) |
1240 | + { |
1241 | + UpdateViewports (); |
1242 | + } |
1243 | + |
1244 | + static void HandleWorkspaceCreated(object o, WorkspaceCreatedArgs args) |
1245 | + { |
1246 | + UpdateViewports (); |
1247 | + } |
1248 | + |
1249 | + static void HandleViewportsChanged(object sender, EventArgs e) |
1250 | + { |
1251 | + UpdateViewports (); |
1252 | + } |
1253 | + |
1254 | + public static bool DesktopShow (Screen screen) |
1255 | + { |
1256 | + return screen.ShowingDesktop; |
1257 | + } |
1258 | + |
1259 | + public static void ShowDesktop (Screen screen) |
1260 | + { |
1261 | + if (!screen.ShowingDesktop) |
1262 | + screen.ToggleShowingDesktop (true); |
1263 | + } |
1264 | + |
1265 | + public static void UnshowDesktop (Screen screen) |
1266 | + { |
1267 | + if (screen.ShowingDesktop) |
1268 | + screen.ToggleShowingDesktop (false); |
1269 | + } |
1270 | + |
1271 | + public static IEnumerable<Window> ViewportWindows (Viewport viewport) |
1272 | + { |
1273 | + var windows = WindowUtils.GetWindows () |
1274 | + .Where (w => w.WindowType != WindowType.Dock && !w.IsSkipTasklist); |
1275 | + |
1276 | + foreach (Window window in windows) { |
1277 | + if (viewport.WindowCenterInViewport (window)) |
1278 | + yield return window; |
1279 | + } |
1280 | + } |
1281 | + |
1282 | + static void UpdateViewports () |
1283 | + { |
1284 | + viewports = new List<Viewport> (); |
1285 | + int currentViewport = 1; |
1286 | + foreach (Wnck.Workspace workspace in Wnck.Screen.Default.Workspaces) { |
1287 | + if (workspace.IsVirtual) { |
1288 | + int viewportWidth; |
1289 | + int viewportHeight; |
1290 | + viewportWidth = workspace.Screen.Width; |
1291 | + viewportHeight = workspace.Screen.Height; |
1292 | + |
1293 | + int rows = workspace.Height / viewportHeight; |
1294 | + int columns = workspace.Width / viewportWidth; |
1295 | + |
1296 | + for (int i = 0; i < rows; i++) { |
1297 | + for (int j = 0; j < columns; j++) { |
1298 | + Gdk.Rectangle area = new Gdk.Rectangle (j * viewportWidth, |
1299 | + i * viewportHeight, |
1300 | + viewportWidth, |
1301 | + viewportHeight); |
1302 | + viewports.Add (new Viewport (string.Format (ViewportFormatString, currentViewport), |
1303 | + area, |
1304 | + workspace)); |
1305 | + currentViewport++; |
1306 | + } |
1307 | + } |
1308 | + } else { |
1309 | + Viewport viewport = new Viewport (string.Format (ViewportFormatString, currentViewport), |
1310 | + new Gdk.Rectangle (0, 0, workspace.Width, workspace.Height), |
1311 | + workspace); |
1312 | + viewports.Add (viewport); |
1313 | + currentViewport++; |
1314 | + } |
1315 | + } |
1316 | + } |
1317 | + } |
1318 | +} |
1319 | |
1320 | === added file 'Do.Interface.Wink/src/Do.Interface.Wink/Viewport.cs' |
1321 | --- Do.Interface.Wink/src/Do.Interface.Wink/Viewport.cs 1970-01-01 00:00:00 +0000 |
1322 | +++ Do.Interface.Wink/src/Do.Interface.Wink/Viewport.cs 2009-03-31 16:23:23 +0000 |
1323 | @@ -0,0 +1,142 @@ |
1324 | +// |
1325 | +// Copyright (C) 2009 GNOME Do |
1326 | +// |
1327 | +// This program is free software: you can redistribute it and/or modify |
1328 | +// it under the terms of the GNU General Public License as published by |
1329 | +// the Free Software Foundation, either version 3 of the License, or |
1330 | +// (at your option) any later version. |
1331 | +// |
1332 | +// This program is distributed in the hope that it will be useful, |
1333 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
1334 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1335 | +// GNU General Public License for more details. |
1336 | +// |
1337 | +// You should have received a copy of the GNU General Public License |
1338 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
1339 | +// |
1340 | + |
1341 | +using System; |
1342 | +using System.Collections.Generic; |
1343 | +using System.Runtime.InteropServices; |
1344 | + |
1345 | + |
1346 | +using Gdk; |
1347 | +using Wnck; |
1348 | + |
1349 | +using Do.Platform; |
1350 | +using Do.Interface.Xlib; |
1351 | + |
1352 | +namespace Do.Interface.Wink |
1353 | +{ |
1354 | + |
1355 | + |
1356 | + public class Viewport |
1357 | + { |
1358 | + Workspace parent; |
1359 | + Rectangle area; |
1360 | + |
1361 | + public string Name { get; private set; } |
1362 | + |
1363 | + internal Rectangle Area { |
1364 | + get { return area; } |
1365 | + } |
1366 | + |
1367 | + internal Viewport(string name, Rectangle area, Workspace parent) |
1368 | + { |
1369 | + this.area = area; |
1370 | + this.parent = parent; |
1371 | + Name = name; |
1372 | + } |
1373 | + |
1374 | + public void MoveWindowInto (Wnck.Window window) |
1375 | + { |
1376 | + if (parent.IsVirtual) { |
1377 | + Rectangle geo; |
1378 | + window.GetGeometry (out geo.X, out geo.Y, out geo.Width, out geo.Height); |
1379 | + |
1380 | + geo.X += window.Workspace.ViewportX; |
1381 | + geo.Y += window.Workspace.ViewportY; |
1382 | + |
1383 | + int x = area.X + (geo.X % area.Width); |
1384 | + int y = area.Y + (geo.Y % area.Height); |
1385 | + |
1386 | + x -= window.Workspace.ViewportX; |
1387 | + y -= window.Workspace.ViewportY; |
1388 | + |
1389 | + if (string.Compare (window.Screen.WindowManagerName, "compiz", true) == 0) { |
1390 | + // This is a compiz-ism. Don't know when they will fix it. You must subtract the top and left |
1391 | + // frame extents from a move operation to get the window to actually show in the right spot. |
1392 | + // Save for maybe kwin, I think only compiz uses Viewports anyhow, so this is ok. |
1393 | + int [] extents = GetWindowFrameExtents (window); |
1394 | + int left_extent = extents [0]; |
1395 | + int top_extent = extents [2]; |
1396 | + |
1397 | + x -= left_extent; |
1398 | + y -= top_extent; |
1399 | + } |
1400 | + |
1401 | + WindowMoveResizeMask mask = WindowMoveResizeMask.X | WindowMoveResizeMask.Y; |
1402 | + window.SetGeometry (WindowGravity.Current, mask, x, y, 0, 0); |
1403 | + } else { |
1404 | + window.MoveToWorkspace (parent); |
1405 | + } |
1406 | + } |
1407 | + |
1408 | + int[] GetWindowFrameExtents (Wnck.Window window) |
1409 | + { |
1410 | + X11Atoms atoms = X11Atoms.Instance; |
1411 | + |
1412 | + IntPtr display; |
1413 | + IntPtr type; |
1414 | + int format; |
1415 | + IntPtr prop_return; |
1416 | + IntPtr nitems, bytes_after; |
1417 | + int result; |
1418 | + int [] extents = new int[4]; |
1419 | + |
1420 | + IntPtr window_handle = (IntPtr) window.Xid; |
1421 | + |
1422 | + display = Xlib.Xlib.GdkDisplayXDisplay (Gdk.Screen.Default.Display); |
1423 | + type = IntPtr.Zero; |
1424 | + |
1425 | + result = Xlib.Xlib.XGetWindowProperty (display, window_handle, atoms._NET_FRAME_EXTENTS, (IntPtr) 0, |
1426 | + (IntPtr) System.Int32.MaxValue, false, atoms.XA_CARDINAL, out type, out format, |
1427 | + out nitems, out bytes_after, out prop_return); |
1428 | + |
1429 | + if (type == atoms.XA_CARDINAL && format == 32) { |
1430 | + extents = new int [(int) nitems]; |
1431 | + for (int i = 0; i < (int) nitems; i++) { |
1432 | + extents [i] = Marshal.ReadInt32 (prop_return, i * 4); |
1433 | + } |
1434 | + } |
1435 | + |
1436 | + return extents; |
1437 | + } |
1438 | + |
1439 | + public bool WindowVisibleInVeiwport (Wnck.Window window) |
1440 | + { |
1441 | + Rectangle geo; |
1442 | + window.GetGeometry (out geo.X, out geo.Y, out geo.Width, out geo.Height); |
1443 | + geo.X += parent.ViewportX; |
1444 | + geo.Y += parent.ViewportY; |
1445 | + |
1446 | + return area.IntersectsWith (geo); |
1447 | + } |
1448 | + |
1449 | + public bool WindowCenterInViewport (Wnck.Window window) |
1450 | + { |
1451 | + Rectangle geo; |
1452 | + window.GetGeometry (out geo.X, out geo.Y, out geo.Width, out geo.Height); |
1453 | + geo.X += parent.ViewportX; |
1454 | + geo.Y += parent.ViewportY; |
1455 | + |
1456 | + Point center = new Point (geo.X + geo.Width / 2, geo.Y + geo.Height / 2); |
1457 | + return Contains (center); |
1458 | + } |
1459 | + |
1460 | + public bool Contains (Gdk.Point point) |
1461 | + { |
1462 | + return area.Contains (point); |
1463 | + } |
1464 | + } |
1465 | +} |
1466 | |
1467 | === modified file 'Do.Interface.Wink/src/Do.Interface.Wink/WindowControl.cs' |
1468 | --- Do.Interface.Wink/src/Do.Interface.Wink/WindowControl.cs 2009-03-20 20:43:06 +0000 |
1469 | +++ Do.Interface.Wink/src/Do.Interface.Wink/WindowControl.cs 2009-03-31 03:39:44 +0000 |
1470 | @@ -88,11 +88,18 @@ |
1471 | |
1472 | public static void FocusWindows (IEnumerable<Window> windows) |
1473 | { |
1474 | - foreach (Window window in windows.Reverse ()) { |
1475 | - if (window.IsInViewport (window.Screen.ActiveWorkspace) && !window.IsMinimized) { |
1476 | - window.CenterAndFocusWindow (); |
1477 | - System.Threading.Thread.Sleep (SleepTime); |
1478 | + if (!windows.Any ()) |
1479 | + return; |
1480 | + |
1481 | + if (windows.Any (w => w.IsInViewport (w.Screen.ActiveWorkspace))) { |
1482 | + foreach (Window window in windows.Reverse ()) { |
1483 | + if (window.IsInViewport (window.Screen.ActiveWorkspace) && !window.IsMinimized) { |
1484 | + window.CenterAndFocusWindow (); |
1485 | + System.Threading.Thread.Sleep (SleepTime); |
1486 | + } |
1487 | } |
1488 | + } else { |
1489 | + windows.First ().CenterAndFocusWindow (); |
1490 | } |
1491 | |
1492 | if (windows.Count () <= 1) |
1493 | @@ -102,7 +109,9 @@ |
1494 | // sometimes compiz plays badly. This hacks around it |
1495 | uint time = Gtk.Global.CurrentEventTime + 200; |
1496 | GLib.Timeout.Add (200, delegate { |
1497 | - windows.Where (w => w.IsInViewport (w.Screen.ActiveWorkspace) && !w.IsMinimized).First ().Activate (time); |
1498 | + try { //unimportant if this fails, its just "nice" |
1499 | + windows.Where (w => w.IsInViewport (w.Screen.ActiveWorkspace) && !w.IsMinimized).First ().Activate (time); |
1500 | + } catch { } |
1501 | return false; |
1502 | }); |
1503 | } |
1504 | @@ -187,6 +196,17 @@ |
1505 | window.Maximize (); |
1506 | } |
1507 | |
1508 | + public static void MoveToWorkspace (Window window, Workspace workspace) |
1509 | + { |
1510 | + MoveToWorkspace (new [] {window}, workspace); |
1511 | + } |
1512 | + |
1513 | + public static void MoveToWorkspace (IEnumerable<Window> windows, Workspace workspace) |
1514 | + { |
1515 | + foreach (Window window in windows.Where (w => w.Workspace != workspace)) |
1516 | + window.MoveToWorkspace (workspace); |
1517 | + } |
1518 | + |
1519 | /// <summary> |
1520 | /// Moves the current viewport to the selected window and then raises it |
1521 | /// </summary> |
1522 | |
1523 | === modified file 'Do.Interface.Wink/src/Do.Interface.Wink/WindowUtils.cs' |
1524 | --- Do.Interface.Wink/src/Do.Interface.Wink/WindowUtils.cs 2009-03-21 02:35:05 +0000 |
1525 | +++ Do.Interface.Wink/src/Do.Interface.Wink/WindowUtils.cs 2009-04-01 01:08:07 +0000 |
1526 | @@ -29,12 +29,6 @@ |
1527 | |
1528 | namespace Do.Interface.Wink |
1529 | { |
1530 | - public enum ClickAction { |
1531 | - Focus, |
1532 | - Minimize, |
1533 | - Restore, |
1534 | - None, |
1535 | - } |
1536 | |
1537 | public static class WindowUtils |
1538 | { |
1539 | @@ -42,7 +36,7 @@ |
1540 | get { return Path.Combine (Services.Paths.UserDataDirectory, "RemapFile"); } |
1541 | } |
1542 | |
1543 | - public static IEnumerable<string> BadPrefixes { |
1544 | + static IEnumerable<string> PrefixStrings { |
1545 | get { |
1546 | yield return "gksu"; |
1547 | yield return "sudo"; |
1548 | @@ -55,35 +49,46 @@ |
1549 | } |
1550 | } |
1551 | |
1552 | + public static IEnumerable<Regex> BadPrefixes { get; private set; } |
1553 | + |
1554 | static Dictionary<string, string> RemapDictionary { get; set; } |
1555 | |
1556 | - static List<Application> application_list; |
1557 | - static bool application_list_update_needed; |
1558 | + static List<Window> window_list; |
1559 | + static bool window_list_update_needed; |
1560 | |
1561 | static Dictionary<int, string> exec_lines = new Dictionary<int, string> (); |
1562 | static DateTime last_update = new DateTime (0); |
1563 | |
1564 | + #region ctor |
1565 | static WindowUtils () |
1566 | { |
1567 | + List<Regex> regex = new List<Regex> (); |
1568 | + foreach (string s in PrefixStrings) { |
1569 | + regex.Add (new Regex (string.Format ("^{0}$", s), RegexOptions.IgnoreCase)); |
1570 | + } |
1571 | + BadPrefixes = regex.AsEnumerable (); |
1572 | + |
1573 | Wnck.Screen.Default.WindowClosed += delegate { |
1574 | - application_list_update_needed = true; |
1575 | + window_list_update_needed = true; |
1576 | }; |
1577 | |
1578 | Wnck.Screen.Default.WindowOpened += delegate { |
1579 | - application_list_update_needed = true; |
1580 | + window_list_update_needed = true; |
1581 | }; |
1582 | |
1583 | Wnck.Screen.Default.ApplicationOpened += delegate { |
1584 | - application_list_update_needed = true; |
1585 | + window_list_update_needed = true; |
1586 | }; |
1587 | |
1588 | Wnck.Screen.Default.ApplicationClosed += delegate { |
1589 | - application_list_update_needed = true; |
1590 | + window_list_update_needed = true; |
1591 | }; |
1592 | |
1593 | BuildRemapDictionary (); |
1594 | } |
1595 | + #endregion |
1596 | |
1597 | + #region Private Methods |
1598 | static void BuildRemapDictionary () |
1599 | { |
1600 | if (!File.Exists (RemapFile)) { |
1601 | @@ -151,117 +156,39 @@ |
1602 | return remapDict; |
1603 | } |
1604 | |
1605 | - /// <summary> |
1606 | - /// Returns a list of all applications on the default screen |
1607 | - /// </summary> |
1608 | - /// <returns> |
1609 | - /// A <see cref="Application"/> array |
1610 | - /// </returns> |
1611 | - public static List<Application> GetApplications () |
1612 | - { |
1613 | - if (application_list == null || application_list_update_needed) { |
1614 | - application_list = new List<Application> (); |
1615 | - foreach (Window w in Wnck.Screen.Default.Windows) { |
1616 | - if (!application_list.Contains (w.Application)) |
1617 | - application_list.Add (w.Application); |
1618 | - } |
1619 | - } |
1620 | - return application_list; |
1621 | - } |
1622 | - |
1623 | - /// <summary> |
1624 | - /// Gets the command line excec string for a PID |
1625 | - /// </summary> |
1626 | - /// <param name="pid"> |
1627 | - /// A <see cref="System.Int32"/> |
1628 | - /// </param> |
1629 | - /// <returns> |
1630 | - /// A <see cref="System.String"/> |
1631 | - /// </returns> |
1632 | - public static string CmdLineForPid (int pid) |
1633 | - { |
1634 | - StreamReader reader; |
1635 | - string cmdline = null; |
1636 | - |
1637 | - try { |
1638 | - string procPath = new [] { "/proc", pid.ToString (), "cmdline" }.Aggregate (Path.Combine); |
1639 | - reader = new StreamReader (procPath); |
1640 | - cmdline = reader.ReadLine ().Replace (Convert.ToChar (0x0), ' '); |
1641 | - reader.Close (); |
1642 | - reader.Dispose (); |
1643 | - } catch { } |
1644 | - |
1645 | - return cmdline; |
1646 | - } |
1647 | - |
1648 | - /// <summary> |
1649 | - /// Returns a list of applications that match an exec string |
1650 | - /// </summary> |
1651 | - /// <param name="exec"> |
1652 | - /// A <see cref="System.String"/> |
1653 | - /// </param> |
1654 | - /// <returns> |
1655 | - /// A <see cref="List"/> |
1656 | - /// </returns> |
1657 | - public static List<Application> GetApplicationList (string exec) |
1658 | - { |
1659 | - List<Application> apps = new List<Application> (); |
1660 | - if (string.IsNullOrEmpty (exec)) |
1661 | - return apps; |
1662 | - |
1663 | - exec = ProcessExecString (exec); |
1664 | - if (string.IsNullOrEmpty (exec)) |
1665 | - return apps; |
1666 | - |
1667 | - UpdateExecList (); |
1668 | - |
1669 | - foreach (KeyValuePair<int, string> kvp in exec_lines) { |
1670 | - if (kvp.Value != null && kvp.Value.Contains (exec)) { |
1671 | - foreach (Application app in GetApplications ()) { |
1672 | - if (app == null) |
1673 | - continue; |
1674 | - |
1675 | - if (app.Pid == kvp.Key || app.Windows.Any (w => w.Pid == kvp.Key)) { |
1676 | - if (app.Windows.Any (win => !win.IsSkipTasklist)) |
1677 | - apps.Add (app); |
1678 | - break; |
1679 | - } |
1680 | - } |
1681 | - } |
1682 | - } |
1683 | - return apps; |
1684 | - } |
1685 | - |
1686 | static void UpdateExecList () |
1687 | { |
1688 | if ((DateTime.UtcNow - last_update).TotalMilliseconds < 200) return; |
1689 | |
1690 | - exec_lines.Clear (); |
1691 | + Dictionary<int, string> old = exec_lines; |
1692 | + |
1693 | + exec_lines = new Dictionary<int, string> (); |
1694 | |
1695 | foreach (string dir in Directory.GetDirectories ("/proc")) { |
1696 | int pid; |
1697 | try { pid = Convert.ToInt32 (Path.GetFileName (dir)); } |
1698 | catch { continue; } |
1699 | |
1700 | + if (old.ContainsKey (pid)) { |
1701 | + exec_lines [pid] = old [pid]; |
1702 | + continue; |
1703 | + } |
1704 | + |
1705 | string exec_line = CmdLineForPid (pid); |
1706 | if (string.IsNullOrEmpty (exec_line)) |
1707 | continue; |
1708 | |
1709 | if (exec_line.Contains ("java") && exec_line.Contains ("jar")) { |
1710 | - foreach (Application app in GetApplications ()) { |
1711 | - if (app == null) |
1712 | + foreach (Window window in GetWindows ()) { |
1713 | + if (window == null) |
1714 | continue; |
1715 | |
1716 | - if (app.Pid == pid || app.Windows.Any (w => w.Pid == pid)) { |
1717 | - foreach (Wnck.Window window in app.Windows.Where (win => !win.IsSkipTasklist)) { |
1718 | - exec_line = window.ClassGroup.ResClass; |
1719 | + if (window.Pid == pid || window.Application.Pid == pid) { |
1720 | + exec_line = window.ClassGroup.ResClass; |
1721 | |
1722 | - // Vuze is retarded |
1723 | - if (exec_line == "SWT") |
1724 | - exec_line = window.Name; |
1725 | - Console.WriteLine (exec_line); |
1726 | - break; |
1727 | - } |
1728 | + // Vuze is retarded |
1729 | + if (exec_line == "SWT") |
1730 | + exec_line = window.Name; |
1731 | } |
1732 | } |
1733 | } |
1734 | @@ -273,16 +200,126 @@ |
1735 | |
1736 | last_update = DateTime.UtcNow; |
1737 | } |
1738 | - |
1739 | + |
1740 | + static ClickAction GetClickAction (IEnumerable<Window> windows) |
1741 | + { |
1742 | + if (!windows.Any ()) |
1743 | + return ClickAction.None; |
1744 | + |
1745 | + if (windows.Any (w => w.IsMinimized && w.IsInViewport (Wnck.Screen.Default.ActiveWorkspace))) |
1746 | + return ClickAction.Restore; |
1747 | + |
1748 | + if (windows.Any (w => w.IsActive && w.IsInViewport (Wnck.Screen.Default.ActiveWorkspace))) |
1749 | + return ClickAction.Minimize; |
1750 | + |
1751 | + return ClickAction.Focus; |
1752 | + } |
1753 | + #endregion |
1754 | + |
1755 | + #region Public Methods |
1756 | + /// <summary> |
1757 | + /// Returns a list of all windows on the default screen |
1758 | + /// </summary> |
1759 | + /// <returns> |
1760 | + /// A <see cref="List"/> |
1761 | + /// </returns> |
1762 | + public static List<Window> GetWindows () |
1763 | + { |
1764 | + if (window_list == null || window_list_update_needed) |
1765 | + window_list = new List<Window> (Wnck.Screen.Default.WindowsStacked); |
1766 | + |
1767 | + return window_list; |
1768 | + } |
1769 | + |
1770 | + /// <summary> |
1771 | + /// Gets the command line excec string for a PID |
1772 | + /// </summary> |
1773 | + /// <param name="pid"> |
1774 | + /// A <see cref="System.Int32"/> |
1775 | + /// </param> |
1776 | + /// <returns> |
1777 | + /// A <see cref="System.String"/> |
1778 | + /// </returns> |
1779 | + public static string CmdLineForPid (int pid) |
1780 | + { |
1781 | + string cmdline = null; |
1782 | + |
1783 | + try { |
1784 | + string procPath = new [] { "/proc", pid.ToString (), "cmdline" }.Aggregate (Path.Combine); |
1785 | + using (StreamReader reader = new StreamReader (procPath)) { |
1786 | + cmdline = reader.ReadLine (); |
1787 | + reader.Close (); |
1788 | + } |
1789 | + } catch { } |
1790 | + |
1791 | + return cmdline; |
1792 | + } |
1793 | + |
1794 | + public static List<Window> WindowListForCmd (string exec) |
1795 | + { |
1796 | + List<Window> windows = new List<Window> (); |
1797 | + if (string.IsNullOrEmpty (exec)) |
1798 | + return windows; |
1799 | + |
1800 | + exec = ProcessExecString (exec); |
1801 | + if (string.IsNullOrEmpty (exec)) |
1802 | + return windows; |
1803 | + |
1804 | + UpdateExecList (); |
1805 | + |
1806 | + foreach (KeyValuePair<int, string> kvp in exec_lines) { |
1807 | + if (!string.IsNullOrEmpty (kvp.Value) && kvp.Value.Contains (exec)) { |
1808 | + // we have a matching exec, now we just find every window whose PID matches this exec |
1809 | + foreach (Window window in GetWindows ()) { |
1810 | + if (window == null) |
1811 | + continue; |
1812 | + |
1813 | + // this window matches the right PID and exec string, we can match it. |
1814 | + bool pidMatch = window.Pid == kvp.Key || |
1815 | + (window.Application != null && window.Application.Pid == kvp.Key); |
1816 | + |
1817 | + if (pidMatch && !windows.Contains (window)) |
1818 | + windows.Add (window); |
1819 | + } |
1820 | + } |
1821 | + } |
1822 | + |
1823 | + return windows; |
1824 | + } |
1825 | + |
1826 | + /// <summary> |
1827 | + /// This method takes in an "execution string" from proc and applies a heureustic to try |
1828 | + /// to magic out the name of the actual executing application. The executing binary is not |
1829 | + /// the desired target all the time. |
1830 | + /// </summary> |
1831 | + /// <param name="exec"> |
1832 | + /// A <see cref="System.String"/> |
1833 | + /// </param> |
1834 | + /// <returns> |
1835 | + /// A <see cref="System.String"/> |
1836 | + /// </returns> |
1837 | public static string ProcessExecString (string exec) |
1838 | { |
1839 | + if (string.IsNullOrEmpty (exec)) |
1840 | + return exec; |
1841 | + |
1842 | + // lower it and trim off white space so we can abuse whitespace a bit |
1843 | exec = exec.ToLower ().Trim (); |
1844 | |
1845 | + // if the user has specified a specific mapping, we can use that here |
1846 | if (RemapDictionary.ContainsKey (exec)) |
1847 | return RemapDictionary [exec]; |
1848 | |
1849 | + // this is the "split" character or the argument separator. If the string contains a null |
1850 | + // it was fetched from /proc/PID/cmdline and will be nicely split up. Otherwise things get a bit |
1851 | + // nasty, and it likely came from a .desktop file. |
1852 | + char splitChar = Convert.ToChar (0x0); |
1853 | + splitChar = exec.Contains (splitChar) ? splitChar : ' '; |
1854 | + |
1855 | + // this part is here soley for the remap file so that users may specify to remap based on just the name |
1856 | + // without the full path. If no remap file match is found, the net effect of this is nothing. |
1857 | if (exec.StartsWith ("/")) { |
1858 | - string first_part = exec.Split (' ') [0]; |
1859 | + string first_part = exec.Split (splitChar) [0]; |
1860 | int length = first_part.Length; |
1861 | first_part = first_part.Split ('/').Last (); |
1862 | |
1863 | @@ -294,25 +331,38 @@ |
1864 | } |
1865 | } |
1866 | |
1867 | - string [] parts = exec.Split (' '); |
1868 | + string [] parts = exec.Split (splitChar); |
1869 | for (int i = 0; i < parts.Length; i++) { |
1870 | - if (parts [i].StartsWith ("-")) |
1871 | + // we're going to use this a lot |
1872 | + string out_val = parts [i]; |
1873 | + |
1874 | + // arguments are useless |
1875 | + if (out_val.StartsWith ("-")) |
1876 | continue; |
1877 | |
1878 | - if (parts [i].Contains ("/")) |
1879 | - parts [i] = parts [i].Split ('/').Last (); |
1880 | - |
1881 | - Regex regex; |
1882 | - foreach (string prefix in BadPrefixes) { |
1883 | - regex = new Regex (string.Format ("^{0}$", prefix), RegexOptions.IgnoreCase); |
1884 | - if (regex.IsMatch (parts [i])) { |
1885 | - parts [i] = null; |
1886 | + // we want the end of paths |
1887 | + if (out_val.Contains ("/")) |
1888 | + out_val = out_val.Split ('/').Last (); |
1889 | + |
1890 | + // wine apps can do it backwards... who knew? |
1891 | + if (out_val.Contains ("\\")) |
1892 | + out_val = out_val.Split ('\\').Last (); |
1893 | + |
1894 | + // null out our part if is a bad prefix |
1895 | + foreach (Regex regex in BadPrefixes) { |
1896 | + if (regex.IsMatch (out_val)) { |
1897 | + out_val = null; |
1898 | break; |
1899 | } |
1900 | } |
1901 | |
1902 | - if (!string.IsNullOrEmpty (parts [i])) { |
1903 | - string out_val = parts [i]; |
1904 | + // check if it was a bad prefix... |
1905 | + if (!string.IsNullOrEmpty (out_val)) { |
1906 | + // sometimes we hide things with shell scripts. This is the most common method of doing it. |
1907 | + if (out_val.EndsWith (".real")) |
1908 | + out_val = out_val.Substring (0, out_val.Length - ".real".Length); |
1909 | + |
1910 | + // give the remap dictionary one last shot at this |
1911 | if (RemapDictionary.ContainsKey (out_val)) |
1912 | out_val = RemapDictionary [out_val]; |
1913 | return out_val; |
1914 | @@ -327,12 +377,10 @@ |
1915 | /// <param name="apps"> |
1916 | /// A <see cref="IEnumerable"/> |
1917 | /// </param> |
1918 | - public static void PerformLogicalClick (IEnumerable<Application> apps) |
1919 | + public static void PerformLogicalClick (IEnumerable<Window> windows) |
1920 | { |
1921 | List<Window> stack = new List<Window> (Wnck.Screen.Default.WindowsStacked); |
1922 | - IEnumerable<Window> windows = apps |
1923 | - .SelectMany (app => app.Windows) |
1924 | - .OrderByDescending (w => stack.IndexOf (w)); |
1925 | + windows = windows.OrderByDescending (w => stack.IndexOf (w)); |
1926 | |
1927 | bool not_in_viewport = !windows.Any (w => !w.IsSkipTasklist && w.IsInViewport (w.Screen.ActiveWorkspace)); |
1928 | bool urgent = windows.Any (w => w.NeedsAttention ()); |
1929 | @@ -348,7 +396,7 @@ |
1930 | } |
1931 | } |
1932 | |
1933 | - switch (GetClickAction (apps)) { |
1934 | + switch (GetClickAction (windows)) { |
1935 | case ClickAction.Focus: |
1936 | WindowControl.FocusWindows (windows); |
1937 | break; |
1938 | @@ -361,26 +409,6 @@ |
1939 | } |
1940 | } |
1941 | |
1942 | - static ClickAction GetClickAction (IEnumerable<Application> apps) |
1943 | - { |
1944 | - if (!apps.Any ()) |
1945 | - return ClickAction.None; |
1946 | - |
1947 | - foreach (Wnck.Application app in apps) { |
1948 | - foreach (Wnck.Window window in app.Windows) { |
1949 | - if (window.IsMinimized && window.IsInViewport (Wnck.Screen.Default.ActiveWorkspace)) |
1950 | - return ClickAction.Restore; |
1951 | - } |
1952 | - } |
1953 | - |
1954 | - foreach (Wnck.Application app in apps) { |
1955 | - foreach (Wnck.Window window in app.Windows) { |
1956 | - if (window.IsActive && window.IsInViewport (Wnck.Screen.Default.ActiveWorkspace)) |
1957 | - return ClickAction.Minimize; |
1958 | - } |
1959 | - } |
1960 | - |
1961 | - return ClickAction.Focus; |
1962 | - } |
1963 | + #endregion |
1964 | } |
1965 | } |
1966 | |
1967 | === added directory 'Do.Interface.Wink/src/Do.Interface.Xlib' |
1968 | === renamed file 'Do.Interface.Linux.Docky/src/XLib/X11Atoms.cs' => 'Do.Interface.Wink/src/Do.Interface.Xlib/X11Atoms.cs' |
1969 | --- Do.Interface.Linux.Docky/src/XLib/X11Atoms.cs 2009-02-23 04:01:36 +0000 |
1970 | +++ Do.Interface.Wink/src/Do.Interface.Xlib/X11Atoms.cs 2009-03-31 16:23:23 +0000 |
1971 | @@ -23,9 +23,18 @@ |
1972 | |
1973 | using System; |
1974 | |
1975 | -namespace Docky.XLib { |
1976 | +namespace Do.Interface.Xlib { |
1977 | |
1978 | - internal class X11Atoms { |
1979 | + public class X11Atoms { |
1980 | + |
1981 | + static X11Atoms instance; |
1982 | + public static X11Atoms Instance { |
1983 | + get { |
1984 | + if (instance == null) |
1985 | + instance = new X11Atoms (Gdk.Screen.Default.Display); |
1986 | + return instance; |
1987 | + } |
1988 | + } |
1989 | |
1990 | // Our atoms |
1991 | public readonly IntPtr AnyPropertyType = (IntPtr)0; |
1992 | @@ -169,8 +178,8 @@ |
1993 | public readonly IntPtr AsyncAtom; |
1994 | |
1995 | |
1996 | - public X11Atoms (Gdk.Window window) { |
1997 | - IntPtr display = XLib.Xlib.GdkDrawableXDisplay (window); |
1998 | + X11Atoms (Gdk.Display dsp) { |
1999 | + IntPtr display = Xlib.GdkDisplayXDisplay (dsp); |
2000 | // make sure this array stays in sync with the statements below |
2001 | string [] atom_names = new string[] { |
2002 | "WM_PROTOCOLS", |
2003 | |
2004 | === renamed file 'Do.Interface.Linux.Docky/src/XLib/Xlib.cs' => 'Do.Interface.Wink/src/Do.Interface.Xlib/Xlib.cs' |
2005 | --- Do.Interface.Linux.Docky/src/XLib/Xlib.cs 2009-01-12 20:15:41 +0000 |
2006 | +++ Do.Interface.Wink/src/Do.Interface.Xlib/Xlib.cs 2009-03-31 16:23:23 +0000 |
2007 | @@ -27,7 +27,7 @@ |
2008 | using System.Collections.Generic; |
2009 | using System.Linq; |
2010 | |
2011 | -namespace Docky.XLib { |
2012 | +namespace Do.Interface.Xlib { |
2013 | |
2014 | public enum PropertyMode |
2015 | { |
2016 | @@ -52,7 +52,7 @@ |
2017 | BottomEnd = 11 |
2018 | } |
2019 | |
2020 | - internal class Xlib { |
2021 | + public static class Xlib { |
2022 | const string libX11 = "X11"; |
2023 | const string libGdkX11 = "libgdk-x11"; |
2024 | |
2025 | @@ -61,7 +61,24 @@ |
2026 | |
2027 | [DllImport (libGdkX11)] |
2028 | static extern IntPtr gdk_x11_drawable_get_xdisplay (IntPtr handle); |
2029 | + |
2030 | + [DllImport (libGdkX11)] |
2031 | + static extern IntPtr gdk_x11_display_get_xdisplay (IntPtr display); |
2032 | |
2033 | + [DllImport (libX11)] |
2034 | + public extern static IntPtr XOpenDisplay (IntPtr display); |
2035 | + |
2036 | + [DllImport (libX11)] |
2037 | + public extern static int XInternAtoms (IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms); |
2038 | + |
2039 | + [DllImport (libX11)] |
2040 | + extern static int XChangeProperty (IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, int mode, IntPtr[] data, int nelements); |
2041 | + |
2042 | + [DllImport (libX11)] |
2043 | + public extern static int XGetWindowProperty (IntPtr display, IntPtr window, IntPtr atom, IntPtr long_offset, |
2044 | + IntPtr long_length, bool delete, IntPtr req_type, out IntPtr actual_type, |
2045 | + out int actual_format, out IntPtr nitems, out IntPtr bytes_after, out IntPtr prop); |
2046 | + |
2047 | public static IntPtr GdkWindowX11Xid (Gdk.Window window) |
2048 | { |
2049 | return gdk_x11_drawable_get_xid (window.Handle); |
2050 | @@ -72,19 +89,16 @@ |
2051 | return gdk_x11_drawable_get_xdisplay (window.Handle); |
2052 | } |
2053 | |
2054 | - [DllImport (libX11)] |
2055 | - public extern static IntPtr XOpenDisplay (IntPtr display); |
2056 | - |
2057 | - [DllImport (libX11)] |
2058 | - public extern static int XInternAtoms (IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms); |
2059 | - |
2060 | - [DllImport (libX11)] |
2061 | - extern static int XChangeProperty (IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, int mode, IntPtr[] data, int nelements); |
2062 | - |
2063 | + public static IntPtr GdkDisplayXDisplay (Gdk.Display display) |
2064 | + { |
2065 | + return gdk_x11_display_get_xdisplay (display.Handle); |
2066 | + } |
2067 | + |
2068 | public static int XChangeProperty (Gdk.Window window, IntPtr property, IntPtr type, int mode, uint[] data) |
2069 | { |
2070 | IntPtr [] dataArray = data.Select (i => (IntPtr) i).ToArray (); |
2071 | return XChangeProperty (GdkDrawableXDisplay (window), GdkWindowX11Xid (window), property, type, 32, mode, dataArray, data.Length); |
2072 | } |
2073 | + |
2074 | } |
2075 | } |
2076 | |
2077 | === modified file 'Do.Platform.Linux/src/Do.Platform/Do.Platform.Linux/UniverseFactoryService.cs' |
2078 | --- Do.Platform.Linux/src/Do.Platform/Do.Platform.Linux/UniverseFactoryService.cs 2009-01-21 23:44:40 +0000 |
2079 | +++ Do.Platform.Linux/src/Do.Platform/Do.Platform.Linux/UniverseFactoryService.cs 2009-03-24 15:04:23 +0000 |
2080 | @@ -18,6 +18,8 @@ |
2081 | // |
2082 | |
2083 | using System; |
2084 | +using System.Collections.Generic; |
2085 | +using System.Linq; |
2086 | |
2087 | using Do.Universe; |
2088 | using Do.Universe.Linux; |
2089 | @@ -28,7 +30,6 @@ |
2090 | |
2091 | public class UniverseFactoryService : IUniverseFactoryService |
2092 | { |
2093 | - |
2094 | public IFileItem NewFileItem (string path) |
2095 | { |
2096 | return new FileItem (path); |
2097 | @@ -41,5 +42,10 @@ |
2098 | IApplicationItem maybe = ApplicationItem.MaybeCreateFromDesktopItem (path); |
2099 | return maybe ?? new NullApplicationItem (path); |
2100 | } |
2101 | + |
2102 | + public IApplicationItem MaybeApplicationItemFromCommand (string cmd) |
2103 | + { |
2104 | + return ApplicationItem.MaybeCreateFromCmd (cmd); |
2105 | + } |
2106 | } |
2107 | } |
2108 | |
2109 | === modified file 'Do.Platform.Linux/src/Do.Universe/ApplicationItem.cs' |
2110 | --- Do.Platform.Linux/src/Do.Universe/ApplicationItem.cs 2009-01-23 23:01:37 +0000 |
2111 | +++ Do.Platform.Linux/src/Do.Universe/ApplicationItem.cs 2009-03-29 17:52:17 +0000 |
2112 | @@ -22,6 +22,7 @@ |
2113 | using System.Linq; |
2114 | using System.Collections.Generic; |
2115 | using System.Runtime.InteropServices; |
2116 | +using System.Text.RegularExpressions; |
2117 | |
2118 | using Gnome; |
2119 | using Mono.Unix; |
2120 | @@ -68,6 +69,34 @@ |
2121 | } |
2122 | return appItem; |
2123 | } |
2124 | + |
2125 | + public static ApplicationItem MaybeCreateFromCmd (string cmd) |
2126 | + { |
2127 | + ApplicationItem appItem = null; |
2128 | + |
2129 | + if (string.IsNullOrEmpty (cmd)) |
2130 | + return appItem; |
2131 | + |
2132 | + cmd = Regex.Escape (cmd); |
2133 | + Regex regex = new Regex (string .Format ("(^| ){0}( |)", cmd)); |
2134 | + foreach (ApplicationItem item in Instances.Values) { |
2135 | + string path = item.Location; |
2136 | + try { |
2137 | + if (path.StartsWith ("file://")) |
2138 | + path = path.Substring ("file://".Length); |
2139 | + |
2140 | + path = Path.GetFileName (path); |
2141 | + } catch { continue; } |
2142 | + |
2143 | + if (regex.IsMatch (path) || regex.IsMatch (item.Exec)) { |
2144 | + appItem = item; |
2145 | + if (item.IsAppropriateForCurrentDesktop && !item.Hidden) |
2146 | + break; |
2147 | + } |
2148 | + } |
2149 | + |
2150 | + return appItem; |
2151 | + } |
2152 | |
2153 | protected DesktopItem item; |
2154 | string name, description, icon, mimetype; |
2155 | @@ -115,6 +144,10 @@ |
2156 | public string Exec { |
2157 | get { return item.GetString ("Exec"); } |
2158 | } |
2159 | + |
2160 | + protected string Location { |
2161 | + get { return item.Location; } |
2162 | + } |
2163 | |
2164 | public bool Hidden { |
2165 | get { return item.GetBoolean ("NoDisplay"); } |
2166 | |
2167 | === modified file 'Do.Platform/src/Do.Platform/Do.Platform.Default/UniverseFactoryService.cs' |
2168 | --- Do.Platform/src/Do.Platform/Do.Platform.Default/UniverseFactoryService.cs 2008-12-12 01:41:51 +0000 |
2169 | +++ Do.Platform/src/Do.Platform/Do.Platform.Default/UniverseFactoryService.cs 2009-03-24 15:04:23 +0000 |
2170 | @@ -41,6 +41,12 @@ |
2171 | Log.Debug ("Default IUniverseFactoryService cannot return a useful IApplicationItem."); |
2172 | return new EmptyApplicationItem (); |
2173 | } |
2174 | + |
2175 | + public IApplicationItem MaybeApplicationItemFromCommand (string cmd) |
2176 | + { |
2177 | + Log.Debug ("Default IUniverseFactoryService cannot return a useful IApplicationItem."); |
2178 | + return null; |
2179 | + } |
2180 | |
2181 | class EmptyFileItem : EmptyItem, IFileItem |
2182 | { |
2183 | |
2184 | === modified file 'Do.Platform/src/Do.Platform/IUniverseFactoryService.cs' |
2185 | --- Do.Platform/src/Do.Platform/IUniverseFactoryService.cs 2008-12-22 00:36:53 +0000 |
2186 | +++ Do.Platform/src/Do.Platform/IUniverseFactoryService.cs 2009-03-24 15:04:23 +0000 |
2187 | @@ -31,5 +31,6 @@ |
2188 | { |
2189 | IFileItem NewFileItem (string path); |
2190 | IApplicationItem NewApplicationItem (string path); |
2191 | + IApplicationItem MaybeApplicationItemFromCommand (string cmd); |
2192 | } |
2193 | } |
2194 | |
2195 | === modified file 'Do.mds' |
2196 | --- Do.mds 2009-03-28 15:34:37 +0000 |
2197 | +++ Do.mds 2009-03-31 17:48:02 +0000 |
2198 | @@ -64,4 +64,4 @@ |
2199 | <Entry filename="Do.Interface.Linux.HUD/Do.Interface.Linux.HUD.mdp" /> |
2200 | <Entry filename="Do.Interface.Wink/Do.Interface.Wink.mdp" /> |
2201 | </Entries> |
2202 | -</Combine> |
2203 | +</Combine> |
2204 | \ No newline at end of file |
2205 | |
2206 | === modified file 'Do/gnome-do.in' |
2207 | --- Do/gnome-do.in 2008-10-27 07:23:04 +0000 |
2208 | +++ Do/gnome-do.in 2009-03-24 15:04:23 +0000 |
2209 | @@ -18,8 +18,8 @@ |
2210 | |
2211 | # If Do is not running, run it. |
2212 | if pgrep -u "`id -un`" '^gnome-do$' >/dev/null; then |
2213 | - mono "$GNOME_DO_EXE" "$@" |
2214 | + mono --debug "$GNOME_DO_EXE" "$@" > ~/do.trace 2>&1 |
2215 | fi |
2216 | while [ "$?" -eq "20" ]; do |
2217 | - mono "$GNOME_DO_EXE" "$@" |
2218 | + mono --debug "$GNOME_DO_EXE" "$@" > ~/do.trace 2>&1 |
2219 | done |
Can you combine HandleWindowClosed and Opened methods? They do exactly the same thing, you should be able to at the very least use EventArgs, but they probably both inherit from a higher level base class. Take a look.
Constify the delay in DelayedUpdate. Magic numbers are evil!
on diff line 182, i really dont like the variable name api, it's confusing since api has a meaning.
There are a bunch of WriteLines, clean them up. If you need them, make them into Log.Debugs
In UnregisterWindo wEvents why do you need a try catch? Whats going to throw an exception adding and removing an event handler?
Diff line 960: Do you need to GetString? This should be done before you get passed the string.
removed the commented out line from ScreenUtils.cs
Again, constify the delay in WindowControl.cs, FocusWindows ()
Looks good otherwise! Fix those things then merge!