[PATCH] directional focus
Michael Leuchtenburg
michael at slashhome.org
Thu Apr 3 00:20:08 EST 2003
Here's a patch to implement directional focus in epistrophy. It should
be applied to the openbox-2_3 revision. And yeah, I'll port it to ob3.
:)
BTW, the algorithm used in this is not optimal, but it's the same one
the direction.jl I have for sawfish uses. If you don't like it, feel
free to change it. And please tell me of any better algorithms you come
up with.
-- michael
-------------- next part --------------
Index: util/epist/parser.cc
===================================================================
RCS file: /cvs/cvsroot/openbox/util/epist/Attic/parser.cc,v
retrieving revision 1.9.8.2
diff -p -u -r1.9.8.2 parser.cc
--- util/epist/parser.cc 2002/12/31 22:52:06 1.9.8.2
+++ util/epist/parser.cc 2003/04/03 04:54:50
@@ -114,6 +114,10 @@ void parser::setAction(string act)
{ "prevwindowofclass", Action::prevWindowOfClass },
{ "nextwindowofclassonallworkspaces", Action::nextWindowOfClassOnAllWorkspaces },
{ "prevwindowofclassonallworkspaces", Action::prevWindowOfClassOnAllWorkspaces },
+ { "upWindow", Action::upWindow },
+ { "downWindow", Action::downWindow },
+ { "leftWindow", Action::leftWindow },
+ { "rightWindow", Action::rightWindow },
{ "changeworkspace", Action::changeWorkspace },
{ "nextworkspace", Action::nextWorkspace },
{ "prevworkspace", Action::prevWorkspace },
Index: util/epist/screen.cc
===================================================================
RCS file: /cvs/cvsroot/openbox/util/epist/Attic/screen.cc,v
retrieving revision 1.82.6.3
diff -p -u -r1.82.6.3 screen.cc
--- util/epist/screen.cc 2002/12/31 22:52:06 1.82.6.3
+++ util/epist/screen.cc 2003/04/03 04:54:50
@@ -246,6 +246,22 @@ void screen::handleKeypress(const XEvent
cycleWindow(state, false, it->number() != 0 ? it->number(): 1,
false, true, true, it->string());
return;
+
+ case Action::upWindow:
+ cycleWindowDirectionally(state,up);
+ return;
+
+ case Action::downWindow:
+ cycleWindowDirectionally(state,down);
+ return;
+
+ case Action::leftWindow:
+ cycleWindowDirectionally(state, left);
+ return;
+
+ case Action::rightWindow:
+ cycleWindowDirectionally(state, right);
+ return;
case Action::changeWorkspace:
changeWorkspace(it->number());
@@ -652,6 +668,96 @@ void screen::cycleWindow(unsigned int st
// 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();
+ }
+}
+
+/*
+ optimally, if there is no currently active window, the directional cycling
+ commands would use the location of the mouse pointer as the base. However,
+ epistrophy doesn't know where the mouse pointer is, so we don't do that
+*/
+void screen::cycleWindowDirectionally(unsigned int state, direction dir)
+
+{
+ assert(_managed);
+
+ if (_clients.empty()) return;
+
+ WindowList::const_iterator current = _clients.begin(),
+ end = _clients.end();
+
+ if (_active == current) {
+ current++;
+ }
+ XWindow *t = *current;
+ XWindow *c = 0;
+ XWindow *a = *_active;
+
+ int t_fitness;
+ int c_fitness;
+
+ if (_active != end) {
+ if (dir == up || dir == down) {
+ t_fitness = abs(t->y() - a->y()) + 2 * abs(t->x() - a->x());
+ } else {
+ t_fitness = abs(t->x() - a->x()) + 2 * abs(t->y() - a->y());
+ }
+ while (++current != end) {
+ // determine if this window is invalid for cycling to
+ c = *current;
+
+ if (current == _active) continue;
+ switch (dir) {
+ case up:
+ if (c->y() > a->y()) continue;
+ break;
+ case down:
+ if (c->y() < a->y()) continue;
+ break;
+ case left:
+ if (c->x() > a->x()) continue;
+ break;
+ case right:
+ if (c->x() < a->x()) continue;
+ break;
+ }
+ if (t->iconic()) continue;
+ if (t->getScreen() != this) continue;
+ if (! (t->desktop() == _active_desktop ||
+ t->desktop() == 0xffffffff)) continue;
+ if (! t->canFocus()) continue;
+
+ if (dir == up || dir == down) {
+ c_fitness = abs(c->y() - a->y()) + 2 * abs(c->x() - a->x());
+ } else {
+ c_fitness = abs(c->x() - a->x()) + 2 * abs(c->y() - a->y());
+ }
+
+ if (c_fitness < t_fitness) {
+ t_fitness = c_fitness;
+ t = c;
+ }
}
}
Index: util/epist/screen.hh
===================================================================
RCS file: /cvs/cvsroot/openbox/util/epist/Attic/screen.hh,v
retrieving revision 1.18.8.2
diff -p -u -r1.18.8.2 screen.hh
--- util/epist/screen.hh 2002/12/31 22:52:06 1.18.8.2
+++ util/epist/screen.hh 2003/04/03 04:54:51
@@ -38,6 +38,8 @@ class screen;
class XAtom;
class ScreenInfo;
+typedef enum { left, right, up, down } direction;
+
class screen {
epist *_epist;
XAtom *_xatom;
@@ -91,6 +93,7 @@ public:
const bool alldesktops = false,
const bool sameclass = false,
const std::string &classname = "");
+ void cycleWindowDirectionally(unsigned int state, direction dir);
void cycleWorkspace(const bool forward, const int increment,
const bool loop = true) const;
void changeWorkspace(const int num) const;
More information about the openbox
mailing list