[gtk/tooltip-redo: 2/2] tooltips: Stop using GTK_WINDOW_POPUP



commit 459c0008c8203178fd41a6044cec870019ebff86
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Dec 28 21:04:19 2019 -0500

    tooltips: Stop using GTK_WINDOW_POPUP
    
    Make GtkTooltipWindow a GtkNative implementation,
    instead of using a GTK_WINDOW_POPUP window.

 gtk/gtktooltip.c              |  82 +++-----
 gtk/gtktooltipwindow.c        | 430 +++++++++++++++++++++++++++++++++++++++++-
 gtk/gtktooltipwindowprivate.h |   9 +
 gtk/ui/gtktooltipwindow.ui    |   7 +-
 4 files changed, 462 insertions(+), 66 deletions(-)
---
diff --git a/gtk/gtktooltip.c b/gtk/gtktooltip.c
index 9b1ef188c3..8bb73fe3f5 100644
--- a/gtk/gtktooltip.c
+++ b/gtk/gtktooltip.c
@@ -95,8 +95,6 @@ struct _GtkTooltip
 
   GtkWidget *window;
 
-  GtkWindow *current_window;
-
   GtkWidget *tooltip_widget;
 
   GdkSurface *last_surface;
@@ -116,7 +114,7 @@ struct _GtkTooltipClass
   GObjectClass parent_class;
 };
 
-#define GTK_TOOLTIP_VISIBLE(tooltip) ((tooltip)->current_window && gtk_widget_get_visible 
(GTK_WIDGET((tooltip)->current_window)))
+#define GTK_TOOLTIP_VISIBLE(tooltip) ((tooltip)->window && gtk_widget_get_visible 
(GTK_WIDGET((tooltip)->window)))
 
 static void       gtk_tooltip_dispose              (GObject         *object);
 
@@ -134,16 +132,7 @@ static void       gtk_tooltip_handle_event_internal (GdkEventType   event_type,
                                                      gdouble       dx,
                                                      gdouble       dy);
 
-static inline GQuark tooltip_quark (void)
-{
-  static GQuark quark;
-
-  if G_UNLIKELY (quark == 0)
-    quark = g_quark_from_static_string ("gdk-display-current-tooltip");
-  return quark;
-}
-
-#define quark_current_tooltip tooltip_quark()
+static GQuark quark_current_tooltip;
 
 G_DEFINE_TYPE (GtkTooltip, gtk_tooltip, G_TYPE_OBJECT);
 
@@ -152,6 +141,8 @@ gtk_tooltip_class_init (GtkTooltipClass *klass)
 {
   GObjectClass *object_class;
 
+  quark_current_tooltip = g_quark_from_static_string ("gdk-display-current-tooltip");
+
   object_class = G_OBJECT_CLASS (klass);
 
   object_class->dispose = gtk_tooltip_dispose;
@@ -165,8 +156,6 @@ gtk_tooltip_init (GtkTooltip *tooltip)
 
   tooltip->browse_mode_enabled = FALSE;
 
-  tooltip->current_window = NULL;
-
   tooltip->tooltip_widget = NULL;
 
   tooltip->last_surface = NULL;
@@ -205,7 +194,7 @@ gtk_tooltip_dispose (GObject *object)
       g_signal_handlers_disconnect_by_func (display,
                                            gtk_tooltip_display_closed,
                                            tooltip);
-      gtk_widget_destroy (tooltip->window);
+      gtk_tooltip_window_set_relative_to (GTK_TOOLTIP_WINDOW (tooltip->window), NULL);
       tooltip->window = NULL;
     }
 
@@ -479,34 +468,27 @@ static void
 gtk_tooltip_set_last_surface (GtkTooltip *tooltip,
                               GdkSurface  *surface)
 {
-  GtkWidget *window_widget = NULL;
-
   if (tooltip->last_surface == surface)
     return;
 
   if (tooltip->last_surface)
     g_object_remove_weak_pointer (G_OBJECT (tooltip->last_surface),
-                                 (gpointer *) &tooltip->last_surface);
+                                  (gpointer *) &tooltip->last_surface);
 
   tooltip->last_surface = surface;
 
   if (tooltip->last_surface)
     g_object_add_weak_pointer (G_OBJECT (tooltip->last_surface),
-                              (gpointer *) &tooltip->last_surface);
+                               (gpointer *) &tooltip->last_surface);
 
   if (surface)
