00001
00002
00003
00004
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
00090 label_->setWidth(
00091 width() - label_->x() - 3 * buttonWidth -
00092 ((foc && areButtonsVisible_) ? 3 + borderWidth_ : borderWidth_));
00093 }
00094 i++;
00095 if (foc) {
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 {
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) {
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 {
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
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
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
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
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
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