+
+ // must be no window to focus
+ if (target == _active)
+ 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.
+ if (_stacked_cycling && state) {
+ if (!_cycling) {
+ // grab modifiers so we can intercept KeyReleases from them
+ grabModifiers();
+ _cycling = true;
+ }
+
+ // if the window is on another desktop, we can't use XSetInputFocus, since
+ // it doesn't imply a workspace change.
+ if (_stacked_raise || (t->desktop() != _active_desktop &&
+ t->desktop() != 0xffffffff))
+ t->focus(); // raise
+ else
+ t->focus(false); // don't raise
+ }
+ else {
+ t->focus();
+ }
+}
+
+
+void screen::cycleWorkspace(const bool forward, const int increment,
+ const bool loop) const {
+ assert(_managed);
+ assert(increment > 0);
+
+ unsigned int destination = _active_desktop;
+
+ 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)
+ changeWorkspace(destination);
+}
+
+
+void screen::changeWorkspace(const int num) const {
+ assert(_managed);
+
+ _xatom->sendClientMessage(_root, XAtom::net_current_desktop, _root, num);
+}
+
+void screen::changeWorkspaceVert(const int num) const {
+ assert(_managed);
+ int width = 0;
+ int num_desktops = (signed)_num_desktops;
+ int active_desktop = (signed)_active_desktop;
+ int wnum = 0;
+
+ _config->getValue(Config::workspaceColumns, width);
+
+ if (width > num_desktops || width <= 0)
+ return;
+
+ // 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);
+ int width = 0;
+ int num_desktops = (signed)_num_desktops;
+ int active_desktop = (signed)_active_desktop;
+ int wnum = 0;
+
+ _config->getValue(Config::workspaceColumns, width);
+
+ 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();
+ int numlockMask, scrolllockMask;
+
+ _epist->getLockModifiers(numlockMask, scrolllockMask);
+
+ XGrabKey(display, keyCode, modifierMask,
+ _root, True, GrabModeAsync, GrabModeAsync);
+ XGrabKey(display, keyCode,
+ modifierMask|LockMask,
+ _root, True, GrabModeAsync, GrabModeAsync);
+ XGrabKey(display, keyCode,
+ modifierMask|scrolllockMask,
+ _root, True, GrabModeAsync, GrabModeAsync);
+ XGrabKey(display, keyCode,
+ modifierMask|numlockMask,
+ _root, True, GrabModeAsync, GrabModeAsync);
+
+ XGrabKey(display, keyCode,
+ modifierMask|LockMask|scrolllockMask,
+ _root, True, GrabModeAsync, GrabModeAsync);
+ XGrabKey(display, keyCode,
+ modifierMask|scrolllockMask|numlockMask,
+ _root, True, GrabModeAsync, GrabModeAsync);
+ XGrabKey(display, keyCode,
+ modifierMask|numlockMask|LockMask,
+ _root, True, GrabModeAsync, GrabModeAsync);
+
+ XGrabKey(display, keyCode,
+ modifierMask|numlockMask|LockMask|scrolllockMask,
+ _root, True, GrabModeAsync, GrabModeAsync);
+}
+
+void screen::ungrabKey(const KeyCode keyCode, const int modifierMask) const {
+
+ Display *display = _epist->getXDisplay();
+ int numlockMask, scrolllockMask;
+
+ _epist->getLockModifiers(numlockMask, scrolllockMask);
+
+ XUngrabKey(display, keyCode, modifierMask, _root);
+ XUngrabKey(display, keyCode, modifierMask|LockMask, _root);
+ XUngrabKey(display, keyCode, modifierMask|scrolllockMask, _root);
+ XUngrabKey(display, keyCode, modifierMask|numlockMask, _root);
+ XUngrabKey(display, keyCode, modifierMask|LockMask|scrolllockMask, _root);
+ XUngrabKey(display, keyCode, modifierMask|scrolllockMask|numlockMask, _root);
+ XUngrabKey(display, keyCode, modifierMask|numlockMask|LockMask, _root);
+ XUngrabKey(display, keyCode, modifierMask|numlockMask|LockMask|
+ scrolllockMask, _root);
+}
+
+
+void screen::grabModifiers() const {
+ Display *display = _epist->getXDisplay();
+
+ XGrabKeyboard(display, rootWindow(), True, GrabModeAsync,
+ GrabModeAsync, CurrentTime);
+}
+
+
+void screen::ungrabModifiers() const {
+ Display *display = _epist->getXDisplay();
+
+ XUngrabKeyboard(display, CurrentTime);
+}
+
+
+bool screen::nothingIsPressed(void) const
+{
+ char keys[32];
+ XQueryKeymap(_epist->getXDisplay(), keys);
+
+ for (int i = 0; i < 32; ++i) {
+ if (keys[i] != 0)
+ return false;
+ }
+
+ return true;
+}