Sophie

Sophie

distrib > Mageia > 9 > x86_64 > by-pkgid > 772338c169ab61c8592d9b95c518a666 > files > 2

lxappearance-obconf-0.2.3-3.git20190221.5.mga9.src.rpm

From b24a454ba8dff76720bb0289076eac054c2e4922 Mon Sep 17 00:00:00 2001
From: bill-auger <mr.j.spam.me@gmail.com>
Date: Mon, 2 Nov 2020 19:04:46 -0500
Subject: complete GTK3 preview implementation (closes sf#768)

the GTK3 preview did not render properly, because it attempted to mimic the GTK2
code too closely - the function which draws to the gdk-pixbuf (the return value
of the drawing functions), and its GDK2 counterpart which it replaced, did not
have feature-parity - i could not find a replacement which does - some of the
features of gdk-pixbuf2 appear to be incompatible with GTK3

the GTK2-compatible function recycled the target gdk-pixbuf, composing the final
graphic, layer upon layer, with each call - however, each call to the replacement
function for GTK3, clobbered the previous gdk-pixbuf; such that the final graphic
represented only the work done in the last call; and so the returned graphic was
much smaller than expected

instead, this change does the incremental compositing, using cairo drawing surfaces,
then finally copies the composite at once, onto the GDK pixbuf which is used by the
GTK2 implementation, and returned per the 'preview_menu' and 'preview_window'
function contracts)
---
 src/preview.c | 363 ++++++++++++++++++++++------------------------------------
 1 file changed, 135 insertions(+), 228 deletions(-)

diff --git a/src/preview.c b/src/preview.c
index a2fc63d..75005f5 100644
--- a/src/preview.c
+++ b/src/preview.c
@@ -17,6 +17,12 @@
    See the COPYING file for a copy of the GNU General Public License.
 */
 
+/*
+ * This file was taken from ObConf; and some modifications were done
+ * to make it a loadable module of LXAppearance.
+ * Later, it was modified to support GTK3, in addition to GTK2.
+ */
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -47,6 +53,14 @@ GdkPixbuf *preview_theme(const gchar *name, const gchar *titlelayout,
                          RrFont *osd_active_font,
                          RrFont *osd_inactive_font);
 
+typedef struct _CairoComposeParams {
+    Display *display;             /* xLib Display */
+    cairo_t *context;             /* cairo context for compositing surface */
+    Visual *visual;               /* xLib display Visual */
+    cairo_surface_t *surface_src; /* RrAppearance.Pixmap conversion surface */
+
+} CairoComposeParams;
+
 /* End forwarded */
 
 static void theme_pixmap_paint(RrAppearance *a, gint w, gint h)
@@ -61,6 +75,80 @@ static guint32 rr_color_pixel(const RrColor *c)
                      + (RrColorBlue(c) << 8) + 0xff);
 }
 
