monitor.cpp (25150B)
1 // Copyright (c) 2003 - 2009 Anselm R Garbe <anselm@garbe.us> 2 // See LICENSE for license details. 3 4 extern "C" { 5 #include <assert.h> 6 #include <X11/keysym.h> 7 #include <X11/Xlib.h> 8 #include <X11/Xutil.h> 9 } 10 11 #include <iostream> 12 #include <sstream> 13 14 #include "monitor.h" 15 16 #include "action.h" 17 #include "actions.h" 18 #include "atoms.h" 19 #include "binder.h" 20 #include "box.h" 21 #include "client.h" 22 #include "clientbar.h" 23 #include "cursors.h" 24 #include "draw.h" 25 #include "font.h" 26 #include "frame.h" 27 #include "inputbar.h" 28 #include "logger.h" 29 #include "menu.h" 30 #include "rectangle.h" 31 #include "slot.h" 32 #include "statusbar.h" 33 #include "theme.h" 34 #include "thing.h" 35 #include "util.h" 36 #include "kernel.h" 37 #include "workspace.h" 38 #include "xcore.h" 39 #include "xfont.h" 40 41 Monitor::Monitor(Display *display, unsigned int id) 42 : Container<Display, LWorkspace, LWorkspace::iterator, Workspace>(display), 43 Rectangle(), detachedClients_(this), stickyClients_(this) 44 { 45 46 ostringstream oss; 47 oss << "monitor[" << id << "]"; 48 prefix_ = oss.str(); 49 id_ = id; 50 themeSettings_ = KERNEL->themeSettings(); 51 commonSettings_ = KERNEL->commonSettings(); 52 sessionSettings_ = KERNEL->sessionSettings(); 53 setWidth(DisplayWidth(attached(), id_)); 54 setHeight(DisplayHeight(attached(), id_)); 55 rootWindow_ = RootWindow(attached(), id_); 56 57 resizeFactor_ = Util::strToUInt( 58 Util::get(commonSettings_, "resize-move.factor")); 59 60 theme_ = new Theme(); 61 maxThing_ = 0; 62 clientIds_ = 0; 63 fixed_ = 0; 64 65 initFonts(); 66 LOGDEBUG("font initialized"); 67 initDisplayString(); 68 LOGDEBUG("display string '" + displayString_ + "' initialized"); 69 theme_->initTheme(themeSettings_, XCORE->defaultColormap(id_)); 70 LOGDEBUG("colors initialized"); 71 initGC(); 72 LOGDEBUG("GC initialized"); 73 initBars(); 74 LOGDEBUG("bars initialized"); 75 XCORE->sync(); 76 #ifdef SLOT_SUPPORT 77 initSlot(); 78 LOGDEBUG("slot initialized"); 79 #endif // SLOT_SUPPORT 80 initWorkspaces(); 81 LOGDEBUG("workspaces initialized"); 82 83 XCORE->selectEvents(rootWindow_, 84 SubstructureRedirectMask | SubstructureNotifyMask 85 | PropertyChangeMask); 86 87 KERNEL->installCursor(Cursors::NORMAL_CURSOR, rootWindow_); 88 89 XCORE->sync(); 90 } 91 92 void Monitor::initFonts() { 93 94 string fontName = Util::get(KERNEL->themeSettings(), "font"); 95 font_ = WFont::load(this, fontName); 96 if (!font_) { 97 // fallback, trying to load "fixed" 98 LOGWARN("cannot load font '" + fontName + 99 "', trying loading default font 'fixed'"); 100 font_ = WFont::load(this, "fixed"); 101 if (!font_) { 102 LOGERROR("cannot load any font", true); 103 // exits WMI 104 } 105 } 106 if (font_->height() < MINIMAL_BARHEIGHT) { 107 font_->setHeight(MINIMAL_BARHEIGHT); 108 } 109 if (font_->type() == WFont::XFT) { 110 fixed_ = XFont::load(this, "fixed"); 111 if (!fixed_) { 112 LOGERROR("cannot load any font", true); 113 // exits WMI 114 } 115 } 116 } 117 118 void Monitor::initBars() { 119 120 Rectangle rect(0, 0, width(), titleBarHeight() + 2); 121 122 if (Util::get(commonSettings_, "statusbar.alignment") != "bottom") { 123 statusBar_ = new StatusBar(this, &rect); 124 inputBar_ = new InputBar(this, &rect); 125 rect.setY(height() - rect.height()); 126 clientBar_ = new ClientBar(this, &rect); 127 } 128 else { 129 clientBar_ = new ClientBar(this, &rect); 130 rect.setY(height() - rect.height()); 131 statusBar_ = new StatusBar(this, &rect); 132 inputBar_ = new InputBar(this, &rect); 133 } 134 135 rect.setY(height() / 2 - rect.height() / 2); 136 box_ = new Box(this, &rect, ""); 137 } 138 139 void Monitor::initGC() { 140 141 unsigned long mask = 142 GCForeground | GCGraphicsExposures 143 | GCFunction | GCSubwindowMode | GCLineWidth 144 | GCPlaneMask; 145 XGCValues gcv; 146 gcv.subwindow_mode=IncludeInferiors; 147 gcv.function=GXxor; 148 gcv.foreground = theme_->FRAME_PSEUDO; 149 gcv.fill_style=FillSolid; 150 gcv.line_width = Util::strToUInt( 151 Util::get(KERNEL->commonSettings(), "border.width")); 152 gcv.plane_mask = AllPlanes; 153 gcv.graphics_exposures = False; 154 if (font_->type() == WFont::NORMAL) { 155 gcv.font = ((XFont *)font_)->font()->fid; 156 mask |= GCFont; 157 } 158 159 pseudoBorderGC_ = XCORE->createGC(rootWindow_, mask, &gcv); 160 161 gcv.function=GXcopy; 162 borderGC_ = XCORE->createGC(rootWindow_, mask, &gcv); 163 } 164 165 Monitor::~Monitor() { 166 for (MClient::iterator it = clients_.begin(); 167 it != clients_.end(); it++) 168 { 169 Client *client = (*it).second; 170 clients_.erase(it); 171 delete client; 172 } 173 delete statusBar_; 174 delete clientBar_; 175 #ifdef SLOT_SUPPORT 176 delete slot_; 177 #endif // SLOT_SUPPORT 178 } 179 180 void Monitor::rectForWorkspace(Workspace *workspace) { 181 182 bool isClientBarVisible = workspace->isClientBarVisible(); 183 bool isStatusBarVisible = workspace->isStatusBarVisible(); 184 185 // bar dimensions 186 if (Util::get(commonSettings_, "statusbar.alignment") != "bottom") { 187 workspace->setY((isStatusBarVisible ? statusBar_->height() : 0)); 188 } 189 else { 190 workspace->setY((isClientBarVisible ? clientBar_->height() : 0)); 191 } 192 workspace->setHeight(height() 193 - (isStatusBarVisible ? statusBar_->height() : 0) 194 - (isClientBarVisible ? clientBar_->height() : 0)); 195 196 #ifdef SLOT_SUPPORT 197 static bool isSlotOverlap = 198 Util::get(commonSettings_, "slot.mode") == "overlap"; 199 // slot dimensions 200 if (workspace->isSlotVisible() && !isSlotOverlap 201 && slot_->hasClients()) 202 { 203 if (slot_->alignment() == LEFT) { 204 workspace->setX(slot_->width()); 205 } 206 else { 207 workspace->setX(x()); 208 } 209 workspace->setWidth(width() - slot_->width()); 210 } 211 else 212 #endif // SLOT_SUPPORT 213 { 214 workspace->setX(x()); 215 workspace->setWidth(width()); 216 } 217 } 218 219 void Monitor::initWorkspaces() { 220 221 string key = prefix_ + ".workspaces"; 222 223 unsigned int workspaceCount = 224 Util::strToUInt(Util::get(sessionSettings_, key)); 225 string id = 226 Util::get(KERNEL->sessionSettings(), prefix_ + ".focused"); 227 unsigned int focusedWSNum = (id != "") ? Util::strToUInt(id) : 0; 228 229 Rectangle rect; 230 Workspace *toFocus = 0; 231 for (unsigned int i = 0; i < workspaceCount; i++) { 232 Workspace *workspace = new Workspace(this, i, &rect); 233 matchWorkspace(workspace, LEFT); 234 attach(workspace); 235 if (i == focusedWSNum) { 236 toFocus = workspace; 237 } 238 } 239 LOGDEBUG("workspaces created"); 240 XCORE->sync(); 241 focus(toFocus); 242 } 243 244 void Monitor::initDisplayString() { 245 246 ostringstream oss; 247 248 displayString_ = DisplayString(attached()); 249 unsigned int dot = displayString_.rfind('.'); 250 251 LOGDEBUG("initializing display string '" + displayString_ + "'"); 252 oss << "DISPLAY="; 253 LOGDEBUG("ok displayString_"); 254 if (dot > 0) { 255 oss << displayString_.substr(0, dot + 1) << id_; 256 } 257 else { 258 oss << displayString_; 259 } 260 261 displayString_ = oss.str(); 262 } 263 264 void Monitor::scanWindows() { 265 266 unsigned int numWindows = 0; 267 Window *windows; 268 XWindowAttributes attr; 269 270 // Queries only the tree of this monitor 271 XCORE->queryTree(rootWindow_, &windows, &numWindows); 272 273 ostringstream oss; 274 oss << "scanning " << numWindows << " windows"; 275 LOGDEBUG(oss.str()); 276 for (unsigned int i = 0; i < numWindows; i++) { 277 XCORE->windowAttributes(windows[i], &attr); 278 279 // ignore default windows 280 if (attr.override_redirect || 281 menuWindow(windows[i]) || 282 (box_->window() == windows[i]) || 283 barWindow(windows[i]) || 284 #ifdef SLOT_SUPPORT 285 slotWindow(windows[i]) || 286 #endif // SLOT_SUPPORT 287 (windows[i] == rootWindow_)) 288 { 289 LOGDEBUG("ignoring scanned window (override redirect)"); 290 continue; 291 } 292 293 if (XCORE->transient(windows[i])) { 294 LOGDEBUG("ignoring scanned window (transient)"); 295 continue; 296 } 297 298 // determine client 299 Client *client; 300 if ((client = clientForWindow(windows[i])) == 0) { 301 if (attr.map_state == IsViewable) { 302 client = new Client(this, windows[i], &attr); 303 addClient(client); 304 attachClient(client); 305 } 306 } 307 } 308 if (windows) { 309 XCORE->free((void *)windows); 310 } 311 } 312 313 Thing *Monitor::thingWindow(Window window) { 314 315 for (LWorkspace::iterator it = begin(); it != end(); it++) { 316 Workspace *workspace = *it; 317 Thing *thing = workspace->thingWindow(window); 318 if (thing) { 319 return thing; 320 } 321 } 322 return 0; 323 } 324 325 326 Bar *Monitor::barWindow(Window window) { 327 328 if (statusBar_->window() == window) { 329 return statusBar_; 330 } 331 if (clientBar_->window() == window) { 332 return clientBar_; 333 } 334 if (inputBar_->window() == window) { 335 return inputBar_; 336 } 337 return 0; 338 } 339 340 Menu *Monitor::menuWindow(Window window) { 341 Menu *menu = clientBar_->menu(); 342 if (clientBar_->menu()->window() == window) { 343 return menu; 344 } 345 346 return 0; 347 } 348 349 #ifdef SLOT_SUPPORT 350 void Monitor::initSlot() { 351 352 Direction align; 353 string valueAlign = Util::get(commonSettings_, "slot.alignment"); 354 Rectangle rect; 355 356 int offsetX = 0; 357 if (valueAlign == "right") { 358 align = RIGHT; 359 offsetX = width() - 1; // initial offset :) 360 } 361 else { 362 align = LEFT; 363 } 364 rect = Rectangle(offsetX, titleBarHeight(), 1, 365 height() - 2 * titleBarHeight()); 366 367 slot_ = new Slot(this, &rect, align); 368 } 369 370 371 Slot *Monitor::slotWindow(Window window) { 372 373 if (slot_->window() == window) { 374 return slot_; 375 } 376 377 return 0; 378 } 379 380 Slot *Monitor::slot() const { 381 return slot_; 382 } 383 384 void Monitor::unslotClient() { 385 386 Client *client = slot_->focused()->focused(); 387 if (client) { 388 slot_->detachClient(client); 389 client->setMode(Client::FLOAT); 390 attachClient(client); 391 } 392 } 393 394 void Monitor::slotClient() { 395 396 Client *client = focusedClient(); 397 if (client) { 398 // HACK: removeClient also removes it from clients 399 // TODO: thus it would be useful to distinguish removeClient 400 // with detachClient -> overwork around wmi-10 401 removeClient(client); 402 addClient(client); // we've to add it again, because it was removed 403 client->setMode(Client::SLOT); 404 attachClient(client); 405 } 406 } 407 408 void Monitor::toggleSlot() { 409 410 if (slot_->isVisible()) { 411 focused()->setSlotVisible(false); 412 slot_->hide(); 413 } 414 else { 415 focused()->setSlotVisible(true); 416 slot_->show(focused()->slotTabName()); 417 slot_->manage(); 418 } 419 420 focused()->setSlotVisible(slot_->isVisible()); 421 } 422 423 void Monitor::cycleSlotTabPrev() { 424 slot_->focused()->hide(); 425 slot_->focus(slot_->prev()); 426 slot_->focused()->show(); 427 slot_->manage(); 428 } 429 430 void Monitor::cycleSlotTabNext() { 431 slot_->focused()->hide(); 432 slot_->focus(slot_->next()); 433 slot_->focused()->show(); 434 slot_->manage(); 435 } 436 #endif // SLOT_SUPPORT 437 438 Client *Monitor::clientForWindow(Window window) { 439 440 if (window == 0 || window == rootWindow_) { 441 return 0; 442 } 443 444 MClient::iterator it = clients_.find((long)window); 445 446 if (it != clients_.end()) { 447 return (*it).second; 448 } 449 450 // client does not exist 451 return 0; 452 } 453 454 void Monitor::addClient(Client *client) { 455 456 clients_[(long)client->clientWindow()] = client; 457 } 458 459 void Monitor::cleanup() { 460 while (clients_.size()) { 461 MClient::iterator it = clients_.begin(); 462 Client *client = (*it).second; 463 removeClient(client); 464 if (!client->transient()) { 465 XCORE->addToSaveSet(client->clientWindow()); 466 } 467 delete client; 468 } 469 } 470 471 Client *Monitor::focusedClient() { 472 return focused()->topClient(); 473 } 474 475 void Monitor::removeClient(Client *client) { 476 477 XCORE->sync(); 478 LOGDEBUG("removing client"); 479 480 Workspace *workspace = client->attached(); 481 if (workspace) { 482 workspace->detachClient(client); 483 LOGDEBUG("client removed from workspace"); 484 } 485 #ifdef SLOT_SUPPORT 486 else if (client->mode() == Client::SLOT) { 487 LOGDEBUG("removing slot client"); 488 slot_->detachClient(client); 489 matchWorkspace(focused(), slot_->alignment()); 490 } 491 #endif 492 else if (!client->isVisible()) { 493 // seems to be an detached client 494 detachedClients_.detach(client); 495 XCORE->sync(); 496 LOGDEBUG("removing detached client"); 497 statusBar_->illuminate(); 498 } 499 // else already detached 500 XCORE->sync(); 501 clients_.erase((long)client->clientWindow()); 502 LOGDEBUG("client removed"); 503 } 504 505 void Monitor::matchWorkspace(Workspace *workspace, Direction dir) { 506 507 rectForWorkspace(workspace); 508 workspace->matchBarNeighbors(dir); 509 #ifdef SLOT_SUPPORT 510 // slot fix 511 slot_->setY(workspace->y()); 512 #endif // SLOT_SUPPORT 513 } 514 515 void Monitor::toggleClientBar() { 516 517 if (clientBar_->isVisible()) { 518 clientBar_->hide(); 519 } 520 else { 521 clientBar_->show(); 522 } 523 524 focused()->setClientBarVisible(clientBar_->isVisible()); 525 Direction dir = 526 (Util::get(commonSettings_, "statusbar.alignment") == "bottom") ? UP : DOWN; 527 matchWorkspace(focused(), dir); 528 #ifdef SLOT_SUPPORT 529 slot_->manage(); 530 #endif // SLOT_SUPPORT 531 } 532 533 void Monitor::toggleStatusBar() { 534 535 if (statusBar_->isVisible()) { 536 statusBar_->hide(); 537 } 538 else { 539 statusBar_->show(); 540 } 541 542 focused()->setStatusBarVisible(statusBar_->isVisible()); 543 Direction dir = 544 (Util::get(commonSettings_, "statusbar.alignment") != "bottom") ? UP : DOWN; 545 matchWorkspace(focused(), dir); 546 #ifdef SLOT_SUPPORT 547 slot_->manage(); 548 #endif // SLOT_SUPPORT 549 } 550 551 void Monitor::toggleAllClientStates() { 552 553 Workspace *workspace = focused(); 554 assert(workspace); 555 Thing *thing = workspace->focusedThing(); 556 557 if (!thing || (thing->type() != Thing::FRAME)) { 558 return; 559 } 560 Frame *frame = (Frame *)thing; 561 562 unsigned int num = frame->size(); 563 for (unsigned int i = 0; (i < num) && (frame->size() != 0); i++) { 564 workspace->changeClientMode(frame->focused(), Client::FLOAT); 565 } 566 statusBar_->illuminate(); 567 } 568 569 void Monitor::attachAllClients() { 570 571 while (detachedClients_.size()) { 572 Client *client = *detachedClients_.begin(); 573 detachedClients_.detach(client); 574 attachClient(client); 575 } 576 } 577 578 void Monitor::detachAllClients() { 579 580 Workspace *workspace = focused(); 581 assert(workspace); 582 583 if (workspace->isFrameMode()) { 584 Frame *frame = workspace->focusedFrame(); 585 unsigned int i = frame->size(); 586 while (i) { 587 detachClient(*frame->begin()); 588 i--; 589 } 590 } 591 else { 592 CClient *floatingClients = workspace->floatingClients(); 593 unsigned int i = floatingClients->size(); 594 while (i) { 595 detachClient(*floatingClients->begin()); 596 i--; 597 } 598 } 599 statusBar_->illuminate(); 600 } 601 602 void Monitor::detachClient(Client *client) { 603 604 if (!client) { 605 return; 606 } 607 608 Workspace *workspace = client->attached(); 609 610 if (workspace) { 611 workspace->detachClient(client); 612 detachedClients_.attach(client); 613 } 614 } 615 616 void Monitor::detachClient() { 617 detachClient(focused()->topClient()); 618 } 619 620 void Monitor::attachClientByName(string name) { 621 622 for (LClient::iterator it = detachedClients_.begin(); 623 it != detachedClients_.end(); it++) 624 { 625 Client *client = *it; 626 if (client->name() == name) { 627 detachedClients_.detach(client); 628 attachClient(client); 629 return; 630 } 631 } 632 } 633 634 void Monitor::attachLastClient() { 635 636 Client *client = detachedClients_.focused(); 637 if (client) { 638 detachedClients_.detach(client); 639 attachClient(client); 640 } 641 } 642 643 void Monitor::attachClient(Client *client) { 644 645 // first we've to init all necessary info 646 client->initICCCM(); 647 648 if (client->state() == IconicState) { 649 assert(!client->attached()); 650 detachedClients_.attach(client); 651 return; 652 } 653 654 // first transient handling 655 Client *transient = client->transient(); 656 657 if (transient && !transient->attached() 658 #ifdef SLOT_SUPPORT 659 && (transient->mode() != Client::SLOT) 660 #endif // SLOT_SUPPORT 661 ) 662 { 663 // attach also the transient, if some 664 detachedClients_.detach(transient); 665 attachClient(transient); 666 } 667 668 #ifdef SLOT_SUPPORT 669 if (client->mode() == Client::SLOT) { 670 // will be handled by the slot 671 LOGDEBUG("new slot client"); 672 slot_->attachClient(client); 673 } 674 else 675 #endif // SLOT_SUPPORT 676 { 677 Workspace *hooked = workspaceForName(client->hooked()); 678 if (hooked && contains(hooked)) { 679 focus(hooked); 680 } 681 focused()->attachClient(client); 682 } 683 } 684 685 void Monitor::attachDetachedClient(Workspace *workspace, Client *client) { 686 687 focus(workspace); 688 detachedClients_.detach(client); 689 attachClient(client); 690 } 691 692 void Monitor::createNewWorkspace(string name) { 693 694 static Rectangle rect; 695 unsigned int id = size(); 696 697 ostringstream key; 698 key << prefix_ << ".workspace[" << id << "]"; 699 700 (*sessionSettings_)[key.str() + ".name"] = name; 701 (*sessionSettings_)[key.str() + ".clientbar"] = "yes"; 702 (*sessionSettings_)[key.str() + ".statusbar"] = "yes"; 703 #ifdef SLOT_SUPPORT 704 (*sessionSettings_)[key.str() + ".slot"] = slot_->tabName(); 705 #endif // SLOT_SUPPORT 706 (*sessionSettings_)[key.str() + ".focused"] = "0"; 707 708 if (focused()) { 709 focused()->hide(); 710 } 711 Workspace *workspace = new Workspace(this , id, this); 712 matchWorkspace(workspace, LEFT); 713 attach(workspace); 714 focused()->show(); 715 716 ostringstream value; 717 value << size(); 718 (*sessionSettings_)[prefix_ + ".workspaces"] = value.str(); 719 } 720 721 void Monitor::serialize() { 722 723 ostringstream value; 724 value << size(); 725 (*sessionSettings_)[prefix_ + ".workspaces"] = value.str(); 726 727 for (LWorkspace::iterator it = begin(); it != end(); it++) { 728 Workspace *workspace = *it; 729 workspace->serialize(); 730 } 731 732 value.str(""); 733 value << focused()->id(); 734 (*sessionSettings_)[prefix_ + ".focused"] = value.str(); 735 } 736 737 void Monitor::focus(Workspace *workspace) { 738 739 workspace->setRequestsFocus(false); 740 if (focused() != workspace) { 741 focused()->hide(); 742 LOGDEBUG("focussing workspace"); 743 XCORE->sync(); 744 Container<Display, LWorkspace, LWorkspace::iterator, 745 Workspace>::focus(workspace); 746 } 747 focused()->show(); 748 updateBars(); 749 } 750 751 void Monitor::focusClient(Client *client) { 752 753 Workspace *workspace = client->attached(); 754 if (workspace) { 755 focus(workspace); 756 workspace->focus(client); 757 } 758 } 759 760 void Monitor::focusClientById(string id) { 761 762 for (MClient::iterator it = clients_.begin(); 763 it != clients_.end(); it++) 764 { 765 Client *client = (*it).second; 766 767 if (client->id() == id) { 768 focusClient(client); 769 } 770 } 771 } 772 773 void Monitor::focusClientByName(string name) { 774 775 for (MClient::iterator it = clients_.begin(); 776 it != clients_.end(); it++) 777 { 778 Client *client = (*it).second; 779 780 if (client->name() == name) { 781 focusClient(client); 782 } 783 } 784 } 785 786 Workspace *Monitor::workspaceForName(string name) { 787 788 for (LWorkspace::iterator it = begin(); it != end(); it++) { 789 if ((*it)->name() == name) { 790 return (Workspace *)*it; 791 } 792 } 793 return 0; 794 } 795 796 void Monitor::focusWorkspaceNum(unsigned int workspaceNum) { 797 798 unsigned int i = 0; 799 for (LWorkspace::iterator it = begin(); it != end(); it++) { 800 if (i == workspaceNum) { 801 focus(*it); 802 return; 803 } 804 i++; 805 } 806 } 807 808 void Monitor::destroyWorkspace(Workspace *workspace) { 809 810 assert(workspace); 811 if (size() > 1) { 812 LClient *clients = workspace->clients(); 813 while (clients->size()) { 814 Client *client = *clients->begin(); 815 detachClient(client); 816 KERNEL->killClient(client); 817 } 818 detach(workspace); 819 Util::remove(sessionSettings_, workspace->prefix()); 820 delete workspace; 821 focused()->show(); 822 updateBars(); 823 } 824 } 825 826 void Monitor::renameWorkspace(Workspace *workspace, string newName) { 827 workspace->setName(newName); 828 (*sessionSettings_)[workspace->prefix() + ".name"] = newName; 829 } 830 831 void Monitor::updateBars() { 832 833 static string value; 834 835 if (XCORE->textProperty(rootWindow_, Atoms::WMI_STATUSTEXT, &value)) { 836 statusBar_->setText(value); 837 } 838 if (XCORE->textProperty(rootWindow_, Atoms::WMI_METERTEXT, &value)) { 839 statusBar_->setMeterText(value); 840 } 841 842 LOGDEBUG("update status"); 843 statusBar_->illuminate(); 844 clientBar_->illuminate(); 845 XCORE->sync(); 846 } 847 848 void Monitor::toggleThingMaximization() { 849 850 if (!focused()) { 851 return; 852 } 853 854 if (maxThing_) { 855 856 maxThing_->copy(maxThing_->prevRectangle()); 857 maxThing_->resize(); 858 focused()->illuminate(); 859 maxThing_ = 0; // reset 860 861 } 862 else { 863 864 Workspace *workspace = focused(); 865 maxThing_ = workspace->focusedThing(); 866 867 if (!maxThing_) { 868 return; 869 } 870 871 maxThing_->prevRectangle()->copy(maxThing_); 872 maxThing_->setX(x()); 873 maxThing_->setY(y()); 874 maxThing_->setWidth(width()); 875 maxThing_->setHeight(height()); 876 maxThing_->resize(); 877 XCORE->raise(maxThing_->window()); 878 maxThing_->illuminate(); 879 } 880 } 881 882 void Monitor::illuminateTransRect(Rectangle *rect, unsigned int barHeight) 883 { 884 Draw::drawTransRectangle(rootWindow_, pseudoBorderGC_, rect, barHeight, 885 KERNEL->borderWidth()); 886 887 // additional size info 888 ostringstream oss; 889 oss << "x=" << rect->x() << ", y=" << rect->y() 890 << ": " << rect->width() << "x" << rect->height(); 891 892 illuminateTransText(rect, oss.str()); 893 } 894 895 unsigned int Monitor::nextClientId() { 896 ++clientIds_; 897 return clientIds_; 898 } 899 900 void Monitor::illuminateTransText(Rectangle *rect, string text) 901 { 902 WFont *font = (font_->type() == WFont::NORMAL) ? 903 font_ : fixed_; 904 905 // additional size info 906 int textWidth = font->textWidth(text); 907 unsigned int fontBaseLine = font->ascent(); 908 unsigned int fontY = rect->y() + rect->height() / 2 909 - font->height() / 2 + fontBaseLine; 910 911 unsigned int fontX = rect->x() + 912 (rect->width() / 2 - textWidth / 2); 913 font->drawText(rootWindow_, pseudoBorderGC_, 914 fontX, fontY, text); 915 } 916 917 918 unsigned int Monitor::id() const { 919 return id_; 920 } 921 922 Window Monitor::rootWindow() const { 923 return rootWindow_; 924 } 925 926 string Monitor::displayString() const { 927 return displayString_; 928 } 929 930 Theme *Monitor::theme() const { 931 return theme_; 932 } 933 934 unsigned int Monitor::resizeFactor() const { 935 return resizeFactor_; 936 } 937 938 string Monitor::prefix() const { 939 return prefix_; 940 } 941 942 Box *Monitor::box() const { 943 return box_; 944 } 945 946 StatusBar *Monitor::statusBar() const { 947 return statusBar_; 948 } 949 950 ClientBar *Monitor::clientBar() const { 951 return clientBar_; 952 } 953 954 CClient *Monitor::detachedClients() { 955 return &detachedClients_; 956 } 957 958 bool Monitor::isThingMaximized() { 959 return maxThing_ != 0; 960 } 961 962 GC Monitor::borderGC() { 963 return borderGC_; 964 } 965 966 CClient *Monitor::stickyClients() { 967 return &stickyClients_; 968 } 969 970 WFont *Monitor::font() const { 971 return font_; 972 } 973 974 unsigned int Monitor::titleBarHeight() const { 975 return font_->height() + 2; 976 } 977 978 MClient *Monitor::clients() { 979 return &clients_; 980 } 981 982 InputBar *Monitor::inputBar() const { 983 return inputBar_; 984 } 985 986 void Monitor::banish() { 987 XCORE->warpPointer(rootWindow_, width(), height()); 988 } 989 990 unsigned int Monitor::buttonWidth() const { 991 return font_->height() + 4; 992 } 993 994 void Monitor::hookClient() { 995 996 Client *client = 0; 997 #ifdef SLOT_SUPPORT 998 if (slot_->isGrabFocus() || 999 (!focused()->clients()->size() && slot_->focused()->focused())) 1000 { 1001 client = slot_->focused()->focused(); 1002 if (client) { 1003 client->setHooked(slot_->tabName()); 1004 return; 1005 } 1006 } 1007 else 1008 #endif // SLOT_SUPPORT 1009 { 1010 client = focused()->topClient(); 1011 if (client) { 1012 client->setHooked(focused()->name()); 1013 } 1014 } 1015 } 1016 1017 void Monitor::unhookClient() { 1018 1019 Client *client = 0; 1020 #ifdef SLOT_SUPPORT 1021 if (slot_->isGrabFocus() || 1022 (!focused()->clients()->size() && slot_->focused()->focused())) 1023 { 1024 client = slot_->focused()->focused(); 1025 if (client) { 1026 client->setHooked(""); 1027 return; 1028 } 1029 } 1030 else 1031 #endif // SLOT_SUPPORT 1032 { 1033 client = focused()->topClient(); 1034 if (client) { 1035 client->setHooked(""); 1036 } 1037 } 1038 }