[gtk/wip/matthiasc/focus2: 4/7] inspector: Add a focus overlay



commit 0c17a700c6ce27fc60e0f18369229f6bccc79146
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Mar 2 20:03:34 2019 -0500

    inspector: Add a focus overlay
    
    Add an overlay that shows a segment of the focus chain.

 gtk/inspector/focusoverlay.c | 135 +++++++++++++++++++++++++++++++++++++++++++
 gtk/inspector/focusoverlay.h |  19 ++++++
 gtk/inspector/meson.build    |   1 +
 gtk/inspector/visual.c       |  38 ++++++++++++
 gtk/inspector/visual.ui      |  27 +++++++++
 5 files changed, 220 insertions(+)
---
diff --git a/gtk/inspector/focusoverlay.c b/gtk/inspector/focusoverlay.c
new file mode 100644
index 0000000000..a46d29ec50
--- /dev/null
+++ b/gtk/inspector/focusoverlay.c
@@ -0,0 +1,135 @@
+#include "config.h"
+#include "focusoverlay.h"
+#include "gtkwidgetprivate.h"
+
+struct _GtkFocusOverlay
+{
+  GtkInspectorOverlay parent_instance;
+};
+
+struct _GtkFocusOverlayClass
+{
+  GtkInspectorOverlayClass parent_class;
+};
+
+G_DEFINE_TYPE (GtkFocusOverlay, gtk_focus_overlay, GTK_TYPE_INSPECTOR_OVERLAY)
+
+static void
+draw_focus_location (GtkWidget   *widget,
+                     GtkWidget   *child,
+                     GtkSnapshot *snapshot,
+                     const char  *color,
+                     const char  *text)
+{
+  GtkAllocation allocation;
+  graphene_rect_t bounds;
+  PangoLayout *layout;
+  PangoRectangle rect;
+  GskRoundedRect rrect;
+  int x, y;
+  GdkRGBA rgba;
+
+  if (child == NULL)
+    return;
+
+  gdk_rgba_parse (&rgba, color);
+
+  gtk_widget_get_allocation (child, &allocation);
+
+  gtk_snapshot_save (snapshot);
+
+  gtk_widget_translate_coordinates (child, widget, 0, 0, &x, &y);
+  gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
+
+  gtk_snapshot_push_debug (snapshot, "Widget focus debugging");
+
+  layout = gtk_widget_create_pango_layout (widget, NULL);
+  pango_layout_set_markup (layout, text, -1);
+  pango_layout_get_extents (layout, NULL, &rect);
+  graphene_rect_init (&bounds,
+                      0, 0,
+                      rect.width / PANGO_SCALE + 20,
+                      rect.height / PANGO_SCALE + 20);
+  gsk_rounded_rect_init_from_rect (&rrect, &bounds, 10.0f); 
+
+  gtk_snapshot_push_rounded_clip (snapshot, &rrect);
+
+  gtk_snapshot_append_color (snapshot, &rgba, &bounds);
+
+  gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (10, 10));
+  gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA) { 1, 1, 1, 1 });
+  g_object_unref (layout);
+
+  gtk_snapshot_pop (snapshot);
+  gtk_snapshot_pop (snapshot);
+
+  gtk_snapshot_restore (snapshot);
+}
+
+static void
+draw_focus_locations (GtkWidget   *widget,
+                      GtkSnapshot *snapshot)
+{
+  GtkWidget *focus;
+  GtkWidget *next;
+  int i;
+  char text[20];
+
+  if (!gtk_widget_get_mapped (widget))
+    return;
+
+  focus = gtk_root_get_focus (GTK_ROOT (widget));
+  if (focus == NULL)
+    return;
+
+  draw_focus_location (widget, focus, snapshot, "rgba(0,0,255,0.4)", "Focus");
+
+  next = focus;
+  for (i = 1; i < 4; i++)
+    {
+      g_snprintf (text, 20, "<big>⇥</big> %d", i);
+      next = gtk_widget_get_next_focus (next, GTK_DIR_TAB_FORWARD);
+      if (!next)
+        break;
+      draw_focus_location (widget, next, snapshot, "rgba(255,0,255,0.4)", text);
+    }
+
+  next = focus;
+  for (i = 1; i < 4; i++)
+    {
+      g_snprintf (text, 20, "<big>⇤</big> %d", i);
+      next = gtk_widget_get_next_focus (next, GTK_DIR_TAB_BACKWARD);
+      if (!next)
+        break;
+      draw_focus_location (widget, next, snapshot, "rgba(255,0,255,0.4)", text);
+    }
+}
+
+static void
+gtk_focus_overlay_snapshot (GtkInspectorOverlay *overlay,
+                            GtkSnapshot         *snapshot,
+                            GskRenderNode       *node,
+                            GtkWidget           *widget)
+{
+  draw_focus_locations (widget, snapshot);
+}
+
+static void
+gtk_focus_overlay_init (GtkFocusOverlay *self)
+{
+
+}
+
+static void
+gtk_focus_overlay_class_init (GtkFocusOverlayClass *klass)
+{
+  GtkInspectorOverlayClass *overlay_class = (GtkInspectorOverlayClass *)klass;
+
+  overlay_class->snapshot = gtk_focus_overlay_snapshot;
+}
+
+GtkInspectorOverlay *
+gtk_focus_overlay_new (void)
+{
+  return g_object_new (GTK_TYPE_FOCUS_OVERLAY, NULL);
+}
diff --git a/gtk/inspector/focusoverlay.h b/gtk/inspector/focusoverlay.h
new file mode 100644
index 0000000000..429a3ef94d
--- /dev/null
+++ b/gtk/inspector/focusoverlay.h
@@ -0,0 +1,19 @@
+
+
+#ifndef __GTK_FOCUS_OVERLAY_H__
+#define __GTK_FOCUS_OVERLAY_H__
+
+#include "inspectoroverlay.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_FOCUS_OVERLAY             (gtk_focus_overlay_get_type ())
+G_DECLARE_FINAL_TYPE (GtkFocusOverlay, gtk_focus_overlay, GTK, FOCUS_OVERLAY, GtkInspectorOverlay)
+
+GtkInspectorOverlay *   gtk_focus_overlay_new                 (void);
+
+G_END_DECLS
+
+
+
+#endif
diff --git a/gtk/inspector/meson.build b/gtk/inspector/meson.build
index a134f8f278..92bd8020d1 100644
--- a/gtk/inspector/meson.build
+++ b/gtk/inspector/meson.build
@@ -6,6 +6,7 @@ inspector_sources = files(
   'css-editor.c',
   'css-node-tree.c',
   'data-list.c',
+  'focusoverlay.c',
   'fpsoverlay.c',
   'general.c',
   'graphdata.c',
diff --git a/gtk/inspector/visual.c b/gtk/inspector/visual.c
index 5a21d1d316..930c51659f 100644
--- a/gtk/inspector/visual.c
+++ b/gtk/inspector/visual.c
@@ -20,6 +20,7 @@
 
 #include "visual.h"
 
+#include "focusoverlay.h"
 #include "fpsoverlay.h"
 #include "updatesoverlay.h"
 #include "layoutoverlay.h"
@@ -83,6 +84,7 @@ struct _GtkInspectorVisualPrivate
   GtkInspectorOverlay *fps_overlay;
   GtkInspectorOverlay *updates_overlay;
   GtkInspectorOverlay *layout_overlay;
+  GtkInspectorOverlay *focus_overlay;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorVisual, gtk_inspector_visual, GTK_TYPE_SCROLLED_WINDOW)
@@ -298,6 +300,41 @@ updates_activate (GtkSwitch          *sw,
   redraw_everything ();
 }
 