+/*! Initialize a Cairo context and surface
+    to be used for compositing various Openbox themed window decoration
+    for the "Window Border" preview pane.
+    These will presumably be destroyed in finalize_composition()
+    after any number of rendering passes through compose_surface()
+    @param params  pointer to a CairoComposeParams struct
+                   which is to describe/hold the destination Cairo context
+    @param w       the desired width of the composite image
+    @param h       the desired height of the composite image
+    @return        returns a new Cairo sufrace */
+static cairo_surface_t* initialize_composite(CairoComposeParams *params,
+                                             gint w, gint h)
+{
+  cairo_surface_t* surface;
+
+  surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
+  params->display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+  params->context = cairo_create(surface);
+  params->visual = DefaultVisual(params->display, 0);
+
+  return surface;
+}
+
+/*! Compose a pre-rendered preview of an Openbox themed window decoration
+    as a layer onto a composite Cairo surface,
+    as created in initialize_composite().
+    @param params     pointer to a CairoComposeParams struct
+                      describing/holding the destination Cairo context
+    @param appearance pointer to an RrAppearance struct, belonging to an RrTheme
+                      to be used as the layer source
+    @param x          the destination x coordinate, for source pixel 0,0
+    @param y          the destination y coordinate, for source pixel 0,0
+    @param w          the width of the source RrAppearance Pixmap
+    @param h          the height of the source RrAppearance Pixmap
+    @return           returns void */
+static void compose_surface(CairoComposeParams *params, RrAppearance *appearance,
+                            gint x, gint y, gint w, gint h)
+{
+    params->surface_src = cairo_xlib_surface_create(params->display,
+                                                    appearance->pixmap,
+                                                    params->visual,
+                                                    w, h);
+
+    cairo_set_source_surface(params->context, params->surface_src, x, y);
+    cairo_paint(params->context);
+
+    cairo_surface_destroy(params->surface_src);
+}
+
+/*! Copy composed Cairo surface onto a new GdkPixbuf;
+    then destroy the source Cairo context and underlying composite surface.
+    These were presumably created in initialize_composite().
+    @param params  pointer to a CairoComposeParams struct
+                   describeing/holding the Cairo context to be destroyed
+    @param surface pointer to a cairo_surface_t
+                   to be used as the source for the GdkPixbuf,
+                   then destroyed
+    @param w       the width of the composite image
+    @param h       the height of the composite image
+    @return        returns a new GdkPixbuf */
+static GdkPixbuf* finalize_composition(CairoComposeParams *params,
+                                       cairo_surface_t *surface,
+                                       gint w, gint h)
+{
+  GdkPixbuf *pixbuf;
+
+  pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, w, h);
+
+  cairo_surface_destroy(surface);
+  cairo_destroy(params->context);
+
+  return pixbuf;
+}
+
 /* XXX: Make this more general */
 static GdkPixbuf* preview_menu(RrTheme *theme)
 {
@@ -75,8 +163,8 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
     RrAppearance *selected;
     RrAppearance *bullet; /* for submenu */
 #if GTK_CHECK_VERSION(3, 0, 0)
-    cairo_surface_t *surface;
-    Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+    cairo_surface_t *surface; /* compositing destination, source for pixbuf */
+    CairoComposeParams compose_params; /* composite surface context */
 #else
     GdkPixmap *pixmap;
 #endif
@@ -130,6 +218,11 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
 
     //height += 3*th + 3*theme->mbwidth + 5*PADDING;
 
+#if GTK_CHECK_VERSION(3, 0, 0)
+    /* initialize cairo context and composite destination surface */
+    surface = initialize_composite(&compose_params, width, height);
+#endif
+
     /* set border */
     pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
     gdk_pixbuf_fill(pixbuf, rr_color_pixel(theme->menu_border_color));
@@ -145,20 +238,7 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
     theme_pixmap_paint(title_text, bw, title_h);
 
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   title_text->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        bw,
-                                        title_h);
-
-   cairo_surface_destroy(surface);
-
+    compose_surface(&compose_params, title_text, x, y, bw, title_h);
 #else
     pixmap = gdk_pixmap_foreign_new(title_text->pixmap);
     pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -174,20 +254,7 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
     theme_pixmap_paint(menu, bw, th);
 
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   menu->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        bw,
-                                        th);
-
-   cairo_surface_destroy(surface);
-
+    compose_surface(&compose_params, menu, x, y, bw, th);
 #else
     pixmap = gdk_pixmap_foreign_new(menu->pixmap);
     pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -204,20 +271,7 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
     /* draw background for normal entry */
     theme_pixmap_paint(background, bw, bh);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   background->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        bw,
-                                        bh);
-
-   cairo_surface_destroy(surface);
-
+    compose_surface(&compose_params, background, x, y, bw, bh);
 #else
     pixmap = gdk_pixmap_foreign_new(background->pixmap);
     pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -234,20 +288,7 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
     RrMinSize(normal, &tw, &th);
     theme_pixmap_paint(normal, tw, th);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   normal->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        tw,
-                                        th);
-
-   cairo_surface_destroy(surface);
-
+    compose_surface(&compose_params, normal, x, y, tw, th);
 #else
     pixmap = gdk_pixmap_foreign_new(normal->pixmap);
     pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -262,20 +303,7 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
     bullet->surface.parenty = PADDING;
     theme_pixmap_paint(bullet, th, th);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   bullet->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   width - theme->mbwidth - th,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        th,
-                                        th);
-
-   cairo_surface_destroy(surface);
-
+    compose_surface(&compose_params, bullet, width - theme->mbwidth - th, y, th, th);
 #else
     pixmap = gdk_pixmap_foreign_new(bullet->pixmap);
     pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -289,20 +317,8 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
     background->surface.parenty = bh;
     theme_pixmap_paint(background, bw, bh);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   background->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x - PADDING,
-                                                   y - PADDING);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        bw,
-                                        bh);
-
-   cairo_surface_destroy(surface);
-
+    compose_surface(&compose_params, background,
+                    x - PADDING, y - PADDING, bw, bh);
 #else
     pixmap = gdk_pixmap_foreign_new(background->pixmap);
     pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -317,20 +333,7 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
     disabled->surface.parenty = PADDING;
     theme_pixmap_paint(disabled, tw, th);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   disabled->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        tw,
-                                        th);
-
-   cairo_surface_destroy(surface);
-
+    compose_surface(&compose_params, disabled, x, y, tw, th);
 #else
     pixmap = gdk_pixmap_foreign_new(disabled->pixmap);
     pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -346,20 +349,8 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
 
     theme_pixmap_paint(background, bw, bh);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   background->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x - PADDING,
-                                                   y - PADDING);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        bw,
-                                        bh);
-
-   cairo_surface_destroy(surface);
-
+    compose_surface(&compose_params, background,
+                    x - PADDING, y - PADDING, bw, bh);
 #else
     pixmap = gdk_pixmap_foreign_new(background->pixmap);
     pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -375,26 +366,21 @@ static GdkPixbuf* preview_menu(RrTheme *theme)
     selected->surface.parenty = PADDING;
     theme_pixmap_paint(selected, tw, th);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   selected->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        tw,
