diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0cb3fa09..fdae6bda 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -46,6 +46,7 @@ src/sysprof/sysprof-processes-section.ui
src/sysprof/sysprof-recording-pad.c
src/sysprof/sysprof-recording-pad.ui
src/sysprof/sysprof-samples-section.ui
+src/sysprof/sysprof-session-filters-widget.ui
src/sysprof/sysprof-sidebar.ui
src/sysprof/sysprof-storage-section.ui
src/sysprof/sysprof-traceables-utility.ui
diff --git a/src/sysprof/icons/scalable/actions/funnel-outline-symbolic.svg b/src/sysprof/icons/scalable/actions/funnel-outline-symbolic.svg
new file mode 100644
index 00000000..10b32288
--- /dev/null
+++ b/src/sysprof/icons/scalable/actions/funnel-outline-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/src/sysprof/meson.build b/src/sysprof/meson.build
index 6a7ccf77..038f58f9 100644
--- a/src/sysprof/meson.build
+++ b/src/sysprof/meson.build
@@ -52,6 +52,7 @@ sysprof_sources = [
'sysprof-scheduler.c',
'sysprof-section.c',
'sysprof-series.c',
+ 'sysprof-session-filters-widget.c',
'sysprof-session-model-item.c',
'sysprof-session-model.c',
'sysprof-session.c',
diff --git a/src/sysprof/style.css b/src/sysprof/style.css
index d5d7b5e2..750ffdf0 100644
--- a/src/sysprof/style.css
+++ b/src/sysprof/style.css
@@ -96,3 +96,17 @@ popover.tasks listview row {
popover.tasks listview row label.heading {
padding-bottom: 3px;
}
+
+sessionfilters row {
+ padding: 3px 0;
+}
+
+sessionfilters row:hover {
+ background: none;
+}
+
+sessionfilters row button {
+ min-width: 0;
+ min-height: 0;
+ padding: 3px;
+}
diff --git a/src/sysprof/sysprof-session-filters-widget.c b/src/sysprof/sysprof-session-filters-widget.c
new file mode 100644
index 00000000..96b2cb2e
--- /dev/null
+++ b/src/sysprof/sysprof-session-filters-widget.c
@@ -0,0 +1,225 @@
+/*
+ * sysprof-session-filters-widget.c
+ *
+ * Copyright 2025 Georges Basile Stavracas Neto
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "sysprof-mark-filter.h"
+#include "sysprof-session-filters-widget.h"
+#include "sysprof-session.h"
+
+struct _SysprofSessionFiltersWidget
+{
+ GtkWidget parent_instance;
+
+ SysprofSession *session;
+};
+
+G_DEFINE_FINAL_TYPE (SysprofSessionFiltersWidget, sysprof_session_filters_widget, GTK_TYPE_WIDGET)
+
+enum {
+ PROP_0,
+ PROP_SESSION,
+ N_PROPS,
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+sysprof_session_filters_widget_remove_filter (GtkWidget *widget,
+ const char *action_name,
+ GVariant *param)
+{
+ SysprofSessionFiltersWidget *self = (SysprofSessionFiltersWidget *) widget;
+ GtkFilter *filter;
+ unsigned int position;
+
+ g_assert (SYSPROF_IS_SESSION_FILTERS_WIDGET (widget));
+ g_assert (SYSPROF_IS_SESSION (self->session));
+
+ filter = sysprof_session_get_filter (self->session);
+ g_assert (GTK_IS_MULTI_FILTER (filter));
+
+ position = g_variant_get_uint32 (param);
+
+ gtk_multi_filter_remove (GTK_MULTI_FILTER (filter), position);
+}
+
+static GVariant *
+item_to_action_target (gpointer unused,
+ GtkFilter *filter,
+ unsigned int position)
+{
+ if (filter)
+ return g_variant_new_uint32 (position);
+
+ return NULL;
+}
+
+static char *
+filter_to_icon_name (gpointer unused,
+ GtkFilter *filter)
+{
+ if (!filter)
+ return g_strdup ("");
+
+ if (SYSPROF_IS_MARK_FILTER (filter))
+ return g_strdup ("mark-chart-symbolic");
+
+ return g_strdup ("funnel-outline-symbolic");
+}
+
+static char *
+filter_to_string (gpointer unused,
+ GtkFilter *filter)
+{
+ if (!filter)
+ return g_strdup ("");
+
+ if (SYSPROF_IS_MARK_FILTER (filter))
+ {
+ SysprofMarkFilter *mark_filter = (SysprofMarkFilter *) filter;
+ SysprofMarkCatalog *catalog = sysprof_mark_filter_get_catalog (mark_filter);
+
+ return g_strdup_printf ("%s / %s",
+ sysprof_mark_catalog_get_group (catalog),
+ sysprof_mark_catalog_get_name (catalog));
+ }
+
+ return g_strdup (G_OBJECT_TYPE_NAME (filter));
+}
+
+static void
+clear_all_filters (SysprofSessionFiltersWidget *self,
+ GtkButton *button)
+{
+ GtkFilter *filter;
+
+ g_assert (SYSPROF_IS_SESSION_FILTERS_WIDGET (self));
+ g_assert (SYSPROF_IS_SESSION (self->session));
+ g_assert (GTK_IS_BUTTON (button));
+
+ filter = sysprof_session_get_filter (self->session);
+ g_assert (GTK_IS_MULTI_FILTER (filter));
+
+ while (g_list_model_get_n_items (G_LIST_MODEL (filter)) > 0)
+ gtk_multi_filter_remove (GTK_MULTI_FILTER (filter), 0);
+}
+
+static void
+sysprof_session_filters_widget_set_session (SysprofSessionFiltersWidget *self,
+ SysprofSession *session)
+{
+ if (g_set_object (&self->session, session))
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SESSION]);
+}
+
+static void
+sysprof_session_filters_widget_finalize (GObject *object)
+{
+ SysprofSessionFiltersWidget *self = (SysprofSessionFiltersWidget *)object;
+
+ g_clear_object (&self->session);
+
+ G_OBJECT_CLASS (sysprof_session_filters_widget_parent_class)->finalize (object);
+}
+
+static void
+sysprof_session_filters_widget_dispose (GObject *object)
+{
+ SysprofSessionFiltersWidget *self = (SysprofSessionFiltersWidget *)object;
+
+ gtk_widget_dispose_template (GTK_WIDGET (self), SYSPROF_TYPE_SESSION_FILTERS_WIDGET);
+
+ G_OBJECT_CLASS (sysprof_session_filters_widget_parent_class)->dispose (object);
+}
+
+static void
+sysprof_session_filters_widget_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SysprofSessionFiltersWidget *self = SYSPROF_SESSION_FILTERS_WIDGET (object);
+
+ switch (prop_id)
+ {
+ case PROP_SESSION:
+ g_value_set_object (value, self->session);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+sysprof_session_filters_widget_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SysprofSessionFiltersWidget *self = SYSPROF_SESSION_FILTERS_WIDGET (object);
+
+ switch (prop_id)
+ {
+ case PROP_SESSION:
+ sysprof_session_filters_widget_set_session (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+sysprof_session_filters_widget_class_init (SysprofSessionFiltersWidgetClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = sysprof_session_filters_widget_finalize;
+ object_class->dispose = sysprof_session_filters_widget_dispose;
+ object_class->get_property = sysprof_session_filters_widget_get_property;
+ object_class->set_property = sysprof_session_filters_widget_set_property;
+
+ properties[PROP_SESSION] =
+ g_param_spec_object ("session", NULL, NULL,
+ SYSPROF_TYPE_SESSION,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-session-filters-widget.ui");
+
+ gtk_widget_class_set_css_name (widget_class, "sessionfilters");
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+
+ gtk_widget_class_bind_template_callback (widget_class, clear_all_filters);
+ gtk_widget_class_bind_template_callback (widget_class, filter_to_icon_name);
+ gtk_widget_class_bind_template_callback (widget_class, filter_to_string);
+ gtk_widget_class_bind_template_callback (widget_class, item_to_action_target);
+
+ gtk_widget_class_install_action (widget_class, "sessionfilters.remove-filter", "u", sysprof_session_filters_widget_remove_filter);
+}
+
+static void
+sysprof_session_filters_widget_init (SysprofSessionFiltersWidget *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/src/sysprof/sysprof-session-filters-widget.h b/src/sysprof/sysprof-session-filters-widget.h
new file mode 100644
index 00000000..22a2c892
--- /dev/null
+++ b/src/sysprof/sysprof-session-filters-widget.h
@@ -0,0 +1,32 @@
+/*
+ * sysprof-session-filters-widget.c
+ *
+ * Copyright 2025 Georges Basile Stavracas Neto
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include
+
+G_BEGIN_DECLS
+
+#define SYSPROF_TYPE_SESSION_FILTERS_WIDGET (sysprof_session_filters_widget_get_type())
+
+G_DECLARE_FINAL_TYPE (SysprofSessionFiltersWidget, sysprof_session_filters_widget, SYSPROF, SESSION_FILTERS_WIDGET, GtkWidget)
+
+G_END_DECLS
diff --git a/src/sysprof/sysprof-session-filters-widget.ui b/src/sysprof/sysprof-session-filters-widget.ui
new file mode 100644
index 00000000..ebad1025
--- /dev/null
+++ b/src/sysprof/sysprof-session-filters-widget.ui
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/sysprof/sysprof-window.c b/src/sysprof/sysprof-window.c
index e81e264b..cc351836 100644
--- a/src/sysprof/sysprof-window.c
+++ b/src/sysprof/sysprof-window.c
@@ -41,6 +41,7 @@
#include "sysprof-pair.h"
#include "sysprof-processes-section.h"
#include "sysprof-samples-section.h"
+#include "sysprof-session-filters-widget.h"
#include "sysprof-sidebar.h"
#include "sysprof-storage-section.h"
#include "sysprof-task-row.h"
@@ -328,6 +329,13 @@ main_view_notify_sidebar (SysprofWindow *self,
gtk_widget_set_sensitive (GTK_WIDGET (self->show_right_sidebar), sidebar != NULL);
}
+static gboolean
+n_filters_to_button_visibility (SysprofWindow *self,
+ unsigned int n_filters)
+{
+ return n_filters > 0;
+}
+
static void
sysprof_window_session_seek_backward (GtkWidget *widget,
const char *action_name,
@@ -617,6 +625,7 @@ sysprof_window_class_init (SysprofWindowClass *klass)
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, stack_title);
gtk_widget_class_bind_template_callback (widget_class, main_view_notify_sidebar);
+ gtk_widget_class_bind_template_callback (widget_class, n_filters_to_button_visibility);
gtk_widget_class_install_action (widget_class, "win.open-capture", NULL, sysprof_window_open_capture_action);
gtk_widget_class_install_action (widget_class, "win.record-capture", NULL, sysprof_window_record_capture_action);
@@ -649,6 +658,7 @@ sysprof_window_class_init (SysprofWindowClass *klass)
g_type_ensure (SYSPROF_TYPE_NETWORK_SECTION);
g_type_ensure (SYSPROF_TYPE_PROCESSES_SECTION);
g_type_ensure (SYSPROF_TYPE_SAMPLES_SECTION);
+ g_type_ensure (SYSPROF_TYPE_SESSION_FILTERS_WIDGET);
g_type_ensure (SYSPROF_TYPE_STORAGE_SECTION);
g_type_ensure (SYSPROF_TYPE_SESSION);
g_type_ensure (SYSPROF_TYPE_SYMBOL);
diff --git a/src/sysprof/sysprof-window.ui b/src/sysprof/sysprof-window.ui
index f4e1e7cb..c18b4a47 100644
--- a/src/sysprof/sysprof-window.ui
+++ b/src/sysprof/sysprof-window.ui
@@ -126,6 +126,36 @@
Toggle Left Panel
+
+
+
6
diff --git a/src/sysprof/sysprof.gresource.xml b/src/sysprof/sysprof.gresource.xml
index 3903b5a5..eb5d9307 100644
--- a/src/sysprof/sysprof.gresource.xml
+++ b/src/sysprof/sysprof.gresource.xml
@@ -8,6 +8,7 @@
icons/scalable/actions/empty-symbolic.svg
icons/scalable/actions/energy-symbolic.svg
icons/scalable/actions/flamegraph-symbolic.svg
+ icons/scalable/actions/funnel-outline-symbolic.svg
icons/scalable/actions/graphics-symbolic.svg
icons/scalable/actions/mark-chart-symbolic.svg
icons/scalable/actions/mark-table-symbolic.svg
@@ -50,6 +51,7 @@
sysprof-processes-section.ui
sysprof-recording-pad.ui
sysprof-samples-section.ui
+ sysprof-session-filters-widget.ui
sysprof-sidebar.ui
sysprof-storage-section.ui
sysprof-task-row.ui