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 --- libmdock/app-id.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 libmdock/app-id.c (limited to 'libmdock/app-id.c') 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; +} -- cgit v1.2.3