00001
00002
00003
00004
00005
00006 extern "C" {
00007 #include <assert.h>
00008 #include <X11/keysym.h>
00009 #include <X11/Xlib.h>
00010 #include <X11/Xutil.h>
00011 }
00012
00013 #include <iostream>
00014 #include <sstream>
00015
00016 #include "monitor.h"
00017
00018 #include "action.h"
00019 #include "actions.h"
00020 #include "atoms.h"
00021 #include "binder.h"
00022 #include "box.h"
00023 #include "client.h"
00024 #include "clientbar.h"
00025 #include "cursors.h"
00026 #include "draw.h"
00027 #include "font.h"
00028 #include "frame.h"
00029 #include "inputbar.h"
00030 #include "logger.h"
00031 #include "menu.h"
00032 #include "rectangle.h"
00033 #include "slot.h"
00034 #include "statusbar.h"
00035 #include "theme.h"
00036 #include "thing.h"
00037 #include "util.h"
00038 #include "kernel.h"
00039 #include "workspace.h"
00040 #include "xcore.h"
00041 #include "xfont.h"
00042
00043 Monitor::Monitor(Display *display, unsigned int id)
00044 : Container<Display, LWorkspace, LWorkspace::iterator, Workspace>(display),
00045 Rectangle(), detachedClients_(this), stickyClients_(this)
00046 {
00047
00048 ostringstream oss;
00049 oss << "monitor[" << id << "]";
00050 prefix_ = oss.str();
00051 id_ = id;
00052 themeSettings_ = KERNEL->themeSettings();
00053 commonSettings_ = KERNEL->commonSettings();
00054 sessionSettings_ = KERNEL->sessionSettings();
00055 setWidth(DisplayWidth(attached(), id_));
00056 setHeight(DisplayHeight(attached(), id_));
00057 rootWindow_ = RootWindow(attached(), id_);
00058
00059 resizeFactor_ = Util::strToUInt(
00060 Util::get(commonSettings_, "resize-move.factor"));
00061
00062 theme_ = new Theme();
00063 maxThing_ = 0;
00064 clientIds_ = 0;
00065 fixed_ = 0;
00066
00067 initFonts();
00068 LOGDEBUG("font initialized");
00069 initDisplayString();
00070 LOGDEBUG("display string '" + displayString_ + "' initialized");
00071 theme_->initTheme(themeSettings_, XCORE->defaultColormap(id_));
00072 LOGDEBUG("colors initialized");
00073 initGC();
00074 LOGDEBUG("GC initialized");
00075 initBars();
00076 LOGDEBUG("bars initialized");
00077 XCORE->sync();
00078 #ifdef SLOT_SUPPORT
00079 initSlot();
00080 LOGDEBUG("slot initialized");
00081 #endif // SLOT_SUPPORT
00082 initWorkspaces();
00083 LOGDEBUG("workspaces initialized");
00084
00085 XCORE->selectEvents(rootWindow_,
00086 SubstructureRedirectMask | SubstructureNotifyMask
00087 | PropertyChangeMask);
00088
00089 KERNEL->installCursor(Cursors::NORMAL_CURSOR, rootWindow_);
00090
00091 XCORE->sync();
00092 }
00093
00094 void Monitor::initFonts() {
00095
00096 string fontName = Util::get(KERNEL->themeSettings(), "font");
00097 font_ = WFont::load(this, fontName);
00098 if (!font_) {
00099
00100 LOGWARN("cannot load font '" + fontName +
00101 "', trying loading default font 'fixed'");
00102 font_ = WFont::load(this, "fixed");
00103 if (!font_) {
00104 LOGERROR("cannot load any font", true);
00105
00106 }
00107 }
00108 if (font_->height() < MINIMAL_BARHEIGHT) {
00109 font_->setHeight(MINIMAL_BARHEIGHT);
00110 }
00111 if (font_->type() == WFont::XFT) {
00112 fixed_ = XFont::load(this, "fixed");
00113 if (!fixed_) {
00114 LOGERROR("cannot load any font", true);
00115
00116 }
00117 }
00118 }
00119
00120 void Monitor::initBars() {
00121
00122 Rectangle rect(0, 0, width(), titleBarHeight() + 2);
00123
00124 if (Util::get(commonSettings_, "statusbar.alignment") != "bottom") {
00125 statusBar_ = new StatusBar(this, &rect);
00126 inputBar_ = new InputBar(this, &rect);
00127 rect.setY(height() - rect.height());
00128 clientBar_ = new ClientBar(this, &rect);
00129 }
00130 else {
00131 clientBar_ = new ClientBar(this, &rect);
00132 rect.setY(height() - rect.height());
00133 statusBar_ = new StatusBar(this, &rect);
00134 inputBar_ = new InputBar(this, &rect);
00135 }
00136
00137 rect.setY(height() / 2 - rect.height() / 2);
00138 box_ = new Box(this, &rect, "");
00139 }
00140
00141 void Monitor::initGC() {
00142
00143 unsigned long mask =
00144 GCForeground | GCGraphicsExposures
00145 | GCFunction | GCSubwindowMode | GCLineWidth
00146 | GCPlaneMask;
00147 XGCValues gcv;
00148 gcv.subwindow_mode=IncludeInferiors;
00149 gcv.function=GXxor;
00150 gcv.foreground = theme_->FRAME_PSEUDO;
00151 gcv.fill_style=FillSolid;
00152 gcv.line_width = Util::strToUInt(
00153 Util::get(KERNEL->commonSettings(), "border.width"));
00154 gcv.plane_mask = AllPlanes;
00155 gcv.graphics_exposures = False;
00156 if (font_->type() == WFont::NORMAL) {
00157 gcv.font = ((XFont *)font_)->font()->fid;
00158 mask |= GCFont;
00159 }
00160
00161 pseudoBorderGC_ = XCORE->createGC(rootWindow_, mask, &gcv);
00162
00163 gcv.function=GXcopy;
00164 borderGC_ = XCORE->createGC(rootWindow_, mask, &gcv);
00165 }
00166
00167 Monitor::~Monitor() {
00168 for (MClient::iterator it = clients_.begin();
00169 it != clients_.end(); it++)
00170 {
00171 Client *client = (*it).second;
00172 clients_.erase(it);
00173 delete client;
00174 }
00175 delete statusBar_;
00176 delete clientBar_;
00177 #ifdef SLOT_SUPPORT
00178 delete slot_;
00179 #endif // SLOT_SUPPORT
00180 }
00181
00182 void Monitor::rectForWorkspace(Workspace *workspace) {
00183
00184 bool isClientBarVisible = workspace->isClientBarVisible();
00185 bool isStatusBarVisible = workspace->isStatusBarVisible();
00186
00187
00188 if (Util::get(commonSettings_, "statusbar.alignment") != "bottom") {
00189 workspace->setY((isStatusBarVisible ? statusBar_->height() : 0));
00190 }
00191 else {
00192 workspace->setY((isClientBarVisible ? clientBar_->height() : 0));
00193 }
00194 workspace->setHeight(height()
00195 - (isStatusBarVisible ? statusBar_->height() : 0)
00196 - (isClientBarVisible ? clientBar_->height() : 0));
00197
00198 #ifdef SLOT_SUPPORT
00199 static bool isSlotOverlap =
00200 Util::get(commonSettings_, "slot.mode") == "overlap";
00201
00202 if (workspace->isSlotVisible() && !isSlotOverlap
00203 && slot_->hasClients())
00204 {
00205 if (slot_->alignment() == LEFT) {
00206 workspace->setX(slot_->width());
00207 }
00208 else {
00209 workspace->setX(x());
00210 }
00211 workspace->setWidth(width() - slot_->width());
00212 }
00213 else
00214 #endif // SLOT_SUPPORT
00215 {
00216 workspace->setX(x());
00217 workspace->setWidth(width());
00218 }
00219 }
00220
00221 void Monitor::initWorkspaces() {
00222
00223 string key = prefix_ + ".workspaces";
00224
00225 unsigned int workspaceCount =
00226 Util::strToUInt(Util::get(sessionSettings_, key));
00227 string id =
00228 Util::get(KERNEL->sessionSettings(), prefix_ + ".focused");
00229 unsigned int focusedWSNum = (id != "") ? Util::strToUInt(id) : 0;
00230
00231 Rectangle rect;
00232 Workspace *toFocus = 0;
00233 for (unsigned int i = 0; i < workspaceCount; i++) {
00234 Workspace *workspace = new Workspace(this, i, &rect);
00235 matchWorkspace(workspace, LEFT);
00236 attach(workspace);
00237 if (i == focusedWSNum) {
00238 toFocus = workspace;
00239 }
00240 }
00241 LOGDEBUG("workspaces created");
00242 XCORE->sync();
00243 focus(toFocus);
00244 }
00245
00246 void Monitor::initDisplayString() {
00247
00248 ostringstream oss;
00249
00250 displayString_ = DisplayString(attached());
00251 unsigned int dot = displayString_.rfind('.');
00252
00253 LOGDEBUG("initializing display string '" + displayString_ + "'");
00254 oss << "DISPLAY=";
00255 LOGDEBUG("ok displayString_");
00256 if (dot > 0) {
00257 oss << displayString_.substr(0, dot + 1) << id_;
00258 }
00259 else {
00260 oss << displayString_;
00261 }
00262
00263 displayString_ = oss.str();
00264 }
00265
00266 void Monitor::scanWindows() {
00267
00268 unsigned int numWindows = 0;
00269 Window *windows;
00270 XWindowAttributes attr;
00271
00272
00273 XCORE->queryTree(rootWindow_, &windows, &numWindows);
00274
00275 ostringstream oss;
00276 oss << "scanning " << numWindows << " windows";
00277 LOGDEBUG(oss.str());
00278 for (unsigned int i = 0; i < numWindows; i++) {
00279 XCORE->windowAttributes(windows[i], &attr);
00280
00281
00282 if (attr.override_redirect ||
00283 menuWindow(windows[i]) ||
00284 (box_->window() == windows[i]) ||
00285 barWindow(windows[i]) ||
00286 #ifdef SLOT_SUPPORT
00287 slotWindow(windows[i]) ||
00288 #endif // SLOT_SUPPORT
00289 (windows[i] == rootWindow_))
00290 {
00291 LOGDEBUG("ignoring scanned window (override redirect)");
00292 continue;
00293 }
00294
00295 if (XCORE->transient(windows[i])) {
00296 LOGDEBUG("ignoring scanned window (transient)");
00297 continue;
00298 }
00299
00300
00301 Client *client;
00302 if ((client = clientForWindow(windows[i])) == 0) {
00303 if (attr.map_state == IsViewable) {
00304 client = new Client(this, windows[i], &attr);
00305 addClient(client);
00306 attachClient(client);
00307 }
00308 }
00309 }
00310 if (windows) {
00311 XCORE->free((void *)windows);
00312 }
00313 }
00314
00315 Thing *Monitor::thingWindow(Window window) {
00316
00317 for (LWorkspace::iterator it = begin(); it != end(); it++) {
00318 Workspace *workspace = *it;
00319 Thing *thing = workspace->thingWindow(window);
00320 if (thing) {
00321 return thing;
00322 }
00323 }
00324 return 0;
00325 }
00326
00327
00328 Bar *Monitor::barWindow(Window window) {
00329
00330 if (statusBar_->window() == window) {
00331 return statusBar_;
00332 }
00333 if (clientBar_->window() == window) {
00334 return clientBar_;
00335 }
00336 if (inputBar_->window() == window) {
00337 return inputBar_;
00338 }
00339 return 0;
00340 }
00341
00342 Menu *Monitor::menuWindow(Window window) {
00343 Menu *menu = clientBar_->menu();
00344 if (clientBar_->menu()->window() == window) {
00345 return menu;
00346 }
00347
00348 return 0;
00349 }
00350
00351 #ifdef SLOT_SUPPORT
00352 void Monitor::initSlot() {
00353
00354 Direction align;
00355 string valueAlign = Util::get(commonSettings_, "slot.alignment");
00356 Rectangle rect;
00357
00358 int offsetX = 0;
00359 if (valueAlign == "right") {
00360 align = RIGHT;
00361 offsetX = width() - 1;
00362 }
00363 else {
00364 align = LEFT;
00365 }
00366 rect = Rectangle(offsetX, titleBarHeight(), 1,
00367 height() - 2 * titleBarHeight());
00368
00369 slot_ = new Slot(this, &rect, align);
00370 }
00371
00372
00373 Slot *Monitor::slotWindow(Window window) {
00374
00375 if (slot_->window() == window) {
00376 return slot_;
00377 }
00378
00379 return 0;
00380 }
00381
00382 Slot *Monitor::slot() const {
00383 return slot_;
00384 }
00385
00386 void Monitor::unslotClient() {
00387
00388 Client *client = slot_->focused()->focused();
00389 if (client) {
00390 slot_->detachClient(client);
00391 client->setMode(Client::FLOAT);
00392 attachClient(client);
00393 }
00394 }
00395
00396 void Monitor::slotClient() {
00397
00398 Client *client = focusedClient();
00399 if (client) {
00400
00401
00402
00403 removeClient(client);
00404 addClient(client);
00405 client->setMode(Client::SLOT);
00406 attachClient(client);
00407 }
00408 }
00409
00410 void Monitor::toggleSlot() {
00411
00412 if (slot_->isVisible()) {
00413 focused()->setSlotVisible(false);
00414 slot_->hide();
00415 }
00416 else {
00417 focused()->setSlotVisible(true);
00418 slot_->show(focused()->slotTabName());
00419 slot_->manage();
00420 }
00421
00422 focused()->setSlotVisible(slot_->isVisible());
00423 }
00424
00425 void Monitor::cycleSlotTabPrev() {
00426 slot_->focused()->hide();
00427 slot_->focus(slot_->prev());
00428 slot_->focused()->show();
00429 slot_->manage();
00430 }
00431
00432 void Monitor::cycleSlotTabNext() {
00433 slot_->focused()->hide();
00434 slot_->focus(slot_->next());
00435 slot_->focused()->show();
00436 slot_->manage();
00437 }
00438 #endif // SLOT_SUPPORT
00439
00440 Client *Monitor::clientForWindow(Window window) {
00441
00442 if (window == 0 || window == rootWindow_) {
00443 return 0;
00444 }
00445
00446 MClient::iterator it = clients_.find((long)window);
00447
00448 if (it != clients_.end()) {
00449 return (*it).second;
00450 }
00451
00452
00453 return 0;
00454 }
00455
00456 void Monitor::addClient(Client *client) {
00457
00458 clients_[(long)client->clientWindow()] = client;
00459 }
00460
00461 void Monitor::cleanup() {
00462 while (clients_.size()) {
00463 MClient::iterator it = clients_.begin();
00464 Client *client = (*it).second;
00465 removeClient(client);
00466 if (!client->transient()) {
00467 XCORE->addToSaveSet(client->clientWindow());
00468 }
00469 delete client;
00470 }
00471 }
00472
00473 Client *Monitor::focusedClient() {
00474 return focused()->topClient();
00475 }
00476
00477 void Monitor::removeClient(Client *client) {
00478
00479 XCORE->sync();
00480 LOGDEBUG("removing client");
00481
00482 Workspace *workspace = client->attached();
00483 if (workspace) {
00484 workspace->detachClient(client);
00485 LOGDEBUG("client removed from workspace");
00486 }
00487 #ifdef SLOT_SUPPORT
00488 else if (client->mode() == Client::SLOT) {
00489 LOGDEBUG("removing slot client");
00490 slot_->detachClient(client);
00491 matchWorkspace(focused(), slot_->alignment());
00492 }
00493 #endif
00494 else if (!client->isVisible()) {
00495
00496 detachedClients_.detach(client);
00497 XCORE->sync();
00498 LOGDEBUG("removing detached client");
00499 statusBar_->illuminate();
00500 }
00501
00502 XCORE->sync();
00503 clients_.erase((long)client->clientWindow());
00504 LOGDEBUG("client removed");
00505 }
00506
00507 void Monitor::matchWorkspace(Workspace *workspace, Direction dir) {
00508
00509 rectForWorkspace(workspace);
00510 workspace->matchBarNeighbors(dir);
00511 #ifdef SLOT_SUPPORT
00512
00513 slot_->setY(workspace->y());
00514 #endif // SLOT_SUPPORT
00515 }
00516
00517 void Monitor::toggleClientBar() {
00518
00519 if (clientBar_->isVisible()) {
00520 clientBar_->hide();
00521 }
00522 else {
00523 clientBar_->show();
00524 }
00525
00526 focused()->setClientBarVisible(clientBar_->isVisible());
00527 Direction dir =
00528 (Util::get(commonSettings_, "statusbar.alignment") == "bottom") ? UP : DOWN;
00529 matchWorkspace(focused(), dir);
00530 #ifdef SLOT_SUPPORT
00531 slot_->manage();
00532 #endif // SLOT_SUPPORT
00533 }
00534
00535 void Monitor::toggleStatusBar() {
00536
00537 if (statusBar_->isVisible()) {
00538 statusBar_->hide();
00539 }
00540 else {
00541 statusBar_->show();
00542 }
00543
00544 focused()->setStatusBarVisible(statusBar_->isVisible());
00545 Direction dir =
00546 (Util::get(commonSettings_, "statusbar.alignment") != "bottom") ? UP : DOWN;
00547 matchWorkspace(focused(), dir);
00548 #ifdef SLOT_SUPPORT
00549 slot_->manage();
00550 #endif // SLOT_SUPPORT
00551 }
00552
00553 void Monitor::toggleAllClientStates() {
00554
00555 Workspace *workspace = focused();
00556 assert(workspace);
00557 Thing *thing = workspace->focusedThing();
00558
00559 if (!thing || (thing->type() != Thing::FRAME)) {
00560 return;
00561 }
00562 Frame *frame = (Frame *)thing;
00563
00564 unsigned int num = frame->size();
00565 for (unsigned int i = 0; (i < num) && (frame->size() != 0); i++) {
00566 workspace->changeClientMode(frame->focused(), Client::FLOAT);
00567 }
00568 statusBar_->illuminate();
00569 }
00570
00571 void Monitor::attachAllClients() {
00572
00573 while (detachedClients_.size()) {
00574 Client *client = *detachedClients_.begin();
00575 detachedClients_.detach(client);
00576 attachClient(client);
00577 }
00578 }
00579
00580 void Monitor::detachAllClients() {
00581
00582 Workspace *workspace = focused();
00583 assert(workspace);
00584
00585 if (workspace->isFrameMode()) {
00586 Frame *frame = workspace->focusedFrame();
00587 unsigned int i = frame->size();
00588 while (i) {
00589 detachClient(*frame->begin());
00590 i--;
00591 }
00592 }
00593 else {
00594 CClient *floatingClients = workspace->floatingClients();
00595 unsigned int i = floatingClients->size();
00596 while (i) {
00597 detachClient(*floatingClients->begin());
00598 i--;
00599 }
00600 }
00601 statusBar_->illuminate();
00602 }
00603
00604 void Monitor::detachClient(Client *client) {
00605
00606 if (!client) {
00607 return;
00608 }
00609
00610 Workspace *workspace = client->attached();
00611
00612 if (workspace) {
00613 workspace->detachClient(client);
00614 detachedClients_.attach(client);
00615 }
00616 }
00617
00618 void Monitor::detachClient() {
00619 detachClient(focused()->topClient());
00620 }
00621
00622 void Monitor::attachClientByName(string name) {
00623
00624 for (LClient::iterator it = detachedClients_.begin();
00625 it != detachedClients_.end(); it++)
00626 {
00627 Client *client = *it;
00628 if (client->name() == name) {
00629 detachedClients_.detach(client);
00630 attachClient(client);
00631 return;
00632 }
00633 }
00634 }
00635
00636 void Monitor::attachLastClient() {
00637
00638 Client *client = detachedClients_.focused();
00639 if (client) {
00640 detachedClients_.detach(client);
00641 attachClient(client);
00642 }
00643 }
00644
00645 void Monitor::attachClient(Client *client) {
00646
00647
00648 client->initICCCM();
00649
00650 if (client->state() == IconicState) {
00651 assert(!client->attached());
00652 detachedClients_.attach(client);
00653 return;
00654 }
00655
00656
00657 Client *transient = client->transient();
00658
00659 if (transient && !transient->attached()
00660 #ifdef SLOT_SUPPORT
00661 && (transient->mode() != Client::SLOT)
00662 #endif
00663 )
00664 {
00665
00666 detachedClients_.detach(transient);
00667 attachClient(transient);
00668 }
00669
00670 #ifdef SLOT_SUPPORT
00671 if (client->mode() == Client::SLOT) {
00672
00673 LOGDEBUG("new slot client");
00674 slot_->attachClient(client);
00675 }
00676 else
00677 #endif // SLOT_SUPPORT
00678 {
00679 Workspace *hooked = workspaceForName(client->hooked());
00680 if (hooked && contains(hooked)) {
00681 focus(hooked);
00682 }
00683 focused()->attachClient(client);
00684 }
00685 }
00686
00687 void Monitor::attachDetachedClient(Workspace *workspace, Client *client) {
00688
00689 focus(workspace);
00690 detachedClients_.detach(client);
00691 attachClient(client);
00692 }
00693
00694 void Monitor::createNewWorkspace(string name) {
00695
00696 static Rectangle rect;
00697 unsigned int id = size();
00698
00699 ostringstream key;
00700 key << prefix_ << ".workspace[" << id << "]";
00701
00702 (*sessionSettings_)[key.str() + ".name"] = name;
00703 (*sessionSettings_)[key.str() + ".clientbar"] = "yes";
00704 (*sessionSettings_)[key.str() + ".statusbar"] = "yes";
00705 #ifdef SLOT_SUPPORT
00706 (*sessionSettings_)[key.str() + ".slot"] = slot_->tabName();
00707 #endif // SLOT_SUPPORT
00708 (*sessionSettings_)[key.str() + ".focused"] = "0";
00709
00710 if (focused()) {
00711 focused()->hide();
00712 }
00713 Workspace *workspace = new Workspace(this , id, this);
00714 matchWorkspace(workspace, LEFT);
00715 attach(workspace);
00716 focused()->show();
00717
00718 ostringstream value;
00719 value << size();
00720 (*sessionSettings_)[prefix_ + ".workspaces"] = value.str();
00721 }
00722
00723 void Monitor::serialize() {
00724
00725 ostringstream value;
00726 value << size();
00727 (*sessionSettings_)[prefix_ + ".workspaces"] = value.str();
00728
00729 for (LWorkspace::iterator it = begin(); it != end(); it++) {
00730 Workspace *workspace = *it;
00731 workspace->serialize();
00732 }
00733
00734 value.str("");
00735 value << focused()->id();
00736 (*sessionSettings_)[prefix_ + ".focused"] = value.str();
00737 }
00738
00739 void Monitor::focus(Workspace *workspace) {
00740
00741 workspace->setRequestsFocus(false);
00742 if (focused() != workspace) {
00743 focused()->hide();
00744 LOGDEBUG("focussing workspace");
00745 XCORE->sync();
00746 Container<Display, LWorkspace, LWorkspace::iterator,
00747 Workspace>::focus(workspace);
00748 }
00749 focused()->show();
00750 updateBars();
00751 }
00752
00753 void Monitor::focusClient(Client *client) {
00754
00755 Workspace *workspace = client->attached();
00756 if (workspace) {
00757 focus(workspace);
00758 workspace->focus(client);
00759 }
00760 }
00761
00762 void Monitor::focusClientById(string id) {
00763
00764 for (MClient::iterator it = clients_.begin();
00765 it != clients_.end(); it++)
00766 {
00767 Client *client = (*it).second;
00768
00769 if (client->id() == id) {
00770 focusClient(client);
00771 }
00772 }
00773 }
00774
00775 void Monitor::focusClientByName(string name) {
00776
00777 for (MClient::iterator it = clients_.begin();
00778 it != clients_.end(); it++)
00779 {
00780 Client *client = (*it).second;
00781
00782 if (client->name() == name) {
00783 focusClient(client);
00784 }
00785 }
00786 }
00787
00788 Workspace *Monitor::workspaceForName(string name) {
00789
00790 for (LWorkspace::iterator it = begin(); it != end(); it++) {
00791 if ((*it)->name() == name) {
00792 return (Workspace *)*it;
00793 }
00794 }
00795 return 0;
00796 }
00797
00798 void Monitor::focusWorkspaceNum(unsigned int workspaceNum) {
00799
00800 unsigned int i = 0;
00801 for (LWorkspace::iterator it = begin(); it != end(); it++) {
00802 if (i == workspaceNum) {
00803 focus(*it);
00804 return;
00805 }
00806 i++;
00807 }
00808 }
00809
00810 void Monitor::destroyWorkspace(Workspace *workspace) {
00811
00812 assert(workspace);
00813 if (size() > 1) {
00814 LClient *clients = workspace->clients();
00815 while (clients->size()) {
00816 Client *client = *clients->begin();
00817 detachClient(client);
00818 KERNEL->killClient(client);
00819 }
00820 detach(workspace);
00821 Util::remove(sessionSettings_, workspace->prefix());
00822 delete workspace;
00823 focused()->show();
00824 updateBars();
00825 }
00826 }
00827
00828 void Monitor::renameWorkspace(Workspace *workspace, string newName) {
00829 workspace->setName(newName);
00830 (*sessionSettings_)[workspace->prefix() + ".name"] = newName;
00831 }
00832
00833 void Monitor::updateBars() {
00834
00835 static string value;
00836
00837 if (XCORE->textProperty(rootWindow_, Atoms::NCWM_STATUSTEXT, &value)) {
00838 statusBar_->setText(value);
00839 }
00840 if (XCORE->textProperty(rootWindow_, Atoms::NCWM_METERTEXT, &value)) {
00841 statusBar_->setMeterText(value);
00842 }
00843
00844 LOGDEBUG("update status");
00845 statusBar_->illuminate();
00846 clientBar_->illuminate();
00847 XCORE->sync();
00848 }
00849
00850 void Monitor::toggleThingMaximization() {
00851
00852 if (!focused()) {
00853 return;
00854 }
00855
00856 if (maxThing_) {
00857
00858 maxThing_->copy(maxThing_->prevRectangle());
00859 maxThing_->resize();
00860 focused()->illuminate();
00861 maxThing_ = 0;
00862
00863 }
00864 else {
00865
00866 Workspace *workspace = focused();
00867 maxThing_ = workspace->focusedThing();
00868
00869 if (!maxThing_) {
00870 return;
00871 }
00872
00873 maxThing_->prevRectangle()->copy(maxThing_);
00874 maxThing_->setX(x());
00875 maxThing_->setY(y());
00876 maxThing_->setWidth(width());
00877 maxThing_->setHeight(height());
00878 maxThing_->resize();
00879 XCORE->raise(maxThing_->window());
00880 maxThing_->illuminate();
00881 }
00882 }
00883
00884 void Monitor::illuminateTransRect(Rectangle *rect, unsigned int barHeight)
00885 {
00886 Draw::drawTransRectangle(rootWindow_, pseudoBorderGC_, rect, barHeight,
00887 KERNEL->borderWidth());
00888
00889
00890 ostringstream oss;
00891 oss << "x=" << rect->x() << ", y=" << rect->y()
00892 << ": " << rect->width() << "x" << rect->height();
00893
00894 illuminateTransText(rect, oss.str());
00895 }
00896
00897 unsigned int Monitor::nextClientId() {
00898 ++clientIds_;
00899 return clientIds_;
00900 }
00901
00902 void Monitor::illuminateTransText(Rectangle *rect, string text)
00903 {
00904 WFont *font = (font_->type() == WFont::NORMAL) ?
00905 font_ : fixed_;
00906
00907
00908 int textWidth = font->textWidth(text);
00909 unsigned int fontBaseLine = font->ascent();
00910 unsigned int fontY = rect->y() + rect->height() / 2
00911 - font->height() / 2 + fontBaseLine;
00912
00913 unsigned int fontX = rect->x() +
00914 (rect->width() / 2 - textWidth / 2);
00915 font->drawText(rootWindow_, pseudoBorderGC_,
00916 fontX, fontY, text);
00917 }
00918
00919
00920 unsigned int Monitor::id() const {
00921 return id_;
00922 }
00923
00924 Window Monitor::rootWindow() const {
00925 return rootWindow_;
00926 }
00927
00928 string Monitor::displayString() const {
00929 return displayString_;
00930 }
00931
00932 Theme *Monitor::theme() const {
00933 return theme_;
00934 }
00935
00936 unsigned int Monitor::resizeFactor() const {
00937 return resizeFactor_;
00938 }
00939
00940 string Monitor::prefix() const {
00941 return prefix_;
00942 }
00943
00944 Box *Monitor::box() const {
00945 return box_;
00946 }
00947
00948 StatusBar *Monitor::statusBar() const {
00949 return statusBar_;
00950 }
00951
00952 ClientBar *Monitor::clientBar() const {
00953 return clientBar_;
00954 }
00955
00956 CClient *Monitor::detachedClients() {
00957 return &detachedClients_;
00958 }
00959
00960 bool Monitor::isThingMaximized() {
00961 return maxThing_ != 0;
00962 }
00963
00964 GC Monitor::borderGC() {
00965 return borderGC_;
00966 }
00967
00968 CClient *Monitor::stickyClients() {
00969 return &stickyClients_;
00970 }
00971
00972 WFont *Monitor::font() const {
00973 return font_;
00974 }
00975
00976 unsigned int Monitor::titleBarHeight() const {
00977 return font_->height() + 2;
00978 }
00979
00980 MClient *Monitor::clients() {
00981 return &clients_;
00982 }
00983
00984 InputBar *Monitor::inputBar() const {
00985 return inputBar_;
00986 }
00987
00988 void Monitor::banish() {
00989 XCORE->warpPointer(rootWindow_, width(), height());
00990 }
00991
00992 unsigned int Monitor::buttonWidth() const {
00993 return font_->height() + 4;
00994 }
00995
00996 void Monitor::hookClient() {
00997
00998 Client *client = 0;
00999 #ifdef SLOT_SUPPORT
01000 if (slot_->isGrabFocus() ||
01001 (!focused()->clients()->size() && slot_->focused()->focused()))
01002 {
01003 client = slot_->focused()->focused();
01004 if (client) {
01005 client->setHooked(slot_->tabName());
01006 return;
01007 }
01008 }
01009 else
01010 #endif // SLOT_SUPPORT
01011 {
01012 client = focused()->topClient();
01013 if (client) {
01014 client->setHooked(focused()->name());
01015 }
01016 }
01017 }
01018
01019 void Monitor::unhookClient() {
01020
01021 Client *client = 0;
01022 #ifdef SLOT_SUPPORT
01023 if (slot_->isGrabFocus() ||
01024 (!focused()->clients()->size() && slot_->focused()->focused()))
01025 {
01026 client = slot_->focused()->focused();
01027 if (client) {
01028 client->setHooked("");
01029 return;
01030 }
01031 }
01032 else
01033 #endif // SLOT_SUPPORT
01034 {
01035 client = focused()->topClient();
01036 if (client) {
01037 client->setHooked("");
01038 }
01039 }
01040 }