Hi,

I played around a little with xinerama awhile ago, and sent the
following patch+comment to the list.  The patch is against 0.65.0, not
the newer stuff, and I haven't looked to see what's changed.  I won't
have any time to play with this for awhile, but if it helps you get
started, great!

best luck,
-emile

-----Forwarded Message-----
From: Emile Snyder <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED]
Subject: xinerama behavior RFC
Date: 30 Sep 2003 09:55:49 -0700

Hello all,

I'm new to the list, although I've been a very happy user of blackbox
for several years now.  Recently I set up my Matrox G400 dual head card
to actually use to monitors, running with Xinerama extensions (monitors
are "windows into" a larger desktop area -- ie. 2 1600x1200 monitors
side by side means your desktop is 3200x1200).  Since blackbox doesn't
do anything special when xinerama is active there's a few annoyances,
and I started tweaking.  The patch at the end of this message is an ugly
hackish way to get more natural (to my way of thinking) window
placement.  It's against 0.65.0; any pointers about the right way to do
what I did are appreciated.  Also, tips about the right diff command to
use, if this wasn't it are welcome.  Before running off and hacking more
I thought I should ask for design input...

So, does anyone else on the list use xinerama (either with blackbox or
not) and/or have any suggestions for behavior that would be nice to tune
in blackbox when using it?  Some possiblities:

* Window placement: this is the biggie for me.  I use mostly xterms plus
the odd mozilla, emacs, evolution, xmms window, etc., so have bbkeys set
up to launch my favs from key combos.  Often I'll drop xterms across the
top of a workspace like that, then run something else to fill the space
below.  When running xinerama the new app plops into the next head over,
because there's still space at the top of my 3200x1200 desktop area.  I
can think of several possible strategies that seem better to me...
  - always place windows in whatever region of the desktop the monitor
with the pointer in it covers.  (This is what I like, and the attached
patch implements it, with some bugs still.  Downside is the potential
non-intuitiveness.  Upside is that windows are associated with your
current "attention area," and it makes it easy to turn off one monitor
to save power/reduce heat some of the time.)
  - first try the region of desktop the the monitor with the pointer
covers, if there's not enough room, try the other monitors, if they
don't have enough room either, then use the monitor with the pointer
after all.  (I can see the argument for this: more intuitive for first
time user perhaps, and makes it easier to tile your workspace
appropriately.)

* Expanding windows to full screen.
Seems like it should be to full current monitor size.  Arguments
against?

* Centered dialog windows.
For instance, the mozilla download dialog pops up in the middle of the
display.  I don't know if this is being done because mozilla asks
blackbox how to put it in the middle, or because mozilla does it's own
magic, but the result is popping up spanning monitors.  Any ideas?

* Edge resistence for pointer between monitors.
Personlly I don't much care about this one.  Any strong feelings?

Thanks all for blackbox; it's my favorite window manager by far.
-emile

------------------------------------------------------------
diff -Naur blackbox-0.65.0/src/BaseDisplay.cc
blackbox-0.65.0-xineramapatched/src/BaseDisplay.cc
--- blackbox-0.65.0/src/BaseDisplay.cc  Wed Aug 28 14:31:46 2002
+++ blackbox-0.65.0-xineramapatched/src/BaseDisplay.cc  Mon Sep 29
14:24:10 2003
@@ -35,6 +35,10 @@
 #  include <X11/extensions/shape.h>
 #endif // SHAPE
 
+#ifdef    XINERAMA
+#  include <X11/extensions/Xinerama.h>
+#endif // XINERAMA
+
 #ifdef    HAVE_FCNTL_H
 #  include <fcntl.h>
 #endif // HAVE_FCNTL_H
@@ -86,6 +90,10 @@
 #include "GCCache.hh"
 #include "Timer.hh"
 #include "Util.hh"
