aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/Makefile.am4
-rw-r--r--tools/dbusmenu-dumper.c129
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 <http://www.gnu.org/licenses/>.
*/
#include <glib.h>
+#include <dbus/dbus-glib.h>
#include <libdbusmenu-glib/client.h>
#include <libdbusmenu-glib/menuitem.h>
+#include <X11/Xlib.h>
+
static GMainLoop * mainloop = NULL;
static void
@@ -90,11 +93,105 @@ 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)
{
if (dbusname != NULL) {
@@ -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);