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
00028 #include "Screen.hh"
00029
00030 #include "I18n.hh"
00031 #include "fluxbox.hh"
00032 #include "Window.hh"
00033 #include "Workspace.hh"
00034 #include "Netizen.hh"
00035 #include "FbWinFrameTheme.hh"
00036 #include "MenuTheme.hh"
00037 #include "RootTheme.hh"
00038 #include "WinButtonTheme.hh"
00039 #include "FbCommands.hh"
00040 #include "BoolMenuItem.hh"
00041 #include "IntResMenuItem.hh"
00042 #include "FbMenu.hh"
00043 #include "LayerMenu.hh"
00044 #include "WinClient.hh"
00045 #include "FbWinFrame.hh"
00046 #include "FbWindow.hh"
00047 #include "Strut.hh"
00048 #include "SlitTheme.hh"
00049 #include "CommandParser.hh"
00050 #include "IconMenuItem.hh"
00051
00052 #include "FbTk/Subject.hh"
00053 #include "FbTk/Directory.hh"
00054 #include "FbTk/SimpleCommand.hh"
00055 #include "FbTk/MultLayers.hh"
00056 #include "FbTk/XLayerItem.hh"
00057 #include "FbTk/MacroCommand.hh"
00058 #include "FbTk/StringUtil.hh"
00059 #include "FbTk/ImageControl.hh"
00060
00061
00062 #ifndef _GNU_SOURCE
00063 #define _GNU_SOURCE
00064 #endif // _GNU_SOURCE
00065
00066 #ifdef HAVE_CONFIG_H
00067 #include "config.h"
00068 #endif // HAVE_CONFIG_H
00069
00070 #ifdef SLIT
00071 #include "Slit.hh"
00072 #else
00073
00074 class Slit {};
00075 #endif // SLIT
00076
00077 #ifdef STDC_HEADERS
00078 #include <sys/types.h>
00079 #endif // STDC_HEADERS
00080
00081 #ifdef HAVE_CTYPE_H
00082 #include <ctype.h>
00083 #endif // HAVE_CTYPE_H
00084
00085 #ifdef HAVE_UNISTD_H
00086 #include <sys/types.h>
00087 #include <unistd.h>
00088 #endif // HAVE_UNISTD_H
00089
00090 #ifdef HAVE_STDARG_H
00091 #include <stdarg.h>
00092 #endif // HAVE_STDARG_H
00093
00094 #ifdef TIME_WITH_SYS_TIME
00095 #include <sys/time.h>
00096 #include <time.h>
00097 #else // !TIME_WITH_SYS_TIME
00098 #ifdef HAVE_SYS_TIME_H
00099 #include <sys/time.h>
00100 #else // !HAVE_SYS_TIME_H
00101 #include <time.h>
00102 #endif // HAVE_SYS_TIME_H
00103 #endif // TIME_WITH_SYS_TIME
00104
00105 #include <X11/Xatom.h>
00106 #include <X11/keysym.h>
00107 #include <X11/cursorfont.h>
00108
00109 #ifdef XINERAMA
00110 extern "C" {
00111 #include <X11/extensions/Xinerama.h>
00112 }
00113 #endif // XINERAMA
00114
00115 #include <iostream>
00116 #include <memory>
00117 #include <algorithm>
00118 #include <functional>
00119
00120 using namespace std;
00121
00122 static bool running = true;
00123 namespace {
00124
00125 int anotherWMRunning(Display *display, XErrorEvent *) {
00126 cerr<<I18n::instance()->
00127 getMessage(FBNLS::ScreenSet, FBNLS::ScreenAnotherWMRunning,
00128 "BScreen::BScreen: an error occured while querying the X server.\n"
00129 " another window manager already running on display ")<<DisplayString(display)<<endl;
00130
00131 running = false;
00132
00133 return -1;
00134 }
00135
00136 class FocusModelMenuItem : public FbTk::MenuItem {
00137 public:
00138 FocusModelMenuItem(const char *label, BScreen &screen,
00139 BScreen::FocusModel model,
00140 FbTk::RefCount<FbTk::Command> &cmd):
00141 FbTk::MenuItem(label, cmd), m_screen(screen), m_focusmodel(model) {
00142 }
00143 bool isEnabled() const { return m_screen.getFocusModel() != m_focusmodel; }
00144 void click(int button, int time) {
00145 m_screen.saveFocusModel(m_focusmodel);
00146 FbTk::MenuItem::click(button, time);
00147 }
00148
00149 private:
00150 BScreen &m_screen;
00151 BScreen::FocusModel m_focusmodel;
00152 };
00153
00154
00155 }
00156
00157 template <>
00158 void FbTk::Resource<BScreen::PlacementPolicy>::setDefaultValue() {
00159 *(*this) = BScreen::ROWSMARTPLACEMENT;
00160 }
00161
00162 template <>
00163 void FbTk::Resource<BScreen::PlacementPolicy>::setFromString(const char *str) {
00164 if (strcasecmp("RowSmartPlacement", str) == 0)
00165 *(*this) = BScreen::ROWSMARTPLACEMENT;
00166 else if (strcasecmp("", str) == 0)
00167 *(*this) = BScreen::COLSMARTPLACEMENT;
00168 else if (strcasecmp("UnderMousePlacement", str) == 0)
00169 *(*this) = BScreen::UNDERMOUSEPLACEMENT;
00170 else if (strcasecmp("CascadePlacement", str) == 0)
00171 *(*this) = BScreen::CASCADEPLACEMENT;
00172 else
00173 setDefaultValue();
00174
00175 }
00176
00177 string FbTk::Resource<BScreen::PlacementPolicy>::getString() {
00178 switch (*(*this)) {
00179 case BScreen::ROWSMARTPLACEMENT:
00180 return "RowSmartPlacement";
00181 case BScreen::COLSMARTPLACEMENT:
00182 return "ColSmartPlacement";
00183 case BScreen::UNDERMOUSEPLACEMENT:
00184 return "UnderMousePlacement";
00185 case BScreen::CASCADEPLACEMENT:
00186 return "CascadePlacement";
00187 }
00188
00189 return "RowSmartPlacement";
00190 }
00191
00192 template <>
00193 void FbTk::Resource<BScreen::RowDirection>::setDefaultValue() {
00194 *(*this) = BScreen::LEFTRIGHT;
00195 }
00196
00197 template <>
00198 void FbTk::Resource<BScreen::RowDirection>::setFromString(const char *str) {
00199 if (strcasecmp("LeftToRight", str) == 0)
00200 *(*this) = BScreen::LEFTRIGHT;
00201 else if (strcasecmp("RightToLeft", str) == 0)
00202 *(*this) = BScreen::RIGHTLEFT;
00203 else
00204 setDefaultValue();
00205
00206 }
00207
00208 string FbTk::Resource<BScreen::RowDirection>::getString() {
00209 switch (*(*this)) {
00210 case BScreen::LEFTRIGHT:
00211 return "LeftToRight";
00212 case BScreen::RIGHTLEFT:
00213 return "RightToLeft";
00214 }
00215
00216 return "LeftToRight";
00217 }
00218
00219
00220 template <>
00221 void FbTk::Resource<BScreen::ColumnDirection>::setDefaultValue() {
00222 *(*this) = BScreen::TOPBOTTOM;
00223 }
00224
00225 template <>
00226 void FbTk::Resource<BScreen::ColumnDirection>::setFromString(const char *str) {
00227 if (strcasecmp("TopToBottom", str) == 0)
00228 *(*this) = BScreen::TOPBOTTOM;
00229 else if (strcasecmp("BottomToTop", str) == 0)
00230 *(*this) = BScreen::BOTTOMTOP;
00231 else
00232 setDefaultValue();
00233
00234 }
00235
00236 string FbTk::Resource<BScreen::ColumnDirection>::getString() {
00237 switch (*(*this)) {
00238 case BScreen::TOPBOTTOM:
00239 return "TopToBottom";
00240 case BScreen::BOTTOMTOP:
00241 return "BottomToTop";
00242 }
00243
00244 return "TopToBottom";
00245 }
00246
00247 template <>
00248 void FbTk::Resource<FbTk::MenuTheme::MenuMode>::setDefaultValue() {
00249 *(*this) = FbTk::MenuTheme::DELAY_OPEN;
00250 }
00251
00252 template <>
00253 string FbTk::Resource<FbTk::MenuTheme::MenuMode>::getString() {
00254 switch (*(*this)) {
00255 case FbTk::MenuTheme::DELAY_OPEN:
00256 return string("Delay");
00257 case FbTk::MenuTheme::CLICK_OPEN:
00258 return string("Click");
00259 }
00260 return string("Delay");
00261 }
00262
00263 template <>
00264 void FbTk::Resource<FbTk::MenuTheme::MenuMode>::setFromString(const char *str) {
00265 if (strcasecmp(str, "Delay") == 0)
00266 *(*this) = FbTk::MenuTheme::DELAY_OPEN;
00267 else if (strcasecmp(str, "Click") == 0)
00268 *(*this) = FbTk::MenuTheme::CLICK_OPEN;
00269 else
00270 setDefaultValue();
00271 }
00272
00273 template<>
00274 std::string FbTk::Resource<BScreen::FocusModel>::
00275 getString() {
00276 switch (m_value) {
00277 case BScreen::SLOPPYFOCUS:
00278 return string("SloppyFocus");
00279 case BScreen::SEMISLOPPYFOCUS:
00280 return string("SemiSloppyFocus");
00281 case BScreen::CLICKTOFOCUS:
00282 return string("ClickToFocus");
00283 }
00284
00285 return string("ClickToFocus");
00286 }
00287
00288 template<>
00289 void FbTk::Resource<BScreen::FocusModel>::
00290 setFromString(char const *strval) {
00291
00292
00293
00294 if (strcasecmp(strval, "SloppyFocus") == 0
00295 || strcasecmp(strval, "AutoRaiseSloppyFocus") == 0)
00296 m_value = BScreen::SLOPPYFOCUS;
00297 else if (strcasecmp(strval, "SemiSloppyFocus") == 0
00298 || strcasecmp(strval, "AutoRaiseSemiSloppyFocus") == 0)
00299 m_value = BScreen::SEMISLOPPYFOCUS;
00300 else if (strcasecmp(strval, "ClickToFocus") == 0)
00301 m_value = BScreen::CLICKTOFOCUS;
00302 else
00303 setDefaultValue();
00304 }
00305
00306 namespace {
00307
00308 class StyleMenuItem: public FbTk::MenuItem {
00309 public:
00310 StyleMenuItem(const std::string &label, const std::string &filename):
00311 FbTk::MenuItem(label.c_str()),
00312 m_filename(FbTk::StringUtil::
00313 expandFilename(filename)) {
00314
00315
00316 FbTk::RefCount<FbTk::Command>
00317 setstyle_cmd(new FbCommands::
00318 SetStyleCmd(m_filename));
00319 setCommand(setstyle_cmd);
00320 setToggleItem(true);
00321 }
00322 bool isSelected() const {
00323 return Fluxbox::instance()->getStyleFilename() == m_filename;
00324 }
00325 private:
00326 const std::string m_filename;
00327 };
00328
00329 void setupWorkspacemenu(BScreen &scr, FbTk::Menu &menu) {
00330 menu.removeAll();
00331 using namespace FbTk;
00332 menu.setLabel("Workspace");
00333 RefCount<Command> new_workspace(new FbTk::SimpleCommand<BScreen, int>(scr, &BScreen::addWorkspace));
00334 RefCount<Command> remove_last(new FbTk::SimpleCommand<BScreen, int>(scr, &BScreen::removeLastWorkspace));
00336 menu.insert("New Workspace", new_workspace);
00337 menu.insert("Remove Last", remove_last);
00338
00339 for (size_t workspace = 0; workspace < scr.getCount(); ++workspace) {
00340 Workspace *wkspc = scr.getWorkspace(workspace);
00341 menu.insert(wkspc->name().c_str(), &wkspc->menu());
00342 }
00343
00344
00345 menu.update();
00346 }
00347
00348 };
00349
00350
00351 BScreen::ScreenResource::ScreenResource(FbTk::ResourceManager &rm,
00352 const std::string &scrname,
00353 const std::string &altscrname):
00354 image_dither(rm, false, scrname+".imageDither", altscrname+".ImageDither"),
00355 opaque_move(rm, false, scrname + ".opaqueMove", altscrname+".OpaqueMove"),
00356 full_max(rm, true, scrname+".fullMaximization", altscrname+".FullMaximization"),
00357 sloppy_window_grouping(rm, true,
00358 scrname+".sloppywindowgrouping", altscrname+".SloppyWindowGrouping"),
00359 workspace_warping(rm, true, scrname+".workspacewarping", altscrname+".WorkspaceWarping"),
00360 desktop_wheeling(rm, true, scrname+".desktopwheeling", altscrname+".DesktopWheeling"),
00361 show_window_pos(rm, true, scrname+".showwindowposition", altscrname+".ShowWindowPosition"),
00362 focus_last(rm, true, scrname+".focusLastWindow", altscrname+".FocusLastWindow"),
00363 focus_new(rm, true, scrname+".focusNewWindows", altscrname+".FocusNewWindows"),
00364 antialias(rm, false, scrname+".antialias", altscrname+".Antialias"),
00365 auto_raise(rm, false, scrname+".autoRaise", altscrname+".AutoRaise"),
00366 click_raises(rm, true, scrname+".clickRaises", altscrname+".ClickRaises"),
00367 rootcommand(rm, "", scrname+".rootCommand", altscrname+".RootCommand"),
00368 resizemode(rm, "", scrname+".resizeMode", altscrname+".ResizeMode"),
00369 focus_model(rm, CLICKTOFOCUS, scrname+".focusModel", altscrname+".FocusModel"),
00370 workspaces(rm, 1, scrname+".workspaces", altscrname+".Workspaces"),
00371 edge_snap_threshold(rm, 0, scrname+".edgeSnapThreshold", altscrname+".EdgeSnapThreshold"),
00372 menu_alpha(rm, 255, scrname+".menuAlpha", altscrname+".MenuAlpha"),
00373 menu_delay(rm, 0, scrname + ".menuDelay", altscrname+".MenuDelay"),
00374 menu_delay_close(rm, 0, scrname + ".menuDelayClose", altscrname+".MenuDelayClose"),
00375 menu_mode(rm, FbTk::MenuTheme::DELAY_OPEN, scrname+".menuMode", altscrname+".MenuMode"),
00376 placement_policy(rm, ROWSMARTPLACEMENT, scrname+".windowPlacement", altscrname+".WindowPlacement"),
00377 row_direction(rm, LEFTRIGHT, scrname+".rowPlacementDirection", altscrname+".RowPlacementDirection"),
00378 col_direction(rm, TOPBOTTOM, scrname+".colPlacementDirection", altscrname+".ColPlacementDirection") {
00379
00380 }
00381
00382 BScreen::BScreen(FbTk::ResourceManager &rm,
00383 const string &screenname, const string &altscreenname,
00384 int scrn, int num_layers) :
00385 m_clientlist_sig(*this),
00386 m_iconlist_sig(*this),
00387 m_workspacecount_sig(*this),
00388 m_workspacenames_sig(*this),
00389 m_currentworkspace_sig(*this),
00390 m_reconfigure_sig(*this),
00391 m_resize_sig(*this),
00392 m_layermanager(num_layers),
00393 cycling_focus(false),
00394 cycling_last(0),
00395 m_windowtheme(new FbWinFrameTheme(scrn)),
00396
00397
00398
00399 m_winbutton_theme(new WinButtonTheme(scrn, *m_windowtheme)),
00400 m_menutheme(new MenuTheme(scrn)),
00401 m_root_theme(new
00402 RootTheme(scrn,
00403 *resource.rootcommand)),
00404 m_root_window(scrn),
00405 resource(rm, screenname, altscreenname),
00406 m_name(screenname),
00407 m_altname(altscreenname),
00408 m_resource_manager(rm),
00409 m_available_workspace_area(new Strut(0, 0, 0, 0)),
00410 m_xinerama_headinfo(0),
00411 m_shutdown(false) {
00412
00413
00414 Display *disp = FbTk::App::instance()->display();
00415
00416 initXinerama();
00417
00418
00419 XErrorHandler old = XSetErrorHandler((XErrorHandler) anotherWMRunning);
00420
00421 rootWindow().setEventMask(ColormapChangeMask | EnterWindowMask | PropertyChangeMask |
00422 SubstructureRedirectMask | KeyPressMask | KeyReleaseMask |
00423 ButtonPressMask | ButtonReleaseMask| SubstructureNotifyMask);
00424
00425 FbTk::App::instance()->sync(false);
00426
00427 XSetErrorHandler((XErrorHandler) old);
00428
00429 managed = running;
00430 if (! managed)
00431 return;
00432
00433 I18n *i18n = I18n::instance();
00434
00435 fprintf(stderr, i18n->getMessage(FBNLS::ScreenSet, FBNLS::ScreenManagingScreen,
00436 "BScreen::BScreen: managing screen %d "
00437 "using visual 0x%lx, depth %d\n"),
00438 screenNumber(), XVisualIDFromVisual(rootWindow().visual()),
00439 rootWindow().depth());
00440
00441 cycling_window = focused_list.end();
00442
00443 rootWindow().setCursor(XCreateFontCursor(disp, XC_left_ptr));
00444
00445 Fluxbox *fluxbox = Fluxbox::instance();
00446
00447 fluxbox->load_rc(*this);
00448
00449
00450 m_image_control.reset(new FbTk::ImageControl(scrn, true, fluxbox->colorsPerChannel(),
00451 fluxbox->getCacheLife(), fluxbox->getCacheMax()));
00452 imageControl().installRootColormap();
00453 root_colormap_installed = true;
00454
00455
00456
00457 m_menutheme->setAlpha(*resource.menu_alpha);
00458 m_menutheme->setMenuMode(*resource.menu_mode);
00459
00460 if (*resource.menu_delay > 5000)
00461 *resource.menu_delay = 5000;
00462 if (*resource.menu_delay < 0)
00463 *resource.menu_delay = 0;
00464
00465 if (*resource.menu_delay_close > 5000)
00466 *resource.menu_delay_close = 5000;
00467 if (*resource.menu_delay_close < 0)
00468 *resource.menu_delay_close = 0;
00469
00470 m_menutheme->setDelayOpen(*resource.menu_delay);
00471 m_menutheme->setDelayClose(*resource.menu_delay_close);
00472
00473 imageControl().setDither(*resource.image_dither);
00474
00475
00476
00477
00478 winFrameTheme().font().setAntialias(*resource.antialias);
00479 menuTheme().titleFont().setAntialias(*resource.antialias);
00480 menuTheme().frameFont().setAntialias(*resource.antialias);
00481
00482
00483
00484
00485 int geom_h = 10;
00486 int geom_w = 100;
00487
00488 XSetWindowAttributes attrib;
00489 unsigned long mask = CWBorderPixel | CWColormap | CWSaveUnder;
00490 attrib.border_pixel = winFrameTheme().border().color().pixel();
00491 attrib.colormap = rootWindow().colormap();
00492 attrib.save_under = true;
00493
00494 winFrameTheme().reconfigSig().attach(this);
00495
00496 m_geom_window =
00497 XCreateWindow(disp, rootWindow().window(),
00498 0, 0, geom_w, geom_h, winFrameTheme().border().width(), rootWindow().depth(),
00499 InputOutput, rootWindow().visual(), mask, &attrib);
00500 geom_visible = false;
00501 geom_pixmap = 0;
00502
00503 renderGeomWindow();
00504
00505
00506
00507 workspacemenu.reset(createMenu(""));
00508 workspacemenu->setInternalMenu();
00510 m_iconmenu.reset(createMenu("Icons"));
00511 m_iconmenu->setInternalMenu();
00512
00513 if (*resource.workspaces != 0) {
00514 for (int i = 0; i < *resource.workspaces; ++i) {
00515 Workspace *wkspc = new Workspace(*this, m_layermanager,
00516 getNameOfWorkspace(m_workspaces_list.size()),
00517 m_workspaces_list.size());
00518 m_workspaces_list.push_back(wkspc);
00519 }
00520 } else {
00521 Workspace *wkspc = new Workspace(*this, m_layermanager,
00522 getNameOfWorkspace(m_workspaces_list.size()),
00523 m_workspaces_list.size());
00524 m_workspaces_list.push_back(wkspc);
00525 }
00526
00527 setupWorkspacemenu(*this, *workspacemenu);
00529 workspacemenu->insert("Icons", m_iconmenu.get());
00530 workspacemenu->update();
00531
00532 m_current_workspace = m_workspaces_list.front();
00533
00534 #ifdef SLIT
00535 m_slit.reset(new Slit(*this, *layerManager().getLayer(Fluxbox::instance()->getDesktopLayer()),
00536 Fluxbox::instance()->getSlitlistFilename().c_str()));
00537 #endif // SLIT
00538
00540
00541 fluxbox->load_rc(*this);
00542
00543
00544 m_configmenu.reset(createMenu("Configuration"));
00545 setupConfigmenu(*m_configmenu.get());
00546 m_configmenu->setInternalMenu();
00547
00548 workspacemenu->setItemSelected(2, true);
00549
00550 rereadMenu();
00551
00552 m_configmenu->update();
00553
00554
00555 changeWorkspaceID(0);
00556 updateNetizenWorkspaceCount();
00557
00558
00559
00560
00561
00563
00564
00565
00566 m_root_theme->lock(true);
00567 FbTk::ThemeManager::instance().load(Fluxbox::instance()->getStyleFilename());
00568 m_root_theme->lock(false);
00569
00570 int i;
00571 unsigned int nchild;
00572 Window r, p, *children;
00573 XQueryTree(disp, rootWindow().window(), &r, &p, &children, &nchild);
00574
00575
00576 for (i = 0; i < (int) nchild; i++) {
00577
00578 if (children[i] == None) continue;
00579
00580 XWMHints *wmhints = XGetWMHints(FbTk::App::instance()->display(),
00581 children[i]);
00582
00583 if (wmhints) {
00584 if ((wmhints->flags & IconWindowHint) &&
00585 (wmhints->icon_window != children[i]))
00586 for (int j = 0; j < (int) nchild; j++) {
00587 if (children[j] == wmhints->icon_window) {
00588 children[j] = None;
00589 break;
00590 }
00591 }
00592 XFree(wmhints);
00593 }
00594 }
00595
00596
00597 for (i = 0; i < (int) nchild; ++i) {
00598 if (children[i] == None || (! fluxbox->validateWindow(children[i])))
00599 continue;
00600
00601 XWindowAttributes attrib;
00602 if (XGetWindowAttributes(disp, children[i],
00603 &attrib)) {
00604 if (attrib.override_redirect)
00605 continue;
00606
00607 if (attrib.map_state != IsUnmapped) {
00608 FluxboxWindow *win = createWindow(children[i]);
00609
00610 if (win) {
00611 XMapRequestEvent mre;
00612 mre.window = children[i];
00613 win->mapRequestEvent(mre);
00614 }
00615 }
00616 }
00617 }
00618
00619 rm.unlock();
00620
00621 XFree(children);
00622
00623 XFlush(disp);
00624 }
00625
00626 BScreen::~BScreen() {
00627 if (! managed)
00628 return;
00629
00630 if (m_rootmenu.get() != 0)
00631 m_rootmenu->removeAll();
00632
00633 if (geom_pixmap != None)
00634 imageControl().removeImage(geom_pixmap);
00635
00636 removeWorkspaceNames();
00637
00638 Workspaces::iterator w_it = m_workspaces_list.begin();
00639 Workspaces::iterator w_it_end = m_workspaces_list.end();
00640 for(; w_it != w_it_end; ++w_it) {
00641 delete (*w_it);
00642 }
00643 m_workspaces_list.clear();
00644
00645 Icons::iterator i_it = m_icon_list.begin();
00646 Icons::iterator i_it_end = m_icon_list.end();
00647 for(; i_it != i_it_end; ++i_it) {
00648 delete (*i_it);
00649 }
00650 m_icon_list.clear();
00651
00652 Netizens::iterator n_it = m_netizen_list.begin();
00653 Netizens::iterator n_it_end = m_netizen_list.end();
00654 for(; n_it != n_it_end; ++n_it) {
00655 delete (*n_it);
00656 }
00657
00658 m_netizen_list.clear();
00659
00660 if (hasXinerama() && m_xinerama_headinfo) {
00661 delete [] m_xinerama_headinfo;
00662 }
00663 }
00664
00665 unsigned int BScreen::currentWorkspaceID() const {
00666 return m_current_workspace->workspaceID();
00667 }
00668
00669 Pixmap BScreen::rootPixmap() const {
00670
00671 Pixmap root_pm = 0;
00672 Display *disp = FbTk::App::instance()->display();
00673 Atom real_type;
00674 int real_format;
00675 unsigned long items_read, items_left;
00676 unsigned int *data;
00677 if (rootWindow().property(XInternAtom(disp, "_XROOTPMAP_ID", false),
00678 0L, 1L,
00679 false, XA_PIXMAP, &real_type,
00680 &real_format, &items_read, &items_left,
00681 (unsigned char **) &data) &&
00682 items_read) {
00683 root_pm = (Pixmap) (*data);
00684 XFree(data);
00685 }
00686
00687 return root_pm;
00688
00689 }
00690
00691 unsigned int BScreen::maxLeft(int head) const {
00692
00693 if (hasXinerama())
00694 return doFullMax() ? getHeadX(head) :
00695 getHeadX(head) + m_available_workspace_area->left();
00696 else
00697 return doFullMax() ? 0 : m_available_workspace_area->left();
00698 }
00699
00700 unsigned int BScreen::maxRight(int head) const {
00701
00702 if (hasXinerama())
00703 return doFullMax() ? getHeadX(head) + getHeadWidth(head) :
00704 getHeadX(head) + getHeadWidth(head) - m_available_workspace_area->right();
00705 else
00706 return doFullMax() ? width() : width() - m_available_workspace_area->right();
00707 }
00708
00709 unsigned int BScreen::maxTop(int head) const {
00710
00711
00712
00713 if (hasXinerama())
00714 return doFullMax() ? getHeadY(head) : getHeadY(head) + m_available_workspace_area->top();
00715 else
00716 return doFullMax() ? 0 : m_available_workspace_area->top();
00717 }
00718
00719 unsigned int BScreen::maxBottom(int head) const {
00720
00721
00722 if (hasXinerama())
00723 return doFullMax() ? getHeadY(head) + getHeadHeight(head) :
00724 getHeadY(head) + getHeadHeight(head) - m_available_workspace_area->bottom();
00725 else
00726 return doFullMax() ? height() : height() - m_available_workspace_area->bottom();
00727 }
00728
00729 void BScreen::update(FbTk::Subject *subj) {
00730
00731
00732
00733 renderGeomWindow();
00734 }
00735
00736 FbTk::Menu *BScreen::createMenu(const std::string &label) {
00737 FbTk::Menu *menu = new FbMenu(menuTheme(),
00738 imageControl(),
00739 *layerManager().getLayer(Fluxbox::instance()->getMenuLayer()));
00740 if (!label.empty())
00741 menu->setLabel(label.c_str());
00742
00743 return menu;
00744 }
00745
00746 void BScreen::hideMenus() {
00747
00748 Fluxbox::instance()->hideExtraMenus(*this);
00749
00750 #ifdef SLIT
00751
00752 if (slit())
00753 slit()->menu().hide();
00754 #endif // SLIT
00755
00756
00757 if (getIconList().size()) {
00758 Icons::iterator it = getIconList().begin();
00759 const Icons::iterator it_end = getIconList().end();
00760 for (; it != it_end; ++it)
00761 (*it)->menu().hide();
00762 }
00763
00764 Workspaces::iterator w_it = getWorkspacesList().begin();
00765 const Workspaces::iterator w_it_end = getWorkspacesList().end();
00766 for (; w_it != w_it_end; ++w_it) {
00767 if ((*w_it)->windowList().size()) {
00768 Workspace::Windows::iterator win_it = (*w_it)->windowList().begin();
00769 const Workspace::Windows::iterator win_it_end = (*w_it)->windowList().end();
00770 for (; win_it != win_it_end; ++win_it) {
00771 (*win_it)->menu().hide();
00772 }
00773 }
00774 }
00775
00776
00777 }
00778
00779 void BScreen::reconfigure() {
00780 m_menutheme->setAlpha(*resource.menu_alpha);
00781 m_menutheme->setMenuMode(*resource.menu_mode);
00782
00783
00784 if (*resource.menu_delay > 5000)
00785 *resource.menu_delay = 5000;
00786 if (*resource.menu_delay < 0)
00787 *resource.menu_delay = 0;
00788
00789 if (*resource.menu_delay_close > 5000)
00790 *resource.menu_delay_close = 5000;
00791 if (*resource.menu_delay_close < 0)
00792 *resource.menu_delay_close = 0;
00793
00794 m_menutheme->setDelayOpen(*resource.menu_delay);
00795 m_menutheme->setDelayClose(*resource.menu_delay_close);
00796
00797
00798 winFrameTheme().font().setAntialias(*resource.antialias);
00799 m_menutheme->titleFont().setAntialias(*resource.antialias);
00800 m_menutheme->frameFont().setAntialias(*resource.antialias);
00801
00802 renderGeomWindow();
00803
00804
00805 workspacemenu->reconfigure();
00806 m_configmenu->reconfigure();
00807
00808
00809
00810
00811
00812
00813
00814
00815 bool restore_menus = ! Fluxbox::instance()->menuTimestampsChanged();
00816
00817
00818 Fluxbox::instance()->clearMenuFilenames();
00819
00820
00821 vector<int> remember_sub;
00822 if (restore_menus) {
00823 FbTk::Menu *menu = m_rootmenu.get();
00824 while (menu) {
00825 int r = menu->currentSubmenu();
00826 if (r < 0) break;
00827 remember_sub.push_back(r);
00828 menu = menu->find(r)->submenu();
00829 }
00830 }
00831
00832 rereadMenu();
00833
00834 if (restore_menus) {
00835
00836 FbTk::Menu *menu = m_rootmenu.get();
00837 for (int i = 0; i < (int)remember_sub.size(); i++ ) {
00838 int sub = remember_sub[i];
00839 if (!menu || sub < 0)
00840 break;
00841 FbTk::MenuItem *item = menu->find(sub);
00842 if (item != 0) {
00843 menu->drawSubmenu(sub);
00844 menu = item->submenu();
00845 } else
00846 menu = 0;
00847
00848 }
00849 }
00850
00851
00852 for_each(m_workspaces_list.begin(),
00853 m_workspaces_list.end(),
00854 mem_fun(&Workspace::reconfigure));
00855
00856
00857 for_each(m_icon_list.begin(),
00858 m_icon_list.end(),
00859 mem_fun(&FluxboxWindow::reconfigure));
00860
00861 imageControl().cleanCache();
00862
00863 m_reconfigure_sig.notify();
00864 }
00865
00866
00867 void BScreen::rereadMenu() {
00868 initMenu();
00869 m_rootmenu->reconfigure();
00870 }
00871
00872
00873 void BScreen::removeWorkspaceNames() {
00874 m_workspace_names.clear();
00875 }
00876
00877 void BScreen::updateWorkspaceNamesAtom() {
00878 m_workspacenames_sig.notify();
00879 }
00880
00881 void BScreen::addIcon(FluxboxWindow *w) {
00882 if (! w) return;
00883
00884 m_icon_list.push_back(w);
00885 updateIconMenu();
00886
00887 m_iconlist_sig.notify();
00888 }
00889
00890
00891 void BScreen::removeIcon(FluxboxWindow *w) {
00892 if (! w)
00893 return;
00894
00895 Icons::iterator erase_it = remove_if(m_icon_list.begin(),
00896 m_icon_list.end(),
00897 bind2nd(equal_to<FluxboxWindow *>(), w));
00898 if (erase_it != m_icon_list.end())
00899 m_icon_list.erase(erase_it);
00900
00901 updateIconMenu();
00902
00903 m_iconlist_sig.notify();
00904 }
00905
00906
00907 void BScreen::updateIconMenu() {
00908 m_iconmenu->removeAll();
00909 Icons::iterator it = m_icon_list.begin();
00910 Icons::iterator it_end = m_icon_list.end();
00911 for (; it != it_end; ++it) {
00912 FluxboxWindow::ClientList::iterator client_it = (*it)->clientList().begin();
00913 FluxboxWindow::ClientList::iterator client_it_end = (*it)->clientList().end();
00914 for (; client_it != client_it_end; ++client_it)
00915 m_iconmenu->insert(new IconMenuItem(**client_it));
00916 }
00917 m_iconmenu->update();
00918 }
00919
00920 void BScreen::removeWindow(FluxboxWindow *win) {
00921 if (win->isIconic())
00922 removeIcon(win);
00923 else
00924 getWorkspace(win->workspaceNumber())->removeWindow(win);
00925 }
00926
00927
00928 void BScreen::removeClient(WinClient &client) {
00929
00930 WinClient *cyc = 0;
00931 if (cycling_window != focused_list.end())
00932 cyc = *cycling_window;
00933
00934 WinClient *focused = Fluxbox::instance()->getFocusedWindow();
00935 focused_list.remove(&client);
00936 if (cyc == &client) {
00937 cycling_window = focused_list.end();
00938 } else if (focused == &client) {
00939
00940
00941 if (client.transientFor() && client.transientFor()->fbwindow())
00942 client.transientFor()->fbwindow()->setInputFocus();
00943 else
00944 Fluxbox::instance()->revertFocus(focused->screen());
00945 }
00946
00947 if (cycling_last == &client)
00948 cycling_last = 0;
00949
00950 for_each(getWorkspacesList().begin(), getWorkspacesList().end(),
00951 mem_fun(&Workspace::updateClientmenu));
00952
00953
00954 Groupables::iterator it = m_expecting_groups.begin();
00955 Groupables::iterator it_end = m_expecting_groups.end();
00956 for (; it != it_end; ++it) {
00957 if (it->second == &client) {
00958 m_expecting_groups.erase(it);
00959
00960 break;
00961 }
00962 }
00963
00964 updateIconMenu();
00965
00966 }
00967
00968 void BScreen::setAntialias(bool value) {
00969 if (*resource.antialias == value)
00970 return;
00971 resource.antialias = value;
00972 reconfigure();
00973 }
00974
00975 int BScreen::addWorkspace() {
00976 Workspace *wkspc = new Workspace(*this, m_layermanager,
00977 "",
00978 m_workspaces_list.size());
00979 m_workspaces_list.push_back(wkspc);
00980 addWorkspaceName(wkspc->name().c_str());
00981
00982 workspacemenu->insert(wkspc->name().c_str(), &wkspc->menu(),
00983 wkspc->workspaceID() + 2);
00984
00985 workspacemenu->update();
00986 saveWorkspaces(m_workspaces_list.size());
00987
00988 updateNetizenWorkspaceCount();
00989
00990 return m_workspaces_list.size();
00991
00992 }
00993
00996 int BScreen::removeLastWorkspace() {
00997 if (m_workspaces_list.size() <= 1)
00998 return 0;
00999 Workspace *wkspc = m_workspaces_list.back();
01000
01001 if (m_current_workspace->workspaceID() == wkspc->workspaceID())
01002 changeWorkspaceID(m_current_workspace->workspaceID() - 1);
01003
01004 wkspc->removeAll();
01005
01006 workspacemenu->remove(wkspc->workspaceID()+2);
01007 workspacemenu->update();
01008
01009
01010 m_workspaces_list.pop_back();
01011 delete wkspc;
01012
01013
01014 updateNetizenWorkspaceCount();
01015 saveWorkspaces(m_workspaces_list.size());
01016
01017 return m_workspaces_list.size();
01018 }
01019
01020
01021 void BScreen::changeWorkspaceID(unsigned int id) {
01022
01023 if (! m_current_workspace || id >= m_workspaces_list.size() ||
01024 id == m_current_workspace->workspaceID())
01025 return;
01026
01027 FbTk::App::instance()->sync(true);
01028
01029 WinClient *focused_client = Fluxbox::instance()->getFocusedWindow();
01030 FluxboxWindow *focused = 0;
01031 if (focused_client)
01032 focused = focused_client->fbwindow();
01033
01034 if (focused && focused->isMoving()) {
01035 if (doOpaqueMove())
01036 reassociateWindow(focused, id, true);
01037
01038 focused->pauseMoving();
01039 }
01040
01041
01042 Workspace *wksp = currentWorkspace();
01043 Workspace::Windows wins = wksp->windowList();
01044 Workspace::Windows::iterator it = wins.begin();
01045 for (; it != wins.end(); ++it) {
01046 if ((*it)->isStuck()) {
01047 reassociateWindow(*it, id, true);
01048 }
01049 }
01050
01051 currentWorkspace()->hideAll();
01052
01053 workspacemenu->setItemSelected(currentWorkspace()->workspaceID() + 2, false);
01054
01055
01056 m_current_workspace = getWorkspace(id);
01057
01058 workspacemenu->setItemSelected(currentWorkspace()->workspaceID() + 2, true);
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 currentWorkspace()->showAll();
01069
01070 if (focused && (focused->isStuck() || focused->isMoving()))
01071 focused->setInputFocus();
01072 else
01073 Fluxbox::instance()->revertFocus(*this);
01074
01075 if (focused && focused->isMoving())
01076 focused->resumeMoving();
01077
01078 updateNetizenCurrentWorkspace();
01079
01080 }
01081
01082
01083 void BScreen::sendToWorkspace(unsigned int id, FluxboxWindow *win, bool changeWS) {
01084 if (! m_current_workspace || id >= m_workspaces_list.size())
01085 return;
01086
01087 if (!win) {
01088 WinClient *client = Fluxbox::instance()->getFocusedWindow();
01089 if (client)
01090 win = client->fbwindow();
01091 }
01092
01093
01094 FbTk::App::instance()->sync(true);
01095
01096 if (win && &win->screen() == this &&
01097 (! win->isStuck())) {
01098
01099
01100 if (win->isIconic())
01101 win->deiconify();
01102
01103
01104 if (id != currentWorkspace()->workspaceID())
01105 win->withdraw();
01106
01107 reassociateWindow(win, id, true);
01108
01109
01110 if (id == currentWorkspace()->workspaceID())
01111 win->deiconify(false, false);
01112
01113
01114 if (changeWS && id != currentWorkspace()->workspaceID()) {
01115 changeWorkspaceID(id);
01116 win->setInputFocus();
01117 }
01118
01119 }
01120
01121 }
01122
01123
01124 void BScreen::addNetizen(Window win) {
01125 Netizen *net = new Netizen(*this, win);
01126 m_netizen_list.push_back(net);
01127
01128 net->sendWorkspaceCount();
01129 net->sendCurrentWorkspace();
01130
01131
01132 Workspaces::iterator it = m_workspaces_list.begin();
01133 Workspaces::iterator it_end = m_workspaces_list.end();
01134 for (; it != it_end; ++it) {
01135 Workspace::Windows::iterator win_it = (*it)->windowList().begin();
01136 Workspace::Windows::iterator win_it_end = (*it)->windowList().end();
01137 for (; win_it != win_it_end; ++win_it) {
01138 net->sendWindowAdd((*win_it)->clientWindow(),
01139 (*it)->workspaceID());
01140 }
01141 }
01142
01143 Window f = ((Fluxbox::instance()->getFocusedWindow()) ?
01144 Fluxbox::instance()->getFocusedWindow()->window() : None);
01145 net->sendWindowFocus(f);
01146 }
01147
01148 void BScreen::removeNetizen(Window w) {
01149 Netizens::iterator it = m_netizen_list.begin();
01150 Netizens::iterator it_end = m_netizen_list.end();
01151 for (; it != it_end; ++it) {
01152 if ((*it)->window() == w) {
01153 Netizen *n = *it;
01154 delete n;
01155 m_netizen_list.erase(it);
01156 break;
01157 }
01158 }
01159 }
01160
01161
01162 void BScreen::updateNetizenCurrentWorkspace() {
01163 m_currentworkspace_sig.notify();
01164 for_each(m_netizen_list.begin(),
01165 m_netizen_list.end(),
01166 mem_fun(&Netizen::sendCurrentWorkspace));
01167 }
01168
01169
01170 void BScreen::updateNetizenWorkspaceCount() {
01171 for_each(m_netizen_list.begin(),
01172 m_netizen_list.end(),
01173 mem_fun(&Netizen::sendWorkspaceCount));
01174
01175 m_workspacecount_sig.notify();
01176 }
01177
01178
01179 void BScreen::updateNetizenWindowFocus() {
01180 Window f = ((Fluxbox::instance()->getFocusedWindow()) ?
01181 Fluxbox::instance()->getFocusedWindow()->window() : None);
01182 for_each(m_netizen_list.begin(),
01183 m_netizen_list.end(),
01184 bind2nd(mem_fun(&Netizen::sendWindowFocus), f));
01185 }
01186
01187
01188 void BScreen::updateNetizenWindowAdd(Window w, unsigned long p) {
01189 Netizens::iterator it = m_netizen_list.begin();
01190 Netizens::iterator it_end = m_netizen_list.end();
01191 for (; it != it_end; ++it) {
01192 (*it)->sendWindowAdd(w, p);
01193 }
01194
01195 m_clientlist_sig.notify();
01196
01197 }
01198
01199
01200 void BScreen::updateNetizenWindowDel(Window w) {
01201 for_each(m_netizen_list.begin(),
01202 m_netizen_list.end(),
01203 bind2nd(mem_fun(&Netizen::sendWindowDel), w));
01204
01205 m_clientlist_sig.notify();
01206 }
01207
01208
01209 void BScreen::updateNetizenWindowRaise(Window w) {
01210 for_each(m_netizen_list.begin(),
01211 m_netizen_list.end(),
01212 bind2nd(mem_fun(&Netizen::sendWindowRaise), w));
01213 }
01214
01215
01216 void BScreen::updateNetizenWindowLower(Window w) {
01217 for_each(m_netizen_list.begin(),
01218 m_netizen_list.end(),
01219 bind2nd(mem_fun(&Netizen::sendWindowLower), w));
01220 }
01221
01222 void BScreen::updateNetizenConfigNotify(XEvent &e) {
01223 Netizens::iterator it = m_netizen_list.begin();
01224 Netizens::iterator it_end = m_netizen_list.end();
01225 for (; it != it_end; ++it)
01226 (*it)->sendConfigNotify(e);
01227 }
01228
01229 FluxboxWindow *BScreen::createWindow(Window client) {
01230 FbTk::App::instance()->sync(false);
01231
01232 #ifdef SLIT
01233 #ifdef KDE
01234
01235
01236 bool iskdedockapp = false;
01237 Atom ajunk;
01238 int ijunk;
01239 unsigned long *data = 0, uljunk;
01240 Display *disp = FbTk::App::instance()->display();
01241
01242 if (XGetWindowProperty(disp, client,
01243 XInternAtom(FbTk::App::instance()->display(),
01244 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False),
01245 0l, 1l, False,
01246 XA_WINDOW, &ajunk, &ijunk, &uljunk,
01247 &uljunk, (unsigned char **) &data) == Success) {
01248
01249 if (data)
01250 iskdedockapp = True;
01251 XFree((void *) data);
01252 data = 0;
01253 }
01254
01255
01256 if (!iskdedockapp) {
01257 Atom kwm1 = XInternAtom(FbTk::App::instance()->display(),
01258 "KWM_DOCKWINDOW", False);
01259 if (XGetWindowProperty(disp, client,
01260 kwm1, 0l, 1l, False,
01261 kwm1, &ajunk, &ijunk, &uljunk,
01262 &uljunk, (unsigned char **) &data) == Success && data) {
01263 iskdedockapp = (data && data[0] != 0);
01264 XFree((void *) data);
01265 data = 0;
01266 }
01267 }
01268
01269 if (iskdedockapp) {
01270 XSelectInput(disp, client, StructureNotifyMask);
01271
01272 if (slit())
01273 slit()->addClient(client);
01274
01275 return 0;
01276 }
01277 #endif // KDE
01278 #endif // SLIT
01279
01280 WinClient *winclient = new WinClient(client, *this);
01281
01282 if (winclient->initial_state == WithdrawnState) {
01283 delete winclient;
01284 #ifdef SLIT
01285 slit()->addClient(client);
01286 #endif // SLIT
01287 return 0;
01288 }
01289
01290 bool new_win = false;
01291
01292
01293 FluxboxWindow *win;
01294 if ((win = findGroupLeft(*winclient)) != 0) {
01295 win->attachClient(*winclient);
01296 Fluxbox::instance()->attachSignals(*winclient);
01297 } else {
01298
01299 Fluxbox::instance()->attachSignals(*winclient);
01300 if (winclient->fbwindow())
01301 win = winclient->fbwindow();
01302 else {
01303 win = new FluxboxWindow(*winclient,
01304 winFrameTheme(),
01305 *layerManager().getLayer(Fluxbox::instance()->getNormalLayer()));
01306
01307 new_win = true;
01308
01309 if (!win->isManaged()) {
01310 delete win;
01311 return 0;
01312 }
01313 }
01314 }
01315
01316
01317
01318 if (doFocusNew())
01319 focused_list.push_front(&win->winClient());
01320 else
01321 focused_list.push_back(&win->winClient());
01322
01323 if (new_win) {
01324 Fluxbox::instance()->attachSignals(*win);
01325 }
01326
01327
01328
01329 FluxboxWindow *otherwin = 0;
01330
01331 if ((otherwin = findGroupRight(*winclient)) && otherwin != win) {
01332 win->attachClient(otherwin->winClient());
01333 }
01334
01335 if (!win->isIconic() && (win->workspaceNumber() == currentWorkspaceID() || win->isStuck())) {
01336 win->show();
01337 }
01338
01339 FbTk::App::instance()->sync(false);
01340 return win;
01341 }
01342
01343 FluxboxWindow *BScreen::createWindow(WinClient &client) {
01344 FluxboxWindow *win = new FluxboxWindow(client,
01345 winFrameTheme(),
01346 *layerManager().getLayer(Fluxbox::instance()->getNormalLayer()));
01347 #ifdef SLIT
01348 if (win->initialState() == WithdrawnState)
01349 slit()->addClient(win->clientWindow());
01350 #endif // SLIT
01351 if (!win->isManaged()) {
01352 delete win;
01353 return 0;
01354 }
01355
01356
01357
01358 Fluxbox::instance()->attachSignals(*win);
01359
01360 if (win->workspaceNumber() == currentWorkspaceID() || win->isStuck())
01361 win->show();
01362
01363 return win;
01364 }
01365
01366 Strut *BScreen::requestStrut(int left, int right, int top, int bottom) {
01367 Strut *str = new Strut(left, right, top, bottom);
01368 m_strutlist.push_back(str);
01369 return str;
01370 }
01371
01372 void BScreen::clearStrut(Strut *str) {
01373 if (str == 0)
01374 return;
01375
01376 std::list<Strut *>::iterator pos = find(m_strutlist.begin(),
01377 m_strutlist.end(),
01378 str);
01379 if (pos == m_strutlist.end())
01380 return;
01381 m_strutlist.erase(pos);
01382 delete str;
01383 }
01384
01386 namespace {
01387 class MaxArea {
01388 public:
01389 MaxArea(Strut &max_area):m_max_area(max_area) { }
01390 void operator ()(const Strut *str) {
01391 static int left, right, bottom, top;
01392 left = std::max(m_max_area.left(), str->left());
01393 right = std::max(m_max_area.right(), str->right());
01394 bottom = std::max(m_max_area.bottom(), str->bottom());
01395 top = std::max(m_max_area.top(), str->top());
01396 m_max_area = Strut(left, right, top, bottom);
01397 }
01398 private:
01399 Strut &m_max_area;
01400 };
01401
01402 };
01403
01404 void BScreen::updateAvailableWorkspaceArea() {
01405
01406
01407
01408 m_available_workspace_area.reset(new Strut(0, 0, 0, 0));
01409
01410
01411 for_each(m_strutlist.begin(),
01412 m_strutlist.end(),
01413 MaxArea(*m_available_workspace_area.get()));
01414 }
01415
01416 void BScreen::addWorkspaceName(const char *name) {
01417 m_workspace_names.push_back(name);
01418 }
01419
01420
01421 string BScreen::getNameOfWorkspace(unsigned int workspace) const {
01422 if (workspace < m_workspace_names.size())
01423 return m_workspace_names[workspace];
01424 else
01425 return "";
01426 }
01427
01428 void BScreen::reassociateWindow(FluxboxWindow *w, unsigned int wkspc_id,
01429 bool ignore_sticky) {
01430 if (w == 0)
01431 return;
01432
01433 if (wkspc_id >= getCount())
01434 wkspc_id = currentWorkspace()->workspaceID();
01435
01436 if (!w->isIconic() && w->workspaceNumber() == wkspc_id)
01437 return;
01438
01439
01440 if (w->isIconic()) {
01441 removeIcon(w);
01442 getWorkspace(wkspc_id)->addWindow(*w);
01443 } else if (ignore_sticky || ! w->isStuck()) {
01444 getWorkspace(w->workspaceNumber())->removeWindow(w);
01445 getWorkspace(wkspc_id)->addWindow(*w);
01446 }
01447 }
01448
01449
01450 void BScreen::nextFocus(int opts) {
01451 const int num_windows = currentWorkspace()->numberOfWindows();
01452
01453 if (num_windows < 1)
01454 return;
01455
01456 if (!(opts & CYCLELINEAR)) {
01457 if (!cycling_focus) {
01458 cycling_focus = True;
01459 cycling_window = focused_list.begin();
01460 cycling_last = 0;
01461 } else {
01462
01463 m_layermanager.restack();
01464 }
01465
01466
01467 FocusedWindows::iterator it = cycling_window;
01468 const FocusedWindows::iterator it_end = focused_list.end();
01469
01470 while (true) {
01471 ++it;
01472 if (it == it_end) {
01473 it = focused_list.begin();
01474 }
01475
01476 if ((*it) == (*cycling_window)) {
01477 break;
01478 }
01479
01480 FluxboxWindow *fbwin = (*it)->m_win;
01481 if (fbwin && !fbwin->isIconic() &&
01482 (fbwin->isStuck()
01483 || fbwin->workspaceNumber() == currentWorkspaceID())) {
01484
01485
01486
01487 WinClient &last_client = fbwin->winClient();
01488
01489 if (! (doSkipWindow(**it, opts) || !fbwin->setCurrentClient(**it)) ) {
01490
01491 if (!cycling_last || cycling_last->fbwindow() != fbwin) {
01492 if (cycling_last)
01493
01494 cycling_last->fbwindow()->setCurrentClient(*cycling_last, false);
01495 cycling_last = &last_client;
01496 }
01497 fbwin->tempRaise();
01498 break;
01499 }
01500 }
01501 }
01502 cycling_window = it;
01503 } else {
01504
01505 Workspace *wksp = currentWorkspace();
01506 Workspace::Windows &wins = wksp->windowList();
01507 Workspace::Windows::iterator it = wins.begin();
01508
01509 FluxboxWindow *focused_group = 0;
01510
01511 bool have_focused = false;
01512 WinClient *focused = Fluxbox::instance()->getFocusedWindow();
01513 if (focused != 0) {
01514 if (focused->screen().screenNumber() == screenNumber()) {
01515 have_focused = true;
01516 focused_group = focused->fbwindow();
01517 }
01518 }
01519
01520 if (!have_focused) {
01521 focused_group = (*it);
01522 } else {
01523
01524 for (; it != wins.end() && (*it) != focused_group; ++it)
01525 continue;
01526 }
01527
01528 do {
01529 ++it;
01530 if (it == wins.end())
01531 it = wins.begin();
01532
01533 if (! (doSkipWindow((*it)->winClient(), opts) || !(*it)->setInputFocus()) )
01534 break;
01535 } while ((*it) != focused_group);
01536
01537 if ((*it) != focused_group && it != wins.end())
01538 (*it)->raise();
01539 }
01540
01541 }
01542
01543
01544 void BScreen::prevFocus(int opts) {
01545 int num_windows = currentWorkspace()->numberOfWindows();
01546
01547 if (num_windows < 1)
01548 return;
01549
01550 if (!(opts & CYCLELINEAR)) {
01551 if (!cycling_focus) {
01552 cycling_focus = true;
01553 cycling_window = focused_list.end();
01554 cycling_last = 0;
01555 } else {
01556
01557 m_layermanager.restack();
01558 }
01559
01560
01561 FocusedWindows::iterator it = cycling_window;
01562 FocusedWindows::iterator it_end = focused_list.end();
01563
01564 while (true) {
01565 --it;
01566 if (it == it_end) {
01567 it = focused_list.end();
01568 --it;
01569 }
01570
01571 if ((*it) == (*cycling_window)) {
01572 break;
01573 }
01574
01575 FluxboxWindow *fbwin = (*it)->m_win;
01576 if (fbwin && !fbwin->isIconic() &&
01577 (fbwin->isStuck()
01578 || fbwin->workspaceNumber() == currentWorkspaceID())) {
01579
01580
01581
01582 WinClient &last_client = fbwin->winClient();
01583
01584
01585 if (! (doSkipWindow(**it, opts) || !fbwin->setCurrentClient(**it)) ) {
01586
01587 if (!cycling_last || cycling_last->fbwindow() != fbwin) {
01588 if (cycling_last)
01589
01590 cycling_last->fbwindow()->setCurrentClient(*cycling_last, false);
01591 cycling_last = &last_client;
01592 }
01593 fbwin->tempRaise();
01594 break;
01595 }
01596 }
01597 }
01598 cycling_window = it;
01599 } else {
01600
01601 Workspace *wksp = currentWorkspace();
01602 Workspace::Windows &wins = wksp->windowList();
01603 Workspace::Windows::iterator it = wins.begin();
01604
01605 FluxboxWindow *focused_group = 0;
01606
01607 bool have_focused = false;
01608 WinClient *focused = Fluxbox::instance()->getFocusedWindow();
01609 if (focused != 0) {
01610 if (focused->screen().screenNumber() == screenNumber()) {
01611 have_focused = true;
01612 focused_group = focused->fbwindow();
01613 }
01614 }
01615
01616 if (!have_focused) {
01617 focused_group = (*it);
01618 } else {
01619
01620 for (; it != wins.end() && (*it) != focused_group; ++it)
01621 continue;
01622 }
01623
01624 do {
01625 if (it == wins.begin())
01626 it = wins.end();
01627 --it;
01628
01629 if (! (doSkipWindow((*it)->winClient(), opts) || !(*it)->setInputFocus()) )
01630 break;
01631 } while ((*it) != focused_group);
01632
01633 if ((*it) != focused_group && it != wins.end())
01634 (*it)->raise();
01635 }
01636 }
01637
01638
01639 void BScreen::raiseFocus() {
01640 bool have_focused = false;
01641 Fluxbox &fb = *Fluxbox::instance();
01642
01643
01644 if (fb.getFocusedWindow()) {
01645 if (fb.getFocusedWindow()->screen().screenNumber() == screenNumber()) {
01646 have_focused = true;
01647 }
01648 }
01649
01650
01651
01652 if (currentWorkspace()->numberOfWindows() > 1 && have_focused)
01653 fb.getFocusedWindow()->raise();
01654 }
01655
01656 void BScreen::setFocusedWindow(WinClient &winclient) {
01657
01658 if (!cycling_focus) {
01659 focused_list.remove(&winclient);
01660 focused_list.push_front(&winclient);
01661 cycling_window = focused_list.begin();
01662 }
01663 }
01664
01665 void BScreen::dirFocus(FluxboxWindow &win, FocusDir dir) {
01666
01667
01668
01669
01670
01671 FluxboxWindow *foundwin = 0;
01672 int weight = 999999, exposure = 0;
01673 int borderW = winFrameTheme().border().width(),
01674 top = win.y(),
01675 bottom = win.y() + win.height() + 2*borderW,
01676 left = win.x(),
01677 right = win.x() + win.width() + 2*borderW;
01678
01679 Workspace::Windows &wins = currentWorkspace()->windowList();
01680 Workspace::Windows::iterator it = wins.begin();
01681 for (; it != wins.end(); ++it) {
01682 if ((*it) == &win) continue;
01683
01684
01685 int edge=0, upper=0, lower=0, oedge=0, oupper=0, olower=0;
01686
01687 int otop = (*it)->y(),
01688 obottom = (*it)->y() + (*it)->height() + 2*borderW,
01689 oleft = (*it)->x(),
01690 oright = (*it)->x() + (*it)->width() + 2*borderW;
01691
01692 switch (dir) {
01693 case FOCUSUP:
01694 edge = obottom;
01695 oedge = bottom;
01696 upper = left;
01697 oupper = oleft;
01698 lower = right;
01699 olower = oright;
01700 break;
01701 case FOCUSDOWN:
01702 edge = top;
01703 oedge = otop;
01704 upper = left;
01705 oupper = oleft;
01706 lower = right;
01707 olower = oright;
01708 break;
01709 case FOCUSLEFT:
01710 edge = oright;
01711 oedge = right;
01712 upper = top;
01713 oupper = otop;
01714 lower = bottom;
01715 olower = obottom;
01716 break;
01717 case FOCUSRIGHT:
01718 edge = left;
01719 oedge = oleft;
01720 upper = top;
01721 oupper = otop;
01722 lower = bottom;
01723 olower = obottom;
01724 break;
01725 }
01726
01727 if (oedge < edge) continue;
01728 if (olower <= upper || oupper >= lower) {
01729
01730 int myweight = 100000 + oedge - edge + abs(upper-oupper)+abs(lower-olower);
01731 if (myweight < weight) {
01732 foundwin = *it;
01733 exposure = 0;
01734 weight = myweight;
01735 }
01736 } else if ((oedge - edge) < weight) {
01737 foundwin = *it;
01738 weight = oedge - edge;
01739 exposure = ((lower < olower)?lower:olower) - ((upper > oupper)?upper:oupper);
01740 } else if (foundwin && oedge - edge == weight) {
01741 int myexp = ((lower < olower)?lower:olower) - ((upper > oupper)?upper:oupper);
01742 if (myexp > exposure) {
01743 foundwin = *it;
01744
01745 exposure = myexp;
01746 }
01747 }
01748 }
01749
01750 if (foundwin)
01751 foundwin->setInputFocus();
01752 }
01753
01754 void BScreen::initMenu() {
01755 I18n *i18n = I18n::instance();
01756
01757 if (m_rootmenu.get()) {
01758
01759
01760 while (m_rootmenu->numberOfItems())
01761 m_rootmenu->remove(0);
01762 m_rootmenu_list.clear();
01763
01764 } else
01765 m_rootmenu.reset(createMenu(""));
01766
01767 bool defaultMenu = true;
01768 Fluxbox * const fb = Fluxbox::instance();
01769 if (fb->getMenuFilename().size() > 0) {
01770 std::string menufilestr = fb->getMenuFilename();
01771 menufilestr = FbTk::StringUtil::expandFilename(menufilestr);
01772 ifstream menu_file(menufilestr.c_str());
01773
01774 if (!menu_file.fail()) {
01775 if (! menu_file.eof()) {
01776 string line;
01777 int row = 0;
01778 while (getline(menu_file, line) && ! menu_file.eof()) {
01779 row++;
01780 if (line[0] != '#') {
01781 string key;
01782 int pos=0;
01783 int err = FbTk::StringUtil::
01784 getStringBetween(key,
01785 line.c_str(),
01786 '[', ']');
01787
01788 if (key == "begin") {
01789 pos += err;
01790 string label;
01791 err = FbTk::StringUtil::
01792 getStringBetween(label,
01793 line.c_str()+pos,
01794 '(', ')');
01795 if (err>0) {
01796 m_rootmenu->setLabel(label.c_str());
01797 defaultMenu = parseMenuFile(menu_file, *m_rootmenu.get(), row);
01798 } else
01799 cerr<<"Error in menufile. Line("<<row<<")"<<endl;
01800 break;
01801 }
01802 }
01803 }
01804 } else {
01805 fprintf(stderr,
01806 i18n->getMessage(
01807 FBNLS::ScreenSet, FBNLS::ScreenEmptyMenuFile,
01808 "%s: Empty menu file"),
01809 menufilestr.c_str());
01810 }
01811 menu_file.close();
01812 } else
01813 perror(menufilestr.c_str());
01814 }
01815
01816 if (defaultMenu) {
01817 FbTk::RefCount<FbTk::Command> restart_fb(new FbCommands::RestartFluxboxCmd(""));
01818 FbTk::RefCount<FbTk::Command> exit_fb(new FbCommands::ExitFluxboxCmd());
01819 FbTk::RefCount<FbTk::Command> execute_xterm(new FbCommands::ExecuteCmd("xterm", screenNumber()));
01820 m_rootmenu->setInternalMenu();
01821 m_rootmenu->insert(i18n->getMessage(FBNLS::ScreenSet, FBNLS::Screenxterm,
01822 "xterm"),
01823 execute_xterm);
01824 m_rootmenu->insert(i18n->getMessage(FBNLS::ScreenSet, FBNLS::ScreenRestart,
01825 "Restart"),
01826 restart_fb);
01827 m_rootmenu->insert(i18n->getMessage(FBNLS::ScreenSet, FBNLS::ScreenExit,
01828 "Exit"),
01829 exit_fb