src/slot.cpp

Go to the documentation of this file.
00001 // Copyright (c) 2003 - 2004 Anselm R. Garbe <anselmg at t-online.de>
00002 // See ../LICENSE.txt for license details.
00003 //
00004 // $Id: slot.cpp 2 2007-05-16 10:38:27Z eg $
00005 
00006 #include "slot.h"
00007 
00008 #ifdef SLOT_SUPPORT
00009 
00010 #include <map>
00011 #include <string>
00012 #include <sstream>
00013 
00014 #include "binder.h"
00015 #include "client.h"
00016 #include "cursors.h"
00017 #include "draw.h"
00018 #include "kernel.h"
00019 #include "label.h"
00020 #include "logger.h"
00021 #include "monitor.h"
00022 #include "theme.h"
00023 #include "util.h"
00024 #include "workspace.h"
00025 #include "xcore.h"
00026 #include "xfont.h"
00027 
00029 Tab::Tab(const string name) {
00030     name_ = name;
00031     focused_ = 0;
00032 }
00033 
00034 Tab::~Tab() {
00035 }
00036 
00037 string Tab::name() const {
00038     return name_;
00039 }
00040 
00041 LClient *Tab::clients() {
00042     return &clients_;
00043 }
00044 
00045 void Tab::addClient(Client *client) {
00046     focused_ = client;
00047     clients_.push_back(client);
00048 }
00049 
00050 void Tab::removeClient(Client *client) {
00051     clients_.remove(client);
00052     if (focused_ == client) {
00053         if (clients_.size()) {
00054             focused_ = clients_.front();
00055         }
00056         else {
00057             focused_ = 0;
00058         }
00059     }
00060 }
00061 
00062 bool Tab::isVisible() const {
00063     return isVisible_;
00064 }
00065 
00066 void Tab::show() {
00067     isVisible_ = true;
00068     for (LClient::iterator it = clients_.begin();
00069             it != clients_.end(); it++)
00070     {
00071         Client *client = *it;
00072         client->show();
00073     }
00074 }
00075 
00076 void Tab::hide() {
00077     isVisible_ = false;
00078     for (LClient::iterator it = clients_.begin();
00079             it != clients_.end(); it++)
00080     {
00081         Client *client = *it;
00082         client->hide();
00083     }
00084 }
00085 
00086 Client *Tab::focused() const {
00087     return focused_;
00088 }
00089 
00090 void Tab::focus(Client *client) {
00091     focused_ = client;
00092 }
00093 
00095 
00096 Slot::Slot(Monitor *monitor, Rectangle *rect, Direction align)
00097     : Widget(monitor, rect),
00098       Container<Monitor, LTab, LTab::iterator, Tab>(monitor)
00099 {
00100     align_ = align;
00101     theme_ = this->monitor()->theme();
00102     isGrabFocus_ = false;
00103 
00104     isSolid_ = (Util::get(KERNEL->commonSettings(), "slot.style") == "solid");
00105     initTabs();
00106 
00107     label_ = new Label(this->monitor(), window(), Label::CENTER, gc());
00108     label_->setX(1);
00109     label_->setY(1);
00110     label_->setWidth(width() - 2);
00111     label_->setHeight(this->monitor()->titleBarHeight());
00112 }
00113 
00114 Slot::~Slot() {
00115 }
00116 
00117 void Slot::initTabs() {
00118 
00119     string tabs = Util::get(KERNEL->commonSettings(), "slot.tabs");
00120 
00121     string name = "";
00122     for (string::iterator it = tabs.begin(); it != tabs.end(); ) {
00123 
00124         char c = *it;
00125         it++;
00126         bool isEndReached = it == tabs.end();
00127 
00128         if ((c == ',') || isEndReached) {
00129             if (isEndReached) {
00130                 name += c;
00131             }
00132             if (name != "") {
00133                 attach(new Tab(name));
00134                 name = "";
00135             }
00136         }
00137         else {
00138             name += c;
00139         }
00140     }
00141 
00142     if (!size()) {
00143         attach(new Tab("default"));
00144     }
00145 }
00146 
00147 void Slot::show(string tabName) {
00148 
00149     if (isVisible()
00150         && tabName == this->tabName()
00151         && hasClients())
00152     {
00153         illuminate();
00154         return;
00155     }
00156     isVisible_ = true;
00157     for (LTab::iterator it = begin(); it != end(); it++) {
00158         Tab *tab = *it;
00159         tab->hide();
00160         if (tab->name() == tabName) {
00161             focus(tab);
00162         }
00163     }
00164     focused()->show();
00165     XCORE->show(window());
00166 }
00167 
00168 void Slot::hide() {
00169     isVisible_ = false;
00170     focused()->hide();
00171     XCORE->hide(window());
00172     monitor()->matchWorkspace(monitor()->focused(), align_);
00173 }
00174 
00175 Direction Slot::alignment() const {
00176     return align_;
00177 }
00178 
00179 void Slot::illuminate() {
00180 
00181     if (!isVisible() || width() == 1) {
00182         return;
00183     }
00184 
00185     if (isSolid_) {
00186         Rectangle rect(*this);
00187         rect.setX(0);
00188         rect.setY(0);
00189         LOGDEBUG("drawing solid background");
00190         // draw solid background
00191         XCORE->setForeground(gc(), theme_->BAR_BACKGROUND);
00192         XCORE->fillRectangle(window(), gc(), &rect);
00193         Draw::drawRectBorder(window(), gc(), &rect,
00194                              theme_->BAR_SHINE, theme_->BAR_BACKGROUND);
00195     }
00196     else {
00197         XCORE->clearWindow(window());
00198     }
00199 
00200     label_->setWidth(width() - 2);
00201     unsigned int offsetY = 1;
00202     unsigned int i = 0;
00203     for (LTab::iterator it = begin(); it != end(); it++) {
00204         Tab *tab = *it;
00205         label_->setY(offsetY + (i * label_->height()));
00206         label_->setText(tab->name());
00207         if (tab == focused()) {
00208             label_->update(theme_->LABEL_BACKGROUND_FOCUSSED,
00209                        theme_->LABEL_TEXT_FOCUSSED,
00210                        theme_->LABEL_SHINE_FOCUSSED,
00211                        theme_->LABEL_SHADOW_FOCUSSED,
00212                        true, true);
00213         }
00214         else {
00215             label_->update(theme_->LABEL_BACKGROUND_NORMAL,
00216                            theme_->LABEL_TEXT_NORMAL,
00217                            theme_->LABEL_SHINE_NORMAL,
00218                            theme_->LABEL_SHADOW_NORMAL,
00219                            true, true);
00220         }
00221         i++;
00222     }
00223 
00224     LClient *clients = focused()->clients();
00225     for (LClient::iterator it = clients->begin();
00226             it != clients->end(); it++)
00227     {
00228         Client *client = *it;
00229         Rectangle rect(*client);
00230         rect.setX(rect.x() - 1);
00231         rect.setY(rect.y() - 1);
00232         rect.setWidth(rect.width() + 2);
00233         rect.setHeight(rect.height() + 2);
00234 
00235         if (client == focused()->focused()) {
00236             Draw::drawRectBorder(window(), gc(), &rect,
00237                                  theme_->TAB_SHINE_ACTIVE_FOCUSSED,
00238                                  theme_->TAB_SHADOW_ACTIVE_FOCUSSED);
00239         }
00240         else {
00241             Draw::drawRectBorder(window(), gc(), &rect,
00242                                  theme_->TAB_SHINE_ACTIVE_NORMAL,
00243                                  theme_->TAB_SHADOW_ACTIVE_NORMAL);
00244         }
00245     }
00246 }
00247 
00248 bool Slot::hasClients() {
00249 
00250     for (LTab::iterator it = begin(); it != end(); it++) {
00251         Tab *tab = *it;
00252         if (tab->clients()->size()) {
00253             return true;
00254         }
00255     }
00256     return false;
00257 }
00258 
00259 void Slot::manage() {
00260 
00261     if (!isVisible()) {
00262         return;
00263     }
00264 
00265     static bool isSlotOverlap =
00266         Util::get(KERNEL->commonSettings(), "slot.mode") == "overlap";
00267     unsigned int cHeight = 0;
00268     unsigned int maxWidth = 1;
00269     LClient *clients = focused()->clients();
00270     if (!clients->size() && hasClients()) {
00271         maxWidth = width();
00272     }
00273     for (LClient::iterator it = clients->begin();
00274             it != clients->end(); it++)
00275     {
00276         Client *client = *it;
00277         cHeight += client->height();
00278         if (maxWidth < client->width()) {
00279             maxWidth = client->width() + 2;
00280         }
00281     }
00282 
00283     if (align_ == RIGHT) {
00284         setX(monitor()->width() - maxWidth);
00285     }
00286     setWidth(maxWidth);
00287 
00288     // apps are centered
00289     unsigned int tabPagerHeight = (size() * label_->height()) + 3;
00290     int offsetY = tabPagerHeight;
00291 
00292     for (LClient::iterator it = clients->begin();
00293             it != clients->end(); it++)
00294     {
00295         Client *client = *it;
00296         client->setY(offsetY);
00297         client->setX((width() - client->width()) / 2);
00298         client->resize();
00299         offsetY += client->height() + 2;
00300     }
00301 
00302     if (isSolid_ && !isSlotOverlap) {
00303         setHeight(monitor()->focused()->height());
00304     }
00305     else {
00306         setHeight(offsetY);
00307     }
00308     monitor()->matchWorkspace(monitor()->focused(), align_);
00309     XCORE->moveResize(window(), this);
00310     illuminate();
00311 }
00312 
00313 Tab *Slot::tabForName(string name) {
00314 
00315     for (LTab::iterator it = begin(); it != end(); it++) {
00316         Tab *tab = *it;
00317         if (tab->name() == name) {
00318             return tab;
00319         }
00320     }
00321 
00322     return 0;
00323 }
00324 
00325 void Slot::attachClient(Client *client) {
00326 
00327     if (width() < client->width()) {
00328         setWidth(client->width());
00329     }
00330 
00331     Binder::instance()->ungrabButtons(client->clientWindow());
00332     Binder::instance()->grabButtons(client->clientWindow(), AnyModifier);
00333 
00334     if (client->hooked() != "") {
00335         Tab *tab = tabForName(client->hooked());
00336         if (tab && (tab != focused())) {
00337             focused()->hide();
00338             focus(tab);
00339             tab->show();
00340         }
00341     }
00342 
00343     focused()->addClient(client);
00344     client->reparent(window(), 0, 0);
00345 
00346     if (isVisible()) {
00347         client->show();
00348     }
00349     manage();
00350 }
00351 
00352 void Slot::detachClient(Client *client) {
00353 
00354     for (LTab::iterator it = begin(); it != end(); it++) {
00355         Tab *tab = *it;
00356         LClient *clients = tab->clients();
00357         bool found = false;
00358         for (LClient::iterator cit = clients->begin();
00359              cit != clients->end(); cit++)
00360         {
00361             found = (client == *cit);
00362             if (found) {
00363                 break;
00364             }
00365         }
00366         if (found) {
00367             tab->removeClient(client);
00368             break;
00369         }
00370     }
00371     if (!client->isDestroyed()) {
00372         if (client->isVisible()) {
00373             client->hide();
00374         }
00375         client->reparent(monitor()->rootWindow(), 0, 0);
00376     }
00377     manage();
00378 }
00379 
00380 void Slot::handleButtonPress(XButtonEvent *event) {
00381 
00382     if (event->button == Button1) {
00383         unsigned int tabPagerHeight = (size() * label_->height()) + 3;
00384 
00385         XCORE->raise(window());
00386         if (event->y < (int)tabPagerHeight) {
00387             unsigned int selTab = event->y / label_->height();
00388             ostringstream oss;
00389             oss << "select tab #" << selTab << " of " << size() << " tabs ";
00390             LOGDEBUG(oss.str());
00391             unsigned int i = 0;
00392             for (LTab::iterator it = begin(); it != end(); it++) {
00393                 if (selTab == i) {
00394                     if (focused() != *it) {
00395                         focused()->hide();
00396                         focus(*it);
00397                         focused()->show();
00398                         manage();
00399                     }
00400                     return;
00401                 }
00402                 i++;
00403             }
00404         }
00405     }
00406     else if (event->button == Button4) {
00407         monitor()->cycleSlotTabPrev();
00408     }
00409     else if (event->button == Button5) {
00410         monitor()->cycleSlotTabNext();
00411     }
00412 }
00413 
00414 void Slot::handleMotionNotify(XMotionEvent *event) {
00415 }
00416 
00417 string Slot::tabName() {
00418     return focused()->name();
00419 }
00420 
00421 bool Slot::isGrabFocus() const {
00422     return isGrabFocus_;
00423 }
00424 
00425 void Slot::setGrabFocus(bool grabFocus) {
00426     Client *client = focused()->focused();
00427     if (isGrabFocus_ && !grabFocus) {
00428         // workspace grabs back the focus
00429         if (client) {
00430             Binder::instance()->ungrabButtons(client->clientWindow());
00431             Binder::instance()->grabButtons(client->clientWindow(), AnyModifier);
00432         }
00433     }
00434     isGrabFocus_ = grabFocus;
00435 }
00436 
00437 void Slot::focusClient(Client *client) {
00438 
00439     for (LTab::iterator it = begin(); it != end(); it++) {
00440         Tab *tab = *it;
00441         LClient *clients = tab->clients();
00442         for (LClient::iterator cit = clients->begin();
00443                 cit != clients->end(); cit++)
00444         {
00445             if (*cit == client) {
00446                 if (tab != focused()) {
00447                     focused()->hide();
00448                     focus(tab);
00449                     tab->show();
00450                     manage();
00451                 }
00452                 Client *old = focused()->focused();
00453                 if (old != client) {
00454                     Binder::instance()->ungrabButtons(old->clientWindow());
00455                     Binder::instance()->grabButtons(old->clientWindow(),
00456                                                     AnyModifier);
00457                 }
00458                 Client *tc = monitor()->focused()->topClient();
00459                 isGrabFocus_ = true;
00460                 if (tc) {
00461                     // unfocus topClient() of workspace, because the
00462                     // slot grabs focus control now
00463                     Binder::instance()->ungrabButtons(tc->clientWindow());
00464                     Binder::instance()->grabButtons(tc->clientWindow(),
00465                                                     AnyModifier);
00466                     monitor()->focused()->illuminate();
00467                 }
00468                 focused()->focus(client);
00469                 Binder::instance()->ungrabButtons(client->clientWindow());
00470                 XCORE->setInputFocus(client->clientWindow());
00471                 illuminate();
00472                 return;
00473             }
00474         }
00475     }
00476 }
00477 #endif // SLOT_SUPPORT

Generated on Thu May 24 15:19:32 2007 for ncwm by  doxygen 1.5.1