After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 468868 - Popup of "appears-as-list" ComboBox does not change screen with its toplevel window
Popup of "appears-as-list" ComboBox does not change screen with its toplevel ...
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Widget: GtkComboBox
2.6.x
Other All
: Normal major
: ---
Assigned To: gtk-bugs
gtk-bugs
: 786771 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2007-08-21 14:27 UTC by nicolas_gtk
Modified: 2017-08-28 19:05 UTC
See Also:
GNOME target: ---
GNOME version: 2.5/2.6


Attachments
Fixed combobox file (151.47 KB, text/plain)
2007-08-22 13:08 UTC, nicolas_gtk
  Details
ComboBox: List-mode popup must open on CB’s screen (1.81 KB, patch)
2017-08-27 21:13 UTC, Daniel Boles
committed Details | Review

Description nicolas_gtk 2007-08-21 14:27:53 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)
Comment 1 nicolas_gtk 2007-08-22 13:08:03 UTC
Created attachment 94111 [details]
Fixed combobox file

C source file
Comment 2 nicolas_gtk 2007-10-03 15:54:10 UTC
Does anyone can give me info on this bug? (or at least change its status, you have the patched file)
Comment 3 Matthias Clasen 2007-10-17 02:54:40 UTC
I failed to reproduce this problem with gtk-demo.
Can you ?
Comment 4 nicolas_gtk 2007-10-17 08:43:45 UTC
(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.


Comment 5 Daniel Boles 2017-08-24 23:37:48 UTC
(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.
Comment 6 Daniel Boles 2017-08-27 21:12:40 UTC
*** Bug 786771 has been marked as a duplicate of this bug. ***
Comment 7 Daniel Boles 2017-08-27 21:13:28 UTC
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
Comment 8 Daniel Boles 2017-08-27 22:44:42 UTC
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.
Comment 9 Daniel Boles 2017-08-27 22:47:39 UTC
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.
Comment 10 Daniel Boles 2017-08-28 08:38:54 UTC
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
Comment 11 Daniel Boles 2017-08-28 19:05:21 UTC
pushed to gtk-2-24 and gtk-3-22 - thanks for the report!