From 9f4213d9d59c84c9c4811a69ee50d4baaab6dc58 Mon Sep 17 00:00:00 2001 From: Aurelien Gateau Date: Mon, 19 Jul 2010 12:53:38 +0200 Subject: Started to implement click-to-dump --- tools/Makefile.am | 4 +- tools/dbusmenu-dumper.c | 129 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 122 insertions(+), 11 deletions(-) diff --git a/tools/Makefile.am b/tools/Makefile.am index 77d6eef..a36d224 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -10,11 +10,11 @@ dbusmenu_dumper_SOURCES = \ dbusmenu_dumper_CFLAGS = \ -I $(srcdir)/.. \ - $(DBUSMENUGLIB_CFLAGS) -Wall -Werror + $(DBUSMENUGLIB_CFLAGS) -I/usr/include/dbus-1.0 -Wall -Werror dbusmenu_dumper_LDADD = \ ../libdbusmenu-glib/libdbusmenu-glib.la \ - $(DBUSMENUGLIB_LIBS) + $(DBUSMENUGLIB_LIBS) -lX11 -ldbus-glib-1 doc_DATA = README.dbusmenu-bench diff --git a/tools/dbusmenu-dumper.c b/tools/dbusmenu-dumper.c index 55d631e..4a0dd03 100644 --- a/tools/dbusmenu-dumper.c +++ b/tools/dbusmenu-dumper.c @@ -21,10 +21,13 @@ with this program. If not, see . */ #include +#include #include #include +#include + static GMainLoop * mainloop = NULL; static void @@ -90,10 +93,104 @@ new_root_cb (DbusmenuClient * client, DbusmenuMenuitem * newroot) return; } +static Window +find_real_window(Display * display, Window w, int depth) +{ + if (depth > 5) { + return None; + } + /*static*/ Atom wm_state = XInternAtom(display, "WM_STATE", False); + Atom type; + int format; + unsigned long nitems, after; + unsigned char* prop; + if (XGetWindowProperty(display, w, wm_state, 0, 0, False, AnyPropertyType, + &type, &format, &nitems, &after, &prop) == Success) { + if (prop != NULL) { + XFree(prop); + } + if (type != None) { + return w; + } + } + Window root, parent; + Window* children; + unsigned int nchildren; + Window ret = None; + if (XQueryTree(display, w, &root, &parent, &children, &nchildren) != 0) { + unsigned int i; + for(i = 0; i < nchildren && ret == None; ++i) { + ret = find_real_window(display, children[ i ], depth + 1); + } + if (children != NULL) { + XFree(children); + } + } + return ret; +} + +static Window +get_window_under_cursor() +{ + Display * display = XOpenDisplay(NULL); + g_return_val_if_fail(display != NULL, None); + + Window root; + Window child; + uint mask; + int rootX, rootY, winX, winY; + XGrabServer(display); + Window root_window = DefaultRootWindow(display); + XQueryPointer(display, root_window, &root, &child, &rootX, &rootY, &winX, &winY, &mask); + if (child == None) { + return None; + } + return find_real_window(display, child, 0); +} static gchar * dbusname = NULL; static gchar * dbusobject = NULL; +static gboolean +init_dbus_vars_from_window(Window window) +{ + DBusGConnection *connection; + GError *error; + DBusGProxy *proxy; + + error = NULL; + connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + if (connection == NULL) { + g_printerr("Failed to open connection to bus: %s\n", error->message); + g_error_free(error); + return FALSE; + } + + proxy = dbus_g_proxy_new_for_name (connection, + "org.ayatana.AppMenu.Registrar", + "/org/ayatana/AppMenu/Registrar", + "org.ayatana.AppMenu.Registrar"); + + error = NULL; + if (!dbus_g_proxy_call (proxy, "GetMenuForWindow", &error, + G_TYPE_UINT, window, G_TYPE_INVALID, + G_TYPE_STRING, &dbusname, DBUS_TYPE_G_OBJECT_PATH, &dbusobject, G_TYPE_INVALID)) + { + g_printerr("ERROR: %s\n", error->message); + g_error_free(error); + g_object_unref(proxy); + return FALSE; + } + + if (!g_strcmp0(dbusobject, "/")) { + return FALSE; + } + + g_object_unref (proxy); + + return TRUE; +} + static gboolean option_dbusname (const gchar * arg, const gchar * value, gpointer data, GError ** error) { @@ -147,16 +244,30 @@ main (int argc, char ** argv) return 1; } - if (dbusname == NULL) { - g_printerr("ERROR: dbus-name not specified\n"); - usage(); - return 1; - } + if (dbusname == NULL && dbusobject == NULL) { + Window window = get_window_under_cursor(); + if (window == None) { + g_printerr("ERROR: could not get the id for the pointed window\n"); + return 1; + } + g_debug("window: %u", (unsigned int)window); + if (!init_dbus_vars_from_window(window)) { + g_printerr("ERROR: could not find a menu for the pointed window\n"); + return 1; + } + g_debug("dbusname: %s, dbusobject: %s", dbusname, dbusobject); + } else { + if (dbusname == NULL) { + g_printerr("ERROR: dbus-name not specified\n"); + usage(); + return 1; + } - if (dbusobject == NULL) { - g_printerr("ERROR: dbus-object not specified\n"); - usage(); - return 1; + if (dbusobject == NULL) { + g_printerr("ERROR: dbus-object not specified\n"); + usage(); + return 1; + } } DbusmenuClient * client = dbusmenu_client_new (dbusname, dbusobject); -- cgit v1.2.3