epist + multihead == <drool>
authorDana Jansens <danakj@orodu.net>
Wed, 24 Jul 2002 08:33:35 +0000 (08:33 +0000)
committerDana Jansens <danakj@orodu.net>
Wed, 24 Jul 2002 08:33:35 +0000 (08:33 +0000)
added next/prevWindowOnAllScreens
added next/prevScreen

util/epist/actions.hh
util/epist/epist.cc
util/epist/epist.hh
util/epist/screen.cc
util/epist/screen.hh
util/epist/window.hh

index 30ea0e6..25f1e96 100644 (file)
@@ -57,18 +57,24 @@ public:
 
     nextWindow, //done for now
     prevWindow, //done for now
-    nextWindowOnAllWorkspaces, //done
-    prevWindowOnAllWorkspaces, //done
+    nextWindowOnAllWorkspaces, //done for now
+    prevWindowOnAllWorkspaces, //done for now
 
-    nextWindowOfClass, //done
-    prevWindowOfClass, //done
-    nextWindowOfClassOnAllWorkspaces, //done
-    prevWindowOfClassOnAllWorkspaces, //done
+    nextWindowOnAllScreens, //done for now
+    prevWindowOnAllScreens, //done for now
+
+    nextWindowOfClass, //done for now
+    prevWindowOfClass, //done for now
+    nextWindowOfClassOnAllWorkspaces, //done for now
+    prevWindowOfClassOnAllWorkspaces, //done for now
 
     changeWorkspace, //done
     nextWorkspace, //done
     prevWorkspace, //done
 
+    nextScreen, //done for now
+    prevScreen, //done for now
+  
     // these are openbox extensions
     showRootMenu,
     showWorkspaceMenu,
index 30b2f47..f3084e8 100644 (file)
@@ -69,10 +69,14 @@ epist::epist(char **argv, char *dpy_name, char *rc_file)
 
   _xatom = new XAtom(getXDisplay());
 
