Xpra: Ticket #1975: Java Window Drift

Server on Centos7 r20582 Client both Python and HTML on Windows r20582 Can't reproduce outside Xpra.

While looking for a good test case for #1974 I found this.

Install java and run:

java -jar windowDrift.jar

The window has set initial bounds (100,y=100,width=450,height=300) that don't change through the java code or user input but the window moves from these bounds. The only change in code is the window toggles visibility every 5 seconds.

sh-4.2$ java -jar windowDrift.jar
Window bounds: java.awt.Rectangle[x=100,y=100,width=450,height=300]
Window bounds: java.awt.Rectangle[x=92,y=69,width=450,height=300]
Window bounds: java.awt.Rectangle[x=84,y=38,width=450,height=300]
Window bounds: java.awt.Rectangle[x=84,y=38,width=450,height=300]
Window bounds: java.awt.Rectangle[x=76,y=7,width=450,height=300]
Window bounds: java.awt.Rectangle[x=76,y=7,width=450,height=300]

Expected output:

Window bounds: java.awt.Rectangle[x=100,y=100,width=450,height=300]
Window bounds: java.awt.Rectangle[x=100,y=100,width=450,height=300]
Window bounds: java.awt.Rectangle[x=100,y=100,width=450,height=300]
Window bounds: java.awt.Rectangle[x=100,y=100,width=450,height=300]
Window bounds: java.awt.Rectangle[x=100,y=100,width=450,height=300]
Window bounds: java.awt.Rectangle[x=100,y=100,width=450,height=300]
Window bounds: java.awt.Rectangle[x=100,y=100,width=450,height=300]
Window bounds: java.awt.Rectangle[x=100,y=100,width=450,height=300]


Tue, 02 Oct 2018 17:22:25 GMT - Mark Harkin: attachment set

Sample jar and source


Wed, 03 Oct 2018 06:50:01 GMT - Antoine Martin: status changed; resolution set

-d geometry,metadata log output (edited):

we ignore the update on the corral window since it is not visible yet:

WindowModel.do_xpra_configure_event: corral window is not visible
_do_update_client_geometry: allocated 440x270 (from <function window_size at 0x7ff7083ce6e0>)
_do_update_client_geometry: size({u'position': (100, 100), 'gravity': 1, u'size': (450, 263)})=440x270
_do_update_client_geometry: position=100x100 (from <function window_position at 0x7ff7083ce848>)
updateprop(geometry, (100, 100, 440, 270)) unchanged

anyway, we process the resize (450x263) on the client window:

do_child_configure_request_event(<X11:ConfigureRequest {\
    'delivered_to': u'0x40003c', 'send_event': '0', 'type': '23', 'detail': '0', \
    'height': '263', 'width': '450', 'window': u'0xe00007', 'above': '0', 'y': '0', 'x': '0', \
    'serial': '0xb48', 'border_width': '0', 'value_mask': '12', 'display': ':15'}>) \
    client=0xe00007, corral=0x40003c, value_mask=Width|Height, \
    size-hints={u'position': (100, 100), 'gravity': 1, u'size': (450, 263)}
updateprop(requested-size, (450, 263)) previous value=(440, 270)
updateprop(geometry, (100, 100, 450, 263)) previous value=(100, 100, 440, 270)

and it sends back a configure packet to the server with this size (440x270):

_process_configure_window([2, 100, 100, 440, 270, {\
    'encoding.scrolling': True, 'encoding.transparency': False, \
    'encodings.rgb_formats': ('YUV420P', 'YUV422P', 'YUV444P', 'GBRP', 'BGRA', 'BGRX', 'RGBA', 'RGBX', 'RGB', 'BGR'), \
    'encoding.full_csc_modes': {'mpeg1': ('YUV420P',), 'mpeg2': ('YUV420P',), '...',)}, \
    'encoding.bit-depth': 24
    }, 0, {}, False, 2, (1776, 1368), ('mod2',)]) old window geometry: (100, 100, 450, 263)

(edited: first run returns 100,100 for position) And the server honours this (older) size value:

updateprop(geometry, (100, 100, 440, 270)) previous value=(100, 100, 450, 263)

The server figures out that the client already uses this value and doesn't send another resize to it. (which would create a resize loop)

And tells the server when it's done:

_process_configure_window([2, 100, 100, 450, 263, {}, 0, {}, False, 2, (1777, 1367), ('mod2',)]) old window geometry: (100, 100, 440, 270)

By this (convoluted) point, the position and size are "correct" on both the client and server.



Java is clearly trying to adjust for the window frame size which is set at 27 for my client's DE.

And sure enough, by making the _NET_FRAME_EXTENTS (#919) feature disabled using r20594 then Java maps the window at a different offset:

Window bounds: java.awt.Rectangle[x=100,y=100,width=450,height=300]
Window bounds: java.awt.Rectangle[x=95,y=75,width=450,height=300]
Window bounds: java.awt.Rectangle[x=95,y=75,width=440,height=270]
Window bounds: java.awt.Rectangle[x=95,y=75,width=440,height=270]
Window bounds: java.awt.Rectangle[x=95,y=75,width=440,height=270]
Window bounds: java.awt.Rectangle[x=95,y=75,width=440,height=270]

It is probably guessing the window offsets, using something like (5,25,5,5).

And that's all I've got time for. Java is a mess, full of ugly hacks: http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/solaris/classes/sun/awt/X11/XWM.java and it's not the first time it gets it wrong: #725 (in particular ticket:705#comment:8).


Wed, 03 Oct 2018 08:42:49 GMT - Mark Harkin:

Thanks.That explains a lot, had no idea how ugly this was. The link to the java source helped, after a quick test setting:

wm-name=NO WM
env=XPRA_FRAME_EXTENTS=False

It improves the result but still moving after some time. I'll look into it further if I've time.


Sat, 23 Jan 2021 05:38:48 GMT - migration script:

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