diff options
Diffstat (limited to 'src/greeter.cpp')
-rw-r--r-- | src/greeter.cpp | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/greeter.cpp b/src/greeter.cpp new file mode 100644 index 0000000..f9cd965 --- /dev/null +++ b/src/greeter.cpp @@ -0,0 +1,161 @@ +/* + * Copyright 2016 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 warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, 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/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + +#include <src/dbus-names.h> +#include <src/greeter.h> + +#include <gio/gio.h> + +class UnityGreeter::Impl +{ +public: + + Impl(): + m_cancellable{g_cancellable_new()} + { + g_bus_get(G_BUS_TYPE_SESSION, m_cancellable, on_bus_ready_static, this); + } + + ~Impl() + { + g_cancellable_cancel(m_cancellable); + g_clear_object(&m_cancellable); + + if (m_subscription_id != 0) + g_dbus_connection_signal_unsubscribe (m_bus, m_subscription_id); + + g_clear_object(&m_bus); + } + + core::Property<bool>& is_active() + { + return m_is_active; + } + +private: + + static void on_bus_ready_static(GObject* /*source*/, GAsyncResult* res, gpointer gself) + { + GError* error {}; + auto bus = g_bus_get_finish (res, &error); + if (error != nullptr) { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning("UsbSnap: Error getting session bus: %s", error->message); + g_clear_error(&error); + } else { + static_cast<Impl*>(gself)->on_bus_ready(bus); + } + g_clear_object(&bus); + } + + void on_bus_ready(GDBusConnection* bus) + { + m_bus = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(bus))); + + g_dbus_connection_call(m_bus, + DBusNames::UnityGreeter::NAME, + DBusNames::UnityGreeter::PATH, + DBusNames::Properties::INTERFACE, + "Get", + g_variant_new("(ss)", DBusNames::UnityGreeter::INTERFACE, "IsActive"), + G_VARIANT_TYPE("(v)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + m_cancellable, + on_get_is_active_ready, + this); + + m_subscription_id = g_dbus_connection_signal_subscribe(m_bus, + DBusNames::UnityGreeter::NAME, + DBusNames::Properties::INTERFACE, + DBusNames::Properties::PropertiesChanged::NAME, + DBusNames::UnityGreeter::PATH, + DBusNames::UnityGreeter::INTERFACE, + G_DBUS_SIGNAL_FLAGS_NONE, + on_properties_changed_signal, + this, + nullptr); + } + + static void on_get_is_active_ready(GObject* source, GAsyncResult* res, gpointer gself) + { + GError* error {}; + auto v = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error); + if (error != nullptr) { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning("UsbSnap: Error getting session bus: %s", error->message); + g_clear_error(&error); + } else { + GVariant* is_active {}; + g_variant_get_child(v, 0, "v", &is_active); + static_cast<Impl*>(gself)->m_is_active.set(g_variant_get_boolean(is_active)); + g_clear_pointer(&is_active, g_variant_unref); + } + g_clear_pointer(&v, g_variant_unref); + } + + static void on_properties_changed_signal(GDBusConnection* /*connection*/, + const gchar* /*sender_name*/, + const gchar* object_path, + const gchar* interface_name, + const gchar* signal_name, + GVariant* parameters, + gpointer gself) + { + g_return_if_fail(!g_strcmp0(object_path, DBusNames::UnityGreeter::PATH)); + g_return_if_fail(!g_strcmp0(interface_name, DBusNames::Properties::INTERFACE)); + g_return_if_fail(!g_strcmp0(signal_name, DBusNames::Properties::PropertiesChanged::NAME)); + g_return_if_fail(g_variant_is_of_type(parameters, G_VARIANT_TYPE(DBusNames::Properties::PropertiesChanged::ARGS_VARIANT_TYPE))); + + auto v = g_variant_get_child_value (parameters, 1); + gboolean is_active {}; + if (g_variant_lookup(v, "IsActive", "b", &is_active)) + { + g_debug("%s is_active changed to %d", G_STRLOC, int(is_active)); + static_cast<Impl*>(gself)->m_is_active.set(is_active); + } + g_clear_pointer(&v, g_variant_unref); + } + + core::Property<bool> m_is_active; + GCancellable* m_cancellable {}; + GDBusConnection* m_bus {}; + unsigned int m_subscription_id {}; +}; + +/*** +**** +***/ + +Greeter::Greeter() =default; + +Greeter::~Greeter() =default; + +UnityGreeter::UnityGreeter(): + impl{new Impl{}} +{ +} + +UnityGreeter::~UnityGreeter() =default; + +core::Property<bool>& +UnityGreeter::is_active() +{ + return impl->is_active(); +} |