Xpra: Ticket #490: Left-clicking on Drop Down Menus with OSX client sometimes results in z-index issues with menu appearing behind the window

The menu behavior changes depending on what has focus: the xpra session window, the menu within the window itself, or outside the window, the menu will either show up right away, or behind the window.

It goes as follows, and acts consistently all the way back to 0.9.8, r4003:

As noted in ticket:484#comment:6

Thu, 09 Jan 2014 22:04:06 GMT - J. Max Mena: attachment set

menu has focus after click

Thu, 09 Jan 2014 22:04:27 GMT - J. Max Mena: attachment set

menu has focus before you click

Thu, 09 Jan 2014 22:05:05 GMT - J. Max Mena: attachment set

Window has focus, after clicking

Thu, 09 Jan 2014 22:05:25 GMT - J. Max Mena: attachment set

Window has focus, before clicking

Thu, 09 Jan 2014 22:05:48 GMT - J. Max Mena: attachment set

Window had no focus, after clicking

Thu, 09 Jan 2014 22:07:03 GMT - J. Max Mena: attachment set

Window has no focus, before clicking

Fri, 10 Jan 2014 01:30:24 GMT - Antoine Martin: owner, status, description changed

Fri, 10 Jan 2014 01:37:49 GMT - Antoine Martin: keywords, milestone set

Can you reproduce the problem with simpler applications, like tests/xpra/test_apps/test_drop_down.py or gedit?

Looks to me like this is a gtk-osx or gtk on osx issue, maybe due to an impedance mismatch between X11 window types and osx windows. We may be able to workaround the problem with judiciously placed calls to raise certain types of windows to force osx to do what is expected for those types of widget windows. May be related to #469

Fri, 10 Jan 2014 13:46:55 GMT - Antoine Martin:

OK, I can reproduce the problem with the drop down menu on this example page: w3schools tryhtml_select2, with chrome only, no such problems with firefox.

I am pretty sure this is the same issue as #336 and #139: drop downs usually use input grabs: after we click on the widget ("mouse down") they expect to receive the "mouse up" event even if the mouse is released outside the drop down menu area they have just created, which never comes because we dispatch it to the parent window instead.

Here is what happens with an OSX client:

Got configure event: <gtk.gdk.Event at 0x19224a88: GDK_CONFIGURE x=814, y=332, width=64, height=78>
Got map event: <gtk.gdk.Event at 0x19224a88: GDK_MAP> - OR=True
focus-out-event for wid=155
_focus_change((<ClientWindow object at 0x18d86c88 (xpra+client+gtk2+client_window+ClientWindow at 0x7b4a7a0)>, \
    <GParamBoolean 'has-toplevel-focus'>)) wid=155, has-toplevel-focus=False, _been_mapped=True
update_focus(155, False) _focused=155
add_packet_to_queue(button-action ...)

(window 155 is the browser window) With Linux and win32 clients, we never get the has-toplevel-focus event, we never send the focus change to the server and so the button-action is delivered to the OR popup menu window.

Sat, 11 Jan 2014 11:10:47 GMT - Antoine Martin: attachment set

adds focus debugging and prevent an OR window from making us unfocus a normal window

Sat, 11 Jan 2014 12:20:25 GMT - Antoine Martin:

I tested with extra debugging (see focus-orignore.patch - which also tries to prevent OR windows from causing the main window to lose focus - mistakenly thinking that focus events were causing this behaviour), and since the problem occurs with Chrome and not with Firefox, I quickly became interested in the drop down window attributes, or lack thereof with Chrome: Firefox correctly uses a UTILITY window type and sets the transient-for property to point to the main window the utility drop down window is for. Chrome on the other hand, creates a NORMAL window without setting transient-for. I thought maybe these attributes helps the client side window manager (OSX) figure out what to do with this override-redirect window (keeping it on top).

Example events with the a patch to force both window-type and transient-for:

But forcing those attributes did not help.

Then, since the linux clients show the behaviour we expect, I tried to compare the client-side packet logging:

No difference there apart from the attributes forced by the patch. The order of the damage-sequence packets do not matter.

I also tried forcing the new OR window to be shown on top using window.present() instead of just window.show, no difference.

