Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
Tracked by #37734
PanosTrak opened this issue Apr 16, 2020 · 20 comments · Fixed by #38727
Closed
Tracked by #37734

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

PanosTrak opened this issue Apr 16, 2020 · 20 comments · Fixed by #38727

Comments

@PanosTrak
Copy link

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

@rsubtil
Copy link
Contributor

rsubtil commented Apr 16, 2020

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.

@CheesecakeCG
Copy link
Contributor

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

@Riteo
Copy link
Contributor

Riteo commented Apr 17, 2020

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.

@Calinou
Copy link
Member

Calinou commented Apr 17, 2020

@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.

@rsubtil
Copy link
Contributor

rsubtil commented Apr 18, 2020

@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..?)

@Calinou
Copy link
Member

Calinou commented Apr 18, 2020

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

@rsubtil
Copy link
Contributor

rsubtil commented Apr 18, 2020

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 😛

@rsubtil
Copy link
Contributor

rsubtil commented Apr 19, 2020

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 😛

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).

@PanosTrak
Copy link
Author

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

This exactly happens to me too!

@CheesecakeCG
Copy link
Contributor

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;
}

@RibalGZ
Copy link

RibalGZ commented May 12, 2020

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

@RibalGZ
Copy link

RibalGZ commented May 12, 2020

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

@akien-mga
Copy link
Member

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.

@RibalGZ
Copy link

RibalGZ commented May 12, 2020

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)

@RibalGZ
Copy link

RibalGZ commented May 12, 2020

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

@Calinou
Copy link
Member

Calinou commented May 12, 2020

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.

@Riteo
Copy link
Contributor

Riteo commented May 12, 2020

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

@Riteo
Copy link
Contributor

Riteo commented May 13, 2020

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?

@rsubtil
Copy link
Contributor

rsubtil commented May 13, 2020

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

@Riteo
Copy link
Contributor

Riteo commented Jun 2, 2020

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.

Riteo pushed a commit to Riteo/godot that referenced this issue Jul 23, 2020
When creating a window, Godot would first register it to the WM(show it) and then set its flags.
This works fine on a floating WM, but on tiling WMs as soon as a window gets registered
the WM immediately acts on the window by scaling it up and treating it as a generic window,
being registered without any special flags.

This commit separates the showing of the window into another function and calls it after the most important flags are set,
making windows with special flags(eg. all popups) work again on tiling WMs.

Fixes godotengine#37930
MarcusElg pushed a commit to MarcusElg/godot that referenced this issue Oct 19, 2020
When creating a window, Godot would first register it to the WM(show it) and then set its flags.
This works fine on a floating WM, but on tiling WMs as soon as a window gets registered
the WM immediately acts on the window by scaling it up and treating it as a generic window,
being registered without any special flags.

This commit separates the showing of the window into another function and calls it after the most important flags are set,
making windows with special flags(eg. all popups) work again on tiling WMs.

Fixes godotengine#37930
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants