mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
589 lines
19 KiB
C
589 lines
19 KiB
C
/* sysprof-window.c
|
|
*
|
|
* Copyright 2023 Christian Hergert <chergert@redhat.com>
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib/gi18n.h>
|
|
|
|
#include "sysprof-counters-section.h"
|
|
#include "sysprof-cpu-section.h"
|
|
#include "sysprof-energy-section.h"
|
|
#include "sysprof-files-section.h"
|
|
#include "sysprof-greeter.h"
|
|
#include "sysprof-logs-section.h"
|
|
#include "sysprof-marks-section.h"
|
|
#include "sysprof-memory-section.h"
|
|
#include "sysprof-metadata-section.h"
|
|
#include "sysprof-network-section.h"
|
|
#include "sysprof-processes-section.h"
|
|
#include "sysprof-samples-section.h"
|
|
#include "sysprof-sidebar.h"
|
|
#include "sysprof-storage-section.h"
|
|
#include "sysprof-window.h"
|
|
|
|
struct _SysprofWindow
|
|
{
|
|
AdwApplicationWindow parent_instance;
|
|
|
|
SysprofDocument *document;
|
|
SysprofSession *session;
|
|
|
|
GtkToggleButton *show_right_sidebar;
|
|
GtkWidget *left_split_overlay;
|
|
GtkWidget *right_split_overlay;
|
|
|
|
guint disposed : 1;
|
|
};
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_DOCUMENT,
|
|
PROP_SESSION,
|
|
N_PROPS
|
|
};
|
|
|
|
G_DEFINE_FINAL_TYPE (SysprofWindow, sysprof_window, ADW_TYPE_APPLICATION_WINDOW)
|
|
|
|
static GParamSpec *properties [N_PROPS];
|
|
|
|
static void
|
|
sysprof_window_update_zoom_actions (SysprofWindow *self)
|
|
{
|
|
const SysprofTimeSpan *visible_time;
|
|
const SysprofTimeSpan *document_time;
|
|
|
|
g_assert (SYSPROF_IS_WINDOW (self));
|
|
|
|
if (self->session == NULL)
|
|
return;
|
|
|
|
visible_time = sysprof_session_get_visible_time (self->session);
|
|
document_time = sysprof_session_get_document_time (self->session);
|
|
|
|
gtk_widget_action_set_enabled (GTK_WIDGET (self),
|
|
"session.zoom-one",
|
|
!sysprof_time_span_equal (visible_time, document_time));
|
|
gtk_widget_action_set_enabled (GTK_WIDGET (self),
|
|
"session.zoom-out",
|
|
!sysprof_time_span_equal (visible_time, document_time));
|
|
gtk_widget_action_set_enabled (GTK_WIDGET (self),
|
|
"session.seek-backward",
|
|
visible_time->begin_nsec > document_time->begin_nsec);
|
|
gtk_widget_action_set_enabled (GTK_WIDGET (self),
|
|
"session.seek-forward",
|
|
visible_time->end_nsec < document_time->end_nsec);
|
|
}
|
|
|
|
static void
|
|
show_greeter (SysprofWindow *self,
|
|
SysprofGreeterPage page)
|
|
{
|
|
SysprofGreeter *greeter;
|
|
|
|
g_assert (SYSPROF_IS_WINDOW (self));
|
|
|
|
greeter = g_object_new (SYSPROF_TYPE_GREETER,
|
|
"transient-for", self,
|
|
NULL);
|
|
sysprof_greeter_set_page (greeter, page);
|
|
gtk_window_present (GTK_WINDOW (greeter));
|
|
}
|
|
|
|
static void
|
|
sysprof_window_open_capture_action (GtkWidget *widget,
|
|
const char *action_name,
|
|
GVariant *param)
|
|
{
|
|
show_greeter (SYSPROF_WINDOW (widget), SYSPROF_GREETER_PAGE_OPEN);
|
|
}
|
|
|
|
static void
|
|
sysprof_window_record_capture_action (GtkWidget *widget,
|
|
const char *action_name,
|
|
GVariant *param)
|
|
{
|
|
show_greeter (SYSPROF_WINDOW (widget), SYSPROF_GREETER_PAGE_RECORD);
|
|
}
|
|
|
|
static void
|
|
sysprof_window_set_document (SysprofWindow *self,
|
|
SysprofDocument *document)
|
|
{
|
|
static const char *callgraph_actions[] = {
|
|
"bottom-up",
|
|
"categorize-frames",
|
|
"hide-system-libraries",
|
|
"include-threads",
|
|
};
|
|
|
|
g_assert (SYSPROF_IS_WINDOW (self));
|
|
g_assert (SYSPROF_IS_DOCUMENT (document));
|
|
g_assert (self->document == NULL);
|
|
g_assert (self->session == NULL);
|
|
|
|
g_set_object (&self->document, document);
|
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DOCUMENT]);
|
|
|
|
self->session = sysprof_session_new (document);
|
|
g_signal_connect_object (self->session,
|
|
"notify::selected-time",
|
|
G_CALLBACK (sysprof_window_update_zoom_actions),
|
|
self,
|
|
G_CONNECT_SWAPPED);
|
|
g_signal_connect_object (self->session,
|
|
"notify::visible-time",
|
|
G_CALLBACK (sysprof_window_update_zoom_actions),
|
|
self,
|
|
G_CONNECT_SWAPPED);
|
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SESSION]);
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (callgraph_actions); i++)
|
|
{
|
|
g_autofree char *action_name = g_strdup_printf ("callgraph.%s", callgraph_actions[i]);
|
|
g_autoptr(GPropertyAction) action = g_property_action_new (action_name, self->session, callgraph_actions[i]);
|
|
|
|
g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (action));
|
|
}
|
|
|
|
sysprof_window_update_zoom_actions (self);
|
|
}
|
|
|
|
static void
|
|
main_view_notify_sidebar (SysprofWindow *self,
|
|
GParamSpec *pspec,
|
|
AdwOverlaySplitView *main_view)
|
|
{
|
|
GtkWidget *sidebar;
|
|
|
|
g_assert (SYSPROF_IS_WINDOW (self));
|
|
g_assert (ADW_IS_OVERLAY_SPLIT_VIEW (main_view));
|
|
|
|
if (self->disposed)
|
|
return;
|
|
|
|
sidebar = adw_overlay_split_view_get_sidebar (main_view);
|
|
|
|
if (sidebar == NULL)
|
|
adw_overlay_split_view_set_show_sidebar (main_view, FALSE);
|
|
|
|
gtk_widget_set_sensitive (GTK_WIDGET (self->show_right_sidebar), sidebar != NULL);
|
|
}
|
|
|
|
static void
|
|
sysprof_window_session_seek_backward (GtkWidget *widget,
|
|
const char *action_name,
|
|
GVariant *param)
|
|
{
|
|
SysprofWindow *self = (SysprofWindow *)widget;
|
|
const SysprofTimeSpan *document_time;
|
|
const SysprofTimeSpan *visible_time;
|
|
SysprofTimeSpan select;
|
|
gint64 duration;
|
|
|
|
g_assert (SYSPROF_IS_WINDOW (self));
|
|
|
|
if (self->session == NULL)
|
|
return;
|
|
|
|
visible_time = sysprof_session_get_visible_time (self->session);
|
|
document_time = sysprof_session_get_document_time (self->session);
|
|
duration = sysprof_time_span_duration (*visible_time);
|
|
|
|
select.begin_nsec = MAX (document_time->begin_nsec, visible_time->begin_nsec - duration);
|
|
select.end_nsec = select.begin_nsec + duration;
|
|
|
|
sysprof_session_select_time (self->session, &select);
|
|
sysprof_session_zoom_to_selection (self->session);
|
|
}
|
|
|
|
static void
|
|
sysprof_window_session_seek_forward (GtkWidget *widget,
|
|
const char *action_name,
|
|
GVariant *param)
|
|
{
|
|
SysprofWindow *self = (SysprofWindow *)widget;
|
|
const SysprofTimeSpan *document_time;
|
|
const SysprofTimeSpan *visible_time;
|
|
SysprofTimeSpan select;
|
|
gint64 duration;
|
|
|
|
g_assert (SYSPROF_IS_WINDOW (self));
|
|
|
|
if (self->session == NULL)
|
|
return;
|
|
|
|
visible_time = sysprof_session_get_visible_time (self->session);
|
|
document_time = sysprof_session_get_document_time (self->session);
|
|
duration = sysprof_time_span_duration (*visible_time);
|
|
|
|
select.begin_nsec = MIN (document_time->end_nsec - duration, visible_time->begin_nsec + duration);
|
|
select.end_nsec = select.begin_nsec + duration;
|
|
|
|
sysprof_session_select_time (self->session, &select);
|
|
sysprof_session_zoom_to_selection (self->session);
|
|
}
|
|
|
|
static void
|
|
sysprof_window_session_zoom_one (GtkWidget *widget,
|
|
const char *action_name,
|
|
GVariant *param)
|
|
{
|
|
SysprofWindow *self = (SysprofWindow *)widget;
|
|
|
|
g_assert (SYSPROF_IS_WINDOW (self));
|
|
|
|
if (self->session == NULL)
|
|
return;
|
|
|
|
sysprof_session_select_time (self->session,
|
|
sysprof_session_get_document_time (self->session));
|
|
}
|
|
|
|
static void
|
|
sysprof_window_session_zoom_in (GtkWidget *widget,
|
|
const char *action_name,
|
|
GVariant *param)
|
|
{
|
|
SysprofWindow *self = (SysprofWindow *)widget;
|
|
const SysprofTimeSpan *visible_time;
|
|
SysprofTimeSpan select;
|
|
gint64 duration;
|
|
|
|
g_assert (SYSPROF_IS_WINDOW (self));
|
|
|
|
if (self->session == NULL)
|
|
return;
|
|
|
|
visible_time = sysprof_session_get_visible_time (self->session);
|
|
duration = sysprof_time_span_duration (*visible_time);
|
|
|
|
select.begin_nsec = visible_time->begin_nsec + (duration / 4);
|
|
select.end_nsec = select.begin_nsec + (duration / 2);
|
|
|
|
sysprof_session_select_time (self->session, &select);
|
|
sysprof_session_zoom_to_selection (self->session);
|
|
}
|
|
|
|
static void
|
|
sysprof_window_session_zoom_out (GtkWidget *widget,
|
|
const char *action_name,
|
|
GVariant *param)
|
|
{
|
|
SysprofWindow *self = (SysprofWindow *)widget;
|
|
SysprofTimeSpan select;
|
|
gint64 duration;
|
|
|
|
g_assert (SYSPROF_IS_WINDOW (self));
|
|
|
|
if (self->session == NULL)
|
|
return;
|
|
|
|
select = *sysprof_session_get_visible_time (self->session);
|
|
duration = sysprof_time_span_duration (select);
|
|
|
|
select.begin_nsec -= floor (duration / 2.);
|
|
select.end_nsec += ceil (duration / 2.);
|
|
|
|
sysprof_session_select_time (self->session, &select);
|
|
sysprof_session_zoom_to_selection (self->session);
|
|
}
|
|
|
|
static void
|
|
sysprof_window_dispose (GObject *object)
|
|
{
|
|
SysprofWindow *self = (SysprofWindow *)object;
|
|
|
|
self->disposed = TRUE;
|
|
|
|
if (self->right_split_overlay)
|
|
adw_overlay_split_view_set_sidebar (ADW_OVERLAY_SPLIT_VIEW (self->right_split_overlay), NULL);
|
|
|
|
gtk_widget_dispose_template (GTK_WIDGET (self), SYSPROF_TYPE_WINDOW);
|
|
|
|
g_clear_object (&self->document);
|
|
g_clear_object (&self->session);
|
|
|
|
G_OBJECT_CLASS (sysprof_window_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
sysprof_window_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
SysprofWindow *self = SYSPROF_WINDOW (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_DOCUMENT:
|
|
g_value_set_object (value, sysprof_window_get_document (self));
|
|
break;
|
|
|
|
case PROP_SESSION:
|
|
g_value_set_object (value, sysprof_window_get_session (self));
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void
|
|
sysprof_window_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
SysprofWindow *self = SYSPROF_WINDOW (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_DOCUMENT:
|
|
sysprof_window_set_document (self, g_value_get_object (value));
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void
|
|
sysprof_window_class_init (SysprofWindowClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
|
|
object_class->dispose = sysprof_window_dispose;
|
|
object_class->get_property = sysprof_window_get_property;
|
|
object_class->set_property = sysprof_window_set_property;
|
|
|
|
properties[PROP_DOCUMENT] =
|
|
g_param_spec_object ("document", NULL, NULL,
|
|
SYSPROF_TYPE_DOCUMENT,
|
|
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
|
|
|
properties[PROP_SESSION] =
|
|
g_param_spec_object ("session", NULL, NULL,
|
|
SYSPROF_TYPE_SESSION,
|
|
(G_PARAM_READABLE | 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-window.ui");
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, show_right_sidebar);
|
|
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, left_split_overlay);
|
|
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, right_split_overlay);
|
|
|
|
gtk_widget_class_bind_template_callback (widget_class, main_view_notify_sidebar);
|
|
|
|
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);
|
|
gtk_widget_class_install_action (widget_class, "session.zoom-one", NULL, sysprof_window_session_zoom_one);
|
|
gtk_widget_class_install_action (widget_class, "session.zoom-out", NULL, sysprof_window_session_zoom_out);
|
|
gtk_widget_class_install_action (widget_class, "session.zoom-in", NULL, sysprof_window_session_zoom_in);
|
|
gtk_widget_class_install_action (widget_class, "session.seek-forward", NULL, sysprof_window_session_seek_forward);
|
|
gtk_widget_class_install_action (widget_class, "session.seek-backward", NULL, sysprof_window_session_seek_backward);
|
|
|
|
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_plus, GDK_CONTROL_MASK, "session.zoom-in", NULL);
|
|
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_equal, GDK_CONTROL_MASK, "session.zoom-in", NULL);
|
|
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_minus, GDK_CONTROL_MASK, "session.zoom-out", NULL);
|
|
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_0, GDK_CONTROL_MASK, "session.zoom-one", NULL);
|
|
|
|
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_bracketleft, GDK_CONTROL_MASK, "session.seek-backward", NULL);
|
|
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_bracketright, GDK_CONTROL_MASK, "session.seek-forward", NULL);
|
|
|
|
g_type_ensure (SYSPROF_TYPE_COUNTERS_SECTION);
|
|
g_type_ensure (SYSPROF_TYPE_CPU_SECTION);
|
|
g_type_ensure (SYSPROF_TYPE_DOCUMENT);
|
|
g_type_ensure (SYSPROF_TYPE_ENERGY_SECTION);
|
|
g_type_ensure (SYSPROF_TYPE_FILES_SECTION);
|
|
g_type_ensure (SYSPROF_TYPE_LOGS_SECTION);
|
|
g_type_ensure (SYSPROF_TYPE_MARKS_SECTION);
|
|
g_type_ensure (SYSPROF_TYPE_MEMORY_SECTION);
|
|
g_type_ensure (SYSPROF_TYPE_METADATA_SECTION);
|
|
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_STORAGE_SECTION);
|
|
g_type_ensure (SYSPROF_TYPE_SESSION);
|
|
g_type_ensure (SYSPROF_TYPE_SIDEBAR);
|
|
}
|
|
|
|
static void
|
|
sysprof_window_init (SysprofWindow *self)
|
|
{
|
|
g_autoptr(GPropertyAction) show_left_sidebar = NULL;
|
|
g_autoptr(GPropertyAction) show_right_sidebar = NULL;
|
|
|
|
gtk_widget_init_template (GTK_WIDGET (self));
|
|
|
|
show_left_sidebar = g_property_action_new ("show-left-sidebar",
|
|
self->left_split_overlay,
|
|
"show-sidebar");
|
|
g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (show_left_sidebar));
|
|
|
|
show_right_sidebar = g_property_action_new ("show-right-sidebar",
|
|
self->right_split_overlay,
|
|
"show-sidebar");
|
|
g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (show_right_sidebar));
|
|
}
|
|
|
|
GtkWidget *
|
|
sysprof_window_new (SysprofApplication *app,
|
|
SysprofDocument *document)
|
|
{
|
|
g_return_val_if_fail (SYSPROF_IS_APPLICATION (app), NULL);
|
|
g_return_val_if_fail (SYSPROF_IS_DOCUMENT (document), NULL);
|
|
|
|
return g_object_new (SYSPROF_TYPE_WINDOW,
|
|
"application", app,
|
|
"document", document,
|
|
NULL);
|
|
}
|
|
|
|
/**
|
|
* sysprof_window_get_session:
|
|
* @self: a #SysprofWindow
|
|
*
|
|
* Gets the session for the window.
|
|
*
|
|
* Returns: (transfer none): a #SysprofSession
|
|
*/
|
|
SysprofSession *
|
|
sysprof_window_get_session (SysprofWindow *self)
|
|
{
|
|
g_return_val_if_fail (SYSPROF_IS_WINDOW (self), NULL);
|
|
|
|
return self->session;
|
|
}
|
|
|
|
/**
|
|
* sysprof_window_get_document:
|
|
* @self: a #SysprofWindow
|
|
*
|
|
* Gets the document for the window.
|
|
*
|
|
* Returns: (transfer none): a #SysprofDocument
|
|
*/
|
|
SysprofDocument *
|
|
sysprof_window_get_document (SysprofWindow *self)
|
|
{
|
|
g_return_val_if_fail (SYSPROF_IS_WINDOW (self), NULL);
|
|
|
|
return self->document;
|
|
}
|
|
|
|
static void
|
|
sysprof_window_load_cb (GObject *object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
SysprofDocumentLoader *loader = (SysprofDocumentLoader *)object;
|
|
g_autoptr(SysprofApplication) app = user_data;
|
|
g_autoptr(SysprofDocument) document = NULL;
|
|
g_autoptr(GError) error = NULL;
|
|
|
|
g_assert (SYSPROF_IS_DOCUMENT_LOADER (loader));
|
|
g_assert (G_IS_ASYNC_RESULT (result));
|
|
g_assert (SYSPROF_IS_APPLICATION (app));
|
|
|
|
g_application_release (G_APPLICATION (app));
|
|
|
|
if (!(document = sysprof_document_loader_load_finish (loader, result, &error)))
|
|
{
|
|
GtkWidget *dialog;
|
|
|
|
dialog = adw_message_dialog_new (NULL, _("Invalid Document"), NULL);
|
|
adw_message_dialog_format_body (ADW_MESSAGE_DIALOG (dialog),
|
|
_("The document could not be loaded. Please check that you have the correct capture file.\n\n%s"),
|
|
error->message);
|
|
adw_message_dialog_add_response (ADW_MESSAGE_DIALOG (dialog), "close", _("Close"));
|
|
gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (dialog));
|
|
gtk_window_present (GTK_WINDOW (dialog));
|
|
}
|
|
else
|
|
{
|
|
GtkWidget *window;
|
|
|
|
window = sysprof_window_new (app, document);
|
|
gtk_window_present (GTK_WINDOW (window));
|
|
}
|
|
}
|
|
|
|
static void
|
|
sysprof_window_apply_loader_settings (SysprofDocumentLoader *loader)
|
|
{
|
|
/* TODO: apply loader settings from gsettings/etc */
|
|
}
|
|
|
|
void
|
|
sysprof_window_open (SysprofApplication *app,
|
|
GFile *file)
|
|
{
|
|
g_autoptr(SysprofDocumentLoader) loader = NULL;
|
|
|
|
g_return_if_fail (SYSPROF_IS_APPLICATION (app));
|
|
g_return_if_fail (G_IS_FILE (file));
|
|
|
|
if (!g_file_is_native (file) ||
|
|
!(loader = sysprof_document_loader_new (g_file_peek_path (file))))
|
|
{
|
|
g_autofree char *uri = g_file_get_uri (file);
|
|
g_warning ("Cannot open non-native file \"%s\"", uri);
|
|
return;
|
|
}
|
|
|
|
g_application_hold (G_APPLICATION (app));
|
|
sysprof_window_apply_loader_settings (loader);
|
|
sysprof_document_loader_load_async (loader,
|
|
NULL,
|
|
sysprof_window_load_cb,
|
|
g_object_ref (app));
|
|
|
|
}
|
|
|
|
void
|
|
sysprof_window_open_fd (SysprofApplication *app,
|
|
int fd)
|
|
{
|
|
g_autoptr(SysprofDocumentLoader) loader = NULL;
|
|
g_autoptr(GError) error = NULL;
|
|
|
|
g_return_if_fail (SYSPROF_IS_APPLICATION (app));
|
|
|
|
if (!(loader = sysprof_document_loader_new_for_fd (fd, &error)))
|
|
{
|
|
g_critical ("Failed to dup FD: %s", error->message);
|
|
return;
|
|
}
|
|
|
|
g_debug ("Opening recording by FD");
|
|
|
|
g_application_hold (G_APPLICATION (app));
|
|
sysprof_window_apply_loader_settings (loader);
|
|
sysprof_document_loader_load_async (loader,
|
|
NULL,
|
|
sysprof_window_load_cb,
|
|
g_object_ref (app));
|
|
|
|
}
|