Skip to content
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

Java Window Drift #1975

Closed
totaam opened this issue Oct 2, 2018 · 4 comments
Closed

Java Window Drift #1975

totaam opened this issue Oct 2, 2018 · 4 comments

Comments

@totaam
Copy link
Collaborator

totaam commented Oct 2, 2018

Issue migrated from trac ticket # 1975

component: server | priority: major | resolution: wontfix

2018-10-02 18:21:57: mjharkin created the issue


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]

@totaam
Copy link
Collaborator Author

totaam commented Oct 2, 2018

2018-10-02 18:22:26: mjharkin uploaded file WindowDrift.zip (10.5 KiB)

Sample jar and source

@totaam
Copy link
Collaborator Author

totaam commented Oct 3, 2018

2018-10-03 07:50:02: antoine changed status from new to closed

@totaam
Copy link
Collaborator Author

totaam commented Oct 3, 2018

2018-10-03 07:50:02: antoine commented


-d geometry,metadata log output (edited):

  • window created and picked up by the server:
Window.read_initial_X11_properties()
WM_PROTOCOLS=['WM_DELETE_WINDOW', 'WM_TAKE_FOCUS']
WM_CLASS=('sun-awt-X11-XFramePeer', 'MainWindow')
wm_hints.input = 0
WM_NORMAL_HINTS={u'position': (100, 100), u'win_gravity': 1, u'size': (440, 270)}
initial X11 position and size: requested((100, 100, 440, 270), \
    {u'position': (100, 100), 'gravity': 1, u'size': (440, 270)})=(100, 100, 440, 270)
setup() hints={u'position': (100, 100), 'gravity': 1, u'size': (440, 270)} size=440x270
updateprop(geometry, (100, 100, 440, 270)) unchanged
setup() resizing windows to 440x270
  • client receives the window packet:
client @31.600 process_new_common: [2, 100, 100, 440, 270, {\
    b'size-constraints': {b'position': (100, 100), b'gravity': 1, b'size': (440, 270)}, \
    b'window-type': (b'NORMAL',), b'xid': b'0xe00007', b'decorations': 1, b'title': b' ', \
    b'icon-title': b'Java', b'class-instance': (b'sun-awt-X11-XFramePeer', b'MainWindow'), \
    b'client-machine': b'desktop', b'pid': 5660, b'set-initial-position': True
    }], \
    metadata={
        b'size-constraints': {b'position': (100, 100), b'gravity': 1, b'size': (440, 270)}, \
        b'window-type': (b'NORMAL',), b'xid': b'0xe00007', \
        b'decorations': 1, b'title': b' ', b'icon-title': b'Java', \
        b'class-instance': (b'sun-awt-X11-XFramePeer', b'MainWindow'), \
        b'client-machine': b'desktop', b'pid': 5660, b'set-initial-position': True}, \
    OR=False
  • java updates the window hints:
Property changed on 0xe00007: WM_NORMAL_HINTS
WM_NORMAL_HINTS={u'position': (100, 100), u'win_gravity': 1, u'size': (450, 263)}
updateprop(size-hints, {u'position': (100, 100), 'gravity': 1, u'size': (450, 263)}) \
    previous value={u'position': (100, 100), 'gravity': 1, u'size': (440, 270)}
XpraServer._window_resized_signaled(WindowModel(0xe00007),(<GParamBoxed 'geometry'>,)) \
    geometry=(100, 100, 450, 263), desktop manager geometry=[100, 100, 440, 270]

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)
  • meanwhile the client has set up the window with the original size (440x270), adjusting the position for the window frame size:
client @31.610 setup_window() position=(100, 100), set_initial_position=True, OR=False, decorated=True
client @31.610 setup_window() window frame sizes={'frame': (0, 0, 37, 0), 'offset': (0, 37)}
client @31.611 setup_window() adjusted initial position=(100, 63)

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)

  • meanwhile the client receives the changed size:
_process_window_move_resize[2, 100, 100, 450, 263, 1] moving / resizing window \
    GLClientWindow(2 : gtk3.GLDrawingArea(2, (440, 270), None)) (id=2) to (100, 100, 450, 263)
window 2 move_resize(100, 100, 450, 263, 450)
unchanged position 100x100, using resize(450, 263)
resize(450, 263, 0) current size=(440, 270), fullscreen=None, maximized=False

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.


  • window gets unmapped, we clean it up:
scrub_x11() x11 properties=['WM_STATE', '_NET_FRAME_EXTENTS', '_NET_WM_ALLOWED_ACTIONS']

  • it gets mapped again, this time the hints contain:
WM_NORMAL_HINTS={u'position': (100, 63), u'win_gravity': 1, u'size': (450, 263)}
initial X11 position and size: requested((100, 63, 450, 263), \
    {u'position': (100, 63), 'gravity': 1, u'size': (450, 263)})=(100, 63, 450, 263)

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 #705#comment:8).

@totaam totaam closed this as completed Oct 3, 2018
@totaam
Copy link
Collaborator Author

totaam commented Oct 3, 2018

2018-10-03 09:42:49: mjharkin commented


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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant