src/frame.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: frame.cpp 2 2007-05-16 10:38:27Z eg $
00005 
00006 extern "C" {
00007 #include <assert.h>
00008 }
00009 
00010 #include <sstream>
00011 
00012 #include "frame.h"
00013 
00014 #include "client.h"
00015 #include "cursors.h"
00016 #include "draw.h"
00017 #include "frame.h"
00018 #include "kernel.h"
00019 #include "label.h"
00020 #include "logger.h"
00021 #include "monitor.h"
00022 #include "split.h"
00023 #include "theme.h"
00024 #include "tree.h"
00025 #include "util.h"
00026 #include "workspace.h"
00027 #include "xcore.h"
00028 
00029 Frame::Frame(Workspace *workspace, Rectangle *rect)
00030     : Thing(workspace->attached(), rect, Thing::FRAME),
00031       Container<Workspace, LClient, LClient::iterator, Client>(workspace)
00032 {
00033     ostringstream oss;
00034     oss << "<" << workspace->nextFrameId() << ">";
00035     setName(oss.str());
00036     isTiled_ = Util::get(KERNEL->commonSettings(), "frame.mode") == "tiled";
00037 }
00038 
00039 Frame::~Frame() {
00040 }
00041 
00042 bool Frame::isFocused() {
00043     bool result = attached() && attached()->focusedFrame() == this;
00044     if (focused()) {
00045         result = result && (focused() == attached()->topClient());
00046     }
00047     return result;
00048 }
00049 
00050 void Frame::focus(Client *client) {
00051 
00052     Container<Workspace, LClient, LClient::iterator, Client>
00053           ::focus(client);
00054     XCORE->raise(client->clientWindow());
00055 }
00056 
00057 void Frame::illuminate() {
00058 
00059     if (!isVisible()) {
00060         return;
00061     }
00062 
00063     illuminateBorder();
00064 
00065     bool foc = this->isFocused();
00066 
00067     if (titleBarHeight_) {
00068 
00069         unsigned int buttonWidth = 0;
00070         unsigned int labelsWidth = width() - 2 * borderWidth_;
00071         unsigned int offsetX = borderWidth_;
00072         if (foc && areButtonsVisible_) {
00073             buttonWidth = monitor()->buttonWidth();
00074             labelsWidth -= (3 * buttonWidth) - 3;
00075         }
00076 
00077         unsigned int labelWidth = size() ? labelsWidth / size() : labelsWidth;
00078 
00079         unsigned int i = 0;
00080         label_->setWidth(labelWidth);
00081         for (LClient::iterator it = begin(); it != end(); ) {
00082 
00083             Client *client = *it;
00084             it++;
00085 
00086             label_->setText(client->name());
00087             label_->setX(offsetX + i * labelWidth);
00088             if (it == end()) {
00089                 // FIX for right button panel irretations
00090                 label_->setWidth(
00091                         width() - label_->x() - 3 * buttonWidth -
00092                         ((foc && areButtonsVisible_) ? 3 + borderWidth_ : borderWidth_));
00093             }
00094             i++;
00095             if (foc) { // FOCUSSED
00096                 if (client == focused()) {
00097                     label_->update(theme_->TAB_BACKGROUND_ACTIVE_FOCUSSED,
00098                                    theme_->TAB_TEXT_ACTIVE_FOCUSSED,
00099                                    theme_->TAB_SHINE_ACTIVE_FOCUSSED,
00100                                    theme_->TAB_SHADOW_ACTIVE_FOCUSSED,
00101                                    true, true);
00102                 }
00103                 else if (client->requestsFocus()) {
00104                     label_->update(theme_->FOCUSREQ_BACKGROUND,
00105                                    theme_->FOCUSREQ_TEXT,
00106                                    theme_->FOCUSREQ_SHINE,
00107                                    theme_->FOCUSREQ_SHADOW,
00108                                    true, true);
00109                 }
00110                 else {
00111                     label_->update(theme_->TAB_BACKGROUND_INACTIVE_FOCUSSED,
00112                                    theme_->TAB_TEXT_INACTIVE_FOCUSSED,
00113                                    theme_->TAB_SHINE_INACTIVE_FOCUSSED,
00114                                    theme_->TAB_SHADOW_INACTIVE_FOCUSSED,
00115                                    true, true);
00116                 }
00117             }
00118             else { // NORMAL
00119                 if (client == focused()) {
00120                     label_->update(theme_->TAB_BACKGROUND_ACTIVE_NORMAL,
00121                                    theme_->TAB_TEXT_ACTIVE_NORMAL,
00122                                    theme_->TAB_SHINE_ACTIVE_NORMAL,
00123                                    theme_->TAB_SHADOW_ACTIVE_NORMAL,
00124                                    true, true);
00125                 }
00126                 else if (client->requestsFocus()) {
00127                     label_->update(theme_->FOCUSREQ_BACKGROUND,
00128                                    theme_->FOCUSREQ_TEXT,
00129                                    theme_->FOCUSREQ_SHINE,
00130                                    theme_->FOCUSREQ_SHADOW,
00131                                    true, true);
00132                 }
00133                 else {
00134                     label_->update(theme_->TAB_BACKGROUND_INACTIVE_NORMAL,
00135                                    theme_->TAB_TEXT_INACTIVE_NORMAL,
00136                                    theme_->TAB_SHINE_INACTIVE_NORMAL,
00137                                    theme_->TAB_SHADOW_INACTIVE_NORMAL,
00138                                    true, true);
00139                 }
00140             }
00141         }
00142         if (!size()) {
00143             label_->setText("<empty>" + name());
00144             if (foc) { // FOCUSSED
00145                 label_->update(theme_->TAB_BACKGROUND_ACTIVE_FOCUSSED,
00146                         theme_->TAB_TEXT_ACTIVE_FOCUSSED,
00147                         theme_->TAB_SHINE_ACTIVE_FOCUSSED,
00148                         theme_->TAB_SHADOW_ACTIVE_FOCUSSED,
00149                         true, true);
00150             }
00151             else { // NORMAL
00152                 label_->update(theme_->TAB_BACKGROUND_ACTIVE_NORMAL,
00153                         theme_->TAB_TEXT_ACTIVE_NORMAL,
00154                         theme_->TAB_SHINE_ACTIVE_NORMAL,
00155                         theme_->TAB_SHADOW_ACTIVE_NORMAL,
00156                         true, true);
00157             }
00158         }
00159     }
00160     if (isTiled_) {
00161         unsigned shine, shadow;
00162         for (LClient::iterator it = begin(); it != end(); it++) {
00163             Client *client = *it;
00164             if (foc && client == focused()) {
00165                 shine = theme_->TILED_SHINE_FOCUSSED;
00166                 shadow = theme_->TILED_SHADOW_FOCUSSED;
00167             }
00168             else {
00169                 shine = theme_->TILED_SHINE_NORMAL;
00170                 shadow = theme_->TILED_SHADOW_NORMAL;
00171             }
00172             Rectangle rect;
00173             rect.setX(client->x() - 1);
00174             rect.setY(client->y() - 1);
00175             rect.setWidth(client->width() + 2);
00176             rect.setHeight(client->height() + 2);
00177             Draw::drawRectBorder(frameWindow_, gc_, &rect, shine, shadow);
00178         }
00179     }
00180 }
00181 
00182 void Frame::resize() {
00183 
00184     label_->setY(borderWidth_);
00185     XCORE->clearWindow(window());
00186     XCORE->moveResize(window(), this);
00187 
00188     fitClientArea();
00189     if (isTiled_ && size() > 1) {
00190         unsigned int colWidth =
00191             Util::strToUInt(Util::get(KERNEL->commonSettings(), "frame.colwidth"));
00192 
00193         colWidth = (clientAreaRect_.width() * colWidth) / 100;
00194         unsigned int stackHeight = clientAreaRect_.height() / (size() - 1);
00195         unsigned int i = 0;
00196 
00197         for (LClient::iterator it = begin(); it != end(); it++) {
00198             Client *client = *it;
00199             if (it == begin()) {
00200                 // left column
00201                 client->copy(&clientAreaRect_);
00202                 client->setX(clientAreaRect_.x() + 1);
00203                 client->setY(clientAreaRect_.y() + 1);
00204                 client->setWidth(colWidth - 2);
00205                 client->setHeight(clientAreaRect_.height() - 2);
00206             }
00207             else {
00208                 // right column
00209                 client->setX(clientAreaRect_.x() + colWidth + 1);
00210                 client->setY(i * stackHeight + clientAreaRect_.y() + 1);
00211                 client->setHeight(stackHeight - 2);
00212                 client->setWidth(clientAreaRect_.width() - colWidth - 2);
00213                 i++;
00214             }
00215             client->resize();
00216         }
00217     }
00218     else {
00219         for (LClient::iterator it = begin(); it != end(); it++) {
00220             Client *client = *it;
00221             matchClientSize(client);
00222         }
00223     }
00224     illuminate();
00225 }
00226 
00227 void Frame::matchClientSize(Client *client)
00228 {
00229     client->copy(&clientAreaRect_);
00230     client->resize();
00231 }
00232 
00233 void Frame::attach(Client *client) {
00234 
00235     if (client->frame() == this) {
00236         LOGWARN("frame already attached.");
00237         return;
00238     }
00239     Container<Workspace, LClient, LClient::iterator, Client>
00240         ::attach(client);
00241     client->setFrame(this);
00242     client->prevRectangle()->copy(client);
00243     client->reparent(window(), clientAreaRect_.x(), clientAreaRect_.y());
00244     XCORE->sync();
00245     if (isVisible()) {
00246         client->show();
00247     }
00248     childs()->remove(client);
00249     childs()->push_front(client);
00250     resize();
00251     LOGDEBUG("attached client to frame");
00252 }
00253 
00254 Client *Frame::detach(Client *client) {
00255 
00256     assert(size() > 0);
00257     XCORE->sync();
00258     LOGDEBUG("detaching clientframe");
00259     Client *next = Container<Workspace, LClient, LClient::iterator, Client>
00260                     ::detach(client);
00261     if (client->isVisible()) {
00262         client->hide();
00263     }
00264     if (size() > 0) {
00265         assert(next);
00266     }
00267     client->reparent(monitor()->rootWindow(), client->x(), client->y());
00268     client->copy(client->prevRectangle());
00269     client->setFrame(0);
00270     if (next) {
00271         resize();
00272     }
00273     return next;
00274 }
00275 
00276 void Frame::handleButtonPress(XButtonEvent *event) {
00277 
00278     // TODO: make buttons customizable
00279     if (event->button == Button1) {
00280 
00281         if (!isFocused()) {
00282             attached()->focus(focused());
00283             return;
00284         }
00285         else {
00286             XCORE->raise(window());
00287         }
00288 
00289         buttonState_ = NONE;
00290         if (titleBarHeight_ && (cursor_ == Cursors::NORMAL_CURSOR) && size()) {
00291             LOGDEBUG("normal cursor / switching client");
00292             int xPosition = event->x;
00293             unsigned int buttonWidth = titleBarHeight_ + 1;
00294             if (areButtonsVisible_) {
00295                 unsigned int offsetButtonGroup = width() - borderWidth_ - 3 * buttonWidth;
00296                 if ((xPosition > (int)offsetButtonGroup) &&
00297                         (xPosition < (int)(width() - borderWidth_ - 1)))
00298                 {
00299                     xPosition -= offsetButtonGroup;
00300                     unsigned int buttonNum = xPosition / buttonWidth;
00301                     switch (buttonNum) {
00302                     case 0:
00303                         buttonState_ = MINCLIENT;
00304                         break;
00305                     case 1:
00306                         buttonState_ = DEMAX;
00307                         break;
00308                     case 2:
00309                         buttonState_ = CLOSE;
00310                         break;
00311                     }
00312                     illuminate();
00313                     return;
00314                 }
00315             }
00316 
00317             // handle label click
00318             xPosition -= borderWidth_;
00319             unsigned int labelsWidth = width() - 2 * borderWidth_
00320                 - (areButtonsVisible_ ? (3 * buttonWidth) - 2 : 0);
00321             unsigned int labelWidth = labelsWidth / size();
00322 
00323             unsigned int clientNum = xPosition / labelWidth;
00324             unsigned int i = 0;
00325 
00326             for (LClient::iterator it = begin(); it != end(); it++) {
00327 
00328                 if (i == clientNum) {
00329                     attached()->focus(*it);
00330                     return;
00331                 }
00332                 i++;
00333             }
00334         }
00335 
00336         if (monitor()->isThingMaximized()) {
00337             return;
00338         }
00339 
00340         Direction dir = DOWN;
00341         if (cursor_ == Cursors::RESIZE_LEFT_CURSOR) {
00342             dir = LEFT;
00343         }
00344         else if (cursor_ == Cursors::RESIZE_RIGHT_CURSOR) {
00345             dir = RIGHT;
00346         }
00347         else if (cursor_ == Cursors::RESIZE_UP_CURSOR) {
00348             dir = UP;
00349         }
00350         else if (cursor_ == Cursors::RESIZE_DOWN_CURSOR) {
00351             dir = DOWN;
00352         }
00353 
00354         // Patch applied by Christof Musik
00355         if (cursor_ != Cursors::NORMAL_CURSOR) {
00356 
00357             if (Split::neighbor(attached()->root(), tree_, dir)) {
00358                 Kernel::instance()->runResizeMode(this, event, dir);
00359             }
00360             else if (event->button == Button4) {
00361                 monitor()->focused()->cycleClientPrev();
00362             } else if (event->button == Button5) {
00363                 monitor()->focused()->cycleClientNext();
00364             }
00365         }
00366     }
00367 }
00368 
00369 void Frame::handleButtonRelease(XButtonEvent *event) {
00370 
00371     if (titleBarHeight_ && (event->button == Button1))
00372     {
00373         if ((buttonState_ != NONE) && monitor()->isThingMaximized()) {
00374             monitor()->toggleThingMaximization();
00375         }
00376         InvertButton state = buttonState_;
00377         buttonState_ = NONE;
00378         switch (state) {
00379         case MINCLIENT:
00380             monitor()->detachClient();
00381             break;
00382         case DEMAX:
00383             attached()->toggleClientMode();
00384             break;
00385         case CLOSE:
00386             XCORE->kill(focused()->clientWindow(), focused()->protocols());
00387             break;
00388         case NONE:
00389             break;
00390         }
00391     }
00392  
00393 }
00394 
00395 Cursor Frame::cursorForXY(int pointerX, int pointerY) {
00396 
00397     if (borderWidth_ == 0) {
00398         return Cursors::NORMAL_CURSOR;
00399     }
00400     bool left = pointerX < clientAreaRect_.x();
00401     bool right = pointerX >=
00402         (int)(clientAreaRect_.x() + clientAreaRect_.width());
00403     bool up;
00404     if (titleBarHeight_) {
00405         up = pointerY <
00406             (int)(clientAreaRect_.y() - titleBarHeight_ - 1);
00407     }
00408     else {
00409         up = pointerY < clientAreaRect_.y();
00410     }
00411     bool down = pointerY >=
00412         (int)(clientAreaRect_.y() + clientAreaRect_.height());
00413 
00414     if (left && Split::neighbor(attached()->root(), tree_, LEFT)) {
00415         return Cursors::RESIZE_LEFT_CURSOR;
00416     }
00417     else if (right && Split::neighbor(attached()->root(), tree_, RIGHT)) {
00418         return Cursors::RESIZE_RIGHT_CURSOR;
00419     }
00420     else if (up && Split::neighbor(attached()->root(), tree_, UP)) {
00421         return Cursors::RESIZE_UP_CURSOR;
00422     }
00423     else if (down && Split::neighbor(attached()->root(), tree_, DOWN)) {
00424         return Cursors::RESIZE_DOWN_CURSOR;
00425     }
00426 
00427     return Cursors::NORMAL_CURSOR;
00428 }
00429 
00430 Tree *Frame::tree() const {
00431     return tree_;
00432 }
00433 
00434 void Frame::setTree(Tree *t) {
00435     tree_ = t;
00436 }
00437 
00438 Window Frame::window() {
00439     return frameWindow_;
00440 }
00441 
00442 void Frame::toggleTiled() {
00443     isTiled_ = !isTiled_;
00444     resize();
00445 }
00446 
00447 void Frame::zoomClient() {
00448     if (focused() && size() > 1) {
00449         if (focused() == *begin()) {
00450             attached()->focus(next());
00451         }
00452         Client *client = focused();
00453         childs()->remove(client);
00454         childs()->push_front(client);
00455         resize();
00456     }
00457 }
00458 

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