2003-01-16 12:41:27 +00:00
|
|
|
// XLayer.cc for FbTk - fluxbox toolkit
|
2006-02-16 06:53:05 +00:00
|
|
|
// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
|
2003-01-16 12:41:27 +00:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
#include "XLayer.hh"
|
|
|
|
#include "XLayerItem.hh"
|
|
|
|
#include "App.hh"
|
2007-12-30 06:44:11 +00:00
|
|
|
#include "FbWindow.hh"
|
|
|
|
#include "MultLayers.hh"
|
2003-01-16 12:41:27 +00:00
|
|
|
|
|
|
|
#include <iostream>
|
2006-10-27 06:57:43 +00:00
|
|
|
|
|
|
|
using std::find;
|
2003-01-16 12:41:27 +00:00
|
|
|
using namespace FbTk;
|
|
|
|
|
2006-10-27 06:57:43 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
using std::cerr;
|
|
|
|
using std::endl;
|
|
|
|
#endif // DEBUG
|
|
|
|
|
2003-01-16 12:41:27 +00:00
|
|
|
XLayer::XLayer(MultLayers &manager, int layernum):
|
2008-10-01 08:38:56 +00:00
|
|
|
m_manager(manager), m_layernum(layernum), m_needs_restack(false) {
|
2003-01-16 12:41:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
XLayer::~XLayer() {
|
2003-02-03 13:45:23 +00:00
|
|
|
|
2003-01-16 12:41:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void XLayer::restack() {
|
2003-07-20 18:05:40 +00:00
|
|
|
if (!m_manager.isUpdatable())
|
|
|
|
return;
|
|
|
|
|
2003-02-03 13:45:23 +00:00
|
|
|
int num_windows = countWindows();
|
2003-01-29 21:42:53 +00:00
|
|
|
|
|
|
|
// each LayerItem can contain several windows
|
2003-02-02 16:32:41 +00:00
|
|
|
iterator it = itemList().begin();
|
|
|
|
iterator it_end = itemList().end();
|
2003-02-03 13:45:23 +00:00
|
|
|
Window *winlist = new Window[num_windows];
|
2003-01-29 21:42:53 +00:00
|
|
|
size_t j=0;
|
2006-10-27 06:57:43 +00:00
|
|
|
|
2003-02-09 14:11:14 +00:00
|
|
|
// add all the windows from each item
|
2004-09-10 04:03:58 +00:00
|
|
|
for (; it != it_end; ++it) {
|
2003-02-09 14:11:14 +00:00
|
|
|
XLayerItem::Windows::const_iterator wit = (*it)->getWindows().begin();
|
|
|
|
XLayerItem::Windows::const_iterator wit_end = (*it)->getWindows().end();
|
2003-02-18 15:08:12 +00:00
|
|
|
for (; wit != wit_end; ++wit) {
|
|
|
|
if ((*wit)->window())
|
|
|
|
winlist[j++] = (*wit)->window();
|
2003-02-09 14:11:14 +00:00
|
|
|
}
|
2003-01-16 12:41:27 +00:00
|
|
|
}
|
|
|
|
|
2003-02-18 15:08:12 +00:00
|
|
|
XRestackWindows(FbTk::App::instance()->display(), winlist, j);
|
2003-01-16 12:41:27 +00:00
|
|
|
|
|
|
|
delete [] winlist;
|
2003-02-09 14:11:14 +00:00
|
|
|
|
2008-10-01 08:38:56 +00:00
|
|
|
m_needs_restack = false;
|
2003-01-16 12:41:27 +00:00
|
|
|
}
|
|
|
|
|
2008-10-01 09:29:59 +00:00
|
|
|
void XLayer::restackAndTempRaise(XLayerItem &item) {
|
|
|
|
int num_windows = countWindows();
|
|
|
|
|
|
|
|
// each LayerItem can contain several windows
|
|
|
|
iterator it = itemList().begin();
|
|
|
|
iterator it_end = itemList().end();
|
|
|
|
Window *winlist = new Window[num_windows];
|
|
|
|
size_t j=0;
|
|
|
|
|
|
|
|
// add windows that go on top
|
|
|
|
XLayerItem::Windows::const_iterator wit = item.getWindows().begin();
|
|
|
|
XLayerItem::Windows::const_iterator wit_end = item.getWindows().end();
|
|
|
|
for (; wit != wit_end; ++wit) {
|
|
|
|
if ((*wit)->window())
|
|
|
|
winlist[j++] = (*wit)->window();
|
|
|
|
}
|
|
|
|
|
|
|
|
// add all the windows from each other item
|
|
|
|
for (; it != it_end; ++it) {
|
|
|
|
if (*it == &item)
|
|
|
|
continue;
|
|
|
|
wit = (*it)->getWindows().begin();
|
|
|
|
wit_end = (*it)->getWindows().end();
|
|
|
|
for (; wit != wit_end; ++wit) {
|
|
|
|
if ((*wit)->window())
|
|
|
|
winlist[j++] = (*wit)->window();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XRestackWindows(FbTk::App::instance()->display(), winlist, j);
|
|
|
|
|
|
|
|
delete [] winlist;
|
|
|
|
}
|
|
|
|
|
2003-02-02 16:32:41 +00:00
|
|
|
int XLayer::countWindows() {
|
2003-02-03 13:45:23 +00:00
|
|
|
int num_windows = 0;
|
2003-02-02 16:32:41 +00:00
|
|
|
iterator it = itemList().begin();
|
|
|
|
iterator it_end = itemList().end();
|
2004-09-10 04:03:58 +00:00
|
|
|
for (; it != it_end; ++it) {
|
2003-02-09 14:11:14 +00:00
|
|
|
num_windows += (*it)->numWindows();
|
2003-02-02 16:32:41 +00:00
|
|
|
}
|
2003-02-03 13:45:23 +00:00
|
|
|
return num_windows;
|
2003-02-02 16:32:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-09 14:11:14 +00:00
|
|
|
// Stack all windows associated with 'item' below the 'above' item
|
2008-10-01 09:29:59 +00:00
|
|
|
void XLayer::stackBelowItem(XLayerItem &item, XLayerItem *above) {
|
2003-07-20 18:05:40 +00:00
|
|
|
if (!m_manager.isUpdatable())
|
|
|
|
return;
|
2003-02-03 13:45:23 +00:00
|
|
|
|
2006-10-27 06:57:43 +00:00
|
|
|
// if there are no windows provided for above us,
|
2007-01-25 18:09:11 +00:00
|
|
|
// then we must restack the entire layer
|
|
|
|
// we can't do XRaiseWindow because a restack then causes OverrideRedirect
|
|
|
|
// windows to get pushed to the bottom
|
2008-10-01 09:29:59 +00:00
|
|
|
if (!above || m_needs_restack) { // must need to go right to top
|
2007-01-25 18:09:11 +00:00
|
|
|
restack();
|
|
|
|
return;
|
2003-01-16 12:41:27 +00:00
|
|
|
}
|
|
|
|
|
2007-01-25 18:09:11 +00:00
|
|
|
Window *winlist;
|
2008-10-01 09:29:59 +00:00
|
|
|
size_t winnum = 1, size = item.numWindows()+1;
|
2007-01-25 18:09:11 +00:00
|
|
|
|
|
|
|
// We do have a window to stack below
|
|
|
|
// so we put it on top, and fill the rest of the array with the ones to go below it.
|
|
|
|
winlist = new Window[size];
|
|
|
|
// assume that above's window exists
|
|
|
|
winlist[0] = above->getWindows().back()->window();
|
|
|
|
|
2003-02-09 14:11:14 +00:00
|
|
|
// fill the rest of the array
|
2008-10-01 09:29:59 +00:00
|
|
|
XLayerItem::Windows::iterator it = item.getWindows().begin();
|
|
|
|
XLayerItem::Windows::iterator it_end = item.getWindows().end();
|
2003-02-18 15:08:12 +00:00
|
|
|
for (; it != it_end; ++it) {
|
2006-10-27 06:57:43 +00:00
|
|
|
if ((*it)->window())
|
2003-02-18 15:08:12 +00:00
|
|
|
winlist[winnum++] = (*it)->window();
|
2003-01-29 21:42:53 +00:00
|
|
|
}
|
2003-02-02 16:32:41 +00:00
|
|
|
|
2003-02-09 14:11:14 +00:00
|
|
|
// stack the windows
|
2003-02-18 15:08:12 +00:00
|
|
|
XRestackWindows(FbTk::App::instance()->display(), winlist, winnum);
|
2003-01-16 12:41:27 +00:00
|
|
|
|
|
|
|
delete [] winlist;
|
2006-10-27 06:57:43 +00:00
|
|
|
|
2003-01-16 12:41:27 +00:00
|
|
|
}
|
|
|
|
|
2006-03-23 02:06:51 +00:00
|
|
|
// We can't just use Restack here, because it won't do anything if they're
|
|
|
|
// already in the same relative order excluding other windows
|
2006-03-20 11:31:24 +00:00
|
|
|
void XLayer::alignItem(XLayerItem &item) {
|
2006-03-23 02:06:51 +00:00
|
|
|
if (itemList().front() == &item) {
|
2008-10-01 09:29:59 +00:00
|
|
|
stackBelowItem(item, m_manager.getLowestItemAboveLayer(m_layernum));
|
2006-03-23 02:06:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-10-27 06:57:43 +00:00
|
|
|
// Note: some other things effectively assume that the window list is
|
2006-03-20 11:31:24 +00:00
|
|
|
// sorted from highest to lowest
|
2006-03-23 02:06:51 +00:00
|
|
|
// get our item
|
2006-10-27 06:57:43 +00:00
|
|
|
iterator myit = find(itemList().begin(), itemList().end(), &item);
|
2006-03-23 02:06:51 +00:00
|
|
|
iterator it = myit;
|
2006-03-20 11:31:24 +00:00
|
|
|
|
2006-03-23 02:06:51 +00:00
|
|
|
// go to the one above it in our layer (top is front, so we decrement)
|
|
|
|
--it;
|
|
|
|
|
|
|
|
// keep going until we find one that is currently visible to the user
|
2006-10-27 06:57:43 +00:00
|
|
|
while (it != itemList().begin() && !(*it)->visible())
|
2006-03-23 02:06:51 +00:00
|
|
|
--it;
|
|
|
|
|
|
|
|
if (it == itemList().begin() && !(*it)->visible())
|
|
|
|
// reached front item, but it wasn't visible, therefore it was already raised
|
2008-10-01 09:29:59 +00:00
|
|
|
stackBelowItem(item, m_manager.getLowestItemAboveLayer(m_layernum));
|
2006-03-23 02:06:51 +00:00
|
|
|
else
|
2008-10-01 09:29:59 +00:00
|
|
|
stackBelowItem(item, *it);
|
2006-03-20 11:31:24 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2003-01-16 12:41:27 +00:00
|
|
|
XLayer::iterator XLayer::insert(XLayerItem &item, unsigned int pos) {
|
|
|
|
#ifdef DEBUG
|
2003-02-09 14:11:14 +00:00
|
|
|
// at this point we don't support insertions into a layer other than at the top
|
|
|
|
if (pos != 0)
|
2003-01-16 12:41:27 +00:00
|
|
|
cerr<<__FILE__<<"("<<__LINE__<<"): Insert using non-zero position not valid in XLayer"<<endl;
|
|
|
|
#endif // DEBUG
|
2006-10-27 06:57:43 +00:00
|
|
|
|
2003-01-16 12:41:27 +00:00
|
|
|
itemList().push_front(&item);
|
|
|
|
// restack below next window up
|
2008-10-01 09:29:59 +00:00
|
|
|
stackBelowItem(item, m_manager.getLowestItemAboveLayer(m_layernum));
|
2003-01-16 12:41:27 +00:00
|
|
|
return itemList().begin();
|
|
|
|
}
|
|
|
|
|
2003-02-09 14:11:14 +00:00
|
|
|
void XLayer::remove(XLayerItem &item) {
|
2003-02-03 13:45:23 +00:00
|
|
|
iterator it = itemList().begin();
|
|
|
|
iterator it_end = itemList().end();
|
|
|
|
for (; it != it_end; ++it) {
|
2003-02-09 14:11:14 +00:00
|
|
|
if (*it == &item) {
|
2003-02-03 13:45:23 +00:00
|
|
|
itemList().erase(it);
|
2003-02-09 14:11:14 +00:00
|
|
|
break;
|
|
|
|
}
|
2003-02-03 13:45:23 +00:00
|
|
|
}
|
2003-01-16 12:41:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void XLayer::raise(XLayerItem &item) {
|
|
|
|
// assume it is already in this layer
|
|
|
|
|
2008-10-01 08:38:56 +00:00
|
|
|
if (&item == itemList().front()) {
|
|
|
|
if (m_needs_restack)
|
|
|
|
restack();
|
2003-01-16 12:41:27 +00:00
|
|
|
return; // nothing to do
|
2008-10-01 08:38:56 +00:00
|
|
|
}
|
2003-01-16 12:41:27 +00:00
|
|
|
|
2006-10-27 06:57:43 +00:00
|
|
|
iterator it = find(itemList().begin(), itemList().end(), &item);
|
2003-02-09 14:11:14 +00:00
|
|
|
if (it != itemList().end())
|
|
|
|
itemList().erase(it);
|
|
|
|
else {
|
2003-04-15 23:20:31 +00:00
|
|
|
#ifdef DEBUG
|
2003-02-09 14:11:14 +00:00
|
|
|
cerr<<__FILE__<<"("<<__LINE__<<"): WARNING: raise on item not in layer["<<m_layernum<<"]"<<endl;
|
2003-04-15 23:20:31 +00:00
|
|
|
#endif // DEBUG
|
2003-02-09 14:11:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-01-16 12:41:27 +00:00
|
|
|
itemList().push_front(&item);
|
2008-10-01 09:29:59 +00:00
|
|
|
stackBelowItem(item, m_manager.getLowestItemAboveLayer(m_layernum));
|
2006-10-27 06:57:43 +00:00
|
|
|
|
2003-01-16 12:41:27 +00:00
|
|
|
}
|
|
|
|
|
2003-04-15 23:09:26 +00:00
|
|
|
void XLayer::tempRaise(XLayerItem &item) {
|
|
|
|
// assume it is already in this layer
|
|
|
|
|
2008-10-01 08:38:56 +00:00
|
|
|
if (!m_needs_restack && &item == itemList().front())
|
2003-04-15 23:09:26 +00:00
|
|
|
return; // nothing to do
|
|
|
|
|
2006-10-27 06:57:43 +00:00
|
|
|
iterator it = find(itemList().begin(), itemList().end(), &item);
|
2003-04-15 23:20:31 +00:00
|
|
|
if (it == itemList().end()) {
|
2003-04-15 23:09:26 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
cerr<<__FILE__<<"("<<__LINE__<<"): WARNING: raise on item not in layer["<<m_layernum<<"]"<<endl;
|
2003-04-15 23:20:31 +00:00
|
|
|
#endif // DEBUG
|
2003-04-15 23:09:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-10-01 09:29:59 +00:00
|
|
|
if (m_needs_restack)
|
|
|
|
restackAndTempRaise(item);
|
|
|
|
else
|
|
|
|
stackBelowItem(item, m_manager.getLowestItemAboveLayer(m_layernum));
|
2006-10-27 06:57:43 +00:00
|
|
|
|
2008-10-01 08:38:56 +00:00
|
|
|
m_needs_restack = true;
|
2003-04-15 23:09:26 +00:00
|
|
|
}
|
|
|
|
|
2003-01-16 12:41:27 +00:00
|
|
|
void XLayer::lower(XLayerItem &item) {
|
|
|
|
// assume already in this layer
|
2003-02-09 14:11:14 +00:00
|
|
|
|
|
|
|
// is it already the lowest?
|
2008-10-01 08:38:56 +00:00
|
|
|
if (&item == itemList().back()) {
|
|
|
|
if (m_needs_restack)
|
|
|
|
restack();
|
2003-01-16 12:41:27 +00:00
|
|
|
return; // nothing to do
|
2008-10-01 08:38:56 +00:00
|
|
|
}
|
2003-01-16 12:41:27 +00:00
|
|
|
|
2006-10-27 06:57:43 +00:00
|
|
|
iterator it = find(itemList().begin(), itemList().end(), &item);
|
2003-02-09 14:11:14 +00:00
|
|
|
if (it != itemList().end())
|
|
|
|
// remove this item
|
|
|
|
itemList().erase(it);
|
|
|
|
#ifdef DEBUG
|
|
|
|
else {
|
|
|
|
cerr<<__FILE__<<"("<<__LINE__<<"): WARNING: lower on item not in layer"<<endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
// add it to the bottom
|
2003-01-16 12:41:27 +00:00
|
|
|
itemList().push_back(&item);
|
2003-02-09 14:11:14 +00:00
|
|
|
|
|
|
|
// find the item we need to stack below
|
|
|
|
// start at the end
|
|
|
|
it = itemList().end();
|
|
|
|
|
|
|
|
// go up one so we have an object (which must exist, since at least this item is in the layer)
|
2003-01-16 12:41:27 +00:00
|
|
|
it--;
|
2006-10-27 06:57:43 +00:00
|
|
|
|
2003-02-09 14:11:14 +00:00
|
|
|
// go down another one
|
|
|
|
// must exist, otherwise our item must == itemList().back()
|
2006-10-27 06:57:43 +00:00
|
|
|
it--;
|
2003-02-09 14:11:14 +00:00
|
|
|
|
|
|
|
// and restack our window below that one.
|
2008-10-01 09:29:59 +00:00
|
|
|
stackBelowItem(item, *it);
|
2003-02-09 14:11:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void XLayer::raiseLayer(XLayerItem &item) {
|
|
|
|
m_manager.raiseLayer(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
void XLayer::lowerLayer(XLayerItem &item) {
|
|
|
|
m_manager.lowerLayer(item);
|
2003-01-16 12:41:27 +00:00
|
|
|
}
|
|
|
|
|
2003-02-09 14:11:14 +00:00
|
|
|
void XLayer::moveToLayer(XLayerItem &item, int layernum) {
|
|
|
|
m_manager.moveToLayer(item, layernum);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-01-16 12:41:27 +00:00
|
|
|
XLayerItem *XLayer::getLowestItem() {
|
2006-10-27 06:57:43 +00:00
|
|
|
if (itemList().empty())
|
2003-02-03 13:45:23 +00:00
|
|
|
return 0;
|
2006-10-27 06:57:43 +00:00
|
|
|
else
|
2003-02-03 13:45:23 +00:00
|
|
|
return itemList().back();
|
2003-01-16 12:41:27 +00:00
|
|
|
}
|
2003-02-02 16:32:41 +00:00
|
|
|
|