fluxbox/src/Slit.cc

1345 lines
42 KiB
C++
Raw Normal View History

2002-11-14 00:23:19 +00:00
// Slit.cc for fluxbox
// Copyright (c) 2002 - 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net)
2002-11-14 00:23:19 +00:00
//
2001-12-11 20:47:02 +00:00
// Slit.cc for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
2001-12-11 20:47:02 +00:00
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2001-12-11 20:47:02 +00:00
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// 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.
2003-07-06 07:09:53 +00:00
// $Id: Slit.cc,v 1.71 2003/07/06 07:09:53 rathnor Exp $
#include "Slit.hh"
2002-04-08 18:58:47 +00:00
2002-03-11 12:29:57 +00:00
//use GNU extensions
2001-12-11 20:47:02 +00:00
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
2002-10-13 21:47:54 +00:00
#ifdef HAVE_CONFIG_H
2003-05-04 20:50:15 +00:00
#include "config.h"
2001-12-11 20:47:02 +00:00
#endif // HAVE_CONFIG_H
2003-06-13 05:04:14 +00:00
#include "I18n.hh"
2001-12-11 20:47:02 +00:00
#include "Screen.hh"
2002-11-30 20:29:27 +00:00
#include "ImageControl.hh"
#include "RefCount.hh"
#include "BoolMenuItem.hh"
#include "EventManager.hh"
#include "SimpleCommand.hh"
#include "MacroCommand.hh"
#include "FbCommands.hh"
#include "LayerMenu.hh"
#include "fluxbox.hh"
#include "XLayer.hh"
2003-04-25 10:46:07 +00:00
#include "RootTheme.hh"
#include "FbTk/Theme.hh"
2003-05-06 01:45:17 +00:00
#include "FbMenu.hh"
2003-05-13 21:12:18 +00:00
#include "Transparent.hh"
#include "IntResMenuItem.hh"
#include "Xinerama.hh"
#include "SlitTheme.hh"
#include "SlitClient.hh"
2003-06-22 12:31:37 +00:00
#include "Xutil.hh"
2003-06-27 15:05:19 +00:00
#include "FbAtoms.hh"
2002-02-04 22:33:09 +00:00
#include <algorithm>
2002-05-29 06:21:59 +00:00
#include <iostream>
#include <cassert>
2002-02-04 22:33:09 +00:00
2002-05-29 06:21:59 +00:00
#ifdef HAVE_SYS_STAT_H
#include <sys/types.h>
#include <sys/stat.h>
2002-05-29 06:21:59 +00:00
#endif // HAVE_SYS_STAT_H
#include <X11/Xatom.h>
2003-06-27 15:05:19 +00:00
#include <X11/Xlib.h>
2002-05-29 06:21:59 +00:00
#include <iostream>
#include <algorithm>
using namespace std;
template<>
void FbTk::Resource<Slit::Placement>::setFromString(const char *strval) {
if (strcasecmp(strval, "TopLeft")==0)
m_value = Slit::TOPLEFT;
else if (strcasecmp(strval, "CenterLeft")==0)
m_value = Slit::CENTERLEFT;
else if (strcasecmp(strval, "BottomLeft")==0)
m_value = Slit::BOTTOMLEFT;
else if (strcasecmp(strval, "TopCenter")==0)
m_value = Slit::TOPCENTER;
else if (strcasecmp(strval, "BottomCenter")==0)
m_value = Slit::BOTTOMCENTER;
else if (strcasecmp(strval, "TopRight")==0)
m_value = Slit::TOPRIGHT;
else if (strcasecmp(strval, "CenterRight")==0)
m_value = Slit::CENTERRIGHT;
else if (strcasecmp(strval, "BottomRight")==0)
m_value = Slit::BOTTOMRIGHT;
else
setDefaultValue();
}
template<>
void FbTk::Resource<Slit::Direction>::setFromString(const char *strval) {
if (strcasecmp(strval, "Vertical") == 0)
m_value = Slit::VERTICAL;
else if (strcasecmp(strval, "Horizontal") == 0)
m_value = Slit::HORIZONTAL;
else
setDefaultValue();
}
string FbTk::Resource<Slit::Placement>::getString() {
switch (m_value) {
case Slit::TOPLEFT:
return string("TopLeft");
break;
case Slit::CENTERLEFT:
return string("CenterLeft");
break;
case Slit::BOTTOMLEFT:
return string("BottomLeft");
break;
case Slit::TOPCENTER:
return string("TopCenter");
break;
case Slit::BOTTOMCENTER:
return string("BottomCenter");
break;
case Slit::TOPRIGHT:
return string("TopRight");
break;
case Slit::CENTERRIGHT:
return string("CenterRight");
break;
case Slit::BOTTOMRIGHT:
return string("BottomRight");
break;
}
//default string
return string("BottomRight");
}
template<>
string FbTk::Resource<Slit::Direction>::getString() {
switch (m_value) {
case Slit::VERTICAL:
return string("Vertical");
break;
case Slit::HORIZONTAL:
return string("Horizontal");
break;
}
// default string
return string("Vertical");
}
namespace {
class SlitClientMenuItem: public FbTk::MenuItem {
public:
explicit SlitClientMenuItem(SlitClient &client, FbTk::RefCount<FbTk::Command> &cmd):
FbTk::MenuItem(client.matchName().c_str(), cmd), m_client(client) {
FbTk::MenuItem::setSelected(client.visible());
// save resources as default click action
FbTk::RefCount<FbTk::Command> save_rc(new FbCommands::SaveResources());
setCommand(save_rc);
}
const std::string &label() const {
return m_client.matchName();
}
bool isSelected() const {
return m_client.visible();
}
void click(int button, int time) {
m_client.setVisible(!m_client.visible());
FbTk::MenuItem::click(button, time);
}
private:
SlitClient &m_client;
};
class SlitDirMenuItem: public FbTk::MenuItem {
public:
SlitDirMenuItem(const char *label, Slit &slit, FbTk::RefCount<FbTk::Command> &cmd)
:FbTk::MenuItem(label,cmd),
m_slit(slit),
m_label(label ? label : "") {
setLabel(m_label.c_str()); // update label
}
2003-06-22 12:31:37 +00:00
void click(int button, int time) {
// toggle direction
if (m_slit.direction() == Slit::HORIZONTAL)
m_slit.setDirection(Slit::VERTICAL);
else
m_slit.setDirection(Slit::HORIZONTAL);
setLabel(m_label.c_str());
FbTk::MenuItem::click(button, time);
}
void setLabel(const char *label) {
I18n *i18n = I18n::instance();
m_label = (label ? label : "");
std::string reallabel = m_label + " " +
( m_slit.direction() == Slit::HORIZONTAL ?
2003-06-22 12:31:37 +00:00
i18n->getMessage(FBNLS::CommonSet, FBNLS::CommonDirectionHoriz,
"Horizontal") :
2003-06-22 12:31:37 +00:00
i18n->getMessage(FBNLS::CommonSet, FBNLS::CommonDirectionVert,
"Vertical") );
FbTk::MenuItem::setLabel(reallabel.c_str());
}
private:
Slit &m_slit;
std::string m_label;
};
class PlaceSlitMenuItem: public FbTk::MenuItem {
public:
PlaceSlitMenuItem(const char *label, Slit &slit, Slit::Placement place, FbTk::RefCount<FbTk::Command> &cmd):
FbTk::MenuItem(label, cmd), m_slit(slit), m_place(place) {
}
bool isEnabled() const { return m_slit.placement() != m_place; }
void click(int button, int time) {
m_slit.setPlacement(m_place);
FbTk::MenuItem::click(button, time);
}
private:
Slit &m_slit;
Slit::Placement m_place;
};
2002-05-29 06:21:59 +00:00
}; // End anonymous namespace
2001-12-11 20:47:02 +00:00
2003-06-05 11:30:06 +00:00
unsigned int Slit::s_eventmask = SubstructureRedirectMask | ButtonPressMask |
EnterWindowMask | LeaveWindowMask | ExposureMask;
Slit::Slit(BScreen &scr, FbTk::XLayer &layer, const char *filename)
2003-06-22 12:31:37 +00:00
: m_hidden(false),
m_screen(scr), m_timer(this),
2003-05-11 17:42:51 +00:00
m_slitmenu(*scr.menuTheme(),
2003-05-15 12:00:46 +00:00
scr.screenNumber(),
2003-05-15 23:30:07 +00:00
scr.imageControl(),
2003-05-11 17:42:51 +00:00
*scr.layerManager().getLayer(Fluxbox::instance()->getMenuLayer())),
m_placement_menu(*scr.menuTheme(),
2003-05-15 12:00:46 +00:00
scr.screenNumber(),
2003-05-15 23:30:07 +00:00
scr.imageControl(),
2003-05-11 17:42:51 +00:00
*scr.layerManager().getLayer(Fluxbox::instance()->getMenuLayer())),
m_clientlist_menu(*scr.menuTheme(),
2003-05-15 12:00:46 +00:00
scr.screenNumber(),
2003-05-15 23:30:07 +00:00
scr.imageControl(),
2003-05-11 17:42:51 +00:00
*scr.layerManager().getLayer(Fluxbox::instance()->getMenuLayer())),
m_layermenu(new LayerMenu<Slit>(*scr.menuTheme(),
2003-05-15 23:30:07 +00:00
scr.screenNumber(),
scr.imageControl(),
*scr.layerManager().getLayer(Fluxbox::instance()->getMenuLayer()),
this,
true)),
2003-05-11 17:42:51 +00:00
//For KDE dock applets
m_kwm1_dockwindow(XInternAtom(FbTk::App::instance()->display(),
"KWM_DOCKWINDOW", False)), //KDE v1.x
m_kwm2_dockwindow(XInternAtom(FbTk::App::instance()->display(),
"_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False)), //KDE v2.x
2003-04-25 10:46:07 +00:00
m_layeritem(0),
2003-06-18 13:55:17 +00:00
m_slit_theme(new SlitTheme(*this)),
m_strut(0),
2003-06-22 12:31:37 +00:00
// resources
m_rc_auto_hide(scr.resourceManager(), false,
scr.name() + ".slit.autoHide", scr.altName() + ".Slit.AutoHide"),
// TODO: this resource name must change
m_rc_maximize_over(scr.resourceManager(), false,
2003-06-22 12:31:37 +00:00
scr.name() + ".slit.maxOver", scr.altName() + ".Slit.MaxOver"),
m_rc_placement(scr.resourceManager(), BOTTOMRIGHT,
scr.name() + ".slit.placement", scr.altName() + ".Slit.Placement"),
m_rc_direction(scr.resourceManager(), VERTICAL,
scr.name() + ".slit.direction", scr.altName() + ".Slit.Direction"),
m_rc_alpha(scr.resourceManager(), 255,
scr.name() + ".slit.alpha", scr.altName() + ".Slit.Alpha"),
m_rc_on_head(scr.resourceManager(), 0,
scr.name() + ".slit.onhead", scr.altName() + ".Slit.onHead"),
m_rc_layernum(scr.resourceManager(), Fluxbox::Layer(Fluxbox::instance()->getDockLayer()),
scr.name() + ".slit.layer", scr.altName() + ".Slit.Layer") {
2001-12-11 20:47:02 +00:00
frame.pixmap = None;
2001-12-11 20:47:02 +00:00
2003-05-11 17:42:51 +00:00
m_timer.setTimeout(200); // default timeout
m_timer.fireOnce(true);
2002-12-01 13:42:15 +00:00
2003-06-22 12:31:37 +00:00
// create main window
2002-12-01 13:42:15 +00:00
XSetWindowAttributes attrib;
unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
CWColormap | CWOverrideRedirect | CWEventMask;
attrib.background_pixmap = None;
attrib.background_pixel = attrib.border_pixel = theme().borderColor().pixel();
2003-05-10 22:59:32 +00:00
attrib.colormap = screen().rootWindow().colormap();
2002-12-01 13:42:15 +00:00
attrib.override_redirect = True;
2003-06-05 11:30:06 +00:00
attrib.event_mask = s_eventmask;
2002-12-01 13:42:15 +00:00
frame.x = frame.y = 0;
frame.width = frame.height = 1;
Display *disp = FbTk::App::instance()->display();
2002-12-01 13:42:15 +00:00
frame.window =
2003-05-10 22:59:32 +00:00
XCreateWindow(disp, screen().rootWindow().window(), frame.x, frame.y,
frame.width, frame.height, theme().borderWidth(),
2003-05-10 22:59:32 +00:00
screen().rootWindow().depth(), InputOutput, screen().rootWindow().visual(),
2002-12-01 13:42:15 +00:00
create_mask, &attrib);
FbTk::EventManager::instance()->add(*this, frame.window);
2003-05-13 21:12:18 +00:00
m_transp.reset(new FbTk::Transparent(screen().rootPixmap(), frame.window.drawable(),
2003-06-24 13:48:34 +00:00
*m_rc_alpha,
2003-05-15 12:00:46 +00:00
screen().screenNumber()));
m_layeritem.reset(new FbTk::XLayerItem(frame.window, layer));
2002-12-01 13:42:15 +00:00
// Get client list for sorting purposes
loadClientList(filename);
setupMenu();
2002-12-01 13:42:15 +00:00
2001-12-11 20:47:02 +00:00
}
2003-06-05 11:30:06 +00:00
2001-12-11 20:47:02 +00:00
Slit::~Slit() {
2003-06-18 13:55:17 +00:00
clearStrut();
if (frame.pixmap != 0)
2003-05-15 23:30:07 +00:00
screen().imageControl().removeImage(frame.pixmap);
2003-06-22 12:31:37 +00:00
shutdown();
2001-12-11 20:47:02 +00:00
}
2003-06-18 13:55:17 +00:00
void Slit::clearStrut() {
if (m_strut != 0) {
screen().clearStrut(m_strut);
m_strut = 0;
}
}
void Slit::updateStrut() {
bool had_strut = m_strut ? true : false;
2003-06-18 13:55:17 +00:00
clearStrut();
// no need for area if we're autohiding or set maximize over
if (doAutoHide() || *m_rc_maximize_over) {
// update screen area if we had a strut before
if (had_strut)
screen().updateAvailableWorkspaceArea();
2003-06-18 13:55:17 +00:00
return;
}
2003-06-18 13:55:17 +00:00
int left = 0, right = 0, top = 0, bottom = 0;
switch (placement()) {
case TOPLEFT:
if (direction() == HORIZONTAL)
top = height();
else
left = width();
2003-06-18 13:55:17 +00:00
break;
case TOPCENTER:
if (direction() == HORIZONTAL)
top = height();
2003-06-18 13:55:17 +00:00
break;
case TOPRIGHT:
if (direction() == HORIZONTAL)
top = height();
else
right = width();
2003-06-18 13:55:17 +00:00
break;
case BOTTOMLEFT:
if (direction() == HORIZONTAL)
bottom = height();
else
left = width();
2003-06-18 13:55:17 +00:00
break;
case BOTTOMCENTER:
// would be strange to have it request size on vertical direction
// each time we add a client
if (direction() == HORIZONTAL)
bottom = height();
break;
case BOTTOMRIGHT:
if (direction() == HORIZONTAL)
bottom = height();
else
right = width();
break;
case CENTERLEFT:
if (direction() == VERTICAL)
left = width();
break;
case CENTERRIGHT:
if (direction() == VERTICAL)
right = width();
break;
}
m_strut = screen().requestStrut(left, right, top, bottom);
screen().updateAvailableWorkspaceArea();
}
2001-12-11 20:47:02 +00:00
void Slit::addClient(Window w) {
#ifdef DEBUG
cerr<<__FILE__": addClient(w = 0x"<<hex<<w<<dec<<")"<<endl;
#endif // DEBUG
2003-05-11 17:42:51 +00:00
// Can't add non existent window
2002-12-01 13:42:15 +00:00
if (w == None)
return;
// Look for slot in client list by name
SlitClient *client = 0;
std::string match_name;
2003-06-22 12:31:37 +00:00
match_name = Xutil::getWMName(w);
2003-05-11 17:42:51 +00:00
SlitClients::iterator it = m_client_list.begin();
SlitClients::iterator it_end = m_client_list.end();
2002-12-01 13:42:15 +00:00
bool found_match = false;
for (; it != it_end; ++it) {
// If the name matches...
if ((*it)->matchName() == match_name) {
2002-12-01 13:42:15 +00:00
// Use the slot if no window is assigned
if ((*it)->window() == None) {
2002-12-01 13:42:15 +00:00
client = (*it);
client->initialize(&screen(), w);
2002-12-01 13:42:15 +00:00
break;
}
// Otherwise keep looking for an unused match or a non-match
found_match = true; // Possibly redundant
2002-11-14 00:23:19 +00:00
2002-12-01 13:42:15 +00:00
} else if (found_match) {
// Insert before first non-match after a previously found match?
client = new SlitClient(&screen(), w);
2003-05-11 17:42:51 +00:00
m_client_list.insert(it, client);
2002-12-01 13:42:15 +00:00
break;
}
}
// Append to client list?
if (client == 0) {
client = new SlitClient(&screen(), w);
2003-05-11 17:42:51 +00:00
m_client_list.push_back(client);
2002-12-01 13:42:15 +00:00
}
Display *disp = FbTk::App::instance()->display();
2002-12-01 13:42:15 +00:00
XWMHints *wmhints = XGetWMHints(disp, w);
if (wmhints != 0) {
2002-12-01 13:42:15 +00:00
if ((wmhints->flags & IconWindowHint) &&
(wmhints->icon_window != None)) {
XMoveWindow(disp, client->clientWindow(), screen().width() + 10,
screen().height() + 10);
XMapWindow(disp, client->clientWindow());
client->setIconWindow(wmhints->icon_window);
client->setWindow(client->iconWindow());
2002-12-01 13:42:15 +00:00
} else {
client->setIconWindow(None);
client->setWindow(client->clientWindow());
2002-12-01 13:42:15 +00:00
}
2003-06-27 15:05:19 +00:00
XFree((void *) wmhints);
2002-12-01 13:42:15 +00:00
} else {
client->setIconWindow(None);
client->setWindow(client->clientWindow());
2002-12-01 13:42:15 +00:00
}
2003-06-27 15:05:19 +00:00
Atom *proto = 0;
int num_return = 0;
FbAtoms *fbatoms = FbAtoms::instance();
if (XGetWMProtocols(disp, w, &proto, &num_return)) {
for (int i = 0; i < num_return; ++i) {
if (proto[i] == fbatoms->getFluxboxStructureMessagesAtom())
screen().addNetizen(w);
}
XFree((void *) proto);
} else {
cerr<<"Warning: Failed to read WM Protocols. "<<endl;
}
2002-12-01 13:42:15 +00:00
XWindowAttributes attrib;
2002-11-14 00:23:19 +00:00
#ifdef KDE
2002-12-01 13:42:15 +00:00
//Check and see if new client is a KDE dock applet
//If so force reasonable size
bool iskdedockapp = false;
2002-12-01 13:42:15 +00:00
Atom ajunk;
int ijunk;
unsigned long *data = 0, uljunk;
2002-12-01 13:42:15 +00:00
// Check if KDE v2.x dock applet
if (XGetWindowProperty(disp, w,
2003-05-11 17:42:51 +00:00
m_kwm2_dockwindow, 0l, 1l, False,
m_kwm2_dockwindow,
2002-12-01 13:42:15 +00:00
&ajunk, &ijunk, &uljunk, &uljunk,
2003-06-22 12:31:37 +00:00
(unsigned char **) &data) == Success && data) {
2002-12-01 13:42:15 +00:00
iskdedockapp = (data && data[0] != 0);
2003-06-27 15:05:19 +00:00
XFree((void *) data);
2003-06-22 12:31:37 +00:00
data = 0;
2002-12-01 13:42:15 +00:00
}
// Check if KDE v1.x dock applet
if (!iskdedockapp) {
if (XGetWindowProperty(disp, w,
2003-05-11 17:42:51 +00:00
m_kwm1_dockwindow, 0l, 1l, False,
m_kwm1_dockwindow,
2002-12-01 13:42:15 +00:00
&ajunk, &ijunk, &uljunk, &uljunk,
2003-06-22 12:31:37 +00:00
(unsigned char **) &data) == Success && data) {
2002-12-01 13:42:15 +00:00
iskdedockapp = (data && data[0] != 0);
2003-06-27 15:05:19 +00:00
XFree((void *) data);
2003-06-22 12:31:37 +00:00
data = 0;
2002-12-01 13:42:15 +00:00
}
}
if (iskdedockapp)
client->resize(24, 24);
2002-12-01 13:42:15 +00:00
else
2002-11-14 00:23:19 +00:00
#endif // KDE
{
if (XGetWindowAttributes(disp, client->window(), &attrib)) {
client->resize(attrib.width, attrib.height);
} else { // set default size if we failed to get window attributes
client->resize(64, 64);
2002-12-01 13:42:15 +00:00
}
}
2001-12-11 20:47:02 +00:00
// disable border for client window
XSetWindowBorderWidth(disp, client->window(), 0);
2001-12-11 20:47:02 +00:00
// disable events to frame.window
frame.window.setEventMask(NoEventMask);
client->disableEvents();
2003-06-05 11:30:06 +00:00
2001-12-11 20:47:02 +00:00
XReparentWindow(disp, client->window(), frame.window.window(), 0, 0);
XMapRaised(disp, client->window());
XChangeSaveSet(disp, client->window(), SetModeInsert);
// reactivate events for frame.window
2003-05-17 11:00:50 +00:00
frame.window.setEventMask(s_eventmask);
// setup event for slit client window
client->enableEvents();
2003-06-05 11:30:06 +00:00
// flush events
2002-12-01 13:42:15 +00:00
XFlush(disp);
// add slit client to eventmanager
FbTk::EventManager::instance()->add(*this, client->clientWindow());
FbTk::EventManager::instance()->add(*this, client->iconWindow());
2001-12-11 20:47:02 +00:00
frame.window.show();
2003-05-13 21:12:18 +00:00
clearWindow();
2002-12-01 13:42:15 +00:00
reconfigure();
2002-05-29 06:21:59 +00:00
updateClientmenu();
2002-12-01 13:42:15 +00:00
saveClientList();
2001-12-11 20:47:02 +00:00
}
void Slit::setDirection(Direction dir) {
*m_rc_direction = dir;
reconfigure();
}
void Slit::setPlacement(Placement place) {
*m_rc_placement = place;
reconfigure();
}
2001-12-11 20:47:02 +00:00
2002-05-29 06:21:59 +00:00
void Slit::removeClient(SlitClient *client, bool remap, bool destroy) {
2003-06-22 12:31:37 +00:00
if (client == 0)
return;
#ifdef DEBUG
cerr<<"Slit::removeClient( client->client_window = 0x"<<hex<<client->clientWindow()<<
", client->icon_window)"<<endl;
#endif // DEBUG
2003-06-22 12:31:37 +00:00
// remove from event manager
if (client->clientWindow() != 0)
FbTk::EventManager::instance()->remove(client->clientWindow());
if (client->iconWindow() != 0)
FbTk::EventManager::instance()->remove(client->iconWindow());
2002-12-01 13:42:15 +00:00
// Destructive removal?
if (destroy)
2003-05-11 17:42:51 +00:00
m_client_list.remove(client);
2002-12-01 13:42:15 +00:00
else // Clear the window info, but keep around to help future sorting?
client->initialize();
screen().removeNetizen(client->window());
2002-12-01 13:42:15 +00:00
if (remap && client->window() != 0) {
Display *disp = FbTk::App::instance()->display();
if (!client->visible())
client->show();
client->disableEvents();
// stop events to frame.window temporarly
frame.window.setEventMask(NoEventMask);
XReparentWindow(disp, client->window(), screen().rootWindow().window(),
client->x(), client->y());
XChangeSaveSet(disp, client->window(), SetModeDelete);
// reactivate events to frame.window
2003-05-17 11:00:50 +00:00
frame.window.setEventMask(s_eventmask);
2002-12-01 13:42:15 +00:00
XFlush(disp);
}
// Destructive removal?
if (destroy)
delete client;
2003-02-17 12:53:21 +00:00
updateClientmenu();
2001-12-11 20:47:02 +00:00
}
2002-02-04 22:33:09 +00:00
void Slit::removeClient(Window w, bool remap) {
2003-06-05 11:30:06 +00:00
#ifdef DEBUG
cerr<<"Slit::removeClient(Window w = 0x"<<hex<<w<<dec<<", remap = "<<remap<<")"<<endl;
#endif // DEBUG
if (w == frame.window)
return;
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
bool reconf = false;
2001-12-11 20:47:02 +00:00
2003-05-11 17:42:51 +00:00
SlitClients::iterator it = m_client_list.begin();
SlitClients::iterator it_end = m_client_list.end();
2002-12-01 13:42:15 +00:00
for (; it != it_end; ++it) {
if ((*it)->window() == w) {
2002-12-01 13:42:15 +00:00
removeClient((*it), remap, false);
reconf = true;
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
break;
}
}
if (reconf)
reconfigure();
2001-12-11 20:47:02 +00:00
}
2002-11-14 00:23:19 +00:00
void Slit::reconfigure() {
2002-12-01 13:42:15 +00:00
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;
const int bevel_width = theme().bevelWidth();
// determine width or height increase
bool height_inc = false;
switch (direction()) {
case VERTICAL:
height_inc = true;
break;
case HORIZONTAL: // already false
break;
}
2002-12-01 13:42:15 +00:00
SlitClients::iterator client_it = m_client_list.begin();
SlitClients::iterator client_it_end = m_client_list.end();
for (; client_it != client_it_end; ++client_it) {
// client created window?
if ((*client_it)->window() != None && (*client_it)->visible()) {
num_windows++;
if (height_inc) {
// increase height of slit for each client (VERTICAL mode)
frame.height += (*client_it)->height() + bevel_width;
// the slit should always have the width of the largest client
if (frame.width < (*client_it)->width())
frame.width = (*client_it)->width();
} else {
// increase width of slit for each client (HORIZONTAL mode)
frame.width += (*client_it)->width() + bevel_width;
// the slit should always have the width of the largest client
if (frame.height < (*client_it)->height())
frame.height = (*client_it)->height();
2002-12-01 13:42:15 +00:00
}
}
2003-05-04 20:50:15 +00:00
}
2002-12-01 13:42:15 +00:00
2003-06-05 11:30:06 +00:00
if (frame.width < 1)
frame.width = 1;
else
frame.width += bevel_width;
2002-12-01 13:42:15 +00:00
2003-06-05 11:30:06 +00:00
if (frame.height < 1)
frame.height = 1;
else
frame.height += bevel_width*2;
2002-12-01 13:42:15 +00:00
reposition();
Display *disp = FbTk::App::instance()->display();
2002-12-01 13:42:15 +00:00
frame.window.setBorderWidth(theme().borderWidth());
frame.window.setBorderColor(theme().borderColor());
2003-05-11 17:42:51 +00:00
// did we actually use slit slots
2002-12-01 13:42:15 +00:00
if (num_windows == 0)
frame.window.hide();
2002-12-01 13:42:15 +00:00
else
frame.window.show();
2002-12-01 13:42:15 +00:00
Pixmap tmp = frame.pixmap;
2003-05-15 23:30:07 +00:00
FbTk::ImageControl &image_ctrl = screen().imageControl();
2003-04-25 10:46:07 +00:00
const FbTk::Texture &texture = m_slit_theme->texture();
2003-05-13 13:28:28 +00:00
if (texture.type() == (FbTk::Texture::FLAT | FbTk::Texture::SOLID) &&
texture.pixmap().drawable() == 0) {
2002-12-01 13:42:15 +00:00
frame.pixmap = None;
frame.window.setBackgroundColor(texture.color());
2002-12-01 13:42:15 +00:00
} else {
2003-05-15 23:30:07 +00:00
frame.pixmap = image_ctrl.renderImage(frame.width, frame.height,
texture);
2003-05-13 13:28:28 +00:00
if (frame.pixmap == 0)
frame.window.setBackgroundColor(texture.color());
else
frame.window.setBackgroundPixmap(frame.pixmap);
2002-12-01 13:42:15 +00:00
}
if (tmp)
2003-05-15 23:30:07 +00:00
image_ctrl.removeImage(tmp);
2003-06-24 13:48:34 +00:00
if (m_transp.get()) {
if (frame.pixmap == 0)
m_transp->setDest(frame.window.drawable(), frame.window.screenNumber());
else
m_transp->setDest(frame.pixmap, frame.window.screenNumber());
m_transp->setAlpha(*m_rc_alpha);
}
2003-05-13 21:12:18 +00:00
clearWindow();
2002-12-01 13:42:15 +00:00
int x = 0, y = 0;
height_inc = false;
switch (direction()) {
2002-12-01 13:42:15 +00:00
case VERTICAL:
x = 0;
2003-04-25 10:46:07 +00:00
y = bevel_width;
height_inc = true;
2002-12-01 13:42:15 +00:00
break;
case HORIZONTAL:
2003-04-25 10:46:07 +00:00
x = bevel_width;
2002-12-01 13:42:15 +00:00
y = 0;
break;
}
2002-12-01 13:42:15 +00:00
client_it = m_client_list.begin();
for (; client_it != client_it_end; ++client_it) {
if ((*client_it)->window() == None)
continue;
//client created window?
if ((*client_it)->visible())
(*client_it)->show();
else {
(*client_it)->disableEvents();
(*client_it)->hide();
(*client_it)->enableEvents();
continue;
}
2003-06-22 12:31:37 +00:00
if (height_inc)
x = (frame.width - (*client_it)->width()) / 2;
else
y = (frame.height - (*client_it)->height()) / 2;
XMoveResizeWindow(disp, (*client_it)->window(), x, y,
(*client_it)->width(), (*client_it)->height());
2002-12-01 13:42:15 +00:00
// for ICCCM compliance
(*client_it)->move(x, y);
2002-12-01 13:42:15 +00:00
XEvent event;
event.type = ConfigureNotify;
2002-12-01 13:42:15 +00:00
event.xconfigure.display = disp;
event.xconfigure.event = (*client_it)->window();
event.xconfigure.window = (*client_it)->window();
event.xconfigure.x = (*client_it)->x();
event.xconfigure.y = (*client_it)->y();
event.xconfigure.width = (*client_it)->width();
event.xconfigure.height = (*client_it)->height();
event.xconfigure.border_width = 0;
event.xconfigure.above = frame.window.window();
event.xconfigure.override_redirect = False;
2002-12-01 13:42:15 +00:00
XSendEvent(disp, (*client_it)->window(), False, StructureNotifyMask,
&event);
2002-12-01 13:42:15 +00:00
if (height_inc)
y += (*client_it)->height() + bevel_width;
else
x += (*client_it)->width() + bevel_width;
} // end for
2002-12-01 13:42:15 +00:00
2003-05-11 17:42:51 +00:00
if (doAutoHide() && !isHidden() && !m_timer.isTiming())
m_timer.start();
2003-05-01 15:03:36 +00:00
2003-05-11 17:42:51 +00:00
m_slitmenu.reconfigure();
updateClientmenu();
2003-06-18 13:55:17 +00:00
updateStrut();
2003-06-22 12:31:37 +00:00
2001-12-11 20:47:02 +00:00
}
2002-08-14 21:51:07 +00:00
void Slit::reposition() {
2002-12-01 13:42:15 +00:00
int head_x = 0,
head_y = 0,
head_w,
head_h;
if (screen().hasXinerama()) {
int head = *m_rc_on_head;
head_x = screen().getHeadX(head);
head_y = screen().getHeadY(head);
head_w = screen().getHeadWidth(head);
head_h = screen().getHeadHeight(head);
2003-05-19 15:32:47 +00:00
} else {
head_w = screen().width();
head_h = screen().height();
}
int border_width = theme().borderWidth();
int bevel_width = theme().bevelWidth();
// make sure at leaste one pixel is visible
if (border_width >= bevel_width)
bevel_width = border_width + 1;
2002-12-01 13:42:15 +00:00
// place the slit in the appropriate place
switch (placement()) {
2002-12-01 13:42:15 +00:00
case TOPLEFT:
frame.x = head_x;
frame.y = head_y;
if (direction() == VERTICAL) {
2003-04-25 10:46:07 +00:00
frame.x_hidden = bevel_width -
border_width - frame.width;
2002-12-01 13:42:15 +00:00
frame.y_hidden = head_y;
} else {
frame.x_hidden = head_x;
2003-04-25 10:46:07 +00:00
frame.y_hidden = bevel_width -
border_width - frame.height;
2002-12-01 13:42:15 +00:00
}
break;
case CENTERLEFT:
frame.x = head_x;
frame.y = head_y + (head_h - frame.height) / 2;
2003-04-25 10:46:07 +00:00
frame.x_hidden = head_x + bevel_width -
border_width - frame.width;
2002-12-01 13:42:15 +00:00
frame.y_hidden = frame.y;
break;
case BOTTOMLEFT:
frame.x = head_x;
2003-04-25 10:46:07 +00:00
frame.y = head_h - frame.height - border_width*2;
if (direction() == VERTICAL) {
2003-04-25 10:46:07 +00:00
frame.x_hidden = head_x + bevel_width -
border_width - frame.width;
2002-12-01 13:42:15 +00:00
frame.y_hidden = frame.y;
} else {
frame.x_hidden = head_x;
frame.y_hidden = head_y + head_h -
2003-04-25 10:46:07 +00:00
bevel_width - border_width;
2002-12-01 13:42:15 +00:00
}
break;
case TOPCENTER:
frame.x = head_x + ((head_w - frame.width) / 2);
frame.y = head_y;
frame.x_hidden = frame.x;
2003-04-25 10:46:07 +00:00
frame.y_hidden = head_y + bevel_width -
border_width - frame.height;
2002-12-01 13:42:15 +00:00
break;
case BOTTOMCENTER:
frame.x = head_x + ((head_w - frame.width) / 2);
2003-04-25 10:46:07 +00:00
frame.y = head_y + head_h - frame.height - border_width*2;
2002-12-01 13:42:15 +00:00
frame.x_hidden = frame.x;
frame.y_hidden = head_y + head_h -
2003-04-25 10:46:07 +00:00
bevel_width - border_width;
2002-12-01 13:42:15 +00:00
break;
case TOPRIGHT:
2003-04-25 10:46:07 +00:00
frame.x = head_x + head_w - frame.width - border_width*2;
2002-12-01 13:42:15 +00:00
frame.y = head_y;
if (direction() == VERTICAL) {
2002-12-01 13:42:15 +00:00
frame.x_hidden = head_x + head_w -
2003-04-25 10:46:07 +00:00
bevel_width - border_width;
2002-12-01 13:42:15 +00:00
frame.y_hidden = head_y;
} else {
frame.x_hidden = frame.x;
2003-04-25 10:46:07 +00:00
frame.y_hidden = head_y + bevel_width -
border_width - frame.height;
2002-12-01 13:42:15 +00:00
}
break;
case CENTERRIGHT:
default:
2003-04-25 10:46:07 +00:00
frame.x = head_x + head_w - frame.width - border_width*2;
2002-12-01 13:42:15 +00:00
frame.y = head_y + ((head_h - frame.height) / 2);
frame.x_hidden = head_x + head_w -
2003-04-25 10:46:07 +00:00
bevel_width - border_width;
2002-12-01 13:42:15 +00:00
frame.y_hidden = frame.y;
break;
case BOTTOMRIGHT:
2003-04-25 10:46:07 +00:00
frame.x = head_x + head_w - frame.width - border_width*2;
frame.y = head_y + head_h - frame.height - border_width*2;
if (direction() == VERTICAL) {
2002-12-01 13:42:15 +00:00
frame.x_hidden = head_x + head_w -
2003-04-25 10:46:07 +00:00
bevel_width - border_width;
2002-12-01 13:42:15 +00:00
frame.y_hidden = frame.y;
} else {
frame.x_hidden = frame.x;
frame.y_hidden = head_y + head_h -
2003-04-25 10:46:07 +00:00
bevel_width - border_width;
2002-12-01 13:42:15 +00:00
}
break;
}
2003-05-11 17:42:51 +00:00
if (isHidden()) {
2003-05-13 13:28:28 +00:00
frame.window.moveResize(frame.x_hidden, frame.y_hidden,
frame.width, frame.height);
2002-12-01 13:42:15 +00:00
} else {
2003-05-13 13:28:28 +00:00
frame.window.moveResize(frame.x, frame.y,
frame.width, frame.height);
2002-12-01 13:42:15 +00:00
}
2003-06-22 12:31:37 +00:00
2001-12-11 20:47:02 +00:00
}
2002-08-14 21:51:07 +00:00
void Slit::shutdown() {
2002-12-01 13:42:15 +00:00
saveClientList();
2003-05-11 17:42:51 +00:00
while (!m_client_list.empty())
removeClient(m_client_list.front(), true, true);
2001-12-11 20:47:02 +00:00
}
void Slit::cycleClientsUp() {
2003-05-11 17:42:51 +00:00
if (m_client_list.size() < 2)
2003-01-12 23:52:37 +00:00
return;
// rotate client list up, ie the first goes last
2003-05-11 17:42:51 +00:00
SlitClients::iterator it = m_client_list.begin();
SlitClient *client = *it;
2003-05-11 17:42:51 +00:00
m_client_list.erase(it);
m_client_list.push_back(client);
reconfigure();
}
void Slit::cycleClientsDown() {
2003-05-11 17:42:51 +00:00
if (m_client_list.size() < 2)
2003-01-12 23:52:37 +00:00
return;
// rotate client list down, ie the last goes first
2003-05-11 17:42:51 +00:00
SlitClient *client = m_client_list.back();
m_client_list.remove(client);
m_client_list.push_front(client);
reconfigure();
}
void Slit::handleEvent(XEvent &event) {
if (event.type == ConfigureRequest) {
configureRequestEvent(event.xconfigurerequest);
} else if (event.type == DestroyNotify) {
removeClient(event.xdestroywindow.window, false);
} else if (event.type == UnmapNotify) {
2003-06-05 11:30:06 +00:00
removeClient(event.xunmap.window);
} else if (event.type == MapRequest) {
#ifdef KDE
//Check and see if client is KDE dock applet.
//If so add to Slit
bool iskdedockapp = false;
Atom ajunk;
int ijunk;
unsigned long *data = (unsigned long *) 0, uljunk;
Display *disp = FbTk::App::instance()->display();
// Check if KDE v2.x dock applet
if (XGetWindowProperty(disp, event.xmaprequest.window,
2003-05-11 19:01:09 +00:00
m_kwm2_dockwindow, 0l, 1l, False,
XA_WINDOW, &ajunk, &ijunk, &uljunk,
&uljunk, (unsigned char **) &data) == Success) {
if (data)
iskdedockapp = True;
2003-06-27 15:05:19 +00:00
XFree((void *) data);
2003-06-22 12:31:37 +00:00
data = 0;
}
// Check if KDE v1.x dock applet
if (!iskdedockapp) {
if (XGetWindowProperty(disp, event.xmaprequest.window,
2003-05-11 19:01:09 +00:00
m_kwm1_dockwindow, 0l, 1l, False,
m_kwm1_dockwindow, &ajunk, &ijunk, &uljunk,
2003-06-22 12:31:37 +00:00
&uljunk, (unsigned char **) &data) == Success && data) {
iskdedockapp = (data && data[0] != 0);
2003-06-27 15:05:19 +00:00
XFree((void *) data);
2003-06-22 12:31:37 +00:00
data = 0;
}
}
2001-12-11 20:47:02 +00:00
if (iskdedockapp) {
XSelectInput(disp, event.xmaprequest.window, StructureNotifyMask);
addClient(event.xmaprequest.window);
}
#endif //KDE
}
}
void Slit::buttonPressEvent(XButtonEvent &e) {
if (e.window != frame.window.window())
2002-12-01 13:42:15 +00:00
return;
if (e.button == Button3) {
2003-05-11 17:42:51 +00:00
if (! m_slitmenu.isVisible()) {
int x = e.x_root - (m_slitmenu.width() / 2),
y = e.y_root - (m_slitmenu.height() / 2);
2002-12-01 13:42:15 +00:00
if (x < 0)
x = 0;
2003-05-15 12:00:46 +00:00
else if (x + m_slitmenu.width() > screen().width())
x = screen().width() - m_slitmenu.width();
2002-12-01 13:42:15 +00:00
if (y < 0)
y = 0;
2003-05-15 12:00:46 +00:00
else if (y + m_slitmenu.height() > screen().height())
y = screen().height() - m_slitmenu.height();
2002-12-01 13:42:15 +00:00
2003-05-11 17:42:51 +00:00
m_slitmenu.move(x, y);
m_slitmenu.show();
2002-12-01 13:42:15 +00:00
} else
2003-05-11 17:42:51 +00:00
m_slitmenu.hide();
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
}
void Slit::enterNotifyEvent(XCrossingEvent &) {
2003-05-11 17:42:51 +00:00
if (! doAutoHide())
2002-12-01 13:42:15 +00:00
return;
2003-05-11 17:42:51 +00:00
if (isHidden()) {
if (! m_timer.isTiming())
m_timer.start();
2002-12-01 13:42:15 +00:00
} else {
2003-05-11 17:42:51 +00:00
if (m_timer.isTiming())
m_timer.stop();
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
}
void Slit::leaveNotifyEvent(XCrossingEvent &ev) {
2003-05-11 17:42:51 +00:00
if (! doAutoHide())
2002-12-01 13:42:15 +00:00
return;
2003-05-11 17:42:51 +00:00
if (isHidden()) {
if (m_timer.isTiming())
m_timer.stop();
2003-05-01 15:03:36 +00:00
} else {
2003-05-11 17:42:51 +00:00
if (! m_timer.isTiming()) {
2003-05-01 15:35:24 +00:00
// the menu is open, keep it firing until it closes
2003-05-11 17:42:51 +00:00
if (m_slitmenu.isVisible())
m_timer.fireOnce(false);
m_timer.start();
2003-05-01 15:35:24 +00:00
}
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
}
2001-12-11 20:47:02 +00:00
2002-11-14 00:23:19 +00:00
void Slit::configureRequestEvent(XConfigureRequestEvent &event) {
2002-12-01 13:42:15 +00:00
bool reconf = false;
XWindowChanges xwc;
2002-11-14 00:23:19 +00:00
xwc.x = event.x;
xwc.y = event.y;
xwc.width = event.width;
xwc.height = event.height;
2002-12-01 13:42:15 +00:00
xwc.border_width = 0;
xwc.sibling = event.above;
xwc.stack_mode = event.detail;
2002-11-14 00:23:19 +00:00
XConfigureWindow(FbTk::App::instance()->display(),
event.window, event.value_mask, &xwc);
2002-11-14 00:23:19 +00:00
2003-05-11 17:42:51 +00:00
SlitClients::iterator it = m_client_list.begin();
SlitClients::iterator it_end = m_client_list.end();
2002-12-01 13:42:15 +00:00
for (; it != it_end; ++it) {
if ((*it)->window() == event.window) {
if ((*it)->width() != ((unsigned) event.width) ||
(*it)->height() != ((unsigned) event.height)) {
(*it)->resize(event.width, event.height);;
2002-11-14 00:23:19 +00:00
2002-12-01 13:42:15 +00:00
reconf = true; //requires reconfiguration
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
break;
}
}
}
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
if (reconf)
reconfigure();
2001-12-11 20:47:02 +00:00
}
2003-05-13 13:28:28 +00:00
void Slit::exposeEvent(XExposeEvent &ev) {
2003-06-24 13:48:34 +00:00
// we don't need to clear the entire window
// just the are that gets exposed
frame.window.clearArea(ev.x, ev.y, ev.width, ev.height);
if (m_transp.get()) {
2003-06-24 20:19:36 +00:00
if ((int)m_transp->alpha() != *m_rc_alpha)
m_transp->setAlpha(*m_rc_alpha);
2003-06-24 13:48:34 +00:00
if (screen().rootPixmap() != m_transp->source())
m_transp->setSource(screen().rootPixmap(), screen().screenNumber());
m_transp->render(frame.window.x() + ev.x, frame.window.y() + ev.y,
ev.x, ev.y,
ev.width, ev.height);
}
2003-05-13 21:12:18 +00:00
}
void Slit::clearWindow() {
2003-05-07 22:53:21 +00:00
frame.window.clear();
2003-06-24 13:48:34 +00:00
if (m_transp.get()) {
2003-06-24 20:19:36 +00:00
if ((int)m_transp->alpha() != *m_rc_alpha)
m_transp->setAlpha(*m_rc_alpha);
2003-05-13 21:12:18 +00:00
if (screen().rootPixmap() != m_transp->source())
2003-05-15 12:00:46 +00:00
m_transp->setSource(screen().rootPixmap(), screen().screenNumber());
2003-05-13 21:12:18 +00:00
m_transp->render(frame.window.x(), frame.window.y(),
0, 0,
frame.window.width(), frame.window.height());
}
2003-05-07 22:53:21 +00:00
}
2001-12-11 20:47:02 +00:00
2002-08-14 21:51:07 +00:00
void Slit::timeout() {
2003-05-11 17:42:51 +00:00
if (doAutoHide()) {
if (!m_slitmenu.isVisible()) {
m_timer.fireOnce(true);
2003-05-01 15:35:24 +00:00
} else
return;
2003-05-01 15:03:36 +00:00
} else
2003-05-11 17:42:51 +00:00
if (!isHidden()) return;
2003-05-01 15:35:24 +00:00
2003-05-11 17:42:51 +00:00
m_hidden = ! m_hidden; // toggle hidden state
if (isHidden())
frame.window.move(frame.x_hidden, frame.y_hidden);
2002-12-01 13:42:15 +00:00
else
frame.window.move(frame.x, frame.y);
2001-12-11 20:47:02 +00:00
}
void Slit::loadClientList(const char *filename) {
if (filename == 0)
return;
m_filename = filename; // save filename so we can save client list later
2002-12-01 13:42:15 +00:00
struct stat buf;
if (!stat(filename, &buf)) {
std::ifstream file(filename);
2002-12-01 13:42:15 +00:00
std::string name;
while (! file.eof()) {
name = "";
std::getline(file, name); // get the entire line
if (name.size() > 0) { // don't add client unless we have a valid line
2002-12-01 13:42:15 +00:00
SlitClient *client = new SlitClient(name.c_str());
2003-05-11 17:42:51 +00:00
m_client_list.push_back(client);
2002-12-01 13:42:15 +00:00
}
}
}
2002-05-29 06:21:59 +00:00
}
void Slit::updateClientmenu() {
// clear old items
2003-05-11 17:42:51 +00:00
m_clientlist_menu.removeAll();
m_clientlist_menu.setLabel("Clients");
FbTk::RefCount<FbTk::Command> cycle_up(new FbTk::SimpleCommand<Slit>(*this, &Slit::cycleClientsUp));
FbTk::RefCount<FbTk::Command> cycle_down(new FbTk::SimpleCommand<Slit>(*this, &Slit::cycleClientsDown));
2003-05-11 17:42:51 +00:00
m_clientlist_menu.insert("Cycle Up", cycle_up);
m_clientlist_menu.insert("Cycle Down", cycle_down);
FbTk::MenuItem *separator = new FbTk::MenuItem("-------");
separator->setEnabled(false);
2003-05-11 17:42:51 +00:00
m_clientlist_menu.insert(separator);
FbTk::RefCount<FbTk::Command> reconfig(new FbTk::SimpleCommand<Slit>(*this, &Slit::reconfigure));
2003-05-11 17:42:51 +00:00
SlitClients::iterator it = m_client_list.begin();
for (; it != m_client_list.end(); ++it) {
if ((*it) != 0 && (*it)->window() != 0)
2003-05-11 17:42:51 +00:00
m_clientlist_menu.insert(new SlitClientMenuItem(*(*it), reconfig));
}
2003-05-11 17:42:51 +00:00
m_clientlist_menu.update();
}
2002-11-14 00:23:19 +00:00
void Slit::saveClientList() {
std::ofstream file(m_filename.c_str());
2003-05-11 17:42:51 +00:00
SlitClients::iterator it = m_client_list.begin();
SlitClients::iterator it_end = m_client_list.end();
2002-12-01 13:42:15 +00:00
std::string prevName;
std::string name;
for (; it != it_end; ++it) {
name = (*it)->matchName();
2002-12-01 13:42:15 +00:00
if (name != prevName)
file << name.c_str() << std::endl;
prevName = name;
}
2002-05-29 06:21:59 +00:00
}
2002-11-14 00:23:19 +00:00
void Slit::setAutoHide(bool val) {
*m_rc_auto_hide = val;
2003-05-11 17:42:51 +00:00
if (doAutoHide()) {
if (! m_timer.isTiming()) {
if (m_slitmenu.isVisible())
m_timer.fireOnce(false);
m_timer.start();
2003-05-01 15:35:24 +00:00
}
2003-05-11 17:42:51 +00:00
}
2002-11-14 00:23:19 +00:00
}
void Slit::setupMenu() {
2002-12-01 13:42:15 +00:00
I18n *i18n = I18n::instance();
using namespace FBNLS;
using namespace FbTk;
FbTk::MacroCommand *s_a_reconf_macro = new FbTk::MacroCommand();
2003-05-13 21:12:18 +00:00
FbTk::MacroCommand *s_a_reconf_slit_macro = new FbTk::MacroCommand();
FbTk::RefCount<FbTk::Command> saverc_cmd(new FbCommands::SaveResources());
FbTk::RefCount<FbTk::Command> reconf_cmd(new FbCommands::ReconfigureFluxboxCmd());
2003-05-13 21:12:18 +00:00
FbTk::RefCount<FbTk::Command> reconf_slit_cmd(new FbTk::SimpleCommand<Slit>(*this, &Slit::reconfigure));
s_a_reconf_macro->add(saverc_cmd);
s_a_reconf_macro->add(reconf_cmd);
2003-05-13 21:12:18 +00:00
s_a_reconf_slit_macro->add(saverc_cmd);
s_a_reconf_slit_macro->add(reconf_slit_cmd);
FbTk::RefCount<FbTk::Command> save_and_reconfigure(s_a_reconf_macro);
2003-05-13 21:12:18 +00:00
FbTk::RefCount<FbTk::Command> save_and_reconfigure_slit(s_a_reconf_slit_macro);
// setup base menu
2003-05-11 17:42:51 +00:00
m_slitmenu.setLabel("Slit");
2003-06-22 12:31:37 +00:00
m_slitmenu.insert(i18n->getMessage(CommonSet, CommonPlacementTitle,
2003-05-11 17:42:51 +00:00
"Placement"),
&m_placement_menu);
m_slitmenu.insert("Layer...", m_layermenu.get());
#ifdef XINERAMA
if (screen().hasXinerama()) {
m_slitmenu.insert("On Head...", new XineramaHeadMenu<Slit>(
2003-06-22 12:31:37 +00:00
*screen().menuTheme(),
screen(),
screen().imageControl(),
*screen().layerManager().getLayer(Fluxbox::instance()->getMenuLayer()),
this
));
}
#endif //XINERAMA
2003-06-22 12:31:37 +00:00
m_slitmenu.insert(new BoolMenuItem(i18n->getMessage(CommonSet, CommonAutoHide,
2003-05-11 17:42:51 +00:00
"Auto hide"),
*m_rc_auto_hide,
2003-05-13 21:12:18 +00:00
save_and_reconfigure_slit));
2003-06-22 12:31:37 +00:00
m_slitmenu.insert(new BoolMenuItem("Maximize Over",
*m_rc_maximize_over,
save_and_reconfigure_slit));
2003-06-24 13:48:34 +00:00
// this saves resources and clears the slit window to update alpha value
2003-05-13 21:12:18 +00:00
FbTk::MenuItem *alpha_menuitem = new IntResMenuItem("Alpha",
m_rc_alpha,
2003-05-13 21:12:18 +00:00
0, 255);
2003-06-24 20:19:36 +00:00
// setup command for alpha value
MacroCommand *alpha_macrocmd = new MacroCommand();
RefCount<Command> clear_cmd(new SimpleCommand<Slit>(*this, &Slit::clearWindow));
alpha_macrocmd->add(saverc_cmd);
alpha_macrocmd->add(clear_cmd);
RefCount<Command> set_alpha_cmd(alpha_macrocmd);
2003-06-24 13:48:34 +00:00
alpha_menuitem->setCommand(set_alpha_cmd);
2003-06-24 20:19:36 +00:00
2003-05-13 21:12:18 +00:00
m_slitmenu.insert(alpha_menuitem);
2003-05-11 17:42:51 +00:00
2003-06-22 12:31:37 +00:00
m_slitmenu.insert(new SlitDirMenuItem(i18n->getMessage(SlitSet, SlitSlitDirection,
2003-05-11 17:42:51 +00:00
"Slit Direction"),
*this,
save_and_reconfigure));
m_slitmenu.insert("Clients", &m_clientlist_menu);
m_slitmenu.update();
// setup sub menu
2003-06-22 12:31:37 +00:00
m_placement_menu.setLabel(i18n->getMessage(SlitSet, SlitSlitPlacement,
"Slit Placement"));
2003-05-11 17:42:51 +00:00
m_placement_menu.setMinimumSublevels(3);
2003-05-24 13:13:22 +00:00
m_layermenu->setInternalMenu();
m_clientlist_menu.setInternalMenu();
// setup items in sub menu
struct {
int set;
int base;
const char *default_str;
Placement slit_placement;
} place_menu[] = {
{CommonSet, CommonPlacementTopLeft, "Top Left", Slit::TOPLEFT},
{CommonSet, CommonPlacementCenterLeft, "Center Left", Slit::CENTERLEFT},
{CommonSet, CommonPlacementBottomLeft, "Bottom Left", Slit::BOTTOMLEFT},
{CommonSet, CommonPlacementTopCenter, "Top Center", Slit::TOPCENTER},
{0, 0, 0, Slit::TOPLEFT}, // middle item, empty
{CommonSet, CommonPlacementBottomCenter, "Bottom Center", Slit::BOTTOMCENTER},
{CommonSet, CommonPlacementTopRight, "Top Right", Slit::TOPRIGHT},
{CommonSet, CommonPlacementCenterRight, "Center Right", Slit::CENTERRIGHT},
{CommonSet, CommonPlacementBottomRight, "Bottom Right", Slit::BOTTOMRIGHT}
};
// create items in sub menu
for (size_t i=0; i<9; ++i) {
if (place_menu[i].default_str == 0) {
2003-05-11 17:42:51 +00:00
m_placement_menu.insert("");
2002-12-01 13:42:15 +00:00
} else {
const char *i18n_str = i18n->getMessage(place_menu[i].set,
place_menu[i].base,
place_menu[i].default_str);
2003-05-11 17:42:51 +00:00
m_placement_menu.insert(new PlaceSlitMenuItem(i18n_str, *this,
2003-06-24 13:48:34 +00:00
place_menu[i].slit_placement,
save_and_reconfigure));
2002-12-01 13:42:15 +00:00
}
}
// finaly update sub menu
2003-05-11 17:42:51 +00:00
m_placement_menu.update();
2001-12-11 20:47:02 +00:00
}
void Slit::moveToLayer(int layernum) {
m_layeritem->moveToLayer(layernum);
2003-07-06 07:09:53 +00:00
*m_rc_layernum = layernum;
}