forked from AuroraMiddleware/gtk
Merge branch 'event-recorder' into 'main'
inspector: Tweaks to the recorder See merge request GNOME/gtk!4256
This commit is contained in:
commit
6ab1aff531
112
gdk/gdkevents.c
112
gdk/gdkevents.c
@ -19,7 +19,7 @@
|
||||
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@ -522,7 +522,8 @@ _gdk_event_queue_find_first (GdkDisplay *display)
|
||||
if (pending_motion)
|
||||
return pending_motion;
|
||||
|
||||
if (event->event_type == GDK_MOTION_NOTIFY && (event->flags & GDK_EVENT_FLUSHED) == 0)
|
||||
if ((event->event_type == GDK_MOTION_NOTIFY || event->event_type == GDK_SCROLL) &&
|
||||
(event->flags & GDK_EVENT_FLUSHED) == 0)
|
||||
pending_motion = tmp_list;
|
||||
else
|
||||
return tmp_list;
|
||||
@ -596,6 +597,9 @@ _gdk_event_unqueue (GdkDisplay *display)
|
||||
/*
|
||||
* If the last N events in the event queue are smooth scroll events
|
||||
* for the same surface and device, combine them into one.
|
||||
*
|
||||
* We give the remaining event a history with N items, and deltas
|
||||
* that are the sum over the history entries.
|
||||
*/
|
||||
void
|
||||
gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
|
||||
@ -605,7 +609,6 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
|
||||
GdkDevice *device = NULL;
|
||||
GdkEvent *last_event = NULL;
|
||||
GList *scrolls = NULL;
|
||||
double delta_x, delta_y;
|
||||
GArray *history = NULL;
|
||||
GdkTimeCoord hist;
|
||||
|
||||
@ -640,35 +643,42 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
|
||||
l = l->prev;
|
||||
}
|
||||
|
||||
delta_x = delta_y = 0;
|
||||
|
||||
while (scrolls && scrolls->next != NULL)
|
||||
{
|
||||
GdkEvent *event = scrolls->data;
|
||||
GList *next = scrolls->next;
|
||||
double dx, dy;
|
||||
gboolean inherited = FALSE;
|
||||
|
||||
if (!history && ((GdkScrollEvent *)event)->history)
|
||||
{
|
||||
history = ((GdkScrollEvent *)event)->history;
|
||||
((GdkScrollEvent *)event)->history = NULL;
|
||||
inherited = TRUE;
|
||||
}
|
||||
|
||||
if (!history)
|
||||
history = g_array_new (FALSE, TRUE, sizeof (GdkTimeCoord));
|
||||
|
||||
gdk_scroll_event_get_deltas (event, &dx, &dy);
|
||||
delta_x += dx;
|
||||
delta_y += dy;
|
||||
if (!inherited)
|
||||
{
|
||||
gdk_scroll_event_get_deltas (event, &dx, &dy);
|
||||
|
||||
memset (&hist, 0, sizeof (GdkTimeCoord));
|
||||
hist.time = gdk_event_get_time (event);
|
||||
hist.flags = GDK_AXIS_FLAG_DELTA_X | GDK_AXIS_FLAG_DELTA_Y;
|
||||
hist.axes[GDK_AXIS_DELTA_X] = dx;
|
||||
hist.axes[GDK_AXIS_DELTA_Y] = dy;
|
||||
memset (&hist, 0, sizeof (GdkTimeCoord));
|
||||
hist.time = gdk_event_get_time (event);
|
||||
hist.flags = GDK_AXIS_FLAG_DELTA_X | GDK_AXIS_FLAG_DELTA_Y;
|
||||
hist.axes[GDK_AXIS_DELTA_X] = dx;
|
||||
hist.axes[GDK_AXIS_DELTA_Y] = dy;
|
||||
|
||||
g_array_append_val (history, hist);
|
||||
g_array_append_val (history, hist);
|
||||
}
|
||||
|
||||
gdk_event_unref (event);
|
||||
g_queue_delete_link (&display->queued_events, scrolls);
|
||||
scrolls = next;
|
||||
}
|
||||
|
||||
if (scrolls)
|
||||
if (scrolls && history)
|
||||
{
|
||||
GdkEvent *old_event, *event;
|
||||
double dx, dy;
|
||||
@ -676,13 +686,29 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
|
||||
old_event = scrolls->data;
|
||||
|
||||
gdk_scroll_event_get_deltas (old_event, &dx, &dy);
|
||||
|
||||
memset (&hist, 0, sizeof (GdkTimeCoord));
|
||||
hist.time = gdk_event_get_time (old_event);
|
||||
hist.flags = GDK_AXIS_FLAG_DELTA_X | GDK_AXIS_FLAG_DELTA_Y;
|
||||
hist.axes[GDK_AXIS_DELTA_X] = dx;
|
||||
hist.axes[GDK_AXIS_DELTA_Y] = dy;
|
||||
g_array_append_val (history, hist);
|
||||
|
||||
dx = dy = 0;
|
||||
for (int i = 0; i < history->len; i++)
|
||||
{
|
||||
GdkTimeCoord *val = &g_array_index (history, GdkTimeCoord, i);
|
||||
dx += val->axes[GDK_AXIS_DELTA_X];
|
||||
dy += val->axes[GDK_AXIS_DELTA_Y];
|
||||
}
|
||||
|
||||
event = gdk_scroll_event_new (surface,
|
||||
device,
|
||||
gdk_event_get_device_tool (old_event),
|
||||
gdk_event_get_time (old_event),
|
||||
gdk_event_get_modifier_state (old_event),
|
||||
delta_x + dx,
|
||||
delta_y + dy,
|
||||
dx,
|
||||
dy,
|
||||
gdk_scroll_event_is_stop (old_event));
|
||||
|
||||
((GdkScrollEvent *)event)->history = history;
|
||||
@ -714,24 +740,41 @@ gdk_motion_event_push_history (GdkEvent *event,
|
||||
g_assert (GDK_IS_EVENT_TYPE (event, GDK_MOTION_NOTIFY));
|
||||
g_assert (GDK_IS_EVENT_TYPE (history_event, GDK_MOTION_NOTIFY));
|
||||
|
||||
if (!self->tool)
|
||||
return;
|
||||
if (G_UNLIKELY (!self->history))
|
||||
self->history = g_array_new (FALSE, TRUE, sizeof (GdkTimeCoord));
|
||||
|
||||
if (((GdkMotionEvent *)history_event)->history)
|
||||
{
|
||||
GArray *history = ((GdkMotionEvent *)history_event)->history;
|
||||
g_array_append_vals (self->history, history->data, history->len);
|
||||
}
|
||||
|
||||
tool = gdk_event_get_device_tool (history_event);
|
||||
|
||||
memset (&hist, 0, sizeof (GdkTimeCoord));
|
||||
hist.time = gdk_event_get_time (history_event);
|
||||
hist.flags = gdk_device_tool_get_axes (tool);
|
||||
|
||||
for (i = GDK_AXIS_X; i < GDK_AXIS_LAST; i++)
|
||||
gdk_event_get_axis (history_event, i, &hist.axes[i]);
|
||||
|
||||
if (G_UNLIKELY (!self->history))
|
||||
self->history = g_array_new (FALSE, TRUE, sizeof (GdkTimeCoord));
|
||||
if (tool)
|
||||
{
|
||||
hist.flags = gdk_device_tool_get_axes (tool);
|
||||
for (i = GDK_AXIS_X; i < GDK_AXIS_LAST; i++)
|
||||
gdk_event_get_axis (history_event, i, &hist.axes[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
hist.flags = GDK_AXIS_FLAG_X | GDK_AXIS_FLAG_Y;
|
||||
gdk_event_get_position (history_event, &hist.axes[GDK_AXIS_X], &hist.axes[GDK_AXIS_Y]);
|
||||
}
|
||||
|
||||
g_array_append_val (self->history, hist);
|
||||
}
|
||||
|
||||
/* If the last N events in the event queue are motion notify
|
||||
* events for the same surface, drop all but the last.
|
||||
*
|
||||
* If a button is held down or the device has a tool, then
|
||||
* we give the remaining events a history containing the N-1
|
||||
* dropped events.
|
||||
*/
|
||||
void
|
||||
_gdk_event_queue_handle_motion_compression (GdkDisplay *display)
|
||||
{
|
||||
@ -741,9 +784,6 @@ _gdk_event_queue_handle_motion_compression (GdkDisplay *display)
|
||||
GdkDevice *pending_motion_device = NULL;
|
||||
GdkEvent *last_motion = NULL;
|
||||
|
||||
/* If the last N events in the event queue are motion notify
|
||||
* events for the same surface, drop all but the last */
|
||||
|
||||
tmp_list = g_queue_peek_tail_link (&display->queued_events);
|
||||
|
||||
while (tmp_list)
|
||||
@ -780,12 +820,11 @@ _gdk_event_queue_handle_motion_compression (GdkDisplay *display)
|
||||
|
||||
if (last_motion != NULL)
|
||||
{
|
||||
GdkModifierType state = gdk_event_get_modifier_state (last_motion);
|
||||
|
||||
if (state &
|
||||
(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
|
||||
GDK_BUTTON4_MASK | GDK_BUTTON5_MASK))
|
||||
gdk_motion_event_push_history (last_motion, pending_motions->data);
|
||||
if ((gdk_event_get_modifier_state (last_motion) &
|
||||
(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK |
|
||||
GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)) ||
|
||||
gdk_event_get_device_tool (last_motion) != NULL)
|
||||
gdk_motion_event_push_history (last_motion, pending_motions->data);
|
||||
}
|
||||
|
||||
gdk_event_unref (pending_motions->data);
|
||||
@ -2907,7 +2946,8 @@ gdk_motion_event_new (GdkSurface *surface,
|
||||
* to the application because they occurred in the same frame as @event.
|
||||
*
|
||||
* Note that only motion and scroll events record history, and motion
|
||||
* events do it only if one of the mouse buttons is down.
|
||||
* events do it only if one of the mouse buttons is down, or the device
|
||||
* has a tool.
|
||||
*
|
||||
* Returns: (transfer container) (array length=out_n_coords) (nullable): an
|
||||
* array of time and coordinates
|
||||
|
@ -209,7 +209,7 @@ struct _GdkTouchEvent
|
||||
* @pointer_emulated: whether the scroll event was the result of
|
||||
* a pointer emulation
|
||||
* @tool: a `GdkDeviceTool`
|
||||
* @history: (element-type GdkScrollHistory): array of times and deltas
|
||||
* @history: (element-type GdkTimeCoord): array of times and deltas
|
||||
* for other scroll events that were compressed before delivering the
|
||||
* current event
|
||||
*
|
||||
@ -233,7 +233,7 @@ struct _GdkScrollEvent
|
||||
gboolean pointer_emulated;
|
||||
gboolean is_stop;
|
||||
GdkDeviceTool *tool;
|
||||
GArray *history; /* <GdkScrollHistory> */
|
||||
GArray *history; /* <GdkTimeCoord> */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -181,7 +181,7 @@ init_formats (GtkInspectorClipboard *self,
|
||||
gtk_list_box_remove (list, GTK_WIDGET (row));
|
||||
|
||||
formats = gdk_clipboard_get_formats (clipboard);
|
||||
|
||||
|
||||
gtypes = gdk_content_formats_get_gtypes (formats, &n);
|
||||
for (i = 0; i < n; i++)
|
||||
add_content_type_row (self, list, g_type_name (gtypes[i]), clipboard, G_CALLBACK (load_gtype), GSIZE_TO_POINTER (gtypes[i]));
|
||||
@ -235,7 +235,6 @@ primary_notify (GdkClipboard *clipboard,
|
||||
init_formats (self, GTK_LIST_BOX (self->primary_formats), clipboard);
|
||||
}
|
||||
|
||||
g_print ("%s: %s\n", pspec->name, gdk_content_formats_to_string (gdk_clipboard_get_formats (clipboard)));
|
||||
init_info (self, GTK_LABEL (self->primary_info), clipboard);
|
||||
}
|
||||
|
||||
|
69
gtk/inspector/eventrecording.c
Normal file
69
gtk/inspector/eventrecording.c
Normal file
@ -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:
|
64
gtk/inspector/eventrecording.h
Normal file
64
gtk/inspector/eventrecording.h
Normal file
@ -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:
|
@ -9,6 +9,7 @@ inspector_sources = files(
|
||||
'controllers.c',
|
||||
'css-editor.c',
|
||||
'css-node-tree.c',
|
||||
'eventrecording.c',
|
||||
'focusoverlay.c',
|
||||
'fpsoverlay.c',
|
||||
'general.c',
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <gtk/gtktreelistmodel.h>
|
||||
#include <gtk/gtktreemodel.h>
|
||||
#include <gtk/gtktreeview.h>
|
||||
#include <gtk/gtkstack.h>
|
||||
#include <gsk/gskrendererprivate.h>
|
||||
#include <gsk/gskrendernodeprivate.h>
|
||||
#include <gsk/gskroundedrectprivate.h>
|
||||
@ -53,6 +54,7 @@
|
||||
#include "recording.h"
|
||||
#include "renderrecording.h"
|
||||
#include "startrecording.h"
|
||||
#include "eventrecording.h"
|
||||
|
||||
struct _GtkInspectorRecorder
|
||||
{
|
||||
@ -70,9 +72,14 @@ struct _GtkInspectorRecorder
|
||||
GtkWidget *render_node_save_button;
|
||||
GtkWidget *render_node_clip_button;
|
||||
GtkWidget *node_property_tree;
|
||||
GtkWidget *recording_data_stack;
|
||||
GtkTreeModel *render_node_properties;
|
||||
GtkTreeModel *event_properties;
|
||||
GtkWidget *event_property_tree;
|
||||
GtkWidget *event_view;
|
||||
|
||||
GtkInspectorRecording *recording; /* start recording if recording or NULL if not */
|
||||
gint64 start_time;
|
||||
|
||||
gboolean debug_nodes;
|
||||
};
|
||||
@ -424,6 +431,75 @@ 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);
|
||||
|
||||
if (strcmp (gtk_stack_get_visible_child_name (GTK_STACK (recorder->recording_data_stack)), "frame_data") == 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_picture_set_paintable (GTK_PICTURE (recorder->event_view), paintable);
|
||||
}
|
||||
|
||||
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 populate_event_properties (GtkListStore *store,
|
||||
GdkEvent *event);
|
||||
|
||||
static void
|
||||
recording_selected (GtkSingleSelection *selection,
|
||||
GParamSpec *pspec,
|
||||
@ -432,29 +508,51 @@ recording_selected (GtkSingleSelection *selection,
|
||||
GtkInspectorRecording *recording;
|
||||
|
||||
if (recorder->recordings == NULL)
|
||||
return;
|
||||
{
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (recorder->recording_data_stack), "no_data");
|
||||
return;
|
||||
}
|
||||
|
||||
recording = gtk_single_selection_get_selected_item (selection);
|
||||
|
||||
if (GTK_INSPECTOR_IS_RENDER_RECORDING (recording))
|
||||
{
|
||||
graphene_rect_t bounds;
|
||||
GskRenderNode *node;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (recorder->recording_data_stack), "frame_data");
|
||||
|
||||
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);
|
||||
show_render_node (recorder, node);
|
||||
}
|
||||
else if (GTK_INSPECTOR_IS_EVENT_RECORDING (recording))
|
||||
{
|
||||
GdkEvent *event;
|
||||
|
||||
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);
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (recorder->recording_data_stack), "event_data");
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
populate_event_properties (GTK_LIST_STORE (recorder->event_properties), event);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (recorder->recording_data_stack), "no_data");
|
||||
|
||||
gtk_picture_set_paintable (GTK_PICTURE (recorder->render_node_view), NULL);
|
||||
g_list_store_remove_all (recorder->render_node_root_model);
|
||||
}
|
||||
@ -1161,6 +1259,227 @@ populate_render_node_properties (GtkListStore *store,
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
event_type_name (GdkEventType type)
|
||||
{
|
||||
const char *event_name[] = {
|
||||
"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_name[type];
|
||||
}
|
||||
|
||||
static const char *
|
||||
scroll_direction_name (GdkScrollDirection dir)
|
||||
{
|
||||
const char *scroll_dir[] = {
|
||||
"Up", "Down", "Left", "Right", "Smooth"
|
||||
};
|
||||
return scroll_dir[dir];
|
||||
}
|
||||
|
||||
static char *
|
||||
modifier_names (GdkModifierType state)
|
||||
{
|
||||
struct {
|
||||
const char *name;
|
||||
int mask;
|
||||
} mods[] = {
|
||||
{ "Shift", GDK_SHIFT_MASK },
|
||||
{ "Lock", GDK_LOCK_MASK },
|
||||
{ "Control", GDK_CONTROL_MASK },
|
||||
{ "Alt", GDK_ALT_MASK },
|
||||
{ "Button1", GDK_BUTTON1_MASK },
|
||||
{ "Button2", GDK_BUTTON2_MASK },
|
||||
{ "Button3", GDK_BUTTON3_MASK },
|
||||
{ "Button4", GDK_BUTTON4_MASK },
|
||||
{ "Button5", GDK_BUTTON5_MASK },
|
||||
{ "Super", GDK_SUPER_MASK },
|
||||
{ "Hyper", GDK_HYPER_MASK },
|
||||
{ "Meta", GDK_META_MASK },
|
||||
};
|
||||
GString *s;
|
||||
|
||||
s = g_string_new ("");
|
||||
|
||||
for (int i = 0; i < G_N_ELEMENTS (mods); i++)
|
||||
{
|
||||
if (state & mods[i].mask)
|
||||
{
|
||||
if (s->len > 0)
|
||||
g_string_append (s, " ");
|
||||
g_string_append (s, mods[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
return g_string_free (s, FALSE);
|
||||
}
|
||||
|
||||
static char *
|
||||
key_event_string (GdkEvent *event)
|
||||
{
|
||||
guint keyval;
|
||||
gunichar c;
|
||||
char buf[5] = { 0, };
|
||||
|
||||
keyval = gdk_key_event_get_keyval (event);
|
||||
c = gdk_keyval_to_unicode (keyval);
|
||||
if (c)
|
||||
{
|
||||
g_unichar_to_utf8 (c, buf);
|
||||
return g_strdup (buf);
|
||||
}
|
||||
|
||||
return g_strdup (gdk_keyval_name (keyval));
|
||||
}
|
||||
|
||||
static void
|
||||
populate_event_properties (GtkListStore *store,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GdkEventType type;
|
||||
GdkDevice *device;
|
||||
double x, y;
|
||||
char *tmp;
|
||||
GdkModifierType state;
|
||||
|
||||
gtk_list_store_clear (store);
|
||||
|
||||
type = gdk_event_get_event_type (event);
|
||||
|
||||
add_text_row (store, "Type", event_type_name (type));
|
||||
add_int_row (store, "Timestamp", gdk_event_get_time (event));
|
||||
|
||||
device = gdk_event_get_device (event);
|
||||
if (device)
|
||||
add_text_row (store, "Device", gdk_device_get_name (device));
|
||||
|
||||
if (gdk_event_get_position (event, &x, &y))
|
||||
{
|
||||
tmp = g_strdup_printf ("%.2f %.2f", x, y);
|
||||
add_text_row (store, "Position", tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
|
||||
state = gdk_event_get_modifier_state (event);
|
||||
if (state != 0)
|
||||
{
|
||||
tmp = modifier_names (state);
|
||||
add_text_row (store, "State", tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
|
||||
switch ((int)type)
|
||||
{
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_BUTTON_RELEASE:
|
||||
add_int_row (store, "Button", gdk_button_event_get_button (event));
|
||||
break;
|
||||
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
add_int_row (store, "Keycode", gdk_key_event_get_keycode (event));
|
||||
add_int_row (store, "Keyval", gdk_key_event_get_keyval (event));
|
||||
tmp = key_event_string (event);
|
||||
add_text_row (store, "Key", tmp);
|
||||
g_free (tmp);
|
||||
add_int_row (store, "Layout", gdk_key_event_get_layout (event));
|
||||
add_int_row (store, "Level", gdk_key_event_get_level (event));
|
||||
add_boolean_row (store, "Is Modifier", gdk_key_event_is_modifier (event));
|
||||
break;
|
||||
|
||||
case GDK_SCROLL:
|
||||
if (gdk_scroll_event_get_direction (event) == GDK_SCROLL_SMOOTH)
|
||||
{
|
||||
gdk_scroll_event_get_deltas (event, &x, &y);
|
||||
tmp = g_strdup_printf ("%.2f %.2f", x, y);
|
||||
add_text_row (store, "Delta", tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_text_row (store, "Direction", scroll_direction_name (gdk_scroll_event_get_direction (event)));
|
||||
}
|
||||
add_boolean_row (store, "Is Stop", gdk_scroll_event_is_stop (event));
|
||||
break;
|
||||
|
||||
case GDK_FOCUS_CHANGE:
|
||||
add_text_row (store, "Direction", gdk_focus_event_get_in (event) ? "In" : "Out");
|
||||
break;
|
||||
|
||||
case GDK_ENTER_NOTIFY:
|
||||
case GDK_LEAVE_NOTIFY:
|
||||
add_int_row (store, "Mode", gdk_crossing_event_get_mode (event));
|
||||
add_int_row (store, "Detail", gdk_crossing_event_get_detail (event));
|
||||
add_boolean_row (store, "Is Focus", gdk_crossing_event_get_focus (event));
|
||||
break;
|
||||
|
||||
case GDK_GRAB_BROKEN:
|
||||
add_boolean_row (store, "Implicit", gdk_grab_broken_event_get_implicit (event));
|
||||
break;
|
||||
|
||||
default:
|
||||
/* FIXME */
|
||||
;
|
||||
}
|
||||
|
||||
if (type == GDK_MOTION_NOTIFY || type == GDK_SCROLL)
|
||||
{
|
||||
GdkTimeCoord *history;
|
||||
guint n_coords;
|
||||
|
||||
history = gdk_event_get_history (event, &n_coords);
|
||||
if (history)
|
||||
{
|
||||
GString *s;
|
||||
|
||||
s = g_string_new ("");
|
||||
|
||||
for (int i = 0; i < n_coords; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
g_string_append (s, "\n");
|
||||
if ((history[i].flags & (GDK_AXIS_FLAG_X|GDK_AXIS_FLAG_Y)) == (GDK_AXIS_FLAG_X|GDK_AXIS_FLAG_Y))
|
||||
g_string_append_printf (s, "%d: %.2f %.2f", history[i].time, history[i].axes[GDK_AXIS_X], history[i].axes[GDK_AXIS_Y]);
|
||||
if ((history[i].flags & (GDK_AXIS_FLAG_DELTA_X|GDK_AXIS_FLAG_DELTA_Y)) == (GDK_AXIS_FLAG_DELTA_X|GDK_AXIS_FLAG_DELTA_Y))
|
||||
g_string_append_printf (s, "%d: %.2f %.2f", history[i].time, history[i].axes[GDK_AXIS_DELTA_X], history[i].axes[GDK_AXIS_DELTA_Y]);
|
||||
}
|
||||
|
||||
add_text_row (store, "History", s->str);
|
||||
|
||||
g_string_free (s, TRUE);
|
||||
g_free (history);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
get_selected_node (GtkInspectorRecorder *recorder)
|
||||
{
|
||||
@ -1324,27 +1643,16 @@ setup_widget_for_recording (GtkListItemFactory *factory,
|
||||
GtkListItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget, *hbox, *label, *button;
|
||||
GtkWidget *widget, *label;
|
||||
|
||||
widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_append (GTK_BOX (widget), hbox);
|
||||
widget = 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_label_set_use_markup (GTK_LABEL (label), TRUE);
|
||||
gtk_box_append (GTK_BOX (hbox), label);
|
||||
|
||||
button = gtk_toggle_button_new ();
|
||||
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
|
||||
gtk_button_set_icon_name (GTK_BUTTON (button), "view-more-symbolic");
|
||||
gtk_box_append (GTK_BOX (hbox), button);
|
||||
|
||||
label = gtk_label_new ("");
|
||||
gtk_widget_hide (label);
|
||||
gtk_box_append (GTK_BOX (widget), label);
|
||||
|
||||
g_object_bind_property (button, "active", label, "visible", 0);
|
||||
label = gtk_label_new ("");
|
||||
gtk_box_append (GTK_BOX (widget), label);
|
||||
|
||||
gtk_widget_set_margin_start (widget, 6);
|
||||
gtk_widget_set_margin_end (widget, 6);
|
||||
@ -1354,32 +1662,116 @@ setup_widget_for_recording (GtkListItemFactory *factory,
|
||||
gtk_list_item_set_child (item, widget);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_event_summary (GdkEvent *event)
|
||||
{
|
||||
double x, y;
|
||||
int type;
|
||||
const char *name;
|
||||
|
||||
gdk_event_get_position (event, &x, &y);
|
||||
type = gdk_event_get_event_type (event);
|
||||
name = event_type_name (type);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GDK_ENTER_NOTIFY:
|
||||
case GDK_LEAVE_NOTIFY:
|
||||
case GDK_MOTION_NOTIFY:
|
||||
case GDK_DRAG_ENTER:
|
||||
case GDK_DRAG_LEAVE:
|
||||
case GDK_DRAG_MOTION:
|
||||
case GDK_DROP_START:
|
||||
case GDK_TOUCH_BEGIN:
|
||||
case GDK_TOUCH_UPDATE:
|
||||
case GDK_TOUCH_END:
|
||||
case GDK_TOUCH_CANCEL:
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_BUTTON_RELEASE:
|
||||
return g_strdup_printf ("%s (%.2f %.2f)", name, x, y);
|
||||
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
{
|
||||
char *tmp, *ret;
|
||||
tmp = key_event_string (event);
|
||||
ret = g_strdup_printf ("%s %s\n", name, tmp);
|
||||
g_free (tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
case GDK_FOCUS_CHANGE:
|
||||
return g_strdup_printf ("%s %s", name, gdk_focus_event_get_in (event) ? "In" : "Out");
|
||||
|
||||
case GDK_GRAB_BROKEN:
|
||||
case GDK_PROXIMITY_IN:
|
||||
case GDK_PROXIMITY_OUT:
|
||||
case GDK_PAD_BUTTON_PRESS:
|
||||
case GDK_PAD_BUTTON_RELEASE:
|
||||
case GDK_PAD_RING:
|
||||
case GDK_PAD_STRIP:
|
||||
case GDK_PAD_GROUP_MODE:
|
||||
return g_strdup_printf ("%s", name);
|
||||
|
||||
case GDK_SCROLL:
|
||||
if (gdk_scroll_event_get_direction (event) == GDK_SCROLL_SMOOTH)
|
||||
{
|
||||
gdk_scroll_event_get_deltas (event, &x, &y);
|
||||
return g_strdup_printf ("%s %.2f %.2f", name, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_strdup_printf ("%s %s", name, scroll_direction_name (gdk_scroll_event_get_direction (event)));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bind_widget_for_recording (GtkListItemFactory *factory,
|
||||
GtkListItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GtkInspectorRecording *recording = gtk_list_item_get_item (item);
|
||||
GtkWidget *widget, *hbox, *label, *button, *label2;
|
||||
GtkWidget *widget, *label, *label2;
|
||||
char *text;
|
||||
|
||||
widget = gtk_list_item_get_child (item);
|
||||
hbox = gtk_widget_get_first_child (widget);
|
||||
label = gtk_widget_get_first_child (hbox);
|
||||
button = gtk_widget_get_next_sibling (label);
|
||||
label2 = gtk_widget_get_next_sibling (hbox);
|
||||
label = gtk_widget_get_first_child (widget);
|
||||
label2 = gtk_widget_get_next_sibling (label);
|
||||
|
||||
gtk_label_set_use_markup (GTK_LABEL (label), 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)));
|
||||
gtk_label_set_label (GTK_LABEL (label), "Frame");
|
||||
gtk_label_set_use_markup (GTK_LABEL (label), FALSE);
|
||||
|
||||
text = g_strdup_printf ("%.3f", gtk_inspector_recording_get_timestamp (recording) / 1000.0);
|
||||
gtk_label_set_label (GTK_LABEL (label2), text);
|
||||
g_free (text);
|
||||
}
|
||||
else if (GTK_INSPECTOR_IS_EVENT_RECORDING (recording))
|
||||
{
|
||||
GdkEvent *event = gtk_inspector_event_recording_get_event (GTK_INSPECTOR_EVENT_RECORDING (recording));
|
||||
|
||||
text = get_event_summary (event);
|
||||
gtk_label_set_label (GTK_LABEL (label), text);
|
||||
g_free (text);
|
||||
|
||||
text = g_strdup_printf ("%.3f", gtk_inspector_recording_get_timestamp (recording) / 1000.0);
|
||||
gtk_label_set_label (GTK_LABEL (label2), text);
|
||||
g_free (text);
|
||||
}
|
||||
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_use_markup (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_label (GTK_LABEL (label2), "");
|
||||
}
|
||||
}
|
||||
@ -1521,6 +1913,9 @@ gtk_inspector_recorder_class_init (GtkInspectorRecorderClass *klass)
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorRecorder, render_node_save_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorRecorder, render_node_clip_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorRecorder, node_property_tree);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorRecorder, recording_data_stack);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorRecorder, event_view);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorRecorder, event_property_tree);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, recordings_clear_all);
|
||||
gtk_widget_class_bind_template_callback (widget_class, recording_selected);
|
||||
@ -1540,8 +1935,8 @@ gtk_inspector_recorder_init (GtkInspectorRecorder *recorder)
|
||||
gtk_widget_init_template (GTK_WIDGET (recorder));
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_widget_for_recording), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_widget_for_recording), NULL);
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_widget_for_recording), recorder);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_widget_for_recording), recorder);
|
||||
gtk_list_view_set_factory (GTK_LIST_VIEW (recorder->recordings_list), factory);
|
||||
g_object_unref (factory);
|
||||
|
||||
@ -1566,13 +1961,16 @@ gtk_inspector_recorder_init (GtkInspectorRecorder *recorder)
|
||||
recorder->render_node_properties = GTK_TREE_MODEL (gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, GDK_TYPE_TEXTURE));
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (recorder->node_property_tree), recorder->render_node_properties);
|
||||
g_object_unref (recorder->render_node_properties);
|
||||
|
||||
recorder->event_properties = GTK_TREE_MODEL (gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, GDK_TYPE_TEXTURE));
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (recorder->event_property_tree), recorder->event_properties);
|
||||
g_object_unref (recorder->event_properties);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1586,6 +1984,7 @@ gtk_inspector_recorder_set_recording (GtkInspectorRecorder *recorder,
|
||||
if (recording)
|
||||
{
|
||||
recorder->recording = gtk_inspector_start_recording_new ();
|
||||
recorder->start_time = 0;
|
||||
gtk_inspector_recorder_add_recording (recorder, recorder->recording);
|
||||
}
|
||||
else
|
||||
@ -1612,13 +2011,25 @@ gtk_inspector_recorder_record_render (GtkInspectorRecorder *recorder,
|
||||
{
|
||||
GtkInspectorRecording *recording;
|
||||
GdkFrameClock *frame_clock;
|
||||
gint64 frame_time;
|
||||
|
||||
if (!gtk_inspector_recorder_is_recording (recorder))
|
||||
return;
|
||||
|
||||
frame_clock = gtk_widget_get_frame_clock (widget);
|
||||
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
|
||||
recording = gtk_inspector_render_recording_new (gdk_frame_clock_get_frame_time (frame_clock),
|
||||
if (recorder->start_time == 0)
|
||||
{
|
||||
recorder->start_time = frame_time;
|
||||
frame_time = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_time = frame_time - recorder->start_time;
|
||||
}
|
||||
|
||||
recording = gtk_inspector_render_recording_new (frame_time,
|
||||
gsk_renderer_get_profiler (renderer),
|
||||
&(GdkRectangle) { 0, 0,
|
||||
gdk_surface_get_width (surface),
|
||||
@ -1629,6 +2040,36 @@ 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;
|
||||
gint64 frame_time;
|
||||
|
||||
if (!gtk_inspector_recorder_is_recording (recorder))
|
||||
return;
|
||||
|
||||
frame_clock = gtk_widget_get_frame_clock (widget);
|
||||
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
|
||||
if (recorder->start_time == 0)
|
||||
{
|
||||
recorder->start_time = frame_time;
|
||||
frame_time = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_time = frame_time - recorder->start_time;
|
||||
}
|
||||
|
||||
recording = gtk_inspector_event_recording_new (frame_time, event);
|
||||
gtk_inspector_recorder_add_recording (recorder, recording);
|
||||
g_object_unref (recording);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_inspector_recorder_set_debug_nodes (GtkInspectorRecorder *recorder,
|
||||
gboolean debug_nodes)
|
||||
|
@ -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_
|
||||
|
@ -86,76 +86,155 @@
|
||||
<object class="GtkSeparator"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="propagate-natural-width">1</property>
|
||||
<object class="GtkStack" id="recording_data_stack">
|
||||
<child>
|
||||
<object class="GtkListView" id="render_node_list">
|
||||
<property name="vexpand">1</property>
|
||||
<property name="hexpand">1</property>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">no_data</property>
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">No data.</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPaned" id="render_paned">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="position">300</property>
|
||||
<property name="wide-handle">1</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<child>
|
||||
<object class="GtkTreeView" id="node_property_tree">
|
||||
<property name="activate-on-single-click">1</property>
|
||||
<signal name="row-activated" handler="node_property_activated"/>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">frame_data</property>
|
||||
<property name="child">
|
||||
<object class="GtkPaned">
|
||||
<property name="position">400</property>
|
||||
<property name="wide-handle">1</property>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Property</property>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="propagate-natural-width">1</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="yalign">0</property>
|
||||
<object class="GtkListView" id="render_node_list">
|
||||
<property name="vexpand">1</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Value</property>
|
||||
<object class="GtkPaned" id="render_paned">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="position">200</property>
|
||||
<property name="wide-handle">1</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="yalign">0</property>
|
||||
<property name="wrap-mode">word</property>
|
||||
<property name="max-width-chars">50</property>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="propagate-natural-width">1</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="node_property_tree">
|
||||
<property name="activate-on-single-click">1</property>
|
||||
<signal name="row-activated" handler="node_property_activated"/>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Property</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Value</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="yalign">0</property>
|
||||
<property name="wrap-mode">word</property>
|
||||
<property name="max-width-chars">50</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCellRendererPixbuf">
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="visible">2</attribute>
|
||||
<attribute name="texture">3</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCellRendererPixbuf">
|
||||
<property name="xalign">0</property>
|
||||
<object class="GtkPicture" id="render_node_view">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="visible">2</attribute>
|
||||
<attribute name="texture">3</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPicture" id="render_node_view">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<object class="GtkStackPage">
|
||||
<property name="name">event_data</property>
|
||||
<property name="child">
|
||||
<object class="GtkPaned">
|
||||
<property name="position">400</property>
|
||||
<property name="wide-handle">1</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="propagate-natural-width">1</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="event_property_tree">
|
||||
<property name="activate-on-single-click">1</property>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Property</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="yalign">0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Value</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="yalign">0</property>
|
||||
<property name="wrap-mode">word</property>
|
||||
<property name="max-width-chars">50</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPicture" id="event_view">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@ -166,3 +245,4 @@
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user