aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2011-02-21 11:22:46 -0600
committerTed Gould <ted@gould.cx>2011-02-21 11:22:46 -0600
commit2f92a8662f5a84f9ef35dd847539f573f60edc5f (patch)
tree9c00fda471a88fcc331c858bc2de66076f7de9ef /tools
parent71020d95b0eb9f583523628261d26336a5dceb39 (diff)
parent34248e4fe3aeef17be5fe9f2339057fbaee81ad2 (diff)
downloadlibdbusmenu-2f92a8662f5a84f9ef35dd847539f573f60edc5f.tar.gz
libdbusmenu-2f92a8662f5a84f9ef35dd847539f573f60edc5f.tar.bz2
libdbusmenu-2f92a8662f5a84f9ef35dd847539f573f60edc5f.zip
Another update to trunk
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.am7
-rwxr-xr-xtools/dbusmenu-bench2
-rw-r--r--tools/dbusmenu-dumper.c251
-rw-r--r--tools/testapp/Makefile.am8
-rw-r--r--tools/testapp/main.c49
5 files changed, 275 insertions, 42 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 77d6eef..48993f1 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -10,11 +10,14 @@ dbusmenu_dumper_SOURCES = \
dbusmenu_dumper_CFLAGS = \
-I $(srcdir)/.. \
- $(DBUSMENUGLIB_CFLAGS) -Wall -Werror
+ $(DBUSMENUGLIB_CFLAGS) \
+ $(DBUSMENUDUMPER_CFLAGS) \
+ -Wall -Werror
dbusmenu_dumper_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
- $(DBUSMENUGLIB_LIBS)
+ $(DBUSMENUGLIB_LIBS) \
+ $(DBUSMENUDUMPER_LIBS)
doc_DATA = README.dbusmenu-bench
diff --git a/tools/dbusmenu-bench b/tools/dbusmenu-bench
index 4b58da8..dcf5f6f 100755
--- a/tools/dbusmenu-bench
+++ b/tools/dbusmenu-bench
@@ -35,7 +35,7 @@ from xml.etree import ElementTree as ET
import dbus
-DBUS_INTERFACE = "org.ayatana.dbusmenu"
+DBUS_INTERFACE = "com.canonical.dbusmenu"
DBUS_SERVICE = "org.dbusmenu.test"
DBUS_PATH = "/MenuBar"
diff --git a/tools/dbusmenu-dumper.c b/tools/dbusmenu-dumper.c
index 55d631e..2db437d 100644
--- a/tools/dbusmenu-dumper.c
+++ b/tools/dbusmenu-dumper.c
@@ -22,25 +22,38 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
#include <libdbusmenu-glib/client.h>
#include <libdbusmenu-glib/menuitem.h>
+#include <X11/Xlib.h>
+
static GMainLoop * mainloop = NULL;
+static gint
+list_str_cmp (gconstpointer a, gconstpointer b)
+{
+ return g_strcmp0((gchar *)a, (gchar *)b);
+}
+
static void
print_menuitem (DbusmenuMenuitem * item, int depth)
{
gchar * space = g_strnfill(depth, ' ');
g_print("%s\"id\": %d", space, dbusmenu_menuitem_get_id(item));
- GList * properties = dbusmenu_menuitem_properties_list(item);
+ GList * properties_raw = dbusmenu_menuitem_properties_list(item);
+ GList * properties = g_list_sort(properties_raw, list_str_cmp);
GList * property;
for (property = properties; property != NULL; property = g_list_next(property)) {
- GValue value = {0};
- g_value_init(&value, G_TYPE_STRING);
- g_value_transform(dbusmenu_menuitem_property_get_value(item, (gchar *)property->data), &value);
- g_print(",\n%s\"%s\": \"%s\"", space, (gchar *)property->data, g_value_get_string(&value));
- g_value_unset(&value);
+ GVariant * variant = dbusmenu_menuitem_property_get_variant(item, (gchar *)property->data);
+ gchar * str = g_variant_print(variant, FALSE);
+ g_print(",\n%s\"%s\": %s", space, (gchar *)property->data, str);
+ g_free(str);
+ g_variant_unref(variant);
}
g_list_free(properties);
@@ -90,11 +103,200 @@ new_root_cb (DbusmenuClient * client, DbusmenuMenuitem * newroot)
return;
}
+/* Window clicking ***************************************************/
+static GdkFilterReturn
+click_filter (GdkXEvent *gdk_xevent,
+ GdkEvent *event,
+ gpointer data);
+
+static Window
+find_real_window (Window w, int depth)
+{
+ if (depth > 5) {
+ return None;
+ }
+ /*static*/ Atom wm_state = XInternAtom(gdk_display, "WM_STATE", False);
+ Atom type;
+ int format;
+ unsigned long nitems, after;
+ unsigned char* prop;
+ if (XGetWindowProperty(gdk_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(gdk_display, w, &root, &parent, &children, &nchildren) != 0) {
+ unsigned int i;
+ for(i = 0; i < nchildren && ret == None; ++i) {
+ ret = find_real_window(children[ i ], depth + 1);
+ }
+ if (children != NULL) {
+ XFree(children);
+ }
+ }
+ return ret;
+}
+
+static Window
+get_window_under_cursor (void)
+{
+ Window root;
+ Window child;
+ uint mask;
+ int rootX, rootY, winX, winY;
+ XQueryPointer(gdk_display, gdk_x11_get_default_root_xwindow(), &root, &child, &rootX, &rootY, &winX, &winY, &mask);
+ if (child == None) {
+ return None;
+ }
+ return find_real_window(child, 0);
+}
+
+static void
+uninstall_click_filter (void)
+{
+ GdkWindow *root;
+
+ root = gdk_get_default_root_window ();
+ gdk_window_remove_filter (root, (GdkFilterFunc) click_filter, NULL);
+
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+
+ gtk_main_quit ();
+}
+
+static GdkFilterReturn
+click_filter (GdkXEvent *gdk_xevent,
+ GdkEvent *event,
+ gpointer data)
+
+{
+ XEvent *xevent = (XEvent *) gdk_xevent;
+ gboolean *success = (gboolean *)data;
+
+ switch (xevent->type) {
+ case ButtonPress:
+ uninstall_click_filter();
+ *success = TRUE;
+ return GDK_FILTER_REMOVE;
+ case KeyPress:
+ if (xevent->xkey.keycode == XKeysymToKeycode(gdk_display, XK_Escape)) {
+ uninstall_click_filter();
+ *success = FALSE;
+ return GDK_FILTER_REMOVE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static gboolean
+install_click_filter (gpointer data)
+{
+ GdkGrabStatus status;
+ GdkCursor *cross;
+ GdkWindow *root;
+
+ root = gdk_get_default_root_window();
+
+ gdk_window_add_filter(root, (GdkFilterFunc) click_filter, data);
+
+ cross = gdk_cursor_new(GDK_CROSS);
+ status = gdk_pointer_grab(root, FALSE, GDK_BUTTON_PRESS_MASK,
+ NULL, cross, GDK_CURRENT_TIME);
+ gdk_cursor_unref(cross);
+
+ if (status != GDK_GRAB_SUCCESS) {
+ g_warning("Pointer grab failed.\n");
+ uninstall_click_filter();
+ return FALSE;
+ }
+
+ status = gdk_keyboard_grab(root, FALSE, GDK_CURRENT_TIME);
+ if (status != GDK_GRAB_SUCCESS) {
+ g_warning("Keyboard grab failed.\n");
+ uninstall_click_filter();
+ return FALSE;
+ }
+
+ gdk_flush();
+ return FALSE;
+}
+
+static gboolean
+wait_for_click (void)
+{
+ gboolean success;
+ g_idle_add (install_click_filter, (gpointer)(&success));
+ gtk_main ();
+ return success;
+}
static gchar * dbusname = NULL;
static gchar * dbusobject = NULL;
static gboolean
+init_dbus_vars_from_window(Window window)
+{
+ GError *error;
+ GDBusProxy *proxy;
+
+ error = NULL;
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "com.canonical.AppMenu.Registrar",
+ "/com/canonical/AppMenu/Registrar",
+ "com.canonical.AppMenu.Registrar",
+ NULL,
+ &error);
+ if (error != NULL) {
+ g_warning("Unable to get registrar proxy: %s", error->message);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ error = NULL;
+ GVariant * retval;
+ GVariant * args[1];
+ args[0] = g_variant_new("u", window);
+
+ retval = g_dbus_proxy_call_sync(proxy,
+ "GetMenuForWindow",
+ g_variant_new_tuple(args, 1),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (error != NULL) {
+ g_warning("Unable to call 'GetMenuForWindow' on registrar: %s", error->message);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ g_variant_get(retval, "(so)", &dbusname, &dbusobject);
+
+ g_variant_unref(retval);
+ g_object_unref(proxy);
+
+ return TRUE;
+}
+
+/* Option parser *****************************************************/
+static gboolean
option_dbusname (const gchar * arg, const gchar * value, gpointer data, GError ** error)
{
if (dbusname != NULL) {
@@ -127,7 +329,8 @@ usage (void)
static GOptionEntry general_options[] = {
{"dbus-name", 'd', 0, G_OPTION_ARG_CALLBACK, option_dbusname, "The name of the program to connect to (i.e. org.test.bob", "dbusname"},
- {"dbus-object", 'o', 0, G_OPTION_ARG_CALLBACK, option_dbusobject, "The path to the Dbus object (i.e /org/test/bob/alvin)", "dbusobject"}
+ {"dbus-object", 'o', 0, G_OPTION_ARG_CALLBACK, option_dbusobject, "The path to the Dbus object (i.e /org/test/bob/alvin)", "dbusobject"},
+ {NULL}
};
int
@@ -147,16 +350,32 @@ 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) {
+ gtk_init(&argc, &argv);
+ if (!wait_for_click()) {
+ return 1;
+ }
+ Window window = get_window_under_cursor();
+ if (window == None) {
+ g_printerr("ERROR: could not get the id for the pointed window\n");
+ return 1;
+ }
+ if (!init_dbus_vars_from_window(window)) {
+ g_printerr("ERROR: could not find a menu for the pointed window\n");
+ return 1;
+ }
+ } 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);
diff --git a/tools/testapp/Makefile.am b/tools/testapp/Makefile.am
index a8b42dd..39de532 100644
--- a/tools/testapp/Makefile.am
+++ b/tools/testapp/Makefile.am
@@ -1,4 +1,10 @@
+if USE_GTK3
+VER=3
+else
+VER=
+endif
+
libexec_PROGRAMS = dbusmenu-testapp
dbusmenu_testapp_SOURCES = \
@@ -12,6 +18,6 @@ dbusmenu_testapp_CFLAGS = \
dbusmenu_testapp_LDADD = \
$(builddir)/../../libdbusmenu-glib/libdbusmenu-glib.la \
- $(builddir)/../../libdbusmenu-gtk/libdbusmenu-gtk.la \
+ $(builddir)/../../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
$(DBUSMENUGTK_LIBS) \
$(DBUSMENUTESTS_LIBS)
diff --git a/tools/testapp/main.c b/tools/testapp/main.c
index f489407..67e962d 100644
--- a/tools/testapp/main.c
+++ b/tools/testapp/main.c
@@ -26,9 +26,7 @@ License version 3 and version 2.1 along with this program. If not, see
<http://www.gnu.org/licenses/>
*/
#include <glib.h>
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-bindings.h>
+#include <gio/gio.h>
#include <json-glib/json-glib.h>
@@ -117,6 +115,24 @@ void init_menu(DbusmenuMenuitem *root, const char *filename)
}
}
+static void
+on_bus (GDBusConnection * connection, const gchar * name, gpointer user_data)
+{
+ DbusmenuServer *server = dbusmenu_server_new("/MenuBar");
+ DbusmenuMenuitem *root = dbusmenu_menuitem_new_with_id(0);
+ init_menu(root, (gchar *)user_data);
+ dbusmenu_server_set_root(server, root);
+
+ return;
+}
+
+static void
+name_lost (GDBusConnection * connection, const gchar * name, gpointer user_data)
+{
+ g_error("Unable to get name '%s' on DBus", name);
+ return;
+}
+
int main (int argc, char ** argv)
{
g_type_init();
@@ -127,25 +143,14 @@ int main (int argc, char ** argv)
}
const char *filename = argv[1];
- GError * error = NULL;
- DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
- DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
- guint nameret = 0;
-
- if (!org_freedesktop_DBus_request_name(bus_proxy, "org.dbusmenu.test", 0, &nameret, &error)) {
- g_error("Unable to call to request name");
- return 1;
- }
-
- if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
- g_error("Unable to get name");
- return 1;
- }
-
- DbusmenuServer *server = dbusmenu_server_new("/MenuBar");
- DbusmenuMenuitem *root = dbusmenu_menuitem_new_with_id(0);
- init_menu(root, filename);
- dbusmenu_server_set_root(server, root);
+ g_bus_own_name(G_BUS_TYPE_SESSION,
+ "org.dbusmenu.test",
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_bus,
+ NULL,
+ name_lost,
+ (gpointer)filename,
+ NULL);
g_main_loop_run(g_main_loop_new(NULL, FALSE));