Awesome: Firefox 60 / Thunderbird 52 weird positioning

Created on 1 Jun 2018  Â·  31Comments  Â·  Source: awesomeWM/awesome

Output of awesome --version:

awesome v4.2 (Human after all)
• Compiled against Lua 5.3.4 (running with Lua 5.3)
• D-Bus support: ✔
• execinfo support: ✔
• xcb-randr version: 1.5
• LGI version: 0.9.2

How to reproduce the issue:

Start firefox 60 or thunderbird 52 in tile layout

Actual result:

Firefox/Thunderbird positions itself above the menubar

Expected result:

Window should be below the menu bar

Setting/Unsetting floating does not help either. Also it is present on all tags at once.

bug confirmed need info

Most helpful comment

Horray!

Thanks to everyone who use the git version of everything. Without you this could have ended up in an official GTK release and in Ubuntu 18.10. It would have been catastrophic for us.

All 31 comments

With "menubar", do you mean the bar at the top of the screen in the default config?
Could you show the output of /usr/bin/xprop for one of these windows? (run xprop in a terminal, click on firefox' window)

Also it is present on all tags at once.

Uhm, what?

Yes, i mean the bar at the top.

And yes, when i open firefox 60 an switch to a different tag then the firefox window is still in the forground.

xprop:

GDK_TIMESTAMP_PROP(GDK_TIMESTAMP_PROP) = 0x61
_NET_WM_DESKTOP(CARDINAL) = 3
_NET_FRAME_EXTENTS(CARDINAL) = 2, 2, 2, 2
WM_STATE(WM_STATE):
        window state: Normal
        icon window: 0x0
WM_HINTS(WM_HINTS):
        Client accepts input or input focus: True
        Initial state is Normal State.
        bitmap id # to use for icon: 0x2400014
        bitmap id # of mask for icon: 0x240001a
        window id # of group leader: 0x2400001
_GTK_THEME_VARIANT(UTF8_STRING) = 
_NET_STARTUP_ID(UTF8_STRING) = "rofi/|usr|lib|firefox|firefox/13129-0-cars10-thinkpad_TIME4397938"
WM_WINDOW_ROLE(STRING) = "browser"
_NET_WM_BYPASS_COMPOSITOR(CARDINAL) = 2
XdndAware(ATOM) = BITMAP
_NET_WM_ICON(CARDINAL) =    Icon (32 x 32):

// icon omitted

    Icon (192 x 192):
    (not shown)
_NET_WM_OPAQUE_REGION(CARDINAL) = 
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
_NET_WM_SYNC_REQUEST_COUNTER(CARDINAL) = 37748754, 37748755
_NET_WM_USER_TIME(CARDINAL) = 4407315
_NET_WM_USER_TIME_WINDOW(WINDOW): window id # 0x2400011
WM_CLIENT_LEADER(WINDOW): window id # 0x2400001
_NET_WM_PID(CARDINAL) = 13137
WM_LOCALE_NAME(STRING) = "en_US.UTF-8"
WM_CLIENT_MACHINE(STRING) = "cars10-thinkpad"
WM_NORMAL_HINTS(WM_SIZE_HINTS):
        program specified minimum size: 300 by 99
        program specified base size: 300 by 99
        window gravity: NorthWest
WM_PROTOCOLS(ATOM): protocols  WM_DELETE_WINDOW, WM_TAKE_FOCUS, _NET_WM_PING, _NET_WM_SYNC_REQUEST
WM_CLASS(STRING) = "Navigator", "Firefox"
WM_ICON_NAME(STRING) = "Manjaro Linux - Mozilla Firefox"
_NET_WM_ICON_NAME(UTF8_STRING) = "Manjaro Linux - Mozilla Firefox"
WM_NAME(STRING) = "Manjaro Linux - Mozilla Firefox"
_NET_WM_NAME(UTF8_STRING) = "Manjaro Linux - Mozilla Firefox"

Hm... nothing out of the ordinary in there. According to that output, firefox should only be on the fourth tag (_NET_WM_DESKTOP = 3), but perhaps it is really tagged with multiple tags? Only the first one is shown here...
Could you run sleep 5 ; awesome-client 'return require("gears.debug").dump_return{client.focus:tags(), client.focus.sticky}' in a terminal, switch to firefox and see what this says? Perhaps also provide your rc.lua? Right now I am quite confused about this...
(In the default config, awful.placement.no_offscreen is responsible for making things not overlap the wibar)

I just tried with the default rc.lua and have a similar behaviour. Output of your command: (paste to terminal and start firefox)

   string "table: 0x5585aea3f7e0
  1 : table: 0x5585aea3f820
    1 : tag: 0x5585adb89498 (tag)
  2 : false (boolean)"

Edit: i just recorded whats happening. Notice how i switch tags after i open firefox.
https://youtu.be/L5LUiclPm60

Sorry, this is not related to the firefox version. I just downgraded to 59 and still have the issue so it will be something else.

Hm... What?

All I can say: Since Firefox also does not have an entry in the tasklist, even awesome thinks it is not visible. But clearly you can still interact with the window, so "it's there".

So, what is your rc.lua looking like? Does this also happen with the default config?

Yes, it happens with the default config - that's the active config In the video.

I found the cause, the issue is because of GTK3 update. i3 currently has similar problems, see this thread for more info
https://forum.manjaro.org/t/strange-always-on-top-window-placement-for-some-clients-in-awesomewm/48506/10

I am author of gtk3-mushrooms, gtk3 patched for classic desktops on Arch Linux. In current stable gtk3 newly created windows are filled by black color. In next gtk3 release newly created windows will be initially transparent — this causes bugs in Awesome and i3wm (i3wm bug here: https://github.com/i3/i3/issues/3297 ).
In gtk3-mushrooms I added patch from next gtk3 release, so bug was discovered earlier. Currently I fixed it and for wm-s without _GTK_FRAME_EXTENTS support newly created windows are filled with theme background.
From gtk3 side, change is introduced by this commit: https://github.com/GNOME/gtk/commit/2ce63a86ba689aa41eb47409c889c469497478b0

I am able to reproduce bug with any gtk3 app (when gtk3 is from gtk-3-22 branch). When gtk3 app is started it's not managed by awesome and goes to left-top corner. I will prepare video.

So, Gtk3 does not want the X11 server to fill the window with its background color. And instead of setting the background color to None, they picked ParentRelative because of some weird code that tries to handle this, but does not actually work when the window is not mapped yet and instead makes this a problem of the WM. And now, instead of fixing this in Gtk by just always using None (why is this ParentRelative even in there?), WMs should have to deal with it. Great.

Plus, I should really make it a habit to ask "anything on awesome's stderr?"...

@cars10 Running awesome with the --no-argb argument should get this working again for you.

@psychon Can you create issue on GTK3's bug tracker on gitlab.gnome.org?

@TomaszGasior What exactly should I tell them? "I do not know why you are using ParentRelative, but None would be so much more convenient for me"

Right now I wonder why only i3 and awesome seem to be affected, but I have a hard time coming up with WMs that try to make transparency in their decorations work...

Perhaps I should just make all awesome users suffer by setting a black background pixel on a window that is used to contain Gtk windows, just so that they see that ParentRelative is definitely the wrong thing to use. :-) (ParentRelative: I want the same background as my parent, if that is black, okay; What they actually want is None, which means "Dear X11 server, do not draw any background")

Edit: Sigh. Gdk needs ParentRelative for working systray icons.
https://bugzilla.gnome.org/show_bug.cgi?id=747524
https://gitlab.gnome.org/GNOME/gtk/commit/374bedc0e2c208ee3fe0bfc698841e5c093e2905

If you think GDK behaves improperly maybe you can ask GTK authors about it on gtk-devel mailing list. It's here: https://mail.gnome.org/mailman/listinfo/gtk-devel-list

Can someone who can reproduce this test the following patch?

  • [x] Does it fix the issue of the un-reparented GTK window?
  • [x] Does transparency in clients still work? (e.g. testable via urxvt -depth 32 -fg grey90 -bg rgba:0000/0000/4444/cccc which should have a semi-transparent background if a compositing manager is running (e.g. xcompmgr))
  • [x] Does transparency in awesome still work? (Uhm.. I am not quite sure how to test this, but I think that replacing awful.titlebar(c)with awful.titlebar(c, { bg_normal = "#fff8" } in the default config should do the trick and produce a window with a semi-transparent, white titlebar; this also requires a compositing manager)

What this does: Every client window with a different depth than the frame window that awesome would create for the titlebars (by default: basically every window except those wanting to use transparency; when using --no-argb this should be the other way around) is reparented into another window just so that we can prevent ParentRelative background from messing with us. Thus, instead of having three windows per client, we would now have four windows per client:

  • The client window itself
  • An invisible window of the same depth of the client just for ParentRelative
    (only if the client window does not have the same depth as the next window)
    (note that this is always created, because X11 does not seem to allow checking for ParentRelative back pixels)
  • The frame window with a depth of our liking so that transparency works; this is used for event handling and drawing the titlebars
  • A special nofocus window that is only created when needed, is related to event-handling and which I won't say more about here.
diff --git a/objects/client.c b/objects/client.c
index c7a0c8e82..0e63da6cb 100644
--- a/objects/client.c
+++ b/objects/client.c
@@ -1270,9 +1270,19 @@ client_geometry_refresh(void)
         xcb_configure_window(globalconf.connection, c->frame_window,
                 XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
                 (uint32_t[]) { geometry.x, geometry.y, geometry.width, geometry.height });
-        xcb_configure_window(globalconf.connection, c->window,
-                XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
-                (uint32_t[]) { real_geometry.x, real_geometry.y, real_geometry.width, real_geometry.height });
+        if (c->container_window != XCB_NONE)
+        {
+            xcb_configure_window(globalconf.connection, c->container_window,
+                    XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
+                    (uint32_t[]) { real_geometry.x, real_geometry.y, real_geometry.width, real_geometry.height });
+            xcb_configure_window(globalconf.connection, c->window,
+                    XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
+                    (uint32_t[]) { 0, 0, real_geometry.width, real_geometry.height });
+        } else {
+            xcb_configure_window(globalconf.connection, c->window,
+                    XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
+                    (uint32_t[]) { real_geometry.x, real_geometry.y, real_geometry.width, real_geometry.height });
+        }

         c->x11_frame_geometry = geometry;
         c->x11_client_geometry = real_geometry;
@@ -1371,6 +1381,26 @@ client_update_properties(lua_State *L, int cidx, client_t *c)
     window_set_opacity(L, cidx, xwindow_get_opacity_from_cookie(opacity));
 }

+static xcb_visualid_t
+pick_visual_for_depth (uint8_t depth)
+{
+    xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(globalconf.screen);
+
+    if (depth == globalconf.default_depth)
+        return globalconf.visual->visual_id;
+    if (depth == globalconf.screen->root_depth)
+        return globalconf.screen->root_visual;
+
+    /* Just pick the first visual of that depth */
+    for(; depth_iter.rem; xcb_depth_next (&depth_iter))
+        if (depth_iter.data->depth == depth)
+            for(xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
+                visual_iter.rem; xcb_visualtype_next (&visual_iter))
+                return visual_iter.data->visual_id;
+
+    return XCB_COPY_FROM_PARENT;
+}
+
 /** Manage a new client.
  * \param w The window.
  * \param wgeom Window geometry.
@@ -1424,6 +1454,40 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_at
                           globalconf.default_cmap
                       });

+    /* is a container window needed? */
+    c->container_window = XCB_NONE;
+    if (wgeom->depth != globalconf.default_depth) {
+        /* The window has a different depth than the window that we would put it
+         * in. If it also has a ParentRelative background, ReparentWindow would
+         * fail so check for that. We cannot check for that so assume the worst.
+         */
+        xcb_colormap_t colormap;
+        xcb_visualid_t visual = pick_visual_for_depth(wgeom->depth);
+
+        if (wgeom->depth == globalconf.screen->root_depth)
+            colormap = globalconf.screen->default_colormap;
+        else
+        {
+            colormap = xcb_generate_id(globalconf.connection);
+            xcb_create_colormap(globalconf.connection, XCB_COLORMAP_ALLOC_NONE,
+                    colormap, globalconf.screen->root, visual);
+        }
+
+        c->container_window = xcb_generate_id(globalconf.connection);
+        xcb_create_window(globalconf.connection, wgeom->depth, c->container_window, c->frame_window,
+                0, 0, wgeom->width, wgeom->height, 0, XCB_COPY_FROM_PARENT,
+                visual, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP,
+                (const uint32_t[]) {
+                    globalconf.screen->black_pixel,
+                    globalconf.screen->black_pixel,
+                    colormap
+                });
+        xcb_map_window(globalconf.connection, c->container_window);
+
+        if (colormap != globalconf.screen->default_colormap)
+            xcb_free_colormap(globalconf.connection, colormap);
+    }
+
     /* The client may already be mapped, thus we must be sure that we don't send
      * ourselves an UnmapNotify due to the xcb_reparent_window().
      *
@@ -1436,7 +1500,10 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_at
                                  globalconf.screen->root,
                                  XCB_CW_EVENT_MASK,
                                  no_event);
-    xcb_reparent_window(globalconf.connection, w, c->frame_window, 0, 0);
+    if (c->container_window != XCB_NONE)
+        xcb_reparent_window(globalconf.connection, w, c->container_window, 0, 0);
+    else
+        xcb_reparent_window(globalconf.connection, w, c->frame_window, 0, 0);
     xcb_map_window(globalconf.connection, w);
     xcb_change_window_attributes(globalconf.connection,
                                  globalconf.screen->root,
@@ -2215,6 +2282,7 @@ client_unmanage(client_t *c, bool window_valid)

     if (c->nofocus_window != XCB_NONE)
         window_array_append(&globalconf.destroy_later_windows, c->nofocus_window);
+    /* container_window is automatically destroyed when its parent is destroyed */
     window_array_append(&globalconf.destroy_later_windows, c->frame_window);

     if(window_valid)
diff --git a/objects/client.h b/objects/client.h
index ee7384988..f38c5a253 100644
--- a/objects/client.h
+++ b/objects/client.h
@@ -51,6 +51,8 @@ typedef enum {
 struct client_t
 {
     WINDOW_OBJECT_HEADER
+    /** Window we use as a container for windows with non-default depth */
+    xcb_window_t container_window;
     /** Window we use for input focus and no-input clients */
     xcb_window_t nofocus_window;
     /** Client logical screen */

2018-06-02_20 00 12

All 3 points seem to work for me (with GNOME/gtk@2ce63a8 and patch on master). Tell me if I missed something / if you need more tests.

@alfunx Thanks a lot.

Sorry to ask you again, but could you test #2280? This sets BackPixmap to None (which is what Gtk actually wants and really should just specify itself) instead of the black BackPixel that my previous patch used.
In detail, I changed (around line 1480 in client.c)

                visual, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP,
                (const uint32_t[]) {
                    globalconf.screen->black_pixel,
                    globalconf.screen->black_pixel,
                    colormap
                });

into

                visual, XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP,
                (const uint32_t[]) {
                    XCB_BACK_PIXMAP_NONE,
                    globalconf.screen->black_pixel,
                    colormap
                });

Can any of you upgrade your GTK to the latest git (3.24 beta) and report if the issue is fixed?

@Elv13 Can't reproduce this issue with GNOME/gtk@5afc01d (branch gtk-3-24) on awesomeWM/awesome@d7e09a0 (current master), seems like it has been fixed.

Horray!

Thanks to everyone who use the git version of everything. Without you this could have ended up in an official GTK release and in Ubuntu 18.10. It would have been catastrophic for us.

Apparently Manjaro Linux patches their GTK+ so that stuff breaks there (according to https://gitlab.gnome.org/GNOME/gtk/issues/1134#note_265753)

Yes they are explicitly patching GTK with GNOME/gtk@2ce63a86: https://github.com/manjaro/packages-extra/blob/master/gtk3-classic/PKGBUILD#L64 (which is not the case in the Arch package).

@alfunx
Manjaro provides two versions of GTK3: vanilla GTK3 package without any patches and alternative version called gtk3-classic which is equal to my package gtk3-mushrooms: https://github.com/TomaszGasior/gtk3-mushrooms

By default Manjaro uses vanilla GTK3 package. Some community editions are using gtk3-classic instead. In all Manjaro editions users are able to replace GTK3 with gtk3-classic. Also Arch Linux's users are able to install my original package from AUR.

Life is awesome again ! :tada: First we are world champions :fr: !
Then simply installing the gtk3 on Manjaro (over gtk3-classic) fixes the problem. No need to restart anything, all apps affected (emacs, evince, chrome) are now handled correctly. Thanks everyone for getting to the bottom of this !

Please note there is no problem with gtk3-classic/mushrooms. gtk3-classic/mushrooms uses patch, which will be part of next gtk3 release,

@TomaszGasior I don't think so. Could you show me the patch you are referring to? In case you mean the patch with gdk_window_x11_set_background: Well, upstream GTK+ also has https://gitlab.gnome.org/GNOME/gtk/commit/01d1bc3c75fd0eff5665f5b9c690c5e1e6c65f13, which makes the problem go away. gtk3-classic/mushrooms does not have this patch, as far as I know.
(Note that alfunx already confirmed more than two weeks ago that GTK+ build from the gtk-3-24 branch does not cause this problem, so I'm not exactly bringing breaking news here.)

Okay. So it gtk3-mushrooms causes bug in Awesome, I will look at this and I will fix it. Probably tomorrow.

@psychon @ameuret @alfunx @Elv13

I'm sorry for my mistake and delayed reaction. Currently (https://github.com/TomaszGasior/gtk3-mushrooms/commit/fba94acbc7612665435d5e33fd78aca1356e3c5c) gtk3-mushrooms contains both patches from GTK's repository: first about gdk_window_x11_set_background and second about avoiding ParentRelative. The second patch was missing previously in my patches. I'm sorry. Now it's fixed in Arch Linux's AUR. Manjaro maintainers of gtk3-classic package (it's gtk3-mushrooms repackaged to a different name) will be notified.

On the other hand, I am very sorry when you are calling my work on gtk3-mushrooms using words like "so that stuff breaks there". I am not creating GTK patches to break Awesome or any other WM. Instead, I am spending my time to make GTK more consistent with desktops other than GNOME — this is my goal. Also, keep in mind that this bug was discovered earlier partially thanks to gtk3-mushrooms existence. Problems with i3wm and Awesome casued by https://github.com/GNOME/gtk/commit/2ce63a86ba689aa41eb47409c889c469497478b0 were reported by Arch Linux and Manjaro users which were using gtk3-mushrooms instead bare GTK package.

@TomaszGasior Sorry if I offended you. That was not my intention. I only wanted to say that Manjaro applies a patch to their GTK+ that makes the problem happen while upstream GTK+ does not make the problem happen (and I have since learned that this statement is actually wrong since there are two GTK+ versions in Manjaro...). I'm sorry for sounding like I wanted to assign blame.

Was this page helpful?
0 / 5 - 0 ratings