Package: qiv
Version: 2.0-3
Severity: wishlist
Tags: patch

qiv is my favourite application for setting the desktop background. However,
there is one disadvantage: qiv sets the background in a way so that
terminals with transparency support cannot grab the pixmap. To support this
the only thing to do is setting the appropriate atoms on the root window,
there is NO disadvantage (such as memory consumption).

As nearly all other background setting applications support this (and I
don't want qiv to stay behind them) I have taken the liberty and created a
patch which does exactly this.

I would be glad if this could be integrated in upstream sources.

-- System Information:
Debian Release: 3.1
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: i386 (i586)
Kernel: Linux 2.6.10-1-386
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968) (ignored: LC_ALL set to C)

Versions of packages qiv depends on:
ii  gdk-imlib1               1.9.14-16.2     imaging library for use with gtk (
ii  libc6                    2.3.2.ds1-20    GNU C Library: Shared libraries an
ii  libglib1.2               1.2.10-9        The GLib library of C routines
ii  libgtk1.2                1.2.10-17       The GIMP Toolkit set of widgets fo
ii  libx11-6                 4.3.0.dfsg.1-10 X Window System protocol client li
ii  libxext6                 4.3.0.dfsg.1-10 X Window System miscellaneous exte
ii  libxi6                   4.3.0.dfsg.1-10 X Window System Input extension li
ii  xlibs                    4.3.0.dfsg.1-10 X Keyboard Extension (XKB) configu

-- no debconf information
diff -Naur qiv-2.0/image.c qiv-2.0.edited/image.c
--- qiv-2.0/image.c	2005-02-09 00:22:26.000000000 +0100
+++ qiv-2.0.edited/image.c	2005-02-09 00:18:09.000000000 +0100
@@ -193,9 +193,16 @@
 {
   GdkWindow *root_win = GDK_ROOT_PARENT();
   GdkVisual *gvis = gdk_window_get_visual(root_win);
-  GdkPixmap *temp;
+  GdkPixmap *pixmap;
   GdkPixmap *m = NULL;
   gchar     *buffer;
+  unsigned char *data_root, *data_esetroot;
+  Display   *display=GDK_DISPLAY();
+  Atom prop_root=XInternAtom(display, "_XROOTPMAP_ID", False),
+    prop_esetroot=XInternAtom(display, "ESETROOT_PMAP_ID", False),
+    xa_pixmap=XInternAtom(display, "PIXMAP", True), prop_type;
+  int prop_format;
+  unsigned long prop_length, after;
 
   gint root_w = screen_x, root_h = screen_y;
   gint root_x = 0, root_y = 0;
@@ -227,17 +234,60 @@
   }
   
   if (to_root_t) {
-    gdk_window_set_back_pixmap(root_win, q->p, FALSE);
+    pixmap=q->p;
   } else {
     GdkGC *rootGC;
     buffer = calloc(1, screen_x * screen_y);
     rootGC = gdk_gc_new(root_win);
-    temp = gdk_pixmap_create_from_data(root_win, buffer, screen_x, 
-	       screen_y, gvis->depth, &image_bg, &image_bg);
-    gdk_draw_pixmap(temp, rootGC, q->p, 0, 0, root_x, root_y, root_w, root_h);
-    gdk_window_set_back_pixmap(root_win, temp, FALSE);
+    pixmap = gdk_pixmap_create_from_data(root_win, buffer, screen_x, 
+             screen_y, gvis->depth, &image_bg, &image_bg);
+    gdk_draw_pixmap(pixmap, rootGC, q->p, 0, 0,
+             root_x, root_y, root_w, root_h);
     gdk_gc_destroy(rootGC);
   }
+  /* Send the pixmap to the server so that it can be referenced by the
+     atoms later on. */
+  gdk_window_set_back_pixmap(root_win, pixmap, FALSE);
+
+  /* set the appropriate properties on the root window to allow other apps to
+     find the pixmap */
+  if (prop_root!=None && prop_esetroot!=None) {
+    /* NB: There once was a GDK/Imlib version of this code. It liked to
+       segfault other apps; there is obviously a discrepancy between what
+       GDK_WINDOW_XWINDOW spits out and what gdk_property_change expects. We
+       don't need GDK anyway for this code snippet since it will not get much
+       simpler with it. Give it a try again once this app has been ported to
+       Gdk/Pixbuf. */
+    Pixmap pixmap_id=GDK_WINDOW_XWINDOW(pixmap);
+    Window xwin=RootWindow(display, DefaultScreen(display));
+
+    /* test whether an existing client should be killed */
+    XGetWindowProperty(display, xwin,
+                       prop_root, 0, 1, False, AnyPropertyType,
+                       &prop_type, &prop_format, &prop_length, &after,
+                       &data_root);
+    if (prop_type==xa_pixmap) {
+      XGetWindowProperty(display, xwin,
+                         prop_esetroot, 0, 1, False, AnyPropertyType,
+                         &prop_type, &prop_format, &prop_length, &after,
+                         &data_esetroot);
+      /* If data structures match the client can be safely killed. In case of
+         data structure mismatch just ignore the client since it possibly could
+         be the window manager. Memory should not be reclaimed in this case. */
+      if (data_root&&data_esetroot&&prop_type==xa_pixmap&&
+          *((Pixmap*)data_root)==*((Pixmap*)data_esetroot))
+        /* Do NOT kill any clients. It seems that GDK is already taking care
+           of killing the pixmap if set with gdk_window_set_back_pixmap.
+           XKillClient(display, *((Pixmap*)data_root)) */;
+    }
+
+    /* really change the property now */
+    XChangeProperty(display, xwin, prop_root, xa_pixmap, 32,
+                    PropModeReplace, (unsigned char*)&pixmap_id, 1);
+    XChangeProperty(display, xwin, prop_esetroot, xa_pixmap, 32,
+                    PropModeReplace, (unsigned char*)&pixmap_id, 1);
+    XSetCloseDownMode(display, RetainPermanent);
+  }
 
   gdk_window_clear(root_win);
   gdk_flush();

Reply via email to