old bb shitz
This commit is contained in:
parent
8f8acc2493
commit
23c11a151a
2 changed files with 0 additions and 877 deletions
778
src/workspace.cc
778
src/workspace.cc
|
@ -1,778 +0,0 @@
|
|||
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "../config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
extern "C" {
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#ifdef HAVE_STDIO_H
|
||||
# include <stdio.h>
|
||||
#endif // HAVE_STDIO_H
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif // HAVE_STRING_H
|
||||
}
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
#include "blackbox.hh"
|
||||
#include "otk/font.hh"
|
||||
#include "otk/display.hh"
|
||||
#include "bbscreen.hh"
|
||||
#include "otk/util.hh"
|
||||
#include "bbwindow.hh"
|
||||
#include "workspace.hh"
|
||||
|
||||
namespace ob {
|
||||
|
||||
Workspace::Workspace(BScreen *scrn, unsigned int i) {
|
||||
screen = scrn;
|
||||
xatom = screen->getBlackbox()->getXAtom();
|
||||
|
||||
cascade_x = cascade_y = 0;
|
||||
#ifdef XINERAMA
|
||||
cascade_region = 0;
|
||||
#endif // XINERAMA
|
||||
|
||||
id = i;
|
||||
|
||||
lastfocus = (BlackboxWindow *) 0;
|
||||
|
||||
readName();
|
||||
}
|
||||
|
||||
|
||||
void Workspace::addWindow(BlackboxWindow *w, bool place, bool sticky) {
|
||||
assert(w != 0);
|
||||
|
||||
if (place) placeWindow(w);
|
||||
|
||||
stackingList.push_front(w);
|
||||
|
||||
if (! sticky)
|
||||
w->setWorkspace(id);
|
||||
|
||||
if (! w->isNormal()) {
|
||||
if (! sticky) {
|
||||
// just give it some number, else bad things happen as it is assumed to
|
||||
// not be on a workspace
|
||||
w->setWindowNumber(0);
|
||||
}
|
||||
} else {
|
||||
if (! sticky)
|
||||
w->setWindowNumber(windowList.size());
|
||||
|
||||
windowList.push_back(w);
|
||||
|
||||
if (screen->doFocusNew() || (w->isTransient() && w->getTransientFor() &&
|
||||
w->getTransientFor()->isFocused())) {
|
||||
if (id != screen->getCurrentWorkspaceID()) {
|
||||
/*
|
||||
not on the focused workspace, so the window is not going to get focus
|
||||
but if the user wants new windows focused, then it should get focus
|
||||
when this workspace does become focused.
|
||||
*/
|
||||
lastfocus = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! w->isDesktop())
|
||||
raiseWindow(w);
|
||||
else
|
||||
lowerWindow(w);
|
||||
}
|
||||
|
||||
|
||||
void Workspace::removeWindow(BlackboxWindow *w, bool sticky) {
|
||||
assert(w != 0);
|
||||
|
||||
stackingList.remove(w);
|
||||
|
||||
// pass focus to the next appropriate window
|
||||
if ((w->isFocused() || w == lastfocus) &&
|
||||
screen->getBlackbox()->state() != Openbox::State_Exiting) {
|
||||
focusFallback(w);
|
||||
}
|
||||
|
||||
if (! w->isNormal()) return;
|
||||
|
||||
BlackboxWindowList::iterator it, end = windowList.end();
|
||||
int i;
|
||||
for (i = 0, it = windowList.begin(); it != end; ++it, ++i)
|
||||
if (*it == w)
|
||||
break;
|
||||
assert(it != end);
|
||||
|
||||
windowList.erase(it);
|
||||
if (! sticky) {
|
||||
BlackboxWindowList::iterator it = windowList.begin();
|
||||
const BlackboxWindowList::iterator end = windowList.end();
|
||||
unsigned int i = 0;
|
||||
for (; it != end; ++it, ++i)
|
||||
(*it)->setWindowNumber(i);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
cascade_x = cascade_y = 0;
|
||||
#ifdef XINERAMA
|
||||
cascade_region = 0;
|
||||
#endif // XINERAMA
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Workspace::focusFallback(const BlackboxWindow *old_window) {
|
||||
BlackboxWindow *newfocus = 0;
|
||||
|
||||
if (id == screen->getCurrentWorkspaceID()) {
|
||||
// The window is on the visible workspace.
|
||||
|
||||
// if it's a transient, then try to focus its parent
|
||||
if (old_window && old_window->isTransient()) {
|
||||
newfocus = old_window->getTransientFor();
|
||||
|
||||
if (! newfocus ||
|
||||
newfocus->isIconic() || // do not focus icons
|
||||
newfocus->getWorkspaceNumber() != id || // or other workspaces
|
||||
! newfocus->setInputFocus())
|
||||
newfocus = 0;
|
||||
}
|
||||
|
||||
if (! newfocus) {
|
||||
BlackboxWindowList::iterator it = stackingList.begin(),
|
||||
end = stackingList.end();
|
||||
for (; it != end; ++it) {
|
||||
BlackboxWindow *tmp = *it;
|
||||
if (tmp && tmp->isNormal() && tmp->setInputFocus()) {
|
||||
// we found our new focus target
|
||||
newfocus = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
screen->getBlackbox()->setFocusedWindow(newfocus);
|
||||
} else {
|
||||
// The window is not on the visible workspace.
|
||||
|
||||
if (old_window && lastfocus == old_window) {
|
||||
// The window was the last-focus target, so we need to replace it.
|
||||
BlackboxWindow *win = (BlackboxWindow*) 0;
|
||||
if (! stackingList.empty())
|
||||
win = stackingList.front();
|
||||
setLastFocusedWindow(win);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Workspace::removeAll(void) {
|
||||
while (! windowList.empty())
|
||||
windowList.front()->iconify();
|
||||
}
|
||||
|
||||
void Workspace::showAll(void) {
|
||||
BlackboxWindowList::iterator it = stackingList.begin();
|
||||
const BlackboxWindowList::iterator end = stackingList.end();
|
||||
for (; it != end; ++it) {
|
||||
BlackboxWindow *bw = *it;
|
||||
// sticky windows arent unmapped on a workspace change so we don't have ot
|
||||
// map them, but sometimes on a restart, another app can unmap our sticky
|
||||
// windows, so we map on startup always
|
||||
if (! bw->isStuck() ||
|
||||
screen->getBlackbox()->state() == Openbox::State_Starting)
|
||||
bw->show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Workspace::hideAll(void) {
|
||||
// withdraw in reverse order to minimize the number of Expose events
|
||||
|
||||
BlackboxWindowList lst(stackingList.rbegin(), stackingList.rend());
|
||||
|
||||
BlackboxWindowList::iterator it = lst.begin();
|
||||
const BlackboxWindowList::iterator end = lst.end();
|
||||
for (; it != end; ++it) {
|
||||
BlackboxWindow *bw = *it;
|
||||
// don't hide sticky windows, or they'll end up flickering on a workspace
|
||||
// change
|
||||
if (! bw->isStuck())
|
||||
bw->withdraw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* returns the number of transients for win, plus the number of transients
|
||||
* associated with each transient of win
|
||||
*/
|
||||
static unsigned int countTransients(const BlackboxWindow * const win) {
|
||||
BlackboxWindowList transients = win->getTransients();
|
||||
if (transients.empty()) return 0;
|
||||
|
||||
unsigned int ret = transients.size();
|
||||
BlackboxWindowList::const_iterator it = transients.begin(),
|
||||
end = transients.end();
|
||||
for (; it != end; ++it)
|
||||
ret += countTransients(*it);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* puts the transients of win into the stack. windows are stacked above
|
||||
* the window before it in the stackvector being iterated, meaning
|
||||
* stack[0] is on bottom, stack[1] is above stack[0], stack[2] is above
|
||||
* stack[1], etc...
|
||||
*/
|
||||
void Workspace::raiseTransients(const BlackboxWindow * const win,
|
||||
StackVector::iterator &stack) {
|
||||
if (win->getTransients().empty()) return; // nothing to do
|
||||
|
||||
// put win's transients in the stack
|
||||
BlackboxWindowList::const_iterator it, end = win->getTransients().end();
|
||||
for (it = win->getTransients().begin(); it != end; ++it) {
|
||||
BlackboxWindow *w = *it;
|
||||
*stack++ = w->getFrameWindow();
|
||||
|
||||
if (! w->isIconic()) {
|
||||
Workspace *wkspc = screen->getWorkspace(w->getWorkspaceNumber());
|
||||
wkspc->stackingList.remove(w);
|
||||
wkspc->stackingList.push_front(w);
|
||||
}
|
||||
}
|
||||
|
||||
// put transients of win's transients in the stack
|
||||
for (it = win->getTransients().begin(); it != end; ++it)
|
||||
raiseTransients(*it, stack);
|
||||
}
|
||||
|
||||
|
||||
void Workspace::lowerTransients(const BlackboxWindow * const win,
|
||||
StackVector::iterator &stack) {
|
||||
if (win->getTransients().empty()) return; // nothing to do
|
||||
|
||||
// put transients of win's transients in the stack
|
||||
BlackboxWindowList::const_reverse_iterator it,
|
||||
end = win->getTransients().rend();
|
||||
for (it = win->getTransients().rbegin(); it != end; ++it)
|
||||
lowerTransients(*it, stack);
|
||||
|
||||
// put win's transients in the stack
|
||||
for (it = win->getTransients().rbegin(); it != end; ++it) {
|
||||
BlackboxWindow *w = *it;
|
||||
*stack++ = w->getFrameWindow();
|
||||
|
||||
if (! w->isIconic()) {
|
||||
Workspace *wkspc = screen->getWorkspace(w->getWorkspaceNumber());
|
||||
wkspc->stackingList.remove(w);
|
||||
wkspc->stackingList.push_back(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Workspace::raiseWindow(BlackboxWindow *w) {
|
||||
BlackboxWindow *win = w;
|
||||
|
||||
if (win->isDesktop()) return;
|
||||
|
||||
// walk up the transient_for's to the window that is not a transient
|
||||
while (win->isTransient() && win->getTransientFor())
|
||||
win = win->getTransientFor();
|
||||
|
||||
// get the total window count (win and all transients)
|
||||
unsigned int i = 1 + countTransients(win);
|
||||
|
||||
// stack the window with all transients above
|
||||
StackVector stack_vector(i);
|
||||
StackVector::iterator stack = stack_vector.begin();
|
||||
|
||||
*(stack++) = win->getFrameWindow();
|
||||
if (! (win->isIconic() || win->isDesktop())) {
|
||||
Workspace *wkspc = screen->getWorkspace(win->getWorkspaceNumber());
|
||||
wkspc->stackingList.remove(win);
|
||||
wkspc->stackingList.push_front(win);
|
||||
}
|
||||
|
||||
raiseTransients(win, stack);
|
||||
|
||||
screen->raiseWindows(&stack_vector[0], stack_vector.size());
|
||||
}
|
||||
|
||||
|
||||
void Workspace::lowerWindow(BlackboxWindow *w) {
|
||||
BlackboxWindow *win = w;
|
||||
|
||||
// walk up the transient_for's to the window that is not a transient
|
||||
while (win->isTransient() && win->getTransientFor())
|
||||
win = win->getTransientFor();
|
||||
|
||||
// get the total window count (win and all transients)
|
||||
unsigned int i = 1 + countTransients(win);
|
||||
|
||||
// stack the window with all transients above
|
||||
StackVector stack_vector(i);
|
||||
StackVector::iterator stack = stack_vector.begin();
|
||||
|
||||
lowerTransients(win, stack);
|
||||
|
||||
*(stack++) = win->getFrameWindow();
|
||||
if (! (win->isIconic() || win->isDesktop())) {
|
||||
Workspace *wkspc = screen->getWorkspace(win->getWorkspaceNumber());
|
||||
wkspc->stackingList.remove(win);
|
||||
wkspc->stackingList.push_back(win);
|
||||
}
|
||||
|
||||
screen->lowerWindows(&stack_vector[0], stack_vector.size());
|
||||
}
|
||||
|
||||
|
||||
void Workspace::reconfigure(void) {
|
||||
std::for_each(windowList.begin(), windowList.end(),
|
||||
std::mem_fun(&BlackboxWindow::reconfigure));
|
||||
}
|
||||
|
||||
|
||||
BlackboxWindow *Workspace::getWindow(unsigned int index) {
|
||||
if (index < windowList.size()) {
|
||||
BlackboxWindowList::iterator it = windowList.begin();
|
||||
while (index-- > 0) // increment to index
|
||||
++it;
|
||||
return *it;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BlackboxWindow*
|
||||
Workspace::getNextWindowInList(BlackboxWindow *w) {
|
||||
BlackboxWindowList::iterator it = std::find(windowList.begin(),
|
||||
windowList.end(),
|
||||
w);
|
||||
assert(it != windowList.end()); // window must be in list
|
||||
++it; // next window
|
||||
if (it == windowList.end())
|
||||
return windowList.front(); // if we walked off the end, wrap around
|
||||
|
||||
return *it;
|
||||
}
|
||||
|
||||
|
||||
BlackboxWindow* Workspace::getPrevWindowInList(BlackboxWindow *w) {
|
||||
BlackboxWindowList::iterator it = std::find(windowList.begin(),
|
||||
windowList.end(),
|
||||
w);
|
||||
assert(it != windowList.end()); // window must be in list
|
||||
if (it == windowList.begin())
|
||||
return windowList.back(); // if we walked of the front, wrap around
|
||||
|
||||
return *(--it);
|
||||
}
|
||||
|
||||
|
||||
BlackboxWindow* Workspace::getTopWindowOnStack(void) const {
|
||||
assert(! stackingList.empty());
|
||||
return stackingList.front();
|
||||
}
|
||||
|
||||
|
||||
unsigned int Workspace::getCount(void) const {
|
||||
return windowList.size();
|
||||
}
|
||||
|
||||
|
||||
void Workspace::appendStackOrder(BlackboxWindowList &stack_order) const {
|
||||
BlackboxWindowList::const_reverse_iterator it = stackingList.rbegin();
|
||||
const BlackboxWindowList::const_reverse_iterator end = stackingList.rend();
|
||||
for (; it != end; ++it)
|
||||
// don't add desktop wnidows, or sticky windows more than once
|
||||
if (! ( (*it)->isDesktop() ||
|
||||
((*it)->isStuck() && id != screen->getCurrentWorkspaceID())))
|
||||
stack_order.push_back(*it);
|
||||
}
|
||||
|
||||
|
||||
bool Workspace::isCurrent(void) const {
|
||||
return (id == screen->getCurrentWorkspaceID());
|
||||
}
|
||||
|
||||
|
||||
bool Workspace::isLastWindow(const BlackboxWindow *w) const {
|
||||
return (w == windowList.back());
|
||||
}
|
||||
|
||||
|
||||
void Workspace::setCurrent(void) {
|
||||
screen->changeWorkspaceID(id);
|
||||
}
|
||||
|
||||
|
||||
void Workspace::readName(void) {
|
||||
otk::OBProperty::StringVect namesList;
|
||||
unsigned long numnames = id + 1;
|
||||
|
||||
// attempt to get from the _NET_WM_DESKTOP_NAMES property
|
||||
if (xatom->get(screen->getRootWindow(), otk::OBProperty::net_desktop_names,
|
||||
otk::OBProperty::utf8, &numnames, &namesList) &&
|
||||
namesList.size() > id) {
|
||||
name = namesList[id];
|
||||
|
||||
} else {
|
||||
/*
|
||||
Use a default name. This doesn't actually change the class. That will
|
||||
happen after the setName changes the root property, and that change
|
||||
makes its way back to this function.
|
||||
*/
|
||||
string tmp = "Workspace %d";
|
||||
assert(tmp.length() < 32);
|
||||
char default_name[32];
|
||||
sprintf(default_name, tmp.c_str(), id + 1);
|
||||
|
||||
setName(default_name); // save this into the _NET_WM_DESKTOP_NAMES property
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Workspace::setName(const string& new_name) {
|
||||
// set the _NET_WM_DESKTOP_NAMES property with the new name
|
||||
otk::OBProperty::StringVect namesList;
|
||||
unsigned long numnames = (unsigned) -1;
|
||||
if (xatom->get(screen->getRootWindow(),
|
||||
otk::OBProperty::net_desktop_names,
|
||||
otk::OBProperty::utf8, &numnames, &namesList) &&
|
||||
namesList.size() > id)
|
||||
namesList[id] = new_name;
|
||||
else
|
||||
namesList.push_back(new_name);
|
||||
|
||||
xatom->set(screen->getRootWindow(), otk::OBProperty::net_desktop_names,
|
||||
otk::OBProperty::utf8, namesList);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate free space available for window placement.
|
||||
*/
|
||||
Workspace::rectList Workspace::calcSpace(const otk::Rect &win,
|
||||
const rectList &spaces) const {
|
||||
otk::Rect isect, extra;
|
||||
rectList result;
|
||||
rectList::const_iterator siter, end = spaces.end();
|
||||
for (siter = spaces.begin(); siter != end; ++siter) {
|
||||
const otk::Rect &curr = *siter;
|
||||
|
||||
if(! win.intersects(curr)) {
|
||||
result.push_back(curr);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Use an intersection of win and curr to determine the space around
|
||||
* curr that we can use.
|
||||
*
|
||||
* NOTE: the spaces calculated can overlap.
|
||||
*/
|
||||
isect = curr & win;
|
||||
|
||||
// left
|
||||
extra.setCoords(curr.left(), curr.top(),
|
||||
isect.left() - screen->getSnapOffset(), curr.bottom());
|
||||
if (extra.valid()) result.push_back(extra);
|
||||
|
||||
// top
|
||||
extra.setCoords(curr.left(), curr.top(),
|
||||
curr.right(), isect.top() - screen->getSnapOffset());
|
||||
if (extra.valid()) result.push_back(extra);
|
||||
|
||||
// right
|
||||
extra.setCoords(isect.right() + screen->getSnapOffset(), curr.top(),
|
||||
curr.right(), curr.bottom());
|
||||
if (extra.valid()) result.push_back(extra);
|
||||
|
||||
// bottom
|
||||
extra.setCoords(curr.left(), isect.bottom() + screen->getSnapOffset(),
|
||||
curr.right(), curr.bottom());
|
||||
if (extra.valid()) result.push_back(extra);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static bool rowRLBT(const otk::Rect &first, const otk::Rect &second) {
|
||||
if (first.bottom() == second.bottom())
|
||||
return first.right() > second.right();
|
||||
return first.bottom() > second.bottom();
|
||||
}
|
||||
|
||||
static bool rowRLTB(const otk::Rect &first, const otk::Rect &second) {
|
||||
if (first.y() == second.y())
|
||||
return first.right() > second.right();
|
||||
return first.y() < second.y();
|
||||
}
|
||||
|
||||
static bool rowLRBT(const otk::Rect &first, const otk::Rect &second) {
|
||||
if (first.bottom() == second.bottom())
|
||||
return first.x() < second.x();
|
||||
return first.bottom() > second.bottom();
|
||||
}
|
||||
|
||||
static bool rowLRTB(const otk::Rect &first, const otk::Rect &second) {
|
||||
if (first.y() == second.y())
|
||||
return first.x() < second.x();
|
||||
return first.y() < second.y();
|
||||
}
|
||||
|
||||
static bool colLRTB(const otk::Rect &first, const otk::Rect &second) {
|
||||
if (first.x() == second.x())
|
||||
return first.y() < second.y();
|
||||
return first.x() < second.x();
|
||||
}
|
||||
|
||||
static bool colLRBT(const otk::Rect &first, const otk::Rect &second) {
|
||||
if (first.x() == second.x())
|
||||
return first.bottom() > second.bottom();
|
||||
return first.x() < second.x();
|
||||
}
|
||||
|
||||
static bool colRLTB(const otk::Rect &first, const otk::Rect &second) {
|
||||
if (first.right() == second.right())
|
||||
return first.y() < second.y();
|
||||
return first.right() > second.right();
|
||||
}
|
||||
|
||||
static bool colRLBT(const otk::Rect &first, const otk::Rect &second) {
|
||||
if (first.right() == second.right())
|
||||
return first.bottom() > second.bottom();
|
||||
return first.right() > second.right();
|
||||
}
|
||||
|
||||
|
||||
bool Workspace::smartPlacement(otk::Rect& win) {
|
||||
rectList spaces;
|
||||
|
||||
//initially the entire screen is free
|
||||
#ifdef XINERAMA
|
||||
if (screen->isXineramaActive() &&
|
||||
screen->getBlackbox()->doXineramaPlacement()) {
|
||||
RectList availableAreas = screen->allAvailableAreas();
|
||||
RectList::iterator it, end = availableAreas.end();
|
||||
|
||||
for (it = availableAreas.begin(); it != end; ++it) {
|
||||
Rect r = *it;
|
||||
r.setRect(r.x() + screen->getSnapOffset(),
|
||||
r.y() + screen->getSnapOffset(),
|
||||
r.width() - screen->getSnapOffset(),
|
||||
r.height() - screen->getSnapOffset());
|
||||
spaces.push_back(*it);
|
||||
}
|
||||
} else
|
||||
#endif // XINERAMA
|
||||
{
|
||||
otk::Rect r = screen->availableArea();
|
||||
r.setRect(r.x() + screen->getSnapOffset(),
|
||||
r.y() + screen->getSnapOffset(),
|
||||
r.width() - screen->getSnapOffset(),
|
||||
r.height() - screen->getSnapOffset());
|
||||
spaces.push_back(r);
|
||||
}
|
||||
|
||||
//Find Free Spaces
|
||||
BlackboxWindowList::const_iterator wit = windowList.begin(),
|
||||
end = windowList.end();
|
||||
otk::Rect tmp;
|
||||
for (; wit != end; ++wit) {
|
||||
const BlackboxWindow* const curr = *wit;
|
||||
|
||||
// watch for shaded windows and full-maxed windows
|
||||
if (curr->isShaded()) {
|
||||
if (screen->getPlaceIgnoreShaded()) continue;
|
||||
} else if (curr->isMaximizedFull()) {
|
||||
if (screen->getPlaceIgnoreMaximized()) continue;
|
||||
}
|
||||
|
||||
tmp.setRect(curr->frameRect().x(), curr->frameRect().y(),
|
||||
curr->frameRect().width() + screen->getWindowStyle()->getBorderWidth(),
|
||||
curr->frameRect().height() + screen->getWindowStyle()->getBorderWidth());
|
||||
|
||||
spaces = calcSpace(tmp, spaces);
|
||||
}
|
||||
|
||||
if (screen->getPlacementPolicy() == BScreen::RowSmartPlacement) {
|
||||
if(screen->getRowPlacementDirection() == BScreen::LeftRight) {
|
||||
if(screen->getColPlacementDirection() == BScreen::TopBottom)
|
||||
std::sort(spaces.begin(), spaces.end(), rowLRTB);
|
||||
else
|
||||
std::sort(spaces.begin(), spaces.end(), rowLRBT);
|
||||
} else {
|
||||
if(screen->getColPlacementDirection() == BScreen::TopBottom)
|
||||
std::sort(spaces.begin(), spaces.end(), rowRLTB);
|
||||
else
|
||||
std::sort(spaces.begin(), spaces.end(), rowRLBT);
|
||||
}
|
||||
} else {
|
||||
if(screen->getColPlacementDirection() == BScreen::TopBottom) {
|
||||
if(screen->getRowPlacementDirection() == BScreen::LeftRight)
|
||||
std::sort(spaces.begin(), spaces.end(), colLRTB);
|
||||
else
|
||||
std::sort(spaces.begin(), spaces.end(), colRLTB);
|
||||
} else {
|
||||
if(screen->getRowPlacementDirection() == BScreen::LeftRight)
|
||||
std::sort(spaces.begin(), spaces.end(), colLRBT);
|
||||
else
|
||||
std::sort(spaces.begin(), spaces.end(), colRLBT);
|
||||
}
|
||||
}
|
||||
|
||||
rectList::const_iterator sit = spaces.begin(), spaces_end = spaces.end();
|
||||
for(; sit != spaces_end; ++sit) {
|
||||
if (sit->width() >= win.width() && sit->height() >= win.height())
|
||||
break;
|
||||
}
|
||||
|
||||
if (sit == spaces_end)
|
||||
return False;
|
||||
|
||||
//set new position based on the empty space found
|
||||
const otk::Rect& where = *sit;
|
||||
win.setX(where.x());
|
||||
win.setY(where.y());
|
||||
|
||||
// adjust the location() based on left/right and top/bottom placement
|
||||
if (screen->getPlacementPolicy() == BScreen::RowSmartPlacement) {
|
||||
if (screen->getRowPlacementDirection() == BScreen::RightLeft)
|
||||
win.setX(where.right() - win.width());
|
||||
if (screen->getColPlacementDirection() == BScreen::BottomTop)
|
||||
win.setY(where.bottom() - win.height());
|
||||
} else {
|
||||
if (screen->getColPlacementDirection() == BScreen::BottomTop)
|
||||
win.setY(win.y() + where.height() - win.height());
|
||||
if (screen->getRowPlacementDirection() == BScreen::RightLeft)
|
||||
win.setX(win.x() + where.width() - win.width());
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
bool Workspace::underMousePlacement(otk::Rect &win) {
|
||||
int x, y, rx, ry;
|
||||
Window c, r;
|
||||
unsigned int m;
|
||||
XQueryPointer(otk::OBDisplay::display, screen->getRootWindow(),
|
||||
&r, &c, &rx, &ry, &x, &y, &m);
|
||||
|
||||
otk::Rect area;
|
||||
#ifdef XINERAMA
|
||||
if (screen->isXineramaActive() &&
|
||||
screen->getBlackbox()->doXineramaPlacement()) {
|
||||
RectList availableAreas = screen->allAvailableAreas();
|
||||
RectList::iterator it, end = availableAreas.end();
|
||||
|
||||
for (it = availableAreas.begin(); it != end; ++it)
|
||||
if (it->contains(rx, ry)) break;
|
||||
assert(it != end); // the mouse isn't inside an area?
|
||||
area = *it;
|
||||
} else
|
||||
#endif // XINERAMA
|
||||
area = screen->availableArea();
|
||||
|
||||
x = rx - win.width() / 2;
|
||||
y = ry - win.height() / 2;
|
||||
|
||||
if (x < area.x())
|
||||
x = area.x();
|
||||
if (y < area.y())
|
||||
y = area.y();
|
||||
if (x + win.width() > area.x() + area.width())
|
||||
x = area.x() + area.width() - win.width();
|
||||
if (y + win.height() > area.y() + area.height())
|
||||
y = area.y() + area.height() - win.height();
|
||||
|
||||
win.setX(x);
|
||||
win.setY(y);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
bool Workspace::cascadePlacement(otk::Rect &win, const int offset) {
|
||||
otk::Rect area;
|
||||
|
||||
#ifdef XINERAMA
|
||||
if (screen->isXineramaActive() &&
|
||||
screen->getBlackbox()->doXineramaPlacement()) {
|
||||
area = screen->allAvailableAreas()[cascade_region];
|
||||
} else
|
||||
#endif // XINERAMA
|
||||
area = screen->availableArea();
|
||||
|
||||
if ((static_cast<signed>(cascade_x + win.width()) > area.right() + 1) ||
|
||||
(static_cast<signed>(cascade_y + win.height()) > area.bottom() + 1)) {
|
||||
cascade_x = cascade_y = 0;
|
||||
#ifdef XINERAMA
|
||||
if (screen->isXineramaActive() &&
|
||||
screen->getBlackbox()->doXineramaPlacement()) {
|
||||
// go to the next xinerama region, and use its area
|
||||
if (++cascade_region >= screen->allAvailableAreas().size())
|
||||
cascade_region = 0;
|
||||
area = screen->allAvailableAreas()[cascade_region];
|
||||
}
|
||||
#endif // XINERAMA
|
||||
}
|
||||
|
||||
if (cascade_x == 0) {
|
||||
cascade_x = area.x() + offset;
|
||||
cascade_y = area.y() + offset;
|
||||
}
|
||||
|
||||
win.setPos(cascade_x, cascade_y);
|
||||
|
||||
cascade_x += offset;
|
||||
cascade_y += offset;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
void Workspace::placeWindow(BlackboxWindow *win) {
|
||||
otk::Rect new_win(0, 0, win->frameRect().width(), win->frameRect().height());
|
||||
bool placed = False;
|
||||
|
||||
switch (screen->getPlacementPolicy()) {
|
||||
case BScreen::RowSmartPlacement:
|
||||
case BScreen::ColSmartPlacement:
|
||||
placed = smartPlacement(new_win);
|
||||
break;
|
||||
case BScreen::UnderMousePlacement:
|
||||
case BScreen::ClickMousePlacement:
|
||||
placed = underMousePlacement(new_win);
|
||||
default:
|
||||
break; // handled below
|
||||
} // switch
|
||||
|
||||
if (placed == False)
|
||||
cascadePlacement(new_win, (win->getTitleHeight() +
|
||||
screen->getWindowStyle()->getBorderWidth() * 2));
|
||||
|
||||
if (new_win.right() > screen->availableArea().right())
|
||||
new_win.setX(screen->availableArea().left());
|
||||
if (new_win.bottom() > screen->availableArea().bottom())
|
||||
new_win.setY(screen->availableArea().top());
|
||||
|
||||
win->configure(new_win.x(), new_win.y(), new_win.width(), new_win.height());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
||||
#ifndef __Workspace_hh
|
||||
#define __Workspace_hh
|
||||
|
||||
extern "C" {
|
||||
#include <X11/Xlib.h>
|
||||
}
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "otk/property.hh"
|
||||
|
||||
namespace ob {
|
||||
|
||||
class BScreen;
|
||||
class Workspace;
|
||||
class BlackboxWindow;
|
||||
|
||||
typedef std::list<BlackboxWindow*> BlackboxWindowList;
|
||||
typedef std::vector<Window> StackVector;
|
||||
|
||||
class Workspace {
|
||||
private:
|
||||
BScreen *screen;
|
||||
BlackboxWindow *lastfocus;
|
||||
otk::OBProperty *xatom;
|
||||
|
||||
BlackboxWindowList stackingList, windowList;
|
||||
|
||||
std::string name;
|
||||
unsigned int id;
|
||||
unsigned int cascade_x, cascade_y;
|
||||
#ifdef XINERAMA
|
||||
unsigned int cascade_region;
|
||||
#endif // XINERAMA
|
||||
|
||||
Workspace(const Workspace&);
|
||||
Workspace& operator=(const Workspace&);
|
||||
|
||||
void raiseTransients(const BlackboxWindow * const win,
|
||||
StackVector::iterator &stack);
|
||||
void lowerTransients(const BlackboxWindow * const win,
|
||||
StackVector::iterator &stack);
|
||||
|
||||
typedef std::vector<otk::Rect> rectList;
|
||||
rectList calcSpace(const otk::Rect &win, const rectList &spaces) const;
|
||||
|
||||
void placeWindow(BlackboxWindow *win);
|
||||
bool cascadePlacement(otk::Rect& win, const int offset);
|
||||
bool smartPlacement(otk::Rect& win);
|
||||
bool underMousePlacement(otk::Rect& win);
|
||||
|
||||
public:
|
||||
Workspace(BScreen *scrn, unsigned int i = 0);
|
||||
|
||||
inline BScreen *getScreen(void) { return screen; }
|
||||
|
||||
inline BlackboxWindow *getLastFocusedWindow(void) { return lastfocus; }
|
||||
|
||||
inline const std::string& getName(void) const { return name; }
|
||||
|
||||
inline unsigned int getID(void) const { return id; }
|
||||
|
||||
inline void setLastFocusedWindow(BlackboxWindow *w) { lastfocus = w; }
|
||||
|
||||
inline const BlackboxWindowList& getStackingList() const
|
||||
{ return stackingList; }
|
||||
|
||||
BlackboxWindow* getWindow(unsigned int index);
|
||||
BlackboxWindow* getNextWindowInList(BlackboxWindow *w);
|
||||
BlackboxWindow* getPrevWindowInList(BlackboxWindow *w);
|
||||
BlackboxWindow* getTopWindowOnStack(void) const;
|
||||
void focusFallback(const BlackboxWindow *old_window);
|
||||
|
||||
bool isCurrent(void) const;
|
||||
bool isLastWindow(const BlackboxWindow* w) const;
|
||||
|
||||
void addWindow(BlackboxWindow *w, bool place = False, bool sticky = False);
|
||||
void removeWindow(BlackboxWindow *w, bool sticky = False);
|
||||
unsigned int getCount(void) const;
|
||||
void appendStackOrder(BlackboxWindowList &stack_order) const;
|
||||
|
||||
void showAll(void);
|
||||
void hideAll(void);
|
||||
void removeAll(void);
|
||||
void raiseWindow(BlackboxWindow *w);
|
||||
void lowerWindow(BlackboxWindow *w);
|
||||
void reconfigure(void);
|
||||
void setCurrent(void);
|
||||
void readName();
|
||||
void setName(const std::string& new_name);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __Workspace_hh
|
||||
|
Loading…
Reference in a new issue