Add debug controller
The debug controller can optionally, when passing --debug-control, enable manipulating debug state, so far enabling/disabling HDR, via D-Bus. It's always created, in order to have a place to store debug state and emit signals etc when it changes, but so far, it doesn't have its own state it tracks, it just mirrors that of the monitor manager. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3432>
This commit is contained in:
parent
d5253b1385
commit
adc5489ba7
12
data/dbus-interfaces/org.gnome.Mutter.DebugControl.xml
Normal file
12
data/dbus-interfaces/org.gnome.Mutter.DebugControl.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE node PUBLIC
|
||||
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
|
||||
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
|
||||
<node>
|
||||
|
||||
<interface name="org.gnome.Mutter.DebugControl">
|
||||
|
||||
<property name="EnableHDR" type="b" access="readwrite" />
|
||||
|
||||
</interface>
|
||||
|
||||
</node>
|
@ -72,6 +72,7 @@ typedef struct _MetaContextMainOptions
|
||||
GList *virtual_monitor_infos;
|
||||
#endif
|
||||
char *trace_file;
|
||||
gboolean debug_control;
|
||||
} MetaContextMainOptions;
|
||||
|
||||
struct _MetaContextMain
|
||||
@ -301,6 +302,13 @@ meta_context_main_configure (MetaContext *context,
|
||||
meta_context_set_trace_file (context, context_main->options.trace_file);
|
||||
#endif
|
||||
|
||||
if (context_main->options.debug_control)
|
||||
{
|
||||
MetaDebugControl *debug_control = meta_context_get_debug_control (context);
|
||||
|
||||
meta_debug_control_export (debug_control);
|
||||
}
|
||||
|
||||
g_unsetenv ("DESKTOP_AUTOSTART_ID");
|
||||
|
||||
return TRUE;
|
||||
@ -671,6 +679,11 @@ meta_context_main_add_option_entries (MetaContextMain *context_main)
|
||||
N_("Profile performance using trace instrumentation"),
|
||||
"FILE"
|
||||
},
|
||||
{
|
||||
"debug-control", 0, 0, G_OPTION_ARG_NONE,
|
||||
&context_main->options.debug_control,
|
||||
N_("Enable debug control D-Bus interface")
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/meta-debug-control.h"
|
||||
#include "core/meta-private-enums.h"
|
||||
#include "core/meta-service-channel.h"
|
||||
#include "core/util-private.h"
|
||||
@ -84,3 +85,5 @@ meta_context_get_profiler (MetaContext *context);
|
||||
void meta_context_set_trace_file (MetaContext *context,
|
||||
const char *trace_file);
|
||||
#endif
|
||||
|
||||
MetaDebugControl * meta_context_get_debug_control (MetaContext *context);
|
||||
|
@ -103,6 +103,8 @@ typedef struct _MetaContextPrivate
|
||||
#ifdef HAVE_WAYLAND
|
||||
MetaServiceChannel *service_channel;
|
||||
#endif
|
||||
|
||||
MetaDebugControl *debug_control;
|
||||
} MetaContextPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaContext, meta_context, G_TYPE_OBJECT)
|
||||
@ -329,7 +331,13 @@ meta_context_real_configure (MetaContext *context,
|
||||
}
|
||||
|
||||
option_context = g_steal_pointer (&priv->option_context);
|
||||
return g_option_context_parse (option_context, argc, argv, error);
|
||||
if (!g_option_context_parse (option_context, argc, argv, error))
|
||||
return FALSE;
|
||||
|
||||
priv->debug_control = g_object_new (META_TYPE_DEBUG_CONTROL,
|
||||
"context", context,
|
||||
NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -747,6 +755,8 @@ meta_context_dispose (GObject *object)
|
||||
|
||||
g_clear_pointer (&priv->backend, meta_backend_destroy);
|
||||
|
||||
g_clear_object (&priv->debug_control);
|
||||
|
||||
g_clear_pointer (&priv->option_context, g_option_context_free);
|
||||
g_clear_pointer (&priv->main_loop, g_main_loop_unref);
|
||||
|
||||
@ -839,3 +849,11 @@ meta_context_init (MetaContext *context)
|
||||
g_warning ("Failed to save the nofile limit: %s", error->message);
|
||||
}
|
||||
}
|
||||
|
||||
MetaDebugControl *
|
||||
meta_context_get_debug_control (MetaContext *context)
|
||||
{
|
||||
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
||||
|
||||
return priv->debug_control;
|
||||
}
|
||||
|
236
src/core/meta-debug-control.c
Normal file
236
src/core/meta-debug-control.c
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Red Hat
|
||||
*
|
||||
* 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 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "core/meta-debug-control.h"
|
||||
|
||||
#include "core/util-private.h"
|
||||
#include "meta/meta-backend.h"
|
||||
#include "meta/meta-context.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_CONTEXT,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[N_PROPS];
|
||||
|
||||
#define META_DEBUG_CONTROL_DBUS_SERVICE "org.gnome.Mutter.DebugControl"
|
||||
#define META_DEBUG_CONTROL_DBUS_PATH "/org/gnome/Mutter/DebugControl"
|
||||
|
||||
struct _MetaDebugControl
|
||||
{
|
||||
MetaDBusDebugControlSkeleton parent;
|
||||
|
||||
MetaContext *context;
|
||||
|
||||
guint dbus_name_id;
|
||||
};
|
||||
|
||||
static void meta_dbus_debug_control_iface_init (MetaDBusDebugControlIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaDebugControl,
|
||||
meta_debug_control,
|
||||
META_DBUS_TYPE_DEBUG_CONTROL_SKELETON,
|
||||
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_DEBUG_CONTROL,
|
||||
meta_dbus_debug_control_iface_init))
|
||||
|
||||
static void
|
||||
meta_dbus_debug_control_iface_init (MetaDBusDebugControlIface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
on_bus_acquired (GDBusConnection *connection,
|
||||
const char *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaDebugControl *debug_control = META_DEBUG_CONTROL (user_data);
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
meta_topic (META_DEBUG_BACKEND,
|
||||
"Acquired D-Bus name '%s', exporting service on '%s'",
|
||||
META_DEBUG_CONTROL_DBUS_SERVICE, META_DEBUG_CONTROL_DBUS_PATH);
|
||||
|
||||
if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (debug_control),
|
||||
connection,
|
||||
META_DEBUG_CONTROL_DBUS_PATH,
|
||||
&error))
|
||||
{
|
||||
g_warning ("Failed to export '%s' object on '%s': %s",
|
||||
META_DEBUG_CONTROL_DBUS_SERVICE,
|
||||
META_DEBUG_CONTROL_DBUS_PATH,
|
||||
error->message);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_enable_hdr_changed (MetaDebugControl *debug_control,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaDBusDebugControl *dbus_debug_control =
|
||||
META_DBUS_DEBUG_CONTROL (debug_control);
|
||||
MetaBackend *backend = meta_context_get_backend (debug_control->context);
|
||||
MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend);
|
||||
gboolean enable;
|
||||
|
||||
enable = meta_dbus_debug_control_get_enable_hdr (dbus_debug_control);
|
||||
g_object_set (G_OBJECT (monitor_manager),
|
||||
"experimental-hdr", enable ? "on" : "off",
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_experimental_hdr_changed (MetaMonitorManager *monitor_manager,
|
||||
GParamSpec *pspec,
|
||||
MetaDebugControl *debug_control)
|
||||
{
|
||||
MetaDBusDebugControl *dbus_debug_control =
|
||||
META_DBUS_DEBUG_CONTROL (debug_control);
|
||||
g_autofree char *experimental_hdr = NULL;
|
||||
gboolean enable;
|
||||
|
||||
g_object_get (G_OBJECT (monitor_manager),
|
||||
"experimental-hdr", &experimental_hdr,
|
||||
NULL);
|
||||
|
||||
enable = g_strcmp0 (experimental_hdr, "on") == 0;
|
||||
if (enable == meta_dbus_debug_control_get_enable_hdr (dbus_debug_control))
|
||||
return;
|
||||
|
||||
meta_dbus_debug_control_set_enable_hdr (META_DBUS_DEBUG_CONTROL (debug_control),
|
||||
g_strcmp0 (experimental_hdr, "on") == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
on_context_started (MetaContext *context,
|
||||
MetaDebugControl *debug_control)
|
||||
{
|
||||
MetaBackend *backend = meta_context_get_backend (context);
|
||||
MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend);
|
||||
|
||||
g_signal_connect (monitor_manager, "notify::experimental-hdr",
|
||||
G_CALLBACK (on_experimental_hdr_changed),
|
||||
debug_control);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_debug_control_constructed (GObject *object)
|
||||
{
|
||||
MetaDebugControl *debug_control = META_DEBUG_CONTROL (object);
|
||||
|
||||
g_signal_connect_object (debug_control->context, "started",
|
||||
G_CALLBACK (on_context_started), debug_control,
|
||||
G_CONNECT_DEFAULT);
|
||||
|
||||
g_signal_connect_object (debug_control, "notify::enable-hdr",
|
||||
G_CALLBACK (on_enable_hdr_changed), debug_control,
|
||||
G_CONNECT_DEFAULT);
|
||||
|
||||
G_OBJECT_CLASS (meta_debug_control_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_debug_control_dispose (GObject *object)
|
||||
{
|
||||
MetaDebugControl *debug_control = META_DEBUG_CONTROL (object);
|
||||
|
||||
g_clear_handle_id (&debug_control->dbus_name_id, g_bus_unown_name);
|
||||
|
||||
G_OBJECT_CLASS (meta_debug_control_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_debug_control_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaDebugControl *debug_control = META_DEBUG_CONTROL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CONTEXT:
|
||||
debug_control->context = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_debug_control_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaDebugControl *debug_control = META_DEBUG_CONTROL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CONTEXT:
|
||||
g_value_set_object (value, debug_control->context);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_debug_control_class_init (MetaDebugControlClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_debug_control_constructed;
|
||||
object_class->dispose = meta_debug_control_dispose;
|
||||
object_class->set_property = meta_debug_control_set_property;
|
||||
object_class->get_property = meta_debug_control_get_property;
|
||||
|
||||
obj_props[PROP_CONTEXT] = g_param_spec_object ("context", NULL, NULL,
|
||||
META_TYPE_CONTEXT,
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_debug_control_init (MetaDebugControl *debug_control)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
meta_debug_control_export (MetaDebugControl *debug_control)
|
||||
{
|
||||
debug_control->dbus_name_id =
|
||||
g_bus_own_name (G_BUS_TYPE_SESSION,
|
||||
META_DEBUG_CONTROL_DBUS_SERVICE,
|
||||
G_BUS_NAME_OWNER_FLAGS_NONE,
|
||||
on_bus_acquired,
|
||||
NULL,
|
||||
NULL,
|
||||
debug_control,
|
||||
NULL);
|
||||
}
|
29
src/core/meta-debug-control.h
Normal file
29
src/core/meta-debug-control.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Red Hat
|
||||
*
|
||||
* 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 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "meta-dbus-debug-control.h"
|
||||
|
||||
#define META_TYPE_DEBUG_CONTROL (meta_debug_control_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaDebugControl,
|
||||
meta_debug_control,
|
||||
META, DEBUG_CONTROL,
|
||||
MetaDBusDebugControlSkeleton)
|
||||
|
||||
void meta_debug_control_export (MetaDebugControl *debug_control);
|
@ -365,6 +365,8 @@ mutter_sources = [
|
||||
'core/meta-context-main.h',
|
||||
'core/meta-context-private.h',
|
||||
'core/meta-context.c',
|
||||
'core/meta-debug-control.c',
|
||||
'core/meta-debug-control.h',
|
||||
'core/meta-fraction.c',
|
||||
'core/meta-fraction.h',
|
||||
'core/meta-gesture-tracker.c',
|
||||
@ -939,6 +941,11 @@ dbus_interfaces = [
|
||||
'interface': 'org.gnome.Mutter.ServiceChannel.xml',
|
||||
'prefix': 'org.gnome.Mutter.',
|
||||
},
|
||||
{
|
||||
'name': 'meta-dbus-debug-control',
|
||||
'interface': 'org.gnome.Mutter.DebugControl.xml',
|
||||
'prefix': 'org.gnome.Mutter',
|
||||
},
|
||||
]
|
||||
|
||||
if have_profiler
|
||||
|
64
tools/debug-control.py
Executable file
64
tools/debug-control.py
Executable file
@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import dbus
|
||||
|
||||
NAME = 'org.gnome.Mutter.DebugControl'
|
||||
INTERFACE = 'org.gnome.Mutter.DebugControl'
|
||||
OBJECT_PATH = '/org/gnome/Mutter/DebugControl'
|
||||
|
||||
PROPS_IFACE = 'org.freedesktop.DBus.Properties'
|
||||
|
||||
def bool_to_string(value):
|
||||
if value:
|
||||
return "true"
|
||||
else:
|
||||
return "false"
|
||||
|
||||
def get_debug_control():
|
||||
bus = dbus.SessionBus()
|
||||
return bus.get_object(NAME, OBJECT_PATH)
|
||||
|
||||
def status():
|
||||
debug_control = get_debug_control()
|
||||
props = debug_control.GetAll(INTERFACE, dbus_interface=PROPS_IFACE)
|
||||
for prop in props:
|
||||
print(f"{prop}: {bool_to_string(props[prop])}")
|
||||
|
||||
def enable(prop):
|
||||
debug_control = get_debug_control()
|
||||
debug_control.Set(INTERFACE, prop, dbus.Boolean(True, variant_level=1),
|
||||
dbus_interface=PROPS_IFACE)
|
||||
|
||||
def disable(prop):
|
||||
debug_control = get_debug_control()
|
||||
debug_control.Set(INTERFACE, prop, dbus.Boolean(False, variant_level=1),
|
||||
dbus_interface=PROPS_IFACE)
|
||||
|
||||
def toggle(prop):
|
||||
debug_control = get_debug_control()
|
||||
|
||||
value = debug_control.Get(INTERFACE, prop, dbus_interface=PROPS_IFACE)
|
||||
debug_control.Set(INTERFACE, prop, dbus.Boolean(not value, variant_level=1),
|
||||
dbus_interface=PROPS_IFACE)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Get and set debug state')
|
||||
|
||||
parser.add_argument('--status', action='store_true')
|
||||
parser.add_argument('--enable', metavar='PROPERTY', type=str, nargs='?')
|
||||
parser.add_argument('--disable', metavar='PROPERTY', type=str, nargs='?')
|
||||
parser.add_argument('--toggle', metavar='PROPERTY', type=str, nargs='?')
|
||||
|
||||
args = parser.parse_args()
|
||||
if args.status:
|
||||
status()
|
||||
elif args.enable:
|
||||
enable(args.enable)
|
||||
elif args.disable:
|
||||
disable(args.disable)
|
||||
elif args.toggle:
|
||||
toggle(args.toggle)
|
||||
else:
|
||||
parser.print_usage()
|
Loading…
Reference in New Issue
Block a user