← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~ted/indicator-appmenu/bamf-it into lp:indicator-appmenu

 

Ted Gould has proposed merging lp:~ted/indicator-appmenu/bamf-it into lp:indicator-appmenu.

Requested reviews:
  Indicator Applet Developers (indicator-applet-developers)


Basic application switching support.  Still doesn't detect applications leaving, but does switch between them.  Also, breaks some Qt apps that send two menus for the same window ID.  I think it's in a good place to end this branch though as it basically works.
-- 
https://code.launchpad.net/~ted/indicator-appmenu/bamf-it/+merge/26779
Your team ayatana-commits is subscribed to branch lp:indicator-appmenu.
=== modified file '.bzrignore'
--- .bzrignore	2010-06-02 14:05:45 +0000
+++ .bzrignore	2010-06-04 04:51:23 +0000
@@ -16,3 +16,4 @@
 scripts/menu-pusher
 src/application-menu-debug-client.h
 src/application-menu-debug-server.h
+tools/current-menu-dump

=== modified file 'configure.ac'
--- configure.ac	2010-06-02 17:50:51 +0000
+++ configure.ac	2010-06-04 04:51:23 +0000
@@ -41,11 +41,13 @@
 INDICATOR_REQUIRED_VERSION=0.3.5
 DBUSMENUGTK_REQUIRED_VERSION=0.3.0
 DBUS_GLIB_REQUIRED_VERSION=0.82
+BAMF_REQUIRED_VERSION=0.2
 
 PKG_CHECK_MODULES(INDICATOR, gtk+-2.0 >= $GTK_REQUIRED_VERSION
                              indicator >= $INDICATOR_REQUIRED_VERSION
                              dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
-                             dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION)
+                             dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION
+                             libbamf >= $BAMF_REQUIRED_VERSION)
 
 AC_SUBST(INDICATOR_CFLAGS)
 AC_SUBST(INDICATOR_LIBS)

=== modified file 'src/indicator-appmenu.c'
--- src/indicator-appmenu.c	2010-06-02 17:28:39 +0000
+++ src/indicator-appmenu.c	2010-06-04 04:51:23 +0000
@@ -30,6 +30,8 @@
 #include <libindicator/indicator.h>
 #include <libindicator/indicator-object.h>
 
+#include <libbamf/bamf-matcher.h>
+
 #include "indicator-appmenu-marshal.h"
 #include "window-menus.h"
 #include "dbus-shared.h"
@@ -67,6 +69,8 @@
 	WindowMenus * default_app;
 	GHashTable * apps;
 
+	BamfMatcher * matcher;
+
 	gulong sig_entry_added;
 	gulong sig_entry_removed;
 
@@ -124,6 +128,10 @@
 static void window_entry_removed                                     (WindowMenus * mw,
                                                                       IndicatorObjectEntry * entry,
                                                                       gpointer user_data);
