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