~and471/+junk/do-with-docky

« back to all changes in this revision

Viewing changes to Do.Interface.Wink/src/Do.Interface.Wink/Viewport.cs

  • Committer: rugby471 at gmail
  • Date: 2010-10-15 16:08:38 UTC
  • Revision ID: rugby471@gmail.com-20101015160838-z9m3utbf7bxzb5ty
reverted to before docky removal

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//  
 
2
//  Copyright (C) 2009 GNOME Do
 
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.Runtime.InteropServices;
 
21
using System.Linq;
 
22
 
 
23
 
 
24
using Gdk;
 
25
using Wnck;
 
26
 
 
27
using Do.Platform;
 
28
using Do.Interface.Xlib;
 
29
 
 
30
namespace Do.Interface.Wink
 
31
{
 
32
        public class Viewport
 
33
        {
 
34
                static Dictionary<Wnck.Window, WindowState> window_states = new Dictionary<Wnck.Window, WindowState> ();
 
35
                
 
36
                private class WindowState {
 
37
                        public Gdk.Rectangle Area;
 
38
                        public Wnck.WindowState State;
 
39
                        
 
40
                        public WindowState (Gdk.Rectangle area, Wnck.WindowState state)
 
41
                        {
 
42
                                Area = area;
 
43
                                State = state;
 
44
                        }
 
45
                }
 
46
                
 
47
                Workspace parent;
 
48
                Rectangle area;
 
49
                
 
50
                public string Name { get; private set; }
 
51
                
 
52
                public Rectangle Area {
 
53
                        get { return area; }
 
54
                }
 
55
                
 
56
                public bool IsActive {
 
57
                        get {
 
58
                                if (!parent.IsVirtual)
 
59
                                        return Wnck.Screen.Default.ActiveWorkspace == parent;
 
60
                                else
 
61
                                        return Wnck.Screen.Default.ActiveWorkspace.ViewportX == area.X && Wnck.Screen.Default.ActiveWorkspace.ViewportY == area.Y;
 
62
                        }
 
63
                }
 
64
                
 
65
                WindowMoveResizeMask MoveMask {
 
66
                        get {
 
67
                                return WindowMoveResizeMask.X | WindowMoveResizeMask.Y;
 
68
                        }
 
69
                }
 
70
                
 
71
                WindowMoveResizeMask ResizeMask {
 
72
                        get {
 
73
                                return WindowMoveResizeMask.Width | WindowMoveResizeMask.Height;
 
74
                        }
 
75
                }
 
76
                
 
77
                WindowMoveResizeMask MoveResizeMask {
 
78
                        get {
 
79
                                return WindowMoveResizeMask.X |
 
80
                                           WindowMoveResizeMask.Y |
 
81
                                           WindowMoveResizeMask.Height |
 
82
                                           WindowMoveResizeMask.Width;
 
83
                        }
 
84
                }
 
85
                
 
86
                internal Viewport(string name, Rectangle area, Workspace parent)
 
87
                {
 
88
                        this.area = area;
 
89
                        this.parent = parent;
 
90
                        Name = name;
 
91
                }
 
92
                
 
93
                public void Present ()
 
94
                {
 
95
                        parent.Screen.MoveViewport (area.X, area.Y);
 
96
                }
 
97
                
 
98
                public bool Contains (Gdk.Point point)
 
99
                {
 
100
                        return area.Contains (point);
 
101
                }
 
102
                
 
103
                private IEnumerable<Wnck.Window> RawWindows ()
 
104
                {
 
105
                        foreach (Wnck.Window window in WindowUtils.GetWindows ()) {
 
106
                                if (WindowCenterInViewport (window) || window.IsSticky)
 
107
                                        yield return window;
 
108
                        }
 
109
                }
 
110
                
 
111
                public IEnumerable<Wnck.Window> Windows ()
 
112
                {
 
113
                        return RawWindows ().Where (w => !w.IsSkipTasklist && w.WindowType != Wnck.WindowType.Dock);
 
114
                }
 
115
                
 
116
                public IEnumerable<Wnck.Window> UnprocessedWindows ()
 
117
                {
 
118
                        return RawWindows ().Where (w => w.WindowType != Wnck.WindowType.Dock);
 
119
                }
 
120
                
 
121
                public void MoveWindowInto (Wnck.Window window)
 
122
                {
 
123
                        if (parent.IsVirtual) {
 
124
                                Rectangle geo = window.EasyGeometry ();
 
125
                                
 
126
                                geo.X += window.Workspace.ViewportX;
 
127
                                geo.Y += window.Workspace.ViewportY;
 
128
                                
 
129
                                int x = area.X + (geo.X % area.Width);
 
130
                                int y = area.Y + (geo.Y % area.Height);
 
131
                                
 
132
                                x -= window.Workspace.ViewportX;
 
133
                                y -= window.Workspace.ViewportY;
 
134
                                
 
135
                                window.SetWorkaroundGeometry (WindowGravity.Current, MoveMask, x, y, 0, 0);
 
136
                        } else {
 
137
                                window.MoveToWorkspace (parent);
 
138
                        }
 
139
                }
 
140
                
 
141
                public bool WindowVisibleInVeiwport (Wnck.Window window)
 
142
                {
 
143
                        if (!window.IsOnWorkspace (parent))
 
144
                                return false;
 
145
                        
 
146
                        Rectangle geo = window.EasyGeometry ();
 
147
                        geo.X += parent.ViewportX;
 
148
                        geo.Y += parent.ViewportY;
 
149
                        
 
150
                        return area.IntersectsWith (geo);
 
151
                }
 
152
                
 
153
                public bool WindowCenterInViewport (Wnck.Window window)
 
154
                {
 
155
                        if (!window.IsOnWorkspace (parent))
 
156
                                return false;
 
157
                                
 
158
                        Rectangle geo = window.EasyGeometry ();
 
159
                        geo.X += parent.ViewportX;
 
160
                        geo.Y += parent.ViewportY;
 
161
                        
 
162
                        Point center = new Point (geo.X + geo.Width / 2, geo.Y + geo.Height / 2);
 
163
                        return Contains (center);
 
164
                }
 
165
                
 
166
                public void RestoreLayout ()
 
167
                {
 
168
                        foreach (Wnck.Window window in Windows ())
 
169
                                RestoreTemporaryWindowGeometry (window);
 
170
                }
 
171
                
 
172
                public void Cascade ()
 
173
                {
 
174
                        IEnumerable<Wnck.Window> windows = Windows ().Where (w => !w.IsMinimized);
 
175
                        if (windows.Count () <= 1) return;
 
176
                        
 
177
                        Gdk.Rectangle screenGeo = GetScreenGeoMinusStruts ();
 
178
                        
 
179
                        int titleBarSize = windows.First ().FrameExtents () [(int) Position.Top];
 
180
                        int windowHeight = screenGeo.Height - ((windows.Count () - 1) * titleBarSize);
 
181
                        int windowWidth = screenGeo.Width - ((windows.Count () - 1) * titleBarSize);
 
182
                        
 
183
                        int count = 0;
 
184
                        int x, y;
 
185
                        foreach (Wnck.Window window in windows) {
 
186
                                x = screenGeo.X + titleBarSize * count - parent.ViewportX;
 
187
                                y = screenGeo.Y + titleBarSize * count - parent.ViewportY;
 
188
                                
 
189
                                SetTemporaryWindowGeometry (window, new Gdk.Rectangle (x, y, windowWidth, windowHeight));
 
190
                                count++;
 
191
                        }
 
192
                }
 
193
                
 
194
                public void ShowDesktop ()
 
195
                {
 
196
                        if (!ScreenUtils.DesktopShown (parent.Screen))
 
197
                                ScreenUtils.ShowDesktop (parent.Screen);
 
198
                        else
 
199
                                ScreenUtils.UnshowDesktop (parent.Screen);
 
200
                }
 
201
                
 
202
                public void Tile ()
 
203
                {
 
204
                        IEnumerable<Wnck.Window> windows = Windows ().Where (w => !w.IsMinimized);
 
205
                        if (windows.Count () <= 1) return;
 
206
                        
 
207
                        Gdk.Rectangle screenGeo = GetScreenGeoMinusStruts ();
 
208
                        
 
209
                        int width, height;
 
210
                        //We are going to tile to a square, so what we want is to find
 
211
                        //the smallest perfect square all our windows will fit into
 
212
                        width = (int) Math.Ceiling (Math.Sqrt (windows.Count ()));
 
213
                        
 
214
                        //Our height is at least one (e.g. a 2x1)
 
215
                        height = 1;
 
216
                        while (width * height < windows.Count ())
 
217
                                height++;
 
218
                        
 
219
                        int windowWidth, windowHeight;
 
220
                        windowWidth = screenGeo.Width / width;
 
221
                        windowHeight = screenGeo.Height / height;
 
222
                        
 
223
                        int row = 0, column = 0;
 
224
                        int x, y;
 
225
                        
 
226
                        foreach (Wnck.Window window in windows) {
 
227
                                x = screenGeo.X + (column * windowWidth) - parent.ViewportX;
 
228
                                y = screenGeo.Y + (row * windowHeight) - parent.ViewportY;
 
229
                                
 
230
                                Gdk.Rectangle windowArea = new Gdk.Rectangle (x, y, windowWidth, windowHeight);;
 
231
                                
 
232
                                if (window == windows.Last ())
 
233
                                        windowArea.Width *= width - column;
 
234
                                
 
235
                                SetTemporaryWindowGeometry (window, windowArea);
 
236
                                
 
237
                                column++;
 
238
                                if (column == width) {
 
239
                                        column = 0;
 
240
                                        row++;
 
241
                                }
 
242
                        }
 
243
                }
 
244
                
 
245
                Gdk.Rectangle GetScreenGeoMinusStruts ()
 
246
                {
 
247
                        IEnumerable<int []> struts = RawWindows ()
 
248
                                .Where (w => w.WindowType == Wnck.WindowType.Dock)
 
249
                                .Select (w => w.GetCardinalProperty (X11Atoms.Instance._NET_WM_STRUT_PARTIAL));
 
250
                        
 
251
                        int [] offsets = new int [4];
 
252
                        for (int i = 0; i < 4; i++)
 
253
                                offsets [i] = struts.Max (a => a[i]);
 
254
                        
 
255
                        Gdk.Rectangle screenGeo = Area;
 
256
                        screenGeo.Width -= offsets [(int) Position.Left] + offsets [(int) Position.Right];
 
257
                        screenGeo.Height -= offsets [(int) Position.Top] + offsets [(int) Position.Bottom];
 
258
                        screenGeo.X += offsets [(int) Position.Left];
 
259
                        screenGeo.Y += offsets [(int) Position.Top];
 
260
                        
 
261
                        return screenGeo;
 
262
                }
 
263
                
 
264
                void SetTemporaryWindowGeometry (Wnck.Window window, Gdk.Rectangle area)
 
265
                {
 
266
                        Gdk.Rectangle oldGeo = window.EasyGeometry ();
 
267
                        
 
268
                        oldGeo.X += parent.ViewportX;
 
269
                        oldGeo.Y += parent.ViewportY;
 
270
                        
 
271
                        if (!window_states.ContainsKey (window)) 
 
272
                                window_states [window] = new WindowState (oldGeo, window.State);
 
273
                        
 
274
                        if (window.IsMaximized)
 
275
                                window.Unmaximize ();
 
276
                        
 
277
                        window.SetWorkaroundGeometry (WindowGravity.Current, MoveResizeMask, area.X, area.Y, area.Width, area.Height);
 
278
                }
 
279
                
 
280
                void RestoreTemporaryWindowGeometry (Wnck.Window window)
 
281
                {
 
282
                        if (!window_states.ContainsKey (window))
 
283
                                return;
 
284
                                
 
285
                        WindowState state = window_states [window];
 
286
                        window.SetWorkaroundGeometry (WindowGravity.Current, MoveResizeMask, state.Area.X - parent.ViewportX, 
 
287
                                                      state.Area.Y - parent.ViewportY, state.Area.Width, state.Area.Height);
 
288
                        
 
289
                        window_states.Remove (window);
 
290
                }
 
291
        }
 
292
}