#490 closed defect (fixed)
Left-clicking on Drop Down Menus with OSX client sometimes results in z-index issues with menu appearing behind the window
Reported by: | J. Max Mena | Owned by: | J. Max Mena |
---|---|---|---|
Priority: | major | Milestone: | 0.11 |
Component: | client | Version: | |
Keywords: | osx | Cc: |
Description (last modified by )
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:
- Left clicking on drop down menus in an xpra session window which does not have focus - the drop down menu works as expected.
- Left clicking on drop down menus in an xpra session window which does have focus - the drop down menu appears "behind" the window (though the drop menu can be clicked "through" the window which "appears" to have focus).
- Left clicking on drop down menus in an xpra session window, when the menu itself has focus - the drop down menu works as expected.
- Using the keyboard to tab to the menu and select it - works as expected. (Presumably this method brings focus to the menu item before "clicking" it, thus working as the instance above.)
As noted in ticket:484#comment:6
Attachments (11)
Change History (25)
Changed 8 years ago by
Attachment: | Xpra4003 menu focus after click.png added |
---|
Changed 8 years ago by
Attachment: | Xpra4003 menu focus before click.png added |
---|
menu has focus before you click
Changed 8 years ago by
Attachment: | xpra4003 window focus after click.png added |
---|
Window has focus, after clicking
Changed 8 years ago by
Attachment: | xpra4003 window focus before click.png added |
---|
Window has focus, before clicking
Changed 8 years ago by
Attachment: | Xpra4003 window no focus after click.png added |
---|
Window had no focus, after clicking
Changed 8 years ago by
Attachment: | Xpra4003 window no focus before click.png added |
---|
Window has no focus, before clicking
comment:1 Changed 8 years ago by
Description: | modified (diff) |
---|---|
Owner: | changed from Antoine Martin to Antoine Martin |
Status: | new → assigned |
comment:2 Changed 8 years ago by
Keywords: | osx added |
---|---|
Milestone: | → 0.12 |
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
comment:3 Changed 8 years ago by
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 send_focus(0) 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.
Changed 8 years ago by
Attachment: | focus-orignore.patch added |
---|
adds focus debugging and prevent an OR window from making us unfocus a normal window
comment:4 Changed 8 years ago by
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
:
- firefox:
send_focus(407) add_packet_to_queue(focus ...) add_packet_to_queue(button-action ...) add_packet_to_queue(button-action ...) add_packet_to_queue(pointer-position ...) * 10 processing packet draw processing packet draw add_packet_to_queue(damage-sequence ...) add_packet_to_queue(damage-sequence ...) add_packet_to_queue(pointer-position ...) processing packet cursor add_packet_to_queue(pointer-position ...) add_packet_to_queue(button-action ...) processing packet new-override-redirect init_window(..) make_new_window: pid=17672, window-type=['UTILITY'], transient-for=407 make_new_window(442, 544, 383, 64, 86, {'fullscreen': False, 'has-alpha': False, 'xid': '0xe04ec6', 'pid': 17672, \ 'window-type': ['UTILITY'], 'maximized': False, 'transient-for': 407, 'override-redirect': True}, True, \ {'encodings.rgb_formats': ['RGB']}, 0)=\ <ClientWindow object at 0x1922c508 (xpra+client+gtk2+client_window+ClientWindow at 0x7b4abc0)>, group_leader_window=None processing packet draw window_state_updated(<ClientWindow object at 0x1922c508 \ (xpra+client+gtk2+client_window+ClientWindow at 0x7b4abc0)>, <gtk.gdk.Event at 0x19219998: GDK_WINDOW_STATE>) \ wid=442, new_window_state=<flags 0 of type GdkWindowState>, fullscreen=False, maximized=False add_packet_to_queue(damage-sequence ...) processing packet draw add_packet_to_queue(damage-sequence ...) processing packet cursor forcing OR for mouse position
- chrome:
update_focus(213, True) _focused=213 add_packet_to_queue(button-action ...) add_packet_to_queue(button-action ...) add_packet_to_queue(pointer-position ...) * 10 processing packet draw processing packet draw add_packet_to_queue(damage-sequence ...) add_packet_to_queue(damage-sequence ...) add_packet_to_queue(pointer-position ...) add_packet_to_queue(button-action ...) processing packet new-override-redirect init_window(..) make_new_window: pid=12659, window-type=['NORMAL'], transient-for=None forcing utility window forcing transient for 213 make_new_window(447, 838, 328, 64, 78, {'fullscreen': False, 'has-alpha': False, 'xid': '0xc16ce9', 'pid': 12659, \ 'window-type': ['UTILITY'], 'maximized': False, 'transient-for': 213, 'override-redirect': True}, True, \ {'encodings.rgb_formats': ['RGB']}, 0)=\ <ClientWindow object at 0x19230828 (xpra+client+gtk2+client_window+ClientWindow at 0x7b4ac70)>, group_leader_window=None processing packet draw window_state_updated(<ClientWindow object at 0x19230828 \ (xpra+client+gtk2+client_window+ClientWindow at 0x7b4ac70)>, <gtk.gdk.Event at 0x192198a8: GDK_WINDOW_STATE>) \ wid=447, new_window_state=<flags 0 of type GdkWindowState>, fullscreen=False, maximized=False add_packet_to_queue(damage-sequence ...) processing packet draw add_packet_to_queue(damage-sequence ...) add_packet_to_queue(button-action ...) forcing OR for mouse position add_packet_to_queue(pointer-position ...)
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:
- linux client:
add_packet_to_queue(button-action ...) processing packet new-override-redirect make_new_window: pid=12659, window-type=['NORMAL'], transient-for=None make_new_window(387, 625, 380, 64, 78, {'fullscreen': False, 'has-alpha': False, 'xid': '0xc078cf', \ 'pid': 12659, 'window-type': ['NORMAL'], 'maximized': False, 'override-redirect': True}, True, \ {'encodings.rgb_formats': ['RGB']}, 0)=<ClientWindow object at 0x7f9d18029140 \ (xpra+client+gtk2+client_window+ClientWindow at 0x3f034e0)>, group_leader_window=None window_state_updated(<ClientWindow object at 0x7f9d18029140 \ (xpra+client+gtk2+client_window+ClientWindow at 0x3f034e0)>, <gtk.gdk.Event at 0x3ec2cb0: GDK_WINDOW_STATE>) \ wid=387, new_window_state=<flags 0 of type GdkWindowState>, fullscreen=False, maximized=False processing packet draw add_packet_to_queue(damage-sequence ...) processing packet draw add_packet_to_queue(damage-sequence ...) add_packet_to_queue(button-action ...) add_packet_to_queue(pointer-position ...)
- OSX client:
add_packet_to_queue(button-action ...) processing packet new-override-redirect init_window(..) make_new_window: pid=12659, window-type=['NORMAL'], transient-for=None forcing utility window forcing transient for 213 make_new_window(393, 783, 328, 64, 78, {'fullscreen': False, 'has-alpha': False, 'xid': '0xc0a27a', \ 'pid': 12659, 'window-type': ['UTILITY'], 'maximized': False, 'transient-for': 213, \ 'override-redirect': True}, True, {'encodings.rgb_formats': ['RGB']}, 0)=\ <ClientWindow object at 0x1922a5a8 (xpra+client+gtk2+client_window+ClientWindow at 0x7b4abc0)>, group_leader_window=None window_state_updated(<ClientWindow object at 0x1922a5a8 \ (xpra+client+gtk2+client_window+ClientWindow at 0x7b4abc0)>, <gtk.gdk.Event at 0x19219878: GDK_WINDOW_STATE>) \ wid=393, new_window_state=<flags 0 of type GdkWindowState>, fullscreen=False, maximized=False processing packet draw processing packet draw add_packet_to_queue(button-action ...) add_packet_to_queue(damage-sequence ...)
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].focused=False window[556].fullscreen=False window[556].has-alpha=False window[556].maximized=False window[556].override-redirect=True window[556].pid=12659 window[556].position=(815, 328) window[556].property.fullscreen=False window[556].property.scaling=(1, 1) window[556].scaling=(1, 1) window[556].size=(64, 78) window[556].suspended=False window[556].total_frames[png]=1 window[556].total_pixels[png]=4992 window[556].tray=False window[556].window-type=('NORMAL',) window[556].xid=0xc1b08e
And with Firefox, the only difference is the window-type
and transient-for
attributes we already know about:
window[559].focused=False window[559].fullscreen=False window[559].has-alpha=False window[559].maximized=False window[559].override-redirect=True window[559].pid=17672 window[559].position=(590, 449) window[559].property.fullscreen=False window[559].property.scaling=(1, 1) window[559].scaling=(1, 1) window[559].size=(64, 86) window[559].suspended=False window[559].total_frames[png]=6 window[559].total_pixels[png]=33024 window[559].transient-for=407 window[559].tray=False window[559].window-type=('UTILITY',) window[559].xid=0xe0be43
So we must be setting attributes differently on the client side, maybe the main window and not the drop down window?
Changed 8 years ago by
Attachment: | focus-force-transientfor.patch added |
---|
patch including all the different changes that were tested - works!
Changed 8 years ago by
Attachment: | focus-force-transientfor-v4.patch added |
---|
trimmed down patch which forces transient-for and fixes focus behaviour on osx
Changed 8 years ago by
Attachment: | focus-force-transientfor-v5.patch added |
---|
better patch which tries to use the currently focused window as transient-for window (if possible)
comment:5 Changed 8 years ago by
Owner: | changed from Antoine Martin to J. Max Mena |
---|---|
Status: | assigned → new |
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:
- that it works
- that this does not cause any focus regressions elsewhere with OR windows (dialogs, popups, etc..)
comment:6 Changed 8 years ago by
Milestone: | 0.12 → 0.11 |
---|
comment:7 Changed 8 years ago by
comment:8 Changed 8 years ago by
Resolution: | → fixed |
---|---|
Status: | new → closed |
Tested in OSX (10.9) running r5178, seems to be working for now. Consistently has the drop-down menu appear at the top.
comment:9 Changed 8 years ago by
comment:10 Changed 8 years ago by
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!).
comment:11 Changed 7 years ago by
comment:12 Changed 5 years ago by
r15606 now forces the focus for initial windows (and this workaround is then disabled after 2 seconds).
We use activateIgnoringOtherApps as explained here: Python, Quartz, GTK, and window focus.
Maybe this workaround can help with #469?
comment:13 Changed 4 years ago by
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.
comment:14 Changed 17 months ago by
this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/490
menu has focus after click