slit order

This commit is contained in:
fluxgen 2002-05-29 06:21:59 +00:00
parent 5fe1edc94d
commit 095ed342bd
2 changed files with 207 additions and 22 deletions

View file

@ -19,7 +19,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // 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 //use GNU extensions
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
@ -42,9 +42,60 @@
#include "Toolbar.hh" #include "Toolbar.hh"
#include <algorithm> #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) { Slit::Slit(BScreen *scr):screen(scr), timer(this), slitmenu(*this) {
assert(scr);
fluxbox = Fluxbox::instance(); fluxbox = Fluxbox::instance();
on_top = screen->isSlitOnTop(); on_top = screen->isSlitOnTop();
@ -66,7 +117,7 @@ Slit::Slit(BScreen *scr):screen(scr), timer(this), slitmenu(*this) {
attrib.colormap = screen->getColormap(); attrib.colormap = screen->getColormap();
attrib.override_redirect = True; attrib.override_redirect = True;
attrib.event_mask = SubstructureRedirectMask | ButtonPressMask | attrib.event_mask = SubstructureRedirectMask | ButtonPressMask |
EnterWindowMask | LeaveWindowMask; EnterWindowMask | LeaveWindowMask;
frame.x = frame.y = 0; frame.x = frame.y = 0;
frame.width = frame.height = 1; frame.width = frame.height = 1;
@ -78,6 +129,9 @@ Slit::Slit(BScreen *scr):screen(scr), timer(this), slitmenu(*this) {
create_mask, &attrib); create_mask, &attrib);
fluxbox->saveSlitSearch(frame.window, this); fluxbox->saveSlitSearch(frame.window, this);
// Get client list for sorting purposes
loadClientList();
reconfigure(); reconfigure();
} }
@ -102,8 +156,37 @@ void Slit::addClient(Window w) {
fluxbox->grab(); fluxbox->grab();
if (fluxbox->validateWindow(w)) { if (fluxbox->validateWindow(w)) {
SlitClient *client = new SlitClient; // Look for slot in client list by name
client->client_window = w; 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); XWMHints *wmhints = XGetWMHints(display, w);
@ -184,22 +267,26 @@ void Slit::addClient(Window w) {
SubstructureNotifyMask | EnterWindowMask); SubstructureNotifyMask | EnterWindowMask);
XFlush(display); XFlush(display);
clientList.push_back(client);
fluxbox->saveSlitSearch(client->client_window, this); fluxbox->saveSlitSearch(client->client_window, this);
fluxbox->saveSlitSearch(client->icon_window, this); fluxbox->saveSlitSearch(client->icon_window, this);
reconfigure(); reconfigure();
saveClientList();
} }
fluxbox->ungrab(); 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->client_window);
fluxbox->removeSlitSearch(client->icon_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); screen->removeNetizen(client->window);
@ -214,7 +301,9 @@ void Slit::removeClient(SlitClient *client, bool remap) {
XFlush(display); XFlush(display);
} }
delete client; // Destructive removal?
if (destroy)
delete client;
} }
@ -227,7 +316,7 @@ void Slit::removeClient(Window w, bool remap) {
SlitClients::iterator it_end = clientList.end(); SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it) { for (; it != it_end; ++it) {
if ((*it)->window == w) { if ((*it)->window == w) {
removeClient((*it), remap); removeClient((*it), remap, false);
reconf = true; reconf = true;
break; break;
@ -243,16 +332,25 @@ void Slit::reconfigure(void) {
frame.width = 0; frame.width = 0;
frame.height = 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()) { switch (screen->getSlitDirection()) {
case VERTICAL: case VERTICAL:
{ {
SlitClients::iterator it = clientList.begin(); SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end(); SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it) { for (; it != it_end; ++it) {
frame.height += (*it)->height + screen->getBevelWidth(); //client created window?
if ((*it)->window != None) {
if (frame.width < (*it)->width) num_windows++;
frame.width = (*it)->width; frame.height += (*it)->height + screen->getBevelWidth();
//frame width < client window?
if (frame.width < (*it)->width)
frame.width = (*it)->width;
}
} }
} }
@ -273,10 +371,14 @@ void Slit::reconfigure(void) {
SlitClients::iterator it = clientList.begin(); SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end(); SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it) { for (; it != it_end; ++it) {
frame.width += (*it)->width + screen->getBevelWidth(); //client created window?
if ((*it)->window != None) {
if (frame.height < (*it)->height) num_windows++;
frame.height = (*it)->height; frame.width += (*it)->width + screen->getBevelWidth();
//frame height < client height?
if (frame.height < (*it)->height)
frame.height = (*it)->height;
}
} }
} }
@ -299,7 +401,8 @@ void Slit::reconfigure(void) {
XSetWindowBorder(display, frame.window, XSetWindowBorder(display, frame.window,
screen->getBorderColor()->getPixel()); screen->getBorderColor()->getPixel());
if (clientList.size()==0) //did we actually use slit slots
if (num_windows == 0)
XUnmapWindow(display, frame.window); XUnmapWindow(display, frame.window);
else else
XMapWindow(display, frame.window); XMapWindow(display, frame.window);
@ -316,7 +419,9 @@ void Slit::reconfigure(void) {
texture); texture);
XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap); XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap);
} }
if (tmp) image_ctrl->removeImage(tmp);
if (tmp)
image_ctrl->removeImage(tmp);
XClearWindow(display, frame.window); XClearWindow(display, frame.window);
int x, y; int x, y;
@ -330,6 +435,10 @@ void Slit::reconfigure(void) {
SlitClients::iterator it = clientList.begin(); SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end(); SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it) { for (; it != it_end; ++it) {
//client created window?
if ((*it)->window == None)
continue;
x = (frame.width - (*it)->width) / 2; x = (frame.width - (*it)->width) / 2;
XMoveResizeWindow(display, (*it)->window, x, y, XMoveResizeWindow(display, (*it)->window, x, y,
@ -371,6 +480,10 @@ void Slit::reconfigure(void) {
SlitClients::iterator it = clientList.begin(); SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end(); SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it) { for (; it != it_end; ++it) {
//client created window?
if ((*it)->window == None)
continue;
y = (frame.height - (*it)->height) / 2; y = (frame.height - (*it)->height) / 2;
XMoveResizeWindow(display, (*it)->window, x, y, XMoveResizeWindow(display, (*it)->window, x, y,
@ -556,8 +669,9 @@ void Slit::reposition(void) {
void Slit::shutdown(void) { void Slit::shutdown(void) {
saveClientList();
while (clientList.size() != 0) while (clientList.size() != 0)
removeClient(clientList.front()); removeClient(clientList.front(), true, true);
} }
@ -663,6 +777,39 @@ void Slit::timeout(void) {
XMoveWindow(display, frame.window, frame.x, frame.y); 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), Slitmenu::Slitmenu(Slit &sl) : Basemenu(sl.screen),
slit(sl) { slit(sl) {
@ -929,4 +1076,25 @@ void Slitmenu::Headmenu::itemSelected(int button, unsigned int index) {
#endif // XINERAMA #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 #endif // SLIT

View file

@ -35,6 +35,7 @@ class Slitmenu;
#include "Basemenu.hh" #include "Basemenu.hh"
#include <list> #include <list>
#include <string>
class Slitmenu : public Basemenu { class Slitmenu : public Basemenu {
public: public:
@ -130,6 +131,7 @@ public:
void reconfigure(void); void reconfigure(void);
void reposition(void); void reposition(void);
void shutdown(void); void shutdown(void);
void saveClientList(void);
void buttonPressEvent(XButtonEvent *); void buttonPressEvent(XButtonEvent *);
void enterNotifyEvent(XCrossingEvent *); void enterNotifyEvent(XCrossingEvent *);
@ -145,13 +147,27 @@ public:
private: private:
class SlitClient { class SlitClient {
public: 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; Window window, client_window, icon_window;
int x, y; int x, y;
unsigned int width, height; 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; Bool on_top, hidden, do_auto_hide;
Display *display; Display *display;
@ -164,6 +180,7 @@ private:
SlitClients clientList; SlitClients clientList;
Slitmenu slitmenu; Slitmenu slitmenu;
std::string clientListPath;
struct frame { struct frame {
Pixmap pixmap; Pixmap pixmap;