[gnome-builder] hover: track original hover position



commit 6439f55eabece537d9a48275f2344e79a0f672b9
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jul 23 11:43:02 2018 -0700

    hover: track original hover position
    
    This ensures that we use an iter that matches the location of the original
    hover position when querying the hover providers.

 src/libide/hover/ide-hover-popover-private.h | 12 +++---
 src/libide/hover/ide-hover-popover.c         | 62 ++++++++++++++++++++++++----
 src/libide/hover/ide-hover.c                 | 23 +++++++----
 3 files changed, 77 insertions(+), 20 deletions(-)
---
diff --git a/src/libide/hover/ide-hover-popover-private.h b/src/libide/hover/ide-hover-popover-private.h
index f4a90efbe..2eb0de6cc 100644
--- a/src/libide/hover/ide-hover-popover-private.h
+++ b/src/libide/hover/ide-hover-popover-private.h
@@ -29,10 +29,12 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (IdeHoverPopover, ide_hover_popover, IDE, HOVER_POPOVER, GtkPopover)
 
-IdeHoverContext *_ide_hover_popover_get_context  (IdeHoverPopover  *self);
-void             _ide_hover_popover_add_provider (IdeHoverPopover  *self,
-                                                  IdeHoverProvider *provider);
-void             _ide_hover_popover_show         (IdeHoverPopover  *self);
-void             _ide_hover_popover_hide         (IdeHoverPopover  *self);
+IdeHoverContext *_ide_hover_popover_get_context    (IdeHoverPopover    *self);
+void             _ide_hover_popover_add_provider   (IdeHoverPopover    *self,
+                                                    IdeHoverProvider   *provider);
+void             _ide_hover_popover_show           (IdeHoverPopover    *self);
+void             _ide_hover_popover_hide           (IdeHoverPopover    *self);
+void             _ide_hover_popover_set_hovered_at (IdeHoverPopover    *self,
+                                                    const GdkRectangle *hovered_at);
 
 G_END_DECLS
diff --git a/src/libide/hover/ide-hover-popover.c b/src/libide/hover/ide-hover-popover.c
index f9e130b8f..edbfa56a7 100644
--- a/src/libide/hover/ide-hover-popover.c
+++ b/src/libide/hover/ide-hover-popover.c
@@ -21,6 +21,7 @@
 #define G_LOG_DOMAIN "ide-hover-popover"
 
 #include <dazzle.h>
+#include <string.h>
 
 #include "hover/ide-hover-context-private.h"
 #include "hover/ide-hover-popover-private.h"
@@ -50,6 +51,11 @@ struct _IdeHoverPopover
    */
   GCancellable *cancellable;
 
+  /*
+   * The position where the hover operation began.
+   */
+  GdkRectangle hovered_at;
+
   /*
    * If we've had any providers added, so that we can short-circuit
    * in that case without having to display the popover.
@@ -60,6 +66,7 @@ struct _IdeHoverPopover
 enum {
   PROP_0,
   PROP_CONTEXT,
+  PROP_HOVERED_AT,
   N_PROPS
 };
 
@@ -164,6 +171,18 @@ ide_hover_popover_get_preferred_height (GtkWidget *widget,
     *nat_height = *min_height;
 }
 
+void
+_ide_hover_popover_set_hovered_at (IdeHoverPopover    *self,
+                                   const GdkRectangle *hovered_at)
+{
+  g_assert (IDE_IS_HOVER_POPOVER (self));
+
+  if (hovered_at != NULL)
+    self->hovered_at = *hovered_at;
+  else
+    memset (&self->hovered_at, 0, sizeof self->hovered_at);
+}
+
 static void
 ide_hover_popover_destroy (GtkWidget *widget)
 {
@@ -191,6 +210,29 @@ ide_hover_popover_get_property (GObject    *object,
       g_value_set_object (value, _ide_hover_popover_get_context (self));
       break;
 
+    case PROP_HOVERED_AT:
+      g_value_set_boxed (value, &self->hovered_at);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_hover_popover_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  IdeHoverPopover *self = IDE_HOVER_POPOVER (object);
+
+  switch (prop_id)
+    {
+    case PROP_HOVERED_AT:
+      _ide_hover_popover_set_hovered_at (self, g_value_get_boxed (value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -203,6 +245,7 @@ ide_hover_popover_class_init (IdeHoverPopoverClass *klass)
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
   object_class->get_property = ide_hover_popover_get_property;
+  object_class->set_property = ide_hover_popover_set_property;
 
   widget_class->destroy = ide_hover_popover_destroy;
   widget_class->get_preferred_height = ide_hover_popover_get_preferred_height;
@@ -213,6 +256,13 @@ ide_hover_popover_class_init (IdeHoverPopoverClass *klass)
                          "The hover context to display to the user",
                          IDE_TYPE_HOVER_CONTEXT,
                          (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_HOVERED_AT] =
+    g_param_spec_boxed ("hovered-at",
+                         "Hovered At",
+                         "The position that the hover originated",
+                         GDK_TYPE_RECTANGLE,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   
   g_object_class_install_properties (object_class, N_PROPS, properties);
 }
@@ -258,7 +308,6 @@ _ide_hover_popover_add_provider (IdeHoverPopover  *self,
 void
 _ide_hover_popover_show (IdeHoverPopover *self)
 {
-  GdkRectangle rect;
   GtkWidget *view;
 
   g_return_if_fail (IDE_IS_HOVER_POPOVER (self));
@@ -267,19 +316,16 @@ _ide_hover_popover_show (IdeHoverPopover *self)
   if (self->has_providers &&
       !g_cancellable_is_cancelled (self->cancellable) &&
       (view = gtk_popover_get_relative_to (GTK_POPOVER (self))) &&
-      GTK_IS_TEXT_VIEW (view) &&
-      gtk_popover_get_pointing_to (GTK_POPOVER (self), &rect))
+      GTK_IS_TEXT_VIEW (view))
     {
       GtkTextIter iter;
       gint x, y;
 
-      /* Get the center of the box */
-      x = rect.x + (rect.width / 2);
-      y = rect.y + (rect.height / 2);
-
       gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view),
                                              GTK_TEXT_WINDOW_WIDGET,