-    window_widget = gtk_native_get_for_surface (surface);
-
-  if (window_widget)
-    window_widget = GTK_WIDGET (gtk_widget_get_root (window_widget));
-
-  if (window_widget &&
-      window_widget != tooltip->window &&
-      GTK_IS_WINDOW (window_widget))
-    gtk_window_set_transient_for (GTK_WINDOW (tooltip->window),
-                                  GTK_WINDOW (window_widget));
+    gtk_tooltip_window_set_relative_to (GTK_TOOLTIP_WINDOW (tooltip->window),
+                                        gtk_native_get_for_surface (surface));
   else
-    gtk_window_set_transient_for (GTK_WINDOW (tooltip->window), NULL);
+    {
+      gtk_tooltip_window_set_relative_to (GTK_TOOLTIP_WINDOW (tooltip->window), NULL);
+      tooltip->window = NULL;
+    }
 }
 
 static gboolean
@@ -567,19 +549,17 @@ gtk_tooltip_position (GtkTooltip *tooltip,
   GtkSettings *settings;
   graphene_rect_t anchor_bounds;
   GdkRectangle anchor_rect;
-  GdkSurface *surface;
   GdkSurface *effective_toplevel;
   GtkWidget *toplevel;
   int rect_anchor_dx = 0;
   int cursor_size;
   int anchor_rect_padding;
 
-  gtk_widget_realize (GTK_WIDGET (tooltip->current_window));
-  surface = gtk_native_get_surface (GTK_NATIVE (tooltip->current_window));
+  gtk_widget_realize (GTK_WIDGET (tooltip->window));
 
   tooltip->tooltip_widget = new_tooltip_widget;
 
-  toplevel = GTK_WIDGET (gtk_widget_get_root (new_tooltip_widget));
+  toplevel = GTK_WIDGET (gtk_widget_get_native (new_tooltip_widget));
   if (gtk_widget_compute_bounds (new_tooltip_widget, toplevel, &anchor_bounds))
     {
       anchor_rect = (GdkRectangle) {
@@ -657,16 +637,12 @@ gtk_tooltip_position (GtkTooltip *tooltip,
         }
     }
 
-  gtk_window_set_transient_for (GTK_WINDOW (tooltip->current_window),
-                                GTK_WINDOW (toplevel));
-
-  gdk_surface_move_to_rect (surface,
-                            &anchor_rect,
-                            GDK_GRAVITY_SOUTH,
-                            GDK_GRAVITY_NORTH,
-                            GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_SLIDE_X,
-                            rect_anchor_dx, 0);
-  gtk_widget_show (GTK_WIDGET (tooltip->current_window));
+  gtk_tooltip_window_position (GTK_TOOLTIP_WINDOW (tooltip->window),
+                               &anchor_rect,
+                               GDK_GRAVITY_SOUTH,
+                               GDK_GRAVITY_NORTH,
+                               GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_SLIDE_X,
+                               rect_anchor_dx, 0);
 }
 
 static void
@@ -704,10 +680,7 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
   if (!return_value)
     return;
 
-  if (!tooltip->current_window)
-    tooltip->current_window = GTK_WINDOW (GTK_TOOLTIP (tooltip)->window);
-
-  /* FIXME: should use tooltip->current_window iso tooltip->window */
+  /* FIXME: should use tooltip->window iso tooltip->window */
   if (display != gtk_widget_get_display (tooltip->window))
     {
       g_signal_handlers_disconnect_by_func (display,
@@ -722,6 +695,8 @@ gtk_tooltip_show_tooltip (GdkDisplay *display)
 
   gtk_tooltip_position (tooltip, display, tooltip_widget, device);
 
+  gtk_widget_show (GTK_WIDGET (tooltip->window));
+
   /* Now a tooltip is visible again on the display, make sure browse
    * mode is enabled.
    */
@@ -765,11 +740,8 @@ gtk_tooltip_hide_tooltip (GtkTooltip *tooltip)
       g_source_set_name_by_id (tooltip->browse_mode_timeout_id, "[gtk] tooltip_browse_mode_expired");
     }
 
-  if (tooltip->current_window)
-    {
-      gtk_widget_hide (GTK_WIDGET (tooltip->current_window));
-      tooltip->current_window = NULL;
-    }
+  if (tooltip->window)
+    gtk_widget_hide (tooltip->window);
 }
 
 static gint
@@ -829,7 +801,7 @@ _gtk_tooltip_hide (GtkWidget *widget)
   display = gtk_widget_get_display (widget);
   tooltip = g_object_get_qdata (G_OBJECT (display), quark_current_tooltip);
 
-  if (!tooltip || !GTK_TOOLTIP_VISIBLE (tooltip) || !tooltip->tooltip_widget)
+  if (!tooltip || !tooltip->window || !tooltip->tooltip_widget)
     return;
 
   if (widget == tooltip->tooltip_widget)
diff --git a/gtk/gtktooltipwindow.c b/gtk/gtktooltipwindow.c
index f614acb60e..75fdfca835 100644
--- a/gtk/gtktooltipwindow.c
+++ b/gtk/gtktooltipwindow.c
@@ -38,11 +38,27 @@
 #include "gtksizerequest.h"
 #include "gtkwindowprivate.h"
 #include "gtkwidgetprivate.h"
+#include "gtknative.h"
+#include "gtkstylecontext.h"
+#include "gtkcssnodeprivate.h"
 
 struct _GtkTooltipWindow
 {
   GtkWindow parent_type;
 
+  GdkSurface *surface;
+  GskRenderer *renderer;
+
+  GdkSurfaceState state;
+  GtkWidget *relative_to;
+  GdkRectangle rect;
+  GdkGravity rect_anchor;
+  GdkGravity surface_anchor;
+  GdkAnchorHints anchor_hints;
+  int dx;
+  int dy;
+  guint surface_transform_changed_cb;
+
   GtkWidget *box;
   GtkWidget *image;
   GtkWidget *label;
@@ -54,13 +70,349 @@ struct _GtkTooltipWindowClass
   GtkWindowClass parent_class;
 };
 
-G_DEFINE_TYPE (GtkTooltipWindow, gtk_tooltip_window, GTK_TYPE_WINDOW)
+static void gtk_tooltip_window_native_init (GtkNativeInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkTooltipWindow, gtk_tooltip_window, GTK_TYPE_BIN,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
+                                                gtk_tooltip_window_native_init))
+
+
+static GdkSurface *
+gtk_tooltip_window_native_get_surface (GtkNative *native)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (native);
+
+  return window->surface;
+}
+
+static GskRenderer *
+gtk_tooltip_window_native_get_renderer (GtkNative *native)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (native);
+
+  return window->renderer;
+}
+
+static void
+gtk_tooltip_window_native_get_surface_transform (GtkNative *native,
+                                                 int       *x,
+                                                 int       *y)
+{
+  GtkStyleContext *context;
+  GtkBorder margin, border, padding;
+
+  context = gtk_widget_get_style_context (GTK_WIDGET (native));
+  gtk_style_context_get_margin (context, &margin);
+  gtk_style_context_get_border (context, &border);
+  gtk_style_context_get_padding (context, &padding);
+
+  *x = margin.left + border.left + padding.left;
+  *y = margin.top + border.top + padding.top;
+}
+
+static void
+move_to_rect (GtkTooltipWindow *window)
+{
+  gdk_surface_move_to_rect (window->surface,
+                            &window->rect,
+                            window->rect_anchor,
+                            window->surface_anchor,
+                            window->anchor_hints,
+                            window->dx,
+                            window->dy);
+}
+
+static void
+gtk_tooltip_window_move_resize (GtkTooltipWindow *window)
+{
+  GtkRequisition req;
+
+  if (window->surface)
+    {
+      gtk_widget_get_preferred_size (GTK_WIDGET (window), NULL, &req);
+      gdk_surface_resize (window->surface, req.width, req.height);
+      move_to_rect (window);
+    }
+}
+
+static void
+gtk_tooltip_window_native_check_resize (GtkNative *native)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (native);
+  GtkWidget *widget = GTK_WIDGET (native);
+
+  if (!_gtk_widget_get_alloc_needed (widget))
+    gtk_widget_ensure_allocate (widget);
+  else if (gtk_widget_get_visible (widget))
+    {
+      gtk_tooltip_window_move_resize (window);
+      if (window->surface)
+        gtk_widget_allocate (GTK_WIDGET (window),
+                             gdk_surface_get_width (window->surface),
+                             gdk_surface_get_height (window->surface),
+                             -1, NULL);
+    }
+}
+
+static void
+gtk_tooltip_window_native_init (GtkNativeInterface *iface)
+{
+  iface->get_surface = gtk_tooltip_window_native_get_surface;
+  iface->get_renderer = gtk_tooltip_window_native_get_renderer;
+  iface->get_surface_transform = gtk_tooltip_window_native_get_surface_transform;
+  iface->check_resize = gtk_tooltip_window_native_check_resize;
+}
+
+static void
+surface_state_changed (GtkWidget *widget)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
+  GdkSurfaceState new_surface_state;
+  GdkSurfaceState changed_mask;
+
+  new_surface_state = gdk_surface_get_state (window->surface);
+  changed_mask = new_surface_state ^ window->state;
+  window->state = new_surface_state;
+
+  if (changed_mask & GDK_SURFACE_STATE_WITHDRAWN)
+    {
+      if (window->state & GDK_SURFACE_STATE_WITHDRAWN)
+        gtk_widget_hide (widget);
+    }
+}
+
+static void
+surface_size_changed (GtkWidget *widget,
+                      guint      width,
+                      guint      height)
+{
+}
+
+static gboolean
+surface_render (GdkSurface     *surface,
+                cairo_region_t *region,
+                GtkWidget      *widget)
+{
+  gtk_widget_render (widget, surface, region);
+  return TRUE;
+}
+
+static gboolean
+surface_event (GdkSurface *surface,
+               GdkEvent   *event,
+               GtkWidget  *widget)
+{
+  gtk_main_do_event (event);
+  return TRUE;
+}
+
+static void
+surface_moved_to_rect (GdkSurface   *surface,
+                       GdkRectangle *flipped_rect,
+                       GdkRectangle *final_rect,
+                       gboolean      flipped_x,
+                       gboolean      flipped_y,
+                       GtkWidget    *widget)
+{
+}
+
+static void
+gtk_tooltip_window_realize (GtkWidget *widget)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
+  GdkDisplay *display;
+  GdkSurface *parent;
+
+  display = gtk_widget_get_display (window->relative_to);
+
+  parent = gtk_native_get_surface (gtk_widget_get_native (window->relative_to));
+  window->surface = gdk_surface_new_popup (display, parent, FALSE);
+
+  gdk_surface_set_widget (window->surface, widget);
+
+  g_signal_connect_swapped (window->surface, "notify::state", G_CALLBACK (surface_state_changed), widget);
+  g_signal_connect_swapped (window->surface, "size-changed", G_CALLBACK (surface_size_changed), widget);
+  g_signal_connect (window->surface, "render", G_CALLBACK (surface_render), widget);
+  g_signal_connect (window->surface, "event", G_CALLBACK (surface_event), widget);
+  g_signal_connect (window->surface, "moved-to-rect", G_CALLBACK (surface_moved_to_rect), widget);
+
+  GTK_WIDGET_CLASS (gtk_tooltip_window_parent_class)->realize (widget);
+
+  window->renderer = gsk_renderer_new_for_surface (window->surface);
+}
+
+static void
+gtk_tooltip_window_unrealize (GtkWidget *widget)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
+
+  GTK_WIDGET_CLASS (gtk_tooltip_window_parent_class)->unrealize (widget);
+
+  gsk_renderer_unrealize (window->renderer);
+  g_clear_object (&window->renderer);
+
+  g_signal_handlers_disconnect_by_func (window->surface, surface_state_changed, widget);
+  g_signal_handlers_disconnect_by_func (window->surface, surface_size_changed, widget);
+  g_signal_handlers_disconnect_by_func (window->surface, surface_render, widget);
+  g_signal_handlers_disconnect_by_func (window->surface, surface_event, widget);
+  g_signal_handlers_disconnect_by_func (window->surface, surface_moved_to_rect, widget);
+  gdk_surface_set_widget (window->surface, NULL);
+  gdk_surface_destroy (window->surface);
+  g_clear_object (&window->surface);
+}
+
+
+static void
+unset_surface_transform_changed_cb (gpointer data)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (data);
+
+  window->surface_transform_changed_cb = 0;
+}
+
+static gboolean
+surface_transform_changed_cb (GtkWidget               *widget,
+                              const graphene_matrix_t *transform,
+                              gpointer                 user_data)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
+
+  move_to_rect (window);
+
+  return G_SOURCE_CONTINUE;
+}
+
+
+static void
+gtk_tooltip_window_map (GtkWidget *widget)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
+  GtkWidget *child;
+
+  gdk_surface_show (window->surface);
+  move_to_rect (window);
+
+  window->surface_transform_changed_cb =
+    gtk_widget_add_surface_transform_changed_callback (window->relative_to,
+                                                       surface_transform_changed_cb,
+                                                       window,
+                                                       unset_surface_transform_changed_cb);
+
+  GTK_WIDGET_CLASS (gtk_tooltip_window_parent_class)->map (widget);
+
+  child = gtk_bin_get_child (GTK_BIN (widget));
+  if (child != NULL && gtk_widget_get_visible (child))
+    gtk_widget_map (child);
+}
+
+static void
+gtk_tooltip_window_unmap (GtkWidget *widget)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
+  GtkWidget *child;
+
+  gtk_widget_remove_surface_transform_changed_callback (window->relative_to,
+                                                        window->surface_transform_changed_cb);
+  window->surface_transform_changed_cb = 0;
+
+  GTK_WIDGET_CLASS (gtk_tooltip_window_parent_class)->unmap (widget);
+  gdk_surface_hide (window->surface);
+
+  child = gtk_bin_get_child (GTK_BIN (widget));
+  if (child != NULL)
+    gtk_widget_unmap (child);
+}
+
+static void
+gtk_tooltip_window_measure (GtkWidget      *widget,
+                            GtkOrientation  orientation,
+                            int             for_size,
+                            int            *minimum,
+                            int            *natural,
+                            int            *minimum_baseline,
+                            int            *natural_baseline)
+{
+  GtkWidget *child;
+
+  child = gtk_bin_get_child (GTK_BIN (widget));
+
+  if (child)
+    gtk_widget_measure (child,
+                        orientation, for_size,
+                        minimum, natural,
+                        minimum_baseline, natural_baseline);
+}
+
+static void
+gtk_tooltip_window_size_allocate (GtkWidget *widget,
+                                  int        width,
+                                  int        height,
+                                  int        baseline)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
+  GtkWidget *child;
+
+  gtk_tooltip_window_move_resize (window);
+
+  child = gtk_bin_get_child (GTK_BIN (window));
+
+  if (child)
+    gtk_widget_allocate (child, width, height, baseline, NULL);
+}
+
+static void
+gtk_tooltip_window_show (GtkWidget *widget)
+{
+  _gtk_widget_set_visible_flag (widget, TRUE);
+  gtk_css_node_validate (gtk_widget_get_css_node (widget));
+  gtk_widget_realize (widget);
+  gtk_tooltip_window_native_check_resize (GTK_NATIVE (widget));
+  gtk_widget_map (widget);
+}
+
+static void
+gtk_tooltip_window_hide (GtkWidget *widget)
+{
+  _gtk_widget_set_visible_flag (widget, FALSE);
+  gtk_widget_unmap (widget);
+}
+
+static void size_changed (GtkWidget        *widget,
+                          int               width,
+                          int               height,
+                          int               baseline,
+                          GtkTooltipWindow *window);
+
+static void
+gtk_tooltip_window_dispose (GObject *object)
+{
+  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (object);
+  
+  if (window->relative_to)
+    {
+      g_signal_handlers_disconnect_by_func (window->relative_to, size_changed, window);
+      gtk_widget_unparent (GTK_WIDGET (window));
+    }
+
+  G_OBJECT_CLASS (gtk_tooltip_window_parent_class)->dispose (object);
+}
 
 static void
 gtk_tooltip_window_class_init (GtkTooltipWindowClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
+  object_class->dispose = gtk_tooltip_window_dispose;
+  widget_class->realize = gtk_tooltip_window_realize;
+  widget_class->unrealize = gtk_tooltip_window_unrealize;
+  widget_class->map = gtk_tooltip_window_map;
+  widget_class->unmap = gtk_tooltip_window_unmap;
+  widget_class->measure = gtk_tooltip_window_measure;
+  widget_class->size_allocate = gtk_tooltip_window_size_allocate;
+  widget_class->show = gtk_tooltip_window_show; 
+  widget_class->hide = gtk_tooltip_window_hide; 
+
   gtk_widget_class_set_css_name (widget_class, I_("tooltip"));
   gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_TOOL_TIP);
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/ui/gtktooltipwindow.ui");
@@ -68,24 +420,20 @@ gtk_tooltip_window_class_init (GtkTooltipWindowClass *klass)
   gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, box);
   gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, image);
   gtk_widget_class_bind_template_child (widget_class, GtkTooltipWindow, label);
