GNOME Bugzilla – Bug 468868
Popup of "appears-as-list" ComboBox does not change screen with its toplevel window
Last modified: 2017-08-28 19:05:21 UTC
Please describe the problem: While trying to change a window from one screen to another, if the window contains a GtkComboboxEntry that "appears-as-list". The GtkComboboxEntry's dropdown list always appears on the first screen of the window (whixh is not the screen of the window) Steps to reproduce: 1. Create a Window with a combobox that "appear as list" (see sample code) 2. Open the dropdown list 3. change the screen of the window 4. Open the dropdown list Actual results: On step 4, the dropdown appears on the first screen Expected results: The dropdown window should appear on the combobox's window. Does this happen every time? yes Other information: here is a sample code that can allow you to reproduce the bug : //// #include <gtk/gtk.h> static GdkScreen* _swap_screen(GdkScreen* anInputScreen) { GdkDisplay * display = gdk_display_get_default (); int num_screen = gdk_display_get_n_screens (display); int input_screen_num = gdk_screen_get_number(anInputScreen); return gdk_display_get_screen(display, ++input_screen_num % num_screen); } static void _change_screen_callback(GtkWidget* aButton, gpointer aUserData) { GtkWidget *aWindow = GTK_WIDGET(aUserData); GdkScreen * aScreen = gtk_window_get_screen(GTK_WINDOW(aWindow)); aScreen = _swap_screen(aScreen); gtk_window_set_screen(GTK_WINDOW(aWindow), aScreen); } static gboolean quit_callback(GtkWidget *widget, GdkEvent *event, gpointer user_data) { gtk_main_quit(); return FALSE; } void create_widget(GtkWidget* aMainWindow) { // container GtkWidget* aVbox = gtk_vbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(aMainWindow), aVbox); // combo // set appears as list property GtkWidget* aWidget = gtk_combo_box_entry_new(); gtk_widget_class_install_style_property ((GtkWidgetClass *)(GTK_COMBO_BOX_ENTRY_GET_CLASS(aWidget)), g_param_spec_boolean("appears-as-list", NULL, NULL, TRUE, G_PARAM_READABLE)); gtk_object_sink(GTK_OBJECT(aWidget)); /// done GtkWidget* aCombobox = gtk_combo_box_entry_new_text(); gtk_combo_box_prepend_text(GTK_COMBO_BOX(aCombobox), "Item 1"); gtk_combo_box_prepend_text(GTK_COMBO_BOX(aCombobox), "Item 2"); gtk_combo_box_prepend_text(GTK_COMBO_BOX(aCombobox), "Item 3"); gtk_box_pack_start(GTK_BOX(aVbox), aCombobox, TRUE, TRUE, 0); // separator GtkWidget* aSeparator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(aVbox), aSeparator, FALSE, FALSE, 0); // button GtkWidget* aChangeScreenButton = gtk_button_new_with_label("change screen"); g_signal_connect ( G_OBJECT(aChangeScreenButton), "clicked", G_CALLBACK(_change_screen_callback), aMainWindow); gtk_box_pack_start(GTK_BOX(aVbox), aChangeScreenButton, TRUE, TRUE, 0); } int main(int argc, char** argv) { gtk_disable_setlocale(); gtk_init(&argc,&argv); GtkWidget *aMainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(aMainWindow), "delete-event", G_CALLBACK(quit_callback), NULL); create_widget(aMainWindow); gtk_widget_show_all(aMainWindow); gtk_main(); return 0; } ///End Code I think this problem can be solved by adding the command (not tested...) gtk_window_set_screen (GTK_WINDOW (combo_box->priv->popup_window), gtk_widget_get_screen (GTK_WIDGET (combo_box))); in the function gtk_combo_box_popup (line 1618 of gtkcombobox.c in Gtk 2.6.10)
Created attachment 94111 [details] Fixed combobox file C source file
Does anyone can give me info on this bug? (or at least change its status, you have the patched file)
I failed to reproduce this problem with gtk-demo. Can you ?
(In reply to comment #3) > I failed to reproduce this problem with gtk-demo. > Can you ? I can reproduce this bug with example "Change Display" of gtk-demo (on a computer with the dual screen : the two screens are on the same display). I added the following lines in function do_changedisplay (just before gtk_widget_show_all (info->window)) <code> GtkWidget * do_changedisplay (GtkWidget *do_widget) { /* existing code*/ ... /* custom code for test */ GtkWidget *combo_box = gtk_combo_box_entry_new_text (); gtk_widget_class_install_style_property ((GtkWidgetClass *)(GTK_COMBO_BOX_ENTRY_GET_CLASS (combo_box)), g_param_spec_boolean ("appears-as-list", NULL, NULL, TRUE, G_PARAM_READABLE)); gtk_combo_box_prepend_text (GTK_COMBO_BOX (combo_box), "Item 1"); gtk_combo_box_prepend_text (GTK_COMBO_BOX (combo_box), "Item 2"); gtk_combo_box_prepend_text (GTK_COMBO_BOX (combo_box), "Item 3"); gtk_box_pack_start (GTK_BOX (vbox), combo_box, TRUE, TRUE, 0); /* end of custom code */ /* existing code */ gtk_widget_show_all (info->window); ... } </code> The bug is the same (popup window appears always on the same screen). The given patch seems to fix it.
(In reply to nicolas_gtk from comment #2) > Does anyone can give me info on this bug? (or at least change its status, > you have the patched file) We'd need a real patch, not just a modified copy of the entire file from some arbitrary point in time. fwiw I wanted to test this but don't readily have a machine that GTK+ interprets has having multiple screens, at the moment.
*** Bug 786771 has been marked as a duplicate of this bug. ***
Created attachment 358535 [details] [review] ComboBox: List-mode popup must open on CB’s screen The screen for the list-mode popup_window was only being set in set_popup_widget(), i.e. when changing modes, so if the ComboBox was moved to a different screen later, the popup would appear on the original one, which is wrong. Worse, this (somehow) crashed when opening some combos in the Inspector. Fix this by moving the call to set_screen() to popup_for_device(), so the popup_window is put on the correct screen each time around. https://bugzilla.gnome.org/show_bug.cgi?id=468868 https://bugzilla.gnome.org/show_bug.cgi?id=786771
Review of attachment 358535 [details] [review]: ::: gtk/gtkcombobox.c @@ +2359,2 @@ /* popup */ + gtk_window_set_screen (GTK_WINDOW (priv->popup_window), A nicer way is to do this in a handler for ComboBox::parent-set. We should also move popup()'s call to window_group_add_window() there, remove the redundant one from list_setup(), and move the call to set_transient_for() from list_setup() to parent_set() so that it actually gets run. list_setup() can then just call the parent_set() handler before connecting ::parent-set to it.
Review of attachment 358535 [details] [review]: (In reply to Daniel Boles from comment #8) > A nicer way is to do this in a handler for ComboBox::parent-set. Duh, no, that doesn't work for the screen. It's fine for the rest that I said, though.
Review of attachment 358535 [details] [review]: commit msg should reflect that the Inspector was just a critical and failure to open the CB, rather than a crash outright
pushed to gtk-2-24 and gtk-3-22 - thanks for the report!