// FbPager.cc for FbPager
// Copyright (c) 2003-2004 Henrik Kinnunen (fluxgen 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$
#include "FbPager.hh"
// fbtk utils
#include "FbTk/EventManager.hh"
#include "FbTk/App.hh"
#include "FbTk/Color.hh"
#include "FbTk/StringUtil.hh"
// client handlers
#include "Ewmh.hh"
#include "FluxboxHandler.hh"
#include "Workspace.hh"
#include "WindowHint.hh"
#include "FbAtoms.hh"
#include "ScaleWindowToWindow.hh"
#include "Resources.hh"
#include "RefBinder.hh"
// x headers
#include <X11/Xatom.h>
#include <X11/Xutil.h>
// std headers
#include <iostream>
#include <cstdio>
#include <cassert>
#include <functional>
#include <algorithm>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H
// copied from fluxbox code
#ifdef HAVE_SSTREAM
#include <sstream>
#define FB_istringstream istringstream
#define FB_ostringstream ostringstream
#elif HAVE_STRSTREAM
#include <strstream>
#define FB_istringstream istrstream
#define FB_ostringstream ostrstream
#else
#error "You dont have sstream or strstream headers!"
#endif // HAVE_STRSTREAM
using namespace std;
namespace {
int handleXErrors(Display *disp, XErrorEvent *xerror) {
return 0;
}
template <typename Container>
void destroyList(Container &c) {
while (!c.empty()) {
delete c.back();
c.pop_back();
}
}
// TODO: is this optimal? i dont think so, but it works so far
bool compareButtonQueues(std::string q1, std::string q2) {
FbTk::StringUtil::removeFirstWhitespace(q1);
FbTk::StringUtil::removeFirstWhitespace(q2);
FbTk::StringUtil::removeTrailingWhitespace(q1);
FbTk::StringUtil::removeTrailingWhitespace(q2);
return q1 == q2;
}
// little helper to keep win visible in bigwin
void respectConstraints(int& x, int& y,
const FbTk::FbWindow& win, const FbTk::FbWindow& bigwin) {
const int left = - static_cast<int>((3 * win.width()) / 4);
const int right = bigwin.width() - win.width() / 4;
const int top = - static_cast<int>((3 * win.height()) / 4);
const int bottom = bigwin.height() - win.height() / 4;
// make sure window isnt dragged out of visible area of workspace
if ( x < left || x > right )
x = win.x();
if ( y < top || y > bottom )
y = win.y();
}
} // end anonymous namespace
namespace FbPager {
FbPager::FbPager(int screen_num, bool withdraw,
bool use_fbhandler,
bool use_ewmhhandler,
bool show_resources,
const char *resource_filename):
m_rootwin(screen_num),
m_window(m_rootwin,
0, 0, // pos
64, 64, // size
// event mask
ButtonPressMask | ButtonReleaseMask | ExposureMask |
FocusChangeMask | StructureNotifyMask|
SubstructureRedirectMask),
m_curr_workspace(0),
m_move_window(),
m_resmanager(0, false),
m_alpha(m_resmanager, 255,
"fbpager.alpha",
"FbPager.Alpha"),
m_start_x(m_resmanager, 0,
"fbpager.x",
"FbPager.x"),
m_start_y(m_resmanager, 0,
"fbpager.y",
"FbPager.y"),
m_workspace_width(m_resmanager, 64,
"fbpager.workspace.width",
"FbPager.Workspace.Width"),
m_workspace_height(m_resmanager, 64,
"fbpager.workspace.height",
"FbPager.Workspace.Height"),
m_workspaces_per_row(m_resmanager, 6400, // big number...
"fbpager.workspacesPerRow",
"FbPager.WorkspacesPerRow"),
m_follow_drag(m_resmanager, false,
"fbpager.followDrag",
"FbPager.FollowDrag"),
m_follow_move(m_resmanager, false,
"fbpager.followMove",
"FbPager.FollowMove"),
m_change_workspace_button(m_resmanager, "11",
"fbpager.changeWorkspaceButton",
"FbPager.ChangeWorkspaceButton"),
m_raise_window_button(m_resmanager, "2",
"fbpager.raiseWindowButton",
"FbPager.RaiseWindowButton"),
m_lower_window_button(m_resmanager, "3",
"fbpager.lowerWindowButton",
"FbPager.LowerWindowButton"),
m_close_window_button(m_resmanager, "3 3 1",
"fbpager.closeWindowButton",
"FbPager.CloseWindowButton"),
m_exit_button(m_resmanager, "1 3 3",
"fbpager.exitButton",
"FbPager.ExitButton"),
m_next_workspace_button(m_resmanager, "4",
"fbpager.nextWorkspaceButton",
"FbPager.NextWorkspaceButton"),
m_prev_workspace_button(m_resmanager, "5",
"fbpager.prevWorkspaceButton",
"FbPager.PrevWorkspaceButton"),
m_move_in_workspace_button(m_resmanager, 1,
"fbpager.moveInWorkspaceButton",
"FbPager.MoveInWorkspaceButton"),
m_drag_to_workspace_button(m_resmanager, 2,
"fbpager.dragToWorkspaceButton",
"FbPager.DragToWorkspaceButtton"),
m_align(m_resmanager, LEFT_TO_RIGHT,
"fbpager.align",
"FbPager.Align"),
m_color_str(m_resmanager, "white",
"fbpager.color",
"FbPager.Color"),
m_window_color_str(m_resmanager, "white",
"fbpager.windowColor",
"FbPager.WindowColor"),
m_focused_window_color_str(m_resmanager, "white",
"fbpager.focusedWindowColor",
"FbPager.FocusedWindowColor"),
m_window_bordercolor_str(m_resmanager, "black",
"fbpager.windowBorderColor",
"FbPager.WindowBorderColor"),
m_background_color_str(m_resmanager, "darkgray",
"fbpager.backgroundColor",
"FbPager.BackgroundColor"),
m_current_background_color_str(m_resmanager, "lightgray",
"fbpager.currentBackgroundColor",
"FbPager.CurrentBackgroundColor"),
m_multiclick_time(m_resmanager, 250,
"fbpager.multiClickTime",
"FbPager.MultiClickTime"),
m_window_icons(m_resmanager, false,
"fbpager.icons",
"FbPager.Icons"),
m_window_border_width(m_resmanager, 1,
"fbpager.windowBorderWidth",
"FbPager.WindowBorderWidth"),
m_last_workspace_num(-1) {
if (use_fbhandler)
m_clienthandlers.push_back(new FluxboxHandler());
if (use_ewmhhandler)
m_clienthandlers.push_back(new Ewmh());
XSetErrorHandler(handleXErrors);
FbTk::EventManager::instance()->add(*this, m_window);
// setup client window
m_window.setBackgroundColor(FbTk::Color((*m_color_str).c_str(), m_window.screenNumber()));
m_window.setAlpha(*m_alpha);
Display *disp = FbTk::App::instance()->display();
Atom wmproto[2];
int wmprot_size = 1;
wmproto[0] = XInternAtom(disp, "WM_DELETE_WINDOW", False);
if (FluxboxHandler::handler() != 0) {
wmprot_size = 2;
wmproto[1] = FbAtoms::instance()->getFluxboxStructureMessagesAtom();
}
XSetWMProtocols(disp, m_window.window(), wmproto, wmprot_size);
XWMHints wmhints;
if (!withdraw) {
WindowHint hint;
hint.add(WindowHint::WHINT_NO_DECOR | WindowHint::WHINT_SKIP_TASKBAR |
WindowHint::WHINT_STICKY | WindowHint::WHINT_SKIP_PAGER |
WindowHint::WHINT_HIDDEN | WindowHint::WHINT_TYPE_DOCK);
ClientHandlerList::iterator it = m_clienthandlers.begin();
ClientHandlerList::iterator it_end = m_clienthandlers.end();
for (; it != it_end; ++it)
(*it)->setHints(m_window, hint);
wmhints.initial_state = NormalState;
} else // withdraw
wmhints.initial_state = WithdrawnState;
// setup no input
wmhints.input = False;
// set which hints we're using
wmhints.flags = StateHint | InputHint;
// set window name
char *name = "FbPager";
XTextProperty windowname;
XStringListToTextProperty(&name, 1, &windowname);
// setup class hints
XClassHint classhints;
classhints.res_name="fbpager";
classhints.res_class="FbPager";
// set window properties
XSetWMProperties(disp, m_window.window(), &windowname, 0, 0, 0,
0, &wmhints, &classhints);
if (resource_filename != 0)
load(resource_filename);
// setup workspace count
ClientHandlerList::iterator it = m_clienthandlers.begin();
ClientHandlerList::iterator it_end = m_clienthandlers.end();
int workspaces = 0;
for (; it != it_end; ++it) {
workspaces = max((*it)->numberOfWorkspaces(m_window.screenNumber()), workspaces);
}
updateWorkspaceCount(workspaces);
// finaly show window
show();
m_window.move(*m_start_x, *m_start_y);
m_window.resize(m_window.width(), m_window.height());
m_last_button_event.time= 0;
if (show_resources) {
// dump resources to stdout
m_resmanager.dump(true);
}
}
FbPager::~FbPager() {
destroyList(m_clienthandlers);
destroyList(m_workspaces);
}
void FbPager::show() {
m_window.show();
}
void FbPager::hide() {
m_window.hide();
}
void FbPager::handleEvent(XEvent &event) {
// here we handle events that're not in FbTk::EventHandler interface
if (event.type == ClientMessage)
clientMessageEvent(event.xclient);
else if (event.type == ConfigureNotify) {
if (event.xconfigure.window != m_window.window()) {
updateWindowHints(event.xconfigure.window);
} else if (event.xconfigure.send_event == True){
if (event.xconfigure.x != m_window.x() ||
event.xconfigure.y != m_window.y() ||
event.xconfigure.width != m_window.width() ||
event.xconfigure.height != m_window.height()) {
m_window.updateGeometry(event.xconfigure.x,
event.xconfigure.y,
event.xconfigure.width,
event.xconfigure.height);
clearWindows(); // update transparency
}
}
} else if (event.type == PropertyNotify) {
propertyEvent(event.xproperty);
} else {
}
}
void FbPager::buttonPressEvent(XButtonEvent &event) {
if ( event.time - m_last_button_event.time > 1000 )
m_button_queue= "";
FB_ostringstream os;
// double click
if (event.time - m_last_button_event.time < *m_multiclick_time &&
event.button == m_last_button_event.button)
os << event.button;
else
os << " " << event.button;
// append button string to current queue
m_button_queue += os.str();
// save last event so we can compare it to next for double click
m_last_button_event = event;
if (event.button == *m_move_in_workspace_button ||
event.button == *m_drag_to_workspace_button ) {
m_move_window.curr_window = 0;
m_move_window.client = ClientWindow(0);
FbTk::FbWindow *win = 0;
for (size_t w = 0; w < m_workspaces.size(); ++w) {
win = m_workspaces[w]->find(event.subwindow);
if (win && win->parent() != 0) {
m_move_window.client = m_workspaces[w]->findClient(*win);
m_move_window.curr_window = win;
m_move_window.curr_workspace= m_workspaces[w];
m_grab_x = event.x - win->x();
m_grab_y = event.y - win->y();
// drag -> move it above all workspaces
if (event.button == *m_drag_to_workspace_button) {
m_move_window.curr_window->reparent(m_window,
m_move_window.curr_window->x() +
m_move_window.curr_workspace->window().x(),
m_move_window.curr_window->y() +
m_move_window.curr_workspace->window().y());
}
break;
}
}
}
}
void FbPager::buttonReleaseEvent(XButtonEvent &event) {
ClientWindow client(0);
if (m_move_window.curr_window != 0 &&
*m_move_in_workspace_button == event.button) {
FbTk::FbWindow &win = *m_move_window.curr_window;
int client_x = win.x(), client_y = win.y();
scaleFromWindowToWindow(*(win.parent()),
m_rootwin,
client_x, client_y);
m_move_window.client.move(client_x, client_y);
client = m_move_window.client;
m_move_window.client = ClientWindow(0);
m_move_window.curr_window = 0;
}
if (m_move_window.curr_window != 0 && *m_drag_to_workspace_button == event.button) {
if (m_last_workspace_num >= 0 &&
m_last_workspace_num < m_workspaces.size()) {
Workspace* workspace = m_workspaces[m_last_workspace_num];
// let someone else send it to the _new_ workspace
if (workspace != m_move_window.curr_workspace) {
ClientHandlerList::iterator it = m_clienthandlers.begin();
ClientHandlerList::iterator it_end = m_clienthandlers.end();
for (; it != it_end; ++it) {
(*it)->sendToWorkspace(m_move_window.client, m_last_workspace_num);
}
}
// drop it to the last workspace, the mouse was over
m_move_window.curr_window->reparent(workspace->window(),
m_move_window.curr_window->x() -
workspace->window().x(),
m_move_window.curr_window->y() -
workspace->window().y());
}
else {
m_move_window.curr_window->reparent(m_move_window.curr_workspace->window(),
m_grab_x,
m_grab_y);
}
// move it to the right position
FbTk::FbWindow &win = *m_move_window.curr_window;
int client_x = win.x(), client_y = win.y();
scaleFromWindowToWindow(*(win.parent()),
m_rootwin,
client_x, client_y);
m_move_window.client.move(client_x, client_y);
// clean up
m_move_window.client = ClientWindow(0);
m_move_window.curr_window = 0;
m_move_window.curr_workspace = 0;
m_button_queue.erase();
} else if (compareButtonQueues(m_button_queue, *m_change_workspace_button)) {
// change workspace
// find out which workspace
Workspace *workspace = 0;
FbTk::FbWindow *win = 0;
size_t workspace_it = 0;
for (; workspace_it < m_workspaces.size(); ++workspace_it) {
if (m_workspaces[workspace_it]->window() == event.window) {
workspace = m_workspaces[workspace_it];
break;
} else {
win = m_workspaces[workspace_it]->find(event.window);
if (win != 0) {
workspace = m_workspaces[workspace_it];
break;
}
}
}
if (workspace != 0)
sendChangeToWorkspace(workspace_it);
} else if (compareButtonQueues(m_button_queue, *m_raise_window_button) &&
client.window() != 0) {
// raise, currently the same as focus
for_each(m_clienthandlers.begin(),
m_clienthandlers.end(),
RefBind(&ClientHandler::setFocus, client));
client.raise();
} else if (compareButtonQueues(m_button_queue, *m_lower_window_button) &&
client.window() != 0) {
client.lower();
} else if (compareButtonQueues(m_button_queue, *m_close_window_button) &&
client.window() != 0) {
for_each(m_clienthandlers.begin(),
m_clienthandlers.end(),
RefBind(&ClientHandler::closeWindow, client));
} else if (compareButtonQueues(m_button_queue, *m_exit_button)) {
// exit
FbTk::App::instance()->end();
} else if (compareButtonQueues(m_button_queue, *m_next_workspace_button)) {
// next workspace
sendChangeToWorkspace(m_curr_workspace < m_workspaces.size() - 1 ?
m_curr_workspace + 1 : 0);
} else if (compareButtonQueues(m_button_queue, *m_prev_workspace_button)) {
// prev workspace
sendChangeToWorkspace(m_curr_workspace > 0 ? m_curr_workspace - 1 :
m_workspaces.size() - 1);
} else {
// ok, we didn't find any queue that match
// so we return without clearing the current queue
return;
}
m_button_queue.erase();
}
void FbPager::motionNotifyEvent(XMotionEvent &event) {
if (m_move_window.curr_window != 0 &&
m_move_window.curr_workspace != 0) {
Workspace* workspace= 0;
size_t w = 0;
size_t old_workspace= m_last_workspace_num;
int left, top, right, bottom, x, y;
// find out, on which workspace the motion started and
// on which workspace we are now
for(; w < m_workspaces.size(); ++w) {
if (m_workspaces[w]->window() == event.window)
workspace= m_workspaces[w];
left = m_workspaces[w]->window().x();
top = m_workspaces[w]->window().y();
right = left + m_workspaces[w]->window().width();
bottom = top + m_workspaces[w]->window().height();
// m_window - coordinate - space
x = m_move_window.curr_workspace->window().x() + event.x;
y = m_move_window.curr_workspace->window().y() + event.y;
// inside the new workspace?
if ( left <= x && x <= right && top <= y && y <= bottom )
m_last_workspace_num= w;
}
int newx = event.x - m_grab_x;
int newy = event.y - m_grab_y;
// just move in current workspace
if (m_last_button_event.button == *m_move_in_workspace_button) {
respectConstraints(newx, newy, *m_move_window.curr_window, workspace->window());
m_move_window.curr_window->move(newx, newy);
if (*m_follow_move) {
FbTk::FbWindow &win = *m_move_window.curr_window;
int client_x = win.x(), client_y = win.y();
scaleFromWindowToWindow(*(win.parent()),
m_rootwin,
client_x, client_y);
m_move_window.client.move(client_x, client_y);
}
// drag between the workspaces
} else if (m_last_button_event.button == *m_drag_to_workspace_button) {
newx += m_move_window.curr_workspace->window().x();
newy += m_move_window.curr_workspace->window().y();
respectConstraints(newx, newy, *m_move_window.curr_window, m_window);
m_move_window.curr_window->move(newx, newy);
if (*m_follow_drag && m_last_workspace_num != old_workspace)
sendChangeToWorkspace(m_last_workspace_num);
}
}
}
void FbPager::exposeEvent(XExposeEvent &event) {
if (m_window == event.window) {
m_window.clearArea(event.x, event.y,
event.width, event.height);
} else {
for (size_t w = 0; w < m_workspaces.size(); ++w) {
if (m_workspaces[w]->window() == event.window) {
FbTk::FbWindow &win = m_workspaces[w]->window();
win.clearArea(event.x, event.y,
event.width, event.height);
return;
} else {
FbTk::FbWindow *win = m_workspaces[w]->find(event.window);
if (win != 0) {
win->clearArea(event.x, event.y,
event.width, event.height);
return;
}
}
}
}
}
void FbPager::clientMessageEvent(XClientMessageEvent &event) {
ClientHandlerList::iterator it = m_clienthandlers.begin();
ClientHandlerList::iterator it_end = m_clienthandlers.end();
for (; it != it_end; ++it) {
if ((*it)->clientMessage(*this, event))
break;
}
}
void FbPager::propertyEvent(XPropertyEvent &event) {
updateWindowHints(event.window);
}
void FbPager::addWindow(Window win, unsigned int workspace_num) {
if (workspace_num >= m_workspaces.size())
return;
m_windows.insert(win);
m_workspaces[workspace_num]->add(win);
// update window mode
updateWindowHints(win);
}
void FbPager::moveToWorkspace(Window win, unsigned int w) {
if (w >= 0x7FFFFFFF) {
updateWindowHints(w);
return;
} else if (w >= m_workspaces.size())
return;
// remove from old workspace
for (size_t workspace=0; workspace < m_workspaces.size(); ++workspace) {
if (w != workspace && m_workspaces[workspace]->find(win) != 0)
m_workspaces[workspace]->remove(win);
}
addWindow(win, w);
}
void FbPager::setFocusedWindow(Window win) {
Workspace::setFocusedWindow(win);
for_each(m_workspaces.begin(),
m_workspaces.end(),
mem_fun(&Workspace::updateFocusedWindow));
}
void FbPager::removeWindow(Window win) {
for_each(m_workspaces.begin(),
m_workspaces.end(),
bind2nd(mem_fun(&Workspace::remove), win));
FbTk::EventManager::instance()->remove(win);
m_windows.erase(win);
}
void FbPager::updateWorkspaceCount(unsigned int num) {
if (num == 0 || num == m_workspaces.size())
return;
if (m_workspaces.size() < num) {
// add some workspaces until we match number of workspaces
FbTk::Color wincolor(m_window_color_str->c_str(), m_window.screenNumber());
FbTk::Color focusedcolor(m_focused_window_color_str->c_str(), m_window.screenNumber());
FbTk::Color bordercol(m_window_bordercolor_str->c_str(), m_window.screenNumber());
FbTk::Color backgroundcol(m_background_color_str->c_str(), m_window.screenNumber());
while (m_workspaces.size() != num) {
Workspace *w = new Workspace(*this, m_window, *m_workspace_width, *m_workspace_height,
focusedcolor,
wincolor,
bordercol,
backgroundcol,
"workspace",
*m_window_icons,
*m_window_border_width);
w->setAlpha(*m_alpha);
m_workspaces.push_back(w);
}
} else { // remove some workspace until we match number or workspaces
while (m_workspaces.size() != num) {
delete m_workspaces.back();
m_workspaces.pop_back();
// extra precaution
if (m_workspaces.empty())
break;
}
}
// update size of our main window and align workspaces
alignWorkspaces();
m_window.showSubwindows();
}
void FbPager::setCurrentWorkspace(unsigned int num) {
if (num >= m_workspaces.size() || num == m_curr_workspace)
return;
// set current workspaces background to "normal" background,
FbTk::Color workspace_background(m_background_color_str->c_str(),
m_window.screenNumber());
m_workspaces[m_curr_workspace]->window().setBackgroundColor(workspace_background);
m_workspaces[m_curr_workspace]->window().clear();
// set next workspace background
// update workspace background
m_workspaces[num]->window().setBackgroundColor(FbTk::
Color(m_current_background_color_str->c_str(),
m_window.screenNumber()));
m_workspaces[num]->window().clear();
m_curr_workspace = num;
}
/**
Setup workspaces position and size in our main window
*/
void FbPager::alignWorkspaces() {
const int bevel = 1;
int diff_x = 0;
int diff_y = 0;
// Fix alignment of workspaces
if (*m_align == LEFT_TO_RIGHT)
diff_x = *m_workspace_width + bevel;
else // align TOP_TO_BOTTOM
diff_y = *m_workspace_height + bevel;
// resize and reposition all workspaces
WorkspaceList::iterator it = m_workspaces.begin();
WorkspaceList::iterator it_end = m_workspaces.end();
int next_pos_x = bevel;
int next_pos_y = bevel;
int workspace = 0;
int max_x = 0;
int max_y = 0;
for (; it != it_end; ++it, next_pos_y += diff_y, next_pos_x += diff_x, ++workspace) {
if (workspace >= *m_workspaces_per_row) {
workspace = 0;
if (*m_align == LEFT_TO_RIGHT) {
next_pos_x = bevel;
next_pos_y += *m_workspace_height + bevel;
} else {
next_pos_y = bevel;
next_pos_x += *m_workspace_width + bevel;
}
}
if (next_pos_x + *m_workspace_width > max_x)
max_x = next_pos_x + *m_workspace_width;
if (next_pos_y + *m_workspace_height > max_y)
max_y = next_pos_y + *m_workspace_height;
(*it)->window().move(next_pos_x, next_pos_y);
(*it)->resize(*m_workspace_width, *m_workspace_height);
}
m_window.resize(max_x + bevel, max_y + bevel);
XSizeHints sizehints;
sizehints.max_width = sizehints.min_width = m_window.width();
sizehints.max_height = sizehints.min_height = m_window.height();
sizehints.flags = PMinSize | PMaxSize;
XSetWMProperties(FbTk::App::instance()->display(), m_window.window(), 0, 0, 0, 0,
&sizehints, 0, 0);
for_each(m_clienthandlers.begin(),
m_clienthandlers.end(),
RefBind(&ClientHandler::moveResize, m_window));
}
void FbPager::sendChangeToWorkspace(unsigned int num) {
assert(num < m_workspaces.size());
ClientHandlerList::iterator it = m_clienthandlers.begin();
ClientHandlerList::iterator it_end = m_clienthandlers.end();
for (; it != it_end; ++it)
(*it)->changeWorkspace(m_window.screenNumber(), num);
}
void FbPager::updateWindowHints(Window win) {
WindowHint hint;
ClientWindow client(win);
ClientHandlerList::iterator it = m_clienthandlers.begin();
ClientHandlerList::iterator it_end = m_clienthandlers.end();
for (; it != it_end; ++it)
(*it)->getHints(client, hint);
for (int workspace = 0; workspace < m_workspaces.size(); workspace++) {
if (m_workspaces[workspace]->find(win) == 0) {
// if the window is sticky then add it to this workspace too
// and if it's not skip_pager nor type_dock
if ((hint.flags() & WindowHint::WHINT_STICKY) &&
!(hint.flags() & WindowHint::WHINT_SKIP_PAGER) &&
!(hint.flags() & WindowHint::WHINT_TYPE_DOCK)) {
cerr<<"STICKY!"<<endl;
m_workspaces[workspace]->add(win);
} else
continue; // normal window without sticky
} else if (!(hint.flags() & WindowHint::WHINT_STICKY) &&
hint.workspace() != workspace ||
(hint.flags() & WindowHint::WHINT_SKIP_PAGER) ||
(hint.flags() & WindowHint::WHINT_TYPE_DOCK)) {
// if win not sticky and if it's not suppose to be on this
// workspace then remove it and try next workspace
m_workspaces[workspace]->remove(win);
continue; // next workspace
}
m_workspaces[workspace]->updateGeometry(win);
if (hint.flags() & WindowHint::WHINT_SHADED) {
m_workspaces[workspace]->shadeWindow(win);
} else
m_workspaces[workspace]->unshadeWindow(win);
if ((hint.flags() & WindowHint::WHINT_ICONIC) &&
!(hint.flags() & WindowHint::WHINT_SHADED))
m_workspaces[workspace]->iconifyWindow(win);
else if (!(hint.flags() & WindowHint::WHINT_SHADED))
m_workspaces[workspace]->deiconifyWindow(win);
} // end for
}
void FbPager::raiseWindow(Window win) {
// raise on all workspace
for_each(m_workspaces.begin(),
m_workspaces.end(),
bind2nd(mem_fun(&Workspace::raiseWindow), win));
}
void FbPager::lowerWindow(Window win) {
// lower on all workspace
for_each(m_workspaces.begin(),
m_workspaces.end(),
bind2nd(mem_fun(&Workspace::lowerWindow), win));
}
void FbPager::load(const std::string &filename) {
if (!m_resmanager.load(FbTk::StringUtil::expandFilename(filename).c_str()))
cerr<<"Failed to load resource file: "<<filename<<endl;
m_window.setAlpha(*m_alpha);
m_window.setBackgroundColor(FbTk::Color((*m_color_str).c_str(), m_window.screenNumber()));
FbTk::Color bgcolor(m_background_color_str->c_str(), m_window.screenNumber());
for (size_t workspace = 0; workspace < m_workspaces.size(); ++workspace) {
m_workspaces[workspace]->setAlpha(*m_alpha);
m_workspaces[workspace]->setWindowColor(*m_focused_window_color_str,
*m_window_color_str,
*m_window_bordercolor_str);
m_workspaces[workspace]->window().setBackgroundColor(bgcolor);
}
}
void FbPager::clearWindows() {
m_window.clear();
for_each(m_workspaces.begin(),
m_workspaces.end(),
mem_fun(&Workspace::clearWindows));
}
} // end namespace FbPager
syntax highlighted by Code2HTML, v. 0.9.1