+
+  gtk_widget_class_set_css_name (widget_class, "tooltip");
 }
 
 static void
 gtk_tooltip_window_init (GtkTooltipWindow *self)
 {
-  GtkWindow *window = GTK_WINDOW (self);
-
   gtk_widget_init_template (GTK_WIDGET (self));
-
-  _gtk_window_request_csd (window);
 }
 
 GtkWidget *
 gtk_tooltip_window_new (void)
 {
-  return g_object_new (GTK_TYPE_TOOLTIP_WINDOW,
-                       "type", GTK_WINDOW_POPUP,
-                       NULL);
+  return g_object_new (GTK_TYPE_TOOLTIP_WINDOW, NULL);
 }
 
 void
@@ -193,3 +541,69 @@ gtk_tooltip_window_set_custom_widget (GtkTooltipWindow *window,
       gtk_widget_show (custom_widget);
     }
 }
+
+static void
+size_changed (GtkWidget        *widget,
+              int               width,
+              int               height,
+              int               baseline,
+              GtkTooltipWindow *window)
+{
+  gtk_native_check_resize (GTK_NATIVE (window));
+}
+
+static void
+relative_to_weak_notify (gpointer data, GObject *former_object)
+{
+  gtk_widget_unparent (GTK_WIDGET (data));
+}
+
+void
+gtk_tooltip_window_set_relative_to (GtkTooltipWindow *window,
+                                    GtkWidget        *relative_to)
+{
+  if (window->relative_to == relative_to)
+    return;
+
+  g_object_ref (window);
+
+  if (window->relative_to)
+    {
+      g_object_weak_unref (G_OBJECT (window->relative_to), relative_to_weak_notify, window);
+      g_signal_handlers_disconnect_by_func (window->relative_to, size_changed, window);
+      gtk_widget_unparent (GTK_WIDGET (window));
+    }
+
+  window->relative_to = relative_to;
+
+  if (window->relative_to)
+    {
+      g_object_weak_ref (G_OBJECT (window->relative_to), relative_to_weak_notify, window);
+      g_signal_connect (window->relative_to, "size-allocate", G_CALLBACK (size_changed), window);
+      gtk_css_node_set_parent (gtk_widget_get_css_node (GTK_WIDGET (window)),
+                               gtk_widget_get_css_node (relative_to));
+      gtk_widget_set_parent (GTK_WIDGET (window), relative_to);
+    }
+
+  g_object_unref (window);
+}
+
+void
+gtk_tooltip_window_position (GtkTooltipWindow *window,
+                             GdkRectangle     *rect,
+                             GdkGravity        rect_anchor,
+                             GdkGravity        surface_anchor,
+                             GdkAnchorHints    anchor_hints,
+                             int               dx,
+                             int               dy)
+{
+  window->rect = *rect;
+  window->rect_anchor = rect_anchor;
+  window->surface_anchor = surface_anchor;
+  window->anchor_hints = anchor_hints;
+  window->dx = dx;
+  window->dy = dy;
+
+  move_to_rect (window);
+}
+
diff --git a/gtk/gtktooltipwindowprivate.h b/gtk/gtktooltipwindowprivate.h
index ad26f8dd92..13556d41e3 100644
--- a/gtk/gtktooltipwindowprivate.h
+++ b/gtk/gtktooltipwindowprivate.h
@@ -49,6 +49,15 @@ void            gtk_tooltip_window_set_image_icon_from_gicon    (GtkTooltipWindo
                                                                  GIcon            *gicon);
 void            gtk_tooltip_window_set_custom_widget            (GtkTooltipWindow *window,
                                                                  GtkWidget        *custom_widget);
+void            gtk_tooltip_window_set_relative_to              (GtkTooltipWindow *window,
+                                                                 GtkWidget        *relative_to);
+void            gtk_tooltip_window_position                     (GtkTooltipWindow *window,
+                                                                 GdkRectangle     *rect,
+                                                                 GdkGravity        rect_anchor,
+                                                                 GdkGravity        surface_anchor,
+                                                                 GdkAnchorHints    anchor_hints,
+                                                                 int               dx,
+                                                                 int               dy);
 
 G_END_DECLS
 
diff --git a/gtk/ui/gtktooltipwindow.ui b/gtk/ui/gtktooltipwindow.ui
index bb4329f18b..2dd5584646 100644
--- a/gtk/ui/gtktooltipwindow.ui
+++ b/gtk/ui/gtktooltipwindow.ui
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface domain="gtk40">
-  <template class="GtkTooltipWindow" parent="GtkWindow">
-    <property name="resizable">0</property>
-    <property name="type-hint">tooltip</property>
+  <template class="GtkTooltipWindow" parent="GtkBin">
+    <style>
+      <class name="background"/>
+    </style>
     <child>
       <object class="GtkBox" id="box">
         <property name="spacing">6</property>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]