From 4c8fcd6a6f2adf9686296f8447895c0e2910075c Mon Sep 17 00:00:00 2001
From: Szunti <Szunti@users.noreply.github.com>
Date: Wed, 17 Oct 2018 21:53:49 +0200
Subject: [PATCH] Add gdk_x11_display_get_parent_relative_pattern().

Fixes #1280, tray icons not drawing background. This is a magic pattern only
usable for gdk_window_set_background_pattern() that sets the underlying
X window's background to ParentRelative.
---
 docs/reference/gdk/gdk3-sections.txt |  1 +
 gdk/gdkwindow.c                      | 11 +++++------
 gdk/x11/gdkmain-x11.c                | 22 ++++++++++++++++++++++
 gdk/x11/gdkwindow-x11.c              | 25 +++++++++++++++++++++++++
 gdk/x11/gdkx11utils.h                |  3 +++
 gtk/deprecated/gtktrayicon-x11.c     |  3 ++-
 6 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt
index 344f257028..7b5649c7bd 100644
--- a/docs/reference/gdk/gdk3-sections.txt
+++ b/docs/reference/gdk/gdk3-sections.txt
@@ -1124,6 +1124,7 @@ gdk_x11_get_default_screen
 gdk_x11_get_default_xdisplay
 gdk_x11_grab_server
 gdk_x11_ungrab_server
+gdk_x11_get_parent_relative_pattern
 gdk_x11_cursor_get_xcursor
 gdk_x11_cursor_get_xdisplay
 gdk_x11_keymap_get_group_for_state
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 6b231f067e..9a0e98217d 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -6442,8 +6442,9 @@ G_GNUC_END_IGNORE_DEPRECATIONS
  *
  * Sets the background of @window.
  *
- * A background of %NULL means that the window will inherit its
- * background from its parent window.
+ * A background of %NULL means that the window won't have any background. On the
+ * X11 backend it's also possible to inherit the background from the parent
+ * window using gdk_x11_get_parent_relative_pattern().
  *
  * The windowing system will normally fill a window with its background
  * when the window is obscured then exposed.
@@ -6478,12 +6479,10 @@ gdk_window_set_background_pattern (GdkWindow       *window,
  * gdk_window_get_background_pattern:
  * @window: a window
  *
- * Gets the pattern used to clear the background on @window. If @window
- * does not have its own background and reuses the parent's, %NULL is
- * returned and you’ll have to query it yourself.
+ * Gets the pattern used to clear the background on @window.
  *
  * Returns: (nullable) (transfer none): The pattern to use for the
- * background or %NULL to use the parent’s background.
+ * background or %NULL if there is no background.
  *
  * Since: 2.22
  *
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
index 74c3849258..64c7cb4302 100644
--- a/gdk/x11/gdkmain-x11.c
+++ b/gdk/x11/gdkmain-x11.c
@@ -465,3 +465,25 @@ gdk_x11_get_default_xdisplay (void)
 {
   return GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 }
+
+/**
+ * gdk_x11_get_parent_relative_pattern:
+ *
+ * Used with gdk_window_set_background_pattern() to inherit background from
+ * parent window. Useful for imitating transparency when compositing is not
+ * available. Otherwise behaves like a transparent pattern.
+ *
+ * Since: 3.24.2
+ *
+ * Deprecated: 3.24: Don't use this function
+ **/
+cairo_pattern_t *
+gdk_x11_get_parent_relative_pattern (void)
+{
+  static cairo_pattern_t *parent_relative_pattern = NULL;
+
+  if (G_UNLIKELY (parent_relative_pattern == NULL))
+    parent_relative_pattern = cairo_pattern_create_rgba (0.0, 0.0, 0.0, 0.0);
+
+  return parent_relative_pattern;
+}
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 7865fa9384..f1f2081b6b 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -2996,6 +2996,31 @@ gdk_window_x11_set_background (GdkWindow      *window,
       return;
     }
 
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  if (pattern == gdk_x11_get_parent_relative_pattern ())
+G_GNUC_END_IGNORE_DEPRECATIONS
+    {
+      GdkWindow *parent;
+
+      /* X throws BadMatch if the parent has a different depth when
+       * using ParentRelative */
+      parent = gdk_window_get_parent (window);
+      if (parent == NULL || window->depth == parent->depth)
+        {
+          XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
+                                      GDK_WINDOW_XID (window), ParentRelative);
+          return;
+        }
+      else
+        {
+          g_warning ("Can't set ParentRelative background for window %#lx, depth of parent doesn't match",
+                     GDK_WINDOW_XID (window));
+          XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
+                                      GDK_WINDOW_XID (window), None);
+          return;
+        }
+    }
+
   switch (cairo_pattern_get_type (pattern))
     {
     case CAIRO_PATTERN_TYPE_SOLID:
diff --git a/gdk/x11/gdkx11utils.h b/gdk/x11/gdkx11utils.h
index 0fa34bcf6c..7b41e210c1 100644
--- a/gdk/x11/gdkx11utils.h
+++ b/gdk/x11/gdkx11utils.h
@@ -72,6 +72,9 @@ void          gdk_x11_grab_server    (void);
 GDK_AVAILABLE_IN_ALL
 void          gdk_x11_ungrab_server  (void);
 
+GDK_DEPRECATED_IN_3_22
+cairo_pattern_t *gdk_x11_get_parent_relative_pattern (void);
+
 G_END_DECLS
 
 #endif /* __GDK_X11_UTILS_H__ */
diff --git a/gtk/deprecated/gtktrayicon-x11.c b/gtk/deprecated/gtktrayicon-x11.c
index c0ad19259b..6cc5e21bba 100644
--- a/gtk/deprecated/gtktrayicon-x11.c
+++ b/gtk/deprecated/gtktrayicon-x11.c
@@ -966,7 +966,8 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
   else
     {
       /* Set a parent-relative background pixmap */
-      gdk_window_set_background_pattern (window, NULL);
+      cairo_pattern_t *parent_relative = gdk_x11_get_parent_relative_pattern ();
+      gdk_window_set_background_pattern (window, parent_relative);
     }
 G_GNUC_END_IGNORE_DEPRECATIONS
 
-- 
2.20.1

