[gnome-builder/wip/gtk4-port] libide/tree: use positioner API to present popovers



commit 6474e45c469fa4582d70dcef167c4e0f0dca25c4
Author: Christian Hergert <chergert redhat com>
Date:   Thu Apr 28 20:28:59 2022 -0700

    libide/tree: use positioner API to present popovers

 src/libide/tree/ide-tree-node.c    | 21 +++++----
 src/libide/tree/ide-tree-private.h |  3 ++
 src/libide/tree/ide-tree.c         | 94 +++++++++-----------------------------
 3 files changed, 37 insertions(+), 81 deletions(-)
---
diff --git a/src/libide/tree/ide-tree-node.c b/src/libide/tree/ide-tree-node.c
index 680f48a03..58c12182b 100644
--- a/src/libide/tree/ide-tree-node.c
+++ b/src/libide/tree/ide-tree-node.c
@@ -24,6 +24,7 @@
 
 #include <glib/gi18n.h>
 
+#include "ide-popover-positioner.h"
 #include "ide-tree-model.h"
 #include "ide-tree-node.h"
 #include "ide-tree-private.h"
@@ -1664,10 +1665,10 @@ ide_tree_node_get_path (IdeTreeNode *self)
   return NULL;
 }
 
-static void
-ide_tree_node_get_area (IdeTreeNode  *node,
-                        IdeTree      *tree,
-                        GdkRectangle *area)
+void
+_ide_tree_node_get_area (IdeTreeNode  *node,
+                         IdeTree      *tree,
+                         GdkRectangle *area)
 {
   GtkTreeViewColumn *column;
   g_autoptr(GtkTreePath) path = NULL;
@@ -1692,6 +1693,7 @@ static gboolean
 ide_tree_node_show_popover_timeout_cb (gpointer data)
 {
   PopupRequest *popreq = data;
+  GtkWidget *positioner;
   GdkRectangle rect;
   GtkAllocation alloc;
 
@@ -1699,7 +1701,7 @@ ide_tree_node_show_popover_timeout_cb (gpointer data)
   g_assert (IDE_IS_TREE_NODE (popreq->self));
   g_assert (GTK_IS_POPOVER (popreq->popover));
 
-  ide_tree_node_get_area (popreq->self, popreq->tree, &rect);
+  _ide_tree_node_get_area (popreq->self, popreq->tree, &rect);
   gtk_widget_get_allocation (GTK_WIDGET (popreq->tree), &alloc);
 
   if ((rect.x + rect.width) > (alloc.x + alloc.width))
@@ -1723,8 +1725,11 @@ ide_tree_node_show_popover_timeout_cb (gpointer data)
       break;
     }
 
-  gtk_popover_set_pointing_to (popreq->popover, &rect);
-  gtk_popover_popup (popreq->popover);
+  if ((positioner = gtk_widget_get_ancestor (GTK_WIDGET (popreq->tree), IDE_TYPE_POPOVER_POSITIONER)))
+    ide_popover_positioner_present (IDE_POPOVER_POSITIONER (positioner),
+                                    popreq->popover,
+                                    GTK_WIDGET (popreq->tree),
+                                    &rect);
 
   g_clear_object (&popreq->self);
   g_clear_object (&popreq->popover);
@@ -1747,7 +1752,7 @@ _ide_tree_node_show_popover (IdeTreeNode *self,
   g_return_if_fail (GTK_IS_POPOVER (popover));
 
   gtk_tree_view_get_visible_rect (GTK_TREE_VIEW (tree), &visible_rect);
-  ide_tree_node_get_area (self, tree, &cell_area);
+  _ide_tree_node_get_area (self, tree, &cell_area);
   gtk_tree_view_convert_bin_window_to_tree_coords (GTK_TREE_VIEW (tree),
                                                    cell_area.x,
                                                    cell_area.y,
diff --git a/src/libide/tree/ide-tree-private.h b/src/libide/tree/ide-tree-private.h
index 77968a522..5b60d0e63 100644
--- a/src/libide/tree/ide-tree-private.h
+++ b/src/libide/tree/ide-tree-private.h
@@ -66,5 +66,8 @@ GIcon        *_ide_tree_node_apply_emblems            (IdeTreeNode     *self,
                                                        GIcon           *base);
 void          _ide_tree_node_apply_colors             (IdeTreeNode     *self,
                                                        GtkCellRenderer *cell);
+void          _ide_tree_node_get_area                 (IdeTreeNode     *self,
+                                                       IdeTree         *tree,
+                                                       GdkRectangle    *area);
 
 G_END_DECLS
diff --git a/src/libide/tree/ide-tree.c b/src/libide/tree/ide-tree.c
index 118affc45..4a6790b77 100644
--- a/src/libide/tree/ide-tree.c
+++ b/src/libide/tree/ide-tree.c
@@ -27,6 +27,7 @@
 #include <libide-threading.h>
 
 #include "ide-cell-renderer-status.h"
+#include "ide-popover-positioner.h"
 #include "ide-tree.h"
 #include "ide-tree-model.h"
 #include "ide-tree-node.h"
@@ -60,9 +61,6 @@ typedef struct
   /* Our context menu popover */
   GtkPopover *popover;
 
-  /* Temporary for show_at_node API */
-  GtkPopover *show_at_node_popover;
-
   /* Stashed drop information to propagate on drop */
   GdkDragAction drop_action;
   GtkTreePath *drop_path;
@@ -406,17 +404,31 @@ ide_tree_popup (IdeTree        *self,
                 double          target_y)
 {
   IdeTreePrivate *priv = ide_tree_get_instance_private (self);
-  const GdkRectangle area = { target_x, target_y, 0, 0 };
+  GdkRectangle area;
+  GtkTextDirection dir;
+  GtkWidget *positioner;
 
   g_assert (IDE_IS_TREE (self));
   g_assert (IDE_IS_TREE_NODE (node));
 
-  if (priv->popover == NULL)
+  if (priv->context_menu == NULL)
+    return;
+
+  if (!(positioner = gtk_widget_get_ancestor (GTK_WIDGET (self), IDE_TYPE_POPOVER_POSITIONER)))
     return;
 
-  gtk_popover_set_pointing_to (priv->popover, &area);
+  priv->popover = GTK_POPOVER (gtk_popover_menu_new_from_model (G_MENU_MODEL (priv->context_menu)));
+  g_object_ref_sink (priv->popover);
+
+  dir = gtk_widget_get_direction (GTK_WIDGET (self));
+  gtk_popover_set_position (priv->popover, dir == GTK_TEXT_DIR_LTR ? GTK_POS_RIGHT : GTK_POS_LEFT);
+
+  _ide_tree_node_get_area (node, self, &area);
 
-  ide_tree_show_popover_at_node (self, node, priv->popover);
+  ide_popover_positioner_present (IDE_POPOVER_POSITIONER (positioner),
+                                  priv->popover,
+                                  GTK_WIDGET (self),
+                                  &area);
 }
 
 static void
@@ -508,26 +520,6 @@ ide_tree_query_tooltip (GtkWidget  *widget,
   return FALSE;
 }
 
-static void
-ide_tree_size_allocate (GtkWidget *widget,
-                        int        width,
-                        int        height,
-                        int        baseline)
-{
-  IdeTree *self = (IdeTree *)widget;
-  IdeTreePrivate *priv = ide_tree_get_instance_private (self);
-
-  g_assert (IDE_IS_TREE (self));
-
-  GTK_WIDGET_CLASS (ide_tree_parent_class)->size_allocate (widget, width, height, baseline);
-
-  if (priv->popover != NULL)
-    gtk_popover_present (priv->popover);
-
-  if (priv->show_at_node_popover != NULL)
-    gtk_popover_present (priv->show_at_node_popover);
-}
-
 static void
 ide_tree_dispose (GObject *object)
 {
@@ -540,8 +532,7 @@ ide_tree_dispose (GObject *object)
   if ((model = ide_tree_get_model (self)))
     _ide_tree_model_release_addins (model);
 
-  g_clear_pointer ((GtkWidget **)&priv->popover, gtk_widget_unparent);
-  g_clear_pointer ((GtkWidget **)&priv->show_at_node_popover, gtk_widget_unparent);
+  g_clear_object (&priv->popover);
 
   gtk_tree_view_set_model (GTK_TREE_VIEW (self), NULL);
 
@@ -567,7 +558,6 @@ ide_tree_class_init (IdeTreeClass *klass)
   object_class->dispose = ide_tree_dispose;
 
   widget_class->query_tooltip = ide_tree_query_tooltip;
-  widget_class->size_allocate = ide_tree_size_allocate;
 
   tree_view_class->row_activated = ide_tree_row_activated;
   tree_view_class->row_expanded = ide_tree_row_expanded;
@@ -641,27 +631,6 @@ ide_tree_new (void)
   return g_object_new (IDE_TYPE_TREE, NULL);
 }
 
-static void
-ide_tree_popover_closed_cb (IdeTree    *self,
-                            GtkPopover *popover)
-{
-  IdeTreePrivate *priv = ide_tree_get_instance_private (self);
-
-  g_assert (IDE_IS_TREE (self));
-  g_assert (GTK_IS_POPOVER (popover));
-
-  if (priv->popover == popover)
-    {
-      gtk_widget_unparent (GTK_WIDGET (popover));
-      priv->popover = NULL;
-    }
-  else if (priv->show_at_node_popover == popover)
-    {
-      gtk_widget_unparent (GTK_WIDGET (popover));
-      priv->show_at_node_popover = NULL;
-    }
-}
-
 void
 ide_tree_set_context_menu (IdeTree *self,
                            GMenu   *menu)
@@ -672,17 +641,7 @@ ide_tree_set_context_menu (IdeTree *self,
   g_return_if_fail (!menu || G_IS_MENU (menu));
 
   if (g_set_object (&priv->context_menu, menu))
-    {
-      GtkTextDirection dir;
-
-      if (priv->popover != NULL)
-        gtk_widget_unparent (GTK_WIDGET (priv->popover));
-
-      priv->popover = GTK_POPOVER (gtk_popover_menu_new_from_model (G_MENU_MODEL (priv->context_menu)));
-      dir = gtk_widget_get_direction (GTK_WIDGET (self));
-      gtk_popover_set_position (priv->popover, dir == GTK_TEXT_DIR_LTR ? GTK_POS_RIGHT : GTK_POS_LEFT);
-      gtk_widget_set_parent (GTK_WIDGET (priv->popover), GTK_WIDGET (self));
-    }
+    g_clear_object (&priv->popover);
 }
 
 void
@@ -690,22 +649,11 @@ ide_tree_show_popover_at_node (IdeTree     *self,
                                IdeTreeNode *node,
                                GtkPopover  *popover)
 {
-  IdeTreePrivate *priv = ide_tree_get_instance_private (self);
-
   g_return_if_fail (IDE_IS_TREE (self));
   g_return_if_fail (IDE_IS_TREE_NODE (node));
   g_return_if_fail (GTK_IS_POPOVER (popover));
   g_return_if_fail (gtk_widget_get_parent (GTK_WIDGET (popover)) == NULL);
 
-  g_clear_pointer ((GtkWidget **)&priv->show_at_node_popover, gtk_widget_unparent);
-  priv->show_at_node_popover = popover;
-  gtk_widget_set_parent (GTK_WIDGET (popover), GTK_WIDGET (self));
-  g_signal_connect_object (popover,
-                           "closed",
-                           G_CALLBACK (ide_tree_popover_closed_cb),
-                           self,
-                           G_CONNECT_SWAPPED);
-
   _ide_tree_node_show_popover (node, self, popover);
 }
 


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