Update of absolute positions in Tk windows not working with Xwayland (Menu opened at wrong location)
When using TK applications together with weston and Xwayland, menus pop up at the wrong location. TK seems to use absolute positions to calculate the menu location on the screen.
I've traced this issue down to be a general issue with obtaining the correct absolute root position of a widget from within TK, even for the root window.
In weston, the XWM window-manager.c
method send_position()
seems to be
responsible for setting the right position on Xserver/Xwayland side.
When invoked by a wayland shell, send_position()
emits an
xcb_configure_window()
call on the current window's frame with the absolute
coordinates it received.
This way the frame (handled by the weston WM) gets updated, but there is nothing that would trigger an update of the actual window in which my TK application runs in. Thus this does not get notified about the updated coordinates.
Under pure X, this works however and I can see events in the xtrace (and Tk tracing) output of Tk like
000:>:00c5: Event (generated) ConfigureNotify(22) event=0x03e00004 window=0x03e00004 above-sibling=None(0x00000000) x=3097 y=620 width=200 height=200 border-width=0 override-redirect=false(0x00)
ConfigureEvent: . x = 3097 y = 620, width = 200, height = 200
send_event = 1, serial = 197 (win 0x1eacac0, wrapper 0x1ff0800)
. parent == 0x401d36, above (nil)
000:<:00c6: 4: Request(127): NoOperation
000:<:00c7: 16: Request(40): TranslateCoordinates src-window=0x03e00004 dst-window=0x00401d36 src-x=0 src-y=0
000:>:00c7:32: Reply to TranslateCoordinates: same-screen=true(0x01) child=0x03e00004 dst-x=2 dst-y=0
000:<:00c8: 8: Request(14): GetGeometry drawable=0x00401d36
000:>:00c8:32: Reply to GetGeometry: depth=0x18 root=0x000001a0 x=3095 y=620 width=204 height=202 border-width=0
wrapperPtr 0x1ff0800 coords 3097,620
wmPtr 0x1eac8c0 coords 3095,620, offsets 2 0
where 0x03e00004
is directly my Tk window.
Und weston, there is no such event received when moving.
The hack I tried to work around this is calling xcb_configure_window()
on the
Tk window instead. However, this does not work because of multiple reasons:
- if the position of the frame is not updated, an update of the window inside will still not give the recent position in TK Thus one needs to set the frame position first and then the window position.
- The x/y position that needs to be set for the application window is set with coordinates relative to the frame. But as this does not really change the X/ position, the Xwayland's dxi code simply drops the received ConfigNotify events.
- Sending calculated absolute coordinates to the window leads to broken placement of it.
Questions that arise on my side are:
- Are my findings correct?
- Is it possible to call xcb_configure_window() with absolute coordinates?
- May I enforce Xwayland to not drop a configure event with non-changing coordinates?
- Is doing this in send_position() the actually right approach? Or should this be done somehow automatically when receiving XCB_CONFIGURE_NOTIFY from the frame?
Reproducing
I can simply reproduce this behavior on any desktop with
weston --xwayland --debug --logger-scopes=xwm-wm-x11
and running this python application from an opened weston-terminal
#!/usr/bin/env python3
from tkinter import *
window=Tk()
def timer():
print( "widget pos: {},{}".format(window.winfo_rootx(), window.winfo_rooty()) )
window.after(1000, timer)
window.tk.eval("wm tracing true")
window.title('Hello Python')
window.after(1000, timer)
window.mainloop()
with
xtrace --timestamps -n ./example.py
Then you can move the window and see that the position is not updated.
Note that it will however update position when resizing or maximizing/minimizing the frame as this also generates config changes of the window (width/height) but also then the absolute position is not correct as it is not the recent one but the previous one.