Commit b4f52020 authored by Federico Mena Quintero's avatar Federico Mena Quintero Committed by Federico Mena Quintero

Update for the new API of the profiler.

2005-07-28  Federico Mena Quintero  <federico@ximian.com>

	* perf/README: Update for the new API of the profiler.

	* perf/gtkwidgetprofiler.[ch]: New files with a widget profiler
	object.  This is the old content of timers.[ch] turned into a nice
	object, with signals for creation and reporting.  The profiler
	needs to maintain some state when reusing the widget, so it's
	useful to turn it into a real object.

	Break down timing show_all into GTK_WIDGET_PROFILER_REPORT_MAP and
	GTK_WIDGET_PROFILER_REPORT_EXPOSE.

	* perf/main.c: Refactor to use GtkWidgetProfiler.

	* perf/appwindow.c (content_area_new): Make this just create a
	notebook, instead of a complex arrangement of panes.

	* perf/widgets.h: New header file for all the "create a widget"
	utility functions.

	* perf/treeview.c: New file.  Moved the tree view part from
	appwindow.c over to here; GtkTreeView really needs its own tests.
	(tree_view_new): Set the shadow type to IN.

	* perf/textview.c: Likewise moved over from appwindow.c, but for
	GtkTextView.
	(text_view_new): Set the shadow type to IN.

	* perf/Makefile.am (testperf_SOURCES): Add the new source files;
	remove appwindow.h and timers.[ch].

	* perf/timers.[ch]: Removed.

	* perf/appwindow.h: Removed.