+  _active = _clients.end();
+  
   for (unsigned int i = 0; i < getNumberOfScreens(); ++i) {
     screen *s = new screen(this, i);
-    if (s->managed())
+    if (s->managed()) {
       _screens.push_back(s);
+      s->updateEverything();
+    }
   }
   if (_screens.empty()) {
     cout << "No compatible window manager found on any screens. Aborting.\n";
@@ -198,6 +202,18 @@ XWindow *epist::findWindow(Window window) const {
   return 0;
 }
 
+
+void epist::cycleScreen(int current, bool forward) const {
+  int dest = current + (forward ? 1 : -1);
+
+  if (dest < 0) dest = (signed)_screens.size() - 1;
+  else if (dest >= (signed)_screens.size()) dest = 0;
+
+  const XWindow *target = _screens[dest]->lastActiveWindow();
+  if (target) target->focus();
+}
+
+
 void epist::addAction(Action::ActionType act, unsigned int modifiers,
                       string key, int number) {
   _actions.push_back(Action(act, XKeysymToKeycode(getXDisplay(),
index 6da3818..1932902 100644 (file)
@@ -31,27 +31,30 @@ extern "C" {
 #include <map>
 
 #include "actions.hh"
+#include "window.hh"
 
 #include "../../src/BaseDisplay.hh"
 
 class XAtom;
 class screen;
-class XWindow;
 
 class epist : public BaseDisplay {
 private:
-  std::string     _rc_file;
-  XAtom          *_xatom;
-  char          **_argv;
+  std::string _rc_file;
+  XAtom *_xatom;
+  char **_argv;
 
   typedef std::vector<screen *> ScreenList;
-  ScreenList      _screens;
+  ScreenList _screens;
 
   typedef std::map<Window, XWindow*> WindowLookup;
   typedef WindowLookup::value_type WindowLookupPair;
   WindowLookup    _windows;
+  
+  WindowList _clients;
+  WindowList::iterator _active;
 
-  ActionList      _actions;
+  ActionList _actions;
   
   virtual void process_event(XEvent *e);
   virtual bool handleSignal(int sig);
@@ -72,12 +75,17 @@ public:
   void removeWindow(XWindow *window);
   XWindow *findWindow(Window window) const;
 
+  void cycleScreen(int current, bool forward) const;
+
   void getLockModifiers(int &numlockMask, int &scrolllockMask) const {
     numlockMask = NumLockMask;
     scrolllockMask = ScrollLockMask;
   }
   
   const ActionList &actions(void) { return _actions; }
+  
+  WindowList& clientsList() { return _clients; }
+  WindowList::iterator& activeWindow() { return _active; }
 };
 
 #endif // __epist_hh
index d711fcb..56f64f0 100644 (file)
@@ -50,14 +50,19 @@ using std::string;
 #include "epist.hh"
 
 
-screen::screen(epist *epist, int number) {
+screen::screen(epist *epist, int number) 
+  : _clients(epist->clientsList()),
+    _active(epist->activeWindow()) {
   _epist = epist;
   _xatom = _epist->xatom();
+  _last_active = _clients.end();
   _number = number;
-  _active = _clients.end();
   _info = _epist->getScreenInfo(_number);
   _root = _info->getRootWindow();
   
+  cout << "root window on screen " << _number << ": 0x" << hex << _root << 
+    dec << endl;
+  
   // find a window manager supporting NETWM, waiting for it to load if we must
   int count = 20;  // try for 20 seconds
   _managed = false;
@@ -76,14 +81,8 @@ screen::screen(epist *epist, int number) {
   }
  
   XSelectInput(_epist->getXDisplay(), _root, PropertyChangeMask);
-
-  updateNumDesktops();
-  updateActiveDesktop();
-  updateClientList();
-  updateActiveWindow();
 }
 
-
 screen::~screen() {
   if (_managed)
     XSelectInput(_epist->getXDisplay(), _root, None);
@@ -162,6 +161,14 @@ void screen::handleKeypress(const XEvent &e) {
     if (e.xkey.keycode == it->keycode() &&
         state == it->modifierMask()) {
       switch (it->type()) {
+      case Action::nextScreen:
+        _epist->cycleScreen(_number, true);
+        return;
+
+      case Action::prevScreen:
+        _epist->cycleScreen(_number, false);
+        return;
+
       case Action::nextWorkspace:
         cycleWorkspace(true);
         return;
@@ -179,27 +186,35 @@ void screen::handleKeypress(const XEvent &e) {
         return;
 
       case Action::nextWindowOnAllWorkspaces:
-        cycleWindow(true, true);
+        cycleWindow(true, false, true);
         return;
 
       case Action::prevWindowOnAllWorkspaces:
+        cycleWindow(false, false, true);
+        return;
+
+      case Action::nextWindowOnAllScreens:
+        cycleWindow(true, true);
+        return;
+
+      case Action::prevWindowOnAllScreens:
         cycleWindow(false, true);
         return;
 
       case Action::nextWindowOfClass:
-        cycleWindow(true, false, true, it->string());
+        cycleWindow(true, false, false, true, it->string());
         return;
 
       case Action::prevWindowOfClass:
-        cycleWindow(false, false, true, it->string());
+        cycleWindow(false, false, false, true, it->string());
         return;
 
       case Action::nextWindowOfClassOnAllWorkspaces:
-        cycleWindow(true, true, true, it->string());
+        cycleWindow(true, false, true, true, it->string());
         return;
 
       case Action::prevWindowOfClassOnAllWorkspaces:
-        cycleWindow(false, true, true, it->string());
+        cycleWindow(false, false, true, true, it->string());
         return;
 
       case Action::changeWorkspace:
@@ -312,6 +327,14 @@ bool screen::doAddWindow(Window window) const {
 }
 
 
+void screen::updateEverything() {
+  updateNumDesktops();
+  updateActiveDesktop();
+  updateClientList();
+  updateActiveWindow();
+}
+
+
 void screen::updateNumDesktops() {
   assert(_managed);
 
@@ -356,26 +379,32 @@ void screen::updateClientList() {
         break;
     if (it == end) {  // didn't already exist
       if (doAddWindow(rootclients[i])) {
-        //cout << "Added window: 0x" << hex << rootclients[i] << dec << endl;
+//        cout << "Added window: 0x" << hex << rootclients[i] << dec << endl;
         _clients.insert(insert_point, new XWindow(_epist, this,
                                                   rootclients[i]));
       }
     }
   }
 
-  // remove clients that no longer exist
+  // remove clients that no longer exist (that belong to this screen)
   for (it = _clients.begin(); it != end;) {
     WindowList::iterator it2 = it;
     ++it;
 
+    // is on another screen?
+    if ((*it2)->getScreen() != this)
+      continue;
+
     for (i = 0; i < num; ++i)
       if (**it2 == rootclients[i])
         break;
     if (i == num)  { // no longer exists
-      //cout << "Removed window: 0x" << hex << (*it2)->window() << dec << endl;
-      // watch for the active window
+//      cout << "Removed window: 0x" << hex << (*it2)->window() << dec << endl;
+      // watch for the active and last-active window
       if (it2 == _active)
         _active = _clients.end();
+      if (it2 == _last_active)
+        _last_active = _clients.end();
       delete *it2;
       _clients.erase(it2);
     }
@@ -385,6 +414,21 @@ void screen::updateClientList() {
 }
 
 
+const XWindow *screen::lastActiveWindow() const {
+  if (_last_active != _clients.end())
+    return *_last_active;
+
+  // find a window if one exists
+  WindowList::const_iterator it, end = _clients.end();
+  for (it = _clients.begin(); it != end; ++it)
+    if ((*it)->getScreen() == this)
+      return *it;
+
+  // no windows on this screen
+  return 0;
+}
+
+
 void screen::updateActiveWindow() {
   assert(_managed);
 
@@ -393,14 +437,19 @@ void screen::updateActiveWindow() {
   
   WindowList::iterator it, end = _clients.end();
   for (it = _clients.begin(); it != end; ++it) {
-    if (**it == a)
+    if (**it == a) {
+      if ((*it)->getScreen() != this)
+        return;
       break;
+    }
   }
   _active = it;
+  _last_active = it;
 
-  //cout << "Active window is now: ";
-  //if (_active == _clients.end()) cout << "None\n";
-  //else cout << "0x" << hex << (*_active)->window() << dec << endl;
+/*  cout << "Active window is now: ";
+  if (_active == _clients.end()) cout << "None\n";
+  else cout << "0x" << hex << (*_active)->window() << dec << endl;
+*/
 }
 
 
@@ -429,37 +478,42 @@ void screen::execCommand(const std::string &cmd) const {
 }
 
 
-void screen::cycleWindow(const bool forward, const bool alldesktops,
-                         const bool sameclass, const string &cn) const {
+void screen::cycleWindow(const bool forward, const bool allscreens,
+                         const bool alldesktops, const bool sameclass,
+                         const string &cn) const {
   assert(_managed);
 
+  if (_clients.empty()) return;
+  
   string classname(cn);
   if (sameclass && classname.empty() && _active != _clients.end())
     classname = (*_active)->appClass();
 
-  WindowList::const_iterator target = _active;
-
-  if (target == _clients.end())
-    target = _clients.begin();
-
-  WindowList::const_iterator begin = target;
+  WindowList::const_iterator target = _active,
+                             first = _active,
+                             begin = _clients.begin(),
+                             end = _clients.end();
  
   do {
     if (forward) {
-      ++target;
-      if (target == _clients.end())
-        target = _clients.begin();
+      if (target == end) {
+        target = begin;
+      } else {
+        ++target;
+        if (target == end)
+          target = begin;
+      }
     } else {
-      if (target == _clients.begin())
-        target = _clients.end();
+      if (target == begin)
+        target = end;
       --target;
     }
 
-    // no window to focus
-    if (target == begin)
+    // must be no window to focus
+    if (target == first)
       return;
-  } while (target == _clients.end() ||
-           (*target)->iconic() ||
+  } while ((*target)->iconic() ||
+           (! allscreens && (*target)->getScreen() != this) ||
            (! alldesktops && (*target)->desktop() != _active_desktop) ||
            (sameclass && ! classname.empty() &&
             (*target)->appClass() != classname));
index be30baa..6d0c87b 100644 (file)
@@ -46,8 +46,9 @@ class screen {
 
   std::string _wm_name;
   
-  WindowList _clients;
-  WindowList::iterator _active;
+  WindowList &_clients;
+  WindowList::iterator &_active;
+  WindowList::iterator _last_active;
   unsigned int _active_desktop;
   unsigned int _num_desktops;
 
@@ -68,12 +69,15 @@ public:
   inline Window rootWindow() const { return _root; }
   inline bool managed() const { return _managed; }
   inline int number() const { return _number; }
+
+  const XWindow *lastActiveWindow() const;
   
   void processEvent(const XEvent &e);
-
   void handleKeypress(const XEvent &e);
+  void updateEverything();
 
-  void cycleWindow(const bool forward, const bool alldesktops = false,
+  void cycleWindow(const bool forward, const bool allscreens = false,
+                   const bool alldesktops = false,
                    const bool sameclass = false,
                    const std::string &classname = "") const;
   void cycleWorkspace(const bool forward, const bool loop = true) const;
index 1874219..fdf2223 100644 (file)
@@ -80,6 +80,7 @@ public:
   XWindow(epist *epist, screen *screen, Window window);
   virtual ~XWindow();
 
+  inline screen *getScreen() const { return _screen; }
   inline Window window() const { return _window; }
   
   inline unsigned int desktop() const { return _desktop; }