summaryrefslogtreecommitdiff
path: root/libmdock
diff options
context:
space:
mode:
Diffstat (limited to 'libmdock')
-rw-r--r--libmdock/mdock-item-menu.c11
-rw-r--r--libmdock/mdock-widget.c228
-rw-r--r--libmdock/mdock-widget.h3
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