head specific strut, patch from Mathieu De Zutter
@@ -22,7 +22,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Screen.cc,v 1.289 2004/09/09 14:29:03 akir Exp $ +// $Id: Screen.cc,v 1.290 2004/09/11 13:30:37 fluxgen Exp $ #include "Screen.hh"@@ -55,6 +55,7 @@ #include "FbWinFrame.hh"
#include "Strut.hh" #include "CommandParser.hh" #include "AtomHandler.hh" +#include "HeadArea.hh" #include "FbTk/I18n.hh"@@ -226,7 +227,6 @@ resource(rm, screenname, altscreenname),
m_name(screenname), m_altname(altscreenname), m_resource_manager(rm), - m_available_workspace_area(new Strut(0, 0, 0, 0)), m_xinerama_headinfo(0), m_shutdown(false) {@@ -250,6 +250,9 @@
managed = running; if (! managed) return; + + // TODO fluxgen: check if this is the right place + m_head_areas = new HeadArea[numHeads() ? numHeads() : 1]; _FB_USES_NLS;@@ -434,6 +437,9 @@
if (hasXinerama() && m_xinerama_headinfo) { delete [] m_xinerama_headinfo; } + + // TODO fluxgen: check if this is the right place + delete [] m_head_areas; } void BScreen::initWindows() {@@ -548,32 +554,36 @@ unsigned int BScreen::currentWorkspaceID() const {
return m_current_workspace->workspaceID(); } +const Strut* BScreen::availableWorkspaceArea(int head) const { + return m_head_areas[head ? head-1 : 0].availableWorkspaceArea(); +} + unsigned int BScreen::maxLeft(int head) const { + // we ignore strut if we're doing full maximization if (hasXinerama()) return doFullMax() ? getHeadX(head) : - getHeadX(head) + m_available_workspace_area->left(); + getHeadX(head) + availableWorkspaceArea(head)->left(); else - return doFullMax() ? 0 : m_available_workspace_area->left(); + return doFullMax() ? 0 : availableWorkspaceArea(head)->left(); } unsigned int BScreen::maxRight(int head) const { // we ignore strut if we're doing full maximization if (hasXinerama()) return doFullMax() ? getHeadX(head) + getHeadWidth(head) : - getHeadX(head) + getHeadWidth(head) - m_available_workspace_area->right(); + getHeadX(head) + getHeadWidth(head) - availableWorkspaceArea(head)->right(); else - return doFullMax() ? width() : width() - m_available_workspace_area->right(); + return doFullMax() ? width() : width() - availableWorkspaceArea(head)->right(); } unsigned int BScreen::maxTop(int head) const { - // we ignore strut if we're doing full maximization - + if (hasXinerama()) - return doFullMax() ? getHeadY(head) : getHeadY(head) + m_available_workspace_area->top(); + return doFullMax() ? getHeadY(head) : getHeadY(head) + availableWorkspaceArea(head)->top(); else - return doFullMax() ? 0 : m_available_workspace_area->top(); + return doFullMax() ? 0 : availableWorkspaceArea(head)->top(); } unsigned int BScreen::maxBottom(int head) const {@@ -581,9 +591,9 @@ // we ignore strut if we're doing full maximization
if (hasXinerama()) return doFullMax() ? getHeadY(head) + getHeadHeight(head) : - getHeadY(head) + getHeadHeight(head) - m_available_workspace_area->bottom(); + getHeadY(head) + getHeadHeight(head) - availableWorkspaceArea(head)->bottom(); else - return doFullMax() ? height() : height() - m_available_workspace_area->bottom(); + return doFullMax() ? height() : height() - availableWorkspaceArea(head)->bottom(); } void BScreen::update(FbTk::Subject *subj) {@@ -1260,58 +1270,46 @@
return win; } -Strut *BScreen::requestStrut(int left, int right, int top, int bottom) { - Strut *str = new Strut(left, right, top, bottom); - m_strutlist.push_back(str); - return str; +Strut *BScreen::requestStrut(int head, int left, int right, int top, int bottom) { + if (head > numHeads() && head != 1) { + // head does not exist (if head == 1, then numHeads() == 0, + // which means no xinerama, but there's a head after all + head = numHeads(); + } + + int begin = head-1; + int end = head; + + if (head == 0) { // all heads (or no xinerama) + begin = 0; + end = (numHeads() ? numHeads() : 1); + } + + Strut* next = 0; + for (int i = begin; i != end; i++) { + next = m_head_areas[i].requestStrut(i+1, left, right, top, bottom, next); + } + + return next; } void BScreen::clearStrut(Strut *str) { - if (str == 0) - return; - // find strut and erase it - std::list<Strut *>::iterator pos = find(m_strutlist.begin(), - m_strutlist.end(), - str); - if (pos == m_strutlist.end()) - return; - m_strutlist.erase(pos); - delete str; + if (str->next()) + clearStrut(str->next()); + int head = str->head() ? str->head() - 1 : 0; + m_head_areas[head].clearStrut(str); + // str is invalid now } -/// helper class for for_each in BScreen::updateAvailableWorkspaceArea() -namespace { -class MaxArea { -public: - MaxArea(Strut &max_area):m_max_area(max_area) { } - void operator ()(const Strut *str) { - static int left, right, bottom, top; - left = std::max(m_max_area.left(), str->left()); - right = std::max(m_max_area.right(), str->right()); - bottom = std::max(m_max_area.bottom(), str->bottom()); - top = std::max(m_max_area.top(), str->top()); - m_max_area = Strut(left, right, top, bottom); - } -private: - Strut &m_max_area; -}; - -} // end anonymous namespace - void BScreen::updateAvailableWorkspaceArea() { - // find max of left, right, top and bottom and set avaible workspace area + size_t n = (numHeads() ? numHeads() : 1); + bool updated = false; - // clear old area - Strut oldarea = *(m_available_workspace_area.get()); - m_available_workspace_area.reset(new Strut(0, 0, 0, 0)); - - // calculate max area - for_each(m_strutlist.begin(), - m_strutlist.end(), - MaxArea(*m_available_workspace_area.get())); + for (size_t i = 0; i < n; i++) { + updated = m_head_areas[i].updateAvailableWorkspaceArea() || updated; + } - // only notify if the area changed - if (oldarea == *(m_available_workspace_area.get())) + if (updated) m_workspace_area_sig.notify(); }@@ -2204,11 +2202,17 @@ #ifdef XINERAMA
Display *display = FbTk::App::instance()->display(); if (!XineramaIsActive(display)) { +#ifdef DEBUG + cerr<<"BScreen::initXinerama(): dont have Xinerama"<<endl; +#endif // DEBUG m_xinerama_avail = false; m_xinerama_headinfo = 0; m_xinerama_num_heads = 0; return; } +#ifdef DEBUG + cerr<<"BScreen::initXinerama(): have Xinerama"<<endl; +#endif // DEBUG m_xinerama_avail = true; XineramaScreenInfo *screen_info;@@ -2222,6 +2226,10 @@ m_xinerama_headinfo[i].y = screen_info[i].y_org;
m_xinerama_headinfo[i].width = screen_info[i].width; m_xinerama_headinfo[i].height = screen_info[i].height; } +#ifdef DEBUG + cerr<<"BScreen::initXinerama(): number of heads ="<<number<<endl; +#endif // DEBUG + #else // XINERAMA // no xinerama m_xinerama_avail = false;@@ -2306,6 +2314,31 @@ return m_xinerama_headinfo[head-1].height;
#else return height(); #endif // XINERAMA +} + +pair<int,int> BScreen::clampToHead(int head, int x, int y, int w, int h) const { + + // if there are multiple heads, head=0 is not valid + // a better way would be to search the closest head + if (head == 0 && numHeads() != 0) + head = 1; + + int hx = getHeadX(head); + int hy = getHeadY(head); + int hw = getHeadWidth(head); + int hh = getHeadHeight(head); + + if (x + w > hx + hw) + x = hx + hw - w; + if (y + h > hy + hh) + y = hy + hh - h; + + if (x < hx) + x = hx; + if (y < hy) + y = hy; + + return make_pair(x,y); } // TODO: when toolbar gets its resources moved into Toolbar.hh/cc, then
@@ -22,7 +22,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Screen.hh,v 1.144 2004/09/09 14:29:04 akir Exp $ +// $Id: Screen.hh,v 1.145 2004/09/11 13:29:35 fluxgen Exp $ #ifndef SCREEN_HH #define SCREEN_HH@@ -61,6 +61,7 @@ class WinClient;
class Workspace; class Strut; class Slit; +class HeadArea; namespace FbTk { class Menu;@@ -304,6 +305,9 @@ int getHeadY(int head) const;
int getHeadWidth(int head) const; int getHeadHeight(int head) const; + // returns the new (x,y) for a rectangle fitted on a head + std::pair<int,int> clampToHead(int head, int x, int y, int w, int h) const; + // magic to allow us to have "on head" placement (menu) without // the object really knowing about it. template <typename OnHeadObject>@@ -333,7 +337,7 @@ FluxboxWindow *createWindow(Window clientwin);
FluxboxWindow *createWindow(WinClient &client); void setupWindowActions(FluxboxWindow &win); /// request workspace space, i.e "don't maximize over this area" - Strut *requestStrut(int left, int right, int top, int bottom); + Strut *requestStrut(int head, int left, int right, int top, int bottom); /// remove requested space and destroy strut void clearStrut(Strut *strut); /// updates max avaible area for the workspace@@ -362,6 +366,8 @@ void initMenu();
bool doSkipWindow(const WinClient &winclient, int options); void renderGeomWindow(); void renderPosWindow(); + + const Strut* availableWorkspaceArea(int head) const; ScreenSubject m_clientlist_sig, ///< client signal@@ -455,13 +461,12 @@ // Xinerama related private data
int m_xinerama_center_x, m_xinerama_center_y; - std::auto_ptr<Strut> m_available_workspace_area; + HeadArea *m_head_areas; struct XineramaHeadInfo { int x, y, width, height; } *m_xinerama_headinfo; - std::list<Strut *> m_strutlist; bool m_shutdown; };
@@ -22,7 +22,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Slit.cc,v 1.99 2004/08/31 19:27:21 akir Exp $ +// $Id: Slit.cc,v 1.100 2004/09/11 13:31:36 fluxgen Exp $ #include "Slit.hh"@@ -407,7 +407,7 @@ if (direction() == VERTICAL)
right = width(); break; } - m_strut = screen().requestStrut(left, right, top, bottom); + m_strut = screen().requestStrut(getOnHead(), left, right, top, bottom); screen().updateAvailableWorkspaceArea(); }
@@ -22,7 +22,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: Toolbar.cc,v 1.152 2004/08/31 19:38:42 akir Exp $ +// $Id: Toolbar.cc,v 1.153 2004/09/11 13:33:07 fluxgen Exp $ #include "Toolbar.hh"@@ -328,7 +328,7 @@ case LEFTBOTTOM:
left = width(); break; }; - m_strut = screen().requestStrut(left, right, top, bottom); + m_strut = screen().requestStrut(getOnHead(), left, right, top, bottom); screen().updateAvailableWorkspaceArea(); }@@ -485,22 +485,21 @@
screen().hideMenus(); if (! menu().isVisible()) { - int x, y; - x = be.x_root - (menu().width() / 2); - y = be.y_root - (menu().height() / 2); + int head = screen().getHead(be.x_root, be.y_root); + int borderw = menu().fbwindow().borderWidth(); + pair<int, int> m = screen().clampToHead( head, + be.x_root - (menu().width() / 2), + be.y_root - (menu().titleWindow().height() / 2), + menu().width() + 2*borderw, + menu().height() + 2*borderw); - if (x < 0) - x = 0; - else if (x + menu().width() > screen().width()) - x = screen().width() - menu().width(); - - if (y < 0) - y = 0; - else if (y + menu().height() > screen().height()) - y = screen().height() - menu().height(); - - menu().move(x, y); + menu().setScreen( + screen().getHeadX(head), + screen().getHeadY(head), + screen().getHeadWidth(head), + screen().getHeadHeight(head)); + menu().move(m.first, m.second); menu().show(); menu().grabInputFocus(); } else