Ticket #11679: lxappearance-obconf-gtk3_preview.patch
File lxappearance-obconf-gtk3_preview.patch, 23.2 KB (added by , 2 years ago) |
---|
-
src/preview.c
From ccede6fe71312498f7e85a231e6a0678e375cdf6 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 #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 compositing with cairo using cairo drawing surfaces, then finally copying at once onto the GDK pixbuf used by the GTK2 implementation (per the function contract), just before returning it --- 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 b 17 17 See the COPYING file for a copy of the GNU General Public License. 18 18 */ 19 19 20 /* 21 * This file was taken from ObConf; and some modifications were done 22 * to make it a loadable module of LXAppearance. 23 * Later, it was modified to support GTK3, in addition to GTK2. 24 */ 25 20 26 #ifdef HAVE_CONFIG_H 21 27 #include <config.h> 22 28 #endif … … GdkPixbuf *preview_theme(const gchar *name, const gchar *titlelayout, 47 53 RrFont *osd_active_font, 48 54 RrFont *osd_inactive_font); 49 55 56 typedef struct _CairoComposeParams { 57 Display *display; /* xLib Display */ 58 cairo_t *context; /* cairo context for compositing surface */ 59 Visual *visual; /* xLib display Visual */ 60 cairo_surface_t *surface_src; /* RrAppearance.Pixmap conversion surface */ 61 62 } CairoComposeParams; 63 50 64 /* End forwarded */ 51 65 52 66 static void theme_pixmap_paint(RrAppearance *a, gint w, gint h) … … static guint32 rr_color_pixel(const RrColor *c) 61 75 + (RrColorBlue(c) << 8) + 0xff); 62 76 } 63 77 78 /*! Initialize a Cairo context and surface 79 to be used for compositing various Openbox themed window decoration 80 for the "Window Border" preview pane. 81 These will presumably be destroyed in finalize_composition() 82 after any number of rendering passes through compose_surface() 83 @param params pointer to a CairoComposeParams struct 84 which is to describe/hold the destination Cairo context 85 @param w the desired width of the composite image 86 @param h the desired height of the composite image 87 @return returns a new Cairo sufrace */ 88 static cairo_surface_t* initialize_composite(CairoComposeParams *params, 89 gint w, gint h) 90 { 91 cairo_surface_t* surface; 92 93 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); 94 params->display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); 95 params->context = cairo_create(surface); 96 params->visual = DefaultVisual(params->display, 0); 97 98 return surface; 99 } 100 101 /*! Compose a pre-rendered preview of an Openbox themed window decoration 102 as a layer onto a composite Cairo surface, 103 as created in initialize_composite(). 104 @param params pointer to a CairoComposeParams struct 105 describing/holding the destination Cairo context 106 @param appearance pointer to an RrAppearance struct, belonging to an RrTheme 107 to be used as the layer source 108 @param x the destination x coordinate, for source pixel 0,0 109 @param y the destination y coordinate, for source pixel 0,0 110 @param w the width of the source RrAppearance Pixmap 111 @param h the height of the source RrAppearance Pixmap 112 @return returns void */ 113 static void compose_surface(CairoComposeParams *params, RrAppearance *appearance, 114 gint x, gint y, gint w, gint h) 115 { 116 params->surface_src = cairo_xlib_surface_create(params->display, 117 appearance->pixmap, 118 params->visual, 119 w, h); 120 121 cairo_set_source_surface(params->context, params->surface_src, x, y); 122 cairo_paint(params->context); 123 124 cairo_surface_destroy(params->surface_src); 125 } 126 127 /*! Copy composed Cairo surface onto a new GdkPixbuf; 128 then destroy the source Cairo context and underlying composite surface. 129 These were presumably created in initialize_composite(). 130 @param params pointer to a CairoComposeParams struct 131 describeing/holding the Cairo context to be destroyed 132 @param surface pointer to a cairo_surface_t 133 to be used as the source for the GdkPixbuf, 134 then destroyed 135 @param w the width of the composite image 136 @param h the height of the composite image 137 @return returns a new GdkPixbuf */ 138 static GdkPixbuf* finalize_composition(CairoComposeParams *params, 139 cairo_surface_t *surface, 140 gint w, gint h) 141 { 142 GdkPixbuf *pixbuf; 143 144 pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, w, h); 145 146 cairo_surface_destroy(surface); 147 cairo_destroy(params->context); 148 149 return pixbuf; 150 } 151 64 152 /* XXX: Make this more general */ 65 153 static GdkPixbuf* preview_menu(RrTheme *theme) 66 154 { … … static GdkPixbuf* preview_menu(RrTheme *theme) 75 163 RrAppearance *selected; 76 164 RrAppearance *bullet; /* for submenu */ 77 165 #if GTK_CHECK_VERSION(3, 0, 0) 78 cairo_surface_t *surface; 79 Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());166 cairo_surface_t *surface; /* compositing destination, source for pixbuf */ 167 CairoComposeParams compose_params; /* composite surface context */ 80 168 #else 81 169 GdkPixmap *pixmap; 82 170 #endif … … static GdkPixbuf* preview_menu(RrTheme *theme) 130 218 131 219 //height += 3*th + 3*theme->mbwidth + 5*PADDING; 132 220 221 #if GTK_CHECK_VERSION(3, 0, 0) 222 /* initialize cairo context and composite destination surface */ 223 surface = initialize_composite(&compose_params, width, height); 224 #endif 225 133 226 /* set border */ 134 227 pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); 135 228 gdk_pixbuf_fill(pixbuf, rr_color_pixel(theme->menu_border_color)); … … static GdkPixbuf* preview_menu(RrTheme *theme) 145 238 theme_pixmap_paint(title_text, bw, title_h); 146 239 147 240 #if GTK_CHECK_VERSION(3, 0, 0) 148 surface = cairo_xlib_surface_create(dpy, 149 title_text->pixmap, 150 DefaultVisual(dpy, 0), 151 x, 152 y); 153 154 pixbuf = gdk_pixbuf_get_from_surface(surface, 155 0, 156 0, 157 bw, 158 title_h); 159 160 cairo_surface_destroy(surface); 161 241 compose_surface(&compose_params, title_text, x, y, bw, title_h); 162 242 #else 163 243 pixmap = gdk_pixmap_foreign_new(title_text->pixmap); 164 244 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_menu(RrTheme *theme) 174 254 theme_pixmap_paint(menu, bw, th); 175 255 176 256 #if GTK_CHECK_VERSION(3, 0, 0) 177 surface = cairo_xlib_surface_create(dpy, 178 menu->pixmap, 179 DefaultVisual(dpy, 0), 180 x, 181 y); 182 183 pixbuf = gdk_pixbuf_get_from_surface(surface, 184 0, 185 0, 186 bw, 187 th); 188 189 cairo_surface_destroy(surface); 190 257 compose_surface(&compose_params, menu, x, y, bw, th); 191 258 #else 192 259 pixmap = gdk_pixmap_foreign_new(menu->pixmap); 193 260 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_menu(RrTheme *theme) 204 271 /* draw background for normal entry */ 205 272 theme_pixmap_paint(background, bw, bh); 206 273 #if GTK_CHECK_VERSION(3, 0, 0) 207 surface = cairo_xlib_surface_create(dpy, 208 background->pixmap, 209 DefaultVisual(dpy, 0), 210 x, 211 y); 212 213 pixbuf = gdk_pixbuf_get_from_surface(surface, 214 0, 215 0, 216 bw, 217 bh); 218 219 cairo_surface_destroy(surface); 220 274 compose_surface(&compose_params, background, x, y, bw, bh); 221 275 #else 222 276 pixmap = gdk_pixmap_foreign_new(background->pixmap); 223 277 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_menu(RrTheme *theme) 234 288 RrMinSize(normal, &tw, &th); 235 289 theme_pixmap_paint(normal, tw, th); 236 290 #if GTK_CHECK_VERSION(3, 0, 0) 237 surface = cairo_xlib_surface_create(dpy, 238 normal->pixmap, 239 DefaultVisual(dpy, 0), 240 x, 241 y); 242 243 pixbuf = gdk_pixbuf_get_from_surface(surface, 244 0, 245 0, 246 tw, 247 th); 248 249 cairo_surface_destroy(surface); 250 291 compose_surface(&compose_params, normal, x, y, tw, th); 251 292 #else 252 293 pixmap = gdk_pixmap_foreign_new(normal->pixmap); 253 294 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_menu(RrTheme *theme) 262 303 bullet->surface.parenty = PADDING; 263 304 theme_pixmap_paint(bullet, th, th); 264 305 #if GTK_CHECK_VERSION(3, 0, 0) 265 surface = cairo_xlib_surface_create(dpy, 266 bullet->pixmap, 267 DefaultVisual(dpy, 0), 268 width - theme->mbwidth - th, 269 y); 270 271 pixbuf = gdk_pixbuf_get_from_surface(surface, 272 0, 273 0, 274 th, 275 th); 276 277 cairo_surface_destroy(surface); 278 306 compose_surface(&compose_params, bullet, width - theme->mbwidth - th, y, th, th); 279 307 #else 280 308 pixmap = gdk_pixmap_foreign_new(bullet->pixmap); 281 309 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_menu(RrTheme *theme) 289 317 background->surface.parenty = bh; 290 318 theme_pixmap_paint(background, bw, bh); 291 319 #if GTK_CHECK_VERSION(3, 0, 0) 292 surface = cairo_xlib_surface_create(dpy, 293 background->pixmap, 294 DefaultVisual(dpy, 0), 295 x - PADDING, 296 y - PADDING); 297 298 pixbuf = gdk_pixbuf_get_from_surface(surface, 299 0, 300 0, 301 bw, 302 bh); 303 304 cairo_surface_destroy(surface); 305 320 compose_surface(&compose_params, background, 321 x - PADDING, y - PADDING, bw, bh); 306 322 #else 307 323 pixmap = gdk_pixmap_foreign_new(background->pixmap); 308 324 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_menu(RrTheme *theme) 317 333 disabled->surface.parenty = PADDING; 318 334 theme_pixmap_paint(disabled, tw, th); 319 335 #if GTK_CHECK_VERSION(3, 0, 0) 320 surface = cairo_xlib_surface_create(dpy, 321 disabled->pixmap, 322 DefaultVisual(dpy, 0), 323 x, 324 y); 325 326 pixbuf = gdk_pixbuf_get_from_surface(surface, 327 0, 328 0, 329 tw, 330 th); 331 332 cairo_surface_destroy(surface); 333 336 compose_surface(&compose_params, disabled, x, y, tw, th); 334 337 #else 335 338 pixmap = gdk_pixmap_foreign_new(disabled->pixmap); 336 339 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_menu(RrTheme *theme) 346 349 347 350 theme_pixmap_paint(background, bw, bh); 348 351 #if GTK_CHECK_VERSION(3, 0, 0) 349 surface = cairo_xlib_surface_create(dpy, 350 background->pixmap, 351 DefaultVisual(dpy, 0), 352 x - PADDING, 353 y - PADDING); 354 355 pixbuf = gdk_pixbuf_get_from_surface(surface, 356 0, 357 0, 358 bw, 359 bh); 360 361 cairo_surface_destroy(surface); 362 352 compose_surface(&compose_params, background, 353 x - PADDING, y - PADDING, bw, bh); 363 354 #else 364 355 pixmap = gdk_pixmap_foreign_new(background->pixmap); 365 356 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_menu(RrTheme *theme) 375 366 selected->surface.parenty = PADDING; 376 367 theme_pixmap_paint(selected, tw, th); 377 368 #if GTK_CHECK_VERSION(3, 0, 0) 378 surface = cairo_xlib_surface_create(dpy, 379 selected->pixmap, 380 DefaultVisual(dpy, 0), 381 x, 382 y); 383 384 pixbuf = gdk_pixbuf_get_from_surface(surface, 385 0, 386 0, 387 tw, 388 th); 389 390 cairo_surface_destroy(surface); 391 369 compose_surface(&compose_params, selected, x, y, tw, th); 392 370 #else 393 371 pixmap = gdk_pixmap_foreign_new(selected->pixmap); 394 372 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, 395 373 gdk_colormap_get_system(), 396 374 0, 0, x, y, tw, th); 397 375 #endif 376 377 #if GTK_CHECK_VERSION(3, 0, 0) 378 // copy composed cairo surface to GDK pixbuf 379 pixbuf = finalize_composition(&compose_params, surface, width, height); 380 #else 381 ; // the GTK2 paths have composed onto the GDK pixbuf directly 382 #endif 383 398 384 return pixbuf; 399 385 } 400 386 … … static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, 405 391 RrAppearance *handle; 406 392 RrAppearance *a; 407 393 #if GTK_CHECK_VERSION(3, 0, 0) 408 cairo_surface_t *surface; 409 Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());394 cairo_surface_t *surface; /* compositing destination, source for pixbuf */ 395 CairoComposeParams compose_params; /* composite surface context */ 410 396 #else 411 397 GdkPixmap *pixmap; 412 398 #endif … … static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, 417 403 418 404 const gchar *layout; 419 405 406 #if GTK_CHECK_VERSION(3, 0, 0) 407 /* initialize cairo context and composite destination surface */ 408 surface = initialize_composite(&compose_params, width, height); 409 #endif 410 420 411 title = focus ? theme->a_focused_title : theme->a_unfocused_title; 421 412 422 413 /* set border */ … … static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, 433 424 434 425 x = y = theme->fbwidth; 435 426 #if GTK_CHECK_VERSION(3, 0, 0) 436 surface = cairo_xlib_surface_create(dpy, 437 title->pixmap, 438 DefaultVisual(dpy, 0), 439 x, 440 y); 441 442 pixbuf = gdk_pixbuf_get_from_surface(surface, 443 0, 444 0, 445 w, 446 h); 447 448 cairo_surface_destroy(surface); 449 427 compose_surface(&compose_params, title, x, y, w, h); 450 428 #else 451 429 pixmap = gdk_pixmap_foreign_new(title->pixmap); 452 430 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, 494 472 495 473 theme_pixmap_paint(a, w, h); 496 474 #if GTK_CHECK_VERSION(3, 0, 0) 497 surface = cairo_xlib_surface_create(dpy, 498 a->pixmap, 499 DefaultVisual(dpy, 0), 500 x, 501 y); 502 503 pixbuf = gdk_pixbuf_get_from_surface(surface, 504 0, 505 0, 506 w, 507 h); 508 509 cairo_surface_destroy(surface); 510 475 compose_surface(&compose_params, a, x, y, w, h); 511 476 #else 512 477 pixmap = gdk_pixmap_foreign_new(a->pixmap); 513 478 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, 528 493 529 494 theme_pixmap_paint(a, w, h); 530 495 #if GTK_CHECK_VERSION(3, 0, 0) 531 surface = cairo_xlib_surface_create(dpy, 532 a->pixmap, 533 DefaultVisual(dpy, 0), 534 x, 535 y); 536 537 pixbuf = gdk_pixbuf_get_from_surface(surface, 538 0, 539 0, 540 w, 541 h); 542 543 cairo_surface_destroy(surface); 544 496 compose_surface(&compose_params, a, x, y, w, h); 545 497 #else 546 498 pixmap = gdk_pixmap_foreign_new(a->pixmap); 547 499 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, 616 568 617 569 theme_pixmap_paint(a, w, h); 618 570 #if GTK_CHECK_VERSION(3, 0, 0) 619 surface = cairo_xlib_surface_create(dpy, 620 a->pixmap, 621 DefaultVisual(dpy, 0), 622 x, 623 y + 1); 624 625 pixbuf = gdk_pixbuf_get_from_surface(surface, 626 0, 627 0, 628 w, 629 h); 630 631 cairo_surface_destroy(surface); 632 571 compose_surface(&compose_params, a, x, y + 1, w, h); 633 572 #else 634 573 pixmap = gdk_pixmap_foreign_new(a->pixmap); 635 574 /* use y + 1 because these buttons should be centered wrt the label … … static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, 653 592 654 593 theme_pixmap_paint(handle, w, h); 655 594 #if GTK_CHECK_VERSION(3, 0, 0) 656 surface = cairo_xlib_surface_create(dpy, 657 handle->pixmap, 658 DefaultVisual(dpy, 0), 659 x, 660 y); 661 662 pixbuf = gdk_pixbuf_get_from_surface(surface, 663 0, 664 0, 665 w, 666 h); 667 668 cairo_surface_destroy(surface); 669 595 compose_surface(&compose_params, handle, x, y, w, h); 670 596 #else 671 597 pixmap = gdk_pixmap_foreign_new(handle->pixmap); 672 598 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, 691 617 692 618 theme_pixmap_paint(a, w, h); 693 619 #if GTK_CHECK_VERSION(3, 0, 0) 694 surface = cairo_xlib_surface_create(dpy, 695 a->pixmap, 696 DefaultVisual(dpy, 0), 697 x, 698 y); 699 700 pixbuf = gdk_pixbuf_get_from_surface(surface, 701 0, 702 0, 703 w, 704 h); 705 706 cairo_surface_destroy(surface); 707 620 compose_surface(&compose_params, a, x, y, w, h); 708 621 #else 709 622 pixmap = gdk_pixmap_foreign_new(a->pixmap); 710 623 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, … … static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, 715 628 /* right grip */ 716 629 x = width - theme->fbwidth - theme->grip_width; 717 630 #if GTK_CHECK_VERSION(3, 0, 0) 718 surface = cairo_xlib_surface_create(dpy, 719 a->pixmap, 720 DefaultVisual(dpy, 0), 721 x, 722 y); 723 724 pixbuf = gdk_pixbuf_get_from_surface(surface, 725 0, 726 0, 727 w, 728 h); 729 730 cairo_surface_destroy(surface); 731 631 compose_surface(&compose_params, a, x, y, w, h); 732 632 #else 733 633 pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap, 734 634 gdk_colormap_get_system(), … … static GdkPixbuf* preview_window(RrTheme *theme, const gchar *titlelayout, 736 636 #endif 737 637 } 738 638 639 #if GTK_CHECK_VERSION(3, 0, 0) 640 // copy composed cairo surface into GDK pixbuf 641 pixbuf = finalize_composition(&compose_params, surface, width, height); 642 #else 643 ; // the GTK2 paths have composed onto the GDK pixbuf directly 644 #endif 645 739 646 /* title separator colour */ 740 647 x = theme->fbwidth; 741 648 y = theme->fbwidth + theme->title_height;