slit order
This commit is contained in:
parent
5fe1edc94d
commit
095ed342bd
2 changed files with 207 additions and 22 deletions
208
src/Slit.cc
208
src/Slit.cc
|
@ -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) {
|
||||||
|
num_windows++;
|
||||||
|
frame.height += (*it)->height + screen->getBevelWidth();
|
||||||
|
|
||||||
if (frame.width < (*it)->width)
|
//frame width < client window?
|
||||||
frame.width = (*it)->width;
|
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
|
||||||
|
|
19
src/Slit.hh
19
src/Slit.hh
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue