X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2FWorkspace.cc;h=5c38cf05b9ecf47b8ebb6e15c5dc20abbb9f9692;hb=fb613db29ffcf1539c91f0ac0ca5d25cb4e593b5;hp=3ef99ea749d054ac3e1016b17e9808af9517dd0e;hpb=8794d357e67abddf9fda9db77b235e294d0ec590;p=chaz%2Fopenbox diff --git a/src/Workspace.cc b/src/Workspace.cc index 3ef99ea7..5c38cf05 100644 --- a/src/Workspace.cc +++ b/src/Workspace.cc @@ -38,6 +38,8 @@ extern "C" { #endif // HAVE_STRING_H } +#include + #include #include @@ -53,10 +55,12 @@ using std::string; #include "Window.hh" #include "Workspace.hh" #include "Windowmenu.hh" +#include "XAtom.hh" Workspace::Workspace(BScreen *scrn, unsigned int i) { screen = scrn; + xatom = screen->getBlackbox()->getXAtom(); cascade_x = cascade_y = 32; @@ -66,7 +70,7 @@ Workspace::Workspace(BScreen *scrn, unsigned int i) { lastfocus = (BlackboxWindow *) 0; - setName(screen->getNameOfWorkspace(id)); + readName(); } @@ -95,19 +99,20 @@ unsigned int Workspace::removeWindow(BlackboxWindow *w) { stackingList.remove(w); - if (w->isFocused() && ! screen->getBlackbox()->doShutdown()) { - BlackboxWindow *newfocus = 0; - if (w->isTransient()) - newfocus = w->getTransientFor(); - if (! newfocus && ! stackingList.empty()) - newfocus = stackingList.front(); - if (! newfocus || ! newfocus->setInputFocus()) - screen->getBlackbox()->setFocusedWindow(0); + // pass focus to the next appropriate window + if ((w->isFocused() || w == lastfocus) && + ! screen->getBlackbox()->doShutdown()) { + focusFallback(w); + + // if the window is sticky, then it needs to be removed on all other + // workspaces too! + if (w->isStuck()) { + for (unsigned int i = 0; i < screen->getWorkspaceCount(); ++i) + if (i != id) + screen->getWorkspace(i)->focusFallback(w); + } } - if (lastfocus == w) - lastfocus = (BlackboxWindow *) 0; - windowList.remove(w); clientmenu->remove(w->getWindowNumber()); clientmenu->update(); @@ -127,6 +132,54 @@ unsigned int Workspace::removeWindow(BlackboxWindow *w) { } +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->windowType() == BlackboxWindow::Type_Dialog || + tmp->windowType() == BlackboxWindow::Type_Normal)) + continue; // don't fallback to special windows + if (tmp && 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::showAll(void) { std::for_each(stackingList.begin(), stackingList.end(), std::mem_fun(&BlackboxWindow::show)); @@ -222,7 +275,6 @@ void Workspace::lowerTransients(const BlackboxWindow * const win, wkspc->stackingList.push_back((*it)); } } - } @@ -282,9 +334,7 @@ void Workspace::lowerWindow(BlackboxWindow *w) { wkspc->stackingList.push_back(win); } - XLowerWindow(screen->getBaseDisplay()->getXDisplay(), stack_vector.front()); - XRestackWindows(screen->getBaseDisplay()->getXDisplay(), - &stack_vector[0], stack_vector.size()); + screen->lowerWindows(&stack_vector[0], stack_vector.size()); } @@ -295,12 +345,6 @@ void Workspace::reconfigure(void) { } -void Workspace::updateFocusModel(void) { - std::for_each(windowList.begin(), windowList.end(), - std::mem_fun(&BlackboxWindow::updateFocusModel)); -} - - BlackboxWindow *Workspace::getWindow(unsigned int index) { if (index < windowList.size()) { BlackboxWindowList::iterator it = windowList.begin(); @@ -355,6 +399,14 @@ unsigned int Workspace::getCount(void) const { } +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) + stack_order.push_back(*it); +} + + bool Workspace::isCurrent(void) const { return (id == screen->getCurrentWorkspaceID()); } @@ -364,24 +416,54 @@ bool Workspace::isLastWindow(const BlackboxWindow* const w) const { return (w == windowList.back()); } + void Workspace::setCurrent(void) { screen->changeWorkspaceID(id); } -void Workspace::setName(const string& new_name) { - if (! new_name.empty()) { - name = new_name; +void Workspace::readName(void) { + XAtom::StringVect namesList; + unsigned long numnames = id + 1; + + // attempt to get from the _NET_WM_DESKTOP_NAMES property + if (xatom->getValue(screen->getRootWindow(), XAtom::net_desktop_names, + XAtom::utf8, numnames, namesList) && + namesList.size() > id) { + name = namesList[id]; + + clientmenu->setLabel(name); + clientmenu->update(); } else { - string tmp =i18n(WorkspaceSet, WorkspaceDefaultNameFormat, "Workspace %d"); + /* + 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 =i18n(WorkspaceSet, WorkspaceDefaultNameFormat, + "Workspace %d"); assert(tmp.length() < 32); char default_name[32]; sprintf(default_name, tmp.c_str(), id + 1); - name = default_name; + + setName(default_name); // save this into the _NET_WM_DESKTOP_NAMES property } +} - clientmenu->setLabel(name); - clientmenu->update(); + +void Workspace::setName(const string& new_name) { + // set the _NET_WM_DESKTOP_NAMES property with the new name + XAtom::StringVect namesList; + unsigned long numnames = (unsigned) -1; + if (xatom->getValue(screen->getRootWindow(), XAtom::net_desktop_names, + XAtom::utf8, numnames, namesList) && + namesList.size() > id) + namesList[id] = new_name; + else + namesList.push_back(new_name); + + xatom->setValue(screen->getRootWindow(), XAtom::net_desktop_names, + XAtom::utf8, namesList); } @@ -487,11 +569,15 @@ bool Workspace::smartPlacement(Rect& win, const Rect& availableArea) { spaces.push_back(availableArea); //initially the entire screen is free //Find Free Spaces - BlackboxWindowList::iterator wit = windowList.begin(), - end = windowList.end(); + BlackboxWindowList::const_iterator wit = windowList.begin(), + end = windowList.end(); Rect tmp; for (; wit != end; ++wit) { const BlackboxWindow* const curr = *wit; + + if (curr->isShaded() && screen->getPlaceIgnoreShaded()) continue; + if (curr->isMaximizedFull() && screen->getPlaceIgnoreMaximized()) continue; + tmp.setRect(curr->frameRect().x(), curr->frameRect().y(), curr->frameRect().width() + screen->getBorderWidth(), curr->frameRect().height() + screen->getBorderWidth()); @@ -502,26 +588,26 @@ bool Workspace::smartPlacement(Rect& win, const Rect& availableArea) { if (screen->getPlacementPolicy() == BScreen::RowSmartPlacement) { if(screen->getRowPlacementDirection() == BScreen::LeftRight) { if(screen->getColPlacementDirection() == BScreen::TopBottom) - sort(spaces.begin(), spaces.end(), rowLRTB); + std::sort(spaces.begin(), spaces.end(), rowLRTB); else - sort(spaces.begin(), spaces.end(), rowLRBT); + std::sort(spaces.begin(), spaces.end(), rowLRBT); } else { if(screen->getColPlacementDirection() == BScreen::TopBottom) - sort(spaces.begin(), spaces.end(), rowRLTB); + std::sort(spaces.begin(), spaces.end(), rowRLTB); else - sort(spaces.begin(), spaces.end(), rowRLBT); + std::sort(spaces.begin(), spaces.end(), rowRLBT); } } else { if(screen->getColPlacementDirection() == BScreen::TopBottom) { if(screen->getRowPlacementDirection() == BScreen::LeftRight) - sort(spaces.begin(), spaces.end(), colLRTB); + std::sort(spaces.begin(), spaces.end(), colLRTB); else - sort(spaces.begin(), spaces.end(), colRLTB); + std::sort(spaces.begin(), spaces.end(), colRLTB); } else { if(screen->getRowPlacementDirection() == BScreen::LeftRight) - sort(spaces.begin(), spaces.end(), colLRBT); + std::sort(spaces.begin(), spaces.end(), colLRBT); else - sort(spaces.begin(), spaces.end(), colRLBT); + std::sort(spaces.begin(), spaces.end(), colRLBT); } } @@ -555,6 +641,31 @@ bool Workspace::smartPlacement(Rect& win, const Rect& availableArea) { } +bool Workspace::underMousePlacement(Rect &win, const Rect &availableArea) { + int x, y, rx, ry; + Window c, r; + unsigned int m; + XQueryPointer(screen->getBlackbox()->getXDisplay(), screen->getRootWindow(), + &r, &c, &rx, &ry, &x, &y, &m); + x = rx - win.width() / 2; + y = ry - win.height() / 2; + + if (x < availableArea.x()) + x = availableArea.x(); + if (y < availableArea.y()) + y = availableArea.y(); + if (x + win.width() > availableArea.x() + availableArea.width()) + x = availableArea.x() + availableArea.width() - win.width(); + if (y + win.height() > availableArea.y() + availableArea.height()) + y = availableArea.y() + availableArea.height() - win.height(); + + win.setX(x); + win.setY(y); + + return True; +} + + bool Workspace::cascadePlacement(Rect &win, const Rect &availableArea) { if ((cascade_x > static_cast(availableArea.width() / 2)) || (cascade_y > static_cast(availableArea.height() / 2))) @@ -582,6 +693,8 @@ void Workspace::placeWindow(BlackboxWindow *win) { case BScreen::ColSmartPlacement: placed = smartPlacement(new_win, availableArea); break; + case BScreen::UnderMousePlacement: + placed = underMousePlacement(new_win, availableArea); default: break; // handled below } // switch