summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Slit.cc210
-rw-r--r--src/Slit.hh19
2 files changed, 207 insertions, 22 deletions
diff --git a/src/Slit.cc b/src/Slit.cc
index 48345c9..79e3d31 100644
--- a/src/Slit.cc
+++ b/src/Slit.cc
@@ -19,7 +19,7 @@
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE. 20// DEALINGS IN THE SOFTWARE.
21 21
22// $Id: Slit.cc,v 1.13 2002/05/08 14:12:28 fluxgen Exp $ 22// $Id: Slit.cc,v 1.14 2002/05/29 06:21:59 fluxgen Exp $
23 23
24//use GNU extensions 24//use GNU extensions
25#ifndef _GNU_SOURCE 25#ifndef _GNU_SOURCE
@@ -42,9 +42,60 @@
42#include "Toolbar.hh" 42#include "Toolbar.hh"
43 43
44#include <algorithm> 44#include <algorithm>
45#include <iostream>
46#include <cassert>
45 47
48#ifdef HAVE_SYS_STAT_H
49# include <sys/types.h>
50# include <sys/stat.h>
51#endif // HAVE_SYS_STAT_H
52
53
54// Utility method for extracting name from window
55namespace {
56 void getWMName(BScreen *screen, Window window, std::string& name) {
57 assert(screen);
58 name = "";
59
60 if (screen != 0 && window != None) {
61 Display *display = screen->getBaseDisplay()->getXDisplay();
62
63 XTextProperty text_prop;
64 char **list;
65 int num;
66 I18n *i18n = I18n::instance();
67
68 if (XGetWMName(display, window, &text_prop)) {
69 if (text_prop.value && text_prop.nitems > 0) {
70 if (text_prop.encoding != XA_STRING) {
71
72 text_prop.nitems = strlen((char *) text_prop.value);
73
74 if ((XmbTextPropertyToTextList(display, &text_prop,
75 &list, &num) == Success) &&
76 (num > 0) && *list) {
77 name = static_cast<char *>(*list);
78 XFreeStringList(list);
79 } else
80 name = (char *)text_prop.value;
81
82 } else
83 name = (char *)text_prop.value;
84 } else
85 name = i18n->getMessage(
86 FBNLS::WindowSet, FBNLS::WindowUnnamed,
87 "Unnamed");
88 } else {
89 name = i18n->getMessage(
90 FBNLS::WindowSet, FBNLS::WindowUnnamed,
91 "Unnamed");
92 }
93 }
94 }
95}; // End anonymous namespace
46 96
47Slit::Slit(BScreen *scr):screen(scr), timer(this), slitmenu(*this) { 97Slit::Slit(BScreen *scr):screen(scr), timer(this), slitmenu(*this) {
98 assert(scr);
48 fluxbox = Fluxbox::instance(); 99 fluxbox = Fluxbox::instance();
49 100
50 on_top = screen->isSlitOnTop(); 101 on_top = screen->isSlitOnTop();
@@ -66,7 +117,7 @@ Slit::Slit(BScreen *scr):screen(scr), timer(this), slitmenu(*this) {
66 attrib.colormap = screen->getColormap(); 117 attrib.colormap = screen->getColormap();
67 attrib.override_redirect = True; 118 attrib.override_redirect = True;
68 attrib.event_mask = SubstructureRedirectMask | ButtonPressMask | 119 attrib.event_mask = SubstructureRedirectMask | ButtonPressMask |
69 EnterWindowMask | LeaveWindowMask; 120 EnterWindowMask | LeaveWindowMask;
70 121
71 frame.x = frame.y = 0; 122 frame.x = frame.y = 0;
72 frame.width = frame.height = 1; 123 frame.width = frame.height = 1;
@@ -78,6 +129,9 @@ Slit::Slit(BScreen *scr):screen(scr), timer(this), slitmenu(*this) {
78 create_mask, &attrib); 129 create_mask, &attrib);
79 fluxbox->saveSlitSearch(frame.window, this); 130 fluxbox->saveSlitSearch(frame.window, this);
80 131
132 // Get client list for sorting purposes
133 loadClientList();
134
81 reconfigure(); 135 reconfigure();
82} 136}
83 137
@@ -102,8 +156,37 @@ void Slit::addClient(Window w) {
102 156
103 fluxbox->grab(); 157 fluxbox->grab();
104 if (fluxbox->validateWindow(w)) { 158 if (fluxbox->validateWindow(w)) {
105 SlitClient *client = new SlitClient; 159 // Look for slot in client list by name
106 client->client_window = w; 160 SlitClient *client = 0;
161 std::string match_name;
162 ::getWMName(screen, w, match_name);
163 SlitClients::iterator it = clientList.begin();
164 SlitClients::iterator it_end = clientList.end();
165 bool found_match = false;
166 for (; it != it_end; ++it) {
167 // If the name matches...
168 if ((*it)->match_name == match_name) {
169 // Use the slot if no window is assigned
170 if ((*it)->window == None) {
171 client = (*it);
172 client->initialize(screen, w);
173 break;
174 }
175 // Otherwise keep looking for an unused match or a non-match
176 found_match = true; // Possibly redundant
177
178 } else if (found_match) {
179 // Insert before first non-match after a previously found match?
180 client = new SlitClient(screen, w);
181 clientList.insert(it, client);
182 break;
183 }
184 }
185 // Append to client list?
186 if (client == 0) {
187 client = new SlitClient(screen, w);
188 clientList.push_back(client);
189 }
107 190
108 XWMHints *wmhints = XGetWMHints(display, w); 191 XWMHints *wmhints = XGetWMHints(display, w);
109 192
@@ -184,22 +267,26 @@ void Slit::addClient(Window w) {
184 SubstructureNotifyMask | EnterWindowMask); 267 SubstructureNotifyMask | EnterWindowMask);
185 XFlush(display); 268 XFlush(display);
186 269
187 clientList.push_back(client);
188
189 fluxbox->saveSlitSearch(client->client_window, this); 270 fluxbox->saveSlitSearch(client->client_window, this);
190 fluxbox->saveSlitSearch(client->icon_window, this); 271 fluxbox->saveSlitSearch(client->icon_window, this);
191 reconfigure(); 272 reconfigure();
273
274 saveClientList();
192 } 275 }
193 276
194 fluxbox->ungrab(); 277 fluxbox->ungrab();
195} 278}
196 279
197 280
198void Slit::removeClient(SlitClient *client, bool remap) { 281void Slit::removeClient(SlitClient *client, bool remap, bool destroy) {
199 fluxbox->removeSlitSearch(client->client_window); 282 fluxbox->removeSlitSearch(client->client_window);
200 fluxbox->removeSlitSearch(client->icon_window); 283 fluxbox->removeSlitSearch(client->icon_window);
201 284
202 clientList.remove(client); 285 // Destructive removal?
286 if (destroy)
287 clientList.remove(client);
288 else // Clear the window info, but keep around to help future sorting?
289 client->initialize();
203 290
204 screen->removeNetizen(client->window); 291 screen->removeNetizen(client->window);
205 292
@@ -214,7 +301,9 @@ void Slit::removeClient(SlitClient *client, bool remap) {
214 XFlush(display); 301 XFlush(display);
215 } 302 }
216 303
217 delete client; 304 // Destructive removal?
305 if (destroy)
306 delete client;
218} 307}
219 308
220 309
@@ -227,7 +316,7 @@ void Slit::removeClient(Window w, bool remap) {
227 SlitClients::iterator it_end = clientList.end(); 316 SlitClients::iterator it_end = clientList.end();
228 for (; it != it_end; ++it) { 317 for (; it != it_end; ++it) {
229 if ((*it)->window == w) { 318 if ((*it)->window == w) {
230 removeClient((*it), remap); 319 removeClient((*it), remap, false);
231 reconf = true; 320 reconf = true;
232 321
233 break; 322 break;
@@ -243,16 +332,25 @@ void Slit::reconfigure(void) {
243 frame.width = 0; 332 frame.width = 0;
244 frame.height = 0; 333 frame.height = 0;
245 334
335 // Need to count windows because not all client list entries
336 // actually correspond to mapped windows.
337 int num_windows = 0;
338
246 switch (screen->getSlitDirection()) { 339 switch (screen->getSlitDirection()) {
247 case VERTICAL: 340 case VERTICAL:
248 { 341 {
249 SlitClients::iterator it = clientList.begin(); 342 SlitClients::iterator it = clientList.begin();
250 SlitClients::iterator it_end = clientList.end(); 343 SlitClients::iterator it_end = clientList.end();
251 for (; it != it_end; ++it) { 344 for (; it != it_end; ++it) {
252 frame.height += (*it)->height + screen->getBevelWidth(); 345 //client created window?
253 346 if ((*it)->window != None) {
254 if (frame.width < (*it)->width) 347 num_windows++;
255 frame.width = (*it)->width; 348 frame.height += (*it)->height + screen->getBevelWidth();
349
350 //frame width < client window?
351 if (frame.width < (*it)->width)
352 frame.width = (*it)->width;
353 }
256 } 354 }
257 } 355 }
258 356
@@ -273,10 +371,14 @@ void Slit::reconfigure(void) {
273 SlitClients::iterator it = clientList.begin(); 371 SlitClients::iterator it = clientList.begin();
274 SlitClients::iterator it_end = clientList.end(); 372 SlitClients::iterator it_end = clientList.end();
275 for (; it != it_end; ++it) { 373 for (; it != it_end; ++it) {
276 frame.width += (*it)->width + screen->getBevelWidth(); 374 //client created window?
277 375 if ((*it)->window != None) {
278 if (frame.height < (*it)->height) 376 num_windows++;
279 frame.height = (*it)->height; 377 frame.width += (*it)->width + screen->getBevelWidth();
378 //frame height < client height?
379 if (frame.height < (*it)->height)
380 frame.height = (*it)->height;
381 }
280 } 382 }
281 } 383 }
282 384
@@ -299,7 +401,8 @@ void Slit::reconfigure(void) {
299 XSetWindowBorder(display, frame.window, 401 XSetWindowBorder(display, frame.window,
300 screen->getBorderColor()->getPixel()); 402 screen->getBorderColor()->getPixel());
301 403
302 if (clientList.size()==0) 404 //did we actually use slit slots
405 if (num_windows == 0)
303 XUnmapWindow(display, frame.window); 406 XUnmapWindow(display, frame.window);
304 else 407 else
305 XMapWindow(display, frame.window); 408 XMapWindow(display, frame.window);
@@ -316,7 +419,9 @@ void Slit::reconfigure(void) {
316 texture); 419 texture);
317 XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap); 420 XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap);
318 } 421 }
319 if (tmp) image_ctrl->removeImage(tmp); 422
423 if (tmp)
424 image_ctrl->removeImage(tmp);
320 XClearWindow(display, frame.window); 425 XClearWindow(display, frame.window);
321 426
322 int x, y; 427 int x, y;
@@ -330,6 +435,10 @@ void Slit::reconfigure(void) {
330 SlitClients::iterator it = clientList.begin(); 435 SlitClients::iterator it = clientList.begin();
331 SlitClients::iterator it_end = clientList.end(); 436 SlitClients::iterator it_end = clientList.end();
332 for (; it != it_end; ++it) { 437 for (; it != it_end; ++it) {
438 //client created window?
439 if ((*it)->window == None)
440 continue;
441
333 x = (frame.width - (*it)->width) / 2; 442 x = (frame.width - (*it)->width) / 2;
334 443
335 XMoveResizeWindow(display, (*it)->window, x, y, 444 XMoveResizeWindow(display, (*it)->window, x, y,
@@ -371,6 +480,10 @@ void Slit::reconfigure(void) {
371 SlitClients::iterator it = clientList.begin(); 480 SlitClients::iterator it = clientList.begin();
372 SlitClients::iterator it_end = clientList.end(); 481 SlitClients::iterator it_end = clientList.end();
373 for (; it != it_end; ++it) { 482 for (; it != it_end; ++it) {
483 //client created window?
484 if ((*it)->window == None)
485 continue;
486
374 y = (frame.height - (*it)->height) / 2; 487 y = (frame.height - (*it)->height) / 2;
375 488
376 XMoveResizeWindow(display, (*it)->window, x, y, 489 XMoveResizeWindow(display, (*it)->window, x, y,
@@ -556,8 +669,9 @@ void Slit::reposition(void) {
556 669
557 670
558void Slit::shutdown(void) { 671void Slit::shutdown(void) {
672 saveClientList();
559 while (clientList.size() != 0) 673 while (clientList.size() != 0)
560 removeClient(clientList.front()); 674 removeClient(clientList.front(), true, true);
561} 675}
562 676
563 677
@@ -663,6 +777,39 @@ void Slit::timeout(void) {
663 XMoveWindow(display, frame.window, frame.x, frame.y); 777 XMoveWindow(display, frame.window, frame.x, frame.y);
664} 778}
665 779
780void Slit::loadClientList(void) {
781 const std::string &filename = fluxbox->getSlitlistFilename();
782 struct stat buf;
783 if (!stat(filename.c_str(), &buf))
784 {
785 std::ifstream file(fluxbox->getSlitlistFilename().c_str());
786 std::string name;
787 while (! file.eof()) {
788 name = "";
789 file >> name;
790 if (name.size() > 0) {
791 SlitClient *client = new SlitClient(name.c_str());
792 clientList.push_back(client);
793 }
794 }
795 }
796}
797
798void Slit::saveClientList(void) {
799 const std::string &filename = fluxbox->getSlitlistFilename();
800 std::ofstream file(filename.c_str());
801 SlitClients::iterator it = clientList.begin();
802 SlitClients::iterator it_end = clientList.end();
803 std::string prevName;
804 std::string name;
805 for (; it != it_end; ++it) {
806 name = (*it)->match_name;
807 if (name != prevName)
808 file << name.c_str() << std::endl;
809 prevName = name;
810 }
811}
812
666 813
667Slitmenu::Slitmenu(Slit &sl) : Basemenu(sl.screen), 814Slitmenu::Slitmenu(Slit &sl) : Basemenu(sl.screen),
668slit(sl) { 815slit(sl) {
@@ -929,4 +1076,25 @@ void Slitmenu::Headmenu::itemSelected(int button, unsigned int index) {
929 1076
930#endif // XINERAMA 1077#endif // XINERAMA
931 1078
1079Slit::SlitClient::SlitClient(const char *name)
1080{
1081 initialize();
1082 match_name = name;
1083}
1084
1085Slit::SlitClient::SlitClient(BScreen *screen, Window w)
1086{
1087 initialize(screen, w);
1088}
1089
1090void Slit::SlitClient::initialize(BScreen *screen, Window w) {
1091 assert(screen);
1092 client_window = w;
1093 window = icon_window = None;
1094 x = y = 0;
1095 width = height = 0;
1096 if (match_name.size() == 0)
1097 getWMName(screen, client_window, match_name);
1098}
1099
932#endif // SLIT 1100#endif // SLIT
diff --git a/src/Slit.hh b/src/Slit.hh
index 75111d0..61a7d33 100644
--- a/src/Slit.hh
+++ b/src/Slit.hh
@@ -35,6 +35,7 @@ class Slitmenu;
35#include "Basemenu.hh" 35#include "Basemenu.hh"
36 36
37#include <list> 37#include <list>
38#include <string>
38 39
39class Slitmenu : public Basemenu { 40class Slitmenu : public Basemenu {
40public: 41public:
@@ -130,6 +131,7 @@ public:
130 void reconfigure(void); 131 void reconfigure(void);
131 void reposition(void); 132 void reposition(void);
132 void shutdown(void); 133 void shutdown(void);
134 void saveClientList(void);
133 135
134 void buttonPressEvent(XButtonEvent *); 136 void buttonPressEvent(XButtonEvent *);
135 void enterNotifyEvent(XCrossingEvent *); 137 void enterNotifyEvent(XCrossingEvent *);
@@ -145,13 +147,27 @@ public:
145private: 147private:
146 class SlitClient { 148 class SlitClient {
147 public: 149 public:
150 SlitClient(BScreen *, Window); // For adding an actual window
151 SlitClient(const char *); // For adding a placeholder
152
153 // Now we pre-initialize a list of slit clients with names for
154 // comparison with incoming client windows. This allows the slit
155 // to maintain a sorted order based on a saved window name list.
156 // Incoming windows not found in the list are appended. Matching
157 // duplicates are inserted after the last found instance of the
158 // matching name.
159 std::string match_name;
160
148 Window window, client_window, icon_window; 161 Window window, client_window, icon_window;
149 162
150 int x, y; 163 int x, y;
151 unsigned int width, height; 164 unsigned int width, height;
165
166 void initialize(BScreen * = NULL, Window = None);
152 }; 167 };
153 168
154 void removeClient(SlitClient *, bool = true); 169 void removeClient(SlitClient *, bool, bool);
170 void loadClientList(void);
155 171
156 Bool on_top, hidden, do_auto_hide; 172 Bool on_top, hidden, do_auto_hide;
157 Display *display; 173 Display *display;
@@ -164,6 +180,7 @@ private:
164 180
165 SlitClients clientList; 181 SlitClients clientList;
166 Slitmenu slitmenu; 182 Slitmenu slitmenu;
183 std::string clientListPath;
167 184
168 struct frame { 185 struct frame {
169 Pixmap pixmap; 186 Pixmap pixmap;