Godot: Godot 4.0.dev editor behaves weird while using i3wm (and maybe other tilling wm's)

Created on 16 Apr 2020  路  20Comments  路  Source: godotengine/godot

Godot version: 4.0.dev

OS/device including version: Manjaro + i3

Issue description: The new editor behaves weird while using i3wm (and maybe other tilling wm's). I know version 4 is still in development, i just wanted to report that!
image
The image below is when clicking the "Editor"
image
The image below is when click the 3 vertical dots
image

Steps to reproduce: Use i3

Minimal reproduction project: I don't need to provide a project because its not a project specific

bug confirmed linuxbsd editor porting

Most helpful comment

I did some research using i3 a while ago, here's what i got from that.
The main issue seems related to the way DisplayServerX11::_create_window works. It:

  1. Creates the window (XCreateWindow)
  2. Maps the window (XMapWindow)
  3. Configures the window(attributes, properties ecc.)

The issue is that mapping the window makes it immediately known to the WM which, at least in the case of i3, can clear some of it properties and resizes the window if there isn't the right atom set.

Now, why does it work randomly? Reading through the debug logs, i found this section, which gives me some hints:

09/05/2020 03:01:22 - WM_CLASS changed to Godot_Engine (instance), [PROJECT_NAME] (class)
09/05/2020 03:01:22 - WM_NAME changed to "Godot"
09/05/2020 03:01:22 - Using legacy window title. Note that in order to get Unicode window titles in i3, the application has to set _NET_WM_NAME (UTF-8)
09/05/2020 03:01:22 - window.c:window_update_name:64 - _NET_WM_NAME not specified, not changing
09/05/2020 03:01:22 - window.c:window_update_leader:139 - CLIENT_LEADER not set on window 0x05a00053.
09/05/2020 03:01:22 - window.c:window_update_transient_for:164 - TRANSIENT_FOR not set on window 0x05a00053.
09/05/2020 03:01:22 - window.c:window_update_strut_partial:189 - _NET_WM_STRUT_PARTIAL not set.
09/05/2020 03:01:22 - window.c:window_update_role:214 - WM_WINDOW_ROLE not set.
09/05/2020 03:01:22 - window.c:window_update_hints:377 - WM_HINTS not set.
09/05/2020 03:01:22 - window.c:window_update_normal_hints:291 - Clearing maximum size
09/05/2020 03:01:22 - window.c:window_update_normal_hints:312 - Clearing size increments
09/05/2020 03:01:22 - window.c:window_update_normal_hints:326 - Clearing base size
09/05/2020 03:01:22 - window.c:window_update_normal_hints:335 - Setting geometry x=1616 y=87 w=294 h=218
09/05/2020 03:01:22 - window.c:window_update_normal_hints:359 - Clearing aspect ratios

It seems that right after mapping _most_ of the times i3 managed Godot's popup instantly, not finding any atoms since they weren't set yet.

I tried moving the mapping to a later stage in that function In my messy fork, effectively swapping step 2 and 3, and it fixed all tooltips and simple popups. More complex popups(Like the "Add Node" window) don't work, and that's where i left off.

My hypotesis for this last part of the issue with those popups is that, maybe they inherit from Window and then they may set their properties after getting shown, but i haven't looked further into this.

Edit: typo

All 20 comments

It's because of the refactor of the window backend: now every "subwindow" in Godot is it's own window, and i3wm tiles them like any other.

Run Godot with godot --single-window until a solution is made.

It looks like it's properly setting them as floating but not keeping their sizes and positions.

It looks like it's properly setting them as floating but not keeping their sizes and positions.

Nope, on tabbed mode it adds another tab with the popup as if it were a normal window.

@Ev1lbl0w Is there anything we can do about it? I wonder if we should detect tiling WMs and force single window mode by default in this case.

@Ev1lbl0w Is there anything we can do about it? I wonder if we should detect tiling WMs and force single window mode by default in this case.

I think we can set some window hints and hope the most popular tiling WM's abide to them. And if that's not the case, there's still the single window option that could be easily toggled (I think there was already an issue/request to make it toggable from the editor settings..?)

@Ev1lbl0w An editor setting was already added in #37391.

Looking at both bspwm and i3wm, they set the window to a "floating" state if the windows have the atom _NET_WM_WINDOW_TYPE_DIALOG set. I'll try implementing this and test if it works properly.

If it does, boy, does it save a ton of headaches :stuck_out_tongue:

So, after fiddling with the code for windows, I can't pinpoint the exact problem. In my setup (bspwm), the window seems to randomly work: sometimes it works fine, other times it becomes tiled, and fill the entire screen. I tried debugging and looking at xprop info, but couldn't pinpoint anything in particular.

But either way, I believe it's best for Godot to act as a single window for tilling WM's. To make Godot work well in this new scenario, I have to write some configs for it. And even them, they only apply to the current game/project I'm working on, and have to redo all them for other projects :stuck_out_tongue:

So, I agree with you @Calinou; it's probably best to detect a tilling WM and set Godot to single-window mode. But still retaining the option for floating docks (like Gimp).

the window seems to randomly work: sometimes it works fine, other times it becomes tiled

This exactly happens to me too!

It looks like in this function it's creating the window then setting it's flags. Maybe i3wm is tiling the window before it knows it should have been floating? I'm really not sure, I'm very new to this.

DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {

    _THREAD_SAFE_METHOD_

    WindowID id = _create_window(p_mode, p_flags, p_rect);
    for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
        if (p_flags & (1 << i)) {
            window_set_flag(WindowFlags(i), true, id);
        }
    }


    return id;
}

In DWM, some dialogs/popups are working well, for example: project settings, editor settings and the exit confirmation.

The problem seems to be with menu dialogs, which are not tiled but they take up to 60% of the screen. With DWM in floating mode, they spawn with correct size but in random positions.

godot --single-window does not solve anything for me

I got this from xprop:
(there are some differences in the ATOMs and minimun sizes)

Menu (takes up 60% of the screen)

WM_TRANSIENT_FOR(WINDOW): window id # 0x4200002
_NET_WM_NAME(UTF8_STRING) =
_VARIABLE_REFRESH(CARDINAL) = 1
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_UTILITY
WM_STATE(WM_STATE):
window state: Normal
icon window: 0x0
_MOTIF_WM_HINTS(_MOTIF_WM_HINTS) = 0x2, 0x50d3d100, 0x0, 0x57e, 0xecd559d0
WM_NORMAL_HINTS(WM_SIZE_HINTS):
WM_CLASS(STRING) = "Godot_Engine", "godot-test"
XdndAware(ATOM) = BITMAP
WM_PROTOCOLS(ATOM): protocols WM_DELETE_WINDOW
WM_NAME(STRING) =
_NET_WM_PID(CARDINAL) = 26071

Exit confirmation (works well)

WM_TRANSIENT_FOR(WINDOW): window id # 0x4200002
_NET_WM_NAME(UTF8_STRING) = "Please Confirm..."
_VARIABLE_REFRESH(CARDINAL) = 1
WM_NORMAL_HINTS(WM_SIZE_HINTS):
program specified minimum size: 200 by 76
program specified maximum size: 200 by 76
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
WM_CLASS(STRING) = "Godot_Engine", "godot-test"
WM_STATE(WM_STATE):
window state: Normal
icon window: 0x0
XdndAware(ATOM) = BITMAP
WM_PROTOCOLS(ATOM): protocols WM_DELETE_WINDOW
WM_NAME(STRING) = "Please Confirm..."
_NET_WM_PID(CARDINAL) = 26071

Settings (works well)

WM_TRANSIENT_FOR(WINDOW): window id # 0x4200002
_NET_WM_NAME(UTF8_STRING) = "Project Settings (project.godot)"
_VARIABLE_REFRESH(CARDINAL) = 1
WM_STATE(WM_STATE):
window state: Normal
icon window: 0x0
WM_NORMAL_HINTS(WM_SIZE_HINTS):
program specified minimum size: 900 by 700
program specified maximum size: 900 by 700
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
WM_CLASS(STRING) = "Godot_Engine", "godot-test"
XdndAware(ATOM) = BITMAP
WM_PROTOCOLS(ATOM): protocols WM_DELETE_WINDOW
WM_NAME(STRING) = "Project Settings (project.godot)"
_NET_WM_PID(CARDINAL) = 26071

godot --single-window does not solve anything for me

That's probably because the flag is only passed to the first instance, which is the project manager if you don't specify a path to a project. godot --single-window -e --path /to/some/project should open the editor in single window mode.
There's also a project setting that you can enable to force it.

Did a quick test changing here the _NET_WM_WINDOW_TYPE_UTILITY atom to _NET_WM_WINDOW_TYPE_DIALOG

Now the menu boxes get the correct size but they are floating in wrong positions (Seems to a miscalculation based on my dual monitor setup).

This change broke some tooltips, so maybe we should allow to choose between the two Atoms (utilities and dialogs)

That's probably because the flag is only passed to the first instance, which is the project manager if you don't specify a path to a project. godot --single-window -e --path /to/some/project should open the editor in single window mode.
There's also a project setting that you can enable to force it.

Thank you, it works

We can probably pass --single-window to the editor execution call from the project manager, like we already do with flags such as --verbose if they're used to start the project manager.

I did some research using i3 a while ago, here's what i got from that.
The main issue seems related to the way DisplayServerX11::_create_window works. It:

  1. Creates the window (XCreateWindow)
  2. Maps the window (XMapWindow)
  3. Configures the window(attributes, properties ecc.)

The issue is that mapping the window makes it immediately known to the WM which, at least in the case of i3, can clear some of it properties and resizes the window if there isn't the right atom set.

Now, why does it work randomly? Reading through the debug logs, i found this section, which gives me some hints:

09/05/2020 03:01:22 - WM_CLASS changed to Godot_Engine (instance), [PROJECT_NAME] (class)
09/05/2020 03:01:22 - WM_NAME changed to "Godot"
09/05/2020 03:01:22 - Using legacy window title. Note that in order to get Unicode window titles in i3, the application has to set _NET_WM_NAME (UTF-8)
09/05/2020 03:01:22 - window.c:window_update_name:64 - _NET_WM_NAME not specified, not changing
09/05/2020 03:01:22 - window.c:window_update_leader:139 - CLIENT_LEADER not set on window 0x05a00053.
09/05/2020 03:01:22 - window.c:window_update_transient_for:164 - TRANSIENT_FOR not set on window 0x05a00053.
09/05/2020 03:01:22 - window.c:window_update_strut_partial:189 - _NET_WM_STRUT_PARTIAL not set.
09/05/2020 03:01:22 - window.c:window_update_role:214 - WM_WINDOW_ROLE not set.
09/05/2020 03:01:22 - window.c:window_update_hints:377 - WM_HINTS not set.
09/05/2020 03:01:22 - window.c:window_update_normal_hints:291 - Clearing maximum size
09/05/2020 03:01:22 - window.c:window_update_normal_hints:312 - Clearing size increments
09/05/2020 03:01:22 - window.c:window_update_normal_hints:326 - Clearing base size
09/05/2020 03:01:22 - window.c:window_update_normal_hints:335 - Setting geometry x=1616 y=87 w=294 h=218
09/05/2020 03:01:22 - window.c:window_update_normal_hints:359 - Clearing aspect ratios

It seems that right after mapping _most_ of the times i3 managed Godot's popup instantly, not finding any atoms since they weren't set yet.

I tried moving the mapping to a later stage in that function In my messy fork, effectively swapping step 2 and 3, and it fixed all tooltips and simple popups. More complex popups(Like the "Add Node" window) don't work, and that's where i left off.

My hypotesis for this last part of the issue with those popups is that, maybe they inherit from Window and then they may set their properties after getting shown, but i haven't looked further into this.

Edit: typo

Ok, so I tried making changes into the generic display server itself which for now I implemented only for the "linuxbsd" platform in my messy fork.

Now a window has to be shown with the show_window() function, but it doesn't seem too difficult to implement(I don't know if there are any other windows to be shown, for now i only added this call into Window and DisplayServerX11 for the main window, there shouldn't be other needed but i'm not sure).

At this point almost everything works with the exception of a few popups (like one which goes "Play current scene" > "Would you like to save the current scene?" > "yes" > popup which closes almost instantly) and some warning in other ones("out of date").

There are also some position issues, are those related to this problem regarding tiling WMs or is it a more general one?

Also, should i start making a pull request?

There are also some position issues, are those related to this problem regarding tiling WMs or is it a more general one?

I think it's a general one: #38591

Lately I've been busy, but I've made some tests and can confirm that the positional issues i got were related to that issue and got fixed by the pull request in its comments.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

blurymind picture blurymind  路  3Comments

bojidar-bg picture bojidar-bg  路  3Comments

n-pigeon picture n-pigeon  路  3Comments

ducdetronquito picture ducdetronquito  路  3Comments

testman42 picture testman42  路  3Comments