Fix race in GtkPlug window creation

According to the XEmbed specification, a window should be created
"elsewhere" and then reparented into the target parent window. Instead,
GTK+ creates the window directly in desired target parent window. This
allows some races to occur.

Another program that does not follow XEmbed is tabbed. XEmbed requires
an _XEMBED_INFO property on the to-be-embedded window, but tabbed does
not check for this property. Thus, as soon as GTK+ creates its window,
tabbed starts managing this window and now GTK+ setting up the window
races with tabbed starting to manage the window.

If tabbed is fast enough to map the window, GTK+ never sees a MapNotify
event, because it did not yet select StructureNotifyMask on its window.
This results in a black window inside of tabbed.

Note that this cannot really be fixed in tabbed, since XEmbed says that
the _XEMBED_INFO property must be already present when the window
appears. Thus, patching tabbed to wait for _XEMBED_INFO to appear is not
something that the spec requires/allows.

Instead, this commit changes GTK+ so that it directly sets the right
event mask when the window is created. This means that there is no more
race between tabbed mapping the window and GTK+ selecting
StructureNotifyMask.

Note that the proper fix would be to do as XEmbed requires: Create the
window elsewhere and then reparent it into the target window. However,
that would require a more invasive patch, so this commit only takes the
"easy approach" of fixing this one race. Hopefully, all the other races
that can occur during window setup are harmless, because the
embedder/socket will hopefully watch for PropertyNotify events as
needed.

Fixes: https://gitlab.gnome.org/GNOME/gtk/issues/757
See-also: https://github.com/awesomeWM/awesome/issues/2385
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2018-10-14 13:59:12 +02:00
parent dbbc7b3859
commit 9ca38c4647

View File

@ -1053,6 +1053,12 @@ _gdk_x11_display_create_window_impl (GdkDisplay *display,
impl->override_redirect = xattributes.override_redirect;
/* This event mask will be set near the end of the function, but to avoid some
* races, the window has to be created with this mask already.
*/
xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
xattributes_mask |= CWEventMask;
/* Sanity checks */
switch (window->window_type)
{