im.pidgin.pidgin.next.minor: 457a3a60abf75010d7855c1f25254e8118d38466

sadrul at pidgin.im sadrul at pidgin.im
Tue Nov 27 21:00:40 EST 2007


-----------------------------------------------------------------
Revision: 457a3a60abf75010d7855c1f25254e8118d38466
Ancestor: da0d4c8ba9b1b9cd941d52c03d6beac54afe1a6e
Author: sadrul at pidgin.im
Date: 2007-11-28T01:54:34
Branch: im.pidgin.pidgin.next.minor

Modified files:
        ChangeLog.API pidgin/gtkconv.c pidgin/gtknotify.c
        pidgin/gtkrequest.c pidgin/gtkutils.c pidgin/gtkutils.h

ChangeLog: 

Try to make a window transient for a suitable parent window. This currently
happens only for the request and notify windows, and only when they are
triggered by some GTK+ event.
There are some issues when a request/notify window pops up from activating
a popup menuitem. I found a fix for when the menuitem is activated by a
keypress. I'll try to find a fix for a mouse-button later.

-------------- next part --------------
============================================================
--- ChangeLog.API	52bdd2272f65bbc2ede73e6cb2e86b84faa45021
+++ ChangeLog.API	ffebba18e0926bf97f901441acec51ad4465f108
@@ -15,6 +15,8 @@ version 2.4.0 (??/??/????):
 		  pidgin_create_dialog.
 		* GTK_IMHTML_NO_SMILEY for GtkIMHtmlOptions means not to look for
 		  smileys in the text. (Florian 'goutnet' Delizy)
+		* pidgin_auto_parent_window to make a window transient for a suitable
+		  parent window.
 
 version 2.3.0 (11/24/2007):
 	libpurple:
============================================================
--- pidgin/gtkconv.c	3cead6dc548476a7beee928e939f305f7f0acba5
+++ pidgin/gtkconv.c	f152ddda1ea63ffc8bdc264cd67e2d0d232ddf81
@@ -8163,7 +8163,7 @@ infopane_press_cb(GtkWidget *widget, Gdk
 	}
 	
 	if (e->button == 3) {
-		/* Right click was pressed. Popup the Send To menu. */
+		/* Right click was pressed. Popup the context menu. */
 		GtkWidget *menu = gtk_menu_new(), *sub;
 		gboolean populated = populate_menu_with_options(menu, gtkconv, TRUE);
 		sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to));
