diff --git a/src/libsysprof-gtk/sysprof-chart-layer.c b/src/libsysprof-gtk/sysprof-chart-layer.c index 4dd401de..5d48a858 100644 --- a/src/libsysprof-gtk/sysprof-chart-layer.c +++ b/src/libsysprof-gtk/sysprof-chart-layer.c @@ -129,3 +129,16 @@ sysprof_chart_layer_set_title (SysprofChartLayer *self, if (g_set_str (&priv->title, title)) g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TITLE]); } + +void +sysprof_chart_layer_snapshot_motion (SysprofChartLayer *self, + GtkSnapshot *snapshot, + double x, + double y) +{ + g_return_if_fail (SYSPROF_IS_CHART_LAYER (self)); + g_return_if_fail (GTK_IS_SNAPSHOT (snapshot)); + + if (SYSPROF_CHART_LAYER_GET_CLASS (self)->snapshot_motion) + SYSPROF_CHART_LAYER_GET_CLASS (self)->snapshot_motion (self, snapshot, x, y); +} diff --git a/src/libsysprof-gtk/sysprof-chart-layer.h b/src/libsysprof-gtk/sysprof-chart-layer.h index b6aba5ff..5b4c6871 100644 --- a/src/libsysprof-gtk/sysprof-chart-layer.h +++ b/src/libsysprof-gtk/sysprof-chart-layer.h @@ -35,14 +35,24 @@ struct _SysprofChartLayerClass { GtkWidgetClass parent_class; + void (*snapshot_motion) (SysprofChartLayer *self, + GtkSnapshot *snapshot, + double x, + double y); + /*< private >*/ gpointer _reserved[16]; }; SYSPROF_AVAILABLE_IN_ALL -const char *sysprof_chart_layer_get_title (SysprofChartLayer *self); +const char *sysprof_chart_layer_get_title (SysprofChartLayer *self); SYSPROF_AVAILABLE_IN_ALL -void sysprof_chart_layer_set_title (SysprofChartLayer *self, - const char *title); +void sysprof_chart_layer_set_title (SysprofChartLayer *self, + const char *title); +SYSPROF_AVAILABLE_IN_ALL +void sysprof_chart_layer_snapshot_motion (SysprofChartLayer *self, + GtkSnapshot *snapshot, + double x, + double y); G_END_DECLS diff --git a/src/libsysprof-gtk/sysprof-chart.c b/src/libsysprof-gtk/sysprof-chart.c index b0315cb5..d154fec4 100644 --- a/src/libsysprof-gtk/sysprof-chart.c +++ b/src/libsysprof-gtk/sysprof-chart.c @@ -26,6 +26,11 @@ typedef struct { SysprofSession *session; char *title; + + double motion_x; + double motion_y; + + guint pointer_in_chart : 1; } SysprofChartPrivate; enum { @@ -39,6 +44,58 @@ G_DEFINE_TYPE_WITH_PRIVATE (SysprofChart, sysprof_chart, GTK_TYPE_WIDGET) static GParamSpec *properties [N_PROPS]; + +static void +sysprof_chart_motion_enter_cb (SysprofChart *self, + double x, + double y, + GtkEventControllerMotion *motion) +{ + SysprofChartPrivate *priv = sysprof_chart_get_instance_private (self); + + g_assert (SYSPROF_IS_CHART (self)); + g_assert (GTK_IS_EVENT_CONTROLLER_MOTION (motion)); + + priv->motion_x = x; + priv->motion_y = y; + priv->pointer_in_chart = TRUE; + + gtk_widget_queue_draw (GTK_WIDGET (self)); +} + +static void +sysprof_chart_motion_cb (SysprofChart *self, + double x, + double y, + GtkEventControllerMotion *motion) +{ + SysprofChartPrivate *priv = sysprof_chart_get_instance_private (self); + + g_assert (SYSPROF_IS_CHART (self)); + g_assert (GTK_IS_EVENT_CONTROLLER_MOTION (motion)); + + priv->motion_x = x; + priv->motion_y = y; + + gtk_widget_queue_draw (GTK_WIDGET (self)); +} + +static void +sysprof_chart_motion_leave_cb (SysprofChart *self, + GtkEventControllerMotion *motion) +{ + SysprofChartPrivate *priv = sysprof_chart_get_instance_private (self); + + g_assert (SYSPROF_IS_CHART (self)); + g_assert (GTK_IS_EVENT_CONTROLLER_MOTION (motion)); + + priv->motion_x = -1; + priv->motion_y = -1; + priv->pointer_in_chart = FALSE; + + gtk_widget_queue_draw (GTK_WIDGET (self)); +} + static void sysprof_chart_size_allocate (GtkWidget *widget, int width, @@ -57,6 +114,29 @@ sysprof_chart_size_allocate (GtkWidget *widget, baseline); } +static void +sysprof_chart_snapshot (GtkWidget *widget, + GtkSnapshot *snapshot) +{ + SysprofChart *self = (SysprofChart *)widget; + SysprofChartPrivate *priv = sysprof_chart_get_instance_private (self); + + g_assert (SYSPROF_IS_CHART (self)); + + GTK_WIDGET_CLASS (sysprof_chart_parent_class)->snapshot (widget, snapshot); + + if (priv->pointer_in_chart) + { + GtkWidget *pick = gtk_widget_pick (widget, priv->motion_x, priv->motion_y, GTK_PICK_DEFAULT); + + if (SYSPROF_IS_CHART_LAYER (pick)) + sysprof_chart_layer_snapshot_motion (SYSPROF_CHART_LAYER (pick), + snapshot, + priv->motion_x, + priv->motion_y); + } +} + static void sysprof_chart_dispose (GObject *object) { @@ -130,6 +210,7 @@ sysprof_chart_class_init (SysprofChartClass *klass) object_class->set_property = sysprof_chart_set_property; widget_class->size_allocate = sysprof_chart_size_allocate; + widget_class->snapshot = sysprof_chart_snapshot; properties [PROP_SESSION] = g_param_spec_object ("session", NULL, NULL, @@ -147,6 +228,29 @@ sysprof_chart_class_init (SysprofChartClass *klass) static void sysprof_chart_init (SysprofChart *self) { + SysprofChartPrivate *priv = sysprof_chart_get_instance_private (self); + GtkEventController *motion; + + priv->motion_x = -1; + priv->motion_y = -1; + + motion = gtk_event_controller_motion_new (); + g_signal_connect_object (motion, + "enter", + G_CALLBACK (sysprof_chart_motion_enter_cb), + self, + G_CONNECT_SWAPPED); + g_signal_connect_object (motion, + "leave", + G_CALLBACK (sysprof_chart_motion_leave_cb), + self, + G_CONNECT_SWAPPED); + g_signal_connect_object (motion, + "motion", + G_CALLBACK (sysprof_chart_motion_cb), + self, + G_CONNECT_SWAPPED); + gtk_widget_add_controller (GTK_WIDGET (self), g_steal_pointer (&motion)); } const char *