mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-08 10:29:40 +01:00
Compare commits
51 Commits
jb17.0.9-b
...
nprovotoro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a40a99e6c0 | ||
|
|
8e2db04c49 | ||
|
|
b508993b60 | ||
|
|
38b521feac | ||
|
|
f473fa15a1 | ||
|
|
5305726ece | ||
|
|
05a8ff9117 | ||
|
|
57c6cbe325 | ||
|
|
c5ba5ff4c8 | ||
|
|
95ada30c3f | ||
|
|
49b53da483 | ||
|
|
84c635c405 | ||
|
|
2be22e8578 | ||
|
|
74b52f068b | ||
|
|
98b3ac5221 | ||
|
|
5c7ffa6578 | ||
|
|
abfc3e2e79 | ||
|
|
2127a64497 | ||
|
|
8238bbcd4c | ||
|
|
0afe6c37bb | ||
|
|
ab95964027 | ||
|
|
15ff5a8489 | ||
|
|
0262d7e646 | ||
|
|
773ceb5f73 | ||
|
|
02a5148e02 | ||
|
|
86a7c75cc2 | ||
|
|
c57030a2ef | ||
|
|
6aebe7dd66 | ||
|
|
78265ab6a4 | ||
|
|
fe849d2ea0 | ||
|
|
d8ae52aeb0 | ||
|
|
ca5562225a | ||
|
|
9e65e2391a | ||
|
|
133a99192a | ||
|
|
b00a6465bb | ||
|
|
cc03cf1117 | ||
|
|
c13eb3036f | ||
|
|
4dd5ea93bb | ||
|
|
0dfbf34b37 | ||
|
|
8982db51d7 | ||
|
|
9a5348efce | ||
|
|
8617cb5c67 | ||
|
|
1d5bc2152d | ||
|
|
d2f126115a | ||
|
|
3169523d80 | ||
|
|
c48f588cb5 | ||
|
|
3fe2a97aa0 | ||
|
|
826f75ee48 | ||
|
|
c452e2f5ad | ||
|
|
473c41003d | ||
|
|
b967f5bc91 |
12
README.md
12
README.md
@@ -9,11 +9,13 @@ It includes a number of enhancements in font rendering, ligatures, HiDPI support
|
||||
Download the latest releases of JetBrains Runtime to use with JetBrains IDEs. The full list
|
||||
can be found on the [releases page](https://github.com/JetBrains/JetBrainsRuntime/releases).
|
||||
|
||||
| IDE Version | Latest JBR | Date Released |
|
||||
| --- |--------------------------------------------------------------------------------------------------------|---------------|
|
||||
| 2023.1 | [17.0.6-b829.1](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.6b829.1) | 14-Feb-2023 |
|
||||
| 2022.3 | [17.0.5-b653.25](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.5b653.25) | 10-Jan-2023 |
|
||||
| 2022.2 | [17.0.5-b469.71](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.5b469.71) | 14-Nov-2022 |
|
||||
| IDE Version | Latest JBR | Date Released |
|
||||
|-------------|---------------------------------------------------------------------------------------------------------|---------------|
|
||||
| 2023.3 | [17.0.9b1087.7](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.9b1087.7) | 20-Nov-2023 |
|
||||
| 2023.2 | [17.0.9b1000.46](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.9b1000.46) | 01-Nov-2023 |
|
||||
| 2023.1 | [17.0.6-b829.1](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.6b829.1) | 14-Feb-2023 |
|
||||
| 2022.3 | [17.0.5-b653.25](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.5b653.25) | 10-Jan-2023 |
|
||||
| 2022.2 | [17.0.5-b469.71](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.5b469.71) | 14-Nov-2022 |
|
||||
|
||||
|
||||
## Contents
|
||||
|
||||
@@ -77,6 +77,7 @@ function create_image_bundle {
|
||||
sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__root_dir"/release > release
|
||||
mv release "$IMAGES_DIR"/"$__root_dir"/release
|
||||
cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__root_dir"/lib
|
||||
cp $IMAGES_DIR/jdk/lib/server/*.jsa "$IMAGES_DIR"/"$__root_dir"/lib/server
|
||||
copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__root_dir"/jmods
|
||||
zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz"
|
||||
fi
|
||||
|
||||
@@ -77,6 +77,7 @@ function create_image_bundle {
|
||||
sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__root_dir"/release > release
|
||||
mv release "$IMAGES_DIR"/"$__root_dir"/release
|
||||
cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__root_dir"/lib
|
||||
cp $IMAGES_DIR/jdk/lib/server/*.jsa "$IMAGES_DIR"/"$__root_dir"/lib/server
|
||||
copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__root_dir"/jmods
|
||||
zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz"
|
||||
fi
|
||||
|
||||
@@ -65,6 +65,7 @@ function create_image_bundle {
|
||||
sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__root_dir"/release > release
|
||||
mv release "$IMAGES_DIR"/"$__root_dir"/release
|
||||
cp $IMAGES_DIR/jdk/lib/src.zip "$IMAGES_DIR"/"$__root_dir"/lib
|
||||
cp $IMAGES_DIR/jdk/lib/server/*.jsa "$IMAGES_DIR"/"$__root_dir"/lib/server
|
||||
copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__root_dir"/jmods
|
||||
zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz"
|
||||
fi
|
||||
|
||||
@@ -29,44 +29,27 @@ BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 16)}
|
||||
|
||||
function do_configure {
|
||||
if [[ "${architecture}" == *aarch64* ]]; then
|
||||
|
||||
sh configure \
|
||||
$WITH_DEBUG_LEVEL \
|
||||
--with-vendor-name="${VENDOR_NAME}" \
|
||||
--with-vendor-version-string="${VENDOR_VERSION_STRING}" \
|
||||
--with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \
|
||||
--with-macosx-bundle-id-base="com.jetbrains.jbr" \
|
||||
--with-jvm-features=shenandoahgc \
|
||||
--with-version-pre= \
|
||||
--with-version-build="${JDK_BUILD_NUMBER}" \
|
||||
--with-version-opt=b"${build_number}" \
|
||||
--with-boot-jdk="$BOOT_JDK" \
|
||||
--with-macosx-version-max="${MACOSX_VERSION_MAX:="11.00.00"}" \
|
||||
--disable-hotspot-gtest --disable-javac-server --disable-full-docs --disable-manpages \
|
||||
--enable-cds=no \
|
||||
$STATIC_CONF_ARGS \
|
||||
$REPRODUCIBLE_BUILD_OPTS \
|
||||
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|
||||
|| do_exit $?
|
||||
MACOSX_VERSION_MAX="11.00.00"
|
||||
else
|
||||
sh configure \
|
||||
$WITH_DEBUG_LEVEL \
|
||||
--with-vendor-name="$VENDOR_NAME" \
|
||||
--with-vendor-version-string="$VENDOR_VERSION_STRING" \
|
||||
--with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \
|
||||
--with-macosx-bundle-id-base="com.jetbrains.jbr" \
|
||||
--with-jvm-features=shenandoahgc \
|
||||
--with-version-pre= \
|
||||
--with-version-build="$JDK_BUILD_NUMBER" \
|
||||
--with-version-opt=b"$build_number" \
|
||||
--with-boot-jdk="$BOOT_JDK" \
|
||||
--with-macosx-version-max="${MACOSX_VERSION_MAX:="10.12.00"}" \
|
||||
--enable-cds=yes \
|
||||
$STATIC_CONF_ARGS \
|
||||
$REPRODUCIBLE_BUILD_OPTS \
|
||||
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|
||||
|| do_exit $?
|
||||
MACOSX_VERSION_MAX="10.12.00"
|
||||
fi
|
||||
sh configure \
|
||||
$WITH_DEBUG_LEVEL \
|
||||
--with-vendor-name="$VENDOR_NAME" \
|
||||
--with-vendor-version-string="$VENDOR_VERSION_STRING" \
|
||||
--with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \
|
||||
--with-macosx-bundle-id-base="com.jetbrains.jbr" \
|
||||
--with-jvm-features=shenandoahgc \
|
||||
--with-version-pre= \
|
||||
--with-version-build="$JDK_BUILD_NUMBER" \
|
||||
--with-version-opt=b"$build_number" \
|
||||
--with-boot-jdk="$BOOT_JDK" \
|
||||
--with-macosx-version-max="${MACOSX_VERSION_MAX}" \
|
||||
--enable-cds=yes \
|
||||
$STATIC_CONF_ARGS \
|
||||
$REPRODUCIBLE_BUILD_OPTS \
|
||||
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|
||||
|| do_exit $?
|
||||
}
|
||||
|
||||
function create_image_bundle {
|
||||
@@ -97,6 +80,7 @@ function create_image_bundle {
|
||||
sed 's/JBR/JBRSDK/g' $JRE_CONTENTS/Home/release > release
|
||||
mv release $JRE_CONTENTS/Home/release
|
||||
cp $IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk/Contents/Home/lib/src.zip $JRE_CONTENTS/Home/lib
|
||||
cp $IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk/Contents/Home/lib/server/*.jsa $JRE_CONTENTS/Home/lib/server
|
||||
copy_jmods "$__modules" "$__modules_path" "$JRE_CONTENTS"/Home/jmods
|
||||
zip_native_debug_symbols $IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk "${JBR}_diz"
|
||||
fi
|
||||
@@ -112,7 +96,7 @@ function create_image_bundle {
|
||||
|
||||
echo Creating "$JBR".tar.gz ...
|
||||
# Normalize timestamp
|
||||
find "$tmp"/"$__root_dir" -print0 | xargs -0 touch -c -h -t "$TOUCH_TIME"
|
||||
#find "$tmp"/"$__root_dir" -print0 | xargs -0 touch -c -h -t "$TOUCH_TIME"
|
||||
|
||||
(cd "$tmp" &&
|
||||
find "$__root_dir" -print0 | LC_ALL=C sort -z | \
|
||||
|
||||
@@ -75,6 +75,7 @@ function create_image_bundle {
|
||||
sed 's/JBR/JBRSDK/g' $__root_dir/release > release
|
||||
mv release $__root_dir/release
|
||||
cp $IMAGES_DIR/jdk/lib/src.zip $__root_dir/lib
|
||||
cp $IMAGES_DIR/jdk/bin/server/*.jsa $__root_dir/bin/server
|
||||
for dir in $(ls -d $IMAGES_DIR/jdk/*); do
|
||||
rsync -amv --include="*/" --include="*.pdb" --exclude="*" $dir $__root_dir
|
||||
done
|
||||
|
||||
@@ -66,6 +66,7 @@ function create_image_bundle {
|
||||
sed 's/JBR/JBRSDK/g' $__root_dir/release > release
|
||||
mv release $__root_dir/release
|
||||
cp $IMAGES_DIR/jdk/lib/src.zip $__root_dir/lib
|
||||
cp $IMAGES_DIR/jdk/bin/server/*.jsa $__root_dir/bin/server
|
||||
for dir in $(ls -d $IMAGES_DIR/jdk/*); do
|
||||
rsync -amv --include="*/" --include="*.pdb" --exclude="*" $dir $__root_dir
|
||||
done
|
||||
|
||||
@@ -62,6 +62,7 @@ function create_image_bundle {
|
||||
sed 's/JBR/JBRSDK/g' $__root_dir/release > release
|
||||
mv release $__root_dir/release
|
||||
cp $IMAGES_DIR/jdk/lib/src.zip $__root_dir/lib
|
||||
cp $IMAGES_DIR/jdk/bin/server/*.jsa $__root_dir/bin/server
|
||||
for dir in $(ls -d $IMAGES_DIR/jdk/*); do
|
||||
rsync -amv --include="*/" --include="*.pdb" --exclude="*" $dir $__root_dir
|
||||
done
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# - Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# - Neither the name of Oracle nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
SOURCEPATH=src
|
||||
CLASSES=build
|
||||
DIST=dist
|
||||
RESOURCES=resources
|
||||
|
||||
RENDERPERF_CLASSES = $(CLASSES)/renderperf/RenderPerfTest.class
|
||||
RENDERPERF_SOURCES = $(SOURCEPATH)/renderperf/RenderPerfTest.java
|
||||
|
||||
RENDERPERF_RESOURCES = $(CLASSES)/renderperf/images/duke.png
|
||||
|
||||
all: mkdirs $(DIST)/RenderPerfTest.jar
|
||||
|
||||
run: mkdirs $(DIST)/RenderPerfTest.jar
|
||||
java -jar $(DIST)/RenderPerfTest.jar
|
||||
|
||||
$(DIST)/RenderPerfTest.jar: \
|
||||
$(RENDERPERF_CLASSES) $(RENDERPERF_RESOURCES) \
|
||||
$(CLASSES)/renderperf.manifest
|
||||
jar cvmf $(CLASSES)/renderperf.manifest $(DIST)/RenderPerfTest.jar -C $(CLASSES) .
|
||||
|
||||
|
||||
$(CLASSES)/renderperf/images/%: $(RESOURCES)/images/%
|
||||
cp -r $< $@
|
||||
|
||||
|
||||
$(CLASSES)/renderperf.manifest:
|
||||
echo "Main-Class: renderperf.RenderPerfTest" > $@
|
||||
|
||||
$(DIST):
|
||||
mkdir $(DIST)
|
||||
|
||||
$(CLASSES):
|
||||
mkdir $(CLASSES)
|
||||
mkdir -p $(CLASSES)/renderperf/images
|
||||
|
||||
mkdirs: $(DIST) $(CLASSES)
|
||||
|
||||
$(RENDERPERF_CLASSES): $(RENDERPERF_SOURCES)
|
||||
javac -g:none -d $(CLASSES) -sourcepath $(SOURCEPATH) $<
|
||||
|
||||
clean:
|
||||
rm -rf $(CLASSES)
|
||||
rm -rf $(DIST)
|
||||
@@ -1,34 +0,0 @@
|
||||
-----------------------------------------------------------------------
|
||||
Introduction
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
RenderPerfTest is a set of on-screen rendering microbenchmarks to
|
||||
analyze the performance of Java2D graphical primitives rendering
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
How To Compile
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
#> cd RenderPerfTest
|
||||
|
||||
The benchmark can be compiled by using either ant:
|
||||
|
||||
#> ant
|
||||
|
||||
or gnumake (assuming there's 'javac' in the path):
|
||||
|
||||
#> gnumake
|
||||
|
||||
The jar files will be generated into RenderPerfTest/dist directory.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
How To Run RenderPerfTest
|
||||
-----------------------------------------------------------------------
|
||||
Run all tests
|
||||
#> ant run
|
||||
or
|
||||
#> java -jar dist/RenderPerfTest.jar
|
||||
|
||||
Run particular test cases
|
||||
|
||||
#> java -jar dist/RenderPerfTest.jar testWhiteTextBubblesGray ...
|
||||
@@ -1,94 +0,0 @@
|
||||
<!--
|
||||
Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Oracle nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->
|
||||
|
||||
<project name="RenderPerfTest" default="dist" basedir=".">
|
||||
<description>
|
||||
simple example build file
|
||||
</description>
|
||||
<!-- set global properties for this build -->
|
||||
<property name="src" location="src"/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="dist" location="dist"/>
|
||||
<property name="resources" location="resources"/>
|
||||
|
||||
<target name="init">
|
||||
<!-- Create the time stamp -->
|
||||
<tstamp/>
|
||||
<!-- Create the build directory structure used by compile -->
|
||||
<mkdir dir="${build}"/>
|
||||
</target>
|
||||
|
||||
<target name="compile" depends="init"
|
||||
description="compile the source " >
|
||||
<!-- Compile the java code from ${src} into ${build} -->
|
||||
<javac includeantruntime="false" debug="off" srcdir="${src}" destdir="${build}"/>
|
||||
</target>
|
||||
|
||||
<target name="run" depends="dist"
|
||||
description="run RenderPerfTest" >
|
||||
<java jar="${dist}/RenderPerfTest.jar"
|
||||
fork="true"
|
||||
>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<target name="resources" depends="init"
|
||||
description="copy resources into build dir" >
|
||||
<!-- Copy the resource files from ${resources} into ${build}/ -->
|
||||
<mkdir dir="${dist}"/>
|
||||
<mkdir dir="${dist}/renderperf"/>
|
||||
<mkdir dir="${build}/renderperf/images"/>
|
||||
<copy todir="${build}/renderperf/images">
|
||||
<fileset dir="resources/renderperf/images" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="dist" depends="compile, resources"
|
||||
description="generate the distribution" >
|
||||
<!-- Create the distribution directory -->
|
||||
<mkdir dir="${dist}"/>
|
||||
|
||||
<!-- Put everything in ${build} into the J2DBench.jar file -->
|
||||
<jar jarfile="${dist}/RenderPerfTest.jar" basedir="${build}">
|
||||
<manifest>
|
||||
<attribute name="Built-By" value="${user.name}"/>
|
||||
<attribute name="Main-Class" value="renderperf.RenderPerfTest"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="clean"
|
||||
description="clean up" >
|
||||
<!-- Delete the ${build} and ${dist} directory trees -->
|
||||
<delete dir="${build}"/>
|
||||
<delete dir="${dist}"/>
|
||||
</target>
|
||||
</project>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1,739 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2020 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package renderperf;
|
||||
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
||||
public class RenderPerfTest {
|
||||
private static HashSet<String> ignoredTests = new HashSet<>();
|
||||
|
||||
private final static int N = 1000;
|
||||
private final static float WIDTH = 800;
|
||||
private final static float HEIGHT = 800;
|
||||
private final static float R = 25;
|
||||
private final static int BW = 50;
|
||||
private final static int BH = 50;
|
||||
private final static int COUNT = 300;
|
||||
private final static int DELAY = 10;
|
||||
private final static int RESOLUTION = 5;
|
||||
private final static int COLOR_TOLERANCE = 10;
|
||||
private final static int MAX_MEASURE_TIME = 5000;
|
||||
|
||||
|
||||
interface Configurable {
|
||||
void configure(Graphics2D g2d);
|
||||
}
|
||||
|
||||
interface Renderable {
|
||||
void setup(Graphics2D g2d);
|
||||
void render(Graphics2D g2d);
|
||||
void update();
|
||||
}
|
||||
|
||||
static class Particles {
|
||||
private float[] bx;
|
||||
private float[] by;
|
||||
private float[] vx;
|
||||
private float[] vy;
|
||||
private float r;
|
||||
private int n;
|
||||
|
||||
private float x0;
|
||||
private float y0;
|
||||
private float width;
|
||||
private float height;
|
||||
|
||||
Particles(int n, float r, float x0, float y0, float width, float height) {
|
||||
bx = new float[n];
|
||||
by = new float[n];
|
||||
vx = new float[n];
|
||||
vy = new float[n];
|
||||
this.n = n;
|
||||
this.r = r;
|
||||
this.x0 = x0;
|
||||
this.y0 = y0;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
for (int i = 0; i < n; i++) {
|
||||
bx[i] = (float) (x0 + r + 0.1 + Math.random() * (width - 2 * r - 0.2 - x0));
|
||||
by[i] = (float) (y0 + r + 0.1 + Math.random() * (height - 2 * r - 0.2 - y0));
|
||||
vx[i] = 0.1f * (float) (Math.random() * 2 * r - r);
|
||||
vy[i] = 0.1f * (float) (Math.random() * 2 * r - r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void render(Graphics2D g2d, ParticleRenderer renderer) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
renderer.render(g2d, i, bx, by, vx, vy);
|
||||
}
|
||||
}
|
||||
|
||||
void update() {
|
||||
for (int i = 0; i < n; i++) {
|
||||
bx[i] += vx[i];
|
||||
if (bx[i] + r > width || bx[i] - r < x0) vx[i] = -vx[i];
|
||||
by[i] += vy[i];
|
||||
if (by[i] + r > height || by[i] - r < y0) vy[i] = -vy[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ParticleRenderable createPR(ParticleRenderer renderer) {
|
||||
return new ParticleRenderable(renderer);
|
||||
}
|
||||
|
||||
static class ParticleRenderable implements Renderable {
|
||||
ParticleRenderer renderer;
|
||||
Configurable configure;
|
||||
|
||||
ParticleRenderable(ParticleRenderer renderer, Configurable configure) {
|
||||
this.renderer = renderer;
|
||||
this.configure = configure;
|
||||
}
|
||||
|
||||
ParticleRenderable(ParticleRenderer renderer) {
|
||||
this(renderer, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup(Graphics2D g2d) {
|
||||
if (configure != null) configure.configure(g2d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g2d) {
|
||||
balls.render(g2d, renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
balls.update();
|
||||
}
|
||||
|
||||
public ParticleRenderable configure(Configurable configure) {
|
||||
this.configure = configure;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
interface ParticleRenderer {
|
||||
void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy);
|
||||
|
||||
}
|
||||
|
||||
static class FlatParticleRenderer implements ParticleRenderer {
|
||||
Color[] colors;
|
||||
float r;
|
||||
|
||||
FlatParticleRenderer(int n, float r) {
|
||||
colors = new Color[n];
|
||||
this.r = r;
|
||||
for (int i = 0; i < n; i++) {
|
||||
colors[i] = new Color((float) Math.random(),
|
||||
(float) Math.random(), (float) Math.random());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
g2d.fillOval((int)(x[id] - r), (int)(y[id] - r), (int)(2*r), (int)(2*r));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class WhiteTextParticleRenderer implements ParticleRenderer {
|
||||
float r;
|
||||
|
||||
WhiteTextParticleRenderer(float r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
void setPaint(Graphics2D g2d, int id) {
|
||||
g2d.setColor(Color.WHITE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
setPaint(g2d, id);
|
||||
g2d.drawString("The quick brown fox jumps over the lazy dog",
|
||||
(int)(x[id] - r), (int)(y[id] - r));
|
||||
g2d.drawString("The quick brown fox jumps over the lazy dog",
|
||||
(int)(x[id] - r), (int)y[id]);
|
||||
g2d.drawString("The quick brown fox jumps over the lazy dog",
|
||||
(int)(x[id] - r), (int)(y[id] + r));
|
||||
}
|
||||
}
|
||||
|
||||
static class TextParticleRenderer extends WhiteTextParticleRenderer {
|
||||
Color[] colors;
|
||||
|
||||
float r;
|
||||
|
||||
TextParticleRenderer(int n, float r) {
|
||||
super(r);
|
||||
colors = new Color[n];
|
||||
this.r = r;
|
||||
for (int i = 0; i < n; i++) {
|
||||
colors[i] = new Color((float) Math.random(),
|
||||
(float) Math.random(), (float) Math.random());
|
||||
}
|
||||
}
|
||||
|
||||
void setPaint(Graphics2D g2d, int id) {
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
}
|
||||
}
|
||||
|
||||
static class LargeTextParticleRenderer extends TextParticleRenderer {
|
||||
|
||||
LargeTextParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
setPaint(g2d, id);
|
||||
Font font = new Font("LucidaGrande", Font.PLAIN, 32);
|
||||
g2d.setFont(font);
|
||||
g2d.drawString("The quick brown fox jumps over the lazy dog",
|
||||
(int)(x[id] - r), (int)(y[id] - r));
|
||||
g2d.drawString("The quick brown fox jumps over the lazy dog",
|
||||
(int)(x[id] - r), (int)y[id]);
|
||||
g2d.drawString("The quick brown fox jumps over the lazy dog",
|
||||
(int)(x[id] - r), (int)(y[id] + r));
|
||||
}
|
||||
}
|
||||
|
||||
static class FlatOvalRotParticleRenderer extends FlatParticleRenderer {
|
||||
|
||||
|
||||
FlatOvalRotParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
}
|
||||
|
||||
void setPaint(Graphics2D g2d, int id) {
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
setPaint(g2d, id);
|
||||
if (Math.abs(vx[id] + vy[id]) > 0.001) {
|
||||
AffineTransform t = (AffineTransform) g2d.getTransform().clone();
|
||||
double l = vx[id] / Math.sqrt(vx[id] * vx[id] + vy[id] * vy[id]);
|
||||
if (vy[id] < 0) {
|
||||
l = -l;
|
||||
}
|
||||
g2d.translate(x[id], y[id]);
|
||||
g2d.rotate(Math.acos(l));
|
||||
g2d.fillOval(-(int)r, (int)(-0.5*r), (int) (2 * r), (int)r);
|
||||
g2d.setTransform(t);
|
||||
} else {
|
||||
g2d.fillOval((int)(x[id] - r), (int)(y[id] - 0.5*r),
|
||||
(int) (2 * r), (int) r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class LinGradOvalRotParticleRenderer extends FlatOvalRotParticleRenderer {
|
||||
|
||||
|
||||
LinGradOvalRotParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setPaint(Graphics2D g2d, int id) {
|
||||
Point2D start = new Point2D.Double(- r, - 0.5*r);
|
||||
Point2D end = new Point2D.Double( 2 * r, r);
|
||||
float[] dist = {0.0f, 1.0f};
|
||||
Color[] cls = {colors[id %colors.length], colors[(colors.length - id) %colors.length]};
|
||||
LinearGradientPaint p =
|
||||
new LinearGradientPaint(start, end, dist, cls);
|
||||
g2d.setPaint(p);
|
||||
}
|
||||
}
|
||||
|
||||
static class FlatBoxParticleRenderer extends FlatParticleRenderer {
|
||||
|
||||
|
||||
FlatBoxParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
}
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
g2d.fillRect((int)(x[id] - r), (int)(y[id] - r), (int)(2*r), (int)(2*r));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class ImgParticleRenderer extends FlatParticleRenderer {
|
||||
BufferedImage dukeImg;
|
||||
|
||||
ImgParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
try {
|
||||
dukeImg = ImageIO.read(
|
||||
Objects.requireNonNull(
|
||||
RenderPerfTest.class.getClassLoader().getResourceAsStream(
|
||||
"renderperf/images/duke.png")));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
g2d.drawImage(dukeImg, (int)(x[id] - r), (int)(y[id] - r), (int)(2*r), (int)(2*r), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class FlatBoxRotParticleRenderer extends FlatParticleRenderer {
|
||||
|
||||
|
||||
FlatBoxRotParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
}
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
if (Math.abs(vx[id] + vy[id]) > 0.001) {
|
||||
AffineTransform t = (AffineTransform) g2d.getTransform().clone();
|
||||
double l = vx[id] / Math.sqrt(vx[id] * vx[id] + vy[id] * vy[id]);
|
||||
if (vy[id] < 0) {
|
||||
l = -l;
|
||||
}
|
||||
g2d.translate(x[id], y[id]);
|
||||
g2d.rotate(Math.acos(l));
|
||||
g2d.fillRect(-(int)r, -(int)r, (int) (2 * r), (int) (2 * r));
|
||||
g2d.setTransform(t);
|
||||
} else {
|
||||
g2d.fillRect((int)(x[id] - r), (int)(y[id] - r),
|
||||
(int) (2 * r), (int) (2 * r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class WiredParticleRenderer extends FlatParticleRenderer {
|
||||
|
||||
|
||||
WiredParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
}
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
g2d.drawOval((int)(x[id] - r), (int)(y[id] - r), (int)(2*r), (int)(2*r));
|
||||
}
|
||||
|
||||
}
|
||||
static class WiredBoxParticleRenderer extends FlatParticleRenderer {
|
||||
|
||||
WiredBoxParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
g2d.drawRect((int)(x[id] - r), (int)(y[id] - r), (int)(2*r), (int)(2*r));
|
||||
}
|
||||
|
||||
}
|
||||
static class SegParticleRenderer extends FlatParticleRenderer {
|
||||
|
||||
SegParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
double v = Math.sqrt(vx[id]*vx[id]+vy[id]*vy[id]);
|
||||
float nvx = (float) (vx[id]/v);
|
||||
float nvy = (float) (vy[id]/v);
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
g2d.drawLine((int)(x[id] - r*nvx), (int)(y[id] - r*nvy),
|
||||
(int)(x[id] + 2*r*nvx), (int)(y[id] + 2*r*nvy));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static class WiredQuadParticleRenderer extends FlatParticleRenderer {
|
||||
|
||||
WiredQuadParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
if (id > 2 && (id % 3) == 0) {
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
g2d.draw(new QuadCurve2D.Float(x[id-3], y[id-3], x[id-2], y[id-2], x[id-1], y[id-1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static class FlatQuadParticleRenderer extends FlatParticleRenderer {
|
||||
|
||||
FlatQuadParticleRenderer(int n, float r) {
|
||||
super(n, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Graphics2D g2d, int id, float[] x, float[] y, float[] vx, float[] vy) {
|
||||
if (id > 2 && (id % 3) == 0) {
|
||||
g2d.setColor(colors[id % colors.length]);
|
||||
g2d.fill(new QuadCurve2D.Float(x[id-3], y[id-3], x[id-2], y[id-2], x[id-1], y[id-1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static class PerfMeter {
|
||||
private String name;
|
||||
private int frame = 0;
|
||||
|
||||
private JPanel panel;
|
||||
|
||||
private long time;
|
||||
private double execTime = 0;
|
||||
private Color expColor = Color.RED;
|
||||
AtomicBoolean waiting = new AtomicBoolean(false);
|
||||
private double fps;
|
||||
|
||||
PerfMeter(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
PerfMeter exec(final Renderable renderable) throws Exception {
|
||||
final CountDownLatch latch = new CountDownLatch(COUNT);
|
||||
final CountDownLatch latchFrame = new CountDownLatch(1);
|
||||
final long endTime = System.currentTimeMillis() + MAX_MEASURE_TIME;
|
||||
|
||||
final JFrame f = new JFrame();
|
||||
f.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
latchFrame.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
panel = new JPanel()
|
||||
{
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
|
||||
super.paintComponent(g);
|
||||
time = System.nanoTime();
|
||||
Graphics2D g2d = (Graphics2D) g.create();
|
||||
renderable.setup(g2d);
|
||||
renderable.render(g2d);
|
||||
g2d.setColor(expColor);
|
||||
g.fillRect(0, 0, BW, BH);
|
||||
}
|
||||
};
|
||||
|
||||
panel.setPreferredSize(new Dimension((int)(WIDTH + BW), (int)(HEIGHT + BH)));
|
||||
panel.setBackground(Color.BLACK);
|
||||
f.add(panel);
|
||||
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
f.pack();
|
||||
f.setVisible(true);
|
||||
}
|
||||
});
|
||||
Robot robot = new Robot();
|
||||
|
||||
Timer timer = new Timer(DELAY, e -> {
|
||||
|
||||
if (waiting.compareAndSet(false, true)) {
|
||||
Color c = robot.getPixelColor(
|
||||
panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW / 2,
|
||||
panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BW / 2);
|
||||
if (isAlmostEqual(c, Color.BLUE)) {
|
||||
expColor = Color.RED;
|
||||
} else {
|
||||
expColor = Color.BLUE;
|
||||
}
|
||||
renderable.update();
|
||||
panel.getParent().repaint();
|
||||
|
||||
} else {
|
||||
while (!isAlmostEqual(
|
||||
robot.getPixelColor(
|
||||
panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW/2,
|
||||
panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BH/2),
|
||||
expColor))
|
||||
{
|
||||
try {
|
||||
Thread.sleep(RESOLUTION);
|
||||
} catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
time = System.nanoTime() - time;
|
||||
execTime += time;
|
||||
frame++;
|
||||
waiting.set(false);
|
||||
}
|
||||
|
||||
if (System.currentTimeMillis() < endTime) {
|
||||
latch.countDown();
|
||||
} else {
|
||||
while(latch.getCount() > 0) latch.countDown();
|
||||
}
|
||||
});
|
||||
timer.start();
|
||||
latch.await();
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
timer.stop();
|
||||
f.setVisible(false);
|
||||
f.dispose();
|
||||
});
|
||||
|
||||
latchFrame.await();
|
||||
if (execTime != 0 && frame != 0) {
|
||||
fps = 1e9 / (execTime / frame);
|
||||
} else {
|
||||
fps = 0;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private void report() {
|
||||
System.err.println(name + " : " + String.format("%.2f FPS", fps));
|
||||
}
|
||||
|
||||
private 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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static final Particles balls = new Particles(N, R, BW, BH, WIDTH, HEIGHT);
|
||||
private static final ParticleRenderer flatRenderer = new FlatParticleRenderer(N, R);
|
||||
private static final ParticleRenderer flatOvalRotRenderer = new FlatOvalRotParticleRenderer(N, R);
|
||||
private static final ParticleRenderer flatBoxRenderer = new FlatBoxParticleRenderer(N, R);
|
||||
private static final ParticleRenderer flatBoxRotRenderer = new FlatBoxRotParticleRenderer(N, R);
|
||||
private static final ParticleRenderer linGradOvalRotRenderer = new LinGradOvalRotParticleRenderer(N, R);
|
||||
private static final ParticleRenderer wiredRenderer = new WiredParticleRenderer(N, R);
|
||||
private static final ParticleRenderer wiredBoxRenderer = new WiredBoxParticleRenderer(N, R);
|
||||
private static final ParticleRenderer segRenderer = new SegParticleRenderer(N, R);
|
||||
private static final ParticleRenderer flatQuadRenderer = new FlatQuadParticleRenderer(N, R);
|
||||
private static final ParticleRenderer wiredQuadRenderer = new WiredQuadParticleRenderer(N, R);
|
||||
private static final ParticleRenderer imgRenderer = new ImgParticleRenderer(N, R);
|
||||
private static final ParticleRenderer textRenderer = new TextParticleRenderer(N, R);
|
||||
private static final ParticleRenderer largeTextRenderer = new LargeTextParticleRenderer(N, R);
|
||||
private static final ParticleRenderer whiteTextRenderer = new WhiteTextParticleRenderer(R);
|
||||
|
||||
private static final Configurable AA = (Graphics2D g2d) ->
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
private static final Configurable TextLCD = (Graphics2D g2d) ->
|
||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
||||
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
|
||||
|
||||
private static final Configurable TextAA = (Graphics2D g2d) ->
|
||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
||||
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
|
||||
public void testFlatBubbles() throws Exception {
|
||||
(new PerfMeter("FlatOval")).exec(createPR(flatRenderer)).report();
|
||||
}
|
||||
|
||||
public void testFlatBubblesAA() throws Exception {
|
||||
(new PerfMeter("FlatOvalAA")).exec(createPR(flatRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testFlatBoxBubbles() throws Exception {
|
||||
(new PerfMeter("FlatBox")).exec(createPR(flatBoxRenderer)).report();
|
||||
}
|
||||
|
||||
public void testFlatBoxBubblesAA() throws Exception {
|
||||
(new PerfMeter("FlatBoxAA")).exec(createPR(flatBoxRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testImgBubbles() throws Exception {
|
||||
(new PerfMeter("Image")).exec(createPR(imgRenderer)).report();
|
||||
}
|
||||
|
||||
public void testImgBubblesAA() throws Exception {
|
||||
(new PerfMeter("ImageAA")).exec(createPR(imgRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testFlatBoxRotBubbles() throws Exception {
|
||||
(new PerfMeter("RotatedBox")).exec(createPR(flatBoxRotRenderer)).report();
|
||||
}
|
||||
|
||||
public void testFlatBoxRotBubblesAA() throws Exception {
|
||||
(new PerfMeter("RotatedBoxAA")).exec(createPR(flatBoxRotRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testFlatOvalRotBubbles() throws Exception {
|
||||
(new PerfMeter("RotatedOval")).exec(createPR(flatOvalRotRenderer)).report();
|
||||
}
|
||||
|
||||
public void testFlatOvalRotBubblesAA() throws Exception {
|
||||
(new PerfMeter("RotatedOvalAA")).exec(createPR(flatOvalRotRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testLinGradOvalRotBubbles() throws Exception {
|
||||
(new PerfMeter("LinGradRotatedOval")).exec(createPR(linGradOvalRotRenderer)).report();
|
||||
}
|
||||
|
||||
public void testLinGradOvalRotBubblesAA() throws Exception {
|
||||
(new PerfMeter("LinGradRotatedOvalAA")).exec(createPR(linGradOvalRotRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testWiredBubbles() throws Exception {
|
||||
(new PerfMeter("WiredBubbles")).exec(createPR(wiredRenderer)).report();
|
||||
}
|
||||
|
||||
public void testWiredBubblesAA() throws Exception {
|
||||
(new PerfMeter("WiredBubblesAA")).exec(createPR(wiredRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testWiredBoxBubbles() throws Exception {
|
||||
(new PerfMeter("WiredBox")).exec(createPR(wiredBoxRenderer)).report();
|
||||
}
|
||||
|
||||
public void testWiredBoxBubblesAA() throws Exception {
|
||||
(new PerfMeter("WiredBoxAA")).exec(createPR(wiredBoxRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testLines() throws Exception {
|
||||
(new PerfMeter("Lines")).exec(createPR(segRenderer)).report();
|
||||
}
|
||||
|
||||
public void testLinesAA() throws Exception {
|
||||
(new PerfMeter("LinesAA")).exec(createPR(segRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testFlatQuad() throws Exception {
|
||||
(new PerfMeter("FlatQuad")).exec(createPR(flatQuadRenderer)).report();
|
||||
}
|
||||
|
||||
public void testFlatQuadAA() throws Exception {
|
||||
(new PerfMeter("FlatQuadAA")).exec(createPR(flatQuadRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testWiredQuad() throws Exception {
|
||||
(new PerfMeter("WiredQuad")).exec(createPR(wiredQuadRenderer)).report();
|
||||
}
|
||||
|
||||
public void testWiredQuadAA() throws Exception {
|
||||
(new PerfMeter("WiredQuadAA")).exec(createPR(wiredQuadRenderer).configure(AA)).report();
|
||||
}
|
||||
|
||||
public void testTextBubblesNoAA() throws Exception {
|
||||
(new PerfMeter("TextNoAA")).exec(createPR(textRenderer)).report();
|
||||
}
|
||||
|
||||
public void testTextBubblesLCD() throws Exception {
|
||||
(new PerfMeter("TextLCD")).exec(createPR(textRenderer).configure(TextLCD)).report();
|
||||
}
|
||||
|
||||
public void testTextBubblesGray() throws Exception {
|
||||
(new PerfMeter("TextGray")).exec(createPR(textRenderer).configure(TextAA)).report();
|
||||
}
|
||||
|
||||
public void testLargeTextBubblesNoAA() throws Exception {
|
||||
(new PerfMeter("LargeTextNoAA")).exec(createPR(largeTextRenderer)).report();
|
||||
}
|
||||
|
||||
public void testLargeTextBubblesLCD() throws Exception {
|
||||
(new PerfMeter("LargeTextLCD")).exec(createPR(largeTextRenderer).configure(TextLCD)).report();
|
||||
}
|
||||
|
||||
public void testLargeTextBubblesGray() throws Exception {
|
||||
(new PerfMeter("LargeTextGray")).exec(createPR(largeTextRenderer).configure(TextAA)).report();
|
||||
}
|
||||
public void testWhiteTextBubblesNoAA() throws Exception {
|
||||
(new PerfMeter("WhiteTextNoAA")).exec(createPR(whiteTextRenderer)).report();
|
||||
}
|
||||
|
||||
public void testWhiteTextBubblesLCD() throws Exception {
|
||||
(new PerfMeter("WhiteTextLCD")).exec(createPR(whiteTextRenderer).configure(TextLCD)).report();
|
||||
}
|
||||
|
||||
public void testWhiteTextBubblesGray() throws Exception {
|
||||
(new PerfMeter("WhiteTextGray")).exec(createPR(whiteTextRenderer).configure(TextAA)).report();
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
throws InvocationTargetException, IllegalAccessException, NoSuchMethodException
|
||||
{
|
||||
RenderPerfTest test = new RenderPerfTest();
|
||||
|
||||
if (args.length > 0) {
|
||||
for (String testCase : args) {
|
||||
Method m = RenderPerfTest.class.getDeclaredMethod(testCase);
|
||||
m.invoke(test);
|
||||
}
|
||||
} else {
|
||||
Method[] methods = RenderPerfTest.class.getDeclaredMethods();
|
||||
for (Method m : methods) {
|
||||
if (m.getName().startsWith("test") && !ignoredTests.contains(m.getName())) {
|
||||
m.invoke(test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -407,16 +407,17 @@ bool SharedClassPathEntry::validate(bool is_class_path) const {
|
||||
FileMapInfo::fail_continue("directory is not empty: %s", name);
|
||||
ok = false;
|
||||
}
|
||||
} else if ((has_timestamp() && _timestamp != st.st_mtime) ||
|
||||
_filesize != st.st_size) {
|
||||
ok = false;
|
||||
if (PrintSharedArchiveAndExit) {
|
||||
FileMapInfo::fail_continue(_timestamp != st.st_mtime ?
|
||||
"Timestamp mismatch" :
|
||||
"File size mismatch");
|
||||
} else {
|
||||
FileMapInfo::fail_continue("A jar file is not the one used while building"
|
||||
" the shared archive file: %s", name);
|
||||
} else {
|
||||
bool size_differs = _filesize != st.st_size;
|
||||
bool time_differs = has_timestamp() && _timestamp != st.st_mtime;
|
||||
if (time_differs || size_differs) {
|
||||
ok = false;
|
||||
if (PrintSharedArchiveAndExit) {
|
||||
FileMapInfo::fail_continue(time_differs ? "Timestamp mismatch" : "File size mismatch");
|
||||
} else {
|
||||
FileMapInfo::fail_continue("This file is not the one used while building"
|
||||
" the shared archive file: %s", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,12 +141,14 @@ public final class CGraphicsDevice extends GraphicsDevice
|
||||
System.out.println("OpenGL pipeline enabled on screen " + displayID);
|
||||
}
|
||||
|
||||
// initializes default device state, might be redundant step since we
|
||||
// call "displayChanged()" later anyway, but we do not want to leave the
|
||||
// device in an inconsistent state after construction
|
||||
// [JBR] we don't call displayChanged after creating a device, so call it here.
|
||||
displayChanged();
|
||||
}
|
||||
|
||||
int getDisplayID() {
|
||||
return displayID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all configurations.
|
||||
*/
|
||||
@@ -224,6 +226,17 @@ public final class CGraphicsDevice extends GraphicsDevice
|
||||
//TODO configs?
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false if display parameters were changed, so we need to recreate the device.
|
||||
*/
|
||||
boolean updateDevice() {
|
||||
int s = scale;
|
||||
double xr = xResolution, yr = yResolution;
|
||||
var b = bounds;
|
||||
displayChanged();
|
||||
return s == scale && xr == xResolution && yr == yResolution && b.equals(bounds);
|
||||
}
|
||||
|
||||
public void displayParametersChanged() {
|
||||
Insets newScreenInsets = nativeGetScreenInsets(displayID);
|
||||
if (!newScreenInsets.equals(screenInsets)) {
|
||||
|
||||
@@ -149,7 +149,8 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
*/
|
||||
private void rebuildDevices() {
|
||||
initDevices();
|
||||
displayChanged();
|
||||
// Do not notify devices, this was already done in initDevices.
|
||||
displayChanger.notifyListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,8 +211,17 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
displayIDs = new int[]{mainDisplayID};
|
||||
}
|
||||
for (int id : displayIDs) {
|
||||
devices.put(id, old.containsKey(id) ? old.remove(id)
|
||||
: new CGraphicsDevice(id));
|
||||
old.compute(id, (i, d) -> {
|
||||
if (d != null && d.updateDevice()) {
|
||||
// Device didn't change -> reuse
|
||||
devices.put(i, d);
|
||||
return null;
|
||||
} else {
|
||||
// Device changed -> create new
|
||||
devices.put(i, new CGraphicsDevice(i));
|
||||
return d;
|
||||
}
|
||||
});
|
||||
}
|
||||
// fetch the main display again, the old value might be outdated
|
||||
mainDisplayID = LWCToolkit.isDispatchingOnMainThread() ? getMainDisplayIDAppKit() : getMainDisplayID();
|
||||
@@ -247,9 +257,12 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
}
|
||||
|
||||
private CGraphicsDevice getSimilarDevice(CGraphicsDevice old) {
|
||||
CGraphicsDevice sameId = devices.get(old.getDisplayID());
|
||||
if (sameId != null) {
|
||||
return sameId;
|
||||
}
|
||||
for (CGraphicsDevice device : devices.values()) {
|
||||
if (device.getBounds().equals(old.getBounds())) {
|
||||
// for now we will use the bounds only
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,4 +640,30 @@ public abstract class MTLSurfaceData extends SurfaceData
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads native image raster into surface.
|
||||
*
|
||||
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
|
||||
* Note: The color data in this image is considered to be premultiplied with alpha.
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
|
||||
* Note: can be null (then whole image used)
|
||||
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
|
||||
*/
|
||||
@Override
|
||||
protected void loadNativeRaster(long pRaster, int width, int height, long pRects, int rectsCount) {
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
MTLContext.setScratchSurface(getMTLGraphicsConfig());
|
||||
rq.flushAndInvokeNow(() -> loadNativeRasterWithRects(getNativeOps(), pRaster, width, height, pRects, rectsCount));
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
markDirty();
|
||||
}
|
||||
|
||||
private static native boolean loadNativeRasterWithRects(long sdops, long pRaster, int width, int height, long pRects, int rectsCount);
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ import javax.accessibility.AccessibleTable;
|
||||
import javax.accessibility.AccessibleText;
|
||||
import javax.accessibility.AccessibleValue;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.JLabel;
|
||||
@@ -1162,4 +1163,18 @@ class CAccessibility implements PropertyChangeListener {
|
||||
return ac == null ? null : AccessibleComponentAccessor.getAccessible(ac);
|
||||
}, c);
|
||||
}
|
||||
|
||||
private static boolean isComboBoxEditable(Accessible a, Component c) {
|
||||
if (a == null) return false;
|
||||
|
||||
return invokeAndWait(new Callable<Boolean>() {
|
||||
public Boolean call() throws Exception {
|
||||
Accessible sa = CAccessible.getSwingAccessible(a);
|
||||
if (sa instanceof JComboBox<?> comboBox) {
|
||||
return comboBox.isEditable();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
private static native void treeNodeCollapsed(long ptr);
|
||||
private static native void selectedCellsChanged(long ptr);
|
||||
private static native void tableContentCacheClear(long ptr);
|
||||
private static native void updateZoomCaretFocus(long ptr);
|
||||
|
||||
private Accessible accessible;
|
||||
|
||||
@@ -132,6 +133,8 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
Object oldValue = e.getOldValue();
|
||||
if (name.equals(ACCESSIBLE_CARET_PROPERTY)) {
|
||||
execute(ptr -> selectedTextChanged(ptr));
|
||||
// Notify macOS Accessibility Zoom to move focus to the new caret location.
|
||||
execute(ptr -> updateZoomCaretFocus(ptr));
|
||||
} else if (name.equals(ACCESSIBLE_TEXT_PROPERTY)) {
|
||||
execute(ptr -> valueChanged(ptr));
|
||||
} else if (name.equals(ACCESSIBLE_SELECTION_PROPERTY)) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.awt.Component;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
@@ -343,4 +344,33 @@ class CAccessibleText {
|
||||
|
||||
return new int[] { line.getStartOffset(), line.getEndOffset() };
|
||||
}
|
||||
|
||||
static double[] getCaretRectangle(final Accessible a, final Component c) {
|
||||
final double[] ret = new double[4];
|
||||
|
||||
if (a == null) return null;
|
||||
|
||||
return CAccessibility.invokeAndWait(new Callable<double[]>() {
|
||||
public double[] call() throws Exception {
|
||||
final Accessible sa = CAccessible.getSwingAccessible(a);
|
||||
if (!(sa instanceof Component)) return null;
|
||||
|
||||
final Component component = (Component) sa;
|
||||
|
||||
final InputMethodRequests imr = component.getInputMethodRequests();
|
||||
if (imr == null) return null;
|
||||
|
||||
final Rectangle caretRectangle = imr.getTextLocation(null);
|
||||
|
||||
if (caretRectangle == null) return null;
|
||||
|
||||
ret[0] = caretRectangle.getX();
|
||||
ret[1] = caretRectangle.getY();
|
||||
ret[2] = 1; // Use 1 as caret width.
|
||||
ret[3] = caretRectangle.getHeight();
|
||||
|
||||
return ret;
|
||||
}
|
||||
}, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,6 +235,8 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
*/
|
||||
public void activate() {
|
||||
isActive = true;
|
||||
|
||||
enableListening(true);
|
||||
}
|
||||
|
||||
public void deactivate(boolean isTemporary) {
|
||||
@@ -267,6 +269,7 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
if (fAwtFocussedComponentPeer != null) {
|
||||
long modelPtr = getNativeViewPtr(fAwtFocussedComponentPeer);
|
||||
nativeEndComposition(modelPtr, fAwtFocussedComponent);
|
||||
nativeEnableListening(modelPtr, false);
|
||||
nativeNotifyPeer(modelPtr, null);
|
||||
}
|
||||
|
||||
@@ -309,6 +312,11 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopListening() {
|
||||
enableListening(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.awt.Toolkit#mapInputMethodHighlight
|
||||
*/
|
||||
@@ -414,6 +422,16 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void enableListening(boolean enable) {
|
||||
if (fAwtFocussedComponentPeer != null) {
|
||||
final long modelPtr = getNativeViewPtr(fAwtFocussedComponentPeer);
|
||||
|
||||
if (modelPtr != 0) {
|
||||
nativeEnableListening(modelPtr, enable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =========================== NSTextInput callbacks ===========================
|
||||
// The 'marked text' that we get from Cocoa. We need to track this separately, since
|
||||
// Java doesn't let us ask the IM context for it.
|
||||
@@ -810,6 +828,13 @@ public class CInputMethod extends InputMethodAdapter {
|
||||
private native void nativeEndComposition(long nativePeer, Component component);
|
||||
private native void nativeHandleEvent(LWComponentPeer<?, ?> peer, AWTEvent event);
|
||||
|
||||
/*
|
||||
* Passing false to the second parameter disables any interaction with
|
||||
* the AppKit text input management subsystem (i.e. input methods, dead keys, maybe smth else)
|
||||
* Passing true there enables it back
|
||||
*/
|
||||
private native void nativeEnableListening(long nativePeerTarget, boolean enable);
|
||||
|
||||
// Returns the locale of the active input method.
|
||||
static native Locale getNativeLocale();
|
||||
|
||||
|
||||
@@ -143,9 +143,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
|
||||
private static native String[] getKeyboardLayoutListNative(boolean includeAll);
|
||||
|
||||
private static native boolean enableKeyboardLayoutNative(String layoutName);
|
||||
|
||||
private static native boolean disableKeyboardLayoutNative(String layoutName);
|
||||
private static native boolean setKeyboardLayoutEnabledNative(String layoutName, boolean enabled);
|
||||
|
||||
public static void switchKeyboardLayout (String layoutName) {
|
||||
if (layoutName == null || layoutName.isEmpty()) {
|
||||
@@ -172,7 +170,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
if (layoutName == null || layoutName.isEmpty()) {
|
||||
throw new RuntimeException("A valid layout ID is expected. Found: " + layoutName);
|
||||
}
|
||||
if (!enableKeyboardLayoutNative(layoutName)) {
|
||||
if (!setKeyboardLayoutEnabledNative(layoutName, true)) {
|
||||
throw new RuntimeException("Couldn't enable layout " + layoutName);
|
||||
}
|
||||
}
|
||||
@@ -181,7 +179,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
if (layoutName == null || layoutName.isEmpty()) {
|
||||
throw new RuntimeException("A valid layout ID is expected. Found: " + layoutName);
|
||||
}
|
||||
if (!disableKeyboardLayoutNative(layoutName)) {
|
||||
if (!setKeyboardLayoutEnabledNative(layoutName, false)) {
|
||||
throw new RuntimeException("Couldn't disable layout " + layoutName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,6 +493,14 @@ TISInputSourceRef GetCurrentUnderlyingLayout(BOOL useNationalLayouts) {
|
||||
CFBooleanGetValue((CFBooleanRef) TISGetInputSourceProperty(currentLayout, kTISPropertyInputSourceIsASCIICapable));
|
||||
TISInputSourceRef underlyingLayout = (!useNationalLayouts || currentAscii) ? currentLayout : nil;
|
||||
|
||||
if (currentLayout) {
|
||||
if (underlyingLayout) {
|
||||
CFAutorelease(currentLayout);
|
||||
} else {
|
||||
CFRelease(currentLayout);
|
||||
}
|
||||
}
|
||||
|
||||
return underlyingLayout;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
// Input method data
|
||||
jobject fInputMethodLOCKABLE;
|
||||
BOOL fInputMethodInteractionEnabled;
|
||||
BOOL fKeyEventsNeeded;
|
||||
BOOL fProcessingKeystroke;
|
||||
NSString* actualCharacters;
|
||||
@@ -68,5 +69,6 @@
|
||||
// Input method-related events
|
||||
- (void)setInputMethod:(jobject)inputMethod;
|
||||
- (void)abandonInput:(jobject) component;
|
||||
- (void)enableImInteraction:(BOOL)enabled;
|
||||
|
||||
@end
|
||||
|
||||
@@ -85,6 +85,7 @@ extern bool isSystemShortcut_NextWindowInApplication(NSUInteger modifiersMask, i
|
||||
|
||||
m_cPlatformView = cPlatformView;
|
||||
fInputMethodLOCKABLE = NULL;
|
||||
fInputMethodInteractionEnabled = YES;
|
||||
fKeyEventsNeeded = NO;
|
||||
fProcessingKeystroke = NO;
|
||||
|
||||
@@ -366,7 +367,9 @@ static void debugPrintNSEvent(NSEvent* event, const char* comment) {
|
||||
NSString *eventCharacters = [event characters];
|
||||
|
||||
// Allow TSM to look at the event and potentially send back NSTextInputClient messages.
|
||||
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
|
||||
if (fInputMethodInteractionEnabled == YES) {
|
||||
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
|
||||
}
|
||||
|
||||
if (fEnablePressAndHold && [event willBeHandledByComplexInputMethod] &&
|
||||
fInputMethodLOCKABLE)
|
||||
@@ -1577,6 +1580,17 @@ static jclass jc_CInputMethod = NULL;
|
||||
[self unmarkText:component];
|
||||
}
|
||||
|
||||
-(void)enableImInteraction:(BOOL)enabled
|
||||
{
|
||||
#ifdef IM_DEBUG
|
||||
fprintf(stderr, "AWTView InputMethod Selector Called : [enableImInteraction:%d]\n", enabled);
|
||||
#endif // IM_DEBUG
|
||||
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
fInputMethodInteractionEnabled = (enabled == YES) ? YES : NO;
|
||||
}
|
||||
|
||||
/******************************** END NSTextInputClient Protocol ********************************/
|
||||
|
||||
- (void)viewDidChangeBackingProperties {
|
||||
|
||||
@@ -1029,6 +1029,8 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
(*env)->DeleteLocalRef(env, platformWindow);
|
||||
|
||||
[AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows];
|
||||
|
||||
[self updateFullScreenButtons];
|
||||
}
|
||||
|
||||
- (void)windowDidMove:(NSNotification *)notification {
|
||||
@@ -1421,10 +1423,12 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
[self updateCustomTitleBarInsets:NO];
|
||||
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
NSString *newFullScreeControls = [PropertiesUtilities
|
||||
NSString *newFullScreenControls1 = [PropertiesUtilities
|
||||
javaSystemPropertyForKey:@"apple.awt.newFullScreeControls" withEnv:env];
|
||||
if ([@"true" isCaseInsensitiveLike:newFullScreeControls]) {
|
||||
[self setWindowFullScreeControls];
|
||||
NSString *newFullScreenControls2 = [PropertiesUtilities
|
||||
javaSystemPropertyForKey:@"apple.awt.newFullScreenControls" withEnv:env];
|
||||
if ([@"true" isCaseInsensitiveLike:newFullScreenControls1] || [@"true" isCaseInsensitiveLike:newFullScreenControls2]) {
|
||||
[self setWindowFullScreenControls];
|
||||
}
|
||||
}
|
||||
[self allowMovingChildrenBetweenSpaces:NO];
|
||||
@@ -1472,7 +1476,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
}
|
||||
|
||||
- (void)windowDidExitFullScreen:(NSNotification *)notification {
|
||||
[self resetWindowFullScreeControls];
|
||||
[self resetWindowFullScreenControls];
|
||||
|
||||
self.isEnterFullScreen = NO;
|
||||
|
||||
@@ -1734,7 +1738,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
[self.nsWindow standardWindowButton:NSWindowMiniaturizeButton].hidden = hidden;
|
||||
}
|
||||
|
||||
- (void) setWindowFullScreeControls {
|
||||
- (void) setWindowFullScreenControls {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
NSString *dfmMode = [PropertiesUtilities javaSystemPropertyForKey:@"apple.awt.distraction.free.mode" withEnv:env];
|
||||
if ([@"true" isCaseInsensitiveLike:dfmMode]) {
|
||||
@@ -1802,21 +1806,19 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
- (void)updateFullScreenButtons: (BOOL) dfm {
|
||||
if (dfm) {
|
||||
if (_fullScreenButtons == nil || _fullScreenOriginalButtons == nil) {
|
||||
NSLog(@"WARNING: updateFullScreenButtons after dfm open but _fullScreenButtons == nil");
|
||||
return;
|
||||
}
|
||||
[_fullScreenOriginalButtons.window.contentView setHidden:NO];
|
||||
[self resetWindowFullScreeControls];
|
||||
[self resetWindowFullScreenControls];
|
||||
} else {
|
||||
if (_fullScreenButtons != nil) {
|
||||
NSLog(@"WARNING: updateFullScreenButtons after dfm exit but _fullScreenButtons != nil");
|
||||
if (!self.isCustomTitleBarEnabled || _fullScreenButtons != nil) {
|
||||
return;
|
||||
}
|
||||
[self setWindowFullScreeControls];
|
||||
[self setWindowFullScreenControls];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) resetWindowFullScreeControls {
|
||||
- (void) resetWindowFullScreenControls {
|
||||
if (_fullScreenButtons != nil) {
|
||||
[_fullScreenButtons removeFromSuperview];
|
||||
_fullScreenButtons = nil;
|
||||
@@ -1869,6 +1871,8 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
} else {
|
||||
[self resetCustomTitleBar];
|
||||
}
|
||||
} else {
|
||||
[self updateFullScreenButtons];
|
||||
}
|
||||
} else if (enabled) {
|
||||
[self updateCustomTitleBarConstraints];
|
||||
@@ -2690,6 +2694,7 @@ void enableFullScreenSpecial(NSWindow *nsWindow) {
|
||||
[nsWindow encodeRestorableStateWithCoder:coder];
|
||||
[coder encodeBool:YES forKey:@"NSIsFullScreen"];
|
||||
NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:coder.encodedData];
|
||||
decoder.requiresSecureCoding = YES;
|
||||
[nsWindow restoreStateWithCoder:decoder];
|
||||
[decoder finishDecoding];
|
||||
[decoder release];
|
||||
@@ -2936,6 +2941,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetRoundedCor
|
||||
w.contentView.wantsLayer = YES;
|
||||
w.contentView.layer.cornerRadius = radius;
|
||||
w.contentView.layer.masksToBounds = YES;
|
||||
w.contentView.layer.opaque = NO;
|
||||
|
||||
if (borderWidth > 0) {
|
||||
CGFloat alpha = (((borderRgb >> 24) & 0xff) / 255.0);
|
||||
|
||||
@@ -199,6 +199,30 @@ JNI_COCOA_ENTER(env);
|
||||
JNI_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CInputMethod
|
||||
* Method: nativeEnableListening
|
||||
* Signature: (JZ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CInputMethod_nativeEnableListening
|
||||
(JNIEnv *env, jobject this, jlong nativePeer, jboolean enable)
|
||||
{
|
||||
|
||||
JNI_COCOA_ENTER(env);
|
||||
|
||||
AWTView * const view = (AWTView *)jlong_to_ptr(nativePeer);
|
||||
if (view == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
|
||||
[view enableImInteraction:(enable == JNI_TRUE ? YES : NO)];
|
||||
}];
|
||||
|
||||
JNI_COCOA_EXIT(env);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CInputMethod
|
||||
* Method: getNativeLocale
|
||||
|
||||
@@ -1045,14 +1045,18 @@ Java_sun_lwawt_macosx_LWCToolkit_setJavaEventsDispatchingOnMainThread(JNIEnv *en
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL
|
||||
JNICALL Java_sun_lwawt_macosx_LWCToolkit_getKeyboardLayoutNativeId(JNIEnv *env, jclass cls) {
|
||||
__block NSString * layoutId = NULL;
|
||||
jstring jLayoutId = NULL;
|
||||
JNI_COCOA_ENTER(env);
|
||||
__block CFStringRef layoutId = nil;
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
TISInputSourceRef source = TISCopyCurrentKeyboardInputSource();
|
||||
layoutId = TISGetInputSourceProperty(source, kTISPropertyInputSourceID);
|
||||
layoutId = (CFStringRef)CFRetain(TISGetInputSourceProperty(source, kTISPropertyInputSourceID));
|
||||
CFRelease(source);
|
||||
}];
|
||||
jLayoutId = NSStringToJavaString(env, (NSString*)layoutId);
|
||||
CFRelease(layoutId);
|
||||
JNI_COCOA_EXIT(env);
|
||||
return NSStringToJavaString(env, layoutId);
|
||||
return jLayoutId;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1062,19 +1066,31 @@ JNICALL Java_sun_lwawt_macosx_LWCToolkit_getKeyboardLayoutNativeId(JNIEnv *env,
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
JNICALL Java_sun_lwawt_macosx_LWCToolkit_switchKeyboardLayoutNative(JNIEnv *env, jclass cls, jstring jLayoutId) {
|
||||
__block OSStatus status = noErr;
|
||||
__block bool success = false;
|
||||
JNI_COCOA_ENTER(env);
|
||||
__block NSString* layoutId = JavaStringToNSString(env, jLayoutId);
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
NSArray* sources = CFBridgingRelease(TISCreateInputSourceList((__bridge CFDictionaryRef)@{ (__bridge NSString*)kTISPropertyInputSourceID : layoutId }, FALSE));
|
||||
TISInputSourceRef source = (__bridge TISInputSourceRef)sources[0];
|
||||
status = TISSelectInputSource(source);
|
||||
if (status != noErr) {
|
||||
NSDictionary* searchParam = @{ (NSString*)kTISPropertyInputSourceID : layoutId };
|
||||
CFArrayRef sources = TISCreateInputSourceList((CFDictionaryRef)searchParam, NO);
|
||||
|
||||
if (CFArrayGetCount(sources) == 0) {
|
||||
NSLog(@"failed to switch to keyboard layout %@: no such layout", layoutId);
|
||||
CFRelease(sources);
|
||||
return;
|
||||
}
|
||||
|
||||
TISInputSourceRef source = (TISInputSourceRef)CFArrayGetValueAtIndex(sources, 0);
|
||||
OSStatus status = TISSelectInputSource(source);
|
||||
if (status == noErr) {
|
||||
success = true;
|
||||
} else {
|
||||
NSLog(@"failed to switch to keyboard layout %@, error code %d", layoutId, status);
|
||||
}
|
||||
|
||||
CFRelease(sources);
|
||||
}];
|
||||
JNI_COCOA_EXIT(env);
|
||||
return status == noErr;
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1084,66 +1100,66 @@ JNICALL Java_sun_lwawt_macosx_LWCToolkit_switchKeyboardLayoutNative(JNIEnv *env,
|
||||
*/
|
||||
JNIEXPORT jarray JNICALL
|
||||
JNICALL Java_sun_lwawt_macosx_LWCToolkit_getKeyboardLayoutListNative(JNIEnv *env, jclass cls, jboolean includeAll) {
|
||||
__block jarray out = NULL;
|
||||
jclass stringClazz = (*env)->FindClass(env, "java/lang/String");
|
||||
jarray out = NULL;
|
||||
JNI_COCOA_ENTER(env);
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
NSArray* sources = CFBridgingRelease(TISCreateInputSourceList(nil, includeAll));
|
||||
int numOfSources = (int)[sources count];
|
||||
out = (*env)->NewObjectArray(env, numOfSources, stringClazz, NULL);
|
||||
for (int i = 0; i < numOfSources; ++i) {
|
||||
id layout = [sources objectAtIndex:i];
|
||||
NSString* layoutId = TISGetInputSourceProperty((TISInputSourceRef)layout, kTISPropertyInputSourceID);
|
||||
jstring layoutIdJava = NSStringToJavaString(env, layoutId);
|
||||
(*env)->SetObjectArrayElement(env, out, i, layoutIdJava);
|
||||
__block NSMutableArray* layoutIds = [[[NSMutableArray alloc] init] autorelease];
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
CFArrayRef sources = TISCreateInputSourceList(nil, includeAll);
|
||||
int numSources = CFArrayGetCount(sources);
|
||||
|
||||
for (int i = 0; i < numSources; ++i) {
|
||||
TISInputSourceRef layout = CFArrayGetValueAtIndex(sources, i);
|
||||
NSString* sourceId = TISGetInputSourceProperty(layout, kTISPropertyInputSourceID);
|
||||
[layoutIds addObject:sourceId];
|
||||
}
|
||||
|
||||
CFRelease(sources);
|
||||
}];
|
||||
|
||||
int numLayoutIds = (int)[layoutIds count];
|
||||
out = (*env)->NewObjectArray(env, numLayoutIds, stringClazz, NULL);
|
||||
for (int i = 0; i < numLayoutIds; ++i) {
|
||||
NSString* layoutId = [layoutIds objectAtIndex:i];
|
||||
jstring jLayoutId = NSStringToJavaString(env, layoutId);
|
||||
(*env)->SetObjectArrayElement(env, out, i, jLayoutId);
|
||||
}
|
||||
}];
|
||||
JNI_COCOA_EXIT(env);
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_LWCToolkit
|
||||
* Method: enableKeyboardLayoutNative
|
||||
* Signature: (Ljava/lang/String;)V
|
||||
* Method: setKeyboardLayoutEnabledNative
|
||||
* Signature: (Ljava/lang/String;Z)V
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
JNICALL Java_sun_lwawt_macosx_LWCToolkit_enableKeyboardLayoutNative(JNIEnv *env, jclass cls, jstring jLayoutId) {
|
||||
__block OSStatus status = noErr;
|
||||
JNICALL Java_sun_lwawt_macosx_LWCToolkit_setKeyboardLayoutEnabledNative(JNIEnv *env, jclass cls, jstring jLayoutId, jboolean enabled) {
|
||||
__block bool success = false;
|
||||
JNI_COCOA_ENTER(env);
|
||||
__block NSString* layoutId = JavaStringToNSString(env, jLayoutId);
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
NSArray* sources = CFBridgingRelease(TISCreateInputSourceList((__bridge CFDictionaryRef)@{ (__bridge NSString*)kTISPropertyInputSourceID : layoutId }, YES));
|
||||
TISInputSourceRef source = (__bridge TISInputSourceRef)sources[0];
|
||||
status = TISEnableInputSource(source);
|
||||
if (status != noErr) {
|
||||
NSLog(@"failed to enable keyboard layout %@, error code %d", layoutId, status);
|
||||
}
|
||||
}];
|
||||
JNI_COCOA_EXIT(env);
|
||||
return status == noErr;
|
||||
}
|
||||
NSDictionary* searchParam = @{ (NSString*)kTISPropertyInputSourceID : layoutId };
|
||||
CFArrayRef sources = TISCreateInputSourceList((CFDictionaryRef)searchParam, YES);
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_LWCToolkit
|
||||
* Method: disableKeyboardLayoutNative
|
||||
* Signature: (Ljava/lang/String;)V
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
JNICALL Java_sun_lwawt_macosx_LWCToolkit_disableKeyboardLayoutNative(JNIEnv *env, jclass cls, jstring jLayoutId) {
|
||||
__block OSStatus status = noErr;
|
||||
JNI_COCOA_ENTER(env);
|
||||
__block NSString* layoutId = JavaStringToNSString(env, jLayoutId);
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
NSArray* sources = CFBridgingRelease(TISCreateInputSourceList((__bridge CFDictionaryRef)@{ (__bridge NSString*)kTISPropertyInputSourceID : layoutId }, YES));
|
||||
TISInputSourceRef source = (__bridge TISInputSourceRef)sources[0];
|
||||
status = TISDisableInputSource(source);
|
||||
if (status != noErr) {
|
||||
NSLog(@"failed to disable keyboard layout %@, error code %d", layoutId, status);
|
||||
if (CFArrayGetCount(sources) == 0) {
|
||||
NSLog(@"failed to set keyboard layout %@ enabled state: no such layout", layoutId);
|
||||
CFRelease(sources);
|
||||
return;
|
||||
}
|
||||
|
||||
TISInputSourceRef source = (TISInputSourceRef)CFArrayGetValueAtIndex(sources, 0);
|
||||
OSStatus status = enabled ? TISEnableInputSource(source) : TISDisableInputSource(source);
|
||||
if (status == noErr) {
|
||||
success = true;
|
||||
} else {
|
||||
NSLog(@"failed to set keyboard layout %@ enabled state, error code %d", layoutId, status);
|
||||
}
|
||||
|
||||
CFRelease(sources);
|
||||
}];
|
||||
JNI_COCOA_EXIT(env);
|
||||
return status == noErr;
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -57,6 +57,18 @@ GET_CACCESSIBILITY_CLASS_RETURN(nil);
|
||||
return value;
|
||||
}
|
||||
|
||||
- (BOOL)isEditable
|
||||
{
|
||||
JNIEnv* env = [ThreadUtilities getJNIEnv];
|
||||
GET_CACCESSIBILITY_CLASS_RETURN(NO);
|
||||
DECLARE_STATIC_METHOD_RETURN(sjm_isComboBoxEditable, sjc_CAccessibility, "isComboBoxEditable", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Z", NO);
|
||||
|
||||
BOOL isEditable = (*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, sjm_isComboBoxEditable, fAccessible, fComponent);
|
||||
CHECK_EXCEPTION();
|
||||
|
||||
return isEditable;
|
||||
}
|
||||
|
||||
// NSAccessibilityElement protocol methods
|
||||
|
||||
- (id)accessibilityValue
|
||||
@@ -66,12 +78,10 @@ GET_CACCESSIBILITY_CLASS_RETURN(nil);
|
||||
if (expanded) {
|
||||
return nil;
|
||||
}
|
||||
if (!expanded &&
|
||||
(value == nil)) {
|
||||
[self accessibleSelection];
|
||||
}
|
||||
|
||||
return [value accessibilityLabel];
|
||||
[self accessibleSelection];
|
||||
|
||||
return value != nil ? [value accessibilityLabel] : nil;
|
||||
}
|
||||
|
||||
- (NSArray *)accessibilitySelectedChildren
|
||||
@@ -79,6 +89,13 @@ GET_CACCESSIBILITY_CLASS_RETURN(nil);
|
||||
return [NSArray arrayWithObject:[self accessibleSelection]];
|
||||
}
|
||||
|
||||
- (NSAccessibilityRole)accessibilityRole
|
||||
{
|
||||
return [self isEditable]
|
||||
? NSAccessibilityComboBoxRole
|
||||
: NSAccessibilityPopUpButtonRole;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (value != nil) {
|
||||
|
||||
@@ -306,6 +306,49 @@ static jmethodID sjm_getAccessibleEditableText = NULL;
|
||||
return [super accessibilityParent];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CAccessible
|
||||
* Method: updateZoomCaretFocus
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_updateZoomCaretFocus
|
||||
(JNIEnv *env, jclass jklass, jlong element)
|
||||
{
|
||||
if (!UAZoomEnabled()) return;
|
||||
|
||||
JNI_COCOA_ENTER(env);
|
||||
[ThreadUtilities performOnMainThread:@selector(postZoomChangeCaretFocus)
|
||||
on:(NavigableTextAccessibility *) jlong_to_ptr(element)
|
||||
withObject:nil
|
||||
waitUntilDone:NO];
|
||||
JNI_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
- (void)postZoomChangeCaretFocus
|
||||
{
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
if (![self isEqual:[NSApp accessibilityFocusedUIElement]]) return;
|
||||
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
|
||||
GET_CACCESSIBLETEXT_CLASS();
|
||||
DECLARE_STATIC_METHOD(jm_getCaretRectangle, sjc_CAccessibleText, "getCaretRectangle",
|
||||
"(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[D");
|
||||
jdoubleArray axCaretBounds = (jdoubleArray) (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
|
||||
jm_getCaretRectangle, fAccessible,
|
||||
fComponent);
|
||||
CHECK_EXCEPTION();
|
||||
if (axCaretBounds == NULL) return;
|
||||
|
||||
jdouble *values = (*env)->GetDoubleArrayElements(env, axCaretBounds, NULL);
|
||||
CGRect caretRect = CGRectMake(values[0], values[1], values[2], values[3]);
|
||||
(*env)->ReleaseDoubleArrayElements(env, axCaretBounds, values, JNI_ABORT);
|
||||
|
||||
UAZoomChangeFocus(&caretRect, &caretRect, kUAZoomFocusTypeInsertionPoint);
|
||||
}
|
||||
|
||||
/*
|
||||
* Other text methods
|
||||
- (NSRange)accessibilitySharedCharacterRange;
|
||||
|
||||
@@ -240,6 +240,23 @@ replaceTextureRegion(MTLContext *mtlc, id<MTLTexture> dest, const SurfaceDataRas
|
||||
}
|
||||
}
|
||||
|
||||
void replaceTexture(MTLContext *mtlc, id<MTLTexture> dest, void* pRaster, int width, int height, int dx1, int dy1, int dx2, int dy2) {
|
||||
MTLRasterFormatInfo rfi = RasterFormatInfos[0];
|
||||
|
||||
SurfaceDataRasInfo srcInfo;
|
||||
memset(&srcInfo, 0, sizeof(SurfaceDataRasInfo));
|
||||
srcInfo.bounds.x1 = dx1;
|
||||
srcInfo.bounds.y1 = dy1;
|
||||
srcInfo.bounds.x2 = dx2;
|
||||
srcInfo.bounds.y2 = dy2;
|
||||
srcInfo.scanStride = width*4;
|
||||
srcInfo.pixelStride = 4;
|
||||
srcInfo.rasBase = pRaster;
|
||||
srcInfo.pixelBitOffset = 0;
|
||||
|
||||
replaceTextureRegion(mtlc, dest, &srcInfo, &rfi, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner loop used for copying a source system memory ("Sw") surface to a
|
||||
* destination MTL "Surface". This method is invoked from
|
||||
|
||||
@@ -348,6 +348,8 @@ Java_sun_java2d_metal_MTLSurfaceData_initOps
|
||||
}
|
||||
}
|
||||
|
||||
extern void replaceTexture(MTLContext *mtlc, id<MTLTexture> dest, void* pRaster, int width, int height, int dx1, int dy1, int dx2, int dy2);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLSurfaceData_clearWindow
|
||||
(JNIEnv *env, jobject mtlsd)
|
||||
@@ -362,6 +364,43 @@ Java_sun_java2d_metal_MTLSurfaceData_clearWindow
|
||||
mtlsdo->layer = NULL;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_java2d_metal_MTLSurfaceData_loadNativeRasterWithRects
|
||||
(JNIEnv *env, jclass clazz,
|
||||
jlong sdops, jlong pRaster, jint width, jint height, jlong pRects, jint rectsCount)
|
||||
{
|
||||
BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(sdops);
|
||||
if (dstOps == NULL || pRaster == 0) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_loadNativeRasterWithRects: params are null");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
id<MTLTexture> dest = dstOps->pTexture;
|
||||
if (dest == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_loadNativeRasterWithRects: dest is null");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
MTLSDOps *dstMTLOps = (MTLSDOps *)dstOps->privOps;
|
||||
MTLContext *ctx = dstMTLOps->configInfo->context;
|
||||
if (pRects == 0 || rectsCount < 1) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLSurfaceData_loadNativeRasterWithRects: do full copy of raster:");
|
||||
replaceTexture(ctx, dest, (void*)pRaster, (int)width, (int)height, 0, 0, (int)width, (int)height);
|
||||
} else {
|
||||
int32_t *pr = (int32_t *) pRects;
|
||||
for (int c = 0; c < rectsCount; ++c) {
|
||||
int32_t x = *(pr++);
|
||||
int32_t y = *(pr++);
|
||||
int32_t w = *(pr++);
|
||||
int32_t h = *(pr++);
|
||||
//fprintf(stderr, "MTLSurfaceData_loadNativeRasterWithRects: process rect %d %d %d %d\n", x, y, w, h);
|
||||
replaceTexture(ctx, dest, (void*)pRaster, (int)width, (int)height, x, y, x + w, y + h);
|
||||
}
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
NSString * getSurfaceDescription(const BMTLSDOps * bmtlsdOps) {
|
||||
if (bmtlsdOps == NULL)
|
||||
return @"NULL";
|
||||
|
||||
@@ -63,6 +63,9 @@ public class JBRApiModule {
|
||||
.withStatic("getFeaturesAsString", "getFeaturesAsString", "com.jetbrains.desktop.FontExtensions")
|
||||
.clientProxy("java.awt.Font$Features", "com.jetbrains.FontExtensions$Features")
|
||||
.service("com.jetbrains.WindowMove", "java.awt.Window$WindowMoveService")
|
||||
.service("com.jetbrains.NativeRasterLoader")
|
||||
.withStatic("loadNativeRaster", "loadNativeRaster", "com.jetbrains.desktop.NativeRasterLoader")
|
||||
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.jetbrains.desktop;
|
||||
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
|
||||
import java.awt.image.VolatileImage;
|
||||
|
||||
class NativeRasterLoader {
|
||||
/**
|
||||
* Loads native image raster into VolatileImage
|
||||
*
|
||||
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
|
||||
* Note: The color data in this image is considered to be premultiplied with alpha.
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
|
||||
* Note: can be null (then whole image used)
|
||||
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
|
||||
*/
|
||||
static void loadNativeRaster(VolatileImage vi, long pRaster, int width, int height, long pRects, int rectsCount) {
|
||||
if (!(vi instanceof SunVolatileImage)) {
|
||||
System.err.printf("Unsupported type of VolatileImage: %s\n", vi);
|
||||
return;
|
||||
}
|
||||
|
||||
SunVolatileImage svi = (SunVolatileImage)vi;
|
||||
sun.java2d.NativeRasterLoader.loadNativeRaster(svi.getDestSurface(), pRaster, width, height, pRects, rectsCount);
|
||||
}
|
||||
}
|
||||
@@ -347,6 +347,13 @@ public abstract class Component implements ImageObserver, MenuContainer,
|
||||
*/
|
||||
private transient volatile GraphicsConfiguration graphicsConfig;
|
||||
|
||||
/**
|
||||
* Last observed value of {@code graphicsConfig.getDefaultTransform()}.
|
||||
* Used for firing 'graphicsContextScaleTransform' property change,
|
||||
* as values returned by {@link #graphicsConfig} may change over time.
|
||||
*/
|
||||
private transient volatile AffineTransform lastGraphicsConfigTransform;
|
||||
|
||||
/**
|
||||
* A reference to a {@code BufferStrategy} object
|
||||
* used to manipulate the buffers on this component.
|
||||
@@ -1208,13 +1215,17 @@ public abstract class Component implements ImageObserver, MenuContainer,
|
||||
return false;
|
||||
}
|
||||
|
||||
AffineTransform tx = graphicsConfig != null ? graphicsConfig.getDefaultTransform() : new AffineTransform();
|
||||
AffineTransform tx = lastGraphicsConfigTransform;
|
||||
AffineTransform newTx = gc != null ? gc.getDefaultTransform() : new AffineTransform();
|
||||
graphicsConfig = gc;
|
||||
if (tx.getScaleX() != newTx.getScaleX() ||
|
||||
tx.getScaleY() != newTx.getScaleY())
|
||||
// We cannot rely on graphicsConfig.getDefaultTransform(),
|
||||
// because its device might have been invalidated and now
|
||||
// reports different scale than it did before.
|
||||
if (!newTx.equals(lastGraphicsConfigTransform))
|
||||
{
|
||||
firePropertyChange("graphicsContextScaleTransform", tx, newTx);
|
||||
lastGraphicsConfigTransform = newTx;
|
||||
firePropertyChange("graphicsContextScaleTransform",
|
||||
tx != null ? tx : new AffineTransform(), newTx);
|
||||
}
|
||||
|
||||
ComponentPeer peer = this.peer;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package sun.java2d;
|
||||
|
||||
public class NativeRasterLoader {
|
||||
/**
|
||||
* Loads native image raster into surface.
|
||||
*
|
||||
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
|
||||
* Note: The color data in this image is considered to be premultiplied with alpha.
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
|
||||
* Note: can be null (then whole image used)
|
||||
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
|
||||
*/
|
||||
public static void loadNativeRaster(Surface surface, long pRaster, int width, int height, long pRects, int rectsCount) {
|
||||
if (surface instanceof SurfaceData) {
|
||||
SurfaceData sd = (SurfaceData)surface;
|
||||
sd.loadNativeRaster(pRaster, width, height, pRects, rectsCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1091,4 +1091,19 @@ public abstract class SurfaceData
|
||||
public double getDefaultScaleY() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads native image raster into surface.
|
||||
*
|
||||
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
|
||||
* Note: The color data in this image is considered to be premultiplied with alpha.
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
|
||||
* Note: can be null (then whole image used)
|
||||
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
|
||||
*/
|
||||
protected void loadNativeRaster(long pRaster, int width, int height, long pRects, int rectsCount) {
|
||||
System.err.println("ERROR: loadNativeRaster must be overriden.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,4 +654,30 @@ public abstract class OGLSurfaceData extends SurfaceData
|
||||
boolean isOnScreen() {
|
||||
return getType() == WINDOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads native image raster into surface.
|
||||
*
|
||||
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
|
||||
* Note: The color data in this image is considered to be premultiplied with alpha.
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
|
||||
* Note: can be null (then whole image used)
|
||||
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
|
||||
*/
|
||||
@Override
|
||||
protected void loadNativeRaster(long pRaster, int width, int height, long pRects, int rectsCount) {
|
||||
OGLRenderQueue rq = OGLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
OGLContext.setScratchSurface(getOGLGraphicsConfig());
|
||||
rq.flushAndInvokeNow(() -> loadNativeRasterWithRects(getNativeOps(), pRaster, width, height, pRects, rectsCount));
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
markDirty();
|
||||
}
|
||||
|
||||
private static native boolean loadNativeRasterWithRects(long sdops, long pRaster, int width, int height, long pRects, int rectsCount);
|
||||
}
|
||||
|
||||
@@ -238,6 +238,44 @@ OGLBlitSwToSurface(OGLContext *oglc, SurfaceDataRasInfo *srcInfo,
|
||||
}
|
||||
}
|
||||
|
||||
void OGLBlitRasterToSurface(OGLSDOps *dstOps, jlong pRaster, jint width, jint height,
|
||||
OGLPixelFormat *pf,
|
||||
jint sx1, jint sy1, jint sx2, jint sy2,
|
||||
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2) {
|
||||
SurfaceDataRasInfo srcInfo;
|
||||
memset(&srcInfo, 0, sizeof(SurfaceDataRasInfo));
|
||||
srcInfo.bounds.x1 = 0;
|
||||
srcInfo.bounds.y1 = 0;
|
||||
srcInfo.bounds.x2 = width;
|
||||
srcInfo.bounds.y2 = height;
|
||||
srcInfo.scanStride = width*4;
|
||||
srcInfo.pixelStride = 4;
|
||||
srcInfo.rasBase = (void*)pRaster;
|
||||
srcInfo.pixelBitOffset = 0;
|
||||
|
||||
unsigned char * r = (unsigned char *)pRaster;
|
||||
//fprintf(stderr, "OGLBlitRasterToSurface:%d,%d,%d,%d,%d,%d,%d,%d....\n", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
|
||||
|
||||
if (dstOps->drawableType == OGLSD_FBOBJECT) {
|
||||
// Note that we unbind the currently bound texture first; this is
|
||||
// recommended procedure when binding an fbobject
|
||||
j2d_glBindTexture(dstOps->textureTarget, 0);
|
||||
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);
|
||||
} else {
|
||||
J2dRlsTraceLn1(J2D_TRACE_ERROR, "Unsupported drawable type %d.", dstOps->drawableType);
|
||||
}
|
||||
|
||||
j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
||||
j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
|
||||
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, srcInfo.scanStride / srcInfo.pixelStride);
|
||||
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, pf->alignment);
|
||||
|
||||
OGLBlitSwToSurface(OGLRenderQueue_GetCurrentContext(), &srcInfo, pf, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
|
||||
|
||||
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner loop used for copying a source system memory ("Sw") surface or
|
||||
* OpenGL "Surface" to a destination OpenGL "Surface", using an OpenGL texture
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#ifndef HEADLESS
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sun_java2d_opengl_OGLSurfaceData.h"
|
||||
|
||||
@@ -41,6 +42,10 @@ extern jboolean OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo);
|
||||
extern void OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo);
|
||||
|
||||
void OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, jint w, jint h);
|
||||
extern void OGLBlitRasterToSurface(OGLSDOps *dstOps, jlong pRaster, jint width, jint height,
|
||||
OGLPixelFormat *pf,
|
||||
jint sx1, jint sy1, jint sx2, jint sy2,
|
||||
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2);
|
||||
|
||||
/**
|
||||
* This table contains the "pixel formats" for all system memory surfaces
|
||||
@@ -526,6 +531,74 @@ Java_sun_java2d_opengl_OGLSurfaceData_getTextureID
|
||||
return (jint)oglsdo->textureID;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_java2d_opengl_OGLSurfaceData_loadNativeRasterWithRects
|
||||
(JNIEnv *env, jclass clazz,
|
||||
jlong sdops, jlong pRaster, jint width, jint height, jlong pRects, jint rectsCount)
|
||||
{
|
||||
OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(sdops);
|
||||
if (oglsdo == NULL || pRaster == 0) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_loadNativeRasterWithRects: params are null");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
//fprintf(stderr, "OGLSurfaceData_loadNativeRasterWithRects: ops=%p r=%p rCount=%d tt=%d texId=%d\n", (void*)sdops, (void*)pRaster, rectsCount, oglsdo->textureTarget, oglsdo->textureID);
|
||||
|
||||
// Set state.
|
||||
OGLPixelFormat pf = PixelFormats[1];
|
||||
const int viaTexSubImage = oglsdo->drawableType != OGLSD_FBOBJECT;
|
||||
// NOTE: both types works correctly under OSX (probably need to choose the fastest one)
|
||||
if (viaTexSubImage) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "OGLSurfaceData_loadNativeRasterWithRects: via glTexSubImage2D");
|
||||
j2d_glEnable(GL_TEXTURE_2D);
|
||||
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
||||
j2d_glBindTexture(GL_TEXTURE_2D, oglsdo->textureID);
|
||||
} else {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "OGLSurfaceData_loadNativeRasterWithRects: via glDrawPix (i.e. OGLBlitSwToSurface)");
|
||||
}
|
||||
|
||||
// Render.
|
||||
if (pRects == 0 || rectsCount < 1) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "OGLSurfaceData_loadNativeRasterWithRects: do full copy of raster:");
|
||||
//unsigned char * r = (unsigned char *)pRaster;
|
||||
//fprintf(stderr, "\t %d,%d,%d,%d,%d,%d,%d,%d....\n", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
|
||||
if (viaTexSubImage) {
|
||||
j2d_glTexSubImage2D(oglsdo->textureTarget, 0,
|
||||
0, 0, width, height,
|
||||
pf.format, pf.type, (GLvoid*)pRaster);
|
||||
} else {
|
||||
OGLBlitRasterToSurface(oglsdo, pRaster, width, height, &pf,
|
||||
0, 0, width, height,
|
||||
0, 0, width, height); }
|
||||
} else {
|
||||
int32_t *pr = (int32_t *) pRects;
|
||||
for (int c = 0; c < rectsCount; ++c) {
|
||||
int32_t x = *(pr++);
|
||||
int32_t y = *(pr++);
|
||||
int32_t w = *(pr++);
|
||||
int32_t h = *(pr++);
|
||||
if (viaTexSubImage) {
|
||||
const GLvoid *srcBytes = (char *)pRaster + y*width*4 + x*4;
|
||||
//fprintf(stderr, "\t[%d, %d, %d, %d] %d\n", x, y, w, h, (int)((char*)srcBytes - (char*)pRaster));
|
||||
j2d_glTexSubImage2D(oglsdo->textureTarget, 0,
|
||||
x, y, w, h,
|
||||
pf.format, pf.type, srcBytes);
|
||||
} else {
|
||||
OGLBlitRasterToSurface(oglsdo, pRaster, width, height, &pf,
|
||||
x, y, x + w, y + h,
|
||||
x, y, x + w, y + h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore state.
|
||||
if (viaTexSubImage) {
|
||||
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes nativeWidth/Height fields of the surfaceData object with
|
||||
* passed arguments.
|
||||
|
||||
@@ -631,6 +631,27 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
updateSizeHints(dimensions);
|
||||
Rectangle client = dimensions.getClientRect();
|
||||
checkShellRect(client);
|
||||
|
||||
if (isTargetUndecorated() && this instanceof XFramePeer framePeer) {
|
||||
if (isMaximized()) {
|
||||
// Under Xorg, if an undecorated (read: client-side decorated)
|
||||
// window has been maximized (either vertically or horizontally),
|
||||
// it cannot change its size programmatically until both maximized
|
||||
// states have been cleared. And since the window is undecorated, it also
|
||||
// cannot change its size with the user's help because
|
||||
// "undecorated" means "no borders" and that, perhaps incorrectly, implies
|
||||
// that there's nothing to grab on in order to resize interactively.
|
||||
// To exit this viscous circle, drop the maximized state. This does have
|
||||
// unpleasant side effects (such as an animation played by the WM), but
|
||||
// those seem to be a lesser evil than the total inability to resize.
|
||||
int state = framePeer.getState();
|
||||
if ((state & Frame.MAXIMIZED_BOTH) != Frame.MAXIMIZED_BOTH) {
|
||||
state &= ~Frame.MAXIMIZED_BOTH;
|
||||
framePeer.setExtendedState(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setShellBounds(client);
|
||||
if (content != null &&
|
||||
!content.getSize().equals(newDimensions.getSize()))
|
||||
@@ -853,33 +874,28 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
|
||||
updateChildrenSizes();
|
||||
|
||||
WindowLocation newLocation = getNewLocation(xe);
|
||||
Dimension newDimension = new Dimension(xe.get_width(), xe.get_height());
|
||||
WindowLocation eventLocation = getNewLocation(xe);
|
||||
Dimension eventDimension = new Dimension(xe.get_width(), xe.get_height());
|
||||
boolean xinerama = XToolkit.localEnv.runningXinerama();
|
||||
|
||||
SunToolkit.executeOnEventHandlerThread(target, () -> {
|
||||
Point newUserLocation = newLocation.getUserLocation();
|
||||
WindowDimensions newDimensions = new WindowDimensions(newUserLocation,
|
||||
new Dimension(scaleDown(newDimension.width), scaleDown(newDimension.height)), getRealInsets(), true);
|
||||
|
||||
Point oldLocation = getLocation();
|
||||
Dimension newSize = xinerama
|
||||
? checkIfOnNewScreen(new Rectangle(eventLocation.getDeviceLocation(), eventDimension))
|
||||
: new Dimension(scaleDown(eventDimension.width), scaleDown(eventDimension.height));
|
||||
Point newUserLocation = eventLocation.getUserLocation();
|
||||
WindowDimensions newDimensions = new WindowDimensions(newUserLocation, newSize, getRealInsets(), true);
|
||||
if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
insLog.finer("Insets are {0}, new dimensions {1}",
|
||||
getRealInsets(), newDimensions);
|
||||
}
|
||||
|
||||
Point oldLocation = getLocation();
|
||||
dimensions = newDimensions;
|
||||
if (!newUserLocation.equals(oldLocation)) {
|
||||
handleMoved(newDimensions);
|
||||
}
|
||||
reconfigureContentWindow(newDimensions);
|
||||
updateChildrenSizes();
|
||||
|
||||
repositionSecurityWarning();
|
||||
|
||||
if (xinerama) {
|
||||
checkIfOnNewScreen(new Rectangle(newLocation.getDeviceLocation(), newDimension));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1423,20 +1439,23 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
if (r.width <= ins.left + ins.right || r.height <= ins.top + ins.bottom) {
|
||||
return;
|
||||
}
|
||||
if (syncSizeOnly && dimensions != null) {
|
||||
dimensions.setSize(r.width, r.height);
|
||||
dimensions.setInsets(ins);
|
||||
boolean isMaximized = target instanceof Frame f && (f.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
||||
// When a window is maximized, affirming its size through an explicit request to the X server
|
||||
// may make the window fullscreen, which has undesirable consequences. Also, when a window
|
||||
// already has the maximized attributes, it is already properly sized, so no need to
|
||||
// resize explicitly.
|
||||
if (!isMaximized) {
|
||||
xSetSize(r.width, r.height);
|
||||
|
||||
if (XWindowPeer.RESIZE_WITH_SCALE) {
|
||||
if (syncSizeOnly && dimensions != null) {
|
||||
dimensions.setSize(r.width, r.height);
|
||||
dimensions.setInsets(ins);
|
||||
boolean isMaximized = target instanceof Frame f && (f.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
||||
// When a window is maximized, affirming its size through an explicit request to the X server
|
||||
// may make the window fullscreen, which has undesirable consequences. Also, when a window
|
||||
// already has the maximized attributes, it is already properly sized, so no need to
|
||||
// resize explicitly.
|
||||
if (!isMaximized) {
|
||||
xSetSize(r.width, r.height);
|
||||
}
|
||||
} else {
|
||||
dimensions = new WindowDimensions(r, ins, false);
|
||||
xSetBounds(r.x, r.y, r.width, r.height);
|
||||
}
|
||||
} else {
|
||||
dimensions = new WindowDimensions(r, ins, false);
|
||||
xSetBounds(r.x, r.y, r.width, r.height);
|
||||
}
|
||||
reconfigureContentWindow(dimensions);
|
||||
doValidateSurface();
|
||||
|
||||
@@ -143,21 +143,24 @@ public class XEmbeddedFramePeer extends XFramePeer {
|
||||
xembedLog.fine(xe.toString());
|
||||
}
|
||||
|
||||
WindowLocation newLocation = getNewLocation(xe);
|
||||
Dimension newDimension = new Dimension(xe.get_width(), xe.get_height());
|
||||
WindowLocation eventLocation = getNewLocation(xe);
|
||||
Dimension eventDimension = new Dimension(xe.get_width(), xe.get_height());
|
||||
boolean xinerama = XToolkit.localEnv.runningXinerama();
|
||||
// fix for 5063031
|
||||
// if we use super.handleConfigureNotifyEvent() we would get wrong
|
||||
// size and position because embedded frame really is NOT a decorated one
|
||||
SunToolkit.executeOnEventHandlerThread(target, () -> {
|
||||
Point newUserLocation = newLocation.getUserLocation();
|
||||
Point newUserLocation = eventLocation.getUserLocation();
|
||||
Rectangle oldBounds = getBounds();
|
||||
Dimension newSize = xinerama
|
||||
? checkIfOnNewScreen(new Rectangle(eventLocation.getDeviceLocation(), eventDimension))
|
||||
: new Dimension(scaleDown(eventDimension.width), scaleDown(eventDimension.height));
|
||||
|
||||
synchronized (getStateLock()) {
|
||||
x = newUserLocation.x;
|
||||
y = newUserLocation.y;
|
||||
width = scaleDown(newDimension.width);
|
||||
height = scaleDown(newDimension.height);
|
||||
width = newSize.width;
|
||||
height = newSize.height;
|
||||
|
||||
dimensions.setClientSize(width, height);
|
||||
dimensions.setLocation(x, y);
|
||||
@@ -167,10 +170,6 @@ public class XEmbeddedFramePeer extends XFramePeer {
|
||||
handleMoved(dimensions);
|
||||
}
|
||||
reconfigureContentWindow(dimensions);
|
||||
|
||||
if (xinerama) {
|
||||
checkIfOnNewScreen(new Rectangle(newLocation.getDeviceLocation(), newDimension));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 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
|
||||
@@ -25,18 +26,29 @@
|
||||
|
||||
package sun.awt.X11;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
import java.awt.im.spi.InputMethodContext;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.X11GraphicsDevice;
|
||||
import sun.awt.X11InputMethod;
|
||||
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.CaretEvent;
|
||||
import javax.swing.event.CaretListener;
|
||||
import javax.swing.text.JTextComponent;
|
||||
|
||||
/**
|
||||
* Input Method Adapter for XIM (without Motif)
|
||||
*
|
||||
@@ -47,6 +59,7 @@ public class XInputMethod extends X11InputMethod {
|
||||
|
||||
public XInputMethod() throws AWTException {
|
||||
super();
|
||||
clientComponentCaretPositionTracker = new ClientComponentCaretPositionTracker(this);
|
||||
}
|
||||
|
||||
public void setInputMethodContext(InputMethodContext context) {
|
||||
@@ -58,8 +71,82 @@ public class XInputMethod extends X11InputMethod {
|
||||
if (peer != null) {
|
||||
adjustStatusWindow(peer.getContentWindow());
|
||||
}
|
||||
|
||||
if (doesSupportMovingCandidatesNativeWindow) {
|
||||
clientComponentCaretPositionTracker.onNotifyClientWindowChange(location);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void activate() {
|
||||
super.activate();
|
||||
|
||||
if (doesSupportMovingCandidatesNativeWindow) {
|
||||
updateCandidatesNativeWindowPosition(true);
|
||||
clientComponentCaretPositionTracker.startTracking(getClientComponent());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void deactivate(boolean isTemporary) {
|
||||
clientComponentCaretPositionTracker.stopTrackingCurrentComponent();
|
||||
super.deactivate(isTemporary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchEvent(AWTEvent e) {
|
||||
if (doesSupportMovingCandidatesNativeWindow) {
|
||||
clientComponentCaretPositionTracker.onDispatchEvent(e);
|
||||
}
|
||||
super.dispatchEvent(e);
|
||||
}
|
||||
|
||||
|
||||
// Is called from native
|
||||
private static boolean isJbNewXimClientEnabled() {
|
||||
try {
|
||||
final String strVal = System.getProperty("jb.awt.newXimClient.enabled");
|
||||
final boolean defVal = true;
|
||||
|
||||
return (strVal == null) ? defVal : Boolean.parseBoolean(strVal);
|
||||
} catch (Exception err) {
|
||||
if (log.isLoggable(PlatformLogger.Level.SEVERE)) {
|
||||
log.severe("Error at isJbNewXimClientEnabled", err);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean preferXBelowTheSpot() {
|
||||
try {
|
||||
if (BrokenImDetectionContext.EATEN_EVENTS_THRESHOLD > 0) {
|
||||
// The fix of JBR-1573,
|
||||
// which is incompatible with the implementation of the native below-the-spot mode (a.k.a. X over-the-spot),
|
||||
// is explicitly enabled.
|
||||
// So let's disable this mode in favor of that fix.
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.WARNING)) {
|
||||
log.warning("The property \"jb.awt.newXimClient.preferBelowTheSpot\" is ignored in favor of the explicitly enabled \"recreate.x11.input.method\"");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
final String strVal = System.getProperty("jb.awt.newXimClient.preferBelowTheSpot");
|
||||
final boolean defVal = true;
|
||||
|
||||
return (strVal == null) ? defVal : Boolean.parseBoolean(strVal);
|
||||
} catch (Exception err) {
|
||||
if (log.isLoggable(PlatformLogger.Level.SEVERE)) {
|
||||
log.severe("Error at isJbNewXimClientEnabled", err);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected boolean openXIM() {
|
||||
return openXIMNative(XToolkit.getDisplay());
|
||||
}
|
||||
@@ -69,14 +156,14 @@ public class XInputMethod extends X11InputMethod {
|
||||
if (peer == null) {
|
||||
return false;
|
||||
}
|
||||
return createXICNative(peer.getContentWindow());
|
||||
return createXICNative(peer.getContentWindow(), preferXBelowTheSpot());
|
||||
}
|
||||
|
||||
protected boolean recreateXIC(int ctxid) {
|
||||
final XComponentPeer peer = (XComponentPeer)getPeer(clientComponentWindow);
|
||||
if (peer == null || pData == 0)
|
||||
return true;
|
||||
return recreateXICNative(peer.getContentWindow(), pData, ctxid);
|
||||
return recreateXICNative(peer.getContentWindow(), pData, ctxid, preferXBelowTheSpot());
|
||||
}
|
||||
protected int releaseXIC() {
|
||||
if (pData == 0)
|
||||
@@ -86,8 +173,7 @@ public class XInputMethod extends X11InputMethod {
|
||||
|
||||
private static volatile long xicFocus = 0;
|
||||
|
||||
protected void setXICFocus(ComponentPeer peer,
|
||||
boolean value, boolean active) {
|
||||
protected void setXICFocus(ComponentPeer peer, boolean value, boolean active) {
|
||||
if (peer == null) {
|
||||
return;
|
||||
}
|
||||
@@ -95,15 +181,17 @@ public class XInputMethod extends X11InputMethod {
|
||||
setXICFocusNative(((XComponentPeer)peer).getContentWindow(),
|
||||
value,
|
||||
active);
|
||||
|
||||
doesSupportMovingCandidatesNativeWindow = value && doesFocusedXICSupportMovingCandidatesNativeWindow();
|
||||
}
|
||||
|
||||
public static long getXICFocus() {
|
||||
return xicFocus;
|
||||
}
|
||||
|
||||
/* XAWT_HACK FIX ME!
|
||||
do NOT call client code!
|
||||
*/
|
||||
/* XAWT_HACK FIX ME!
|
||||
do NOT call client code!
|
||||
*/
|
||||
protected Container getParent(Component client) {
|
||||
return client.getParent();
|
||||
}
|
||||
@@ -222,12 +310,12 @@ public class XInputMethod extends X11InputMethod {
|
||||
|
||||
|
||||
static {
|
||||
int eatenEventsThresholdInitializer = 7;
|
||||
final String eventsThresholdMode = System.getProperty("recreate.x11.input.method", "true");
|
||||
int eatenEventsThresholdInitializer = 0;
|
||||
final String eventsThresholdMode = System.getProperty("recreate.x11.input.method", "false");
|
||||
|
||||
if ("false".equals(eventsThresholdMode)) {
|
||||
eatenEventsThresholdInitializer = 0;
|
||||
} else if (!"true".equals(eventsThresholdMode)) {
|
||||
if ("true".equalsIgnoreCase(eventsThresholdMode)) {
|
||||
eatenEventsThresholdInitializer = 7;
|
||||
} else if (!"false".equalsIgnoreCase(eventsThresholdMode)) {
|
||||
try {
|
||||
eatenEventsThresholdInitializer = Integer.parseInt(eventsThresholdMode);
|
||||
} catch (NumberFormatException err) {
|
||||
@@ -245,14 +333,397 @@ public class XInputMethod extends X11InputMethod {
|
||||
}
|
||||
|
||||
|
||||
// JBR-2460
|
||||
private volatile boolean doesSupportMovingCandidatesNativeWindow = false;
|
||||
private Point lastKnownCandidatesNativeWindowAbsolutePosition = null;
|
||||
|
||||
private void updateCandidatesNativeWindowPosition(final boolean forceUpdate) {
|
||||
assert(SwingUtilities.isEventDispatchThread());
|
||||
|
||||
if (!doesSupportMovingCandidatesNativeWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Component clientComponent = getClientComponent();
|
||||
if (clientComponent == null) {
|
||||
// No client
|
||||
return;
|
||||
}
|
||||
|
||||
final Window clientComponentWindow = getClientComponentWindow();
|
||||
if (clientComponentWindow == null) {
|
||||
// Impossible?
|
||||
return;
|
||||
}
|
||||
|
||||
if (!clientComponent.isShowing() || (!clientComponentWindow.isShowing())) {
|
||||
// Components are not showing yet, so it's impossible to determine their location on the screen
|
||||
// and/or the location of the caret
|
||||
return;
|
||||
}
|
||||
|
||||
final Point clientComponentAbsolutePos = clientComponent.getLocationOnScreen();
|
||||
final int clientComponentAbsoluteMaxX = clientComponentAbsolutePos.x + clientComponent.getWidth();
|
||||
final int clientComponentAbsoluteMaxY = clientComponentAbsolutePos.y + clientComponent.getHeight();
|
||||
|
||||
// Initial values are the fallback which is the bottom-left corner of the component
|
||||
final Point expectedCandidatesNativeWindowAbsolutePos = new Point(
|
||||
clientComponentAbsolutePos.x,
|
||||
clientComponentAbsoluteMaxY
|
||||
);
|
||||
|
||||
final InputMethodRequests clientImr = clientComponent.getInputMethodRequests();
|
||||
if (clientImr != null) {
|
||||
// An active client
|
||||
|
||||
final Rectangle caretRect = clientImr.getTextLocation(null);
|
||||
if (caretRect != null) {
|
||||
expectedCandidatesNativeWindowAbsolutePos.x = caretRect.x;
|
||||
expectedCandidatesNativeWindowAbsolutePos.y = caretRect.y + caretRect.height;
|
||||
}
|
||||
}
|
||||
|
||||
// Clamping within the client component's visible rect (if available and not empty) or just its bounds
|
||||
final var clientComponentVisibleRect = getJComponentVisibleRectIfNotEmpty(clientComponent);
|
||||
if (clientComponentVisibleRect == null) {
|
||||
expectedCandidatesNativeWindowAbsolutePos.x =
|
||||
Math.max(clientComponentAbsolutePos.x, Math.min(expectedCandidatesNativeWindowAbsolutePos.x, clientComponentAbsoluteMaxX - 1));
|
||||
expectedCandidatesNativeWindowAbsolutePos.y =
|
||||
Math.max(clientComponentAbsolutePos.y, Math.min(expectedCandidatesNativeWindowAbsolutePos.y, clientComponentAbsoluteMaxY - 1));
|
||||
} else {
|
||||
final int visibleBoundsAbsoluteMinX = clientComponentAbsolutePos.x + clientComponentVisibleRect.x;
|
||||
final int visibleBoundsAbsoluteMaxX = visibleBoundsAbsoluteMinX + clientComponentVisibleRect.width;
|
||||
final int visibleBoundsAbsoluteMinY = clientComponentAbsolutePos.y + clientComponentVisibleRect.y;
|
||||
final int visibleBoundsAbsoluteMaxY = visibleBoundsAbsoluteMinY + clientComponentVisibleRect.height;
|
||||
|
||||
expectedCandidatesNativeWindowAbsolutePos.x =
|
||||
Math.max(visibleBoundsAbsoluteMinX, Math.min(expectedCandidatesNativeWindowAbsolutePos.x, visibleBoundsAbsoluteMaxX - 1));
|
||||
expectedCandidatesNativeWindowAbsolutePos.y =
|
||||
Math.max(visibleBoundsAbsoluteMinY, Math.min(expectedCandidatesNativeWindowAbsolutePos.y, visibleBoundsAbsoluteMaxY - 1));
|
||||
}
|
||||
|
||||
// Scaling the coordinates according to the screen's current scaling settings.
|
||||
// To do it properly, we have to know the screen which the point is on.
|
||||
// The code below supposes this is the one which clientComponent belongs to, because we've clamped
|
||||
// the point coordinates within the component's bounds above.
|
||||
final X11GraphicsDevice candidatesNativeWindowDevice = getComponentX11Device(clientComponent);
|
||||
if (candidatesNativeWindowDevice != null) {
|
||||
expectedCandidatesNativeWindowAbsolutePos.x =
|
||||
candidatesNativeWindowDevice.scaleUpX(expectedCandidatesNativeWindowAbsolutePos.x);
|
||||
expectedCandidatesNativeWindowAbsolutePos.y =
|
||||
candidatesNativeWindowDevice.scaleUpY(expectedCandidatesNativeWindowAbsolutePos.y);
|
||||
}
|
||||
|
||||
// Clamping within screen bounds (to avoid the input candidates window to appear outside a screen).
|
||||
final Rectangle closestScreenScaledBounds = new Rectangle();
|
||||
final X11GraphicsDevice candidatesNativeWindowClosestScreen = findClosestScreenToPoint(
|
||||
closestScreenScaledBounds,
|
||||
expectedCandidatesNativeWindowAbsolutePos,
|
||||
candidatesNativeWindowDevice
|
||||
);
|
||||
if (candidatesNativeWindowClosestScreen != null) {
|
||||
final int screenScaledBoundsXMax = closestScreenScaledBounds.x + closestScreenScaledBounds.width - 1;
|
||||
final int screenScaledBoundsYMax = closestScreenScaledBounds.y + closestScreenScaledBounds.height - 1;
|
||||
|
||||
expectedCandidatesNativeWindowAbsolutePos.x =
|
||||
Math.max(closestScreenScaledBounds.x, Math.min(expectedCandidatesNativeWindowAbsolutePos.x, screenScaledBoundsXMax));
|
||||
expectedCandidatesNativeWindowAbsolutePos.y =
|
||||
Math.max(closestScreenScaledBounds.y, Math.min(expectedCandidatesNativeWindowAbsolutePos.y, screenScaledBoundsYMax));
|
||||
}
|
||||
|
||||
if (forceUpdate || !expectedCandidatesNativeWindowAbsolutePos.equals(lastKnownCandidatesNativeWindowAbsolutePosition)) {
|
||||
// adjustCandidatesNativeWindowPosition expects coordinates relative to the client window
|
||||
final Point clientComponentWindowAbsolutePos = clientComponentWindow.getLocationOnScreen();
|
||||
final X11GraphicsDevice clientComponentWindowDevice = getComponentX11Device(clientComponentWindow);
|
||||
if (clientComponentWindowDevice != null) {
|
||||
clientComponentWindowAbsolutePos.x =
|
||||
clientComponentWindowDevice.scaleUpX(clientComponentWindowAbsolutePos.x);
|
||||
clientComponentWindowAbsolutePos.y =
|
||||
clientComponentWindowDevice.scaleUpY(clientComponentWindowAbsolutePos.y);
|
||||
}
|
||||
|
||||
final int relativeX = expectedCandidatesNativeWindowAbsolutePos.x - clientComponentWindowAbsolutePos.x;
|
||||
final int relativeY = expectedCandidatesNativeWindowAbsolutePos.y - clientComponentWindowAbsolutePos.y;
|
||||
|
||||
awtLock();
|
||||
try {
|
||||
adjustCandidatesNativeWindowPosition(relativeX, relativeY);
|
||||
} finally {
|
||||
awtUnlock();
|
||||
}
|
||||
|
||||
lastKnownCandidatesNativeWindowAbsolutePosition = expectedCandidatesNativeWindowAbsolutePos;
|
||||
}
|
||||
}
|
||||
|
||||
private static Rectangle getJComponentVisibleRectIfNotEmpty(final Component component) {
|
||||
if (component instanceof JComponent jComponent) {
|
||||
final Rectangle result = jComponent.getVisibleRect();
|
||||
if ((result != null) && (result.width > 0) && (result.height > 0)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static X11GraphicsDevice getComponentX11Device(final Component component) {
|
||||
if (component == null) return null;
|
||||
|
||||
final var componentGc = component.getGraphicsConfiguration();
|
||||
if (componentGc == null) return null;
|
||||
|
||||
return (componentGc.getDevice() instanceof X11GraphicsDevice result) ? result : null;
|
||||
}
|
||||
|
||||
private static X11GraphicsDevice findClosestScreenToPoint(
|
||||
final Rectangle outScreenScaledBounds,
|
||||
final Point absolutePointScaled,
|
||||
final X11GraphicsDevice... screensToCheckFirst
|
||||
) {
|
||||
assert(outScreenScaledBounds != null);
|
||||
|
||||
if (absolutePointScaled == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Iterator<X11GraphicsDevice> screensToCheck =
|
||||
Stream.concat( // screensToCheckFirst + GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()
|
||||
Arrays.stream(screensToCheckFirst),
|
||||
Stream.<Supplier<GraphicsDevice[]>>of(() -> {
|
||||
final var localGe = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
if (localGe != null) {
|
||||
return localGe.getScreenDevices();
|
||||
}
|
||||
return null;
|
||||
}).flatMap(supplier -> Stream.of(supplier.get()))
|
||||
).map(device -> (device instanceof X11GraphicsDevice screen) ? screen : null)
|
||||
.filter(Objects::nonNull)
|
||||
.iterator();
|
||||
|
||||
int closestScreenMinDistance = Integer.MAX_VALUE;
|
||||
X11GraphicsDevice result = null;
|
||||
while (screensToCheck.hasNext()) {
|
||||
final X11GraphicsDevice screen = screensToCheck.next();
|
||||
|
||||
final Rectangle screenBoundsScaled = screen.getBounds();
|
||||
if (screenBoundsScaled == null) {
|
||||
continue;
|
||||
}
|
||||
screenBoundsScaled.width = screen.scaleUp(screenBoundsScaled.width);
|
||||
screenBoundsScaled.height = screen.scaleUp(screenBoundsScaled.height);
|
||||
|
||||
final int distance = obtainDistanceBetween(screenBoundsScaled, absolutePointScaled);
|
||||
if (distance < closestScreenMinDistance) {
|
||||
result = screen;
|
||||
closestScreenMinDistance = distance;
|
||||
|
||||
outScreenScaledBounds.x = screenBoundsScaled.x;
|
||||
outScreenScaledBounds.y = screenBoundsScaled.y;
|
||||
outScreenScaledBounds.width = screenBoundsScaled.width;
|
||||
outScreenScaledBounds.height = screenBoundsScaled.height;
|
||||
|
||||
if (distance < 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int obtainDistanceBetween(final Rectangle rectangle, final Point absolutePointScaled) {
|
||||
if ((rectangle.width < 1) || (rectangle.height < 1)) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
final int screenBoundsScaledXMax = rectangle.x + rectangle.width - 1;
|
||||
final int screenBoundsScaledYMax = rectangle.y + rectangle.height - 1;
|
||||
|
||||
final int dx = Math.max(0, Math.max(rectangle.x - absolutePointScaled.x, absolutePointScaled.x - screenBoundsScaledXMax));
|
||||
final int dy = Math.max(0, Math.max(rectangle.y - absolutePointScaled.y, absolutePointScaled.y - screenBoundsScaledYMax));
|
||||
|
||||
return dx + dy; // just sum is enough for our purposes
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Native methods
|
||||
*/
|
||||
private native boolean openXIMNative(long display);
|
||||
private native boolean createXICNative(long window);
|
||||
private native boolean recreateXICNative(long window, long px11data, int ctxid);
|
||||
private native boolean createXICNative(long window, boolean preferBelowTheSpot);
|
||||
private native boolean recreateXICNative(long window, long px11data, int ctxid, boolean preferBelowTheSpot);
|
||||
private native int releaseXICNative(long px11data);
|
||||
private native void setXICFocusNative(long window,
|
||||
boolean value, boolean active);
|
||||
private native void setXICFocusNative(long window, boolean value, boolean active);
|
||||
private native void adjustStatusWindow(long window);
|
||||
|
||||
private native boolean doesFocusedXICSupportMovingCandidatesNativeWindow();
|
||||
|
||||
private native void adjustCandidatesNativeWindowPosition(int x, int y);
|
||||
|
||||
|
||||
/**
|
||||
* This class tries to track all the cases when the position of the parent XInputMethod's candidate window has
|
||||
* to be updated. Here are the examples of such cases:
|
||||
* <ul>
|
||||
* <li>The caret position has changed ;
|
||||
* <li>The component has been moved/resized ;
|
||||
* <li>The component's window has been moved/resized ;
|
||||
* <li>The component's text has been changed ;
|
||||
* </ul>
|
||||
* Tracking makes sense only when the parent XIM is in a mode allowing to move a native candidates window.
|
||||
* This is controlled by a flag {@link XInputMethod#doesSupportMovingCandidatesNativeWindow}.
|
||||
* Thus, the tracking gets enabled (via {@link #startTracking(Component)}) only when the flag is evaluated to true.
|
||||
*/
|
||||
private static class ClientComponentCaretPositionTracker implements ComponentListener, CaretListener, TextListener
|
||||
{
|
||||
public ClientComponentCaretPositionTracker(XInputMethod owner) {
|
||||
this.owner = new WeakReference<>(owner);
|
||||
}
|
||||
|
||||
|
||||
public void startTracking(final Component component) {
|
||||
stopTrackingCurrentComponent();
|
||||
|
||||
if (component == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
trackedComponent = new WeakReference<>(component);
|
||||
|
||||
// Moving and changing the size causes a possible change of caret position
|
||||
component.addComponentListener(this);
|
||||
|
||||
if (component instanceof JTextComponent jtc) {
|
||||
jtc.addCaretListener(this);
|
||||
isCaretListenerInstalled = true;
|
||||
} else if (component instanceof TextComponent tc) {
|
||||
tc.addTextListener(this);
|
||||
isTextListenerInstalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void stopTrackingCurrentComponent() {
|
||||
final Component trackedComponentStrong;
|
||||
if (trackedComponent == null) {
|
||||
trackedComponentStrong = null;
|
||||
} else {
|
||||
trackedComponentStrong = trackedComponent.get();
|
||||
trackedComponent.clear();
|
||||
trackedComponent = null;
|
||||
}
|
||||
|
||||
if (trackedComponentStrong == null) {
|
||||
isCaretListenerInstalled = false;
|
||||
isTextListenerInstalled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTextListenerInstalled) {
|
||||
isTextListenerInstalled = false;
|
||||
((TextComponent)trackedComponentStrong).removeTextListener(this);
|
||||
}
|
||||
|
||||
if (isCaretListenerInstalled) {
|
||||
isCaretListenerInstalled = false;
|
||||
((JTextComponent)trackedComponentStrong).removeCaretListener(this);
|
||||
}
|
||||
|
||||
trackedComponentStrong.removeComponentListener(this);
|
||||
}
|
||||
|
||||
/* Listening callbacks */
|
||||
|
||||
public void onDispatchEvent(AWTEvent event) {
|
||||
if (isCaretListenerInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int eventId = event.getID();
|
||||
|
||||
if ( (eventId >= MouseEvent.MOUSE_FIRST) && (eventId <= MouseEvent.MOUSE_LAST) ) {
|
||||
// The event hasn't been dispatched yet, so the caret position couldn't be changed.
|
||||
// Hence, we have to postpone the updating request.
|
||||
SwingUtilities.invokeLater(() -> updateImCandidatesNativeWindowPosition(false));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !isTextListenerInstalled && (eventId >= KeyEvent.KEY_FIRST) && (eventId <= KeyEvent.KEY_LAST) ) {
|
||||
// The event hasn't been dispatched yet, so the caret position couldn't be changed.
|
||||
// Hence, we have to postpone the updating request.
|
||||
SwingUtilities.invokeLater(() -> updateImCandidatesNativeWindowPosition(false));
|
||||
}
|
||||
}
|
||||
|
||||
public void onNotifyClientWindowChange(Rectangle location) {
|
||||
if (location != null) {
|
||||
updateImCandidatesNativeWindowPosition(lastKnownClientWindowBounds == null);
|
||||
}
|
||||
lastKnownClientWindowBounds = location;
|
||||
}
|
||||
|
||||
// ComponentListener
|
||||
|
||||
@Override
|
||||
public void componentHidden(ComponentEvent e) {}
|
||||
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent e) {
|
||||
updateImCandidatesNativeWindowPosition(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
updateImCandidatesNativeWindowPosition(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentShown(ComponentEvent e) {
|
||||
updateImCandidatesNativeWindowPosition(false);
|
||||
}
|
||||
|
||||
// CaretListener
|
||||
|
||||
@Override
|
||||
public void caretUpdate(CaretEvent e) {
|
||||
updateImCandidatesNativeWindowPosition(false);
|
||||
}
|
||||
|
||||
// TextListener
|
||||
|
||||
@Override
|
||||
public void textValueChanged(TextEvent e) {
|
||||
updateImCandidatesNativeWindowPosition(false);
|
||||
}
|
||||
|
||||
/* Private parts */
|
||||
|
||||
private final WeakReference<XInputMethod> owner;
|
||||
private WeakReference<Component> trackedComponent = null;
|
||||
private boolean isCaretListenerInstalled = false;
|
||||
private boolean isTextListenerInstalled = false;
|
||||
private Rectangle lastKnownClientWindowBounds = null;
|
||||
|
||||
|
||||
private void updateImCandidatesNativeWindowPosition(boolean forceUpdate) {
|
||||
final XInputMethod ownerStrong = owner.get();
|
||||
|
||||
if ((ownerStrong == null) || (ownerStrong.isDisposed())) {
|
||||
// The owning XInputMethod instance is no longer valid
|
||||
|
||||
stopTrackingCurrentComponent();
|
||||
owner.clear();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ownerStrong.isActive) {
|
||||
stopTrackingCurrentComponent(); // will start tracking back when the owner gets active back
|
||||
return;
|
||||
}
|
||||
|
||||
ownerStrong.updateCandidatesNativeWindowPosition(forceUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
final ClientComponentCaretPositionTracker clientComponentCaretPositionTracker;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
*/
|
||||
|
||||
package sun.awt.X11;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Hashtable;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
@@ -1717,6 +1718,20 @@ public class XKeysym {
|
||||
|
||||
keysym2JavaKeycodeHash.put( Long.valueOf(XConstants.NoSymbol), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN));
|
||||
|
||||
/* JetBrains Runtime mappings to fix JBR-6215, they override L3-L10, R1-R4 which have nonsensical defaults. */
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F13), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F13, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F14), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F14, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F15), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F15, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F16), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F16, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F17), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F17, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F18), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F18, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F19), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F19, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F20), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F20, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F21), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F21, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F22), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F22, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F23), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F23, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
keysym2JavaKeycodeHash.put ( Long.valueOf(XKeySymConstants.XK_F24), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F24, KeyEvent.KEY_LOCATION_STANDARD));
|
||||
|
||||
/* Reverse search of keysym by keycode. */
|
||||
|
||||
/* Add keyboard locking codes. */
|
||||
|
||||
@@ -82,15 +82,11 @@ final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProt
|
||||
}
|
||||
|
||||
private void requestState(XWindowPeer window, int state) {
|
||||
/*
|
||||
* We have to use toggle for maximization because of transitions
|
||||
* from maximization in one direction only to maximization in the
|
||||
* other direction only.
|
||||
*/
|
||||
int old_net_state = getState(window);
|
||||
int max_changed = (state ^ old_net_state) & (Frame.MAXIMIZED_BOTH);
|
||||
|
||||
XClientMessageEvent req = new XClientMessageEvent();
|
||||
int action = 0;
|
||||
try {
|
||||
switch(max_changed) {
|
||||
case 0:
|
||||
@@ -98,14 +94,22 @@ final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProt
|
||||
case Frame.MAXIMIZED_HORIZ:
|
||||
req.set_data(1, XA_NET_WM_STATE_MAXIMIZED_HORZ.getAtom());
|
||||
req.set_data(2, 0);
|
||||
action = ((state & Frame.MAXIMIZED_HORIZ) == Frame.MAXIMIZED_HORIZ)
|
||||
? _NET_WM_STATE_ADD
|
||||
: _NET_WM_STATE_REMOVE;
|
||||
break;
|
||||
case Frame.MAXIMIZED_VERT:
|
||||
req.set_data(1, XA_NET_WM_STATE_MAXIMIZED_VERT.getAtom());
|
||||
req.set_data(2, 0);
|
||||
action = ((state & Frame.MAXIMIZED_VERT) == Frame.MAXIMIZED_VERT)
|
||||
? _NET_WM_STATE_ADD
|
||||
: _NET_WM_STATE_REMOVE;
|
||||
break;
|
||||
case Frame.MAXIMIZED_BOTH:
|
||||
// Somehow this doesn't work when changing HORZ->VERT, but works VERT->HORZ
|
||||
req.set_data(1, XA_NET_WM_STATE_MAXIMIZED_HORZ.getAtom());
|
||||
req.set_data(2, XA_NET_WM_STATE_MAXIMIZED_VERT.getAtom());
|
||||
action = _NET_WM_STATE_TOGGLE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@@ -117,7 +121,7 @@ final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProt
|
||||
req.set_window(window.getWindow());
|
||||
req.set_message_type(XA_NET_WM_STATE.getAtom());
|
||||
req.set_format(32);
|
||||
req.set_data(0, _NET_WM_STATE_TOGGLE);
|
||||
req.set_data(0, action);
|
||||
XToolkit.awtLock();
|
||||
try {
|
||||
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
|
||||
|
||||
@@ -1203,15 +1203,25 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private final Hashtable<GraphicsConfiguration, Insets> cachedInsets = new Hashtable<>();
|
||||
private final Map<GraphicsConfiguration, Insets> cachedInsets = new HashMap<>();
|
||||
private void resetScreenInsetsCache() {
|
||||
cachedInsets.clear();
|
||||
XToolkit.awtLock();
|
||||
try {
|
||||
cachedInsets.clear();
|
||||
} finally {
|
||||
XToolkit.awtUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getScreenInsets(final GraphicsConfiguration gc) {
|
||||
if (useCachedInsets) {
|
||||
return (Insets)cachedInsets.computeIfAbsent(gc, this::getScreenInsetsImpl).clone();
|
||||
XToolkit.awtLock();
|
||||
try {
|
||||
return (Insets) cachedInsets.computeIfAbsent(gc, this::getScreenInsetsImpl).clone();
|
||||
} finally {
|
||||
XToolkit.awtUnlock();
|
||||
}
|
||||
} else {
|
||||
return getScreenInsetsImpl(gc);
|
||||
}
|
||||
|
||||
@@ -1849,6 +1849,7 @@ final class XWM
|
||||
Native.putLong(data, 2, 0);
|
||||
Native.putLong(data, 3, 0);
|
||||
|
||||
XToolkit.awtLock();
|
||||
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
|
||||
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
|
||||
XA_GTK_FRAME_EXTENTS.getAtom(),
|
||||
@@ -1857,8 +1858,8 @@ final class XWM
|
||||
data, 4);
|
||||
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
|
||||
} finally {
|
||||
XToolkit.awtUnlock();
|
||||
unsafe.freeMemory(data);
|
||||
data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,8 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
= "true".equals(GetPropertyAction.privilegedGetProperty("transients.desktop.check", "true"));
|
||||
static final boolean FULL_MODAL_TRANSIENTS_CHAIN
|
||||
= "true".equals(GetPropertyAction.privilegedGetProperty("full.modal.transients.chain"));
|
||||
static final boolean RESIZE_WITH_SCALE
|
||||
= "true".equals(GetPropertyAction.privilegedGetProperty("resize.with.scale", "false"));
|
||||
|
||||
// should be synchronized on awtLock
|
||||
private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>();
|
||||
@@ -659,8 +661,9 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
* called to check if we've been moved onto a different screen
|
||||
* Based on checkNewXineramaScreen() in awt_GraphicsEnv.c
|
||||
* newBounds are specified in device space.
|
||||
* Returns the corrected dimension of this window.
|
||||
*/
|
||||
public boolean checkIfOnNewScreen(Rectangle newBounds) {
|
||||
public Dimension checkIfOnNewScreen(Rectangle newBounds) {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
|
||||
log.finest("XWindowPeer: Check if we've been moved to a new screen since we're running in Xinerama mode");
|
||||
}
|
||||
@@ -669,7 +672,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
int curScreenNum = ((X11GraphicsDevice)getGraphicsConfiguration().getDevice()).getScreen();
|
||||
int newScreenNum = curScreenNum;
|
||||
GraphicsDevice[] gds = XToolkit.localEnv.getScreenDevices();
|
||||
GraphicsConfiguration newGC = null;
|
||||
GraphicsConfiguration newGC = getGraphicsConfiguration();
|
||||
|
||||
for (int i = 0; i < gds.length; i++) {
|
||||
X11GraphicsDevice device = (X11GraphicsDevice) gds[i];
|
||||
@@ -689,38 +692,47 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ensure that after window will be moved to another monitor and (probably)
|
||||
// resized as a result, majority of its area will stay on the new monitor
|
||||
if (newScreenNum != curScreenNum) {
|
||||
X11GraphicsDevice device = (X11GraphicsDevice) gds[newScreenNum];
|
||||
Rectangle screenBounds = newGC.getBounds();
|
||||
// Rescale screen size to native unscaled coordinates
|
||||
screenBounds.width = device.scaleUp(screenBounds.width);
|
||||
screenBounds.height = device.scaleUp(screenBounds.height);
|
||||
// Rescale window to new screen's scale
|
||||
newBounds.width = newBounds.width * device.getScaleFactor() / graphicsConfig.getScale();
|
||||
newBounds.height = newBounds.height * device.getScaleFactor() / graphicsConfig.getScale();
|
||||
|
||||
Rectangle intersection = screenBounds.intersection(newBounds);
|
||||
if (intersection.isEmpty() ||
|
||||
intersection.width * intersection.height <= newBounds.width * newBounds.height / 2) {
|
||||
newScreenNum = curScreenNum; // Don't move to new screen
|
||||
Rectangle newScaledBounds = newBounds.getBounds();
|
||||
if (XWindowPeer.RESIZE_WITH_SCALE) {
|
||||
// Try to guess that after the window has been moved to another monitor and (probably)
|
||||
// resized as a result, the majority of its area will still be on that new monitor.
|
||||
// This is a guess since we cannot predict the result of the resize operation where
|
||||
// the window manager has the final say.
|
||||
boolean isMaximized = target instanceof Frame f && (f.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
||||
if (newScreenNum != curScreenNum && !isMaximized) {
|
||||
X11GraphicsDevice device = (X11GraphicsDevice) gds[newScreenNum];
|
||||
Rectangle screenBounds = newGC.getBounds();
|
||||
// Rescale screen size to native unscaled coordinates
|
||||
screenBounds.width = device.scaleUp(screenBounds.width);
|
||||
screenBounds.height = device.scaleUp(screenBounds.height);
|
||||
// Rescale window to new screen's scale
|
||||
newScaledBounds.width = newBounds.width * device.getScaleFactor() / graphicsConfig.getScale();
|
||||
newScaledBounds.height = newBounds.height * device.getScaleFactor() / graphicsConfig.getScale();
|
||||
Rectangle intersection = screenBounds.intersection(newScaledBounds);
|
||||
if (intersection.isEmpty() ||
|
||||
intersection.width * intersection.height <= newScaledBounds.width * newScaledBounds.height / 2) {
|
||||
newScreenNum = curScreenNum; // Don't move to the new screen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var device = (X11GraphicsDevice) newGC.getDevice();
|
||||
Dimension newSize = newScaledBounds.getSize();
|
||||
newSize.width = device.scaleDown(newSize.width);
|
||||
newSize.height = device.scaleDown(newSize.height);
|
||||
if (newScreenNum != curScreenNum) {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
|
||||
log.finest("XWindowPeer: Moved to a new screen");
|
||||
}
|
||||
var gc = newGC;
|
||||
var device = (X11GraphicsDevice) gc.getDevice();
|
||||
var acc = AWTAccessor.getComponentAccessor();
|
||||
syncSizeOnly = true;
|
||||
acc.setSize(target, device.scaleDown(newBounds.width), device.scaleDown(newBounds.height));
|
||||
acc.setGraphicsConfiguration(target, gc);
|
||||
acc.setSize(target, newSize.width, newSize.height);
|
||||
acc.setGraphicsConfiguration(target, newGC);
|
||||
syncSizeOnly = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return newSize;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -854,18 +866,20 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
insLog.fine(xe.toString());
|
||||
}
|
||||
|
||||
WindowLocation newLocation = getNewLocation(xe);
|
||||
Dimension newDimension = new Dimension(xe.get_width(), xe.get_height());
|
||||
WindowLocation eventLocation = getNewLocation(xe);
|
||||
Dimension eventDimension = new Dimension(xe.get_width(), xe.get_height());
|
||||
boolean xinerama = XToolkit.localEnv.runningXinerama();
|
||||
|
||||
SunToolkit.executeOnEventHandlerThread(target, () -> {
|
||||
Point newUserLocation = newLocation.getUserLocation();
|
||||
Rectangle oldBounds = getBounds();
|
||||
|
||||
Dimension newSize = xinerama
|
||||
? checkIfOnNewScreen(new Rectangle(eventLocation.getDeviceLocation(), eventDimension))
|
||||
: new Dimension(scaleDown(eventDimension.width), scaleDown(eventDimension.height));;
|
||||
Point newUserLocation = eventLocation.getUserLocation();
|
||||
x = newUserLocation.x;
|
||||
y = newUserLocation.y;
|
||||
width = scaleDown(newDimension.width);
|
||||
height = scaleDown(newDimension.height);
|
||||
width = newSize.width;
|
||||
height = newSize.height;
|
||||
|
||||
if (!getBounds().getSize().equals(oldBounds.getSize())) {
|
||||
AWTAccessor.getComponentAccessor().setSize(target, width, height);
|
||||
@@ -876,10 +890,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
|
||||
}
|
||||
repositionSecurityWarning();
|
||||
|
||||
if (xinerama) {
|
||||
checkIfOnNewScreen(new Rectangle(newLocation.getDeviceLocation(), newDimension));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -564,7 +564,9 @@ public abstract class X11InputMethodBase extends InputMethodAdapter {
|
||||
* @see java.awt.im.spi.InputMethod#removeNotify
|
||||
*/
|
||||
public synchronized void removeNotify() {
|
||||
dispose();
|
||||
stopListening();
|
||||
awtFocussedComponent = null;
|
||||
clientComponentWindow = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,4 +61,17 @@ public abstract class XSurfaceData extends SurfaceData {
|
||||
protected native void setInvalid();
|
||||
|
||||
protected static native void XSetGraphicsExposures(long xgc, boolean needExposures);
|
||||
|
||||
/**
|
||||
* Loads native image raster into surface.
|
||||
*
|
||||
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
|
||||
* Note: The color data in this image is considered to be premultiplied with alpha.
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
|
||||
* Note: can be null (then whole image used)
|
||||
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
|
||||
*/
|
||||
protected static native boolean loadNativeRasterWithRects(long sdops, long pRaster, int width, int height, long pRects, int rectsCount);
|
||||
}
|
||||
|
||||
@@ -761,4 +761,20 @@ public abstract class XRSurfaceData extends XSurfaceData {
|
||||
public void setStaticSrcTx(AffineTransform staticSrcTx) {
|
||||
this.staticSrcTx = staticSrcTx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads native image raster into surface.
|
||||
*
|
||||
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
|
||||
* Note: The color data in this image is considered to be premultiplied with alpha.
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
|
||||
* Note: can be null (then whole image used)
|
||||
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
|
||||
*/
|
||||
@Override
|
||||
protected void loadNativeRaster(long pRaster, int width, int height, long pRects, int rectsCount) {
|
||||
loadNativeRasterWithRects(getNativeOps(), pRaster, width, height, pRects, rectsCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1703,3 +1703,90 @@ Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures
|
||||
XSetGraphicsExposures(awt_display, (GC) xgc, needExposures ? True : False);
|
||||
#endif /* !HEADLESS */
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_java2d_x11_X11SurfaceData
|
||||
* Method: loadNativeRasterWithRects
|
||||
* Signature:
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_java2d_x11_XSurfaceData_loadNativeRasterWithRects
|
||||
(JNIEnv *env, jclass clazz,
|
||||
jlong sdops, jlong pRaster, jint width, jint height, jlong pRects, jint rectsCount)
|
||||
{
|
||||
SurfaceDataOps *dstOps = (SurfaceDataOps *)jlong_to_ptr(sdops);
|
||||
if (dstOps == NULL || pRaster == 0) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "XSurfaceData_loadNativeRasterWithRects: params are null");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
if (pRects == 0 || rectsCount < 1) {
|
||||
SurfaceDataRasInfo dstInfo;
|
||||
memset(&dstInfo, 0, sizeof(SurfaceDataRasInfo));
|
||||
dstInfo.bounds.x1 = 0;
|
||||
dstInfo.bounds.y1 = 0;
|
||||
dstInfo.bounds.x2 = width;
|
||||
dstInfo.bounds.y2 = height;
|
||||
|
||||
if (dstOps->Lock(env, dstOps, &dstInfo, SD_LOCK_WRITE) != SD_SUCCESS) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "XSurfaceData_loadNativeRasterWithRects: can't lock dest.");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
dstOps->GetRasInfo(env, dstOps, &dstInfo);
|
||||
if (dstInfo.rasBase) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "XSurfaceData_loadNativeRasterWithRects: copy whole memory.");
|
||||
memcpy(dstInfo.rasBase, (void *)jlong_to_ptr(pRaster), width * height * 4);
|
||||
} else {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "XSurfaceData_loadNativeRasterWithRects: can't get pointer of dest raster.");
|
||||
}
|
||||
|
||||
SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
|
||||
SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
|
||||
} else {
|
||||
int32_t *pr = (int32_t *)jlong_to_ptr(pRects);
|
||||
for (int c = 0; c < rectsCount; ++c) {
|
||||
int32_t x = *(pr++);
|
||||
int32_t y = *(pr++);
|
||||
int32_t w = *(pr++);
|
||||
int32_t h = *(pr++);
|
||||
|
||||
SurfaceDataRasInfo dstInfo;
|
||||
memset(&dstInfo, 0, sizeof(SurfaceDataRasInfo));
|
||||
dstInfo.bounds.x1 = x;
|
||||
dstInfo.bounds.y1 = y;
|
||||
dstInfo.bounds.x2 = x + w;
|
||||
dstInfo.bounds.y2 = y + h;
|
||||
|
||||
if (dstOps->Lock(env, dstOps, &dstInfo, SD_LOCK_WRITE) != SD_SUCCESS) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "XSurfaceData_loadNativeRasterWithRects: can't lock dest rect.");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
dstOps->GetRasInfo(env, dstOps, &dstInfo);
|
||||
if (dstInfo.rasBase) {
|
||||
char* pSrc = (char*)PtrCoord(pRaster, x, 4, y, width*4);
|
||||
char* pDst = (char*)PtrCoord(dstInfo.rasBase, x, dstInfo.pixelStride, y, dstInfo.scanStride);
|
||||
if (dstInfo.scanStride == width*4) {
|
||||
J2dTraceLn4(J2D_TRACE_VERBOSE, "XSurfaceData_loadNativeRasterWithRects: copy rect %d,%d - %d,%d [FAST]", x, y, w, h);
|
||||
memcpy(pDst, pSrc, width*h*4);
|
||||
} else {
|
||||
J2dTraceLn4(J2D_TRACE_VERBOSE, "XSurfaceData_loadNativeRasterWithRects: copy rect %d,%d - %d,%d [line by line]", x, y, w, h);
|
||||
for (int line = 0; line < h; ++line) {
|
||||
memcpy(pDst, pSrc, w*4);
|
||||
pSrc += width*4;
|
||||
pDst += dstInfo.scanStride;
|
||||
}
|
||||
}
|
||||
SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
|
||||
} else {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "XSurfaceData_loadNativeRasterWithRects: can't get pointer of dest raster (rect).");
|
||||
}
|
||||
|
||||
SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@ import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import sun.awt.datatransfer.ClipboardTransferable;
|
||||
import sun.awt.datatransfer.DataTransferer;
|
||||
import sun.awt.datatransfer.SunClipboard;
|
||||
|
||||
@@ -91,6 +92,39 @@ final class WClipboard extends SunClipboard {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ======================= JBR-5980 Pasting from clipboard not working reliably in Windows =======================
|
||||
private static final boolean isContentsCacheDisabled; // initialized in the static block below
|
||||
private static final boolean areOwnershipExtraChecksEnabled; // initialized in the static block below
|
||||
|
||||
@Override
|
||||
public synchronized Transferable getContents(Object requestor) {
|
||||
if (isContentsCacheDisabled) {
|
||||
// JBR-5980: sometimes the cache (this.contents) doesn't reset when something gets copied to the
|
||||
// system clipboard outside of the Java app. This workaround allows to disable the caching, so
|
||||
// each call to getContents will result in reading the clipboard content from the system through
|
||||
// Win32 Clipbaord API.
|
||||
|
||||
return new ClipboardTransferable((SunClipboard)this);
|
||||
}
|
||||
|
||||
return super.getContents(requestor);
|
||||
}
|
||||
|
||||
// Upcall from native
|
||||
private void ensureNoOwnedData() {
|
||||
boolean thereAreOwnedData = false;
|
||||
synchronized (this) {
|
||||
thereAreOwnedData = ((this.owner != null) || (this.contents != null));
|
||||
}
|
||||
if (thereAreOwnedData) {
|
||||
// to properly clear everything
|
||||
lostOwnershipImpl();
|
||||
}
|
||||
}
|
||||
// ===============================================================================================================
|
||||
|
||||
|
||||
private void lostSelectionOwnershipImpl() {
|
||||
lostOwnershipImpl();
|
||||
}
|
||||
@@ -121,9 +155,28 @@ final class WClipboard extends SunClipboard {
|
||||
*/
|
||||
private native void publishClipboardData(long format, byte[] bytes);
|
||||
|
||||
private static native void init();
|
||||
private static native void init(boolean areOwnershipExtraChecksEnabled);
|
||||
static {
|
||||
init();
|
||||
// ====================== JBR-5980 Pasting from clipboard not working reliably in Windows ======================
|
||||
boolean flagInitializer = false; // let's fall back in the default behavior
|
||||
try {
|
||||
// is "false" by default due to JBR-6267
|
||||
flagInitializer =
|
||||
"true".equalsIgnoreCase(System.getProperty("awt.windows.clipboard.cache.disabled", "false"));
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
isContentsCacheDisabled = flagInitializer;
|
||||
|
||||
flagInitializer = false; // let's fall back in the default behavior
|
||||
try {
|
||||
flagInitializer =
|
||||
"true".equalsIgnoreCase(System.getProperty("awt.windows.clipboard.extraOwnershipChecksEnabled", "true"));
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
areOwnershipExtraChecksEnabled = flagInitializer;
|
||||
// =============================================================================================================
|
||||
|
||||
init(areOwnershipExtraChecksEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -435,6 +435,7 @@ final class WInputMethod extends InputMethodAdapter
|
||||
endCompositionNative(context, DISCARD_INPUT);
|
||||
awtFocussedComponent = null;
|
||||
awtFocussedComponentPeer = null;
|
||||
stopListening();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -593,27 +594,35 @@ final class WInputMethod extends InputMethodAdapter
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
Component client = getClientComponent();
|
||||
Rectangle caretRect = null;
|
||||
|
||||
if (client != null) {
|
||||
if (!client.isShowing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (haveActiveClient()) {
|
||||
Rectangle rc = inputContext.getTextLocation(TextHitInfo.leading(0));
|
||||
x = rc.x;
|
||||
y = rc.y + rc.height;
|
||||
} else {
|
||||
Point pt = client.getLocationOnScreen();
|
||||
Dimension size = client.getSize();
|
||||
x = pt.x;
|
||||
y = pt.y + size.height;
|
||||
caretRect = inputContext.getTextLocation(TextHitInfo.leading(0));
|
||||
}
|
||||
if (caretRect == null) {
|
||||
Point pt = client.getLocationOnScreen();
|
||||
Dimension size = client.getSize();
|
||||
caretRect = new Rectangle(pt, size);
|
||||
}
|
||||
}
|
||||
|
||||
openCandidateWindow(awtFocussedComponentPeer, x, y);
|
||||
if (caretRect == null) {
|
||||
openCandidateWindow(awtFocussedComponentPeer, 0, 0, 0, 0);
|
||||
} else {
|
||||
openCandidateWindow(
|
||||
awtFocussedComponentPeer,
|
||||
caretRect.x,
|
||||
caretRect.y,
|
||||
caretRect.x + caretRect.width - ( (caretRect.width > 0) ? 1 : 0),
|
||||
caretRect.y + caretRect.height - ( (caretRect.height > 0) ? 1 : 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
WToolkit.postEvent(WToolkit.targetToAppContext(source),
|
||||
@@ -657,6 +666,6 @@ final class WInputMethod extends InputMethodAdapter
|
||||
private native String getNativeIMMDescription();
|
||||
static native Locale getNativeLocale();
|
||||
static native boolean setNativeLocale(String localeName);
|
||||
private native void openCandidateWindow(WComponentPeer peer, int x, int y);
|
||||
private native void openCandidateWindow(WComponentPeer peer, int caretLeftX, int caretTopY, int caretRightX, int caretBottomY);
|
||||
private native boolean isCompositionStringAvailable(int context);
|
||||
}
|
||||
|
||||
@@ -1023,4 +1023,32 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
|
||||
*/
|
||||
public static native boolean updateWindowAccelImpl(long pd3dsd, long pData,
|
||||
int w, int h);
|
||||
|
||||
/**
|
||||
* Loads native image raster into surface.
|
||||
*
|
||||
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
|
||||
* Note: The color data in this image is considered to be premultiplied with alpha.
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
|
||||
* Note: can be null (then whole image used)
|
||||
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
|
||||
*/
|
||||
@Override
|
||||
protected void loadNativeRaster(long pRaster, int width, int height, long pRects, int rectsCount) {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// make sure we have a current context before uploading
|
||||
// the sysmem data to the texture object
|
||||
D3DContext.setScratchSurface(getContext());
|
||||
rq.flushAndInvokeNow(() -> loadNativeRasterWithRects(getNativeOps(), pRaster, width, height, pRects, rectsCount));
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
markDirty();
|
||||
}
|
||||
|
||||
private static native boolean loadNativeRasterWithRects(long pData, long pRaster, int width, int height, long pRects, int rectsCount);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "D3DPipeline.h"
|
||||
#include <jlong.h>
|
||||
#include <cstdint>
|
||||
#include "D3DSurfaceData.h"
|
||||
#include "D3DPipelineManager.h"
|
||||
#include "Trace.h"
|
||||
@@ -32,7 +33,18 @@
|
||||
#include "awt_Window.h"
|
||||
#include "awt_BitmapUtil.h"
|
||||
#include "D3DRenderQueue.h"
|
||||
#include "D3DBlitLoops.h"
|
||||
|
||||
#include "GraphicsPrimitiveMgr.h"
|
||||
#include "IntArgb.h"
|
||||
#include "IntArgbPre.h"
|
||||
#include "IntRgb.h"
|
||||
#include "IntBgr.h"
|
||||
|
||||
extern "C" BlitFunc IntArgbToIntArgbPreConvert;
|
||||
extern "C" BlitFunc IntArgbPreToIntArgbConvert;
|
||||
extern "C" BlitFunc IntArgbBmToIntArgbConvert;
|
||||
extern "C" BlitFunc IntRgbToIntArgbConvert;
|
||||
|
||||
// REMIND: move to awt_Component.h
|
||||
extern "C" HWND AwtComponent_GetHWnd(JNIEnv *env, jlong pData);
|
||||
@@ -163,6 +175,134 @@ D3DSD_Unlock(JNIEnv *env,
|
||||
JNU_ThrowInternalError(env, "D3DSD_Unlock not implemented!");
|
||||
}
|
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
jboolean loadNativeRasterWithRectsImpl(
|
||||
D3DSDOps * d3dsdo, jlong pRaster, jint width, jint height,
|
||||
jlong pRects, jint rectsCount
|
||||
) {
|
||||
D3DPipelineManager * pMgr = D3DPipelineManager::GetInstance();
|
||||
if (d3dsdo == NULL || d3dsdo->pResource == NULL || pMgr == NULL || pRaster == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "D3DSurfaceData_loadNativeRasterWithRects: null param.");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
J2dTraceLn3(J2D_TRACE_VERBOSE, "D3DSurfaceData_loadNativeRasterWithRects: ops=%p r=%p rCount=%d\n", (void*)d3dsdo, (void*)pRaster, rectsCount);
|
||||
|
||||
HRESULT res;
|
||||
D3DContext *pCtx;
|
||||
if (FAILED(res = pMgr->GetD3DContext(d3dsdo->adapter, &pCtx))) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "D3DSurfaceData_loadNativeRasterWithRects: failed GetD3DContext.");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Blit via tiles
|
||||
//
|
||||
|
||||
D3DResource *pBlitTextureRes = NULL;
|
||||
res = pCtx->GetResourceManager()->GetBlitTexture(&pBlitTextureRes);
|
||||
if (FAILED(res)) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "D3DSurfaceData_loadNativeRasterWithRects: failed GetBlitTexture.");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *pBlitSurface = pBlitTextureRes->GetSurface();
|
||||
IDirect3DTexture9 *pBlitTexture = pBlitTextureRes->GetTexture();
|
||||
D3DSURFACE_DESC *pBlitDesc = pBlitTextureRes->GetDesc();
|
||||
|
||||
res = pCtx->BeginScene(STATE_TEXTUREOP);
|
||||
if (FAILED(res)) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "D3DSurfaceData_loadNativeRasterWithRects: failed BeginScene.");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
res = pCtx->SetTexture(pBlitTexture);
|
||||
if (FAILED(res)) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "D3DSurfaceData_loadNativeRasterWithRects: failed SetTexture.");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
IDirect3DDevice9 *pd3dDevice = pCtx->Get3DDevice();
|
||||
pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
|
||||
pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE);
|
||||
pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
|
||||
SurfaceDataRasInfo srcInfo;
|
||||
ZeroMemory(&srcInfo, sizeof(SurfaceDataRasInfo));
|
||||
srcInfo.bounds.x1 = 0;
|
||||
srcInfo.bounds.y1 = 0;
|
||||
srcInfo.bounds.x2 = width;
|
||||
srcInfo.bounds.y2 = height;
|
||||
srcInfo.scanStride = width*4;
|
||||
srcInfo.pixelStride = 4;
|
||||
srcInfo.rasBase = (void*)pRaster;
|
||||
srcInfo.pixelBitOffset = 0;
|
||||
|
||||
const jint tw = pBlitDesc->Width;
|
||||
const jint th = pBlitDesc->Height;
|
||||
jint sy, dy;
|
||||
jint sx, dx;
|
||||
for (sy = 0, dy = 0; sy < height; sy += th, dy += th) {
|
||||
jint sh = ((sy + th) > height) ? (height - sy) : th;
|
||||
jint dh = ((dy + th) > height) ? (height - dy) : th;
|
||||
|
||||
for (sx = 0, dx = 0; sx < width; sx += tw, dx += tw) {
|
||||
jint sw = ((sx + tw) > width) ? (width - sx) : tw;
|
||||
jint dw = ((dx + tw) > width) ? (width - dx) : tw;
|
||||
|
||||
if (pRects == 0 || rectsCount < 1) {
|
||||
//fprintf(stderr, "D3D_loadNativeRasterWithRects: do full copy of tile\n");
|
||||
D3DBL_CopyImageToIntXrgbSurface(&srcInfo, ST_INT_ARGB, pBlitTextureRes, sx, sy, sw, sh, 0, 0);
|
||||
const double tx1 = ((double)sw) / tw;
|
||||
const double ty1 = ((double)sh) / th;
|
||||
res = pCtx->pVCacher->DrawTexture((float)dx, (float)dy, (float)(dx+dw), (float)(dy+dh),
|
||||
0.0f, 0.0f, (float)tx1, (float)ty1);
|
||||
} else {
|
||||
int32_t *pr = (int32_t *) pRects;
|
||||
for (int c = 0; c < rectsCount; ++c) {
|
||||
const int32_t rx = *(pr++);
|
||||
const int32_t ry = *(pr++);
|
||||
const int32_t rw = *(pr++);
|
||||
const int32_t rh = *(pr++);
|
||||
// Check intersection with tile.
|
||||
if (sx + sw <= rx || sy + sh <= ry || rx + rw <= sx || rx + rw <= sx)
|
||||
continue;
|
||||
|
||||
// Calc intersection rect.
|
||||
const int32_t rcX0 = MAX(sx, rx);
|
||||
const int32_t rcY0 = MAX(sy, ry);
|
||||
const int32_t rcX1 = MIN(sx + sw, rx + rw);
|
||||
const int32_t rcY1 = MIN(sy + sh, ry + rh);
|
||||
const int32_t rectW = rcX1 - rcX0;
|
||||
const int32_t rectH = rcY1 - rcY0;
|
||||
const int32_t relX0 = rcX0 - sx;
|
||||
const int32_t relY0 = rcY0 - sy;
|
||||
const int32_t relX1 = rcX1 - sx;
|
||||
const int32_t relY1 = rcY1 - sy;
|
||||
|
||||
// Blit.
|
||||
D3DBL_CopyImageToIntXrgbSurface(&srcInfo, ST_INT_ARGB, pBlitTextureRes, rcX0, rcY0, rectW, rectH, relX0, relY0);
|
||||
|
||||
// Render.
|
||||
const double tx0 = ((double)relX0) / tw;
|
||||
const double ty0 = ((double)relY0) / th;
|
||||
const double tx1 = ((double)relX1) / tw;
|
||||
const double ty1 = ((double)relY1) / th;
|
||||
res = pCtx->pVCacher->DrawTexture(
|
||||
(float)dx + relX0, (float)dy + relY0, (float)(dx + relX1), (float)(dy + relY1),
|
||||
(float)tx0, (float)ty0, (float)tx1, (float)ty1);
|
||||
}
|
||||
}
|
||||
|
||||
res = pCtx->pVCacher->Render();
|
||||
}
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
// ------------ D3DSurfaceData's JNI methods ----------------
|
||||
|
||||
|
||||
@@ -636,4 +776,17 @@ JNICALL Java_sun_java2d_d3d_D3DSurfaceData_updateWindowAccelImpl
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: sun_java2d_d3d_D3DSurfaceData
|
||||
* Method: loadNativeRasterWithRects
|
||||
* Signature:
|
||||
*/
|
||||
JNIEXPORT
|
||||
jboolean JNICALL Java_sun_java2d_d3d_D3DSurfaceData_loadNativeRasterWithRects
|
||||
(JNIEnv *env, jclass clazz, jlong pData, jlong pRaster, jint width, jint height, jlong pRects,
|
||||
jint rectsCount) {
|
||||
return loadNativeRasterWithRectsImpl((D3DSDOps *) jlong_to_ptr(pData), pRaster, width, height, pRects, rectsCount);
|
||||
}
|
||||
} // namespace extern C
|
||||
@@ -37,9 +37,7 @@
|
||||
jmethodID AwtClipboard::lostSelectionOwnershipMID;
|
||||
jobject AwtClipboard::theCurrentClipboard;
|
||||
|
||||
/* This flag is set while we call EmptyClipboard to indicate to
|
||||
WM_DESTROYCLIPBOARD handler that we are not losing ownership */
|
||||
BOOL AwtClipboard::isGettingOwnership = FALSE;
|
||||
volatile LONG /* BOOL */ AwtClipboard::isGettingOwnership = FALSE;
|
||||
|
||||
volatile jmethodID AwtClipboard::handleContentsChangedMID;
|
||||
volatile BOOL AwtClipboard::isClipboardViewerRegistered = FALSE;
|
||||
@@ -51,6 +49,8 @@ volatile BOOL AwtClipboard::isClipboardViewerRegistered = FALSE;
|
||||
*/
|
||||
|
||||
void AwtClipboard::LostOwnership(JNIEnv *env) {
|
||||
(void)::InterlockedExchange(&AwtClipboard::isOwner, FALSE); // isOwner = FALSE;
|
||||
|
||||
if (theCurrentClipboard != NULL) {
|
||||
env->CallVoidMethod(theCurrentClipboard, lostSelectionOwnershipMID);
|
||||
DASSERT(!safe_ExceptionOccurred(env));
|
||||
@@ -93,6 +93,52 @@ void AwtClipboard::UnregisterClipboardViewer(JNIEnv *env) {
|
||||
CATCH_BAD_ALLOC;
|
||||
}
|
||||
|
||||
|
||||
// ======================== JBR-5980 Pasting from clipboard not working reliably in Windows ===========================
|
||||
volatile BOOL AwtClipboard::areOwnershipExtraChecksEnabled = FALSE;
|
||||
volatile LONG /* BOOL */ AwtClipboard::isOwner = FALSE;
|
||||
jmethodID AwtClipboard::ensureNoOwnedDataMID = nullptr;
|
||||
|
||||
void AwtClipboard::SetOwnershipExtraChecksEnabled(BOOL enabled) {
|
||||
areOwnershipExtraChecksEnabled = enabled;
|
||||
}
|
||||
|
||||
void AwtClipboard::ExtraCheckOfOwnership() {
|
||||
if (areOwnershipExtraChecksEnabled != TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
JNIEnv* const env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
if (env == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isOwner =
|
||||
// Checks the actual value of AwtClipboard::isOwner without altering it
|
||||
(::InterlockedCompareExchange(&AwtClipboard::isOwner, TRUE, TRUE) != LONG{FALSE});
|
||||
if (isOwner) {
|
||||
const HWND toolkitHwnd = AwtToolkit::GetInstance().GetHWnd();
|
||||
|
||||
if (::OpenClipboard(toolkitHwnd) == 0) {
|
||||
// failed to open the clipboard
|
||||
return;
|
||||
}
|
||||
const HWND clipboardOwnerHwnd = ::GetClipboardOwner();
|
||||
::CloseClipboard();
|
||||
|
||||
if (clipboardOwnerHwnd != toolkitHwnd) {
|
||||
AwtClipboard::LostOwnership(env);
|
||||
}
|
||||
} else {
|
||||
if ((theCurrentClipboard != nullptr) && (ensureNoOwnedDataMID != nullptr)) {
|
||||
env->CallVoidMethod(theCurrentClipboard, ensureNoOwnedDataMID);
|
||||
DASSERT(!safe_ExceptionOccurred(env));
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====================================================================================================================
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
void awt_clipboard_uninitialize(JNIEnv *env) {
|
||||
@@ -111,7 +157,7 @@ void awt_clipboard_uninitialize(JNIEnv *env) {
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_windows_WClipboard_init(JNIEnv *env, jclass cls)
|
||||
Java_sun_awt_windows_WClipboard_init(JNIEnv *env, jclass cls, jboolean areOwnershipExtraChecksEnabled)
|
||||
{
|
||||
TRY;
|
||||
|
||||
@@ -119,6 +165,11 @@ Java_sun_awt_windows_WClipboard_init(JNIEnv *env, jclass cls)
|
||||
env->GetMethodID(cls, "lostSelectionOwnershipImpl", "()V");
|
||||
DASSERT(AwtClipboard::lostSelectionOwnershipMID != NULL);
|
||||
|
||||
AwtClipboard::ensureNoOwnedDataMID = env->GetMethodID(cls, "ensureNoOwnedData", "()V");
|
||||
DASSERT(AwtClipboard::ensureNoOwnedDataMID != nullptr);
|
||||
|
||||
AwtClipboard::SetOwnershipExtraChecksEnabled( (areOwnershipExtraChecksEnabled == JNI_TRUE) ? TRUE : FALSE );
|
||||
|
||||
CATCH_BAD_ALLOC;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,14 @@
|
||||
|
||||
class AwtClipboard {
|
||||
private:
|
||||
static BOOL isGettingOwnership;
|
||||
// This flag is set while we call EmptyClipboard to indicate to WM_DESTROYCLIPBOARD handler that
|
||||
// we are not losing ownership
|
||||
// Although the variable's type is LONG, it's supposed to be treated as BOOL,
|
||||
// with the only possible values TRUE and FALSE.
|
||||
// Also, all accesses to the variable (both reading and writing) MUST be performed using
|
||||
// Windows Interlocked Variable Access API.
|
||||
// LONG is only used to make sure it's safe to pass the variable to ::Interlocked*** functions.
|
||||
static volatile LONG /* BOOL */ isGettingOwnership;
|
||||
static volatile BOOL isClipboardViewerRegistered;
|
||||
static volatile jmethodID handleContentsChangedMID;
|
||||
|
||||
@@ -44,19 +51,40 @@ public:
|
||||
static jobject theCurrentClipboard;
|
||||
|
||||
INLINE static void GetOwnership() {
|
||||
AwtClipboard::isGettingOwnership = TRUE;
|
||||
(void)::InterlockedExchange(&isGettingOwnership, TRUE); // isGettingOwnership = TRUE
|
||||
VERIFY(EmptyClipboard());
|
||||
AwtClipboard::isGettingOwnership = FALSE;
|
||||
(void)::InterlockedExchange(&isGettingOwnership, FALSE); // isGettingOwnership = FALSE
|
||||
(void)::InterlockedExchange(&isOwner, TRUE); // isOwner = TRUE;
|
||||
}
|
||||
|
||||
INLINE static BOOL IsGettingOwnership() {
|
||||
return isGettingOwnership;
|
||||
// Returns the actual value of isGettingOwnership without altering it
|
||||
return ::InterlockedCompareExchange(&isGettingOwnership, TRUE, TRUE) != LONG{FALSE};
|
||||
}
|
||||
|
||||
static void LostOwnership(JNIEnv *env);
|
||||
static void WmClipboardUpdate(JNIEnv *env);
|
||||
static void RegisterClipboardViewer(JNIEnv *env, jobject jclipboard);
|
||||
static void UnregisterClipboardViewer(JNIEnv *env);
|
||||
|
||||
// ===================== JBR-5980 Pasting from clipboard not working reliably in Windows ==========================
|
||||
public:
|
||||
static jmethodID ensureNoOwnedDataMID;
|
||||
|
||||
public:
|
||||
static void SetOwnershipExtraChecksEnabled(BOOL enabled);
|
||||
// Checks if ownership has been lost since the last check or the last acquiring of ownership
|
||||
static void ExtraCheckOfOwnership();
|
||||
|
||||
private:
|
||||
static volatile BOOL areOwnershipExtraChecksEnabled;
|
||||
// Although the variable's type is LONG, it's supposed to be treated as BOOL,
|
||||
// with the only possible values TRUE and FALSE.
|
||||
// Also, all accesses to the variable (both reading and writing) MUST be performed using
|
||||
// Windows Interlocked Variable Access API.
|
||||
// LONG is only used to make sure it's safe to pass the variable to ::Interlocked*** functions.
|
||||
static volatile LONG /* BOOL */ isOwner;
|
||||
// ================================================================================================================
|
||||
};
|
||||
|
||||
#endif /* AWT_CLIPBOARD_H */
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "jlong.h"
|
||||
#include "awt_AWTEvent.h"
|
||||
#include "awt_BitmapUtil.h"
|
||||
#include "awt_Clipboard.h"
|
||||
#include "awt_Component.h"
|
||||
#include "awt_Cursor.h"
|
||||
#include "awt_Dimension.h"
|
||||
@@ -1603,6 +1604,12 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_ACTIVATEAPP:
|
||||
if (wParam == TRUE) {
|
||||
// the window is being activated, let's check if we still own the clipboard
|
||||
AwtClipboard::ExtraCheckOfOwnership();
|
||||
}
|
||||
break;
|
||||
case WM_MOUSEACTIVATE: {
|
||||
AwtWindow *window = GetContainer();
|
||||
if (window && window->IsFocusableWindow()) {
|
||||
@@ -4038,49 +4045,63 @@ void AwtComponent::SetCompositionWindow(RECT& r)
|
||||
ImmReleaseContext(hwnd, hIMC);
|
||||
}
|
||||
|
||||
void AwtComponent::OpenCandidateWindow(int x, int y)
|
||||
{
|
||||
void AwtComponent::OpenCandidateWindow(
|
||||
const int caretLeftX,
|
||||
const int caretTopY,
|
||||
const int caretRightX,
|
||||
const int caretBottomY
|
||||
) {
|
||||
UINT bits = 1;
|
||||
POINT p = {0, 0}; // upper left corner of the client area
|
||||
HWND hWnd = ImmGetHWnd();
|
||||
if (!::IsWindowVisible(hWnd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
HWND hTop = GetTopLevelParentForWindow(hWnd);
|
||||
::ClientToScreen(hTop, &p);
|
||||
int sx = ScaleUpAbsX(x) - p.x;
|
||||
int sy = ScaleUpAbsY(y) - p.y;
|
||||
const int sCaretLeftX = ScaleUpAbsX(caretLeftX) - p.x;
|
||||
const int sCaretTopY = ScaleUpAbsY(caretTopY) - p.y;
|
||||
const int sCaretRightX = ScaleUpAbsX(caretRightX) - p.x;
|
||||
const int sCaretBottomY = ScaleUpAbsY(caretBottomY) - p.y;
|
||||
|
||||
if (!m_bitsCandType) {
|
||||
SetCandidateWindow(m_bitsCandType, sx, sy);
|
||||
SetCandidateWindow(m_bitsCandType, sCaretLeftX, sCaretTopY, sCaretRightX, sCaretBottomY);
|
||||
return;
|
||||
}
|
||||
for (int iCandType=0; iCandType<32; iCandType++, bits<<=1) {
|
||||
if ( m_bitsCandType & bits )
|
||||
SetCandidateWindow(iCandType, sx, sy);
|
||||
SetCandidateWindow(iCandType, sCaretLeftX, sCaretTopY, sCaretRightX, sCaretBottomY);
|
||||
}
|
||||
}
|
||||
|
||||
void AwtComponent::SetCandidateWindow(int iCandType, int x, int y)
|
||||
{
|
||||
void AwtComponent::SetCandidateWindow(
|
||||
const int iCandType,
|
||||
const int caretLeftX,
|
||||
const int caretTopY,
|
||||
const int caretRightX,
|
||||
const int caretBottomY
|
||||
) {
|
||||
HWND hwnd = ImmGetHWnd();
|
||||
HIMC hIMC = ImmGetContext(hwnd);
|
||||
if (hIMC) {
|
||||
CANDIDATEFORM cf;
|
||||
cf.dwStyle = CFS_CANDIDATEPOS;
|
||||
ImmGetCandidateWindow(hIMC, 0, &cf);
|
||||
if (x != cf.ptCurrentPos.x || y != cf.ptCurrentPos.y) {
|
||||
if (caretLeftX != cf.ptCurrentPos.x || caretBottomY != cf.ptCurrentPos.y) {
|
||||
cf.dwIndex = iCandType;
|
||||
cf.dwStyle = CFS_CANDIDATEPOS;
|
||||
cf.ptCurrentPos = {x, y};
|
||||
cf.rcArea = {0, 0, 0, 0};
|
||||
cf.dwStyle = CFS_EXCLUDE;
|
||||
cf.ptCurrentPos = {caretLeftX, caretBottomY};
|
||||
cf.rcArea = {caretLeftX, caretTopY, caretRightX, caretBottomY};
|
||||
|
||||
ImmSetCandidateWindow(hIMC, &cf);
|
||||
}
|
||||
COMPOSITIONFORM cfr;
|
||||
cfr.dwStyle = CFS_POINT;
|
||||
ImmGetCompositionWindow(hIMC, &cfr);
|
||||
if (x != cfr.ptCurrentPos.x || y != cfr.ptCurrentPos.y) {
|
||||
if (caretLeftX != cfr.ptCurrentPos.x || caretBottomY != cfr.ptCurrentPos.y) {
|
||||
cfr.dwStyle = CFS_POINT;
|
||||
cfr.ptCurrentPos = {x, y};
|
||||
cfr.ptCurrentPos = {caretLeftX, caretBottomY};
|
||||
cfr.rcArea = {0, 0, 0, 0};
|
||||
ImmSetCompositionWindow(hIMC, &cfr);
|
||||
}
|
||||
|
||||
@@ -552,8 +552,8 @@ public:
|
||||
virtual MsgRouting WmPaste();
|
||||
|
||||
virtual void SetCompositionWindow(RECT &r);
|
||||
virtual void OpenCandidateWindow(int x, int y);
|
||||
virtual void SetCandidateWindow(int iCandType, int x, int y);
|
||||
virtual void OpenCandidateWindow(int caretLeftX, int caretTopY, int caretRightX, int caretBottomY);
|
||||
virtual void SetCandidateWindow(int iCandType, int caretLeftX, int caretTopY, int caretRightX, int caretBottomY);
|
||||
virtual MsgRouting WmImeSetContext(BOOL fSet, LPARAM *lplParam);
|
||||
virtual MsgRouting WmImeNotify(WPARAM subMsg, LPARAM bitsCandType);
|
||||
virtual MsgRouting WmImeStartComposition();
|
||||
|
||||
@@ -407,7 +407,7 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WInputMethod_setStatusWindowVisible
|
||||
* Signature: (Lsun/awt/windows/WComponentPeer;II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_awt_windows_WInputMethod_openCandidateWindow
|
||||
(JNIEnv *env, jobject self, jobject peer, jint x, jint y)
|
||||
(JNIEnv *env, jobject self, jobject peer, jint caretLeftX, jint caretTopY, jint caretRightX, jint caretBottomY)
|
||||
{
|
||||
TRY;
|
||||
|
||||
@@ -415,19 +415,26 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WInputMethod_openCandidateWindow
|
||||
JNI_CHECK_PEER_RETURN(peer);
|
||||
|
||||
jobject peerGlobalRef = env->NewGlobalRef(peer);
|
||||
if (peerGlobalRef == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// WARNING! MAKELONG macro treats the given values as unsigned.
|
||||
// This may lead to some bugs in multiscreen configurations, as
|
||||
// coordinates can be negative numbers. So, while handling
|
||||
// WM_AWT_OPENCANDIDATEWINDOW message in AwtToolkit, we should
|
||||
// carefully extract right x and y values using GET_X_LPARAM and
|
||||
// GET_Y_LPARAM, not LOWORD and HIWORD
|
||||
// See CR 4805862, AwtToolkit::WndProc
|
||||
// it'd be better to replace the static_cast with a placement new, but it's broken
|
||||
// in debug builds because the "new" expression is redefined as a macro
|
||||
::RECT* const caretRect = static_cast<::RECT*>( safe_Malloc(sizeof(::RECT)) );
|
||||
// safe_Malloc throws an std::bad_alloc if fails, so we don't need to add a nullptr check here
|
||||
*caretRect = ::RECT{ caretLeftX, caretTopY, caretRightX, caretBottomY };
|
||||
|
||||
// use special message to open candidate window in main thread.
|
||||
AwtToolkit::GetInstance().InvokeInputMethodFunction(WM_AWT_OPENCANDIDATEWINDOW,
|
||||
(WPARAM)peerGlobalRef, MAKELONG(x, y));
|
||||
// global ref is deleted in message handler
|
||||
// use a special message to open a candidate window in main thread.
|
||||
static_assert( sizeof(peerGlobalRef) <= sizeof(WPARAM), "peerGlobalRef may not fit into WPARAM type" );
|
||||
static_assert( sizeof(caretRect) <= sizeof(LPARAM), "caretRect may not fit into LPARAM type" );
|
||||
AwtToolkit::GetInstance().InvokeInputMethodFunction(
|
||||
WM_AWT_OPENCANDIDATEWINDOW,
|
||||
reinterpret_cast<WPARAM>(peerGlobalRef),
|
||||
reinterpret_cast<LPARAM>(caretRect)
|
||||
);
|
||||
|
||||
// peerGlobalRef and caretRect are deleted in the message handler (AwtToolkit::WndProc)
|
||||
|
||||
CATCH_BAD_ALLOC;
|
||||
}
|
||||
|
||||
@@ -1247,16 +1247,33 @@ LRESULT CALLBACK AwtToolkit::WndProc(HWND hWnd, UINT message,
|
||||
return (LRESULT)activateKeyboardLayout((HKL)lParam);
|
||||
}
|
||||
case WM_AWT_OPENCANDIDATEWINDOW: {
|
||||
jobject peerObject = (jobject)wParam;
|
||||
AwtComponent* p = (AwtComponent*)JNI_GET_PDATA(peerObject);
|
||||
jobject peerObject = reinterpret_cast<jobject>(wParam);
|
||||
AwtComponent* p = reinterpret_cast<AwtComponent*>( JNI_GET_PDATA(peerObject) );
|
||||
DASSERT( !IsBadReadPtr(p, sizeof(AwtObject)));
|
||||
// fix for 4805862: use GET_X_LPARAM and GET_Y_LPARAM macros
|
||||
// instead of LOWORD and HIWORD
|
||||
p->OpenCandidateWindow(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
env->DeleteGlobalRef(peerObject);
|
||||
|
||||
::RECT* caretRect = reinterpret_cast<::RECT*>(lParam);
|
||||
DASSERT( !IsBadReadPtr(caretRect, sizeof(*caretRect)) );
|
||||
|
||||
if ( (p != nullptr) && (caretRect != nullptr) ) {
|
||||
p->OpenCandidateWindow(caretRect->left, caretRect->top, caretRect->right, caretRect->bottom);
|
||||
}
|
||||
|
||||
// Cleaning up
|
||||
if (caretRect != nullptr) {
|
||||
free(caretRect);
|
||||
caretRect = nullptr;
|
||||
}
|
||||
if (peerObject != nullptr) {
|
||||
env->DeleteGlobalRef(peerObject);
|
||||
peerObject = nullptr;
|
||||
}
|
||||
p = nullptr;
|
||||
|
||||
// Returning to AwtToolkit::InvokeInputMethodFunction
|
||||
AwtToolkit& tk = AwtToolkit::GetInstance();
|
||||
tk.m_inputMethodData = 0;
|
||||
::SetEvent(tk.m_inputMethodWaitEvent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
18
src/jetbrains.api/src/com/jetbrains/NativeRasterLoader.java
Normal file
18
src/jetbrains.api/src/com/jetbrains/NativeRasterLoader.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.jetbrains;
|
||||
|
||||
import java.awt.image.VolatileImage;
|
||||
|
||||
public interface NativeRasterLoader {
|
||||
/**
|
||||
* Loads native image raster into VolatileImage.
|
||||
*
|
||||
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
|
||||
* Note: The color data in this image is considered to be premultiplied with alpha.
|
||||
* @param width width of image in pixels
|
||||
* @param height height of image in pixels
|
||||
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
|
||||
* Note: can be null (then whole image used)
|
||||
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
|
||||
*/
|
||||
void loadNativeRaster(VolatileImage vi, long pRaster, int width, int height, long pRects, int rectsCount);
|
||||
}
|
||||
@@ -6,9 +6,9 @@
|
||||
# 2. When only new API is added, or some existing API was @Deprecated - increment MINOR, reset PATCH to 0
|
||||
# 3. For major backwards incompatible API changes - increment MAJOR, reset MINOR and PATCH to 0
|
||||
|
||||
VERSION = 1.9.0
|
||||
VERSION = 1.10.0
|
||||
|
||||
# Hash is used to track changes to jetbrains.api, so you would not forget to update version when needed.
|
||||
# When you make any changes, "make jbr-api" will fail and ask you to update hash and version number here.
|
||||
|
||||
HASH = 34E293D39C67B301086DDAD59EB9426
|
||||
HASH = 825E9B6832D82F59A0FFEAA4DA6F4A2
|
||||
|
||||
92
test/hotspot/jtreg/jbFdProblemList.txt
Normal file
92
test/hotspot/jtreg/jbFdProblemList.txt
Normal file
@@ -0,0 +1,92 @@
|
||||
#
|
||||
# Copyright (c) 2016, 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.
|
||||
#
|
||||
|
||||
#############################################################################
|
||||
#
|
||||
# List of quarantined tests -- tests that should not be run by default, because
|
||||
# they may fail due to known reason. The reason (CR#) must be mandatory specified.
|
||||
#
|
||||
# List items are testnames followed by labels, all MUST BE commented
|
||||
# as to why they are here and use a label:
|
||||
# generic-all Problems on all platforms
|
||||
# generic-ARCH Where ARCH is one of: x64, i586, ppc64, ppc64le, s390x etc.
|
||||
# OSNAME-all Where OSNAME is one of: linux, windows, macosx, aix
|
||||
# OSNAME-ARCH Specific on to one OSNAME and ARCH, e.g. macosx-x64
|
||||
# OSNAME-REV Specific on to one OSNAME and REV, e.g. macosx-10.7.4
|
||||
#
|
||||
# More than one label is allowed but must be on the same line.
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
|
||||
#############################################################################
|
||||
|
||||
# gtest
|
||||
|
||||
#gtest/AsyncLogGtest.java initial_run generic-all
|
||||
|
||||
# :hotspot_compiler
|
||||
|
||||
compiler/c2/irTests/TestVectorConditionalMove.java NOBUG windows-aarch64 # compiler.lib.ir_framework.driver.irmatching.IRViolationException: There were one or multiple IR rule failures. Please check stderr for more information.
|
||||
compiler/ciReplay/TestInlining.java 8300210 generic-all
|
||||
compiler/ciReplay/TestIncrementalInlining.java NOBUG generic-all
|
||||
compiler/ciReplay/TestInliningProtectionDomain.java NOBUG generic-all
|
||||
compiler/ciReplay/TestLambdas.java 8300210 generic-all
|
||||
compiler/ciReplay/TestServerVM.java 8300210 generic-all
|
||||
compiler/ciReplay/TestUnresolvedClasses.java NOBUG generic-all
|
||||
|
||||
#############################################################################
|
||||
|
||||
# :hotspot_gc
|
||||
|
||||
gc/stress/gcold/TestGCOldWithShenandoah.java#iu-aggressive NOBUG generic-all timeout
|
||||
|
||||
#############################################################################
|
||||
|
||||
# :hotspot_runtime
|
||||
|
||||
runtime/cds/appcds/dynamicArchive/TestDynamicDumpAtOom.java JBR-6291 generic-all
|
||||
|
||||
#############################################################################
|
||||
|
||||
# :hotspot_serviceability
|
||||
|
||||
serviceability/sa/ClhsdbCDSCore.java initial_run,NOBUG generic-aarch64,macosx-all Can't attach to the core file
|
||||
|
||||
#############################################################################
|
||||
|
||||
# :hotspot_misc
|
||||
|
||||
#############################################################################
|
||||
|
||||
|
||||
#############################################################################
|
||||
|
||||
# :vmTestbase_*
|
||||
|
||||
#############################################################################
|
||||
|
||||
vmTestbase/gc/gctests/LargeObjects/large002/TestDescription.java NOBUG linux-all timeout
|
||||
vmTestbase/gc/gctests/StringInternSyncWithGC/StringInternSyncWithGC.java NOBUG macosx-all timeout on macstudio
|
||||
|
||||
vmTestbase/jit/misctests/fpustack/GraphApplet.java NOBUG windows-aarch64 timeout
|
||||
@@ -47,15 +47,20 @@ gtest/LargePageGtests.java#use-large-pages-1G initial_run linux-all
|
||||
gtest/GTestWrapper.java initial_run generic-all
|
||||
gtest/MetaspaceUtilsGtests.java initial_run generic-all
|
||||
gtest/MetaspaceGtests.java#balanced-no-ccs initial_run generic-all
|
||||
gtest/MetaspaceGtests.java#balanced-with-guards JBR-5718 generic-all
|
||||
gtest/MetaspaceGtests.java#reclaim-aggressive-debug JBR-5718 generic-all
|
||||
gtest/MetaspaceGtests.java#reclaim-none-debug JBR-5718 generic-all
|
||||
gtest/MetaspaceGtests.java#reclaim-aggressive-ndebug initial_run generic-all
|
||||
gtest/LargePageGtests.java#use-large-pages initial_run linux-all,windows-all
|
||||
|
||||
gtest/NativeHeapTrimmerGtest.java JBR-5718 generic-all
|
||||
gtest/NMTGtests.java#nmt-detail JBR-5718 generic-all
|
||||
gtest/NMTGtests.java#nmt-off JBR-5718 generic-all
|
||||
gtest/NMTGtests.java#nmt-summary JBR-5718 generic-all
|
||||
|
||||
gc/stress/TestReclaimStringsLeaksMemory.java initial_run windows-all
|
||||
|
||||
gc/shenandoah/TestAllocHumongousFragment.java#aggressive 8309622 generic-all
|
||||
gc/shenandoah/TestAllocObjects.java#aggressive initial_run generic-all
|
||||
gc/shenandoah/TestAllocObjects.java#iu-aggressive initial_run generic-all
|
||||
gc/shenandoah/mxbeans/TestChurnNotifications.java#aggressive initial_run generic-all
|
||||
@@ -71,7 +76,6 @@ compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java 8
|
||||
compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all
|
||||
|
||||
compiler/runtime/Test8168712.java 8211769,8211771 generic-ppc64,generic-ppc64le,linux-s390x
|
||||
runtime/Thread/ThreadCountLimit.java 8293872 linux-all
|
||||
|
||||
compiler/rtm/locking/TestRTMAbortRatio.java 8183263 generic-x64
|
||||
compiler/rtm/locking/TestRTMAbortThreshold.java 8183263 generic-x64
|
||||
@@ -98,15 +102,15 @@ gc/epsilon/TestMemoryMXBeans.java 8206434 generic-all
|
||||
gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java 8156755 generic-all
|
||||
gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all
|
||||
gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all
|
||||
gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64
|
||||
gc/metaspace/TestMetaspacePerfCounters.java#id3 initial_run generic-all
|
||||
gc/stress/gclocker/TestExcessGCLockerCollections.java 8229120 generic-all
|
||||
gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all
|
||||
gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all
|
||||
gc/stress/gclocker/TestGCLockerWithShenandoah.java initial_run generic-all
|
||||
gc/stress/gclocker/TestGCLockerWithShenandoah.java#aggressive initial_run generic-all
|
||||
gc/stress/gcold/TestGCOldWithShenandoah.java#iu-aggressive initial_run windows-all
|
||||
gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all
|
||||
gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64
|
||||
gc/metaspace/TestMetaspacePerfCounters.java#id3 initial_run generic-all
|
||||
|
||||
gc/stress/gcold/TestGCOldWithShenandoah.java initial_run windows-all
|
||||
|
||||
#############################################################################
|
||||
|
||||
@@ -125,19 +129,24 @@ runtime/memory/ReadFromNoaccessArea.java initial_run windows-aarch64
|
||||
runtime/cds/appcds/methodHandles/MethodHandlesInvokersTest.java initial_run generic-all
|
||||
runtime/cds/appcds/methodHandles/MethodHandlesCastFailureTest.java initial_run generic-all
|
||||
runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java initial_run generic-all
|
||||
runtime/ReservedStack/ReservedStackTestCompiler.java initial_run windows-aarch64
|
||||
runtime/cds/appcds/dynamicArchive/CDSStreamTestDriver.java initial_run generic-all
|
||||
runtime/ErrorHandling/CreateCoredumpOnCrash.java initial_run windows-aarch64
|
||||
runtime/ReservedStack/ReservedStackTest.java initial_run windows-aarch64
|
||||
runtime/cds/appcds/methodHandles/MethodHandlesPermuteArgumentsTest.java initial_run generic-all
|
||||
runtime/cds/appcds/methodHandles/MethodHandlesAsCollectorTest.java initial_run generic-all
|
||||
runtime/cds/SharedBaseAddress.java initial_run generic-all
|
||||
runtime/cds/appcds/methodHandles/MethodHandlesSpreadArgumentsTest.java initial_run generic-all
|
||||
runtime/cds/appcds/dynamicArchive/CDSStreamTestDriver.java initial_run generic-all
|
||||
runtime/ReservedStack/ReservedStackTestCompiler.java initial_run windows-aarch64
|
||||
runtime/ErrorHandling/CreateCoredumpOnCrash.java initial_run windows-aarch64
|
||||
runtime/ErrorHandling/MachCodeFramesInErrorFile.java JBR-6289 windows-aarch64
|
||||
runtime/ReservedStack/ReservedStackTest.java initial_run windows-aarch64
|
||||
runtime/Thread/ThreadCountLimit.java 8293872 linux-all
|
||||
runtime/Thread/TooSmallStackSize.java JBR-6350 windows-aarch64
|
||||
|
||||
#############################################################################
|
||||
|
||||
# :hotspot_serviceability
|
||||
|
||||
serviceability/dcmd/vm/TrimLibcHeapTest.java 8312625 linux-all
|
||||
|
||||
serviceability/sa/sadebugd/DebugdConnectTest.java 8239062 macosx-x64
|
||||
serviceability/sa/TestRevPtrsForInvokeDynamic.java 8241235 generic-all
|
||||
|
||||
@@ -145,6 +154,7 @@ serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java 8225354 w
|
||||
serviceability/jvmti/RedefineClasses/TestMultipleClasses.java initial_run windows-all
|
||||
serviceability/jvmti/SetBreakpoint/TestManyBreakpoints.java initial_run generic-aarch64
|
||||
|
||||
serviceability/sa/ClhsdbInspect.java JBR-6351 windows-aarch64
|
||||
serviceability/sa/ClhsdbJstackXcompStress.java initial_run windows-all
|
||||
|
||||
serviceability/sa/ClhsdbPrintAs.java initial_run generic-all
|
||||
@@ -192,7 +202,11 @@ vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001/TestDes
|
||||
|
||||
vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java 7034630 generic-all
|
||||
vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java initial_run linux-all
|
||||
vmTestbase/nsk/jdi/Value/type/type002/type002.java time_out_intermittent macosx-x64
|
||||
vmTestbase/nsk/jdi/Value/type/type003/TestDescription.java time_out_intermittent macosx-all
|
||||
vmTestbase/nsk/jdi/VirtualMachine/canGetBytecodes/cangetbytecodes001/TestDescription.java time_out_intermittent macosx-aarch64
|
||||
vmTestbase/nsk/jdi/VirtualMachine/canGetCurrentContendedMonitor/cangccm001/TestDescription.java time_out_intermittent macosx-aarch64
|
||||
vmTestbase/nsk/jdi/VirtualMachine/canGetMonitorInfo/cangetmonitorinfo001/TestDescription.java JBR-6361 macosx-aarch64
|
||||
|
||||
vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java 8208250 generic-all
|
||||
vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java 8208250 generic-all
|
||||
@@ -220,7 +234,7 @@ vmTestbase/vm/mlvm/indy/func/jvmti/redefineClassInBootstrap/TestDescription.java
|
||||
vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2none_a/TestDescription.java 8013267 generic-all
|
||||
vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_b/TestDescription.java 8013267 generic-all
|
||||
vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_b/TestDescription.java 8013267 generic-all
|
||||
vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java#id0 8269393 macos-aarch64
|
||||
vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java#id0 8269393 macosx-aarch64
|
||||
|
||||
|
||||
vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java 7199837 generic-all
|
||||
@@ -289,5 +303,6 @@ vmTestbase/nsk/sysdict/vm/stress/btree/btree009/btree009.java initial_run window
|
||||
resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java 8220624 generic-all
|
||||
|
||||
testlibrary_tests/ir_framework/tests/TestDTestAndExclude.java initial_run windows-all
|
||||
testlibrary_tests/ir_framework/tests/TestSanity.java JBR-6352 windows-x64
|
||||
|
||||
jb/applications/ctw/plugins_cucumber_java_lib_cucumber_java.java JBR-6084 windows-all
|
||||
@@ -204,7 +204,7 @@ public class MainModuleOnly extends DynamicArchiveTestBase {
|
||||
"--module-path", moduleDir.toString(),
|
||||
"-m", TEST_MODULE1)
|
||||
.assertAbnormalExit(
|
||||
"A jar file is not the one used while building the shared archive file:");
|
||||
"This file is not the one used while building the shared archive file:");
|
||||
// create an archive with a non-empty directory in the --module-path.
|
||||
// The dumping process will exit with an error due to non-empty directory
|
||||
// in the --module-path.
|
||||
|
||||
@@ -65,7 +65,7 @@ public class MainModuleOnly {
|
||||
private static Path moduleDir2 = null;
|
||||
private static Path destJar = null;
|
||||
|
||||
private static final String jarFileError = "A jar file is not the one used while building the shared archive file:";
|
||||
private static final String jarFileError = "This file is not the one used while building the shared archive file:";
|
||||
|
||||
public static void buildTestModule() throws Exception {
|
||||
|
||||
|
||||
@@ -130,14 +130,12 @@ public class RowToleranceTransitivityTest {
|
||||
static void test() throws Exception {
|
||||
robot.delay(500);
|
||||
|
||||
// Set focus on the first component to start traversal
|
||||
if (!setFocusOn(ft, new Runnable() {
|
||||
public void run() {
|
||||
clickOn(ft);
|
||||
}
|
||||
})) {
|
||||
System.out.println("Couldn't set focus on " + ft);
|
||||
throw new RuntimeException("Test couldn't be performed.");
|
||||
clickOn(ft);
|
||||
|
||||
robot.delay(500);
|
||||
|
||||
if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != ft) {
|
||||
throw new RuntimeException("Cannot set initial focus");
|
||||
}
|
||||
|
||||
robot.delay(500);
|
||||
|
||||
@@ -34,37 +34,43 @@
|
||||
import java.awt.Frame;
|
||||
import java.awt.Robot;
|
||||
import java.awt.TextArea;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import test.java.awt.regtesthelpers.Util;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class TextAreaEditing {
|
||||
|
||||
final static Robot robot = Util.createRobot();
|
||||
private int testFailCount;
|
||||
private boolean isTestFail;
|
||||
private StringBuilder testFailMessage;
|
||||
private volatile int testFailCount = 0;
|
||||
private volatile boolean isTestFail = false;
|
||||
private final StringBuilder testFailMessage = new StringBuilder();
|
||||
|
||||
private Frame mainFrame;
|
||||
private TextArea textArea;
|
||||
private Frame mainFrame = null;
|
||||
private TextArea textArea = null;
|
||||
|
||||
private TextAreaEditing() {
|
||||
testFailMessage = new StringBuilder();
|
||||
mainFrame = new Frame();
|
||||
mainFrame.setSize(200, 200);
|
||||
private TextAreaEditing() throws InterruptedException, InvocationTargetException {
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
mainFrame = new Frame();
|
||||
mainFrame.setSize(200, 200);
|
||||
|
||||
textArea = new TextArea();
|
||||
mainFrame.add(textArea);
|
||||
mainFrame.setVisible(true);
|
||||
textArea = new TextArea();
|
||||
mainFrame.add(textArea);
|
||||
mainFrame.setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
private void dispose() {
|
||||
if (mainFrame != null) {
|
||||
mainFrame.dispose();
|
||||
}
|
||||
private void dispose() throws InterruptedException, InvocationTargetException {
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
if (mainFrame != null) {
|
||||
mainFrame.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] s) {
|
||||
public static void main(String[] s) throws InterruptedException, InvocationTargetException {
|
||||
TextAreaEditing textArea = new TextAreaEditing();
|
||||
textArea.testReplaceRange();
|
||||
textArea.testInsert();
|
||||
@@ -74,79 +80,90 @@ public class TextAreaEditing {
|
||||
textArea.dispose();
|
||||
}
|
||||
|
||||
private void testReplaceRange() {
|
||||
textArea.setText(null);
|
||||
textArea.replaceRange("Replace", 0, 0);
|
||||
textArea.setText(null);
|
||||
checkTest("");
|
||||
private void testReplaceRange() throws InterruptedException, InvocationTargetException {
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
textArea.setText(null);
|
||||
textArea.replaceRange("Replace", 0, 0);
|
||||
textArea.setText(null);
|
||||
checkTest("");
|
||||
|
||||
textArea.setText("SetText");
|
||||
textArea.replaceRange("Replace", 0, 3);
|
||||
checkTest("ReplaceText");
|
||||
textArea.setText("SetText");
|
||||
textArea.replaceRange("Replace", 0, 3);
|
||||
checkTest("ReplaceText");
|
||||
|
||||
textArea.replaceRange("String", textArea.getText().length(),
|
||||
textArea.getText().length());
|
||||
checkTest("ReplaceTextString");
|
||||
textArea.replaceRange("String", textArea.getText().length(),
|
||||
textArea.getText().length());
|
||||
checkTest("ReplaceTextString");
|
||||
|
||||
textArea.replaceRange("String", 0, 0);
|
||||
checkTest("StringReplaceTextString");
|
||||
textArea.replaceRange("String", 0, 0);
|
||||
checkTest("StringReplaceTextString");
|
||||
|
||||
textArea.replaceRange("replaceRange", 0, textArea.getText().length());
|
||||
checkTest("replaceRange");
|
||||
textArea.replaceRange("replaceRange", 0, textArea.getText().length());
|
||||
checkTest("replaceRange");
|
||||
});
|
||||
}
|
||||
|
||||
private void testInsert() {
|
||||
textArea.setText(null);
|
||||
textArea.insert("Insert", 0);
|
||||
textArea.setText("");
|
||||
checkTest("");
|
||||
private void testInsert() throws InterruptedException, InvocationTargetException {
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
textArea.setText(null);
|
||||
textArea.insert("Insert", 0);
|
||||
textArea.setText("");
|
||||
checkTest("");
|
||||
|
||||
textArea.setText("SetText");
|
||||
textArea.insert("Insert", 3);
|
||||
checkTest("SetInsertText");
|
||||
textArea.setText("SetText");
|
||||
textArea.insert("Insert", 3);
|
||||
checkTest("SetInsertText");
|
||||
|
||||
textArea.insert("Insert", 0);
|
||||
checkTest("InsertSetInsertText");
|
||||
textArea.insert("Insert", 0);
|
||||
checkTest("InsertSetInsertText");
|
||||
|
||||
textArea.insert("Insert", textArea.getText().length());
|
||||
checkTest("InsertSetInsertTextInsert");
|
||||
textArea.insert("Insert", textArea.getText().length());
|
||||
checkTest("InsertSetInsertTextInsert");
|
||||
});
|
||||
}
|
||||
|
||||
private void testAppend() {
|
||||
textArea.setText(null);
|
||||
textArea.append("Append");
|
||||
textArea.setText(null);
|
||||
checkTest("");
|
||||
private void testAppend() throws InterruptedException, InvocationTargetException {
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
textArea.setText(null);
|
||||
textArea.append("Append");
|
||||
textArea.setText(null);
|
||||
checkTest("");
|
||||
|
||||
textArea.setText("SetText");
|
||||
textArea.append("Append");
|
||||
checkTest("SetTextAppend");
|
||||
textArea.setText("SetText");
|
||||
textArea.append("Append");
|
||||
checkTest("SetTextAppend");
|
||||
|
||||
textArea.append("");
|
||||
checkTest("SetTextAppend");
|
||||
textArea.setText("");
|
||||
checkTest("");
|
||||
textArea.append("");
|
||||
checkTest("SetTextAppend");
|
||||
textArea.setText("");
|
||||
checkTest("");
|
||||
});
|
||||
}
|
||||
|
||||
private void testSetText() {
|
||||
textArea.setText(null);
|
||||
textArea.requestFocus();
|
||||
private void testSetText() throws InterruptedException, InvocationTargetException {
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
textArea.setText(null);
|
||||
textArea.requestFocus();
|
||||
});
|
||||
Util.clickOnComp(textArea, robot);
|
||||
Util.waitForIdle(robot);
|
||||
robot.keyPress(KeyEvent.VK_A);
|
||||
robot.delay(5);
|
||||
robot.keyRelease(KeyEvent.VK_A);
|
||||
Util.waitForIdle(robot);
|
||||
textArea.setText(null);
|
||||
checkTest("");
|
||||
textArea.setText("CaseSensitive");
|
||||
checkTest("CaseSensitive");
|
||||
textArea.setText("caseSensitive");
|
||||
checkTest("caseSensitive");
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
textArea.setText(null);
|
||||
checkTest("");
|
||||
textArea.setText("CaseSensitive");
|
||||
checkTest("CaseSensitive");
|
||||
textArea.setText("caseSensitive");
|
||||
checkTest("caseSensitive");
|
||||
});
|
||||
}
|
||||
|
||||
private void checkTest(String str) {
|
||||
assert SwingUtilities.isEventDispatchThread();
|
||||
|
||||
if (str != null && !str.equals(textArea.getText())) {
|
||||
testFailMessage.append("TestFail line : ");
|
||||
testFailMessage.append(Thread.currentThread().getStackTrace()[2].
|
||||
@@ -161,7 +178,7 @@ public class TextAreaEditing {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkFailures() {
|
||||
private void checkFailures() throws InterruptedException, InvocationTargetException {
|
||||
if (isTestFail) {
|
||||
testFailMessage.insert(0, "Test Fail count : " + testFailCount
|
||||
+ System.getProperty("line.separator"));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 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
|
||||
@@ -178,6 +179,8 @@ public class GrabTest {
|
||||
f1.setVisible(true);
|
||||
Util.waitForIdle(robot);
|
||||
Util.clickOnTitle(f1, robot);
|
||||
robot.delay(100);
|
||||
Util.waitForIdle(robot);
|
||||
if (!ungrabbed) {
|
||||
passed = false;
|
||||
System.err.println("Failure: [5] Press inside of other Frame's title didn't cause ungrab");
|
||||
|
||||
86
test/jdk/java/awt/a11y/AccessibleJComboBoxVoiceOverTest.java
Normal file
86
test/jdk/java/awt/a11y/AccessibleJComboBoxVoiceOverTest.java
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 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
|
||||
* @summary Test for VoiceOver-specific issues of JComboBox
|
||||
* @author dmitry.drobotov@jetbrains.com
|
||||
* @run main/manual AccessibleJComboBoxVoiceOverTest
|
||||
* @requires (os.family == "mac")
|
||||
*/
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.FlowLayout;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class AccessibleJComboBoxVoiceOverTest extends AccessibleComponentTest {
|
||||
|
||||
@java.lang.Override
|
||||
public CountDownLatch createCountDownLatch() {
|
||||
return new CountDownLatch(1);
|
||||
}
|
||||
|
||||
void createCombobox() {
|
||||
INSTRUCTIONS = """
|
||||
INSTRUCTIONS:
|
||||
Check VoiceOver-specific issues of JComboBox.
|
||||
|
||||
Turn VoiceOver on, and Tab to the combo box.
|
||||
|
||||
Use VO+Space shortcut to open the combo box and select a new item.
|
||||
Move keyboard focus away from the combo box using Shift+Tab and then back to the combo box by Tab.
|
||||
Repeat the same step with VoiceOver cursor navigation using VO+Left and VO+Right.
|
||||
|
||||
If in both cases VoiceOver reads the newly selected value, press PASS, otherwise press FAIL.""";
|
||||
|
||||
JPanel frame = new JPanel();
|
||||
|
||||
String[] NAMES = {"One", "Two", "Three", "Four", "Five"};
|
||||
JComboBox<String> combo = new JComboBox<>(NAMES);
|
||||
|
||||
JLabel label = new JLabel("This is combobox:");
|
||||
label.setLabelFor(combo);
|
||||
|
||||
frame.setLayout(new FlowLayout());
|
||||
frame.add(label);
|
||||
frame.add(combo);
|
||||
exceptionString = "AccessibleJComboBoxVoiceOver test failed!";
|
||||
super.createUI(frame, "AccessibleJComboBoxVoiceOverTest");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AccessibleJComboBoxVoiceOverTest test = new AccessibleJComboBoxVoiceOverTest();
|
||||
|
||||
countDownLatch = test.createCountDownLatch();
|
||||
SwingUtilities.invokeLater(test::createCombobox);
|
||||
countDownLatch.await();
|
||||
|
||||
if (!testResult) {
|
||||
throw new RuntimeException(a11yTest.exceptionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
test/jdk/jb/build/CDSArchivesTest.sh
Normal file
31
test/jdk/jb/build/CDSArchivesTest.sh
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# @test
|
||||
# @summary CDSArchivesTest.sh checks jsa files exist in jbrsdk distributions, jbr distributions are skipped
|
||||
# @run shell CDSArchivesTest.sh
|
||||
|
||||
if [ -z "${TESTJAVA}" ]; then
|
||||
echo "TESTJAVA undefined: testing cancelled"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source ${TESTJAVA}/release
|
||||
echo "Checking $IMPLEMENTOR_VERSION"
|
||||
if [[ "$IMPLEMENTOR_VERSION" != *"JBRSDK"* ]]; then
|
||||
echo "Test executed for JBRSDK only"
|
||||
echo "skipping the test"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
FIND="/usr/bin/find"
|
||||
files=$(${FIND} ${TESTJAVA} -name "*.jsa")
|
||||
ls -l $files
|
||||
if [ $? != 0 ]; then
|
||||
echo "Command failed."
|
||||
exit 1
|
||||
elif [ -z "$files" ]; then
|
||||
echo "*** FAILED *** jsa-files not found"
|
||||
echo "\n*** FAILED *** Test failed"
|
||||
exit 1
|
||||
fi
|
||||
echo "\nTest passed"
|
||||
@@ -22,7 +22,11 @@
|
||||
*/
|
||||
|
||||
import com.jetbrains.JBR;
|
||||
import util.*;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.utils.MouseUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -34,6 +38,8 @@ import java.util.List;
|
||||
* @test
|
||||
* @summary Verify mouse events in custom title bar's area added by ActionListener
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm ActionListenerTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 ActionListenerTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 ActionListenerTest
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
*/
|
||||
|
||||
import com.jetbrains.JBR;
|
||||
import util.CommonAPISuite;
|
||||
import util.Task;
|
||||
import util.TaskResult;
|
||||
import util.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
@@ -33,6 +33,8 @@ import java.lang.invoke.MethodHandles;
|
||||
* @test
|
||||
* @summary Verify modifying of title bar height
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm ChangeTitleBarHeightTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 ChangeTitleBarHeightTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 ChangeTitleBarHeightTest
|
||||
|
||||
@@ -1,6 +1,29 @@
|
||||
/*
|
||||
* Copyright 2000-2023 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import com.jetbrains.JBR;
|
||||
import com.jetbrains.WindowDecorations;
|
||||
import util.ScreenShotHelpers;
|
||||
import test.jb.testhelpers.screenshot.ScreenShotHelpers;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Color;
|
||||
@@ -16,6 +39,8 @@ import java.io.IOException;
|
||||
* @test
|
||||
* @summary Verify modifying of title bar height
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm CheckFullScreen
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 CheckFullScreen
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 CheckFullScreen
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
*/
|
||||
|
||||
import com.jetbrains.JBR;
|
||||
import util.CommonAPISuite;
|
||||
import util.Task;
|
||||
import util.TaskResult;
|
||||
import util.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
@@ -33,6 +33,8 @@ import java.lang.invoke.MethodHandles;
|
||||
* @test
|
||||
* @summary Verify creating to a custom title bar
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm CreateTitleBarTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 CreateTitleBarTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 CreateTitleBarTest
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
* questions.
|
||||
*/
|
||||
import com.jetbrains.JBR;
|
||||
import util.*;
|
||||
import test.jb.testhelpers.screenshot.ScreenShotHelpers;
|
||||
import test.jb.testhelpers.screenshot.Rect;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
@@ -36,6 +40,8 @@ import java.util.List;
|
||||
* @test
|
||||
* @summary Detect and check behavior of clicking to native controls
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm DialogNativeControlsTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 DialogNativeControlsTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 DialogNativeControlsTest
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2023 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
import com.jetbrains.JBR;
|
||||
import com.jetbrains.WindowDecorations;
|
||||
import util.*;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.awt.event.WindowStateListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Detect and check behavior of clicking to native controls
|
||||
* @requires (os.family == "mac")
|
||||
* @modules java.desktop/com.apple.eawt
|
||||
* java.desktop/com.apple.eawt.event
|
||||
* @run main/othervm FrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 FrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 FrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 FrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 FrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.5 FrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=3.0 FrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=3.5 FrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=4.0 FrameNativeControlsMacOSTest
|
||||
*/
|
||||
public class FrameNativeControlsMacOSTest {
|
||||
|
||||
public static void main(String... args) {
|
||||
List<Function<WindowDecorations.CustomTitleBar, Window>> functions =
|
||||
List.of(TestUtils::createFrameWithCustomTitleBar, TestUtils::createJFrameWithCustomTitleBar);
|
||||
TaskResult result = CommonAPISuite.runTestSuite(functions, frameNativeControlsClicks);
|
||||
|
||||
if (!result.isPassed()) {
|
||||
final String message = String.format("%s FAILED. %s", MethodHandles.lookup().lookupClass().getName(), result.getError());
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final Task frameNativeControlsClicks = new Task("Frame native controls clicks") {
|
||||
private boolean closingActionCalled;
|
||||
private boolean iconifyingActionCalled;
|
||||
private boolean maximizingActionDetected;
|
||||
private boolean deiconifyindActionDetected;
|
||||
|
||||
private final WindowListener windowListener = new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
closingActionCalled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
iconifyingActionCalled = true;
|
||||
|
||||
if (window.getName().equals("Frame")) {
|
||||
((Frame) window).setState(Frame.NORMAL);
|
||||
} else if (window.getName().equals("JFrame")) {
|
||||
((JFrame) window).setState(JFrame.NORMAL);
|
||||
}
|
||||
|
||||
window.setVisible(true);
|
||||
window.requestFocus();
|
||||
}
|
||||
};
|
||||
|
||||
private final WindowStateListener windowStateListener = new WindowAdapter() {
|
||||
@Override
|
||||
public void windowStateChanged(WindowEvent e) {
|
||||
System.out.println("change " + e.getOldState() + " -> " + e.getNewState());
|
||||
if (e.getNewState() == 6) {
|
||||
maximizingActionDetected = true;
|
||||
}
|
||||
if (e.getOldState() == 1 && e.getNewState() == 0) {
|
||||
deiconifyindActionDetected = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void prepareTitleBar() {
|
||||
titleBar = JBR.getWindowDecorations().createCustomTitleBar();
|
||||
titleBar.setHeight(TestUtils.TITLE_BAR_HEIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
closingActionCalled = false;
|
||||
iconifyingActionCalled = false;
|
||||
maximizingActionDetected = false;
|
||||
deiconifyindActionDetected = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanup() {
|
||||
window.removeWindowListener(windowListener);
|
||||
window.removeWindowStateListener(windowStateListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customizeWindow() {
|
||||
window.addWindowListener(windowListener);
|
||||
window.addWindowStateListener(windowStateListener);
|
||||
|
||||
if (window.getName().equals("JFrame")) {
|
||||
com.apple.eawt.FullScreenUtilities.addFullScreenListenerTo(window, new com.apple.eawt.FullScreenListener() {
|
||||
@Override
|
||||
public void windowEnteringFullScreen(com.apple.eawt.event.FullScreenEvent fse) {
|
||||
maximizingActionDetected = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowEnteredFullScreen(com.apple.eawt.event.FullScreenEvent fse) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowExitingFullScreen(com.apple.eawt.event.FullScreenEvent fse) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowExitedFullScreen(com.apple.eawt.event.FullScreenEvent fse) {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void test() throws Exception {
|
||||
robot.delay(500);
|
||||
robot.mouseMove(window.getLocationOnScreen().x + window.getWidth() / 2,
|
||||
window.getLocationOnScreen().y + window.getHeight() / 2);
|
||||
robot.delay(500);
|
||||
|
||||
BufferedImage image = ScreenShotHelpers.takeScreenshot(window);
|
||||
List<Rect> foundControls = ScreenShotHelpers.findControls(image, window, titleBar);
|
||||
|
||||
if (foundControls.size() == 0) {
|
||||
passed = false;
|
||||
System.out.println("Error: no controls found");
|
||||
}
|
||||
|
||||
foundControls.forEach(control -> {
|
||||
System.out.println("Using control: " + control);
|
||||
int x = window.getLocationOnScreen().x + control.getX1() + (control.getX2() - control.getX1()) / 2;
|
||||
int y = window.getLocationOnScreen().y + control.getY1() + (control.getY2() - control.getY1()) / 2;
|
||||
System.out.println("Click to (" + x + ", " + y + ")");
|
||||
|
||||
int screenX = window.getBounds().x;
|
||||
int screenY = window.getBounds().y;
|
||||
int h = window.getBounds().height;
|
||||
int w = window.getBounds().width;
|
||||
|
||||
robot.waitForIdle();
|
||||
robot.mouseMove(x, y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.waitForIdle();
|
||||
window.setBounds(screenX, screenY, w, h);
|
||||
window.setVisible(true);
|
||||
robot.waitForIdle();
|
||||
});
|
||||
|
||||
if (!maximizingActionDetected) {
|
||||
err("maximizing action was not detected");
|
||||
}
|
||||
|
||||
if (!closingActionCalled) {
|
||||
err("closing action was not detected");
|
||||
}
|
||||
|
||||
if (!iconifyingActionCalled) {
|
||||
err("iconifying action was not detected");
|
||||
}
|
||||
if (!deiconifyindActionDetected) {
|
||||
err("deiconifying action was not detected");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -22,7 +22,12 @@
|
||||
*/
|
||||
import com.jetbrains.JBR;
|
||||
import com.jetbrains.WindowDecorations;
|
||||
import util.*;
|
||||
import test.jb.testhelpers.screenshot.ScreenShotHelpers;
|
||||
import test.jb.testhelpers.screenshot.Rect;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import java.awt.Frame;
|
||||
@@ -40,7 +45,9 @@ import java.util.function.Function;
|
||||
/*
|
||||
* @test
|
||||
* @summary Detect and check behavior of clicking to native controls
|
||||
* @requires (os.family == "windows")
|
||||
* @requires (os.family == "windows") | (os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm FrameNativeControlsTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 FrameNativeControlsTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 FrameNativeControlsTest
|
||||
@@ -54,8 +61,7 @@ import java.util.function.Function;
|
||||
public class FrameNativeControlsTest {
|
||||
|
||||
public static void main(String... args) {
|
||||
List<Function<WindowDecorations.CustomTitleBar, Window>> functions =
|
||||
List.of(TestUtils::createFrameWithCustomTitleBar, TestUtils::createJFrameWithCustomTitleBar);
|
||||
List<Function<WindowDecorations.CustomTitleBar, Window>> functions = List.of(TestUtils::createFrameWithCustomTitleBar);
|
||||
TaskResult result = CommonAPISuite.runTestSuite(functions, frameNativeControlsClicks);
|
||||
|
||||
if (!result.isPassed()) {
|
||||
@@ -140,7 +146,7 @@ public class FrameNativeControlsTest {
|
||||
BufferedImage image = ScreenShotHelpers.takeScreenshot(window);
|
||||
List<Rect> foundControls = ScreenShotHelpers.findControls(image, window, titleBar);
|
||||
|
||||
if (foundControls.size() == 0) {
|
||||
if (foundControls.isEmpty()) {
|
||||
passed = false;
|
||||
System.out.println("Error: no controls found");
|
||||
}
|
||||
|
||||
@@ -21,7 +21,13 @@
|
||||
* questions.
|
||||
*/
|
||||
import com.jetbrains.JBR;
|
||||
import util.*;
|
||||
|
||||
import test.jb.testhelpers.screenshot.ScreenShotHelpers;
|
||||
import test.jb.testhelpers.screenshot.Rect;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
|
||||
import java.awt.Robot;
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -32,6 +38,8 @@ import java.util.List;
|
||||
* @test
|
||||
* @summary Verify a property to change visibility of native controls
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm HiddenNativeControlsTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 HiddenNativeControlsTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 HiddenNativeControlsTest
|
||||
@@ -89,7 +97,7 @@ public class HiddenNativeControlsTest {
|
||||
System.out.println("Found controls at the title bar:");
|
||||
foundControls.forEach(System.out::println);
|
||||
|
||||
if (foundControls.size() != 0) {
|
||||
if (!foundControls.isEmpty()) {
|
||||
err("controls are disabled, but found in the screenshot");
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,15 @@
|
||||
*/
|
||||
|
||||
import com.jetbrains.JBR;
|
||||
import util.*;
|
||||
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.utils.MouseUtils;
|
||||
import util.AWTTask;
|
||||
import util.SwingTask;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
@@ -39,6 +44,8 @@ import java.util.List;
|
||||
* @test
|
||||
* @summary Verify control under native actions in custom title bar
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm HitTestClientArea
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 HitTestClientArea
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 HitTestClientArea
|
||||
|
||||
@@ -23,7 +23,11 @@
|
||||
|
||||
import com.jetbrains.JBR;
|
||||
import util.*;
|
||||
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
import test.jb.testhelpers.utils.MouseUtils;
|
||||
import javax.swing.*;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Button;
|
||||
@@ -42,6 +46,8 @@ import java.util.List;
|
||||
* @test
|
||||
* @summary Verify control under native actions in custom title bar
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm HitTestNonClientArea
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 HitTestNonClientArea
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 HitTestNonClientArea
|
||||
|
||||
@@ -22,7 +22,12 @@
|
||||
*/
|
||||
import com.jetbrains.JBR;
|
||||
import util.*;
|
||||
|
||||
import test.jb.testhelpers.screenshot.ScreenShotHelpers;
|
||||
import test.jb.testhelpers.screenshot.Rect;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
@@ -37,6 +42,8 @@ import java.util.List;
|
||||
* @test
|
||||
* @summary Detect and check behavior of clicking to native controls
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm JDialogNativeControlsTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 JDialogNativeControlsTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 JDialogNativeControlsTest
|
||||
|
||||
@@ -23,21 +23,18 @@
|
||||
|
||||
import com.jetbrains.JBR;
|
||||
import com.jetbrains.WindowDecorations;
|
||||
import util.CommonAPISuite;
|
||||
import util.Task;
|
||||
import util.TaskResult;
|
||||
import util.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Robot;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -45,6 +42,8 @@ import java.util.function.Function;
|
||||
* @test
|
||||
* @summary Verify ability to maximize window by clicking to custom title bar area
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm MaximizeWindowTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 MaximizeWindowTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 MaximizeWindowTest
|
||||
|
||||
@@ -40,6 +40,8 @@ import java.util.concurrent.TimeUnit;
|
||||
* @test
|
||||
* @summary Regression test for JBR-3157 Maximized window with custom decorations isn't focused on showing
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm MaximizedWindowFocusTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 MaximizedWindowFocusTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 MaximizedWindowFocusTest
|
||||
|
||||
@@ -23,7 +23,12 @@
|
||||
|
||||
import com.jetbrains.JBR;
|
||||
import util.*;
|
||||
|
||||
import test.jb.testhelpers.screenshot.ScreenShotHelpers;
|
||||
import test.jb.testhelpers.screenshot.Rect;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
import java.awt.Frame;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
@@ -38,6 +43,8 @@ import java.util.List;
|
||||
* @test
|
||||
* @summary Detect and check behavior of clicking to native controls
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm MinimizingWindowTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 MinimizingWindowTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 MinimizingWindowTest
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
import com.jetbrains.JBR;
|
||||
import com.jetbrains.WindowDecorations;
|
||||
import util.*;
|
||||
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
@@ -39,6 +42,8 @@ import java.util.concurrent.TimeUnit;
|
||||
* @test
|
||||
* @summary Verify mouse events on custom title bar area
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm MouseEventsOnClientArea
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 MouseEventsOnClientArea
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 MouseEventsOnClientArea
|
||||
|
||||
@@ -22,17 +22,23 @@
|
||||
*/
|
||||
|
||||
import com.jetbrains.JBR;
|
||||
import util.*;
|
||||
|
||||
import test.jb.testhelpers.screenshot.ScreenShotHelpers;
|
||||
import test.jb.testhelpers.screenshot.Rect;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
import java.awt.Robot;
|
||||
import java.util.List;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Verify a property to change visibility of native controls
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm NativeControlsVisibilityTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 NativeControlsVisibilityTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 NativeControlsVisibilityTest
|
||||
|
||||
@@ -21,7 +21,13 @@
|
||||
* questions.
|
||||
*/
|
||||
import com.jetbrains.JBR;
|
||||
import util.*;
|
||||
import test.jb.testhelpers.screenshot.ScreenShotHelpers;
|
||||
import test.jb.testhelpers.screenshot.Rect;
|
||||
import test.jb.testhelpers.screenshot.RectCoordinates;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Robot;
|
||||
@@ -33,6 +39,8 @@ import java.lang.invoke.MethodHandles;
|
||||
* @test
|
||||
* @summary Verify custom title bar in case of window resizing
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm WindowResizeTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WindowResizeTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WindowResizeTest
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
* questions.
|
||||
*/
|
||||
import com.jetbrains.JBR;
|
||||
import util.CommonAPISuite;
|
||||
import util.Task;
|
||||
import util.TaskResult;
|
||||
import util.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
|
||||
import java.awt.Robot;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
@@ -33,6 +33,8 @@ import java.lang.invoke.MethodHandles;
|
||||
* @test
|
||||
* @summary Verify custom title bar in case of changing visibility of a window
|
||||
* @requires (os.family == "windows" | os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm WindowVisibilityTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WindowVisibilityTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WindowVisibilityTest
|
||||
|
||||
@@ -22,7 +22,12 @@
|
||||
*/
|
||||
|
||||
import com.jetbrains.JBR;
|
||||
import util.*;
|
||||
import test.jb.testhelpers.screenshot.ScreenShotHelpers;
|
||||
import test.jb.testhelpers.screenshot.Rect;
|
||||
import test.jb.testhelpers.TitleBar.CommonAPISuite;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Robot;
|
||||
@@ -34,6 +39,8 @@ import java.util.List;
|
||||
* @test
|
||||
* @summary Verify a property to change visibility of native controls
|
||||
* @requires os.family == "windows"
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar ../../../testhelpers/utils
|
||||
* @build TestUtils TaskResult Task CommonAPISuite MouseUtils ScreenShotHelpers Rect RectCoordinates MouseUtils
|
||||
* @run main/othervm WindowsControlWidthTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WindowsControlWidthTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WindowsControlWidthTest
|
||||
|
||||
@@ -2,6 +2,9 @@ package util;
|
||||
|
||||
import com.jetbrains.WindowDecorations;
|
||||
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import java.awt.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@ package util;
|
||||
|
||||
import com.jetbrains.WindowDecorations;
|
||||
|
||||
import test.jb.testhelpers.TitleBar.Task;
|
||||
import test.jb.testhelpers.TitleBar.TaskResult;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package util;
|
||||
|
||||
public class TaskResult {
|
||||
|
||||
private final boolean passed;
|
||||
private final boolean metConditions;
|
||||
private final String error;
|
||||
|
||||
public TaskResult(boolean passed, String error) {
|
||||
this.passed = passed;
|
||||
this.metConditions = true;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public TaskResult(boolean metConditions, boolean passed, String error) {
|
||||
this.metConditions = metConditions;
|
||||
this.passed = passed;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public boolean isPassed() {
|
||||
return passed;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public TaskResult merge(TaskResult another) {
|
||||
final String error = this.error + "\n" + another.error;
|
||||
final boolean status = this.passed && another.passed;
|
||||
return new TaskResult(status, error);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,7 +36,6 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
|
||||
public class PopupIncomingFocusTest {
|
||||
private static final CompletableFuture<Boolean> windowOpened = new CompletableFuture<>();
|
||||
private static final CompletableFuture<Boolean> popupOpened = new CompletableFuture<>();
|
||||
private static final CompletableFuture<Boolean> result = new CompletableFuture<>();
|
||||
private static Robot robot;
|
||||
@@ -51,7 +50,7 @@ public class PopupIncomingFocusTest {
|
||||
robot.setAutoWaitForIdle(true);
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(PopupIncomingFocusTest::init);
|
||||
windowOpened.get(10, TimeUnit.SECONDS);
|
||||
robot.delay(1000);
|
||||
launchProcessWithWindow();
|
||||
clickAt(button);
|
||||
popupOpened.get(10, TimeUnit.SECONDS);
|
||||
@@ -74,12 +73,6 @@ public class PopupIncomingFocusTest {
|
||||
frame = new JFrame();
|
||||
frame.add(button);
|
||||
frame.setBounds(50, 50, 200, 100);
|
||||
frame.addWindowFocusListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowGainedFocus(WindowEvent e) {
|
||||
windowOpened.complete(Boolean.TRUE);
|
||||
}
|
||||
});
|
||||
|
||||
field = new JTextField(10);
|
||||
field.getCaret().setBlinkRate(0); // prevent caret blink timer from keeping event thread running
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
import java.awt.Robot;
|
||||
import java.awt.Toolkit;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.WindowConstants;
|
||||
@@ -85,10 +86,17 @@ public class GetScreenInsets468 implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void disposeAll() {
|
||||
private void disposeAll() throws InterruptedException, InvocationTargetException {
|
||||
|
||||
for (JFrame frame : frames) {
|
||||
frame.setVisible(false);
|
||||
frame.dispose();
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
frame.setVisible(false);
|
||||
});
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
frame.dispose();
|
||||
});
|
||||
robot.delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright 2000-2023 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
import com.apple.eawt.FullScreenListener;
|
||||
import com.apple.eawt.FullScreenUtilities;
|
||||
import com.apple.eawt.event.FullScreenEvent;
|
||||
import com.jetbrains.JBR;
|
||||
import com.jetbrains.WindowDecorations;
|
||||
import test.jb.testhelpers.TitleBar.TestUtils;
|
||||
import test.jb.testhelpers.screenshot.ScreenShotHelpers;
|
||||
import test.jb.testhelpers.screenshot.Rect;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Detect and check behavior of clicking to native controls
|
||||
* @requires (os.family == "mac")
|
||||
* @library ../../../testhelpers/screenshot ../../../testhelpers/TitleBar
|
||||
* @build TestUtils ScreenShotHelpers Rect RectCoordinates
|
||||
* @modules java.desktop/com.apple.eawt
|
||||
* java.desktop/com.apple.eawt.event
|
||||
* @run main/othervm JFrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 JFrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 JFrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 JFrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 JFrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.5 JFrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=3.0 JFrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=3.5 JFrameNativeControlsMacOSTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=4.0 JFrameNativeControlsMacOSTest
|
||||
*/
|
||||
public class JFrameNativeControlsMacOSTest {
|
||||
|
||||
private static WindowDecorations.CustomTitleBar titleBar;
|
||||
private static JFrame jFrame;
|
||||
private static WindowListener windowListener;
|
||||
private static WindowStateListener windowStateListener;
|
||||
private static FullScreenListener fullScreenListener;
|
||||
|
||||
private static boolean closingActionCalled = false;
|
||||
private static boolean iconifyingActionCalled = false;
|
||||
private static volatile boolean maximizingActionDetected = false;
|
||||
private static boolean deiconifyindActionDetected = false;
|
||||
private static boolean passed = true;
|
||||
private static String error = "";
|
||||
|
||||
private static Robot robot;
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
robot = new Robot();
|
||||
robot.setAutoDelay(50);
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(JFrameNativeControlsMacOSTest::prepareUI);
|
||||
|
||||
robot.delay(500);
|
||||
robot.mouseMove(jFrame.getLocationOnScreen().x + jFrame.getWidth() / 2,
|
||||
jFrame.getLocationOnScreen().y + jFrame.getHeight() / 2);
|
||||
robot.delay(500);
|
||||
|
||||
BufferedImage image = ScreenShotHelpers.takeScreenshot(jFrame);
|
||||
List<Rect> foundControls = ScreenShotHelpers.findControls(image, jFrame, titleBar);
|
||||
|
||||
if (foundControls.isEmpty()) {
|
||||
System.out.println("Error: no controls found");
|
||||
}
|
||||
foundControls.forEach(control -> {
|
||||
System.out.println("Using control: " + control);
|
||||
int x = jFrame.getLocationOnScreen().x + control.getX1() + (control.getX2() - control.getX1()) / 2;
|
||||
int y = jFrame.getLocationOnScreen().y + control.getY1() + (control.getY2() - control.getY1()) / 2;
|
||||
System.out.println("Click to (" + x + ", " + y + ")");
|
||||
|
||||
int screenX = jFrame.getBounds().x;
|
||||
int screenY = jFrame.getBounds().y;
|
||||
int h = jFrame.getBounds().height;
|
||||
int w = jFrame.getBounds().width;
|
||||
|
||||
robot.waitForIdle();
|
||||
robot.mouseMove(x, y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.waitForIdle();
|
||||
if (maximizingActionDetected) {
|
||||
robot.keyPress(KeyEvent.VK_META);
|
||||
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||
robot.keyPress(KeyEvent.VK_F);
|
||||
robot.keyRelease(KeyEvent.VK_META);
|
||||
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||
robot.keyRelease(KeyEvent.VK_F);
|
||||
robot.delay(500);
|
||||
}
|
||||
jFrame.setBounds(screenX, screenY, w, h);
|
||||
jFrame.setVisible(true);
|
||||
robot.waitForIdle();
|
||||
});
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(JFrameNativeControlsMacOSTest::disposeUI);
|
||||
}
|
||||
|
||||
if (!maximizingActionDetected) {
|
||||
err("maximizing action was not detected");
|
||||
}
|
||||
|
||||
if (!closingActionCalled) {
|
||||
err("closing action was not detected");
|
||||
}
|
||||
|
||||
if (!iconifyingActionCalled) {
|
||||
err("iconifying action was not detected");
|
||||
}
|
||||
if (!deiconifyindActionDetected) {
|
||||
err("deiconifying action was not detected");
|
||||
}
|
||||
if (!passed) {
|
||||
System.out.println("TEST FAILED");
|
||||
} else {
|
||||
System.out.println("TEST PASSED");
|
||||
}
|
||||
}
|
||||
|
||||
private static void prepareUI() {
|
||||
titleBar = JBR.getWindowDecorations().createCustomTitleBar();
|
||||
titleBar.setHeight(TestUtils.TITLE_BAR_HEIGHT);
|
||||
jFrame = TestUtils.createJFrameWithCustomTitleBar(titleBar);
|
||||
|
||||
addWindowListener();
|
||||
addWindowStateListener();
|
||||
addMacOsFullScreenListener();
|
||||
jFrame.setVisible(true);
|
||||
jFrame.setAlwaysOnTop(true);
|
||||
jFrame.requestFocus();
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
jFrame.removeWindowListener(windowListener);
|
||||
jFrame.removeWindowStateListener(windowStateListener);
|
||||
FullScreenUtilities.removeFullScreenListenerFrom(jFrame, fullScreenListener);
|
||||
if (jFrame != null) {
|
||||
jFrame.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static void addWindowListener() {
|
||||
windowListener = new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
closingActionCalled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
iconifyingActionCalled = true;
|
||||
|
||||
jFrame.setState(JFrame.NORMAL);
|
||||
jFrame.setVisible(true);
|
||||
jFrame.requestFocus();
|
||||
}
|
||||
};
|
||||
jFrame.addWindowListener(windowListener);
|
||||
}
|
||||
|
||||
private static void addWindowStateListener() {
|
||||
windowStateListener = new WindowAdapter() {
|
||||
@Override
|
||||
public void windowStateChanged(WindowEvent e) {
|
||||
System.out.println("change " + e.getOldState() + " -> " + e.getNewState());
|
||||
if (e.getNewState() == 6) {
|
||||
maximizingActionDetected = true;
|
||||
}
|
||||
if (e.getOldState() == 1 && e.getNewState() == 0) {
|
||||
deiconifyindActionDetected = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
jFrame.addWindowStateListener(windowStateListener);
|
||||
}
|
||||
|
||||
private static void addMacOsFullScreenListener() {
|
||||
fullScreenListener = new FullScreenListener() {
|
||||
@Override
|
||||
public void windowEnteringFullScreen(FullScreenEvent fse) {
|
||||
maximizingActionDetected = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowEnteredFullScreen(FullScreenEvent fse) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowExitingFullScreen(FullScreenEvent fse) {
|
||||
System.out.println("Exiting fullscreen");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowExitedFullScreen(FullScreenEvent fse) {
|
||||
System.out.println("Exited fullscreen");
|
||||
}
|
||||
};
|
||||
FullScreenUtilities.addFullScreenListenerTo(jFrame, fullScreenListener);
|
||||
}
|
||||
|
||||
private static void err(String message) {
|
||||
error = error + message + "\n";
|
||||
passed = false;
|
||||
System.out.println(message);
|
||||
}
|
||||
|
||||
}
|
||||
159
test/jdk/jb/javax/swing/Frame/ExtendedFrameState.java
Normal file
159
test/jdk/jb/javax/swing/Frame/ExtendedFrameState.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2023 JetBrains s.r.o.
|
||||
* 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
|
||||
* @summary Verifies transitions between extended frame states
|
||||
* @requires os.family == "linux"
|
||||
* @run main ExtendedFrameState
|
||||
*/
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.WindowConstants;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Robot;
|
||||
import java.awt.Toolkit;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class ExtendedFrameState {
|
||||
static final int DELAY_MS = 1000;
|
||||
JFrame frame;
|
||||
Robot robot = new Robot();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
var toolkit = Toolkit.getDefaultToolkit();
|
||||
if (toolkit.isFrameStateSupported(Frame.MAXIMIZED_HORIZ)
|
||||
&& toolkit.isFrameStateSupported(Frame.MAXIMIZED_VERT)
|
||||
&& toolkit.isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
|
||||
var test = new ExtendedFrameState();
|
||||
|
||||
try {
|
||||
test.prepare();
|
||||
test.execute();
|
||||
} finally {
|
||||
test.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExtendedFrameState() throws Exception {
|
||||
}
|
||||
|
||||
void prepare() {
|
||||
runSwing(() -> {
|
||||
frame = new JFrame("ExtendedFrameState");
|
||||
frame.setUndecorated(true);
|
||||
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
JPanel panel = new JPanel();
|
||||
panel.add(new JLabel("label text"));
|
||||
frame.setContentPane(panel);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
void execute() {
|
||||
setState(Frame.NORMAL);
|
||||
assertStateIs(Frame.NORMAL);
|
||||
|
||||
// NORMAL -> MAXIMIZED_VERT
|
||||
setState(Frame.MAXIMIZED_VERT);
|
||||
assertStateIs(Frame.MAXIMIZED_VERT);
|
||||
|
||||
// MAXIMIZED_VERT -> NORMAL
|
||||
setState(Frame.NORMAL);
|
||||
assertStateIs(Frame.NORMAL);
|
||||
|
||||
// NORMAL -> MAXIMIZED_HORIZ
|
||||
setState(Frame.MAXIMIZED_HORIZ);
|
||||
assertStateIs(Frame.MAXIMIZED_HORIZ);
|
||||
|
||||
// MAXIMIZED_HORIZ -> MAXIMIZED_VERT
|
||||
// This transition is not supported by the WM for some obscure reason
|
||||
//setState(Frame.MAXIMIZED_VERT);
|
||||
//assertStateIs(Frame.MAXIMIZED_VERT);
|
||||
|
||||
// MAXIMIZED_VERT -> MAXIMIZED_HORIZ
|
||||
setState(Frame.MAXIMIZED_HORIZ);
|
||||
assertStateIs(Frame.MAXIMIZED_HORIZ);
|
||||
|
||||
// MAXIMIZED_HORIZ -> NORMAL
|
||||
setState(Frame.NORMAL);
|
||||
assertStateIs(Frame.NORMAL);
|
||||
|
||||
// NORMAL -> MAXIMIZED_BOTH
|
||||
setState(Frame.MAXIMIZED_BOTH);
|
||||
assertStateIs(Frame.MAXIMIZED_BOTH);
|
||||
|
||||
// MAXIMIZED_BOTH -> MAXIMIZED_HORIZ
|
||||
setState(Frame.MAXIMIZED_HORIZ);
|
||||
assertStateIs(Frame.MAXIMIZED_HORIZ);
|
||||
|
||||
// MAXIMIZED_HORIZ -> MAXIMIZED_BOTH
|
||||
setState(Frame.MAXIMIZED_BOTH);
|
||||
assertStateIs(Frame.MAXIMIZED_BOTH);
|
||||
|
||||
// MAXIMIZED_BOTH -> MAXIMIZED_VERT
|
||||
setState(Frame.MAXIMIZED_VERT);
|
||||
assertStateIs(Frame.MAXIMIZED_VERT);
|
||||
|
||||
// MAXIMIZED_VERT -> NORMAL
|
||||
setState(Frame.NORMAL);
|
||||
assertStateIs(Frame.NORMAL);
|
||||
}
|
||||
|
||||
void setState(int state) {
|
||||
runSwing(() -> {
|
||||
frame.setExtendedState(state);
|
||||
});
|
||||
robot.waitForIdle();
|
||||
robot.delay(DELAY_MS);
|
||||
}
|
||||
|
||||
void assertStateIs(int idealState) {
|
||||
runSwing(() -> {
|
||||
int realState = frame.getExtendedState();
|
||||
if (idealState != realState) {
|
||||
throw new RuntimeException(
|
||||
String.format("Expected frame state %d, got %d", idealState, realState));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
runSwing(() -> {
|
||||
frame.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
private static void runSwing(Runnable r) {
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(r);
|
||||
} catch (InterruptedException e) {
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user