From 7d99640d11f7435110b2aabe3108121fd0d1e252 Mon Sep 17 00:00:00 2001 From: MSVSphere Packaging Team Date: Tue, 26 Nov 2024 17:19:47 +0300 Subject: [PATCH] import libwnck3-43.0-9.el10 --- .gitignore | 1 + .libwnck3.metadata | 1 + ...e_avoid_segfault_in_invalidate_icons.patch | 29 + ...0001-Expose-window-scaling-factor_43.patch | 58 + ...t-the-correct-PID-for-clients-inside.patch | 75 + ...se-cairo-surfaces-to-render-icons_43.patch | 1324 +++++++++++++++++ ...nge-icons-to-being-cairo-surfaces_43.patch | 772 ++++++++++ ...ark-GdkPixbuf-icons-as-deprecated_43.patch | 189 +++ ...klist-Add-surface-loader-function_43.patch | 134 ++ SPECS/libwnck3.spec | 279 ++++ 10 files changed, 2862 insertions(+) create mode 100644 .gitignore create mode 100644 .libwnck3.metadata create mode 100644 SOURCES/libwnck3_handle_avoid_segfault_in_invalidate_icons.patch create mode 100644 SOURCES/libwnck_0001-Expose-window-scaling-factor_43.patch create mode 100644 SOURCES/libwnck_0001-Revert-xutils-Get-the-correct-PID-for-clients-inside.patch create mode 100644 SOURCES/libwnck_0002-icons-Use-cairo-surfaces-to-render-icons_43.patch create mode 100644 SOURCES/libwnck_0003-xutils-Change-icons-to-being-cairo-surfaces_43.patch create mode 100644 SOURCES/libwnck_0004-icons-Mark-GdkPixbuf-icons-as-deprecated_43.patch create mode 100644 SOURCES/libwnck_0005-tasklist-Add-surface-loader-function_43.patch create mode 100644 SPECS/libwnck3.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4837ed3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/libwnck-43.0.tar.xz diff --git a/.libwnck3.metadata b/.libwnck3.metadata new file mode 100644 index 0000000..80835fb --- /dev/null +++ b/.libwnck3.metadata @@ -0,0 +1 @@ +fb3a66bfcd4296983712ba3c95d6560ba2494cfe SOURCES/libwnck-43.0.tar.xz diff --git a/SOURCES/libwnck3_handle_avoid_segfault_in_invalidate_icons.patch b/SOURCES/libwnck3_handle_avoid_segfault_in_invalidate_icons.patch new file mode 100644 index 0000000..d107f25 --- /dev/null +++ b/SOURCES/libwnck3_handle_avoid_segfault_in_invalidate_icons.patch @@ -0,0 +1,29 @@ +From 6ceb684442eb26e3bdb8a38bf52264ad55f96a7b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alberts=20Muktup=C4=81vels?= +Date: Tue, 20 Sep 2022 15:40:22 +0300 +Subject: [PATCH] handle: avoid segfault in invalidate_icons + +Screens variable won't be initialized if default icon sizes are +set/changed before using wnck_screen_get_default. + +https://bugs.launchpad.net/ubuntu/+source/libwnck3/+bug/1990263 +--- + libwnck/wnck-handle.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libwnck/wnck-handle.c b/libwnck/wnck-handle.c +index e12ff882..8d5da45c 100644 +--- a/libwnck/wnck-handle.c ++++ b/libwnck/wnck-handle.c +@@ -70,6 +70,9 @@ invalidate_icons (WnckHandle *self) + Display *xdisplay; + int i; + ++ if (self->screens == NULL) ++ return; ++ + xdisplay = _wnck_get_default_display (); + + for (i = 0; i < ScreenCount (xdisplay); ++i) +-- + diff --git a/SOURCES/libwnck_0001-Expose-window-scaling-factor_43.patch b/SOURCES/libwnck_0001-Expose-window-scaling-factor_43.patch new file mode 100644 index 0000000..2fa6e8b --- /dev/null +++ b/SOURCES/libwnck_0001-Expose-window-scaling-factor_43.patch @@ -0,0 +1,58 @@ +From 27b7ebb8092a36f0fb32e3277577ff9f09d309e6 Mon Sep 17 00:00:00 2001 +From: Victor Kareh +Date: Tue, 6 Aug 2019 09:59:59 -0400 +Subject: [PATCH 1/5] Expose window scaling factor + +--- + libwnck/private.h | 2 ++ + libwnck/util.c | 21 +++++++++++++++++++++ + 2 files changed, 23 insertions(+) + +diff --git a/libwnck/private.h b/libwnck/private.h +index d5e48d9..6741e1e 100644 +--- a/libwnck/private.h ++++ b/libwnck/private.h +@@ -37,6 +37,8 @@ G_BEGIN_DECLS + + WnckHandle *_wnck_get_handle (void); + ++int _wnck_get_window_scaling_factor (void); ++ + void _wnck_application_process_property_notify (WnckApplication *app, + XEvent *xevent); + void _wnck_window_process_property_notify (WnckWindow *window, +diff --git a/libwnck/util.c b/libwnck/util.c +index 83659dc..a58a99e 100644 +--- a/libwnck/util.c ++++ b/libwnck/util.c +@@ -164,6 +164,27 @@ _wnck_get_handle (void) + return wnck_handle; + } + ++/** ++ * _wnck_get_window_scaling_factor: ++ * ++ * Retrieves the internal scale factor that maps from window coordinates to the ++ * actual device pixels. On traditional systems this is 1, on high density ++ * outputs, it can be a higher value (typically 2). ++ */ ++int ++_wnck_get_window_scaling_factor (void) ++{ ++ GdkScreen *screen; ++ GValue value = G_VALUE_INIT; ++ ++ g_value_init (&value, G_TYPE_INT); ++ ++ screen = gdk_screen_get_default (); ++ if (gdk_screen_get_setting (screen, "gdk-window-scaling-factor", &value)) ++ return g_value_get_int (&value); ++ return 1; ++} ++ + /** + * wnck_set_default_icon_size: + * @size: the default size for windows and application standard icons. +-- +2.37.2 + diff --git a/SOURCES/libwnck_0001-Revert-xutils-Get-the-correct-PID-for-clients-inside.patch b/SOURCES/libwnck_0001-Revert-xutils-Get-the-correct-PID-for-clients-inside.patch new file mode 100644 index 0000000..a45fc2e --- /dev/null +++ b/SOURCES/libwnck_0001-Revert-xutils-Get-the-correct-PID-for-clients-inside.patch @@ -0,0 +1,75 @@ +From 9c4551c67d6fe854f7d37970398f5d5c9d17c28e Mon Sep 17 00:00:00 2001 +From: raveit65 +Date: Thu, 29 Sep 2022 10:31:16 +0200 +Subject: [PATCH] Revert "xutils: Get the correct PID for clients inside PID + namespaces" + +This reverts commit 07694559cc0c65ce1cca9ac33b165cef84c34d5e. + +- fixing https://gitlab.gnome.org/GNOME/libwnck/-/issues/154#note_1562760 +--- + libwnck/xutils.c | 36 +++--------------------------------- + 1 file changed, 3 insertions(+), 33 deletions(-) + +diff --git a/libwnck/xutils.c b/libwnck/xutils.c +index 60ae7b2..f2a2d3c 100644 +--- a/libwnck/xutils.c ++++ b/libwnck/xutils.c +@@ -27,9 +27,6 @@ + #if HAVE_CAIRO_XLIB_XRENDER + #include + #endif +-#ifdef HAVE_XRES +-#include +-#endif + #include "screen.h" + #include "window.h" + #include "private.h" +@@ -1149,41 +1146,14 @@ int + _wnck_get_pid (Screen *screen, + Window xwindow) + { +- int pid = -1; +- +-#ifdef HAVE_XRES +- XResClientIdSpec client_spec; +- long client_id_count = 0; +- XResClientIdValue *client_ids = NULL; +- +- client_spec.client = xwindow; +- client_spec.mask = XRES_CLIENT_ID_PID_MASK; +- +- if (XResQueryClientIds (DisplayOfScreen (screen), 1, &client_spec, +- &client_id_count, &client_ids) == Success) +- { +- long i; +- +- for (i = 0; i < client_id_count; i++) +- { +- pid = XResGetClientPid (&client_ids[i]); +- if (pid != -1) +- break; +- } +- +- XResClientIdsDestroy (client_id_count, client_ids); +- +- if (pid != -1) +- return pid; +- } +-#endif ++ int val; + + if (!_wnck_get_cardinal (screen, xwindow, + _wnck_atom_get ("_NET_WM_PID"), +- &pid)) ++ &val)) + return 0; + else +- return pid; ++ return val; + } + + char* +-- +2.37.3 + diff --git a/SOURCES/libwnck_0002-icons-Use-cairo-surfaces-to-render-icons_43.patch b/SOURCES/libwnck_0002-icons-Use-cairo-surfaces-to-render-icons_43.patch new file mode 100644 index 0000000..41465d4 --- /dev/null +++ b/SOURCES/libwnck_0002-icons-Use-cairo-surfaces-to-render-icons_43.patch @@ -0,0 +1,1324 @@ +From 882fab71ee0260b1b70cb53edbc2bd2e9d35ebd3 Mon Sep 17 00:00:00 2001 +From: Victor Kareh +Date: Fri, 27 Nov 2020 11:25:08 -0500 +Subject: [PATCH 2/5] icons: Use cairo surfaces to render icons + +This replaces GdkPixbuf manipulation with the cairo_surface equivalents. +As a result, icons can now render sharply in HiDPI displays. +--- + libwnck/application.c | 151 ++++++++++++++++++--- + libwnck/application.h | 3 + + libwnck/class-group.c | 172 +++++++++++++++++++----- + libwnck/class-group.h | 3 + + libwnck/pager.c | 20 +-- + libwnck/selector.c | 103 +++++++-------- + libwnck/tasklist.c | 173 ++++++++++++------------- + libwnck/window.c | 139 +++++++++++++++++--- + libwnck/window.h | 3 + + libwnck/wnck-image-menu-item-private.h | 3 + + libwnck/wnck-image-menu-item.c | 8 ++ + 11 files changed, 556 insertions(+), 222 deletions(-) + +diff --git a/libwnck/application.c b/libwnck/application.c +index 9ab7f48..d8283cc 100644 +--- a/libwnck/application.c ++++ b/libwnck/application.c +@@ -62,8 +62,8 @@ struct _WnckApplicationPrivate + + WnckWindow *name_window; /* window we are using name of */ + +- GdkPixbuf *icon; +- GdkPixbuf *mini_icon; ++ cairo_surface_t *icon; ++ cairo_surface_t *mini_icon; + + WnckIconCache *icon_cache; + +@@ -159,13 +159,8 @@ wnck_application_finalize (GObject *object) + g_free (application->priv->name); + application->priv->name = NULL; + +- if (application->priv->icon) +- g_object_unref (G_OBJECT (application->priv->icon)); +- application->priv->icon = NULL; +- +- if (application->priv->mini_icon) +- g_object_unref (G_OBJECT (application->priv->mini_icon)); +- application->priv->mini_icon = NULL; ++ g_clear_pointer (&application->priv->icon, cairo_surface_destroy); ++ g_clear_pointer (&application->priv->mini_icon, cairo_surface_destroy); + + _wnck_icon_cache_free (application->priv->icon_cache); + application->priv->icon_cache = NULL; +@@ -336,14 +331,20 @@ get_icons (WnckApplication *app) + { + app->priv->need_emit_icon_changed = TRUE; + +- if (app->priv->icon) +- g_object_unref (G_OBJECT (app->priv->icon)); ++ g_clear_pointer (&app->priv->icon, cairo_surface_destroy); ++ g_clear_pointer (&app->priv->mini_icon, cairo_surface_destroy); + +- if (app->priv->mini_icon) +- g_object_unref (G_OBJECT (app->priv->mini_icon)); ++ if (icon) ++ { ++ app->priv->icon = gdk_cairo_surface_create_from_pixbuf (icon, 0, NULL); ++ g_clear_object (&icon); ++ } + +- app->priv->icon = icon; +- app->priv->mini_icon = mini_icon; ++ if (mini_icon) ++ { ++ app->priv->mini_icon = gdk_cairo_surface_create_from_pixbuf (mini_icon, 0, NULL); ++ g_clear_object (&mini_icon); ++ } + } + + /* FIXME we should really fall back to using the icon +@@ -404,12 +405,39 @@ find_icon_window (WnckApplication *app) + GdkPixbuf* + wnck_application_get_icon (WnckApplication *app) + { ++ static const cairo_user_data_key_t app_icon_pixbuf_key; ++ + g_return_val_if_fail (WNCK_IS_APPLICATION (app), NULL); + + _wnck_application_load_icons (app); + + if (app->priv->icon) +- return app->priv->icon; ++ { ++ GdkPixbuf *pixbuf; ++ ++ pixbuf = cairo_surface_get_user_data (app->priv->icon, &app_icon_pixbuf_key); ++ ++ if (pixbuf == NULL) ++ { ++ int scaling_factor; ++ ++ pixbuf = gdk_pixbuf_get_from_surface (app->priv->icon, ++ 0, ++ 0, ++ cairo_image_surface_get_width (app->priv->icon), ++ cairo_image_surface_get_height (app->priv->icon)); ++ ++ scaling_factor = _wnck_get_window_scaling_factor (); ++ pixbuf = gdk_pixbuf_scale_simple (pixbuf, ++ gdk_pixbuf_get_width (pixbuf) / scaling_factor, ++ gdk_pixbuf_get_height (pixbuf) / scaling_factor, ++ GDK_INTERP_BILINEAR); ++ ++ cairo_surface_set_user_data (app->priv->icon, &app_icon_pixbuf_key, pixbuf, g_object_unref); ++ } ++ ++ return pixbuf; ++ } + else + { + WnckWindow *w = find_icon_window (app); +@@ -435,12 +463,39 @@ wnck_application_get_icon (WnckApplication *app) + GdkPixbuf* + wnck_application_get_mini_icon (WnckApplication *app) + { ++ static const cairo_user_data_key_t app_mini_icon_pixbuf_key; ++ + g_return_val_if_fail (WNCK_IS_APPLICATION (app), NULL); + + _wnck_application_load_icons (app); + + if (app->priv->mini_icon) +- return app->priv->mini_icon; ++ { ++ GdkPixbuf *pixbuf; ++ ++ pixbuf = cairo_surface_get_user_data (app->priv->mini_icon, &app_mini_icon_pixbuf_key); ++ ++ if (pixbuf == NULL) ++ { ++ int scaling_factor; ++ ++ pixbuf = gdk_pixbuf_get_from_surface (app->priv->mini_icon, ++ 0, ++ 0, ++ cairo_image_surface_get_width (app->priv->mini_icon), ++ cairo_image_surface_get_height (app->priv->mini_icon)); ++ ++ scaling_factor = _wnck_get_window_scaling_factor (); ++ pixbuf = gdk_pixbuf_scale_simple (pixbuf, ++ gdk_pixbuf_get_width (pixbuf) / scaling_factor, ++ gdk_pixbuf_get_height (pixbuf) / scaling_factor, ++ GDK_INTERP_BILINEAR); ++ ++ cairo_surface_set_user_data (app->priv->mini_icon, &app_mini_icon_pixbuf_key, pixbuf, g_object_unref); ++ } ++ ++ return pixbuf; ++ } + else + { + WnckWindow *w = find_icon_window (app); +@@ -451,6 +506,68 @@ wnck_application_get_mini_icon (WnckApplication *app) + } + } + ++/** ++ * wnck_application_get_icon_surface: ++ * @app: a #WnckApplication. ++ * ++ * Gets the icon-surface to be used for @app. If no icon-surfaceis set for @app, ++ * a suboptimal heuristic is used to find an appropriate icon. If no icon-surface ++ * was found, a fallback icon-surface is used. ++ * ++ * Return value: (transfer full): a reference to the icon-surface for @app. The ++ * caller should unreference the cairo_surface_t once done ++ * with it. ++ **/ ++cairo_surface_t* ++wnck_application_get_icon_surface (WnckApplication *app) ++{ ++ g_return_val_if_fail (WNCK_IS_APPLICATION (app), NULL); ++ ++ _wnck_application_load_icons (app); ++ ++ if (app->priv->icon) ++ return cairo_surface_reference (app->priv->icon); ++ else ++ { ++ WnckWindow *w = find_icon_window (app); ++ if (w) ++ return wnck_window_get_icon_surface (w); ++ else ++ return NULL; ++ } ++} ++ ++/** ++ * wnck_application_get_mini_icon_surface: ++ * @app: a #WnckApplication. ++ * ++ * Gets the mini-icon-surface to be used for @app. If no mini-icon-surfaceis set ++ * for @app, a suboptimal heuristic is used to find an appropriate icon. If no ++ * mini-icon-surface was found, a fallback mini-icon-surface is used. ++ * ++ * Return value: (transfer full): a reference to the mini-icon-surface for @app. ++ * The caller should unreference the cairo_surface_t once ++ * done with it. ++ **/ ++cairo_surface_t* ++wnck_application_get_mini_icon_surface (WnckApplication *app) ++{ ++ g_return_val_if_fail (WNCK_IS_APPLICATION (app), NULL); ++ ++ _wnck_application_load_icons (app); ++ ++ if (app->priv->mini_icon) ++ return cairo_surface_reference (app->priv->mini_icon); ++ else ++ { ++ WnckWindow *w = find_icon_window (app); ++ if (w) ++ return wnck_window_get_mini_icon_surface (w); ++ else ++ return NULL; ++ } ++} ++ + /** + * wnck_application_get_icon_is_fallback: + * @app: a #WnckApplication +diff --git a/libwnck/application.h b/libwnck/application.h +index 40fe4c6..f3ea970 100644 +--- a/libwnck/application.h ++++ b/libwnck/application.h +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + G_BEGIN_DECLS + +@@ -92,6 +93,8 @@ const char* wnck_application_get_icon_name (WnckApplication *app); + int wnck_application_get_pid (WnckApplication *app); + GdkPixbuf* wnck_application_get_icon (WnckApplication *app); + GdkPixbuf* wnck_application_get_mini_icon (WnckApplication *app); ++cairo_surface_t* wnck_application_get_icon_surface (WnckApplication *app); ++cairo_surface_t* wnck_application_get_mini_icon_surface (WnckApplication *app); + gboolean wnck_application_get_icon_is_fallback (WnckApplication *app); + const char* wnck_application_get_startup_id (WnckApplication *app); + +diff --git a/libwnck/class-group.c b/libwnck/class-group.c +index 46d1f24..e6c45d6 100644 +--- a/libwnck/class-group.c ++++ b/libwnck/class-group.c +@@ -59,8 +59,8 @@ struct _WnckClassGroupPrivate { + GHashTable *window_icon_handlers; + GHashTable *window_name_handlers; + +- GdkPixbuf *icon; +- GdkPixbuf *mini_icon; ++ cairo_surface_t *icon; ++ cairo_surface_t *mini_icon; + }; + + G_DEFINE_TYPE_WITH_PRIVATE (WnckClassGroup, wnck_class_group, G_TYPE_OBJECT); +@@ -171,17 +171,8 @@ wnck_class_group_finalize (GObject *object) + class_group->priv->window_name_handlers = NULL; + } + +- if (class_group->priv->icon) +- { +- g_object_unref (class_group->priv->icon); +- class_group->priv->icon = NULL; +- } +- +- if (class_group->priv->mini_icon) +- { +- g_object_unref (class_group->priv->mini_icon); +- class_group->priv->mini_icon = NULL; +- } ++ g_clear_pointer (&class_group->priv->icon, cairo_surface_destroy); ++ g_clear_pointer (&class_group->priv->mini_icon, cairo_surface_destroy); + + G_OBJECT_CLASS (wnck_class_group_parent_class)->finalize (object); + } +@@ -370,7 +361,8 @@ set_name (WnckClassGroup *class_group) + + /* Walks the list of applications, trying to get an icon from them */ + static void +-get_icons_from_applications (WnckClassGroup *class_group, GdkPixbuf **icon, GdkPixbuf **mini_icon) ++get_icons_from_applications (WnckClassGroup *class_group, ++ cairo_surface_t **icon, cairo_surface_t **mini_icon) + { + GList *l; + +@@ -386,15 +378,15 @@ get_icons_from_applications (WnckClassGroup *class_group, GdkPixbuf **icon, GdkP + app = wnck_window_get_application (window); + if (app) + { +- *icon = wnck_application_get_icon (app); +- *mini_icon = wnck_application_get_mini_icon (app); ++ *icon = wnck_application_get_icon_surface (app); ++ *mini_icon = wnck_application_get_mini_icon_surface (app); + + if (*icon && *mini_icon) + return; + else + { +- *icon = NULL; +- *mini_icon = NULL; ++ g_clear_pointer (icon, cairo_surface_destroy); ++ g_clear_pointer (mini_icon, cairo_surface_destroy); + } + } + } +@@ -402,7 +394,8 @@ get_icons_from_applications (WnckClassGroup *class_group, GdkPixbuf **icon, GdkP + + /* Walks the list of windows, trying to get an icon from them */ + static void +-get_icons_from_windows (WnckClassGroup *class_group, GdkPixbuf **icon, GdkPixbuf **mini_icon) ++get_icons_from_windows (WnckClassGroup *class_group, ++ cairo_surface_t **icon, cairo_surface_t **mini_icon) + { + GList *l; + +@@ -415,15 +408,15 @@ get_icons_from_windows (WnckClassGroup *class_group, GdkPixbuf **icon, GdkPixbuf + + window = WNCK_WINDOW (l->data); + +- *icon = wnck_window_get_icon (window); +- *mini_icon = wnck_window_get_mini_icon (window); ++ *icon = wnck_window_get_icon_surface (window); ++ *mini_icon = wnck_window_get_mini_icon_surface (window); + + if (*icon && *mini_icon) + return; + else + { +- *icon = NULL; +- *mini_icon = NULL; ++ g_clear_pointer (icon, cairo_surface_destroy); ++ g_clear_pointer (mini_icon, cairo_surface_destroy); + } + } + } +@@ -434,7 +427,7 @@ get_icons_from_windows (WnckClassGroup *class_group, GdkPixbuf **icon, GdkPixbuf + static void + set_icon (WnckClassGroup *class_group) + { +- GdkPixbuf *icon, *mini_icon; ++ cairo_surface_t *icon, *mini_icon; + gboolean icons_reffed = FALSE; + + get_icons_from_applications (class_group, &icon, &mini_icon); +@@ -448,28 +441,39 @@ set_icon (WnckClassGroup *class_group) + + handle = wnck_screen_get_handle (class_group->priv->screen); + +- _wnck_get_fallback_icons (&icon, ++ GdkPixbuf *icon_pixbuf, *mini_icon_pixbuf; ++ ++ _wnck_get_fallback_icons (&icon_pixbuf, + _wnck_handle_get_default_icon_size (handle), +- &mini_icon, ++ &mini_icon_pixbuf, + _wnck_handle_get_default_mini_icon_size (handle)); ++ if (icon_pixbuf) ++ { ++ icon = gdk_cairo_surface_create_from_pixbuf (icon_pixbuf, 0, NULL); ++ g_clear_object (&icon_pixbuf); ++ } ++ ++ if (mini_icon_pixbuf) ++ { ++ mini_icon = gdk_cairo_surface_create_from_pixbuf (mini_icon_pixbuf, 0, NULL); ++ g_clear_object (&mini_icon_pixbuf); ++ } ++ + icons_reffed = TRUE; + } + + g_assert (icon && mini_icon); + +- if (class_group->priv->icon) +- g_object_unref (class_group->priv->icon); +- +- if (class_group->priv->mini_icon) +- g_object_unref (class_group->priv->mini_icon); ++ g_clear_pointer (&class_group->priv->icon, cairo_surface_destroy); ++ g_clear_pointer (&class_group->priv->mini_icon, cairo_surface_destroy); + + class_group->priv->icon = icon; + class_group->priv->mini_icon = mini_icon; + + if (!icons_reffed) + { +- g_object_ref (class_group->priv->icon); +- g_object_ref (class_group->priv->mini_icon); ++ cairo_surface_reference (class_group->priv->icon); ++ cairo_surface_reference (class_group->priv->mini_icon); + } + + g_signal_emit (G_OBJECT (class_group), signals[ICON_CHANGED], 0); +@@ -702,9 +706,39 @@ wnck_class_group_get_name (WnckClassGroup *class_group) + GdkPixbuf * + wnck_class_group_get_icon (WnckClassGroup *class_group) + { ++ static const cairo_user_data_key_t class_group_icon_pixbuf_key; ++ + g_return_val_if_fail (class_group != NULL, NULL); + +- return class_group->priv->icon; ++ if (class_group->priv->icon) ++ { ++ GdkPixbuf *pixbuf; ++ ++ pixbuf = cairo_surface_get_user_data (class_group->priv->icon, &class_group_icon_pixbuf_key); ++ ++ if (pixbuf == NULL) ++ { ++ int scaling_factor; ++ ++ pixbuf = gdk_pixbuf_get_from_surface (class_group->priv->icon, ++ 0, ++ 0, ++ cairo_image_surface_get_width (class_group->priv->icon), ++ cairo_image_surface_get_height (class_group->priv->icon)); ++ ++ scaling_factor = _wnck_get_window_scaling_factor (); ++ pixbuf = gdk_pixbuf_scale_simple (pixbuf, ++ gdk_pixbuf_get_width (pixbuf) / scaling_factor, ++ gdk_pixbuf_get_height (pixbuf) / scaling_factor, ++ GDK_INTERP_BILINEAR); ++ ++ cairo_surface_set_user_data (class_group->priv->icon, &class_group_icon_pixbuf_key, pixbuf, g_object_unref); ++ } ++ ++ return pixbuf; ++ } ++ ++ return NULL; + } + + /** +@@ -723,8 +757,76 @@ wnck_class_group_get_icon (WnckClassGroup *class_group) + **/ + GdkPixbuf * + wnck_class_group_get_mini_icon (WnckClassGroup *class_group) ++{ ++ static const cairo_user_data_key_t class_group_mini_icon_pixbuf_key; ++ ++ g_return_val_if_fail (class_group != NULL, NULL); ++ ++ if (class_group->priv->mini_icon) ++ { ++ GdkPixbuf *pixbuf; ++ ++ pixbuf = cairo_surface_get_user_data (class_group->priv->mini_icon, &class_group_mini_icon_pixbuf_key); ++ ++ if (pixbuf == NULL) ++ { ++ int scaling_factor; ++ ++ pixbuf = gdk_pixbuf_get_from_surface (class_group->priv->mini_icon, ++ 0, ++ 0, ++ cairo_image_surface_get_width (class_group->priv->mini_icon), ++ cairo_image_surface_get_height (class_group->priv->mini_icon)); ++ ++ scaling_factor = _wnck_get_window_scaling_factor (); ++ pixbuf = gdk_pixbuf_scale_simple (pixbuf, ++ gdk_pixbuf_get_width (pixbuf) / scaling_factor, ++ gdk_pixbuf_get_height (pixbuf) / scaling_factor, ++ GDK_INTERP_BILINEAR); ++ ++ cairo_surface_set_user_data (class_group->priv->mini_icon, &class_group_mini_icon_pixbuf_key, pixbuf, g_object_unref); ++ } ++ ++ return pixbuf; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * wnck_class_group_get_icon_surface: ++ * @class_group: a #WnckClassGroup. ++ * ++ * Gets the icon-surface to be used for @class_group. Since there is no way to ++ * properly find the icon-surface, the same suboptimal heuristic as the one for ++ * wnck_class_group_get_icon() is used to find it. ++ * ++ * Return value: (transfer full): the icon-surface for @class_group. The caller should ++ * unreference the returned cairo_surface_t once done with it. ++ **/ ++cairo_surface_t * ++wnck_class_group_get_icon_surface (WnckClassGroup *class_group) ++{ ++ g_return_val_if_fail (class_group != NULL, NULL); ++ ++ return cairo_surface_reference (class_group->priv->icon); ++} ++ ++/** ++ * wnck_class_group_get_mini_icon_surface: ++ * @class_group: a #WnckClassGroup. ++ * ++ * Gets the mini-icon-surface to be used for @class_group. Since there is no way to ++ * properly find the mini-icon-surface, the same suboptimal heuristic as the one for ++ * wnck_class_group_get_icon() is used to find it. ++ * ++ * Return value: (transfer full): the mini-icon-surface for @class_group. The caller should ++ * unreference the returned cairo_surface_t once done with it. ++ **/ ++cairo_surface_t * ++wnck_class_group_get_mini_icon_surface (WnckClassGroup *class_group) + { + g_return_val_if_fail (class_group != NULL, NULL); + +- return class_group->priv->mini_icon; ++ return cairo_surface_reference (class_group->priv->mini_icon); + } +diff --git a/libwnck/class-group.h b/libwnck/class-group.h +index 581cd22..122e0ed 100644 +--- a/libwnck/class-group.h ++++ b/libwnck/class-group.h +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + G_BEGIN_DECLS + +@@ -82,6 +83,8 @@ const char * wnck_class_group_get_name (WnckClassGroup *class_group); + + GdkPixbuf *wnck_class_group_get_icon (WnckClassGroup *class_group); + GdkPixbuf *wnck_class_group_get_mini_icon (WnckClassGroup *class_group); ++cairo_surface_t *wnck_class_group_get_icon_surface (WnckClassGroup *class_group); ++cairo_surface_t *wnck_class_group_get_mini_icon_surface (WnckClassGroup *class_group); + + #ifndef WNCK_DISABLE_DEPRECATED + G_DEPRECATED_FOR(wnck_class_group_get_id) +diff --git a/libwnck/pager.c b/libwnck/pager.c +index 4df766c..9b09928 100644 +--- a/libwnck/pager.c ++++ b/libwnck/pager.c +@@ -984,8 +984,9 @@ draw_window (cairo_t *cr, + gboolean translucent) + { + GtkStyleContext *context; +- GdkPixbuf *icon; ++ cairo_surface_t *icon; + int icon_x, icon_y, icon_w, icon_h; ++ int scaling_factor; + gboolean is_active; + GdkRGBA fg; + gdouble translucency; +@@ -1015,14 +1016,15 @@ draw_window (cairo_t *cr, + cairo_pop_group_to_source (cr); + cairo_paint_with_alpha (cr, translucency); + +- icon = wnck_window_get_icon (win); ++ icon = wnck_window_get_icon_surface (win); + + icon_w = icon_h = 0; ++ scaling_factor = gtk_widget_get_scale_factor (widget); + + if (icon) + { +- icon_w = gdk_pixbuf_get_width (icon); +- icon_h = gdk_pixbuf_get_height (icon); ++ icon_w = cairo_image_surface_get_width (icon) / scaling_factor; ++ icon_h = cairo_image_surface_get_height (icon) / scaling_factor; + + /* If the icon is too big, fall back to mini icon. + * We don't arbitrarily scale the icon, because it's +@@ -1031,11 +1033,12 @@ draw_window (cairo_t *cr, + if (icon_w > (winrect->width - 2) || + icon_h > (winrect->height - 2)) + { +- icon = wnck_window_get_mini_icon (win); ++ cairo_surface_destroy (icon); ++ icon = wnck_window_get_mini_icon_surface (win); + if (icon) + { +- icon_w = gdk_pixbuf_get_width (icon); +- icon_h = gdk_pixbuf_get_height (icon); ++ icon_w = cairo_image_surface_get_width (icon) / scaling_factor; ++ icon_h = cairo_image_surface_get_height (icon) / scaling_factor; + + /* Give up. */ + if (icon_w > (winrect->width - 2) || +@@ -1051,7 +1054,7 @@ draw_window (cairo_t *cr, + icon_y = winrect->y + (winrect->height - icon_h) / 2; + + cairo_push_group (cr); +- gtk_render_icon (context, cr, icon, icon_x, icon_y); ++ gtk_render_icon_surface (context, cr, icon, icon_x, icon_y); + cairo_pop_group_to_source (cr); + cairo_paint_with_alpha (cr, translucency); + } +@@ -1072,6 +1075,7 @@ draw_window (cairo_t *cr, + cairo_stroke (cr); + + gtk_style_context_restore (context); ++ cairo_surface_destroy (icon); + } + + static WnckWindow * +diff --git a/libwnck/selector.c b/libwnck/selector.c +index 4cf6189..fcc3322 100644 +--- a/libwnck/selector.c ++++ b/libwnck/selector.c +@@ -135,103 +135,96 @@ wnck_selector_get_screen (WnckSelector *selector) + gdk_x11_screen_get_screen_number (screen)); + } + +-static GdkPixbuf * ++static cairo_surface_t * + wnck_selector_get_default_window_icon (void) + { +- static GdkPixbuf *retval = NULL; ++ static cairo_surface_t *retval = NULL; ++ GdkPixbuf *pixbuf; + + if (retval) + return retval; + +- retval = gdk_pixbuf_new_from_resource ("/org/gnome/libwnck/default_icon.png", NULL); ++ pixbuf = gdk_pixbuf_new_from_resource ("/org/gnome/libwnck/default_icon.png", NULL); + +- g_assert (retval); ++ g_assert (pixbuf); ++ ++ retval = gdk_cairo_surface_create_from_pixbuf (pixbuf, 0, NULL); ++ ++ g_object_unref (pixbuf); + + return retval; + } + +-static GdkPixbuf * +-wnck_selector_dimm_icon (GdkPixbuf *pixbuf) ++static void ++wnck_selector_dimm_icon (cairo_t *cr, cairo_surface_t *surface) + { +- int x, y, pixel_stride, row_stride; +- guchar *row, *pixels; +- int w, h; +- GdkPixbuf *dimmed; ++ cairo_surface_t *temp; ++ cairo_t *temp_cr; + +- w = gdk_pixbuf_get_width (pixbuf); +- h = gdk_pixbuf_get_height (pixbuf); ++ g_assert (surface != NULL); ++ g_assert (cairo_surface_get_content (surface) != CAIRO_CONTENT_COLOR); + +- if (gdk_pixbuf_get_has_alpha (pixbuf)) +- dimmed = gdk_pixbuf_copy (pixbuf); +- else +- dimmed = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); ++ temp = cairo_surface_create_similar (surface, ++ cairo_surface_get_content (surface), ++ cairo_image_surface_get_width (surface), ++ cairo_image_surface_get_height (surface)); + +- pixel_stride = 4; ++ temp_cr = cairo_create (temp); + +- row = gdk_pixbuf_get_pixels (dimmed); +- row_stride = gdk_pixbuf_get_rowstride (dimmed); ++ cairo_set_source_surface (temp_cr, surface, 0, 0); ++ cairo_paint_with_alpha (temp_cr, 0.5); + +- for (y = 0; y < h; y++) +- { +- pixels = row; +- for (x = 0; x < w; x++) +- { +- pixels[3] /= 2; +- pixels += pixel_stride; +- } +- row += row_stride; +- } ++ cairo_set_operator (cr, CAIRO_OPERATOR_IN); ++ cairo_set_source_surface (cr, temp, 0, 0); ++ cairo_paint (cr); + +- return dimmed; ++ cairo_destroy (temp_cr); ++ cairo_surface_destroy (temp); + } + + void + _wnck_selector_set_window_icon (GtkWidget *image, + WnckWindow *window) + { +- GdkPixbuf *pixbuf, *freeme, *freeme2; +- int width, height; ++ cairo_surface_t *orig, *surface; ++ cairo_t *cr; ++ int scaling_factor; + int icon_size = -1; + +- pixbuf = NULL; +- freeme = NULL; +- freeme2 = NULL; ++ orig = NULL; ++ surface = NULL; + + if (window) +- pixbuf = wnck_window_get_mini_icon (window); ++ orig = wnck_window_get_mini_icon_surface (window); + +- if (!pixbuf) +- pixbuf = wnck_selector_get_default_window_icon (); ++ if (!orig) ++ orig = wnck_selector_get_default_window_icon (); + + if (icon_size == -1) + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &icon_size); + +- width = gdk_pixbuf_get_width (pixbuf); +- height = gdk_pixbuf_get_height (pixbuf); ++ surface = cairo_surface_create_similar_image (orig, ++ cairo_image_surface_get_format (orig), ++ cairo_image_surface_get_width (orig), ++ cairo_image_surface_get_height (orig)); + +- if (icon_size != -1 && (width > icon_size || height > icon_size)) +- { +- double scale; ++ scaling_factor = _wnck_get_window_scaling_factor (); ++ cairo_surface_set_device_scale (surface, (double)scaling_factor, (double)scaling_factor); + +- scale = ((double) icon_size) / MAX (width, height); ++ cr = cairo_create (surface); + +- pixbuf = gdk_pixbuf_scale_simple (pixbuf, width * scale, +- height * scale, GDK_INTERP_BILINEAR); +- freeme = pixbuf; +- } ++ cairo_set_source_surface (cr, orig, 0, 0); ++ cairo_paint (cr); + + if (window && wnck_window_is_minimized (window)) + { +- pixbuf = wnck_selector_dimm_icon (pixbuf); +- freeme2 = pixbuf; ++ wnck_selector_dimm_icon (cr, surface); + } + +- gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); ++ gtk_image_set_from_surface (GTK_IMAGE (image), surface); + +- if (freeme) +- g_object_unref (freeme); +- if (freeme2) +- g_object_unref (freeme2); ++ cairo_destroy (cr); ++ cairo_surface_destroy (surface); + } + + static void +diff --git a/libwnck/tasklist.c b/libwnck/tasklist.c +index b773247..10c6cc8 100644 +--- a/libwnck/tasklist.c ++++ b/libwnck/tasklist.c +@@ -289,11 +289,11 @@ static WnckTask *wnck_task_new_from_startup_sequence (WnckTasklist *tasklis + #endif + static gboolean wnck_task_get_needs_attention (WnckTask *task); + ++static cairo_surface_t *wnck_task_get_icon (WnckTask *task); + + static char *wnck_task_get_text (WnckTask *task, + gboolean icon_text, + gboolean include_state); +-static GdkPixbuf *wnck_task_get_icon (WnckTask *task); + static gint wnck_task_compare_alphabetically (gconstpointer a, + gconstpointer b); + static gint wnck_task_compare (gconstpointer a, +@@ -637,10 +637,10 @@ wnck_button_set_handle (WnckButton *self, + } + + static void +-wnck_button_set_image_from_pixbuf (WnckButton *self, +- GdkPixbuf *pixbuf) ++wnck_button_set_image_from_surface (WnckButton *self, ++ cairo_surface_t *surface) + { +- gtk_image_set_from_pixbuf (GTK_IMAGE (self->image), pixbuf); ++ gtk_image_set_from_surface (GTK_IMAGE (self->image), surface); + } + + static void +@@ -3533,7 +3533,7 @@ wnck_task_popup_menu (WnckTask *task, + GtkWidget *menu; + WnckTask *win_task; + char *text; +- GdkPixbuf *pixbuf; ++ cairo_surface_t *surface; + GtkWidget *menu_item; + GList *l, *list; + +@@ -3577,15 +3577,15 @@ wnck_task_popup_menu (WnckTask *task, + gtk_widget_set_tooltip_text (menu_item, text); + g_free (text); + +- pixbuf = wnck_task_get_icon (win_task); +- if (pixbuf) ++ surface = wnck_task_get_icon (win_task); ++ if (surface) + { + WnckImageMenuItem *item; + + item = WNCK_IMAGE_MENU_ITEM (menu_item); + +- wnck_image_menu_item_set_image_from_icon_pixbuf (item, pixbuf); +- g_object_unref (pixbuf); ++ wnck_image_menu_item_set_image_from_icon_surface (item, surface); ++ cairo_surface_destroy (surface); + } + + gtk_widget_show (menu_item); +@@ -3771,102 +3771,78 @@ wnck_task_get_text (WnckTask *task, + } + + static void +-wnck_dimm_icon (GdkPixbuf *pixbuf) ++wnck_dimm_icon (cairo_t *cr, cairo_surface_t *surface) + { +- int x, y, pixel_stride, row_stride; +- guchar *row, *pixels; +- int w, h; ++ cairo_surface_t *temp; ++ cairo_t *temp_cr; + +- g_assert (pixbuf != NULL); ++ g_assert (surface != NULL); ++ g_assert (cairo_surface_get_content (surface) != CAIRO_CONTENT_COLOR); + +- w = gdk_pixbuf_get_width (pixbuf); +- h = gdk_pixbuf_get_height (pixbuf); ++ temp = cairo_surface_create_similar (surface, ++ cairo_surface_get_content (surface), ++ cairo_image_surface_get_width (surface), ++ cairo_image_surface_get_height (surface)); + +- g_assert (gdk_pixbuf_get_has_alpha (pixbuf)); ++ temp_cr = cairo_create (temp); + +- pixel_stride = 4; ++ cairo_set_source_surface (temp_cr, surface, 0, 0); ++ cairo_paint_with_alpha (temp_cr, 0.5); + +- row = gdk_pixbuf_get_pixels (pixbuf); +- row_stride = gdk_pixbuf_get_rowstride (pixbuf); ++ cairo_set_operator (cr, CAIRO_OPERATOR_IN); ++ cairo_set_source_surface (cr, temp, 0, 0); ++ cairo_paint (cr); + +- for (y = 0; y < h; y++) +- { +- pixels = row; +- +- for (x = 0; x < w; x++) +- { +- pixels[3] /= 2; +- +- pixels += pixel_stride; +- } +- +- row += row_stride; +- } ++ cairo_destroy (temp_cr); ++ cairo_surface_destroy (temp); + } + +-static GdkPixbuf * ++static cairo_surface_t * + wnck_task_scale_icon (gsize mini_icon_size, +- GdkPixbuf *orig, ++ cairo_surface_t *orig, + gboolean minimized) + { +- int w, h; +- GdkPixbuf *pixbuf; ++ int scaling_factor; ++ cairo_surface_t *surface; ++ cairo_t *cr; + + if (!orig) + return NULL; + +- w = gdk_pixbuf_get_width (orig); +- h = gdk_pixbuf_get_height (orig); ++ surface = cairo_surface_create_similar_image (orig, ++ cairo_image_surface_get_format (orig), ++ cairo_image_surface_get_width (orig), ++ cairo_image_surface_get_height (orig)); + +- if (h != (int) mini_icon_size || +- !gdk_pixbuf_get_has_alpha (orig)) +- { +- double scale; +- +- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, +- TRUE, +- 8, +- mini_icon_size * w / (double) h, +- mini_icon_size); +- +- scale = mini_icon_size / (double) gdk_pixbuf_get_height (orig); +- +- gdk_pixbuf_scale (orig, +- pixbuf, +- 0, 0, +- gdk_pixbuf_get_width (pixbuf), +- gdk_pixbuf_get_height (pixbuf), +- 0, 0, +- scale, scale, +- GDK_INTERP_HYPER); +- } +- else +- pixbuf = orig; ++ scaling_factor = _wnck_get_window_scaling_factor (); ++ cairo_surface_set_device_scale (surface, (double)scaling_factor, (double)scaling_factor); ++ ++ cr = cairo_create (surface); ++ ++ cairo_set_source_surface (cr, orig, 0, 0); ++ cairo_paint (cr); + + if (minimized) + { +- if (orig == pixbuf) +- pixbuf = gdk_pixbuf_copy (orig); +- +- wnck_dimm_icon (pixbuf); ++ wnck_dimm_icon (cr, surface); + } + +- if (orig == pixbuf) +- g_object_ref (pixbuf); ++ cairo_destroy (cr); + +- return pixbuf; ++ return surface; + } + + +-static GdkPixbuf * ++static cairo_surface_t * + wnck_task_get_icon (WnckTask *task) + { + WnckWindowState state; +- GdkPixbuf *pixbuf; + WnckHandle *handle; + gsize mini_icon_size; ++ cairo_surface_t *surface; ++ cairo_surface_t *mini_icon; + +- pixbuf = NULL; ++ surface = NULL; + + handle = task->tasklist->priv->handle; + mini_icon_size = _wnck_handle_get_default_mini_icon_size (handle); +@@ -3874,17 +3850,21 @@ wnck_task_get_icon (WnckTask *task) + switch (task->type) + { + case WNCK_TASK_CLASS_GROUP: +- pixbuf = wnck_task_scale_icon (mini_icon_size, +- wnck_class_group_get_mini_icon (task->class_group), +- FALSE); ++ mini_icon = wnck_class_group_get_mini_icon_surface (task->class_group); ++ surface = wnck_task_scale_icon (mini_icon_size, mini_icon, FALSE); ++ ++ cairo_surface_destroy (mini_icon); + break; + + case WNCK_TASK_WINDOW: + state = wnck_window_get_state (task->window); + +- pixbuf = wnck_task_scale_icon (mini_icon_size, +- wnck_window_get_mini_icon (task->window), +- state & WNCK_WINDOW_STATE_MINIMIZED); ++ mini_icon = wnck_window_get_mini_icon_surface (task->window); ++ surface = wnck_task_scale_icon (mini_icon_size, ++ mini_icon, ++ state & WNCK_WINDOW_STATE_MINIMIZED); ++ ++ cairo_surface_destroy (mini_icon); + break; + + case WNCK_TASK_STARTUP_SEQUENCE: +@@ -3905,16 +3885,28 @@ wnck_task_get_icon (WnckTask *task) + + if (loaded != NULL) + { +- pixbuf = wnck_task_scale_icon (mini_icon_size, loaded, FALSE); ++ cairo_surface_t *temp; ++ ++ temp = gdk_cairo_surface_create_from_pixbuf (loaded, 0, NULL); ++ surface = wnck_task_scale_icon (mini_icon_size, temp, FALSE); ++ ++ cairo_surface_destroy (temp); + g_object_unref (G_OBJECT (loaded)); + } + } + } + +- if (pixbuf == NULL) ++ if (surface == NULL) + { ++ GdkPixbuf *pixbuf; + _wnck_get_fallback_icons (NULL, 0, + &pixbuf, mini_icon_size); ++ ++ if (pixbuf != NULL) ++ { ++ surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 0, NULL); ++ g_object_unref (pixbuf); ++ } + } + #endif + break; +@@ -3923,7 +3915,7 @@ wnck_task_get_icon (WnckTask *task) + break; + } + +- return pixbuf; ++ return surface; + } + + static gboolean +@@ -3972,12 +3964,13 @@ wnck_task_get_needs_attention (WnckTask *task) + static void + wnck_task_update_visible_state (WnckTask *task) + { +- GdkPixbuf *pixbuf; ++ cairo_surface_t *surface; + char *text; + +- pixbuf = wnck_task_get_icon (task); +- wnck_button_set_image_from_pixbuf (WNCK_BUTTON (task->button), pixbuf); +- g_clear_object (&pixbuf); ++ surface = wnck_task_get_icon (task); ++ wnck_button_set_image_from_surface (WNCK_BUTTON (task->button), surface); ++ if (surface) ++ cairo_surface_destroy (surface); + + text = wnck_task_get_text (task, TRUE, TRUE); + if (text != NULL) +@@ -4448,7 +4441,7 @@ wnck_task_draw (GtkWidget *widget, + static void + wnck_task_create_widgets (WnckTask *task, GtkReliefStyle relief) + { +- GdkPixbuf *pixbuf; ++ cairo_surface_t *surface; + char *text; + static const GtkTargetEntry targets[] = { + { (gchar *) "application/x-wnck-window-id", 0, 0 } +@@ -4477,9 +4470,9 @@ wnck_task_create_widgets (WnckTask *task, GtkReliefStyle relief) + gtk_drag_dest_set (GTK_WIDGET (task->button), 0, + NULL, 0, GDK_ACTION_DEFAULT); + +- pixbuf = wnck_task_get_icon (task); +- wnck_button_set_image_from_pixbuf (WNCK_BUTTON (task->button), pixbuf); +- g_clear_object (&pixbuf); ++ surface = wnck_task_get_icon (task); ++ wnck_button_set_image_from_surface (WNCK_BUTTON (task->button), surface); ++ cairo_surface_destroy (surface); + + text = wnck_task_get_text (task, TRUE, TRUE); + wnck_button_set_text (WNCK_BUTTON (task->button), text); +diff --git a/libwnck/window.c b/libwnck/window.c +index 35bb37c..f01b4c2 100644 +--- a/libwnck/window.c ++++ b/libwnck/window.c +@@ -87,8 +87,8 @@ struct _WnckWindowPrivate + + WnckWindowType wintype; + +- GdkPixbuf *icon; +- GdkPixbuf *mini_icon; ++ cairo_surface_t *icon; ++ cairo_surface_t *mini_icon; + + WnckIconCache *icon_cache; + +@@ -411,13 +411,8 @@ wnck_window_finalize (GObject *object) + g_free (window->priv->session_id_utf8); + window->priv->session_id_utf8 = NULL; + +- if (window->priv->icon) +- g_object_unref (G_OBJECT (window->priv->icon)); +- window->priv->icon = NULL; +- +- if (window->priv->mini_icon) +- g_object_unref (G_OBJECT (window->priv->mini_icon)); +- window->priv->mini_icon = NULL; ++ g_clear_pointer (&window->priv->icon, cairo_surface_destroy); ++ g_clear_pointer (&window->priv->mini_icon, cairo_surface_destroy); + + _wnck_icon_cache_free (window->priv->icon_cache); + window->priv->icon_cache = NULL; +@@ -2132,14 +2127,20 @@ get_icons (WnckWindow *window) + { + window->priv->need_emit_icon_changed = TRUE; + +- if (window->priv->icon) +- g_object_unref (G_OBJECT (window->priv->icon)); ++ g_clear_pointer (&window->priv->icon, cairo_surface_destroy); ++ g_clear_pointer (&window->priv->mini_icon, cairo_surface_destroy); + +- if (window->priv->mini_icon) +- g_object_unref (G_OBJECT (window->priv->mini_icon)); ++ if (icon) ++ { ++ window->priv->icon = gdk_cairo_surface_create_from_pixbuf (icon, 0, NULL); ++ g_clear_object (&icon); ++ } + +- window->priv->icon = icon; +- window->priv->mini_icon = mini_icon; ++ if (mini_icon) ++ { ++ window->priv->mini_icon = gdk_cairo_surface_create_from_pixbuf (mini_icon, 0, NULL); ++ g_clear_object (&mini_icon); ++ } + } + + g_assert ((window->priv->icon && window->priv->mini_icon) || +@@ -2173,11 +2174,41 @@ _wnck_window_load_icons (WnckWindow *window) + GdkPixbuf* + wnck_window_get_icon (WnckWindow *window) + { ++ static const cairo_user_data_key_t window_icon_pixbuf_key; ++ + g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL); + + _wnck_window_load_icons (window); + +- return window->priv->icon; ++ if (window->priv->icon) ++ { ++ GdkPixbuf *pixbuf; ++ ++ pixbuf = cairo_surface_get_user_data (window->priv->icon, &window_icon_pixbuf_key); ++ ++ if (pixbuf == NULL) ++ { ++ int scaling_factor; ++ ++ pixbuf = gdk_pixbuf_get_from_surface (window->priv->icon, ++ 0, ++ 0, ++ cairo_image_surface_get_width (window->priv->icon), ++ cairo_image_surface_get_height (window->priv->icon)); ++ ++ scaling_factor = _wnck_get_window_scaling_factor (); ++ pixbuf = gdk_pixbuf_scale_simple (pixbuf, ++ gdk_pixbuf_get_width (pixbuf) / scaling_factor, ++ gdk_pixbuf_get_height (pixbuf) / scaling_factor, ++ GDK_INTERP_BILINEAR); ++ ++ cairo_surface_set_user_data (window->priv->icon, &window_icon_pixbuf_key, pixbuf, g_object_unref); ++ } ++ ++ return pixbuf; ++ } ++ ++ return NULL; + } + + /** +@@ -2194,12 +2225,86 @@ wnck_window_get_icon (WnckWindow *window) + **/ + GdkPixbuf* + wnck_window_get_mini_icon (WnckWindow *window) ++{ ++ static const cairo_user_data_key_t window_mini_icon_pixbuf_key; ++ ++ g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL); ++ ++ _wnck_window_load_icons (window); ++ ++ if (window->priv->mini_icon) ++ { ++ GdkPixbuf *pixbuf; ++ ++ pixbuf = cairo_surface_get_user_data (window->priv->mini_icon, &window_mini_icon_pixbuf_key); ++ ++ if (pixbuf == NULL) ++ { ++ int scaling_factor; ++ ++ pixbuf = gdk_pixbuf_get_from_surface (window->priv->mini_icon, ++ 0, ++ 0, ++ cairo_image_surface_get_width (window->priv->mini_icon), ++ cairo_image_surface_get_height (window->priv->mini_icon)); ++ ++ scaling_factor = _wnck_get_window_scaling_factor (); ++ pixbuf = gdk_pixbuf_scale_simple (pixbuf, ++ gdk_pixbuf_get_width (pixbuf) / scaling_factor, ++ gdk_pixbuf_get_height (pixbuf) / scaling_factor, ++ GDK_INTERP_BILINEAR); ++ ++ cairo_surface_set_user_data (window->priv->mini_icon, &window_mini_icon_pixbuf_key, pixbuf, g_object_unref); ++ } ++ ++ return pixbuf; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * wnck_window_get_icon_surface: ++ * @window: a #WnckWindow. ++ * ++ * Gets the icon-surface to be used for @window. If no icon-surface was found, a ++ * fallback icon-surface is used. wnck_window_get_icon_is_fallback() can be used ++ * to tell if the icon-surface is the fallback icon-surface. ++ * ++ * Return value: (transfer full): a reference to the icon-surface for @window. ++ * The caller should unreference the returned cairo_surface_t ++ * once done with it. ++ **/ ++cairo_surface_t* ++wnck_window_get_icon_surface (WnckWindow *window) ++{ ++ g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL); ++ ++ _wnck_window_load_icons (window); ++ ++ return cairo_surface_reference (window->priv->icon); ++} ++ ++/** ++ * wnck_window_get_mini_icon_surface: ++ * @window: a #WnckWindow. ++ * ++ * Gets the mini-icon-surface to be used for @window. If no mini-icon-surface ++ * was found, a fallback mini-icon-surface is used. wnck_window_get_icon_is_fallback() ++ * can be used to tell if the mini-icon-surface is the fallback mini-icon-surface. ++ * ++ * Return value: (transfer full): a reference to the mini-icon-surface for @window. ++ * The caller should unreference the returned cairo_surface_t ++ * once done with it. ++ **/ ++cairo_surface_t* ++wnck_window_get_mini_icon_surface (WnckWindow *window) + { + g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL); + + _wnck_window_load_icons (window); + +- return window->priv->mini_icon; ++ return cairo_surface_reference (window->priv->mini_icon); + } + + /** +diff --git a/libwnck/window.h b/libwnck/window.h +index 47c6543..2bec086 100644 +--- a/libwnck/window.h ++++ b/libwnck/window.h +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + G_BEGIN_DECLS + +@@ -382,6 +383,8 @@ gboolean wnck_window_transient_is_most_recently_activated (WnckWindow *window); + + GdkPixbuf* wnck_window_get_icon (WnckWindow *window); + GdkPixbuf* wnck_window_get_mini_icon (WnckWindow *window); ++cairo_surface_t* wnck_window_get_icon_surface (WnckWindow *window); ++cairo_surface_t* wnck_window_get_mini_icon_surface (WnckWindow *window); + + gboolean wnck_window_get_icon_is_fallback (WnckWindow *window); + +diff --git a/libwnck/wnck-image-menu-item-private.h b/libwnck/wnck-image-menu-item-private.h +index 265289d..5c47517 100644 +--- a/libwnck/wnck-image-menu-item-private.h ++++ b/libwnck/wnck-image-menu-item-private.h +@@ -34,6 +34,9 @@ GtkWidget *wnck_image_menu_item_new_with_label (const gchar *l + void wnck_image_menu_item_set_image_from_icon_pixbuf (WnckImageMenuItem *item, + GdkPixbuf *pixbuf); + ++void wnck_image_menu_item_set_image_from_icon_surface (WnckImageMenuItem *item, ++ cairo_surface_t *surface); ++ + void wnck_image_menu_item_set_image_from_window (WnckImageMenuItem *item, + WnckWindow *window); + +diff --git a/libwnck/wnck-image-menu-item.c b/libwnck/wnck-image-menu-item.c +index e8e6d87..7f5efdc 100644 +--- a/libwnck/wnck-image-menu-item.c ++++ b/libwnck/wnck-image-menu-item.c +@@ -219,6 +219,14 @@ wnck_image_menu_item_set_image_from_icon_pixbuf (WnckImageMenuItem *item, + gtk_widget_show (item->image); + } + ++void ++wnck_image_menu_item_set_image_from_icon_surface (WnckImageMenuItem *item, ++ cairo_surface_t *surface) ++{ ++ gtk_image_set_from_surface (GTK_IMAGE (item->image), surface); ++ gtk_widget_show (item->image); ++} ++ + void + wnck_image_menu_item_set_image_from_window (WnckImageMenuItem *item, + WnckWindow *window) +-- +2.37.2 + diff --git a/SOURCES/libwnck_0003-xutils-Change-icons-to-being-cairo-surfaces_43.patch b/SOURCES/libwnck_0003-xutils-Change-icons-to-being-cairo-surfaces_43.patch new file mode 100644 index 0000000..f0f1396 --- /dev/null +++ b/SOURCES/libwnck_0003-xutils-Change-icons-to-being-cairo-surfaces_43.patch @@ -0,0 +1,772 @@ +From 53d505622e90805684260873d0fbadaec9e2d3ed Mon Sep 17 00:00:00 2001 +From: Victor Kareh +Date: Mon, 20 Jan 2020 13:38:59 -0500 +Subject: [PATCH 3/5] xutils: Change icons to being cairo surfaces + +Since all icons are stored internally as cairo surfaces, we should be +returning icons as cairo surfaces from the private functions in xutils. +This simplifies the drawing codepath and makes us able to delete a bunch +of GdkPixbuf manipulation. + +adapted from https://gitlab.gnome.org/GNOME/mutter/commit/af7f51b9 +--- + libwnck/application.c | 22 +-- + libwnck/class-group.c | 17 +- + libwnck/tasklist.c | 9 +- + libwnck/window.c | 22 +-- + libwnck/wnck-icon-cache-private.h | 15 +- + libwnck/wnck-icon-cache.c | 299 +++++++++++++----------------- + libwnck/xutils.c | 42 ++--- + libwnck/xutils.h | 11 +- + 8 files changed, 179 insertions(+), 258 deletions(-) + +diff --git a/libwnck/application.c b/libwnck/application.c +index d8283cc..b441eb6 100644 +--- a/libwnck/application.c ++++ b/libwnck/application.c +@@ -309,10 +309,11 @@ static void + get_icons (WnckApplication *app) + { + WnckHandle *handle; +- GdkPixbuf *icon; +- GdkPixbuf *mini_icon; ++ cairo_surface_t *icon; ++ cairo_surface_t *mini_icon; + gsize normal_size; + gsize mini_size; ++ int scaling_factor; + + handle = wnck_screen_get_handle (app->priv->screen); + +@@ -320,6 +321,7 @@ get_icons (WnckApplication *app) + mini_icon = NULL; + normal_size = _wnck_handle_get_default_icon_size (handle); + mini_size = _wnck_handle_get_default_mini_icon_size (handle); ++ scaling_factor = _wnck_get_window_scaling_factor (); + + if (_wnck_read_icons (app->priv->screen, + app->priv->xwindow, +@@ -327,24 +329,16 @@ get_icons (WnckApplication *app) + &icon, + normal_size, + &mini_icon, +- mini_size)) ++ mini_size, ++ scaling_factor)) + { + app->priv->need_emit_icon_changed = TRUE; + + g_clear_pointer (&app->priv->icon, cairo_surface_destroy); + g_clear_pointer (&app->priv->mini_icon, cairo_surface_destroy); + +- if (icon) +- { +- app->priv->icon = gdk_cairo_surface_create_from_pixbuf (icon, 0, NULL); +- g_clear_object (&icon); +- } +- +- if (mini_icon) +- { +- app->priv->mini_icon = gdk_cairo_surface_create_from_pixbuf (mini_icon, 0, NULL); +- g_clear_object (&mini_icon); +- } ++ app->priv->icon = icon; ++ app->priv->mini_icon = mini_icon; + } + + /* FIXME we should really fall back to using the icon +diff --git a/libwnck/class-group.c b/libwnck/class-group.c +index e6c45d6..7899497 100644 +--- a/libwnck/class-group.c ++++ b/libwnck/class-group.c +@@ -441,23 +441,10 @@ set_icon (WnckClassGroup *class_group) + + handle = wnck_screen_get_handle (class_group->priv->screen); + +- GdkPixbuf *icon_pixbuf, *mini_icon_pixbuf; +- +- _wnck_get_fallback_icons (&icon_pixbuf, ++ _wnck_get_fallback_icons (&icon, + _wnck_handle_get_default_icon_size (handle), +- &mini_icon_pixbuf, ++ &mini_icon, + _wnck_handle_get_default_mini_icon_size (handle)); +- if (icon_pixbuf) +- { +- icon = gdk_cairo_surface_create_from_pixbuf (icon_pixbuf, 0, NULL); +- g_clear_object (&icon_pixbuf); +- } +- +- if (mini_icon_pixbuf) +- { +- mini_icon = gdk_cairo_surface_create_from_pixbuf (mini_icon_pixbuf, 0, NULL); +- g_clear_object (&mini_icon_pixbuf); +- } + + icons_reffed = TRUE; + } +diff --git a/libwnck/tasklist.c b/libwnck/tasklist.c +index 10c6cc8..3e7b789 100644 +--- a/libwnck/tasklist.c ++++ b/libwnck/tasklist.c +@@ -3898,15 +3898,8 @@ wnck_task_get_icon (WnckTask *task) + + if (surface == NULL) + { +- GdkPixbuf *pixbuf; + _wnck_get_fallback_icons (NULL, 0, +- &pixbuf, mini_icon_size); +- +- if (pixbuf != NULL) +- { +- surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 0, NULL); +- g_object_unref (pixbuf); +- } ++ &surface, mini_icon_size); + } + #endif + break; +diff --git a/libwnck/window.c b/libwnck/window.c +index f01b4c2..5c97675 100644 +--- a/libwnck/window.c ++++ b/libwnck/window.c +@@ -2105,10 +2105,11 @@ static void + get_icons (WnckWindow *window) + { + WnckHandle *handle; +- GdkPixbuf *icon; +- GdkPixbuf *mini_icon; ++ cairo_surface_t *icon; ++ cairo_surface_t *mini_icon; + gsize normal_size; + gsize mini_size; ++ int scaling_factor; + + handle = wnck_screen_get_handle (window->priv->screen); + +@@ -2116,6 +2117,7 @@ get_icons (WnckWindow *window) + mini_icon = NULL; + normal_size = _wnck_handle_get_default_icon_size (handle); + mini_size = _wnck_handle_get_default_mini_icon_size (handle); ++ scaling_factor = _wnck_get_window_scaling_factor (); + + if (_wnck_read_icons (window->priv->screen, + window->priv->xwindow, +@@ -2123,24 +2125,16 @@ get_icons (WnckWindow *window) + &icon, + normal_size, + &mini_icon, +- mini_size)) ++ mini_size, ++ scaling_factor)) + { + window->priv->need_emit_icon_changed = TRUE; + + g_clear_pointer (&window->priv->icon, cairo_surface_destroy); + g_clear_pointer (&window->priv->mini_icon, cairo_surface_destroy); + +- if (icon) +- { +- window->priv->icon = gdk_cairo_surface_create_from_pixbuf (icon, 0, NULL); +- g_clear_object (&icon); +- } +- +- if (mini_icon) +- { +- window->priv->mini_icon = gdk_cairo_surface_create_from_pixbuf (mini_icon, 0, NULL); +- g_clear_object (&mini_icon); +- } ++ window->priv->icon = icon; ++ window->priv->mini_icon = mini_icon; + } + + g_assert ((window->priv->icon && window->priv->mini_icon) || +diff --git a/libwnck/wnck-icon-cache-private.h b/libwnck/wnck-icon-cache-private.h +index 6a3d5ec..d3c39e2 100644 +--- a/libwnck/wnck-icon-cache-private.h ++++ b/libwnck/wnck-icon-cache-private.h +@@ -38,13 +38,14 @@ void _wnck_icon_cache_set_want_fallback (WnckIconCache *icon_cache + gboolean setting); + gboolean _wnck_icon_cache_get_is_fallback (WnckIconCache *icon_cache); + +-gboolean _wnck_read_icons (WnckScreen *screen, +- Window xwindow, +- WnckIconCache *icon_cache, +- GdkPixbuf **iconp, +- int ideal_size, +- GdkPixbuf **mini_iconp, +- int ideal_mini_size); ++gboolean _wnck_read_icons (WnckScreen *screen, ++ Window xwindow, ++ WnckIconCache *icon_cache, ++ cairo_surface_t **iconp, ++ int ideal_size, ++ cairo_surface_t **mini_iconp, ++ int ideal_mini_size, ++ int scaling_factor); + + G_END_DECLS + +diff --git a/libwnck/wnck-icon-cache.c b/libwnck/wnck-icon-cache.c +index 9ff8d15..d9e67e8 100644 +--- a/libwnck/wnck-icon-cache.c ++++ b/libwnck/wnck-icon-cache.c +@@ -44,8 +44,8 @@ struct _WnckIconCache + IconOrigin origin; + Pixmap prev_pixmap; + Pixmap prev_mask; +- GdkPixbuf *icon; +- GdkPixbuf *mini_icon; ++ cairo_surface_t *icon; ++ cairo_surface_t *mini_icon; + int ideal_size; + int ideal_mini_size; + guint want_fallback : 1; +@@ -139,49 +139,65 @@ find_best_size (gulong *data, + return FALSE; + } + +-static void +-argbdata_to_pixdata (gulong *argb_data, int len, guchar **pixdata) ++static cairo_surface_t * ++argbdata_to_surface (gulong *argb_data, ++ int w, ++ int h, ++ int ideal_w, ++ int ideal_h, ++ int scaling_factor) + { +- guchar *p; +- int i; ++ cairo_surface_t *surface, *icon; ++ cairo_t *cr; ++ int y, x, stride; ++ uint32_t *data; + +- *pixdata = g_new (guchar, len * 4); +- p = *pixdata; ++ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); ++ cairo_surface_set_device_scale (surface, (double)scaling_factor, (double)scaling_factor); ++ stride = cairo_image_surface_get_stride (surface) / sizeof (uint32_t); ++ data = (uint32_t *) cairo_image_surface_get_data (surface); + + /* One could speed this up a lot. */ +- i = 0; +- while (i < len) ++ for (y = 0; y < h; y++) + { +- guint argb; +- guint rgba; +- +- argb = argb_data[i]; +- rgba = (argb << 8) | (argb >> 24); +- +- *p = rgba >> 24; +- ++p; +- *p = (rgba >> 16) & 0xff; +- ++p; +- *p = (rgba >> 8) & 0xff; +- ++p; +- *p = rgba & 0xff; +- ++p; +- +- ++i; ++ for (x = 0; x < w; x++) ++ { ++ uint32_t *p = &data[y * stride + x]; ++ gulong *d = &argb_data[y * w + x]; ++ *p = *d; ++ } + } ++ ++ cairo_surface_mark_dirty (surface); ++ ++ icon = cairo_surface_create_similar_image (surface, ++ cairo_image_surface_get_format (surface), ++ ideal_w, ideal_h); ++ ++ cairo_surface_set_device_scale (icon, (double)scaling_factor, (double)scaling_factor); ++ ++ cr = cairo_create (icon); ++ cairo_scale (cr, ideal_w / (double)w, ideal_h / (double)h); ++ cairo_set_source_surface (cr, surface, 0, 0); ++ cairo_paint (cr); ++ ++ cairo_set_operator (cr, CAIRO_OPERATOR_IN); ++ cairo_paint (cr); ++ ++ cairo_destroy (cr); ++ cairo_surface_destroy (surface); ++ ++ return icon; + } + + static gboolean +-read_rgb_icon (Screen *screen, +- Window xwindow, +- int ideal_size, +- int ideal_mini_size, +- int *width, +- int *height, +- guchar **pixdata, +- int *mini_width, +- int *mini_height, +- guchar **mini_pixdata) ++read_rgb_icon (Screen *screen, ++ Window xwindow, ++ int ideal_size, ++ int ideal_mini_size, ++ cairo_surface_t **iconp, ++ cairo_surface_t **mini_iconp, ++ int scaling_factor) + { + Display *display; + Atom type; +@@ -219,7 +235,9 @@ read_rgb_icon (Screen *screen, + return FALSE; + } + +- if (!find_best_size (data, nitems, ideal_size, &w, &h, &best)) ++ if (!find_best_size (data, nitems, ++ ideal_size, ++ &w, &h, &best)) + { + XFree (data); + return FALSE; +@@ -233,14 +251,8 @@ read_rgb_icon (Screen *screen, + return FALSE; + } + +- *width = w; +- *height = h; +- +- *mini_width = mini_w; +- *mini_height = mini_h; +- +- argbdata_to_pixdata (best, w * h, pixdata); +- argbdata_to_pixdata (best_mini, mini_w * mini_h, mini_pixdata); ++ *iconp = argbdata_to_surface (best, w, h, ideal_size, ideal_size, scaling_factor); ++ *mini_iconp = argbdata_to_surface (best_mini, mini_w, mini_h, ideal_mini_size, ideal_mini_size, scaling_factor); + + XFree (data); + +@@ -248,27 +260,27 @@ read_rgb_icon (Screen *screen, + } + + static gboolean +-try_pixmap_and_mask (Screen *screen, +- Pixmap src_pixmap, +- Pixmap src_mask, +- GdkPixbuf **iconp, +- int ideal_size, +- GdkPixbuf **mini_iconp, +- int ideal_mini_size) ++try_pixmap_and_mask (Screen *screen, ++ Pixmap src_pixmap, ++ Pixmap src_mask, ++ cairo_surface_t **iconp, ++ int ideal_size, ++ cairo_surface_t **mini_iconp, ++ int ideal_mini_size, ++ int scaling_factor) + { + cairo_surface_t *surface, *mask_surface, *image; + GdkDisplay *gdk_display; +- GdkPixbuf *unscaled; + int width, height; + cairo_t *cr; + + if (src_pixmap == None) + return FALSE; + +- surface = _wnck_cairo_surface_get_from_pixmap (screen, src_pixmap); ++ surface = _wnck_cairo_surface_get_from_pixmap (screen, src_pixmap, scaling_factor); + + if (surface && src_mask != None) +- mask_surface = _wnck_cairo_surface_get_from_pixmap (screen, src_mask); ++ mask_surface = _wnck_cairo_surface_get_from_pixmap (screen, src_mask, scaling_factor); + else + mask_surface = NULL; + +@@ -324,26 +336,41 @@ try_pixmap_and_mask (Screen *screen, + return FALSE; + } + +- unscaled = gdk_pixbuf_get_from_surface (image, +- 0, 0, +- width, height); ++ if (image) ++ { ++ int image_w, image_h; + +- cairo_surface_destroy (image); ++ image_w = cairo_image_surface_get_width (image); ++ image_h = cairo_image_surface_get_height (image); ++ ++ *iconp = cairo_surface_create_similar (image, ++ cairo_surface_get_content (image), ++ ideal_size, ++ ideal_size); ++ ++ cairo_surface_set_device_scale (*iconp, (double)scaling_factor, (double)scaling_factor); ++ ++ cr = cairo_create (*iconp); ++ cairo_scale (cr, ideal_size / (double)image_w, ideal_size / (double)image_h); ++ cairo_set_source_surface (cr, image, 0, 0); ++ cairo_paint (cr); ++ cairo_destroy (cr); ++ ++ *mini_iconp = cairo_surface_create_similar (image, ++ cairo_surface_get_content (image), ++ ideal_mini_size, ++ ideal_mini_size); ++ ++ cairo_surface_set_device_scale (*mini_iconp, (double)scaling_factor, (double)scaling_factor); ++ ++ cr = cairo_create (*mini_iconp); ++ cairo_scale (cr, ideal_mini_size / (double)image_w, ideal_mini_size / (double)image_h); ++ cairo_set_source_surface (cr, image, 0, 0); ++ cairo_paint (cr); ++ cairo_destroy (cr); ++ ++ cairo_surface_destroy (image); + +- if (unscaled) +- { +- *iconp = +- gdk_pixbuf_scale_simple (unscaled, +- ideal_size, +- ideal_size, +- GDK_INTERP_BILINEAR); +- *mini_iconp = +- gdk_pixbuf_scale_simple (unscaled, +- ideal_mini_size, +- ideal_mini_size, +- GDK_INTERP_BILINEAR); +- +- g_object_unref (G_OBJECT (unscaled)); + return TRUE; + } + else +@@ -354,13 +381,8 @@ static void + clear_icon_cache (WnckIconCache *icon_cache, + gboolean dirty_all) + { +- if (icon_cache->icon) +- g_object_unref (G_OBJECT (icon_cache->icon)); +- icon_cache->icon = NULL; +- +- if (icon_cache->mini_icon) +- g_object_unref (G_OBJECT (icon_cache->mini_icon)); +- icon_cache->mini_icon = NULL; ++ g_clear_pointer (&icon_cache->icon, cairo_surface_destroy); ++ g_clear_pointer (&icon_cache->mini_icon, cairo_surface_destroy); + + icon_cache->origin = USING_NO_ICON; + +@@ -372,89 +394,26 @@ clear_icon_cache (WnckIconCache *icon_cache, + } + + static void +-replace_cache (WnckIconCache *icon_cache, +- IconOrigin origin, +- GdkPixbuf *new_icon, +- GdkPixbuf *new_mini_icon) ++replace_cache (WnckIconCache *icon_cache, ++ IconOrigin origin, ++ cairo_surface_t *new_icon, ++ cairo_surface_t *new_mini_icon) + { + clear_icon_cache (icon_cache, FALSE); + + icon_cache->origin = origin; + + if (new_icon) +- g_object_ref (G_OBJECT (new_icon)); ++ cairo_surface_reference (new_icon); + + icon_cache->icon = new_icon; + + if (new_mini_icon) +- g_object_ref (G_OBJECT (new_mini_icon)); ++ cairo_surface_reference (new_mini_icon); + + icon_cache->mini_icon = new_mini_icon; + } + +-static void +-free_pixels (guchar *pixels, +- gpointer data) +-{ +- g_free (pixels); +-} +- +-static GdkPixbuf* +-scaled_from_pixdata (guchar *pixdata, +- int w, +- int h, +- int new_w, +- int new_h) +-{ +- GdkPixbuf *src; +- GdkPixbuf *dest; +- +- src = gdk_pixbuf_new_from_data (pixdata, +- GDK_COLORSPACE_RGB, +- TRUE, +- 8, +- w, h, w * 4, +- free_pixels, +- NULL); +- +- if (src == NULL) +- return NULL; +- +- if (w != h) +- { +- GdkPixbuf *tmp; +- int size; +- +- size = MAX (w, h); +- +- tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size, size); +- +- if (tmp != NULL) +- { +- gdk_pixbuf_fill (tmp, 0); +- gdk_pixbuf_copy_area (src, 0, 0, w, h, +- tmp, +- (size - w) / 2, (size - h) / 2); +- +- g_object_unref (src); +- src = tmp; +- } +- } +- +- if (w != new_w || h != new_h) +- { +- dest = gdk_pixbuf_scale_simple (src, new_w, new_h, GDK_INTERP_BILINEAR); +- +- g_object_unref (G_OBJECT (src)); +- } +- else +- { +- dest = src; +- } +- +- return dest; +-} +- + WnckIconCache* + _wnck_icon_cache_new (void) + { +@@ -528,22 +487,17 @@ _wnck_icon_cache_get_is_fallback (WnckIconCache *icon_cache) + } + + gboolean +-_wnck_read_icons (WnckScreen *screen, +- Window xwindow, +- WnckIconCache *icon_cache, +- GdkPixbuf **iconp, +- int ideal_size, +- GdkPixbuf **mini_iconp, +- int ideal_mini_size) ++_wnck_read_icons (WnckScreen *screen, ++ Window xwindow, ++ WnckIconCache *icon_cache, ++ cairo_surface_t **iconp, ++ int ideal_size, ++ cairo_surface_t **mini_iconp, ++ int ideal_mini_size, ++ int scaling_factor) + { + Screen *xscreen; + Display *display; +- guchar *pixdata; +- int w, h; +- guchar *mini_pixdata; +- int mini_w, mini_h; +- Pixmap pixmap; +- Pixmap mask; + XWMHints *hints; + + /* Return value is whether the icon changed */ +@@ -556,6 +510,9 @@ _wnck_read_icons (WnckScreen *screen, + *iconp = NULL; + *mini_iconp = NULL; + ++ ideal_size *= scaling_factor; ++ ideal_mini_size *= scaling_factor; ++ + if (ideal_size != icon_cache->ideal_size || + ideal_mini_size != icon_cache->ideal_mini_size) + clear_icon_cache (icon_cache, TRUE); +@@ -566,8 +523,6 @@ _wnck_read_icons (WnckScreen *screen, + if (!_wnck_icon_cache_get_icon_invalidated (icon_cache)) + return FALSE; /* we have no new info to use */ + +- pixdata = NULL; +- + /* Our algorithm here assumes that we can't have for example origin + * < USING_NET_WM_ICON and icon_cache->net_wm_icon_dirty == FALSE + * unless we have tried to read NET_WM_ICON. +@@ -579,21 +534,15 @@ _wnck_read_icons (WnckScreen *screen, + + if (icon_cache->origin <= USING_NET_WM_ICON && + icon_cache->net_wm_icon_dirty) +- + { + icon_cache->net_wm_icon_dirty = FALSE; + + if (read_rgb_icon (xscreen, xwindow, + ideal_size, + ideal_mini_size, +- &w, &h, &pixdata, +- &mini_w, &mini_h, &mini_pixdata)) ++ iconp, mini_iconp, ++ scaling_factor)) + { +- *iconp = scaled_from_pixdata (pixdata, w, h, ideal_size, ideal_size); +- +- *mini_iconp = scaled_from_pixdata (mini_pixdata, mini_w, mini_h, +- ideal_mini_size, ideal_mini_size); +- + replace_cache (icon_cache, USING_NET_WM_ICON, + *iconp, *mini_iconp); + +@@ -604,6 +553,9 @@ _wnck_read_icons (WnckScreen *screen, + if (icon_cache->origin <= USING_WM_HINTS && + icon_cache->wm_hints_dirty) + { ++ Pixmap pixmap; ++ Pixmap mask; ++ + icon_cache->wm_hints_dirty = FALSE; + + _wnck_error_trap_push (display); +@@ -632,7 +584,8 @@ _wnck_read_icons (WnckScreen *screen, + { + if (try_pixmap_and_mask (xscreen, pixmap, mask, + iconp, ideal_size, +- mini_iconp, ideal_mini_size)) ++ mini_iconp, ideal_mini_size, ++ scaling_factor)) + { + icon_cache->prev_pixmap = pixmap; + icon_cache->prev_mask = mask; +diff --git a/libwnck/xutils.c b/libwnck/xutils.c +index 60ae7b2..476f027 100644 +--- a/libwnck/xutils.c ++++ b/libwnck/xutils.c +@@ -1389,7 +1389,8 @@ _wnck_select_input (Screen *screen, + + cairo_surface_t * + _wnck_cairo_surface_get_from_pixmap (Screen *screen, +- Pixmap xpixmap) ++ Pixmap xpixmap, ++ int scaling_factor) + { + cairo_surface_t *surface; + Display *display; +@@ -1407,6 +1408,9 @@ _wnck_cairo_surface_get_from_pixmap (Screen *screen, + &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret)) + goto TRAP_POP; + ++ w_ret *= scaling_factor; ++ h_ret *= scaling_factor; ++ + if (depth_ret == 1) + { + surface = cairo_xlib_surface_create_for_bitmap (display, +@@ -1463,7 +1467,7 @@ _wnck_gdk_pixbuf_get_from_pixmap (Screen *screen, + cairo_surface_t *surface; + GdkPixbuf *retval; + +- surface = _wnck_cairo_surface_get_from_pixmap (screen, xpixmap); ++ surface = _wnck_cairo_surface_get_from_pixmap (screen, xpixmap, 1); + + if (surface == NULL) + return NULL; +@@ -1478,36 +1482,30 @@ _wnck_gdk_pixbuf_get_from_pixmap (Screen *screen, + return retval; + } + +-static GdkPixbuf* ++static cairo_surface_t* + default_icon_at_size (int size) + { +- GdkPixbuf *base; ++ GdkPixbuf *pixbuf; ++ cairo_surface_t *surface; + +- base = gdk_pixbuf_new_from_resource ("/org/gnome/libwnck/default_icon.png", NULL); ++ pixbuf = gdk_pixbuf_new_from_resource_at_scale ("/org/gnome/libwnck/default_icon.png", ++ size, size, ++ TRUE, NULL); + +- g_assert (base); ++ g_assert (pixbuf); + +- if (gdk_pixbuf_get_width (base) == size && +- gdk_pixbuf_get_height (base) == size) +- { +- return base; +- } +- else +- { +- GdkPixbuf *scaled; ++ surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 0, NULL); + +- scaled = gdk_pixbuf_scale_simple (base, size, size, GDK_INTERP_BILINEAR); +- g_object_unref (G_OBJECT (base)); ++ g_clear_object (&pixbuf); + +- return scaled; +- } ++ return surface; + } + + void +-_wnck_get_fallback_icons (GdkPixbuf **iconp, +- int ideal_size, +- GdkPixbuf **mini_iconp, +- int ideal_mini_size) ++_wnck_get_fallback_icons (cairo_surface_t **iconp, ++ int ideal_size, ++ cairo_surface_t **mini_iconp, ++ int ideal_mini_size) + { + if (iconp) + *iconp = default_icon_at_size (ideal_size); +diff --git a/libwnck/xutils.h b/libwnck/xutils.h +index 4e5c620..51e8e55 100644 +--- a/libwnck/xutils.h ++++ b/libwnck/xutils.h +@@ -156,10 +156,10 @@ void _wnck_keyboard_size (WnckScreen *screen, + void _wnck_toggle_showing_desktop (Screen *screen, + gboolean show); + +-void _wnck_get_fallback_icons (GdkPixbuf **iconp, +- int ideal_size, +- GdkPixbuf **mini_iconp, +- int ideal_mini_size); ++void _wnck_get_fallback_icons (cairo_surface_t **iconp, ++ int ideal_size, ++ cairo_surface_t **mini_iconp, ++ int ideal_mini_size); + + void _wnck_get_window_geometry (Screen *screen, + Window xwindow, +@@ -192,7 +192,8 @@ void _wnck_set_desktop_layout (Screen *xscreen, + int columns); + + cairo_surface_t *_wnck_cairo_surface_get_from_pixmap (Screen *screen, +- Pixmap xpixmap); ++ Pixmap xpixmap, ++ int scaling_factor); + + GdkPixbuf* _wnck_gdk_pixbuf_get_from_pixmap (Screen *screen, + Pixmap xpixmap); +-- +2.37.2 + diff --git a/SOURCES/libwnck_0004-icons-Mark-GdkPixbuf-icons-as-deprecated_43.patch b/SOURCES/libwnck_0004-icons-Mark-GdkPixbuf-icons-as-deprecated_43.patch new file mode 100644 index 0000000..cc3940c --- /dev/null +++ b/SOURCES/libwnck_0004-icons-Mark-GdkPixbuf-icons-as-deprecated_43.patch @@ -0,0 +1,189 @@ +From d8316f3e2745fde9039f03a1e619f13132f21bf4 Mon Sep 17 00:00:00 2001 +From: Victor Kareh +Date: Tue, 11 Feb 2020 07:40:47 -0500 +Subject: [PATCH 4/5] icons: Mark GdkPixbuf icons as deprecated + +Since we have migrated icons to render as cairo surfaces we can now mark +GdkPixbuf icons as deprecated without having to break the API. +--- + libwnck/application.c | 8 ++++++++ + libwnck/application.h | 6 ++++++ + libwnck/class-group.c | 4 ++++ + libwnck/class-group.h | 4 ++++ + libwnck/test-wnck.c | 2 +- + libwnck/window.c | 6 ++++++ + libwnck/window.h | 4 ++++ + 7 files changed, 33 insertions(+), 1 deletion(-) + +diff --git a/libwnck/application.c b/libwnck/application.c +index b441eb6..9096ddb 100644 +--- a/libwnck/application.c ++++ b/libwnck/application.c +@@ -395,6 +395,8 @@ find_icon_window (WnckApplication *app) + * Return value: (transfer none): the icon for @app. The caller should + * reference the returned GdkPixbuf if it needs to keep + * the icon around. ++ * ++ * Deprecated:41.0: Use wnck_application_get_icon_surface() instead. + **/ + GdkPixbuf* + wnck_application_get_icon (WnckApplication *app) +@@ -434,10 +436,12 @@ wnck_application_get_icon (WnckApplication *app) + } + else + { ++G_GNUC_BEGIN_IGNORE_DEPRECATIONS + WnckWindow *w = find_icon_window (app); + if (w) + return wnck_window_get_icon (w); + else ++G_GNUC_END_IGNORE_DEPRECATIONS + return NULL; + } + } +@@ -453,6 +457,8 @@ wnck_application_get_icon (WnckApplication *app) + * Return value: (transfer none): the mini-icon for @app. The caller should + * reference the returned GdkPixbuf if it needs to keep + * the mini-icon around. ++ * ++ * Deprecated:41.0: Use wnck_application_get_mini_icon_surface() instead. + **/ + GdkPixbuf* + wnck_application_get_mini_icon (WnckApplication *app) +@@ -492,10 +498,12 @@ wnck_application_get_mini_icon (WnckApplication *app) + } + else + { ++G_GNUC_BEGIN_IGNORE_DEPRECATIONS + WnckWindow *w = find_icon_window (app); + if (w) + return wnck_window_get_mini_icon (w); + else ++G_GNUC_END_IGNORE_DEPRECATIONS + return NULL; + } + } +diff --git a/libwnck/application.h b/libwnck/application.h +index f3ea970..4d9078e 100644 +--- a/libwnck/application.h ++++ b/libwnck/application.h +@@ -91,10 +91,16 @@ int wnck_application_get_n_windows (WnckApplication *app); + const char* wnck_application_get_name (WnckApplication *app); + const char* wnck_application_get_icon_name (WnckApplication *app); + int wnck_application_get_pid (WnckApplication *app); ++ ++G_DEPRECATED_FOR(wnck_application_get_icon_surface) + GdkPixbuf* wnck_application_get_icon (WnckApplication *app); ++ ++G_DEPRECATED_FOR(wnck_application_get_mini_icon_surface) + GdkPixbuf* wnck_application_get_mini_icon (WnckApplication *app); ++ + cairo_surface_t* wnck_application_get_icon_surface (WnckApplication *app); + cairo_surface_t* wnck_application_get_mini_icon_surface (WnckApplication *app); ++ + gboolean wnck_application_get_icon_is_fallback (WnckApplication *app); + const char* wnck_application_get_startup_id (WnckApplication *app); + +diff --git a/libwnck/class-group.c b/libwnck/class-group.c +index 7899497..026e995 100644 +--- a/libwnck/class-group.c ++++ b/libwnck/class-group.c +@@ -689,6 +689,8 @@ wnck_class_group_get_name (WnckClassGroup *class_group) + * the icon around. + * + * Since: 2.2 ++ * ++ * Deprecated:41.0: Use wnck_class_group_get_icon_surface() instead. + **/ + GdkPixbuf * + wnck_class_group_get_icon (WnckClassGroup *class_group) +@@ -741,6 +743,8 @@ wnck_class_group_get_icon (WnckClassGroup *class_group) + * to keep the mini-icon around. + * + * Since: 2.2 ++ * ++ * Deprecated:41.0: Use wnck_class_group_get_mini_icon_surface() instead. + **/ + GdkPixbuf * + wnck_class_group_get_mini_icon (WnckClassGroup *class_group) +diff --git a/libwnck/class-group.h b/libwnck/class-group.h +index 122e0ed..dee0e7c 100644 +--- a/libwnck/class-group.h ++++ b/libwnck/class-group.h +@@ -81,8 +81,12 @@ const char * wnck_class_group_get_id (WnckClassGroup *class_group); + + const char * wnck_class_group_get_name (WnckClassGroup *class_group); + ++G_DEPRECATED_FOR(wnck_class_group_get_icon_surface) + GdkPixbuf *wnck_class_group_get_icon (WnckClassGroup *class_group); ++ ++G_DEPRECATED_FOR(wnck_class_group_get_mini_icon_surface) + GdkPixbuf *wnck_class_group_get_mini_icon (WnckClassGroup *class_group); ++ + cairo_surface_t *wnck_class_group_get_icon_surface (WnckClassGroup *class_group); + cairo_surface_t *wnck_class_group_get_mini_icon_surface (WnckClassGroup *class_group); + +diff --git a/libwnck/test-wnck.c b/libwnck/test-wnck.c +index 77085cd..649c2e6 100644 +--- a/libwnck/test-wnck.c ++++ b/libwnck/test-wnck.c +@@ -523,7 +523,7 @@ icon_set_func (GtkTreeViewColumn *tree_column, + return; + + g_object_set (GTK_CELL_RENDERER (cell), +- "pixbuf", wnck_window_get_mini_icon (window), ++ "surface", wnck_window_get_mini_icon_surface (window), + NULL); + } + +diff --git a/libwnck/window.c b/libwnck/window.c +index 5c97675..3cd800d 100644 +--- a/libwnck/window.c ++++ b/libwnck/window.c +@@ -21,6 +21,8 @@ + * License along with this library; if not, see . + */ + ++#undef WNCK_DISABLE_DEPRECATED ++ + #include + + #include +@@ -2164,6 +2166,8 @@ _wnck_window_load_icons (WnckWindow *window) + * Return value: (transfer none): the icon for @window. The caller should + * reference the returned GdkPixbuf if it needs to keep + * the icon around. ++ * ++ * Deprecated:41.0: Use wnck_window_get_icon_surface() instead. + **/ + GdkPixbuf* + wnck_window_get_icon (WnckWindow *window) +@@ -2216,6 +2220,8 @@ wnck_window_get_icon (WnckWindow *window) + * Return value: (transfer none): the mini-icon for @window. The caller should + * reference the returned GdkPixbuf if it needs to keep + * the icon around. ++ * ++ * Deprecated:41.0: Use wnck_window_get_mini_icon_surface() instead. + **/ + GdkPixbuf* + wnck_window_get_mini_icon (WnckWindow *window) +diff --git a/libwnck/window.h b/libwnck/window.h +index 2bec086..d7e52f1 100644 +--- a/libwnck/window.h ++++ b/libwnck/window.h +@@ -381,8 +381,12 @@ void wnck_window_activate_transient (WnckWindow *window, + guint32 timestamp); + gboolean wnck_window_transient_is_most_recently_activated (WnckWindow *window); + ++G_DEPRECATED_FOR(wnck_window_get_icon_surface) + GdkPixbuf* wnck_window_get_icon (WnckWindow *window); ++ ++G_DEPRECATED_FOR(wnck_window_get_mini_icon_surface) + GdkPixbuf* wnck_window_get_mini_icon (WnckWindow *window); ++ + cairo_surface_t* wnck_window_get_icon_surface (WnckWindow *window); + cairo_surface_t* wnck_window_get_mini_icon_surface (WnckWindow *window); + +-- +2.37.2 + diff --git a/SOURCES/libwnck_0005-tasklist-Add-surface-loader-function_43.patch b/SOURCES/libwnck_0005-tasklist-Add-surface-loader-function_43.patch new file mode 100644 index 0000000..b93d5cb --- /dev/null +++ b/SOURCES/libwnck_0005-tasklist-Add-surface-loader-function_43.patch @@ -0,0 +1,134 @@ +From 6cdfd1fe219c207bcc3355fde21b58979cdbf633 Mon Sep 17 00:00:00 2001 +From: Victor Kareh +Date: Thu, 3 Jun 2021 14:04:06 -0400 +Subject: [PATCH 5/5] tasklist: Add surface loader function + +Since the tasklist now supports cairo_surface_t icons, we provide +a similar icon loader function that takes surface icons. +--- + libwnck/tasklist.c | 50 +++++++++++++++++++++++++++++++++++++++++++++- + libwnck/tasklist.h | 26 ++++++++++++++++++++++++ + 2 files changed, 75 insertions(+), 1 deletion(-) + +diff --git a/libwnck/tasklist.c b/libwnck/tasklist.c +index 3e7b789..225f62e 100644 +--- a/libwnck/tasklist.c ++++ b/libwnck/tasklist.c +@@ -235,6 +235,10 @@ struct _WnckTasklistPrivate + void *icon_loader_data; + GDestroyNotify free_icon_loader_data; + ++ WnckLoadSurfaceFunction surface_loader; ++ void *surface_loader_data; ++ GDestroyNotify free_surface_loader_data; ++ + #ifdef HAVE_STARTUP_NOTIFICATION + SnDisplay *sn_display; + SnMonitorContext *sn_context; +@@ -1215,6 +1219,11 @@ wnck_tasklist_finalize (GObject *object) + tasklist->priv->free_icon_loader_data = NULL; + tasklist->priv->icon_loader_data = NULL; + ++ if (tasklist->priv->free_surface_loader_data != NULL) ++ (* tasklist->priv->free_surface_loader_data) (tasklist->priv->surface_loader_data); ++ tasklist->priv->free_surface_loader_data = NULL; ++ tasklist->priv->surface_loader_data = NULL; ++ + g_clear_object (&tasklist->priv->handle); + + G_OBJECT_CLASS (wnck_tasklist_parent_class)->finalize (object); +@@ -1455,6 +1464,31 @@ wnck_tasklist_set_icon_loader (WnckTasklist *tasklist, + tasklist->priv->free_icon_loader_data = free_data_func; + } + ++/** ++ * wnck_tasklist_set_surface_loader: ++ * @tasklist: a #WnckTasklist ++ * @load_surface_func: icon loader function ++ * @data: data for icon loader function ++ * @free_data_func: function to free the data ++ * ++ * Sets a function to be used for loading cairo surface icons. ++ **/ ++void ++wnck_tasklist_set_surface_loader (WnckTasklist *tasklist, ++ WnckLoadSurfaceFunction load_surface_func, ++ void *data, ++ GDestroyNotify free_data_func) ++{ ++ g_return_if_fail (WNCK_IS_TASKLIST (tasklist)); ++ ++ if (tasklist->priv->free_surface_loader_data != NULL) ++ (* tasklist->priv->free_surface_loader_data) (tasklist->priv->surface_loader_data); ++ ++ tasklist->priv->surface_loader = load_surface_func; ++ tasklist->priv->surface_loader_data = data; ++ tasklist->priv->free_surface_loader_data = free_data_func; ++} ++ + static void + get_layout (GtkOrientation orientation, + int for_size, +@@ -3869,7 +3903,21 @@ wnck_task_get_icon (WnckTask *task) + + case WNCK_TASK_STARTUP_SEQUENCE: + #ifdef HAVE_STARTUP_NOTIFICATION +- if (task->tasklist->priv->icon_loader != NULL) ++ if (task->tasklist->priv->surface_loader != NULL) ++ { ++ const char *icon; ++ ++ icon = sn_startup_sequence_get_icon_name (task->startup_sequence); ++ if (icon != NULL) ++ { ++ surface = (* task->tasklist->priv->surface_loader) (icon, ++ mini_icon_size, ++ 0, ++ task->tasklist->priv->surface_loader_data); ++ ++ } ++ } ++ else if (task->tasklist->priv->icon_loader != NULL) + { + const char *icon; + +diff --git a/libwnck/tasklist.h b/libwnck/tasklist.h +index 5407d34..373eaaa 100644 +--- a/libwnck/tasklist.h ++++ b/libwnck/tasklist.h +@@ -141,6 +141,32 @@ void wnck_tasklist_set_icon_loader (WnckTasklist *tasklist, + void *data, + GDestroyNotify free_data_func); + ++/** ++ * WnckLoadSurfaceFunction: ++ * @icon_name: an icon name as in the Icon field in a .desktop file for the ++ * icon to load. ++ * @size: the desired icon size. ++ * @flags: not defined to do anything yet. ++ * @data: data passed to the function, set when the #WnckLoadSurfaceFunction has ++ * been set for the #WnckTasklist. ++ * ++ * Specifies the type of function passed to wnck_tasklist_set_icon_loader(). ++ * ++ * Returns: it should return a cairo_surface_t of @icon_name ++ * at size @size, or %NULL if no icon for @icon_name at size @size could be ++ * loaded. ++ * ++ */ ++typedef cairo_surface_t* (*WnckLoadSurfaceFunction) (const char *icon_name, ++ int size, ++ unsigned int flags, ++ void *data); ++ ++void wnck_tasklist_set_surface_loader (WnckTasklist *tasklist, ++ WnckLoadSurfaceFunction load_surface_func, ++ void *data, ++ GDestroyNotify free_data_func); ++ + G_END_DECLS + + #endif /* WNCK_TASKLIST_H */ +-- +2.37.2 + diff --git a/SPECS/libwnck3.spec b/SPECS/libwnck3.spec new file mode 100644 index 0000000..ab269df --- /dev/null +++ b/SPECS/libwnck3.spec @@ -0,0 +1,279 @@ +%global source_name libwnck + +Summary: Window Navigator Construction Kit +Name: libwnck3 +Version: 43.0 +Release: 9%{?dist} +URL: http://download.gnome.org/sources/%{source_name}/ +Source0: http://download.gnome.org/sources/%{source_name}/40/%{source_name}-%{version}.tar.xz +License: LGPL-2.0-or-later + +# https://gitlab.gnome.org/GNOME/libwnck/-/merge_requests/10 +Patch2: libwnck_0001-Expose-window-scaling-factor_43.patch +Patch3: libwnck_0002-icons-Use-cairo-surfaces-to-render-icons_43.patch +Patch4: libwnck_0003-xutils-Change-icons-to-being-cairo-surfaces_43.patch +Patch5: libwnck_0004-icons-Mark-GdkPixbuf-icons-as-deprecated_43.patch +Patch6: libwnck_0005-tasklist-Add-surface-loader-function_43.patch +# fix https://gitlab.gnome.org/GNOME/libwnck/-/issues/154#note_1562760 +# https://gitlab.gnome.org/GNOME/libwnck/-/commit/07694559cc0c65ce1cca9ac33b165cef84c34d5e +Patch7: libwnck_0001-Revert-xutils-Get-the-correct-PID-for-clients-inside.patch +# https://bugs.launchpad.net/ubuntu/+source/libwnck3/+bug/1990263 +# https://gitlab.gnome.org/GNOME/libwnck/-/merge_requests/46 +Patch8: libwnck3_handle_avoid_segfault_in_invalidate_icons.patch + +BuildRequires: gcc +BuildRequires: meson +BuildRequires: gettext +BuildRequires: glib2-devel +BuildRequires: gobject-introspection-devel +BuildRequires: gtk3-devel +BuildRequires: gtk-doc +BuildRequires: libXres-devel +BuildRequires: pango-devel +BuildRequires: startup-notification-devel + +Requires: startup-notification + +%description +libwnck (pronounced "libwink") is used to implement pagers, tasklists, +and other such things. It allows applications to monitor information +about open windows, workspaces, their names/icons, and so forth. + +%package devel +Summary: Libraries and headers for libwnck +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The %{name}-devel package contains libraries and header files for +developing applications that use %{name}. + + +%prep +%autosetup -n %{source_name}-%{version} -p1 + + +%build +%meson -Dgtk_doc=true +%meson_build + + +%install +%meson_install + +%find_lang %{source_name}-3.0 --with-gnome --all-name + + +%ldconfig_scriptlets + + +%files -f %{source_name}-3.0.lang +%license COPYING +%doc AUTHORS README NEWS +%{_libdir}/%{source_name}-3.so.0* +%{_bindir}/wnck-urgency-monitor +%{_libdir}/girepository-1.0/Wnck-3.0.typelib + +%files devel +%{_bindir}/wnckprop +%{_libdir}/%{source_name}-3.so +%{_libdir}/pkgconfig/* +%{_includedir}/%{source_name}-3.0/ +%{_datadir}/gir-1.0/Wnck-3.0.gir +%doc %{_datadir}/gtk-doc + + +%changelog +* Tue Nov 26 2024 MSVSphere Packaging Team - 43.0-9 +- Rebuilt for MSVSphere 10 + +* Mon Jun 24 2024 Troy Dawson - 43.0-9 +- Bump release for June 2024 mass rebuild + +* Thu Jan 25 2024 Fedora Release Engineering - 43.0-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Sun Jan 21 2024 Fedora Release Engineering - 43.0-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Tue Nov 21 2023 Wolfgang Ulbrich - 43.0-6 +- fix rhbz (#2242944) +- disable Revert-pager-do-not-change-workspace-size-from-size patch + +* Thu Jul 20 2023 Fedora Release Engineering - 43.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Thu Jan 19 2023 Fedora Release Engineering - 43.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Fri Oct 07 2022 Wolfgang Ulbrich - 43.0-3 +- fix https://bugs.launchpad.net/ubuntu/+source/libwnck3/+bug/1990263 + +* Thu Sep 29 2022 Wolfgang Ulbrich - 43.0-2 +- fix https://gitlab.gnome.org/GNOME/libwnck/-/issues/154 + +* Mon Sep 19 2022 Wolfgang Ulbrich - 43.0-1 +- update to 43.0 + +* Thu Jul 21 2022 Fedora Release Engineering - 40.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Sat Feb 19 2022 Wolfgang Ulbrich - 40.1-1 +- update to 40.1 + +* Thu Jan 20 2022 Fedora Release Engineering - 40.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Sun Dec 12 2021 Wolfgang Ulbrich - 40.0-4 +- use https://gitlab.gnome.org/GNOME/libwnck/-/commit/bd8ab37 +- Scale tasklist icons + +* Thu Jul 22 2021 Fedora Release Engineering - 40.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Fri Jun 11 2021 Wolfgang Ulbrich - 40.0-2 +- revert https://gitlab.gnome.org/GNOME/libwnck/-/commit/3456b74 +- fixes rhbz #1971048 +- and https://github.com/mate-desktop/mate-panel/issues/1230 + +* Wed May 26 2021 Kalev Lember - 40.0-1 +- Update to 40.0 +- Tighten soname globs + +* Tue Jan 26 2021 Fedora Release Engineering - 3.36.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Tue Jul 28 2020 Fedora Release Engineering - 3.36.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Sat Mar 28 2020 Wolfgang Ulbrich - 3.36.0-1 +- update to 3.36.0 + +* Wed Jan 29 2020 Fedora Release Engineering - 3.32.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Jul 25 2019 Fedora Release Engineering - 3.32.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Wed May 01 2019 Phil Wyett - 3.32.0-1 +- Update to 3.32.0 + +* Fri Feb 01 2019 Kalev Lember - 3.31.4-1 +- Update to 3.31.4 +- Switch to the meson build system + +* Fri Feb 01 2019 Fedora Release Engineering - 3.24.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Fri Jul 13 2018 Fedora Release Engineering - 3.24.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Wed Feb 07 2018 Fedora Release Engineering - 3.24.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Mon Jul 31 2017 Kalev Lember - 3.24.1-1 +- Update to 3.24.1 + +* Wed Jul 26 2017 Fedora Release Engineering - 3.24.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Sat Jul 22 2017 Wolfgang Ulbrich - 3.24.0-2 +- fix locale dir +- https://git.gnome.org/browse/libwnck/commit/?id=4feb967 + +* Sun Jul 02 2017 Wolfgang Ulbrich - 3.24.0-1 +- Update to 3.24.0 +- modernize spec file + +* Fri Feb 10 2017 Fedora Release Engineering - 3.20.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Wed Jun 29 2016 Wolfgang Ulbrich - 3.20.1-1 +- Update to 3.20.1 + +* Wed Jun 22 2016 Richard Hughes - 3.20.0-1 +- Update to 3.20.0 + +* Tue Feb 16 2016 Richard Hughes - 3.14.1-1 +- Update to 3.14.1 + +* Thu Feb 04 2016 Fedora Release Engineering - 3.14.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Wed Jun 17 2015 Fedora Release Engineering - 3.14.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Tue Nov 25 2014 Kalev Lember - 3.14.0-1 +- Update to 3.14.0 + +* Wed Sep 03 2014 Kalev Lember - 3.4.9-1 +- Update to 3.4.9 +- Tighten -devel subpackage deps + +* Sun Aug 17 2014 Fedora Release Engineering - 3.4.7-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Tue Jul 22 2014 Kalev Lember - 3.4.7-3 +- Rebuilt for gobject-introspection 1.41.4 + +* Sat Jun 07 2014 Fedora Release Engineering - 3.4.7-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Thu Aug 22 2013 Kalev Lember - 3.4.7-1 +- Update to 3.4.7 + +* Sat Aug 03 2013 Fedora Release Engineering - 3.4.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Tue Feb 19 2013 Richard Hughes - 3.4.5-1 +- Update to 3.4.5 + +* Thu Feb 14 2013 Fedora Release Engineering - 3.4.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Mon Nov 12 2012 Kalev Lember - 3.4.4-1 +- Update to 3.4.4 + +* Sat Sep 22 2012 Kalev Lember - 3.4.3-1 +- Update to 3.4.3 + +* Fri Jul 27 2012 Fedora Release Engineering - 3.4.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Fri May 18 2012 Richard Hughes - 3.4.2-1 +- Update to 3.4.2 + +* Tue Mar 27 2012 Kalev Lember - 3.4.0-1 +- Update to 3.4.0 + +* Tue Feb 7 2012 Matthias Clasen - 3.3.5-1 +- Update to 3.3.5 + +* Fri Jan 13 2012 Fedora Release Engineering - 3.2.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Oct 26 2011 Fedora Release Engineering - 3.2.1-2 +- Rebuilt for glibc bug#747377 + +* Mon Oct 17 2011 Matthias Clasen - 3.2.1-1 +- Update to 3.2.1 + +* Tue Sep 27 2011 Ray - 3.2.0-1 +- Update to 3.2.0 + +* Mon Sep 19 2011 Matthias Clasen 3.1.92-1 +- Update to 3.1.92 + +* Wed Aug 31 2011 Matthias Clasen 3.1.90-1 +- Update to 3.1.90 + +* Wed Jul 6 2011 Matthias Clasen 3.0.2-1 +- Update to 3.0.2 + +* Thu Feb 10 2011 Matthias Clasen 2.91.6-3 +- Rebuild against newer gtk3 + +* Tue Feb 08 2011 Fedora Release Engineering - 2.91.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Feb 02 2011 Ray Strode 2.91.6-1 +- Initial import.