From 5fec1906cc4faf83ec2424aa48c2a050b0254d15 Mon Sep 17 00:00:00 2001
From: simonb <simonb>
Date: Tue, 10 May 2005 16:29:00 +0000
Subject: cache the root pixmap (per screen)

---
 ChangeLog            |   3 ++
 src/FbTk/FbPixmap.cc | 141 ++++++++++++++++++++++++++++++++++++++-------------
 src/FbTk/FbPixmap.hh |   9 ++++
 src/fluxbox.cc       |   9 +++-
 4 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 294c1db..81a6bd6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,9 @@
 (Format: Year/Month/Day)
 Changes for 0.9.13
 *05/05/10:
+  * Cache root pixmap, watch for property changes (Simon)
+    (previously was checked EVERY time = lots)
+    FbTk/FbPixmap.hh/cc fluxbox.cc
   * minor tweak to configure.in (thanx php-coder)
 *05/05/09:
   * Fix for fbrun and completion (thanx Vadim)
diff --git a/src/FbTk/FbPixmap.cc b/src/FbTk/FbPixmap.cc
index b2937c3..ce28f0e 100644
--- a/src/FbTk/FbPixmap.cc
+++ b/src/FbTk/FbPixmap.cc
@@ -24,6 +24,7 @@
 #include "FbPixmap.hh"
 #include "App.hh"
 #include "GContext.hh"
