~ubuntu-branches/ubuntu/wily/docky/wily-proposed

« back to all changes in this revision

Viewing changes to Docky/Docky/Interface/AutohideManager.cs

  • Committer: Bazaar Package Importer
  • Author(s): Christopher James Halse Rogers
  • Date: 2010-02-17 15:10:07 UTC
  • Revision ID: james.westby@ubuntu.com-20100217151007-msxpd0lsj300ndde
Tags: upstream-2.0.0
ImportĀ upstreamĀ versionĀ 2.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//  
 
2
//  Copyright (C) 2009 Jason Smith
 
3
// 
 
4
//  This program is free software: you can redistribute it and/or modify
 
5
//  it under the terms of the GNU General Public License as published by
 
6
//  the Free Software Foundation, either version 3 of the License, or
 
7
//  (at your option) any later version.
 
8
// 
 
9
//  This program is distributed in the hope that it will be useful,
 
10
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
//  GNU General Public License for more details.
 
13
// 
 
14
//  You should have received a copy of the GNU General Public License
 
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
// 
 
17
 
 
18
using System;
 
19
using System.Collections.Generic;
 
20
using System.ComponentModel;
 
21
using System.Linq;
 
22
using System.Text;
 
23
 
 
24
using Cairo;
 
25
using Gdk;
 
26
using Gtk;
 
27
using Wnck;
 
28
 
 
29
using Docky.Services;
 
30
 
 
31
namespace Docky.Interface
 
