-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
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
Popup menus (including context menus) pop up briefly and disappear if another menu is already open #50367
Comments
See also #44997. Can you reproduce this after enabling Single Window Mode in the Editor Settings? |
With single window mode, top bar menus behave normally (new menu opens, old closes), but context menus can no longer be opened if another popup menu (top bar OR context) is already open (the old one is not getting closed). |
This is how it looks chronologically without single window mode (I click on one top bar item, then click on another)
|
I am not sure however what exactly closes them (sets visibility to false).
|
The Message does not have a sender or other origin info, so it is kind of an anonymous trolling at this point. struct Message {
Callable callable;
int16_t type;
union {
int16_t notification;
int16_t args;
};
}; |
ok, i have dumped the method names of the calls being pushed into the message queue while this thing happens
Now we know the exact method name that gets pushed, and this name is |
and here is our trace Thread 1 "godot.linuxbsd." hit Breakpoint 1, MessageQueue::push_call (this=0x6faeb30, p_id=..., p_method=...,
p_args=0x7fffffffda80, p_argcount=0, p_show_error=<optimized out>) at core/object/message_queue.cpp:48
48 print_line("hide was pushed");
(gdb) backtrace
#0 MessageQueue::push_call (this=0x6faeb30, p_id=..., p_method=..., p_args=0x7fffffffda80, p_argcount=0,
p_show_error=<optimized out>) at core/object/message_queue.cpp:48
#1 0x0000000003aeed2b in MessageQueue::push_call (p_arg5=..., p_arg4=..., p_arg3=..., p_arg2=..., p_arg1=..., p_method=...,
p_id=..., this=<optimized out>) at core/object/message_queue.cpp:66
#2 MessageQueue::push_call (this=<optimized out>, p_object=p_object@entry=0xe2a5820, p_method=..., p_arg1=..., p_arg2=...,
p_arg3=..., p_arg4=..., p_arg5=...) at core/object/message_queue.cpp:124
#3 0x0000000003af2862 in Object::call_deferred (this=this@entry=0xe2a5820, p_method=..., p_arg1=..., p_arg2=..., p_arg3=...,
p_arg4=..., p_arg5=...) at core/object/object.cpp:1650
#4 0x000000000253586f in Popup::_close_pressed (this=0xe2a5820) at scene/gui/popup.cpp:106
#5 0x0000000003afef6a in Object::emit_signal (this=0x8c052d0, p_name=..., p_args=<optimized out>, p_argcount=<optimized out>)
at core/object/object.cpp:1099
#6 0x0000000003affd90 in Object::emit_signal (this=this@entry=0x8c052d0, p_name=..., p_arg1=..., p_arg2=..., p_arg3=...,
p_arg4=..., p_arg5=...) at core/object/object.cpp:1154
#7 0x00000000023e1341 in Window::_event_callback (this=0x8c052d0, p_event=<optimized out>) at scene/main/window.cpp:328
#8 0x0000000000844c7b in DisplayServerX11::_send_window_event (this=<optimized out>, wd=..., p_event=4294958880)
at platform/linuxbsd/display_server_x11.cpp:2681
#9 0x0000000000850395 in DisplayServerX11::process_events (this=0x70795d0) at platform/linuxbsd/display_server_x11.cpp:3048
#10 0x000000000083a5d0 in OS_LinuxBSD::run (this=this@entry=0x7fffffffe130) at platform/linuxbsd/os_linuxbsd.cpp:274
#11 0x000000000082e832 in main (argc=3, argv=0x7fffffffe638) at platform/linuxbsd/godot_linuxbsd.cpp:58 and for the second close (seems the same?) Thread 1 "godot.linuxbsd." hit Breakpoint 1, MessageQueue::push_call (this=0x6faeb30, p_id=..., p_method=...,
p_args=0x7fffffffda80, p_argcount=0, p_show_error=<optimized out>) at core/object/message_queue.cpp:48
48 print_line("hide was pushed");
(gdb) backtrace
#0 MessageQueue::push_call (this=0x6faeb30, p_id=..., p_method=..., p_args=0x7fffffffda80, p_argcount=0,
p_show_error=<optimized out>) at core/object/message_queue.cpp:48
#1 0x0000000003aeed2b in MessageQueue::push_call (p_arg5=..., p_arg4=..., p_arg3=..., p_arg2=..., p_arg1=..., p_method=...,
p_id=..., this=<optimized out>) at core/object/message_queue.cpp:66
#2 MessageQueue::push_call (this=<optimized out>, p_object=p_object@entry=0xe5c0df0, p_method=..., p_arg1=..., p_arg2=...,
p_arg3=..., p_arg4=..., p_arg5=...) at core/object/message_queue.cpp:124
#3 0x0000000003af2862 in Object::call_deferred (this=this@entry=0xe5c0df0, p_method=..., p_arg1=..., p_arg2=..., p_arg3=...,
p_arg4=..., p_arg5=...) at core/object/object.cpp:1650
#4 0x000000000253586f in Popup::_close_pressed (this=0xe5c0df0) at scene/gui/popup.cpp:106
#5 0x0000000003afef6a in Object::emit_signal (this=0x8c052d0, p_name=..., p_args=<optimized out>, p_argcount=<optimized out>)
at core/object/object.cpp:1099
#6 0x0000000003affd90 in Object::emit_signal (this=this@entry=0x8c052d0, p_name=..., p_arg1=..., p_arg2=..., p_arg3=...,
p_arg4=..., p_arg5=...) at core/object/object.cpp:1154
#7 0x00000000023e1341 in Window::_event_callback (this=0x8c052d0, p_event=<optimized out>) at scene/main/window.cpp:328
#8 0x0000000000844c7b in DisplayServerX11::_send_window_event (this=<optimized out>, wd=..., p_event=4294958880)
at platform/linuxbsd/display_server_x11.cpp:2681
#9 0x0000000000850395 in DisplayServerX11::process_events (this=0x70795d0) at platform/linuxbsd/display_server_x11.cpp:3048
#10 0x000000000083a5d0 in OS_LinuxBSD::run (this=this@entry=0x7fffffffe130) at platform/linuxbsd/os_linuxbsd.cpp:274
#11 0x000000000082e832 in main (argc=3, argv=0x7fffffffe638) at platform/linuxbsd/godot_linuxbsd.cpp:58 |
In BOTH cases DisplayServer sends Also, one can notice that the window and the popup are different objects (they have different |
ok, noticed optimizing gets in the way too much, so here is a stack with an unoptimized build. Thread 1 "godot.linuxbsd." hit Breakpoint 1, MessageQueue::push_call (this=0x98c1f50, p_id=..., p_method=...,
p_args=0x7fffffffd440, p_argcount=0, p_show_error=false) at core/object/message_queue.cpp:48
48 print_line("hide was pushed");
(gdb) backtrace
#0 MessageQueue::push_call (this=0x98c1f50, p_id=..., p_method=..., p_args=0x7fffffffd440, p_argcount=0, p_show_error=false)
at core/object/message_queue.cpp:48
#1 0x0000000005d296f3 in MessageQueue::push_call (this=0x98c1f50, p_id=..., p_method=..., p_arg1=..., p_arg2=...,
p_arg3=..., p_arg4=..., p_arg5=...) at core/object/message_queue.cpp:66
#2 0x0000000005d2a45b in MessageQueue::push_call (this=0x98c1f50, p_object=0x10bb81e0, p_method=..., p_arg1=..., p_arg2=...,
p_arg3=..., p_arg4=..., p_arg5=...) at core/object/message_queue.cpp:124
#3 0x0000000005d3bbea in Object::call_deferred (this=0x10bb81e0, p_method=..., p_arg1=..., p_arg2=..., p_arg3=...,
p_arg4=..., p_arg5=...) at core/object/object.cpp:1650
#4 0x0000000004622d18 in Popup::_close_pressed (this=0x10bb81e0) at scene/gui/popup.cpp:106
#5 0x0000000004622c3c in Popup::_parent_focused (this=0x10bb81e0) at scene/gui/popup.cpp:97
#6 0x0000000004625aba in call_with_variant_args_helper<Popup>(Popup*, void (Popup::*)(), Variant const**, Callable::CallError&, IndexSequence<>) (p_instance=0x10bb81e0, p_method=(void (Popup::*)(Popup * const)) 0x4622c06 <Popup::_parent_focused()>,
p_args=0x7fffffffd9f0, r_error=...) at ./core/variant/binder_common.h:218
#7 0x0000000004625942 in call_with_variant_args<Popup> (p_instance=0x10bb81e0,
p_method=(void (Popup::*)(Popup * const)) 0x4622c06 <Popup::_parent_focused()>, p_args=0x7fffffffd9f0, p_argcount=0,
r_error=...) at ./core/variant/binder_common.h:332
#8 0x00000000046257b9 in CallableCustomMethodPointer<Popup>::call (this=0x1d3196b0, p_arguments=0x7fffffffd9f0,
p_argcount=0, r_return_value=..., r_call_error=...) at ./core/object/callable_method_pointer.h:96
#9 0x0000000005a999af in Callable::call (this=0xbc9c160, p_arguments=0x7fffffffd9f0, p_argcount=0, r_return_value=...,
r_call_error=...) at core/variant/callable.cpp:50
#10 0x0000000005d34706 in Object::emit_signal (this=0xb57d150, p_name=..., p_args=0x7fffffffd9f0, p_argcount=0)
at core/object/object.cpp:1099
#11 0x0000000005d34e18 in Object::emit_signal (this=0xb57d150, p_name=..., p_arg1=..., p_arg2=..., p_arg3=..., p_arg4=...,
p_arg5=...) at core/object/object.cpp:1154
#12 0x0000000004498962 in Window::_event_callback (this=0xb57d150, p_event=DisplayServer::WINDOW_EVENT_FOCUS_IN)
at scene/main/window.cpp:328
#13 0x00000000044b739b in call_with_variant_args_helper<Window, DisplayServer::WindowEvent, 0ul> (p_instance=0xb57d150,
p_method=
(void (Window::*)(Window * const, DisplayServer::WindowEvent)) 0x4498606 <Window::_event_callback(DisplayServer::WindowEvent)>, p_args=0x7fffffffdd98, r_error=...) at ./core/variant/binder_common.h:218
#14 0x00000000044b4633 in call_with_variant_args<Window, DisplayServer::WindowEvent> (p_instance=0xb57d150, p_method=
(void (Window::*)(Window * const, DisplayServer::WindowEvent)) 0x4498606 <Window::_event_callback(DisplayServer::WindowEvent)>, p_args=0x7fffffffdd98, p_argcount=1, r_error=...) at ./core/variant/binder_common.h:332
#15 0x00000000044b1063 in CallableCustomMethodPointer<Window, DisplayServer::WindowEvent>::call (this=0x1cff91c0,
p_arguments=0x7fffffffdd98, p_argcount=1, r_return_value=..., r_call_error=...)
at ./core/object/callable_method_pointer.h:96
#16 0x0000000005a999af in Callable::call (this=0x9bcc5f8, p_arguments=0x7fffffffdd98, p_argcount=1, r_return_value=...,
r_call_error=...) at core/variant/callable.cpp:50
#17 0x000000000208d464 in DisplayServerX11::_send_window_event (this=0x998cca0, wd=...,
p_event=DisplayServer::WINDOW_EVENT_FOCUS_IN) at platform/linuxbsd/display_server_x11.cpp:2681
#18 0x000000000208eb9b in DisplayServerX11::process_events (this=0x998cca0) at platform/linuxbsd/display_server_x11.cpp:3048
#19 0x0000000002078870 in OS_LinuxBSD::run (this=0x7fffffffe140) at platform/linuxbsd/os_linuxbsd.cpp:274
#20 0x00000000020757a4 in main (argc=3, argv=0x7fffffffe638) at platform/linuxbsd/godot_linuxbsd.cpp:58
|
During gdb-mediated interrogation of the Window which gets focused (and hereby closes all popups which are set to close on parent focus), it transpires that this window has an empty title. Size and position-wise it spans the whole editor, so probably it is a root window of sorts. |
Indeed. Unlike |
trying to bisect (master) so far: |
Ok, so the picture is now almost clear.
As a consequence, we click, main window gets focus (that it has previously lost?), and both popups get hidden because they are indirect children. |
Thanks for investigating! It looks like there's something wrong with the other of events somehow. Even if the click gives focus to the main window and closes the previous popup, the new popup should still be created afterwards and not end up being closed. 6d1ef8e was needed to fix cases of popups that stayed open when clicking somewhere else in the editor (like property edit fields). I think I've seen this issue or something similar when working on 5315bff and thought I fixed it. Which WM are you using? I had tested on Gnome, KDE and XFCE back then (on Ubuntu). I'll try to check when I find some time, but if you'd like to investigate further, you can uncomment this preprocessor in the X11 display server to get more info about incoming X11 events and created/destroyed windows: godot/platform/linuxbsd/display_server_x11.cpp Lines 88 to 93 in 30d4732
|
Thanks. Random behaviour on Wayfire suggests a race condition. Which would probably depend on the speed of the window manager with dwm and i3 being the quickest around. |
More detailed chronology
This chronology indeed looks weird. So, first of all, popup happens earlier than focus signal gets to the root window. And secondly, the focus event on the root window happens twice. |
For comparison, here is how this looks under LXQt
|
With x11 debug as proposed (patholgic example, dwm)
|
Button presses are pushed through via input event queue flushes. backtrace of a button click (pathologic) Thread 1 "godot.linuxbsd." hit Breakpoint 1, MenuButton::pressed (this=0x10ed63b0) at scene/gui/menu_button.cpp:59
59 print_line("menu_button clicked \n");
(gdb) backtrace
#0 MenuButton::pressed (this=0x10ed63b0) at scene/gui/menu_button.cpp:59
#1 0x00000000044bdb44 in BaseButton::_pressed (this=0x10ed63b0) at scene/gui/base_button.cpp:127
#2 0x00000000044be43b in BaseButton::on_action_event (this=0x10ed63b0, p_event=...) at scene/gui/base_button.cpp:159
#3 0x00000000044bd752 in BaseButton::_gui_input (this=0x10ed63b0, p_event=...) at scene/gui/base_button.cpp:67
#4 0x0000000004610ece in MenuButton::_gui_input (this=0x10ed63b0, p_event=...) at scene/gui/menu_button.cpp:74
#5 0x0000000003a1ab1a in call_with_variant_args_helper<__UnexistingClass, Ref<InputEvent>, 0ul> (p_instance=0x10ed63b0,
p_method=&virtual table offset 528, p_args=0x7fffffffd3e0, r_error=...) at ./core/variant/binder_common.h:218
#6 0x0000000003a19807 in call_with_variant_args_dv<__UnexistingClass, Ref<InputEvent> > (p_instance=0x10ed63b0,
p_method=&virtual table offset 528, p_args=0x7fffffffd4f0, p_argcount=1, r_error=..., default_values=...)
at ./core/variant/binder_common.h:365
#7 0x0000000003a13b30 in MethodBindT<Ref<InputEvent> >::call (this=0xad04210, p_object=0x10ed63b0, p_args=0x7fffffffd4f0,
p_arg_count=1, r_error=...) at ./core/object/method_bind.h:285
#8 0x000000000445d613 in Viewport::_gui_call_input (this=0xb577280, p_control=0x10ed63b0, p_input=...)
at scene/main/viewport.cpp:1656
#9 0x000000000445e60b in Viewport::_gui_input_event (this=0xb577280, p_event=...) at scene/main/viewport.cpp:1912
#10 0x000000000446530c in Viewport::input (this=0xb577280, p_event=..., p_local_coords=false) at scene/main/viewport.cpp:3062
#11 0x000000000449bf3c in Window::_window_input (this=0xb577280, p_ev=...) at scene/main/window.cpp:927
#12 0x00000000044b76bf in call_with_variant_args_helper<Window, Ref<InputEvent> const&, 0ul> (p_instance=0xb577280, p_method=
(void (Window::*)(Window * const, const Ref<InputEvent> &)) 0x449bcbc <Window::_window_input(Ref<InputEvent> const&)>,
p_args=0x7fffffffdc08, r_error=...) at ./core/variant/binder_common.h:218
#13 0x00000000044b497f in call_with_variant_args<Window, Ref<InputEvent> const&> (p_instance=0xb577280, p_method=
(void (Window::*)(Window * const, const Ref<InputEvent> &)) 0x449bcbc <Window::_window_input(Ref<InputEvent> const&)>,
p_args=0x7fffffffdc08, p_argcount=1, r_error=...) at ./core/variant/binder_common.h:332
#14 0x00000000044b0f31 in CallableCustomMethodPointer<Window, Ref<InputEvent> const&>::call (this=0x1cffc500,
p_arguments=0x7fffffffdc08, p_argcount=1, r_return_value=..., r_call_error=...)
at ./core/object/callable_method_pointer.h:96
#15 0x0000000005a99daf in Callable::call (this=0x7fffffffdc30, p_arguments=0x7fffffffdc08, p_argcount=1, r_return_value=...,
r_call_error=...) at core/variant/callable.cpp:50
#16 0x000000000208d282 in DisplayServerX11::_dispatch_input_event (this=0x998cca0, p_event=...)
at platform/linuxbsd/display_server_x11.cpp:2662
#17 0x000000000208d0bf in DisplayServerX11::_dispatch_input_events (p_event=...)
at platform/linuxbsd/display_server_x11.cpp:2645
#18 0x0000000005a4ac8b in Input::_parse_input_event_impl (this=0x98f7270, p_event=..., p_is_emulated=false)
at core/input/input.cpp:643
#19 0x0000000005a49b24 in Input::parse_input_event (this=0x98f7270, p_event=...) at core/input/input.cpp:465
#20 0x0000000005a4c068 in Input::flush_accumulated_events (this=0x98f7270) at core/input/input.cpp:858
#21 0x00000000020911be in DisplayServerX11::process_events (this=0x998cca0) at platform/linuxbsd/display_server_x11.cpp:3496
#22 0x0000000002078870 in OS_LinuxBSD::run (this=0x7fffffffe140) at platform/linuxbsd/os_linuxbsd.cpp:274
#23 0x00000000020757a4 in main (argc=3, argv=0x7fffffffe638) at platform/linuxbsd/godot_linuxbsd.cpp:58 |
This is what happens if one knocks out https://github.com/godotengine/godot/blob/master/platform/linuxbsd/display_server_x11.cpp#L3177
|
Nice findings! Your interpretation of the problem makes sense.
If I remember correctly this was still important for focus to work correctly. When the line is disabled, does clicking on the main window still closes any previous popup correctly (if you don't open a new popup)?
Yeah, I can see how that could be part of the problem. I'm not sure what the proper fix or design would be, but it might be something to investigate. Although there's still something I don't fully understand in this chain of events:
I understand the first change of focus from 6 to 0 is due to the mouse click, then the new window (7) is created and focused. But I wonder what is causing the last change of focus from 7 to 0 which is causing the new popup to close. I wonder if it could be due to this when the previous popup (6) is closed somehow: godot/platform/linuxbsd/display_server_x11.cpp Lines 1115 to 1119 in c0da576
Or maybe the use of |
No, the popup still remains open if this line is knocked out and if i click somewhere else.
As for the source of the second focus of the Main Window, you are right.
|
from The specified focus window must be viewable at the time XSetInputFocus
is called, or a BadMatch error results. If the focus window later be‐
comes not viewable, the X server evaluates the revert_to argument to
determine the new focus window as follows:
• If revert_to is RevertToParent, the focus reverts to the parent
(or the closest viewable ancestor), and the new revert_to value is
taken to be RevertToNone.
• If revert_to is RevertToPointerRoot or RevertToNone, the focus re‐
verts to PointerRoot or None, respectively. When the focus re‐
verts, the X server generates FocusIn and FocusOut events, but the
last-focus-change time is not affected. RevertTo kicks in only when the focus is lost due to the non-viewability of the current focus. Here, the problem is not RevertTo usage, but the fact that In fact, if i just comment out this single line in XSetInputFocus(x11_display, wd_parent.x11_window, RevertToPointerRoot, CurrentTime); |
@pouleyKetchoupp I played with it for some time and i cannot seem to produce a situation where the program fails because this line in I do run into some strange behaviour when using keyboard navigation, but i am not yet sure if it is because of this change, needs more testing. |
@Houkime Great job on investigating and testing! I made that change as part of #41456, but unfortunately I didn't write a note about the exact case it was fixing in the PR and now I don't remember, my bad :/ It might be that it's needed for keyboard controls as you suggested, since in this case the WM or the focus set on mouse click events would not be able to do the work. I'll do some tests on my side as well, on Gnome/KDE so we can have a clearer idea what this focus change in Automatic tests would be great. On linux we would have to also test on different WMs to do it right so that could add to the complexity, but I totally agree it would help a lot to have it (even starting with something simple). |
No, keyboard shenanigans are not related to the knocked out line. Or at least, they are not caused by the knockout (The line might still be necessary for them to actually work in the future). |
Ok, so i tried to make some test at least for this particular bug. extends Node2D
func _ready():
var but1 = MenuButton.new()
prepare_popup_button(but1)
but1.text = "button1"
but1.rect_position = Vector2(100,0)
var but2 = MenuButton.new()
prepare_popup_button(but2)
but2.text = "button2"
but2.rect_position = Vector2(300,0)
await wait_idle_frames(100)
print("pressing 1st button")
await realistic_lclick(center(but1))
await wait_idle_frames(20)
print("pressing 2nd button")
await realistic_lclick(center(but2))
await wait_idle_frames(20)
assert(but1.get_popup().visible == false,\
"first popup remains open. FAILURE")
assert(but2.get_popup().visible == true,\
"second popup gets hidden. FAILURE")
func center(control):
return (control.get_rect().position + control.get_rect().end)/2
func realistic_lclick(vector2):
var press_ev = InputEventMouseButton.new()
press_ev.pressed = true
press_ev.button_index = MOUSE_BUTTON_LEFT
press_ev.button_mask = MOUSE_BUTTON_MASK_LEFT
press_ev.position = vector2
print("input - parsing press")
Input.parse_input_event(press_ev)
await wait_idle_frames(20)
var release_ev = InputEventMouseButton.new()
release_ev.pressed = false
release_ev.button_index = MOUSE_BUTTON_LEFT
release_ev.button_mask = MOUSE_BUTTON_MASK_LEFT
release_ev.position = vector2
print ("input - parsing release")
Input.parse_input_event(release_ev)
func wait_idle_frames(n):
for i in range(n):
await get_tree().process_frame
func prepare_popup_button(popup_button):
popup_button.text = "TEST BUTTON"
var submenu = PopupMenu.new()
submenu.set_name("submenu")
submenu.add_item("submenu item")
popup_button.get_popup().add_child(submenu)
popup_button.get_popup().add_submenu_item("submenu label","submenu")
add_child(popup_button) It looks like this (first just editor, then i press F5, and the test runs, and then editor shows me the failed assert) This outputs (with debug things)
And it fails. Unfortunately not because the second menu closes but because the first menu remains open. A project if you want: |
The idea of gdscript-based test came from here godotengine/godot-proposals#1760. @Xrayez, this issue is a bit stuck because i cannot reliably test if everything would be ok if i delete one line of code that produces this bug, or refactor anything to make the focus handling design intentions clearer. You have previously tried to make this sort of automated testing for godot, do you have eny recommendations on how to proceed? There are at least Qt and GTK who handle this integration reliably SOMEHOW, but i need to research on how exactly they are doing this. Also, they might be effectively single-window or sth. |
@pouleyKetchoupp also one could entirely separate closing of popup menus from X11 specifics or focus-handling in general, leaving it entirely on the |
A desktop automation framework like Robot Framework could be suited here. |
Or one can just ask X11 nicely, since we are including the X11 headers anyway. This is what xdotool does for mouseclicks faking. Notice how if we want to send to the current window, it is a very simple function (makes use of int _xdo_mousebutton(const xdo_t *xdo, Window window, int button, int is_press) {
int ret = 0;
if (window == CURRENTWINDOW) {
ret = XTestFakeButtonEvent(xdo->xdpy, button, is_press, CurrentTime);
XFlush(xdo->xdpy);
return _is_success("XTestFakeButtonEvent(down)", ret == 0, xdo);
} else {
/* Send to specific window */
int screen = 0;
XButtonEvent xbpe;
charcodemap_t *active_mod;
int active_mod_n;
xdo_get_mouse_location(xdo, &xbpe.x_root, &xbpe.y_root, &screen);
xdo_get_active_modifiers(xdo, &active_mod, &active_mod_n);
xbpe.window = window;
xbpe.button = button;
xbpe.display = xdo->xdpy;
xbpe.root = RootWindow(xdo->xdpy, screen);
xbpe.same_screen = True; /* Should we detect if window is on the same
screen as cursor? */
xbpe.state = xdo_get_input_state(xdo);
xbpe.subwindow = None;
xbpe.time = CurrentTime;
xbpe.type = (is_press ? ButtonPress : ButtonRelease);
/* Get the coordinates of the cursor relative to xbpe.window and also find what
* subwindow it might be on */
XTranslateCoordinates(xdo->xdpy, xbpe.root, xbpe.window,
xbpe.x_root, xbpe.y_root, &xbpe.x, &xbpe.y, &xbpe.subwindow);
/* Normal behavior of 'mouse up' is that the modifier mask includes
* 'ButtonNMotionMask' where N is the button being released. This works the
* same way with keys, too. */
if (!is_press) { /* is mouse up */
switch(button) {
case 1: xbpe.state |= Button1MotionMask; break;
case 2: xbpe.state |= Button2MotionMask; break;
case 3: xbpe.state |= Button3MotionMask; break;
case 4: xbpe.state |= Button4MotionMask; break;
case 5: xbpe.state |= Button5MotionMask; break;
}
}
ret = XSendEvent(xdo->xdpy, window, True, ButtonPressMask, (XEvent *)&xbpe);
XFlush(xdo->xdpy);
free(active_mod);
return _is_success("XSendEvent(mousedown)", ret == 0, xdo);
}
} |
I'm not using Godot 4.x currently so I'm not really familiar with the new windows system in Godot to be honest. There's a fuzzer currently integrated into CI: godot/.github/workflows/linux_builds.yml Lines 156 to 187 in 0f78e36
and AFAIK it does test GUI classes (basically all classes which are exposed in But even if it does such testing, it would be difficult to reproduce. Testing this on a even deeper level may end up being too much work, or too much maintenance work, multiplied by differences in platform implementations (what about Windows platform)? As I've previously said, GDScript works fine in single-windowed mode in 3.x, for instance I've recently created some tests for X11 specific testing facilities could be integrated if they help the initial development I guess, but at the end of the day, it would make more sense to come up with something which does not require dealing with platform-specific functions directly, that's more implementation detail. Having said that, I really don't know how to proceed with this specific issue, rendering/WMs is not my area of expertise/interest, just some food for thought! |
@Houkime Sorry for the delayed answer. I was able to confirm the issue on Archlinux/i3 and opened #50712, please check if it's working for you. I also figured out the reason I had added this focus on parent in Thanks again for all the investigation! I agree with the idea that we would be better off with proper regression tests for the editor ui system, especially on X11. I don't personally have enough bandwidth to spend too much time on Linux these days, but contributions on this topic are very welcome.
That sounds like an interesting idea too. I imagine it would have a to be a refactoring of all platform code and would need proper evaluation, but in the long run it does seem like it could make things easier (at least for X11, I don't know other platforms as well). |
Godot version
v4.0.dev.custom_build [a0d800e]
System information
Arch Linux (kernel 5.12.14-arch1-1, X11)
Issue description
The initial menu gets closed, but the new menu gets closed too, after a brief flicker of existence.
(flicker always happens, it is not always captured because of limited gif fps, but i do it multiple times in gifs to be sure.)
Expected behaviour
Steps to reproduce
Minimal reproduction project
Not applicable. (a new empty project is just as good as anything else)
The text was updated successfully, but these errors were encountered: