You've already forked ukui-settings-daemon
mirror of
https://github.com/ukui/ukui-settings-daemon.git
synced 2026-03-09 09:24:39 -07:00
371 lines
12 KiB
C++
371 lines
12 KiB
C++
#include <dbus/dbus-glib.h>
|
|
#include <dbus/dbus-glib-lowlevel.h>
|
|
#include <libmate-desktop/mate-gsettings.h>
|
|
|
|
#include "plugin-manager.h"
|
|
#include "clib-syslog.h"
|
|
|
|
#include <QApplication>
|
|
|
|
#define USD_DBUS_NAME "org.ukui.SettingsDaemon"
|
|
#define DEBUG_KEY "mate-settings-daemon"
|
|
#define DEBUG_SCHEMA "org.mate.debug"
|
|
|
|
#define UKUI_SESSION_DBUS_NAME "org.gnome.SessionManager"
|
|
#define UKUI_SESSION_DBUS_OBJECT "/org/gnome/SessionManager"
|
|
#define UKUI_SESSION_DBUS_INTERFACE "org.gnome.SessionManager"
|
|
#define UKUI_SESSION_PRIVATE_DBUS_INTERFACE "org.gnome.SessionManager.ClientPrivate"
|
|
|
|
static DBusGConnection* get_session_bus (void);
|
|
static gboolean bus_register (DBusGConnection *bus);
|
|
|
|
static void on_session_query_end (DBusGProxy *proxy, guint flags, PluginManager *manager);
|
|
static void on_session_end (DBusGProxy *proxy, guint flags, PluginManager *manager);
|
|
static DBusGProxy* get_bus_proxy (DBusGConnection *connection);
|
|
static gboolean acquire_name_on_proxy (DBusGProxy *bus_proxy);
|
|
static void set_session_over_handler (DBusGConnection *bus, PluginManager *manager);
|
|
static DBusHandlerResult bus_message_handler (DBusConnection *connection, DBusMessage* message, void* user_data);
|
|
static gboolean timed_exit_cb (void);
|
|
|
|
static void parse_args (int *argc, char ***argv);
|
|
static void debug_changed (GSettings *settings, gchar *key, gpointer user_data);
|
|
|
|
static gboolean no_daemon = TRUE;
|
|
static gboolean replace = FALSE;
|
|
static gboolean debug = FALSE;
|
|
static gboolean do_timed_exit = FALSE;
|
|
static int term_signal_pipe_fds[2]; // pipe line for ....
|
|
|
|
static GOptionEntry entries[] = {
|
|
{ "debug", 0, 0, G_OPTION_ARG_NONE, &debug, ("Enable debugging code"), NULL },
|
|
{ "replace", 0, 0, G_OPTION_ARG_NONE, &replace, ("Replace the current daemon"), NULL },
|
|
{ "no-daemon", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &no_daemon, ("Don't become a daemon"), NULL },
|
|
{ "timed-exit", 0, 0, G_OPTION_ARG_NONE, &do_timed_exit, ("Exit after a time (for debugging)"), NULL },
|
|
{ NULL },
|
|
};
|
|
|
|
int main (int argc, char* argv[])
|
|
{
|
|
PluginManager* manager = NULL;
|
|
DBusGConnection* bus = NULL;
|
|
gboolean res;
|
|
GError* error = NULL;
|
|
GSettings* debug_settings = NULL;
|
|
|
|
syslog_init("ukui-settings-daemon", LOG_LOCAL6);
|
|
|
|
CT_SYSLOG(LOG_DEBUG, "starting...");
|
|
|
|
|
|
CT_SYSLOG(LOG_DEBUG, "本地化...");
|
|
// bindtextdomain (GETTEXT_PACKAGE, UKUI_SETTINGS_LOCALEDIR);
|
|
// bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
|
// textdomain (GETTEXT_PACKAGE);
|
|
// setlocale (LC_ALL, "");
|
|
|
|
// FIXME:// QT parse command line
|
|
CT_SYSLOG(LOG_DEBUG, "解析命令行参数...");
|
|
parse_args (&argc, &argv);
|
|
|
|
QApplication app(argc, argv);
|
|
|
|
/* Allows to enable/disable debug from GSettings only if it is not set from argument */
|
|
if (mate_gsettings_schema_exists (DEBUG_SCHEMA)) {
|
|
debug_settings = g_settings_new (DEBUG_SCHEMA);
|
|
debug = g_settings_get_boolean (debug_settings, DEBUG_KEY);
|
|
g_signal_connect (debug_settings, "changed::" DEBUG_KEY, G_CALLBACK (debug_changed), NULL);
|
|
if (debug) {
|
|
g_setenv ("G_MESSAGES_DEBUG", "all", FALSE);
|
|
}
|
|
}
|
|
|
|
CT_SYSLOG(LOG_DEBUG, "dbus session...");
|
|
bus = get_session_bus ();
|
|
if (bus == NULL) {
|
|
CT_SYSLOG(LOG_ERR, "Could not get a connection to the bus!");
|
|
goto out;
|
|
}
|
|
|
|
CT_SYSLOG(LOG_DEBUG, "dbus register...");
|
|
if (!bus_register (bus)) {
|
|
CT_SYSLOG(LOG_ERR, "dbus register error!");
|
|
goto out;
|
|
}
|
|
|
|
manager = PluginManager::getInstance();
|
|
if (manager == NULL) {
|
|
CT_SYSLOG(LOG_ERR, "Unable to register object");
|
|
goto out;
|
|
}
|
|
|
|
CT_SYSLOG(LOG_DEBUG, "set session handler...");
|
|
set_session_over_handler (bus, manager);
|
|
|
|
/* If we aren't started by dbus then load the plugins automatically. Otherwise, wait for an Awake etc. */
|
|
if (g_getenv ("DBUS_STARTER_BUS_TYPE") == NULL) {
|
|
error = NULL;
|
|
res = manager->managerStart();
|
|
if (! res) {
|
|
CT_SYSLOG(LOG_ERR, "Unable to start: %s", error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
}
|
|
// FIXME:// maybe error
|
|
if (do_timed_exit) {
|
|
g_timeout_add_seconds (30, (GSourceFunc) timed_exit_cb, NULL);
|
|
}
|
|
|
|
return app.exec();
|
|
out:
|
|
|
|
if (bus != NULL) dbus_g_connection_unref (bus);
|
|
if (manager != NULL) g_object_unref (manager);
|
|
if (debug_settings != NULL) g_object_unref (debug_settings);
|
|
|
|
CT_SYSLOG(LOG_DEBUG, "SettingsDaemon finished");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void parse_args (int *argc, char ***argv)
|
|
{
|
|
GError *error;
|
|
GOptionContext *context;
|
|
|
|
context = g_option_context_new (NULL);
|
|
|
|
g_option_context_add_main_entries (context, entries, NULL);
|
|
//g_option_context_add_group (context, gtk_get_option_group (FALSE));
|
|
|
|
error = NULL;
|
|
if (!g_option_context_parse (context, argc, argv, &error)) {
|
|
if (error != NULL) {
|
|
CT_SYSLOG(LOG_ERR, "%s", error->message);
|
|
g_error_free (error);
|
|
} else {
|
|
CT_SYSLOG(LOG_ERR, "Unable to initialize GTK+");
|
|
}
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
g_option_context_free (context);
|
|
|
|
// FIXME:// debug log not use
|
|
// if (debug) g_setenv ("G_MESSAGES_DEBUG", "all", FALSE);
|
|
}
|
|
|
|
static void debug_changed (GSettings *settings, gchar *key, gpointer user_data)
|
|
{
|
|
debug = g_settings_get_boolean (settings, DEBUG_KEY);
|
|
if (debug) {
|
|
CT_SYSLOG(LOG_ERR, "Enable DEBUG");
|
|
g_setenv ("G_MESSAGES_DEBUG", "all", FALSE);
|
|
} else {
|
|
CT_SYSLOG(LOG_ERR, "Disable DEBUG");
|
|
g_unsetenv ("G_MESSAGES_DEBUG");
|
|
}
|
|
}
|
|
|
|
static DBusGConnection* get_session_bus (void)
|
|
{
|
|
GError *error;
|
|
DBusGConnection *bus;
|
|
DBusConnection *connection;
|
|
|
|
error = NULL;
|
|
bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
|
|
if (bus == NULL) {
|
|
CT_SYSLOG(LOG_ERR, "Couldn't connect to session bus: %s", error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
|
|
connection = dbus_g_connection_get_connection (bus);
|
|
dbus_connection_add_filter (connection, (DBusHandleMessageFunction) bus_message_handler, NULL, NULL);
|
|
dbus_connection_set_exit_on_disconnect (connection, FALSE);
|
|
|
|
out:
|
|
return bus;
|
|
}
|
|
|
|
static void on_session_over (DBusGProxy *proxy, PluginManager *manager)
|
|
{
|
|
/* not used, see on_session_end instead */
|
|
}
|
|
|
|
static void set_session_over_handler (DBusGConnection* bus, PluginManager* manager)
|
|
{
|
|
DBusGProxy *session_proxy;
|
|
DBusGProxy *private_proxy;
|
|
gchar *client_id = NULL;
|
|
const char *startup_id;
|
|
GError *error = NULL;
|
|
gboolean res;
|
|
|
|
if (NULL != bus) QApplication::exit();
|
|
|
|
session_proxy = dbus_g_proxy_new_for_name (bus, UKUI_SESSION_DBUS_NAME, UKUI_SESSION_DBUS_OBJECT, UKUI_SESSION_DBUS_INTERFACE);
|
|
dbus_g_object_register_marshaller(g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, G_TYPE_INVALID);
|
|
dbus_g_proxy_add_signal(session_proxy, "SessionOver", G_TYPE_INVALID);
|
|
dbus_g_proxy_connect_signal(session_proxy, "SessionOver", G_CALLBACK (on_session_over), manager, NULL);
|
|
|
|
/* Register with ukui-session */
|
|
startup_id = g_getenv ("DESKTOP_AUTOSTART_ID");
|
|
if (startup_id != NULL && *startup_id != '\0') {
|
|
res = dbus_g_proxy_call (session_proxy, "RegisterClient", &error, G_TYPE_STRING, "ukui-settings-daemon",
|
|
G_TYPE_STRING, startup_id, G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, &client_id, G_TYPE_INVALID);
|
|
if (!res) {
|
|
CT_SYSLOG(LOG_ERR, "failed to register client '%s': %s", startup_id, error->message);
|
|
g_error_free (error);
|
|
} else {
|
|
/* get org.gnome.SessionManager.ClientPrivate interface */
|
|
private_proxy = dbus_g_proxy_new_for_name_owner (bus, UKUI_SESSION_DBUS_NAME,
|
|
client_id, UKUI_SESSION_PRIVATE_DBUS_INTERFACE, &error);
|
|
if (private_proxy == NULL) {
|
|
CT_SYSLOG(LOG_ERR, "DBUS error: %s", error->message);
|
|
g_error_free (error);
|
|
} else {
|
|
/* get QueryEndSession */
|
|
dbus_g_proxy_add_signal (private_proxy, "QueryEndSession", G_TYPE_UINT, G_TYPE_INVALID);
|
|
dbus_g_proxy_connect_signal (private_proxy, "QueryEndSession", G_CALLBACK (on_session_query_end), manager, NULL);
|
|
/* get EndSession */
|
|
dbus_g_proxy_add_signal (private_proxy, "EndSession", G_TYPE_UINT, G_TYPE_INVALID);
|
|
dbus_g_proxy_connect_signal (private_proxy, "EndSession", G_CALLBACK (on_session_end), manager, NULL);
|
|
}
|
|
g_free (client_id);
|
|
}
|
|
}
|
|
|
|
// FIXME://
|
|
// watch_for_term_signal (manager);
|
|
}
|
|
|
|
static void on_session_query_end (DBusGProxy *proxy, guint flags, PluginManager *manager)
|
|
{
|
|
GError *error = NULL;
|
|
gboolean ret = FALSE;
|
|
|
|
/* send response */
|
|
ret = dbus_g_proxy_call (proxy, "EndSessionResponse", &error, G_TYPE_BOOLEAN, TRUE /* ok */, G_TYPE_STRING, NULL /* reason */, G_TYPE_INVALID, G_TYPE_INVALID);
|
|
if (!ret) {
|
|
CT_SYSLOG(LOG_ERR, "failed to send session response: %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
|
|
static void on_session_end (DBusGProxy *proxy, guint flags, PluginManager *manager)
|
|
{
|
|
GError *error = NULL;
|
|
gboolean ret = FALSE;
|
|
|
|
/* send response */
|
|
ret = dbus_g_proxy_call (proxy, "EndSessionResponse", &error, G_TYPE_BOOLEAN, TRUE /* ok */, G_TYPE_STRING, NULL /* reason */, G_TYPE_INVALID, G_TYPE_INVALID);
|
|
if (!ret) {
|
|
CT_SYSLOG(LOG_ERR, "failed to send session response: %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
|
|
// FIXME://
|
|
manager->managerStop();
|
|
QApplication::exit();
|
|
}
|
|
|
|
static gboolean bus_register (DBusGConnection *bus)
|
|
{
|
|
DBusGProxy *bus_proxy;
|
|
gboolean ret;
|
|
|
|
ret = FALSE;
|
|
|
|
bus_proxy = get_bus_proxy (bus);
|
|
|
|
if (bus_proxy == NULL) {
|
|
CT_SYSLOG(LOG_ERR, "Could not construct bus_proxy object");
|
|
goto out;
|
|
}
|
|
|
|
ret = acquire_name_on_proxy (bus_proxy);
|
|
g_object_unref (bus_proxy);
|
|
|
|
if (!ret) {
|
|
CT_SYSLOG(LOG_ERR, "Could not acquire name");
|
|
goto out;
|
|
}
|
|
|
|
CT_SYSLOG(LOG_DEBUG, "Successfully connected to D-Bus");
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static DBusGProxy* get_bus_proxy (DBusGConnection *connection)
|
|
{
|
|
DBusGProxy *bus_proxy;
|
|
|
|
bus_proxy = dbus_g_proxy_new_for_name (connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
|
|
|
|
return bus_proxy;
|
|
}
|
|
|
|
static gboolean acquire_name_on_proxy (DBusGProxy *bus_proxy)
|
|
{
|
|
GError *error;
|
|
guint result;
|
|
gboolean res;
|
|
gboolean ret;
|
|
guint32 flags;
|
|
|
|
ret = FALSE;
|
|
|
|
flags = DBUS_NAME_FLAG_DO_NOT_QUEUE|DBUS_NAME_FLAG_ALLOW_REPLACEMENT;
|
|
if (replace) flags |= DBUS_NAME_FLAG_REPLACE_EXISTING;
|
|
|
|
error = NULL;
|
|
res = dbus_g_proxy_call (bus_proxy, "RequestName", &error, G_TYPE_STRING, USD_DBUS_NAME, G_TYPE_UINT, flags, G_TYPE_INVALID, G_TYPE_UINT, &result, G_TYPE_INVALID);
|
|
if (! res) {
|
|
if (error != NULL) {
|
|
CT_SYSLOG(LOG_ERR, "Failed to acquire %s: %s", USD_DBUS_NAME, error->message);
|
|
g_error_free (error);
|
|
} else {
|
|
CT_SYSLOG(LOG_ERR, "Failed to acquire %s", USD_DBUS_NAME);
|
|
}
|
|
goto out;
|
|
}
|
|
|
|
if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
|
|
if (error != NULL) {
|
|
CT_SYSLOG(LOG_ERR, "Failed to acquire %s: %s", USD_DBUS_NAME, error->message);
|
|
g_error_free (error);
|
|
} else {
|
|
CT_SYSLOG(LOG_ERR, "Failed to acquire %s", USD_DBUS_NAME);
|
|
}
|
|
goto out;
|
|
}
|
|
|
|
ret = TRUE;
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static DBusHandlerResult bus_message_handler (DBusConnection *connection, DBusMessage* message, void* user_data)
|
|
{
|
|
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
|
|
QApplication::exit();
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
}
|
|
else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameLost")) {
|
|
CT_SYSLOG(LOG_ERR, "D-Bus name lost, quitting");
|
|
QApplication::exit();
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
}
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
|
|
static gboolean timed_exit_cb (void)
|
|
{
|
|
QApplication::exit();
|
|
return FALSE;
|
|
}
|