wmi

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

monitor.cpp (25150B)


      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 <X11/keysym.h>
      7 #include <X11/Xlib.h>
      8 #include <X11/Xutil.h>
      9 }
     10 
     11 #include <iostream>
     12 #include <sstream>
     13 
     14 #include "monitor.h"
     15 
     16 #include "action.h"
     17 #include "actions.h"
     18 #include "atoms.h"
     19 #include "binder.h"
     20 #include "box.h"
     21 #include "client.h"
     22 #include "clientbar.h"
     23 #include "cursors.h"
     24 #include "draw.h"
     25 #include "font.h"
     26 #include "frame.h"
     27 #include "inputbar.h"
     28 #include "logger.h"
     29 #include "menu.h"
     30 #include "rectangle.h"
     31 #include "slot.h"
     32 #include "statusbar.h"
     33 #include "theme.h"
     34 #include "thing.h"
     35 #include "util.h"
     36 #include "kernel.h"
     37 #include "workspace.h"
     38 #include "xcore.h"
     39 #include "xfont.h"
     40 
     41 Monitor::Monitor(Display *display, unsigned int id)
     42     : Container<Display, LWorkspace, LWorkspace::iterator, Workspace>(display),
     43       Rectangle(), detachedClients_(this), stickyClients_(this)
     44 {
     45 
     46     ostringstream oss;
     47     oss << "monitor[" << id << "]";
     48     prefix_ = oss.str();
     49     id_ = id;
     50     themeSettings_ = KERNEL->themeSettings();
     51     commonSettings_ = KERNEL->commonSettings();
     52     sessionSettings_ = KERNEL->sessionSettings();
     53     setWidth(DisplayWidth(attached(), id_));
     54     setHeight(DisplayHeight(attached(), id_));
     55     rootWindow_ = RootWindow(attached(), id_);
     56 
     57     resizeFactor_ = Util::strToUInt(
     58             Util::get(commonSettings_, "resize-move.factor"));
     59 
     60     theme_ = new Theme();
     61     maxThing_ = 0;
     62     clientIds_ = 0;
     63     fixed_ = 0;
     64 
     65     initFonts();
     66     LOGDEBUG("font initialized");
     67     initDisplayString();
     68     LOGDEBUG("display string '" + displayString_ + "' initialized");
     69     theme_->initTheme(themeSettings_, XCORE->defaultColormap(id_));
     70     LOGDEBUG("colors initialized");
     71     initGC();
     72     LOGDEBUG("GC initialized");
     73     initBars();
     74     LOGDEBUG("bars initialized");
     75     XCORE->sync();
     76 #ifdef SLOT_SUPPORT
     77     initSlot();
     78     LOGDEBUG("slot initialized");
     79 #endif // SLOT_SUPPORT
     80     initWorkspaces();
     81     LOGDEBUG("workspaces initialized");
     82 
     83     XCORE->selectEvents(rootWindow_,
     84                  SubstructureRedirectMask | SubstructureNotifyMask 
     85                  | PropertyChangeMask);
     86 
     87     KERNEL->installCursor(Cursors::NORMAL_CURSOR, rootWindow_);
     88 
     89     XCORE->sync();
     90 }
     91 
     92 void Monitor::initFonts() {
     93 
     94     string fontName = Util::get(KERNEL->themeSettings(), "font");
     95     font_ = WFont::load(this, fontName);
     96     if (!font_) {
     97         // fallback, trying to load "fixed"
     98         LOGWARN("cannot load font '" + fontName +
     99                      "', trying loading default font 'fixed'");
    100         font_ = WFont::load(this, "fixed");
    101         if (!font_) {
    102             LOGERROR("cannot load any font", true);
    103             // exits WMI
    104         }
    105     }
    106     if (font_->height() < MINIMAL_BARHEIGHT) {
    107         font_->setHeight(MINIMAL_BARHEIGHT);
    108     }
    109     if (font_->type() == WFont::XFT) {
    110         fixed_ = XFont::load(this, "fixed");
    111         if (!fixed_) {
    112             LOGERROR("cannot load any font", true);
    113             // exits WMI
    114         }
    115     }
    116 }
    117 
    118 void Monitor::initBars() {
    119 
    120     Rectangle rect(0, 0, width(),  titleBarHeight() + 2);
    121 
    122     if (Util::get(commonSettings_, "statusbar.alignment") != "bottom") {
    123         statusBar_ = new StatusBar(this, &rect);
    124         inputBar_ = new InputBar(this, &rect);
    125         rect.setY(height() - rect.height());
    126         clientBar_ = new ClientBar(this, &rect);
    127     }
    128     else {
    129         clientBar_ = new ClientBar(this, &rect);
    130         rect.setY(height() - rect.height());
    131         statusBar_ = new StatusBar(this, &rect);
    132         inputBar_ = new InputBar(this, &rect);
    133     }
    134 
    135     rect.setY(height() / 2 - rect.height() / 2);
    136     box_ = new Box(this, &rect, "");
    137 }
    138 
    139 void Monitor::initGC() {
    140 
    141     unsigned long mask = 
    142                   GCForeground | GCGraphicsExposures
    143                 | GCFunction | GCSubwindowMode | GCLineWidth
    144                 | GCPlaneMask;
    145     XGCValues gcv;
    146     gcv.subwindow_mode=IncludeInferiors;
    147     gcv.function=GXxor;
    148     gcv.foreground = theme_->FRAME_PSEUDO;
    149     gcv.fill_style=FillSolid;
    150     gcv.line_width = Util::strToUInt(
    151             Util::get(KERNEL->commonSettings(), "border.width"));
    152     gcv.plane_mask = AllPlanes;
    153     gcv.graphics_exposures = False;
    154     if (font_->type() == WFont::NORMAL) {
    155         gcv.font = ((XFont *)font_)->font()->fid;
    156         mask |= GCFont;
    157     }
    158 
    159     pseudoBorderGC_ = XCORE->createGC(rootWindow_, mask, &gcv);
    160 
    161     gcv.function=GXcopy;
    162     borderGC_ = XCORE->createGC(rootWindow_, mask, &gcv);
    163 }
    164 
    165 Monitor::~Monitor() {
    166     for (MClient::iterator it = clients_.begin();
    167          it != clients_.end(); it++)
    168     {
    169         Client *client = (*it).second;
    170         clients_.erase(it);
    171         delete client;
    172     }
    173     delete statusBar_;
    174     delete clientBar_;
    175 #ifdef SLOT_SUPPORT
    176     delete slot_;
    177 #endif // SLOT_SUPPORT
    178 }
    179 
    180 void Monitor::rectForWorkspace(Workspace *workspace) {
    181 
    182     bool isClientBarVisible = workspace->isClientBarVisible();
    183     bool isStatusBarVisible = workspace->isStatusBarVisible();
    184 
    185     // bar dimensions
    186     if (Util::get(commonSettings_, "statusbar.alignment") != "bottom") {
    187         workspace->setY((isStatusBarVisible ? statusBar_->height() : 0));
    188     }
    189     else {
    190         workspace->setY((isClientBarVisible ? clientBar_->height() : 0));
    191     }
    192     workspace->setHeight(height()
    193                          - (isStatusBarVisible ?  statusBar_->height() : 0)
    194                          - (isClientBarVisible ?  clientBar_->height() : 0));
    195 
    196 #ifdef SLOT_SUPPORT
    197     static bool isSlotOverlap =
    198         Util::get(commonSettings_, "slot.mode") == "overlap";
    199     // slot dimensions
    200     if (workspace->isSlotVisible() && !isSlotOverlap
    201         && slot_->hasClients())
    202     {
    203         if (slot_->alignment() == LEFT) {
    204             workspace->setX(slot_->width());
    205         }
    206         else {
    207             workspace->setX(x());
    208         }
    209         workspace->setWidth(width() - slot_->width());
    210     }
    211     else
    212 #endif // SLOT_SUPPORT
    213     {
    214         workspace->setX(x());
    215         workspace->setWidth(width());
    216     }
    217 }
    218 
    219 void Monitor::initWorkspaces() {
    220 
    221     string key = prefix_ + ".workspaces";
    222 
    223     unsigned int workspaceCount =
    224         Util::strToUInt(Util::get(sessionSettings_, key));
    225     string id =
    226         Util::get(KERNEL->sessionSettings(), prefix_ + ".focused");
    227     unsigned int focusedWSNum = (id != "") ? Util::strToUInt(id) : 0;
    228 
    229     Rectangle rect;
    230     Workspace *toFocus = 0;
    231     for (unsigned int i = 0; i < workspaceCount; i++) {
    232         Workspace *workspace = new Workspace(this, i, &rect);
    233         matchWorkspace(workspace, LEFT);
    234         attach(workspace);
    235         if (i == focusedWSNum) {
    236             toFocus = workspace;
    237         }
    238     }
    239     LOGDEBUG("workspaces created");
    240     XCORE->sync();
    241     focus(toFocus);
    242 }
    243 
    244 void Monitor::initDisplayString() {
    245 
    246     ostringstream oss;
    247 
    248     displayString_ = DisplayString(attached());
    249     unsigned int dot = displayString_.rfind('.');
    250 
    251     LOGDEBUG("initializing display string '" + displayString_ + "'");
    252     oss << "DISPLAY=";
    253     LOGDEBUG("ok displayString_");
    254     if (dot > 0) {
    255         oss << displayString_.substr(0, dot + 1) << id_;
    256     }
    257     else {
    258         oss << displayString_;
    259     }
    260 
    261     displayString_ = oss.str();
    262 }
    263 
    264 void Monitor::scanWindows() {
    265 
    266     unsigned int numWindows = 0;
    267     Window *windows;
    268     XWindowAttributes attr;
    269 
    270     // Queries only the tree of this monitor
    271     XCORE->queryTree(rootWindow_, &windows, &numWindows);
    272 
    273     ostringstream oss;
    274     oss << "scanning " << numWindows << " windows";
    275     LOGDEBUG(oss.str());
    276     for (unsigned int i = 0; i < numWindows; i++) {
    277         XCORE->windowAttributes(windows[i], &attr);
    278 
    279         // ignore default windows
    280         if (attr.override_redirect ||
    281             menuWindow(windows[i]) ||
    282             (box_->window() == windows[i]) ||
    283             barWindow(windows[i]) ||
    284 #ifdef SLOT_SUPPORT
    285             slotWindow(windows[i]) ||
    286 #endif // SLOT_SUPPORT
    287             (windows[i] == rootWindow_))
    288         {
    289             LOGDEBUG("ignoring scanned window (override redirect)");
    290             continue;
    291         }
    292 
    293         if (XCORE->transient(windows[i])) {
    294             LOGDEBUG("ignoring scanned window (transient)");
    295             continue;
    296         }
    297 
    298         // determine client
    299         Client *client;
    300         if ((client = clientForWindow(windows[i])) == 0) {
    301             if (attr.map_state == IsViewable) {
    302                 client = new Client(this, windows[i], &attr);
    303                 addClient(client);
    304                 attachClient(client);
    305             }
    306         }
    307     }
    308     if (windows) {
    309         XCORE->free((void *)windows);
    310     }
    311 }
    312 
    313 Thing *Monitor::thingWindow(Window window) {
    314 
    315     for (LWorkspace::iterator it = begin(); it != end(); it++) {
    316         Workspace *workspace = *it;
    317         Thing *thing = workspace->thingWindow(window);
    318         if (thing) {
    319             return thing;
    320         }
    321     }
    322     return 0;
    323 }
    324 
    325 
    326 Bar *Monitor::barWindow(Window window) {
    327 
    328     if (statusBar_->window() == window) {
    329         return statusBar_;
    330     }
    331     if (clientBar_->window() == window) {
    332         return clientBar_;
    333     }
    334     if (inputBar_->window() == window) {
    335         return inputBar_;
    336     }
    337     return 0;
    338 }
    339 
    340 Menu *Monitor::menuWindow(Window window) {
    341     Menu *menu = clientBar_->menu();
    342     if (clientBar_->menu()->window() == window) {
    343         return menu;
    344     }
    345 
    346     return 0;
    347 }
    348 
    349 #ifdef SLOT_SUPPORT
    350 void Monitor::initSlot() {
    351 
    352     Direction align;
    353     string valueAlign = Util::get(commonSettings_, "slot.alignment");
    354     Rectangle rect;
    355 
    356     int offsetX = 0;
    357     if (valueAlign == "right") {
    358         align = RIGHT;
    359         offsetX = width() - 1; // initial offset :)
    360     }
    361     else {
    362         align = LEFT;
    363     }
    364     rect = Rectangle(offsetX, titleBarHeight(), 1,
    365                      height() - 2 * titleBarHeight());
    366 
    367     slot_ = new Slot(this, &rect, align);
    368 }
    369 
    370 
    371 Slot *Monitor::slotWindow(Window window) {
    372 
    373     if (slot_->window() == window) {
    374         return slot_;
    375     }
    376 
    377     return 0;
    378 }
    379 
    380 Slot *Monitor::slot() const {
    381     return slot_;
    382 }
    383 
    384 void Monitor::unslotClient() {
    385 
    386     Client *client = slot_->focused()->focused();
    387     if (client) {
    388         slot_->detachClient(client);
    389         client->setMode(Client::FLOAT);
    390         attachClient(client);
    391     }
    392 }
    393 
    394 void Monitor::slotClient() {
    395 
    396     Client *client = focusedClient();
    397     if (client) {
    398         // HACK: removeClient also removes it from clients
    399         // TODO: thus it would be useful to distinguish removeClient
    400         //       with detachClient -> overwork around wmi-10
    401         removeClient(client);
    402         addClient(client); // we've to add it again, because it was removed
    403         client->setMode(Client::SLOT);
    404         attachClient(client);
    405     }
    406 }
    407 
    408 void Monitor::toggleSlot() {
    409 
    410     if (slot_->isVisible()) {
    411         focused()->setSlotVisible(false);
    412         slot_->hide();
    413     }
    414     else {
    415         focused()->setSlotVisible(true);
    416         slot_->show(focused()->slotTabName());
    417         slot_->manage();
    418     }
    419 
    420     focused()->setSlotVisible(slot_->isVisible());
    421 }
    422 
    423 void Monitor::cycleSlotTabPrev() {
    424     slot_->focused()->hide();
    425     slot_->focus(slot_->prev());
    426     slot_->focused()->show();
    427     slot_->manage();
    428 }
    429 
    430 void Monitor::cycleSlotTabNext() {
    431     slot_->focused()->hide();
    432     slot_->focus(slot_->next());
    433     slot_->focused()->show();
    434     slot_->manage();
    435 }
    436 #endif // SLOT_SUPPORT
    437 
    438 Client *Monitor::clientForWindow(Window window) {
    439 
    440     if (window == 0 || window == rootWindow_) {
    441         return 0;
    442     }
    443 
    444     MClient::iterator it = clients_.find((long)window);
    445 
    446     if (it != clients_.end()) {
    447         return (*it).second;
    448     }
    449 
    450     // client does not exist
    451     return 0;
    452 }
    453 
    454 void Monitor::addClient(Client *client) {
    455 
    456     clients_[(long)client->clientWindow()] = client;
    457 }
    458 
    459 void Monitor::cleanup() {
    460     while (clients_.size()) {
    461         MClient::iterator it = clients_.begin();
    462         Client *client = (*it).second;
    463         removeClient(client);
    464         if (!client->transient()) {
    465             XCORE->addToSaveSet(client->clientWindow());
    466         }
    467         delete client;
    468     }
    469 }
    470 
    471 Client *Monitor::focusedClient() {
    472     return focused()->topClient();
    473 }
    474 
    475 void Monitor::removeClient(Client *client) {
    476 
    477     XCORE->sync();
    478     LOGDEBUG("removing client");
    479 
    480     Workspace *workspace = client->attached();
    481     if (workspace) {
    482         workspace->detachClient(client);
    483         LOGDEBUG("client removed from workspace");
    484     }
    485 #ifdef SLOT_SUPPORT
    486     else if (client->mode() == Client::SLOT) {
    487         LOGDEBUG("removing slot client");
    488         slot_->detachClient(client);
    489         matchWorkspace(focused(), slot_->alignment());
    490     }
    491 #endif
    492     else if (!client->isVisible()) {
    493         // seems to be an detached client
    494         detachedClients_.detach(client);
    495         XCORE->sync();
    496         LOGDEBUG("removing detached client");
    497         statusBar_->illuminate();
    498     }
    499     // else already detached
    500     XCORE->sync();
    501     clients_.erase((long)client->clientWindow());
    502     LOGDEBUG("client removed");
    503 }
    504 
    505 void Monitor::matchWorkspace(Workspace *workspace, Direction dir) {
    506 
    507     rectForWorkspace(workspace);
    508     workspace->matchBarNeighbors(dir);
    509 #ifdef SLOT_SUPPORT
    510     // slot fix
    511     slot_->setY(workspace->y());
    512 #endif // SLOT_SUPPORT
    513 }
    514 
    515 void Monitor::toggleClientBar() {
    516 
    517     if (clientBar_->isVisible()) {
    518         clientBar_->hide();
    519     }
    520     else {
    521         clientBar_->show();
    522     }
    523 
    524     focused()->setClientBarVisible(clientBar_->isVisible());
    525     Direction dir =
    526         (Util::get(commonSettings_, "statusbar.alignment") == "bottom") ? UP : DOWN;
    527     matchWorkspace(focused(), dir);
    528 #ifdef SLOT_SUPPORT
    529     slot_->manage();
    530 #endif // SLOT_SUPPORT
    531 }
    532 
    533 void Monitor::toggleStatusBar() {
    534 
    535     if (statusBar_->isVisible()) {
    536         statusBar_->hide();
    537     }
    538     else {
    539         statusBar_->show();
    540     }
    541 
    542     focused()->setStatusBarVisible(statusBar_->isVisible());
    543     Direction dir =
    544         (Util::get(commonSettings_, "statusbar.alignment") != "bottom") ? UP : DOWN;
    545     matchWorkspace(focused(), dir);
    546 #ifdef SLOT_SUPPORT
    547     slot_->manage();
    548 #endif // SLOT_SUPPORT
    549 }
    550 
    551 void Monitor::toggleAllClientStates() {
    552 
    553     Workspace *workspace = focused();
    554     assert(workspace);
    555     Thing *thing = workspace->focusedThing();
    556 
    557     if (!thing || (thing->type() != Thing::FRAME)) {
    558         return;
    559     }
    560     Frame *frame = (Frame *)thing;
    561 
    562     unsigned int num = frame->size();
    563     for (unsigned int i = 0; (i < num) && (frame->size() != 0); i++) {
    564         workspace->changeClientMode(frame->focused(), Client::FLOAT);
    565     }
    566     statusBar_->illuminate();
    567 }
    568 
    569 void Monitor::attachAllClients() {
    570 
    571     while (detachedClients_.size()) {
    572         Client *client = *detachedClients_.begin();
    573         detachedClients_.detach(client);
    574         attachClient(client);
    575     }
    576 }
    577 
    578 void Monitor::detachAllClients() {
    579 
    580     Workspace *workspace = focused();
    581     assert(workspace);
    582 
    583     if (workspace->isFrameMode()) {
    584         Frame *frame = workspace->focusedFrame();
    585         unsigned int i = frame->size();
    586         while (i) {
    587             detachClient(*frame->begin());
    588             i--;
    589         }
    590     }
    591     else {
    592         CClient *floatingClients = workspace->floatingClients();
    593         unsigned int i = floatingClients->size();
    594         while (i) {
    595             detachClient(*floatingClients->begin());
    596             i--;
    597         }
    598     }
    599     statusBar_->illuminate();
    600 }
    601 
    602 void Monitor::detachClient(Client *client) {
    603 
    604     if (!client) {
    605         return;
    606     }
    607 
    608     Workspace *workspace = client->attached();
    609 
    610     if (workspace) {
    611         workspace->detachClient(client);
    612         detachedClients_.attach(client);
    613     }
    614 }
    615 
    616 void Monitor::detachClient() {
    617     detachClient(focused()->topClient());
    618 }
    619 
    620 void Monitor::attachClientByName(string name) {
    621 
    622     for (LClient::iterator it = detachedClients_.begin();
    623             it != detachedClients_.end(); it++)
    624     {
    625         Client *client = *it;
    626         if (client->name() == name) {
    627             detachedClients_.detach(client);
    628             attachClient(client);
    629             return;
    630         }
    631     }
    632 }
    633 
    634 void Monitor::attachLastClient() {
    635 
    636     Client *client = detachedClients_.focused();
    637     if (client) {
    638         detachedClients_.detach(client);
    639         attachClient(client);
    640     }
    641 }
    642 
    643 void Monitor::attachClient(Client *client) {
    644 
    645     // first we've to init all necessary info
    646     client->initICCCM();
    647 
    648     if (client->state() == IconicState) {
    649         assert(!client->attached());
    650         detachedClients_.attach(client);
    651         return;
    652     }
    653 
    654     // first transient handling
    655     Client *transient = client->transient();
    656 
    657     if (transient && !transient->attached()
    658 #ifdef SLOT_SUPPORT
    659         && (transient->mode() != Client::SLOT)
    660 #endif // SLOT_SUPPORT
    661         )
    662     {
    663         // attach also the transient, if some
    664         detachedClients_.detach(transient);
    665         attachClient(transient);
    666     }
    667 
    668 #ifdef SLOT_SUPPORT
    669     if (client->mode() == Client::SLOT) {
    670         // will be handled by the slot
    671         LOGDEBUG("new slot client");
    672         slot_->attachClient(client);
    673     }
    674     else
    675 #endif // SLOT_SUPPORT
    676     {
    677         Workspace *hooked = workspaceForName(client->hooked());
    678         if (hooked && contains(hooked)) {
    679             focus(hooked);
    680         }
    681         focused()->attachClient(client);
    682     }
    683 }
    684 
    685 void Monitor::attachDetachedClient(Workspace *workspace, Client *client) {
    686 
    687     focus(workspace);
    688     detachedClients_.detach(client);
    689     attachClient(client);
    690 }
    691 
    692 void Monitor::createNewWorkspace(string name) {
    693 
    694     static Rectangle rect;
    695     unsigned int id = size();
    696 
    697     ostringstream key;
    698     key << prefix_ << ".workspace[" << id << "]";
    699 
    700     (*sessionSettings_)[key.str() + ".name"] = name;
    701     (*sessionSettings_)[key.str() + ".clientbar"] = "yes";
    702     (*sessionSettings_)[key.str() + ".statusbar"] = "yes";
    703 #ifdef SLOT_SUPPORT
    704     (*sessionSettings_)[key.str() + ".slot"] = slot_->tabName();
    705 #endif // SLOT_SUPPORT
    706     (*sessionSettings_)[key.str() + ".focused"] = "0";
    707 
    708     if (focused()) {
    709         focused()->hide();
    710     }
    711     Workspace *workspace = new Workspace(this , id, this);
    712     matchWorkspace(workspace, LEFT);
    713     attach(workspace);
    714     focused()->show();
    715 
    716     ostringstream value;
    717     value << size();
    718     (*sessionSettings_)[prefix_ + ".workspaces"] = value.str();
    719 }
    720 
    721 void Monitor::serialize() {
    722 
    723     ostringstream value;
    724     value << size();
    725     (*sessionSettings_)[prefix_ + ".workspaces"] = value.str();
    726 
    727     for (LWorkspace::iterator it = begin(); it != end(); it++) {
    728          Workspace *workspace = *it;
    729          workspace->serialize();
    730     }
    731 
    732     value.str("");
    733     value << focused()->id();
    734     (*sessionSettings_)[prefix_ + ".focused"] = value.str();
    735 }
    736 
    737 void Monitor::focus(Workspace *workspace) {
    738 
    739     workspace->setRequestsFocus(false);
    740     if (focused() != workspace) {
    741         focused()->hide();
    742         LOGDEBUG("focussing workspace");
    743         XCORE->sync();
    744         Container<Display, LWorkspace, LWorkspace::iterator,
    745             Workspace>::focus(workspace);
    746     }
    747     focused()->show();
    748     updateBars();
    749 }
    750 
    751 void Monitor::focusClient(Client *client) {
    752 
    753     Workspace *workspace = client->attached();
    754     if (workspace) {
    755         focus(workspace);
    756         workspace->focus(client);
    757     }
    758 }
    759 
    760 void Monitor::focusClientById(string id) {
    761 
    762     for (MClient::iterator it = clients_.begin();
    763             it != clients_.end(); it++)
    764     {
    765         Client *client = (*it).second;
    766 
    767         if (client->id() == id) {
    768             focusClient(client);
    769         }
    770     }
    771 }
    772 
    773 void Monitor::focusClientByName(string name) {
    774 
    775     for (MClient::iterator it = clients_.begin();
    776             it != clients_.end(); it++)
    777     {
    778         Client *client = (*it).second;
    779 
    780         if (client->name() == name) {
    781             focusClient(client);
    782         }
    783     }
    784 }
    785 
    786 Workspace *Monitor::workspaceForName(string name) {
    787 
    788     for (LWorkspace::iterator it = begin(); it != end(); it++) {
    789         if ((*it)->name() == name) {
    790             return (Workspace *)*it;
    791         }
    792     }
    793     return 0;
    794 }
    795 
    796 void Monitor::focusWorkspaceNum(unsigned int workspaceNum) {
    797 
    798     unsigned int i = 0;
    799     for (LWorkspace::iterator it = begin(); it != end(); it++) {
    800         if (i == workspaceNum) {
    801             focus(*it);
    802             return;
    803         }
    804         i++;
    805     }
    806 }
    807 
    808 void Monitor::destroyWorkspace(Workspace *workspace) {
    809 
    810     assert(workspace);
    811     if (size() > 1) {
    812         LClient *clients = workspace->clients();
    813         while (clients->size()) {
    814             Client *client = *clients->begin();
    815             detachClient(client);
    816             KERNEL->killClient(client);
    817         }
    818         detach(workspace);
    819         Util::remove(sessionSettings_, workspace->prefix());
    820         delete workspace;
    821         focused()->show();
    822         updateBars();
    823     }
    824 }
    825 
    826 void Monitor::renameWorkspace(Workspace *workspace, string newName) {
    827     workspace->setName(newName);
    828     (*sessionSettings_)[workspace->prefix() + ".name"] = newName;
    829 }
    830 
    831 void Monitor::updateBars() {
    832 
    833     static string value;
    834 
    835     if (XCORE->textProperty(rootWindow_, Atoms::WMI_STATUSTEXT, &value)) {
    836         statusBar_->setText(value);
    837     }
    838     if (XCORE->textProperty(rootWindow_, Atoms::WMI_METERTEXT, &value)) {
    839         statusBar_->setMeterText(value);
    840     }
    841 
    842     LOGDEBUG("update status");
    843     statusBar_->illuminate();
    844     clientBar_->illuminate();
    845     XCORE->sync();
    846 }
    847 
    848 void Monitor::toggleThingMaximization() {
    849 
    850     if (!focused()) {
    851         return;
    852     }
    853 
    854     if (maxThing_) {
    855 
    856         maxThing_->copy(maxThing_->prevRectangle());
    857         maxThing_->resize();
    858         focused()->illuminate();
    859         maxThing_ = 0; // reset
    860 
    861     }
    862     else {
    863 
    864         Workspace *workspace = focused();
    865         maxThing_ = workspace->focusedThing();
    866 
    867         if (!maxThing_) {
    868             return;
    869         }
    870 
    871         maxThing_->prevRectangle()->copy(maxThing_);
    872         maxThing_->setX(x());
    873         maxThing_->setY(y());
    874         maxThing_->setWidth(width());
    875         maxThing_->setHeight(height());
    876         maxThing_->resize();
    877         XCORE->raise(maxThing_->window());
    878         maxThing_->illuminate();
    879     }
    880 }
    881 
    882 void Monitor::illuminateTransRect(Rectangle *rect, unsigned int barHeight)
    883 {
    884     Draw::drawTransRectangle(rootWindow_, pseudoBorderGC_, rect, barHeight,
    885                              KERNEL->borderWidth());
    886 
    887     // additional size info
    888     ostringstream oss;
    889     oss << "x=" << rect->x()  << ", y=" << rect->y()
    890         << ": " << rect->width() << "x" << rect->height();
    891 
    892     illuminateTransText(rect, oss.str());
    893 }
    894 
    895 unsigned int Monitor::nextClientId() {
    896     ++clientIds_;
    897     return clientIds_;
    898 }
    899 
    900 void Monitor::illuminateTransText(Rectangle *rect, string text)
    901 {
    902     WFont *font = (font_->type() == WFont::NORMAL) ?
    903                     font_ : fixed_;
    904 
    905     // additional size info
    906     int textWidth = font->textWidth(text);
    907     unsigned int fontBaseLine = font->ascent();
    908     unsigned int fontY = rect->y() + rect->height() / 2
    909                 - font->height() / 2 + fontBaseLine;
    910 
    911     unsigned int fontX = rect->x() +
    912                 (rect->width() / 2 - textWidth / 2);
    913     font->drawText(rootWindow_, pseudoBorderGC_,
    914                     fontX, fontY, text);
    915 }
    916 
    917 
    918 unsigned int Monitor::id() const {
    919     return id_;
    920 }
    921 
    922 Window Monitor::rootWindow() const {
    923     return rootWindow_;
    924 }
    925 
    926 string Monitor::displayString() const {
    927     return displayString_;
    928 }
    929 
    930 Theme *Monitor::theme() const {
    931     return theme_;
    932 }
    933 
    934 unsigned int Monitor::resizeFactor() const {
    935     return resizeFactor_;
    936 }
    937 
    938 string Monitor::prefix() const {
    939     return prefix_;
    940 }
    941 
    942 Box *Monitor::box() const {
    943     return box_;
    944 }
    945 
    946 StatusBar *Monitor::statusBar() const {
    947     return statusBar_;
    948 }
    949 
    950 ClientBar *Monitor::clientBar() const {
    951     return clientBar_;
    952 }
    953 
    954 CClient *Monitor::detachedClients() {
    955     return &detachedClients_;
    956 }
    957 
    958 bool Monitor::isThingMaximized() {
    959     return maxThing_ != 0;
    960 }
    961 
    962 GC Monitor::borderGC() {
    963     return borderGC_;
    964 }
    965 
    966 CClient *Monitor::stickyClients() {
    967     return &stickyClients_;
    968 }
    969 
    970 WFont *Monitor::font() const {
    971     return font_;
    972 }
    973 
    974 unsigned int Monitor::titleBarHeight() const {
    975     return font_->height() + 2;
    976 }
    977 
    978 MClient *Monitor::clients() {
    979     return &clients_;
    980 }
    981 
    982 InputBar *Monitor::inputBar() const {
    983     return inputBar_;
    984 }
    985 
    986 void Monitor::banish() {
    987     XCORE->warpPointer(rootWindow_, width(), height());
    988 }
    989 
    990 unsigned int Monitor::buttonWidth() const {
    991     return font_->height() + 4;
    992 }
    993 
    994 void Monitor::hookClient() {
    995 
    996     Client *client = 0;
    997 #ifdef SLOT_SUPPORT
    998     if (slot_->isGrabFocus() ||
    999         (!focused()->clients()->size() && slot_->focused()->focused()))
   1000     {
   1001         client = slot_->focused()->focused();
   1002         if (client) {
   1003             client->setHooked(slot_->tabName());
   1004             return;
   1005         }
   1006     }
   1007     else
   1008 #endif // SLOT_SUPPORT 
   1009     {
   1010         client = focused()->topClient();
   1011         if (client) {
   1012             client->setHooked(focused()->name());
   1013         }
   1014     }
   1015 }
   1016 
   1017 void Monitor::unhookClient() {
   1018 
   1019     Client *client = 0;
   1020 #ifdef SLOT_SUPPORT
   1021     if (slot_->isGrabFocus() ||
   1022         (!focused()->clients()->size() && slot_->focused()->focused()))
   1023     {
   1024         client = slot_->focused()->focused();
   1025         if (client) {
   1026             client->setHooked("");
   1027             return;
   1028         }
   1029     }
   1030     else
   1031 #endif // SLOT_SUPPORT
   1032     {
   1033         client = focused()->topClient();
   1034         if (client) {
   1035             client->setHooked("");
   1036         }
   1037     }
   1038 }