diff --git a/panels/bluetooth/cc-bluetooth-panel.c b/panels/bluetooth/cc-bluetooth-panel.c index 36c58bf4d90372ac4d300c8df2acb58f95802dc8..5a60d70c8e3b1f9237a2173e69e664ad74d51ec3 100644 --- a/panels/bluetooth/cc-bluetooth-panel.c +++ b/panels/bluetooth/cc-bluetooth-panel.c @@ -24,6 +24,7 @@ #include #include +#include #include #include "cc-bluetooth-panel.h" @@ -310,20 +311,18 @@ cc_bluetooth_panel_init (CcBluetoothPanel *self) self->cancellable = g_cancellable_new (); /* RFKill */ - self->rfkill = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Rfkill", - "/org/gnome/SettingsDaemon/Rfkill", - "org.gnome.SettingsDaemon.Rfkill", - NULL, NULL); - self->properties = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Rfkill", - "/org/gnome/SettingsDaemon/Rfkill", - "org.freedesktop.DBus.Properties", - NULL, NULL); + self->rfkill = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Rfkill", + "/org/gnome/SettingsDaemon/Rfkill", + "org.gnome.SettingsDaemon.Rfkill", + NULL, NULL); + self->properties = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Rfkill", + "/org/gnome/SettingsDaemon/Rfkill", + "org.freedesktop.DBus.Properties", + NULL, NULL); self->stack = gtk_stack_new (); gtk_stack_set_homogeneous (GTK_STACK (self->stack), TRUE); @@ -343,10 +342,10 @@ cc_bluetooth_panel_init (CcBluetoothPanel *self) gtk_container_add (GTK_CONTAINER (self), self->stack); airplane_mode_changed (NULL, NULL, NULL, self); - g_signal_connect (self->rfkill, "g-properties-changed", - G_CALLBACK (airplane_mode_changed), self); - g_signal_connect_swapped (G_OBJECT (self->widget), "adapter-status-changed", - G_CALLBACK (cc_bluetooth_panel_update_power), self); + g_signal_connect_object (self->rfkill, "g-properties-changed", + G_CALLBACK (airplane_mode_changed), self, 0); + g_signal_connect_object (G_OBJECT (self->widget), "adapter-status-changed", + G_CALLBACK (cc_bluetooth_panel_update_power), self, G_CONNECT_SWAPPED); g_signal_connect (G_OBJECT (WID ("switch_bluetooth")), "notify::active", G_CALLBACK (power_callback), self); diff --git a/panels/color/cc-color-calibrate.c b/panels/color/cc-color-calibrate.c index d21ad058fbfa6a8449581e3a2ca43db4885796be..9357eee72d3c05b7540157069599dd93a1cf43cb 100644 --- a/panels/color/cc-color-calibrate.c +++ b/panels/color/cc-color-calibrate.c @@ -28,6 +28,8 @@ #include #include +#include "shell/cc-object-storage.h" + #define GNOME_DESKTOP_USE_UNSTABLE_API #include @@ -884,14 +886,13 @@ cc_color_calibrate_setup (CcColorCalibrate *calibrate, g_return_val_if_fail (calibrate->priv->device_kind != CD_SENSOR_CAP_UNKNOWN, FALSE); /* use logind to disable system state idle */ - priv->proxy_inhibit = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - NULL, - error); + priv->proxy_inhibit = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + NULL, + error); if (priv->proxy_inhibit == NULL) { ret = FALSE; @@ -899,27 +900,26 @@ cc_color_calibrate_setup (CcColorCalibrate *calibrate, } /* start the calibration session daemon */ - priv->proxy_helper = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - CD_SESSION_DBUS_SERVICE, - CD_SESSION_DBUS_PATH, - CD_SESSION_DBUS_INTERFACE_DISPLAY, - NULL, - error); + priv->proxy_helper = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + CD_SESSION_DBUS_SERVICE, + CD_SESSION_DBUS_PATH, + CD_SESSION_DBUS_INTERFACE_DISPLAY, + NULL, + error); if (priv->proxy_helper == NULL) { ret = FALSE; goto out; } - g_signal_connect (priv->proxy_helper, - "g-properties-changed", - G_CALLBACK (cc_color_calibrate_property_changed_cb), - calibrate); - g_signal_connect (priv->proxy_helper, - "g-signal", - G_CALLBACK (cc_color_calibrate_signal_cb), - calibrate); + g_signal_connect_object (priv->proxy_helper, + "g-properties-changed", + G_CALLBACK (cc_color_calibrate_property_changed_cb), + calibrate, 0); + g_signal_connect_object (priv->proxy_helper, + "g-signal", + G_CALLBACK (cc_color_calibrate_signal_cb), + calibrate, 0); out: return ret; } diff --git a/panels/color/cc-color-panel.c b/panels/color/cc-color-panel.c index d901b623eaa42d915ab5b4513174eaef670c5319..e7957debaeafb53473ae601e1b9a6e35d59aae3d 100644 --- a/panels/color/cc-color-panel.c +++ b/panels/color/cc-color-panel.c @@ -49,7 +49,6 @@ struct _CcColorPanelPrivate GPtrArray *devices; GPtrArray *sensors; GCancellable *cancellable; - GDBusProxy *proxy; GSettings *settings; GSettings *settings_colord; GtkBuilder *builder; diff --git a/panels/common/cc-common-language.c b/panels/common/cc-common-language.c index 028213acbc0f7579ee1f323a8fb5423af4adb944..4ea4f06ad55eade1ada1140d9427a78582f9f36e 100644 --- a/panels/common/cc-common-language.c +++ b/panels/common/cc-common-language.c @@ -33,6 +33,7 @@ #include #include "cc-common-language.h" +#include "shell/cc-object-storage.h" static char *get_lang_for_user_object_path (const char *path); @@ -175,14 +176,13 @@ get_lang_for_user_object_path (const char *path) GVariant *props; char *lang; - user = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.Accounts", - path, - "org.freedesktop.Accounts.User", - NULL, - &error); + user = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.Accounts", + path, + "org.freedesktop.Accounts.User", + NULL, + &error); if (user == NULL) { g_warning ("Failed to get proxy for user '%s': %s", path, error->message); diff --git a/panels/display/cc-display-panel.c b/panels/display/cc-display-panel.c index 13f5332e9f6ff066fac1ac4137eacc44b969db53..550376776a5ef0bd984f4ebdbde79a51c93eadca 100644 --- a/panels/display/cc-display-panel.c +++ b/panels/display/cc-display-panel.c @@ -29,6 +29,7 @@ #include #include +#include "shell/cc-object-storage.h" #include "shell/list-box-helper.h" #include @@ -3117,7 +3118,7 @@ shell_proxy_ready (GObject *source, GDBusProxy *proxy; GError *error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (!proxy) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -3336,17 +3337,16 @@ cc_display_panel_init (CcDisplayPanel *self) g_signal_connect (self, "map", G_CALLBACK (mapped_cb), NULL); self->priv->shell_cancellable = g_cancellable_new (); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NULL, - "org.gnome.Shell", - "/org/gnome/Shell", - "org.gnome.Shell", - self->priv->shell_cancellable, - (GAsyncReadyCallback) shell_proxy_ready, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + "org.gnome.Shell", + "/org/gnome/Shell", + "org.gnome.Shell", + self->priv->shell_cancellable, + (GAsyncReadyCallback) shell_proxy_ready, + self); g_bus_get (G_BUS_TYPE_SESSION, self->priv->shell_cancellable, diff --git a/panels/display/cc-night-light-dialog.c b/panels/display/cc-night-light-dialog.c index a2bbc683e1291212325f1872f853b796fe8e5b8f..1d03ba3934db7d476d24c92e907979e410008d22 100644 --- a/panels/display/cc-night-light-dialog.c +++ b/panels/display/cc-night-light-dialog.c @@ -27,6 +27,8 @@ #include "cc-night-light-dialog.h" #include "cc-night-light-widget.h" +#include "shell/cc-object-storage.h" + struct _CcNightLightDialog { GObject parent; GtkBuilder *builder; @@ -385,14 +387,14 @@ dialog_got_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_da { CcNightLightDialog *self = (CcNightLightDialog *) user_data; g_autoptr(GError) error = NULL; - self->proxy_color = g_dbus_proxy_new_for_bus_finish (res, &error); + self->proxy_color = cc_object_storage_create_dbus_proxy_finish (res, &error); if (self->proxy_color == NULL) { g_warning ("failed to connect to g-s-d: %s", error->message); return; } - g_signal_connect (self->proxy_color, "g-properties-changed", - G_CALLBACK (dialog_color_properties_changed_cb), self); + g_signal_connect_object (self->proxy_color, "g-properties-changed", + G_CALLBACK (dialog_color_properties_changed_cb), self, 0); dialog_update_state (self); self->timer_id = g_timeout_add_seconds (10, dialog_tick_cb, self); } @@ -402,7 +404,7 @@ dialog_got_proxy_props_cb (GObject *source_object, GAsyncResult *res, gpointer u { CcNightLightDialog *self = (CcNightLightDialog *) user_data; g_autoptr(GError) error = NULL; - self->proxy_color_props = g_dbus_proxy_new_for_bus_finish (res, &error); + self->proxy_color_props = cc_object_storage_create_dbus_proxy_finish (res, &error); if (self->proxy_color_props == NULL) { g_warning ("failed to connect to g-s-d: %s", error->message); @@ -669,25 +671,23 @@ cc_night_light_dialog_init (CcNightLightDialog *self) gtk_box_pack_start (box, self->night_light_widget, FALSE, FALSE, 0); gtk_widget_show (self->night_light_widget); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Color", - "/org/gnome/SettingsDaemon/Color", - "org.gnome.SettingsDaemon.Color", - self->cancellable, - dialog_got_proxy_cb, - self); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Color", - "/org/gnome/SettingsDaemon/Color", - "org.freedesktop.DBus.Properties", - self->cancellable, - dialog_got_proxy_props_cb, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Color", + "/org/gnome/SettingsDaemon/Color", + "org.gnome.SettingsDaemon.Color", + self->cancellable, + dialog_got_proxy_cb, + self); + + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Color", + "/org/gnome/SettingsDaemon/Color", + "org.freedesktop.DBus.Properties", + self->cancellable, + dialog_got_proxy_props_cb, + self); /* clock settings_display */ self->settings_clock = g_settings_new (CLOCK_SCHEMA); diff --git a/panels/info/cc-info-overview-panel.c b/panels/info/cc-info-overview-panel.c index 411c1c90543922d2ac72259528c2ce9ac56500fd..4301090f9c6df5a912da81b6f89d82784059680d 100644 --- a/panels/info/cc-info-overview-panel.c +++ b/panels/info/cc-info-overview-panel.c @@ -22,6 +22,7 @@ #include #include "shell/cc-hostname-entry.h" +#include "shell/cc-object-storage.h" #include "cc-info-resources.h" #include "info-cleanup.h" @@ -235,13 +236,12 @@ get_renderer_from_session (void) char *renderer; g_autoptr(GError) error = NULL; - session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SessionManager", - "/org/gnome/SessionManager", - "org.gnome.SessionManager", - NULL, &error); + session_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SessionManager", + "/org/gnome/SessionManager", + "org.gnome.SessionManager", + NULL, &error); if (error != NULL) { g_warning ("Unable to connect to create a proxy for org.gnome.SessionManager: %s", @@ -302,13 +302,12 @@ has_dual_gpu (void) gboolean ret; g_autoptr(GError) error = NULL; - switcheroo_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "net.hadess.SwitcherooControl", - "/net/hadess/SwitcherooControl", - "net.hadess.SwitcherooControl", - NULL, &error); + switcheroo_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "net.hadess.SwitcherooControl", + "/net/hadess/SwitcherooControl", + "net.hadess.SwitcherooControl", + NULL, &error); if (switcheroo_proxy == NULL) { g_debug ("Unable to connect to create a proxy for net.hadess.SwitcherooControl: %s", @@ -720,14 +719,13 @@ info_overview_panel_setup_virt (CcInfoOverviewPanel *self) g_autoptr(GVariant) variant = NULL; GVariant *inner; - systemd_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1", - NULL, - &error); + systemd_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1", + NULL, + &error); if (systemd_proxy == NULL) { diff --git a/panels/network/cc-network-panel.c b/panels/network/cc-network-panel.c index 51ea823f78d94d21c56e88bdc4cf2f4f2b6098c2..405b538cf59f2f34620839a33a5004f810e9e209 100644 --- a/panels/network/cc-network-panel.c +++ b/panels/network/cc-network-panel.c @@ -23,6 +23,8 @@ #include #include +#include "shell/cc-object-storage.h" + #include "cc-network-panel.h" #include "cc-network-resources.h" @@ -876,16 +878,24 @@ cc_network_panel_init (CcNetworkPanel *panel) /* add the virtual proxy device */ panel_add_proxy_device (panel); + /* Create and store a NMClient instance if it doesn't exist yet */ + if (!cc_object_storage_has_object (CC_OBJECT_NMCLIENT)) { + NMClient *client = nm_client_new (NULL, NULL); + cc_object_storage_add_object (CC_OBJECT_NMCLIENT, client); + g_object_unref (client); + } + /* use NetworkManager client */ - panel->client = nm_client_new (NULL, NULL); - g_signal_connect (panel->client, "notify::nm-running" , - G_CALLBACK (manager_running), panel); - g_signal_connect (panel->client, "notify::active-connections", - G_CALLBACK (active_connections_changed), panel); - g_signal_connect (panel->client, "device-added", - G_CALLBACK (device_added_cb), panel); - g_signal_connect (panel->client, "device-removed", - G_CALLBACK (device_removed_cb), panel); + panel->client = cc_object_storage_get_object (CC_OBJECT_NMCLIENT); + + g_signal_connect_object (panel->client, "notify::nm-running" , + G_CALLBACK (manager_running), panel, 0); + g_signal_connect_object (panel->client, "notify::active-connections", + G_CALLBACK (active_connections_changed), panel, 0); + g_signal_connect_object (panel->client, "device-added", + G_CALLBACK (device_added_cb), panel, 0); + g_signal_connect_object (panel->client, "device-removed", + G_CALLBACK (device_removed_cb), panel, 0); /* Setup ModemManager client */ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); @@ -907,8 +917,8 @@ cc_network_panel_init (CcNetworkPanel *panel) } /* add remote settings such as VPN settings as virtual devices */ - g_signal_connect (panel->client, NM_CLIENT_CONNECTION_ADDED, - G_CALLBACK (notify_connection_added_cb), panel); + g_signal_connect_object (panel->client, NM_CLIENT_CONNECTION_ADDED, + G_CALLBACK (notify_connection_added_cb), panel, 0); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (panel)); g_signal_connect_after (toplevel, "map", G_CALLBACK (on_toplevel_map), panel); diff --git a/panels/network/cc-wifi-panel.c b/panels/network/cc-wifi-panel.c index 2c1cd17b7fd836cc60bab1a7dc4e6ae9e209bb54..64321752cd4fca996e09814881fff482e28a40be 100644 --- a/panels/network/cc-wifi-panel.c +++ b/panels/network/cc-wifi-panel.c @@ -23,6 +23,7 @@ #include "net-device-wifi.h" #include "network-dialogs.h" +#include "shell/cc-object-storage.h" #include "shell/list-box-helper.h" #include @@ -421,7 +422,7 @@ rfkill_proxy_acquired_cb (GObject *source_object, GError *error; error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (error) { @@ -618,37 +619,47 @@ cc_wifi_panel_init (CcWifiPanel *self) self->cancellable = g_cancellable_new (); self->devices = g_ptr_array_new_with_free_func (g_object_unref); - /* Load NetworkManager */ - self->client = nm_client_new (NULL, NULL); - - g_signal_connect (self->client, - "device-added", - G_CALLBACK (device_added_cb), - self); - - g_signal_connect (self->client, - "device-removed", - G_CALLBACK (device_removed_cb), - self); + /* Create and store a NMClient instance if it doesn't exist yet */ + if (!cc_object_storage_has_object (CC_OBJECT_NMCLIENT)) + { + NMClient *client = nm_client_new (NULL, NULL); + cc_object_storage_add_object (CC_OBJECT_NMCLIENT, client); + g_object_unref (client); + } - g_signal_connect (self->client, - "notify::wireless-enabled", - G_CALLBACK (wireless_enabled_cb), - self); + /* Load NetworkManager */ + self->client = cc_object_storage_get_object (CC_OBJECT_NMCLIENT); + + g_signal_connect_object (self->client, + "device-added", + G_CALLBACK (device_added_cb), + self, + 0); + + g_signal_connect_object (self->client, + "device-removed", + G_CALLBACK (device_removed_cb), + self, + 0); + + g_signal_connect_object (self->client, + "notify::wireless-enabled", + G_CALLBACK (wireless_enabled_cb), + self, + 0); /* Load Wi-Fi devices */ load_wifi_devices (self); /* Acquire Airplane Mode proxy */ - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Rfkill", - "/org/gnome/SettingsDaemon/Rfkill", - "org.gnome.SettingsDaemon.Rfkill", - self->cancellable, - rfkill_proxy_acquired_cb, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Rfkill", + "/org/gnome/SettingsDaemon/Rfkill", + "org.gnome.SettingsDaemon.Rfkill", + self->cancellable, + rfkill_proxy_acquired_cb, + self); /* Handle comment-line arguments after loading devices */ handle_argv (self); diff --git a/panels/notifications/cc-notifications-panel.c b/panels/notifications/cc-notifications-panel.c index 1265b5b6fdd95ae8789255d6a58fe0ac97fdf170..0b1b834ca1c33cec8bd11c31f5fddb460e49ad65 100644 --- a/panels/notifications/cc-notifications-panel.c +++ b/panels/notifications/cc-notifications-panel.c @@ -25,6 +25,7 @@ #include #include +#include "shell/cc-object-storage.h" #include "shell/list-box-helper.h" #include "cc-notifications-panel.h" #include "cc-notifications-resources.h" @@ -150,7 +151,7 @@ on_perm_store_ready (GObject *source_object, GDBusProxy *proxy; GError *error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -241,15 +242,14 @@ cc_notifications_panel_init (CcNotificationsPanel *panel) gtk_widget_show (w); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.impl.portal.PermissionStore", - "/org/freedesktop/impl/portal/PermissionStore", - "org.freedesktop.impl.portal.PermissionStore", - panel->apps_load_cancellable, - on_perm_store_ready, - panel); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.impl.portal.PermissionStore", + "/org/freedesktop/impl/portal/PermissionStore", + "org.freedesktop.impl.portal.PermissionStore", + panel->apps_load_cancellable, + on_perm_store_ready, + panel); } static const char * diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c index f9b67a4583abf8b525349ea4f2303d9965226d9f..b78c17a4992894acaadafb822313cc92d6e23dcd 100644 --- a/panels/power/cc-power-panel.c +++ b/panels/power/cc-power-panel.c @@ -29,6 +29,7 @@ #include #endif +#include "shell/cc-object-storage.h" #include "shell/list-box-helper.h" #include "cc-power-panel.h" #include "cc-power-resources.h" @@ -1083,7 +1084,7 @@ got_screen_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_da CcPowerPanel *self; GDBusProxy *screen_proxy; - screen_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + screen_proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (screen_proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1096,8 +1097,8 @@ got_screen_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_da self->priv->screen_proxy = screen_proxy; /* we want to change the bar if the user presses brightness buttons */ - g_signal_connect (screen_proxy, "g-properties-changed", - G_CALLBACK (on_screen_property_change), self); + g_signal_connect_object (screen_proxy, "g-properties-changed", + G_CALLBACK (on_screen_property_change), self, 0); sync_screen_brightness (self); als_enabled_state_changed (self); @@ -1120,7 +1121,7 @@ got_kbd_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) CcPowerPanel *self; GDBusProxy *kbd_proxy; - kbd_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + kbd_proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (kbd_proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1133,8 +1134,8 @@ got_kbd_proxy_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) self->priv->kbd_proxy = kbd_proxy; /* we want to change the bar if the user presses brightness buttons */ - g_signal_connect (kbd_proxy, "g-properties-changed", - G_CALLBACK (on_kbd_property_change), self); + g_signal_connect_object (kbd_proxy, "g-properties-changed", + G_CALLBACK (on_kbd_property_change), self, 0); sync_kbd_brightness (self); } @@ -1440,13 +1441,31 @@ nm_device_changed (NMClient *client, gtk_widget_set_visible (priv->mobile_row, has_mobile_devices (priv->nm_client)); } +static void +setup_nm_client (CcPowerPanel *self, + NMClient *client) +{ + CcPowerPanelPrivate *priv = self->priv; + + priv->nm_client = client; + + g_signal_connect_object (priv->nm_client, "notify", + G_CALLBACK (nm_client_state_changed), self, 0); + g_signal_connect_object (priv->nm_client, "device-added", + G_CALLBACK (nm_device_changed), self, 0); + g_signal_connect_object (priv->nm_client, "device-removed", + G_CALLBACK (nm_device_changed), self, 0); + + nm_client_state_changed (priv->nm_client, NULL, self); + nm_device_changed (priv->nm_client, NULL, self); +} + static void nm_client_ready_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { CcPowerPanel *self; - CcPowerPanelPrivate *priv; NMClient *client; GError *error = NULL; @@ -1467,18 +1486,12 @@ nm_client_ready_cb (GObject *source_object, } self = user_data; - priv = self->priv; - priv->nm_client = client; - g_signal_connect (priv->nm_client, "notify", - G_CALLBACK (nm_client_state_changed), self); - g_signal_connect (priv->nm_client, "device-added", - G_CALLBACK (nm_device_changed), self); - g_signal_connect (priv->nm_client, "device-removed", - G_CALLBACK (nm_device_changed), self); + /* Setup the client */ + setup_nm_client (self, client); - nm_client_state_changed (priv->nm_client, NULL, self); - nm_device_changed (priv->nm_client, NULL, self); + /* Store the object in the cache too */ + cc_object_storage_add_object (CC_OBJECT_NMCLIENT, client); } #endif @@ -1648,13 +1661,12 @@ iio_proxy_appeared_cb (GDBusConnection *connection, GError *error = NULL; self->priv->iio_proxy = - g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "net.hadess.SensorProxy", - "/net/hadess/SensorProxy", - "net.hadess.SensorProxy", - NULL, &error); + cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "net.hadess.SensorProxy", + "/net/hadess/SensorProxy", + "net.hadess.SensorProxy", + NULL, &error); if (error != NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1887,29 +1899,35 @@ add_power_saving_section (CcPowerPanel *self) g_signal_connect (G_OBJECT (priv->mobile_switch), "notify::active", G_CALLBACK (mobile_switch_changed), self); - nm_client_new_async (priv->cancellable, nm_client_ready_cb, self); + /* Create and store a NMClient instance if it doesn't exist yet */ + if (cc_object_storage_has_object (CC_OBJECT_NMCLIENT)) + setup_nm_client (self, cc_object_storage_get_object (CC_OBJECT_NMCLIENT)); + else + nm_client_new_async (priv->cancellable, nm_client_ready_cb, self); g_signal_connect (G_OBJECT (priv->wifi_switch), "notify::active", G_CALLBACK (wifi_switch_changed), self); #endif #ifdef HAVE_BLUETOOTH - priv->bt_rfkill = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Rfkill", - "/org/gnome/SettingsDaemon/Rfkill", - "org.gnome.SettingsDaemon.Rfkill", - NULL, NULL); + + priv->bt_rfkill = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Rfkill", + "/org/gnome/SettingsDaemon/Rfkill", + "org.gnome.SettingsDaemon.Rfkill", + NULL, + NULL); + if (priv->bt_rfkill) { - priv->bt_properties = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Rfkill", - "/org/gnome/SettingsDaemon/Rfkill", - "org.freedesktop.DBus.Properties", - NULL, NULL); + priv->bt_properties = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Rfkill", + "/org/gnome/SettingsDaemon/Rfkill", + "org.freedesktop.DBus.Properties", + NULL, + NULL); } row = no_prelight_row_new (); @@ -1944,8 +1962,8 @@ add_power_saving_section (CcPowerPanel *self) gtk_widget_show_all (box); gtk_widget_set_no_show_all (row, TRUE); priv->bt_row = row; - g_signal_connect_swapped (G_OBJECT (priv->bt_rfkill), "g-properties-changed", - G_CALLBACK (bt_powered_state_changed), self); + g_signal_connect_object (priv->bt_rfkill, "g-properties-changed", + G_CALLBACK (bt_powered_state_changed), self, G_CONNECT_SWAPPED); g_signal_connect (G_OBJECT (priv->bt_switch), "notify::active", G_CALLBACK (bt_switch_changed), self); @@ -2509,24 +2527,22 @@ cc_power_panel_init (CcPowerPanel *self) priv->cancellable = g_cancellable_new (); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Power", - "/org/gnome/SettingsDaemon/Power", - "org.gnome.SettingsDaemon.Power.Screen", - priv->cancellable, - got_screen_proxy_cb, - self); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SettingsDaemon.Power", - "/org/gnome/SettingsDaemon/Power", - "org.gnome.SettingsDaemon.Power.Keyboard", - priv->cancellable, - got_kbd_proxy_cb, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Power", + "/org/gnome/SettingsDaemon/Power", + "org.gnome.SettingsDaemon.Power.Screen", + priv->cancellable, + got_screen_proxy_cb, + self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SettingsDaemon.Power", + "/org/gnome/SettingsDaemon/Power", + "org.gnome.SettingsDaemon.Power.Keyboard", + priv->cancellable, + got_kbd_proxy_cb, + self); priv->chassis_type = get_chassis_type (priv->cancellable); diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c index 55a1682b476158f4f2262eca3f92ed5cda92483c..4815c45205f1712351ab77357c2d7028390d4164 100644 --- a/panels/printers/cc-printers-panel.c +++ b/panels/printers/cc-printers-panel.c @@ -18,6 +18,8 @@ #include +#include "shell/cc-object-storage.h" + #include "cc-printers-panel.h" #include "cc-printers-resources.h" #include "pp-printer.h" @@ -608,14 +610,13 @@ attach_to_cups_notifier_cb (GObject *source_object, priv->subscription_renewal_id = g_timeout_add_seconds (RENEW_INTERVAL, renew_subscription, self); - priv->cups_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - 0, - NULL, - CUPS_DBUS_NAME, - CUPS_DBUS_PATH, - CUPS_DBUS_INTERFACE, - NULL, - &error); + priv->cups_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + CUPS_DBUS_NAME, + CUPS_DBUS_PATH, + CUPS_DBUS_INTERFACE, + NULL, + &error); if (!priv->cups_proxy) { diff --git a/panels/privacy/cc-privacy-panel.c b/panels/privacy/cc-privacy-panel.c index 428dafef7c9e17b195be87373851945e3d048dd5..daa050a41431d2039ada6c1c37cf86f9e3e01f03 100644 --- a/panels/privacy/cc-privacy-panel.c +++ b/panels/privacy/cc-privacy-panel.c @@ -18,6 +18,7 @@ * Author: Matthias Clasen */ +#include "shell/cc-object-storage.h" #include "shell/list-box-helper.h" #include "cc-privacy-panel.h" #include "cc-privacy-resources.h" @@ -463,7 +464,7 @@ on_gclue_manager_ready (GObject *source_object, GDBusProxy *proxy; GError *error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -475,10 +476,11 @@ on_gclue_manager_ready (GObject *source_object, self = user_data; self->priv->gclue_manager = proxy; - g_signal_connect (self->priv->gclue_manager, - "g-properties-changed", - G_CALLBACK (on_gclue_manager_props_changed), - self); + g_signal_connect_object (self->priv->gclue_manager, + "g-properties-changed", + G_CALLBACK (on_gclue_manager_props_changed), + self, + 0); update_location_label (self); } @@ -783,7 +785,7 @@ on_perm_store_ready (GObject *source_object, GVariant *params; GError *error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (proxy == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -842,25 +844,23 @@ add_location (CcPrivacyPanel *self) g_free, g_object_unref); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.GeoClue2", - "/org/freedesktop/GeoClue2/Manager", - "org.freedesktop.GeoClue2.Manager", - priv->cancellable, - on_gclue_manager_ready, - self); - - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.impl.portal.PermissionStore", - "/org/freedesktop/impl/portal/PermissionStore", - "org.freedesktop.impl.portal.PermissionStore", - priv->cancellable, - on_perm_store_ready, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.GeoClue2", + "/org/freedesktop/GeoClue2/Manager", + "org.freedesktop.GeoClue2.Manager", + priv->cancellable, + on_gclue_manager_ready, + self); + + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.impl.portal.PermissionStore", + "/org/freedesktop/impl/portal/PermissionStore", + "org.freedesktop.impl.portal.PermissionStore", + priv->cancellable, + on_perm_store_ready, + self); } static void diff --git a/panels/region/cc-region-panel.c b/panels/region/cc-region-panel.c index 48c0d7ac0403d1a3ac0678be0fe043997a1c5e4a..232c3faad1b7f474c28a9d93a88ec6d997c3fec7 100644 --- a/panels/region/cc-region-panel.c +++ b/panels/region/cc-region-panel.c @@ -26,6 +26,7 @@ #include #include +#include "shell/cc-object-storage.h" #include "shell/list-box-helper.h" #include "cc-region-panel.h" #include "cc-region-resources.h" @@ -1796,7 +1797,7 @@ session_proxy_ready (GObject *source, GDBusProxy *proxy; GError *error = NULL; - proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); if (!proxy) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1832,15 +1833,14 @@ cc_region_panel_init (CcRegionPanel *self) priv->cancellable = g_cancellable_new (); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.gnome.SessionManager", - "/org/gnome/SessionManager", - "org.gnome.SessionManager", - priv->cancellable, - session_proxy_ready, - self); + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + "org.gnome.SessionManager", + "/org/gnome/SessionManager", + "org.gnome.SessionManager", + priv->cancellable, + session_proxy_ready, + self); setup_login_button (self); setup_language_section (self); diff --git a/shell/cc-application.c b/shell/cc-application.c index 8beb6171449ffc0393d29a43a64b2b66ae8e9e6a..144cbeeb67cd5d7aa384e64b9e9e0e234068f100 100644 --- a/shell/cc-application.c +++ b/shell/cc-application.c @@ -26,6 +26,7 @@ #include #include "cc-application.h" +#include "cc-object-storage.h" #include "cc-panel-loader.h" #include "cc-shell-log.h" #include "cc-window.h" @@ -264,6 +265,15 @@ cc_application_startup (GApplication *application) self->window = cc_window_new (GTK_APPLICATION (application)); } +static void +cc_application_finalize (GObject *object) +{ + /* Destroy the object storage cache when finalizing */ + cc_object_storage_destroy (); + + G_OBJECT_CLASS (cc_application_parent_class)->finalize (object); +} + static GObject * cc_application_constructor (GType type, guint n_construct_params, @@ -289,6 +299,7 @@ cc_application_class_init (CcApplicationClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GApplicationClass *application_class = G_APPLICATION_CLASS (klass); + object_class->finalize = cc_application_finalize; object_class->constructor = cc_application_constructor; application_class->activate = cc_application_activate; application_class->startup = cc_application_startup; @@ -299,6 +310,8 @@ cc_application_class_init (CcApplicationClass *klass) static void cc_application_init (CcApplication *self) { + cc_object_storage_initialize (); + g_application_add_main_option_entries (G_APPLICATION (self), all_options); } diff --git a/shell/cc-object-storage.c b/shell/cc-object-storage.c new file mode 100644 index 0000000000000000000000000000000000000000..0e708dc3b109d4f860b98b0043c1b38419d50ff6 --- /dev/null +++ b/shell/cc-object-storage.c @@ -0,0 +1,438 @@ +/* cc-object-storage.h + * + * Copyright 2018 Georges Basile Stavracas Neto + * + * 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 2 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 . + */ + +#define G_LOG_DOMAIN "cc-object-storage" + +#include "cc-object-storage.h" + +struct _CcObjectStorage +{ + GObject parent_instance; + + GHashTable *id_to_object; +}; + +G_DEFINE_TYPE (CcObjectStorage, cc_object_storage, G_TYPE_OBJECT) + +/* Singleton instance */ +CcObjectStorage *_instance = NULL; + +/* GTask API to create a new D-Bus proxy */ +typedef struct +{ + GBusType bus_type; + GDBusProxyFlags flags; + gchar *name; + gchar *path; + gchar *interface; + gboolean cached; +} TaskData; + +static TaskData* +task_data_new (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface) +{ + TaskData *data = g_slice_new (TaskData); + data->bus_type = bus_type; + data->flags =flags; + data->name = g_strdup (name); + data->path = g_strdup (path); + data->interface = g_strdup (interface); + data->cached = FALSE; + + return data; +} + +static void +task_data_free (TaskData *data) +{ + g_free (data->name); + g_free (data->path); + g_free (data->interface); + g_slice_free (TaskData, data); +} + +static void +create_dbus_proxy_in_thread_cb (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + g_autoptr(GDBusProxy) proxy = NULL; + g_autoptr(GError) local_error = NULL; + TaskData *data = task_data; + + proxy = g_dbus_proxy_new_for_bus_sync (data->bus_type, + data->flags, + NULL, + data->name, + data->path, + data->interface, + cancellable, + &local_error); + + if (local_error) + { + g_task_return_error (task, local_error); + return; + } + + g_task_return_pointer (task, g_object_ref (g_steal_pointer (&proxy)), g_object_unref); +} + +static void +cc_object_storage_finalize (GObject *object) +{ + CcObjectStorage *self = (CcObjectStorage *)object; + + g_debug ("Destroying cached objects"); + + g_clear_pointer (&self->id_to_object, g_hash_table_destroy); + + G_OBJECT_CLASS (cc_object_storage_parent_class)->finalize (object); +} + +static void +cc_object_storage_class_init (CcObjectStorageClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = cc_object_storage_finalize; +} + +static void +cc_object_storage_init (CcObjectStorage *self) +{ + self->id_to_object = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); +} + +/** + * cc_object_storage_has_object: + * @key: the unique string identifier of the object + * + * Checks whether there is an object associated with @key. + * + * Returns: %TRUE if the object is stored, %FALSE otherwise. + */ +gboolean +cc_object_storage_has_object (const gchar *key) +{ + g_assert (CC_IS_OBJECT_STORAGE (_instance)); + g_assert (key != NULL); + + return g_hash_table_contains (_instance->id_to_object, key); +} + +/** + * cc_object_storage_add_object: + * @key: the unique string identifier of the object + * @object: (type GObject): the object to be stored + * + * Adds @object to the object storage. It is a programming error to try to + * add an object that was already added. + * + * @object must be a GObject. + * + * Always check if the object is stored with cc_object_storage_has_object() + * before calling this function. + */ +void +cc_object_storage_add_object (const gchar *key, + gpointer object) +{ + /* Trying to add an object that was already added is a hard error. Each + * object must be added once, and only once, over the entire lifetime + * of the application. + */ + g_assert (CC_IS_OBJECT_STORAGE (_instance)); + g_assert (key != NULL); + g_assert (G_IS_OBJECT (object)); + g_assert (!g_hash_table_contains (_instance->id_to_object, key)); + + g_debug ("Adding object %s (%s → %p) to the storage", + g_type_name (G_OBJECT_TYPE (object)), + key, + object); + + g_hash_table_insert (_instance->id_to_object, g_strdup (key), g_object_ref (object)); +} + +/** + * cc_object_storage_get_object: + * @key: the unique string identifier of the object + * + * Retrieves the object associated with @key. It is a programming error to + * try to retrieve an object before adding it. + * + * Always check if the object is stored with cc_object_storage_has_object() + * before calling this function. + * + * Returns: (transfer full): the GObject associated with @key. + */ +gpointer +cc_object_storage_get_object (const gchar *key) +{ + /* Trying to peek an object that was not yet added is a hard error. Users + * of this API need to first check if the object is available with + * cc_object_storage_has_object(). + */ + g_assert (CC_IS_OBJECT_STORAGE (_instance)); + g_assert (key != NULL); + g_assert (g_hash_table_contains (_instance->id_to_object, key)); + + return g_object_ref (g_hash_table_lookup (_instance->id_to_object, key)); +} + +/** + * cc_object_storage_create_dbus_proxy_sync: + * @name: the D-Bus name + * @flags: the D-Bus proxy flags + * @path: the D-Bus object path + * @interface: the D-Bus interface name + * @cancellable: (nullable): #GCancellable to cancel the operation + * @error: (nullable): return location for a #GError + * + * Synchronously create a #GDBusProxy with @name, @path and @interface, + * stores it in the cache, and returns the newly created proxy. + * + * If a proxy with that signature is already created, it will be used + * instead of creating a new one. + * + * Returns: (transfer full)(nullable): the new #GDBusProxy. + */ +gpointer +cc_object_storage_create_dbus_proxy_sync (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GDBusProxy) proxy = NULL; + g_autoptr(GError) local_error = NULL; + g_autofree gchar *key = NULL; + + g_assert (CC_IS_OBJECT_STORAGE (_instance)); + g_assert (name && *name); + g_assert (path && *path); + g_assert (interface && *interface); + g_assert (!error || !*error); + + key = g_strdup_printf ("CcObjectStorage::dbus-proxy(%s,%s,%s)", name, path, interface); + + /* Check if a DBus proxy with that signature is already available; if it is, + * return that instead of a new one. + */ + if (g_hash_table_contains (_instance->id_to_object, key)) + return cc_object_storage_get_object (key); + + proxy = g_dbus_proxy_new_for_bus_sync (bus_type, + flags, + NULL, + name, + path, + interface, + cancellable, + &local_error); + + if (local_error) + { + g_propagate_error (error, local_error); + return NULL; + } + + /* Store the newly created D-Bus proxy */ + cc_object_storage_add_object (key, proxy); + + return g_steal_pointer (&proxy); +} + + +/** + * cc_object_storage_create_dbus_proxy: + * @name: the D-Bus name + * @flags: the D-Bus proxy flags + * @path: the D-Bus object path + * @interface: the D-Bus interface name + * @cancellable: (nullable): #GCancellable to cancel the operation + * @callback: callback for when the async operation is finished + * @user_data: user data for @callback + * + * Asynchronously create a #GDBusProxy with @name, @path and @interface. + * + * If a proxy with that signature is already created, it will be used instead of + * creating a new one. + * + * It is a programming error to create the an identical proxy while asynchronously + * creating one. Not cancelling this operation will result in an assertion failure + * when calling cc_object_storage_create_dbus_proxy_finish(). + */ +void +cc_object_storage_create_dbus_proxy (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + g_autofree gchar *key = NULL; + TaskData *data = NULL; + + g_assert (CC_IS_OBJECT_STORAGE (_instance)); + g_assert (name && *name); + g_assert (path && *path); + g_assert (interface && *interface); + g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); + + data = task_data_new (bus_type, flags, name, path, interface); + + task = g_task_new (_instance, cancellable, callback, user_data); + g_task_set_source_tag (task, cc_object_storage_create_dbus_proxy); + g_task_set_task_data (task, data, (GDestroyNotify) task_data_free); + + /* Check if the D-Bus proxy is already created */ + key = g_strdup_printf ("CcObjectStorage::dbus-proxy(%s,%s,%s)", name, path, interface); + + if (g_hash_table_contains (_instance->id_to_object, key)) + { + /* Mark this GTask as already cached, so we can call the right assertions + * on the callback + * */ + data->cached = TRUE; + + g_debug ("Found in cache the D-Bus proxy %s", key); + + g_task_return_pointer (task, cc_object_storage_get_object (key), g_object_unref); + return; + } + + g_task_run_in_thread (task, create_dbus_proxy_in_thread_cb); +} + +/** + * cc_object_storage_create_dbus_proxy_finish: + * @result: + * @error: (nullable): return location for a #GError + * + * Finishes a D-Bus proxy creation started by cc_object_storage_create_dbus_proxy(). + * + * Synchronously create a #GDBusProxy with @name, @path and @interface, + * stores it in the cache, and returns the newly created proxy. + * + * If a proxy with that signature is already created, it will be used + * instead of creating a new one. + * + * Returns: (transfer full)(nullable): the new #GDBusProxy. + */ +gpointer +cc_object_storage_create_dbus_proxy_finish (GAsyncResult *result, + GError **error) +{ + g_autoptr(GDBusProxy) proxy = NULL; + g_autoptr(GError) local_error = NULL; + g_autofree gchar *key = NULL; + TaskData *task_data; + GTask *task; + + task = G_TASK (result); + + g_assert (task && G_TASK (result)); + g_assert (!error || !*error); + + task_data = g_task_get_task_data (task); + + key = g_strdup_printf ("CcObjectStorage::dbus-proxy(%s,%s,%s)", + task_data->name, + task_data->path, + task_data->interface); + + /* Either we have the object stored right when trying to create it - in which case, + * task_data->cached == TRUE and cc_object_storage_has_object (key) == TRUE - or we + * didn't have a cached proxy before, and we shouldn't have it now. + * + * This is to force consumers of this code to *never* try to create the same D-Bus + * proxy asynchronously multiple times. Trying to do so is considered a programming + * error. + */ + g_assert (task_data != NULL); + g_assert (task_data->cached == cc_object_storage_has_object (key)); + + /* Retrieve the newly created proxy */ + proxy = g_task_propagate_pointer (task, &local_error); + + /* If the proxy is not cached, do the normal caching routine */ + if (local_error) + { + g_propagate_error (error, local_error); + return NULL; + } + + /* If the proxy is already cached, destroy the newly created and used the cached proxy + * instead. + */ + if (cc_object_storage_has_object (key)) + return cc_object_storage_get_object (key); + + /* Store the newly created D-Bus proxy */ + cc_object_storage_add_object (key, proxy); + + return g_steal_pointer (&proxy); +} + +/** + * cc_object_storage_init: + * + * Initializes the single CcObjectStorage. This must be called only once, + * and before every other method of this object. + */ +void +cc_object_storage_initialize (void) +{ + g_assert (_instance == NULL); + + if (g_once_init_enter (&_instance)) + { + CcObjectStorage *instance = g_object_new (CC_TYPE_OBJECT_STORAGE, NULL); + + g_debug ("Initializing object storage"); + + g_once_init_leave (&_instance, instance); + } +} + +/** + * cc_object_storage_destroy: + * + * Destroys the instance of #CcObjectStorage. This must be called only + * once during the application lifetime. It is a programming error to + * call this function multiple times + */ +void +cc_object_storage_destroy (void) +{ + g_assert (_instance != NULL); + + g_clear_object (&_instance); +} diff --git a/shell/cc-object-storage.h b/shell/cc-object-storage.h new file mode 100644 index 0000000000000000000000000000000000000000..efea0e294e454ef0a841d893fc8d1a0772dde1df --- /dev/null +++ b/shell/cc-object-storage.h @@ -0,0 +1,65 @@ +/* cc-object-storage.h + * + * Copyright 2018 Georges Basile Stavracas Neto + * + * 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 2 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 . + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +/* Default storage keys */ +#define CC_OBJECT_NMCLIENT "CcObjectStorage::nm-client" + + +#define CC_TYPE_OBJECT_STORAGE (cc_object_storage_get_type()) + +G_DECLARE_FINAL_TYPE (CcObjectStorage, cc_object_storage, CC, OBJECT_STORAGE, GObject) + +gboolean cc_object_storage_has_object (const gchar *key); + +void cc_object_storage_add_object (const gchar *key, + gpointer object); + +gpointer cc_object_storage_get_object (const gchar *key); + +gpointer cc_object_storage_create_dbus_proxy_sync (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface, + GCancellable *cancellable, + GError **error); + +void cc_object_storage_create_dbus_proxy (GBusType bus_type, + GDBusProxyFlags flags, + const gchar *name, + const gchar *path, + const gchar *interface, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gpointer cc_object_storage_create_dbus_proxy_finish (GAsyncResult *result, + GError **error); + +void cc_object_storage_initialize (void); + +void cc_object_storage_destroy (void); + +G_END_DECLS diff --git a/shell/cc-window.c b/shell/cc-window.c index f7593dc55aeb9f3a8a8331d77308f61dde3cf4e2..fea3cf567bf1f3174052b37c876409120acbb719 100644 --- a/shell/cc-window.c +++ b/shell/cc-window.c @@ -20,6 +20,8 @@ * Author: Thomas Wood */ +#define G_LOG_DOMAIN "cc-window" + #include #include "cc-window.h" @@ -31,6 +33,7 @@ #include #include #include +#include #include "cc-panel.h" #include "cc-shell.h" @@ -117,14 +120,21 @@ activate_panel (CcWindow *self, const gchar *name, GIcon *gicon) { + g_autoptr (GTimer) timer = NULL; GtkWidget *box, *title_widget; const gchar *icon_name; + gdouble ellapsed_time; if (!id) return FALSE; + timer = g_timer_new (); + g_settings_set_string (self->settings, "last-panel", id); + /* Begin the profile */ + g_timer_start (timer); + self->current_panel = GTK_WIDGET (cc_panel_loader_load_by_name (CC_SHELL (self), id, parameters)); cc_shell_set_active_panel (CC_SHELL (self), CC_PANEL (self->current_panel)); gtk_widget_show (self->current_panel); @@ -156,6 +166,13 @@ activate_panel (CcWindow *self, self->current_panel_box = box; + /* Finish profiling */ + g_timer_stop (timer); + + ellapsed_time = g_timer_elapsed (timer, NULL); + + g_debug ("Time to open panel '%s': %lfs", name, ellapsed_time); + return TRUE; } @@ -288,12 +305,15 @@ set_active_panel_from_id (CcShell *shell, GVariant *parameters, GError **error) { + g_autoptr(GIcon) gicon = NULL; + g_autofree gchar *name = NULL; GtkTreeIter iter; - gboolean iter_valid; - gchar *name = NULL; - GIcon *gicon = NULL; - CcWindow *self = CC_WINDOW (shell); GtkWidget *old_panel; + CcWindow *self; + gboolean iter_valid; + gboolean activated; + + self = CC_WINDOW (shell); /* When loading the same panel again, just set its parameters */ if (g_strcmp0 (self->current_panel_id, start_id) == 0) @@ -332,26 +352,25 @@ set_active_panel_from_id (CcShell *shell, if (!name) { g_warning ("Could not find settings panel \"%s\"", start_id); + return TRUE; } - else if (!activate_panel (CC_WINDOW (shell), start_id, parameters, name, gicon)) - { - /* Failed to activate the panel for some reason, - * let's keep the old panel around instead */ - } - else - { - /* Successful activation */ - g_free (self->current_panel_id); - self->current_panel_id = g_strdup (start_id); - if (old_panel) - gtk_container_remove (GTK_CONTAINER (self->stack), old_panel); + /* Activate the panel */ + activated = activate_panel (CC_WINDOW (shell), start_id, parameters, name, gicon); - cc_panel_list_set_active_panel (CC_PANEL_LIST (self->panel_list), start_id); - } + /* Failed to activate the panel for some reason, let's keep the old + * panel around instead */ + if (!activated) + return TRUE; + + /* Successful activation */ + g_free (self->current_panel_id); + self->current_panel_id = g_strdup (start_id); + + if (old_panel) + gtk_container_remove (GTK_CONTAINER (self->stack), old_panel); - g_clear_pointer (&name, g_free); - g_clear_object (&gicon); + cc_panel_list_set_active_panel (CC_PANEL_LIST (self->panel_list), start_id); return TRUE; } @@ -370,13 +389,10 @@ set_active_panel (CcWindow *shell, /* set the new panel */ if (panel) - { - shell->active_panel = g_object_ref (panel); - } + shell->active_panel = g_object_ref (panel); else - { - shell_show_overview_page (shell); - } + shell_show_overview_page (shell); + g_object_notify (G_OBJECT (shell), "active-panel"); } } @@ -779,4 +795,4 @@ cc_window_set_search_item (CcWindow *center, gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (center->search_bar), TRUE); gtk_entry_set_text (GTK_ENTRY (center->search_entry), search); gtk_editable_set_position (GTK_EDITABLE (center->search_entry), -1); -} \ No newline at end of file +} diff --git a/shell/meson.build b/shell/meson.build index d9364521b6614a429c9f2db8c681c32f6933f991..0946ada744244d7057c9a98e5761159fba8b8723 100644 --- a/shell/meson.build +++ b/shell/meson.build @@ -46,6 +46,7 @@ common_sources = files( 'cc-application.c', 'cc-editable-entry.c', 'cc-hostname-entry.c', + 'cc-object-storage.c', 'cc-panel-loader.c', 'cc-panel.c', 'cc-shell-category-view.c',