diff options
-rw-r--r-- | libmdock/mdock-widget.c | 171 |
1 files changed, 96 insertions, 75 deletions
diff --git a/libmdock/mdock-widget.c b/libmdock/mdock-widget.c index 06080bf..1ce9a4d 100644 --- a/libmdock/mdock-widget.c +++ b/libmdock/mdock-widget.c @@ -35,6 +35,7 @@ struct _MDockWidgetPrivate GHashTable *appid_to_item; GHashTable *desktopid_to_item; GHashTable *window_to_item; + gboolean loading_settings; }; G_DEFINE_TYPE(MDockWidget, mdock_widget, GTK_TYPE_BOX) @@ -49,6 +50,96 @@ enum { static GParamSpec *obj_properties[N_PROPERTIES] = { NULL }; +static void save_items_to_settings(MDockWidget *self) +{ + GSettings *settings = self->priv->settings; + GSequenceIter *seq_iter = g_sequence_get_begin_iter(self->priv->items); + GVariantBuilder builder; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("as")); + + while (!g_sequence_iter_is_end(seq_iter)) { + MDockItem *item = MDOCK_ITEM(g_sequence_get(seq_iter)); + + if (mdock_item_get_pinned(item)) { + GDesktopAppInfo *info = mdock_item_get_desktop_app_info(item); + if (info) { + g_variant_builder_add(&builder, "s", g_desktop_app_info_get_filename(info)); + } + } + + seq_iter = g_sequence_iter_next(seq_iter); + } + + self->priv->loading_settings = TRUE; + g_settings_set(settings, "items", "as", &builder); + self->priv->loading_settings = FALSE; +} + +static void handle_item_pinned_changed(MDockWidget *self, GParamSpec *spec, MDockItem *item) +{ + if (!self->priv->loading_settings) { + save_items_to_settings(self); + } +} + +static void connect_item(MDockWidget *self, MDockItem *item) +{ + g_signal_connect_object(item, "notify::pinned", + G_CALLBACK(handle_item_pinned_changed), self, + G_CONNECT_SWAPPED); + + g_settings_bind(self->priv->settings, "icon-size", + item, "icon-size", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); +} + + +static void reload_items_from_settings(MDockWidget *self) +{ + GSettings *settings = self->priv->settings; + + self->priv->loading_settings = TRUE; + + GVariantIter *set_iter; + g_settings_get(settings, "items", "as", &set_iter); + + GSequenceIter *seq_iter = g_sequence_get_begin_iter(self->priv->items); + + gchar *value; + while (g_variant_iter_next(set_iter, "s", &value)) { + GDesktopAppInfo *set_appinfo = g_desktop_app_info_new_from_filename(value); + const gchar *set_desktopid = g_app_info_get_id(G_APP_INFO(set_appinfo)); + + GSequenceIter *iter = g_hash_table_lookup(self->priv->desktopid_to_item, set_desktopid); + if (iter) { + // This item is already on the dock, let's move it to the front and pin it. + MDockItem *item = MDOCK_ITEM(g_sequence_get(iter)); + mdock_item_set_pinned(item, TRUE); + g_sequence_move(iter, seq_iter); + } else { + // Item not already in the dock. + MDockItem *item = mdock_item_new(); + mdock_item_set_desktop_app_info(item, set_appinfo); + mdock_item_set_pinned(item, TRUE); + + connect_item(self, item); + + iter = g_sequence_insert_before(seq_iter, item); + g_hash_table_insert(self->priv->desktopid_to_item, g_strdup(set_desktopid), iter); + gtk_widget_show(GTK_WIDGET(item)); + gtk_box_pack_start(GTK_BOX(self), GTK_WIDGET(item), TRUE, FALSE, 0); + } + + g_object_unref(set_appinfo); + g_free(value); + } + + g_variant_iter_free(set_iter); + + self->priv->loading_settings = FALSE; +} + static void handle_active_window_changed(MDockWidget *self, WnckWindow *previous_window, WnckScreen *screen) { WnckWindow *window = wnck_screen_get_active_window(screen); @@ -121,9 +212,7 @@ static void handle_window_opened(MDockWidget *self, WnckWindow *window, WnckScre g_object_unref(app_info); } - g_settings_bind(self->priv->settings, "icon-size", - item, "icon-size", - G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); + connect_item(self, item); mdock_item_add_window(item, window); @@ -137,79 +226,11 @@ static void handle_window_opened(MDockWidget *self, WnckWindow *window, WnckScre gtk_box_pack_start(GTK_BOX(self), GTK_WIDGET(item), TRUE, FALSE, 0); } -static void load_items_from_settings(MDockWidget *self, GSettings *settings) -{ - GVariantIter *set_iter; - GVariant *set_value; - GSequenceIter *seq_iter = g_sequence_get_begin_iter(self->priv->items); - - g_settings_get(settings, "items", "as", &set_iter); - set_value = g_variant_iter_next_value(set_iter); - - g_debug("Loading settings %p %p", set_value, seq_iter); - - while (set_value || !g_sequence_iter_is_end(seq_iter)) { - gboolean advance_set = FALSE, advance_seq = FALSE; - MDockItem *item = NULL; - GDesktopAppInfo *seq_appinfo = NULL; - GDesktopAppInfo *set_appinfo = NULL; - - g_debug("Iteration %p %p", set_value, seq_iter); - - if (!g_sequence_iter_is_end(seq_iter)) { - item = MDOCK_ITEM(g_sequence_get(seq_iter)); - seq_appinfo = mdock_item_get_desktop_app_info(item); - } - if (set_value) { - set_appinfo = g_desktop_app_info_new_from_filename(g_variant_get_string(set_value, NULL)); - } - - if (set_appinfo && seq_appinfo) { - const gchar *set_desktopid = g_app_info_get_id(G_APP_INFO(set_appinfo)); - const gchar *seq_desktopid = g_app_info_get_id(G_APP_INFO(seq_appinfo)); - const gboolean seq_pinned = mdock_item_get_pinned(item); - - // TODO broken - g_warning("broken"); - } else if (set_appinfo) { - g_debug("from set only"); - item = mdock_item_new(); - mdock_item_set_desktop_app_info(item, set_appinfo); - mdock_item_set_pinned(item, TRUE); - - GSequenceIter *iter = g_sequence_append(self->priv->items, item); - const gchar *desktopid = g_app_info_get_id(G_APP_INFO(set_appinfo)); - g_hash_table_insert(self->priv->desktopid_to_item, g_strdup(desktopid), iter); - gtk_widget_show(GTK_WIDGET(item)); - gtk_box_pack_start(GTK_BOX(self), GTK_WIDGET(item), TRUE, FALSE, 0); - - advance_set = TRUE; - } else if (seq_appinfo) { - g_debug("from seq only"); - if (mdock_item_get_pinned(item)) { - mdock_item_set_pinned(item, FALSE); - } - advance_seq = TRUE; - } - - g_object_unref(set_appinfo); - - if (advance_set && set_appinfo) { - g_variant_unref(set_value); - set_value = g_variant_iter_next_value(set_iter); - - } - if (advance_seq && !g_sequence_iter_is_end(seq_iter)) { - seq_iter = g_sequence_iter_next(seq_iter); - } - } - - g_variant_iter_free(set_iter); -} - static void handle_settings_items_changed(MDockWidget *self, gchar *key, GSettings *settings) { - load_items_from_settings(self, settings); + if (!self->priv->loading_settings) { + reload_items_from_settings(self); + } } static void mdock_widget_constructed(GObject *obj) @@ -238,7 +259,7 @@ static void mdock_widget_constructed(GObject *obj) self->priv->window_to_item = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); - load_items_from_settings(self, self->priv->settings); + reload_items_from_settings(self); GList *windows = wnck_screen_get_windows_stacked(self->priv->wnck_screen); for (GList *l = windows; l; l = g_list_next(l)) { |