parent 375cb32b
2005-07-28 Federico Mena Quintero <federico@ximian.com>
* perf/README: Update for the new API of the profiler.
* perf/gtkwidgetprofiler.[ch]: New files with a widget profiler
object. This is the old content of timers.[ch] turned into a nice
object, with signals for creation and reporting. The profiler
needs to maintain some state when reusing the widget, so it's
useful to turn it into a real object.
Break down timing show_all into GTK_WIDGET_PROFILER_REPORT_MAP and
GTK_WIDGET_PROFILER_REPORT_EXPOSE.
* perf/main.c: Refactor to use GtkWidgetProfiler.
* perf/appwindow.c (content_area_new): Make this just create a
notebook, instead of a complex arrangement of panes.
* perf/widgets.h: New header file for all the "create a widget"
utility functions.
* perf/treeview.c: New file. Moved the tree view part from
appwindow.c over to here; GtkTreeView really needs its own tests.
(tree_view_new): Set the shadow type to IN.
* perf/textview.c: Likewise moved over from appwindow.c, but for
GtkTextView.
(text_view_new): Set the shadow type to IN.
* perf/Makefile.am (testperf_SOURCES): Add the new source files;
remove appwindow.h and timers.[ch].
* perf/timers.[ch]: Removed.
* perf/appwindow.h: Removed.
2005-07-29 Tor Lillqvist <tml@novell.com>
* gdk/win32/gdkevents-win32.c: Remove ifdeffed out code relating
......
2005-07-28 Federico Mena Quintero <federico@ximian.com>
* perf/README: Update for the new API of the profiler.
* perf/gtkwidgetprofiler.[ch]: New files with a widget profiler
object. This is the old content of timers.[ch] turned into a nice
object, with signals for creation and reporting. The profiler
needs to maintain some state when reusing the widget, so it's
useful to turn it into a real object.
Break down timing show_all into GTK_WIDGET_PROFILER_REPORT_MAP and
GTK_WIDGET_PROFILER_REPORT_EXPOSE.
* perf/main.c: Refactor to use GtkWidgetProfiler.
* perf/appwindow.c (content_area_new): Make this just create a
notebook, instead of a complex arrangement of panes.
* perf/widgets.h: New header file for all the "create a widget"
utility functions.
* perf/treeview.c: New file. Moved the tree view part from
appwindow.c over to here; GtkTreeView really needs its own tests.
(tree_view_new): Set the shadow type to IN.
* perf/textview.c: Likewise moved over from appwindow.c, but for
GtkTextView.
(text_view_new): Set the shadow type to IN.
* perf/Makefile.am (testperf_SOURCES): Add the new source files;
remove appwindow.h and timers.[ch].
* perf/timers.[ch]: Removed.
* perf/appwindow.h: Removed.
2005-07-29 Tor Lillqvist <tml@novell.com>
* gdk/win32/gdkevents-win32.c: Remove ifdeffed out code relating
......
2005-07-28 Federico Mena Quintero <federico@ximian.com>
* perf/README: Update for the new API of the profiler.
* perf/gtkwidgetprofiler.[ch]: New files with a widget profiler
object. This is the old content of timers.[ch] turned into a nice
object, with signals for creation and reporting. The profiler
needs to maintain some state when reusing the widget, so it's
useful to turn it into a real object.
Break down timing show_all into GTK_WIDGET_PROFILER_REPORT_MAP and
GTK_WIDGET_PROFILER_REPORT_EXPOSE.
* perf/main.c: Refactor to use GtkWidgetProfiler.
* perf/appwindow.c (content_area_new): Make this just create a
notebook, instead of a complex arrangement of panes.
* perf/widgets.h: New header file for all the "create a widget"
utility functions.
* perf/treeview.c: New file. Moved the tree view part from
appwindow.c over to here; GtkTreeView really needs its own tests.
(tree_view_new): Set the shadow type to IN.
* perf/textview.c: Likewise moved over from appwindow.c, but for
GtkTextView.
(text_view_new): Set the shadow type to IN.
* perf/Makefile.am (testperf_SOURCES): Add the new source files;
remove appwindow.h and timers.[ch].
* perf/timers.[ch]: Removed.
* perf/appwindow.h: Removed.
2005-07-29 Tor Lillqvist <tml@novell.com>
* gdk/win32/gdkevents-win32.c: Remove ifdeffed out code relating
......
......@@ -28,12 +28,73 @@ testperf_DEPENDENCIES = $(TEST_DEPS)
testperf_LDADD = $(LDADDS)
testperf_SOURCES = \
appwindow.c \
appwindow.h \
main.c \
timers.c \
timers.h
EXTRA_DIST = \
README
testperf_SOURCES = \
appwindow.c \
gtkwidgetprofiler.c \
gtkwidgetprofiler.h \
main.c \
marshalers.c \
marshalers.h \
textview.c \
treeview.c \
typebuiltins.c \
typebuiltins.h \
widgets.h
BUILT_SOURCES = \
marshalers.c \
marshalers.h \
typebuiltins.c \
typebuiltins.h
stamp_files = \
stamp-marshalers.h \
stamp-typebuiltins.h
headers_with_enums = \
gtkwidgetprofiler.h
MAINTAINERCLEANFILES = $(BUILT_SOURCES) $(stamp_files)
marshalers.h: stamp-marshalers.h
@true
stamp-marshalers.h: @REBUILD@ marshalers.list
$(GLIB_GENMARSHAL) --prefix=_gtk_marshal $(srcdir)/marshalers.list --header >> xgen-gmlh \
&& (cmp -s xgen-gmlh marshalers.h || cp xgen-gmlh marshalers.h) \
&& rm -f xgen-gmlh \
&& echo timestamp > $(@F)
marshalers.c: @REBUILD@ marshalers.list
$(GLIB_GENMARSHAL) --prefix=_gtk_marshal $(srcdir)/marshalers.list --body >> xgen-gmlc \
&& cp xgen-gmlc marshalers.c \
&& rm -f xgen-gmlc
typebuiltins.h: stamp-typebuiltins.h
@true
stamp-typebuiltins.h: @REBUILD@ $(headers_with_enums) Makefile
( cd $(srcdir) && glib-mkenums \
--fhead "#ifndef __TYPE_BUILTINS_H__\n#define __TYPE_BUILTINS_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
--fprod "/* enumerations from \"@filename@\" */\n" \
--vhead "GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define GTK_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
--ftail "G_END_DECLS\n\n#endif /* __TYPE_BUILTINS_H__ */" \
$(headers_with_enums) ) >> xgen-gtbh \
&& (cmp -s xgen-gtbh typebuiltins.h || cp xgen-gtbh typebuiltins.h ) \
&& rm -f xgen-gtbh \
&& echo timestamp > $(@F)
typebuiltins.c: @REBUILD@ $(headers_with_enums) Makefile
( cd $(srcdir) && glib-mkenums \
--fhead "#include \"gtkwidgetprofiler.h\"" \
--ftail "#define __TYPE_BUILTINS_C__\n" \
--fprod "\n/* enumerations from \"@filename@\" */" \
--vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \
--vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
--vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \
$(headers_with_enums) ) > xgen-gtbc \
&& cp xgen-gtbc typebuiltins.c \
&& rm -f xgen-gtbc
EXTRA_DIST = \
README \
marshalers.list \
$(BUILT_SOURCES)
......@@ -6,63 +6,75 @@ performant does not only mean "paint widgets fast". It also means
things like the time needed to set up widgets, to map and draw a
window for the first time, and emitting/propagating signals.
The following is accurate as of 2005/07/26.
The following is accurate as of 2005/07/28.
Using the framework
-------------------
Right now the framework is very simple; it just has utility functions
to time widget creation, drawing, and destruction. To run such a
test, you use the functions in timers.h. You can call this:
to time widget creation, mapping, exposure, and destruction. To run
such a test, you use the GtkWidgetProfiler object in
gtkwidgetprofiler.h.
timer_time_widget (create_func, report_func, user_data);
The gtk_widget_profiler_profile_boot() function will emit the
"create-widget" signal so that you can create your widget for
testing. It will then take timings for the widget, and emit the
"report" signal as appropriate.
You must provide the create_funcn and report_func callbacks.
The "create-widget" signal:
The create_func:
The handler has this form:
This simply creates a toplevel window with some widgets inside it.
It is important that you do not show any of the widgets; the
framework will call gtk_widget_show_all() on the toplevel window
automatically at the right time.
GtkWidget *create_widget_callback (GtkWidgetProfiler *profiler,
gpointer user_data);
The report_func:
You need to create a widget in your handler, and return it. Do not
show the widget; the profiler will do that by itself at the right
time, and will actually complain if you show the widget.
This function will get called when timer_time_widget() reaches an
interesting point in the lifecycle of your widget. See timers.h and
the TimerReport enumeration; this is what gets passed as the
"report" argument to your report_func. Right now, your function
will be called three times for each call to timer_time_widget():
1. With report = TIMER_REPORT_WIDGET_CREATION. A timer gets
started right before timer_time_widget() calls create_func,
and it gets stopped when your create_func returns. This
measures the time it takes to set up a toplevel window (but
not show it).
The "report" signal:
2. With report = TIMER_REPORT_WIDGET_SHOW. A timer gets started
right before timer_time_widget() calls gtk_widget_show_all()
on your toplevel window, and it gets stopped when the window
has been fully shown and painted to the screen.
This function will get called when the profiler wants to report that
it finished timing an important stage in the lifecycle of your
widget. The handler has this form:
3. With report = TIMER_REPORT_WIDGET_DESTRUCTION. A timer gets
started right before timer_time_widget() calls
gtk_widget_destroy() on your toplevel window, and it gets
stopped when gtk_widget_destroy() returns.
void report_callback (GtkWidgetProfiler *profiler,
GtkWidgetProfilerReport report,
GtkWidget *widget,
gdouble elapsed,
gpointer user_data);
As a very basic example of using timer_time_widget(), you can use
something like this:
The "report" argument tells you what happened to your widget:
GTK_WIDGET_PROFILER_REPORT_CREATE. A timer gets started right
before the profiler emits the "create-widget" signal,, and it gets
stopped when your callback returns with the new widget. This
measures the time it takes to set up your widget, but not show it.
GTK_WIDGET_PROFILER_REPORT_MAP. A timer gets started right before
the profiler calls gtk_widget_show_all() on your widget, and it
gets stopped when the the widget has been mapped.
GTK_WIDGET_PROFILER_REPORT_EXPOSE. A timer gets started right before
the profiler starts waiting for GTK+ and the X server to finish
painting your widget, and it gets stopped when the widget is fully
painted to the screen.
GTK_WIDGET_PROFILER_REPORT_DESTROY. A timer gets started right
before the profiler calls gtk_widget_destroy() on your widget, and
it gets stopped when gtk_widget_destroy() returns.
As a very basic example of using GtkWidgetProfiler is this:
----------------------------------------------------------------------
#include <stdio.h>
#include <gtk/gtk.h>
#include "timers.h"
#define ITERS 20
#include "gtkwidgetprofiler.h"
static GtkWidget *
create_cb (gpointer data)
create_widget_cb (GtkWidgetProfiler *profiler, gpointer data)
{
GtkWidget *window;
......@@ -73,47 +85,66 @@ create_cb (gpointer data)
}
static void
report_cb (TimerReport report, gdouble elapsed, gpointer data)
report_cb (GtkWidgetProfiler *profiler, GtkWidgetProfilerReport report, GtkWidget *widget, gdouble elapsed, gpointer data)
{
const char *type;
switch (report) {
case TIMER_REPORT_WIDGET_CREATION:
case GTK_WIDGET_PROFILER_REPORT_CREATE:
type = "widget creation";
break;
case TIMER_REPORT_WIDGET_SHOW:
type = "widget show";
case GTK_WIDGET_PROFILER_REPORT_MAP:
type = "widget map";
break;
case TIMER_REPORT_WIDGET_DESTRUCTION:
case GTK_WIDGET_PROFILER_REPORT_EXPOSE:
type = "widget expose";
break;
case GTK_WIDGET_PROFILER_REPORT_DESTROY:
type = "widget destruction";
break;
default:
g_assert_not_reached ();
type = NULL;
}
fprintf (stderr, "%s: %g sec\n", type, elapsed);
if (report == GTK_WIDGET_PROFILER_REPORT_DESTROY)
fputs ("\n", stderr);
}
int
main (int argc, char **argv)
{
int i;
GtkWidgetProfiler *profiler;
gtk_init (&argc, &argv);
for (i = 0; i < ITERS; i++)
timer_time_widget (create_cb, report_cb, NULL);
profiler = gtk_widget_profiler_new ();
g_signal_connect (profiler, "create-widget",
G_CALLBACK (create_widget_cb), NULL);
g_signal_connect (profiler, "report",
G_CALLBACK (report_cb), NULL);
gtk_widget_profiler_set_num_iterations (profiler, 100);
gtk_widget_profiler_profile_boot (profiler);
return 0;
}
}
----------------------------------------------------------------------
Getting meaningful results
--------------------------
Getting times for widget creation/drawing/destruction is interesting,
but how do you actually find the places that need optimizing?
Getting times for widget creation/mapping/exposing/destruction is
interesting, but how do you actually find the places that need
optimizing?
Why, you run the tests under a profiler, of course.
......
......@@ -13,6 +13,8 @@
#include <string.h>
#include <gtk/gtk.h>
#include "widgets.h"
static void
quit_cb (GtkWidget *widget, gpointer data)
{
......@@ -150,230 +152,38 @@ toolbar_new (GtkUIManager *ui)
return gtk_ui_manager_get_widget (ui, "/MainToolbar");
}
struct row_data {
char *stock_id;
char *text1;
char *text2;
};
static struct row_data row_data[] = {
{ GTK_STOCK_NEW, "First", "Here bygynneth the Book of the tales of Caunterbury." },
{ GTK_STOCK_OPEN, "Second", "Whan that Aprille, with hise shoures soote," },
{ GTK_STOCK_ABOUT, "Third", "The droghte of March hath perced to the roote" },
{ GTK_STOCK_ADD, "Fourth", "And bathed every veyne in swich licour," },
{ GTK_STOCK_APPLY, "Fifth", "Of which vertu engendred is the flour;" },
{ GTK_STOCK_BOLD, "Sixth", "Whan Zephirus eek with his swete breeth" },
{ GTK_STOCK_CANCEL, "Seventh", "Inspired hath in every holt and heeth" },
{ GTK_STOCK_CDROM, "Eighth", "The tendre croppes, and the yonge sonne" },
{ GTK_STOCK_CLEAR, "Ninth", "Hath in the Ram his halfe cours yronne," },
{ GTK_STOCK_CLOSE, "Tenth", "And smale foweles maken melodye," },
{ GTK_STOCK_COLOR_PICKER, "Eleventh", "That slepen al the nyght with open eye-" },
{ GTK_STOCK_CONVERT, "Twelfth", "So priketh hem Nature in hir corages-" },
{ GTK_STOCK_CONNECT, "Thirteenth", "Thanne longen folk to goon on pilgrimages" },
{ GTK_STOCK_COPY, "Fourteenth", "And palmeres for to seken straunge strondes" },
{ GTK_STOCK_CUT, "Fifteenth", "To ferne halwes, kowthe in sondry londes;" },
{ GTK_STOCK_DELETE, "Sixteenth", "And specially, from every shires ende" },
{ GTK_STOCK_DIRECTORY, "Seventeenth", "Of Engelond, to Caunturbury they wende," },
{ GTK_STOCK_DISCONNECT, "Eighteenth", "The hooly blisful martir for the seke" },
{ GTK_STOCK_EDIT, "Nineteenth", "That hem hath holpen, whan that they were seeke." },
{ GTK_STOCK_EXECUTE, "Twentieth", "Bifil that in that seson, on a day," },
{ GTK_STOCK_FILE, "Twenty-first", "In Southwerk at the Tabard as I lay," },
{ GTK_STOCK_FIND, "Twenty-second", "Redy to wenden on my pilgrymage" },
{ GTK_STOCK_FIND_AND_REPLACE, "Twenty-third", "To Caunterbury, with ful devout corage," },
{ GTK_STOCK_FLOPPY, "Twenty-fourth", "At nyght were come into that hostelrye" },
{ GTK_STOCK_FULLSCREEN, "Twenty-fifth", "Wel nyne and twenty in a compaignye" },
{ GTK_STOCK_GOTO_BOTTOM, "Twenty-sixth", "Of sondry folk, by aventure yfalle" },
};
static GtkTreeModel *
tree_model_new (void)
{
GtkListStore *list;
int i;
list = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
for (i = 0; i < G_N_ELEMENTS (row_data); i++)
{
GtkTreeIter iter;
gtk_list_store_append (list, &iter);
gtk_list_store_set (list,
&iter,
0, row_data[i].stock_id,
1, row_data[i].text1,
2, row_data[i].text2,
-1);
}
return GTK_TREE_MODEL (list);
}
static GtkWidget *
tree_view_new (void)
drawing_area_new (void)
{
GtkWidget *sw;
GtkWidget *tree;
GtkTreeModel *model;
GtkTreeViewColumn *column;
sw = gtk_scrolled_window_new (NULL, NULL);
model = tree_model_new ();
tree = gtk_tree_view_new_with_model (model);
g_object_unref (model);
gtk_widget_set_size_request (tree, 300, 100);
column = gtk_tree_view_column_new_with_attributes ("Icon",
gtk_cell_renderer_pixbuf_new (),
"stock-id", 0,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
column = gtk_tree_view_column_new_with_attributes ("Index",
gtk_cell_renderer_text_new (),
"text", 1,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
column = gtk_tree_view_column_new_with_attributes ("Canterbury Tales",
gtk_cell_renderer_text_new (),
"text", 2,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
gtk_container_add (GTK_CONTAINER (sw), tree);
return sw;
}
static GtkWidget *
left_pane_new (void)
{
return tree_view_new ();
}
GtkWidget *darea;
static GtkWidget *
text_view_new (void)
{
GtkWidget *sw;
GtkWidget *text_view;
GtkTextBuffer *buffer;
sw = gtk_scrolled_window_new (NULL, NULL);
text_view = gtk_text_view_new ();
gtk_widget_set_size_request (text_view, 400, 300);
gtk_container_add (GTK_CONTAINER (sw), text_view);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
gtk_text_buffer_set_text (buffer,
"In felaweshipe, and pilgrimes were they alle,\n"
"That toward Caunterbury wolden ryde.\n"
"The chambres and the stables weren wyde,\n"
"And wel we weren esed atte beste;\n"
"And shortly, whan the sonne was to reste,\n"
"\n"
"So hadde I spoken with hem everychon \n"
"That I was of hir felaweshipe anon, \n"
"And made forward erly for to ryse \n"
"To take our wey, ther as I yow devyse. \n"
" But nathelees, whil I have tyme and space, \n"
" \n"
"Er that I ferther in this tale pace, \n"
"Me thynketh it acordaunt to resoun \n"
"To telle yow al the condicioun \n"
"Of ech of hem, so as it semed me, \n"
"And whiche they weren, and of what degree, \n"
" \n"
"And eek in what array that they were inne; \n"
"And at a knyght than wol I first bigynne. \n"
" A knyght ther was, and that a worthy man, \n"
"That fro the tyme that he first bigan \n"
"To riden out, he loved chivalrie, \n"
" \n"
"Trouthe and honour, fredom and curteisie. \n"
"Ful worthy was he in his lordes werre, \n"
" \n"
"And therto hadde he riden, no man ferre, \n"
"As wel in Cristendom as in Hethenesse, \n"
"And evere honoured for his worthynesse. \n"
" \n"
" At Alisaundre he was, whan it was wonne; \n"
"Ful ofte tyme he hadde the bord bigonne \n"
"Aboven alle nacions in Pruce; \n"
"In Lettow hadde he reysed, and in Ruce, \n"
"No cristen man so ofte of his degree. \n",
-1);
return sw;
darea = gtk_drawing_area_new ();
gtk_widget_set_size_request (darea, 640, 480);
return darea;
}
static GtkWidget *
upper_right_new (void)
content_area_new (void)
{
GtkWidget *notebook;
notebook = gtk_notebook_new ();
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
text_view_new (),
drawing_area_new (),
gtk_label_new ("First"));
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
text_view_new (),
drawing_area_new (),
gtk_label_new ("Second"));
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
text_view_new (),
drawing_area_new (),
gtk_label_new ("Third"));
return notebook;
}
static GtkWidget *
lower_right_new (void)
{
return tree_view_new ();
}
static GtkWidget *
right_pane_new (void)
{
GtkWidget *paned;
GtkWidget *upper_right;
GtkWidget *lower_right;
paned = gtk_vpaned_new ();
upper_right = upper_right_new ();
gtk_paned_pack1 (GTK_PANED (paned), upper_right, TRUE, TRUE);
lower_right = lower_right_new ();
gtk_paned_pack2 (GTK_PANED (paned), lower_right, TRUE, TRUE);
return paned;
}
static GtkWidget *
content_area_new (void)
{
GtkWidget *hpaned;
GtkWidget *left, *right;
hpaned = gtk_hpaned_new ();
left = left_pane_new ();
gtk_paned_pack1 (GTK_PANED (hpaned), left, TRUE, TRUE);
right = right_pane_new ();
gtk_paned_pack2 (GTK_PANED (hpaned), right, TRUE, TRUE);
return hpaned;
}
static GtkWidget *
status_bar_new (void)
{
......@@ -417,7 +227,7 @@ appwindow_new (void)
gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
widget = status_bar_new ();
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
gtk_box_pack_end (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
return window;
}
#include "config.h"
#include <string.h>
#include "gtkwidgetprofiler.h"
#include "marshalers.h"
#include "typebuiltins.h"
typedef enum {
STATE_NOT_CREATED,
STATE_INSTRUMENTED_NOT_MAPPED,
STATE_INSTRUMENTED_MAPPED
} State;
struct _GtkWidgetProfilerPrivate {
State state;
GtkWidget *profiled_widget;
GtkWidget *toplevel;
int n_iterations;
GTimer *timer;
gulong toplevel_expose_event_id;
gulong toplevel_property_notify_event_id;
GdkAtom profiler_atom;
guint profiling : 1;
};
G_DEFINE_TYPE (GtkWidgetProfiler, gtk_widget_profiler, G_TYPE_OBJECT);
static void gtk_widget_profiler_finalize (GObject *object);
enum {
CREATE_WIDGET,
REPORT,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static void
gtk_widget_profiler_class_init (GtkWidgetProfilerClass *class)
{
GObjectClass *object_class;
object_class = (GObjectClass *) class;
signals[CREATE_WIDGET] =
g_signal_new ("create-widget",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWidgetProfilerClass, create_widget),
NULL, NULL,
_gtk_marshal_OBJECT__VOID,
G_TYPE_OBJECT, 0);
signals[REPORT] =
g_signal_new ("report",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkWidgetProfilerClass, report),
NULL, NULL,
_gtk_marshal_VOID__ENUM_OBJECT_DOUBLE,
G_TYPE_NONE, 3,
GTK_TYPE_WIDGET_PROFILER_REPORT,
G_TYPE_OBJECT,
G_TYPE_DOUBLE);
object_class->finalize = gtk_widget_profiler_finalize;
}
static void
gtk_widget_profiler_init (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
priv = g_new0 (GtkWidgetProfilerPrivate, 1);
profiler->priv = priv;
priv->state = STATE_NOT_CREATED;
priv->n_iterations = 1;
priv->timer = g_timer_new ();
priv->profiler_atom = gdk_atom_intern ("GtkWidgetProfiler", FALSE);
}
static void
reset_state (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
priv = profiler->priv;
if (priv->toplevel)
{
g_signal_handler_disconnect (priv->toplevel, priv->toplevel_expose_event_id);
priv->toplevel_expose_event_id = 0;
g_signal_handler_disconnect (priv->toplevel, priv->toplevel_property_notify_event_id);
priv->toplevel_property_notify_event_id = 0;
gtk_widget_destroy (priv->toplevel);
priv->toplevel = NULL;
priv->profiled_widget = NULL;
}
priv->state = STATE_NOT_CREATED;
}
static void
gtk_widget_profiler_finalize (GObject *object)
{
GtkWidgetProfiler *profiler;