version bump
[blackbox.git] / src / StackingList.cc
blob0be8d6ee97ab8af0bbd4a6642b8c7d866f51ba37
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // StackingList.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2005 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000, 2002 - 2005
5 // Bradley T Hughes <bhughes at trolltech.com>
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a
8 // copy of this software and associated documentation files (the "Software"),
9 // to deal in the Software without restriction, including without limitation
10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 // and/or sell copies of the Software, and to permit persons to whom the
12 // Software is furnished to do so, subject to the following conditions:
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
25 #include "StackingList.hh"
26 #include "Window.hh"
28 #include <Unicode.hh>
30 #include <cassert>
31 #include <cstdio>
34 static StackEntity * const zero = 0;
37 StackingList::StackingList(void) {
38 desktop = stack.insert(stack.begin(), zero);
39 below = stack.insert(desktop, zero);
40 normal = stack.insert(below, zero);
41 above = stack.insert(normal, zero);
42 fullscreen = stack.insert(above, zero);
46 StackingList::iterator StackingList::insert(StackEntity *entity) {
47 assert(entity);
49 iterator& it = layer(entity->layer());
50 it = stack.insert(it, entity);
51 return it;
55 StackingList::iterator StackingList::append(StackEntity *entity) {
56 assert(entity);
58 iterator& it = layer(entity->layer());
59 if (!*it) { // empty layer
60 it = stack.insert(it, entity);
61 return it;
64 // find the end of the layer (the zero pointer)
65 iterator tmp = std::find(it, stack.end(), zero);
66 assert(tmp != stack.end());
67 tmp = stack.insert(tmp, entity);
68 return tmp;
72 StackingList::iterator StackingList::remove(StackEntity *entity) {
73 assert(entity);
75 iterator& pos = layer(entity->layer());
76 iterator it = std::find(pos, stack.end(), entity);
77 assert(it != stack.end());
78 if (it == pos) ++pos;
79 it = stack.erase(it);
80 assert(stack.size() >= 5);
81 return it;
85 StackingList::iterator& StackingList::layer(Layer which) {
86 switch (which) { // teehee
87 case LayerNormal:
88 return normal;
89 case LayerFullScreen:
90 return fullscreen;
91 case LayerAbove:
92 return above;
93 case LayerBelow:
94 return below;
95 case LayerDesktop:
96 return desktop;
99 assert(0);
100 return normal;
104 void StackingList::changeLayer(StackEntity *entity, Layer new_layer) {
105 assert(entity);
107 (void) remove(entity);
108 entity->setLayer(new_layer);
109 (void) insert(entity);
113 StackingList::iterator StackingList::raise(StackEntity *entity) {
114 assert(entity);
116 // find the top of the layer and 'entity'
117 iterator& pos = layer(entity->layer());
118 const iterator send = stack.end();
119 iterator it = std::find(pos, send, entity);
120 assert(it != send);
122 if (it == pos) {
123 // entity is already at the top
124 return pos;
127 // raise the entity
128 (void) stack.erase(it);
129 return pos = stack.insert(pos, entity);
133 StackingList::iterator StackingList::lower(StackEntity *entity) {
134 assert(entity);
136 // find the top of the layer and 'entity'
137 iterator& pos = layer(entity->layer());
138 const iterator send = stack.end();
139 iterator it = std::find(pos, send, entity);
140 assert(it != send);
142 iterator next = it;
143 ++next;
144 assert(next != send);
145 if (!(*next)) {
146 // entity is already at the bottom
147 return it;
150 if (it == pos) {
151 // entity is at the top of the layer, adjust the layer iterator to
152 // the next entity
153 ++pos;
155 assert((*pos));
157 // lower the entity
158 (void) stack.erase(it);
159 it = std::find(pos, send, zero);
160 assert(it != send);
161 return stack.insert(it, entity);
165 StackEntity *StackingList::front(void) const {
166 assert(stack.size() > 5);
168 if (*fullscreen) return *fullscreen;
169 if (*above) return *above;
170 if (*normal) return *normal;
171 if (*below) return *below;
172 // we do not return desktop entities
173 assert(0);
175 // this point is never reached, but the compiler doesn't know that.
176 return zero;
180 StackEntity *StackingList::back(void) const {
181 assert(stack.size() > 5);
183 const_iterator it = desktop, _end = stack.begin();
184 for (--it; it != _end; --it) {
185 if (*it) return *it;
188 assert(0);
189 return zero;
193 static void print_entity(StackEntity *entity)
195 BlackboxWindow *win = dynamic_cast<BlackboxWindow *>(entity);
196 if (win) {
197 fprintf(stderr, " 0x%lx: window 0x%lx %p '%s'\n",
198 win->windowID(), win->clientWindow(), win,
199 bt::toLocale(win->title()).c_str());
200 } else if (entity) {
201 fprintf(stderr, " 0x%lx: %p unknown entity\n",
202 entity->windowID(), entity);
203 } else {
204 fprintf(stderr, " zero\n");
209 void StackingList::dump(void) const {
210 const_iterator it = stack.begin(), _end = stack.end();
211 fprintf(stderr, "Stack:\n");
212 for (; it != _end; ++it)
213 print_entity(*it);
215 fprintf(stderr, "Layers:\n");
216 print_entity(*fullscreen);
217 print_entity(*above);
218 print_entity(*normal);
219 print_entity(*below);
220 print_entity(*desktop);