+static void active_window_changed                                    (BamfMatcher * matcher,
+                                                                      BamfView * oldview,
+                                                                      BamfView * newview,
+                                                                      gpointer user_data);
 static gboolean _application_menu_debug_server_current_menu          (IndicatorAppmenuDebug * iappd,
                                                                       guint * windowid,
                                                                       gchar ** objectpath,
@@ -189,7 +197,18 @@
 {
 	self->default_app = NULL;
 	self->debug = NULL;
-	self->apps = g_hash_table_new_full(NULL, NULL, NULL, g_object_unref);
+	self->apps = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
+	self->matcher = NULL;
+
+	/* Get the default BAMF matcher */
+	self->matcher = bamf_matcher_get_default();
+	if (self->matcher == NULL) {
+		/* we don't want to exit out of Unity -- but this
+		   should really never happen */
+		g_warning("Unable to get BAMF matcher, can not watch applications switch!");
+	} else {
+		g_signal_connect(G_OBJECT(self->matcher), "active-window-changed", G_CALLBACK(active_window_changed), self);
+	}
 
 	/* Register this object on DBus */
 	DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
@@ -222,6 +241,13 @@
 {
 	IndicatorAppmenu * iapp = INDICATOR_APPMENU(object);
 
+	/* bring down the matcher before resetting to no menu so we don't
+	   get match signals */
+	if (iapp->matcher != NULL) {
+		g_object_unref(iapp->matcher);
+		iapp->matcher = NULL;
+	}
+
 	/* No specific ref */
 	switch_default_app (iapp, NULL);
 
@@ -314,6 +340,16 @@
 	/* Remove old */
 	if (iapp->default_app != NULL) {
 		for (entries = window_menus_get_entries(iapp->default_app); entries != NULL; entries = g_list_next(entries)) {
+			IndicatorObjectEntry * entry = (IndicatorObjectEntry *)entries->data;
+
+			if (entry->label != NULL) {
+				gtk_widget_hide(GTK_WIDGET(entry->label));
+			}
+
+			if (entry->menu != NULL) {
+				gtk_menu_detach(entry->menu);
+			}
+
 			g_signal_emit(G_OBJECT(iapp), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID, 0, entries->data, TRUE);
 		}
 	}
@@ -346,6 +382,12 @@
 	/* Add new */
 	if (iapp->default_app != NULL) {
 		for (entries = window_menus_get_entries(iapp->default_app); entries != NULL; entries = g_list_next(entries)) {
+			IndicatorObjectEntry * entry = (IndicatorObjectEntry *)entries->data;
+
+			if (entry->label != NULL) {
+				gtk_widget_show(GTK_WIDGET(entry->label));
+			}
+
 			g_signal_emit(G_OBJECT(iapp), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID, 0, entries->data, TRUE);
 		}
 	}
@@ -353,20 +395,51 @@
 	return;
 }
 
+/* Recieve the signal that the window being shown
+   has now changed. */
+static void
+active_window_changed (BamfMatcher * matcher, BamfView * oldview, BamfView * newview, gpointer user_data)
+{
+	if (!BAMF_IS_WINDOW(newview)) {
+		/* We're only dealing with windows currently */
+		return;
+	}
+	BamfWindow * window = BAMF_WINDOW(newview);
+
+	IndicatorAppmenu * appmenu = INDICATOR_APPMENU(user_data);
+
+	guint32 xid = bamf_window_get_xid(window);
+	g_debug("window changed to %d", xid);
+	
+	WindowMenus * menus = g_hash_table_lookup(appmenu->apps, GINT_TO_POINTER(xid));
+
+	/* Note: This function can handle menus being NULL */
+	switch_default_app(appmenu, menus);
+
+	return;
+}
+
 /* A new window wishes to register it's windows with us */
 static gboolean
 _application_menu_registrar_server_register_window (IndicatorAppmenu * iapp, guint windowid, const gchar * objectpath, DBusGMethodInvocation * method)
 {
-	if (TRUE || g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(windowid)) == NULL) {
+	g_debug("Registering window ID %d with path %s from %s", windowid, objectpath, dbus_g_method_get_sender(method));
+
+	if (g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(windowid)) == NULL) {
 		WindowMenus * wm = window_menus_new(windowid, dbus_g_method_get_sender(method), objectpath);
-		//g_hash_table_insert(iapp->apps, GUINT_TO_POINTER(windowid), wm);
-
-		/* TODO: Check to see if it's the visible window */
-		switch_default_app(iapp, wm);
+		g_hash_table_insert(iapp->apps, GUINT_TO_POINTER(windowid), wm);
 
 		g_signal_emit(G_OBJECT(iapp), signals[WINDOW_REGISTERED], 0, windowid, objectpath, TRUE);
+
+		/* Node: Does not cause ref */
+		BamfWindow * win = bamf_matcher_get_active_window(iapp->matcher);
+		guint32 xid = bamf_window_get_xid(win);
+
+		if (xid == windowid) {
+			switch_default_app(iapp, wm);
+		}
 	} else {
-		g_warning("Already have a menu for window ID %X with path %s from %s", windowid, objectpath, dbus_g_method_get_sender(method));
+		g_warning("Already have a menu for window ID %d with path %s from %s", windowid, objectpath, dbus_g_method_get_sender(method));
 	}
 
 	dbus_g_method_return(method);

=== modified file 'src/window-menus.c'
--- src/window-menus.c	2010-06-02 17:44:59 +0000
+++ src/window-menus.c	2010-06-04 04:51:23 +0000
@@ -128,6 +128,18 @@
 	WindowMenusPrivate * priv = WINDOW_MENUS_GET_PRIVATE(object);
 
 	if (priv->entries != NULL) {
+		int i;
+		for (i = 0; i < priv->entries->len; i++) {
+			IndicatorObjectEntry * entry;
+			entry = g_array_index(priv->entries, IndicatorObjectEntry *, i);
+			
+			if (entry->label != NULL) {
+				g_object_unref(entry->label);
+			}
+			if (entry->menu != NULL) {
+				g_object_unref(entry->menu);
+			}
+		}
 		g_array_free(priv->entries, TRUE);
 		priv->entries = NULL;
 	}
@@ -300,10 +312,18 @@
 	IndicatorObjectEntry * entry = g_new0(IndicatorObjectEntry, 1);
 
 	entry->label = GTK_LABEL(gtk_label_new_with_mnemonic(dbusmenu_menuitem_property_get(newentry, DBUSMENU_MENUITEM_PROP_LABEL)));
+
+	if (entry->label != NULL) {
+		g_object_ref(entry->label);
+	}
+
 	entry->menu = dbusmenu_gtkclient_menuitem_get_submenu(priv->client, newentry);
 
 	if (entry->menu == NULL) {
 		g_debug("Submenu for %s is NULL", dbusmenu_menuitem_property_get(newentry, DBUSMENU_MENUITEM_PROP_LABEL));
+	} else {
+		g_object_ref(entry->menu);
+		gtk_menu_detach(entry->menu);
 	}
 
 	gtk_widget_show(GTK_WIDGET(entry->label));


Follow ups