aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/XLayer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk/XLayer.cc')
-rw-r--r--src/FbTk/XLayer.cc366
1 files changed, 366 insertions, 0 deletions
diff --git a/src/FbTk/XLayer.cc b/src/FbTk/XLayer.cc
new file mode 100644
index 0000000..023a80d
--- /dev/null
+++ b/src/FbTk/XLayer.cc
@@ -0,0 +1,366 @@
1// XLayer.cc for FbTk - fluxbox toolkit
2// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
3// and Simon Bowden (rathnor at users.sourceforge.net)
4//
5// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
22
23// $Id: XLayer.cc,v 1.8 2003/04/15 23:20:31 rathnor Exp $
24
25#include "XLayer.hh"
26#include "XLayerItem.hh"
27#include "App.hh"
28
29#include <iostream>
30using namespace std;
31using namespace FbTk;
32
33XLayer::XLayer(MultLayers &manager, int layernum):
34 m_manager(manager), m_layernum(layernum) {
35}
36
37XLayer::~XLayer() {
38
39}
40
41void XLayer::restack() {
42 int num_windows = countWindows();
43
44 // each LayerItem can contain several windows
45 iterator it = itemList().begin();
46 iterator it_end = itemList().end();
47 it = itemList().begin();
48 it_end = itemList().end();
49 Window *winlist = new Window[num_windows];
50 size_t j=0;
51
52 // add all the windows from each item
53 for (size_t i=0; it != it_end; ++it, i++) {
54 XLayerItem::Windows::const_iterator wit = (*it)->getWindows().begin();
55 XLayerItem::Windows::const_iterator wit_end = (*it)->getWindows().end();
56 for (; wit != wit_end; ++wit) {
57 if ((*wit)->window())
58 winlist[j++] = (*wit)->window();
59 }
60 }
61
62 XRestackWindows(FbTk::App::instance()->display(), winlist, j);
63
64 delete [] winlist;
65
66}
67
68int XLayer::countWindows() {
69 int num_windows = 0;
70 iterator it = itemList().begin();
71 iterator it_end = itemList().end();
72 for (size_t i=0; it != it_end; ++it, i++) {
73 num_windows += (*it)->numWindows();
74 }
75 return num_windows;
76}
77
78
79// Stack all windows associated with 'item' below the 'above' item
80void XLayer::stackBelowItem(XLayerItem *item, XLayerItem *above) {
81
82 Window *winlist;
83 size_t winnum, size, num = item->numWindows();
84
85 // if there are no windows provided for above us,
86 // then we must have to go right to the top of the stack
87 if (!above) { // must need to go right to top
88 if (item->getWindows().front()->window())
89 XRaiseWindow(FbTk::App::instance()->display(), item->getWindows().front()->window());
90
91 // if this XLayerItem has more than one window,
92 // then we'll stack the rest in under the front one too
93 // our size needs to be the number of windows in the group, since there isn't one above.
94 if (num > 1) {
95 winnum = 0;
96 // stack relative to top one (just raised)
97 size = num;
98 winlist = new Window[size];
99 } else {
100 // we've raised the window, nothing else to do
101 return;
102 }
103 } else {
104 // We do have a window to stack below
105
106 // so we put it on top, and fill the rest of the array with the ones to go below it.
107 winnum = 1;
108 size = num+1;
109 winlist = new Window[size];
110 // assume that above's window exists
111 winlist[0] = above->getWindows().back()->window();
112 }
113
114 // fill the rest of the array
115 XLayerItem::Windows::iterator it = item->getWindows().begin();
116 XLayerItem::Windows::iterator it_end = item->getWindows().end();
117 for (; it != it_end; ++it) {
118 if ((*it)->window())
119 winlist[winnum++] = (*it)->window();
120 }
121
122 // stack the windows
123 XRestackWindows(FbTk::App::instance()->display(), winlist, winnum);
124
125 delete [] winlist;
126
127}
128
129XLayer::iterator XLayer::insert(XLayerItem &item, unsigned int pos) {
130#ifdef DEBUG
131 // at this point we don't support insertions into a layer other than at the top
132 if (pos != 0)
133 cerr<<__FILE__<<"("<<__LINE__<<"): Insert using non-zero position not valid in XLayer"<<endl;
134#endif // DEBUG
135
136 itemList().push_front(&item);
137 // restack below next window up
138 stackBelowItem(&item, m_manager.getLowestItemAboveLayer(m_layernum));
139 return itemList().begin();
140}
141
142void XLayer::remove(XLayerItem &item) {
143 iterator it = itemList().begin();
144 iterator it_end = itemList().end();
145 for (; it != it_end; ++it) {
146 if (*it == &item) {
147 itemList().erase(it);
148 break;
149 }
150 }
151}
152
153void XLayer::cycleUp() {
154 // need to find highest visible window, and move it to bottom
155 iterator it = itemList().begin();
156 iterator it_end = itemList().end();
157 while (it != it_end && !(*it)->visible())
158 ++it;
159
160 // if there is something to do
161 if (it != it_end)
162 lower(**it);
163
164}
165
166void XLayer::cycleDown() {
167 // need to find lowest visible window, and move it to top
168 // so use a reverse iterator, and the same logic as cycleUp()
169 reverse_iterator it = itemList().rbegin();
170 reverse_iterator it_end = itemList().rend();
171 while (it != it_end && !(*it)->visible())
172 ++it;
173
174 // if there is something to do
175 if (it != it_end)
176 raise(**it);
177
178}
179
180void XLayer::stepUp(XLayerItem &item) {
181 // need to find next visible window upwards, and put it above that
182
183 if (&item == itemList().front())
184 return; // nothing to do
185
186 // TODO: is there a better way of doing this?
187
188 // get our item
189 iterator myit = std::find(itemList().begin(), itemList().end(), &item);
190 iterator it = myit;
191
192 // go to the one above it in our layer (top is front, so we decrement)
193 --it;
194
195 // keep going until we find one that is currently visible to the user
196 while (it != itemList().begin() && !(*it)->visible())
197 --it;
198
199 if (it == itemList().begin() && !(*it)->visible()) {
200 // reached front item, but it wasn't visible, therefore it was already raised
201 } else {
202 // it is the next visible item down, we need to be above it.
203 // remove that item from the list and add it back to before it (the one we want to go above)
204
205 itemList().erase(myit);
206 itemList().insert(it, &item);
207
208 // if we've reached the top of the layer, we need to stack below the next one up
209 if (it == itemList().begin()) {
210 stackBelowItem(&item, m_manager.getLowestItemAboveLayer(m_layernum));
211 } else {
212 // otherwise go up one in this layer (i.e. above the one we want to go above)
213 --it;
214 // and stack below that.
215 stackBelowItem(&item, *it);
216 }
217 }
218}
219
220void XLayer::stepDown(XLayerItem &item) {
221 // need to find next visible window down, and put it below that
222
223 // if we're already the bottom of the layer
224 if (&item == itemList().back())
225 return; // nothing to do
226
227 // get our position
228 iterator myit = std::find(itemList().begin(), itemList().end(), &item);
229 iterator it = myit;
230
231 // go one below it (top is front, so we must increment)
232 it++;
233 iterator it_end = itemList().end();
234
235 // keep going down until we find a visible one
236 while (it != it_end && !(*it)->visible())
237 it++;
238
239 // if we didn't reach the end, then stack below the
240 // item that we found.
241 if (it != it_end)
242 stackBelowItem(&item, *it);
243 // if we did reach the end, then there are no visible windows, so we don't do anything
244}
245
246void XLayer::raise(XLayerItem &item) {
247 // assume it is already in this layer
248
249 if (&item == itemList().front())
250 return; // nothing to do
251
252 iterator it = std::find(itemList().begin(), itemList().end(), &item);
253 if (it != itemList().end())
254 itemList().erase(it);
255 else {
256#ifdef DEBUG
257 cerr<<__FILE__<<"("<<__LINE__<<"): WARNING: raise on item not in layer["<<m_layernum<<"]"<<endl;
258#endif // DEBUG
259 return;
260 }
261
262 itemList().push_front(&item);
263 stackBelowItem(&item, m_manager.getLowestItemAboveLayer(m_layernum));
264
265}
266
267void XLayer::tempRaise(XLayerItem &item) {
268 // assume it is already in this layer
269
270 if (&item == itemList().front())
271 return; // nothing to do
272
273 iterator it = std::find(itemList().begin(), itemList().end(), &item);
274 if (it == itemList().end()) {
275#ifdef DEBUG
276 cerr<<__FILE__<<"("<<__LINE__<<"): WARNING: raise on item not in layer["<<m_layernum<<"]"<<endl;
277#endif // DEBUG
278 return;
279 }
280
281 // don't add it back to the top
282 stackBelowItem(&item, m_manager.getLowestItemAboveLayer(m_layernum));
283
284}
285
286void XLayer::lower(XLayerItem &item) {
287 // assume already in this layer
288
289 // is it already the lowest?
290 if (&item == itemList().back())
291 return; // nothing to do
292
293 iterator it = std::find(itemList().begin(), itemList().end(), &item);
294 if (it != itemList().end())
295 // remove this item
296 itemList().erase(it);
297#ifdef DEBUG
298 else {
299 cerr<<__FILE__<<"("<<__LINE__<<"): WARNING: lower on item not in layer"<<endl;
300 return;
301 }
302#endif // DEBUG
303
304 // add it to the bottom
305 itemList().push_back(&item);
306
307 // find the item we need to stack below
308 // start at the end
309 it = itemList().end();
310
311 // go up one so we have an object (which must exist, since at least this item is in the layer)
312 it--;
313
314 // go down another one
315 // must exist, otherwise our item must == itemList().back()
316 it--;
317
318 // and restack our window below that one.
319 stackBelowItem(&item, *it);
320}
321
322void XLayer::raiseLayer(XLayerItem &item) {
323 m_manager.raiseLayer(item);
324}
325
326void XLayer::lowerLayer(XLayerItem &item) {
327 m_manager.lowerLayer(item);
328}
329
330void XLayer::moveToLayer(XLayerItem &item, int layernum) {
331 m_manager.moveToLayer(item, layernum);
332}
333
334
335XLayerItem *XLayer::getLowestItem() {
336 if (itemList().empty())
337 return 0;
338 else
339 return itemList().back();
340}
341
342XLayerItem *XLayer::getItemBelow(XLayerItem &item) {
343 // get our iterator
344 iterator it = std::find(itemList().begin(), itemList().end(), &item);
345
346 // go one lower
347 it++;
348
349 // if one lower is the end, there is no item below, otherwise we've got it
350 if (it == itemList().end())
351 return 0;
352 else
353 return *it;
354}
355
356XLayerItem *XLayer::getItemAbove(XLayerItem &item) {
357 // get our iterator
358 iterator it = std::find(itemList().begin(), itemList().end(), &item);
359
360 // if this is the beginning (top-most item), do nothing, otherwise give the next one up
361 // the list (which must be there since we aren't the beginning)
362 if (it == itemList().begin())
363 return 0;
364 else
365 return *(--it);
366}