#705 closed defect (fixed)
Java applications running with JDK6 or older can produce windows 1 pixel high / wide
Reported by: | Antoine Martin | Owned by: | Antoine Martin |
---|---|---|---|
Priority: | critical | Milestone: | 0.15 |
Component: | core | Version: | trunk |
Keywords: | Cc: | hd.akbarpour@… |
Description (last modified by )
Attached is a very simple test case.
export JAVA_HOME=/opt/jdk1.6 $JAVA_HOME/bin/javac Main.java $JAVA_HOME/bin/java Main
Click on the button and the dialog window appears correctly, close it and try again and it gets mapped as a 1 pixel high window..
I have tested many versions of Java, including the IBM SDK, opensdk, Sun's SDK, etc..
This only affects Java 6 and earlier. (which is the version supported in centos 5 and some centos 6 installations..)
r7959 added CreateNotify
support for X11 event logging since the window seemed to be configured wrong by the time we get notified.
- logging window creation the first time (correct - summary):
Reconfigure on withdrawn window (190,70) x_event_filter event=(None, 'child-map-request-event')/MapRequest window=0x16d Found a potential client new window 0xa0001e _read_initial_properties: geometry=(0, 0, 190, 70, 24) _update_client_geometry: using initial size=(190, 70) and position=(0, 0) _do_update_client_geometry: sanitized hints=WMSizeHints({'set_initial_position': True, 'win_gravity': 1}) Discovered new ordinary window: WindowModel(0xa0001e - " ") (geometry=(0, 0, 190, 70)) found transient_for=<gtk.gdk.Window object at 0x7f9c3c0923c0 (GdkWindow at 0x16f85a0)>, xid=0xa00007 new_window(new-window, WindowModel(0xa0001e - " "), 5, 0, 0, 190, 70, None) \ metadata={'opacity': -1, 'size-constraints': {'set-initial-position': True}, \ 'window-type': ['DIALOG'], 'client-machine': 'laptop', 'xid': '0xa0001e', \ 'title': ' ', 'transient-for': 4, 'icon-title': 'Java', 'pid': -1, 'group-leader-xid': 10485767} x_event_filter event=(None, 'child-map-request-event')/MapRequest took 29.4ms client configured window 5 - WindowModel(0xa0001e - " "), at: (0, 0, 190, 70)
- second time around (buggy):
Reconfigure on withdrawn window (1,1) x_event_filter event=(None, 'child-map-request-event')/MapRequest window=0x16d Found a potential client new window 0xa0002c _read_initial_properties: geometry=(0, 0, 1, 1, 24) _update_client_geometry: using initial size=(1, 1) and position=(0, 0) _do_update_client_geometry: sanitized hints=WMSizeHints({'set_initial_position': True, 'win_gravity': 1}) Discovered new ordinary window: WindowModel(0xa0002c - " ") (geometry=(0, 0, 1, 1)) found transient_for=<gtk.gdk.Window object at 0x7f9c3c0923c0 (GdkWindow at 0x16f85a0)>, xid=0xa00007 new_window(new-window, WindowModel(0xa0002c - " "), 6, 0, 0, 1, 1, None) \ metadata={'opacity': -1, 'size-constraints': {'set-initial-position': True}, \ 'window-type': ['DIALOG'], 'client-machine': 'laptop', 'xid': '0xa0002c', \ 'title': ' ', 'transient-for': 4, 'icon-title': 'Java', 'pid': -1, 'group-leader-xid': 10485767} x_event_filter event=(None, 'child-map-request-event')/MapRequest took 30.4ms client configured window 6 - WindowModel(0xa0002c - " "), at: (0, 0, 1, 1)
So the problem occurs very early on, when we read the window's initial dimensions.
It looks like Java is caching something (in one of its numerous hidden event windows?) which causes the new dialog window to inherit the wrong size. During a reparent maybe?
This obviously does not happen with other window managers, so we must be doing something wrong.
This ticket was originally recorded as a JOGL bug - but as can be seen in the example code, that was wrong, JOGL has nothing to do with it.
Attachments (4)
Change History (16)
comment:1 Changed 8 years ago by
Description: | modified (diff) |
---|---|
Owner: | changed from Antoine Martin to Antoine Martin |
Priority: | major → critical |
Status: | new → assigned |
Summary: | some JOGL windows get mapped incorrectly and appear blank or the wrong size → Java applications running with JDK6 or older can produce windows 1 pixel high |
comment:2 Changed 8 years ago by
Changed 8 years ago by
Attachment: | test-Xnest-twm.xtrace added |
---|
xtrace of the test application running under twm via Xnest
comment:3 Changed 8 years ago by
Summary: | Java applications running with JDK6 or older can produce windows 1 pixel high → Java applications running with JDK6 or older can produce windows 1 pixel high / wide |
---|
Interesting: by killing (kill -9
) the xpra server at various points and doing the other steps from a shadow copy with no window manager running, I have narrowed down the problem to the mapping of the initial 2 windows:
- if xpra maps the main window and the dialog window at least once, the bug will occur afterwards, even with twm or no window manager
- if xpra only maps just the main window, or the just the first dialog window but not the main window, the bug does not occur!
I also found a ticket which looks very similar: JOSM starts as few pixel width window. - but the resolution does not apply here.
comment:4 Changed 8 years ago by
Comparing the two xtraces, edited from the moment of the button release that creates the new dialog window:
twm does:
000:<:0365: 56: Request(1): CreateWindow depth=0x18 window=0x00600029 parent=0x00000025 \ x=0 y=0 width=200 height=71 border-width=0 class=InputOutput(0x0001) \ visual=0x00000020 value-list={border-pixel=0x00000000 bit-gravity=NorthWest(0x01) \ backing-store=NotUseful(0x00) override-redirect=false(0x00) \ event-mask=ButtonPress,ButtonRelease,EnterWindow,LeaveWindow,PointerMotion,ButtonMotion,Exposure,VisibilityChange,StructureNotify,PropertyChange,OwnerGrabButton \ colormap=0x00000021} 000:<:0366: 28: Request(18): ChangeProperty mode=Replace(0x00) window=0x00600029 property=0x27("WM_NAME") type=0x1f("STRING") data=' ' (..) 000:>:0370:44: GetWindowAttributes: (..) map-is-installed=true(0x01) map-state=Unmapped(0x00) override-redirect=false(0x00) 000:>:0371:32: Reply to GetGeometry: depth=0x18 root=0x00000025 x=0 y=0 width=200 height=71 border-width=0 (..) 000:<:0383: 48: Request(1): CreateWindow depth=0x18 window=0x0060002f parent=0x00000025 \ x=0 y=0 width=16 height=16 border-width=0 class=InputOutput(0x0001) visual=0x00000020 \ value-list={background-pixmap=0x0060002b border-pixel=0x00000020 event-mask=PropertyChange,OwnerGrabButton colormap=0x00000021} 000:<:0384: 48: Request(18): ChangeProperty mode=Replace(0x00) window=0x0060002f property=0x27("WM_NAME") type=0x1f("STRING") \ data='sun-awt-X11-XIconWindow' (..) 000:<:0389: 60: Request(18): ChangeProperty mode=Replace(0x00) window=0x00600029 property=0x23("WM_HINTS") type=0x23("WM_HINTS") \ data=0x0000006c,0x00000000,0x00000000,0x0060002b,0x0060002f,0x00000000,0x00000000,0x0060002d,0x00600006; 000:<:038a: 96: Request(18): ChangeProperty mode=Replace(0x00) window=0x00600029 property=0x28("WM_NORMAL_HINTS") type=0x29("WM_SIZE_HINTS") \ data=0x0000020d,0x00000000,0x00000000,0x000000c8,0x00000047,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001; (..) 000:<:038b: 52: Request(1): CreateWindow depth=0x18 window=0x00600030 parent=0x00600029 \ x=0 y=-29 width=200 height=100 border-width=0 class=InputOutput(0x0001) \ visual=0x00000020 value-list={border-pixel=0x00000000 bit-gravity=NorthWest(0x01) \ backing-store=NotUseful(0x00) \ event-mask=KeyPress,KeyRelease,ButtonPress,ButtonRelease,EnterWindow,LeaveWindow,PointerMotion,ButtonMotion,Exposure,FocusChange,PropertyChange,OwnerGrabButton colormap=0x00000021} 000:<:038c: 40: Request(18): ChangeProperty mode=Replace(0x00) window=0x00600030 property=0x27("WM_NAME") type=0x1f("STRING") \ data='Content window' (..) 000:<:0392: 8: Request(8): MapWindow window=0x00600030 000:<:0393: 36: Request(1): CreateWindow depth=0x00 window=0x00600032 parent=0x00600029 \ x=-1 y=-1 width=1 height=1 border-width=0 class=InputOnly(0x0002) visual=CopyFromParent(0x00000000) \ value-list={event-mask=KeyPress,KeyRelease,SubstructureNotify,FocusChange,PropertyChange,OwnerGrabButton} 000:<:0394: 36: Request(18): ChangeProperty mode=Replace(0x00) window=0x00600032 property=0x27("WM_NAME") type=0x1f("STRING") \ data='FocusProxy' (..) 000:<:039a: 48: Request(1): CreateWindow depth=0x18 window=0x00600033 parent=0x00600030 \ x=0 y=0 width=1 height=1 border-width=0 class=InputOutput(0x0001) visual=0x00000020 \ value-list={border-pixel=0x00000000 backing-store=NotUseful(0x00) event-mask=KeyPress,KeyRelease,ButtonPress,ButtonRelease,EnterWindow,LeaveWindow,PointerMotion,ButtonMotion,Exposure,StructureNotify,FocusChange,PropertyChange,OwnerGrabButton \ colormap=0x00000021} 000:<:039b: 48: Request(18): ChangeProperty mode=Replace(0x00) window=0x00600033 property=0x27("WM_NAME") type=0x1f("STRING") \ data='sun-awt-X11-XButtonPeer' (..) 000:<:03a2: 28: Request(12): ConfigureWindow window=0x00600033 values={x=0 y=0 width=1 height=1} 000:<:03a3: 8: Request(8): MapWindow window=0x00600033 000:<:03a4: 8: Request(15): QueryTree window=0x00600030 000:>:03a4: Event MapNotify(19) event=0x00600033 window=0x00600033 override-redirect=false(0x00) 000:<:03a6: 28: Request(12): ConfigureWindow window=0x00600033 values={x=0 y=29 width=200 height=71} 000:>:03a8: Event ConfigureNotify(22) event=0x00600033 window=0x00600033 above-sibling=None(0x00000000) \ x=0 y=29 width=200 height=71 border-width=0 override-redirect=false(0x00) (..) 000:<:03b6: 16: Request(12): ConfigureWindow window=0x00600029 values={stack-mode=Above(0x00)} 000:<:03b7: 8: Request(8): MapWindow window=0x00600029 (..) 000:>:03b7: Event ReparentNotify(21) event=0x00600029 window=0x00600029 parent=0x004000a5 x=0 y=29 override-redirect=false(0x00) 000:>:03b7: Event (generated) ConfigureNotify(22) event=0x00600029 window=0x00600029 above-sibling=0x004000a5 x=2 y=31 width=200 height=71 border-width=0 override-redirect=false(0x00) 000:>:03b7: Event MapNotify(19) event=0x00600029 window=0x00600029 override-redirect=false(0x00) (..) 000:>:03b8: Event PropertyNotify(28) window=0x00600029 atom=0xf5("WM_STATE") time=0x07aa0198 state=NewValue(0x00) (..) 000:>:03b9:44: Reply to GetWindowAttributes: (..) map-is-installed=true(0x01) map-state=Viewable(0x02) override-redirect=false(0x00) (..) 000:>:03ba:32: Reply to GetGeometry: depth=0x18 root=0x00000025 x=0 y=0 width=200 height=100 border-width=2
Which can be translated as (verbs are as seen from the application context):
- create normal input/output window 0x00600029 named " " of size 200x71 which is a child of the root window 0x00000025 (it will be referred to as the "main window")
- create normal input/output window 0x0060002f named "sun-awt-X11-XIconWindow" of size 16x16 as a child of 0x00600029
- set
WM_HINTS
andWM_NORMAL_HINTS
on the main window - create normal input/output window 0x00600030 named "Content window" of size 200x100 as a child of the main window
- map "Content Window"
- create input only window 0x00600032 named "
FocusProxy
" of size 1x1 as a child of the main window - create normal input/output window 0x00600033 named "sun-awt-X11-XButtonPeer" of size 1x1 as a child of the "Content Window"
MapWindow
the "sun-awt-X11-XButtonPeer" (and theMapNotify
is duly received) - all still at size of 1x1, once mapped it is configured (and the configure notify is duly received) for the same position and size as the main window (its parent)- request that the main window is configured to be on top (stack above)
- request
MapWindow
the "main window" - the main window is reparented into 0x004000a5 (presumably twm's frame) at (0,29)
- the main window is configured above-sibling 0x004000a5, and with the same position (2,31) and dimensions (200x71) as before
- the main window is mapped and its WM_STATE" is set to normal
- query the window attributes and geometry on 0x004000a5 (its size is 200x100, it is
Viewable
, etc) - update the main window's normal hints
comment:5 Changed 8 years ago by
with xpra it does this:
- create normal input/output window 0x00800019 named " " which is a child of the root window 0x00000044 (this is the "main window")
- no
XIconWindow
window is created... (and I don't think we care about that - at least not for this bug, we'll see if window icons are missing with Java apps later) - set hints (as above)
- create normal input/output window 0x0080001b named "Content Window" of size 200x100 as a child of the main window above
- create the
FocusProxy
(0x0080001d) - create the
XButtonPeer
(0x0080001e) - map the button peer (as above)
- request that the main window is configured to be on top
- request
MapWindow
the "main window" - the main window is configured, but above-sibling is not set... (not honoured - we have no code for this)
- the main window is reparented into 0x0040012c, at (0,0) - we explicitly set it to (0,0) as the coordinates are meant to be relative?
- the main window is mapped and its WM_STATE is normal
- query the window attributes and geometry on 0x0040012c: its position is (0,0) still, is is
Viewable
, its size is OK (200x71) .. - odd configures event are seen for the main window: width=0, height=0 ! (maybe a response to the stack request?, which may have zero width and height.. or something)
Some of the configure requests aren't honoured, and some of those don't make much sense!
000:<:02b1: 20: Request(12): ConfigureWindow window=0x00800019 values={width=0 height=0} 000:<:02b2: 20: Request(12): ConfigureWindow window=0x00800019 values={x=0 y=0} 000:<:02b3: 28: Request(12): ConfigureWindow window=0x0080001b values={x=-4 y=-28 width=2370 height=1530 (..) 000:<:02b5: 28: Request(12): ConfigureWindow window=0x0080001b values={x=-4 y=-28 width=2560 height=1600} (..) 000:<:02b8: 28: Request(12): ConfigureWindow window=0x0080001e values={x=4 y=28 width=190 height=70}
000:>:02b9: Event ConfigureNotify(22) event=0x0080001e window=0x0080001e above-sibling=None(0x00000000) \ x=4 y=28 width=190 height=70 000:>:02ba: Event (generated) ClientMessage(33) format=0x20 window=0x00800019 type=0xea("WM_PROTOCOLS") \ data=0xeb,0x00,0x00,0x00,0xac,0x7e,0x62,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00;
Need to investigate:
- honour
stack-mode
inConfigureWindow
- when reparenting, preserve position instead of setting it to 0,0
- fix missing
ConfigureNotify
and weird dimensions..
comment:6 Changed 8 years ago by
Cc: | hd.akbarpour@… added |
---|
comment:7 Changed 8 years ago by
Attacking this from different angles:
- JDK versions:
after testing more JDK versions, openjdk6 builds do not have this problem! (tested with java-1.6.0-icedtea-1.13.2.x86_64
built from source using the icedtea SRPM)
So there must be a fix in icedtea / openjdk which solves this bug (relevant link: What is the difference between JVM, JDK, JRE & OpenJDK?). It is a rather large patch set unfortunately, and we don't have the source for the buggy Sun SDK...
No problems either with java-1.5.0-gcj.
Since there are a few tricks in the Java source code based on the window manager name, I added r8025 which allows us to easily set it (_NET_WM_NAME
on the ewmh window). Alternatively, wmname could be used for testing.
I've tried a few of them (LG3D
, Sawfish
, Compiz
) and this did not help.
I've also tried setting: AWT_TOOLKIT=MToolkit
- no change (wasn't really expecting it to work since we are a reparenting window manager), it did cause crashes with some of the window manager names. (in catgets
called from GetAllProtocolsMgr
- whatever this is, probably because it is not expecting us to reparent)
Useful information on this subject can be found here: http://awesome.naquadah.org/wiki/Problems_with_Java
This looks like it could be related: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6632124 and http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6429775, but we do set _NET_FRAME_EXTENTS
as early as we can already.
Also found a good reference for focus events: Java 6 Focus Spec.
- Logging from the Java side:
- create a
logging.properties
file withjava.util.logging.ConsoleHandler.level = FINE
in it - run the example code with:
java -Djava.util.logging.config.file=./logging.properties Main |& tee log
- create a
Then stripping the date+time from the debug output with:
sed -r 's/^.*:[0-9][0-9] //g' < log > nodate.log
And comparing the buggy one (sun jdk -) with the working version (openjdk +), I see:
- on startup:
-FINE: sun.awt.X11.XNETProtocol@6019d0a1:_NET_SUPPORTED:305 supports [256, 262, 261, _NET_WM_WINDOW_TYPE:260, 267, NET_SUPPORTING_WM_CHECK:271, 278, 279, 276, 277, 282, 283, _NET_WM_WINDOW_TYPE_DIALOG: 280, 281, 285, 303, 304, 35, _NET_SUPPORTED:305, 306, 307, 39, 308, 309, 37, 310, 36, 311, 312, WM_STATE:313, 314, 315, 40, 316, 317, 318, 319, 321, 320, 68, 67, NET_WM_STATE_SKIP_TASKBAR:255, _NET_WM_STATE_MAXIMIZED_VERT:253, _NET_WM_STATE_MODAL:252, _NET_WM_STATE_FULLSCREEN:251, _NET_WM_STATE:248, 246, _NET_WM_NAME:245, 244, 238, _NET_FRAME_EXTENTS:239, 237, 234] +FINE: sun.awt.X11.XNETProtocol@4917015d:_NET_SUPPORTED:305 supports [320, _NET_WM_STATE_HIDDEN:321, 68, 67, 244, _NET_WM_NAME:245, 246, _NET_WM_STATE_MODAL:252, _NET_WM_STATE_MAXIMIZED_VERT:253, _NET_WM_STATE_SKIP_TASKBAR:255, _NET_WM_STATE:248, _NET_WM_STATE_FULLSCREEN:251, 237, _NET_FRAME_EXTENTS:239, 238, 234, 267, _NET_SUPPORTING_WM_CHECK:271, _NET_WM_STATE_SKIP_PAGER:256, _NET_WM_WINDOW_TYPE:260, 261, 262, 281, _NET_WM_WINDOW_TYPE_DIALOG:280, 283, 282, 285, 277, 276, 279, 278, 303, 315, 40, 314, WM_STATE:313, 312, 319, 318, 317, 316, 307, 306, _NET_SUPPORTED:305, 304, 35, 36, 311, 37, 310, 309, 39, 308]
- the root window bounds (workspace usable area) is only detected properly by opensdk:
MaximumWindowBounds=java.awt.Rectangle[x=0,y=0,width=2560,height=1600] MaximumWindowBounds=java.awt.Rectangle[x=0,y=0,width=2560,height=1560] ScreenInsets=java.awt.Insets[top=0,left=0,bottom=0,right=0] ScreenInsets=java.awt.Insets[top=0,left=0,bottom=40,right=0]
mixOnHiding
/isMixingNeeded
- frame extents:
-sun.awt.X11.XNETProtocol requestWMExtents -FINE: Requesting NET_WM_EXTENTS +sun.awt.X11.XWM requestWMExtents +FINE: Requesting FRAME_EXTENTS
- quite a few "containing window" get logged because opensdk lacks disposing = false at the end of the line...
XConfigureEvent
also logged because it includes thesun.awt.X11.XFramePeer
object address...- when creating the dialog, opensdk logs:
reparented: false
- so it looks like there is code in there to deal with reparenting.. - what is this for?
+FINE: Unhandled XErrorEvent: id=10485789, serial=724, ec=8, rc=42, mc=0 +FINE: Unhandled XErrorEvent: id=10485795, serial=443, ec=8, rc=42, mc=0
- looks like some calculations are off:
-FINE: Initial dimensions [java.awt.Point[x=0,y=0], java.awt.Dimension[width=2370,height=1530](bounds)+java.awt.Insets[top=28,left=4,bottom=1502,right=2366]] +FINE: Initial dimensions [java.awt.Point[x=0,y=0], java.awt.Dimension[width=200,height=100](bounds)+java.awt.Insets[top=25,left=5,bottom=5,right=5]] (..) -FINE: this = java.awt.Button[button1,4,28,-2170x-1430,invalid,label=Close]; areBoundsValid = false +FINE: this = java.awt.Button[button1,5,25,190x70,invalid,label=Close]; areBoundsValid = false
Looks like something is calculating based on the screen size, and getting it badly wrong!
Changed 8 years ago by
Attachment: | jdk-vs-openjdk.log added |
---|
diff between broken and working debug log
comment:8 Changed 8 years ago by
Found this in the Java patch nomotif-6706121.patch
- worth a read:
Unfortunately the concept of "insets" borrowed to AWT from Win32 is *absolutely*, *unbelievably* foreign to X11. Few WMs provide the size of frame decor (i.e. insets) in a property they set on the client window, so we check if we can get away with just peeking at it. [Future versions of wm-spec might add a standardized hint for this].
Otherwise we do some special casing. Actually the fallback code ("default" case) seems to cover most of the existing WMs (modulo Reparent/Configure? order perhaps?).
Fallback code tries to account for the two most common cases:
- single reparenting parent window is the WM frame [twm, olwm, sawfish]
- double reparenting parent is a lining exactly the size of the client grandpa is the WM frame [mwm, e!, kwin, fvwm2 ... ]
This code is absolutely horrible, no wonder they refactored it in JDK 7!
See also JDK bug 4304985: Frame opening fails to restore location
I think what is happening is that the code checks for the parent size, finds it is the same as the window (because we don't have any window decorations on the server!) and assumes that the real window frame has to be the grand parent... which is the root window, and it is huge which causes the crazy large inset calculations.
Setting the window manager as Sawfish
seems to fix this problem!
(makes Java assume single-reparenting behaviour)
Run xpra as of r8033 (will backport the important bits):
XPRA_NET_WM_NAME=Sawfish xpra start ...
Keeping this ticket open as we may want to find a cleaner solution, one that does not involve lying about our window manager name!
Changed 8 years ago by
updated test class which also dumps information about the graphics context
comment:9 Changed 8 years ago by
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
Backport in r8061. Closing.
comment:10 Changed 8 years ago by
comment:11 Changed 7 years ago by
comment:12 Changed 17 months ago by
this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/705
I have also tried:
xwininfo -root -tree
first and second run (no significant change)So... that leaves tracing the X11 calls done by twm and comparing with xpra's. Oh joy.