[gtk/event-recorder] wip: Add event recording to the inspector
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/event-recorder] wip: Add event recording to the inspector
- Date: Tue, 14 Dec 2021 22:41:08 +0000 (UTC)
commit 5a69a15ba3b52990219ffd68ec957a296c4c99f2
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Dec 14 17:40:19 2021 -0500
wip: Add event recording to the inspector
The basics work here, but the UX needs to be
redone to make this useful.
gtk/inspector/eventrecording.c | 69 ++++++++++++++
gtk/inspector/eventrecording.h | 64 +++++++++++++
gtk/inspector/meson.build | 1 +
gtk/inspector/recorder.c | 208 ++++++++++++++++++++++++++++++++++++++---
gtk/inspector/recorder.h | 4 +
gtk/inspector/window.c | 8 +-
6 files changed, 338 insertions(+), 16 deletions(-)
---
diff --git a/gtk/inspector/eventrecording.c b/gtk/inspector/eventrecording.c
new file mode 100644
index 0000000000..d24d51455a
--- /dev/null
+++ b/gtk/inspector/eventrecording.c
@@ -0,0 +1,69 @@
+/*
+ * 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 "eventrecording.h"
+
+G_DEFINE_TYPE (GtkInspectorEventRecording, gtk_inspector_event_recording, GTK_TYPE_INSPECTOR_RECORDING)
+
+static void
+gtk_inspector_event_recording_finalize (GObject *object)
+{
+ GtkInspectorEventRecording *recording = GTK_INSPECTOR_EVENT_RECORDING (object);
+
+ g_clear_pointer (&recording->event, gdk_event_unref);
+
+ G_OBJECT_CLASS (gtk_inspector_event_recording_parent_class)->finalize (object);
+}
+
+static void
+gtk_inspector_event_recording_class_init (GtkInspectorEventRecordingClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_inspector_event_recording_finalize;
+}
+
+static void
+gtk_inspector_event_recording_init (GtkInspectorEventRecording *vis)
+{
+}
+
+GtkInspectorRecording *
+gtk_inspector_event_recording_new (gint64 timestamp,
+ GdkEvent *event)
+{
+ GtkInspectorEventRecording *recording;
+
+ recording = g_object_new (GTK_TYPE_INSPECTOR_EVENT_RECORDING,
+ "timestamp", timestamp,
+ NULL);
+
+ recording->event = gdk_event_ref (event);
+
+ return GTK_INSPECTOR_RECORDING (recording);
+}
+
+GdkEvent *
+gtk_inspector_event_recording_get_event (GtkInspectorEventRecording *recording)
+{
+ return recording->event;
+}
+
+// vim: set et sw=2 ts=2:
diff --git a/gtk/inspector/eventrecording.h b/gtk/inspector/eventrecording.h
new file mode 100644
index 0000000000..11c126c6a0
--- /dev/null
+++ b/gtk/inspector/eventrecording.h
@@ -0,0 +1,64 @@
+/*
+ * 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/>.
+ */
+
+#ifndef _GTK_INSPECTOR_EVENT_RECORDING_H_
+#define _GTK_INSPECTOR_EVENT_RECORDING_H_
+
+#include <gdk/gdk.h>
+#include <gsk/gsk.h>
+#include "gsk/gskprofilerprivate.h"
+
+#include "inspector/recording.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_INSPECTOR_EVENT_RECORDING (gtk_inspector_event_recording_get_type())
+#define GTK_INSPECTOR_EVENT_RECORDING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),
GTK_TYPE_INSPECTOR_EVENT_RECORDING, GtkInspectorEventRecording))
+#define GTK_INSPECTOR_EVENT_RECORDING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),
GTK_TYPE_INSPECTOR_EVENT_RECORDING, GtkInspectorEventRecordingClass))
+#define GTK_INSPECTOR_IS_EVENT_RECORDING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),
GTK_TYPE_INSPECTOR_EVENT_RECORDING))
+#define GTK_INSPECTOR_IS_EVENT_RECORDING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),
GTK_TYPE_INSPECTOR_EVENT_RECORDING))
+#define GTK_INSPECTOR_EVENT_RECORDING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),
GTK_TYPE_INSPECTOR_EVENT_RECORDING, GtkInspectorEventRecordingClass))
+
+
+typedef struct _GtkInspectorEventRecordingPrivate GtkInspectorEventRecordingPrivate;
+
+typedef struct _GtkInspectorEventRecording
+{
+ GtkInspectorRecording parent;
+
+ GdkEvent *event;
+} GtkInspectorEventRecording;
+
+typedef struct _GtkInspectorEventRecordingClass
+{
+ GtkInspectorRecordingClass parent;
+} GtkInspectorEventRecordingClass;
+
+GType gtk_inspector_event_recording_get_type (void);
+
+GtkInspectorRecording *
+ gtk_inspector_event_recording_new (gint64 timestamp,
+ GdkEvent *event);
+
+GdkEvent * gtk_inspector_event_recording_get_event (GtkInspectorEventRecording *recording);
+
+
+G_END_DECLS
+
+#endif // _GTK_INSPECTOR_EVENT_RECORDING_H_
+
+// vim: set et sw=2 ts=2:
diff --git a/gtk/inspector/meson.build b/gtk/inspector/meson.build
index 422eab7f24..08031b2c9a 100644
--- a/gtk/inspector/meson.build
+++ b/gtk/inspector/meson.build
@@ -9,6 +9,7 @@ inspector_sources = files(
'controllers.c',
'css-editor.c',
'css-node-tree.c',
+ 'eventrecording.c',
'focusoverlay.c',
'fpsoverlay.c',
'general.c',
diff --git a/gtk/inspector/recorder.c b/gtk/inspector/recorder.c
index 35f52cd6b0..8cf8e32129 100644
--- a/gtk/inspector/recorder.c
+++ b/gtk/inspector/recorder.c
@@ -52,6 +52,7 @@
#include "recording.h"
#include "renderrecording.h"
+#include "eventrecording.h"
#include "startrecording.h"
struct _GtkInspectorRecorder
@@ -424,6 +425,63 @@ bind_widget_for_render_node (GtkSignalListItemFactory *factory,
g_object_unref (paintable);
}
+static void
+show_render_node (GtkInspectorRecorder *recorder,
+ GskRenderNode *node)
+{
+ graphene_rect_t bounds;
+ GdkPaintable *paintable;
+
+ gsk_render_node_get_bounds (node, &bounds);
+ paintable = gtk_render_node_paintable_new (node, &bounds);
+ gtk_picture_set_paintable (GTK_PICTURE (recorder->render_node_view), paintable);
+
+ g_list_store_splice (recorder->render_node_root_model,
+ 0, g_list_model_get_n_items (G_LIST_MODEL (recorder->render_node_root_model)),
+ (gpointer[1]) { paintable },
+ 1);
+ g_object_unref (paintable);
+}
+
+static GskRenderNode *
+make_dot (double x, double y)
+{
+ GskRenderNode *fill, *dot;
+ GdkRGBA red = (GdkRGBA){ 1, 0, 0, 1 };
+ graphene_rect_t rect = GRAPHENE_RECT_INIT (x - 3, y - 3, 6, 6);
+ graphene_size_t corner = GRAPHENE_SIZE_INIT (3, 3);
+ GskRoundedRect clip;
+
+ fill = gsk_color_node_new (&red, &rect);
+ dot = gsk_rounded_clip_node_new (fill, gsk_rounded_rect_init (&clip, &rect,
+ &corner, &corner, &corner, &corner));
+ gsk_render_node_unref (fill);
+
+ return dot;
+}
+
+static void
+show_event (GtkInspectorRecorder *recorder,
+ GskRenderNode *node,
+ GdkEvent *event)
+{
+ GskRenderNode *temp;
+ double x, y;
+
+ if (gdk_event_get_position (event, &x, &y))
+ {
+ GskRenderNode *dot = make_dot (x, y);
+ temp = gsk_container_node_new ((GskRenderNode *[]) { node, dot }, 2);
+ gsk_render_node_unref (dot);
+ }
+ else
+ temp = gsk_render_node_ref (node);
+
+ show_render_node (recorder, temp);
+
+ gsk_render_node_unref (temp);
+}
+
static void
recording_selected (GtkSingleSelection *selection,
GParamSpec *pspec,
@@ -438,20 +496,32 @@ recording_selected (GtkSingleSelection *selection,
if (GTK_INSPECTOR_IS_RENDER_RECORDING (recording))
{
- graphene_rect_t bounds;
GskRenderNode *node;
- GdkPaintable *paintable;
node = gtk_inspector_render_recording_get_node (GTK_INSPECTOR_RENDER_RECORDING (recording));
- gsk_render_node_get_bounds (node, &bounds);
- paintable = gtk_render_node_paintable_new (node, &bounds);
- gtk_picture_set_paintable (GTK_PICTURE (recorder->render_node_view), paintable);
-
- g_list_store_splice (recorder->render_node_root_model,
- 0, g_list_model_get_n_items (G_LIST_MODEL (recorder->render_node_root_model)),
- (gpointer[1]) { paintable },
- 1);
- g_object_unref (paintable);
+ show_render_node (recorder, node);
+ }
+ else if (GTK_INSPECTOR_IS_EVENT_RECORDING (recording))
+ {
+ GdkEvent *event;
+
+ event = gtk_inspector_event_recording_get_event (GTK_INSPECTOR_EVENT_RECORDING (recording));
+
+ for (guint pos = gtk_single_selection_get_selected (selection) - 1; pos > 0; pos--)
+ {
+ GtkInspectorRecording *item = g_list_model_get_item (G_LIST_MODEL (selection), pos);
+
+ g_object_unref (item);
+ if (GTK_INSPECTOR_IS_RENDER_RECORDING (item))
+ {
+ GskRenderNode *node;
+
+ node = gtk_inspector_render_recording_get_node (GTK_INSPECTOR_RENDER_RECORDING (item));
+ show_event (recorder, node, event);
+ break;
+ }
+ }
+
}
else
{
@@ -1354,6 +1424,78 @@ setup_widget_for_recording (GtkListItemFactory *factory,
gtk_list_item_set_child (item, widget);
}
+static const char *
+get_event_name (GdkEvent *event)
+{
+ const char *event_names[] = {
+ "Delete",
+ "Motion",
+ "Button Press",
+ "Button Release",
+ "Key Press",
+ "Key Release",
+ "Enter",
+ "Leave",
+ "Focus",
+ "Proximity In",
+ "Proximity Out",
+ "Drag Enter",
+ "Drag Leave",
+ "Drag Motion",
+ "Drop Start",
+ "Scroll",
+ "Grab Broken",
+ "Touch Begin",
+ "Touch Update",
+ "Touch End",
+ "Touch Cancel",
+ "Touchpad Swipe",
+ "Touchpad Pinch",
+ "Pad Button Press",
+ "Pad Button Release",
+ "Pad Rind",
+ "Pad Strip",
+ "Pad Group Mode"
+ };
+
+ return event_names[gdk_event_get_event_type (event)];
+}
+
+static char *
+get_event_info (GdkEvent *event)
+{
+ double x, y;
+ GString *s;
+
+ s = g_string_new ("");
+
+ if (gdk_event_get_position (event, &x, &y))
+ g_string_append_printf (s, "Position %g %g", x, y);
+
+ switch ((int)gdk_event_get_event_type (event))
+ {
+ default:
+ case GDK_DELETE:
+ case GDK_MOTION_NOTIFY:
+ break;
+
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ g_string_append_printf (s, "\nButton %d", s->len > 0 ? "\n" : "", gdk_button_event_get_button (event));
+ break;
+
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ g
+ }
+
+ if (s->len > 0)
+ return g_string_free (s, FALSE);
+
+ g_string_free (s, TRUE);
+ return NULL;
+}
+
static void
bind_widget_for_recording (GtkListItemFactory *factory,
GtkListItem *item,
@@ -1368,18 +1510,39 @@ bind_widget_for_recording (GtkListItemFactory *factory,
button = gtk_widget_get_next_sibling (label);
label2 = gtk_widget_get_next_sibling (hbox);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
+
if (GTK_INSPECTOR_IS_RENDER_RECORDING (recording))
{
gtk_label_set_label (GTK_LABEL (label), "<b>Frame</b>");
gtk_widget_show (button);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
gtk_label_set_label (GTK_LABEL (label2), gtk_inspector_render_recording_get_profiler_info
(GTK_INSPECTOR_RENDER_RECORDING (recording)));
}
+ else if (GTK_INSPECTOR_IS_EVENT_RECORDING (recording))
+ {
+ GdkEvent *event = gtk_inspector_event_recording_get_event (GTK_INSPECTOR_EVENT_RECORDING (recording));
+ char *text;
+
+ text = g_strdup_printf ("<b>%s Event</b>", get_event_name (event));
+ gtk_label_set_label (GTK_LABEL (label), text);
+ g_free (text);
+
+ text = get_event_info (event);
+ if (text)
+ {
+ gtk_widget_show (button);
+ gtk_label_set_label (GTK_LABEL (label2), text);
+ g_free (text);
+ }
+ else
+ {
+ gtk_widget_hide (button);
+ }
+ }
else
{
gtk_label_set_label (GTK_LABEL (label), "<b>Start of Recording</b>");
gtk_widget_hide (button);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
gtk_label_set_label (GTK_LABEL (label2), "");
}
}
@@ -1572,7 +1735,6 @@ static void
gtk_inspector_recorder_add_recording (GtkInspectorRecorder *recorder,
GtkInspectorRecording *recording)
{
- g_print ("appending %s\n", G_OBJECT_TYPE_NAME (recording));
g_list_store_append (G_LIST_STORE (recorder->recordings), recording);
}
@@ -1629,6 +1791,24 @@ gtk_inspector_recorder_record_render (GtkInspectorRecorder *recorder,
g_object_unref (recording);
}
+void
+gtk_inspector_recorder_record_event (GtkInspectorRecorder *recorder,
+ GtkWidget *widget,
+ GdkEvent *event)
+{
+ GtkInspectorRecording *recording;
+ GdkFrameClock *frame_clock;
+
+ if (!gtk_inspector_recorder_is_recording (recorder))
+ return;
+
+ frame_clock = gtk_widget_get_frame_clock (widget);
+
+ recording = gtk_inspector_event_recording_new (gdk_frame_clock_get_frame_time (frame_clock), event);
+ gtk_inspector_recorder_add_recording (recorder, recording);
+ g_object_unref (recording);
+}
+
void
gtk_inspector_recorder_set_debug_nodes (GtkInspectorRecorder *recorder,
gboolean debug_nodes)
diff --git a/gtk/inspector/recorder.h b/gtk/inspector/recorder.h
index 925aa3eeb5..be5260879b 100644
--- a/gtk/inspector/recorder.h
+++ b/gtk/inspector/recorder.h
@@ -44,6 +44,10 @@ void gtk_inspector_recorder_record_render (GtkInspectorRec
const cairo_region_t *region,
GskRenderNode *node);
+void gtk_inspector_recorder_record_event (GtkInspectorRecorder *recorder,
+ GtkWidget *widget,
+ GdkEvent *event);
+
G_END_DECLS
#endif // _GTK_INSPECTOR_RECORDER_H_
diff --git a/gtk/inspector/window.c b/gtk/inspector/window.c
index 8b07fb3de3..a950233424 100644
--- a/gtk/inspector/window.c
+++ b/gtk/inspector/window.c
@@ -184,7 +184,7 @@ open_object_details (GtkWidget *button, GtkInspectorWindow *iw)
GObject *selected;
selected = gtk_inspector_object_tree_get_selected (GTK_INSPECTOR_OBJECT_TREE (iw->object_tree));
-
+
gtk_inspector_window_set_object (iw, selected, CHILD_KIND_WIDGET, 0);
gtk_stack_set_visible_child_name (GTK_STACK (iw->object_stack), "object-details");
@@ -752,7 +752,7 @@ gtk_inspector_window_get (GdkDisplay *display)
iw = GTK_WIDGET (g_object_get_data (G_OBJECT (display), "-gtk-inspector"));
if (!iw)
- iw = GTK_WIDGET (gtk_inspector_window_new (display));
+ iw = GTK_WIDGET (gtk_inspector_window_new (display));
return iw;
}
@@ -873,6 +873,10 @@ gtk_inspector_handle_event (GdkEvent *event)
if (iw == NULL)
return FALSE;
+ gtk_inspector_recorder_record_event (GTK_INSPECTOR_RECORDER (iw->widget_recorder),
+ gtk_get_event_widget (event),
+ event);
+
g_signal_emit (iw, signals[EVENT], 0, event, &handled);
return handled;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]