diff options
Diffstat (limited to 'libmdock')
-rw-r--r-- | libmdock/mdock-item-menu.c | 11 | ||||
-rw-r--r-- | libmdock/mdock-widget.c | 228 | ||||
-rw-r--r-- | libmdock/mdock-widget.h | 3 |
3 files changed, 141 insertions, 101 deletions
diff --git a/libmdock/mdock-item-menu.c b/libmdock/mdock-item-menu.c index 39495af..02de0bb 100644 --- a/libmdock/mdock-item-menu.c +++ b/libmdock/mdock-item-menu.c @@ -53,6 +53,7 @@ static GParamSpec *obj_properties[N_PROPERTIES] = { NULL }; #ifdef HAVE_ZEITGEIST +#define INITIAL_REFRESH_DELAY 3 #define RECENT_FETCH_MIN_INTERVAL 15 G_DEFINE_QUARK(mdock-item-menu-file, mdock_item_menu_file) @@ -205,6 +206,15 @@ static gboolean handle_menu_map(MDockItemMenu *self, GdkEventAny *event) return FALSE; } +static gboolean initial_menu_refresh(gpointer user_data) +{ + MDockItemMenu *self = MDOCK_ITEM_MENU(user_data); + // If we have never refreshed the menu so far, do an initial one now. + if (self->priv->recent_fetch_time == 0) { + refresh_recent_menu(self); + } +} + #endif static void handle_item_pinned(MDockItemMenu *self, GParamSpec *spec, MDockItem *item) @@ -304,6 +314,7 @@ mdock_item_menu_constructed(GObject *object) #ifdef HAVE_ZEITGEIST g_signal_connect(self, "map-event", G_CALLBACK(handle_menu_map), self); + g_timeout_add_seconds(INITIAL_REFRESH_DELAY, initial_menu_refresh, self); #endif } diff --git a/libmdock/mdock-widget.c b/libmdock/mdock-widget.c index 6507fbb..8efaf19 100644 --- a/libmdock/mdock-widget.c +++ b/libmdock/mdock-widget.c @@ -39,7 +39,6 @@ struct _MDockWidgetPrivate { - gchar *settings_path; GSettings *settings; WnckScreen *wnck_screen; GSequence *items; @@ -59,7 +58,7 @@ G_DEFINE_TYPE(MDockWidget, mdock_widget, GTK_TYPE_BOX) enum { PROP_0, - PROP_SETTINGS_PATH, + PROP_SETTINGS, N_PROPERTIES }; @@ -190,10 +189,33 @@ static void show_item_popup(MDockWidget *self, MDockItem *item) self->priv->current_popup_item = item; } +static gboolean filter_deleted_group(gpointer key, gpointer value, gpointer user_data) +{ + return value == user_data; +} + +static void remove_item(MDockWidget *self, GSequenceIter *iter) +{ + MDockItem *item = MDOCK_ITEM(g_sequence_get(iter)); + g_hash_table_foreach_remove(self->priv->appid_to_item, filter_deleted_group, iter); + g_hash_table_foreach_remove(self->priv->desktopid_to_item, filter_deleted_group, iter); + g_sequence_remove(iter); + if (self->priv->current_popup_item == item) { + hide_item_popup(self); + } + gtk_widget_destroy(GTK_WIDGET(item)); +} + static void handle_item_pinned_changed(MDockWidget *self, GParamSpec *spec, MDockItem *item) { if (!self->priv->loading_settings) { save_items_to_settings(self); + + if (!mdock_item_get_pinned(item) && mdock_item_get_num_windows(item) == 0) { + // Not pinned and without windows? + GSequenceIter *iter = g_object_get_qdata(G_OBJECT(item), mdock_widget_item_iter_quark()); + remove_item(self, iter); + } } } @@ -531,51 +553,68 @@ static void connect_item(MDockWidget *self, MDockItem *item, GSequenceIter *posi 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)); + if (self->priv->settings) { + GVariantIter *set_iter; + g_settings_get(self->priv->settings, "items", "as", &set_iter); + + 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); + MDockItem *item; + if (iter) { + // This item is already on the dock, let's move it to the front and pin it. + 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. + item = mdock_item_new(); + mdock_item_set_desktop_app_info(item, set_appinfo); + mdock_item_set_pinned(item, TRUE); - 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); - - iter = g_sequence_insert_before(seq_iter, item); - g_hash_table_insert(self->priv->desktopid_to_item, g_strdup(set_desktopid), iter); - - connect_item(self, item, iter); - - gtk_widget_show(GTK_WIDGET(item)); - gtk_box_pack_start(GTK_BOX(self), GTK_WIDGET(item), TRUE, TRUE, 0); - if (!g_sequence_iter_is_end(seq_iter)) { - // Fix the order! - gtk_box_reorder_child(GTK_BOX(self), GTK_WIDGET(item), - g_sequence_iter_get_position(iter)); + iter = g_sequence_insert_before(seq_iter, item); + g_hash_table_insert(self->priv->desktopid_to_item, g_strdup(set_desktopid), iter); + + connect_item(self, item, iter); + + gtk_widget_show(GTK_WIDGET(item)); + gtk_box_pack_start(GTK_BOX(self), GTK_WIDGET(item), TRUE, TRUE, 0); } + + // Fix the box order of the item... + gtk_box_reorder_child(GTK_BOX(self), GTK_WIDGET(item), + g_sequence_iter_get_position(iter)); + + g_object_unref(set_appinfo); + g_free(value); } - g_object_unref(set_appinfo); - g_free(value); + g_variant_iter_free(set_iter); } - g_variant_iter_free(set_iter); + while (!g_sequence_iter_is_end(seq_iter)) { + MDockItem *item = g_sequence_get(seq_iter); + if (mdock_item_get_pinned(item)) { + mdock_item_set_pinned(item, FALSE); + if (mdock_item_get_num_windows(item) == 0) { + // Remove this item + // The iterator will be destroyed, so take care. + GSequenceIter *iter = seq_iter; + seq_iter = g_sequence_iter_next(iter); + remove_item(self, iter); + continue; + } + } + + seq_iter = g_sequence_iter_next(seq_iter); + } self->priv->loading_settings = FALSE; } @@ -591,11 +630,6 @@ static void handle_active_window_changed(MDockWidget *self, WnckWindow *previous } } -static gboolean filter_deleted_group(gpointer key, gpointer value, gpointer user_data) -{ - return value == user_data; -} - static void handle_window_closed(MDockWidget *self, WnckWindow *window, WnckScreen *screen) { GSequenceIter *iter = g_hash_table_lookup(self->priv->window_to_item, window); @@ -611,13 +645,7 @@ static void handle_window_closed(MDockWidget *self, WnckWindow *window, WnckScre if (!mdock_item_has_windows(item) && !mdock_item_get_pinned(item)) { // Removing item from dock - g_hash_table_foreach_remove(self->priv->appid_to_item, filter_deleted_group, iter); - g_hash_table_foreach_remove(self->priv->desktopid_to_item, filter_deleted_group, iter); - g_sequence_remove(iter); - if (self->priv->current_popup_item == item) { - hide_item_popup(self); - } - gtk_widget_destroy(GTK_WIDGET(item)); + remove_item(self, iter); } } @@ -681,49 +709,10 @@ static void handle_settings_items_changed(MDockWidget *self, gchar *key, GSettin } } -static void mdock_widget_constructed(GObject *obj) -{ - MDockWidget *self = MDOCK_WIDGET(obj); - - G_OBJECT_CLASS(mdock_widget_parent_class)->constructed(obj); - - g_debug("Constructing with path: %s", self->priv->settings_path); - self->priv->settings = g_settings_new_with_path("com.javispedro.mdock.widget", - self->priv->settings_path); - g_signal_connect_object(self->priv->settings, "changed::items", - G_CALLBACK(handle_settings_items_changed), self, G_CONNECT_SWAPPED); - - self->priv->wnck_screen = wnck_screen_get_default(); - g_signal_connect_object(self->priv->wnck_screen, "active-window-changed", - G_CALLBACK(handle_active_window_changed), self, G_CONNECT_SWAPPED); - g_signal_connect_object(self->priv->wnck_screen, "window-closed", - G_CALLBACK(handle_window_closed), self, G_CONNECT_SWAPPED); - g_signal_connect_object(self->priv->wnck_screen, "window-opened", - G_CALLBACK(handle_window_opened), self, G_CONNECT_SWAPPED); - - self->priv->items = g_sequence_new(NULL); - self->priv->appid_to_item = g_hash_table_new_full(app_id_hash, app_id_equal, - (GDestroyNotify)app_id_destroy, NULL); - self->priv->desktopid_to_item = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); - self->priv->window_to_item = g_hash_table_new_full(g_direct_hash, g_direct_equal, - NULL, NULL); - - 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)) { - WnckWindow *window = l->data; - handle_window_opened(self, window, self->priv->wnck_screen); - } -} - static void mdock_widget_dispose(GObject *obj) { MDockWidget *self = MDOCK_WIDGET(obj); - if (self->priv->settings) { - g_clear_object(&self->priv->settings); - } + g_clear_object(&self->priv->settings); if (self->priv->wnck_screen) { g_signal_handlers_disconnect_by_data(self->priv->wnck_screen, self); self->priv->wnck_screen = NULL; @@ -734,7 +723,6 @@ static void mdock_widget_dispose(GObject *obj) static void mdock_widget_finalize(GObject *obj) { MDockWidget *self = MDOCK_WIDGET(obj); - g_free(self->priv->settings_path); g_sequence_free(self->priv->items); g_hash_table_destroy(self->priv->appid_to_item); g_hash_table_destroy(self->priv->desktopid_to_item); @@ -749,8 +737,17 @@ static void mdock_widget_set_property(GObject *object, { MDockWidget *self = MDOCK_WIDGET(object); switch (property_id) { - case PROP_SETTINGS_PATH: - self->priv->settings_path = g_value_dup_string(value); + case PROP_SETTINGS: + if (self->priv->settings) { + g_signal_handlers_disconnect_by_data(self->priv->settings, self); + g_object_unref(self->priv->settings); + } + self->priv->settings = g_value_dup_object(value); + if (self->priv->settings) { + g_signal_connect_object(self->priv->settings, "changed::items", + G_CALLBACK(handle_settings_items_changed), self, G_CONNECT_SWAPPED); + } + reload_items_from_settings(self); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); @@ -765,8 +762,8 @@ static void mdock_widget_get_property(GObject *object, { MDockWidget *self = MDOCK_WIDGET(object); switch (property_id) { - case PROP_SETTINGS_PATH: - g_value_set_string(value, self->priv->settings_path); + case PROP_SETTINGS: + g_value_set_object(value, self->priv->settings); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); @@ -787,6 +784,28 @@ static void mdock_widget_init(MDockWidget *self) gtk_drag_dest_set(GTK_WIDGET(self), 0, drag_types, G_N_ELEMENTS(drag_types), GDK_ACTION_MOVE); + + self->priv->wnck_screen = wnck_screen_get_default(); + g_signal_connect_object(self->priv->wnck_screen, "active-window-changed", + G_CALLBACK(handle_active_window_changed), self, G_CONNECT_SWAPPED); + g_signal_connect_object(self->priv->wnck_screen, "window-closed", + G_CALLBACK(handle_window_closed), self, G_CONNECT_SWAPPED); + g_signal_connect_object(self->priv->wnck_screen, "window-opened", + G_CALLBACK(handle_window_opened), self, G_CONNECT_SWAPPED); + + self->priv->items = g_sequence_new(NULL); + self->priv->appid_to_item = g_hash_table_new_full(app_id_hash, app_id_equal, + (GDestroyNotify)app_id_destroy, NULL); + self->priv->desktopid_to_item = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + self->priv->window_to_item = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, NULL); + + GList *windows = wnck_screen_get_windows_stacked(self->priv->wnck_screen); + for (GList *l = windows; l; l = g_list_next(l)) { + WnckWindow *window = l->data; + handle_window_opened(self, window, self->priv->wnck_screen); + } } static void mdock_widget_class_init(MDockWidgetClass *klass) @@ -797,17 +816,16 @@ static void mdock_widget_class_init(MDockWidgetClass *klass) widget_class->drag_motion = mdock_widget_drag_motion; GObjectClass *obj_class = G_OBJECT_CLASS(klass); - obj_class->constructed = mdock_widget_constructed; obj_class->dispose = mdock_widget_dispose; obj_class->finalize = mdock_widget_finalize; obj_class->set_property = mdock_widget_set_property; obj_class->get_property = mdock_widget_get_property; - obj_properties[PROP_SETTINGS_PATH] = g_param_spec_string("settings-path", - "Path to GSettings for this widget", - "Set the path to GSettings for this widget", - "/com/javispedro/mdock/standalone/", - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_SETTINGS] = g_param_spec_object("settings", + "GSettings object this widget will use", + "Set the path to GSettings for this widget", + G_TYPE_SETTINGS, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties(obj_class, N_PROPERTIES, obj_properties); @@ -824,7 +842,15 @@ GtkWidget *mdock_widget_new(void) return GTK_WIDGET(g_object_new(MDOCK_TYPE_WIDGET, NULL)); } +GtkWidget *mdock_widget_new_with_settings(GSettings *settings) +{ + return GTK_WIDGET(g_object_new(MDOCK_TYPE_WIDGET, "settings", settings, NULL)); +} + GtkWidget *mdock_widget_new_with_settings_path(const gchar *path) { - return GTK_WIDGET(g_object_new(MDOCK_TYPE_WIDGET, "settings-path", path, NULL)); + GSettings *settings = g_settings_new_with_path(MDOCK_WIDGET_GSETTINGS_SCHEMA, path); + GtkWidget *self = mdock_widget_new_with_settings(settings); + g_object_unref(settings); + return self; } diff --git a/libmdock/mdock-widget.h b/libmdock/mdock-widget.h index 2771095..2c49b04 100644 --- a/libmdock/mdock-widget.h +++ b/libmdock/mdock-widget.h @@ -31,6 +31,8 @@ G_BEGIN_DECLS #define MDOCK_IS_WIDGET_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE((c), MDOCK_TYPE_WIDGET)) #define MDOCK_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), MDOCK_TYPE_WIDGET, MDockWidgetClass)) +#define MDOCK_WIDGET_GSETTINGS_SCHEMA "com.javispedro.mdock.widget" + typedef struct _MDockWidget MDockWidget; typedef struct _MDockWidgetClass MDockWidgetClass; typedef struct _MDockWidgetPrivate MDockWidgetPrivate; @@ -52,6 +54,7 @@ GType mdock_widget_get_type(void); gint mdock_widget_get_n_items(MDockWidget *widget); GtkWidget *mdock_widget_new(void); +GtkWidget *mdock_widget_new_with_settings(GSettings *settings); GtkWidget *mdock_widget_new_with_settings_path(const gchar *path); G_END_DECLS |