summaryrefslogtreecommitdiff
path: root/libmdock
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2015-01-19 00:07:22 +0100
committerJavier <dev.git@javispedro.com>2015-01-19 00:07:22 +0100
commitcd89c60570d17cad28928f3495eded7af2b45431 (patch)
treea7d13d4f0d63e852062964fcf79ca9d5ad70ae15 /libmdock
parenta215500011290121925cfe929d71b80696732230 (diff)
downloadmdock-cd89c60570d17cad28928f3495eded7af2b45431.tar.gz
mdock-cd89c60570d17cad28928f3495eded7af2b45431.zip
initially app-id support
Diffstat (limited to 'libmdock')
-rw-r--r--libmdock/Makefile.am18
-rw-r--r--libmdock/app-id.c157
-rw-r--r--libmdock/app-id.h44
-rw-r--r--libmdock/com.javispedro.mdock.widget.gschema.xml9
-rw-r--r--libmdock/matcher.c238
-rw-r--r--libmdock/matcher.h27
-rw-r--r--libmdock/mdock-enums.c6
-rw-r--r--libmdock/mdock-enums.h25
-rw-r--r--libmdock/mdock-item.c56
-rw-r--r--libmdock/mdock-item.h55
-rw-r--r--libmdock/mdock-widget.c103
-rw-r--r--libmdock/mdock-widget.h4
12 files changed, 733 insertions, 9 deletions
diff --git a/libmdock/Makefile.am b/libmdock/Makefile.am
index eac1880..7c5514e 100644
--- a/libmdock/Makefile.am
+++ b/libmdock/Makefile.am
@@ -1,10 +1,14 @@
-AM_CPPFLAGS = $(GTK_CFLAGS)
-AM_LDFLAGS = $(GTK_LIBS)
-
lib_LTLIBRARIES = libmdock.la
-libmdock_la_SOURCES = mdock-widget.c mdock-widget.h
-libmdock_la_CPPFLAGS = $(GTK_CFLAGS) $(WNCK_CFLAGS) -DG_LOG_DOMAIN=\"libmdock\"
-libmdock_la_LIBADD = $(GTK_LIBS) $(WNCK_LIBS)
+libmdock_la_SOURCES = mdock-widget.h mdock-widget.c mdock-enums.h mdock-enums.c mdock-item.h mdock-item.c matcher.h matcher.c app-id.h app-id.c
+libmdock_la_CPPFLAGS = $(GTK_CFLAGS) $(GIO_CFLAGS) $(WNCK_CFLAGS) $(GTOP_CFLAGS) -D_GNU_SOURCE -DG_LOG_DOMAIN=\"libmdock\"
+libmdock_la_LIBADD = $(GTK_LIBS) $(GIO_LIBS) $(WNCK_LIBS) $(GTOP_LIBS)
+
+gsettings_SCHEMAS = com.javispedro.mdock.widget.gschema.xml
+
+include_HEADERS = mdock-widget.h mdock-item.h mdock-enums.h
+CLEANFILES = mdock-enums.c
-include_HEADERS = mdock-widget.h
+mdock-enums.c: mdock-enums.h
+ glib-mkenums $< > $@
+@GSETTINGS_RULES@
diff --git a/libmdock/app-id.c b/libmdock/app-id.c
new file mode 100644
index 0000000..b54ed6c
--- /dev/null
+++ b/libmdock/app-id.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2015 Javier S. Pedro <dev.git@javispedro.com>
+ *
+ * This file is part of MDock.
+ *
+ * MDock is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MDock is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MDock. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <gdk/gdkx.h>
+#include <glibtop/procuid.h>
+#include <glibtop/procwd.h>
+#include <string.h>
+#include "app-id.h"
+
+AppId * app_id_new()
+{
+ return g_slice_new0(AppId);
+}
+
+AppId * app_id_create(const gchar *host, gint uid, const gchar *executable, const gchar *wm_class_class, const gchar *wm_class_name)
+{
+ AppId *appid = g_slice_new(AppId);
+ appid->host = g_strdup(host);
+ appid->uid = uid;
+ appid->executable = g_strdup(executable);
+ appid->wm_class_class = g_strdup(wm_class_class);
+ appid->wm_class_name = g_strdup(wm_class_name);
+}
+
+void app_id_destroy(AppId *appid)
+{
+ g_free(appid->host);
+ g_free(appid->executable);
+ g_free(appid->wm_class_class);
+ g_free(appid->wm_class_name);
+ g_slice_free(AppId, appid);
+}
+
+guint app_id_hash(gconstpointer appid_pointer)
+{
+ const AppId *appid = appid_pointer;
+ return g_str_hash(appid->host) + appid->uid + g_str_hash(appid->executable) + g_str_hash(appid->wm_class_class) + g_str_hash(appid->wm_class_name);
+}
+
+gboolean app_id_equal(gconstpointer ap, gconstpointer bp)
+{
+ const AppId *a = ap, *b = bp;
+ return strcmp(a->host, b->host) == 0 &&
+ a->uid == b->uid &&
+ g_strcmp0(a->executable, b->executable) == 0 &&
+ g_strcmp0(a->wm_class_class, b->wm_class_class) == 0 &&
+ g_strcmp0(a->wm_class_name, b->wm_class_name) == 0;
+}
+
+static gchar *text_property_to_string(Display *dpy, XTextProperty *prop)
+{
+ gchar *str = NULL;
+ char **list;
+ int count = 0;
+ if (Xutf8TextPropertyToTextList(dpy, prop, &list, &count) == Success) {
+ if (count > 0) {
+ str = g_strdup(list[0]);
+ }
+ XFreeStringList(list);
+ }
+
+ return str;
+}
+
+static gchar *text_property_to_lower_string(Display *dpy, XTextProperty *prop)
+{
+ gchar *str = NULL;
+ char **list;
+ int count = 0;
+ if (Xutf8TextPropertyToTextList(dpy, prop, &list, &count) == Success) {
+ if (count > 0) {
+ str = g_utf8_strdown(list[0], -1);
+ }
+ XFreeStringList(list);
+ }
+
+ return str;
+}
+
+static gboolean is_local_host(const gchar *host) {
+ if (strcmp(host, "localhost") == 0) {
+ return TRUE;
+ } else if (strcmp(host, g_get_host_name()) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+AppId * app_id_from_window(WnckWindow *window)
+{
+ AppId *appid = g_slice_new0(AppId);
+ Display *dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default());
+ Window w = wnck_window_get_xid(window);
+
+ XTextProperty textprop;
+ if (XGetWMClientMachine(dpy, w, &textprop)) {
+ appid->host = text_property_to_lower_string(dpy, &textprop);
+ XFree(textprop.value);
+ }
+
+ pid_t pid = wnck_window_get_pid(window);
+
+ if (pid) {
+ glibtop_proc_uid proc_uid;
+ glibtop_get_proc_uid(&proc_uid, pid);
+ if (proc_uid.flags & (1L << GLIBTOP_PROC_UID_UID)) {
+ appid->uid = proc_uid.uid;
+ }
+
+ if (!appid->host || is_local_host(appid->host)) {
+ glibtop_proc_wd proc_wd;
+ gchar **dirs = glibtop_get_proc_wd(&proc_wd, pid);
+
+ if (proc_wd.flags & (1 << GLIBTOP_PROC_WD_EXE)) {
+ appid->executable = g_strdup(proc_wd.exe);
+ }
+
+ g_strfreev(dirs);
+ }
+ } else {
+ appid->uid = getuid();
+ appid->executable = NULL;
+ }
+
+ XClassHint classhint;
+ if (XGetClassHint(dpy, w, &classhint)) {
+ if (classhint.res_class) {
+ appid->wm_class_class = g_ascii_strdown(classhint.res_class, -1);
+ XFree(classhint.res_class);
+ }
+ if (classhint.res_name) {
+ appid->wm_class_name = g_ascii_strdown(classhint.res_name, -1);
+ XFree(classhint.res_name);
+ }
+ }
+
+ return appid;
+}
diff --git a/libmdock/app-id.h b/libmdock/app-id.h
new file mode 100644
index 0000000..df69ab6
--- /dev/null
+++ b/libmdock/app-id.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 Javier S. Pedro <dev.git@javispedro.com>
+ *
+ * This file is part of MDock.
+ *
+ * MDock is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MDock is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MDock. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MDOCK_APPID_H_
+#define _MDOCK_APPID_H_
+
+#include <glib.h>
+#define WNCK_I_KNOW_THIS_IS_UNSTABLE 1
+#include <libwnck/libwnck.h>
+
+typedef struct _AppId {
+ gchar *host;
+ gint uid;
+ gchar *executable;
+ gchar *wm_class_class;
+ gchar *wm_class_name;
+} AppId;
+
+AppId * app_id_new();
+AppId * app_id_create(const gchar *host, gint uid, const gchar *executable, const gchar *wm_class_class, const gchar *wm_class_name);
+void app_id_destroy(AppId *appid);
+
+guint app_id_hash(gconstpointer appid);
+gboolean app_id_equal(gconstpointer ap, gconstpointer bp);
+
+AppId * app_id_from_window(WnckWindow *window);
+
+#endif /* _MDOCK_APPID_H_ */
diff --git a/libmdock/com.javispedro.mdock.widget.gschema.xml b/libmdock/com.javispedro.mdock.widget.gschema.xml
new file mode 100644
index 0000000..9b05fa1
--- /dev/null
+++ b/libmdock/com.javispedro.mdock.widget.gschema.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<schemalist>
+ <schema id="com.javispedro.mdock.widget">
+ <key name="items" type="a(ss)">
+ <default>[]</default>
+ <summary>Items in the dock</summary>
+ </key>
+ </schema>
+</schemalist>
diff --git a/libmdock/matcher.c b/libmdock/matcher.c
new file mode 100644
index 0000000..25e2b2f
--- /dev/null
+++ b/libmdock/matcher.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2015 Javier S. Pedro <dev.git@javispedro.com>
+ *
+ * This file is part of MDock.
+ *
+ * MDock is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MDock is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MDock. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ftw.h>
+#include <string.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+#include "matcher.h"
+
+static gboolean init_done = FALSE;
+static GAppInfoMonitor *appinfo_monitor;
+static guint refresh_timeout;
+static GHashTable *info_by_exec;
+static GHashTable *info_by_wmclass;
+
+typedef struct _DesktopItem
+{
+ gint priority;
+ gchar *desktop_file;
+} DesktopItem;
+
+typedef struct _DesktopItemList
+{
+ GSList *list;
+} DesktopItemList;
+
+static DesktopItem * desktop_item_create()
+{
+ return g_slice_new(DesktopItem);
+}
+
+static void desktop_item_destroy(DesktopItem *item)
+{
+ g_free(item->desktop_file);
+ g_slice_free(DesktopItem, item);
+}
+
+static gint desktop_item_compare(gconstpointer ap, gconstpointer bp)
+{
+ const DesktopItem *a = ap, *b = bp;
+ return b->priority - a->priority;
+}
+
+static void desktop_item_list_destroy(DesktopItemList *l)
+{
+ g_slist_free_full(l->list, (GDestroyNotify)desktop_item_destroy);
+}
+
+static gint compute_priority(GDesktopAppInfo *info, gint base_priority)
+{
+ gint prio = base_priority;
+
+ if (g_app_info_should_show(G_APP_INFO(info))) {
+ prio += 32000;
+ }
+
+ const gchar *cmdline = g_app_info_get_commandline(G_APP_INFO(info));
+ prio -= strlen(cmdline);
+
+ return prio;
+}
+
+static void add_desktop_item_by_exec(const gchar *exec, GDesktopAppInfo *info, gint base_priority)
+{
+ DesktopItem *item = desktop_item_create();
+ item->priority = compute_priority(info, base_priority);
+ item->desktop_file = g_strdup(g_app_info_get_id(G_APP_INFO(info)));
+
+ DesktopItemList *elist = g_hash_table_lookup(info_by_exec, exec);
+ if (!elist) {
+ elist = g_slice_new0(DesktopItemList);
+ g_hash_table_insert(info_by_exec, g_strdup(exec), elist);
+ }
+
+ elist->list = g_slist_append(elist->list, item);
+}
+
+static void add_desktop_item_by_wmclass(const gchar *wmclass, GDesktopAppInfo *info, gint base_priority)
+{
+ DesktopItem *item = desktop_item_create();
+ item->priority = compute_priority(info, base_priority);
+ item->desktop_file = g_strdup(g_app_info_get_id(G_APP_INFO(info)));
+
+ DesktopItemList *elist = g_hash_table_lookup(info_by_wmclass, wmclass);
+ if (!elist) {
+ elist = g_slice_new0(DesktopItemList);
+ g_hash_table_insert(info_by_wmclass, g_strdup(wmclass), elist);
+ }
+
+ elist->list = g_slist_append(elist->list, item);
+}
+
+static void add_desktop_info(GDesktopAppInfo *info)
+{
+ const char *quoted_executable = g_app_info_get_executable(G_APP_INFO(info));
+ gchar *executable = NULL;
+ if (quoted_executable) {
+ executable = g_shell_unquote(quoted_executable, NULL);
+ }
+
+ if (executable && executable[0]) {
+ if (g_path_is_absolute(executable)) {
+ add_desktop_item_by_exec(executable, info, 4000);
+ } else {
+ gchar *execpath = g_find_program_in_path(executable);
+ if (execpath) {
+ add_desktop_item_by_exec(execpath, info, 0);
+ } else {
+ g_warning("Could not find executable in path: '%s'", executable);
+ }
+ g_free(execpath);
+ }
+ }
+
+ const gchar *wmclass = g_desktop_app_info_get_startup_wm_class(info);
+ if (wmclass && wmclass[0]) {
+ add_desktop_item_by_wmclass(wmclass, info, 128000);
+ }
+
+ if (executable && executable[0]) {
+ gchar *basename = g_path_get_basename(executable);
+ add_desktop_item_by_wmclass(basename, info, -32000);
+ g_free(basename);
+ }
+
+ g_free(executable);
+}
+
+static void refresh_appinfo()
+{
+ g_debug("Refreshing application info...");
+
+ g_hash_table_remove_all(info_by_exec);
+ g_hash_table_remove_all(info_by_wmclass);
+
+ GList *list = g_app_info_get_all();
+ for (GList *l = g_list_first(list); l; l = g_list_next(l)) {
+ add_desktop_info(G_DESKTOP_APP_INFO(l->data));
+ }
+
+ g_list_free_full(list, g_object_unref);
+}
+
+static gboolean appinfo_timeout(gpointer user_data)
+{
+ refresh_appinfo();
+ refresh_timeout = 0;
+ return G_SOURCE_REMOVE;
+}
+
+static void appinfo_changed(GAppInfoMonitor *monitor, gpointer user_data)
+{
+ g_debug("Appinfo changed");
+ if (refresh_timeout == 0) {
+ refresh_timeout = g_timeout_add_seconds(10, appinfo_timeout, 0);
+ }
+}
+
+static gboolean init_matcher(void)
+{
+ if (!init_done) {
+ refresh_timeout = 0;
+ appinfo_monitor = g_app_info_monitor_get();
+ g_signal_connect(appinfo_monitor, "changed",
+ G_CALLBACK(appinfo_changed), 0);
+
+ info_by_exec = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify)desktop_item_list_destroy);
+ info_by_wmclass = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify)desktop_item_list_destroy);
+
+ refresh_appinfo();
+ }
+
+ return TRUE;
+}
+
+static GSList * matches_by_executable(const gchar *exec)
+{
+ DesktopItemList *elist = g_hash_table_lookup(info_by_exec, exec);
+
+ if (elist) {
+ return g_slist_copy(elist->list);
+ } else {
+ return NULL;
+ }
+}
+
+static GSList * matches_by_wmclass(const gchar *wmclass)
+{
+ DesktopItemList *elist = g_hash_table_lookup(info_by_wmclass, wmclass);
+
+ if (elist) {
+ return g_slist_copy(elist->list);
+ } else {
+ return NULL;
+ }
+}
+
+const gchar * match_application_to_desktop_file(AppId *appid)
+{
+ if (!init_matcher()) return NULL;
+
+ GSList *list = NULL;
+
+ if (appid->executable) {
+ list = g_slist_concat(list, matches_by_executable(appid->executable));
+ }
+ if (appid->wm_class_name) {
+ list = g_slist_concat(list, matches_by_wmclass(appid->wm_class_name));
+ }
+
+ if (list) {
+ list = g_slist_sort(list, desktop_item_compare);
+ DesktopItem *best = list->data;
+ g_slist_free(list);
+ return best->desktop_file;
+ } else {
+ return NULL;
+ }
+}
diff --git a/libmdock/matcher.h b/libmdock/matcher.h
new file mode 100644
index 0000000..46fe4a6
--- /dev/null
+++ b/libmdock/matcher.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2015 Javier S. Pedro <dev.git@javispedro.com>
+ *
+ * This file is part of MDock.
+ *
+ * MDock is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MDock is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MDock. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MDOCK_MATCHER_H_
+#define _MDOCK_MATCHER_H_
+
+#include "app-id.h"
+
+const gchar * match_application_to_desktop_file(AppId *appid);
+
+#endif /* _MDOCK_MATCHER_H_ */
diff --git a/libmdock/mdock-enums.c b/libmdock/mdock-enums.c
new file mode 100644
index 0000000..6fb66a5
--- /dev/null
+++ b/libmdock/mdock-enums.c
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/libmdock/mdock-enums.h b/libmdock/mdock-enums.h
new file mode 100644
index 0000000..c5f74bb
--- /dev/null
+++ b/libmdock/mdock-enums.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015 Javier S. Pedro <dev.git@javispedro.com>
+ *
+ * This file is part of MDock.
+ *
+ * MDock is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MDock is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MDock. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MDOCK_ENUMS_H_
+#define _MDOCK_ENUMS_H_
+
+
+
+#endif /* _MDOCK_ENUMS_H_ */
diff --git a/libmdock/mdock-item.c b/libmdock/mdock-item.c
new file mode 100644
index 0000000..726644f
--- /dev/null
+++ b/libmdock/mdock-item.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Javier S. Pedro <dev.git@javispedro.com>
+ *
+ * This file is part of MDock.
+ *
+ * MDock is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MDock is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MDock. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mdock-item.h"
+
+#define MDOCK_ITEM_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), MDOCK_TYPE_ITEM, MDockItemPrivate))
+
+struct _MDockItemPrivate
+{
+};
+
+G_DEFINE_TYPE (MDockItem, mdock_item, GTK_TYPE_BOX)
+
+static void
+mdock_item_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (mdock_item_parent_class)->finalize (object);
+}
+
+static void
+mdock_item_class_init (MDockItemClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = mdock_item_finalize;
+
+ g_type_class_add_private (object_class, sizeof (MDockItemPrivate));
+}
+
+static void
+mdock_item_init (MDockItem *self)
+{
+ self->priv = MDOCK_ITEM_GET_PRIVATE (self);
+}
+
+MDockItem *
+mdock_item_new ()
+{
+ return g_object_new (MDOCK_TYPE_ITEM, NULL);
+}
diff --git a/libmdock/mdock-item.h b/libmdock/mdock-item.h
new file mode 100644
index 0000000..42c3610
--- /dev/null
+++ b/libmdock/mdock-item.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 Javier S. Pedro <dev.git@javispedro.com>
+ *
+ * This file is part of MDock.
+ *
+ * MDock is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MDock is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MDock. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MDOCK_ITEM_H__
+#define __MDOCK_ITEM_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define MDOCK_TYPE_ITEM (mdock_item_get_type())
+#define MDOCK_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MDOCK_TYPE_ITEM, MDockItem))
+#define MDOCK_ITEM_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MDOCK_TYPE_ITEM, MDockItem const))
+#define MDOCK_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MDOCK_TYPE_ITEM, MDockItemClass))
+#define MDOCK_IS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MDOCK_TYPE_ITEM))
+#define MDOCK_IS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MDOCK_TYPE_ITEM))
+#define MDOCK_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MDOCK_TYPE_ITEM, MDockItemClass))
+
+typedef struct _MDockItem MDockItem;
+typedef struct _MDockItemClass MDockItemClass;
+typedef struct _MDockItemPrivate MDockItemPrivate;
+
+struct _MDockItem {
+ GtkBin parent;
+
+ MDockItemPrivate *priv;
+};
+
+struct _MDockItemClass {
+ GtkBinClass parent_class;
+};
+
+GType mdock_item_get_type (void) G_GNUC_CONST;
+MDockItem *mdock_item_new (void);
+
+
+G_END_DECLS
+
+#endif /* __MDOCK_ITEM_H__ */
diff --git a/libmdock/mdock-widget.c b/libmdock/mdock-widget.c
index e69de29..8da6869 100644
--- a/libmdock/mdock-widget.c
+++ b/libmdock/mdock-widget.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2015 Javier S. Pedro <dev.git@javispedro.com>
+ *
+ * This file is part of MDock.
+ *
+ * MDock is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MDock is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MDock. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtk/gtk.h>
+
+#define WNCK_I_KNOW_THIS_IS_UNSTABLE 1
+#include <libwnck/libwnck.h>
+
+#include "mdock-widget.h"
+#include "mdock-item.h"
+#include "matcher.h"
+
+struct _MDockWidgetPrivate
+{
+ WnckScreen *wnck_screen;
+ GSequence *groups;
+};
+
+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))
+
+static void handle_active_window_changed(MDockWidget *self, WnckWindow *previous_window, WnckScreen *screen)
+{
+
+}
+
+static void handle_window_closed(MDockWidget *self, WnckWindow *window, WnckScreen *screen)
+{
+
+}
+
+static void handle_window_opened(MDockWidget *self, WnckWindow *window, WnckScreen *screen)
+{
+ 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);
+}
+
+static void mdock_widget_dispose(GObject *obj)
+{
+ MDockWidget *self = MDOCK_WIDGET(obj);
+ if (self->priv->wnck_screen) {
+ g_signal_handlers_disconnect_by_data(self->priv->wnck_screen, self);
+ self->priv->wnck_screen = NULL;
+ }
+ G_OBJECT_CLASS(mdock_widget_parent_class)->dispose(obj);
+}
+
+static void mdock_widget_class_init(MDockWidgetClass *klass)
+{
+ // GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+ obj_class->dispose = mdock_widget_dispose;
+
+ g_type_class_add_private(klass, sizeof(MDockWidgetPrivate));
+}
+
+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);
+
+ self->priv->groups = g_sequence_new(NULL);
+
+ g_debug("widget init");
+
+ 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);
+ }
+}
+
+GtkWidget *mdock_widget_new(void)
+{
+ return GTK_WIDGET(g_object_new(MDOCK_TYPE_WIDGET, NULL));
+}
diff --git a/libmdock/mdock-widget.h b/libmdock/mdock-widget.h
index 1caf262..00ad496 100644
--- a/libmdock/mdock-widget.h
+++ b/libmdock/mdock-widget.h
@@ -35,14 +35,14 @@ typedef struct _MDockWidget MDockWidget;
typedef struct _MDockWidgetClass MDockWidgetClass;
typedef struct _MDockWidgetPrivate MDockWidgetPrivate;
-struct _TopMenuWidget
+struct _MDockWidget
{
GtkBox parent_instance;
MDockWidgetPrivate *priv;
};
-struct _TopMenuWidgetClass
+struct _MDockWidgetClass
{
GtkBoxClass parent_class;
};