From cd89c60570d17cad28928f3495eded7af2b45431 Mon Sep 17 00:00:00 2001 From: Javier Date: Mon, 19 Jan 2015 00:07:22 +0100 Subject: initially app-id support --- .gitignore | 36 ++++ configure.ac | 7 +- libmdock/Makefile.am | 18 +- libmdock/app-id.c | 157 ++++++++++++++ libmdock/app-id.h | 44 ++++ libmdock/com.javispedro.mdock.widget.gschema.xml | 9 + libmdock/matcher.c | 238 +++++++++++++++++++++ libmdock/matcher.h | 27 +++ libmdock/mdock-enums.c | 6 + libmdock/mdock-enums.h | 25 +++ libmdock/mdock-item.c | 56 +++++ libmdock/mdock-item.h | 55 +++++ libmdock/mdock-widget.c | 103 +++++++++ libmdock/mdock-widget.h | 4 +- ...edro.mdock.MatePanelApplet.mate-panel-applet.in | 10 + ...l.applet.MDockMatePanelAppletFactory.service.in | 3 + test/Makefile.am | 3 - test/mdock-standalone.c | 3 +- 18 files changed, 790 insertions(+), 14 deletions(-) create mode 100644 .gitignore create mode 100644 libmdock/app-id.c create mode 100644 libmdock/app-id.h create mode 100644 libmdock/com.javispedro.mdock.widget.gschema.xml create mode 100644 libmdock/matcher.c create mode 100644 libmdock/matcher.h create mode 100644 libmdock/mdock-enums.c create mode 100644 libmdock/mdock-enums.h create mode 100644 libmdock/mdock-item.c create mode 100644 libmdock/mdock-item.h create mode 100644 mate-applet/com.javispedro.mdock.MatePanelApplet.mate-panel-applet.in create mode 100644 mate-applet/org.mate.panel.applet.MDockMatePanelAppletFactory.service.in diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f6513ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +*.creator.user +*.am.user +config.h +.deps +.libs +*~ +*.o +*.la +*.lo +libmdock/*.gschema.valid +mate-applet/*.mate-panel-applet +mate-applet/*.service +mate-applet/mdock-mate-panel-applet +test/mdock-standalone +missing +compile +m4/libtool.m4 +m4/lt*.m4 +ltmain.sh +libtool +texinfo.tex +Makefile +Makefile.in +Makefile.msc +aclocal.m4 +autom4te.cache +config.guess +config.log +config.status +config.sub +configure +depcomp +INSTALL +install-sh +stamp-h1 + diff --git a/configure.ac b/configure.ac index 20ecfc1..5e64854 100644 --- a/configure.ac +++ b/configure.ac @@ -5,7 +5,7 @@ AC_PREREQ([2.69]) AC_INIT(libtopmenu-gtk, 1.0, javier@javispedro.com) AC_CONFIG_SRCDIR([libmdock/mdock-widget.h]) AC_CONFIG_HEADERS([config.h]) -AM_INIT_AUTOMAKE([foreign]) +AM_INIT_AUTOMAKE([-Wall -Wno-extra-portability foreign]) AC_CONFIG_MACRO_DIR([m4]) @@ -17,11 +17,16 @@ AC_ARG_ENABLE([mate-applet], # Checks for programs. AC_PROG_CC AM_PROG_CC_C_O +AC_PROG_CC_STDC AC_PROG_LIBTOOL +GLIB_GSETTINGS + # Checks for libraries. PKG_CHECK_MODULES([GTK], [gtk+-x11-2.0]) +PKG_CHECK_MODULES([GIO], [gio-unix-2.0]) PKG_CHECK_MODULES([WNCK], [libwnck-1.0]) +PKG_CHECK_MODULES([GTOP], [libgtop-2.0]) AS_IF([test "x$enable_mate_applet" != xno], [PKG_CHECK_MODULES([MATEPANELAPPLET], [libmatepanelapplet-4.0], 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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#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 + * + * 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 . + */ + +#ifndef _MDOCK_APPID_H_ +#define _MDOCK_APPID_H_ + +#include +#define WNCK_I_KNOW_THIS_IS_UNSTABLE 1 +#include + +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 @@ + + + + + [] + Items in the dock + + + 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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#ifndef __MDOCK_ITEM_H__ +#define __MDOCK_ITEM_H__ + +#include + +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 + * + * 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 . + */ + +#include + +#define WNCK_I_KNOW_THIS_IS_UNSTABLE 1 +#include + +#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; }; diff --git a/mate-applet/com.javispedro.mdock.MatePanelApplet.mate-panel-applet.in b/mate-applet/com.javispedro.mdock.MatePanelApplet.mate-panel-applet.in new file mode 100644 index 0000000..7bcfdfd --- /dev/null +++ b/mate-applet/com.javispedro.mdock.MatePanelApplet.mate-panel-applet.in @@ -0,0 +1,10 @@ +[Applet Factory] +Id=MDockMatePanelAppletFactory +Location=@LIBEXECDIR@/mdock-mate-panel-applet +Name=MDock Mate Panel Applet Factory +Description=MDock Mate Panel Applet Factory + +[MDockMatePanelApplet] +Name=MDock Panel Applet +Description=MDock taskbar +Icon=user-trash-full diff --git a/mate-applet/org.mate.panel.applet.MDockMatePanelAppletFactory.service.in b/mate-applet/org.mate.panel.applet.MDockMatePanelAppletFactory.service.in new file mode 100644 index 0000000..cbab2c4 --- /dev/null +++ b/mate-applet/org.mate.panel.applet.MDockMatePanelAppletFactory.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.mate.panel.applet.MDockMatePanelAppletFactory +Exec=@LIBEXECDIR@/mdock-mate-panel-applet diff --git a/test/Makefile.am b/test/Makefile.am index 6ac6987..65d5220 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,8 +1,5 @@ noinst_PROGRAMS = mdock-standalone -AM_CPPFLAGS = $(GTK_CFLAGS) -AM_LDFLAGS = $(GTK_LIBS) - mdock_standalone_SOURCES = mdock-standalone.c mdock_standalone_CPPFLAGS = $(GTK_CFLAGS) mdock_standalone_LDADD = $(GTK_LIBS) ../libmdock/libmdock.la diff --git a/test/mdock-standalone.c b/test/mdock-standalone.c index e164bea..fee91a6 100644 --- a/test/mdock-standalone.c +++ b/test/mdock-standalone.c @@ -34,7 +34,6 @@ static void construct_main_window() int main(int argc, char **argv) { gtk_init(&argc, &argv); - gtk_main(); construct_main_window(); @@ -42,5 +41,7 @@ int main(int argc, char **argv) gtk_widget_show_all(GTK_WIDGET(mainwin)); + gtk_main(); + return EXIT_SUCCESS; } -- cgit v1.2.3