Commit 52d060cc authored by Vincent Untz's avatar Vincent Untz
Browse files

panel: Load objects from GSettings on startup

This is far from the end of porting the panel objects to GSettings, but
we can now have the full default panel!

The object loading code was moved to its own file.
parent 8b79ec6d
......@@ -67,6 +67,7 @@ panel_sources = \
panel-ditem-editor.c \
panel-layout.c \
panel-modules.c \
panel-object-loader.c \
panel-applet-info.c
panel_headers = \
......@@ -116,6 +117,7 @@ panel_headers = \
panel-icon-names.h \
panel-layout.h \
panel-modules.h \
panel-object-loader.h \
panel-schemas.h \
panel-applet-info.h
......
......@@ -14,6 +14,7 @@
#include <glib/gi18n.h>
#include <gdk/gdkx.h>
#include <libpanel-util/panel-glib.h>
#include <libpanel-util/panel-show.h>
#include "button-widget.h"
......@@ -33,8 +34,7 @@
#include "panel-globals.h"
#include "panel-properties-dialog.h"
#include "panel-lockdown.h"
#define SMALL_ICON_SIZE 20
#include "panel-schemas.h"
static GSList *registered_applets = NULL;
static GSList *queued_position_saves = NULL;
......@@ -788,276 +788,6 @@ panel_applet_destroy (GtkWidget *widget,
g_free (info);
}
typedef struct {
char *id;
PanelObjectType type;
char *toplevel_id;
int position;
guint right_stick : 1;
} PanelAppletToLoad;
/* Each time those lists get both empty,
* panel_applet_queue_initial_unhide_toplevels() should be called */
static GSList *panel_applets_to_load = NULL;
static GSList *panel_applets_loading = NULL;
/* We have a timeout to always unhide toplevels after a delay, in case of some
* blocking applet */
#define UNHIDE_TOPLEVELS_TIMEOUT_SECONDS 5
static guint panel_applet_unhide_toplevels_timeout = 0;
static gboolean panel_applet_have_load_idle = FALSE;
static void
free_applet_to_load (PanelAppletToLoad *applet)
{
g_free (applet->id);
applet->id = NULL;
g_free (applet->toplevel_id);
applet->toplevel_id = NULL;
g_free (applet);
}
gboolean
panel_applet_on_load_queue (const char *id)
{
GSList *li;
for (li = panel_applets_to_load; li != NULL; li = li->next) {
PanelAppletToLoad *applet = li->data;
if (strcmp (applet->id, id) == 0)
return TRUE;
}
for (li = panel_applets_loading; li != NULL; li = li->next) {
PanelAppletToLoad *applet = li->data;
if (strcmp (applet->id, id) == 0)
return TRUE;
}
return FALSE;
}
/* This doesn't do anything if the initial unhide already happened */
static gboolean
panel_applet_queue_initial_unhide_toplevels (gpointer user_data)
{
GSList *l;
if (panel_applet_unhide_toplevels_timeout != 0) {
g_source_remove (panel_applet_unhide_toplevels_timeout);
panel_applet_unhide_toplevels_timeout = 0;
}
for (l = panel_toplevel_list_toplevels (); l != NULL; l = l->next)
panel_toplevel_queue_initial_unhide ((PanelToplevel *) l->data);
return FALSE;
}
void
panel_applet_stop_loading (const char *id)
{
PanelAppletToLoad *applet;
GSList *l;
for (l = panel_applets_loading; l; l = l->next) {
applet = l->data;
if (strcmp (applet->id, id) == 0)
break;
}
/* this can happen if we reload an applet after it crashed,
* for example */
if (l != NULL) {
panel_applets_loading = g_slist_delete_link (panel_applets_loading, l);
free_applet_to_load (applet);
}
if (panel_applets_loading == NULL && panel_applets_to_load == NULL)
panel_applet_queue_initial_unhide_toplevels (NULL);
}
static gboolean
panel_applet_load_idle_handler (gpointer dummy)
{
PanelObjectType applet_type;
PanelAppletToLoad *applet = NULL;
PanelToplevel *toplevel = NULL;
PanelWidget *panel_widget;
GSList *l;
if (!panel_applets_to_load) {
panel_applet_have_load_idle = FALSE;
return FALSE;
}
for (l = panel_applets_to_load; l; l = l->next) {
applet = l->data;
toplevel = panel_toplevel_get_by_id (applet->toplevel_id);
if (toplevel)
break;
}
if (!l) {
/* All the remaining applets don't have a panel */
for (l = panel_applets_to_load; l; l = l->next)
free_applet_to_load (l->data);
g_slist_free (panel_applets_to_load);
panel_applets_to_load = NULL;
panel_applet_have_load_idle = FALSE;
if (panel_applets_loading == NULL) {
/* unhide any potential initially hidden toplevel */
panel_applet_queue_initial_unhide_toplevels (NULL);
}
return FALSE;
}
panel_applets_to_load = g_slist_delete_link (panel_applets_to_load, l);
panel_applets_loading = g_slist_append (panel_applets_loading, applet);
panel_widget = panel_toplevel_get_panel_widget (toplevel);
if (applet->right_stick) {
if (!panel_widget->packed)
applet->position = panel_widget->size - applet->position;
else
applet->position = -1;
}
/* We load applets asynchronously, so we specifically don't call
* panel_applet_stop_loading() for this type. However, in case of
* failure during the load, we might call panel_applet_stop_loading()
* synchronously, which will make us lose the content of the applet
* variable. So we save the type to be sure we always ignore the
* applets. */
applet_type = applet->type;
switch (applet_type) {
case PANEL_OBJECT_APPLET:
panel_applet_frame_load_from_gconf (
panel_widget,
applet->position,
applet->id);
break;
case PANEL_OBJECT_MENU:
panel_menu_button_load_from_gconf (panel_widget,
applet->position,
TRUE,
applet->id);
break;
case PANEL_OBJECT_LAUNCHER:
launcher_load_from_gconf (panel_widget,
applet->position,
applet->id);
break;
case PANEL_OBJECT_ACTION:
panel_action_button_load_from_gconf (
panel_widget,
applet->position,
TRUE,
applet->id);
break;
case PANEL_OBJECT_MENU_BAR:
panel_menu_bar_load_from_gconf (
panel_widget,
applet->position,
TRUE,
applet->id);
break;
case PANEL_OBJECT_SEPARATOR:
panel_separator_load_from_gconf (panel_widget,
applet->position,
applet->id);
break;
default:
g_assert_not_reached ();
break;
}
/* Only the real applets will do a late stop_loading */
if (applet_type != PANEL_OBJECT_APPLET)
panel_applet_stop_loading (applet->id);
return TRUE;
}
void
panel_applet_queue_applet_to_load (const char *id,
PanelObjectType type,
const char *toplevel_id,
int position,
gboolean right_stick)
{
PanelAppletToLoad *applet;
if (!toplevel_id) {
g_warning ("No toplevel on which to load object '%s'\n", id);
return;
}
applet = g_new0 (PanelAppletToLoad, 1);
applet->id = g_strdup (id);
applet->type = type;
applet->toplevel_id = g_strdup (toplevel_id);
applet->position = position;
applet->right_stick = right_stick != FALSE;
panel_applets_to_load = g_slist_prepend (panel_applets_to_load, applet);
}
static int
panel_applet_compare (const PanelAppletToLoad *a,
const PanelAppletToLoad *b)
{
int c;
if ((c = strcmp (a->toplevel_id, b->toplevel_id)))
return c;
else if (a->right_stick != b->right_stick)
return b->right_stick ? -1 : 1;
else
return a->position - b->position;
}
void
panel_applet_load_queued_applets (gboolean initial_load)
{
if (!panel_applets_to_load) {
panel_applet_queue_initial_unhide_toplevels (NULL);
return;
}
if (panel_applets_to_load && panel_applet_unhide_toplevels_timeout == 0) {
/* Install a timeout to make sure we don't block the
* unhiding because of an applet that doesn't load */
panel_applet_unhide_toplevels_timeout =
g_timeout_add_seconds (UNHIDE_TOPLEVELS_TIMEOUT_SECONDS,
panel_applet_queue_initial_unhide_toplevels,
NULL);
}
panel_applets_to_load = g_slist_sort (panel_applets_to_load,
(GCompareFunc) panel_applet_compare);
if ( ! panel_applet_have_load_idle) {
/* on panel startup, we don't care about redraws of the
* toplevels since they are hidden, so we give a higher
* priority to loading of applets */
if (initial_load)
g_idle_add_full (G_PRIORITY_HIGH_IDLE,
panel_applet_load_idle_handler,
NULL, NULL);
else
g_idle_add (panel_applet_load_idle_handler, NULL);
panel_applet_have_load_idle = TRUE;
}
}
static G_CONST_RETURN char *
panel_applet_get_toplevel_id (AppletInfo *applet)
{
......
......@@ -52,7 +52,6 @@ AppletInfo *panel_applet_register (GtkWidget *applet,
gboolean exactpos,
PanelObjectType type,
const char *id);
void panel_applet_stop_loading (const char *id);
const char *panel_applet_get_id (AppletInfo *info);
const char *panel_applet_get_id_by_widget (GtkWidget *widget);
......@@ -63,15 +62,6 @@ GSList *panel_applet_list_applets (void);
void panel_applet_clean (AppletInfo *info);
void panel_applet_queue_applet_to_load (const char *id,
PanelObjectType type,
const char *toplevel_id,
int position,
gboolean right_stick);
void panel_applet_load_queued_applets (gboolean initial_load);
gboolean panel_applet_on_load_queue (const char *id);
void panel_applet_add_callback (AppletInfo *info,
const gchar *callback_name,
const gchar *stock_item,
......
......@@ -41,6 +41,7 @@
#include "panel-marshal.h"
#include "panel-background.h"
#include "panel-lockdown.h"
#include "panel-object-loader.h"
#include "panel-stock-icons.h"
#include "xstuff.h"
#include "panel-compatibility.h"
......@@ -53,7 +54,7 @@ static void panel_applet_frame_loading_failed (const char *iid,
PanelWidget *panel,
const char *id);
static void panel_applet_frame_load (const gchar *iid,
static void panel_applet_frame_load_helper (const gchar *iid,
PanelWidget *panel,
int position,
gboolean exactpos,
......@@ -582,7 +583,7 @@ _panel_applet_frame_activated (PanelAppletFrame *frame,
panel_applet_frame_init_properties (frame);
panel_applet_stop_loading (frame_act->id);
panel_object_loader_stop_loading (frame_act->id);
panel_applet_frame_activating_free (frame_act);
}
......@@ -697,8 +698,8 @@ panel_applet_frame_reload_response (GtkWidget *dialog,
panel_applet_clean (info);
}
panel_applet_frame_load (iid, panel,
position, TRUE, id);
panel_applet_frame_load_helper (iid, panel,
position, TRUE, id);
g_free (iid);
g_free (id);
......@@ -931,15 +932,15 @@ panel_applet_frame_loading_failed (const char *iid,
/* Note: this call will free the memory for id, so the variable should
* not get accessed afterwards. */
panel_applet_stop_loading (id);
panel_object_loader_stop_loading (id);
}
static void
panel_applet_frame_load (const gchar *iid,
PanelWidget *panel,
int position,
gboolean exactpos,
const char *id)
panel_applet_frame_load_helper (const gchar *iid,
PanelWidget *panel,
int position,
gboolean exactpos,
const char *id)
{
PanelAppletFrameActivating *frame_act;
......@@ -949,12 +950,12 @@ panel_applet_frame_load (const gchar *iid,
if (g_slist_find_custom (no_reload_applets, id,
(GCompareFunc) strcmp)) {
panel_applet_stop_loading (id);
panel_object_loader_stop_loading (id);
return;
}
if (panel_lockdown_is_applet_disabled (panel_lockdown_get (), iid)) {
panel_applet_stop_loading (id);
panel_object_loader_stop_loading (id);
return;
}
......@@ -971,23 +972,24 @@ panel_applet_frame_load (const gchar *iid,
}
void
panel_applet_frame_load_from_gconf (PanelWidget *panel_widget,
int position,
const char *id)
panel_applet_frame_load (GSettings *settings,
PanelWidget *panel_widget,
int position,
const char *id)
{
gchar *applet_iid;
g_return_if_fail (panel_widget != NULL);
g_return_if_fail (id != NULL);
applet_iid = panel_compatibility_get_applet_iid (id);
applet_iid = panel_compatibility_get_applet_iid (settings, id);
if (!applet_iid) {
panel_applet_stop_loading (id);
panel_object_loader_stop_loading (id);
return;
}
panel_applet_frame_load (applet_iid, panel_widget,
position, TRUE, id);
panel_applet_frame_load_helper (applet_iid, panel_widget,
position, TRUE, id);
g_free (applet_iid);
}
......
......@@ -83,7 +83,8 @@ void panel_applet_frame_create (PanelToplevel *toplevel,
int position,
const char *iid);
void panel_applet_frame_load_from_gconf (PanelWidget *panel_widget,
void panel_applet_frame_load (GSettings *settings,
PanelWidget *panel_widget,
int position,
const char *id);
......
......@@ -23,10 +23,13 @@
#include <config.h>
#include "panel-compatibility.h"
#include <libpanel-util/panel-glib.h>
#include "panel-profile.h"
#include "panel-applets-manager.h"
#include "panel-profile.h"
#include "panel-schemas.h"
#include "panel-compatibility.h"
void
panel_compatiblity_migrate_settings_menu_button (GConfClient *client,
......@@ -49,66 +52,42 @@ panel_compatiblity_migrate_settings_menu_button (GConfClient *client,
}
gchar *
panel_compatibility_get_applet_iid (const gchar *id)
panel_compatibility_get_applet_iid (GSettings *settings,
const gchar *id)
{
GConfClient *client = panel_gconf_get_client ();
PanelAppletInfo *info;
const char *key;
gchar *applet_iid;
gchar *object_iid;
gboolean needs_migration;
const char *iid;
/*
* There are two compatibility steps here:
*
* 1) we need to migrate from bonobo_iid to applet_iid if there's no
* value in the applet_iid key. Always.
*
* 2) we need to try to migrate the iid to a new iid. We can't assume
* that the fact that the applet_iid key was used mean anything
* since the value there could well be a bonobo iid.
* The reason we really have to try to migrate first is this case:
* if an applet was added with the bonobo iid but gets ported later
* to dbus, then the reference to the bonobo iid will only be valid
* as an old reference.
* And if migration fails, we just use the iid as it is.
*/
needs_migration = FALSE;
key = panel_gconf_full_key (PANEL_GCONF_APPLETS, id, "applet_iid");
applet_iid = gconf_client_get_string (client, key, NULL);
if (!applet_iid || !applet_iid[0]) {
needs_migration = TRUE;
key = panel_gconf_full_key (PANEL_GCONF_APPLETS, id, "bonobo_iid");
applet_iid = gconf_client_get_string (client, key, NULL);
if (!applet_iid || !applet_iid[0])
return NULL;
object_iid = g_settings_get_string (settings, PANEL_OBJECT_IID_KEY);
if (PANEL_GLIB_STR_EMPTY (object_iid)) {
g_free (object_iid);
return NULL;
}
info = panel_applets_manager_get_applet_info_from_old_id (applet_iid);
info = panel_applets_manager_get_applet_info_from_old_id (object_iid);
if (!info)
info = panel_applets_manager_get_applet_info (applet_iid);
info = panel_applets_manager_get_applet_info (object_iid);
if (!info)
if (!info) {
g_free (object_iid);
return NULL;
}
iid = panel_applet_info_get_iid (info);
/* migrate if the iid in the configuration is different than the real
* iid that will get used */
if (!g_str_equal (iid, applet_iid))
if (!g_str_equal (iid, object_iid))
needs_migration = TRUE;
g_free (applet_iid);
g_free (object_iid);
if (needs_migration) {
key = panel_gconf_full_key (PANEL_GCONF_APPLETS, id, "applet_iid");
gconf_client_set_string (client, key, iid, NULL);
}
if (needs_migration)
g_settings_set_string (settings, PANEL_OBJECT_IID_KEY, iid);
return g_strdup (iid);
}
......@@ -33,7 +33,8 @@ G_BEGIN_DECLS
void panel_compatiblity_migrate_settings_menu_button (GConfClient *client,
const char *id);
gchar *panel_compatibility_get_applet_iid (const gchar *id);
gchar *panel_compatibility_get_applet_iid (GSettings *settings,
const gchar *id);
G_END_DECLS
......
......@@ -37,6 +37,7 @@
#include "panel.h"
#include "panel-multiscreen.h"
#include "panel-object-loader.h"
#include "panel-schemas.h"
#include "panel-toplevel.h"
......@@ -586,10 +587,17 @@ panel_layout_load_toplevel (const char *toplevel_id)
static void
panel_layout_load_object (const char *object_id)
{
char *path;
if (PANEL_GLIB_STR_EMPTY (object_id))
return;
/* TODO */
path = g_strdup_printf ("%s%s/",
PANEL_LAYOUT_OBJECT_PATH, object_id);
panel_object_loader_queue (object_id, path);
g_free (path);
}
static char *
......@@ -698,5 +706,7 @@ panel_layout_load (void)
panel_layout_ensure_toplevel_per_screen ();
panel_object_loader_do_load (TRUE);
return TRUE;
}
/*
* panel-object-loader.c: object loader
* vim: set et:
*
* Copyright (C) 2011 Novell, Inc.
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Most of this code is originally from applet.c.
*
* Authors:
* Vincent Untz <vuntz@gnome.org>
*/
#include <config.h>
#include <string.h>
#include <gio/gio.h>
#include <libpanel-util/panel-glib.h>