00001
00002
00003
00004
00005
00006 #include "slot.h"
00007
00008 #ifdef SLOT_SUPPORT
00009
00010 #include <map>
00011 #include <string>
00012 #include <sstream>
00013
00014 #include "binder.h"
00015 #include "client.h"
00016 #include "cursors.h"
00017 #include "draw.h"
00018 #include "kernel.h"
00019 #include "label.h"
00020 #include "logger.h"
00021 #include "monitor.h"
00022 #include "theme.h"
00023 #include "util.h"
00024 #include "workspace.h"
00025 #include "xcore.h"
00026 #include "xfont.h"
00027
00029 Tab::Tab(const string name) {
00030 name_ = name;
00031 focused_ = 0;
00032 }
00033
00034 Tab::~Tab() {
00035 }
00036
00037 string Tab::name() const {
00038 return name_;
00039 }
00040
00041 LClient *Tab::clients() {
00042 return &clients_;
00043 }
00044
00045 void Tab::addClient(Client *client) {
00046 focused_ = client;
00047 clients_.push_back(client);
00048 }
00049
00050 void Tab::removeClient(Client *client) {
00051 clients_.remove(client);
00052 if (focused_ == client) {
00053 if (clients_.size()) {
00054 focused_ = clients_.front();
00055 }
00056 else {
00057 focused_ = 0;
00058 }
00059 }
00060 }
00061
00062 bool Tab::isVisible() const {
00063 return isVisible_;
00064 }
00065
00066 void Tab::show() {
00067 isVisible_ = true;
00068 for (LClient::iterator it = clients_.begin();
00069 it != clients_.end(); it++)
00070 {
00071 Client *client = *it;
00072 client->show();
00073 }
00074 }
00075
00076 void Tab::hide() {
00077 isVisible_ = false;
00078 for (LClient::iterator it = clients_.begin();
00079 it != clients_.end(); it++)
00080 {
00081 Client *client = *it;
00082 client->hide();
00083 }
00084 }
00085
00086 Client *Tab::focused() const {
00087 return focused_;
00088 }
00089
00090 void Tab::focus(Client *client) {
00091 focused_ = client;
00092 }
00093
00095
00096 Slot::Slot(Monitor *monitor, Rectangle *rect, Direction align)
00097 : Widget(monitor, rect),
00098 Container<Monitor, LTab, LTab::iterator, Tab>(monitor)
00099 {
00100 align_ = align;
00101 theme_ = this->monitor()->theme();
00102 isGrabFocus_ = false;
00103
00104 isSolid_ = (Util::get(KERNEL->commonSettings(), "slot.style") == "solid");
00105 initTabs();
00106
00107 label_ = new Label(this->monitor(), window(), Label::CENTER, gc());
00108 label_->setX(1);
00109 label_->setY(1);
00110 label_->setWidth(width() - 2);
00111 label_->setHeight(this->monitor()->titleBarHeight());
00112 }
00113
00114 Slot::~Slot() {
00115 }
00116
00117 void Slot::initTabs() {
00118
00119 string tabs = Util::get(KERNEL->commonSettings(), "slot.tabs");
00120
00121 string name = "";
00122 for (string::iterator it = tabs.begin(); it != tabs.end(); ) {
00123
00124 char c = *it;
00125 it++;
00126 bool isEndReached = it == tabs.end();
00127
00128 if ((c == ',') || isEndReached) {
00129 if (isEndReached) {
00130 name += c;
00131 }
00132 if (name != "") {
00133 attach(new Tab(name));
00134 name = "";
00135 }
00136 }
00137 else {
00138 name += c;
00139 }
00140 }
00141
00142 if (!size()) {
00143 attach(new Tab("default"));
00144 }
00145 }
00146
00147 void Slot::show(string tabName) {
00148
00149 if (isVisible()
00150 && tabName == this->tabName()
00151 && hasClients())
00152 {
00153 illuminate();
00154 return;
00155 }
00156 isVisible_ = true;
00157 for (LTab::iterator it = begin(); it != end(); it++) {
00158 Tab *tab = *it;
00159 tab->hide();
00160 if (tab->name() == tabName) {
00161 focus(tab);
00162 }
00163 }
00164 focused()->show();
00165 XCORE->show(window());
00166 }
00167
00168 void Slot::hide() {
00169 isVisible_ = false;
00170 focused()->hide();
00171 XCORE->hide(window());
00172 monitor()->matchWorkspace(monitor()->focused(), align_);
00173 }
00174
00175 Direction Slot::alignment() const {
00176 return align_;
00177 }
00178
00179 void Slot::illuminate() {
00180
00181 if (!isVisible() || width() == 1) {
00182 return;
00183 }
00184
00185 if (isSolid_) {
00186 Rectangle rect(*this);
00187 rect.setX(0);
00188 rect.setY(0);
00189 LOGDEBUG("drawing solid background");
00190
00191 XCORE->setForeground(gc(), theme_->BAR_BACKGROUND);
00192 XCORE->fillRectangle(window(), gc(), &rect);
00193 Draw::drawRectBorder(window(), gc(), &rect,
00194 theme_->BAR_SHINE, theme_->BAR_BACKGROUND);
00195 }
00196 else {
00197 XCORE->clearWindow(window());
00198 }
00199
00200 label_->setWidth(width() - 2);
00201 unsigned int offsetY = 1;
00202 unsigned int i = 0;
00203 for (LTab::iterator it = begin(); it != end(); it++) {
00204 Tab *tab = *it;
00205 label_->setY(offsetY + (i * label_->height()));
00206 label_->setText(tab->name());
00207 if (tab == focused()) {
00208 label_->update(theme_->LABEL_BACKGROUND_FOCUSSED,
00209 theme_->LABEL_TEXT_FOCUSSED,
00210 theme_->LABEL_SHINE_FOCUSSED,
00211 theme_->LABEL_SHADOW_FOCUSSED,
00212 true, true);
00213 }
00214 else {
00215 label_->update(theme_->LABEL_BACKGROUND_NORMAL,
00216 theme_->LABEL_TEXT_NORMAL,
00217 theme_->LABEL_SHINE_NORMAL,
00218 theme_->LABEL_SHADOW_NORMAL,
00219 true, true);
00220 }
00221 i++;
00222 }
00223
00224 LClient *clients = focused()->clients();
00225 for (LClient::iterator it = clients->begin();
00226 it != clients->end(); it++)
00227 {
00228 Client *client = *it;
00229 Rectangle rect(*client);
00230 rect.setX(rect.x() - 1);
00231 rect.setY(rect.y() - 1);
00232 rect.setWidth(rect.width() + 2);
00233 rect.setHeight(rect.height() + 2);
00234
00235 if (client == focused()->focused()) {
00236 Draw::drawRectBorder(window(), gc(), &rect,
00237 theme_->TAB_SHINE_ACTIVE_FOCUSSED,
00238 theme_->TAB_SHADOW_ACTIVE_FOCUSSED);
00239 }
00240 else {
00241 Draw::drawRectBorder(window(), gc(), &rect,
00242 theme_->TAB_SHINE_ACTIVE_NORMAL,
00243 theme_->TAB_SHADOW_ACTIVE_NORMAL);
00244 }
00245 }
00246 }
00247
00248 bool Slot::hasClients() {
00249
00250 for (LTab::iterator it = begin(); it != end(); it++) {
00251 Tab *tab = *it;
00252 if (tab->clients()->size()) {
00253 return true;
00254 }
00255 }
00256 return false;
00257 }
00258
00259 void Slot::manage() {
00260
00261 if (!isVisible()) {
00262 return;
00263 }
00264
00265 static bool isSlotOverlap =
00266 Util::get(KERNEL->commonSettings(), "slot.mode") == "overlap";
00267 unsigned int cHeight = 0;
00268 unsigned int maxWidth = 1;
00269 LClient *clients = focused()->clients();
00270 if (!clients->size() && hasClients()) {
00271 maxWidth = width();
00272 }
00273 for (LClient::iterator it = clients->begin();
00274 it != clients->end(); it++)
00275 {
00276 Client *client = *it;
00277 cHeight += client->height();
00278 if (maxWidth < client->width()) {
00279 maxWidth = client->width() + 2;
00280 }
00281 }
00282
00283 if (align_ == RIGHT) {
00284 setX(monitor()->width() - maxWidth);
00285 }
00286 setWidth(maxWidth);
00287
00288
00289 unsigned int tabPagerHeight = (size() * label_->height()) + 3;
00290 int offsetY = tabPagerHeight;
00291
00292 for (LClient::iterator it = clients->begin();
00293 it != clients->end(); it++)
00294 {
00295 Client *client = *it;
00296 client->setY(offsetY);
00297 client->setX((width() - client->width()) / 2);
00298 client->resize();
00299 offsetY += client->height() + 2;
00300 }
00301
00302 if (isSolid_ && !isSlotOverlap) {
00303 setHeight(monitor()->focused()->height());
00304 }
00305 else {
00306 setHeight(offsetY);
00307 }
00308 monitor()->matchWorkspace(monitor()->focused(), align_);
00309 XCORE->moveResize(window(), this);
00310 illuminate();
00311 }
00312
00313 Tab *Slot::tabForName(string name) {
00314
00315 for (LTab::iterator it = begin(); it != end(); it++) {
00316 Tab *tab = *it;
00317 if (tab->name() == name) {
00318 return tab;
00319 }
00320 }
00321
00322 return 0;
00323 }
00324
00325 void Slot::attachClient(Client *client) {
00326
00327 if (width() < client->width()) {
00328 setWidth(client->width());
00329 }
00330
00331 Binder::instance()->ungrabButtons(client->clientWindow());
00332 Binder::instance()->grabButtons(client->clientWindow(), AnyModifier);
00333
00334 if (client->hooked() != "") {
00335 Tab *tab = tabForName(client->hooked());
00336 if (tab && (tab != focused())) {
00337 focused()->hide();
00338 focus(tab);
00339 tab->show();
00340 }
00341 }
00342
00343 focused()->addClient(client);
00344 client->reparent(window(), 0, 0);
00345
00346 if (isVisible()) {
00347 client->show();
00348 }
00349 manage();
00350 }
00351
00352 void Slot::detachClient(Client *client) {
00353
00354 for (LTab::iterator it = begin(); it != end(); it++) {
00355 Tab *tab = *it;
00356 LClient *clients = tab->clients();
00357 bool found = false;
00358 for (LClient::iterator cit = clients->begin();
00359 cit != clients->end(); cit++)
00360 {
00361 found = (client == *cit);
00362 if (found) {
00363 break;
00364 }
00365 }
00366 if (found) {
00367 tab->removeClient(client);
00368 break;
00369 }
00370 }
00371 if (!client->isDestroyed()) {
00372 if (client->isVisible()) {
00373 client->hide();
00374 }
00375 client->reparent(monitor()->rootWindow(), 0, 0);
00376 }
00377 manage();
00378 }
00379
00380 void Slot::handleButtonPress(XButtonEvent *event) {
00381
00382 if (event->button == Button1) {
00383 unsigned int tabPagerHeight = (size() * label_->height()) + 3;
00384
00385 XCORE->raise(window());
00386 if (event->y < (int)tabPagerHeight) {
00387 unsigned int selTab = event->y / label_->height();
00388 ostringstream oss;
00389 oss << "select tab #" << selTab << " of " << size() << " tabs ";
00390 LOGDEBUG(oss.str());
00391 unsigned int i = 0;
00392 for (LTab::iterator it = begin(); it != end(); it++) {
00393 if (selTab == i) {
00394 if (focused() != *it) {
00395 focused()->hide();
00396 focus(*it);
00397 focused()->show();
00398 manage();
00399 }
00400 return;
00401 }
00402 i++;
00403 }
00404 }
00405 }
00406 else if (event->button == Button4) {
00407 monitor()->cycleSlotTabPrev();
00408 }
00409 else if (event->button == Button5) {
00410 monitor()->cycleSlotTabNext();
00411 }
00412 }
00413
00414 void Slot::handleMotionNotify(XMotionEvent *event) {
00415 }
00416
00417 string Slot::tabName() {
00418 return focused()->name();
00419 }
00420
00421 bool Slot::isGrabFocus() const {
00422 return isGrabFocus_;
00423 }
00424
00425 void Slot::setGrabFocus(bool grabFocus) {
00426 Client *client = focused()->focused();
00427 if (isGrabFocus_ && !grabFocus) {
00428
00429 if (client) {
00430 Binder::instance()->ungrabButtons(client->clientWindow());
00431 Binder::instance()->grabButtons(client->clientWindow(), AnyModifier);
00432 }
00433 }
00434 isGrabFocus_ = grabFocus;
00435 }
00436
00437 void Slot::focusClient(Client *client) {
00438
00439 for (LTab::iterator it = begin(); it != end(); it++) {
00440 Tab *tab = *it;
00441 LClient *clients = tab->clients();
00442 for (LClient::iterator cit = clients->begin();
00443 cit != clients->end(); cit++)
00444 {
00445 if (*cit == client) {
00446 if (tab != focused()) {
00447 focused()->hide();
00448 focus(tab);
00449 tab->show();
00450 manage();
00451 }
00452 Client *old = focused()->focused();
00453 if (old != client) {
00454 Binder::instance()->ungrabButtons(old->clientWindow());
00455 Binder::instance()->grabButtons(old->clientWindow(),
00456 AnyModifier);
00457 }
00458 Client *tc = monitor()->focused()->topClient();
00459 isGrabFocus_ = true;
00460 if (tc) {
00461
00462
00463 Binder::instance()->ungrabButtons(tc->clientWindow());
00464 Binder::instance()->grabButtons(tc->clientWindow(),
00465 AnyModifier);
00466 monitor()->focused()->illuminate();
00467 }
00468 focused()->focus(client);
00469 Binder::instance()->ungrabButtons(client->clientWindow());
00470 XCORE->setInputFocus(client->clientWindow());
00471 illuminate();
00472 return;
00473 }
00474 }
00475 }
00476 }
00477 #endif // SLOT_SUPPORT