-                                        th);
-
-   cairo_surface_destroy(surface);
-
+    compose_surface(&compose_params, selected, x, y, tw, th);
 #else
     pixmap = gdk_pixmap_foreign_new(selected->pixmap);
     pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                           gdk_colormap_get_system(),
                                           0, 0, x, y, tw, th);
 #endif
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+    // copy composed cairo surface to GDK pixbuf
+    pixbuf = finalize_composition(&compose_params, surface, width, height);
+#else
+    ; // the GTK2 paths have composed onto the GDK pixbuf directly
+#endif
+
     return pixbuf;
 }
 
@@ -405,8 +391,8 @@ static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout,
     RrAppearance *handle;
     RrAppearance *a;
 #if GTK_CHECK_VERSION(3, 0, 0)
-    cairo_surface_t *surface;
-    Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+    cairo_surface_t *surface; /* compositing destination, source for pixbuf */
+    CairoComposeParams compose_params; /* composite surface context */
 #else
     GdkPixmap *pixmap;
 #endif
@@ -417,6 +403,11 @@ static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout,
 
     const gchar *layout;
 
+#if GTK_CHECK_VERSION(3, 0, 0)
+    /* initialize cairo context and composite destination surface */
+    surface = initialize_composite(&compose_params, width, height);
+#endif
+
     title = focus ? theme->a_focused_title : theme->a_unfocused_title;
 
     /* set border */
@@ -433,20 +424,7 @@ static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout,
 
     x = y = theme->fbwidth;
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   title->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        w,
-                                        h);
-
-   cairo_surface_destroy(surface);
-
+    compose_surface(&compose_params, title, x, y, w, h);
 #else
     pixmap = gdk_pixmap_foreign_new(title->pixmap);
     pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -494,20 +472,7 @@ static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout,
 
             theme_pixmap_paint(a, w, h);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   a->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        w,
-                                        h);
-
-   cairo_surface_destroy(surface);
-
+            compose_surface(&compose_params, a, x, y, w, h);
 #else
             pixmap = gdk_pixmap_foreign_new(a->pixmap);
             pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -528,20 +493,7 @@ static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout,
 
             theme_pixmap_paint(a, w, h);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   a->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        w,
-                                        h);
-
-   cairo_surface_destroy(surface);
-
+            compose_surface(&compose_params, a, x, y, w, h);
 #else
             pixmap = gdk_pixmap_foreign_new(a->pixmap);
             pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -616,20 +568,7 @@ static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout,
 
             theme_pixmap_paint(a, w, h);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   a->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y + 1);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        w,
-                                        h);
-
-   cairo_surface_destroy(surface);
-
+            compose_surface(&compose_params, a, x, y + 1, w, h);
 #else
             pixmap = gdk_pixmap_foreign_new(a->pixmap);
             /* use y + 1 because these buttons should be centered wrt the label
@@ -653,20 +592,7 @@ static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout,
 
         theme_pixmap_paint(handle, w, h);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   handle->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        w,
-                                        h);
-
-   cairo_surface_destroy(surface);
-
+        compose_surface(&compose_params, handle, x, y, w, h);
 #else
         pixmap = gdk_pixmap_foreign_new(handle->pixmap);
         pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -691,20 +617,7 @@ static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout,
 
         theme_pixmap_paint(a, w, h);
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   a->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        w,
-                                        h);
-
-   cairo_surface_destroy(surface);
-
+        compose_surface(&compose_params, a, x, y, w, h);
 #else
         pixmap = gdk_pixmap_foreign_new(a->pixmap);
         pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
@@ -715,20 +628,7 @@ static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout,
         /* right grip */
         x = width - theme->fbwidth - theme->grip_width;
 #if GTK_CHECK_VERSION(3, 0, 0)
-    surface = cairo_xlib_surface_create(dpy,
-                                                   a->pixmap,
-                                                   DefaultVisual(dpy, 0),
-                                                   x,
-                                                   y);
-
-    pixbuf = gdk_pixbuf_get_from_surface(surface,
-                                        0,
-                                        0,
-                                        w,
-                                        h);
-
-   cairo_surface_destroy(surface);
-
+        compose_surface(&compose_params, a, x, y, w, h);
 #else
         pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                               gdk_colormap_get_system(),
@@ -736,6 +636,13 @@ static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout,
 #endif
     }
 
+#if GTK_CHECK_VERSION(3, 0, 0)
+    // copy composed cairo surface into GDK pixbuf
+    pixbuf = finalize_composition(&compose_params, surface, width, height);
+#else
+    ; // the GTK2 paths have composed onto the GDK pixbuf directly
+#endif
+
     /* title separator colour */
     x = theme->fbwidth;
     y = theme->fbwidth + theme->title_height;
-- 
cgit v1.2.2