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.cc371
1 files changed, 371 insertions, 0 deletions
diff --git a/src/FbTk/XLayer.cc b/src/FbTk/XLayer.cc
new file mode 100644
index 0000000..8164444
--- /dev/null
+++ b/src/FbTk/XLayer.cc
@@ -0,0 +1,371 @@
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.9 2003/07/20 18:05:40 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 if (!m_manager.isUpdatable())
43 return;
44
45 int num_windows = countWindows();
46
47 // each LayerItem can contain several windows
48 iterator it = itemList().begin();
49 iterator it_end = itemList().end();
50 it = itemList().begin();
51 it_end = itemList().end();
52 Window *winlist = new Window[num_windows];
53 size_t j=0;
54
55 // add all the windows from each item
56 for (size_t i=0; it != it_end; ++it, i++) {
57 XLayerItem::Windows::const_iterator wit = (*it)->getWindows().begin();
58 XLayerItem::Windows::const_iterator wit_end = (*it)->getWindows().end();
59 for (; wit != wit_end; ++wit) {
60 if ((*wit)->window())
61 winlist[j++] = (*wit)->window();
62 }
63 }
64
65 XRestackWindows(FbTk::App::instance()->display(), winlist, j);
66
67 delete [] winlist;
68
69}
70
71int XLayer::countWindows() {
72 int num_windows = 0;
73 iterator it = itemList().begin();
74 iterator it_end = itemList().end();
75 for (size_t i=0; it != it_end; ++it, i++) {
76 num_windows += (*it)->numWindows();
77 }
78 return num_windows;
79}
80
81
82// Stack all windows associated with 'item' below the 'above' item
83void XLayer::stackBelowItem(XLayerItem *item, XLayerItem *above) {
84 if (!m_manager.isUpdatable())
85 return;
86
87 Window *winlist;
88 size_t winnum, size, num = item->numWindows();
89
90 // if there are no windows provided for above us,
91 // then we must have to go right to the top of the stack
92 if (!above) { // must need to go right to top
93 if (item->getWindows().front()->window())
94 XRaiseWindow(FbTk::App::instance()->display(), item->getWindows().front()->window());
95
96 // if this XLayerItem has more than one window,
97 // then we'll stack the rest in under the front one too
98 // our size needs to be the number of windows in the group, since there isn't one above.
99 if (num > 1) {
100 winnum = 0;
101 // stack relative to top one (just raised)
102 size = num;
103 winlist = new Window[size];
104 } else {
105 // we've raised the window, nothing else to do
106 return;
107 }
108 } else {
109 // We do have a window to stack below
110
111 // so we put it on top, and fill the rest of the array with the ones to go below it.
112 winnum = 1;
113 size = num+1;
114 winlist = new Window[size];
115 // assume that above's window exists
116 winlist[0] = above->getWindows().back()->window();
117 }
118
119 // fill the rest of the array
120 XLayerItem::Windows::iterator it = item->getWindows().begin();
121 XLayerItem::Windows::iterator it_end = item->getWindows().end();
122 for (; it != it_end; ++it) {
123 if ((*it)->window())
124 winlist[winnum++] = (*it)->window();
125 }
126
127 // stack the windows
128 XRestackWindows(FbTk::App::instance()->display(), winlist, winnum);
129
130 delete [] winlist;
131
132}
133
134XLayer::iterator XLayer::insert(XLayerItem &item, unsigned int pos) {
135#ifdef DEBUG
136 // at this point we don't support insertions into a layer other than at the top
137 if (pos != 0)
138 cerr<<__FILE__<<"("<<__LINE__<<"): Insert using non-zero position not valid in XLayer"<<endl;
139#endif // DEBUG
140
141 itemList().push_front(&item);
142 // restack below next window up
143 stackBelowItem(&item, m_manager.getLowestItemAboveLayer(m_layernum));
144 return itemList().begin();
145}
146
147void XLayer::remove(XLayerItem &item) {
148 iterator it = itemList().begin();
149 iterator it_end = itemList().end();
150 for (; it != it_end; ++it) {
151 if (*it == &item) {
152 itemList().erase(it);
153 break;
154 }
155 }
156}
157
158void XLayer::cycleUp() {
159 // need to find highest visible window, and move it to bottom
160 iterator it = itemList().begin();
161 iterator it_end = itemList().end();
162 while (it != it_end && !(*it)->visible())
163 ++it;
164
165 // if there is something to do
166 if (it != it_end)
167 lower(**it);
168
169}
170
171void XLayer::cycleDown() {
172 // need to find lowest visible window, and move it to top
173 // so use a reverse iterator, and the same logic as cycleUp()
174 reverse_iterator it = itemList().rbegin();
175 reverse_iterator it_end = itemList().rend();
176 while (it != it_end && !(*it)->visible())
177 ++it;
178
179 // if there is something to do
180 if (it != it_end)
181 raise(**it);
182
183}
184
185void XLayer::stepUp(XLayerItem &item) {
186 // need to find next visible window upwards, and put it above that
187
188 if (&item == itemList().front())
189 return; // nothing to do
190
191 // TODO: is there a better way of doing this?
192
193 // get our item
194 iterator myit = std::find(itemList().begin(), itemList().end(), &item);
195 iterator it = myit;
196
197 // go to the one above it in our layer (top is front, so we decrement)
198 --it;
199
200 // keep going until we find one that is currently visible to the user
201 while (it != itemList().begin() && !(*it)->visible())
202 --it;
203
204 if (it == itemList().begin() && !(*it)->visible()) {
205 // reached front item, but it wasn't visible, therefore it was already raised
206 } else {
207 // it is the next visible item down, we need to be above it.
208 // remove that item from the list and add it back to before it (the one we want to go above)
209
210 itemList().erase(myit);
211 itemList().insert(it, &item);
212
213 // if we've reached the top of the layer, we need to stack below the next one up
214 if (it == itemList().begin()) {
215 stackBelowItem(&item, m_manager.getLowestItemAboveLayer(m_layernum));
216 } else {
217 // otherwise go up one in this layer (i.e. above the one we want to go above)
218 --it;
219 // and stack below that.
220 stackBelowItem(&item, *it);
221 }
222 }
223}
224
225void XLayer::stepDown(XLayerItem &item) {
226 // need to find next visible window down, and put it below that
227
228 // if we're already the bottom of the layer
229 if (&item == itemList().back())
230 return; // nothing to do
231
232 // get our position
233 iterator myit = std::find(itemList().begin(), itemList().end(), &item);
234 iterator it = myit;
235
236 // go one below it (top is front, so we must increment)
237 it++;
238 iterator it_end = itemList().end();
239
240 // keep going down until we find a visible one
241 while (it != it_end && !(*it)->visible())
242 it++;
243
244 // if we didn't reach the end, then stack below the
245 // item that we found.
246 if (it != it_end)
247 stackBelowItem(&item, *it);
248 // if we did reach the end, then there are no visible windows, so we don't do anything
249}
250
251void XLayer::raise(XLayerItem &item) {
252 // assume it is already in this layer
253
254 if (&item == itemList().front())
255 return; // nothing to do
256
257 iterator it = std::find(itemList().begin(), itemList().end(), &item);
258 if (it != itemList().end())
259 itemList().erase(it);
260 else {
261#ifdef DEBUG
262 cerr<<__FILE__<<"("<<__LINE__<<"): WARNING: raise on item not in layer["<<m_layernum<<"]"<<endl;
263#endif // DEBUG
264 return;
265 }
266
267 itemList().push_front(&item);
268 stackBelowItem(&item, m_manager.getLowestItemAboveLayer(m_layernum));
269
270}
271
272void XLayer::tempRaise(XLayerItem &item) {
273 // assume it is already in this layer
274
275 if (&item == itemList().front())
276 return; // nothing to do
277
278 iterator it = std::find(itemList().begin(), itemList().end(), &item);
279 if (it == itemList().end()) {
280#ifdef DEBUG
281 cerr<<__FILE__<<"("<<__LINE__<<"): WARNING: raise on item not in layer["<<m_layernum<<"]"<<endl;
282#endif // DEBUG
283 return;
284 }
285
286 // don't add it back to the top
287 stackBelowItem(&item, m_manager.getLowestItemAboveLayer(m_layernum));
288
289}
290
291void XLayer::lower(XLayerItem &item) {
292 // assume already in this layer
293
294 // is it already the lowest?
295 if (&item == itemList().back())
296 return; // nothing to do
297
298 iterator it = std::find(itemList().begin(), itemList().end(), &item);
299 if (it != itemList().end())
300 // remove this item
301 itemList().erase(it);
302#ifdef DEBUG
303 else {
304 cerr<<__FILE__<<"("<<__LINE__<<"): WARNING: lower on item not in layer"<<endl;
305 return;
306 }
307#endif // DEBUG
308
309 // add it to the bottom
310 itemList().push_back(&item);
311
312 // find the item we need to stack below
313 // start at the end
314 it = itemList().end();
315
316 // go up one so we have an object (which must exist, since at least this item is in the layer)
317 it--;
318
319 // go down another one
320 // must exist, otherwise our item must == itemList().back()
321 it--;
322
323 // and restack our window below that one.
324 stackBelowItem(&item, *it);
325}
326
327void XLayer::raiseLayer(XLayerItem &item) {
328 m_manager.raiseLayer(item);
329}
330
331void XLayer::lowerLayer(XLayerItem &item) {
332 m_manager.lowerLayer(item);
333}
334
335void XLayer::moveToLayer(XLayerItem &item, int layernum) {
336 m_manager.moveToLayer(item, layernum);
337}
338
339
340XLayerItem *XLayer::getLowestItem() {
341 if (itemList().empty())
342 return 0;
343 else
344 return itemList().back();
345}
346
347XLayerItem *XLayer::getItemBelow(XLayerItem &item) {
348 // get our iterator
349 iterator it = std::find(itemList().begin(), itemList().end(), &item);
350
351 // go one lower
352 it++;
353
354 // if one lower is the end, there is no item below, otherwise we've got it
355 if (it == itemList().end())
356 return 0;
357 else
358 return *it;
359}
360
361XLayerItem *XLayer::getItemAbove(XLayerItem &item) {
362 // get our iterator
363 iterator it = std::find(itemList().begin(), itemList().end(), &item);
364
365 // if this is the beginning (top-most item), do nothing, otherwise give the next one up
366 // the list (which must be there since we aren't the beginning)
367 if (it == itemList().begin())
368 return 0;
369 else
370 return *(--it);
371}