[gtk/event-recorder] inspector: Highlight event sequences




commit 4f751aa53d76003565adae0f68fc37be675614d4
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Dec 15 21:56:53 2021 -0500

    inspector: Highlight event sequences
    
    Optionally, highlight rows of events whose
    event sequences match the selected event.

 .../scalable/actions/function-linear-symbolic.svg  |   2 +
 gtk/inspector/inspector.css                        |   4 +
 gtk/inspector/meson.build                          |   1 +
 gtk/inspector/recorder.c                           | 116 +++++++++++++++--
 gtk/inspector/recorder.h                           |   6 +
 gtk/inspector/recorder.ui                          |   8 ++
 gtk/inspector/recorderrow.c                        | 138 +++++++++++++++++++++
 gtk/inspector/recorderrow.h                        |  24 ++++
 8 files changed, 287 insertions(+), 12 deletions(-)
---
diff --git a/gtk/icons/scalable/actions/function-linear-symbolic.svg 
b/gtk/icons/scalable/actions/function-linear-symbolic.svg
new file mode 100644
index 0000000000..0d3dfd5440
--- /dev/null
+++ b/gtk/icons/scalable/actions/function-linear-symbolic.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"; xmlns:xlink="http://www.w3.org/1999/xlink"; height="16px" viewBox="0 
0 16 16" width="16px"><filter id="a" height="100%" width="100%" x="0%" y="0%"><feColorMatrix 
in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><mask id="b"><g 
filter="url(#a)"><path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/></g></mask><clipPath id="c"><path d="m 
0 0 h 1600 v 1200 h -1600 z"/></clipPath><mask id="d"><g filter="url(#a)"><path d="m 0 0 h 16 v 16 h -16 z" 
fill-opacity="0.05"/></g></mask><clipPath id="e"><path d="m 0 0 h 1600 v 1200 h -1600 z"/></clipPath><mask 
id="f"><g filter="url(#a)"><path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/></g></mask><clipPath 
id="g"><path d="m 0 0 h 1600 v 1200 h -1600 z"/></clipPath><mask id="h"><g filter="url(#a)"><path d="m 0 0 h 
16 v 16 h -16 z" fill-opacity="0.05"/></g></mask><clipPath id="i"><path d="m 0 0 h 1600 v 1200 h -1600 
z"/></clipPath><mask id="j"><g filter="url(#a)">
 <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/></g></mask><clipPath id="k"><path d="m 0 0 h 1600 v 
1200 h -1600 z"/></clipPath><mask id="l"><g filter="url(#a)"><path d="m 0 0 h 16 v 16 h -16 z" 
fill-opacity="0.05"/></g></mask><clipPath id="m"><path d="m 0 0 h 1600 v 1200 h -1600 z"/></clipPath><mask 
id="n"><g filter="url(#a)"><path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/></g></mask><clipPath 
id="o"><path d="m 0 0 h 1600 v 1200 h -1600 z"/></clipPath><mask id="p"><g filter="url(#a)"><path d="m 0 0 h 
16 v 16 h -16 z" fill-opacity="0.3"/></g></mask><clipPath id="q"><path d="m 0 0 h 1600 v 1200 h -1600 
z"/></clipPath><mask id="r"><g filter="url(#a)"><path d="m 0 0 h 16 v 16 h -16 z" 
fill-opacity="0.5"/></g></mask><clipPath id="s"><path d="m 0 0 h 1600 v 1200 h -1600 z"/></clipPath><g 
clip-path="url(#c)" mask="url(#b)" transform="matrix(1 0 0 1 -16 -816)"><path d="m 562.460938 212.058594 h 
10.449218 c -1.183594 0.492187 -1.296875 2.460937 0 3 h -10.449218 z m 0 0" fill="
 #2e3436"/></g><g clip-path="url(#e)" mask="url(#d)" transform="matrix(1 0 0 1 -16 -816)"><path d="m 16 748 h 
1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/></g><g clip-path="url(#g)" mask="url(#f)" 
transform="matrix(1 0 0 1 -16 -816)"><path d="m 17 747 h 1 v 1 h -1 z m 0 0" fill="#2e3436" 
fill-rule="evenodd"/></g><g clip-path="url(#i)" mask="url(#h)" transform="matrix(1 0 0 1 -16 -816)"><path 
d="m 18 750 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/></g><g clip-path="url(#k)" 
mask="url(#j)" transform="matrix(1 0 0 1 -16 -816)"><path d="m 16 750 h 1 v 1 h -1 z m 0 0" fill="#2e3436" 
fill-rule="evenodd"/></g><g clip-path="url(#m)" mask="url(#l)" transform="matrix(1 0 0 1 -16 -816)"><path 
d="m 17 751 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/></g><g clip-path="url(#o)" 
mask="url(#n)" transform="matrix(1 0 0 1 -16 -816)"><path d="m 19 751 h 1 v 1 h -1 z m 0 0" fill="#2e3436" 
fill-rule="evenodd"/></g><g clip-path="url(#q)" mask="url(#p)" transform="matr
 ix(1 0 0 1 -16 -816)"><path d="m 136 776 v 7 h 7 v -7 z m 0 0" fill="#2e3436"/></g><g clip-path="url(#s)" 
mask="url(#r)" transform="matrix(1 0 0 1 -16 -816)"><path d="m 219 758 h 3 v 12 h -3 z m 0 0" 
fill="#2e3436"/></g><g fill="#2e3436"><path d="m 11.507812 3.078125 l -8.429687 8.429687 c 0.765625 0.039063 
1.375 0.648438 1.414063 1.414063 l 8.429687 -8.429687 c -0.765625 -0.039063 -1.375 -0.648438 -1.414063 
-1.414063 z m 0 0"/><path d="m 3 11 c -1.097656 0 -2 0.902344 -2 2 s 0.902344 2 2 2 s 2 -0.902344 2 -2 s 
-0.902344 -2 -2 -2 z m 0 1 c 0.558594 0 1 0.441406 1 1 s -0.441406 1 -1 1 s -1 -0.441406 -1 -1 s 0.441406 -1 
1 -1 z m 0 0"/><path d="m 13 1 c -1.097656 0 -2 0.902344 -2 2 s 0.902344 2 2 2 s 2 -0.902344 2 -2 s -0.902344 
-2 -2 -2 z m 0 1 c 0.558594 0 1 0.441406 1 1 s -0.441406 1 -1 1 s -1 -0.441406 -1 -1 s 0.441406 -1 1 -1 z m 0 
0"/></g></svg>
diff --git a/gtk/inspector/inspector.css b/gtk/inspector/inspector.css
index 702dc59690..33cad8a691 100644
--- a/gtk/inspector/inspector.css
+++ b/gtk/inspector/inspector.css
@@ -55,3 +55,7 @@ picture.light {
   min-width: 10px;
   min-height: 10px;
 }
+
+row:not(:selected) > .highlight {
+  background-color: rgba(135, 206, 250, 0.4);
+}
diff --git a/gtk/inspector/meson.build b/gtk/inspector/meson.build
index 08031b2c9a..fb9817fb41 100644
--- a/gtk/inspector/meson.build
+++ b/gtk/inspector/meson.build
@@ -31,6 +31,7 @@ inspector_sources = files(
   'prop-holder.c',
   'prop-list.c',
   'recorder.c',
+  'recorderrow.c',
   'recording.c',
   'renderrecording.c',
   'resource-holder.c',
diff --git a/gtk/inspector/recorder.c b/gtk/inspector/recorder.c
index 09114206e4..94930cba9e 100644
--- a/gtk/inspector/recorder.c
+++ b/gtk/inspector/recorder.c
@@ -55,6 +55,7 @@
 #include "renderrecording.h"
 #include "startrecording.h"
 #include "eventrecording.h"
+#include "recorderrow.h"
 
 struct _GtkInspectorRecorder
 {
@@ -82,6 +83,9 @@ struct _GtkInspectorRecorder
   gint64 start_time;
 
   gboolean debug_nodes;
+  gboolean highlight_sequences;
+
+  GdkEventSequence *selected_sequence;
 };
 
 typedef struct _GtkInspectorRecorderClass
@@ -95,6 +99,8 @@ enum
   PROP_0,
   PROP_RECORDING,
   PROP_DEBUG_NODES,
+  PROP_HIGHLIGHT_SEQUENCES,
+  PROP_SELECTED_SEQUENCE,
   LAST_PROP
 };
 
@@ -506,6 +512,7 @@ recording_selected (GtkSingleSelection   *selection,
                     GtkInspectorRecorder *recorder)
 {
   GtkInspectorRecording *recording;
+  GdkEventSequence *selected_sequence = NULL;
 
   if (recorder->recordings == NULL)
     {
@@ -548,6 +555,9 @@ recording_selected (GtkSingleSelection   *selection,
         }
 
       populate_event_properties (GTK_LIST_STORE (recorder->event_properties), event);
+
+      if (recorder->highlight_sequences)
+        selected_sequence = gdk_event_get_event_sequence (event);
     }
   else
     {
@@ -556,6 +566,8 @@ recording_selected (GtkSingleSelection   *selection,
       gtk_picture_set_paintable (GTK_PICTURE (recorder->render_node_view), NULL);
       g_list_store_remove_all (recorder->render_node_root_model);
     }
+
+  gtk_inspector_recorder_set_selected_sequence (recorder, selected_sequence);
 }
 
 static GdkTexture *
@@ -1428,6 +1440,12 @@ populate_event_properties (GtkListStore *store,
   type = gdk_event_get_event_type (event);
 
   add_text_row (store, "Type", event_type_name (type));
+  if (gdk_event_get_event_sequence (event) != NULL)
+    {
+      tmp = g_strdup_printf ("%p", gdk_event_get_event_sequence (event));
+      add_text_row (store, "Sequence", tmp);
+      g_free (tmp);
+    }
   add_int_row (store, "Timestamp", gdk_event_get_time (event));
 
   device = gdk_event_get_device (event);
@@ -1747,23 +1765,27 @@ setup_widget_for_recording (GtkListItemFactory *factory,
                             GtkListItem        *item,
                             gpointer            data)
 {
-  GtkWidget *widget, *label;
+  GtkWidget *row, *box, *label;
 
-  widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  row = g_object_new (GTK_TYPE_INSPECTOR_RECORDER_ROW, NULL);
+
+  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
   label = gtk_label_new ("");
   gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
   gtk_widget_set_hexpand (label, TRUE);
-  gtk_box_append (GTK_BOX (widget), label);
+  gtk_box_append (GTK_BOX (box), label);
 
   label = gtk_label_new ("");
-  gtk_box_append (GTK_BOX (widget), label);
+  gtk_box_append (GTK_BOX (box), label);
+
+  gtk_widget_set_margin_start (box, 6);
+  gtk_widget_set_margin_end (box, 6);
+  gtk_widget_set_margin_top (box, 6);
+  gtk_widget_set_margin_bottom (box, 6);
 
-  gtk_widget_set_margin_start (widget, 6);
-  gtk_widget_set_margin_end (widget, 6);
-  gtk_widget_set_margin_top (widget, 6);
-  gtk_widget_set_margin_bottom (widget, 6);
+  gtk_widget_set_parent (box, row);
 
-  gtk_list_item_set_child (item, widget);
+  gtk_list_item_set_child (item, row);
 }
 
 static char *
@@ -1841,14 +1863,19 @@ bind_widget_for_recording (GtkListItemFactory *factory,
                            GtkListItem        *item,
                            gpointer            data)
 {
+  GtkInspectorRecorder *recorder = GTK_INSPECTOR_RECORDER (data);
   GtkInspectorRecording *recording = gtk_list_item_get_item (item);
-  GtkWidget *widget, *label, *label2;
+  GtkWidget *row, *box, *label, *label2;
   char *text;
 
-  widget = gtk_list_item_get_child (item);
-  label = gtk_widget_get_first_child (widget);
+  row = gtk_list_item_get_child (item);
+  box = gtk_widget_get_first_child (row);
+  label = gtk_widget_get_first_child (box);
   label2 = gtk_widget_get_next_sibling (label);
 
+  g_object_set (row, "sequence", NULL, NULL);
+  g_object_bind_property (recorder, "selected-sequence", row, "match-sequence", G_BINDING_SYNC_CREATE);
+
   gtk_label_set_use_markup (GTK_LABEL (label), FALSE);
 
   if (GTK_INSPECTOR_IS_RENDER_RECORDING (recording))
@@ -1864,6 +1891,8 @@ bind_widget_for_recording (GtkListItemFactory *factory,
     {
       GdkEvent *event = gtk_inspector_event_recording_get_event (GTK_INSPECTOR_EVENT_RECORDING (recording));
 
+      g_object_set (row, "sequence", gdk_event_get_event_sequence (event), NULL);
+
       text = get_event_summary (event);
       gtk_label_set_label (GTK_LABEL (label), text);
       g_free (text);
@@ -1939,6 +1968,14 @@ gtk_inspector_recorder_get_property (GObject    *object,
       g_value_set_boolean (value, recorder->debug_nodes);
       break;
 
+    case PROP_HIGHLIGHT_SEQUENCES:
+      g_value_set_boolean (value, recorder->highlight_sequences);
+      break;
+
+    case PROP_SELECTED_SEQUENCE:
+      g_value_set_pointer (value, recorder->selected_sequence);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
@@ -1963,6 +2000,14 @@ gtk_inspector_recorder_set_property (GObject      *object,
       gtk_inspector_recorder_set_debug_nodes (recorder, g_value_get_boolean (value));
       break;
 
+    case PROP_HIGHLIGHT_SEQUENCES:
+      gtk_inspector_recorder_set_highlight_sequences (recorder, g_value_get_boolean (value));
+      break;
+
+    case PROP_SELECTED_SEQUENCE:
+      recorder->selected_sequence = g_value_get_pointer (value);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
@@ -2005,6 +2050,9 @@ gtk_inspector_recorder_class_init (GtkInspectorRecorderClass *klass)
                           FALSE,
                           G_PARAM_READWRITE);
 
+  props[PROP_HIGHLIGHT_SEQUENCES] = g_param_spec_boolean ("highlight-sequences", "", "", FALSE, 
G_PARAM_READWRITE);
+  props[PROP_SELECTED_SEQUENCE] = g_param_spec_pointer ("selected-sequence", "", "", G_PARAM_READWRITE);
+
   g_object_class_install_properties (object_class, LAST_PROP, props);
 
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/recorder.ui");
@@ -2197,4 +2245,48 @@ gtk_inspector_recorder_set_debug_nodes (GtkInspectorRecorder *recorder,
   g_object_notify_by_pspec (G_OBJECT (recorder), props[PROP_DEBUG_NODES]);
 }
 
+void
+gtk_inspector_recorder_set_highlight_sequences (GtkInspectorRecorder *recorder,
+                                                gboolean              highlight_sequences)
+{
+  GdkEventSequence *sequence = NULL;
+
+  if (recorder->highlight_sequences == highlight_sequences)
+    return;
+
+  recorder->highlight_sequences = highlight_sequences;
+
+  if (highlight_sequences)
+    {
+      GtkSingleSelection *selection;
+      GtkInspectorRecording *recording;
+      GdkEvent *event;
+
+      selection = GTK_SINGLE_SELECTION (gtk_list_view_get_model (GTK_LIST_VIEW (recorder->recordings_list)));
+      recording = gtk_single_selection_get_selected_item (selection);
+
+      if (GTK_INSPECTOR_IS_EVENT_RECORDING (recording))
+        {
+          event = gtk_inspector_event_recording_get_event (GTK_INSPECTOR_EVENT_RECORDING (recording));
+          sequence = gdk_event_get_event_sequence (event);
+        }
+    }
+
+  gtk_inspector_recorder_set_selected_sequence (recorder, sequence);
+
+  g_object_notify_by_pspec (G_OBJECT (recorder), props[PROP_HIGHLIGHT_SEQUENCES]);
+}
+
+void
+gtk_inspector_recorder_set_selected_sequence (GtkInspectorRecorder *recorder,
+                                              GdkEventSequence     *sequence)
+{
+  if (recorder->selected_sequence == sequence)
+    return;
+
+  recorder->selected_sequence = sequence;
+
+  g_object_notify_by_pspec (G_OBJECT (recorder), props[PROP_SELECTED_SEQUENCE]);
+}
+
 
diff --git a/gtk/inspector/recorder.h b/gtk/inspector/recorder.h
index be5260879b..1ce908036a 100644
--- a/gtk/inspector/recorder.h
+++ b/gtk/inspector/recorder.h
@@ -37,6 +37,12 @@ gboolean        gtk_inspector_recorder_is_recording             (GtkInspectorRec
 void            gtk_inspector_recorder_set_debug_nodes          (GtkInspectorRecorder   *recorder,
                                                                  gboolean                debug_nodes);
 
+void            gtk_inspector_recorder_set_highlight_sequences  (GtkInspectorRecorder   *recorder,
+                                                                 gboolean                
highlight_sequences);
+
+void            gtk_inspector_recorder_set_selected_sequence    (GtkInspectorRecorder   *recorder,
+                                                                 GdkEventSequence       *sequence);
+
 void            gtk_inspector_recorder_record_render            (GtkInspectorRecorder   *recorder,
                                                                  GtkWidget              *widget,
                                                                  GskRenderer            *renderer,
diff --git a/gtk/inspector/recorder.ui b/gtk/inspector/recorder.ui
index 4accd7fa44..d3bee18312 100644
--- a/gtk/inspector/recorder.ui
+++ b/gtk/inspector/recorder.ui
@@ -34,6 +34,14 @@
                 <property name="tooltip-text" translatable="yes">Add debug nodes</property>
                 <property name="active" bind-source="GtkInspectorRecorder" bind-property="debug-nodes" 
bind-flags="bidirectional|sync-create"/>
                 <property name="halign">start</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkToggleButton">
+                <property name="icon-name">function-linear-symbolic</property>
+                <property name="tooltip-text" translatable="yes">Highlight event sequences</property>
+                <property name="active" bind-source="GtkInspectorRecorder" 
bind-property="highlight-sequences" bind-flags="bidirectional|sync-create"/>
+                <property name="halign">start</property>
                 <property name="hexpand">1</property>
               </object>
             </child>
diff --git a/gtk/inspector/recorderrow.c b/gtk/inspector/recorderrow.c
new file mode 100644
index 0000000000..37ceab7e3f
--- /dev/null
+++ b/gtk/inspector/recorderrow.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include "recorderrow.h"
+
+#include <gtk/gtkbinlayout.h>
+
+/* This is a minimal widget whose purpose it is to compare the event sequence
+ * of its row in the recordings list with the event sequence of the selected
+ * row, and highlight itself if they match.
+ */
+
+struct _GtkInspectorRecorderRow
+{
+  GtkWidget parent;
+
+  gpointer sequence;
+  gpointer match_sequence;
+};
+
+enum {
+  PROP_SEQUENCE = 1,
+  PROP_MATCH_SEQUENCE,
+  LAST_PROP
+};
+
+static GParamSpec *props[LAST_PROP] = { NULL, };
+
+G_DEFINE_TYPE (GtkInspectorRecorderRow, gtk_inspector_recorder_row, GTK_TYPE_WIDGET)
+
+static void
+gtk_inspector_recorder_row_init (GtkInspectorRecorderRow *self)
+{
+}
+
+static void
+dispose (GObject *object)
+{
+  GtkInspectorRecorderRow *self = GTK_INSPECTOR_RECORDER_ROW (object);
+
+  gtk_widget_unparent (gtk_widget_get_first_child (GTK_WIDGET (self)));
+
+  G_OBJECT_CLASS (gtk_inspector_recorder_row_parent_class)->dispose (object);
+}
+
+static void
+update_style (GtkInspectorRecorderRow *self)
+{
+  if (self->sequence == self->match_sequence && self->sequence != NULL)
+    gtk_widget_add_css_class (GTK_WIDGET (self), "highlight");
+  else
+    gtk_widget_remove_css_class (GTK_WIDGET (self), "highlight");
+}
+
+static void
+gtk_inspector_recorder_row_get_property (GObject    *object,
+                                         guint       param_id,
+                                         GValue     *value,
+                                         GParamSpec *pspec)
+{
+  GtkInspectorRecorderRow *self = GTK_INSPECTOR_RECORDER_ROW (object);
+
+  switch (param_id)
+    {
+    case PROP_SEQUENCE:
+      g_value_set_pointer (value, self->sequence);
+      break;
+
+    case PROP_MATCH_SEQUENCE:
+      g_value_set_pointer (value, self->match_sequence);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_inspector_recorder_row_set_property (GObject      *object,
+                                         guint         param_id,
+                                         const GValue *value,
+                                         GParamSpec   *pspec)
+{
+  GtkInspectorRecorderRow *self = GTK_INSPECTOR_RECORDER_ROW (object);
+
+  switch (param_id)
+    {
+    case PROP_SEQUENCE:
+      self->sequence = g_value_get_pointer (value);
+      update_style (self);
+      break;
+
+    case PROP_MATCH_SEQUENCE:
+      self->match_sequence = g_value_get_pointer (value);
+      update_style (self);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_inspector_recorder_row_class_init (GtkInspectorRecorderRowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->dispose = dispose;
+  object_class->set_property = gtk_inspector_recorder_row_set_property;
+  object_class->get_property = gtk_inspector_recorder_row_get_property;
+
+  props[PROP_SEQUENCE] = g_param_spec_pointer ("sequence", "", "", G_PARAM_READWRITE);
+  props[PROP_MATCH_SEQUENCE] = g_param_spec_pointer ("match-sequence", "", "", G_PARAM_READWRITE);
+
+  g_object_class_install_properties (object_class, LAST_PROP, props);
+
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+}
diff --git a/gtk/inspector/recorderrow.h b/gtk/inspector/recorderrow.h
new file mode 100644
index 0000000000..6aa835107b
--- /dev/null
+++ b/gtk/inspector/recorderrow.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtkwidget.h>
+
+#define GTK_TYPE_INSPECTOR_RECORDER_ROW (gtk_inspector_recorder_row_get_type ())
+
+G_DECLARE_FINAL_TYPE (GtkInspectorRecorderRow, gtk_inspector_recorder_row, GTK, INSPECTOR_RECORDER_ROW, 
GtkWidget)


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