+#include "Transparent.hh"
 
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
@@ -34,6 +35,22 @@ using namespace std;
 
 namespace FbTk {
 
+Pixmap *FbPixmap::m_root_pixmaps = 0;
+
+const char* FbPixmap::root_prop_ids[] = {
+    "_XROOTPMAP_ID",
+    "_XSETROOT_ID",
+    0
+};
+
+// same number as in root_prop_ids
+Atom FbPixmap::root_prop_atoms[] = {
+    None,
+    None,
+    None
+};
+
+
 FbPixmap::FbPixmap():m_pm(0),
                      m_width(0), m_height(0),
                      m_depth(0) {
@@ -297,53 +314,107 @@ Pixmap FbPixmap::release() {
     return ret;
 }
 
+void FbPixmap::rootwinPropertyNotify(int screen_num, Atom atom) {
+    if (!FbTk::Transparent::haveRender()) 
+        return;
+
+    checkAtoms();
+    for (int i=0; root_prop_ids[i] != 0; ++i) {
+        if (root_prop_atoms[i] == atom) {
+            Pixmap root_pm = None;
+            Atom real_type;
+            int real_format;
+            unsigned long items_read, items_left;
+            unsigned long *data;
+
+            unsigned int prop = 0;
+            if (XGetWindowProperty(display(),
+                                   RootWindow(display(), i),
+                                   root_prop_atoms[i],
+                                   0l, 1l,
+                                   False, XA_PIXMAP,
+                                   &real_type, &real_format,
+                                   &items_read, &items_left,
+                                   (unsigned char **) &data) == Success) {
+                if (real_format == 32 && items_read == 1) {
+                    root_pm = (Pixmap) (*data);
+                }
+                XFree(data);
+                if (root_pm != None)
+                    setRootPixmap(screen_num, root_pm);
+            }
+            break;
+        }
+    }
+}
+
+void FbPixmap::setRootPixmap(int screen_num, Pixmap pm) {
+    if (!m_root_pixmaps) {
+        m_root_pixmaps = new Pixmap[ScreenCount(display())];
+    }
+
+    m_root_pixmaps[screen_num] = pm;
+}
+
 Pixmap FbPixmap::getRootPixmap(int screen_num) {
+    if (!FbTk::Transparent::haveRender()) 
+        return None;
+
+    if (!m_root_pixmaps) {
+        int numscreens = ScreenCount(display());
+        for (int i=0; i < numscreens; ++i) {
+            Atom real_type;
+            int real_format;
+            unsigned long items_read, items_left;
+            unsigned long *data;
 
-    Atom real_type;
-    int real_format;
-    unsigned long items_read, items_left;
-    unsigned long *data;
-
-    unsigned int prop = 0;
-    static const char* prop_ids[] = {
-      "_XROOTPMAP_ID",
-      "_XSETROOT_ID",
-      0
-    };
-    static bool print_error = true; // print error_message only once
-    static const char* error_message = { "\n\n !!! WARNING WARNING WARNING WARNING !!!!!\n"
+            unsigned int prop = 0;
+
+            static bool print_error = true; // print error_message only once
+            static const char* error_message = { "\n\n !!! WARNING WARNING WARNING WARNING !!!!!\n"
         "   if you experience problems with transparency:\n"
         "   you are using a wallpapersetter that \n"
         "   uses _XSETROOT_ID .. which we do not support.\n"
         "   consult 'fbsetbg -i' or try any other wallpapersetter\n"
         "   that uses _XROOTPMAP_ID !\n"
         " !!! WARNING WARNING WARNING WARNING !!!!!!\n\n"
-    };
-
-    Pixmap root_pm = None;
-    for (prop = 0; prop_ids[prop]; prop++) {
-        if (XGetWindowProperty(display(),
-                               RootWindow(display(), screen_num),
-                               XInternAtom(display(), prop_ids[prop], False),
-                               0l, 1l,
-                               False, XA_PIXMAP,
-                               &real_type, &real_format,
-                               &items_read, &items_left,
-                               (unsigned char **) &data) == Success) {
-            if (real_format == 32 && items_read == 1) {
-                if (print_error && strcmp(prop_ids[prop], "_XSETROOT_ID") == 0) {
-                    cerr<<error_message;
-                    print_error = false;
-                } else
-                    root_pm = (Pixmap) (*data);
+            };
+
+            Pixmap root_pm = None;
+            for (prop = 0; root_prop_ids[prop]; prop++) {
+                checkAtoms();
+                if (XGetWindowProperty(display(),
+                                       RootWindow(display(), i),
+                                       root_prop_atoms[i],
+                                       0l, 1l,
+                                       False, XA_PIXMAP,
+                                       &real_type, &real_format,
+                                       &items_read, &items_left,
+                                       (unsigned char **) &data) == Success) {
+                    if (real_format == 32 && items_read == 1) {
+                        if (print_error && strcmp(root_prop_ids[prop], "_XSETROOT_ID") == 0) {
+                            cerr<<error_message;
+                            print_error = false;
+                        } else
+                            root_pm = (Pixmap) (*data);
+                    }
+                    XFree(data);
+                    if (root_pm != None)
+                        break;
+                }
             }
-            XFree(data);
-            if (root_pm != None)
-                break;
+            setRootPixmap(i, root_pm);
         }
     }
+    return m_root_pixmaps[screen_num];
+}
 
-    return root_pm;
+void FbPixmap::checkAtoms() {
+    for (int i=0; root_prop_ids[i] != 0; ++i) {
+        if (root_prop_atoms[i] == None) {
+            root_prop_atoms[i] = XInternAtom(display(), root_prop_ids[i], False);
+        }
+    }
 }
 
 void FbPixmap::free() {
diff --git a/src/FbTk/FbPixmap.hh b/src/FbTk/FbPixmap.hh
index c8640a2..ca81cf4 100644
--- a/src/FbTk/FbPixmap.hh
+++ b/src/FbTk/FbPixmap.hh
@@ -69,6 +69,7 @@ public:
     inline int depth() const { return m_depth; }
 
     static Pixmap getRootPixmap(int screen_num);
+    static void FbPixmap::rootwinPropertyNotify(int screen_num, Atom atom);
 
     void create(Drawable src,
                 unsigned int width, unsigned int height,
@@ -79,6 +80,14 @@ private:
     Pixmap m_pm;
     unsigned int m_width, m_height;
     int m_depth;
+
+    /// Functions relating to the maintenance of root window pixmap caching
+    static void checkAtoms();
+    static void setRootPixmap(int screen_num, Pixmap pm);
+    // array of pixmaps: 1 per screen
+    static Pixmap *m_root_pixmaps;
+    static const char *root_prop_ids[];
+    static Atom  root_prop_atoms[];
 };
 
 } // end namespace FbTk
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 271d93f..f01224f 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -657,8 +657,15 @@ void Fluxbox::handleEvent(XEvent * const e) {
                e->type == LeaveNotify) {
         m_last_time = e->xcrossing.time;
         m_mousescreen = searchScreen(e->xcrossing.root);
-    } else if (e->type == PropertyNotify)
+    } else if (e->type == PropertyNotify) {
         m_last_time = e->xproperty.time;
+        // check transparency atoms if it's a root pm
+        
+        BScreen *screen = searchScreen(e->xproperty.window);
+        if (screen) {
+            FbTk::FbPixmap::rootwinPropertyNotify(screen->screenNumber(), e->xproperty.atom);
+        }
+    }
 
     // we need to check focus out for menus before
     // we call FbTk eventhandler
-- 
cgit v0.11.2