add back some xinerama support (toolbar, slit (+menu), screen)
@@ -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.171 2003/05/18 22:01:14 fluxgen Exp $ +// $Id: Screen.cc,v 1.172 2003/05/19 14:26:29 rathnor Exp $ #include "Screen.hh"@@ -113,6 +113,12 @@ #endif // MAXPATHLEN
#include <X11/Xatom.h> #include <X11/keysym.h> + +#ifdef XINERAMA +extern "C" { +#include <X11/extensions/Xinerama.h> +} +#endif // XINERAMA #include <iostream> #include <memory>@@ -480,13 +486,14 @@ toolbar_mode(rm, ToolbarHandler::ICONS, scrname+".toolbar.mode", altscrname+".Toolbar.Mode"),
toolbar_on_head(rm, 0, scrname+".toolbar.onhead", altscrname+".Toolbar.onHead"), toolbar_placement(rm, Toolbar::BOTTOMCENTER, scrname+".toolbar.placement", altscrname+".Toolbar.Placement"), - slit_auto_hide(rm, false, - scrname+".slit.autoHide", altscrname+".Slit.AutoHide"), - slit_placement(rm, Slit::BOTTOMRIGHT, - scrname+".slit.placement", altscrname+".Slit.Placement"), - slit_direction(rm, Slit::VERTICAL, - scrname+".slit.direction", altscrname+".Slit.Direction"), - slit_alpha(rm, 255, scrname+".slit.alpha", altscrname+".Slit.Alpha") { + slit_auto_hide(rm, false, + scrname+".slit.autoHide", altscrname+".Slit.AutoHide"), + slit_placement(rm, Slit::BOTTOMRIGHT, + scrname+".slit.placement", altscrname+".Slit.Placement"), + slit_direction(rm, Slit::VERTICAL, + scrname+".slit.direction", altscrname+".Slit.Direction"), + slit_alpha(rm, 255, scrname+".slit.alpha", altscrname+".Slit.Alpha"), + slit_on_head(rm, 0, scrname+".slit.onhead", altscrname+".Slit.onHead") { };@@ -515,6 +522,10 @@ m_toolbarhandler(0) {
Display *disp = FbTk::App::instance()->display(); + +#ifdef XINERAMA + initXinerama(disp); +#endif // XINERAMA event_mask = ColormapChangeMask | EnterWindowMask | PropertyChangeMask | SubstructureRedirectMask | KeyPressMask | KeyReleaseMask |@@ -761,6 +772,12 @@ delete (*n_it);
} netizenList.clear(); + +#ifdef XINERAMA + if (hasXinerama() && m_xinerama_headinfo) { + delete [] m_xinerama_headinfo; + } +#endif // XINERAMA } const FbTk::Menu &BScreen::toolbarModemenu() const {@@ -2524,3 +2541,102 @@
//!! TODO: should we re-maximize the maximized windows? } + +#ifdef XINERAMA + +void BScreen::initXinerama(Display *display) { + if (!XineramaIsActive(display)) { + m_xinerama_avail = false; + m_xinerama_headinfo = 0; + return; + } + m_xinerama_avail = true; + + XineramaScreenInfo *screen_info; + int number; + screen_info = XineramaQueryScreens(display, &number); + m_xinerama_headinfo = new XineramaHeadInfo[number]; + m_xinerama_num_heads = number; + for (int i=0; i < number; i++) { + m_xinerama_headinfo[i].x = screen_info[i].x_org; + 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; + } + +} + +int BScreen::getHead(int x, int y) const { + if (!hasXinerama()) return 0; + + for (int i=0; i < m_xinerama_num_heads; i++) { + if (x >= m_xinerama_headinfo[i].x && + x < (m_xinerama_headinfo[i].x + m_xinerama_headinfo[i].width) && + y >= m_xinerama_headinfo[i].y && + y < (m_xinerama_headinfo[i].y + m_xinerama_headinfo[i].height)) { + return i+1; + } + } + + return 0; +} + +int BScreen::getCurrHead() const { + if (!hasXinerama()) return 0; + int root_x, root_y, ignore_i; + + unsigned int ignore_ui; + + Window ignore_w; + + XQueryPointer(FbTk::App::instance()->display(), + rootWindow().window(), &ignore_w, + &ignore_w, &root_x, &root_y, + &ignore_i, &ignore_i, &ignore_ui); + return getHead(root_x, root_y); + +} + +int BScreen::getHeadX(int head) const { + if (head == 0 || head > m_xinerama_num_heads) return 0; + return m_xinerama_headinfo[head-1].x; +} + +int BScreen::getHeadY(int head) const { + if (head == 0 || head > m_xinerama_num_heads) return 0; + return m_xinerama_headinfo[head-1].y; +} + +int BScreen::getHeadWidth(int head) const { + if (head == 0 || head > m_xinerama_num_heads) return width(); + return m_xinerama_headinfo[head-1].width; +} + +int BScreen::getHeadHeight(int head) const { + if (head == 0 || head > m_xinerama_num_heads) return height(); + return m_xinerama_headinfo[head-1].height; +} + +template <> +int BScreen::getOnHead<Toolbar>(Toolbar &tbar) { + return getToolbarOnHead(); +} + +template <> +void BScreen::setOnHead<Toolbar>(Toolbar &tbar, int head) { + saveToolbarOnHead(head); + tbar.reconfigure(); +} + +template <> +int BScreen::getOnHead<Slit>(Slit &tbar) { + return getSlitOnHead(); +} + +template <> +void BScreen::setOnHead<Slit>(Slit &slit, int head) { + saveSlitOnHead(head); + slit.reconfigure(); +} + +#endif // XINERAMA
@@ -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.99 2003/05/18 22:00:04 fluxgen Exp $ +// $Id: Screen.hh,v 1.100 2003/05/19 14:26:30 rathnor Exp $ #ifndef SCREEN_HH #define SCREEN_HH@@ -116,8 +116,8 @@ inline void saveSlitPlacement(Slit::Placement p) { resource.slit_placement = p; }
inline void saveSlitDirection(Slit::Direction d) { resource.slit_direction = d; } inline void saveSlitAutoHide(bool t) { resource.slit_auto_hide = t; } - inline unsigned int getSlitOnHead() const { return resource.slit_on_head; } - inline void saveSlitOnHead(unsigned int h) { resource.slit_on_head = h; } + inline int getSlitOnHead() const { return *resource.slit_on_head; } + inline void saveSlitOnHead(int h) { *resource.slit_on_head = h; } inline const Toolbar *toolbar() const { return m_toolbarhandler->getToolbar(); } inline Toolbar *toolbar() { return m_toolbarhandler->getToolbar(); }@@ -296,6 +296,29 @@ /// that depends on screen size (toolbar, slit)
/// (and maximized windows?) void updateSize(); +#ifdef XINERAMA + // Xinerama-related functions + inline bool hasXinerama() const { return m_xinerama_avail; } + inline int numHeads() const { return m_xinerama_num_heads; } + + void initXinerama(Display *display); + + int getHead(int x, int y) const; + int getCurrHead() const; + int getHeadX(int head) const; + int getHeadY(int head) const; + int getHeadWidth(int head) const; + int getHeadHeight(int head) const; + + // magic to allow us to have "on head" placement without + // the object really knowing about it. + template <typename OnHeadObject> + int getOnHead(OnHeadObject &obj); + + template <typename OnHeadObject> + void setOnHead(OnHeadObject &obj, int head); +#endif // XINERAMA + // notify netizens void updateNetizenCurrentWorkspace(); void updateNetizenWorkspaceCount();@@ -412,9 +435,7 @@ FbTk::Resource<Toolbar::Placement> toolbar_placement;
FbTk::Resource<bool> slit_auto_hide; FbTk::Resource<Slit::Placement> slit_placement; FbTk::Resource<Slit::Direction> slit_direction; - FbTk::Resource<int> slit_alpha; - - unsigned int slit_on_head; + FbTk::Resource<int> slit_alpha, slit_on_head; std::string strftime_format;@@ -425,6 +446,21 @@
} resource; std::auto_ptr<ToolbarHandler> m_toolbarhandler; + +#ifdef XINERAMA + // Xinerama related private data + bool m_xinerama_avail; + int m_xinerama_num_heads; + + int m_xinerama_center_x, m_xinerama_center_y; + + struct XineramaHeadInfo { + int x, y, width, height; + } *m_xinerama_headinfo; + + + +#endif };
@@ -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.55 2003/05/17 11:00:50 fluxgen Exp $ +// $Id: Slit.cc,v 1.56 2003/05/19 14:26:30 rathnor Exp $ #include "Slit.hh"@@ -51,6 +51,10 @@ #include "FbTk/Theme.hh"
#include "FbMenu.hh" #include "Transparent.hh" #include "IntResMenuItem.hh" + +#ifdef XINERAMA +#include "Xinerama.hh" +#endif // XINERAMA #include <algorithm> #include <iostream>@@ -790,8 +794,20 @@ head_y = 0,
head_w, head_h; - head_w = screen().width(); - head_h = screen().height(); +#ifdef XINERAMA + if (screen().hasXinerama()) { + int head = screen().getSlitOnHead(); + head_x = screen().getHeadX(head); + head_y = screen().getHeadY(head); + head_w = screen().getHeadWidth(head); + head_h = screen().getHeadHeight(head); + } else +#endif // XINERAMA + { + head_w = screen().width(); + head_h = screen().height(); + } + int border_width = screen().rootTheme().borderWidth(); int bevel_width = screen().rootTheme().bevelWidth();@@ -1206,6 +1222,18 @@ &m_placement_menu);
m_slitmenu.insert("Layer...", m_layermenu.get()); +#ifdef XINERAMA + if (screen().hasXinerama()) { + m_slitmenu.insert("On Head...", new XineramaHeadMenu<Slit>( + *screen().menuTheme(), + screen(), + screen().imageControl(), + *screen().layerManager().getLayer(Fluxbox::instance()->getMenuLayer()), + this + )); + } + +#endif //XINERAMA m_slitmenu.insert(new BoolMenuItem(i18n->getMessage( CommonSet, CommonAutoHide, "Auto hide"),
@@ -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.84 2003/05/17 11:30:59 fluxgen Exp $ +// $Id: Toolbar.cc,v 1.85 2003/05/19 14:26:30 rathnor Exp $ #include "Toolbar.hh"@@ -42,6 +42,10 @@ #include "MacroCommand.hh"
#include "RootTheme.hh" #include "BoolMenuItem.hh" #include "FbWinFrameTheme.hh" + +#ifdef XINERAMA +#include "Xinerama.hh" +#endif XINERAMA // use GNU extensions #ifndef _GNU_SOURCE@@ -134,6 +138,18 @@
menu.setInternalMenu(); menu.insert("Layer...", &tbar.layermenu()); +#ifdef XINERAMA + if (tbar.screen().hasXinerama()) { + menu.insert("On Head...", new XineramaHeadMenu<Toolbar>( + *tbar.screen().menuTheme(), + tbar.screen(), + tbar.screen().imageControl(), + *tbar.screen().layerManager().getLayer(Fluxbox::instance()->getMenuLayer()), + &tbar + )); + } + +#endif //XINERAMA // setup items in placement menu struct {@@ -1091,10 +1107,21 @@ head_y = 0,
head_w, head_h; - m_place = where; +#ifdef XINERAMA + if (screen().hasXinerama()) { + int head = screen().getToolbarOnHead(); + head_x = screen().getHeadX(head); + head_y = screen().getHeadY(head); + head_w = screen().getHeadWidth(head); + head_h = screen().getHeadHeight(head); + } else +#endif // XINERAMA + { + head_w = screen().width(); + head_h = screen().height(); + } - head_w = screen().width(); - head_h = screen().height(); + m_place = where; frame.width = head_w * screen().getToolbarWidthPercent() / 100; frame.height = m_theme.font().height();
@@ -0,0 +1,105 @@
+// Xinerama.hh for Fluxbox - helpful tools for multiple heads +// Copyright (c) 2003 Henrik Kinnunen (fluxgen at users.sourceforge.net) +// and Simon Bowden (rathnor at users.sourceforge.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// 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: Xinerama.hh,v 1.1 2003/05/19 14:26:30 rathnor Exp $ + +#ifndef XINERAMA_HH +#define XINERAMA_HH + +#include "MenuItem.hh" +#include "FbMenu.hh" +#include "FbCommands.hh" +#include "RefCount.hh" +#include "SimpleCommand.hh" + +#include "fluxbox.hh" + +// provides a generic way for giving an object a xinerama head menu +// The object must have two functions: +// int getOnHead(), and +// void setOnHead(int) + +/// this class holds the xinerama items +template <typename ItemType> +class XineramaHeadMenuItem : public FbTk::MenuItem { +public: + XineramaHeadMenuItem(const char *label, ItemType *object, int headnum, + FbTk::RefCount<FbTk::Command> &cmd): + FbTk::MenuItem(label,cmd), m_object(object), m_headnum(headnum) {} + XineramaHeadMenuItem(const char *label, ItemType *object, int headnum): + FbTk::MenuItem(label), m_object(object), m_headnum(headnum) {} + + bool isEnabled() const { return m_object->screen().getOnHead(*m_object) != m_headnum; } ; + void click(int button, int time) { + m_object->screen().setOnHead(*m_object, m_headnum); + FbTk::MenuItem::click(button, time); + } + +private: + ItemType *m_object; + int m_headnum; +}; + + +/// Create a xinerama menu +template <typename ItemType> +class XineramaHeadMenu : public FbMenu { +public: + XineramaHeadMenu(FbTk::MenuTheme &tm, BScreen &screen, FbTk::ImageControl &imgctrl, + FbTk::XLayer &layer, ItemType *item); + +private: + ItemType *m_object; +}; + + +template <typename ItemType> +XineramaHeadMenu<ItemType>::XineramaHeadMenu(FbTk::MenuTheme &tm, BScreen &screen, FbTk::ImageControl &imgctrl, + FbTk::XLayer &layer, ItemType *item): + FbMenu(tm, screen.screenNumber(), imgctrl, layer), + m_object(item) +{ + + FbTk::RefCount<FbTk::Command> saverc_cmd(new FbTk::SimpleCommand<Fluxbox>( + *Fluxbox::instance(), + &Fluxbox::save_rc)); + char tname[128]; + for (int i=1; i <= screen.numHeads(); ++i) { + // TODO: nls +/* + sprintf(tname, I18n::instance()-> + getMessage( + FBNLS::ScreenSet, + FBNLS::XineramaDefaultHeadFormat, + "Head %d"), i); //m_id starts at 0 +*/ + sprintf(tname, "Head %d", i); + insert(new XineramaHeadMenuItem<ItemType>( + tname, m_object, i, saverc_cmd)); + } + // TODO: nls + insert(new XineramaHeadMenuItem<ItemType>( + "All Heads", m_object, 0, saverc_cmd)); + update(); +} + +#endif // XINERAMA_HH