The win32 workaround code in _button_action which simulates a mouse-down event in some cases looked quite suspicious - but it does not fire in this case.

When clicking slowly, one can see that the drop-down menu window only gets pushed down the window stacking order when we release the button, presumably because OSX sees this as a click on the main window (which it is) and decides to raise it then. But then, why is Firefox's window treated any different?? Well xpra info doesn't show any difference whatsoever between the case where it "works" and when it doesn't (which seems to be a little hit and miss - depending on how fast you click and release the button):

window[556].position=(815, 328)
window[556].property.scaling=(1, 1)
window[556].scaling=(1, 1)
window[556].size=(64, 78)

And with Firefox, the only difference is the window-type and transient-for attributes we already know about:

window[559].position=(590, 449)
window[559].property.scaling=(1, 1)
window[559].scaling=(1, 1)
window[559].size=(64, 86)

So we must be setting attributes differently on the client side, maybe the main window and not the drop down window?

Sat, 11 Jan 2014 13:08:22 GMT - Antoine Martin: attachment set

patch including all the different changes that were tested - works!

Sat, 11 Jan 2014 13:08:55 GMT - Antoine Martin: attachment set

trimmed down patch which forces transient-for and fixes focus behaviour on osx

Sat, 11 Jan 2014 13:19:39 GMT - Antoine Martin: attachment set

better patch which tries to use the currently focused window as transient-for window (if possible)

Sat, 11 Jan 2014 13:22:53 GMT - Antoine Martin: owner, status changed

Never mind... the patch I was testing with changed the metadata too late, this patch works. I am not merging it yet because what it does is quite nasty.

What should happen is that Chrome should just be setting transient-for on its override-redirect windows like Firefox does. win32 and Linux honour OR windows without this, but OSX does not. I suspect that the native OSX builds of Chrome do so, someone should submit a patch to Chrome to do the same thing on Linux and win32.

The patch does something naughty when running on OSX: it finds a suitable window using the window's "pid" attribute and uses it..

The problem is that we're just guessing which window to use: we grab a NORMAL non-OR window and use it (preferring the currently focused window - otherwise, the first one we come accross..) It may not be the right one! But there isn't much more we can do: OR windows can come up at any time, not necessarily driven by user input.. and not necessarily already focused.

So please test on OSX only:

Sat, 11 Jan 2014 13:23:03 GMT - Antoine Martin: milestone changed

Mon, 13 Jan 2014 14:32:53 GMT - Antoine Martin:

Works-for-me(tm). Merged in r5176 and backport in r5177 since I need to prepare another stable branch update, please see comment:5 and close after testing.

Tue, 14 Jan 2014 21:41:58 GMT - J. Max Mena: status changed; resolution set

Tested in OSX (10.9) running r5178, seems to be working for now. Consistently has the drop-down menu appear at the top.

Sat, 08 Feb 2014 07:56:33 GMT - Antoine Martin:

Note: r5176 had been reverted for trunk in r5396 as #139 is a better/cleaner solution to this problem.

Mon, 18 Aug 2014 09:16:21 GMT - Antoine Martin: attachment set

code to force focus on osx

Mon, 18 Aug 2014 09:16:50 GMT - Antoine Martin:

Since I cannot reproduce this, can you please record a short video (less than 5 seconds) showing how you reproduce this, maybe I'm not doing it right.

Assuming the problems is focus / raising related, maybe we can use this code: https://github.com/facelessuser/Rummage/blob/master/_gui/platform_window_focus.py (edit: 404, fortunate that I also attached it to this ticket!).

Mon, 05 Jan 2015 11:08:51 GMT - Antoine Martin:

Note: this may be impacted by recent changes in trunk for 0.15: see #718, #765

Fri, 14 Apr 2017 06:46:03 GMT - Antoine Martin:

r15606 now forces the focus for initial windows (and this workaround is then disabled after 2 seconds). We use Python, Quartz, GTK, and window focus. Maybe this workaround can help with #469?

Thu, 18 Oct 2018 06:25:24 GMT - Antoine Martin:

Note: we also use this force-focus code in the new GUI (#1762) but this could be done better still: as well as using a timer, we could listen for the focus event and disable the workaround when the window gets focus.

Sat, 23 Jan 2021 04:57:10 GMT - migration script:

this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/490