Alan,
No, I’m not currently set up to test OpenJDK PR’s on other platforms.
I’m fuzzy on exactly what happens automatically in an OpenJDK PR. Are my
new unit tests automatically run on a variety of platforms? (That is:
are my new unit tests part of what executes here
<https://github.com/mickleness/jdk/actions/runs/5197802507/jobs/9386648003>?
Or does that skip several UI-based unit tests?)
I do have a Windows machine, but IIRC setting up OpenJDK to build on my
Mac was difficult, and I don’t want to go through that again on Windows
unless I really have to.
- Jeremy
------ Original Message ------
From "Alan Snyder" <[email protected]>
To "Jeremy" <[email protected]>
Cc [email protected]
Date 6/7/23, 2:06:23 PM
Subject Re: RFR: JDK-8303950: [macos]Translucent Windows Flicker on
Repaint
Are you able to test on platforms other than macOS? (I’m not, so I can’t help
with that.)
Alan
On Jun 7, 2023, at 10:53 AM, Jeremy <[email protected]> wrote:
# Problem Summary
For non-opaque windows, Window#paint calls `gg.fillRect(0, 0, getWidth(),
getHeight())` before `super.paint(g)`.
This can cause flickering on Mac, and the flickering seems to have gotten much
worse in recent JVMs. (See movie attachments to original ticket.)
# Discussion
This is my 2nd PR for this ticket. The original is
[here](https://github.com/openjdk/jdk/pull/12993); that proposed change was IMO
more invasive/scarier. It was auto-closed after 8 weeks of inactivity, and I'd
rather offer this PR instead.
In that previous discussion Alan Snyder framed the core problem as a "lack of
synchronization" (see [comment
here](https://github.com/openjdk/jdk/pull/12993#issuecomment-1467528061)). If the monitor
refreshes/flushes after we've called `fillRect` *but before we finish `super.paint`*: it
makes sense that we'd see a flicker.
I agree with Alan, but I think the problem can also be framed as a
mixing-Swing-with-AWT issue. (Which IMO will involve an easier fix.)
This PR is a low-risk change (relative to the previous PR) that intercepts
calls to repaint a Window that is also RootPaneContainer. Now we'll redirect
those calls to paint the JRootPane instead. This means we'll exclusively paint
within Swing's/RepaintManager's double-buffered architecture, so we bypass the
risky call to `fillRect` on the screen's Graphics2D. (And this change occurs
within RepaintManager, so we're clearly already in Swing's architecture.)
So with this change: we paint everything to the double-buffer, and the *only
time* we paint to the Window's Graphics2D is when have set up a
AlphaComposite.Src and replace its contents with our buffer's contents.
# Tests
This PR includes a new test for 8303950 itself. This is pretty
self-explanatory: we repaint a trivial animation for a few seconds and use the
Robot to see if a pixel is the expected color.
This PR also includes a test called `bug8303950_legacyWindowPaintBehavior`
that creates a grid of 4 windows with varying opacity/backgrounds:
<img width="805" alt="image"
src="https://github.com/openjdk/jdk/assets/7669569/497c21a0-ed18-413f-a5c7-3ea146644fd6">
I was surprised by how these windows rendered, but I don't think that's worth debating
here. This test simply makes sure that we preserve this preexisting behavior. The broad
"rules" appear to be:
1. If a JComponent identifies as opaque (see `JComponent.isOpaque`) then the
JComponent's background is used. (In this case: that's the opaque green top two
windows.) This is probably coming from `ComponentUI.update`
2. If a JRootPane has a translucent background, that color "wins". It doesn't
composite on top of a window's translucent background: it simply *replaces* it. (See the
blue-ish bottom-right window. Note it's blue -- not purple.) This is probably because the
RepaintManager uses `AlphaComposite.Src` in a couple of places to replace its destination
Graphics.
3. If a JRootPane has a null background color, then the Window's background
color paints as expected. (See the red-ish bottom-left window.)
-------------
Commit messages:
- 8303950: working on occasional unit failures
- 8303950: avoid System.exit(1)
- 8303950: adding opaque white window under test windows
- 8303950: this resolves bug8303950 by adding special RootPaneContainer
behavior
- 8303950: adding unit test for legacy window behavior
- 8303950: fixing false negative
- 8303950: adding failing test to identify problem
- Merge pull request #4 from openjdk/master
- Merge pull request #3 from openjdk/master
- Merge pull request #2 from openjdk/master
- ... and 1 more: https://git.openjdk.org/jdk/compare/98a7a60f...37834391
Changes: https://git.openjdk.org/jdk/pull/14363/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=14363&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8303950
Stats: 409 lines in 3 files changed: 407 ins; 1 del; 1 mod
Patch: https://git.openjdk.org/jdk/pull/14363.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/14363/head:pull/14363
PR: https://git.openjdk.org/jdk/pull/14363