all repos — fluxbox @ 095ed342bd5c0c2b25858e50e8786e4a212e59b0

custom fork of the fluxbox windowmanager

slit order
fluxgen fluxgen
commit

095ed342bd5c0c2b25858e50e8786e4a212e59b0

parent

5fe1edc94d9add88563e84ff336a91af0669c30b

2 files changed, 207 insertions(+), 22 deletions(-)

jump to
M src/Slit.ccsrc/Slit.cc

@@ -19,7 +19,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING

// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Slit.cc,v 1.13 2002/05/08 14:12:28 fluxgen Exp $ +// $Id: Slit.cc,v 1.14 2002/05/29 06:21:59 fluxgen Exp $ //use GNU extensions #ifndef _GNU_SOURCE

@@ -42,9 +42,60 @@ #include "Slit.hh"

#include "Toolbar.hh" #include <algorithm> +#include <iostream> +#include <cassert> + +#ifdef HAVE_SYS_STAT_H +# include <sys/types.h> +# include <sys/stat.h> +#endif // HAVE_SYS_STAT_H +// Utility method for extracting name from window +namespace { + void getWMName(BScreen *screen, Window window, std::string& name) { + assert(screen); + name = ""; + + if (screen != 0 && window != None) { + Display *display = screen->getBaseDisplay()->getXDisplay(); + + XTextProperty text_prop; + char **list; + int num; + I18n *i18n = I18n::instance(); + + if (XGetWMName(display, window, &text_prop)) { + if (text_prop.value && text_prop.nitems > 0) { + if (text_prop.encoding != XA_STRING) { + + text_prop.nitems = strlen((char *) text_prop.value); + + if ((XmbTextPropertyToTextList(display, &text_prop, + &list, &num) == Success) && + (num > 0) && *list) { + name = static_cast<char *>(*list); + XFreeStringList(list); + } else + name = (char *)text_prop.value; + + } else + name = (char *)text_prop.value; + } else + name = i18n->getMessage( + FBNLS::WindowSet, FBNLS::WindowUnnamed, + "Unnamed"); + } else { + name = i18n->getMessage( + FBNLS::WindowSet, FBNLS::WindowUnnamed, + "Unnamed"); + } + } + } +}; // End anonymous namespace + Slit::Slit(BScreen *scr):screen(scr), timer(this), slitmenu(*this) { + assert(scr); fluxbox = Fluxbox::instance(); on_top = screen->isSlitOnTop();

@@ -66,7 +117,7 @@ screen->getBorderColor()->getPixel();

attrib.colormap = screen->getColormap(); attrib.override_redirect = True; attrib.event_mask = SubstructureRedirectMask | ButtonPressMask | - EnterWindowMask | LeaveWindowMask; + EnterWindowMask | LeaveWindowMask; frame.x = frame.y = 0; frame.width = frame.height = 1;

@@ -77,6 +128,9 @@ frame.width, frame.height, screen->getBorderWidth(),

screen->getDepth(), InputOutput, screen->getVisual(), create_mask, &attrib); fluxbox->saveSlitSearch(frame.window, this); + + // Get client list for sorting purposes + loadClientList(); reconfigure(); }

@@ -102,8 +156,37 @@ return;

