forked from AuroraMiddleware/gtk
inspector: Bring back debug updates
This time, they are implemented as an overlay, so they require a running inspector and can't be enabled via env variable anymore.
This commit is contained in:
parent
2699c15a99
commit
6de4c63a67
@ -42,6 +42,7 @@ G_DEFINE_TYPE (GtkHighlightOverlay, gtk_highlight_overlay, GTK_TYPE_INSPECTOR_OV
|
||||
static void
|
||||
gtk_highlight_overlay_snapshot (GtkInspectorOverlay *overlay,
|
||||
GtkSnapshot *snapshot,
|
||||
GskRenderNode *node,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkHighlightOverlay *self = GTK_HIGHLIGHT_OVERLAY (overlay);
|
||||
|
@ -34,6 +34,7 @@ G_DEFINE_ABSTRACT_TYPE (GtkInspectorOverlay, gtk_inspector_overlay, G_TYPE_OBJEC
|
||||
static void
|
||||
gtk_inspector_overlay_default_snapshot (GtkInspectorOverlay *self,
|
||||
GtkSnapshot *snapshot,
|
||||
GskRenderNode *node,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
}
|
||||
@ -58,9 +59,10 @@ gtk_inspector_overlay_init (GtkInspectorOverlay *self)
|
||||
void
|
||||
gtk_inspector_overlay_snapshot (GtkInspectorOverlay *self,
|
||||
GtkSnapshot *snapshot,
|
||||
GskRenderNode *node,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GTK_INSPECTOR_OVERLAY_GET_CLASS (self)->snapshot (self, snapshot, widget);
|
||||
GTK_INSPECTOR_OVERLAY_GET_CLASS (self)->snapshot (self, snapshot, node, widget);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -34,12 +34,14 @@ struct _GtkInspectorOverlayClass
|
||||
|
||||
void (* snapshot) (GtkInspectorOverlay *self,
|
||||
GtkSnapshot *snapshot,
|
||||
GskRenderNode *node,
|
||||
GtkWidget *widget);
|
||||
void (* queue_draw) (GtkInspectorOverlay *self);
|
||||
};
|
||||
|
||||
void gtk_inspector_overlay_snapshot (GtkInspectorOverlay *self,
|
||||
GtkSnapshot *snapshot,
|
||||
GskRenderNode *node,
|
||||
GtkWidget *widget);
|
||||
void gtk_inspector_overlay_queue_draw (GtkInspectorOverlay *self);
|
||||
|
||||
|
@ -35,6 +35,7 @@ inspector_sources = files(
|
||||
'statistics.c',
|
||||
'strv-editor.c',
|
||||
'treewalk.c',
|
||||
'updatesoverlay.c',
|
||||
'visual.c',
|
||||
'window.c',
|
||||
)
|
||||
|
281
gtk/inspector/updatesoverlay.c
Normal file
281
gtk/inspector/updatesoverlay.c
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* 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.1 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "updatesoverlay.h"
|
||||
|
||||
#include "gtkintl.h"
|
||||
#include "gtkwidget.h"
|
||||
|
||||
#include "gsk/gskrendernodeprivate.h"
|
||||
|
||||
/* duration before we start fading in us */
|
||||
#define GDK_DRAW_REGION_MIN_DURATION 50 * 1000
|
||||
/* duration when fade is finished in us */
|
||||
#define GDK_DRAW_REGION_MAX_DURATION 200 * 1000
|
||||
|
||||
typedef struct {
|
||||
gint64 timestamp;
|
||||
cairo_region_t *region;
|
||||
} GtkUpdate;
|
||||
|
||||
typedef struct {
|
||||
GQueue *updates;
|
||||
GskRenderNode *last;
|
||||
GtkWidget *widget;
|
||||
guint tick_callback;
|
||||
gulong unmap_callback;
|
||||
} GtkWidgetUpdates;
|
||||
|
||||
struct _GtkUpdatesOverlay
|
||||
{
|
||||
GtkInspectorOverlay parent_instance;
|
||||
|
||||
GHashTable *toplevels; /* widget => GtkWidgetUpdates */
|
||||
};
|
||||
|
||||
struct _GtkUpdatesOverlayClass
|
||||
{
|
||||
GtkInspectorOverlayClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkUpdatesOverlay, gtk_updates_overlay, GTK_TYPE_INSPECTOR_OVERLAY)
|
||||
|
||||
static void
|
||||
gtk_update_free (gpointer data)
|
||||
{
|
||||
GtkUpdate *region = data;
|
||||
|
||||
cairo_region_destroy (region->region);
|
||||
g_slice_free (GtkUpdate, region);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_widget_updates_release_widget (GtkWidgetUpdates *updates)
|
||||
{
|
||||
g_assert (updates->widget);
|
||||
g_signal_handler_disconnect (updates->widget, updates->unmap_callback);
|
||||
if (updates->tick_callback)
|
||||
gtk_widget_remove_tick_callback (updates->widget, updates->tick_callback);
|
||||
updates->tick_callback = 0;
|
||||
updates->widget = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_widget_updates_free (gpointer data)
|
||||
{
|
||||
GtkWidgetUpdates *updates = data;
|
||||
|
||||
g_queue_free_full (updates->updates, gtk_update_free);
|
||||
g_clear_pointer (&updates->last, gsk_render_node_unref);
|
||||
if (updates->widget)
|
||||
gtk_widget_updates_release_widget (updates);
|
||||
|
||||
g_slice_free (GtkWidgetUpdates, updates);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_widget_updates_tick (GtkWidget *widget,
|
||||
GdkFrameClock *clock,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidgetUpdates *updates = data;
|
||||
GtkUpdate *draw;
|
||||
gint64 now;
|
||||
|
||||
now = gdk_frame_clock_get_frame_time (clock);
|
||||
|
||||
for (draw = g_queue_pop_tail (updates->updates);
|
||||
draw != NULL && (now - draw->timestamp >= GDK_DRAW_REGION_MAX_DURATION);
|
||||
draw = g_queue_pop_tail (updates->updates))
|
||||
{
|
||||
gtk_update_free (draw);
|
||||
}
|
||||
|
||||
gdk_surface_queue_expose (gtk_widget_get_surface (widget));
|
||||
if (draw)
|
||||
{
|
||||
g_queue_push_tail (updates->updates, draw);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
updates->tick_callback = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidgetUpdates *
|
||||
gtk_update_overlay_lookup_for_widget (GtkUpdatesOverlay *self,
|
||||
GtkWidget *widget,
|
||||
gboolean create)
|
||||
{
|
||||
GtkWidgetUpdates *updates = g_hash_table_lookup (self->toplevels, widget);
|
||||
|
||||
if (updates || !create)
|
||||
return updates;
|
||||
|
||||
updates = g_slice_new0 (GtkWidgetUpdates);
|
||||
updates->updates = g_queue_new ();
|
||||
updates->widget = widget;
|
||||
updates->unmap_callback = g_signal_connect_swapped (widget, "unmap", G_CALLBACK (gtk_widget_updates_release_widget), updates);
|
||||
|
||||
g_hash_table_insert (self->toplevels, g_object_ref (widget), updates);
|
||||
return updates;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_widget_updates_add (GtkWidgetUpdates *updates,
|
||||
gint64 timestamp,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GtkUpdate *update;
|
||||
GList *l;
|
||||
|
||||
update = g_slice_new0 (GtkUpdate);
|
||||
update->timestamp = timestamp;
|
||||
update->region = region;
|
||||
for (l = g_queue_peek_head_link (updates->updates); l != NULL; l = l->next)
|
||||
{
|
||||
GtkUpdate *u = l->data;
|
||||
cairo_region_subtract (u->region, region);
|
||||
}
|
||||
g_queue_push_head (updates->updates, update);
|
||||
if (updates->tick_callback == 0)
|
||||
updates->tick_callback = gtk_widget_add_tick_callback (updates->widget, gtk_widget_updates_tick, updates, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_updates_overlay_snapshot (GtkInspectorOverlay *overlay,
|
||||
GtkSnapshot *snapshot,
|
||||
GskRenderNode *node,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkUpdatesOverlay *self = GTK_UPDATES_OVERLAY (overlay);
|
||||
GtkWidgetUpdates *updates;
|
||||
GtkUpdate *draw;
|
||||
gint64 now;
|
||||
GList *l;
|
||||
|
||||
updates = gtk_update_overlay_lookup_for_widget (self, widget, TRUE);
|
||||
now = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
|
||||
|
||||
if (updates->last)
|
||||
{
|
||||
cairo_region_t *diff;
|
||||
|
||||
diff = cairo_region_create ();
|
||||
gsk_render_node_diff (updates->last, node, diff);
|
||||
if (cairo_region_is_empty (diff))
|
||||
cairo_region_destroy (diff);
|
||||
else
|
||||
gtk_widget_updates_add (updates, now, diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_region_t *region;
|
||||
graphene_rect_t bounds;
|
||||
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
region = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
|
||||
floor (bounds.origin.x),
|
||||
floor (bounds.origin.y),
|
||||
ceil (bounds.origin.x + bounds.size.width) - floor (bounds.origin.x),
|
||||
ceil (bounds.origin.y + bounds.size.height) - floor (bounds.origin.y)
|
||||
});
|
||||
gtk_widget_updates_add (updates, now, region);
|
||||
}
|
||||
g_clear_pointer (&updates->last, gsk_render_node_unref);
|
||||
updates->last = gsk_render_node_ref (node);
|
||||
|
||||
for (l = g_queue_peek_head_link (updates->updates); l != NULL; l = l->next)
|
||||
{
|
||||
double progress;
|
||||
guint i;
|
||||
|
||||
draw = l->data;
|
||||
|
||||
if (now - draw->timestamp < GDK_DRAW_REGION_MIN_DURATION)
|
||||
progress = 0.0;
|
||||
else if (now - draw->timestamp < GDK_DRAW_REGION_MAX_DURATION)
|
||||
progress = (double) (now - draw->timestamp - GDK_DRAW_REGION_MIN_DURATION)
|
||||
/ (GDK_DRAW_REGION_MAX_DURATION - GDK_DRAW_REGION_MIN_DURATION);
|
||||
else
|
||||
break;
|
||||
|
||||
for (i = 0; i < cairo_region_num_rectangles (draw->region); i++)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
|
||||
cairo_region_get_rectangle (draw->region, i, &rect);
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
&(GdkRGBA) { 1, 0, 0, 0.4 * (1 - progress) },
|
||||
&GRAPHENE_RECT_INIT(rect.x, rect.y, rect.width, rect.height),
|
||||
"Debug Updates<%g>", progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_updates_overlay_queue_draw (GtkInspectorOverlay *overlay)
|
||||
{
|
||||
GtkUpdatesOverlay *self = GTK_UPDATES_OVERLAY (overlay);
|
||||
GHashTableIter iter;
|
||||
gpointer widget;
|
||||
|
||||
g_hash_table_iter_init (&iter, self->toplevels);
|
||||
while (g_hash_table_iter_next (&iter, &widget, NULL))
|
||||
gdk_surface_queue_expose (gtk_widget_get_surface (widget));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_updates_overlay_dispose (GObject *object)
|
||||
{
|
||||
GtkUpdatesOverlay *self = GTK_UPDATES_OVERLAY (object);
|
||||
|
||||
g_hash_table_unref (self->toplevels);
|
||||
|
||||
G_OBJECT_CLASS (gtk_updates_overlay_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_updates_overlay_class_init (GtkUpdatesOverlayClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GtkInspectorOverlayClass *overlay_class = GTK_INSPECTOR_OVERLAY_CLASS (klass);
|
||||
|
||||
overlay_class->snapshot = gtk_updates_overlay_snapshot;
|
||||
overlay_class->queue_draw = gtk_updates_overlay_queue_draw;
|
||||
|
||||
gobject_class->dispose = gtk_updates_overlay_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_updates_overlay_init (GtkUpdatesOverlay *self)
|
||||
{
|
||||
self->toplevels = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, gtk_widget_updates_free);
|
||||
}
|
||||
|
||||
GtkInspectorOverlay *
|
||||
gtk_updates_overlay_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_UPDATES_OVERLAY, NULL);
|
||||
}
|
||||
|
34
gtk/inspector/updatesoverlay.h
Normal file
34
gtk/inspector/updatesoverlay.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright © 2018 Benjamin Otte
|
||||
*
|
||||
* 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.1 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_UPDATES_OVERLAY_H__
|
||||
#define __GTK_UPDATES_OVERLAY_H__
|
||||
|
||||
#include "inspectoroverlay.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_UPDATES_OVERLAY (gtk_updates_overlay_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkUpdatesOverlay, gtk_updates_overlay, GTK, UPDATES_OVERLAY, GtkInspectorOverlay)
|
||||
|
||||
GtkInspectorOverlay * gtk_updates_overlay_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_UPDATES_OVERLAY_H__ */
|
@ -20,6 +20,9 @@
|
||||
|
||||
#include "visual.h"
|
||||
|
||||
#include "updatesoverlay.h"
|
||||
#include "window.h"
|
||||
|
||||
#include "gtkadjustment.h"
|
||||
#include "gtkbox.h"
|
||||
#include "gtkcomboboxtext.h"
|
||||
@ -65,6 +68,7 @@ struct _GtkInspectorVisualPrivate
|
||||
|
||||
GtkWidget *debug_box;
|
||||
GtkWidget *rendering_mode_combo;
|
||||
GtkWidget *updates_switch;
|
||||
GtkWidget *baselines_switch;
|
||||
GtkWidget *layout_switch;
|
||||
GtkWidget *touchscreen_switch;
|
||||
@ -75,6 +79,8 @@ struct _GtkInspectorVisualPrivate
|
||||
GtkWidget *texture_rectangle_switch;
|
||||
|
||||
GtkAdjustment *focus_adjustment;
|
||||
|
||||
GtkInspectorOverlay *updates_overlay;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorVisual, gtk_inspector_visual, GTK_TYPE_SCROLLED_WINDOW)
|
||||
@ -220,6 +226,41 @@ font_scale_entry_activated (GtkEntry *entry,
|
||||
update_font_scale (vis, factor, TRUE, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
updates_activate (GtkSwitch *sw,
|
||||
GParamSpec *pspec,
|
||||
GtkInspectorVisual *vis)
|
||||
{
|
||||
GtkInspectorVisualPrivate *priv = vis->priv;
|
||||
GtkInspectorWindow *iw;
|
||||
gboolean updates;
|
||||
|
||||
updates = gtk_switch_get_active (sw);
|
||||
iw = GTK_INSPECTOR_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (vis)));
|
||||
if (iw == NULL)
|
||||
return;
|
||||
|
||||
if (updates)
|
||||
{
|
||||
if (priv->updates_overlay == NULL)
|
||||
{
|
||||
priv->updates_overlay = gtk_updates_overlay_new ();
|
||||
gtk_inspector_window_add_overlay (iw, priv->updates_overlay);
|
||||
g_object_unref (priv->updates_overlay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->updates_overlay != NULL)
|
||||
{
|
||||
gtk_inspector_window_remove_overlay (iw, priv->updates_overlay);
|
||||
priv->updates_overlay = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
redraw_everything ();
|
||||
}
|
||||
|
||||
static void
|
||||
baselines_activate (GtkSwitch *sw)
|
||||
{
|
||||
@ -860,6 +901,7 @@ gtk_inspector_visual_class_init (GtkInspectorVisualClass *klass)
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/visual.ui");
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, rendering_mode_combo);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, updates_switch);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, direction_combo);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, baselines_switch);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, layout_switch);
|
||||
@ -885,6 +927,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, updates_activate);
|
||||
gtk_widget_class_bind_template_callback (widget_class, direction_changed);
|
||||
gtk_widget_class_bind_template_callback (widget_class, rendering_mode_changed);
|
||||
gtk_widget_class_bind_template_callback (widget_class, baselines_activate);
|
||||
|
@ -405,6 +405,33 @@
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<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="updates_label">
|
||||
<property name="label" translatable="yes">Show Graphic Updates</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="updates_switch">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="hexpand">1</property>
|
||||
<signal name="notify::active" handler="updates_activate"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
@ -625,6 +652,7 @@
|
||||
<widget name="hidpi_label"/>
|
||||
<widget name="animation_label"/>
|
||||
<widget name="rendering_mode_label"/>
|
||||
<widget name="updates_label"/>
|
||||
<widget name="baselines_label"/>
|
||||
<widget name="layout_label"/>
|
||||
<widget name="touchscreen_label"/>
|
||||
|
@ -427,7 +427,7 @@ gtk_inspector_prepare_render (GtkWidget *widget,
|
||||
|
||||
for (l = iw->overlays; l; l = l->next)
|
||||
{
|
||||
gtk_inspector_overlay_snapshot (l->data, snapshot, widget);
|
||||
gtk_inspector_overlay_snapshot (l->data, snapshot, node, widget);
|
||||
}
|
||||
|
||||
gsk_render_node_unref (node);
|
||||
|
Loading…
Reference in New Issue
Block a user