wmi

git clone git://oldgit.suckless.org/wmi/
Log | Files | Refs | LICENSE

workspace.cpp (23895B)


      1 // Copyright (c) 2003 - 2009 Anselm R Garbe <anselm@garbe.us>
      2 // See LICENSE for license details.
      3 
      4 extern "C" {
      5 #include <assert.h>
      6 #include <unistd.h>
      7 #include <X11/Xlib.h>
      8 }
      9 
     10 #include <map>
     11 #include <sstream>
     12 
     13 #include "workspace.h"
     14 
     15 #include "binder.h"
     16 #include "clientbar.h"
     17 #include "float.h"
     18 #include "frame.h"
     19 #include "kernel.h"
     20 #include "logger.h"
     21 #include "kernel.h"
     22 #include "monitor.h"
     23 #include "slot.h"
     24 #include "split.h"
     25 #include "statusbar.h"
     26 #include "thing.h"
     27 #include "tree.h"
     28 #include "util.h"
     29 #include "xcore.h"
     30 
     31 Workspace::Workspace(Monitor *monitor, unsigned int id, Rectangle *rect)
     32     : Rectangle(*rect), floatingClients_(monitor), frames_(monitor)
     33 {
     34     id_ = id;
     35     root_ = new Tree(0, this);
     36     isFrameMode_ = true;
     37     requestsFocus_ = false;
     38     frameIds_ = 0;
     39     monitor_ = monitor;
     40 
     41     ostringstream oss;
     42     oss << monitor->prefix() << ".workspace[" << id_ << "]";
     43     prefix_ = oss.str().c_str();
     44 
     45     isClientBarVisible_ = (Util::get(KERNEL->sessionSettings(),
     46                           prefix_ + ".clientbar") == "yes");
     47     isStatusBarVisible_ = (Util::get(KERNEL->sessionSettings(),
     48                            prefix_ + ".statusbar") == "yes");
     49 #ifdef SLOT_SUPPORT
     50     slotTabName_ = Util::get(KERNEL->sessionSettings(), prefix_ + ".slot");
     51 #endif // SLOT_SUPPORT
     52 
     53     name_ = Util::get(KERNEL->sessionSettings(), prefix_ + ".name");
     54 
     55     oss.str("");
     56     oss << "workspace my dim: " << x() << ", " << y() << ", " << width()
     57         << ", " << height();
     58     LOGDEBUG(oss.str());
     59     XCORE->sync();
     60 }
     61 
     62 Workspace::~Workspace() {
     63     delete root_;
     64 }
     65 
     66 void Workspace::focus(Thing *thing, bool raise) {
     67 
     68     if (!thing) {
     69         XCORE->setInputFocus(PointerRoot);
     70         illuminate();
     71         return;
     72     }
     73 
     74     Client *client = 0;
     75     Frame *frame = 0;
     76     if (thing->type() == Thing::CLIENT) {
     77         client = (Client *)thing;
     78         if (client->frame()) {
     79             LOGDEBUG("client has frame");
     80             frame = client->frame();
     81             frame->focus(client);
     82         }
     83     }
     84     else {
     85         frame = (Frame *)thing;
     86     }
     87 
     88     if (frame) {
     89         LOGDEBUG("focussing frame");
     90         if (raise) {
     91             for (LFrame::iterator it = frames_.begin();
     92                     it != frames_.end(); it++)
     93             {
     94                 XCORE->raise(((Frame *)*it)->window());
     95             }
     96             XCORE->raise(frame->window());
     97         }
     98         frames_.focus(frame);
     99         client = frame->focused();
    100     }
    101 
    102     if (client) {
    103         // grabbing/ungrabbing of the button
    104         Client *tc = topClient();
    105         if (tc && tc != client) {
    106             Binder::instance()->ungrabButtons(tc->clientWindow());
    107             Binder::instance()->grabButtons(tc->clientWindow(), AnyModifier);
    108         }
    109 
    110         LOGDEBUG("focussing client");
    111         client->setRequestsFocus(false);
    112 #ifdef SLOT_SUPPORT
    113         attached()->slot()->setGrabFocus(false);
    114 #endif
    115 
    116         Binder::instance()->ungrabButtons(client->clientWindow());
    117 
    118         removePushClient(client);
    119         if (!frame) {
    120             floatingClients_.focus(client);
    121         }
    122 
    123         if (raise) {
    124             XCORE->raise(client->window());
    125         }
    126 #ifdef SLOT_SUPPORT
    127         static bool isSlotOverlap =
    128             Util::get(KERNEL->commonSettings(), "slot.mode") == "overlap";
    129         if (isSlotOverlap || (isSlotVisible()
    130             && (isFrameMode_ != (bool)frame))) {
    131             XCORE->raise(monitor_->slot()->window());
    132         }
    133 #endif // SLOT_SUPPORT
    134         XCORE->setInputFocus(client->clientWindow());
    135     }
    136     isFrameMode_ = frame;
    137     illuminate();
    138 }
    139 
    140 void Workspace::hide() {
    141 
    142     for (LClient::iterator it = attached()->stickyClients()->begin();
    143          it != attached()->stickyClients()->end(); it++)
    144     {
    145         Client *client = *it;
    146         client->setAttached(0);
    147         floatingClients_.detach(client);
    148     }
    149     for (LClient::iterator it = floatingClients_.begin();
    150          it != floatingClients_.end(); it++)
    151     {
    152         (*it)->hide();
    153     }
    154 
    155     for (LFrame::iterator it = frames_.begin();
    156          it != frames_.end(); it++)
    157     {
    158         (*it)->hide();
    159     }
    160 }
    161 
    162 void Workspace::show() {
    163 
    164     for (LClient::iterator it = attached()->stickyClients()->begin();
    165          it != attached()->stickyClients()->end(); it++)
    166     {
    167         Client *client = *it;
    168         client->setAttached(this);
    169         floatingClients_.attach(client);
    170     }
    171 
    172     for (LClient::iterator it = floatingClients_.begin();
    173          it != floatingClients_.end(); it++)
    174     {
    175         (*it)->show();
    176     }
    177 
    178     for (LFrame::iterator it = frames_.begin();
    179          it != frames_.end(); it++)
    180     {
    181         (*it)->show();
    182     }
    183 
    184     focus(topClient());
    185 
    186     if (isClientBarVisible_) {
    187         attached()->clientBar()->show();
    188     }
    189     else {
    190         attached()->clientBar()->hide();
    191     }
    192     if (isStatusBarVisible_) {
    193         attached()->statusBar()->show();
    194     }
    195     else {
    196         attached()->statusBar()->hide();
    197     }
    198 #ifdef SLOT_SUPPORT
    199     Slot *slot = attached()->slot();
    200     if (isSlotVisible()) {
    201         bool doManage = (slotTabName_ != slot->tabName());
    202         slot->show(slotTabName_);
    203         if (doManage) {
    204             slot->manage();
    205         }
    206     }
    207     else {
    208         slot->hide();
    209     }
    210     slotTabName_ = slot->isVisible() ?  slot->tabName() : "";
    211 #endif // SLOT_SUPPORT
    212 }
    213 
    214 void Workspace::illuminate() {
    215 
    216     if (attached()->focused() != this) {
    217         return;
    218     }
    219 
    220     for (LClient::iterator it = floatingClients_.begin();
    221          it != floatingClients_.end(); it++)
    222     {
    223         (*it)->illuminate();
    224     }
    225 
    226     LOGDEBUG("floating clients illuminated, going to illuminate frames");
    227     for (LFrame::iterator it = frames_.begin();
    228          it != frames_.end(); it++)
    229     {
    230         (*it)->illuminate();
    231     }
    232     attached()->updateBars();
    233 }
    234 
    235 void Workspace::swapFrame(Direction dir) {
    236 
    237     Frame *frame1 = focusedFrame();
    238     Frame *frame2 = nextFrame(dir);
    239     if (!frame1 || !frame2) {
    240         return;
    241     }
    242 
    243     Tree *tree1 = frame1->tree();
    244     Tree *tree2 = frame2->tree();
    245 
    246     tree1->setFrame(frame2);
    247     tree2->setFrame(frame1);
    248     frame2->setTree(tree1);
    249     frame1->setTree(tree2);
    250     Split::adjustSize(tree1, ((dir == LEFT) || (dir == RIGHT)));
    251     Split::adjustSize(tree2, ((dir == LEFT) || (dir == RIGHT)));
    252 }
    253 
    254 void Workspace::swapClient(Direction dir) {
    255 
    256     Frame *frame1 = focusedFrame();
    257     if (!frame1) {
    258         return;
    259     }
    260 
    261     Frame *frame2 = nextFrame(dir);
    262 
    263     if (frame1 && frame2) {
    264 
    265         Client *client1 = frame1->focused();
    266         Client *client2 = frame2->focused();
    267 
    268         frame1->detach(client1);
    269         frame2->detach(client2);
    270         frame2->attach(client1);
    271         frame1->attach(client2);
    272         frame1->illuminate();
    273         frame2->illuminate();
    274     }
    275 }
    276 
    277 Tree *Workspace::neighborTree(Direction dir) {
    278 
    279     if (focusedFrame()) {
    280         return Split::neighbor(root_, focusedFrame()->tree(), dir);
    281     }
    282     return 0;
    283 }
    284 
    285 #define EPSILON 3
    286 
    287 Frame *Workspace::recentVisitedFrame(Direction dir) {
    288 
    289     if (!focusedFrame()) {
    290         return 0;
    291     }
    292     Frame *focusedFrame = this->focusedFrame();
    293     Tree *focusedTree = focusedFrame->tree();
    294     // This algorithm is somewhat magic, because it uses the
    295     // fact of the state of the globalClientStack_. 
    296     for (LClient::iterator it = globalClientStack_.begin();
    297             it != globalClientStack_.end(); it++)
    298     {
    299         Client *client = *it;
    300         Frame *frame = client->frame();
    301         if (frame && (frame != focusedFrame)) {
    302 
    303             Tree *tree = frame->tree();
    304             if (Split::isNeighbor(focusedTree, tree, dir)) {
    305                 bool isIgnore = false;
    306                 switch (dir) {
    307                 case LEFT:
    308                     isIgnore =
    309                         (int)(tree->x() + tree->width() + EPSILON) <
    310                         focusedTree->x();
    311                     isIgnore = isIgnore || (focusedTree->y() > tree->y()) ||
    312                         (focusedTree->height() < tree->height());
    313                     break;
    314                 case RIGHT:
    315                     isIgnore =
    316                         (int)(focusedTree->x() + focusedTree->width() +
    317                         EPSILON) < tree->x();
    318                     isIgnore = isIgnore || (focusedTree->y() > tree->y()) ||
    319                         (focusedTree->height() < tree->height());
    320                     break;
    321                 case UP:
    322                     isIgnore =
    323                         (int)(tree->y() + tree->height() + EPSILON) <
    324                         focusedTree->y();
    325                     isIgnore = isIgnore || (focusedTree->x() > tree->x()) ||
    326                         (focusedTree->width() < tree->width());
    327                     break;
    328                 case DOWN:
    329                     isIgnore =
    330                         (int)(focusedTree->y() + focusedTree->height() +
    331                         EPSILON) < tree->y();
    332                     isIgnore = isIgnore || (focusedTree->x() > tree->x()) ||
    333                         (focusedTree->width() < tree->width());
    334                     break;
    335                 default:
    336                     break;
    337                 }
    338                 if (!isIgnore) {
    339                     return frame;
    340                 }
    341             }
    342         }
    343     }
    344     return 0;
    345 }
    346 
    347 Frame *Workspace::nextFrame(Direction dir, bool isResize) {
    348 
    349     Tree *neighbor = neighborTree(dir);
    350 
    351     if (neighbor && isResize) { // normal case
    352         return Split::firstLeaf(neighbor);
    353     }
    354     else if (neighbor) {
    355 
    356         Frame *result = Split::firstLeaf(neighbor);
    357         Frame *recent = recentVisitedFrame(dir);
    358 
    359         if (recent && recent != result && recent != focusedFrame()) {
    360             result = recent;
    361         }
    362 
    363         return result;
    364     }
    365 
    366     return 0;
    367 }
    368 
    369 void Workspace::selectFrame(Direction dir) {
    370 
    371     Frame *next = nextFrame(dir, false);
    372 
    373     if (next) {
    374         focus(next->focused());
    375     }
    376 }
    377 
    378 void Workspace::attachFrame(Frame *frame, Direction dir) {
    379 
    380     Tree *root = root_;
    381 
    382     if (focusedFrame()) {
    383         root = focusedFrame()->tree();
    384     }
    385 
    386     Split::attach(root, frame, dir);
    387 
    388     frames_.attach(frame);
    389     frame->show();
    390 }
    391 
    392 Frame *Workspace::newFrame() {
    393 
    394     assert((frames_.size() == 0));
    395     Frame *frame = new Frame(this, this);
    396     attachFrame(frame, LEFT); // direction doesn't matter
    397 
    398     return frame;
    399 }
    400 
    401 void Workspace::attachClient(Client *client, bool isChangeMode) {
    402 
    403     if (!client->frameWindow() && client->hasDecoration()) {
    404         LOGDEBUG("creating frame window for client");
    405         client->createFrame();
    406     }
    407 
    408     client->setAttached(this);
    409     if (client->mode() == Client::MAX) {
    410         // MAX mode is only allowed with decoration
    411         Frame *frame = 0;
    412         if (isChangeMode) {
    413             frame = frameForPoint(
    414                     client->x() + client->width() / 2,
    415                     client->y() + client->height() / 2);
    416         }
    417         else {
    418             frame = focusedFrame();
    419         }
    420         if (!frame) {
    421             frame = newFrame();
    422         }
    423         frame->attach(client);
    424         focus(frame->focused());
    425         return;
    426     }
    427     else if (client->mode() == Client::STICKY) {
    428         attached()->stickyClients()->attach(client);
    429     }
    430 
    431     for (LClient::iterator it = floatingClients_.begin();
    432             it != floatingClients_.end(); it++)
    433     {
    434         if (*it == client) {
    435             return;
    436         }
    437     }
    438     floatingClients_.attach(client);
    439     if (client->frameWindow()) {
    440         client->reparent(client->frameWindow(), client->x(), client->y());
    441     }
    442     XCORE->sync();
    443     Util::fitInto(client, attached());
    444     if (!isChangeMode) {
    445         if (client->isCentered()) {
    446             Float::center(client, this);
    447         }
    448     }
    449     client->resize();
    450     client->show();
    451     focus(client);
    452 }
    453 
    454 void Workspace::destroyFrame(Frame *frame) {
    455 
    456     unsigned int i = frame->size();
    457     while (i) {
    458         Client *client = *frame->begin();
    459         attached()->detachClient(client);
    460         KERNEL->killClient(client);
    461         i--;
    462     }
    463     assert(frame->size() < 1);
    464     frames_.detach(frame);
    465     Split::detach(root_, frame->tree());
    466     delete frame;
    467     LOGDEBUG("frame destroyed");
    468 }
    469 
    470 void Workspace::sendClient(Direction dir) {
    471 
    472     Frame *from = focusedFrame();
    473     Frame *to = nextFrame(dir);
    474 
    475     if (from && to) {
    476         Client *client = from->focused();
    477         if (!from->detach(client) &&
    478             (Util::get(KERNEL->commonSettings(), "frame.autodestroy") == "yes"))
    479         {
    480             destroyFrame(from);
    481         }
    482         client->initICCCM();
    483         to->attach(client);
    484         focus(to->focused());
    485     }
    486 }
    487 
    488 void Workspace::joinFrame(Direction dir) {
    489 
    490     Frame *from = focusedFrame();
    491     Frame *to = nextFrame(dir);
    492 
    493     if (from && to) {
    494 
    495         for (unsigned int i = from->size(); i > 0; i--) {
    496             Client *client = from->focused();
    497             if (from->detach(client) == 0) {
    498                 destroyFrame(from);
    499             }
    500             client->initICCCM();
    501             to->attach(client);
    502         }
    503         focus(to->focused());
    504     }
    505 }
    506 
    507 void Workspace::splitFrame(Direction dir) {
    508 
    509     Frame *frame = focusedFrame();
    510     if (frame && frame->size() > 1) {
    511         Frame *splitFrame = new Frame(this, frame);
    512         LOGDEBUG("split frame");
    513         Client *client = frame->focused();
    514         frame->detach(client);
    515         attachFrame(splitFrame, dir);
    516         splitFrame->attach(client);
    517         focus(splitFrame->focused());
    518     }
    519 }
    520 
    521 void Workspace::resize(Thing *thing, Direction dir, bool grow) {
    522 
    523     switch (thing->type()) {
    524     case Thing::FRAME:
    525         resizeFrame(dir, grow);
    526         break;
    527     case Thing::CLIENT:
    528         if (((Client *)thing)->hasDecoration()) {
    529             resizeClient(dir, grow);
    530         }
    531         break;
    532     }
    533 }
    534 
    535 void Workspace::resizeFrame(Direction dir, bool grow) {
    536 
    537     Monitor *monitor = attached();
    538     int stepW = width() / 100 * monitor->resizeFactor();
    539     int stepH = height() / 100 * monitor->resizeFactor();
    540 
    541     if (!grow) {
    542         stepW *= -1;
    543         stepH *= -1;
    544         dir = Util::reverseDir(dir);
    545     }
    546 
    547     Split::resize(root_, focusedFrame()->tree(),
    548                   dir, stepW, stepH);
    549 }
    550 
    551 void Workspace::detachClient(Client *client) {
    552 
    553     // we need to remove all references to a sticky client on *all*
    554     // other workspaces first
    555     if (client->mode() == Client::STICKY) {
    556         for (LWorkspace::iterator it = attached()->begin();
    557                 it != attached()->end(); it++)
    558         {
    559             Workspace *workspace = *it;
    560             if (workspace == this) {
    561                 continue;
    562             }
    563             workspace->removeClient(client);
    564         }
    565         attached()->stickyClients()->detach(client);
    566     }
    567 
    568     Frame *frame = client->frame();
    569     if (frame) {
    570         if (!frame->detach(client) &&
    571             (Util::get(KERNEL->commonSettings(), "frame.autodestroy") == "yes"))
    572         {
    573             destroyFrame(frame);
    574         }
    575     }
    576     else {
    577         floatingClients_.detach(client);
    578         if (client->isVisible()) {
    579             client->hide();
    580         }
    581         client->reparent(attached()->rootWindow(),
    582                          client->x(), client->y());
    583     }
    584     LOGDEBUG("detached from containers");
    585 
    586     removeClient(client);
    587 
    588     client->setAttached(0);
    589 
    590     assert(client != topClient());
    591     if (topClient()) {
    592         focus(topClient());
    593     }
    594     else {
    595         illuminate();
    596     }
    597     LOGDEBUG("final stuff of detaching client");
    598 }
    599 
    600 Frame *Workspace::focusedFrame() const {
    601     return frames_.focused();
    602 }
    603 
    604 Thing *Workspace::thingWindow(Window window) {
    605 
    606     for (LClient::iterator it = floatingClients_.begin();
    607          it != floatingClients_.end(); it++)
    608     {
    609         Client *client = *it;
    610         if (client->frameWindow() == window) {
    611             return client;
    612         }
    613     }
    614     for (LFrame::iterator it = frames_.begin();
    615          it != frames_.end(); it++)
    616     {
    617         Frame *frame = *it;
    618         if (frame->window() == window) {
    619             return frame;
    620         }
    621     }
    622     return 0;
    623 }
    624 
    625 void Workspace::matchBarNeighbors(Direction dir) {
    626 
    627     // TODO: take care of dir
    628     // commits current workspace rectangle to root_ tree map element
    629     root_->copy(this);
    630     Split::adjustSize(root_, ((dir == LEFT) || (dir == RIGHT)));
    631 }
    632 
    633 void Workspace::lower() {
    634 
    635     Thing *thing = focusedThing();
    636 
    637     if (!thing) {
    638         return;
    639     }
    640 
    641     XCORE->lower(thing->window());
    642 }
    643 
    644 void Workspace::raise() {
    645 
    646     Client *client = topClient();
    647 
    648     if (!client) {
    649         return;
    650     }
    651 
    652     focus(client);
    653 }
    654 
    655 void Workspace::changeClientMode(Client *client, Client::Mode mode) {
    656     assert(client);
    657     detachClient(client);
    658     client->setMode(mode);
    659     attachClient(client, true);
    660 }
    661 
    662 void Workspace::toggleClientMode() {
    663     Client *client = topClient();
    664     if (client) {
    665         changeClientMode(client, (client->mode() == Client::MAX) ?
    666                                  Client::FLOAT : Client::MAX);
    667     }
    668 }
    669 
    670 void Workspace::toggleClientSticky() {
    671     Client *client = topClient();
    672     if (client) {
    673         if (client->mode() != Client::STICKY) {
    674             changeClientMode(client, Client::STICKY);
    675         }
    676         else {
    677             changeClientMode(client, Client::FLOAT);
    678         }
    679     }
    680 }
    681 
    682 void Workspace::resizeClient(Direction dir, bool grow) {
    683 
    684     Client *client = topClient();
    685     if (!client || !client->hasDecoration()) {
    686         return;
    687     }
    688 
    689     Monitor *monitor = attached();
    690 
    691     int stepW = width() / 100 * monitor->resizeFactor();
    692     int stepH = height() / 100 * monitor->resizeFactor();
    693 
    694     if ((dir == LEFT) || (dir == UP)) {
    695         stepW *= -1;
    696         stepH *= -1;
    697     }
    698 
    699     Float::resize(client, grow ? dir : Util::reverseDir(dir),
    700                   stepW, stepH);
    701 
    702     client->resize();
    703 }
    704 
    705 void Workspace::moveClient(Direction dir) {
    706 
    707     Client *client = topClient();
    708     if (!client) {
    709         return;
    710     }
    711 
    712     Monitor *monitor = attached();
    713 
    714     // review: correct
    715     int stepW = width() / 100 * monitor->resizeFactor();
    716     int stepH = height() / 100 * monitor->resizeFactor();
    717 
    718     if ((dir == LEFT) || (dir == UP)) {
    719         stepW *= -1;
    720         stepH *= -1;
    721     }
    722 
    723     if ((dir == LEFT) || (dir == RIGHT)) {
    724         Float::move(client, stepW, 0);
    725     }
    726     else {
    727         Float::move(client, 0, stepH);
    728     }
    729 
    730     client->resize();
    731 }
    732 
    733 
    734 void Workspace::serialize() {
    735 
    736     (*KERNEL->sessionSettings())[prefix_ + ".name"] = name_;
    737     (*KERNEL->sessionSettings())[prefix_ + ".clientbar"] =
    738         isClientBarVisible_ ? "yes" : "no";
    739     (*KERNEL->sessionSettings())[prefix_ + ".statusbar"] =
    740         isStatusBarVisible_ ? "yes" : "no";
    741 #ifdef SLOT_SUPPORT
    742     (*KERNEL->sessionSettings())[prefix_ + ".slot"] = slotTabName_;
    743 #endif // SLOT_SUPPORT
    744 }
    745 
    746 Frame *Workspace::frameForPoint(unsigned int x, unsigned int y) {
    747 
    748     for (LFrame::iterator it = frames_.begin();
    749          it != frames_.end(); it++)
    750     {
    751         Frame *frame = *it;
    752         if (Util::isPointWithinRect(x, y, frame, this)) {
    753             return frame;
    754         }
    755     }
    756     return focusedFrame();
    757 }
    758 
    759 void Workspace::toggleBorders(bool visible) {
    760 
    761     for (LFrame::iterator it = frames_.begin();
    762             it != frames_.end(); it++)
    763     {
    764         Frame *frame = *it;
    765         frame->setBorderWidth(visible ? KERNEL->borderWidth() : 0);
    766         frame->resize();
    767     }
    768     for (LClient::iterator it = floatingClients_.begin();
    769             it != floatingClients_.end(); it++)
    770     {
    771         Client *client = *it;
    772         if (client->hasDecoration()) {
    773             client->setBorderWidth(visible ? KERNEL->borderWidth() : 0);
    774             client->resize();
    775         }
    776     }
    777 }
    778 
    779 void Workspace::toggleBars(bool visible) {
    780 
    781     for (LFrame::iterator it = frames_.begin();
    782             it != frames_.end(); it++)
    783     {
    784         Frame *frame = *it;
    785         frame->setTitleBarHeight(visible ? attached()->titleBarHeight() : 0);
    786         frame->resize();
    787     }
    788     for (LClient::iterator it = floatingClients_.begin();
    789             it != floatingClients_.end(); it++)
    790     {
    791         Client *client = *it;
    792         if (client->hasDecoration()) {
    793             client->setTitleBarHeight(visible ? attached()->titleBarHeight() : 0);
    794             client->resize();
    795         }
    796     }
    797 }
    798 
    799 void Workspace::cycleClientNext() {
    800 
    801     if (isFrameMode_) {
    802         if (focusedFrame()) {
    803             focus(focusedFrame()->next());
    804         }
    805     }
    806     else {
    807         focus(floatingClients_.next());
    808     }
    809 }
    810 
    811 void Workspace::cycleClientPrev() {
    812 
    813     if (isFrameMode_) {
    814         if (focusedFrame()) {
    815             focus(focusedFrame()->prev());
    816         }
    817     }
    818     else {
    819         focus(floatingClients_.prev());
    820     }
    821 }
    822 
    823 void Workspace::toggleMode() {
    824     isFrameMode_ = !isFrameMode_;
    825     if (isFrameMode_) {
    826         if (focusedFrame()) {
    827             focus(focusedFrame()->focused());
    828         }
    829         else {
    830             focus(0);
    831         }
    832     }
    833     else {
    834         for (LClient::iterator it = floatingClients_.begin();
    835              it != floatingClients_.end(); it++)
    836         {
    837             XCORE->raise(((Client *)*it)->window());
    838         }
    839         focus(floatingClients_.focused());
    840     }
    841 }
    842 
    843 void Workspace::removePushClient(Client *client) {
    844     removeClient(client);
    845     pushClient(client);
    846 }
    847 
    848 void Workspace::removeClient(Client *client) {
    849     if (stackContainsClient(client)) {
    850         globalClientStack_.remove(client);
    851     }
    852 }
    853 
    854 void Workspace::pushClient(Client *client) {
    855     if (!stackContainsClient(client)) {
    856         globalClientStack_.push_front(client);
    857     }
    858 }
    859 
    860 bool Workspace::stackContainsClient(Client *client) {
    861     for (LClient::iterator it = globalClientStack_.begin();
    862             it != globalClientStack_.end(); it++)
    863     {
    864         if (client == *it) {
    865             return true;
    866         }
    867     }
    868     return false;
    869 }
    870 
    871 Client *Workspace::topClient() {
    872 
    873 #ifdef SLOT_SUPPORT
    874     if (isSlotVisible() && attached()->slot()->isGrabFocus()) {
    875         // if the slot grabs the focus currently, this workspace
    876         // has temprarily no focussed topClient - so just return
    877         // 0.
    878         return 0;
    879     }
    880 #endif
    881     if (globalClientStack_.size()) {
    882         return globalClientStack_.front();
    883     }
    884     return 0;
    885 }
    886 
    887 unsigned int Workspace::nextFrameId() {
    888     ++frameIds_;
    889     return frameIds_;
    890 }
    891 
    892 unsigned int Workspace::id() const {
    893     return id_;
    894 }
    895 
    896 void Workspace::setName(string name) {
    897     name_ = name;
    898 }
    899 
    900 string Workspace::name() const {
    901     return name_;
    902 }
    903 
    904 string Workspace::prefix() const {
    905     return prefix_;
    906 }
    907 
    908 Tree* Workspace::root() const {
    909     return root_;
    910 }
    911 
    912 bool Workspace::isFrameMode() const {
    913     return isFrameMode_;
    914 }
    915 
    916 void Workspace::setClientBarVisible(bool visible) {
    917     isClientBarVisible_ = visible;
    918 }
    919 
    920 void Workspace::setStatusBarVisible(bool visible) {
    921     isStatusBarVisible_ = visible;
    922 }
    923 
    924 #ifdef SLOT_SUPPORT
    925 void Workspace::setSlotVisible(bool visible) {
    926     slotTabName_ = visible ?
    927         attached()->slot()->tabName() : "";
    928 }
    929 
    930 bool Workspace::isSlotVisible() const {
    931     return slotTabName_ != "";
    932 }
    933 
    934 string Workspace::slotTabName() const {
    935     return slotTabName_;
    936 }
    937 #endif // SLOT_SUPPORT
    938 
    939 Thing *Workspace::focusedThing() {
    940 
    941     Client *client = topClient();
    942     return (client && client->frame()) ? (Thing *)client->frame() :
    943         (Thing *)client;
    944 }
    945 
    946 void Workspace::fitClient() {
    947 
    948     Client *client = topClient();
    949     if (client) {
    950         Util::fitInto(client, this);
    951         client->resize();
    952     }
    953 }
    954 
    955 bool Workspace::isClientBarVisible() const {
    956     return isClientBarVisible_;
    957 }
    958 
    959 bool Workspace::isStatusBarVisible() const {
    960     return isStatusBarVisible_;
    961 }
    962 
    963 Monitor *Workspace::attached() const {
    964     return monitor_;
    965 }
    966 
    967 CClient *Workspace::floatingClients() {
    968     return &floatingClients_;
    969 }
    970 
    971 CFrame *Workspace::frames() {
    972     return &frames_;
    973 }
    974 
    975 bool Workspace::requestsFocus() const {
    976     return requestsFocus_;
    977 }
    978 
    979 void Workspace::setRequestsFocus(bool requestsFocus) {
    980     requestsFocus_ = requestsFocus;
    981 }
    982 
    983 LClient *Workspace::clients() {
    984     return &globalClientStack_;
    985 }
    986