wmi

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

thing.cpp (10483B)


      1 // Copyright (c) 2003 - 2009 Anselm R Garbe <anselm@garbe.us>
      2 // See LICENSE for license details.
      3 
      4 #include "thing.h"
      5 
      6 #include "client.h"
      7 #include "cursors.h"
      8 #include "draw.h"
      9 #include "font.h"
     10 #include "frame.h"
     11 #include "kernel.h"
     12 #include "label.h"
     13 #include "logger.h"
     14 #include "monitor.h"
     15 #include "theme.h"
     16 #include "workspace.h"
     17 #include "xcore.h"
     18 #include "xfont.h"
     19 
     20 Thing::Thing(Monitor *monitor, Rectangle *rect, Type type)
     21     : Rectangle(*rect)
     22 {
     23     monitor_ = monitor;
     24     type_ = type;
     25     isVisible_ = false;
     26     hasDecoration_ = false;
     27     clientAreaRect_ = Rectangle(*rect);
     28     name_ = "";
     29 
     30     // view
     31     theme_ = monitor_->theme();
     32 
     33     areButtonsVisible_ =
     34         (Util::get(KERNEL->commonSettings(), "frame.buttons") == "yes");
     35 
     36     cursor_ = Cursors::NORMAL_CURSOR;
     37     prevRect_ = new Rectangle(*rect);
     38     buttonState_ = NONE;
     39 
     40     // creates frame window
     41     if (type == FRAME) {
     42         initFrameWindow();
     43         fitClientArea();
     44     }
     45     else {
     46         frameWindow_ = 0;
     47         gc_ = 0;
     48         label_ = 0;
     49         titleBarHeight_ = 0;
     50         borderWidth_ = 0;
     51     }
     52 }
     53 
     54 Thing::~Thing() {
     55     delete prevRect_;
     56 
     57     if (frameWindow_) {
     58         delete label_;
     59         XCORE->free(gc_);
     60         XCORE->destroy(frameWindow_);
     61         LOGDEBUG("frame destroyed");
     62     }
     63 }
     64 
     65 void Thing::initFrameWindow() {
     66 
     67     titleBarHeight_ =
     68         (Util::get(KERNEL->commonSettings(), "default.bar-mode")
     69          == "show") ? monitor_->titleBarHeight() : 0;
     70     borderWidth_ = 
     71         (Util::get(KERNEL->commonSettings(), "default.border-mode")
     72          == "show") ? KERNEL->borderWidth() : 0;
     73 
     74     if (type_ == CLIENT) {
     75         setX(x() - borderWidth_);
     76         setY(y() - titleBarHeight_ - borderWidth_ - 1);
     77         setWidth(width() + 2 * borderWidth_);
     78         setHeight(height() + titleBarHeight_ + 2 * borderWidth_ + 1);
     79     }
     80 
     81     XSetWindowAttributes attr;
     82     attr.background_pixmap = ParentRelative;
     83     attr.override_redirect = 1;
     84     frameWindow_ = XCORE->createWindow(this->monitor()->rootWindow(), &attr,
     85                                        x(), y(), width(), height(),
     86                                        CWOverrideRedirect | CWBackPixmap);
     87 
     88     LOGDEBUG("init GC for frame");
     89     initGC();
     90     label_ = new Label(this->monitor(), frameWindow_, Label::CENTER, gc_);
     91     label_->setY(borderWidth_);
     92     label_->setHeight(titleBarHeight_);
     93 
     94     XCORE->selectEvents(frameWindow_,
     95             ExposureMask | SubstructureRedirectMask | SubstructureNotifyMask |
     96             ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
     97 
     98     KERNEL->installCursor(Cursors::NORMAL_CURSOR, frameWindow_);
     99     hasDecoration_ = true;
    100 }
    101 
    102 Thing::Type Thing::type() const {
    103     return type_;
    104 }
    105 
    106 Monitor *Thing::monitor() const {
    107     return monitor_;
    108 }
    109 
    110 bool Thing::isVisible() const {
    111     return isVisible_;
    112 }
    113 
    114 void Thing::initGC() {
    115 
    116     if (frameWindow_) {
    117         unsigned long mask =
    118             GCForeground | GCBackground |
    119             GCFunction | GCLineWidth | GCLineStyle;
    120 
    121         XGCValues gcv;
    122         gcv.function = GXcopy;
    123         gcv.line_width = 1;
    124         gcv.line_style = LineSolid;
    125         if (monitor()->font()->type() == WFont::NORMAL) {
    126             gcv.font = ((XFont *)monitor()->font())->font()->fid;
    127             mask |= GCFont;
    128         }
    129         gc_ = XCORE->createGC(frameWindow_, mask, &gcv);
    130     }
    131 }
    132 
    133 void Thing::illuminateBorder() {
    134 
    135     if (!isVisible_ || !frameWindow_) {
    136         return;
    137     }
    138 
    139     bool focused = isFocused();
    140 
    141     if (titleBarHeight_) {
    142         label_->setText("");
    143         label_->setX(borderWidth_);
    144         label_->setWidth(width() - 2 * borderWidth_);
    145 
    146         if (focused) {
    147             label_->update(theme_->FRAME_BACKGROUND_FOCUSSED, 0,
    148                            theme_->FRAME_SHINE_FOCUSSED,
    149                            theme_->FRAME_SHADOW_FOCUSSED);
    150         }
    151         else {
    152             label_->update(theme_->FRAME_BACKGROUND_NORMAL, 0,
    153                            theme_->FRAME_SHINE_NORMAL,
    154                            theme_->FRAME_SHADOW_NORMAL);
    155         }
    156     }
    157 
    158     LOGDEBUG("drawing border");
    159     if (focused) {
    160         Draw::drawBorder(frameWindow_, gc_, monitor()->borderGC(), this,
    161                         theme_->FRAME_BACKGROUND_FOCUSSED,
    162                         theme_->FRAME_SHINE_FOCUSSED,
    163                         theme_->FRAME_SHADOW_FOCUSSED,
    164                         titleBarHeight_ + borderWidth_,
    165                         borderWidth_);
    166     }
    167     else {
    168         Draw::drawBorder(frameWindow_, gc_, monitor()->borderGC(), this,
    169                         theme_->FRAME_BACKGROUND_NORMAL,
    170                         theme_->FRAME_SHINE_NORMAL,
    171                         theme_->FRAME_SHADOW_NORMAL,
    172                         titleBarHeight_ + borderWidth_,
    173                         borderWidth_);
    174     }
    175 
    176     if (titleBarHeight_ && areButtonsVisible_ && focused) {
    177 
    178         if (type_ == FRAME && !((Frame *)this)->size()) {
    179             // no need to draw buttons
    180             return;
    181         }
    182 
    183         // detach button
    184         label_->setText("");
    185         label_->setX(width() - borderWidth_ - 3 * monitor_->buttonWidth());
    186         label_->setWidth(monitor_->buttonWidth());
    187         if (buttonState_ != MINCLIENT) {
    188 
    189             Draw::drawDetachButton(frameWindow_, gc_, label_,
    190                            theme_->BUTTON_BACKGROUND_NORMAL,
    191                            theme_->BUTTON_SHINE_BORDER_NORMAL,
    192                            theme_->BUTTON_SHADOW_BORDER_NORMAL,
    193                            theme_->BUTTON_SHINE_FIGURE_NORMAL,
    194                            theme_->BUTTON_SHADOW_FIGURE_NORMAL);
    195         }
    196         else {
    197 
    198             Draw::drawDetachButton(frameWindow_, gc_, label_,
    199                            theme_->BUTTON_BACKGROUND_PRESSED,
    200                            theme_->BUTTON_SHINE_BORDER_PRESSED,
    201                            theme_->BUTTON_SHADOW_BORDER_PRESSED,
    202                            theme_->BUTTON_SHINE_FIGURE_PRESSED,
    203                            theme_->BUTTON_SHADOW_FIGURE_PRESSED);
    204         }
    205 
    206         // (de)max client button
    207         label_->setX(label_->x() + monitor_->buttonWidth());
    208 
    209         if (buttonState_ != DEMAX) {
    210 
    211             if (type_ == CLIENT) {
    212 
    213                 Draw::drawMaxButton(frameWindow_, gc_, label_,
    214                            theme_->BUTTON_BACKGROUND_NORMAL,
    215                            theme_->BUTTON_SHINE_BORDER_NORMAL,
    216                            theme_->BUTTON_SHADOW_BORDER_NORMAL,
    217                            theme_->BUTTON_SHINE_FIGURE_NORMAL,
    218                            theme_->BUTTON_SHADOW_FIGURE_NORMAL);
    219             }
    220             else {
    221 
    222                 Draw::drawFloatButton(frameWindow_, gc_, label_,
    223                            theme_->BUTTON_BACKGROUND_NORMAL,
    224                            theme_->BUTTON_SHINE_BORDER_NORMAL,
    225                            theme_->BUTTON_SHADOW_BORDER_NORMAL,
    226                            theme_->BUTTON_SHINE_FIGURE_NORMAL,
    227                            theme_->BUTTON_SHADOW_FIGURE_NORMAL);
    228             }
    229         }
    230         else {
    231 
    232             if (type_ == CLIENT) {
    233 
    234                 Draw::drawMaxButton(frameWindow_, gc_, label_,
    235                            theme_->BUTTON_BACKGROUND_PRESSED,
    236                            theme_->BUTTON_SHINE_BORDER_PRESSED,
    237                            theme_->BUTTON_SHADOW_BORDER_PRESSED,
    238                            theme_->BUTTON_SHINE_FIGURE_PRESSED,
    239                            theme_->BUTTON_SHADOW_FIGURE_PRESSED);
    240             }
    241             else {
    242 
    243                 Draw::drawFloatButton(frameWindow_, gc_, label_,
    244                            theme_->BUTTON_BACKGROUND_PRESSED,
    245                            theme_->BUTTON_SHINE_BORDER_PRESSED,
    246                            theme_->BUTTON_SHADOW_BORDER_PRESSED,
    247                            theme_->BUTTON_SHINE_FIGURE_PRESSED,
    248                            theme_->BUTTON_SHADOW_FIGURE_PRESSED);
    249             }
    250 
    251         }
    252 
    253         // close button
    254         label_->setX(label_->x() + monitor_->buttonWidth());
    255         if (buttonState_ != CLOSE) {
    256 
    257             Draw::drawCloseButton(frameWindow_, gc_, label_,
    258                     theme_->BUTTON_BACKGROUND_NORMAL,
    259                     theme_->BUTTON_SHINE_BORDER_NORMAL,
    260                     theme_->BUTTON_SHADOW_BORDER_NORMAL,
    261                     theme_->BUTTON_SHINE_FIGURE_NORMAL,
    262                     theme_->BUTTON_SHADOW_FIGURE_NORMAL);
    263         }
    264         else {
    265 
    266             Draw::drawCloseButton(frameWindow_, gc_, label_,
    267                     theme_->BUTTON_BACKGROUND_PRESSED,
    268                     theme_->BUTTON_SHINE_BORDER_PRESSED,
    269                     theme_->BUTTON_SHADOW_BORDER_PRESSED,
    270                     theme_->BUTTON_SHINE_FIGURE_PRESSED,
    271                     theme_->BUTTON_SHADOW_FIGURE_PRESSED);
    272 
    273         }
    274     }
    275 }
    276 
    277 void Thing::handleMotionNotify(XMotionEvent *event) {
    278 
    279     if (monitor()->isThingMaximized()) {
    280         return;
    281     }
    282 
    283     Cursor cursor = cursorForXY(event->x, event->y);
    284 
    285     if (cursor != cursor_) {
    286         cursor_ = cursor;
    287         KERNEL->installCursor(cursor, frameWindow_);
    288     }
    289 
    290     if (buttonState_ != NONE) {
    291         buttonState_ = NONE;
    292         illuminate();
    293     }
    294 }
    295 
    296 void Thing::setTitleBarHeight(unsigned int titleBarHeight) {
    297     titleBarHeight_ = titleBarHeight;
    298 }
    299 
    300 void Thing::setBorderWidth(unsigned int borderWidth) {
    301     borderWidth_ = borderWidth;
    302 }
    303 
    304 unsigned int Thing::borderWidth() const {
    305     return borderWidth_;
    306 }
    307 
    308 unsigned int Thing::titleBarHeight() const {
    309     return titleBarHeight_;
    310 }
    311 
    312 Rectangle *Thing::prevRectangle() const {
    313     return prevRect_;
    314 }
    315 
    316 Thing::InvertButton Thing::buttonState() const {
    317     return buttonState_;
    318 }
    319 
    320 void Thing::setButtonState(InvertButton state) {
    321     buttonState_ = state;
    322 }
    323 
    324 void Thing::show() {
    325     if (frameWindow_) {
    326         XCORE->show(frameWindow_);
    327         isVisible_ = true;
    328     }
    329 }
    330 
    331 void Thing::hide() {
    332     if (frameWindow_) {
    333         XCORE->hide(frameWindow_);
    334         isVisible_ = false;
    335     }
    336 }
    337 
    338 void Thing::fitClientArea() {
    339 
    340     clientAreaRect_.setX(borderWidth_);
    341     clientAreaRect_.setY(titleBarHeight_ + borderWidth_ +
    342                          (titleBarHeight_ ? 1 : 0));
    343     clientAreaRect_.setWidth(width() - 2 * borderWidth_);
    344     clientAreaRect_.setHeight(height() - titleBarHeight_
    345                               - 2 * borderWidth_
    346                               - (titleBarHeight_ ? 1 : 0));
    347 }
    348 
    349 void Thing::setName(string name) {
    350     name_ = name;
    351 }
    352 
    353 string Thing::name() const {
    354     return name_;
    355 }
    356 
    357 bool Thing::hasDecoration() const {
    358     return hasDecoration_;
    359 }