fluxbox->grab(); if (fluxbox->validateWindow(w)) { - SlitClient *client = new SlitClient; - client->client_window = w; + // Look for slot in client list by name + SlitClient *client = 0; + std::string match_name; + ::getWMName(screen, w, match_name); + SlitClients::iterator it = clientList.begin(); + SlitClients::iterator it_end = clientList.end(); + bool found_match = false; + for (; it != it_end; ++it) { + // If the name matches... + if ((*it)->match_name == match_name) { + // Use the slot if no window is assigned + if ((*it)->window == None) { + client = (*it); + client->initialize(screen, w); + break; + } + // Otherwise keep looking for an unused match or a non-match + found_match = true; // Possibly redundant + + } else if (found_match) { + // Insert before first non-match after a previously found match? + client = new SlitClient(screen, w); + clientList.insert(it, client); + break; + } + } + // Append to client list? + if (client == 0) { + client = new SlitClient(screen, w); + clientList.push_back(client); + } XWMHints *wmhints = XGetWMHints(display, w);

@@ -184,22 +267,26 @@ XSelectInput(display, client->window, StructureNotifyMask |

SubstructureNotifyMask | EnterWindowMask); XFlush(display); - clientList.push_back(client); - fluxbox->saveSlitSearch(client->client_window, this); fluxbox->saveSlitSearch(client->icon_window, this); reconfigure(); + + saveClientList(); } fluxbox->ungrab(); } -void Slit::removeClient(SlitClient *client, bool remap) { +void Slit::removeClient(SlitClient *client, bool remap, bool destroy) { fluxbox->removeSlitSearch(client->client_window); fluxbox->removeSlitSearch(client->icon_window); - clientList.remove(client); + // Destructive removal? + if (destroy) + clientList.remove(client); + else // Clear the window info, but keep around to help future sorting? + client->initialize(); screen->removeNetizen(client->window);

@@ -214,7 +301,9 @@ ButtonPressMask | EnterWindowMask | LeaveWindowMask);

XFlush(display); } - delete client; + // Destructive removal? + if (destroy) + delete client; }

@@ -227,7 +316,7 @@ SlitClients::iterator it = clientList.begin();

