-// -*- mode: C++; indent-tabs-mode: nil; -*-
-// screen.cc for Epistophy - a key handler for NETWM/EWMH window managers.
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+// screen.cc for Epistrophy - a key handler for NETWM/EWMH window managers.
// Copyright (c) 2002 - 2002 Ben Jansens <ben at orodu.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a
#include "../../src/XAtom.hh"
#include "screen.hh"
#include "epist.hh"
-
+#include "config.hh"
screen::screen(epist *epist, int number)
: _clients(epist->clientsList()),
_number = number;
_info = _epist->getScreenInfo(_number);
_root = _info->getRootWindow();
-
+
// find a window manager supporting NETWM, waiting for it to load if we must
int count = 20; // try for 20 seconds
_managed = false;
// root window
if (e.xproperty.atom == _xatom->getAtom(XAtom::net_number_of_desktops))
updateNumDesktops();
- if (e.xproperty.atom == _xatom->getAtom(XAtom::net_current_desktop))
+ else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_current_desktop))
updateActiveDesktop();
- if (e.xproperty.atom == _xatom->getAtom(XAtom::net_active_window))
+ else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_active_window))
updateActiveWindow();
- if (e.xproperty.atom == _xatom->getAtom(XAtom::net_client_list)) {
+ else if (e.xproperty.atom == _xatom->getAtom(XAtom::net_client_list)) {
// catch any window unmaps first
XEvent ev;
if (XCheckTypedWindowEvent(_epist->getXDisplay(), e.xany.window,
return;
case Action::nextWorkspace:
- cycleWorkspace(true);
+ cycleWorkspace(true, it->number() != 0 ? it->number(): 1);
return;
case Action::prevWorkspace:
- cycleWorkspace(false);
+ cycleWorkspace(false, it->number() != 0 ? it->number(): 1);
return;
case Action::nextWindow:
- cycleWindow(true);
+
+ cycleWindow(true, it->number() != 0 ? it->number(): 1);
return;
case Action::prevWindow:
- cycleWindow(false);
+ cycleWindow(false, it->number() != 0 ? it->number(): 1);
return;
case Action::nextWindowOnAllWorkspaces:
- cycleWindow(true, false, true);
+ cycleWindow(true, it->number() != 0 ? it->number(): 1, false, true);
return;
case Action::prevWindowOnAllWorkspaces:
- cycleWindow(false, false, true);
+ cycleWindow(false, it->number() != 0 ? it->number(): 1, false, true);
return;
case Action::nextWindowOnAllScreens:
- cycleWindow(true, true);
+ cycleWindow(true, it->number() != 0 ? it->number(): 1, true);
return;
case Action::prevWindowOnAllScreens:
- cycleWindow(false, true);
+ cycleWindow(false, it->number() != 0 ? it->number(): 1, true);
return;
case Action::nextWindowOfClass:
- cycleWindow(true, false, false, true, it->string());
+ cycleWindow(true, it->number() != 0 ? it->number(): 1,
+ false, false, true, it->string());
return;
case Action::prevWindowOfClass:
- cycleWindow(false, false, false, true, it->string());
+ cycleWindow(false, it->number() != 0 ? it->number(): 1,
+ false, false, true, it->string());
return;
case Action::nextWindowOfClassOnAllWorkspaces:
- cycleWindow(true, false, true, true, it->string());
+ cycleWindow(true, it->number() != 0 ? it->number(): 1,
+ false, true, true, it->string());
return;
case Action::prevWindowOfClassOnAllWorkspaces:
- cycleWindow(false, false, true, true, it->string());
+ cycleWindow(false, it->number() != 0 ? it->number(): 1,
+ false, true, true, it->string());
return;
case Action::changeWorkspace:
changeWorkspace(it->number());
return;
+ case Action::upWorkspace:
+ changeWorkspaceVert(-1);
+ return;
+
+ case Action::downWorkspace:
+ changeWorkspaceVert(1);
+ return;
+
+ case Action::leftWorkspace:
+ changeWorkspaceHorz(-1);
+ return;
+
+ case Action::rightWorkspace:
+ changeWorkspaceHorz(1);
+ return;
+
case Action::execute:
execCommand(it->string());
return;
return;
case Action::moveWindowUp:
- window->move(window->x(), window->y() - it->number());
+ window->move(window->x(), window->y() -
+ (it->number() != 0 ? it->number(): 1));
return;
case Action::moveWindowDown:
- window->move(window->x(), window->y() + it->number());
+ window->move(window->x(), window->y() +
+ (it->number() != 0 ? it->number(): 1));
return;
case Action::moveWindowLeft:
- window->move(window->x() - it->number(), window->y());
+ window->move(window->x() - (it->number() != 0 ? it->number(): 1),
+ window->y());
return;
case Action::moveWindowRight:
- window->move(window->x() + it->number(), window->y());
+ window->move(window->x() + (it->number() != 0 ? it->number(): 1),
+ window->y());
return;
case Action::resizeWindowWidth:
- window->resize(it->number(), 0);
+ window->resizeRel(it->number(), 0);
return;
case Action::resizeWindowHeight:
- window->resize(0, it->number());
+ window->resizeRel(0, it->number());
return;
case Action::toggleshade:
case Action::toggleMaximizeFull:
window->toggleMaximize(XWindow::Max_Full);
return;
+
+ case Action::toggleDecorations:
+ window->decorate(! window->decorated());
+ return;
default:
assert(false); // unhandled action type!
}
-void screen::cycleWindow(const bool forward, const bool allscreens,
- const bool alldesktops, const bool sameclass,
- const string &cn) const {
+void screen::cycleWindow(const bool forward, const int increment,
+ const bool allscreens, const bool alldesktops,
+ const bool sameclass, const string &cn) const {
assert(_managed);
+ assert(increment > 0);
if (_clients.empty()) return;
-
+
string classname(cn);
if (sameclass && classname.empty() && _active != _clients.end())
classname = (*_active)->appClass();
WindowList::const_iterator target = _active,
begin = _clients.begin(),
end = _clients.end();
-
- while (1) {
- if (forward) {
- if (target == end) {
- target = begin;
+
+ const XWindow *t = 0;
+
+ for (int x = 0; x < increment; ++x) {
+ while (1) {
+ if (forward) {
+ if (target == end) {
+ target = begin;
+ } else {
+ ++target;
+ }
} else {
- ++target;
+ if (target == begin)
+ target = end;
+ --target;
}
- } else {
- if (target == begin)
- target = end;
- --target;
- }
-
- // must be no window to focus
- if (target == _active)
- return;
- // start back at the beginning of the loop
- if (target == end)
- continue;
+ // must be no window to focus
+ if (target == _active)
+ return;
- // determine if this window is invalid for cycling to
- const XWindow *t = *target;
- if (t->iconic()) continue;
- if (! allscreens && t->getScreen() != this) continue;
- if (! alldesktops && ! (t->desktop() == _active_desktop ||
- t->desktop() == 0xffffffff)) continue;
- if (sameclass && ! classname.empty() &&
- t->appClass() != classname) continue;
- if (! t->canFocus()) continue;
-
- // found a good window!
- t->focus();
- return;
+ // start back at the beginning of the loop
+ if (target == end)
+ continue;
+
+ // determine if this window is invalid for cycling to
+ t = *target;
+ if (t->iconic()) continue;
+ if (! allscreens && t->getScreen() != this) continue;
+ if (! alldesktops && ! (t->desktop() == _active_desktop ||
+ t->desktop() == 0xffffffff)) continue;
+ if (sameclass && ! classname.empty() &&
+ t->appClass() != classname) continue;
+ if (! t->canFocus()) continue;
+
+ // found a good window so break out of the while, and perhaps continue
+ // with the for loop
+ break;
+ }
}
+
+ // phew. we found the window, so focus it.
+ t->focus();
}
-void screen::cycleWorkspace(const bool forward, const bool loop) const {
+void screen::cycleWorkspace(const bool forward, const int increment,
+ const bool loop) const {
assert(_managed);
+ assert(increment > 0);
unsigned int destination = _active_desktop;
- if (forward) {
- if (destination < _num_desktops - 1)
- ++destination;
- else if (loop)
- destination = 0;
- } else {
- if (destination > 0)
- --destination;
- else if (loop)
- destination = _num_desktops - 1;
+ for (int x = 0; x < increment; ++x) {
+ if (forward) {
+ if (destination < _num_desktops - 1)
+ ++destination;
+ else if (loop)
+ destination = 0;
+ } else {
+ if (destination > 0)
+ --destination;
+ else if (loop)
+ destination = _num_desktops - 1;
+ }
}
if (destination != _active_desktop)
_xatom->sendClientMessage(_root, XAtom::net_current_desktop, _root, num);
}
+void screen::changeWorkspaceVert(const int num) const {
+ assert(_managed);
+ const Config *conf = _epist->getConfig();
+ int width = conf->getNumberValue(Config::workspaceColumns);
+
+ if (width > _num_desktops || width <= 0)
+ return;
+
+ int wnum;
+
+ // a cookie to the person that makes this pretty
+ if (num < 0) {
+ wnum = _active_desktop - width;
+ if (wnum < 0) {
+ wnum = _num_desktops/width * width + _active_desktop;
+ if (wnum >= _num_desktops)
+ wnum = _num_desktops - 1;
+ }
+ }
+ else {
+ wnum = _active_desktop + width;
+ if (wnum >= _num_desktops) {
+ wnum = (_active_desktop + width) % _num_desktops - 1;
+ if (wnum < 0)
+ wnum = 0;
+ }
+ }
+ changeWorkspace(wnum);
+}
+
+void screen::changeWorkspaceHorz(const int num) const {
+ assert(_managed);
+ const Config *conf = _epist->getConfig();
+ int width = conf->getNumberValue(Config::workspaceColumns);
+ int wnum;
+
+ if (width > _num_desktops || width <= 0)
+ return;
+
+ if (num < 0) {
+ if (_active_desktop % width != 0)
+ changeWorkspace(_active_desktop - 1);
+ else {
+ wnum = _active_desktop + width - 1;
+ if (wnum >= _num_desktops)
+ wnum = _num_desktops - 1;
+ }
+ }
+ else {
+ if (_active_desktop % width != width - 1) {
+ wnum = _active_desktop + 1;
+ if (wnum >= _num_desktops)
+ wnum = _num_desktops / width * width;
+ }
+ else
+ wnum = _active_desktop - width + 1;
+ }
+ changeWorkspace(wnum);
+}
+
void screen::grabKey(const KeyCode keyCode, const int modifierMask) const {
Display *display = _epist->getXDisplay();