============================================================
--- pidgin/gtknotify.c	4a1812fcd29fe4424adf89865e4b0f7deedc0c46
+++ pidgin/gtknotify.c	fcdecd5714ca8e71c1b407bff4450e06fda78810
@@ -284,6 +284,8 @@ pidgin_notify_message(PurpleNotifyMsgTyp
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
 
+	pidgin_auto_parent_window(dialog);
+
 	gtk_widget_show_all(dialog);
 
 	return dialog;
@@ -684,6 +686,8 @@ pidgin_notify_formatted(const char *titl
 	g_object_set_data(G_OBJECT(window), "info-widget", imhtml);
 
 	/* Show the window */
+	pidgin_auto_parent_window(window);
+
 	gtk_widget_show(window);
 
 	return window;
@@ -894,6 +898,8 @@ pidgin_notify_searchresults(PurpleConnec
 	pidgin_notify_searchresults_new_rows(gc, results, data);
 
 	/* Show the window */
+	pidgin_auto_parent_window(window);
+
 	gtk_widget_show(window);
 	return data;
 }
============================================================
--- pidgin/gtkrequest.c	72f053d9098adc6c1cc9cc0ac25607db12c64405
+++ pidgin/gtkrequest.c	c698c330d40d7470a8bd84491dacfc844a06bc09
@@ -439,6 +439,8 @@ pidgin_request_input(const char *title, 
 	pidgin_set_accessible_label (entry, label);
 	data->u.input.entry = entry;
 
+	pidgin_auto_parent_window(dialog);
+
 	/* Show everything. */
 	gtk_widget_show(dialog);
 
@@ -546,6 +548,8 @@ pidgin_request_choice(const char *title,
 	g_object_set_data(G_OBJECT(dialog), "radio", radio);
 
 	/* Show everything. */
+	pidgin_auto_parent_window(dialog);
+
 	gtk_widget_show_all(dialog);
 
 	return data;
@@ -661,6 +665,8 @@ pidgin_request_action(const char *title,
 		gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_action);
 
 	/* Show everything. */
+	pidgin_auto_parent_window(dialog);
+
 	gtk_widget_show_all(dialog);
 
 	return data;
@@ -1394,6 +1400,8 @@ pidgin_request_fields(const char *title,
 	if (!purple_request_fields_all_required_filled(fields))
 		gtk_widget_set_sensitive(button, FALSE);
 
+	pidgin_auto_parent_window(win);
+
 	gtk_widget_show(win);
 
 	return data;
@@ -1601,6 +1609,8 @@ pidgin_request_file(const char *title, c
 					 G_CALLBACK(file_ok_check_if_exists_cb), data);
 #endif /* FILECHOOSER */
 
+	pidgin_auto_parent_window(filesel);
+
 	data->dialog = filesel;
 	gtk_widget_show(filesel);
 
@@ -1652,6 +1662,8 @@ pidgin_request_folder(const char *title,
 #endif
 
 	data->dialog = dirsel;
+	pidgin_auto_parent_window(dirsel);
+
 	gtk_widget_show(dirsel);
 
 	return (void *)data;
============================================================
--- pidgin/gtkutils.c	0d9cb43e8df70ba43c59d2b83535c04ea6ef7f79
+++ pidgin/gtkutils.c	f350a8fecb960ac71eb7f05a09c0e32be8072dcc
@@ -3312,3 +3312,107 @@ void pidgin_text_combo_box_entry_set_tex
 	gtk_entry_set_text(GTK_ENTRY(GTK_BIN((widget))->child), (text));
 }
 
+gboolean pidgin_auto_parent_window(GtkWidget *widget)
+{
+#if 0
+	/* This looks at the most recent window that received focus, and makes
+	 * that the parent window. */
+#ifndef _WIN32
+	static GdkAtom _WindowTime = GDK_NONE;
+	static GdkAtom _Cardinal = GDK_NONE;
+	GList *windows = NULL;
+	GtkWidget *parent = NULL;
+	time_t window_time = 0;
+
+	windows = gtk_window_list_toplevels();
+
+	if (_WindowTime == GDK_NONE) {
+		_WindowTime = gdk_x11_xatom_to_atom(gdk_x11_get_xatom_by_name("_NET_WM_USER_TIME"));
+	}
+	if (_Cardinal == GDK_NONE) {
+		_Cardinal = gdk_atom_intern("CARDINAL", FALSE);
+	}
+
+	while (windows) {
+		GtkWidget *window = windows->data;
+		guchar *data = NULL;
+		int al = 0;
+		time_t value;
+
+		windows = g_list_delete_link(windows, windows);
+
+		if (window == widget ||
+				!GTK_WIDGET_VISIBLE(window))
+			continue;
+
+		if (!gdk_property_get(window->window, _WindowTime, _Cardinal, 0, sizeof(time_t), FALSE,
+				NULL, NULL, &al, &data))
+			continue;
+		value = *(time_t *)data;
+		if (window_time < value) {
+			window_time = value;
+			parent = window;
+		}
+		g_free(data);
+	}
+	if (windows)
+		g_list_free(windows);
+	if (parent) {
+		if (!gtk_get_current_event() && gtk_window_has_toplevel_focus(GTK_WINDOW(parent))) {
+			/* The window is in focus, and the new window was not triggered by a keypress/click
+			 * event. So do not set it transient, to avoid focus stealing and all that.
+			 */
+			return FALSE;
+		}
+		gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(parent));
+		return TRUE;
+	}
+	return FALSE;
+#endif
+#else
+	/* This finds the currently active window and makes that the parent window. */
+	GList *windows = NULL;
+	GtkWidget *parent = NULL;
+	GdkEvent *event = gtk_get_current_event();
+	GdkWindow *menu = NULL;
+
+	if (event == NULL)
+		/* The window was not triggered by a user action. */
+		return FALSE;
+
+	/* We need to special case events from a popup menu. */
+	if (event->type == GDK_BUTTON_RELEASE) {
+		/* XXX: Neither of the following works:
+			menu = event->button.window;
+			menu = gdk_window_get_parent(event->button.window);
+			menu = gdk_window_get_toplevel(event->button.window);
+		*/
+	} else if (event->type == GDK_KEY_PRESS)
+		menu = event->key.window;
+
+	windows = gtk_window_list_toplevels();
+	while (windows) {
+		GtkWidget *window = windows->data;
+		windows = g_list_delete_link(windows, windows);
+
+		if (window == widget ||
+				!GTK_WIDGET_VISIBLE(window)) {
+			continue;
+		}
+
+		if (gtk_window_has_toplevel_focus(GTK_WINDOW(window)) ||
+				(menu && menu == window->window)) {
+			parent = window;
+			break;
+		}
+	}
+	if (windows)
+		g_list_free(windows);
+	if (parent) {
+		gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(parent));
+		return TRUE;
+	}
+	return FALSE;
+#endif
+}
+
============================================================
--- pidgin/gtkutils.h	7c98029c3be852990b736ce6ee3b988c534ad943
+++ pidgin/gtkutils.h	0e942b173e025518f0003b5afc7c28a1d50348f6
@@ -780,5 +780,15 @@ void pidgin_text_combo_box_entry_set_tex
  */
 void pidgin_text_combo_box_entry_set_text(GtkWidget *widget, const char *text);
 
+/**
+ * Automatically make a window transient to a suitable parent window.
+ *
+ * @param window    The window to make transient.
+ *
+ * @return  Whether the window was made transient or not.
+ * @since 2.4.0
+ */
+gboolean pidgin_auto_parent_window(GtkWidget *window);
+
 #endif /* _PIDGINUTILS_H_ */
 


More information about the Commits mailing list