set_attached_to
seems to be the correct way to position a popup window relative to a widget in wayland:
Examples of places where specifying this relation is useful are for instance [...] a completion popup window created by Gtk.Entry [...]
Unfortunately this only yields an error
Gdk-Message: 12:13:16.143: Window 0x1822340 is a temporary window without parent, application will not be able to position it on screen.
Trying to uncomment the popup.set_parent(entry)
line only adds a warning:
(try_entry_popup.py:4539): Gtk-WARNING **: 12:17:34.185: Can't set a parent on a toplevel widget
followed by the same error.
Here is a minimal example:
#!/usr/bin/env python
# stripped down from https://gitlab.gnome.org/GNOME/gtk/issues/1541#note_396391
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
entry = Gtk.Entry()
popup = Gtk.Window(type=Gtk.WindowType.POPUP)
#popup.set_parent(entry)
popup.set_attached_to(entry)
popup.show_all()
layout = Gtk.VBox()
layout.pack_start(entry, False, True, 0)
window = Gtk.Window()
window.connect("destroy", Gtk.main_quit)
window.add(layout)
window.show_all()
Gtk.main()
From the entry completion source it looks like it definitely should work. Is it using private features ? Or what am I missing ?
Well, not really: gtk_window_set_attached_to has nothing to do with positioning, it's important for accessibility (a11y) and to apply theming in a correct way. If you want to position your popup window you can follow what it's done in https://gitlab.gnome.org/GNOME/gtk/blob/075dcc142aa525778268165095de019b736f3efa/gtk/gtkentrycompletion.c#L1597
Here's a very simple implementation:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
def on_button_clicked(widget):
popup = Gtk.Window(type=Gtk.WindowType.POPUP)
# optionally you may set an appropriate type hint, but it's not required.
popup.set_attached_to(entry)
popup.set_transient_for(window)
gdk_window = entry.get_window()
gdk_window_origin = gdk_window.get_origin()
x = gdk_window_origin[1]
y = gdk_window_origin[2]
allocation = entry.get_allocation()
x += allocation.x
y += allocation.y + allocation.height
popup.move(x, y)
popup.show_all()
button = Gtk.Button()
button.connect('clicked', on_button_clicked)
entry = Gtk.Entry()
layout = Gtk.VBox()
layout.pack_start(button, False, True, 0)
layout.pack_start(entry, False, True, 0)
window = Gtk.Window()
window.connect("destroy", Gtk.main_quit)
window.add(layout)
window.show_all()
Gtk.main()