/* * Copyright (C) 2010-2011 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * 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 . * * Authored by: Jason Smith * Marco Trevisan (TreviƱo) <3v1n0@ubuntu.com> * */ #include #include "bamf-control.h" #include "bamf-application.h" #include "bamf-daemon.h" #include "bamf-matcher.h" G_DEFINE_TYPE (BamfControl, bamf_control, BAMF_DBUS_TYPE_CONTROL_SKELETON); #define BAMF_CONTROL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE(obj, \ BAMF_TYPE_CONTROL, BamfControlPrivate)) struct _BamfControlPrivate { GDBusConnection *connection; guint launched_signal; GList *sources; }; static void bamf_control_on_launched_callback (GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) { const gchar *desktop_file; gint64 pid; g_variant_get_child (parameters, 0, "^&ay", &desktop_file); g_variant_get_child (parameters, 2, "x", &pid); bamf_matcher_register_desktop_file_for_pid (bamf_matcher_get_default (), desktop_file, pid); } static void on_bus_connection (GObject *source_object, GAsyncResult *res, gpointer user_data) { BamfControl *self; GError *error = NULL; g_return_if_fail (BAMF_IS_CONTROL (user_data)); self = BAMF_CONTROL (user_data); self->priv->connection = g_bus_get_finish (res, &error); if (error) { g_warning ("Got error when connecting to session bus: %s", error->message); g_clear_error (&error); self->priv->connection = NULL; return; } self->priv->launched_signal = g_dbus_connection_signal_subscribe (self->priv->connection, NULL, "org.gtk.gio.DesktopAppInfo", "Launched", "/org/gtk/gio/DesktopAppInfo", NULL, G_DBUS_SIGNAL_FLAGS_NONE, bamf_control_on_launched_callback, self, NULL); } static void bamf_control_constructed (GObject *object) { if (G_OBJECT_CLASS (bamf_control_parent_class)->constructed) G_OBJECT_CLASS (bamf_control_parent_class)->constructed (object); g_bus_get (G_BUS_TYPE_SESSION, NULL, on_bus_connection, object); } static gboolean on_dbus_handle_quit (BamfDBusControl *interface, GDBusMethodInvocation *invocation, BamfControl *self) { g_dbus_method_invocation_return_value (invocation, NULL); bamf_control_quit (self); return TRUE; } static gboolean on_dbus_handle_insert_desktop_file (BamfDBusControl *interface, GDBusMethodInvocation *invocation, const gchar *desktop_file, BamfControl *self) { g_dbus_method_invocation_return_value (invocation, NULL); bamf_control_insert_desktop_file (self, desktop_file); return TRUE; } static gboolean on_dbus_handle_register_application_for_pid (BamfDBusControl *interface, GDBusMethodInvocation *invocation, const gchar *application, guint pid, BamfControl *self) { g_dbus_method_invocation_return_value (invocation, NULL); bamf_control_register_application_for_pid (self, application, pid); return TRUE; } static gboolean on_dbus_handle_create_local_desktop_file (BamfDBusControl *interface, GDBusMethodInvocation *invocation, const gchar *desktop_file, BamfControl *self) { g_dbus_method_invocation_return_value (invocation, NULL); bamf_control_create_local_desktop_file (self, desktop_file); return TRUE; } static void bamf_control_init (BamfControl * self) { self->priv = BAMF_CONTROL_GET_PRIVATE (self); self->priv->sources = NULL; /* Registering signal callbacks to reply to dbus method calls */ g_signal_connect (self, "handle-quit", G_CALLBACK (on_dbus_handle_quit), self); g_signal_connect (self, "handle-om-nom-nom-desktop-file", G_CALLBACK (on_dbus_handle_insert_desktop_file), self); g_signal_connect (self, "handle-insert-desktop-file", G_CALLBACK (on_dbus_handle_insert_desktop_file), self); g_signal_connect (self, "handle-register-application-for-pid", G_CALLBACK (on_dbus_handle_register_application_for_pid), self); g_signal_connect (self, "handle-create-local-desktop-file", G_CALLBACK (on_dbus_handle_create_local_desktop_file), self); } static void bamf_control_finalize (GObject *object) { BamfControl *self = BAMF_CONTROL (object); if (self->priv->connection) { if (self->priv->launched_signal) { g_dbus_connection_signal_unsubscribe (self->priv->connection, self->priv->launched_signal); } g_object_unref (self->priv->connection); } g_list_free_full (self->priv->sources, g_object_unref); } static void bamf_control_class_init (BamfControlClass * klass) { GObjectClass *obj_class = G_OBJECT_CLASS (klass); obj_class->constructed = bamf_control_constructed; obj_class->finalize = bamf_control_finalize; g_type_class_add_private (klass, sizeof (BamfControlPrivate)); } void bamf_control_register_application_for_pid (BamfControl *control, const char *application, gint32 pid) { BamfMatcher *matcher = bamf_matcher_get_default (); bamf_matcher_register_desktop_file_for_pid (matcher, application, pid); } void bamf_control_insert_desktop_file (BamfControl *control, const char *path) { BamfMatcher *matcher = bamf_matcher_get_default (); bamf_matcher_load_desktop_file (matcher, path); } void bamf_control_create_local_desktop_file (BamfControl *control, const char *app_path) { BamfMatcher *matcher; BamfView *view; g_return_if_fail (BAMF_IS_CONTROL (control)); g_return_if_fail (app_path); matcher = bamf_matcher_get_default (); view = bamf_matcher_get_view_by_path (matcher, app_path); if (BAMF_IS_APPLICATION (view)) bamf_application_create_local_desktop_file (BAMF_APPLICATION (view)); } static gboolean bamf_control_on_quit (BamfControl *control) { BamfDaemon *daemon = bamf_daemon_get_default (); bamf_daemon_stop (daemon); return FALSE; } void bamf_control_quit (BamfControl *control) { g_idle_add ((GSourceFunc) bamf_control_on_quit, control); } BamfControl * bamf_control_get_default (void) { static BamfControl *control; if (!BAMF_IS_CONTROL (control)) { control = (BamfControl *) g_object_new (BAMF_TYPE_CONTROL, NULL); } return control; }