+static void
+focus_activate (GtkSwitch          *sw,
+                GParamSpec         *pspec,
+                GtkInspectorVisual *vis)
+{
+  GtkInspectorVisualPrivate *priv = vis->priv;
+  GtkInspectorWindow *iw;
+  gboolean focus;
+
+  focus = gtk_switch_get_active (sw);
+  iw = GTK_INSPECTOR_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (vis)));
+  if (iw == NULL)
+    return;
+
+  if (focus)
+    {
+      if (priv->focus_overlay == NULL)
+        {
+          priv->focus_overlay = gtk_focus_overlay_new ();
+          gtk_inspector_window_add_overlay (iw, priv->focus_overlay);
+          g_object_unref (priv->focus_overlay);
+        }
+    }
+  else
+    {
+      if (priv->focus_overlay != NULL)
+        {
+          gtk_inspector_window_remove_overlay (iw, priv->focus_overlay);
+          priv->focus_overlay = NULL;
+        }
+    }
+
+  redraw_everything ();
+}
+
 static void
 baselines_activate (GtkSwitch *sw)
 {
@@ -952,6 +989,7 @@ gtk_inspector_visual_class_init (GtkInspectorVisualClass *klass)
   gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, font_scale_entry);
   gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, font_scale_adjustment);
 
+  gtk_widget_class_bind_template_callback (widget_class, focus_activate);
   gtk_widget_class_bind_template_callback (widget_class, fps_activate);
   gtk_widget_class_bind_template_callback (widget_class, updates_activate);
   gtk_widget_class_bind_template_callback (widget_class, direction_changed);
diff --git a/gtk/inspector/visual.ui b/gtk/inspector/visual.ui
index 1b143fd291..a9948e7d61 100644
--- a/gtk/inspector/visual.ui
+++ b/gtk/inspector/visual.ui
@@ -371,6 +371,33 @@
             <child>
               <object class="GtkListBox" id="debug_box">
                 <property name="selection-mode">none</property>
+                <child>
+                  <object class="GtkListBoxRow">
+                    <property name="activatable">0</property>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="margin">10</property>
+                        <property name="spacing">40</property>
+                        <child>
+                          <object class="GtkLabel" id="focus_label">
+                            <property name="label" translatable="yes">Show focus overlay</property>
+                            <property name="halign">start</property>
+                            <property name="valign">baseline</property>
+                            <property name="xalign">0.0</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkSwitch" id="focus_switch">
+                            <property name="halign">end</property>
+                            <property name="valign">baseline</property>
+                            <property name="hexpand">1</property>
+                            <signal name="notify::active" handler="focus_activate"/>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
                 <child>
                   <object class="GtkListBoxRow">
                     <property name="activatable">0</property>


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