+#include "blackbox.hh"
+#include "Screen.hh"
+#include "Workspace.hh"
+#include "Window.hh"
 

 // X error handler to handle any and all X errors while the application
is
@@ -411,6 +419,10 @@
               
HeightOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(),
                                               screen_number)));
 
+  // Figure out how many xinerama displays we have, and for each index
set the rect of it's bounding box
+  //xineramarects.push_back(rect);
+  initXineramaRects();
+
   /*
     If the default depth is at least 8 we will use that,
     otherwise we try to find the largest TrueColor visual.
@@ -466,3 +478,95 @@
   display_string = string("DISPLAY=") + default_string + '.' +
     itostring(static_cast<unsigned long>(screen_number));
 }
+
+void ScreenInfo::initXineramaRects () {
+#ifdef    XINERAMA
+    if (XineramaIsActive(basedisplay->getXDisplay())) {
+        XineramaScreenInfo *infos;
+        int n_infos;
+        int i;
+        
+        n_infos = 0;
+        infos = XineramaQueryScreens (basedisplay->getXDisplay(),
&n_infos);
+
+#ifdef DEBUG
+        fprintf(stderr, "ScreenInfo::initXineramaRects() Found %d
Xinerama screens on display %s\n",
+                n_infos, basedisplay->getXDisplayName());
+#endif // DEBUG
+
+        if (n_infos > 0) {
+            //screen->xinerama_infos = g_new (MetaXineramaScreenInfo,
n_infos);
+            //screen->n_xinerama_infos = n_infos;
+            xineramarects.resize(n_infos);
+
+            i = 0;
+            while (i < n_infos) {
+#ifdef DEBUG
+                fprintf(stderr, "ScreenInfo::initXineramaRects() infos
%d screen_number=%d, x_org=%d, y_org=%d, width=%d, height=%d\n",
+                        i, infos[i].screen_number, infos[i].x_org,
infos[i].y_org, infos[i].width, infos[i].height);
+#endif // DEBUG
+                xineramarects[i] = Rect(infos[i].x_org, infos[i].y_org,
infos[i].width, infos[i].height);
+                
+                ++i;
+            }
+        }
+        
+        if (infos)
+            XFree (infos);
+    } else {
+        //meta_topic (META_DEBUG_XINERAMA,
+        //            "No XFree86 Xinerama extension or XFree86
Xinerama inactive on display %s\n",
+        //            display->name);
+        xineramarects.push_back(rect);
+    }
+#else
+    xineramarects.push_back(rect);
+#endif // XINERAMA
+}
+
+
+//const Rect& ScreenInfo::getRect(BlackboxWindow *w) const
+const Rect& ScreenInfo::getRect(void) const
+{
+    Window root_return, child_return;
+    int root_x_return = 0;
+    int root_y_return = 0;
+    int win_x_return = 0;
+    int win_y_return = 0;
+    unsigned int mask_return = 0;
+    Bool queryreturn = XQueryPointer(basedisplay->getXDisplay(),
getRootWindow(),
+                                     &root_return, &child_return,
&root_x_return, &root_y_return,
+                                     &win_x_return, &win_y_return,
&mask_return);
+
+#ifdef    DEBUG
+    fprintf(stderr, "ScreenInfo::getRect(void): XQueryPointer returned
%d, root_x=%d root_y=%d\n", 
+            queryreturn, root_x_return, root_y_return);
+#endif // DEBUG
+
+    if (queryreturn) {
+        std::vector<Rect>::const_iterator i = xineramarects.begin();
+        while (i != xineramarects.end()) {
+            //if (w->mouseIn(*i)) { return *i; }
+            if ((i->left() <= root_x_return) && (i->right() >=
root_x_return)
+                && (i->top() <= root_y_return) && (i->bottom() >=
root_y_return)) {
+#ifdef DEBUG
+                fprintf(stderr, "ScreenInfo::getRect(void): returning
rect topLeft:(%d, %d) bottomRight:(%d, %d)\n",
+                        i->left(), i->top(), i->right(), i->bottom());
+#endif
+                //return rect;
+                return *i;
+            }
+            i++;
+        }
+    }
+
+    // Figure out which xinerama display we're on (ie. where the
pointer is)...
+    //std::vector<Rect>::const_iterator i = xineramarects.begin();
+    //while (i != xineramarects.end()) {
+    //    if (w->mouseIn(*i)) { return *i; }
+    //}
+
+    // Not on same screen as root window?
+    // Return that rect from our vector of xineramarects.        
+    return xineramarects[0];
+}
diff -Naur blackbox-0.65.0/src/BaseDisplay.hh
blackbox-0.65.0-xineramapatched/src/BaseDisplay.hh
--- blackbox-0.65.0/src/BaseDisplay.hh  Sat Jul 27 14:01:14 2002
+++ blackbox-0.65.0-xineramapatched/src/BaseDisplay.hh  Mon Sep 29
08:47:46 2003
@@ -35,6 +35,7 @@
 // forward declaration
 class BaseDisplay;
 class BGCCache;
+class BlackboxWindow;
 
 #include "Timer.hh"
 #include "Util.hh"
@@ -51,6 +52,11 @@
   std::string display_string;
   Rect rect;
 
+    /// EDS
+    std::vector<Rect> xineramarects;
+
+    void initXineramaRects();
+
 public:
   ScreenInfo(BaseDisplay *d, unsigned int num);
 
@@ -60,8 +66,9 @@
   inline Colormap getColormap(void) const { return colormap; }
   inline int getDepth(void) const { return depth; }
   inline unsigned int getScreenNumber(void) const
-    { return screen_number; }
-  inline const Rect& getRect(void) const { return rect; }
+  { return screen_number; }
+    //inline const Rect& getRect(void) const { return rect; }
+  const Rect& getRect(void) const;
   inline unsigned int getWidth(void) const { return rect.width(); }
   inline unsigned int getHeight(void) const { return rect.height(); }
   inline const std::string& displayString(void) const
diff -Naur blackbox-0.65.0/src/Makefile.am
blackbox-0.65.0-xineramapatched/src/Makefile.am
--- blackbox-0.65.0/src/Makefile.am     Tue Jun  4 09:35:51 2002
+++ blackbox-0.65.0-xineramapatched/src/Makefile.am     Mon Sep 29 00:30:50
2003
@@ -22,7 +22,7 @@
 DEFAULT_MENU=$(pkgdatadir)/menu
 DEFAULT_STYLE=$(pkgdatadir)/styles/Results
 
-CPPFLAGS= @CPPFLAGS@ @SHAPE@ @ORDEREDPSEUDO@ \
+CPPFLAGS= @CPPFLAGS@ @SHAPE@ @XINERAMA@ @ORDEREDPSEUDO@ \
 @DEBUG@ @NLS@ @TIMEDCACHE@ \
 -DLOCALEPATH=\"$(pkgdatadir)/nls\" \
 -DDEFAULTMENU=\"$(DEFAULT_MENU)\" \
diff -Naur blackbox-0.65.0/src/Screen.cc
blackbox-0.65.0-xineramapatched/src/Screen.cc
--- blackbox-0.65.0/src/Screen.cc       Wed Sep  4 10:15:58 2002
+++ blackbox-0.65.0-xineramapatched/src/Screen.cc       Mon Sep 29 14:41:49
2003
@@ -1644,6 +1644,9 @@
 const Rect& BScreen::availableArea(void) const {
   if (doFullMax())
     return getRect(); // return the full screen
+
+  //updateAvailableArea();
+  return getRect();
   return usableArea;
 }
 
diff -Naur blackbox-0.65.0/src/Window.cc
blackbox-0.65.0-xineramapatched/src/Window.cc
--- blackbox-0.65.0/src/Window.cc       Tue Sep 17 08:23:35 2002
+++ blackbox-0.65.0-xineramapatched/src/Window.cc       Mon Sep 29 13:48:52
2003
@@ -2741,11 +2741,6 @@
 

 void BlackboxWindow::motionNotifyEvent(const XMotionEvent *me) {
-#ifdef DEBUG
-  fprintf(stderr, "BlackboxWindow::motionNotifyEvent() for 0x%lx\n",
-          client.window);
-#endif
-
   if (!flags.resizing && me->state & Button1Mask && (functions &
Func_Move) &&
       (frame.title == me->window || frame.label == me->window ||
        frame.handle == me->window || frame.window == me->window)) {
diff -Naur blackbox-0.65.0/src/Window.hh
blackbox-0.65.0-xineramapatched/src/Window.hh
--- blackbox-0.65.0/src/Window.hh       Fri Aug 23 11:03:26 2002
+++ blackbox-0.65.0-xineramapatched/src/Window.hh       Mon Sep 29 13:51:13
2003
@@ -228,6 +228,7 @@
       bevel_w;
   } frame;
 
+
   BlackboxWindow(const BlackboxWindow&);
   BlackboxWindow& operator=(const BlackboxWindow&);
 
diff -Naur blackbox-0.65.0/src/Workspace.cc
blackbox-0.65.0-xineramapatched/src/Workspace.cc
--- blackbox-0.65.0/src/Workspace.cc    Fri Aug  9 23:29:42 2002
+++ blackbox-0.65.0-xineramapatched/src/Workspace.cc    Mon Sep 29 14:37:52
2003
@@ -550,6 +550,11 @@
   rectList spaces;
   spaces.push_back(availableArea); //initially the entire screen is
free
 
+#ifdef DEBUG
+  fprintf(stderr, "Workspace::smartPlacement, availableArea is (%d, %d)
-> (%d, %d)\n",
+          availableArea.left(), availableArea.top(),
availableArea.right(), availableArea.bottom());
+#endif //DEBUG
+
   //Find Free Spaces
   BlackboxWindowList::const_iterator wit = windowList.begin(),
     end = windowList.end();
@@ -593,6 +598,10 @@
 
   rectList::const_iterator sit = spaces.begin(), spaces_end =
spaces.end();
   for(; sit != spaces_end; ++sit) {
+#ifdef DEBUG
+    fprintf(stderr, "Workspace::smartPlacement, trying (%d, %d) -> (%d,
%d)\n",
+            sit->left(), sit->top(), sit->right(), sit->bottom());
+#endif // DEBUG
     if (sit->width() >= win.width() && sit->height() >= win.height())
       break;
   }
@@ -638,9 +647,16 @@
 

 void Workspace::placeWindow(BlackboxWindow *win) {
-  Rect availableArea(screen->availableArea()),
-    new_win(availableArea.x(), availableArea.y(),
-            win->frameRect().width(), win->frameRect().height());
+#ifdef DEBUG
+  fprintf(stderr, "Workspace::placeWindow about to call
screen->availableArea()\n");
+#endif
+  Rect availableArea(screen->availableArea());
+#ifdef DEBUG
+  fprintf(stderr, "Workspace::placeWindow availableArea is (%d, %d) ->
(%d, %d)\n",
+          availableArea.left(), availableArea.top(),
availableArea.right(), availableArea.bottom());
+#endif
+  Rect new_win(availableArea.x(), availableArea.y(),
+               win->frameRect().width(), win->frameRect().height());
   bool placed = False;
 
   switch (screen->getPlacementPolicy()) {
+-----------------------------------------------------------------
Outside of a dog, a book is a man's best friend. Inside of a dog, it's
too dark to read. -- Groucho Marx
+-----------------------------------------------------------------


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
List archives:  http://asgardsrealm.net/lurker/splash/index.html
Trouble? Contact [EMAIL PROTECTED]

Reply via email to