32
{
 
33
 
 
34
 
 
35
        public class AutohideManager : IDisposable
 
36
        {
 
37
                public event EventHandler HiddenChanged;
 
38
                public event EventHandler DockHoveredChanged;
 
39
                
 
40
                Gdk.Rectangle cursor_area, intersect_area, last_known_geo;
 
41
                Wnck.Screen screen;
 
42
                CursorTracker tracker;
 
43
                int pid;
 
44
                uint timer;
 
45
                
 
46
                bool WindowIntersectingOther { get; set; }
 
47
                
 
48
                bool dockHoverd;
 
49
                public bool DockHovered {
 
50
                        get { return dockHoverd; }
 
51
                        private set {
 
52
                                if (dockHoverd == value)
 
53
                                        return;
 
54
                                
 
55
                                dockHoverd = value;
 
56
                                OnDockHoveredChanged ();
 
57
                        }
 
58
                }
 
59
                
 
60
                bool hidden;
 
61
                public bool Hidden {
 
62
                        get { return hidden; } 
 
63
                        private set { 
 
64
                                if (hidden == value)
 
65
                                        return;
 
66
                                
 
67
                                hidden = value; 
 
68
                                OnHiddenChanged ();
 
69
                        } 
 
70
                }
 
71
                
 
72
                AutohideType behavior;
 
73
                public AutohideType Behavior { 
 
74
                        get { return behavior; } 
 
75
                        set { 
 
76
                                if (behavior == value)
 
77
                                        return;
 
78
                                
 
79
                                behavior = value; 
 
80
                                if (behavior == AutohideType.None) {
 
81
                                        Hidden = false;
 
82
                                }
 
83
                        } 
 
84
                }
 
85
                
 
86
                internal AutohideManager (Gdk.Screen screen)
 
87
                {
 
88
                        pid = System.Diagnostics.Process.GetCurrentProcess ().Id;
 
89
                        
 
90
                        tracker = CursorTracker.ForDisplay (screen.Display);
 
91
                        this.screen = Wnck.Screen.Get (screen.Number);
 
92
                        
 
93
                        tracker.CursorPositionChanged   += HandleCursorPositionChanged;
 
94
                        this.screen.ActiveWindowChanged += HandleActiveWindowChanged;
 
95
                        this.screen.WindowOpened        += HandleWindowOpened;
 
96
                        this.screen.WindowClosed        += HandleWindowClosed;
 
97
                }
 
98
                
 
99
                public void SetCursorArea (Gdk.Rectangle area)
 
100
                {
 
101
                        if (cursor_area == area)
 
102
                                return;
 
103
                        cursor_area = area;
 
104
                        DockHovered = cursor_area.Contains (tracker.Cursor) 
 
105
                                && (screen.ActiveWindow == null || (screen.ActiveWindow != null && !screen.ActiveWindow.IsFullscreen));
 
106
                        SetHidden ();
 
107
                        
 
108
                }
 
109
                
 
110
                public void SetIntersectArea (Gdk.Rectangle area)
 
111
                {
 
112
                        if (intersect_area == area)
 
113
                                return;
 
114
                        
 
115
                        intersect_area = area;
 
116
                        UpdateWindowIntersect ();
 
117
                }
 
118
                
 
119
                void HandleCursorPositionChanged (object sender, CursorPostionChangedArgs args)
 
120
                {
 
121
                        DockHovered = cursor_area.Contains (tracker.Cursor)
 
122
                                && (screen.ActiveWindow == null || (screen.ActiveWindow != null && !screen.ActiveWindow.IsFullscreen));
 
123
                        SetHidden ();
 
124
                }
 
125
 
 
126
                void HandleActiveWindowChanged (object o, ActiveWindowChangedArgs args)
 
127
                {
 
128
                        if (args.PreviousWindow != null)
 
129
                                args.PreviousWindow.GeometryChanged -= HandleGeometryChanged;
 
130
                        
 
131
                        if (timer > 0)
 
132
                                GLib.Source.Remove (timer);
 
133
                        
 
134
                        timer = GLib.Timeout.Add (200, delegate {
 
135
                                SetupActiveWindow ();
 
136
                                UpdateWindowIntersect ();
 
137
                                timer = 0;
 
138
                                return false;
 
139
                        });
 
140
                }
 
141
                
 
142
                void HandleWindowOpened (object sender, WindowOpenedArgs args)
 
143
                {
 
144
                        UpdateWindowIntersect ();
 
145
                }
 
146
                
 
147
                void HandleWindowClosed (object sender, WindowClosedArgs args)
 
148
                {
 
149
                        UpdateWindowIntersect ();
 
150
                }
 
151
                
 
152
                void SetupActiveWindow ()
 
153
                {
 
154
                        Wnck.Window active = screen.ActiveWindow;
 
155
                        if (active != null) {
 
156
                                active.GeometryChanged += HandleGeometryChanged; 
 
157
                                last_known_geo = active.EasyGeometry ();
 
158
                        }
 
159
                }
 
160
                
 
161
                void HandleGeometryChanged (object sender, EventArgs e)
 
162
                {
 
163
                        Wnck.Window window = sender as Wnck.Window;
 
164
                        
 
165
                        if (sender == null)
 
166
                                return;
 
167
                        
 
168
                        Gdk.Rectangle geo = window.EasyGeometry ();
 
169
                        
 
170
                        if (geo == last_known_geo)
 
171
                                return;
 
172
                        
 
173
                        last_known_geo = geo;
 
174
                        
 
175
                        if (timer > 0)
 
176
                                GLib.Source.Remove (timer);
 
177
                        
 
178
                        timer = GLib.Timeout.Add (200, delegate {
 
179
                                UpdateWindowIntersect ();
 
180
                                timer = 0;
 
181
                                return false;
 
182
                        });
 
183
                }
 
184
                
 
185
                bool IsIntersectableWindow (Wnck.Window window)
 
186
                {
 
187
                        return window != null &&
 
188
                                !window.IsMinimized &&
 
189
                                window.Pid != pid &&
 
190
                                window.WindowType != Wnck.WindowType.Desktop &&
 
191
                                window.WindowType != Wnck.WindowType.Dock &&
 
192
                                window.WindowType != Wnck.WindowType.Splashscreen &&
 
193
                                window.WindowType != Wnck.WindowType.Menu &&
 
194
                                Wnck.Screen.Default.ActiveWorkspace != null &&
 
195
                                window.IsVisibleOnWorkspace (Wnck.Screen.Default.ActiveWorkspace);
 
196
                }
 
197
                
 
198
                void UpdateWindowIntersect ()
 
199
                {
 
200
                        Gdk.Rectangle adjustedDockArea = intersect_area;
 
201
                        adjustedDockArea.Inflate (-2, -2);
 
202
                        
 
203
                        bool intersect = false;
 
204
                        Wnck.Window activeWindow = screen.ActiveWindow;
 
205
                        
 
206
                        try {
 
207
                                foreach (Wnck.Window window in screen.Windows.Where (w => IsIntersectableWindow (w))) {
 
208
                                        if (Behavior == AutohideType.Intellihide && activeWindow != null && activeWindow.Pid != window.Pid) {
 
209
                                                continue;
 
210
                                        }
 
211
                                        
 
212
                                        if (window.EasyGeometry ().IntersectsWith (adjustedDockArea)) {
 
213
                                                intersect = true;
 
214
                                                break;
 
215
                                        }
 
216
                                }
 
217
                        } catch (Exception e) {
 
218
                                Log<AutohideManager>.Error ("Failed to update window intersect: '{0}'", e.Message);
 
219
                                Log<AutohideManager>.Debug (e.StackTrace);
 
220
                        }
 
221
                        
 
222
                        if (WindowIntersectingOther != intersect) {
 
223
                                WindowIntersectingOther = intersect;
 
224
                                SetHidden ();
 
225
                        }
 
226
                }
 
227
                
 
228
                void SetHidden ()
 
229
                {
 
230
                        switch (Behavior) {
 
231
                        default:
 
232
                        case AutohideType.None:
 
233
                                Hidden = false;
 
234
                                break;
 
235
                        case AutohideType.Autohide:
 
236
                                Hidden = !DockHovered;
 
237
                                break;
 
238
                        case AutohideType.Intellihide:
 
239
                        case AutohideType.UniversalIntellihide:
 
240
                                Hidden = !DockHovered && WindowIntersectingOther;
 
241
                                break;
 
242
                        }
 
243
                }
 
244
                
 
245
                void OnDockHoveredChanged ()
 
246
                {
 
247
                        if (DockHoveredChanged != null)
 
248
                                DockHoveredChanged (this, EventArgs.Empty);
 
249
                }
 
250
                
 
251
                void OnHiddenChanged ()
 
252
                {
 
253
                        if (HiddenChanged != null)
 
254
                                HiddenChanged (this, EventArgs.Empty);
 
255
                }
 
256
 
 
257
                #region IDisposable implementation
 
258
                public void Dispose ()
 
259
                {
 
260
                        if (screen != null) {
 
261
                                screen.ActiveWindowChanged -= HandleActiveWindowChanged;
 
262
                                if (screen.ActiveWindow != null)
 
263
                                        screen.ActiveWindow.GeometryChanged -= HandleGeometryChanged;
 
264
                                screen.WindowOpened -= HandleWindowOpened;
 
265
                                screen.WindowClosed -= HandleWindowClosed;
 
266
                        }
 
267
                        
 
268
                        if (tracker != null)
 
269
                                tracker.CursorPositionChanged -= HandleCursorPositionChanged;
 
270
                }
 
271
                #endregion
 
272
        }
 
273
}