00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "Window.hh"
00028
00029 #include "WinClient.hh"
00030 #include "I18n.hh"
00031 #include "fluxbox.hh"
00032 #include "Screen.hh"
00033 #include "FbWinFrameTheme.hh"
00034 #include "MenuTheme.hh"
00035 #include "FbAtoms.hh"
00036 #include "RootTheme.hh"
00037 #include "Workspace.hh"
00038 #include "LayerMenu.hh"
00039 #include "FbWinFrame.hh"
00040 #include "WinButton.hh"
00041 #include "WinButtonTheme.hh"
00042 #include "SendToMenu.hh"
00043
00044 #include "FbTk/StringUtil.hh"
00045 #include "FbTk/TextButton.hh"
00046 #include "FbTk/Compose.hh"
00047 #include "FbTk/EventManager.hh"
00048 #include "FbTk/MultiButtonMenuItem.hh"
00049 #include "FbTk/KeyUtil.hh"
00050
00051 #ifdef HAVE_CONFIG_H
00052 #include "config.h"
00053 #endif // HAVE_CONFIG_H
00054 #ifdef SHAPE
00055 #include <X11/extensions/shape.h>
00056 #endif // SHAPE
00057
00058
00059 #ifndef _GNU_SOURCE
00060 #define _GNU_SOURCE
00061 #endif // _GNU_SOURCE
00062
00063 #include <X11/Xatom.h>
00064 #include <X11/keysym.h>
00065
00066 #include <cstring>
00067 #include <cstdio>
00068 #include <iostream>
00069 #include <cassert>
00070 #include <functional>
00071 #include <algorithm>
00072
00073 using namespace std;
00074
00075 namespace {
00076
00077 void grabButton(Display *display, unsigned int button,
00078 Window window, Cursor cursor) {
00079
00080 const int numlock = FbTk::KeyUtil::instance().numlock();
00081 const int capslock = FbTk::KeyUtil::instance().capslock();
00082 const int scrolllock = FbTk::KeyUtil::instance().scrolllock();
00083
00084
00085
00086
00087
00088 XGrabButton(display, button, Mod1Mask|numlock, window, True,
00089 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
00090 GrabModeAsync, None, cursor);
00091
00092 XGrabButton(display, button, Mod1Mask|scrolllock, window, True,
00093 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
00094 GrabModeAsync, None, cursor);
00095
00096
00097 XGrabButton(display, button, Mod1Mask|capslock, window, True,
00098 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
00099 GrabModeAsync, None, cursor);
00100
00101
00102 XGrabButton(display, Button1, Mod1Mask|capslock|numlock, window, True,
00103 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
00104 GrabModeAsync, None, cursor);
00105
00106
00107 XGrabButton(display, button, Mod1Mask|capslock|scrolllock, window, True,
00108 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
00109 GrabModeAsync, None, cursor);
00110
00111
00112 XGrabButton(display, button, Mod1Mask|capslock|numlock|scrolllock, window,
00113 True,
00114 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
00115 GrabModeAsync, None, cursor);
00116
00117
00118 XGrabButton(display, button, Mod1Mask|numlock|scrolllock, window, True,
00119 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
00120 GrabModeAsync, None, cursor);
00121
00122 }
00123
00124
00125 typedef struct scanargs {
00126 Window w;
00127 Bool leave, inferior, enter;
00128 } scanargs;
00129
00130
00131 static Bool queueScanner(Display *, XEvent *e, char *args) {
00132 if (e->type == LeaveNotify &&
00133 e->xcrossing.window == ((scanargs *) args)->w &&
00134 e->xcrossing.mode == NotifyNormal) {
00135 ((scanargs *) args)->leave = true;
00136 ((scanargs *) args)->inferior = (e->xcrossing.detail == NotifyInferior);
00137 } else if (e->type == EnterNotify &&
00138 e->xcrossing.mode == NotifyUngrab)
00139 ((scanargs *) args)->enter = true;
00140
00141 return false;
00142 }
00143
00145 WinClient *getRootTransientFor(WinClient *client) {
00146 while (client->transientFor()) {
00147 assert(client != client->transientFor());
00148 client = client->transientFor();
00149 }
00150 return client;
00151 }
00152
00153
00155 void raiseFluxboxWindow(FluxboxWindow &win) {
00156 if (win.oplock) return;
00157 win.oplock = true;
00158
00159
00160
00161 if (!win.winClient().transientList().empty())
00162 win.screen().layerManager().lock();
00163
00164 if (!win.isIconic()) {
00165 win.screen().updateNetizenWindowRaise(win.clientWindow());
00166 win.layerItem().raise();
00167 }
00168
00169
00170 WinClient::TransientList::const_iterator it = win.winClient().transientList().begin();
00171 WinClient::TransientList::const_iterator it_end = win.winClient().transientList().end();
00172 for (; it != it_end; ++it) {
00173 if ((*it)->fbwindow() && !(*it)->fbwindow()->isIconic())
00174
00175 raiseFluxboxWindow(*(*it)->fbwindow());
00176 }
00177 win.oplock = false;
00178
00179 if (!win.winClient().transientList().empty())
00180 win.screen().layerManager().unlock();
00181 }
00182
00184 void lowerFluxboxWindow(FluxboxWindow &win) {
00185 if (win.oplock) return;
00186 win.oplock = true;
00187
00188
00189
00190 if (!win.winClient().transientList().empty())
00191 win.screen().layerManager().lock();
00192
00193 if (!win.isIconic()) {
00194 win.screen().updateNetizenWindowLower(win.clientWindow());
00195 win.layerItem().lower();
00196 }
00197
00198 WinClient::TransientList::const_iterator it = win.winClient().transientList().begin();
00199 WinClient::TransientList::const_iterator it_end = win.winClient().transientList().end();
00200 for (; it != it_end; ++it) {
00201 if ((*it)->fbwindow() && !(*it)->fbwindow()->isIconic())
00202
00203 lowerFluxboxWindow(*(*it)->fbwindow());
00204 }
00205 win.oplock = false;
00206 if (!win.winClient().transientList().empty())
00207 win.screen().layerManager().unlock();
00208 }
00209
00211 void tempRaiseFluxboxWindow(FluxboxWindow &win) {
00212 if (win.oplock) return;
00213 win.oplock = true;
00214
00215 if (!win.winClient().transientList().empty())
00216 win.screen().layerManager().lock();
00217
00218 if (!win.isIconic()) {
00219
00220 win.layerItem().tempRaise();
00221 }
00222
00223
00224 WinClient::TransientList::const_iterator it = win.winClient().transientList().begin();
00225 WinClient::TransientList::const_iterator it_end = win.winClient().transientList().end();
00226 for (; it != it_end; ++it) {
00227 if ((*it)->fbwindow() && !(*it)->fbwindow()->isIconic())
00228
00229 tempRaiseFluxboxWindow(*(*it)->fbwindow());
00230 }
00231 win.oplock = false;
00232
00233 if (!win.winClient().transientList().empty())
00234 win.screen().layerManager().unlock();
00235
00236 }
00237
00238 class SetClientCmd:public FbTk::Command {
00239 public:
00240 explicit SetClientCmd(WinClient &client):m_client(client) {
00241 }
00242 void execute() {
00243 if (m_client.m_win != 0)
00244 m_client.m_win->setCurrentClient(m_client);
00245 }
00246 private:
00247 WinClient &m_client;
00248 };
00249
00250 };
00251
00252 template <>
00253 void LayerMenuItem<FluxboxWindow>::click(int button, int time) {
00254 m_object->moveToLayer(m_layernum);
00255 }
00256
00257 FluxboxWindow::FluxboxWindow(WinClient &client, FbWinFrameTheme &tm,
00258 FbTk::XLayer &layer):
00259 oplock(false),
00260 m_hintsig(*this),
00261 m_statesig(*this),
00262 m_layersig(*this),
00263 m_workspacesig(*this),
00264 m_diesig(*this),
00265 m_focussig(*this),
00266 m_titlesig(*this),
00267 moving(false), resizing(false), shaded(false),
00268 iconic(false), focused(false),
00269 stuck(false), m_managed(false),
00270 maximized(MAX_NONE),
00271 m_screen(client.screen()),
00272 display(FbTk::App::instance()->display()),
00273 m_windowmenu(client.screen().menuTheme(), client.screen().imageControl(),
00274 *client.screen().layerManager().getLayer(Fluxbox::instance()->getMenuLayer())),
00275 m_old_decoration(DECOR_NORMAL),
00276 m_client(&client),
00277 m_frame(tm, client.screen().imageControl(), 0, 0, 100, 100),
00278 m_layeritem(m_frame.window(), layer),
00279 m_layernum(layer.getLayerNum()),
00280 m_parent(client.screen().rootWindow()),
00281 m_resize_corner(RIGHTBOTTOM) {
00282
00283 init();
00284 }
00285
00286
00287 FluxboxWindow::~FluxboxWindow() {
00288 #ifdef DEBUG
00289 cerr<<__FILE__<<"("<<__LINE__<<"): starting ~FluxboxWindow("<<this<<")"<<endl;
00290 cerr<<__FILE__<<"("<<__LINE__<<"): num clients = "<<numClients()<<endl;
00291 cerr<<__FILE__<<"("<<__LINE__<<"): curr client = "<<m_client<<endl;
00292 cerr<<__FILE__<<"("<<__LINE__<<"): m_labelbuttons.size = "<<m_labelbuttons.size()<<endl;
00293 #endif // DEBUG
00294
00295 if (moving || resizing || m_attaching_tab) {
00296 screen().hideGeometry();
00297 XUngrabPointer(display, CurrentTime);
00298 }
00299
00300
00301 Fluxbox::instance()->removeWindowSearchGroup(frame().window().window());
00302
00303 Client2ButtonMap::iterator it = m_labelbuttons.begin();
00304 Client2ButtonMap::iterator it_end = m_labelbuttons.end();
00305 for (; it != it_end; ++it) {
00306 frame().removeLabelButton(*(*it).second);
00307 delete (*it).second;
00308 }
00309 m_labelbuttons.clear();
00310
00311 m_timer.stop();
00312
00313
00314 m_diesig.notify();
00315
00316 if (m_client != 0)
00317 delete m_client;
00318 m_client = 0;
00319
00320 if (m_clientlist.size() > 1) {
00321 cerr<<__FILE__<<"("<<__FUNCTION__<<") WARNING! clientlist > 1"<<endl;
00322 while (!m_clientlist.empty()) {
00323 detachClient(*m_clientlist.back());
00324 }
00325 }
00326
00327
00328 ExtraMenus::iterator mit = m_extramenus.begin();
00329 ExtraMenus::iterator mit_end = m_extramenus.end();
00330 for (; mit != mit_end; ++mit) {
00331
00332
00333
00334
00335
00336 mit->second->setInternalMenu(false);
00337 }
00338
00339 #ifdef DEBUG
00340 cerr<<__FILE__<<"("<<__LINE__<<"): ~FluxboxWindow("<<this<<")"<<endl;
00341 #endif // DEBUG
00342 }
00343
00344
00345 void FluxboxWindow::init() {
00346 m_attaching_tab = 0;
00347
00348 assert(m_client);
00349 m_client->m_win = this;
00350 m_client->setGroupLeftWindow(None);
00351
00352
00353 m_shaped = false;
00354
00355 if (Fluxbox::instance()->haveShape()) {
00356 Shape::setShapeNotify(winClient());
00357 m_shaped = Shape::isShaped(winClient());
00358 }
00359
00360 frame().setUseShape(!m_shaped);
00361
00363
00364 m_clientlist.push_back(m_client);
00365 #ifdef DEBUG
00366 cerr<<__FILE__<<": FluxboxWindow::init(this="<<this<<", client="<<hex<<
00367 m_client->window()<<", frame = "<<frame().window().window()<<dec<<")"<<endl;
00368
00369 #endif // DEBUG
00370
00371 Fluxbox &fluxbox = *Fluxbox::instance();
00372
00373
00374 frame().gripLeft().setCursor(frame().theme().lowerLeftAngleCursor());
00375 frame().gripRight().setCursor(frame().theme().lowerRightAngleCursor());
00376
00377
00378 FbTk::TextButton *btn = new FbTk::TextButton(frame().label(),
00379 frame().theme().font(),
00380 m_client->title());
00381 btn->setJustify(frame().theme().justify());
00382 m_labelbuttons[m_client] = btn;
00383 frame().addLabelButton(*btn);
00384 frame().setLabelButtonFocus(*btn);
00385 btn->show();
00386 FbTk::EventManager &evm = *FbTk::EventManager::instance();
00387
00388 btn->setEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask |
00389 ButtonMotionMask | EnterWindowMask);
00390
00391 FbTk::RefCount<FbTk::Command> set_client_cmd(new SetClientCmd(*m_client));
00392 btn->setOnClick(set_client_cmd);
00393 evm.add(*this, btn->window());
00394 evm.add(*this, m_client->window());
00395
00396
00397
00398 frame().setEventHandler(*this);
00399
00400 frame().resize(m_client->width(), m_client->height());
00401
00402 m_last_focus_time.tv_sec = m_last_focus_time.tv_usec = 0;
00403
00404 m_blackbox_attrib.workspace = m_workspace_number = ~0;
00405
00406 m_blackbox_attrib.flags = m_blackbox_attrib.attrib = m_blackbox_attrib.stack = 0;
00407 m_blackbox_attrib.premax_x = m_blackbox_attrib.premax_y = 0;
00408 m_blackbox_attrib.premax_w = m_blackbox_attrib.premax_h = 0;
00409
00410
00411 decorations.tab = true;
00412
00413 decorations.enabled = true;
00414
00415
00416 decorations.menu = true;
00417
00418 decorations.titlebar = decorations.border = decorations.handle = true;
00419 decorations.maximize = decorations.close =
00420 decorations.sticky = decorations.shade = decorations.tab = true;
00421
00422
00423 functions.resize = functions.move = functions.iconify = functions.maximize = true;
00424 decorations.close = false;
00425
00426 if (m_client->getBlackboxHint() != 0)
00427 updateBlackboxHintsFromClient(*m_client);
00428 else
00429 updateMWMHintsFromClient(*m_client);
00430
00432
00433 XWindowAttributes wattrib;
00434 if (! m_client->getAttrib(wattrib) ||
00435 !wattrib.screen
00436 || wattrib.override_redirect) {
00437 return;
00438 }
00439
00440
00441 m_client->old_bw = wattrib.border_width;
00442 m_client->x = wattrib.x; m_client->y = wattrib.y;
00443
00444 m_timer.setTimeout(fluxbox.getAutoRaiseDelay());
00445 FbTk::RefCount<FbTk::Command> raise_cmd(new FbTk::SimpleCommand<FluxboxWindow>(*this, &FluxboxWindow::raise));
00446 m_timer.setCommand(raise_cmd);
00447 m_timer.fireOnce(true);
00448
00449 if (m_client->initial_state == WithdrawnState) {
00450 return;
00451 }
00452
00453 m_managed = true;
00454
00455 Fluxbox::instance()->saveWindowSearchGroup(frame().window().window(), this);
00456
00457
00458 m_client->updateTransientInfo();
00459
00460
00461 if (m_client->isTransient()) {
00462 decorations.maximize = functions.maximize = false;
00463 decorations.handle = false;
00464 }
00465
00466 if ((m_client->normal_hint_flags & PMinSize) &&
00467 (m_client->normal_hint_flags & PMaxSize) &&
00468 m_client->max_width != 0 && m_client->max_width <= m_client->min_width &&
00469 m_client->max_height != 0 && m_client->max_height <= m_client->min_height) {
00470 decorations.maximize = decorations.handle =
00471 functions.resize = functions.maximize = false;
00472 decorations.tab = false;
00473 }
00474
00475 upsize();
00476
00477 applyDecorations(true);
00478
00479 associateClientWindow(true, wattrib.x, wattrib.y, wattrib.width, wattrib.height);
00480
00481 grabButtons();
00482
00483 if (m_workspace_number < 0 || m_workspace_number >= screen().getCount())
00484 m_workspace_number = screen().currentWorkspaceID();
00485
00486 restoreAttributes();
00487
00488 bool place_window = true;
00489 if (fluxbox.isStartup() || m_client->isTransient() ||
00490 m_client->normal_hint_flags & (PPosition|USPosition)) {
00491
00492 frame().gravityTranslate(wattrib.x, wattrib.y, m_client->gravity(), false);
00493
00494 if (! fluxbox.isStartup()) {
00495
00496 int real_x = frame().x();
00497 int real_y = frame().y();
00498
00499 if (real_x >= 0 &&
00500 real_y + frame().y() >= 0 &&
00501 real_x <= (signed) screen().width() &&
00502 real_y <= (signed) screen().height())
00503 place_window = false;
00504
00505 } else
00506 place_window = false;
00507
00508 }
00509 if (wattrib.width <= 0)
00510 wattrib.width = 1;
00511 if (wattrib.height <= 0)
00512 wattrib.height = 1;
00513
00514
00515 if (m_client->isTransient() &&
00516 m_client->transientFor()->fbwindow() &&
00517 m_client->transientFor()->fbwindow() != this)
00518 layerItem().setLayer(m_client->transientFor()->fbwindow()->layerItem().getLayer());
00519 else
00520 moveToLayer(m_layernum);
00521
00522 if (!place_window)
00523 moveResize(frame().x(), frame().y(), frame().width(), frame().height());
00524
00525
00526
00527 screen().getWorkspace(m_workspace_number)->addWindow(*this, place_window);
00528
00529 if (shaded) {
00530 shaded = false;
00531 shade();
00532 }
00533
00534 if (maximized && functions.maximize) {
00535
00536 int req_maximized = maximized;
00537
00538 maximized = MAX_NONE;
00539 maximize(req_maximized);
00540 }
00541
00542 if (stuck) {
00543 stuck = false;
00544 stick();
00545 deiconify();
00546 }
00547
00548 setState(m_current_state);
00549
00550
00551 addExtraMenu("Send To...", new SendToMenu(*this));
00552 addExtraMenu("Layer...",
00553 new LayerMenu<FluxboxWindow>(screen().menuTheme(),
00554 screen().imageControl(),
00555 *screen().layerManager().getLayer(Fluxbox::instance()->getMenuLayer()),
00556 this,
00557 false));
00558
00559
00560
00561
00562 sendConfigureNotify();
00563
00564 setFocusFlag(false);
00565
00566 if (m_shaped)
00567 shape();
00568
00569 FbTk::App::instance()->sync(false);
00570
00571 }
00572
00574 void FluxboxWindow::shape() {
00575 #ifdef SHAPE
00576 if (m_shaped) {
00577 XShapeCombineShape(display,
00578 frame().window().window(), ShapeBounding,
00579 0, frame().clientArea().y(),
00580 m_client->window(),
00581 ShapeBounding, ShapeSet);
00582 XFlush(display);
00583 }
00584 #endif // SHAPE
00585
00586 }
00587
00588
00590 void FluxboxWindow::attachClient(WinClient &client) {
00592 if (client.m_win == this)
00593 return;
00594
00595
00596 frame().setClientWindow(client);
00597 FbTk::EventManager &evm = *FbTk::EventManager::instance();
00598
00599
00600 Window leftwin = None;
00601 if (!clientList().empty())
00602 leftwin = clientList().back()->window();
00603
00604 client.setGroupLeftWindow(leftwin);
00605
00606 if (client.fbwindow() != 0) {
00607 FluxboxWindow *old_win = client.fbwindow();
00608
00609
00610 ClientList::iterator client_it = old_win->clientList().begin();
00611 ClientList::iterator client_it_end = old_win->clientList().end();
00612 for (; client_it != client_it_end; ++client_it) {
00613
00614 evm.add(*this, (*client_it)->window());
00615
00616
00617 frame().setClientWindow(**client_it);
00618 moveResizeClient(**client_it,
00619 frame().clientArea().x(),
00620 frame().clientArea().y(),
00621 frame().clientArea().width(),
00622 frame().clientArea().height());
00623
00624 (*client_it)->m_win = this;
00625
00626
00627 FbTk::TextButton *btn = new FbTk::TextButton(frame().label(),
00628 frame().theme().font(),
00629 (*client_it)->title());
00630 btn->setJustify(frame().theme().justify());
00631 m_labelbuttons[(*client_it)] = btn;
00632 frame().addLabelButton(*btn);
00633 btn->show();
00634
00635 btn->setEventMask(ExposureMask | ButtonPressMask |
00636 ButtonReleaseMask | ButtonMotionMask |
00637 EnterWindowMask);
00638
00639
00640 FbTk::RefCount<FbTk::Command>
00641 set_client_cmd(new SetClientCmd(*(*client_it)));
00642 btn->setOnClick(set_client_cmd);
00643 evm.add(*this, btn->window());
00644
00645 (*client_it)->saveBlackboxAttribs(m_blackbox_attrib);
00646 }
00647
00648
00649
00650
00651 m_clientlist.splice(m_clientlist.end(), old_win->m_clientlist);
00652 old_win->m_client = 0;
00653
00654 delete old_win;
00655
00656 } else {
00657
00658 FbTk::TextButton *btn = new FbTk::TextButton(frame().label(),
00659 frame().theme().font(),
00660 client.title());
00661 m_labelbuttons[&client] = btn;
00662 frame().addLabelButton(*btn);
00663 btn->show();
00664 FbTk::EventManager &evm = *FbTk::EventManager::instance();
00665
00666 btn->setEventMask(ExposureMask | ButtonPressMask |
00667 ButtonReleaseMask | ButtonMotionMask |
00668 EnterWindowMask);
00669
00670
00671 FbTk::RefCount<FbTk::Command> set_client_cmd(new SetClientCmd(client));
00672 btn->setOnClick(set_client_cmd);
00673 evm.add(*this, btn->window());
00674
00675 client.m_win = this;
00676
00677 client.saveBlackboxAttribs(m_blackbox_attrib);
00678 m_clientlist.push_back(&client);
00679 }
00680
00681
00682
00683
00684 m_statesig.notify();
00685 m_workspacesig.notify();
00686 m_layersig.notify();
00687
00688 frame().reconfigure();
00689
00690
00691 m_client->raise();
00692 }
00693
00694
00696 bool FluxboxWindow::detachClient(WinClient &client) {
00697 if (client.m_win != this || numClients() <= 1)
00698 return false;
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 Window leftwin = None;
00709 ClientList::iterator client_it_end = clientList().end();
00710 ClientList::iterator client_it = clientList().begin();
00711 ClientList::iterator client_it_before = client_it_end;
00712 ClientList::iterator client_it_after = clientList().begin();
00713 if (!clientList().empty()) {
00714 ++client_it_after;
00715 if (clientList().front() == &client) {
00716 leftwin = None;
00717 } else {
00718 ++client_it;
00719 client_it_before = clientList().begin();
00720 ++client_it_after;
00721
00722 while (client_it != client_it_end) {
00723 if (*client_it == &client) {
00724 break;
00725 }
00726 ++client_it_before;
00727 ++client_it;
00728 ++client_it_after;
00729 }
00730 }
00731 }
00732
00733
00734 if (client_it_before != client_it_end)
00735 leftwin = (*client_it_before)->window();
00736
00737 if (client_it_after != client_it_end)
00738 (*client_it_after)->setGroupLeftWindow(leftwin);
00739
00740 removeClient(client);
00741
00742
00743
00744 client.m_win = screen().createWindow(client);
00745 m_client->raise();
00746 setInputFocus();
00747 return true;
00748 }
00749
00750 void FluxboxWindow::detachCurrentClient() {
00751
00752 if (numClients() <= 1)
00753 return;
00754 detachClient(*m_client);
00755 }
00756
00758 bool FluxboxWindow::removeClient(WinClient &client) {
00759 if (client.m_win != this || numClients() == 0)
00760 return false;
00761
00762 #ifdef DEBUG
00763 cerr<<__FILE__<<"("<<__FUNCTION__<<")["<<this<<"]"<<endl;
00764 #endif // DEBUG
00765
00766
00767 if (m_client == &client) {
00768
00769
00770 if (&client == m_clientlist.back())
00771 prevClient();
00772 else
00773 nextClient();
00774 }
00775
00776 client.m_win = 0;
00777 m_clientlist.remove(&client);
00778
00779 if (m_client == &client) {
00780 if (m_clientlist.empty())
00781 m_client = 0;
00782 else
00783
00784 m_client = m_clientlist.back();
00785 }
00786
00787 FbTk::EventManager &evm = *FbTk::EventManager::instance();
00788 evm.remove(client.window());
00789
00790 FbTk::TextButton *label_btn = m_labelbuttons[&client];
00791 if (label_btn != 0) {
00792 frame().removeLabelButton(*label_btn);
00793 evm.remove(label_btn->window());
00794 delete label_btn;
00795 label_btn = 0;
00796 }
00797
00798 m_labelbuttons.erase(&client);
00799
00800 frame().reconfigure();
00801
00802 #ifdef DEBUG
00803 cerr<<__FILE__<<"("<<__FUNCTION__<<")["<<this<<"] numClients = "<<numClients()<<endl;
00804 #endif // DEBUG
00805
00806 return true;
00807 }
00808
00810 WinClient *FluxboxWindow::findClient(Window win) {
00811 ClientList::iterator it = find_if(clientList().begin(),
00812 clientList().end(),
00813 FbTk::Compose(bind2nd(equal_to<Window>(), win),
00814 mem_fun(&WinClient::window)));
00815 return (it == clientList().end() ? 0 : *it);
00816 }
00817
00819 void FluxboxWindow::nextClient() {
00820 if (numClients() <= 1)
00821 return;
00822
00823 ClientList::iterator it = find(m_clientlist.begin(), m_clientlist.end(), m_client);
00824 WinClient *client = 0;
00825 if (it == m_clientlist.end()) {
00826 client = m_clientlist.front();
00827 } else {
00828 it++;
00829 if (it == m_clientlist.end())
00830 client = m_clientlist.front();
00831 else
00832 client = *it;
00833 }
00834 setCurrentClient(*client, true);
00835 }
00836
00837 void FluxboxWindow::prevClient() {
00838 if (numClients() <= 1)
00839 return;
00840
00841 ClientList::iterator it = find(m_clientlist.begin(), m_clientlist.end(), m_client);
00842 WinClient *client = 0;
00843 if (it == m_clientlist.end()) {
00844 client = m_clientlist.front();
00845 } else {
00846 if (it == m_clientlist.begin())
00847 client = m_clientlist.back();
00848 else
00849 client = *(--it);
00850 }
00851
00852 setCurrentClient(*client, true);
00853 }
00854
00855
00856 void FluxboxWindow::moveClientLeft() {
00857 if (m_clientlist.size() == 1 ||
00858 *m_clientlist.begin() == &winClient())
00859 return;
00860
00861 frame().moveLabelButtonLeft(*m_labelbuttons[&winClient()]);
00862
00863 ClientList::iterator it = find(m_clientlist.begin(), m_clientlist.end(), &winClient());
00864 ClientList::iterator new_pos = it;
00865 new_pos--;
00866 m_clientlist.erase(it);
00867 m_clientlist.insert(new_pos, &winClient());
00868
00869 updateClientLeftWindow();
00870
00871 }
00872
00873 void FluxboxWindow::moveClientRight() {
00874 if (m_clientlist.size() == 1)
00875 return;
00876
00877 frame().moveLabelButtonRight(*m_labelbuttons[&winClient()]);
00878
00879 ClientList::iterator it = find(m_clientlist.begin(), m_clientlist.end(), &winClient());
00880 ClientList::iterator new_pos = m_clientlist.erase(it);
00881 new_pos++;
00882 m_clientlist.insert(new_pos, &winClient());
00883
00884 updateClientLeftWindow();
00885 }
00886
00888 void FluxboxWindow::updateClientLeftWindow() {
00889
00890
00891
00892
00893
00894 ClientList::iterator it = clientList().begin();
00895 ClientList::iterator it_end = clientList().end();
00896
00897 (*it)->setGroupLeftWindow(0);
00898 WinClient *last_client = *it;
00899 ++it;
00900 for (; it != it_end; ++it) {
00901 (*it)->setGroupLeftWindow(last_client->window());
00902 last_client = *it;
00903 }
00904 }
00905
00906 bool FluxboxWindow::setCurrentClient(WinClient &client, bool setinput) {
00907
00908 if (client.m_win != this)
00909 return false;
00910
00911 m_client = &client;
00912 m_client->raise();
00913 if (setinput && setInputFocus()) {
00914 frame().setLabelButtonFocus(*m_labelbuttons[m_client]);
00915 return true;
00916 }
00917
00918 return false;
00919 }
00920
00921 bool FluxboxWindow::isGroupable() const {
00922 if (isResizable() && isMaximizable() && !winClient().isTransient())
00923 return true;
00924 return false;
00925 }
00926
00927 void FluxboxWindow::associateClientWindow(bool use_attrs, int x, int y, unsigned int width, unsigned int height) {
00928 m_client->setBorderWidth(0);
00929 updateTitleFromClient(*m_client);
00930 updateIconNameFromClient(*m_client);
00931
00932 if (use_attrs)
00933 frame().moveResizeForClient(x, y,
00934 width, height);
00935 else
00936 frame().resizeForClient(m_client->width(), m_client->height());
00937
00938 frame().setClientWindow(*m_client);
00939 }
00940
00941
00942 void FluxboxWindow::grabButtons() {
00943
00944 XGrabButton(display, Button1, AnyModifier,
00945 frame().window().window(), True, ButtonPressMask,
00946 GrabModeSync, GrabModeSync, None, None);
00947 XUngrabButton(display, Button1, Mod1Mask|Mod2Mask|Mod3Mask, frame().window().window());
00948
00949 if (Fluxbox::instance()->useMod1()) {
00950 XGrabButton(display, Button1, Mod1Mask, frame().window().window(), True,
00951 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
00952 GrabModeAsync, None, frame().theme().moveCursor());
00953
00954
00955 grabButton(display, Button1, frame().window().window(), frame().theme().moveCursor());
00956
00957 XGrabButton(display, Button2, Mod1Mask, frame().window().window(), True,
00958 ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None);
00959
00960 XGrabButton(display, Button3, Mod1Mask, frame().window().window(), True,
00961 ButtonReleaseMask | ButtonMotionMask, GrabModeAsync,
00962 GrabModeAsync, None, None);
00963
00964
00965 grabButton(display, Button3, frame().window().window(), None);
00966 }
00967 }
00968
00969
00970 void FluxboxWindow::reconfigure() {
00971
00972 upsize();
00973
00974 applyDecorations();
00975
00976 setFocusFlag(focused);
00977
00978 moveResize(frame().x(), frame().y(), frame().width(), frame().height());
00979
00980 grabButtons();
00981
00982 frame().setDoubleClickTime(Fluxbox::instance()->getDoubleClickInterval());
00983 frame().setUpdateDelayTime(Fluxbox::instance()->getUpdateDelayTime());
00984
00985 frame().reconfigure();
00986
00987 m_windowmenu.reconfigure();
00988
00989 }
00990
00992 void FluxboxWindow::updateTitleFromClient(WinClient &client) {
00993 client.updateTitle();
00994
00995
00996 if (m_labelbuttons[&client]->text() != client.title()) {
00997 m_labelbuttons[&client]->setText(client.title());
00998 m_labelbuttons[&client]->clear();
00999 m_labelbuttons[&client]->updateTransparent();
01000 }
01001 }
01002
01004 void FluxboxWindow::updateIconNameFromClient(WinClient &client) {
01005 client.updateIconTitle();
01006 }
01007
01008 void FluxboxWindow::updateMWMHintsFromClient(WinClient &client) {
01009 const WinClient::MwmHints *hint = client.getMwmHint();
01010
01011 if (!hint) return;
01012
01013 if (hint->flags & MwmHintsDecorations) {
01014 if (hint->decorations & MwmDecorAll) {
01015 decorations.titlebar = decorations.handle = decorations.border =
01016 decorations.iconify = decorations.maximize =
01017 decorations.close = decorations.menu = true;
01018 } else {
01019 decorations.titlebar = decorations.handle = decorations.border =
01020 decorations.iconify = decorations.maximize =
01021 decorations.close = decorations.tab = false;
01022 decorations.menu = true;
01023 if (hint->decorations & MwmDecorBorder)
01024 decorations.border = true;
01025 if (hint->decorations & MwmDecorHandle)
01026 decorations.handle = true;
01027 if (hint->decorations & MwmDecorTitle) {
01028
01029 decorations.titlebar = decorations.tab = true;
01030 }
01031
01032 if (hint->decorations & MwmDecorMenu)
01033 decorations.menu = true;
01034 if (hint->decorations & MwmDecorIconify)
01035 decorations.iconify = true;
01036 if (hint->decorations & MwmDecorMaximize)
01037 decorations.maximize = true;
01038 }
01039 }
01040
01041 if (hint->flags & MwmHintsFunctions) {
01042 if (hint->functions & MwmFuncAll) {
01043 functions.resize = functions.move = functions.iconify =
01044 functions.maximize = functions.close = true;
01045 } else {
01046 functions.resize = functions.move = functions.iconify =
01047 functions.maximize = functions.close = false;
01048
01049 if (hint->functions & MwmFuncResize)
01050 functions.resize = true;
01051 if (hint->functions & MwmFuncMove)
01052 functions.move = true;
01053 if (hint->functions & MwmFuncIconify)
01054 functions.iconify = true;
01055 if (hint->functions & MwmFuncMaximize)
01056 functions.maximize = true;
01057 if (hint->functions & MwmFuncClose)
01058 functions.close = true;
01059 }
01060 }
01061 }
01062
01063 void FluxboxWindow::updateFunctions() {
01064 if (!m_client)
01065 return;
01066 bool changed = false;
01067 if (m_client->isClosable() != functions.close) {
01068 functions.close = m_client->isClosable();
01069 changed = true;
01070 }
01071
01072 if (changed)
01073 setupWindow();
01074 }
01075
01076 void FluxboxWindow::updateBlackboxHintsFromClient(const WinClient &client) {
01077 const FluxboxWindow::BlackboxHints *hint = client.getBlackboxHint();
01078 if (!hint) return;
01079
01080 if (hint->flags & ATTRIB_SHADED)
01081 shaded = (hint->attrib & ATTRIB_SHADED);
01082
01083 if ((hint->flags & ATTRIB_MAXHORIZ) &&
01084 (hint->flags & ATTRIB_MAXVERT))
01085 maximized = ((hint->attrib &
01086 (ATTRIB_MAXHORIZ |
01087 ATTRIB_MAXVERT)) ? MAX_FULL : MAX_NONE);
01088 else if (hint->flags & ATTRIB_MAXVERT)
01089 maximized = ((hint->attrib &
01090 ATTRIB_MAXVERT) ? MAX_VERT : MAX_NONE);
01091 else if (hint->flags & ATTRIB_MAXHORIZ)
01092 maximized = ((hint->attrib &
01093 ATTRIB_MAXHORIZ) ? MAX_HORZ : MAX_NONE);
01094
01095 if (hint->flags & ATTRIB_OMNIPRESENT)
01096 stuck = (hint->attrib &
01097 ATTRIB_OMNIPRESENT);
01098
01099 if (hint->flags & ATTRIB_WORKSPACE)
01100 m_workspace_number = hint->workspace;
01101
01102 if (hint->flags & ATTRIB_STACK)
01103 m_workspace_number = hint->stack;
01104
01105 if (hint->flags & ATTRIB_DECORATION) {
01106 m_old_decoration = static_cast<Decoration>(hint->decoration);
01107 setDecoration(m_old_decoration);
01108 }
01109 }
01110
01111 void FluxboxWindow::move(int x, int y, int gravity) {
01112 moveResize(x, y, frame().width(), frame().height(), gravity);
01113 }
01114
01115 void FluxboxWindow::resize(unsigned int width, unsigned int height) {
01116 moveResize(frame().x(), frame().y(), width, height);
01117 }
01118
01119 void FluxboxWindow::moveResize(int new_x, int new_y,
01120 unsigned int new_width, unsigned int new_height, int gravity) {
01121
01122 if (gravity != ForgetGravity) {
01123 frame().gravityTranslate(new_x, new_y, gravity, false);
01124 }
01125
01126 bool send_event = (frame().x() != new_x || frame().y() != new_y);
01127
01128 if (new_width != frame().width() || new_height != frame().height()) {
01129 if ((((signed) frame().width()) + new_x) < 0)
01130 new_x = 0;
01131 if ((((signed) frame().height()) + new_y) < 0)
01132 new_y = 0;
01133
01134 downsize();
01135 if (!isResizable()) {
01136 new_width = width();
01137 new_height = height();
01138 }
01139
01140 frame().moveResize(new_x, new_y, new_width, new_height);
01141 setFocusFlag(focused);
01142
01143
01144 shaded = false;
01145 send_event = true;
01146 } else if (send_event)
01147 frame().move(new_x, new_y);
01148
01149 if (send_event && ! moving) {
01150 sendConfigureNotify();
01151 }
01152
01153 shape();
01154
01155 if (!moving) {
01156 m_last_resize_x = new_x;
01157 m_last_resize_y = new_y;
01158 }
01159 }
01160
01161
01162
01163
01164
01165
01166 bool FluxboxWindow::setInputFocus() {
01167
01168 if (((signed) (frame().x() + frame().width())) < 0) {
01169 if (((signed) (frame().y() + frame().height())) < 0) {
01170 moveResize(frame().window().borderWidth(), frame().window().borderWidth(),
01171 frame().width(), frame().height());
01172 } else if (frame().y() > (signed) screen().height()) {
01173 moveResize(frame().window().borderWidth(), screen().height() - frame().height(),
01174 frame().width(), frame().height());
01175 } else {
01176 moveResize(frame().window().borderWidth(), frame().y() + frame().window().borderWidth(),
01177 frame().width(), frame().height());
01178 }
01179 } else if (frame().x() > (signed) screen().width()) {
01180 if (((signed) (frame().y() + frame().height())) < 0) {
01181 moveResize(screen().width() - frame().width(), frame().window().borderWidth(),
01182 frame().width(), frame().height());
01183 } else if (frame().y() > (signed) screen().height()) {
01184 moveResize(screen().width() - frame().width(),
01185 screen().height() - frame().height(),
01186 frame().width(), frame().height());
01187 } else {
01188 moveResize(screen().width() - frame().width(),
01189 frame().y() + frame().window().borderWidth(),
01190 frame().width(), frame().height());
01191 }
01192 }
01193
01194 if (! m_client->validateClient())
01195 return false;
01196
01197 if (!m_client->transients.empty() && m_client->isModal()) {
01198 WinClient::TransientList::iterator it = m_client->transients.begin();
01199 WinClient::TransientList::iterator it_end = m_client->transients.end();
01200 for (; it != it_end; ++it) {
01201 if ((*it)->isModal())
01202 return (*it)->fbwindow()->setCurrentClient(**it, true);
01203 }
01204 }
01205
01206 bool ret = false;
01207
01208 if (m_client->getFocusMode() == WinClient::F_LOCALLYACTIVE ||
01209 m_client->getFocusMode() == WinClient::F_PASSIVE) {
01210
01211 m_client->setInputFocus(RevertToPointerRoot, CurrentTime);
01212
01213 FbTk::App *app = FbTk::App::instance();
01214
01215 XFlush(app->display());
01216
01217 m_client->sendFocus();
01218
01219 app->sync(false);
01220 app->sync(false);
01221
01222 ret = true;
01223 } else {
01224 ret = m_client->sendFocus();
01225 }
01226
01227
01228 return ret;
01229 }
01230
01231 void FluxboxWindow::hide() {
01232 #ifdef DEBUG
01233 cerr<<__FILE__<<"("<<__FUNCTION__<<")["<<this<<"]"<<endl;
01234 #endif // DEBUG
01235 m_windowmenu.hide();
01236 frame().hide();
01237 }
01238
01239 void FluxboxWindow::show() {
01240 frame().show();
01241 }
01242
01246 void FluxboxWindow::iconify() {
01247 if (isIconic())
01248 return;
01249
01250 menu().hide();
01251 iconic = true;
01252
01253 setState(IconicState);
01254
01255 frame().hide();
01256
01257 ClientList::iterator client_it = m_clientlist.begin();
01258 const ClientList::iterator client_it_end = m_clientlist.end();
01259 for (; client_it != client_it_end; ++client_it) {
01260 WinClient &client = *(*client_it);
01261 client.setEventMask(NoEventMask);
01262 client.hide();
01263 client.setEventMask(PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
01264 if (client.transientFor() &&
01265 client.transientFor()->fbwindow()) {
01266 if (!client.transientFor()->fbwindow()->isIconic()) {
01267 client.transientFor()->fbwindow()->iconify();
01268 }
01269 }
01270
01271 if (!client.transientList().empty()) {
01272 WinClient::TransientList::iterator it = client.transientList().begin();
01273 WinClient::TransientList::iterator it_end = client.transientList().end();
01274 for (; it != it_end; it++)
01275 if ((*it)->fbwindow())
01276 (*it)->fbwindow()->iconify();
01277 }
01278 }
01279
01280 WinClient *focused_client = Fluxbox::instance()->getFocusedWindow();
01281 if (focused_client && focused_client->fbwindow() == this)
01282 Fluxbox::instance()->revertFocus(screen());
01283
01284 }
01285
01286 void FluxboxWindow::deiconify(bool reassoc, bool do_raise) {
01287 if (numClients() == 0)
01288 return;
01289
01290 if (oplock) return;
01291 oplock = true;
01292
01293 if (iconic || reassoc) {
01294 screen().reassociateWindow(this, screen().currentWorkspace()->workspaceID(), false);
01295 } else if (moving || m_workspace_number != screen().currentWorkspace()->workspaceID()) {
01296 oplock = false;
01297 return;
01298 }
01299
01300 bool was_iconic = iconic;
01301
01302 iconic = false;
01303 setState(NormalState);
01304
01305 ClientList::iterator client_it = clientList().begin();
01306 ClientList::iterator client_it_end = clientList().end();
01307 for (; client_it != client_it_end; ++client_it) {
01308 (*client_it)->setEventMask(NoEventMask);
01309 (*client_it)->show();
01310 (*client_it)->setEventMask(PropertyChangeMask | StructureNotifyMask | FocusChangeMask);
01311 }
01312
01313 show();
01314
01315 if (was_iconic && screen().doFocusNew())
01316 setInputFocus();
01317
01318 if (reassoc && !m_client->transients.empty()) {
01319
01320 client_it = clientList().begin();
01321 for (; client_it != client_it_end; ++client_it) {
01322
01323 WinClient::TransientList::iterator trans_it =
01324 (*client_it)->transientList().begin();
01325 WinClient::TransientList::iterator trans_it_end =
01326 (*client_it)->transientList().end();
01327 for (; trans_it != trans_it_end; ++trans_it) {
01328 if ((*trans_it)->fbwindow())
01329 (*trans_it)->fbwindow()->deiconify(true, false);
01330 }
01331 }
01332 }
01333
01334 oplock = false;
01335
01336 if (do_raise)
01337 raise();
01338 }
01339
01343 void FluxboxWindow::withdraw() {
01344 iconic = false;
01345
01346 if (isResizing())
01347 stopResizing();
01348
01349 frame().hide();
01350
01351 m_windowmenu.hide();
01352 }
01353
01357 void FluxboxWindow::maximize(int type) {
01358 if (isIconic())
01359 deiconify();
01360
01361 int head = screen().getHead(frame().window());
01362 int new_x = frame().x(),
01363 new_y = frame().y(),
01364 new_w = frame().width(),
01365 new_h = frame().height();
01366
01367 int orig_max = maximized;
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394 if (!(type == MAX_HORZ && orig_max != MAX_FULL ||
01395 type == MAX_VERT && orig_max == MAX_FULL ||
01396 type == MAX_NONE && !(orig_max & MAX_VERT) ||
01397 type == MAX_FULL && orig_max == MAX_VERT)) {
01398
01399 if (orig_max & MAX_VERT) {
01400 new_y = m_old_pos_y;
01401 new_h = m_old_height;
01402 } else {
01403 m_old_pos_y = new_y;
01404 m_old_height = new_h;
01405 new_y = screen().maxTop(head);
01406 new_h = screen().maxBottom(head) - new_y - 2*frame().window().borderWidth();
01407 }
01408 maximized ^= MAX_VERT;
01409 }
01410
01411
01412 if (!(type == MAX_VERT && orig_max != MAX_FULL ||
01413 type == MAX_HORZ && orig_max == MAX_FULL ||
01414 type == MAX_NONE && !(orig_max & MAX_HORZ) ||
01415 type == MAX_FULL && orig_max == MAX_HORZ)) {
01416
01417 if (orig_max & MAX_HORZ) {
01418 new_x = m_old_pos_x;
01419 new_w = m_old_width;
01420 } else {
01421
01422 m_old_pos_x = new_x;
01423 m_old_width = new_w;
01424 new_x = screen().maxLeft(head);
01425 new_w = screen().maxRight(head) - new_x - 2*frame().window().borderWidth();
01426 }
01427 maximized ^= MAX_HORZ;
01428 }
01429
01430 moveResize(new_x, new_y, new_w, new_h);
01431
01432 }
01436 void FluxboxWindow::maximizeHorizontal() {
01437 maximize(MAX_HORZ);
01438 }
01439
01443 void FluxboxWindow::maximizeVertical() {
01444 maximize(MAX_VERT);
01445 }
01446
01450 void FluxboxWindow::maximizeFull() {
01451 maximize(MAX_FULL);
01452 }
01453
01454
01455 void FluxboxWindow::setWorkspace(int n) {
01456 unsigned int old_wkspc = m_workspace_number;
01457
01458 m_workspace_number = n;
01459
01460 m_blackbox_attrib.flags |= ATTRIB_WORKSPACE;
01461 m_blackbox_attrib.workspace = m_workspace_number;
01462
01463
01464 if (!stuck && old_wkspc != m_workspace_number) {
01465 #ifdef DEBUG
01466 cerr<<this<<" notify workspace signal"<<endl;
01467 #endif // DEBUG
01468 m_workspacesig.notify();
01469 }
01470 }
01471
01472 void FluxboxWindow::setLayerNum(int layernum) {
01473 m_layernum = layernum;
01474
01475 m_blackbox_attrib.flags |= ATTRIB_STACK;
01476 m_blackbox_attrib.stack = layernum;
01477 saveBlackboxAttribs();
01478
01479 #ifdef DEBUG
01480 cerr<<this<<" notify layer signal"<<endl;
01481 #endif // DEBUG
01482
01483 m_layersig.notify();
01484 }
01485
01486 void FluxboxWindow::shade() {
01487
01488 if (!decorations.titlebar)
01489 return;
01490
01491 frame().shade();
01492
01493 if (shaded) {
01494 shaded = false;
01495 m_blackbox_attrib.flags ^= ATTRIB_SHADED;
01496 m_blackbox_attrib.attrib ^= ATTRIB_SHADED;
01497
01498 setState(NormalState);
01499 } else {
01500 shaded = true;
01501 m_blackbox_attrib.flags |= ATTRIB_SHADED;
01502 m_blackbox_attrib.attrib |= ATTRIB_SHADED;
01503
01504 setState(IconicState);
01505 }
01506
01507 }
01508
01509
01510 void FluxboxWindow::stick() {
01511
01512 if (stuck) {
01513 m_blackbox_attrib.flags ^= ATTRIB_OMNIPRESENT;
01514 m_blackbox_attrib.attrib ^= ATTRIB_OMNIPRESENT;
01515
01516 stuck = false;
01517
01518 } else {
01519 stuck = true;
01520
01521 m_blackbox_attrib.flags |= ATTRIB_OMNIPRESENT;
01522 m_blackbox_attrib.attrib |= ATTRIB_OMNIPRESENT;
01523
01524 }
01525
01526 setState(m_current_state);
01527
01528 m_workspacesig.notify();
01529
01530 }
01531
01532
01533 void FluxboxWindow::raise() {
01534 if (isIconic())
01535 deiconify();
01536
01537
01538 WinClient *client = getRootTransientFor(m_client);
01539
01540
01541 if (client == 0)
01542 client = m_client;
01543
01544
01545 if (client->fbwindow())
01546 raiseFluxboxWindow(*client->fbwindow());
01547 }
01548
01549 void FluxboxWindow::lower() {
01550 if (isIconic())
01551 deiconify();
01552
01553
01554 WinClient *client = getRootTransientFor(m_client);
01555
01556
01557 if (client == 0)
01558 client = m_client;
01559
01560 if (client->fbwindow())
01561 lowerFluxboxWindow(*client->fbwindow());
01562 }
01563
01564 void FluxboxWindow::tempRaise() {
01565 if (isIconic())
01566 deiconify();
01567
01568
01569 WinClient *client = getRootTransientFor(m_client);
01570
01571
01572 if (client == 0)
01573 client = m_client;
01574
01575 if (client->fbwindow())
01576 tempRaiseFluxboxWindow(*client->fbwindow());
01577 }
01578
01579
01580 void FluxboxWindow::raiseLayer() {
01581
01582 if (layerNum() == (Fluxbox::instance()->getMenuLayer()+1))
01583 return;
01584
01585
01586 WinClient *client = getRootTransientFor(m_client);
01587
01588
01589 if (client == 0)
01590 client = m_client;
01591
01592 FluxboxWindow *win = client->fbwindow();
01593 if (!win) return;
01594
01595 if (!win->isIconic())
01596 screen().updateNetizenWindowRaise(client->window());
01597
01598 win->layerItem().raiseLayer();
01599
01600
01601 int layer_num = win->layerItem().getLayerNum();
01602 win->setLayerNum(layer_num);
01603
01604 WinClient::TransientList::const_iterator it = client->transientList().begin();
01605 WinClient::TransientList::const_iterator it_end = client->transientList().end();
01606 for (; it != it_end; ++it) {
01607 win = (*it)->fbwindow();
01608 if (win && !win->isIconic()) {
01609 screen().updateNetizenWindowRaise((*it)->window());
01610 win->layerItem().moveToLayer(layer_num);
01611 win->setLayerNum(layer_num);
01612 }
01613 }
01614 }
01615
01616 void FluxboxWindow::lowerLayer() {
01617
01618 WinClient *client = getRootTransientFor(m_client);
01619
01620
01621 if (client == 0)
01622 client = m_client;
01623
01624 FluxboxWindow *win = client->fbwindow();
01625 if (!win) return;
01626
01627 if (!win->isIconic()) {
01628 screen().updateNetizenWindowLower(client->window());
01629 }
01630 win->layerItem().lowerLayer();
01631
01632 int layer_num = win->layerItem().getLayerNum();
01633 win->setLayerNum(layer_num);
01634
01635 WinClient::TransientList::const_iterator it = client->transientList().begin();
01636 WinClient::TransientList::const_iterator it_end = client->transientList().end();
01637 for (; it != it_end; ++it) {
01638 win = (*it)->fbwindow();
01639 if (win && !win->isIconic()) {
01640 screen().updateNetizenWindowLower((*it)->window());
01641 win->layerItem().moveToLayer(layer_num);
01642 win->setLayerNum(layer_num);
01643 }
01644 }
01645 }
01646
01647
01648 void FluxboxWindow::moveToLayer(int layernum) {
01649 Fluxbox * fluxbox = Fluxbox::instance();
01650
01651
01652 if (layernum <= fluxbox->getMenuLayer()) {
01653 layernum = fluxbox->getMenuLayer() + 1;
01654 }
01655
01656
01657 WinClient *client = getRootTransientFor(m_client);
01658
01659
01660 if (client == 0)
01661 client = m_client;
01662
01663 FluxboxWindow *win = client->fbwindow();
01664 if (!win) return;
01665
01666 if (!win->isIconic()) {
01667 screen().updateNetizenWindowRaise(client->window());
01668 }
01669 win->layerItem().moveToLayer(layernum);
01670
01671 layernum = win->layerItem().getLayerNum();
01672 win->setLayerNum(layernum);
01673
01674 WinClient::TransientList::const_iterator it = client->transientList().begin();
01675 WinClient::TransientList::const_iterator it_end = client->transientList().end();
01676 for (; it != it_end; ++it) {
01677 win = (*it)->fbwindow();
01678 if (win && !win->isIconic()) {
01679 screen().updateNetizenWindowRaise((*it)->window());
01680 win->layerItem().moveToLayer(layernum);
01681 win->setLayerNum(layernum);
01682 }
01683 }
01684 }
01685
01686
01687
01688
01689 void FluxboxWindow::setFocusFlag(bool focus) {
01690 bool was_focused = isFocused();
01691 focused = focus;
01692
01693
01694 if (focused) {
01695 gettimeofday(&m_last_focus_time, 0);
01696 screen().setFocusedWindow(*m_client);
01697 }
01698
01699 installColormap(focus);
01700
01701 if (focus != frame().focused())
01702 frame().setFocus(focus);
01703
01704 if ((screen().isSloppyFocus() || screen().isSemiSloppyFocus())
01705 && screen().doAutoRaise()) {
01706 if (focused)
01707 m_timer.start();
01708 else
01709 m_timer.stop();
01710 }
01711
01712
01713 if (was_focused != focus)
01714 m_focussig.notify();
01715 }
01716
01717
01718 void FluxboxWindow::installColormap(bool install) {
01719 if (m_client == 0) return;
01720
01721 Fluxbox *fluxbox = Fluxbox::instance();
01722 fluxbox->grab();
01723 if (! m_client->validateClient())
01724 return;
01725
01726 int i = 0, ncmap = 0;
01727 Colormap *cmaps = XListInstalledColormaps(display, m_client->window(), &ncmap);
01728 XWindowAttributes wattrib;
01729 if (cmaps) {
01730 if (m_client->getAttrib(wattrib)) {
01731 if (install) {
01732
01733 for (i = 0; i < ncmap; i++) {
01734 if (*(cmaps + i) == wattrib.colormap) {
01735
01736 install = false;
01737 break;
01738 }
01739 }
01740
01741 if (install)
01742 XInstallColormap(display, wattrib.colormap);
01743 } else {
01744 for (i = 0; i &l