Merge
This commit is contained in:
commit
19ce23c645
@ -1705,7 +1705,7 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n
|
||||
// pre-loop, the main-loop may not execute at all. Later in life this
|
||||
// zero-trip guard will become the minimum-trip guard when we unroll
|
||||
// the main-loop.
|
||||
Node *min_opaq = new OpaqueZeroTripGuardNode(C, limit);
|
||||
Node *min_opaq = new OpaqueZeroTripGuardNode(C, limit, b_test);
|
||||
Node *min_cmp = new CmpINode(pre_incr, min_opaq);
|
||||
Node *min_bol = new BoolNode(min_cmp, b_test);
|
||||
register_new_node(min_opaq, new_pre_exit);
|
||||
@ -1994,7 +1994,7 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree* loop, Node_List& old_new,
|
||||
// (the previous loop trip-counter exit value) because we will be changing
|
||||
// the exit value (via additional unrolling) so we cannot constant-fold away the zero
|
||||
// trip guard until all unrolling is done.
|
||||
Node *zer_opaq = new OpaqueZeroTripGuardNode(C, incr);
|
||||
Node *zer_opaq = new OpaqueZeroTripGuardNode(C, incr, main_end->test_trip());
|
||||
Node *zer_cmp = new CmpINode(zer_opaq, limit);
|
||||
Node *zer_bol = new BoolNode(zer_cmp, main_end->test_trip());
|
||||
register_new_node(zer_opaq, new_main_exit);
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "opto/node.hpp"
|
||||
#include "opto/opcodes.hpp"
|
||||
#include "subnode.hpp"
|
||||
|
||||
//------------------------------Opaque1Node------------------------------------
|
||||
// A node to prevent unwanted optimizations. Allows constant folding.
|
||||
@ -72,9 +73,16 @@ class OpaqueLoopStrideNode : public Opaque1Node {
|
||||
|
||||
class OpaqueZeroTripGuardNode : public Opaque1Node {
|
||||
public:
|
||||
OpaqueZeroTripGuardNode(Compile* C, Node *n) : Opaque1Node(C, n) {
|
||||
// This captures the test that returns true when the loop is entered. It depends on whether the loop goes up or down.
|
||||
// This is used by CmpINode::Value.
|
||||
BoolTest::mask _loop_entered_mask;
|
||||
OpaqueZeroTripGuardNode(Compile* C, Node* n, BoolTest::mask loop_entered_test) :
|
||||
Opaque1Node(C, n), _loop_entered_mask(loop_entered_test) {
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
virtual uint size_of() const {
|
||||
return sizeof(*this);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------Opaque3Node------------------------------------
|
||||
|
@ -1683,6 +1683,13 @@ void PhaseIterGVN::add_users_to_worklist( Node *n ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (use->Opcode() == Op_OpaqueZeroTripGuard) {
|
||||
assert(use->outcnt() <= 1, "OpaqueZeroTripGuard can't be shared");
|
||||
if (use->outcnt() == 1) {
|
||||
Node* cmp = use->unique_out();
|
||||
_worklist.push(cmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1901,6 +1908,7 @@ void PhaseCCP::push_more_uses(Unique_Node_List& worklist, Node* parent, const No
|
||||
push_loadp(worklist, use);
|
||||
push_and(worklist, parent, use);
|
||||
push_cast_ii(worklist, parent, use);
|
||||
push_opaque_zero_trip_guard(worklist, use);
|
||||
}
|
||||
|
||||
|
||||
@ -2021,6 +2029,12 @@ void PhaseCCP::push_cast_ii(Unique_Node_List& worklist, const Node* parent, cons
|
||||
}
|
||||
}
|
||||
|
||||
void PhaseCCP::push_opaque_zero_trip_guard(Unique_Node_List& worklist, const Node* use) const {
|
||||
if (use->Opcode() == Op_OpaqueZeroTripGuard) {
|
||||
push_if_not_bottom_type(worklist, use->unique_out());
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------do_transform-----------------------------------
|
||||
// Top level driver for the recursive transformer
|
||||
void PhaseCCP::do_transform() {
|
||||
|
@ -596,6 +596,7 @@ class PhaseCCP : public PhaseIterGVN {
|
||||
static void push_load_barrier(Unique_Node_List& worklist, const BarrierSetC2* barrier_set, const Node* use);
|
||||
void push_and(Unique_Node_List& worklist, const Node* parent, const Node* use) const;
|
||||
void push_cast_ii(Unique_Node_List& worklist, const Node* parent, const Node* use) const;
|
||||
void push_opaque_zero_trip_guard(Unique_Node_List& worklist, const Node* use) const;
|
||||
|
||||
public:
|
||||
PhaseCCP( PhaseIterGVN *igvn ); // Compute conditional constants
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "opto/matcher.hpp"
|
||||
#include "opto/movenode.hpp"
|
||||
#include "opto/mulnode.hpp"
|
||||
#include "opto/opaquenode.hpp"
|
||||
#include "opto/opcodes.hpp"
|
||||
#include "opto/phaseX.hpp"
|
||||
#include "opto/subnode.hpp"
|
||||
@ -661,6 +662,47 @@ const Type *CmpINode::sub( const Type *t1, const Type *t2 ) const {
|
||||
return TypeInt::CC; // else use worst case results
|
||||
}
|
||||
|
||||
const Type* CmpINode::Value(PhaseGVN* phase) const {
|
||||
Node* in1 = in(1);
|
||||
Node* in2 = in(2);
|
||||
// If this test is the zero trip guard for a main or post loop, check whether, with the opaque node removed, the test
|
||||
// would constant fold so the loop is never entered. If so return the type of the test without the opaque node removed:
|
||||
// make the loop unreachable.
|
||||
// The reason for this is that the iv phi captures the bounds of the loop and if the loop becomes unreachable, it can
|
||||
// become top. In that case, the loop must be removed.
|
||||
// This is safe because:
|
||||
// - as optimizations proceed, the range of iterations executed by the main loop narrows. If no iterations remain, then
|
||||
// we're done with optimizations for that loop.
|
||||
// - the post loop is initially not reachable but as long as there's a main loop, the zero trip guard for the post
|
||||
// loop takes a phi that merges the pre and main loop's iv and can't constant fold the zero trip guard. Once, the main
|
||||
// loop is removed, there's no need to preserve the zero trip guard for the post loop anymore.
|
||||
if (in1 != NULL && in2 != NULL) {
|
||||
uint input = 0;
|
||||
Node* cmp = NULL;
|
||||
BoolTest::mask test;
|
||||
if (in1->Opcode() == Op_OpaqueZeroTripGuard && phase->type(in1) != Type::TOP) {
|
||||
cmp = new CmpINode(in1->in(1), in2);
|
||||
test = ((OpaqueZeroTripGuardNode*)in1)->_loop_entered_mask;
|
||||
}
|
||||
if (in2->Opcode() == Op_OpaqueZeroTripGuard && phase->type(in2) != Type::TOP) {
|
||||
assert(cmp == NULL, "A cmp with 2 OpaqueZeroTripGuard inputs");
|
||||
cmp = new CmpINode(in1, in2->in(1));
|
||||
test = ((OpaqueZeroTripGuardNode*)in2)->_loop_entered_mask;
|
||||
}
|
||||
if (cmp != NULL) {
|
||||
const Type* cmp_t = cmp->Value(phase);
|
||||
const Type* t = BoolTest(test).cc2logical(cmp_t);
|
||||
cmp->destruct(phase);
|
||||
if (t == TypeInt::ZERO) {
|
||||
return cmp_t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SubNode::Value(phase);
|
||||
}
|
||||
|
||||
|
||||
// Simplify a CmpU (compare 2 integers) node, based on local information.
|
||||
// If both inputs are constants, compare them.
|
||||
const Type *CmpUNode::sub( const Type *t1, const Type *t2 ) const {
|
||||
|
@ -153,6 +153,7 @@ public:
|
||||
virtual int Opcode() const;
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
virtual const Type *sub( const Type *, const Type * ) const;
|
||||
virtual const Type* Value(PhaseGVN* phase) const;
|
||||
};
|
||||
|
||||
//------------------------------CmpUNode---------------------------------------
|
||||
|
@ -34,7 +34,7 @@ import java.util.Objects;
|
||||
* Random Bit Generator).
|
||||
* <p>
|
||||
* According to
|
||||
* <a href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">
|
||||
* <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">
|
||||
* NIST Special Publication 800-90A Revision 1, Recommendation for Random
|
||||
* Number Generation Using Deterministic Random Bit Generators</a> (800-90Ar1),
|
||||
* <blockquote>
|
||||
|
@ -43,7 +43,7 @@ import java.util.regex.Pattern;
|
||||
*
|
||||
* <p>A cryptographically strong random number minimally complies with the
|
||||
* statistical random number generator tests specified in
|
||||
* <a href="http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.140-2.pdf">
|
||||
* <a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.140-2.pdf">
|
||||
* <i>FIPS 140-2, Security Requirements for Cryptographic Modules</i></a>,
|
||||
* section 4.9.1.
|
||||
* Additionally, {@code SecureRandom} must produce non-deterministic output.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -366,6 +366,8 @@ public class DefaultCaret extends Rectangle implements Caret, FocusListener, Mou
|
||||
}
|
||||
}
|
||||
|
||||
private int savedBlinkRate = 0;
|
||||
private boolean isBlinkRateSaved = false;
|
||||
// --- FocusListener methods --------------------------
|
||||
|
||||
/**
|
||||
@ -379,8 +381,21 @@ public class DefaultCaret extends Rectangle implements Caret, FocusListener, Mou
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (component.isEnabled()) {
|
||||
if (component.isEditable()) {
|
||||
setVisible(true);
|
||||
if (isBlinkRateSaved) {
|
||||
setBlinkRate(savedBlinkRate);
|
||||
savedBlinkRate = 0;
|
||||
isBlinkRateSaved = false;
|
||||
}
|
||||
} else {
|
||||
if (getBlinkRate() != 0) {
|
||||
if (!isBlinkRateSaved) {
|
||||
savedBlinkRate = getBlinkRate();
|
||||
isBlinkRateSaved = true;
|
||||
}
|
||||
setBlinkRate(0);
|
||||
}
|
||||
}
|
||||
setVisible(true);
|
||||
setSelectionVisible(true);
|
||||
updateSystemSelection();
|
||||
}
|
||||
@ -1031,17 +1046,29 @@ public class DefaultCaret extends Rectangle implements Caret, FocusListener, Mou
|
||||
* @see Caret#setBlinkRate
|
||||
*/
|
||||
public void setBlinkRate(int rate) {
|
||||
if (rate < 0) {
|
||||
throw new IllegalArgumentException("Invalid blink rate: " + rate);
|
||||
}
|
||||
if (rate != 0) {
|
||||
if (flasher == null) {
|
||||
flasher = new Timer(rate, handler);
|
||||
if (component.isEditable()) {
|
||||
if (flasher == null) {
|
||||
flasher = new Timer(rate, handler);
|
||||
}
|
||||
flasher.setDelay(rate);
|
||||
} else {
|
||||
savedBlinkRate = rate;
|
||||
isBlinkRateSaved = true;
|
||||
}
|
||||
flasher.setDelay(rate);
|
||||
} else {
|
||||
if (flasher != null) {
|
||||
flasher.stop();
|
||||
flasher.removeActionListener(handler);
|
||||
flasher = null;
|
||||
}
|
||||
if (component.isEditable() && isBlinkRateSaved) {
|
||||
savedBlinkRate = 0;
|
||||
isBlinkRateSaved = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1053,6 +1080,9 @@ public class DefaultCaret extends Rectangle implements Caret, FocusListener, Mou
|
||||
* @see Caret#getBlinkRate
|
||||
*/
|
||||
public int getBlinkRate() {
|
||||
if (isBlinkRateSaved) {
|
||||
return savedBlinkRate;
|
||||
}
|
||||
return (flasher == null) ? 0 : flasher.getDelay();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8298176
|
||||
* @summary Must remove OpaqueZeroTripGuardPostLoop after main loop disappears else
|
||||
* the zero-trip-guard of the post loop cannot die and leaves an inconsistent
|
||||
* graph behind.
|
||||
* @run main/othervm -Xcomp -XX:-TieredCompilation
|
||||
* -XX:CompileCommand=compileonly,TestOpaqueZeroTripGuardPostLoopRemoval::test*
|
||||
* -XX:CompileCommand=dontinline,TestOpaqueZeroTripGuardPostLoopRemoval::*
|
||||
* TestOpaqueZeroTripGuardPostLoopRemoval
|
||||
*/
|
||||
|
||||
public class TestOpaqueZeroTripGuardPostLoopRemoval {
|
||||
static long x;
|
||||
|
||||
public static void main(String[] strArr) {
|
||||
test_001();
|
||||
test_002();
|
||||
try {
|
||||
test_003();
|
||||
} catch (Exception e) {
|
||||
// Expected
|
||||
}
|
||||
test_004();
|
||||
test_005();
|
||||
}
|
||||
|
||||
static void test_001() {
|
||||
int b = 6;
|
||||
for (long l = 1; l < 9; l++) {
|
||||
b++;
|
||||
}
|
||||
for (int i = 1; i < 1000; i*=2) {
|
||||
for (int j = 1; j < 2; j++) {
|
||||
x = b + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_002() {
|
||||
int b = 6;
|
||||
for (long l = 60; l < 3000; l+=3) {
|
||||
// bounds of loop: no work for post loop
|
||||
b += 33; // any multiple of iv step
|
||||
}
|
||||
for (int i = 1; i < 1000; i*=2) {
|
||||
for (int j = 1; j < 2; j++) {
|
||||
x = b + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dontInline() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
static int test_003() {
|
||||
int y = 3;
|
||||
for (int i = 0; i < 9; ) {
|
||||
for (long l = 1; l < 5; l++) {
|
||||
y *= 2;
|
||||
}
|
||||
while (true) {
|
||||
dontInline();
|
||||
}
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
static void test_004() {
|
||||
for (int i2 = 4; i2 < 13; i2++) {
|
||||
double d = 56;
|
||||
for (long l = 1; l < 5; l++) {
|
||||
d = d + 3;
|
||||
}
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int d2 = i2; d2 < 2; d2 = 3) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int test_005() {
|
||||
long arr[]=new long[400];
|
||||
for (int i = 3; i < 177; i++) {
|
||||
for (int j = 0; j < 10; j++){}
|
||||
}
|
||||
int y = 0;
|
||||
for (int i = 15; i < 356; i++) {
|
||||
// Inner loop prevents strip-mining of outer loop
|
||||
// later, inner loop is removed, so outer does pre-main-post without strip-mining
|
||||
for (int j = 0; j < 10; j++){
|
||||
y |= 1;
|
||||
}
|
||||
}
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
@ -659,8 +659,6 @@ javax/swing/JPopupMenu/6800513/bug6800513.java 7184956 macosx-all
|
||||
javax/swing/JTabbedPane/8007563/Test8007563.java 8051591 generic-all
|
||||
javax/swing/JTabbedPane/4624207/bug4624207.java 8064922 macosx-all
|
||||
javax/swing/SwingUtilities/TestBadBreak/TestBadBreak.java 8160720 generic-all
|
||||
javax/swing/text/DefaultCaret/HidingSelection/HidingSelectionTest.java 8194048 windows-all
|
||||
javax/swing/text/DefaultCaret/HidingSelection/MultiSelectionTest.java 8213562 linux-all
|
||||
javax/swing/JFileChooser/6798062/bug6798062.java 8146446 windows-all
|
||||
javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all,linux-all
|
||||
javax/swing/dnd/8139050/NativeErrorsInTableDnD.java 8202765 macosx-all,linux-all
|
||||
|
@ -126,6 +126,7 @@ jdk_util = \
|
||||
jdk_util_other = \
|
||||
java/util \
|
||||
sun/util \
|
||||
jdk/internal/util \
|
||||
-:jdk_collections \
|
||||
-:jdk_concurrent \
|
||||
-:jdk_stream
|
||||
|
150
test/jdk/java/awt/Graphics2D/DrawPrimitivesTest.java
Normal file
150
test/jdk/java/awt/Graphics2D/DrawPrimitivesTest.java
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, JetBrains s.r.o.. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @key headful
|
||||
* @bug 8287600 8291266 8299207
|
||||
* @requires os.family == "mac"
|
||||
* @summary [macosx] Some primitives do not render in metal pipeline
|
||||
* @run main DrawPrimitivesTest
|
||||
*/
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Robot;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
public abstract class DrawPrimitivesTest extends JFrame {
|
||||
private final static int W = 800;
|
||||
private final static int H = 800;
|
||||
private final static Color[] color = { Color.RED, Color.BLUE, Color.GREEN};
|
||||
private final static int COLOR_TOLERANCE = 10;
|
||||
private final CountDownLatch latchRender = new CountDownLatch(1);
|
||||
private volatile int frameX0 = 0;
|
||||
private volatile int frameY0 = 0;
|
||||
private final String name;
|
||||
|
||||
|
||||
private static boolean isAlmostEqual(Color c1, Color c2) {
|
||||
return Math.abs(c1.getRed() - c2.getRed()) < COLOR_TOLERANCE &&
|
||||
Math.abs(c1.getGreen() - c2.getGreen()) < COLOR_TOLERANCE &&
|
||||
Math.abs(c1.getBlue() - c2.getBlue()) < COLOR_TOLERANCE;
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException, AWTException, InvocationTargetException {
|
||||
new DrawPrimitivesTest("drawLine") {
|
||||
public void renderPrimitive(Graphics2D g2d, int x0, int y0, int w, int h) {
|
||||
g2d.drawLine(x0, y0, x0+w, y0+h);
|
||||
}
|
||||
}.runTest();
|
||||
|
||||
new DrawPrimitivesTest("fillRect") {
|
||||
public void renderPrimitive(Graphics2D g2d, int x0, int y0, int w, int h) {
|
||||
g2d.fillRect(x0, y0, w, h);
|
||||
}
|
||||
}.runTest();
|
||||
|
||||
new DrawPrimitivesTest("fillOvalAA") {
|
||||
public void renderPrimitive(Graphics2D g2d, int x0, int y0, int w, int h) {
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2d.fillOval(x0, y0, w, h);
|
||||
}
|
||||
}.runTest();
|
||||
}
|
||||
|
||||
public abstract void renderPrimitive(Graphics2D g2d, int x0, int y0, int w, int h);
|
||||
|
||||
public DrawPrimitivesTest(String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void runTest() throws InterruptedException, InvocationTargetException, AWTException {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
add(new JPanel() {
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(W, H);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
g2d.setColor(Color.YELLOW);
|
||||
int c = 0;
|
||||
for (int i = 0; i < W; i += 10) {
|
||||
for (int j = 0; j < H; j += 10) {
|
||||
c = (c + 1) % color.length;
|
||||
g2d.setColor(color[c]);
|
||||
renderPrimitive(g2d, i, j, 10, 10);
|
||||
}
|
||||
}
|
||||
Point p = getLocationOnScreen();
|
||||
frameX0 = p.x;
|
||||
frameY0 = p.y - getInsets().top;
|
||||
|
||||
latchRender.countDown();
|
||||
}
|
||||
});
|
||||
setPreferredSize(new Dimension(W, H));
|
||||
pack();
|
||||
setVisible(true);
|
||||
});
|
||||
|
||||
latchRender.await();
|
||||
Thread.sleep(1000);
|
||||
|
||||
Robot robot = new Robot();
|
||||
|
||||
boolean hasEmptyContent = true;
|
||||
l:for (int i = frameX0 + W/3; i < frameX0 + (2*W)/3; i++) {
|
||||
for (int j = 0; j < 10; j += 2) {
|
||||
if (isAlmostEqual(robot.getPixelColor(i, frameY0 + H / 2 + j), Color.RED)) {
|
||||
hasEmptyContent = false;
|
||||
break l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
setVisible(false);
|
||||
dispose();
|
||||
});
|
||||
|
||||
if (hasEmptyContent) {
|
||||
throw new RuntimeException(name + ": Empty content");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,10 +21,17 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Point;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -39,7 +46,6 @@ public class HidingSelectionTest {
|
||||
private static JTextField field1;
|
||||
private static JTextField field2;
|
||||
private static JFrame frame;
|
||||
private static Rectangle bounds;
|
||||
private static JMenu menu;
|
||||
private static JTextField anotherWindow;
|
||||
private static Point menuLoc;
|
||||
@ -67,17 +73,9 @@ public class HidingSelectionTest {
|
||||
Robot robot = new Robot();
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
bounds = field2.getBounds();
|
||||
bounds.setLocation(field2.getLocationOnScreen());
|
||||
});
|
||||
BufferedImage nosel = robot.createScreenCapture(bounds);
|
||||
|
||||
SwingUtilities.invokeAndWait(field2::requestFocus);
|
||||
SwingUtilities.invokeAndWait(field2::selectAll);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
BufferedImage sel = robot.createScreenCapture(bounds);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
menuLoc = menu.getLocationOnScreen();
|
||||
@ -89,7 +87,7 @@ public class HidingSelectionTest {
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (!biEqual(robot.createScreenCapture(bounds), sel)) {
|
||||
if (!field2.getCaret().isSelectionVisible()) {
|
||||
throw new RuntimeException("Test fails: menu hides selection");
|
||||
}
|
||||
|
||||
@ -98,7 +96,7 @@ public class HidingSelectionTest {
|
||||
SwingUtilities.invokeAndWait(field1::requestFocus);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (!biEqual(robot.createScreenCapture(bounds), nosel)) {
|
||||
if (field2.getCaret().isSelectionVisible()) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: focus lost doesn't hide selection");
|
||||
}
|
||||
@ -119,35 +117,12 @@ public class HidingSelectionTest {
|
||||
SwingUtilities.invokeAndWait(anotherWindow::requestFocus);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (biEqual(robot.createScreenCapture(bounds), nosel)) {
|
||||
if (!field2.getCaret().isSelectionVisible()) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: switch window hides selection");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(anotherWindow::selectAll);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (biEqual(robot.createScreenCapture(bounds), sel)) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: selection ownership is lost selection is shown");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(frame2::dispose);
|
||||
SwingUtilities.invokeLater(frame::dispose);
|
||||
}
|
||||
|
||||
static boolean biEqual(BufferedImage i1, BufferedImage i2) {
|
||||
if (i1.getWidth() == i2.getWidth() &&
|
||||
i1.getHeight() == i2.getHeight()) {
|
||||
for (int x = 0; x < i1.getWidth(); x++) {
|
||||
for (int y = 0; y < i1.getHeight(); y++) {
|
||||
if (i1.getRGB(x, y) != i2.getRGB(x, y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,10 +21,17 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Point;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -40,131 +47,113 @@ public class MultiSelectionTest {
|
||||
private static JTextField field1;
|
||||
private static JTextField field2;
|
||||
private static JFrame frame;
|
||||
private static Rectangle bounds;
|
||||
private static JMenu menu;
|
||||
private static JTextField anotherWindow;
|
||||
private static Point menuLoc;
|
||||
private static JFrame frame2;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
frame = new JFrame();
|
||||
field1 = new JTextField("field1 ");
|
||||
field2 = new JTextField("field2 ");
|
||||
field1.setEditable(false);
|
||||
field2.setEditable(false);
|
||||
frame.getContentPane().setLayout(new FlowLayout());
|
||||
frame.getContentPane().add(field1);
|
||||
frame.getContentPane().add(field2);
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
menu = new JMenu("menu");
|
||||
menu.add(new JMenuItem("item"));
|
||||
menuBar.add(menu);
|
||||
frame.setJMenuBar(menuBar);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
});
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
frame = new JFrame();
|
||||
field1 = new JTextField("field1 ");
|
||||
field2 = new JTextField("field2 ");
|
||||
field1.setEditable(false);
|
||||
field2.setEditable(false);
|
||||
frame.getContentPane().setLayout(new FlowLayout());
|
||||
frame.getContentPane().add(field1);
|
||||
frame.getContentPane().add(field2);
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
menu = new JMenu("menu");
|
||||
menu.add(new JMenuItem("item"));
|
||||
menuBar.add(menu);
|
||||
frame.setJMenuBar(menuBar);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
});
|
||||
|
||||
Robot robot = new Robot();
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
bounds = field2.getBounds();
|
||||
bounds.setLocation(field2.getLocationOnScreen());
|
||||
});
|
||||
BufferedImage nosel = robot.createScreenCapture(bounds);
|
||||
Robot robot = new Robot();
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
|
||||
SwingUtilities.invokeAndWait(field2::requestFocus);
|
||||
SwingUtilities.invokeAndWait(field2::selectAll);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
BufferedImage sel = robot.createScreenCapture(bounds);
|
||||
SwingUtilities.invokeAndWait(field2::requestFocus);
|
||||
SwingUtilities.invokeAndWait(field2::selectAll);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
menuLoc = menu.getLocationOnScreen();
|
||||
menuLoc.translate(10, 10);
|
||||
});
|
||||
robot.mouseMove(menuLoc.x, menuLoc.y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.delay(50);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (!biEqual(robot.createScreenCapture(bounds), sel)) {
|
||||
throw new RuntimeException("Test fails: menu hides selection");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(
|
||||
MenuSelectionManager.defaultManager()::clearSelectedPath);
|
||||
SwingUtilities.invokeAndWait(field1::requestFocus);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (!biEqual(robot.createScreenCapture(bounds), sel)) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: focus lost hides single selection");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(field1::selectAll);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (!biEqual(robot.createScreenCapture(bounds), nosel)) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: focus lost doesn't hide selection upon multi selection");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(field2::requestFocus);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (!biEqual(robot.createScreenCapture(bounds), sel)) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: focus gain hides selection upon multi selection");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(field2::requestFocus);
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(() ->{
|
||||
frame2 = new JFrame();
|
||||
Point loc = frame.getLocationOnScreen();
|
||||
loc.translate(0, frame.getHeight());
|
||||
frame2.setLocation(loc);
|
||||
anotherWindow = new JTextField("textField3");
|
||||
frame2.add(anotherWindow);
|
||||
frame2.pack();
|
||||
frame2.setVisible(true);
|
||||
});
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(anotherWindow::requestFocus);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (biEqual(robot.createScreenCapture(bounds), nosel)) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: switch window hides selection");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(anotherWindow::selectAll);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (biEqual(robot.createScreenCapture(bounds), sel)) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: selection ownership is lost selection is shown");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(frame2::dispose);
|
||||
SwingUtilities.invokeLater(frame::dispose);
|
||||
}
|
||||
|
||||
static boolean biEqual(BufferedImage i1, BufferedImage i2) {
|
||||
if (i1.getWidth() == i2.getWidth() &&
|
||||
i1.getHeight() == i2.getHeight()) {
|
||||
for (int x = 0; x < i1.getWidth(); x++) {
|
||||
for (int y = 0; y < i1.getHeight(); y++) {
|
||||
if (i1.getRGB(x, y) != i2.getRGB(x, y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
menuLoc = menu.getLocationOnScreen();
|
||||
menuLoc.translate(10, 10);
|
||||
});
|
||||
robot.mouseMove(menuLoc.x, menuLoc.y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.delay(50);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (!field2.getCaret().isSelectionVisible()) {
|
||||
throw new RuntimeException("Test fails: menu hides selection");
|
||||
}
|
||||
return true;
|
||||
|
||||
SwingUtilities.invokeAndWait(
|
||||
MenuSelectionManager.defaultManager()::clearSelectedPath);
|
||||
SwingUtilities.invokeAndWait(field1::requestFocus);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (field2.getSelectedText() == null || field2.getSelectedText().length() == 0) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: focus lost hides single selection");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(field1::selectAll);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (field2.getCaret().isSelectionVisible()) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: focus lost doesn't hide selection upon multi selection");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(field2::requestFocus);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (!field2.getCaret().isSelectionVisible()) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: focus gain hides selection upon multi selection");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(field2::requestFocus);
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
frame2 = new JFrame();
|
||||
Point loc = frame.getLocationOnScreen();
|
||||
loc.translate(0, frame.getHeight());
|
||||
frame2.setLocation(loc);
|
||||
anotherWindow = new JTextField("textField3");
|
||||
frame2.add(anotherWindow);
|
||||
frame2.pack();
|
||||
frame2.setVisible(true);
|
||||
});
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(anotherWindow::requestFocus);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (!field2.getCaret().isSelectionVisible()) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: switch window hides selection");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(anotherWindow::selectAll);
|
||||
robot.waitForIdle();
|
||||
robot.delay(200);
|
||||
if (field2.getCaret().isSelectionVisible()) {
|
||||
throw new RuntimeException(
|
||||
"Test fails: selection ownership is lost selection is shown");
|
||||
}
|
||||
} finally {
|
||||
if (frame2 != null) {
|
||||
SwingUtilities.invokeLater(frame2::dispose);
|
||||
}
|
||||
SwingUtilities.invokeLater(frame::dispose);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user