# HG changeset patch # User Sadrul Habib Chowdhury # Date 1196214874 0 # Node ID c88a3f2dbb529b6f907c801bba23898b6a90485d # Parent b05a8f1db1c3dcfca1b78ce0fb9013ed8a9a5d02 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. diff -r b05a8f1db1c3 -r c88a3f2dbb52 ChangeLog.API --- a/ChangeLog.API Wed Nov 28 00:17:27 2007 +0000 +++ b/ChangeLog.API Wed Nov 28 01:54:34 2007 +0000 @@ -15,6 +15,8 @@ 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: diff -r b05a8f1db1c3 -r c88a3f2dbb52 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Wed Nov 28 00:17:27 2007 +0000 +++ b/pidgin/gtkconv.c Wed Nov 28 01:54:34 2007 +0000 @@ -8163,7 +8163,7 @@ } 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)); diff -r b05a8f1db1c3 -r c88a3f2dbb52 pidgin/gtknotify.c --- a/pidgin/gtknotify.c Wed Nov 28 00:17:27 2007 +0000 +++ b/pidgin/gtknotify.c Wed Nov 28 01:54:34 2007 +0000 @@ -284,6 +284,8 @@ 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 @@ 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_new_rows(gc, results, data); /* Show the window */ + pidgin_auto_parent_window(window); + gtk_widget_show(window); return data; } diff -r b05a8f1db1c3 -r c88a3f2dbb52 pidgin/gtkrequest.c --- a/pidgin/gtkrequest.c Wed Nov 28 00:17:27 2007 +0000 +++ b/pidgin/gtkrequest.c Wed Nov 28 01:54:34 2007 +0000 @@ -439,6 +439,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ #endif data->dialog = dirsel; + pidgin_auto_parent_window(dirsel); + gtk_widget_show(dirsel); return (void *)data; diff -r b05a8f1db1c3 -r c88a3f2dbb52 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Wed Nov 28 00:17:27 2007 +0000 +++ b/pidgin/gtkutils.c Wed Nov 28 01:54:34 2007 +0000 @@ -3312,3 +3312,107 @@ 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 +} + diff -r b05a8f1db1c3 -r c88a3f2dbb52 pidgin/gtkutils.h --- a/pidgin/gtkutils.h Wed Nov 28 00:17:27 2007 +0000 +++ b/pidgin/gtkutils.h Wed Nov 28 01:54:34 2007 +0000 @@ -780,5 +780,15 @@ */ 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_ */