wmi

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

clientbar.cpp (10313B)


      1 // Copyright (c) 2003 - 2009 Anselm R Garbe <anselm@garbe.us>
      2 // See LICENSE for license details.
      3 
      4 #include <list>
      5 #include <string>
      6 #include <sstream>
      7 
      8 #include "clientbar.h"
      9 
     10 #include "client.h"
     11 #include "cursors.h"
     12 #include "draw.h"
     13 #include "frame.h"
     14 #include "label.h"
     15 #include "logger.h"
     16 #include "menu.h"
     17 #include "monitor.h"
     18 #include "theme.h"
     19 #include "thing.h"
     20 #include "validators.h"
     21 #include "workspace.h"
     22 #include "xcore.h"
     23 
     24 ClientBar::ClientBar(Monitor *monitor, Rectangle *rect)
     25     : Bar(monitor, rect)
     26 {
     27     isModeButtonPressed_ = isMenuButtonPressed_ = false;
     28     mode_ = PAGER;
     29     menu_ = new Menu(monitor);
     30 }
     31 
     32 ClientBar::~ClientBar() {
     33 }
     34 
     35 void ClientBar::illuminate() {
     36 
     37     if (!isVisible()) {
     38         return;
     39     }
     40 
     41     LOGDEBUG("going to draw border");
     42     drawBorder();
     43 
     44     label_->setText("");
     45     label_->setX(1);
     46     label_->setWidth(width() - 2);
     47     label_->update(theme_->BAR_BACKGROUND, theme_->BAR_TEXT,
     48                    theme_->BAR_SHINE, theme_->BAR_SHADOW);
     49 
     50     updateMenuButton();
     51     if (mode_ == PAGER) {
     52         updateClientPager();
     53     }
     54     else {
     55         updateClientInfo();
     56     }
     57     updateModeButton();
     58 }
     59 
     60 
     61 void ClientBar::updateClientPager() {
     62 
     63     Workspace *workspace = monitor()->focused();
     64     CClient *clients = workspace->floatingClients();
     65     if (clients->size() > 0) {
     66         unsigned int offsetX = isButtonVisible_ ? monitor()->buttonWidth() + 3 : 1;
     67         unsigned int clientsWidth = width() - 2;
     68         if (isButtonVisible_) {
     69            clientsWidth -= (2 * monitor()->buttonWidth() + 4);
     70         }
     71         unsigned int i = 0;
     72         unsigned int clientWidth = clientsWidth / clients->size();
     73         label_->setWidth(clientWidth);
     74         for (LClient::iterator it = clients->begin(); it != clients->end(); ) {
     75             Client *client = *it;
     76             it++;
     77 
     78             label_->setX(offsetX + i * clientWidth);
     79             if (it == clients->end()) {
     80                 // FIX for right button irretations
     81                 label_->setWidth(width() - label_->x()
     82                         - (isButtonVisible_ ? monitor()->buttonWidth() + 3 : 1));
     83             }
     84             unsigned long shine, shadow;
     85             label_->setText(client->name());
     86             if (client->isFocused()) {
     87                 shine = theme_->TAB_SHINE_ACTIVE_FOCUSSED;
     88                 shadow = theme_->TAB_SHADOW_ACTIVE_FOCUSSED;
     89                 label_->update(theme_->TAB_BACKGROUND_ACTIVE_FOCUSSED,
     90                         theme_->TAB_TEXT_ACTIVE_FOCUSSED,
     91                         shine, shadow, true, true);
     92             }
     93             else if (client->requestsFocus()) {
     94                 shine = theme_->FOCUSREQ_SHINE;
     95                 shadow = theme_->FOCUSREQ_SHADOW;
     96                 label_->update(theme_->FOCUSREQ_BACKGROUND,
     97                                theme_->FOCUSREQ_TEXT,
     98                                shine, shadow, true, true);
     99             }
    100             else {
    101                 shine = theme_->TAB_SHINE_ACTIVE_NORMAL;
    102                 shadow = theme_->TAB_SHADOW_ACTIVE_NORMAL;
    103                 label_->update(theme_->TAB_BACKGROUND_ACTIVE_NORMAL,
    104                         theme_->TAB_TEXT_ACTIVE_NORMAL,
    105                         shine, shadow, true, true);
    106             }
    107 
    108             if (client->mode() == Client::STICKY) {
    109                 Draw::drawStickyNotifier(window(), gc(), label_,
    110                                          shine, shadow,
    111                                          label_->textWidth());
    112             }
    113             i++;
    114         }
    115     }
    116 }
    117 
    118 void ClientBar::updateMenuButton() {
    119 
    120     // button stuff
    121     if (!isButtonVisible_) {
    122         return;
    123     }
    124 
    125     label_->setText("");
    126     label_->setX(1);
    127     label_->setWidth(monitor()->buttonWidth());
    128     if (isMenuButtonPressed_) {
    129         Draw::drawMenuButton(window(), gc(), label_,
    130                 theme_->BUTTON_BACKGROUND_PRESSED,
    131                 theme_->BUTTON_SHINE_BORDER_PRESSED,
    132                 theme_->BUTTON_SHADOW_BORDER_PRESSED,
    133                 theme_->BUTTON_SHINE_FIGURE_PRESSED,
    134                 theme_->BUTTON_SHADOW_FIGURE_PRESSED);
    135     }
    136     else {
    137         Draw::drawMenuButton(window(), gc(), label_,
    138                 theme_->BUTTON_BACKGROUND_NORMAL,
    139                 theme_->BUTTON_SHINE_BORDER_NORMAL,
    140                 theme_->BUTTON_SHADOW_BORDER_NORMAL,
    141                 theme_->BUTTON_SHINE_FIGURE_NORMAL,
    142                 theme_->BUTTON_SHADOW_FIGURE_NORMAL);
    143     }
    144 }
    145 
    146 void ClientBar::updateModeButton() {
    147 
    148     // button stuff
    149     if (!isButtonVisible_) {
    150         return;
    151     }
    152 
    153     Workspace *workspace = monitor()->focused();
    154 
    155     label_->setText("");
    156     label_->setX(width() - monitor()->buttonWidth() - 1);
    157     label_->setWidth(monitor()->buttonWidth());
    158     if (isModeButtonPressed_) {
    159         if (workspace->isFrameMode()) {
    160             Draw::drawFloatButton(window(), gc(), label_,
    161                     theme_->BUTTON_BACKGROUND_PRESSED,
    162                     theme_->BUTTON_SHINE_BORDER_PRESSED,
    163                     theme_->BUTTON_SHADOW_BORDER_PRESSED,
    164                     theme_->BUTTON_SHINE_FIGURE_PRESSED,
    165                     theme_->BUTTON_SHADOW_FIGURE_PRESSED,
    166                     workspace->floatingClients()->size());
    167         }
    168         else {
    169             Draw::drawMaxButton(window(), gc(), label_,
    170                     theme_->BUTTON_BACKGROUND_PRESSED,
    171                     theme_->BUTTON_SHINE_BORDER_PRESSED,
    172                     theme_->BUTTON_SHADOW_BORDER_PRESSED,
    173                     theme_->BUTTON_SHINE_FIGURE_PRESSED,
    174                     theme_->BUTTON_SHADOW_FIGURE_PRESSED,
    175                     workspace->focusedFrame() &&
    176                     workspace->focusedFrame()->size());
    177         }
    178     }
    179     else {
    180         if (workspace->isFrameMode()) {
    181             Draw::drawFloatButton(window(), gc(), label_,
    182                     theme_->BUTTON_BACKGROUND_NORMAL,
    183                     theme_->BUTTON_SHINE_BORDER_NORMAL,
    184                     theme_->BUTTON_SHADOW_BORDER_NORMAL,
    185                     theme_->BUTTON_SHINE_FIGURE_NORMAL,
    186                     theme_->BUTTON_SHADOW_FIGURE_NORMAL,
    187                     workspace->floatingClients()->size());
    188         }
    189         else {
    190             Draw::drawMaxButton(window(), gc(), label_,
    191                     theme_->BUTTON_BACKGROUND_NORMAL,
    192                     theme_->BUTTON_SHINE_BORDER_NORMAL,
    193                     theme_->BUTTON_SHADOW_BORDER_NORMAL,
    194                     theme_->BUTTON_SHINE_FIGURE_NORMAL,
    195                     theme_->BUTTON_SHADOW_FIGURE_NORMAL,
    196                     workspace->focusedFrame() &&
    197                     workspace->focusedFrame()->size());
    198         }
    199     }
    200 }
    201 
    202 void ClientBar::updateClientInfo() {
    203 
    204     // client info stuff
    205     Workspace *focusedWorkspace = monitor()->focused();
    206     Client *client = focusedWorkspace->topClient();
    207     unsigned int offsetX = isButtonVisible_ ? monitor()->buttonWidth() + 3 : 1;
    208     unsigned int clientInfoWidth = width() - 2;
    209     if (isButtonVisible_) {
    210         clientInfoWidth -= (2 * monitor()->buttonWidth() + 4);
    211     }
    212     label_->setX(offsetX);
    213     label_->setWidth(clientInfoWidth);
    214     label_->setText(client ? client->name() : "");
    215     label_->update(theme_->LABEL_BACKGROUND_FOCUSSED,
    216             theme_->LABEL_TEXT_FOCUSSED,
    217             theme_->LABEL_SHINE_FOCUSSED,
    218             theme_->LABEL_SHADOW_FOCUSSED,
    219             true, true);
    220     if (client->mode() == Client::STICKY) {
    221         Draw::drawStickyNotifier(window(), gc(), label_,
    222                                  theme_->LABEL_SHINE_FOCUSSED,
    223                                  theme_->LABEL_SHADOW_FOCUSSED,
    224                                  label_->textWidth());
    225     }
    226 }
    227 
    228 void ClientBar::handleButtonRelease(XButtonEvent *event) {
    229 
    230     if ((event->window != window())) {
    231         return;
    232     }
    233 
    234     if (isModeButtonPressed_) {
    235         isModeButtonPressed_ = false;
    236         Workspace *ws = monitor()->focused();
    237         if ((event->button == Button1) &&
    238             Validators::instance()->validateToggleMode())
    239         {
    240             ws->toggleMode();
    241         }
    242         illuminate();
    243     }
    244     else if (isMenuButtonPressed_) {
    245         toggleMenuMode();
    246     }
    247 }
    248 
    249 void ClientBar::toggleMenuMode() {
    250 
    251     if (menu_->isVisible()) {
    252         menu_->hide();
    253         isMenuButtonPressed_ = false;
    254     }
    255     else {
    256         menu_->show();
    257     }
    258     illuminate();
    259 }
    260 
    261 void ClientBar::handleButtonPress(XButtonEvent *event) {
    262 
    263     if ((event->window != window())) {
    264         return;
    265     }
    266 
    267     XCORE->raise(window());
    268 
    269     // TODO: make buttons customizable
    270     if (event->button == Button1) {
    271         invokeClickedThing(event->x);
    272     }
    273     else if (event->button == Button4) {
    274         monitor()->focused()->cycleClientPrev();
    275     }
    276     else if (event->button == Button5) {
    277         monitor()->focused()->cycleClientNext();
    278     }
    279 }
    280 
    281 void ClientBar::handleMotionNotify(XMotionEvent *event) {
    282 
    283     if (isModeButtonPressed_) {
    284         isModeButtonPressed_ = false;
    285         illuminate();
    286     }
    287 }
    288 
    289 void ClientBar::invokeClickedThing(int xPosition) {
    290 
    291     if (isButtonVisible_) {
    292         if (xPosition < (int)(monitor()->buttonWidth() + 1)) {
    293             isMenuButtonPressed_ = true;
    294         }
    295         else if (xPosition > (int)(width() - monitor()->buttonWidth() - 2)) {
    296             isModeButtonPressed_ = true;
    297         }
    298         illuminate();
    299         if (isModeButtonPressed_ || isMenuButtonPressed_) {
    300             return;
    301         }
    302     }
    303 
    304     if (mode_ != PAGER) {
    305         illuminate();
    306         return;
    307     }
    308 
    309     Workspace *workspace = monitor()->focused();
    310     unsigned int clientsWidth = width() - 2;
    311     if (isButtonVisible_) {
    312         clientsWidth -= (2 * monitor()->buttonWidth() + 4);
    313         xPosition -= (monitor()->buttonWidth() + 3);
    314     }
    315     else {
    316         xPosition -= 1;
    317     }
    318 
    319     CClient *clients = workspace->floatingClients();
    320     if (!clients->size()) {
    321         return;
    322     }
    323 
    324     unsigned int clientNum = xPosition / (clientsWidth / clients->size());
    325     unsigned i = 0;
    326     for (LClient::iterator it = clients->begin(); it != clients->end(); it++) {
    327         if (i == clientNum) {
    328             workspace->focus(*it);
    329             illuminate();
    330             return;
    331         }
    332         i++;
    333     }
    334 }
    335 
    336 Menu *ClientBar::menu() const {
    337     return menu_;
    338 }
    339 
    340 void ClientBar::setMode(ClientBar::Mode mode) {
    341     mode_ = mode;
    342 }
    343 
    344 ClientBar::Mode ClientBar::mode() const {
    345     return mode_;
    346 }