SlitClients::iterator it_end = clientList.end(); for (; it != it_end; ++it) { if ((*it)->window == w) { - removeClient((*it), remap); + removeClient((*it), remap, false); reconf = true; break;

@@ -243,16 +332,25 @@ void Slit::reconfigure(void) {

frame.width = 0; frame.height = 0; + // Need to count windows because not all client list entries + // actually correspond to mapped windows. + int num_windows = 0; + switch (screen->getSlitDirection()) { case VERTICAL: { SlitClients::iterator it = clientList.begin(); SlitClients::iterator it_end = clientList.end(); for (; it != it_end; ++it) { - frame.height += (*it)->height + screen->getBevelWidth(); - - if (frame.width < (*it)->width) - frame.width = (*it)->width; + //client created window? + if ((*it)->window != None) { + num_windows++; + frame.height += (*it)->height + screen->getBevelWidth(); + + //frame width < client window? + if (frame.width < (*it)->width) + frame.width = (*it)->width; + } } }

@@ -273,10 +371,14 @@ {

SlitClients::iterator it = clientList.begin(); SlitClients::iterator it_end = clientList.end(); for (; it != it_end; ++it) { - frame.width += (*it)->width + screen->getBevelWidth(); - - if (frame.height < (*it)->height) - frame.height = (*it)->height; + //client created window? + if ((*it)->window != None) { + num_windows++; + frame.width += (*it)->width + screen->getBevelWidth(); + //frame height < client height? + if (frame.height < (*it)->height) + frame.height = (*it)->height; + } } }

@@ -299,7 +401,8 @@ XSetWindowBorderWidth(display ,frame.window, screen->getBorderWidth());

XSetWindowBorder(display, frame.window, screen->getBorderColor()->getPixel()); - if (clientList.size()==0) + //did we actually use slit slots + if (num_windows == 0) XUnmapWindow(display, frame.window); else XMapWindow(display, frame.window);

@@ -316,7 +419,9 @@ frame.pixmap = image_ctrl->renderImage(frame.width, frame.height,

texture); XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap); } - if (tmp) image_ctrl->removeImage(tmp); + + if (tmp) + image_ctrl->removeImage(tmp); XClearWindow(display, frame.window); int x, y;

@@ -330,6 +435,10 @@ {

SlitClients::iterator it = clientList.begin(); SlitClients::iterator it_end = clientList.end(); for (; it != it_end; ++it) { + //client created window? + if ((*it)->window == None) + continue; + x = (frame.width - (*it)->width) / 2; XMoveResizeWindow(display, (*it)->window, x, y,

@@ -371,6 +480,10 @@ {

SlitClients::iterator it = clientList.begin(); SlitClients::iterator it_end = clientList.end(); for (; it != it_end; ++it) { + //client created window? + if ((*it)->window == None) + continue; + y = (frame.height - (*it)->height) / 2; XMoveResizeWindow(display, (*it)->window, x, y,

@@ -556,8 +669,9 @@ }

void Slit::shutdown(void) { + saveClientList(); while (clientList.size() != 0) - removeClient(clientList.front()); + removeClient(clientList.front(), true, true); }

@@ -663,6 +777,39 @@ else

XMoveWindow(display, frame.window, frame.x, frame.y); } +void Slit::loadClientList(void) { + const std::string &filename = fluxbox->getSlitlistFilename(); + struct stat buf; + if (!stat(filename.c_str(), &buf)) + { + std::ifstream file(fluxbox->getSlitlistFilename().c_str()); + std::string name; + while (! file.eof()) { + name = ""; + file >> name; + if (name.size() > 0) { + SlitClient *client = new SlitClient(name.c_str()); + clientList.push_back(client); + } + } + } +} + +void Slit::saveClientList(void) { + const std::string &filename = fluxbox->getSlitlistFilename(); + std::ofstream file(filename.c_str()); + SlitClients::iterator it = clientList.begin(); + SlitClients::iterator it_end = clientList.end(); + std::string prevName; + std::string name; + for (; it != it_end; ++it) { + name = (*it)->match_name; + if (name != prevName) + file << name.c_str() << std::endl; + prevName = name; + } +} + Slitmenu::Slitmenu(Slit &sl) : Basemenu(sl.screen), slit(sl) {

@@ -928,5 +1075,26 @@ }

} #endif // XINERAMA + +Slit::SlitClient::SlitClient(const char *name) +{ + initialize(); + match_name = name; +} + +Slit::SlitClient::SlitClient(BScreen *screen, Window w) +{ + initialize(screen, w); +} + +void Slit::SlitClient::initialize(BScreen *screen, Window w) { + assert(screen); + client_window = w; + window = icon_window = None; + x = y = 0; + width = height = 0; + if (match_name.size() == 0) + getWMName(screen, client_window, match_name); +} #endif // SLIT
M src/Slit.hhsrc/Slit.hh

@@ -35,6 +35,7 @@

#include "Basemenu.hh" #include <list> +#include <string> class Slitmenu : public Basemenu { public:

@@ -130,6 +131,7 @@ void removeClient(Window, bool = true);

void reconfigure(void); void reposition(void); void shutdown(void); + void saveClientList(void); void buttonPressEvent(XButtonEvent *); void enterNotifyEvent(XCrossingEvent *);

@@ -145,13 +147,27 @@

private: class SlitClient { public: + SlitClient(BScreen *, Window); // For adding an actual window + SlitClient(const char *); // For adding a placeholder + + // Now we pre-initialize a list of slit clients with names for + // comparison with incoming client windows. This allows the slit + // to maintain a sorted order based on a saved window name list. + // Incoming windows not found in the list are appended. Matching + // duplicates are inserted after the last found instance of the + // matching name. + std::string match_name; + Window window, client_window, icon_window; int x, y; unsigned int width, height; + + void initialize(BScreen * = NULL, Window = None); }; - void removeClient(SlitClient *, bool = true); + void removeClient(SlitClient *, bool, bool); + void loadClientList(void); Bool on_top, hidden, do_auto_hide; Display *display;

@@ -164,6 +180,7 @@ typedef std::list<SlitClient *> SlitClients;

SlitClients clientList; Slitmenu slitmenu; + std::string clientListPath; struct frame { Pixmap pixmap;