diff options
Diffstat (limited to 'libmdock/mdock-widget.c')
-rw-r--r-- | libmdock/mdock-widget.c | 195 |
1 files changed, 171 insertions, 24 deletions
diff --git a/libmdock/mdock-widget.c b/libmdock/mdock-widget.c index defca10..a5d1307 100644 --- a/libmdock/mdock-widget.c +++ b/libmdock/mdock-widget.c @@ -28,22 +28,61 @@ struct _MDockWidgetPrivate { + gchar *settings_path; + GSettings *settings; WnckScreen *wnck_screen; - GSequence *groups; + GSequence *items; + GHashTable *appid_to_item; + GHashTable *desktopid_to_item; + GHashTable *window_to_item; }; G_DEFINE_TYPE(MDockWidget, mdock_widget, GTK_TYPE_BOX) #define MDOCK_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), MDOCK_TYPE_WIDGET, MDockWidgetPrivate)) +enum { + PROP_0, + PROP_SETTINGS_PATH, + N_PROPERTIES +}; + +static GParamSpec *obj_properties[N_PROPERTIES] = { NULL }; + static void handle_active_window_changed(MDockWidget *self, WnckWindow *previous_window, WnckScreen *screen) { + WnckWindow *window = wnck_screen_get_active_window(screen); + GSequenceIter *iter = g_hash_table_lookup(self->priv->window_to_item, window); + if (iter) { + MDockItem *item = MDOCK_ITEM(g_sequence_get(iter)); + mdock_item_set_last_active_window(item, window); + } +} +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); + if (!iter) { + // We never managed this window + return; + } + + MDockItem *item = MDOCK_ITEM(g_sequence_get(iter)); + mdock_item_remove_window(item, window); + g_hash_table_remove(self->priv->window_to_item, window); + if (mdock_item_get_num_windows(item) == 0) { + // Removing window! + 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); + gtk_widget_destroy(GTK_WIDGET(item)); + } } static void handle_window_opened(MDockWidget *self, WnckWindow *window, WnckScreen *screen) @@ -51,16 +90,90 @@ static void handle_window_opened(MDockWidget *self, WnckWindow *window, WnckScre if (wnck_window_is_skip_tasklist(window)) { return; } - g_debug("Window opened: %s", wnck_window_get_name(window)); + AppId *appid = app_id_from_window(window); - g_debug("%s %d %s %s %s", appid->host, appid->uid, appid->executable, appid->wm_class_class, appid->wm_class_name); + GSequenceIter *iter = g_hash_table_lookup(self->priv->appid_to_item, appid); + if (iter) { + MDockItem *item = MDOCK_ITEM(g_sequence_get(iter)); + mdock_item_add_window(item, window); + app_id_destroy(appid); + g_hash_table_insert(self->priv->window_to_item, window, iter); + return; + } + const gchar *desktopid = match_appid_to_desktopid(appid); - g_debug("desktopid: %s", desktopid); + if (desktopid) { + iter = g_hash_table_lookup(self->priv->desktopid_to_item, desktopid); + if (iter) { + MDockItem *item = MDOCK_ITEM(g_sequence_get(iter)); + mdock_item_add_window(item, window); + g_hash_table_insert(self->priv->appid_to_item, appid, iter); // takes ownership of appid + g_hash_table_insert(self->priv->window_to_item, window, iter); + return; + } + } + + MDockItem *item = mdock_item_new(MDOCK_ITEM_TYPE_APPLICATION); + iter = g_sequence_append(self->priv->items, item); + if (desktopid) { + GDesktopAppInfo *app_info = g_desktop_app_info_new(desktopid); + mdock_item_set_desktop_app_info(item, app_info); + 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); + + mdock_item_add_window(item, window); + + g_hash_table_insert(self->priv->appid_to_item, appid, iter); // takes ownership of appid + if (desktopid) { + g_hash_table_insert(self->priv->desktopid_to_item, g_strdup(desktopid), iter); + } + g_hash_table_insert(self->priv->window_to_item, window, iter); + + gtk_widget_show(GTK_WIDGET(item)); + gtk_box_pack_start(GTK_BOX(self), GTK_WIDGET(item), TRUE, FALSE, 0); +} + +static void mdock_widget_constructed(GObject *obj) +{ + MDockWidget *self = MDOCK_WIDGET(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); + + 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_dispose(GObject *obj) { MDockWidget *self = MDOCK_WIDGET(obj); + if (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; @@ -68,38 +181,72 @@ static void mdock_widget_dispose(GObject *obj) G_OBJECT_CLASS(mdock_widget_parent_class)->dispose(obj); } -static void mdock_widget_class_init(MDockWidgetClass *klass) +static void mdock_widget_finalize(GObject *obj) { - // GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + 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); + g_hash_table_destroy(self->priv->window_to_item); + G_OBJECT_CLASS(mdock_widget_parent_class)->dispose(obj); +} - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - obj_class->dispose = mdock_widget_dispose; +static void mdock_widget_set_property(GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + MDockWidget *self = MDOCK_WIDGET(object); + switch (property_id) { + case PROP_SETTINGS_PATH: + self->priv->settings_path = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} - g_type_class_add_private(klass, sizeof(MDockWidgetPrivate)); +static void mdock_widget_get_property(GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + MDockWidget *self = MDOCK_WIDGET(object); + switch (property_id) { + case PROP_SETTINGS_PATH: + g_value_set_string(value, self->priv->settings_path); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } } static void mdock_widget_init(MDockWidget *self) { self->priv = MDOCK_WIDGET_GET_PRIVATE(self); +} - 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); +static void mdock_widget_class_init(MDockWidgetClass *klass) +{ + 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; - self->priv->groups = g_sequence_new(NULL); + 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); - g_debug("widget init"); + g_object_class_install_properties(obj_class, N_PROPERTIES, obj_properties); - GList *windows = wnck_screen_get_windows_stacked(self->priv->wnck_screen); - for (GList *l = g_list_first(windows); l; l = g_list_next(l)) { - g_debug("list"); - WnckWindow *window = l->data; - handle_window_opened(self, window, self->priv->wnck_screen); - } + g_type_class_add_private(klass, sizeof(MDockWidgetPrivate)); } GtkWidget *mdock_widget_new(void) |