-                                             x, y, &x, &y);
+                                             self->hovered_at.x,
+                                             self->hovered_at.y,
+                                             &x, &y);
       gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter, x, y);
 
       _ide_hover_context_query_async (self->context,
diff --git a/src/libide/hover/ide-hover.c b/src/libide/hover/ide-hover.c
index 514053720..62c068bee 100644
--- a/src/libide/hover/ide-hover.c
+++ b/src/libide/hover/ide-hover.c
@@ -173,7 +173,8 @@ ide_hover_popover_destroy_cb (IdeHover        *self,
 static gboolean
 ide_hover_get_bounds (IdeHover    *self,
                       GtkTextIter *begin,
-                      GtkTextIter *end)
+                      GtkTextIter *end,
+                      GtkTextIter *hover)
 {
   GtkTextView *view;
   GtkTextIter iter;
@@ -182,13 +183,14 @@ ide_hover_get_bounds (IdeHover    *self,
   g_assert (IDE_IS_HOVER (self));
   g_assert (begin != NULL);
   g_assert (end != NULL);
+  g_assert (hover != NULL);
+
+  memset (begin, 0, sizeof *begin);
+  memset (end, 0, sizeof *end);
+  memset (hover, 0, sizeof *hover);
 
   if (!(view = dzl_signal_group_get_target (self->signals)))
-    {
-      memset (begin, 0, sizeof *begin);
-      memset (end, 0, sizeof *end);
-      return FALSE;
-    }
+    return FALSE;
 
   g_assert (GTK_IS_TEXT_VIEW (view));
 
@@ -201,6 +203,8 @@ ide_hover_get_bounds (IdeHover    *self,
   if (!gtk_text_view_get_iter_at_location (view, &iter, x, y))
     return FALSE;
 
+  *hover = iter;
+
   if (!_ide_source_iter_inside_word (&iter))
     {
       *begin = iter;
@@ -231,8 +235,10 @@ ide_hover_motion_timeout_cb (gpointer data)
   GdkRectangle rect;
   GdkRectangle begin_rect;
   GdkRectangle end_rect;
+  GdkRectangle hover_rect;
   GtkTextIter begin;
   GtkTextIter end;
+  GtkTextIter hover;
 
   g_assert (IDE_IS_HOVER (self));
 
@@ -246,7 +252,7 @@ ide_hover_motion_timeout_cb (gpointer data)
     return G_SOURCE_REMOVE;
 
   /* Make sure we're over text */
-  if (!ide_hover_get_bounds (self, &begin, &end))
+  if (!ide_hover_get_bounds (self, &begin, &end, &hover))
     return G_SOURCE_REMOVE;
 
   if (self->popover == NULL)
@@ -290,12 +296,15 @@ ide_hover_motion_timeout_cb (gpointer data)
   self->state = IDE_HOVER_STATE_DISPLAY;
   gtk_text_view_get_iter_location (GTK_TEXT_VIEW (view), &begin, &begin_rect);
   gtk_text_view_get_iter_location (GTK_TEXT_VIEW (view), &end, &end_rect);
+  gtk_text_view_get_iter_location (GTK_TEXT_VIEW (view), &hover, &hover_rect);
   gdk_rectangle_union (&begin_rect, &end_rect, &rect);
 
   gtk_text_view_buffer_to_window_coords (GTK_TEXT_VIEW (view),
                                          GTK_TEXT_WINDOW_WIDGET,
                                          rect.x, rect.y, &rect.x, &rect.y);
 
+  _ide_hover_popover_set_hovered_at (self->popover, &hover_rect);
+
   if (gtk_text_iter_equal (&begin, &end) &&
       gtk_text_iter_starts_line (&begin))
     {


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