Merge branch 'xinerama_randr'
@@ -1,5 +1,10 @@
(Format: Year/Month/Day) Changes for 1.0.1: +*08/01/27: + * Reload the Xinerama layout on RandR signal (Tomas) + Screen.cc/hh + * Move windows out of inactive heads upon Xinerama layout change (Tomas) + Screen.cc/hh *07/12/28: * Added new key command :Delay {<command>} [<int>], which runs the command after a delay of <int> microseconds (default is 200 milliseconds) (Mark)
@@ -360,6 +360,12 @@
Display *disp = m_root_window.display(); Fluxbox *fluxbox = Fluxbox::instance(); + // TODO fluxgen: check if this is the right place (it was not -lis) + // + // Create the first one, initXinerama will expand this if needed. + m_head_areas.resize(1); + m_head_areas[0] = new HeadArea(); + initXinerama(); // setup error handler to catch "screen already managed by other wm"@@ -401,9 +407,6 @@ &ret_bytes_after, &ret_prop) == Success) {
m_restart = (ret_prop != NULL); XFree(ret_prop); } - - // TODO fluxgen: check if this is the right place - m_head_areas = new HeadArea[numHeads() ? numHeads() : 1]; #ifdef HAVE_RANDR // setup RANDR for this screens root window@@ -600,7 +603,8 @@ // slit must be destroyed before headAreas (Struts)
m_slit.reset(0); // TODO fluxgen: check if this is the right place - delete [] m_head_areas; + for (int i = 0; i < m_head_areas.size(); i++) + delete m_head_areas[i]; delete m_focus_control; delete m_placement_strategy;@@ -722,7 +726,12 @@ return m_current_workspace->workspaceID();
} const Strut* BScreen::availableWorkspaceArea(int head) const { - return m_head_areas[head ? head-1 : 0].availableWorkspaceArea(); + if (head > numHeads()) { + /* May this ever happen? */ + static Strut whole(-1 /* should never be used */, 0, width(), 0, height()); + return &whole; + } + return m_head_areas[head ? head-1 : 0]->availableWorkspaceArea(); } unsigned int BScreen::maxLeft(int head) const {@@ -1412,7 +1421,7 @@ }
Strut* next = 0; for (int i = begin; i != end; i++) { - next = m_head_areas[i].requestStrut(i+1, left, right, top, bottom, next); + next = m_head_areas[i]->requestStrut(i+1, left, right, top, bottom, next); } return next;@@ -1422,7 +1431,9 @@ void BScreen::clearStrut(Strut *str) {
if (str->next()) clearStrut(str->next()); int head = str->head() ? str->head() - 1 : 0; - m_head_areas[head].clearStrut(str); + /* The number of heads may have changed, be careful. */ + if (head < numHeads()) + m_head_areas[head]->clearStrut(str); // str is invalid now }@@ -1431,7 +1442,7 @@ size_t n = (numHeads() ? numHeads() : 1);
bool updated = false; for (size_t i = 0; i < n; i++) { - updated = m_head_areas[i].updateAvailableWorkspaceArea() || updated; + updated = m_head_areas[i]->updateAvailableWorkspaceArea() || updated; } if (updated)@@ -1886,6 +1897,9 @@ m_pos_window.reconfigTheme();
} void BScreen::updateSize() { + // update xinerama layout + initXinerama(); + // force update geometry rootWindow().updateGeometry();@@ -1895,6 +1909,9 @@
// send resize notify m_resize_sig.notify(); m_workspace_area_sig.notify(); + + // move windows out of inactive heads + clearHeads(); }@@ -1941,10 +1958,13 @@ #ifdef XINERAMA
Display *display = FbTk::App::instance()->display(); if (!XineramaIsActive(display)) { +notactive: #ifdef DEBUG cerr<<"BScreen::initXinerama(): dont have Xinerama"<<endl; #endif // DEBUG m_xinerama_avail = false; + if (m_xinerama_headinfo) + delete [] m_xinerama_headinfo; m_xinerama_headinfo = 0; m_xinerama_num_heads = 0; return;@@ -1957,6 +1977,19 @@
XineramaScreenInfo *screen_info; int number; screen_info = XineramaQueryScreens(display, &number); + + /* The call may have actually failed. If this is the first time we init + * Xinerama, fall back to turning it off. If not, pretend nothing + * happened -- another event will tell us and it will work then. */ + if (!screen_info) { + if (m_xinerama_headinfo) + return; + else + goto notactive; + } + + if (m_xinerama_headinfo) + delete [] m_xinerama_headinfo; m_xinerama_headinfo = new XineramaHeadInfo[number]; m_xinerama_num_heads = number; for (int i=0; i < number; i++) {@@ -1970,12 +2003,40 @@ #ifdef DEBUG
cerr<<"BScreen::initXinerama(): number of heads ="<<number<<endl; #endif // DEBUG + /* Reallocate to the new number of heads. */ + int ha_num = numHeads() ? numHeads() : 1, ha_oldnum = m_head_areas.size(); + if (ha_num > ha_oldnum) { + m_head_areas.resize(ha_num); + for (int i = ha_oldnum; i < ha_num; i++) + m_head_areas[i] = new HeadArea(); + } else if (ha_num < ha_oldnum) { + for (int i = ha_num; i < ha_oldnum; i++) + delete m_head_areas[i]; + m_head_areas.resize(ha_num); + } + #else // XINERAMA // no xinerama m_xinerama_avail = false; m_xinerama_num_heads = 0; #endif // XINERAMA +} + +/* Move windows out of inactive heads */ +void BScreen::clearHeads() { + if (!hasXinerama()) return; + + for (Workspaces::iterator i = m_workspaces_list.begin(); + i != m_workspaces_list.end(); i++) { + for (Workspace::Windows::iterator win = (*i)->windowList().begin(); + win != (*i)->windowList().end(); win++) { + if (getHead((*win)->fbWindow()) == 0) { + // first head is a safe bet here + (*win)->placeWindow(1); + } + } + } } int BScreen::getHead(int x, int y) const {
@@ -406,6 +406,7 @@ /// @return umber of xinerama heads
int numHeads() const { return m_xinerama_num_heads; } void initXinerama(); + void clearHeads(); /** * Determines head number for a position * @param x position in pixels on the screen@@ -590,7 +591,7 @@ bool m_xinerama_avail;
int m_xinerama_num_heads; int m_xinerama_center_x, m_xinerama_center_y; - HeadArea *m_head_areas; + std::vector<HeadArea *> m_head_areas; struct XineramaHeadInfo { int x, y, width, height;
@@ -48,10 +48,6 @@ #include "FbTk/XLayer.hh"
#include "RootTheme.hh" #include "FbMenu.hh" -#ifdef XINERAMA -#include "Xinerama.hh" -#endif // XINERAMA - #include "SlitTheme.hh" #include "SlitClient.hh" #include "Xutil.hh"@@ -270,6 +266,9 @@ *scr.layerManager().getLayer(Layer::MENU)),
m_slitmenu(scr.menuTheme(), scr.imageControl(), *scr.layerManager().getLayer(Layer::MENU)), +#ifdef XINERAMA + m_xineramaheadmenu(0), +#endif // XINERAMA frame(scr.rootWindow()), //For KDE dock applets m_kwm1_dockwindow(XInternAtom(FbTk::App::instance()->display(),@@ -482,8 +481,7 @@
if (wmhints != 0) { if ((wmhints->flags & IconWindowHint) && (wmhints->icon_window != None)) { - XMoveWindow(disp, client->clientWindow(), screen().width() + 10, - screen().height() + 10); + XMoveWindow(disp, client->clientWindow(), -100, -100); XMapWindow(disp, client->clientWindow()); client->setIconWindow(wmhints->icon_window); client->setWindow(client->iconWindow());@@ -1113,6 +1111,10 @@ }
void Slit::update(FbTk::Subject *subj) { reconfigure(); +#ifdef XINERAMA + if (subj == &m_screen.resizeSig() && m_xineramaheadmenu) + m_xineramaheadmenu->reloadHeads(); +#endif // XINERAMA } void Slit::clearWindow() {@@ -1254,6 +1256,7 @@
#ifdef XINERAMA if (screen().hasXinerama()) { m_slitmenu.insert(_FB_XTEXT(Menu, OnHead, "On Head...", "Title of On Head menu"), + m_xineramaheadmenu = new XineramaHeadMenu<Slit>( screen().menuTheme(), screen(),
@@ -29,6 +29,10 @@ #include "SlitTheme.hh"
#include "LayerMenu.hh" #include "Layer.hh" +#ifdef XINERAMA +#include "Xinerama.hh" +#endif // XINERAMA + #include "FbTk/Menu.hh" #include "FbTk/FbWindow.hh" #include "FbTk/Timer.hh"@@ -144,6 +148,9 @@
SlitClients m_client_list; std::auto_ptr<LayerMenu> m_layermenu; FbMenu m_clientlist_menu, m_slitmenu; +#ifdef XINERAMA + XineramaHeadMenu<Slit> *m_xineramaheadmenu; +#endif // XINERAMA std::string m_filename; struct frame {
@@ -35,10 +35,6 @@ #include "Keys.hh"
#include "Screen.hh" #include "WindowCmd.hh" -#ifdef XINERAMA -#include "Xinerama.hh" -#endif // XINERAMA - #include "Strut.hh" #include "FbTk/CommandParser.hh" #include "Layer.hh"@@ -216,6 +212,9 @@ *scrn.layerManager().getLayer(Layer::MENU)),
m_toolbarmenu(scrn.menuTheme(), scrn.imageControl(), *scrn.layerManager().getLayer(Layer::MENU)), +#ifdef XINERAMA + m_xineramaheadmenu(0), +#endif // XINERAMA m_theme(scrn.screenNumber()), m_tool_factory(scrn), m_strut(0),@@ -629,6 +628,10 @@ rearrangeItems();
else reconfigure(); +#ifdef XINERAMA + if (subj == &m_screen.resizeSig() && m_xineramaheadmenu) + m_xineramaheadmenu->reloadHeads(); +#endif // XINERAMA } void Toolbar::setPlacement(Toolbar::Placement where) {@@ -872,6 +875,7 @@ menu().insert(_FB_XTEXT(Menu, Layer, "Layer...", "Title of Layer menu"), &layerMenu());
#ifdef XINERAMA if (screen().hasXinerama()) { menu().insert(_FB_XTEXT(Menu, OnHead, "On Head...", "Title of On Head menu"), + m_xineramaheadmenu = new XineramaHeadMenu<Toolbar>(screen().menuTheme(), screen(), screen().imageControl(),
@@ -31,6 +31,10 @@ #include "ToolFactory.hh"
#include "ToolTheme.hh" #include "Layer.hh" +#ifdef XINERAMA +#include "Xinerama.hh" +#endif // XINERAMA + #include "FbTk/Timer.hh" #include "FbTk/Resource.hh" #include "FbTk/Observer.hh"@@ -159,6 +163,9 @@
FbTk::XLayerItem m_layeritem; ///< layer item, must be declared before layermenu LayerMenu m_layermenu; FbMenu m_placementmenu, m_toolbarmenu; +#ifdef XINERAMA + XineramaHeadMenu<Toolbar> *m_xineramaheadmenu; +#endif // XINERAMA // themes
@@ -25,6 +25,7 @@ #define XINERAMA_HH
#include "FbMenu.hh" #include "fluxbox.hh" +#include "Screen.hh" #include "FbTk/RefCount.hh" #include "FbTk/SimpleCommand.hh"@@ -59,14 +60,16 @@
/// Create a xinerama menu template <typename ItemType> -class XineramaHeadMenu : public FbMenu { +class XineramaHeadMenu : public ToggleMenu { public: XineramaHeadMenu(FbTk::ThemeProxy<FbTk::MenuTheme> &tm, BScreen &screen, FbTk::ImageControl &imgctrl, FbTk::XLayer &layer, ItemType &item, const FbTk::FbString & title = ""); + void reloadHeads(); private: ItemType &m_object; + BScreen &m_screen; };@@ -75,15 +78,22 @@ XineramaHeadMenu<ItemType>::XineramaHeadMenu(
FbTk::ThemeProxy<FbTk::MenuTheme> &tm, BScreen &screen, FbTk::ImageControl &imgctrl, FbTk::XLayer &layer, ItemType &item, const FbTk::FbString & title): - FbMenu(tm, imgctrl, layer), - m_object(item) + ToggleMenu(tm, imgctrl, layer), + m_object(item), m_screen(screen) { setLabel(title); + reloadHeads(); +} + +template <typename ItemType> +void XineramaHeadMenu<ItemType>::reloadHeads() +{ + removeAll(); FbTk::RefCount<FbTk::Command<void> > saverc_cmd(new FbTk::SimpleCommand<Fluxbox>( *Fluxbox::instance(), &Fluxbox::save_rc)); char tname[128]; - for (int i=1; i <= screen.numHeads(); ++i) { + for (int i=1; i <= m_screen.numHeads(); ++i) { // TODO: nls /* sprintf(tname, I18n::instance()->
@@ -844,6 +844,7 @@ default: {
#ifdef HAVE_RANDR if (e->type == m_randr_event_type) { + XRRUpdateConfiguration(e); // update root window size in screen BScreen *scr = searchScreen(e->xany.window); if (scr != 0)