head specific strut, patch from Mathieu De Zutter

This commit is contained in:
fluxgen 2004-09-11 13:33:07 +00:00
parent ad63de0281
commit 3775776963
4 changed files with 115 additions and 78 deletions

View file

@ -22,7 +22,7 @@
// 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 "Strut.hh"
#include "CommandParser.hh"
#include "AtomHandler.hh"
#include "HeadArea.hh"
#include "FbTk/I18n.hh"
@ -226,7 +227,6 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
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 @@ BScreen::BScreen(FbTk::ResourceManager &rm,
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 @@ BScreen::~BScreen() {
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 @@ unsigned int BScreen::maxBottom(int head) const {
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 @@ FluxboxWindow *BScreen::createWindow(WinClient &client) {
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 @@ void BScreen::initXinerama() {
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 @@ void BScreen::initXinerama() {
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;
@ -2308,6 +2316,31 @@ int BScreen::getHeadHeight(int head) const {
#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
// this can be gone and a consistent interface for the two used
// on the actual objects

View file

@ -22,7 +22,7 @@
// 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 @@ public:
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 @@ public:
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
@ -363,6 +367,8 @@ private:
void renderGeomWindow();
void renderPosWindow();
const Strut* availableWorkspaceArea(int head) const;
ScreenSubject
m_clientlist_sig, ///< client signal
m_iconlist_sig, ///< notify if a window gets iconified/deiconified
@ -455,13 +461,12 @@ private:
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;
};

View file

@ -22,7 +22,7 @@
// 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 @@ void Slit::updateStrut() {
right = width();
break;
}
m_strut = screen().requestStrut(left, right, top, bottom);
m_strut = screen().requestStrut(getOnHead(), left, right, top, bottom);
screen().updateAvailableWorkspaceArea();
}

View file

@ -22,7 +22,7 @@
// 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 @@ void Toolbar::updateStrut() {
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 @@ void Toolbar::buttonPressEvent(XButtonEvent &be) {
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