mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-08 01:21:42 +01:00
Compare commits
34 Commits
jb17_0_2-b
...
vkempik/do
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8257490278 | ||
|
|
9f10f63459 | ||
|
|
0cb7b4565c | ||
|
|
e19109f401 | ||
|
|
c450a40e16 | ||
|
|
fe79f047d0 | ||
|
|
484bc6f18f | ||
|
|
1af965d658 | ||
|
|
d330782b50 | ||
|
|
ff6002ab87 | ||
|
|
ee9fe4ee55 | ||
|
|
b8e1373b53 | ||
|
|
1b9f385336 | ||
|
|
cd9cc5f395 | ||
|
|
54199dc06c | ||
|
|
66ddc58397 | ||
|
|
c5d124735c | ||
|
|
409e4932ad | ||
|
|
3bbd930114 | ||
|
|
0019142eaf | ||
|
|
41feaaedf0 | ||
|
|
3948c3538c | ||
|
|
497d00d82e | ||
|
|
37ceee0ce3 | ||
|
|
74dfdfbbfe | ||
|
|
8f1223d69a | ||
|
|
6d4c958c9a | ||
|
|
8730341c70 | ||
|
|
2aff4529b9 | ||
|
|
efd58e83eb | ||
|
|
1aa5510721 | ||
|
|
c14bfc9349 | ||
|
|
4d7b0f15c1 | ||
|
|
ac03a7a1e8 |
@@ -11,6 +11,7 @@ can be found on the [releases page](https://github.com/JetBrains/JetBrainsRuntim
|
||||
|
||||
| IDE Version | Latest JBR | Date Released |
|
||||
| --- | --- | --- |
|
||||
| 2022.1 | [17_0_2-b315.1](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr17_0_2b315.1) | 09-Feb-2022 |
|
||||
| 2021.3 | [17_0_1-b164.8](https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr17_0_1b164.8) | 15-Nov-2021 |
|
||||
|
||||
## Contents
|
||||
|
||||
22
jb/project/docker/Dockerfile.musl_aarch64
Normal file
22
jb/project/docker/Dockerfile.musl_aarch64
Normal file
@@ -0,0 +1,22 @@
|
||||
# NOTE: This Dockerfile is meant to be used from the mkdocker_musl_x64.sh script.
|
||||
|
||||
# Pull a concrete version of Linux that does NOT recieve updates after it's
|
||||
# been created. This is so that the image is as stable as possible to make
|
||||
# image creation reproducible.
|
||||
# NB: this also means there may be no security-related fixes there, need to
|
||||
# move the version to the next manually.
|
||||
FROM arm64v8/alpine:3.12
|
||||
|
||||
# Install the necessary build tools
|
||||
RUN apk --no-cache add --update bash grep tar zip bzip2 fontconfig build-base \
|
||||
git libx11-dev libxext-dev libxrandr-dev libxrender-dev libxt-dev \
|
||||
libxtst-dev autoconf freetype-dev cups-dev alsa-lib-dev file \
|
||||
fontconfig fontconfig-dev linux-headers
|
||||
|
||||
# Set up boot JDK for building
|
||||
COPY boot_jdk_musl_aarch64.tar.gz /jdk17/
|
||||
RUN cd /jdk17 && tar --strip-components=1 -xzf boot_jdk_musl_aarch64.tar.gz && rm /jdk17/boot_jdk_musl_aarch64.tar.gz
|
||||
ENV BOOT_JDK=/jdk17
|
||||
|
||||
RUN git config --global user.email "teamcity@jetbrains.com" && \
|
||||
git config --global user.name "builduser"
|
||||
22
jb/project/docker/Dockerfile.musl_x64
Normal file
22
jb/project/docker/Dockerfile.musl_x64
Normal file
@@ -0,0 +1,22 @@
|
||||
# NOTE: This Dockerfile is meant to be used from the mkdocker_musl_x64.sh script.
|
||||
|
||||
# Pull a concrete version of Linux that does NOT recieve updates after it's
|
||||
# been created. This is so that the image is as stable as possible to make
|
||||
# image creation reproducible.
|
||||
# NB: this also means there may be no security-related fixes there, need to
|
||||
# move the version to the next manually.
|
||||
FROM alpine:3.5
|
||||
|
||||
# Install the necessary build tools
|
||||
RUN apk --no-cache add --update bash grep tar zip bzip2 fontconfig build-base \
|
||||
git libx11-dev libxext-dev libxrandr-dev libxrender-dev libxt-dev \
|
||||
libxtst-dev autoconf freetype-dev cups-dev alsa-lib-dev file \
|
||||
fontconfig fontconfig-dev linux-headers
|
||||
|
||||
# Set up boot JDK for building
|
||||
COPY boot_jdk_musl_amd64.tar.gz /jdk17/
|
||||
RUN cd /jdk17 && tar --strip-components=1 -xzf boot_jdk_musl_amd64.tar.gz && rm /jdk17/boot_jdk_musl_amd64.tar.gz
|
||||
ENV BOOT_JDK=/jdk17
|
||||
|
||||
RUN git config --global user.email "teamcity@jetbrains.com" && \
|
||||
git config --global user.name "builduser"
|
||||
26
jb/project/docker/mkdocker_musl_aarch64.sh
Executable file
26
jb/project/docker/mkdocker_musl_aarch64.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# This script creates a Docker image suitable for building musl AArch64 variant
|
||||
# of the JetBrains Runtime version 17.
|
||||
|
||||
BOOT_JDK_REMOTE_FILE=zulu17.32.13-ca-jdk17.0.2-linux_musl_aarch64.tar.gz
|
||||
BOOT_JDK_SHA=6b920559abafbe9bdef386a20ecf3a2f318bc1f0d8359eb1f95aee26606bbc70
|
||||
BOOT_JDK_LOCAL_FILE=boot_jdk_musl_aarch64.tar.gz
|
||||
|
||||
if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then
|
||||
# Obtain "boot JDK" from outside of the container.
|
||||
wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE
|
||||
else
|
||||
echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download"
|
||||
fi
|
||||
|
||||
# Verify that what we've downloaded can be trusted.
|
||||
sha256sum -c - <<EOF
|
||||
$BOOT_JDK_SHA *$BOOT_JDK_LOCAL_FILE
|
||||
EOF
|
||||
|
||||
docker build -t jbr17buildenv -f Dockerfile.musl_aarch64 .
|
||||
|
||||
# NB: the resulting container can (and should) be used without the network
|
||||
# connection (--network none) during build in order to reduce the chance
|
||||
# of build contamination.
|
||||
26
jb/project/docker/mkdocker_musl_x64.sh
Executable file
26
jb/project/docker/mkdocker_musl_x64.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# This script creates a Docker image suitable for building musl-x64 variant
|
||||
# of the JetBrains Runtime version 17.
|
||||
|
||||
BOOT_JDK_REMOTE_FILE=zulu17.32.13-ca-jdk17.0.2-linux_musl_x64.tar.gz
|
||||
BOOT_JDK_SHA=bcc5342011bd9f3643372aadbdfa68d47463ff0d8621668a0bdf2910614d95c6
|
||||
BOOT_JDK_LOCAL_FILE=boot_jdk_musl_amd64.tar.gz
|
||||
|
||||
if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then
|
||||
# Obtain "boot JDK" from outside of the container.
|
||||
wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE
|
||||
else
|
||||
echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download"
|
||||
fi
|
||||
|
||||
# Verify that what we've downloaded can be trusted.
|
||||
sha256sum -c - <<EOF
|
||||
$BOOT_JDK_SHA *$BOOT_JDK_LOCAL_FILE
|
||||
EOF
|
||||
|
||||
docker build -t jbr17buildenv -f Dockerfile.musl_x64 .
|
||||
|
||||
# NB: the resulting container can (and should) be used without the network
|
||||
# connection (--network none) during build in order to reduce the chance
|
||||
# of build contamination.
|
||||
@@ -1,6 +1,18 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
tag_prefix="jbr-"
|
||||
function do_maketest() {
|
||||
if [ "${bundle_type: -1}" == "t" ]; then
|
||||
echo ${bundle_type%?}
|
||||
return 1
|
||||
else
|
||||
echo ${bundle_type}
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
function getVersionProp() {
|
||||
grep "^${1}" make/conf/version-numbers.conf | cut -d'=' -f2
|
||||
}
|
||||
|
||||
while getopts ":i?" o; do
|
||||
case "${o}" in
|
||||
@@ -12,27 +24,25 @@ while getopts ":i?" o; do
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [ $# -le $min_parameters_count ]; then
|
||||
build_number=$1
|
||||
bundle_type=$2
|
||||
architecture=$3 # aarch64 or x64
|
||||
else
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
architecture=$5 # aarch64 or x64
|
||||
fi
|
||||
build_number=$1
|
||||
bundle_type=$2
|
||||
architecture=$3 # aarch64 or x64
|
||||
|
||||
bundle_type=$(do_maketest)
|
||||
do_maketest=$?
|
||||
tag_prefix="jbr-"
|
||||
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "$tag_prefix" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -g | tail -n 1)
|
||||
JBSDK_VERSION=${JBSDK_VERSION:=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $2}')}
|
||||
VERSION_FEATURE=$(getVersionProp "DEFAULT_VERSION_FEATURE")
|
||||
VERSION_INTERIM=$(getVersionProp "DEFAULT_VERSION_INTERIM")
|
||||
VERSION_UPDATE=$(getVersionProp "DEFAULT_VERSION_UPDATE")
|
||||
[[ $VERSION_UPDATE = 0 ]] && JBSDK_VERSION="$VERSION_FEATURE" || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}"
|
||||
echo "##teamcity[setParameter name='env.JBSDK_VERSION' value='${JBSDK_VERSION}']"
|
||||
JDK_BUILD_NUMBER=${JDK_BUILD_NUMBER:=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $3}')}
|
||||
[ -z $JDK_BUILD_NUMBER ] && JDK_BUILD_NUMBER=1
|
||||
echo "##teamcity[setParameter name='env.JDK_UPDATE_NUMBER' value='${JDK_BUILD_NUMBER}']"
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
|
||||
VENDOR_NAME="JetBrains s.r.o."
|
||||
VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION_WITH_DOTS}+${JDK_BUILD_NUMBER}-${build_number}"
|
||||
VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION}+${JDK_BUILD_NUMBER}-${build_number}"
|
||||
[ -z "$bundle_type" ] || VENDOR_VERSION_STRING="${VENDOR_VERSION_STRING}-${bundle_type}"
|
||||
|
||||
do_reset_changes=0
|
||||
@@ -54,15 +64,17 @@ case "$OS_NAME" in
|
||||
BUILD_TIME="$(date --utc --date=@$SOURCE_DATE_EPOCH +%F)"
|
||||
REPRODUCIBLE_TAR_OPTS="--mtime=@$SOURCE_DATE_EPOCH --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime"
|
||||
;;
|
||||
CYGWIN*)
|
||||
COPYRIGHT_YEAR="$(date --utc --date=@$SOURCE_DATE_EPOCH +%Y)"
|
||||
BUILD_TIME="$(date --utc --date=@$SOURCE_DATE_EPOCH +%F)"
|
||||
REPRODUCIBLE_TAR_OPTS="--mtime=@$SOURCE_DATE_EPOCH --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime"
|
||||
;;
|
||||
Darwin)
|
||||
COPYRIGHT_YEAR="$(date -u -r $SOURCE_DATE_EPOCH +%Y)"
|
||||
BUILD_TIME="$(date -u -r $SOURCE_DATE_EPOCH +%F)"
|
||||
TOUCH_TIME="$(date -u -r $SOURCE_DATE_EPOCH +%Y%m%d%H%M.%S)"
|
||||
REPRODUCIBLE_TAR_OPTS="--uid 0 --gid 0 --numeric-owner"
|
||||
;;
|
||||
*)
|
||||
# TODO: Windows
|
||||
;;
|
||||
esac
|
||||
|
||||
REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build
|
||||
@@ -73,7 +85,7 @@ REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build
|
||||
|
||||
function do_exit() {
|
||||
exit_code=$1
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
|
||||
if [ $do_reset_dcevm -eq 1 ]; then
|
||||
[ ! -z $HEAD_REVISION ] && git reset --hard $HEAD_REVISION
|
||||
fi
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
# The following parameter must be specified:
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
#
|
||||
|
||||
min_parameters_count=1
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
function is_musl {
|
||||
libc=$(ldd /bin/ls | grep 'musl' | head -1 | cut -d ' ' -f1)
|
||||
if [ -z $libc ]; then
|
||||
# This is not Musl, return 1 == false
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
LIBC_TYPE_SUFFIX=''
|
||||
|
||||
if is_musl; then LIBC_TYPE_SUFFIX='musl-' ; fi
|
||||
|
||||
sh configure \
|
||||
--with-debug-level=release \
|
||||
--with-vendor-name="${VENDOR_NAME}" \
|
||||
@@ -34,7 +36,7 @@ sh configure \
|
||||
make clean CONF=linux-aarch64-server-release || exit $?
|
||||
make images CONF=linux-aarch64-server-release test-image || exit $?
|
||||
|
||||
JBSDK=${JBRSDK_BASE_NAME}-linux-aarch64-b${build_number}
|
||||
JBSDK=${JBRSDK_BASE_NAME}-linux-${LIBC_TYPE_SUFFIX}aarch64-b${build_number}
|
||||
BASE_DIR=build/linux-aarch64-server-release/images
|
||||
JSDK=${BASE_DIR}/jdk
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
@@ -60,8 +62,8 @@ JBR_BUNDLE=jbr
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
rm -rf $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-aarch64-b$build_number
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64
|
||||
JBR=$JBR_BASE_NAME-linux-${LIBC_TYPE_SUFFIX}aarch64-b$build_number
|
||||
grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64
|
||||
echo Running jlink....
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
@@ -76,7 +78,7 @@ tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE}
|
||||
touch -c -d @$SOURCE_DATE_EPOCH $JBR.tar
|
||||
gzip $JBR.tar || exit $?
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-aarch64-b$build_number
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-${LIBC_TYPE_SUFFIX}test-aarch64-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built;possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
# This script makes test-image along with JDK images when bundle_type is set to "jcef".
|
||||
# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images.
|
||||
#
|
||||
# Environment variables:
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument
|
||||
# to configure
|
||||
# By default JDK_BUILD_NUMBER is set zero
|
||||
# JCEF_PATH - specifies the path to the directory with JCEF binaries.
|
||||
# By default JCEF binaries should be located in ./jcef_linux_x64
|
||||
|
||||
min_parameters_count=2
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JCEF_PATH=${JCEF_PATH:=./jcef_linux_x64}
|
||||
@@ -41,14 +36,27 @@ function do_configure {
|
||||
|| do_exit $?
|
||||
}
|
||||
|
||||
function is_musl {
|
||||
libc=$(ldd /bin/ls | grep 'musl' | head -1 | cut -d ' ' -f1)
|
||||
if [ -z $libc ]; then
|
||||
# This is not Musl, return 1 == false
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
function create_image_bundle {
|
||||
__bundle_name=$1
|
||||
__arch_name=$2
|
||||
__modules_path=$3
|
||||
__modules=$4
|
||||
|
||||
libc_type_suffix=''
|
||||
|
||||
if is_musl; then libc_type_suffix='musl-' ; fi
|
||||
|
||||
[ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-"
|
||||
JBR=${__bundle_name}-${JBSDK_VERSION}-linux-x64-${fastdebug_infix}b${build_number}
|
||||
JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x64-${fastdebug_infix}b${build_number}
|
||||
|
||||
echo Running jlink....
|
||||
[ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name"
|
||||
@@ -85,6 +93,7 @@ RELEASE_NAME=linux-x86_64-server-release
|
||||
case "$bundle_type" in
|
||||
"jcef")
|
||||
do_reset_changes=1
|
||||
do_maketest=1
|
||||
;;
|
||||
"nomod" | "")
|
||||
bundle_type=""
|
||||
@@ -119,7 +128,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
fi
|
||||
|
||||
# create runtime image bundle
|
||||
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
|
||||
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
|
||||
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
# create sdk image bundle
|
||||
@@ -129,9 +138,10 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type
|
||||
fi
|
||||
create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-test-x64-b${build_number}
|
||||
if [ $do_maketest -eq 1 ]; then
|
||||
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-${libc_type_suffix}test-x64-b${build_number}
|
||||
echo Creating "$JBRSDK_TEST" ...
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
|
||||
make test-image CONF=$RELEASE_NAME || do_exit $?
|
||||
tar -pcf "$JBRSDK_TEST".tar -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
|
||||
[ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz"
|
||||
|
||||
@@ -61,7 +61,7 @@ JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
rm -rf $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-x86-b$build_number
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
echo Running jlink....
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
@@ -77,4 +77,4 @@ gzip $JBR.tar || exit $?
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x86-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' --exclude='test/hotspot/gtest' test || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
|
||||
@@ -1,29 +1,24 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built;possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
# This script makes test-image along with JDK images when bundle_type is set to "jcef".
|
||||
# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images.
|
||||
#
|
||||
# Environment variables:
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument
|
||||
# to configure
|
||||
# By default JDK_BUILD_NUMBER is set zero
|
||||
# JCEF_PATH - specifies the path to the directory with JCEF binaries.
|
||||
# By default JCEF binaries should be located in ./jcef_mac
|
||||
# MACOSX_VERSION_MAX - specifies value for the --with-macosx-version-max parameter. By default it is 10.12.00 for x64
|
||||
# and 11.00.00 for aarch64
|
||||
|
||||
min_parameters_count=3
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JCEF_PATH=${JCEF_PATH:=./jcef_mac}
|
||||
@@ -124,6 +119,7 @@ RELEASE_NAME=macosx-${CONF_ARCHITECTURE}-server-release
|
||||
case "$bundle_type" in
|
||||
"jcef")
|
||||
do_reset_changes=1
|
||||
do_maketest=1
|
||||
;;
|
||||
"nomod" | "")
|
||||
bundle_type=""
|
||||
@@ -144,10 +140,7 @@ make images CONF=$RELEASE_NAME || do_exit $?
|
||||
|
||||
IMAGES_DIR=build/$RELEASE_NAME/images
|
||||
|
||||
major_version=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $1}')
|
||||
minor_version=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $3}')
|
||||
[ -z "$minor_version" -o "$minor_version" = "0" ] && version_dir=$major_version || version_dir=$JBSDK_VERSION_WITH_DOTS
|
||||
JSDK=$IMAGES_DIR/jdk-bundle/jdk-$version_dir.jdk/Contents/Home
|
||||
JSDK=$IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk/Contents/Home
|
||||
JSDK_MODS_DIR=$IMAGES_DIR/jmods
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
@@ -160,7 +153,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
fi
|
||||
|
||||
# create runtime image bundle
|
||||
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
|
||||
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
|
||||
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
# create sdk image bundle
|
||||
@@ -170,9 +163,10 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type
|
||||
fi
|
||||
create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $?
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
if [ $do_maketest -eq 1 ]; then
|
||||
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-osx-test-${architecture}-b${build_number}
|
||||
echo Creating "$JBRSDK_TEST" ...
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
|
||||
make test-image CONF=$RELEASE_NAME || do_exit $?
|
||||
[ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz"
|
||||
COPYFILE_DISABLE=1 tar -pczf "$JBRSDK_TEST".tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git modules.list modules.list
|
||||
index 054f21d1ee0..d9a121f0273 100644
|
||||
--- modules.list
|
||||
+++ modules.list
|
||||
@@ -49,4 +49,7 @@ jdk.unsupported,
|
||||
diff --git jb/project/tools/common/modules.list jb/project/tools/common/modules.list
|
||||
index 522acb7cb43..c40e689d5de 100644
|
||||
--- jb/project/tools/common/modules.list
|
||||
+++ jb/project/tools/common/modules.list
|
||||
@@ -51,4 +51,7 @@ jdk.unsupported.desktop,
|
||||
jdk.xml.dom,
|
||||
jdk.zipfs,
|
||||
jdk.hotspot.agent,
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built;possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
# This script makes test-image along with JDK images when bundle_type is set to "jcef".
|
||||
# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images.
|
||||
#
|
||||
# Environment variables:
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument
|
||||
# to configure
|
||||
# By default JDK_BUILD_NUMBER is set zero
|
||||
# JCEF_PATH - specifies the path to the directory with JCEF binaries.
|
||||
# By default JCEF binaries should be located in ./jcef_win_x64
|
||||
|
||||
min_parameters_count=2
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
WORK_DIR=$(pwd)
|
||||
@@ -39,7 +34,9 @@ function do_configure {
|
||||
--with-toolchain-version=$TOOLCHAIN_VERSION \
|
||||
--with-boot-jdk=$BOOT_JDK \
|
||||
--disable-ccache \
|
||||
--enable-cds=yes || do_exit $?
|
||||
--enable-cds=yes \
|
||||
$REPRODUCIBLE_BUILD_OPTS \
|
||||
|| do_exit $?
|
||||
}
|
||||
|
||||
function create_image_bundle {
|
||||
@@ -69,6 +66,7 @@ RELEASE_NAME=windows-x86_64-server-release
|
||||
case "$bundle_type" in
|
||||
"jcef")
|
||||
do_reset_changes=0
|
||||
do_maketest=1
|
||||
;;
|
||||
"nomod" | "")
|
||||
bundle_type=""
|
||||
@@ -82,13 +80,13 @@ esac
|
||||
|
||||
if [ -z "$INC_BUILD" ]; then
|
||||
do_configure || do_exit $?
|
||||
if [ -z "$bundle_type" ]; then
|
||||
if [ $do_maketest -eq 1 ]; then
|
||||
make LOG=info CONF=$RELEASE_NAME clean images test-image || do_exit $?
|
||||
else
|
||||
make LOG=info CONF=$RELEASE_NAME clean images || do_exit $?
|
||||
fi
|
||||
else
|
||||
if [ -z "$bundle_type" ]; then
|
||||
if [ $do_maketest -eq 1 ]; then
|
||||
make LOG=info CONF=$RELEASE_NAME images test-image || do_exit $?
|
||||
else
|
||||
make LOG=info CONF=$RELEASE_NAME images || do_exit $?
|
||||
@@ -108,8 +106,9 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
jbr_name_postfix="_${bundle_type}"
|
||||
fi
|
||||
|
||||
# create runtime image bundle
|
||||
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
|
||||
# create runtime image bundlef
|
||||
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
|
||||
modules+=",jdk.crypto.mscapi"
|
||||
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
# create sdk image bundle
|
||||
@@ -119,4 +118,4 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type
|
||||
fi
|
||||
create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_MODS_DIR" "$modules" || do_exit $?
|
||||
|
||||
do_exit 0
|
||||
do_exit 0
|
||||
|
||||
@@ -53,7 +53,8 @@ mv release ${JBRSDK_BUNDLE}/release
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
rm -rf ${JBR_BUNDLE}
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
echo ",jdk.crypto.mscapi" >> modules.list.x86
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list.x86 | sed s/" "//g) --output ${JBR_BUNDLE} || exit $?
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies udate release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the bundles without any additional modules (jcef)
|
||||
# jcef - the bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built;possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
# This script packs test-image along with JDK images when bundle_type is set to "jcef".
|
||||
# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images.
|
||||
#
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
[ "$bundle_type" == "jcef" ] && do_maketest=1
|
||||
|
||||
function pack_jbr {
|
||||
__bundle_name=$1
|
||||
@@ -51,7 +41,7 @@ fi
|
||||
pack_jbr jbr${jbr_name_postfix} jbr
|
||||
pack_jbr jbrsdk${jbr_name_postfix} jbrsdk
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
if [ $do_maketest -eq 1 ]; then
|
||||
JBRSDK_TEST=$JBRSDK_BUNDLE-$JBSDK_VERSION-windows-test-x64-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
|
||||
|
||||
@@ -784,10 +784,8 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
|
||||
test "x$ENABLE_REPRODUCIBLE_BUILD" = xtrue; then
|
||||
# There is a known issue with the pathmap if the mapping is made to the
|
||||
# empty string. Add a minimal string "s" as prefix to work around this.
|
||||
workspace_root_win=`$FIXPATH_BASE print "${WORKSPACE_ROOT%/}"`
|
||||
# PATHMAP_FLAGS is also added to LDFLAGS in flags-ldflags.m4.
|
||||
PATHMAP_FLAGS="-pathmap:${workspace_root_win//\//\\\\}=s \
|
||||
-pathmap:${workspace_root_win}=s"
|
||||
PATHMAP_FLAGS="-pathmap:${WORKSPACE_ROOT}=s"
|
||||
FILE_MACRO_CFLAGS="$PATHMAP_FLAGS"
|
||||
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${FILE_MACRO_CFLAGS}],
|
||||
PREFIX: $3,
|
||||
|
||||
@@ -117,7 +117,7 @@ const char* Abstract_VM_Version::vm_vendor() {
|
||||
#ifdef VENDOR
|
||||
return VENDOR;
|
||||
#else
|
||||
return "Oracle Corporation";
|
||||
return "JetBrains s.r.o.";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.jetbrains.internal;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@@ -103,9 +105,10 @@ public class JBRApi {
|
||||
JBRApi.outerLookup = outerLookup;
|
||||
try {
|
||||
Class<?> metadataClass = outerLookup.findClass("com.jetbrains.JBR$Metadata");
|
||||
knownServices = Set.of((String[]) outerLookup.findStaticVarHandle(metadataClass,
|
||||
Lookup lookup = MethodHandles.privateLookupIn(metadataClass, outerLookup);
|
||||
knownServices = Set.of((String[]) lookup.findStaticVarHandle(metadataClass,
|
||||
"KNOWN_SERVICES", String[].class).get());
|
||||
knownProxies = Set.of((String[]) outerLookup.findStaticVarHandle(metadataClass,
|
||||
knownProxies = Set.of((String[]) lookup.findStaticVarHandle(metadataClass,
|
||||
"KNOWN_PROXIES", String[].class).get());
|
||||
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
@@ -156,13 +159,52 @@ public class JBRApi {
|
||||
RegisteredProxyInfo info = registeredProxyInfoByTargetName.get(targetName);
|
||||
if (info == null) return null;
|
||||
try {
|
||||
return (info.type() == ProxyInfo.Type.CLIENT_PROXY ? info.apiModule() : outerLookup)
|
||||
return (info.type().isPublicApi() ? outerLookup : info.apiModule())
|
||||
.findClass(info.interfaceName());
|
||||
} catch (ClassNotFoundException | IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static InternalServiceBuilder internalServiceBuilder(Lookup interFace, String target) {
|
||||
return new InternalServiceBuilder(new RegisteredProxyInfo(
|
||||
interFace, interFace.lookupClass().getName(), target, ProxyInfo.Type.INTERNAL_SERVICE, new ArrayList<>()));
|
||||
}
|
||||
|
||||
public static class InternalServiceBuilder {
|
||||
|
||||
private final RegisteredProxyInfo info;
|
||||
|
||||
private InternalServiceBuilder(RegisteredProxyInfo info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public InternalServiceBuilder withStatic(String methodName, String clazz) {
|
||||
return withStatic(methodName, clazz, methodName);
|
||||
}
|
||||
|
||||
public InternalServiceBuilder withStatic(String interfaceMethodName, String clazz, String methodName) {
|
||||
info.staticMethods().add(
|
||||
new RegisteredProxyInfo.StaticMethodMapping(interfaceMethodName, clazz, methodName));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object build() {
|
||||
ProxyInfo info = ProxyInfo.resolve(this.info);
|
||||
if (info == null) return null;
|
||||
ProxyGenerator generator = new ProxyGenerator(info);
|
||||
if (!generator.areAllMethodsImplemented()) return null;
|
||||
generator.defineClasses();
|
||||
MethodHandle constructor = generator.findConstructor();
|
||||
generator.init();
|
||||
try {
|
||||
return constructor.invoke();
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@linkplain com.jetbrains.bootstrap.JBRApiBootstrap#MODULES registry classes}
|
||||
* to register a new mapping for corresponding modules.
|
||||
|
||||
@@ -78,7 +78,7 @@ class ProxyGenerator {
|
||||
*/
|
||||
ProxyGenerator(ProxyInfo info) {
|
||||
this.info = info;
|
||||
generateBridge = info.type != ProxyInfo.Type.CLIENT_PROXY;
|
||||
generateBridge = info.type.isPublicApi();
|
||||
int nameId = nameCounter.getAndIncrement();
|
||||
proxyName = Type.getInternalName(info.interFace) + "$$JBRApiProxy$" + nameId;
|
||||
bridgeName = generateBridge ? info.apiModule.lookupClass().getPackageName().replace('.', '/') + "/" +
|
||||
@@ -153,7 +153,7 @@ class ProxyGenerator {
|
||||
} else {
|
||||
MethodHandle c = generatedProxy.findConstructor(generatedProxy.lookupClass(),
|
||||
MethodType.methodType(void.class, Object.class));
|
||||
if (info.type == ProxyInfo.Type.SERVICE) {
|
||||
if (info.type.isService()) {
|
||||
try {
|
||||
return MethodHandles.foldArguments(c, info.target.findConstructor(info.target.lookupClass(),
|
||||
MethodType.methodType(void.class)).asType(MethodType.methodType(Object.class)));
|
||||
|
||||
@@ -66,7 +66,7 @@ class ProxyInfo {
|
||||
}
|
||||
|
||||
Lookup getInterfaceLookup() {
|
||||
return type == Type.CLIENT_PROXY ? apiModule : JBRApi.outerLookup;
|
||||
return type == Type.CLIENT_PROXY || type == Type.INTERNAL_SERVICE ? apiModule : JBRApi.outerLookup;
|
||||
}
|
||||
|
||||
Lookup getTargetLookup() {
|
||||
@@ -74,12 +74,18 @@ class ProxyInfo {
|
||||
}
|
||||
|
||||
private Lookup lookup(Lookup lookup, String clazz) {
|
||||
try {
|
||||
return MethodHandles.privateLookupIn(lookup.findClass(clazz), lookup);
|
||||
} catch (ClassNotFoundException | IllegalAccessException e) {
|
||||
if (lookup == JBRApi.outerLookup) return null;
|
||||
else throw new RuntimeException(e);
|
||||
String[] nestedClasses = clazz.split("\\$");
|
||||
clazz = "";
|
||||
for (int i = 0; i < nestedClasses.length; i++) {
|
||||
try {
|
||||
if (i != 0) clazz += "$";
|
||||
clazz += nestedClasses[i];
|
||||
lookup = MethodHandles.privateLookupIn(lookup.findClass(clazz), lookup);
|
||||
} catch (ClassNotFoundException | IllegalAccessException ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return lookup;
|
||||
}
|
||||
|
||||
record StaticMethodMapping(Lookup lookup, String methodName) {}
|
||||
@@ -90,6 +96,15 @@ class ProxyInfo {
|
||||
enum Type {
|
||||
PROXY,
|
||||
SERVICE,
|
||||
CLIENT_PROXY
|
||||
CLIENT_PROXY,
|
||||
INTERNAL_SERVICE;
|
||||
|
||||
public boolean isPublicApi() {
|
||||
return this == PROXY || this == SERVICE;
|
||||
}
|
||||
|
||||
public boolean isService() {
|
||||
return this == SERVICE || this == INTERNAL_SERVICE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,6 +249,13 @@ public final class CStrike extends PhysicalStrike {
|
||||
}
|
||||
}
|
||||
|
||||
int getSlot0GlyphImagePtrs(int[] glyphCodes, long[] images, int len) {
|
||||
int ourGlyphs = 0;
|
||||
while (ourGlyphs < len && (glyphCodes[ourGlyphs] & CompositeGlyphMapper.SLOTMASK) == 0) ourGlyphs++;
|
||||
getGlyphImagePtrs(glyphCodes, images, ourGlyphs);
|
||||
return ourGlyphs;
|
||||
}
|
||||
|
||||
// called from the Sun2D renderer
|
||||
void getGlyphImagePtrs(int[] glyphCodes, long[] images, int len) {
|
||||
synchronized (glyphInfoCache) {
|
||||
|
||||
@@ -38,11 +38,10 @@ import java.beans.PropertyChangeListener;
|
||||
import java.lang.annotation.Native;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.Arrays;
|
||||
@@ -76,24 +75,18 @@ import sun.lwawt.LWWindowPeer;
|
||||
@SuppressWarnings("removal")
|
||||
class CAccessibility implements PropertyChangeListener {
|
||||
private static Set<String> ignoredRoles;
|
||||
private static final int INVOKE_TIMEOUT_SECONDS_DEFAULT = 1;
|
||||
private static final int INVOKE_TIMEOUT_SECONDS;
|
||||
|
||||
static {
|
||||
AtomicInteger invokeTimeoutSecondsRef = new AtomicInteger();
|
||||
// Need to load the native library for this code.
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
System.loadLibrary("awt");
|
||||
invokeTimeoutSecondsRef.set(
|
||||
// (-1) for the infinite timeout
|
||||
Integer.getInteger("sun.lwawt.macosx.CAccessibility.invokeTimeoutSeconds",
|
||||
INVOKE_TIMEOUT_SECONDS_DEFAULT));
|
||||
return null;
|
||||
}
|
||||
// (-1) for the infinite timeout
|
||||
@SuppressWarnings("removal")
|
||||
int value = java.security.AccessController.doPrivileged(
|
||||
(PrivilegedAction<Integer>) () -> {
|
||||
// Need to load the native library for this code.
|
||||
System.loadLibrary("awt");
|
||||
return Integer.getInteger("sun.lwawt.macosx.CAccessibility.invokeTimeoutSeconds", 1);
|
||||
});
|
||||
INVOKE_TIMEOUT_SECONDS = invokeTimeoutSecondsRef.get();
|
||||
INVOKE_TIMEOUT_SECONDS = value;
|
||||
}
|
||||
|
||||
static CAccessibility sAccessibility;
|
||||
|
||||
@@ -66,6 +66,7 @@ import sun.awt.AWTAccessor.ComponentAccessor;
|
||||
import sun.awt.AWTAccessor.WindowAccessor;
|
||||
import sun.awt.AWTThreading;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.lwawt.LWComponentPeer;
|
||||
import sun.lwawt.LWLightweightFramePeer;
|
||||
import sun.lwawt.LWToolkit;
|
||||
import sun.lwawt.LWWindowPeer;
|
||||
@@ -290,7 +291,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
new Property<CPlatformWindow>(WINDOW_TRANSPARENT_TITLE_BAR_HEIGHT) {
|
||||
public void applyProperty(final CPlatformWindow c, final Object value) {
|
||||
if (value != null && (value instanceof Float)) {
|
||||
c.execute(ptr -> nativeSetTransparentTitleBarHeight(ptr, (float) value));
|
||||
c.execute(ptr -> AWTThreading.executeWaitToolkit(wait -> nativeSetTransparentTitleBarHeight(ptr, (float) value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1456,28 +1457,20 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
isFullScreenAnimationOn = false;
|
||||
}
|
||||
|
||||
// called from client via reflection
|
||||
private void setTransparentTitleBarHeight(float height) {
|
||||
execute(ptr -> {
|
||||
nativeSetTransparentTitleBarHeight(ptr, height);
|
||||
});
|
||||
}
|
||||
|
||||
private volatile List<Rectangle> customDecorHitTestSpots;
|
||||
|
||||
// called from client via reflection
|
||||
private void setCustomDecorationHitTestSpots(List<Rectangle> hitTestSpots) {
|
||||
this.customDecorHitTestSpots = new CopyOnWriteArrayList<>(hitTestSpots);
|
||||
}
|
||||
|
||||
// called from native
|
||||
private boolean hitTestCustomDecoration(float x, float y) {
|
||||
List<Rectangle> spots = customDecorHitTestSpots;
|
||||
if (spots == null) return false;
|
||||
for (Rectangle spot : spots) {
|
||||
if (spot.contains(x, y)) return true;
|
||||
// JBR API internals
|
||||
private static void setCustomDecorationTitleBarHeight(Window target, ComponentPeer peer, float height) {
|
||||
if (peer instanceof LWComponentPeer) {
|
||||
PlatformWindow platformWindow = ((LWComponentPeer<?, ?>) peer).getPlatformWindow();
|
||||
if (platformWindow instanceof CPlatformWindow) {
|
||||
((CPlatformWindow) platformWindow).execute(ptr -> {
|
||||
AWTThreading.executeWaitToolkit(wait -> nativeSetTransparentTitleBarHeight(ptr, height));
|
||||
});
|
||||
if (target instanceof javax.swing.RootPaneContainer) {
|
||||
final javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer)target).getRootPane();
|
||||
if (rootpane != null) rootpane.putClientProperty(WINDOW_TRANSPARENT_TITLE_BAR_HEIGHT, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ import java.net.URL;
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@@ -675,30 +676,12 @@ public final class LWCToolkit extends LWToolkit {
|
||||
return invokeAndWait(callable, component, -1);
|
||||
}
|
||||
|
||||
static <T> T invokeAndWait(final Callable<T> callable, Component component, int timeoutSeconds) throws Exception {
|
||||
public static <T> T invokeAndWait(final Callable<T> callable, Component component, int timeoutSeconds) throws Exception {
|
||||
final CallableWrapper<T> wrapper = new CallableWrapper<>(callable);
|
||||
invokeAndWait(wrapper, component, false, timeoutSeconds);
|
||||
return wrapper.getResult();
|
||||
}
|
||||
|
||||
static final class CancelableRunnable implements Runnable {
|
||||
volatile Runnable runnable;
|
||||
|
||||
public CancelableRunnable(Runnable runnable) {
|
||||
this.runnable = runnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Runnable r = runnable;
|
||||
if (r != null) r.run();
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
runnable = null;
|
||||
}
|
||||
}
|
||||
|
||||
static final class CallableWrapper<T> implements Runnable {
|
||||
final Callable<T> callable;
|
||||
T object;
|
||||
@@ -776,7 +759,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
invokeAndWait(runnable, component, false, -1);
|
||||
}
|
||||
|
||||
static void invokeAndWait(Runnable runnable, Component component, boolean processEvents, int timeoutSeconds)
|
||||
public static void invokeAndWait(Runnable runnable, Component component, boolean processEvents, int timeoutSeconds)
|
||||
throws InvocationTargetException
|
||||
{
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
@@ -784,24 +767,17 @@ public final class LWCToolkit extends LWToolkit {
|
||||
}
|
||||
|
||||
boolean nonBlockingRunLoop;
|
||||
CancelableRunnable cancelableRunnable = new CancelableRunnable(runnable);
|
||||
|
||||
synchronized (priorityInvocationPending) {
|
||||
nonBlockingRunLoop = priorityInvocationPending.get();
|
||||
if (!nonBlockingRunLoop) blockingRunLoopCounter.incrementAndGet();
|
||||
}
|
||||
|
||||
final long mediator = createAWTRunLoopMediator();
|
||||
AWTThreading.TrackedInvocationEvent invocationEvent =
|
||||
AWTThreading.createAndTrackInvocationEvent(component, runnable, true);
|
||||
|
||||
InvocationEvent invocationEvent =
|
||||
AWTThreading.createAndTrackInvocationEvent(component,
|
||||
cancelableRunnable,
|
||||
() -> {
|
||||
if (mediator != 0) {
|
||||
stopAWTRunLoop(mediator);
|
||||
}
|
||||
},
|
||||
true);
|
||||
long mediator = createAWTRunLoopMediator();
|
||||
invocationEvent.onDone(() -> stopAWTRunLoop(mediator));
|
||||
|
||||
if (component != null) {
|
||||
AppContext appContext = SunToolkit.targetToAppContext(component);
|
||||
@@ -815,10 +791,21 @@ public final class LWCToolkit extends LWToolkit {
|
||||
((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent);
|
||||
}
|
||||
|
||||
CompletableFuture<Void> eventDispatchThreadFreeFuture =
|
||||
AWTThreading.getInstance(component).onEventDispatchThreadFree(() -> {
|
||||
if (!invocationEvent.isDone()) {
|
||||
// EventQueue is now empty but the posted InvocationEvent is still not dispatched,
|
||||
// consider it lost then.
|
||||
invocationEvent.dispose("InvocationEvent was lost");
|
||||
}
|
||||
});
|
||||
|
||||
invocationEvent.onDone(() -> eventDispatchThreadFreeFuture.cancel(false));
|
||||
|
||||
if (!doAWTRunLoop(mediator, nonBlockingRunLoop, timeoutSeconds)) {
|
||||
new Throwable("Invocation timed out (" + timeoutSeconds + "sec)").printStackTrace();
|
||||
cancelableRunnable.cancel();
|
||||
invocationEvent.dispose("InvocationEvent has timed out");
|
||||
}
|
||||
|
||||
if (!nonBlockingRunLoop) blockingRunLoopCounter.decrementAndGet();
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
NSWindowTabbingMode javaWindowTabbingMode;
|
||||
BOOL isEnterFullScreen;
|
||||
CGFloat _transparentTitleBarHeight;
|
||||
id<NSObject> _windowWillEnterFullScreenNotification;
|
||||
id<NSObject> _windowWillExitFullScreenNotification;
|
||||
id<NSObject> _windowDidExitFullScreenNotification;
|
||||
NSMutableArray* _transparentTitleBarConstraints;
|
||||
NSLayoutConstraint *_transparentTitleBarHeightConstraint;
|
||||
NSMutableArray *_transparentTitleBarButtonCenterXConstraints;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <objc/objc-runtime.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include <java_awt_Window_CustomWindowDecoration.h>
|
||||
#import "sun_lwawt_macosx_CPlatformWindow.h"
|
||||
#import "com_apple_eawt_event_GestureHandler.h"
|
||||
#import "com_apple_eawt_FullScreenHandler.h"
|
||||
@@ -1294,10 +1295,10 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
NSView* titlebarContainer = titlebar.superview;
|
||||
NSView* themeFrame = titlebarContainer.superview;
|
||||
|
||||
NSMutableArray* newConstraints = [[NSMutableArray alloc] init];
|
||||
_transparentTitleBarConstraints = [[NSMutableArray alloc] init];
|
||||
titlebarContainer.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
_transparentTitleBarHeightConstraint = [titlebarContainer.heightAnchor constraintEqualToConstant:_transparentTitleBarHeight];
|
||||
[newConstraints addObjectsFromArray:@[
|
||||
[_transparentTitleBarConstraints addObjectsFromArray:@[
|
||||
[titlebarContainer.leftAnchor constraintEqualToAnchor:themeFrame.leftAnchor],
|
||||
[titlebarContainer.widthAnchor constraintEqualToAnchor:themeFrame.widthAnchor],
|
||||
[titlebarContainer.topAnchor constraintEqualToAnchor:themeFrame.topAnchor],
|
||||
@@ -1310,7 +1311,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
for (NSView* view in @[titlebar, windowDragView])
|
||||
{
|
||||
view.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[newConstraints addObjectsFromArray:@[
|
||||
[_transparentTitleBarConstraints addObjectsFromArray:@[
|
||||
[view.leftAnchor constraintEqualToAnchor:titlebarContainer.leftAnchor],
|
||||
[view.rightAnchor constraintEqualToAnchor:titlebarContainer.rightAnchor],
|
||||
[view.topAnchor constraintEqualToAnchor:titlebarContainer.topAnchor],
|
||||
@@ -1326,7 +1327,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
button.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
NSLayoutConstraint* buttonCenterXConstraint = [button.centerXAnchor constraintEqualToAnchor:titlebarContainer.leftAnchor constant:(_transparentTitleBarHeight/2.0 + (index * horizontalButtonOffset))];
|
||||
[_transparentTitleBarButtonCenterXConstraints addObject:buttonCenterXConstraint];
|
||||
[newConstraints addObjectsFromArray:@[
|
||||
[_transparentTitleBarConstraints addObjectsFromArray:@[
|
||||
[button.widthAnchor constraintLessThanOrEqualToAnchor:titlebarContainer.heightAnchor multiplier:0.5],
|
||||
// Those corrections are required to keep the icons perfectly round because macOS adds a constant 2 px in resulting height to their frame
|
||||
[button.heightAnchor constraintEqualToAnchor: button.widthAnchor multiplier:14.0/12.0 constant:-2.0],
|
||||
@@ -1335,7 +1336,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
]];
|
||||
}];
|
||||
|
||||
[NSLayoutConstraint activateConstraints:newConstraints];
|
||||
[NSLayoutConstraint activateConstraints:_transparentTitleBarConstraints];
|
||||
}
|
||||
|
||||
- (void) updateTransparentTitleBarConstraints
|
||||
@@ -1361,20 +1362,22 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
NSView* titlebarContainer = titlebar.superview;
|
||||
NSView* themeFrame = titlebarContainer.superview;
|
||||
|
||||
[NSLayoutConstraint deactivateConstraints:_transparentTitleBarConstraints];
|
||||
|
||||
AWTWindowDragView* windowDragView;
|
||||
for (NSView* view in titlebar.subviews) {
|
||||
if ([view isMemberOfClass:[AWTWindowDragView class]]) {
|
||||
windowDragView = view;
|
||||
}
|
||||
if (view.translatesAutoresizingMaskIntoConstraints == NO) {
|
||||
[view removeConstraints:view.constraints];
|
||||
view.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
}
|
||||
}
|
||||
[windowDragView removeFromSuperview];
|
||||
[titlebarContainer removeConstraints:titlebarContainer.constraints];
|
||||
titlebarContainer.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
titlebar.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
|
||||
_transparentTitleBarConstraints = nil;
|
||||
_transparentTitleBarHeightConstraint = nil;
|
||||
_transparentTitleBarButtonCenterXConstraints = nil;
|
||||
}
|
||||
@@ -1403,23 +1406,44 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
});
|
||||
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
|
||||
NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];
|
||||
[defaultCenter addObserverForName:NSWindowWillEnterFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
_windowWillEnterFullScreenNotification = [defaultCenter addObserverForName:NSWindowWillEnterFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
[self resetTitleBar];
|
||||
}];
|
||||
[defaultCenter addObserverForName:NSWindowWillExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
_windowWillExitFullScreenNotification = [defaultCenter addObserverForName:NSWindowWillExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
[self setWindowControlsHidden:YES];
|
||||
}];
|
||||
[defaultCenter addObserverForName:NSWindowDidExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
_windowDidExitFullScreenNotification = [defaultCenter addObserverForName:NSWindowDidExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
[self setUpTransparentTitleBar];
|
||||
[self setWindowControlsHidden:NO];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) configureWindowAndListenersForDefaultTitleBar
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
[self.nsWindow setTitlebarAppearsTransparent:NO];
|
||||
[self.nsWindow setTitleVisibility:NSWindowTitleVisible];
|
||||
[self.nsWindow setStyleMask:[self.nsWindow styleMask]&(~NSWindowStyleMaskFullSizeContentView)];
|
||||
|
||||
if (!self.isFullScreen) {
|
||||
[self resetTitleBar];
|
||||
}
|
||||
});
|
||||
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
|
||||
[defaultCenter removeObserver:_windowWillEnterFullScreenNotification];
|
||||
[defaultCenter removeObserver:_windowWillExitFullScreenNotification];
|
||||
[defaultCenter removeObserver:_windowDidExitFullScreenNotification];
|
||||
_windowWillEnterFullScreenNotification = _windowWillExitFullScreenNotification = _windowDidExitFullScreenNotification = nil;
|
||||
}
|
||||
|
||||
- (void) setTransparentTitleBarHeight: (CGFloat) transparentTitleBarHeight
|
||||
{
|
||||
if (_transparentTitleBarHeight == transparentTitleBarHeight) return;
|
||||
if (_transparentTitleBarHeight != 0.0f) {
|
||||
_transparentTitleBarHeight = transparentTitleBarHeight;
|
||||
if (_transparentTitleBarHeightConstraint != nil || _transparentTitleBarButtonCenterXConstraints != nil) {
|
||||
if (transparentTitleBarHeight == 0.0f) {
|
||||
[self configureWindowAndListenersForDefaultTitleBar];
|
||||
} else if (_transparentTitleBarHeightConstraint != nil || _transparentTitleBarButtonCenterXConstraints != nil) {
|
||||
[self updateTransparentTitleBarConstraints];
|
||||
}
|
||||
} else {
|
||||
@@ -1455,11 +1479,18 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
|
||||
if (platformWindow != NULL) {
|
||||
GET_CPLATFORM_WINDOW_CLASS_RETURN(YES);
|
||||
DECLARE_METHOD_RETURN(jm_hitTestCustomDecoration, jc_CPlatformWindow, "hitTestCustomDecoration", "(FF)Z", YES);
|
||||
NSRect frame = [self.window frame];
|
||||
float windowHeight = frame.size.height;
|
||||
returnValue = (*env)->CallBooleanMethod(env, platformWindow, jm_hitTestCustomDecoration, point.x, windowHeight - point.y) == JNI_TRUE ? NO : YES;
|
||||
CHECK_EXCEPTION_IN_ENV(env);
|
||||
DECLARE_FIELD_RETURN(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;", YES);
|
||||
DECLARE_CLASS_RETURN(jc_Window, "java/awt/Window", YES);
|
||||
DECLARE_METHOD_RETURN(jm_hitTestCustomDecoration, jc_Window, "hitTestCustomDecoration", "(II)I", YES);
|
||||
jobject awtWindow = (*env)->GetObjectField(env, platformWindow, jf_target);
|
||||
if (awtWindow != NULL) {
|
||||
NSRect frame = [self.window frame];
|
||||
float windowHeight = frame.size.height;
|
||||
returnValue = (*env)->CallIntMethod(env, awtWindow, jm_hitTestCustomDecoration, (jint) point.x, (jint) (windowHeight - point.y)) ==
|
||||
(jint) java_awt_Window_CustomWindowDecoration_NO_HIT_SPOT ? YES : NO;
|
||||
CHECK_EXCEPTION();
|
||||
(*env)->DeleteLocalRef(env, awtWindow);
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, platformWindow);
|
||||
}
|
||||
return returnValue;
|
||||
|
||||
@@ -161,8 +161,8 @@ void initializeActions() {
|
||||
[sActions setObject:NSAccessibilityPressAction forKey:@"click"];
|
||||
[sActions setObject:NSAccessibilityIncrementAction forKey:@"increment"];
|
||||
[sActions setObject:NSAccessibilityDecrementAction forKey:@"decrement"];
|
||||
[sActions setObject:NSAccessibilityShowMenuAction forKey:@"togglePopup"];
|
||||
[sActions setObject:NSAccessibilityPressAction forKey:@"toggleExpand"];
|
||||
[sActions setObject:NSAccessibilityShowMenuAction forKey:@"toggle popup"];
|
||||
[sActions setObject:NSAccessibilityPressAction forKey:@"toggleexpand"];
|
||||
|
||||
sActionSelectors = [[NSMutableDictionary alloc] initWithCapacity:actionsCount];
|
||||
|
||||
|
||||
@@ -632,6 +632,8 @@ JNI_COCOA_ENTER(env);
|
||||
|
||||
AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator);
|
||||
|
||||
if (mediatorObject == nil) return;
|
||||
|
||||
[ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO];
|
||||
|
||||
[mediatorObject release];
|
||||
|
||||
@@ -30,6 +30,7 @@ public class JBRApiModule {
|
||||
.withStatic("getSubpixelResolution", "sun.font.FontUtilities")
|
||||
.service("com.jetbrains.JBRFileDialogService", null)
|
||||
.withStatic("getFileDialog", "com.jetbrains.desktop.JBRFileDialog", "get")
|
||||
.proxy("com.jetbrains.JBRFileDialog", "com.jetbrains.desktop.JBRFileDialog");
|
||||
.proxy("com.jetbrains.JBRFileDialog", "com.jetbrains.desktop.JBRFileDialog")
|
||||
.service("com.jetbrains.CustomWindowDecoration", "java.awt.Window$CustomWindowDecoration");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,6 +358,7 @@ public class EventQueue {
|
||||
if (shouldNotify) {
|
||||
if (theEvent.getSource() != AWTAutoShutdown.getInstance()) {
|
||||
AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
|
||||
AWTThreading.getInstance(dispatchThread).notifyEventDispatchThreadBusy();
|
||||
}
|
||||
pushPopCond.signalAll();
|
||||
} else if (notifyID) {
|
||||
@@ -570,6 +571,7 @@ public class EventQueue {
|
||||
return event;
|
||||
}
|
||||
AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
|
||||
AWTThreading.getInstance(dispatchThread).notifyEventDispatchThreadFree();
|
||||
pushPopCond.await();
|
||||
} finally {
|
||||
pushPopLock.unlock();
|
||||
@@ -1128,6 +1130,7 @@ public class EventQueue {
|
||||
t.setPriority(Thread.NORM_PRIORITY + 1);
|
||||
t.setDaemon(false);
|
||||
AWTAutoShutdown.getInstance().notifyThreadBusy(t);
|
||||
AWTThreading.getInstance(t).notifyEventDispatchThreadBusy();
|
||||
return t;
|
||||
}
|
||||
}
|
||||
@@ -1158,6 +1161,7 @@ public class EventQueue {
|
||||
dispatchThread = null;
|
||||
}
|
||||
AWTAutoShutdown.getInstance().notifyThreadFree(edt);
|
||||
AWTThreading.getInstance(edt).notifyEventDispatchThreadFree();
|
||||
/*
|
||||
* Event was posted after EDT events pumping had stopped, so start
|
||||
* another EDT to handle this event
|
||||
|
||||
@@ -46,13 +46,17 @@ import java.io.ObjectOutputStream;
|
||||
import java.io.OptionalDataException;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Native;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.AccessController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
@@ -64,6 +68,7 @@ import javax.accessibility.AccessibleRole;
|
||||
import javax.accessibility.AccessibleState;
|
||||
import javax.accessibility.AccessibleStateSet;
|
||||
|
||||
import com.jetbrains.internal.JBRApi;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AWTPermissions;
|
||||
import sun.awt.AppContext;
|
||||
@@ -4007,7 +4012,66 @@ public class Window extends Container implements Accessible {
|
||||
}
|
||||
|
||||
private volatile boolean hasCustomDecoration;
|
||||
private volatile List<Map.Entry<Shape, Integer>> customDecorHitTestSpots;
|
||||
private volatile int customDecorTitleBarHeight = -1; // 0 can be a legal value when no title bar is expected
|
||||
|
||||
// called from native
|
||||
private int hitTestCustomDecoration(int x, int y) {
|
||||
var spots = customDecorHitTestSpots;
|
||||
if (spots == null) return CustomWindowDecoration.NO_HIT_SPOT;
|
||||
for (var spot : spots) {
|
||||
if (spot.getKey().contains(x, y)) return spot.getValue();
|
||||
}
|
||||
return CustomWindowDecoration.NO_HIT_SPOT;
|
||||
}
|
||||
|
||||
private static class CustomWindowDecoration {
|
||||
|
||||
@Native public static final int
|
||||
NO_HIT_SPOT = 0,
|
||||
OTHER_HIT_SPOT = 1,
|
||||
MINIMIZE_BUTTON = 2,
|
||||
MAXIMIZE_BUTTON = 3,
|
||||
CLOSE_BUTTON = 4,
|
||||
MENU_BAR = 5;
|
||||
|
||||
void setCustomDecorationEnabled(Window window, boolean enabled) {
|
||||
window.hasCustomDecoration = enabled;
|
||||
if (MacOS.INSTANCE != null && window.customDecorTitleBarHeight > 0f) {
|
||||
MacOS.INSTANCE.setTitleBarHeight(window, window.peer, enabled ? window.customDecorTitleBarHeight : 0);
|
||||
}
|
||||
}
|
||||
boolean isCustomDecorationEnabled(Window window) {
|
||||
return window.hasCustomDecoration;
|
||||
}
|
||||
|
||||
void setCustomDecorationHitTestSpots(Window window, List<Map.Entry<Shape, Integer>> spots) {
|
||||
window.customDecorHitTestSpots = List.copyOf(spots);
|
||||
}
|
||||
List<Map.Entry<Shape, Integer>> getCustomDecorationHitTestSpots(Window window) {
|
||||
return window.customDecorHitTestSpots;
|
||||
}
|
||||
|
||||
void setCustomDecorationTitleBarHeight(Window window, int height) {
|
||||
if (height >= 0) {
|
||||
window.customDecorTitleBarHeight = height;
|
||||
if (MacOS.INSTANCE != null && window.hasCustomDecoration) {
|
||||
MacOS.INSTANCE.setTitleBarHeight(window, window.peer, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
int getCustomDecorationTitleBarHeight(Window window) {
|
||||
return window.customDecorTitleBarHeight;
|
||||
}
|
||||
|
||||
private interface MacOS {
|
||||
MacOS INSTANCE = (MacOS) JBRApi.internalServiceBuilder(MethodHandles.lookup(), null)
|
||||
.withStatic("setTitleBarHeight", "sun.lwawt.macosx.CPlatformWindow", "setCustomDecorationTitleBarHeight").build();
|
||||
void setTitleBarHeight(Window target, ComponentPeer peer, float height);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
boolean hasCustomDecoration() {
|
||||
return hasCustomDecoration;
|
||||
}
|
||||
@@ -4015,6 +4079,7 @@ public class Window extends Container implements Accessible {
|
||||
/**
|
||||
* Set via reflection (JB JdkEx API).
|
||||
*/
|
||||
@Deprecated
|
||||
void setHasCustomDecoration() {
|
||||
hasCustomDecoration = true;
|
||||
}
|
||||
|
||||
@@ -8,15 +8,27 @@ import java.awt.event.InvocationEvent;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Used to perform a cross threads (EventDispatch, Toolkit) execution so that the execution does not cause a deadlock.
|
||||
*
|
||||
* Note: the log messages are tested by jdk/jb/java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java
|
||||
*/
|
||||
public class AWTThreading {
|
||||
private static final PlatformLogger logger = PlatformLogger.getLogger("sun.awt.AWTThreading");
|
||||
private static final PlatformLogger logger = PlatformLogger.getLogger(AWTThreading.class.getName());
|
||||
|
||||
private static final Runnable EMPTY_RUNNABLE = () -> {};
|
||||
|
||||
private static final AtomicReference<Function<Thread, AWTThreading>> theAWTThreadingFactory =
|
||||
new AtomicReference<>(AWTThreading::new);
|
||||
|
||||
private final Thread eventDispatchThread;
|
||||
|
||||
private ExecutorService executor;
|
||||
// every invokeAndWait() pushes a queue of invocations
|
||||
@@ -24,13 +36,21 @@ public class AWTThreading {
|
||||
|
||||
private int level; // re-entrance level
|
||||
|
||||
private final List<CompletableFuture<Void>> eventDispatchThreadStateNotifiers = new ArrayList<>();
|
||||
private volatile boolean isEventDispatchThreadFree;
|
||||
|
||||
// invocations should be dispatched on proper EDT (per AppContext)
|
||||
private static final Map<Thread, AWTThreading> EDT_TO_INSTANCE_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class TrackingQueue extends LinkedBlockingQueue<InvocationEvent> {}
|
||||
|
||||
private AWTThreading() {}
|
||||
/**
|
||||
* WARNING: for testing purpose, use {@link AWTThreading#getInstance(Thread)} instead.
|
||||
*/
|
||||
public AWTThreading(Thread edt) {
|
||||
eventDispatchThread = edt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a callable from EventDispatch thread (EDT). It's assumed the callable either performs a blocking execution on Toolkit
|
||||
@@ -178,8 +198,15 @@ public class AWTThreading {
|
||||
* <li>If the event is first dispatched from EventQueue - it gets removed from the tracking queue.
|
||||
* <li>If the event is first dispatched from the tracking queue - its dispatching on EventQueue will be noop.
|
||||
* <ul>
|
||||
*
|
||||
* @param source the source of the event
|
||||
* @param onDispatched called back on event dispatching
|
||||
* @param catchThrowables should catch Throwable's or propagate to the EventDispatch thread's loop
|
||||
*/
|
||||
public static InvocationEvent createAndTrackInvocationEvent(Object source, Runnable runnable, Runnable listener, boolean catchThrowables) {
|
||||
public static TrackedInvocationEvent createAndTrackInvocationEvent(Object source,
|
||||
Runnable onDispatched,
|
||||
boolean catchThrowables)
|
||||
{
|
||||
AWTThreading instance = getInstance(source);
|
||||
if (instance != null) {
|
||||
synchronized (instance.invocations) {
|
||||
@@ -187,65 +214,204 @@ public class AWTThreading {
|
||||
instance.invocations.push(new TrackingQueue());
|
||||
}
|
||||
final TrackingQueue queue = instance.invocations.peek();
|
||||
final InvocationEvent[] eventRef = new InvocationEvent[1];
|
||||
final AtomicReference<TrackedInvocationEvent> eventRef = new AtomicReference<>();
|
||||
|
||||
queue.add(eventRef[0] = new InvocationEvent(
|
||||
source,
|
||||
runnable,
|
||||
// Wrap the original completion listener so that it:
|
||||
// - guarantees a single run either from dispatch or dispose
|
||||
// - removes the invocation event from the tracking queue
|
||||
new Runnable() {
|
||||
WeakReference<TrackingQueue> queueRef = new WeakReference<>(queue);
|
||||
eventRef.set(TrackedInvocationEvent.create(
|
||||
source,
|
||||
onDispatched,
|
||||
new Runnable() {
|
||||
final WeakReference<TrackingQueue> queueRef = new WeakReference<>(queue);
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (queueRef != null) {
|
||||
if (listener != null) {
|
||||
listener.run();
|
||||
}
|
||||
TrackingQueue q = queueRef.get();
|
||||
if (q != null) {
|
||||
q.remove(eventRef[0]);
|
||||
}
|
||||
queueRef = null;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
TrackingQueue queue = queueRef.get();
|
||||
queueRef.clear();
|
||||
if (queue != null) {
|
||||
queue.remove(eventRef.get());
|
||||
}
|
||||
},
|
||||
catchThrowables)
|
||||
{
|
||||
@Override
|
||||
public void dispatch() {
|
||||
if (!isDispatched()) {
|
||||
super.dispatch();
|
||||
}
|
||||
}
|
||||
});
|
||||
return eventRef[0];
|
||||
},
|
||||
catchThrowables));
|
||||
|
||||
queue.add(eventRef.get());
|
||||
return eventRef.get();
|
||||
}
|
||||
}
|
||||
return new InvocationEvent(source, runnable, listener, catchThrowables);
|
||||
return TrackedInvocationEvent.create(source, onDispatched, () -> {}, catchThrowables);
|
||||
}
|
||||
|
||||
private static AWTThreading getInstance(Object obj) {
|
||||
if (obj == null) return null;
|
||||
@SuppressWarnings("serial")
|
||||
public static class TrackedInvocationEvent extends InvocationEvent {
|
||||
private final long creationTime = System.currentTimeMillis();
|
||||
private final Throwable throwable = new Throwable();
|
||||
private final CompletableFuture<Void> futureResult = new CompletableFuture<>();
|
||||
|
||||
// dispatched or disposed
|
||||
private final AtomicBoolean isFinished = new AtomicBoolean(false);
|
||||
|
||||
static TrackedInvocationEvent create(Object source,
|
||||
Runnable onDispatch,
|
||||
Runnable onDone,
|
||||
boolean catchThrowables)
|
||||
{
|
||||
final AtomicReference<TrackedInvocationEvent> eventRef = new AtomicReference<>();
|
||||
eventRef.set(new TrackedInvocationEvent(
|
||||
source,
|
||||
onDispatch,
|
||||
() -> {
|
||||
if (onDone != null) {
|
||||
onDone.run();
|
||||
}
|
||||
TrackedInvocationEvent thisEvent = eventRef.get();
|
||||
if (!thisEvent.isDispatched()) {
|
||||
// If we're here - this {onDone} is being disposed.
|
||||
thisEvent.finishIfNotYet(() ->
|
||||
// If we're here - this {onDone} is called by the outer AWTAccessor.getInvocationEventAccessor().dispose()
|
||||
// which we do not control, so complete here.
|
||||
thisEvent.futureResult.completeExceptionally(new Throwable("InvocationEvent was disposed"))
|
||||
);
|
||||
}
|
||||
},
|
||||
catchThrowables));
|
||||
return eventRef.get();
|
||||
}
|
||||
|
||||
protected TrackedInvocationEvent(Object source, Runnable onDispatched, Runnable onDone, boolean catchThrowables) {
|
||||
super(source,
|
||||
Optional.of(onDispatched).orElse(EMPTY_RUNNABLE),
|
||||
Optional.of(onDone).orElse(EMPTY_RUNNABLE),
|
||||
catchThrowables);
|
||||
|
||||
futureResult.whenComplete((r, ex) -> {
|
||||
if (ex != null) {
|
||||
String message = ex.getMessage() + " (awaiting " + (System.currentTimeMillis() - creationTime) + " ms)";
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
ex.initCause(throwable);
|
||||
logger.fine(message, ex);
|
||||
} else if (logger.isLoggable(PlatformLogger.Level.INFO)) {
|
||||
StackTraceElement[] stack = throwable.getStackTrace();
|
||||
logger.info(message + ". Originated at " + stack[stack.length - 1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch() {
|
||||
finishIfNotYet(super::dispatch);
|
||||
futureResult.complete(null);
|
||||
}
|
||||
|
||||
public void dispose(String reason) {
|
||||
finishIfNotYet(() -> AWTAccessor.getInvocationEventAccessor().dispose(this));
|
||||
futureResult.completeExceptionally(new Throwable(reason));
|
||||
}
|
||||
|
||||
private void finishIfNotYet(Runnable finish) {
|
||||
if (!isFinished.getAndSet(true)) {
|
||||
finish.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the event is dispatched or disposed.
|
||||
*/
|
||||
public boolean isDone() {
|
||||
return futureResult.isDone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the runnable when it's done (immediately if it's done).
|
||||
*/
|
||||
public void onDone(Runnable runnable) {
|
||||
futureResult.whenComplete((r, ex) -> Optional.of(runnable).orElse(EMPTY_RUNNABLE).run());
|
||||
}
|
||||
}
|
||||
|
||||
public static AWTThreading getInstance(Object obj) {
|
||||
if (obj == null) {
|
||||
return getInstance(Toolkit.getDefaultToolkit().getSystemEventQueue());
|
||||
}
|
||||
|
||||
AppContext appContext = SunToolkit.targetToAppContext(obj);
|
||||
if (appContext == null) return null;
|
||||
if (appContext == null) {
|
||||
return getInstance(Toolkit.getDefaultToolkit().getSystemEventQueue());
|
||||
}
|
||||
|
||||
return getInstance((EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY));
|
||||
}
|
||||
|
||||
private static AWTThreading getInstance(EventQueue eq) {
|
||||
public static AWTThreading getInstance(EventQueue eq) {
|
||||
if (eq == null) return null;
|
||||
|
||||
return getInstance(AWTAccessor.getEventQueueAccessor().getDispatchThread(eq));
|
||||
}
|
||||
|
||||
private static AWTThreading getInstance(Thread edt) {
|
||||
if (edt == null) return null;
|
||||
public static AWTThreading getInstance(Thread edt) {
|
||||
assert edt != null;
|
||||
|
||||
return EDT_TO_INSTANCE_MAP.computeIfAbsent(edt, key -> new AWTThreading());
|
||||
return EDT_TO_INSTANCE_MAP.computeIfAbsent(edt, key -> theAWTThreadingFactory.get().apply(edt));
|
||||
}
|
||||
|
||||
public Thread getEventDispatchThread() {
|
||||
return eventDispatchThread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@code AWTThreading} instance factory.
|
||||
* WARNING: for testing purpose.
|
||||
*/
|
||||
public static void setAWTThreadingFactory(Function<Thread, AWTThreading> factory) {
|
||||
theAWTThreadingFactory.set(factory);
|
||||
}
|
||||
|
||||
public void notifyEventDispatchThreadFree() {
|
||||
List<CompletableFuture<Void>> notifiers = Collections.emptyList();
|
||||
synchronized (eventDispatchThreadStateNotifiers) {
|
||||
isEventDispatchThreadFree = true;
|
||||
if (eventDispatchThreadStateNotifiers.size() > 0) {
|
||||
notifiers = List.copyOf(eventDispatchThreadStateNotifiers);
|
||||
}
|
||||
}
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
logger.finer("notifyEventDispatchThreadFree");
|
||||
}
|
||||
// notify callbacks out of the synchronization block
|
||||
notifiers.forEach(f -> f.complete(null));
|
||||
}
|
||||
|
||||
public void notifyEventDispatchThreadBusy() {
|
||||
synchronized (eventDispatchThreadStateNotifiers) {
|
||||
isEventDispatchThreadFree = false;
|
||||
}
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
logger.finer("notifyEventDispatchThreadBusy");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a callback and returns a {@code CompletableFuture} reporting the case when the associated EventDispatch thread
|
||||
* has gone sleeping and stopped dispatching events because of empty EventQueue. If the EventDispatch thread is free
|
||||
* at the moment then the callback is called immediately on the caller's thread and the future completes.
|
||||
*/
|
||||
public CompletableFuture<Void> onEventDispatchThreadFree(Runnable runnable) {
|
||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||
future.thenRun(Optional.of(runnable).orElse(EMPTY_RUNNABLE));
|
||||
|
||||
if (!isEventDispatchThreadFree) {
|
||||
synchronized (eventDispatchThreadStateNotifiers) {
|
||||
if (!isEventDispatchThreadFree) {
|
||||
eventDispatchThreadStateNotifiers.add(future);
|
||||
future.whenComplete((r, ex) -> eventDispatchThreadStateNotifiers.remove(future));
|
||||
return future;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
logger.finer("onEventDispatchThreadFree: free at the moment");
|
||||
}
|
||||
future.complete(null);
|
||||
return future;
|
||||
}
|
||||
|
||||
public interface Task {
|
||||
|
||||
@@ -37,7 +37,9 @@
|
||||
#include "sizecalc.h"
|
||||
#include <jni_util.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "awt.h"
|
||||
#include "debug_assert.h"
|
||||
|
||||
static void *gtk3_libhandle = NULL;
|
||||
static void *gthread_libhandle = NULL;
|
||||
@@ -2911,17 +2913,45 @@ static void transform_detail_string (const gchar *detail,
|
||||
}
|
||||
}
|
||||
|
||||
inline static int scale_down_to_plus_inf(int what, int scale) {
|
||||
return (int)ceilf(what / (float)scale);
|
||||
}
|
||||
|
||||
inline static int scale_down_to_minus_inf(int what, int scale) {
|
||||
return (int)floorf(what / (float)scale);
|
||||
}
|
||||
|
||||
static gboolean gtk3_get_drawable_data(JNIEnv *env, jintArray pixelArray,
|
||||
int x, jint y, jint width, jint height, jint jwidth, int dx, int dy,
|
||||
jint scale) {
|
||||
GdkPixbuf *pixbuf;
|
||||
jint *ary;
|
||||
|
||||
int skip_left = 0;
|
||||
int skip_top = 0;
|
||||
GdkWindow *root = (*fp_gdk_get_default_root_window)();
|
||||
if (gtk3_version_3_10) {
|
||||
int win_scale = (*fp_gdk_window_get_scale_factor)(root);
|
||||
|
||||
// Scale the coordinate and size carefully such that the captured area
|
||||
// is at least as large as requested. We trim off excess later by
|
||||
// using the skip_* variables.
|
||||
const int x_scaled = scale_down_to_minus_inf(x, win_scale);
|
||||
const int y_scaled = scale_down_to_minus_inf(y, win_scale);
|
||||
skip_left = x - x_scaled*win_scale;
|
||||
skip_top = y - y_scaled*win_scale;
|
||||
DASSERT(skip_left >= 0 && skip_top >= 0);
|
||||
|
||||
const int x_right_scaled = scale_down_to_plus_inf(x + width, win_scale);
|
||||
const int width_scaled = x_right_scaled - x_scaled;
|
||||
DASSERT(width_scaled > 0);
|
||||
|
||||
const int y_bottom_scaled = scale_down_to_plus_inf(y + height, win_scale);
|
||||
const int height_scaled = y_bottom_scaled - y_scaled;
|
||||
DASSERT(height_scaled > 0);
|
||||
|
||||
pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(
|
||||
root, x, y, (int) (width / (float) win_scale + 0.5), (int) (height / (float) win_scale + 0.5));
|
||||
root, x_scaled, y_scaled, width_scaled, height_scaled);
|
||||
} else {
|
||||
pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(root, x, y, width, height);
|
||||
}
|
||||
@@ -2956,7 +2986,8 @@ static gboolean gtk3_get_drawable_data(JNIEnv *env, jintArray pixelArray,
|
||||
int index;
|
||||
for (_y = 0; _y < height; _y++) {
|
||||
for (_x = 0; _x < width; _x++) {
|
||||
p = pix + (intptr_t) _y * stride + _x * nchan;
|
||||
p = pix + (intptr_t) (_y + skip_top) * stride
|
||||
+ (_x + skip_left) * nchan;
|
||||
|
||||
index = (_y + dy) * jwidth + (_x + dx);
|
||||
ary[index] = 0xff000000
|
||||
|
||||
@@ -55,8 +55,11 @@ import java.awt.image.DataBufferInt;
|
||||
import java.awt.peer.WindowPeer;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
@@ -991,31 +994,29 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
|
||||
return err;
|
||||
}
|
||||
|
||||
private volatile List<Rectangle> customDecorHitTestSpots;
|
||||
private volatile int customDecorTitleBarHeight = -1; // 0 can be a legal value when no title bar is expected
|
||||
|
||||
// called from client via reflection
|
||||
@Deprecated
|
||||
private void setCustomDecorationHitTestSpots(List<Rectangle> hitTestSpots) {
|
||||
this.customDecorHitTestSpots = new CopyOnWriteArrayList<>(hitTestSpots);
|
||||
List<Map.Entry<Shape, Integer>> spots = new ArrayList<>();
|
||||
for (Rectangle spot : hitTestSpots) spots.add(Map.entry(spot, 1));
|
||||
try {
|
||||
Field f = Window.class.getDeclaredField("customDecorHitTestSpots");
|
||||
f.setAccessible(true);
|
||||
f.set(target, spots);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
// called from client via reflection
|
||||
@Deprecated
|
||||
private void setCustomDecorationTitleBarHeight(int height) {
|
||||
if (height >= 0) customDecorTitleBarHeight = height;
|
||||
}
|
||||
|
||||
// called from native
|
||||
private boolean hitTestCustomDecoration(int x, int y) {
|
||||
List<Rectangle> spots = customDecorHitTestSpots;
|
||||
if (spots == null) return false;
|
||||
for (Rectangle spot : spots) {
|
||||
if (spot.contains(x, y)) return true;
|
||||
try {
|
||||
Field f = Window.class.getDeclaredField("customDecorTitleBarHeight");
|
||||
f.setAccessible(true);
|
||||
f.set(target, height);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// called from native
|
||||
private int getCustomDecorationTitleBarHeight() {
|
||||
return customDecorTitleBarHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1646,6 +1646,9 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
case WM_NCRBUTTONDOWN:
|
||||
mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), RIGHT_BUTTON);
|
||||
break;
|
||||
case WM_NCMOUSEMOVE:
|
||||
mr = WmNcMouseMove(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
if (ignoreNextLBTNUP) {
|
||||
ignoreNextLBTNUP = FALSE;
|
||||
@@ -2330,6 +2333,9 @@ MsgRouting AwtComponent::WmNcMouseDown(WPARAM hitTest, int x, int y, int button)
|
||||
MsgRouting AwtComponent::WmNcMouseUp(WPARAM hitTest, int x, int y, int button) {
|
||||
return mrDoDefault;
|
||||
}
|
||||
MsgRouting AwtComponent::WmNcMouseMove(WPARAM hitTest, int x, int y) {
|
||||
return mrDoDefault;
|
||||
}
|
||||
|
||||
MsgRouting AwtComponent::WmWindowPosChanging(LPARAM windowPos) {
|
||||
return mrDoDefault;
|
||||
|
||||
@@ -525,6 +525,7 @@ public:
|
||||
int wheelRotation, BOOL isHorizontal);
|
||||
virtual MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button);
|
||||
virtual MsgRouting WmNcMouseUp(WPARAM hitTest, int x, int y, int button);
|
||||
virtual MsgRouting WmNcMouseMove(WPARAM hitTest, int x, int y);
|
||||
virtual MsgRouting WmWindowPosChanging(LPARAM windowPos);
|
||||
virtual MsgRouting WmWindowPosChanged(LPARAM windowPos);
|
||||
virtual void WmTouch(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <dwmapi.h>
|
||||
|
||||
#include <java_lang_Integer.h>
|
||||
#include <java_awt_Window_CustomWindowDecoration.h>
|
||||
#include <sun_awt_windows_WEmbeddedFrame.h>
|
||||
#include <sun_awt_windows_WEmbeddedFramePeer.h>
|
||||
|
||||
@@ -622,6 +623,23 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
|
||||
if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) {
|
||||
m_grabbedWindow->Ungrab();
|
||||
}
|
||||
// For windows with custom decorations, handle caption-related mouse events
|
||||
// Do not handle events from caption itself to preserve native drag behavior
|
||||
if (HasCustomDecoration()) {
|
||||
switch (hitTest) {
|
||||
case HTMINBUTTON:
|
||||
case HTMAXBUTTON:
|
||||
case HTCLOSE:
|
||||
case HTMENU:
|
||||
RECT rcWindow;
|
||||
GetWindowRect(GetHWnd(), &rcWindow);
|
||||
WmMouseDown(GetButtonMK(button),
|
||||
x - rcWindow.left,
|
||||
y - rcWindow.top,
|
||||
button);
|
||||
return mrConsume;
|
||||
}
|
||||
}
|
||||
if (!IsFocusableWindow() && (button & LEFT_BUTTON)) {
|
||||
switch (hitTest) {
|
||||
case HTTOP:
|
||||
@@ -653,6 +671,24 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
|
||||
return AwtWindow::WmNcMouseDown(hitTest, x, y, button);
|
||||
}
|
||||
|
||||
MsgRouting AwtFrame::WmNcMouseMove(WPARAM hitTest, int x, int y) {
|
||||
// For windows with custom decorations, handle caption-related mouse events
|
||||
if (HasCustomDecoration()) {
|
||||
switch (hitTest) {
|
||||
case HTMINBUTTON:
|
||||
case HTMAXBUTTON:
|
||||
case HTCLOSE:
|
||||
case HTMENU:
|
||||
case HTCAPTION:
|
||||
RECT rcWindow;
|
||||
GetWindowRect(GetHWnd(), &rcWindow);
|
||||
WmMouseMove(0, x - rcWindow.left, y - rcWindow.top);
|
||||
if (hitTest != HTCAPTION) return mrConsume; // Preserve default window drag for HTCAPTION
|
||||
}
|
||||
}
|
||||
return AwtWindow::WmNcMouseMove(hitTest, x, y);
|
||||
}
|
||||
|
||||
// Override AwtWindow::Reshape() to handle minimized/maximized
|
||||
// frames (see 6525850, 4065534)
|
||||
void AwtFrame::Reshape(int x, int y, int w, int h)
|
||||
@@ -1670,7 +1706,7 @@ BOOL AwtFrame::HasCustomDecoration()
|
||||
if (!m_pHasCustomDecoration) {
|
||||
m_pHasCustomDecoration = new BOOL;
|
||||
JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
*m_pHasCustomDecoration = JNU_CallMethodByName(env, NULL, GetTarget(env), "hasCustomDecoration", "()Z").z;
|
||||
*m_pHasCustomDecoration = JNU_GetFieldByName(env, NULL, GetTarget(env), "hasCustomDecoration", "Z").z;
|
||||
}
|
||||
return *m_pHasCustomDecoration;
|
||||
}
|
||||
@@ -1712,10 +1748,8 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) {
|
||||
AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL);
|
||||
|
||||
JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
int titleHeight = (int)JNU_CallMethodByName(env, NULL, frame->GetPeer(env),
|
||||
"getCustomDecorationTitleBarHeight", "()I",
|
||||
frame->ScaleDownX(x - rcWindow.left),
|
||||
frame->ScaleDownY(y - rcWindow.top)).i;
|
||||
int titleHeight = (int)JNU_GetFieldByName(env, NULL, frame->GetTarget(env),
|
||||
"customDecorTitleBarHeight", "I").i;
|
||||
if (titleHeight >= 0) {
|
||||
titleHeight = frame->ScaleUpY(titleHeight);
|
||||
insets.top = titleHeight; // otherwise leave default
|
||||
@@ -1728,12 +1762,23 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) {
|
||||
if (y >= rcWindow.top &&
|
||||
y < rcWindow.top + insets.top)
|
||||
{
|
||||
if (JNU_CallMethodByName(env, NULL, frame->GetPeer(env),
|
||||
"hitTestCustomDecoration", "(II)Z",
|
||||
frame->ScaleDownX(x - rcWindow.left),
|
||||
frame->ScaleDownY(y - rcWindow.top)).z)
|
||||
{
|
||||
return HTNOWHERE;
|
||||
jint customSpot = JNU_CallMethodByName(env, NULL, frame->GetTarget(env),
|
||||
"hitTestCustomDecoration", "(II)I",
|
||||
frame->ScaleDownX(x - rcWindow.left),
|
||||
frame->ScaleDownY(y - rcWindow.top)).i;
|
||||
switch (customSpot) {
|
||||
case java_awt_Window_CustomWindowDecoration_NO_HIT_SPOT:
|
||||
break; // Nothing
|
||||
case java_awt_Window_CustomWindowDecoration_MINIMIZE_BUTTON:
|
||||
return HTMINBUTTON;
|
||||
case java_awt_Window_CustomWindowDecoration_MAXIMIZE_BUTTON:
|
||||
return HTMAXBUTTON;
|
||||
case java_awt_Window_CustomWindowDecoration_CLOSE_BUTTON:
|
||||
return HTCLOSE;
|
||||
case java_awt_Window_CustomWindowDecoration_MENU_BAR:
|
||||
return HTMENU;
|
||||
default:
|
||||
return HTNOWHERE;
|
||||
}
|
||||
fOnResizeBorder = (y < (rcWindow.top - rcFrame.top));
|
||||
uRow = 0;
|
||||
|
||||
@@ -111,6 +111,7 @@ public:
|
||||
MsgRouting WmMouseMove(UINT flags, int x, int y);
|
||||
MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button);
|
||||
MsgRouting WmNcMouseUp(WPARAM hitTest, int x, int y, int button);
|
||||
MsgRouting WmNcMouseMove(WPARAM hitTest, int x, int y);
|
||||
MsgRouting WmGetIcon(WPARAM iconType, LRESULT& retVal);
|
||||
MsgRouting WmShowWindow(BOOL show, UINT status);
|
||||
MsgRouting WmWindowPosChanging(LPARAM windowPos);
|
||||
|
||||
117
src/jetbrains.api/src/com/jetbrains/CustomWindowDecoration.java
Normal file
117
src/jetbrains.api/src/com/jetbrains/CustomWindowDecoration.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2000-2021 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.jetbrains;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public interface CustomWindowDecoration {
|
||||
|
||||
/*CONST java.awt.Window.*_HIT_SPOT*/
|
||||
/*CONST java.awt.Window.*_BUTTON*/
|
||||
/*CONST java.awt.Window.MENU_BAR*/
|
||||
|
||||
void setCustomDecorationEnabled(Window window, boolean enabled);
|
||||
boolean isCustomDecorationEnabled(Window window);
|
||||
|
||||
void setCustomDecorationHitTestSpots(Window window, List<Map.Entry<Shape, Integer>> spots);
|
||||
List<Map.Entry<Shape, Integer>> getCustomDecorationHitTestSpots(Window window);
|
||||
|
||||
void setCustomDecorationTitleBarHeight(Window window, int height);
|
||||
int getCustomDecorationTitleBarHeight(Window window);
|
||||
|
||||
|
||||
@SuppressWarnings("all")
|
||||
class __Fallback implements CustomWindowDecoration {
|
||||
|
||||
private final Method
|
||||
hasCustomDecoration,
|
||||
setHasCustomDecoration,
|
||||
setCustomDecorationHitTestSpots,
|
||||
setCustomDecorationTitleBarHeight;
|
||||
private final Field peer;
|
||||
|
||||
__Fallback() throws Exception {
|
||||
hasCustomDecoration = Window.class.getDeclaredMethod("hasCustomDecoration");
|
||||
hasCustomDecoration.setAccessible(true);
|
||||
setHasCustomDecoration = Window.class.getDeclaredMethod("setHasCustomDecoration");
|
||||
setHasCustomDecoration.setAccessible(true);
|
||||
Class<?> wpeer = Class.forName("sun.awt.windows.WWindowPeer");
|
||||
setCustomDecorationHitTestSpots = wpeer.getDeclaredMethod("setCustomDecorationHitTestSpots", List.class);
|
||||
setCustomDecorationHitTestSpots.setAccessible(true);
|
||||
setCustomDecorationTitleBarHeight = wpeer.getDeclaredMethod("setCustomDecorationTitleBarHeight", int.class);
|
||||
setCustomDecorationTitleBarHeight.setAccessible(true);
|
||||
peer = Component.class.getDeclaredField("peer");
|
||||
peer.setAccessible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCustomDecorationEnabled(Window window, boolean enabled) {
|
||||
if (enabled) {
|
||||
try {
|
||||
setHasCustomDecoration.invoke(window);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomDecorationEnabled(Window window) {
|
||||
try {
|
||||
return (boolean) hasCustomDecoration.invoke(window);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCustomDecorationHitTestSpots(Window window, List<Map.Entry<Shape, Integer>> spots) {
|
||||
List<Rectangle> hitTestSpots = spots.stream().map(e -> e.getKey().getBounds()).collect(Collectors.toList());
|
||||
try {
|
||||
setCustomDecorationHitTestSpots.invoke(peer.get(window), hitTestSpots);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map.Entry<Shape, Integer>> getCustomDecorationHitTestSpots(Window window) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCustomDecorationTitleBarHeight(Window window, int height) {
|
||||
try {
|
||||
setCustomDecorationTitleBarHeight.invoke(peer.get(window), height);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCustomDecorationTitleBarHeight(Window window) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,15 @@ public class JBR {
|
||||
|
||||
private JBR() {}
|
||||
|
||||
private static <T> T getService(Class<T> interFace, FallbackSupplier<T> fallback) {
|
||||
T service = getService(interFace);
|
||||
try {
|
||||
return service != null ? service : fallback != null ? fallback.get() : null;
|
||||
} catch (Throwable ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static <T> T getService(Class<T> interFace) {
|
||||
return api == null ? null : api.getService(interFace);
|
||||
}
|
||||
@@ -94,6 +103,11 @@ public class JBR {
|
||||
<T> T getService(Class<T> interFace);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface FallbackSupplier<T> {
|
||||
T get() throws Throwable;
|
||||
}
|
||||
|
||||
// ========================== Generated metadata ==========================
|
||||
|
||||
/**
|
||||
|
||||
@@ -92,7 +92,7 @@ public class Gensrc {
|
||||
}
|
||||
|
||||
private static String generate(String content) throws IOException {
|
||||
Pattern pattern = compile("/\\*CONST ((?:[a-zA-Z0-9]+\\.)+)([a-zA-Z0-9_*]+)\s*\\*/");
|
||||
Pattern pattern = compile("/\\*CONST ((?:[a-zA-Z0-9]+\\.)+)([a-zA-Z0-9_*]+)\\s*\\*/");
|
||||
for (;;) {
|
||||
Matcher matcher = pattern.matcher(content);
|
||||
if (!matcher.find()) return content;
|
||||
@@ -102,15 +102,23 @@ public class Gensrc {
|
||||
for (Path module : modules.paths) {
|
||||
Path f = module.resolve("share/classes").resolve(file);
|
||||
if (Files.exists(f)) {
|
||||
Pattern namePattern = compile(name.replaceAll("\\*", "[a-zA-Z0-9_]+") + "\s*=");
|
||||
Pattern statementPattern = compile("((?:(?:public|protected|private|static|final)\s+){2,3})([a-zA-Z0-9]+)\s+([^;]+);");
|
||||
Pattern namePattern = compile(name.replaceAll("\\*", "\\\\w+"));
|
||||
Pattern statementPattern = compile(
|
||||
"((?:(?:MODS) ){2,3})([a-zA-Z0-9]+) (FIELD(?:, FIELD)*);"
|
||||
.replaceAll("MODS", "public|protected|private|static|final")
|
||||
.replaceAll("FIELD", "\\\\w+ = [\\\\w\"']+ ")
|
||||
.replaceAll(" ", "\\\\s+")
|
||||
.replaceAll(" ", "\\\\s*")
|
||||
);
|
||||
Matcher statementMatcher = statementPattern.matcher(Files.readString(f));
|
||||
while (statementMatcher.find()) {
|
||||
String mods = statementMatcher.group(1);
|
||||
if (!mods.contains("static") || !mods.contains("final")) continue;
|
||||
for (String s : statementMatcher.group(3).split(",")) {
|
||||
if (!namePattern.matcher(s).find()) continue;
|
||||
statements.add("public static final " + statementMatcher.group(2) + " " + s.strip() + ";");
|
||||
s = s.strip();
|
||||
String nm = s.substring(0, s.indexOf('=')).strip();
|
||||
if (!namePattern.matcher(nm).matches()) continue;
|
||||
statements.add("public static final " + statementMatcher.group(2) + " " + s + ";");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -164,7 +172,7 @@ public class Gensrc {
|
||||
}
|
||||
|
||||
private static Service[] findPublicServiceInterfaces() {
|
||||
Pattern javadocPattern = Pattern.compile("/\\*\\*((?:.|\n)*?)(\s|\n)*\\*/");
|
||||
Pattern javadocPattern = Pattern.compile("/\\*\\*((?:.|\n)*?)\\s*\\*/");
|
||||
return modules.services.stream()
|
||||
.map(fullName -> {
|
||||
if (fullName.indexOf('$') != -1) return null; // Only top level services can be public
|
||||
@@ -186,7 +194,8 @@ public class Gensrc {
|
||||
javadocEnd = 0;
|
||||
}
|
||||
return new Service(name, javadoc,
|
||||
content.substring(javadocEnd, indexOfDeclaration).contains("@Deprecated"));
|
||||
content.substring(javadocEnd, indexOfDeclaration).contains("@Deprecated"),
|
||||
content.contains("__Fallback"));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
@@ -197,7 +206,7 @@ public class Gensrc {
|
||||
private static String generateMethodsForService(Service service) {
|
||||
return """
|
||||
private static class $__Holder {<DEPRECATED>
|
||||
private static final $ INSTANCE = api != null ? api.getService($.class) : null;
|
||||
private static final $ INSTANCE = getService($.class, <FALLBACK>);
|
||||
}
|
||||
/**
|
||||
* @return true if current runtime has implementation for all methods in {@link $}
|
||||
@@ -214,12 +223,13 @@ public class Gensrc {
|
||||
return $__Holder.INSTANCE;
|
||||
}
|
||||
"""
|
||||
.replace("<FALLBACK>", service.hasFallback ? "$.__Fallback::new" : "null")
|
||||
.replaceAll("\\$", service.name)
|
||||
.replace("<JAVADOC>", service.javadoc)
|
||||
.replaceAll("<DEPRECATED>", service.deprecated ? "\n@Deprecated" : "");
|
||||
}
|
||||
|
||||
private record Service(String name, String javadoc, boolean deprecated) {}
|
||||
private record Service(String name, String javadoc, boolean deprecated, boolean hasFallback) {}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,7 +250,7 @@ public class Gensrc {
|
||||
}
|
||||
|
||||
private void findInModule(String content) {
|
||||
Pattern servicePattern = compile("(service|proxy|twoWayProxy)\s*\\(([^)]+)");
|
||||
Pattern servicePattern = compile("(service|proxy|twoWayProxy)\\s*\\(([^)]+)");
|
||||
Matcher matcher = servicePattern.matcher(content);
|
||||
while (matcher.find()) {
|
||||
String type = matcher.group(1);
|
||||
|
||||
@@ -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 = 0.0.2
|
||||
VERSION = 0.0.4
|
||||
|
||||
# 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 = 814F29888E5EB6C23DF27B53636E9F94
|
||||
HASH = 74417FA361EA554F9C90873A3FF354
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
@@ -109,6 +109,7 @@ public class LambdaEagerInit {
|
||||
static void testDefaultArchiveWithEagerInitializationEnabled() throws Exception {
|
||||
// run with default CDS archive with the -Djdk.internal.lambda.disableEagerInitialization=true property
|
||||
CDSOptions runOpts = (new CDSOptions())
|
||||
.setXShareMode("auto")
|
||||
.addPrefix("-cp", appJar, testProperty, "-Xlog:class+load,cds=debug")
|
||||
.setUseSystemArchive(true)
|
||||
.setUseVersion(false)
|
||||
@@ -122,13 +123,16 @@ public class LambdaEagerInit {
|
||||
static void testDefaultArchiveWithEagerInitializationDisabled() throws Exception {
|
||||
// run with default CDS archive without the -Djdk.internal.lambda.disableEagerInitialization=true property
|
||||
CDSOptions runOpts = (new CDSOptions())
|
||||
.setXShareMode("auto")
|
||||
.addPrefix("-cp", appJar, "-Xlog:class+load,cds=debug")
|
||||
.setUseSystemArchive(true)
|
||||
.setUseVersion(false)
|
||||
.addSuffix(mainClass);
|
||||
.addSuffix("-showversion", mainClass);
|
||||
OutputAnalyzer output = CDSTestUtils.runWithArchive(runOpts);
|
||||
output.shouldMatch(lambdaLoadedFromArchive)
|
||||
.shouldMatch(cdsLoadedLambdaProxy)
|
||||
.shouldHaveExitValue(0);
|
||||
if (output.getStderr().contains("sharing")) {
|
||||
output.shouldMatch(lambdaLoadedFromArchive)
|
||||
.shouldMatch(cdsLoadedLambdaProxy);
|
||||
}
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,17 @@ import java.awt.Dimension;
|
||||
import java.awt.DisplayMode;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.file.Path;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.WindowConstants;
|
||||
import jdk.jfr.Recording;
|
||||
import java.io.IOException;
|
||||
import jdk.jfr.consumer.RecordedEvent;
|
||||
import jdk.jfr.consumer.RecordedFrame;
|
||||
import jdk.jfr.consumer.RecordingFile;
|
||||
|
||||
/*
|
||||
* @test
|
||||
@@ -39,20 +43,21 @@ import javax.swing.WindowConstants;
|
||||
*
|
||||
* @summary Test verifies that there is no extra allocation after display mode switch
|
||||
*
|
||||
* @run main/othervm -Xmx750M ExtraAllocationTest
|
||||
* @run main/othervm -Xmx750M ExtraAllocationTest
|
||||
*/
|
||||
|
||||
|
||||
public class ExtraAllocationTest {
|
||||
private static final int MAX_MODES = 10;
|
||||
private static final int W = 500;
|
||||
private static final int H = 500;
|
||||
static JFrame f = null;
|
||||
|
||||
public static void main(String[] args) throws InterruptedException, InvocationTargetException {
|
||||
MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
|
||||
memBean.gc();
|
||||
Thread.sleep(2000);
|
||||
static long th = ((long) W * H * 32) / (8 * 2);
|
||||
public static void main(String[] args) throws InterruptedException, InvocationTargetException,
|
||||
IOException
|
||||
{
|
||||
Recording recording = new Recording();
|
||||
recording.enable("jdk.ObjectAllocationOutsideTLAB");
|
||||
recording.start();
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
f = new JFrame();
|
||||
f.add(new JPanel());
|
||||
@@ -66,35 +71,38 @@ public class ExtraAllocationTest {
|
||||
GraphicsDevice d = ge.getDefaultScreenDevice();
|
||||
|
||||
if (d.isDisplayChangeSupported()) {
|
||||
DisplayMode odm = d.getDisplayMode();
|
||||
DisplayMode[] modes = d.getDisplayModes();
|
||||
try {
|
||||
int modesCount = Math.min(modes.length, MAX_MODES);
|
||||
int modesCount = Math.min(modes.length, MAX_MODES);
|
||||
|
||||
for (int i = 0; i < modesCount; i++) {
|
||||
DisplayMode mode = modes[i];
|
||||
int w = mode.getWidth();
|
||||
int h = mode.getHeight();
|
||||
int bpp = mode.getBitDepth();
|
||||
long th = ((long) W * H * bpp) / (8 * 2);
|
||||
DisplayMode newMode =
|
||||
new DisplayMode(w, h, bpp, DisplayMode.REFRESH_RATE_UNKNOWN);
|
||||
long usedHeap = memBean.getHeapMemoryUsage().getUsed();
|
||||
d.setDisplayMode(newMode);
|
||||
Thread.sleep(2000);
|
||||
long memDiff = memBean.getHeapMemoryUsage().getUsed() - usedHeap;
|
||||
if (memDiff > th) {
|
||||
throw new RuntimeException("Extra allocation detected: " + memDiff);
|
||||
}
|
||||
ManagementFactory.getMemoryMXBean().gc();
|
||||
Thread.sleep(2000);
|
||||
for (int i = 0; i < modesCount; i++) {
|
||||
DisplayMode mode = modes[i];
|
||||
try {
|
||||
d.setDisplayMode(mode);
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
d.setDisplayMode(odm);
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
}
|
||||
f.setVisible(false);
|
||||
f.dispose();
|
||||
Thread.sleep(1000);
|
||||
Path path = Path.of("recording.jfr");
|
||||
recording.dump(path);
|
||||
recording.close();
|
||||
for (RecordedEvent event : RecordingFile.readAllEvents(path)) {
|
||||
if ("jdk.ObjectAllocationOutsideTLAB".equalsIgnoreCase(event.getEventType().getName())) {
|
||||
for (RecordedFrame recordedFrame :event.getStackTrace().getFrames()) {
|
||||
if (recordedFrame.isJavaFrame() &&
|
||||
"java.awt.image.DataBufferInt".equals(
|
||||
recordedFrame.getMethod().getType().getName()) &&
|
||||
event.getLong("allocationSize") > th)
|
||||
{
|
||||
throw new RuntimeException("Extra allocation detected: " +
|
||||
event.getLong("allocationSize"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,20 +27,29 @@ import java.awt.Color;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Panel;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Robot;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.swing.UIManager;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @key headful
|
||||
* @bug 8073320
|
||||
* @bug 8073320 8280861
|
||||
* @summary Windows HiDPI support
|
||||
* @author Alexander Scherbatiy
|
||||
* @requires (os.family == "linux" | os.family == "windows")
|
||||
* @requires !display.XWayland
|
||||
* @run main/othervm -Dsun.java2d.win.uiScaleX=3 -Dsun.java2d.win.uiScaleY=2
|
||||
* HiDPIRobotScreenCaptureTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale=1
|
||||
* HiDPIRobotScreenCaptureTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale=2
|
||||
* HiDPIRobotScreenCaptureTest
|
||||
*/
|
||||
|
||||
public class HiDPIRobotScreenCaptureTest {
|
||||
@@ -60,7 +69,14 @@ public class HiDPIRobotScreenCaptureTest {
|
||||
}
|
||||
|
||||
Frame frame = new Frame();
|
||||
frame.setBounds(40, 30, 400, 300);
|
||||
// Position the frame on prime number coordinates to avoid
|
||||
// them being multiple of the desktop scale; this tests Linux
|
||||
// color picker better.
|
||||
// Also, the position should be far enough from the top left
|
||||
// corner of the screen to reduce the chance of being repositioned
|
||||
// by the system because that area's occupied by the global
|
||||
// menu bar and such.
|
||||
frame.setBounds(83, 97, 400, 300);
|
||||
frame.setUndecorated(true);
|
||||
|
||||
Panel panel = new Panel(new BorderLayout());
|
||||
@@ -78,6 +94,13 @@ public class HiDPIRobotScreenCaptureTest {
|
||||
g.fillRect(0, h / 2, w / 2, h / 2);
|
||||
g.setColor(COLORS[3]);
|
||||
g.fillRect(w / 2, h / 2, w / 2, h / 2);
|
||||
|
||||
// Several distinct pixels next to one another
|
||||
// in order to test color picker's precision.
|
||||
for (int i = 1; i < 4; i++) {
|
||||
g.setColor(COLORS[i]);
|
||||
g.fillRect(i, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -86,11 +109,15 @@ public class HiDPIRobotScreenCaptureTest {
|
||||
frame.setVisible(true);
|
||||
Robot robot = new Robot();
|
||||
robot.waitForIdle();
|
||||
Thread.sleep(200);
|
||||
robot.delay(500);
|
||||
|
||||
final Point screenLocation = frame.getLocationOnScreen();
|
||||
checkPixelColors(robot, screenLocation.x, screenLocation.y);
|
||||
|
||||
Rectangle rect = canvas.getBounds();
|
||||
rect.setLocation(canvas.getLocationOnScreen());
|
||||
|
||||
System.out.println("Creating screen capture of " + rect);
|
||||
BufferedImage image = robot.createScreenCapture(rect);
|
||||
frame.dispose();
|
||||
|
||||
@@ -101,20 +128,53 @@ public class HiDPIRobotScreenCaptureTest {
|
||||
throw new RuntimeException("Wrong image size!");
|
||||
}
|
||||
|
||||
if (image.getRGB(w / 4, h / 4) != COLORS[0].getRGB()) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
|
||||
if (image.getRGB(3 * w / 4, h / 4) != COLORS[1].getRGB()) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
checkRectColor(image, new Rectangle(0, 0, w / 2, h / 2), COLORS[0]);
|
||||
checkRectColor(image, new Rectangle(w / 2, 0, w / 2, h / 2), COLORS[1]);
|
||||
checkRectColor(image, new Rectangle(0, h / 2, w / 2, h / 2), COLORS[2]);
|
||||
checkRectColor(image, new Rectangle(w / 2, h / 2, w / 2, h / 2), COLORS[3]);
|
||||
}
|
||||
|
||||
if (image.getRGB(w / 4, 3 * h / 4) != COLORS[2].getRGB()) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
static void checkPixelColors(Robot robot, int x, int y) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
final Color actualColor = robot.getPixelColor(x + i, y);
|
||||
System.out.print("Checking color at " + (x + i) + ", " + y + " to be equal to " + COLORS[i]);
|
||||
if (!actualColor.equals(COLORS[i])) {
|
||||
System.out.println("... Mismatch: found " + actualColor + " instead");
|
||||
throw new RuntimeException("Wrong screen pixel color");
|
||||
|
||||
if (image.getRGB(3 * w / 4, 3 * h / 4) != COLORS[3].getRGB()) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
} else {
|
||||
System.out.println("... OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final int OFFSET = 5;
|
||||
static void checkRectColor(BufferedImage image, Rectangle rect, Color expectedColor) {
|
||||
System.out.println("Checking rectangle " + rect + " to have color " + expectedColor);
|
||||
final Point[] pointsToCheck = new Point[] {
|
||||
new Point(rect.x + OFFSET, rect.y + OFFSET), // top left corner
|
||||
new Point(rect.x + rect.width - OFFSET, rect.y + OFFSET), // top right corner
|
||||
new Point(rect.x + rect.width / 2, rect.y + rect.height / 2), // center
|
||||
new Point(rect.x + OFFSET, rect.y + rect.height - OFFSET), // bottom left corner
|
||||
new Point(rect.x + rect.width - OFFSET, rect.y + rect.height - OFFSET) // bottom right corner
|
||||
};
|
||||
|
||||
for (final var point : pointsToCheck) {
|
||||
System.out.print("Checking color at " + point + " to be equal to " + expectedColor);
|
||||
final int actualColor = image.getRGB(point.x, point.y);
|
||||
if (actualColor != expectedColor.getRGB()) {
|
||||
System.out.println("... Mismatch: found " + new Color(actualColor) + " instead. Check image.png.");
|
||||
try {
|
||||
ImageIO.write(image, "png", new File("image.png"));
|
||||
} catch(IOException e) {
|
||||
System.out.println("failed to save image.png.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
} else {
|
||||
System.out.println("... OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
/*
|
||||
* @test
|
||||
* @key headful
|
||||
* @bug 8162959
|
||||
* @bug 8162959 8280861
|
||||
* @requires !display.XWayland
|
||||
* @summary Validate output of createMultiResolutionScreenCapture
|
||||
* new API which returns MultiResolutionImage.
|
||||
* @run main/othervm -Dsun.java2d.uiScale=1 ScreenCaptureTest
|
||||
@@ -44,6 +45,7 @@ import java.awt.Color;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Panel;
|
||||
import java.awt.Point;
|
||||
import java.awt.Robot;
|
||||
import java.util.List;
|
||||
|
||||
@@ -58,7 +60,14 @@ public class ScreenCaptureTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
frame = new Frame();
|
||||
frame.setBounds(0, 0, 400, 400);
|
||||
// Position the frame on prime number coordinates to avoid
|
||||
// them being multiple of the desktop scale; this tests Linux
|
||||
// color picker better.
|
||||
// Also, the position should be far enough from the top left
|
||||
// corner of the screen to reduce the chance of being repositioned
|
||||
// by the system because that area's occupied by the global
|
||||
// menu bar and such.
|
||||
frame.setBounds(83, 97, 400, 400);
|
||||
frame.setUndecorated(true);
|
||||
robot = new Robot();
|
||||
Panel panel = new Panel(new BorderLayout());
|
||||
@@ -87,97 +96,112 @@ public class ScreenCaptureTest {
|
||||
int w = frame.getWidth();
|
||||
int h = frame.getHeight();
|
||||
|
||||
// getPixelColor Test
|
||||
// Check pixel color in first quardant GREEN; x=100, y=100
|
||||
if (!robot.getPixelColor(w / 4, h / 4).equals(COLORS[0])) {
|
||||
throw new RuntimeException("Wrong Pixel Color! Expected GREEN");
|
||||
}
|
||||
// Check pixel color in second quardant; BLUE, x=300, y=100
|
||||
if (!robot.getPixelColor(3 * w / 4, h / 4).equals(COLORS[1])) {
|
||||
throw new RuntimeException("Wrong Pixel Color! Expected BLUE");
|
||||
}
|
||||
// Check pixel color in third quardant; ORANGE, x=100, y=300
|
||||
if (!robot.getPixelColor(w / 4, 3 * h / 4).equals(COLORS[2])) {
|
||||
throw new RuntimeException("Wrong Pixel Color! Expected ORANGE");
|
||||
}
|
||||
// Check pixel color in fourth quardant; RED, x=300, y=300
|
||||
if (!robot.getPixelColor(3 * w / 4, 3 * h / 4).equals(COLORS[3])) {
|
||||
throw new RuntimeException("Wrong Pixel Color! Expected RED");
|
||||
}
|
||||
final Point screenLocation = frame.getLocationOnScreen();
|
||||
final int x = screenLocation.x;
|
||||
final int y = screenLocation.y;
|
||||
try {
|
||||
// getPixelColor() tests
|
||||
checkRectColor(new Rectangle(x, y, w / 2, h / 2), COLORS[0]);
|
||||
checkRectColor(new Rectangle(x + w / 2, y, w / 2, h / 2), COLORS[1]);
|
||||
checkRectColor(new Rectangle(x, y + h / 2, w / 2, h / 2), COLORS[2]);
|
||||
checkRectColor(new Rectangle(x + w / 2, y + h / 2, w / 2, h / 2), COLORS[3]);
|
||||
|
||||
// createScreenCaptureTest
|
||||
AffineTransform tx = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice().getDefaultConfiguration()
|
||||
.getDefaultTransform();
|
||||
// createScreenCaptureTest
|
||||
AffineTransform tx = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice().getDefaultConfiguration()
|
||||
.getDefaultTransform();
|
||||
|
||||
if (tx.getScaleX() == 1 && tx.getScaleY() == 1) {
|
||||
isHiDPI = false;
|
||||
}
|
||||
|
||||
MultiResolutionImage image
|
||||
= robot.createMultiResolutionScreenCapture(frame.getBounds());
|
||||
List<Image> imageList = image.getResolutionVariants();
|
||||
int size = imageList.size();
|
||||
BufferedImage lowResImage;
|
||||
BufferedImage highResImage;
|
||||
|
||||
if (!isHiDPI) {
|
||||
// Check if output is MultiResolutionImage with one variant
|
||||
if (size != 1) {
|
||||
throw new RuntimeException(" Invalid variant size");
|
||||
if (tx.getScaleX() == 1 && tx.getScaleY() == 1) {
|
||||
isHiDPI = false;
|
||||
}
|
||||
|
||||
lowResImage = (BufferedImage) imageList.get(0);
|
||||
System.out.println(frame.getBounds());
|
||||
System.out.println(lowResImage.getWidth()+" "+lowResImage.getHeight());
|
||||
if (frame.getWidth() != lowResImage.getWidth()
|
||||
MultiResolutionImage image
|
||||
= robot.createMultiResolutionScreenCapture(frame.getBounds());
|
||||
List<Image> imageList = image.getResolutionVariants();
|
||||
int size = imageList.size();
|
||||
BufferedImage lowResImage;
|
||||
BufferedImage highResImage;
|
||||
|
||||
if (!isHiDPI) {
|
||||
// Check if output is MultiResolutionImage with one variant
|
||||
if (size != 1) {
|
||||
throw new RuntimeException(" Invalid variant size");
|
||||
}
|
||||
|
||||
lowResImage = (BufferedImage) imageList.get(0);
|
||||
System.out.println(frame.getBounds());
|
||||
System.out.println(lowResImage.getWidth() + " " + lowResImage.getHeight());
|
||||
if (frame.getWidth() != lowResImage.getWidth()
|
||||
|| frame.getHeight() != lowResImage.getHeight()) {
|
||||
throw new RuntimeException(" Invalid Image size");
|
||||
throw new RuntimeException(" Invalid Image size");
|
||||
}
|
||||
|
||||
} else {
|
||||
// Check if output contains two variants.
|
||||
if (size != 2) {
|
||||
throw new RuntimeException(" Invalid variant size");
|
||||
}
|
||||
|
||||
// Check if hight resolution image size is scale times low resolution image.
|
||||
lowResImage = (BufferedImage) imageList.get(0);
|
||||
highResImage = (BufferedImage) imageList.get(1);
|
||||
|
||||
int lW = (int) lowResImage.getWidth();
|
||||
int lH = (int) lowResImage.getHeight();
|
||||
int hW = (int) highResImage.getWidth();
|
||||
int hH = (int) highResImage.getHeight();
|
||||
|
||||
if (hW != (tx.getScaleX() * lW) || hH != (tx.getScaleY() * lH)) {
|
||||
throw new RuntimeException(" Invalid Resolution Variants");
|
||||
}
|
||||
|
||||
// Check if both image colors are same at some location.
|
||||
if (lowResImage.getRGB(lW / 4, lH / 4)
|
||||
!= highResImage.getRGB(hW / 4, hH / 4)) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
|
||||
if (lowResImage.getRGB(3 * lW / 4, lH / 4)
|
||||
!= highResImage.getRGB(3 * hW / 4, hH / 4)) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
|
||||
if (lowResImage.getRGB(lW / 4, 3 * lH / 4)
|
||||
!= highResImage.getRGB(hW / 4, 3 * hH / 4)) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
|
||||
if (lowResImage.getRGB(3 * lW / 4, 3 * lH / 4)
|
||||
!= highResImage.getRGB(3 * hW / 4, 3 * hH / 4)) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Check if output contains two variants.
|
||||
if (size != 2) {
|
||||
throw new RuntimeException(" Invalid variant size");
|
||||
}
|
||||
|
||||
// Check if hight resolution image size is scale times low resolution image.
|
||||
lowResImage = (BufferedImage) imageList.get(0);
|
||||
highResImage = (BufferedImage) imageList.get(1);
|
||||
|
||||
int lW = (int) lowResImage.getWidth();
|
||||
int lH = (int) lowResImage.getHeight();
|
||||
int hW = (int) highResImage.getWidth();
|
||||
int hH = (int) highResImage.getHeight();
|
||||
|
||||
if ( hW != (tx.getScaleX() * lW) || hH != (tx.getScaleY() * lH)) {
|
||||
throw new RuntimeException(" Invalid Resolution Variants");
|
||||
}
|
||||
|
||||
// Check if both image colors are same at some location.
|
||||
if (lowResImage.getRGB(lW / 4, lH / 4)
|
||||
!= highResImage.getRGB(hW / 4, hH / 4)) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
|
||||
if (lowResImage.getRGB(3 * lW / 4, lH / 4)
|
||||
!= highResImage.getRGB(3 * hW / 4, hH / 4)) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
|
||||
if (lowResImage.getRGB(lW / 4, 3 * lH / 4)
|
||||
!= highResImage.getRGB(hW / 4, 3 * hH / 4)) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
|
||||
if (lowResImage.getRGB(3 * lW / 4, 3 * lH / 4)
|
||||
!= highResImage.getRGB(3 * hW / 4, 3 * hH / 4)) {
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
}
|
||||
|
||||
} finally {
|
||||
frame.dispose();
|
||||
}
|
||||
|
||||
frame.dispose();
|
||||
}
|
||||
|
||||
|
||||
private static final int OFFSET = 5;
|
||||
static void checkRectColor(Rectangle rect, Color expectedColor) {
|
||||
System.out.println("Checking rectangle " + rect + " to have color " + expectedColor);
|
||||
final Point[] pointsToCheck = new Point[] {
|
||||
new Point(rect.x + OFFSET, rect.y + OFFSET), // top left corner
|
||||
new Point(rect.x + rect.width - OFFSET, rect.y + OFFSET), // top right corner
|
||||
new Point(rect.x + rect.width / 2, rect.y + rect.height / 2), // center
|
||||
new Point(rect.x + OFFSET, rect.y + rect.height - OFFSET), // bottom left corner
|
||||
new Point(rect.x + rect.width - OFFSET, rect.y + rect.height - OFFSET) // bottom right corner
|
||||
};
|
||||
|
||||
for (final var point : pointsToCheck) {
|
||||
System.out.print("Checking color at " + point + " to be equal to " + expectedColor);
|
||||
final Color actualColor = robot.getPixelColor(point.x, point.y);
|
||||
if (!actualColor.equals(expectedColor)) {
|
||||
System.out.println("... Mismatch: found " + actualColor + " instead");
|
||||
throw new RuntimeException("Wrong image color!");
|
||||
} else {
|
||||
System.out.println("... OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
183
test/jdk/java/awt/a11y/AccessibleActionsTest.java
Normal file
183
test/jdk/java/awt/a11y/AccessibleActionsTest.java
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 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
|
||||
* @bug 8281338
|
||||
* @summary Test for an element that has more than one Accessibility Action
|
||||
* @author Artem.Semenov@jetbrains.com
|
||||
* @run main/manual AccessibleActionsTest
|
||||
* @requires (os.family == "mac")
|
||||
*/
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleAction;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreeModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Hashtable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class AccessibleActionsTest extends AccessibleComponentTest {
|
||||
|
||||
@Override
|
||||
public CountDownLatch createCountDownLatch() {
|
||||
return new CountDownLatch(1);
|
||||
}
|
||||
|
||||
void createTest() {
|
||||
INSTRUCTIONS = "INSTRUCTIONS:\n"
|
||||
+ "Check a11y actions.\n\n"
|
||||
+ "Turn screen reader on, and Tab to the label.\n\n"
|
||||
+ "Perform the VO action \"Press\" (VO+space)\n"
|
||||
+ "Perform the VO action \"Show menu\" (VO+m)\n\n"
|
||||
+ "If after the first action the text of the label has changed, and after the second action the menu appears tab further and press PASS, otherwise press FAIL.";
|
||||
|
||||
exceptionString = "AccessibleAction test failed!";
|
||||
super.createUI(new AccessibleActionsTestFrame(), "AccessibleActionsTest");
|
||||
}
|
||||
|
||||
void createTree() {
|
||||
INSTRUCTIONS = "INSTRUCTIONS:\n"
|
||||
+ "Check a11y actions.\n\n"
|
||||
+ "Turn screen reader on, and Tab to the label.\n\n"
|
||||
+ "Perform the VO action \"Press\" (VO+space) on tree nodes\n\n"
|
||||
+ "If after press the tree node is expanded tab further and press PASS, otherwise press FAIL.";
|
||||
|
||||
String root = "Root";
|
||||
String[] nodes = new String[] {"One node", "Two node"};
|
||||
String[][] leafs = new String[][]{{"leaf 1.1", "leaf 1.2", "leaf 1.3", "leaf 1.4"},
|
||||
{"leaf 2.1", "leaf 2.2", "leaf 2.3", "leaf 2.4"}};
|
||||
|
||||
Hashtable<String, String[]> data = new Hashtable<String, String[]>();
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
data.put(nodes[i], leafs[i]);
|
||||
}
|
||||
|
||||
JTree tree = new JTree(data);
|
||||
tree.setRootVisible(true);
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new FlowLayout());
|
||||
JScrollPane scrollPane = new JScrollPane(tree);
|
||||
panel.add(scrollPane);
|
||||
panel.setFocusable(false);
|
||||
|
||||
exceptionString = "AccessibleAction test failed!";
|
||||
super.createUI(panel, "AccessibleActionsTest");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AccessibleActionsTest test = new AccessibleActionsTest();
|
||||
|
||||
countDownLatch = test.createCountDownLatch();
|
||||
SwingUtilities.invokeLater(test::createTest);
|
||||
countDownLatch.await();
|
||||
|
||||
if (!testResult) {
|
||||
throw new RuntimeException(a11yTest.exceptionString);
|
||||
}
|
||||
|
||||
countDownLatch = test.createCountDownLatch();
|
||||
SwingUtilities.invokeLater(test::createTree);
|
||||
countDownLatch.await();
|
||||
|
||||
if (!testResult) {
|
||||
throw new RuntimeException(a11yTest.exceptionString);
|
||||
}
|
||||
}
|
||||
|
||||
private class AccessibleActionsTestFrame extends JPanel {
|
||||
|
||||
public AccessibleActionsTestFrame() {
|
||||
MyLabel label = new MyLabel("I'm waiting for the push");
|
||||
label.setComponentPopupMenu(createPopup());
|
||||
label.setFocusable(true);
|
||||
add(label);
|
||||
setLayout(new FlowLayout());
|
||||
}
|
||||
|
||||
private static class MyLabel extends JLabel {
|
||||
public MyLabel(String text) {
|
||||
super(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleContext getAccessibleContext() {
|
||||
if (accessibleContext == null) {
|
||||
accessibleContext = new MyAccessibleJLabel();
|
||||
}
|
||||
return accessibleContext;
|
||||
}
|
||||
|
||||
private class MyAccessibleJLabel extends JLabel.AccessibleJLabel {
|
||||
@Override
|
||||
public AccessibleAction getAccessibleAction() {
|
||||
return new AccessibleAction() {
|
||||
@Override
|
||||
public int getAccessibleActionCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessibleActionDescription(int i) {
|
||||
if (i == 0) {
|
||||
return AccessibleAction.CLICK;
|
||||
}
|
||||
return AccessibleAction.TOGGLE_POPUP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doAccessibleAction(int i) {
|
||||
if (i == 0) {
|
||||
changeText(MyLabel.this, "label is pressed");
|
||||
return true;
|
||||
}
|
||||
JPopupMenu popup = createPopup();
|
||||
popup.show(MyLabel.this, 0, 0);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static JPopupMenu createPopup() {
|
||||
JPopupMenu popup = new JPopupMenu("MENU");
|
||||
popup.add("One");
|
||||
popup.add("Two");
|
||||
popup.add("Three");
|
||||
return popup;
|
||||
}
|
||||
|
||||
private static void changeText(JLabel label, String text) {
|
||||
label.setText(text);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,9 @@ import java.awt.geom.*;
|
||||
import java.awt.image.*;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
public class GradientPaints extends Canvas {
|
||||
|
||||
@@ -68,8 +70,8 @@ public class GradientPaints extends Canvas {
|
||||
(int)(TESTW * TESTH * 0.18);
|
||||
private static final int ALLOWED_MISMATCHES_RADIAL =
|
||||
(int)(TESTW * TESTH * 0.45);
|
||||
private static final int ALLOWED_RENDER_ATTEMPTS = 5;
|
||||
|
||||
private static boolean done;
|
||||
private static boolean verbose;
|
||||
|
||||
private static final Color[] COLORS = {
|
||||
@@ -83,8 +85,8 @@ public class GradientPaints extends Canvas {
|
||||
new Color(128, 128, 128),
|
||||
};
|
||||
|
||||
private static enum PaintType {BASIC, LINEAR, RADIAL};
|
||||
private static enum XformType {IDENTITY, TRANSLATE, SCALE, SHEAR, ROTATE};
|
||||
private enum PaintType {BASIC, LINEAR, RADIAL}
|
||||
private enum XformType {IDENTITY, TRANSLATE, SCALE, SHEAR, ROTATE}
|
||||
private static final int[] numStopsArray = {2, 4, 7};
|
||||
private static final Object[] hints = {
|
||||
RenderingHints.VALUE_ANTIALIAS_OFF,
|
||||
@@ -92,35 +94,14 @@ public class GradientPaints extends Canvas {
|
||||
};
|
||||
|
||||
public void paint(Graphics g) {
|
||||
synchronized (this) {
|
||||
if (!done) {
|
||||
done = true;
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void testOne(BufferedImage refImg, VolatileImage testImg) {
|
||||
Graphics2D gref = refImg.createGraphics();
|
||||
Graphics2D gtest = testImg.createGraphics();
|
||||
Paint paint =
|
||||
makePaint(PaintType.RADIAL, CycleMethod.REPEAT,
|
||||
ColorSpaceType.SRGB, XformType.IDENTITY, 7);
|
||||
Object aahint = hints[0];
|
||||
renderTest(gref, paint, aahint);
|
||||
renderTest(gtest, paint, aahint);
|
||||
Toolkit.getDefaultToolkit().sync();
|
||||
compareImages(refImg, testImg.getSnapshot(),
|
||||
TOLERANCE, 0, "");
|
||||
gref.dispose();
|
||||
gtest.dispose();
|
||||
painted.countDown();
|
||||
}
|
||||
|
||||
private void testAll(Graphics gscreen,
|
||||
BufferedImage refImg, VolatileImage testImg)
|
||||
BufferedImage refImg, VolatileImage testImg, GraphicsConfiguration gc)
|
||||
{
|
||||
Graphics2D gref = refImg.createGraphics();
|
||||
Graphics2D gtest = testImg.createGraphics();
|
||||
testImg.validate(gc);
|
||||
for (PaintType paintType : PaintType.values()) {
|
||||
for (CycleMethod cycleMethod : CycleMethod.values()) {
|
||||
for (ColorSpaceType colorSpace : ColorSpaceType.values()) {
|
||||
@@ -138,16 +119,32 @@ public class GradientPaints extends Canvas {
|
||||
" numStops=" + numStops +
|
||||
" aa=" + aahint;
|
||||
renderTest(gref, paint, aahint);
|
||||
renderTest(gtest, paint, aahint);
|
||||
gscreen.drawImage(testImg, 0, 0, null);
|
||||
Toolkit.getDefaultToolkit().sync();
|
||||
int allowedMismatches =
|
||||
paintType == PaintType.RADIAL ?
|
||||
ALLOWED_MISMATCHES_RADIAL :
|
||||
ALLOWED_MISMATCHES_LINEAR;
|
||||
compareImages(refImg, testImg.getSnapshot(),
|
||||
TOLERANCE, allowedMismatches,
|
||||
msg);
|
||||
int allowedMismatches = paintType == PaintType.RADIAL ?
|
||||
ALLOWED_MISMATCHES_RADIAL : ALLOWED_MISMATCHES_LINEAR;
|
||||
int attempt = 0;
|
||||
while (true) {
|
||||
Graphics2D gtest = testImg.createGraphics();
|
||||
renderTest(gtest, paint, aahint);
|
||||
gscreen.drawImage(testImg, 0, 0, null);
|
||||
Toolkit.getDefaultToolkit().sync();
|
||||
gtest.dispose();
|
||||
BufferedImage snapshot = testImg.getSnapshot();
|
||||
if (testImg.contentsLost() &&
|
||||
testImg.validate(gc) != VolatileImage.IMAGE_OK)
|
||||
{
|
||||
if (attempt++ >= ALLOWED_RENDER_ATTEMPTS) {
|
||||
throw new RuntimeException("Cannot render to VI");
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
compareImages(refImg, snapshot, allowedMismatches, msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,7 +152,6 @@ public class GradientPaints extends Canvas {
|
||||
}
|
||||
}
|
||||
gref.dispose();
|
||||
gtest.dispose();
|
||||
}
|
||||
|
||||
private Paint makePaint(PaintType paintType,
|
||||
@@ -172,7 +168,6 @@ public class GradientPaints extends Canvas {
|
||||
int focusX = ctrX + 20;
|
||||
int focusY = ctrY + 20;
|
||||
float radius = 100.0f;
|
||||
Paint paint;
|
||||
AffineTransform transform;
|
||||
|
||||
Color[] colors = Arrays.copyOf(COLORS, numStops);
|
||||
@@ -181,57 +176,30 @@ public class GradientPaints extends Canvas {
|
||||
fractions[i] = ((float)i) / (fractions.length-1);
|
||||
}
|
||||
|
||||
switch (xformType) {
|
||||
default:
|
||||
case IDENTITY:
|
||||
transform = new AffineTransform();
|
||||
break;
|
||||
case TRANSLATE:
|
||||
transform = AffineTransform.getTranslateInstance(2, 2);
|
||||
break;
|
||||
case SCALE:
|
||||
transform = AffineTransform.getScaleInstance(1.2, 1.4);
|
||||
break;
|
||||
case SHEAR:
|
||||
transform = AffineTransform.getShearInstance(0.1, 0.1);
|
||||
break;
|
||||
case ROTATE:
|
||||
transform = AffineTransform.getRotateInstance(Math.PI / 4,
|
||||
getWidth()/2,
|
||||
getHeight()/2);
|
||||
break;
|
||||
}
|
||||
transform = switch (xformType) {
|
||||
case IDENTITY -> new AffineTransform();
|
||||
case TRANSLATE -> AffineTransform.getTranslateInstance(2, 2);
|
||||
case SCALE -> AffineTransform.getScaleInstance(1.2, 1.4);
|
||||
case SHEAR -> AffineTransform.getShearInstance(0.1, 0.1);
|
||||
case ROTATE -> AffineTransform.getRotateInstance(Math.PI / 4,
|
||||
getWidth() >> 1, getHeight() >> 1);
|
||||
};
|
||||
|
||||
switch (paintType) {
|
||||
case BASIC:
|
||||
boolean cyclic = (cycleMethod != CycleMethod.NO_CYCLE);
|
||||
paint =
|
||||
new GradientPaint(startX, startY, Color.RED,
|
||||
endX, endY, Color.BLUE, cyclic);
|
||||
break;
|
||||
|
||||
default:
|
||||
case LINEAR:
|
||||
paint =
|
||||
new LinearGradientPaint(new Point2D.Float(startX, startY),
|
||||
new Point2D.Float(endX, endY),
|
||||
fractions, colors,
|
||||
cycleMethod, colorSpace,
|
||||
transform);
|
||||
break;
|
||||
|
||||
case RADIAL:
|
||||
paint =
|
||||
new RadialGradientPaint(new Point2D.Float(ctrX, ctrY),
|
||||
radius,
|
||||
new Point2D.Float(focusX, focusY),
|
||||
fractions, colors,
|
||||
cycleMethod, colorSpace,
|
||||
transform);
|
||||
break;
|
||||
}
|
||||
|
||||
return paint;
|
||||
return switch (paintType) {
|
||||
case BASIC -> new GradientPaint(startX, startY, Color.RED,
|
||||
endX, endY, Color.BLUE, (cycleMethod != CycleMethod.NO_CYCLE));
|
||||
case LINEAR -> new LinearGradientPaint(new Point2D.Float(startX, startY),
|
||||
new Point2D.Float(endX, endY),
|
||||
fractions, colors,
|
||||
cycleMethod, colorSpace,
|
||||
transform);
|
||||
case RADIAL -> new RadialGradientPaint(new Point2D.Float(ctrX, ctrY),
|
||||
radius,
|
||||
new Point2D.Float(focusX, focusY),
|
||||
fractions, colors,
|
||||
cycleMethod, colorSpace,
|
||||
transform);
|
||||
};
|
||||
}
|
||||
|
||||
private void renderTest(Graphics2D g2d, Paint p, Object aahint) {
|
||||
@@ -248,7 +216,7 @@ public class GradientPaints extends Canvas {
|
||||
|
||||
private static void compareImages(BufferedImage refImg,
|
||||
BufferedImage testImg,
|
||||
int tolerance, int allowedMismatches,
|
||||
int allowedMismatches,
|
||||
String msg)
|
||||
{
|
||||
int numMismatches = 0;
|
||||
@@ -261,7 +229,7 @@ public class GradientPaints extends Canvas {
|
||||
for (int x = x1; x < x2; x++) {
|
||||
Color expected = new Color(refImg.getRGB(x, y));
|
||||
Color actual = new Color(testImg.getRGB(x, y));
|
||||
if (!isSameColor(expected, actual, tolerance)) {
|
||||
if (!isSameColor(expected, actual)) {
|
||||
numMismatches++;
|
||||
}
|
||||
}
|
||||
@@ -277,6 +245,7 @@ public class GradientPaints extends Canvas {
|
||||
ImageIO.write(testImg, "png",
|
||||
new File("GradientPaints.cap.png"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (!verbose) {
|
||||
System.err.println(msg);
|
||||
@@ -285,53 +254,49 @@ public class GradientPaints extends Canvas {
|
||||
numMismatches +
|
||||
") exceeds limit (" +
|
||||
allowedMismatches +
|
||||
") with tolerance=" +
|
||||
tolerance);
|
||||
") with tolerance=" + TOLERANCE);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSameColor(Color c1, Color c2, int e) {
|
||||
private static boolean isSameColor(Color c1, Color c2) {
|
||||
int r1 = c1.getRed();
|
||||
int g1 = c1.getGreen();
|
||||
int b1 = c1.getBlue();
|
||||
int r2 = c2.getRed();
|
||||
int g2 = c2.getGreen();
|
||||
int b2 = c2.getBlue();
|
||||
int rmin = Math.max(r2-e, 0);
|
||||
int gmin = Math.max(g2-e, 0);
|
||||
int bmin = Math.max(b2-e, 0);
|
||||
int rmax = Math.min(r2+e, 255);
|
||||
int gmax = Math.min(g2+e, 255);
|
||||
int bmax = Math.min(b2+e, 255);
|
||||
if (r1 >= rmin && r1 <= rmax &&
|
||||
g1 >= gmin && g1 <= gmax &&
|
||||
b1 >= bmin && b1 <= bmax)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
int rmin = Math.max(r2- TOLERANCE, 0);
|
||||
int gmin = Math.max(g2- TOLERANCE, 0);
|
||||
int bmin = Math.max(b2- TOLERANCE, 0);
|
||||
int rmax = Math.min(r2+ TOLERANCE, 255);
|
||||
int gmax = Math.min(g2+ TOLERANCE, 255);
|
||||
int bmax = Math.min(b2+ TOLERANCE, 255);
|
||||
return r1 >= rmin && r1 <= rmax &&
|
||||
g1 >= gmin && g1 <= gmax &&
|
||||
b1 >= bmin && b1 <= bmax;
|
||||
}
|
||||
|
||||
static CountDownLatch painted = new CountDownLatch(1);
|
||||
static Frame frame = null;
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 1 && args[0].equals("-verbose")) {
|
||||
verbose = true;
|
||||
}
|
||||
|
||||
GradientPaints test = new GradientPaints();
|
||||
Frame frame = new Frame();
|
||||
frame.add(test);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
frame = new Frame();
|
||||
frame.add(test);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
});
|
||||
|
||||
// Wait until the component's been painted
|
||||
synchronized (test) {
|
||||
while (!done) {
|
||||
try {
|
||||
test.wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Failed: Interrupted");
|
||||
}
|
||||
}
|
||||
try {
|
||||
painted.await();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Failed: Interrupted");
|
||||
}
|
||||
|
||||
GraphicsConfiguration gc = frame.getGraphicsConfiguration();
|
||||
@@ -345,10 +310,9 @@ public class GradientPaints extends Canvas {
|
||||
BufferedImage refImg =
|
||||
new BufferedImage(TESTW, TESTH, BufferedImage.TYPE_INT_RGB);
|
||||
VolatileImage testImg = frame.createVolatileImage(TESTW, TESTH);
|
||||
testImg.validate(gc);
|
||||
|
||||
try {
|
||||
test.testAll(test.getGraphics(), refImg, testImg);
|
||||
test.testAll(test.getGraphics(), refImg, testImg, gc);
|
||||
} finally {
|
||||
frame.dispose();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @requires (os.family == "linux")
|
||||
* @requires !display.XWayland
|
||||
* @key headful
|
||||
* @bug 8214112
|
||||
* @summary Tests JPasswordField selected Text background color
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @requires (os.family == "linux")
|
||||
* @requires !display.XWayland
|
||||
* @key headful
|
||||
* @bug 8218472
|
||||
* @summary Tests JProgressBar highlight color
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @requires (os.family == "linux")
|
||||
* @requires !display.XWayland
|
||||
* @key headful
|
||||
* @bug 8218469
|
||||
* @summary Tests JSlider is rendered properly with gtk3
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @requires (os.family == "linux")
|
||||
* @requires !display.XWayland
|
||||
* @key headful
|
||||
* @bug 8214112
|
||||
* @summary Tests JSpinner selected Text background color
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @requires (os.family == "linux")
|
||||
* @requires !display.XWayland
|
||||
* @key headful
|
||||
* @bug 8218479
|
||||
* @summary Tests JTextPane background color
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @requires (os.family == "linux")
|
||||
* @requires !display.XWayland
|
||||
* @key headful
|
||||
* @bug 8214253
|
||||
* @summary Tests JToolTip background color
|
||||
|
||||
106
test/jdk/jb/build/CheckJBRModules.java
Normal file
106
test/jdk/jb/build/CheckJBRModules.java
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2022 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 jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @requires !vm.graal.enabled
|
||||
* @summary Verifies the list of available modules
|
||||
* @library /test/lib
|
||||
* @run main CheckJBRModules
|
||||
*/
|
||||
public class CheckJBRModules {
|
||||
static final String moduleNames[] = {
|
||||
"java.base",
|
||||
"java.compiler",
|
||||
"java.datatransfer",
|
||||
"java.desktop",
|
||||
"java.instrument",
|
||||
"java.logging",
|
||||
"java.management",
|
||||
"java.management.rmi",
|
||||
"java.naming",
|
||||
"java.net.http",
|
||||
"java.prefs",
|
||||
"java.rmi",
|
||||
"java.scripting",
|
||||
"java.se",
|
||||
"java.security.jgss",
|
||||
"java.security.sasl",
|
||||
"java.smartcardio",
|
||||
"java.sql",
|
||||
"java.sql.rowset",
|
||||
"java.transaction.xa",
|
||||
"java.xml",
|
||||
"java.xml.crypto",
|
||||
"jdk.accessibility",
|
||||
"jdk.attach",
|
||||
"jdk.charsets",
|
||||
"jdk.compiler",
|
||||
"jdk.crypto.cryptoki",
|
||||
"jdk.crypto.ec",
|
||||
"jdk.dynalink",
|
||||
"jdk.httpserver",
|
||||
"jdk.internal.ed",
|
||||
"jdk.internal.le",
|
||||
"jdk.internal.vm.ci",
|
||||
"jdk.javadoc",
|
||||
"jdk.jdi",
|
||||
"jdk.jdwp.agent",
|
||||
"jdk.jfr",
|
||||
"jdk.jsobject",
|
||||
"jdk.localedata",
|
||||
"jdk.management",
|
||||
"jdk.management.agent",
|
||||
"jdk.management.jfr",
|
||||
"jdk.naming.dns",
|
||||
"jdk.naming.rmi",
|
||||
"jdk.net",
|
||||
"jdk.sctp",
|
||||
"jdk.security.auth",
|
||||
"jdk.security.jgss",
|
||||
"jdk.unsupported",
|
||||
"jdk.unsupported.desktop",
|
||||
"jdk.xml.dom",
|
||||
"jdk.zipfs",
|
||||
"jdk.hotspot.agent",
|
||||
"jdk.jcmd" };
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
final OutputAnalyzer oa = exec("--list-modules").shouldHaveExitValue(0);
|
||||
for(String moduleName : moduleNames) {
|
||||
oa.shouldContain(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* java args... returning the OutputAnalyzer to analyzer the output
|
||||
*/
|
||||
private static OutputAnalyzer exec(String... args) throws Exception {
|
||||
return ProcessTools.executeTestJava(args)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out);
|
||||
}
|
||||
}
|
||||
53
test/jdk/jb/build/CheckJBRModulesWindows.java
Normal file
53
test/jdk/jb/build/CheckJBRModulesWindows.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2022 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 jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @requires !vm.graal.enabled
|
||||
* @requires (os.family == "windows")
|
||||
* @summary Verifies the list of available modules specific to Windows
|
||||
* @library /test/lib
|
||||
* @run main CheckJBRModulesWindows
|
||||
*/
|
||||
public class CheckJBRModulesWindows {
|
||||
static final String moduleNames[] = { "jdk.crypto.mscapi" };
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
final OutputAnalyzer oa = exec("--list-modules").shouldHaveExitValue(0);
|
||||
for(String moduleName : moduleNames) {
|
||||
oa.shouldContain(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* java args... returning the OutputAnalyzer to analyzer the output
|
||||
*/
|
||||
private static OutputAnalyzer exec(String... args) throws Exception {
|
||||
return ProcessTools.executeTestJava(args)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out);
|
||||
}
|
||||
}
|
||||
@@ -35,13 +35,13 @@ public class ProxyInfoResolvingTest {
|
||||
JBRApi.ModuleRegistry r = init();
|
||||
// No mapping defined -> null
|
||||
requireNull(getProxy(ProxyInfoResolvingTest.class));
|
||||
// Invalid JBR-side target class -> error
|
||||
// Invalid JBR-side target class -> null
|
||||
r.proxy(InterfaceWithoutImplementation.class.getName(), "absentImpl");
|
||||
mustFail(() -> getProxy(InterfaceWithoutImplementation.class), RuntimeException.class, ClassNotFoundException.class);
|
||||
// Invalid JBR-side target static method mapping -> error
|
||||
requireNull(getProxy(InterfaceWithoutImplementation.class));
|
||||
// Invalid JBR-side target static method mapping -> null
|
||||
r.service(ServiceWithoutImplementation.class.getName(), null)
|
||||
.withStatic("someMethod", "NoClass");
|
||||
mustFail(() -> getProxy(ServiceWithoutImplementation.class), RuntimeException.class, ClassNotFoundException.class);
|
||||
requireNull(getProxy(ServiceWithoutImplementation.class));
|
||||
// Service without target class or static method mapping -> null
|
||||
r.service(EmptyService.class.getName(), null);
|
||||
requireNull(getProxy(EmptyService.class));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -9,11 +9,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import sun.awt.InvokeOnToolkitHelper;
|
||||
import sun.lwawt.macosx.CThreading;
|
||||
import sun.lwawt.macosx.LWCToolkit;
|
||||
|
||||
import javax.swing.*;
|
||||
import sun.awt.AWTThreading;
|
||||
|
||||
/*
|
||||
* @test
|
||||
@@ -50,6 +48,7 @@ public class AWTThreadingTest {
|
||||
|
||||
static void runGui() {
|
||||
frame = new JFrame("frame");
|
||||
frame.getContentPane().setBackground(Color.green);
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setSize(200, 200);
|
||||
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
@@ -88,7 +87,7 @@ public class AWTThreadingTest {
|
||||
EventQueue.invokeLater(() -> {
|
||||
passed.set(false);
|
||||
|
||||
Boolean success = InvokeOnToolkitHelper.invokeAndBlock(() -> {
|
||||
Boolean success = AWTThreading.executeWaitToolkit(() -> {
|
||||
try {
|
||||
return CThreading.executeOnAppKit(() -> Boolean.TRUE);
|
||||
} catch (Throwable e) {
|
||||
|
||||
229
test/jdk/jb/java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java
Normal file
229
test/jdk/jb/java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java
Normal file
@@ -0,0 +1,229 @@
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import java.awt.event.InvocationEvent;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.*;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AWTThreading;
|
||||
import sun.lwawt.macosx.CThreading;
|
||||
import sun.lwawt.macosx.LWCToolkit;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Tests different scenarios for LWCToolkit.invokeAndWait().
|
||||
* @requires (os.family == "mac")
|
||||
* @modules java.desktop/sun.lwawt.macosx java.desktop/sun.awt
|
||||
* @run main LWCToolkitInvokeAndWaitTest
|
||||
* @run main/othervm -DAWTThreading.level.FINER=true LWCToolkitInvokeAndWaitTest
|
||||
* @author Anton Tarasov
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public class LWCToolkitInvokeAndWaitTest {
|
||||
// This property is used in {CAccessibility}
|
||||
private static final int INVOKE_TIMEOUT_SECONDS = Integer.getInteger("sun.lwawt.macosx.CAccessibility.invokeTimeoutSeconds", 1);
|
||||
|
||||
static TestLogHandler LOG_HANDLER = new TestLogHandler();
|
||||
static volatile CompletableFuture<Boolean> FUTURE;
|
||||
static volatile CountDownLatch EDT_FAST_FREE_LATCH;
|
||||
static volatile JFrame FRAME;
|
||||
static volatile Thread MAIN_THREAD;
|
||||
static int TEST_COUNTER;
|
||||
|
||||
static final Runnable CONSUME_DISPATCHING = () -> FUTURE.completeExceptionally(new Throwable("Unexpected dispatching!"));
|
||||
|
||||
static {
|
||||
AWTThreading.setAWTThreadingFactory(edt -> new AWTThreading(edt) {
|
||||
@Override
|
||||
public CompletableFuture<Void> onEventDispatchThreadFree(Runnable runnable) {
|
||||
if (EDT_FAST_FREE_LATCH != null) {
|
||||
// 1. wait for the invocation event to be dispatched
|
||||
// 2. wait for EDT to become free
|
||||
trycatch(() -> EDT_FAST_FREE_LATCH.await());
|
||||
|
||||
EDT_FAST_FREE_LATCH = null;
|
||||
}
|
||||
// if EDT is free the runnable should be called immediately
|
||||
return super.onEventDispatchThreadFree(runnable);
|
||||
}
|
||||
@Override
|
||||
public void notifyEventDispatchThreadFree() {
|
||||
if (EDT_FAST_FREE_LATCH != null &&
|
||||
// if the invocation event is dispatched by now
|
||||
EDT_FAST_FREE_LATCH.getCount() == 1)
|
||||
{
|
||||
EDT_FAST_FREE_LATCH.countDown();
|
||||
}
|
||||
super.notifyEventDispatchThreadFree();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
MAIN_THREAD = Thread.currentThread();
|
||||
|
||||
trycatch(() -> {
|
||||
Logger log = LogManager.getLogManager().getLogger(AWTThreading.class.getName());
|
||||
log.setUseParentHandlers(false);
|
||||
log.addHandler(LOG_HANDLER);
|
||||
if (Boolean.getBoolean("AWTThreading.level.FINER")) {
|
||||
log.setLevel(Level.FINER);
|
||||
}
|
||||
});
|
||||
|
||||
Consumer<InvocationEvent> noop = e -> {};
|
||||
|
||||
try {
|
||||
trycatch(() -> EventQueue.invokeAndWait(LWCToolkitInvokeAndWaitTest::runGui));
|
||||
|
||||
test("InvocationEvent is normally dispatched",
|
||||
"",
|
||||
noop,
|
||||
() -> System.out.println("I'm dispatched"));
|
||||
|
||||
test("InvocationEvent is lost",
|
||||
"lost",
|
||||
noop,
|
||||
CONSUME_DISPATCHING);
|
||||
|
||||
EDT_FAST_FREE_LATCH = new CountDownLatch(2);
|
||||
test("InvocationEvent is lost (EDT becomes fast free)",
|
||||
"lost",
|
||||
// notify the invocationEvent has been dispatched
|
||||
invocationEvent -> EDT_FAST_FREE_LATCH.countDown(),
|
||||
CONSUME_DISPATCHING);
|
||||
|
||||
test("InvocationEvent is disposed",
|
||||
"disposed",
|
||||
invocationEvent -> AWTAccessor.getInvocationEventAccessor().dispose(invocationEvent),
|
||||
CONSUME_DISPATCHING);
|
||||
|
||||
test("InvocationEvent is timed out (delayed before dispatching)",
|
||||
"timed out",
|
||||
invocationEvent -> sleep(INVOKE_TIMEOUT_SECONDS * 4),
|
||||
CONSUME_DISPATCHING);
|
||||
|
||||
test("InvocationEvent is timed out (delayed during dispatching)",
|
||||
"timed out",
|
||||
noop,
|
||||
() -> sleep(INVOKE_TIMEOUT_SECONDS * 4));
|
||||
|
||||
} finally {
|
||||
FRAME.dispose();
|
||||
}
|
||||
System.out.println("Test PASSED");
|
||||
}
|
||||
|
||||
static void runGui() {
|
||||
FRAME = new JFrame(LWCToolkitInvokeAndWaitTest.class.getSimpleName());
|
||||
FRAME.getContentPane().setBackground(Color.green);
|
||||
FRAME.setLocationRelativeTo(null);
|
||||
FRAME.setSize(200, 200);
|
||||
FRAME.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
FRAME.setVisible(true);
|
||||
}
|
||||
|
||||
static void test(String testCaption,
|
||||
String expectedInLog,
|
||||
Consumer<InvocationEvent> onBeforeDispatching,
|
||||
Runnable onDispatching)
|
||||
{
|
||||
System.out.println("\n(" + (++TEST_COUNTER) + ") TEST: " + testCaption);
|
||||
|
||||
FUTURE = new CompletableFuture<>();
|
||||
FUTURE.whenComplete((r, ex) -> Optional.of(ex).ifPresent(Throwable::printStackTrace));
|
||||
|
||||
EventQueue.invokeLater(() -> subTest(onBeforeDispatching, onDispatching));
|
||||
|
||||
trycatch(() -> {
|
||||
if (!FUTURE.get(INVOKE_TIMEOUT_SECONDS * 2L, TimeUnit.SECONDS)) {
|
||||
throw new RuntimeException("Test FAILED! (negative result)");
|
||||
}
|
||||
});
|
||||
|
||||
// let AppKit and EDT print all the logging
|
||||
var latch = new CountDownLatch(1);
|
||||
CThreading.executeOnAppKit(latch::countDown);
|
||||
trycatch(latch::await);
|
||||
trycatch(() -> EventQueue.invokeAndWait(() -> {}));
|
||||
|
||||
if (!LOG_HANDLER.testContains(expectedInLog)) {
|
||||
throw new RuntimeException("Test FAILED! (not found in the log: \"" + expectedInLog + "\")");
|
||||
}
|
||||
|
||||
System.out.println("(" + TEST_COUNTER + ") SUCCEEDED\n");
|
||||
}
|
||||
|
||||
static void subTest(Consumer<InvocationEvent> onBeforeDispatching, Runnable onDispatching) {
|
||||
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new EventQueue() {
|
||||
@Override
|
||||
protected void dispatchEvent(AWTEvent event) {
|
||||
//
|
||||
// Intercept the invocation posted from Appkit.
|
||||
//
|
||||
if (event instanceof AWTThreading.TrackedInvocationEvent) {
|
||||
System.out.println("Before dispatching: " + event);
|
||||
onBeforeDispatching.accept((InvocationEvent)event);
|
||||
|
||||
if (onDispatching == CONSUME_DISPATCHING) {
|
||||
System.out.println("Consuming: " + event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.dispatchEvent(event);
|
||||
}
|
||||
});
|
||||
CThreading.executeOnAppKit(() -> trycatch(() -> {
|
||||
//
|
||||
// Post an invocation from AppKit.
|
||||
//
|
||||
LWCToolkit.invokeAndWait(onDispatching, FRAME, false, INVOKE_TIMEOUT_SECONDS);
|
||||
FUTURE.complete(true);
|
||||
}));
|
||||
}
|
||||
|
||||
static void sleep(int seconds) {
|
||||
trycatch(() -> Thread.sleep(seconds * 1000L));
|
||||
}
|
||||
|
||||
static void trycatch(ThrowableRunnable runnable) {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Exception e) {
|
||||
if (Thread.currentThread() == MAIN_THREAD) {
|
||||
throw new RuntimeException("Test FAILED!", e);
|
||||
} else {
|
||||
FUTURE.completeExceptionally(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ThrowableRunnable {
|
||||
void run() throws Exception;
|
||||
}
|
||||
|
||||
static class TestLogHandler extends StreamHandler {
|
||||
public StringBuilder buffer = new StringBuilder();
|
||||
|
||||
public TestLogHandler() {
|
||||
// Use System.out to merge with the test printing.
|
||||
super(System.out, new SimpleFormatter());
|
||||
setLevel(Level.ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(LogRecord record) {
|
||||
buffer.append(record.getMessage());
|
||||
super.publish(record);
|
||||
flush();
|
||||
}
|
||||
|
||||
public boolean testContains(String str) {
|
||||
boolean contains = buffer.toString().contains(str);
|
||||
buffer.setLength(0);
|
||||
return contains;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,20 +35,20 @@ public enum Layout_ABC implements LayoutKey {
|
||||
// located on the left side of the key 1 on the Apple International English keyboard
|
||||
// SECTION ('§', '§', '±', '±'),
|
||||
|
||||
VK_MINUS ('-', '–', '_', '—'),
|
||||
VK_EQUALS ('=', '≠', '+', '±'),
|
||||
VK_MINUS ('-', '–', '_', '—', '\u001F'),
|
||||
VK_EQUALS ('=', '≠', '+', '±', '='),
|
||||
|
||||
VK_OPEN_BRACKET ('[', '“', '{', '”'),
|
||||
VK_CLOSE_BRACKET (']', '‘', '}', '’'),
|
||||
VK_OPEN_BRACKET ('[', '“', '{', '”', '\u001B'),
|
||||
VK_CLOSE_BRACKET (']', '‘', '}', '’', '\u001D'),
|
||||
|
||||
VK_SEMICOLON (';', '…', ':', 'Ú'),
|
||||
VK_QUOTE ('\'', 'æ', '"', 'Æ'),
|
||||
VK_BACK_SLASH ('\\', '«', '|', '»'),
|
||||
VK_SEMICOLON (';', '…', ':', 'Ú', ';'),
|
||||
VK_QUOTE ('\'', 'æ', '"', 'Æ', '\''),
|
||||
VK_BACK_SLASH ('\\', '«', '|', '»', '\u001C'),
|
||||
|
||||
VK_BACK_QUOTE (KeyChar.ch('`'), KeyChar.dead('`'), KeyChar.ch('~'), KeyChar.ch('`')),
|
||||
VK_COMMA (',', '≤', '<', '¯'),
|
||||
VK_PERIOD ('.', '≥', '>', '˘'),
|
||||
VK_SLASH ('/', '÷', '?', '¿'),
|
||||
VK_BACK_QUOTE (KeyChar.ch('`'), KeyChar.dead('`'), KeyChar.ch('~'), KeyChar.ch('`'), KeyChar.ch('`')),
|
||||
VK_COMMA (',', '≤', '<', '¯', ','),
|
||||
VK_PERIOD ('.', '≥', '>', '˘', '.'),
|
||||
VK_SLASH ('/', '÷', '?', '¿', '/'),
|
||||
|
||||
//VK_1 ('1', '¡', '!', '⁄'),
|
||||
//VK_2 ('2', '™', '@', '€'),
|
||||
@@ -99,12 +99,12 @@ public enum Layout_ABC implements LayoutKey {
|
||||
|
||||
private final Key key;
|
||||
|
||||
Layout_ABC(char no, char alt, char shift, char alt_shift) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift));
|
||||
Layout_ABC(char no, char alt, char shift, char alt_shift, char control) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift, control));
|
||||
}
|
||||
|
||||
Layout_ABC(KeyChar no, KeyChar alt, KeyChar shift, KeyChar alt_shift) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift));
|
||||
Layout_ABC(KeyChar no, KeyChar alt, KeyChar shift, KeyChar alt_shift, KeyChar control) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift, control));
|
||||
}
|
||||
|
||||
public Key getKey() {
|
||||
|
||||
@@ -30,20 +30,20 @@ public enum Layout_FRENCH_PC implements LayoutKey {
|
||||
// Enum name must be the same as KeyEvent.VK_ constant name corresponding to the key on US keyboard layout
|
||||
// Note that '\u0000' may be used if no char is mapped to a key + modifier or if one wants to skip its testing
|
||||
|
||||
VK_MINUS (')', ']', '°', ']'),
|
||||
VK_EQUALS ('=', '}', '+', '≠'),
|
||||
VK_MINUS (')', ']', '°', ']', '\u001B'),
|
||||
VK_EQUALS ('=', '}', '+', '≠', '\u001F'),
|
||||
|
||||
VK_OPEN_BRACKET (KeyChar.dead('^'), KeyChar.ch('ô'), KeyChar.dead('¨'), KeyChar.ch('Ô')),
|
||||
VK_CLOSE_BRACKET ('$', '¤', '£', '¥'),
|
||||
VK_OPEN_BRACKET (KeyChar.dead('^'), KeyChar.ch('ô'), KeyChar.dead('¨'), KeyChar.ch('Ô'), KeyChar.ch('\u001E')),
|
||||
VK_CLOSE_BRACKET ('$', '¤', '£', '¥', '\u001D'),
|
||||
|
||||
VK_SEMICOLON ('m', 'µ', 'M', 'Ó'),
|
||||
VK_QUOTE ('ù', 'Ù', '%', '‰'),
|
||||
VK_BACK_SLASH ('*', '@', 'μ', '#'),
|
||||
VK_SEMICOLON ('m', 'µ', 'M', 'Ó', '\r'),
|
||||
VK_QUOTE ('ù', 'Ù', '%', '‰', 'ù'),
|
||||
VK_BACK_SLASH ('*', '@', 'μ', '#', '\u001C'),
|
||||
|
||||
VK_BACK_QUOTE ('<', '«', '>', '≥'),
|
||||
VK_COMMA (';', '…', '.', '•'),
|
||||
VK_PERIOD (':', '÷', '/', '\\'),
|
||||
VK_SLASH ('!', '¡', '§', '±'),
|
||||
VK_BACK_QUOTE ('<', '«', '>', '≥', '<'),
|
||||
VK_COMMA (';', '…', '.', '•', ';'),
|
||||
VK_PERIOD (':', '÷', '/', '\\', ':'),
|
||||
VK_SLASH ('!', '¡', '§', '±', '='),
|
||||
|
||||
;
|
||||
|
||||
@@ -51,12 +51,12 @@ public enum Layout_FRENCH_PC implements LayoutKey {
|
||||
|
||||
private final Key key;
|
||||
|
||||
Layout_FRENCH_PC(char no, char alt, char shift, char alt_shift) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift));
|
||||
Layout_FRENCH_PC(char no, char alt, char shift, char alt_shift, char control) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift, control));
|
||||
}
|
||||
|
||||
Layout_FRENCH_PC(KeyChar no, KeyChar alt, KeyChar shift, KeyChar alt_shift) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift));
|
||||
Layout_FRENCH_PC(KeyChar no, KeyChar alt, KeyChar shift, KeyChar alt_shift, KeyChar control) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift, control));
|
||||
}
|
||||
|
||||
public Key getKey() {
|
||||
|
||||
@@ -31,20 +31,20 @@ public enum Layout_GERMAN implements LayoutKey {
|
||||
// Note that '\u0000' may be used if no char is mapped to a key + modifier or if one wants to skip its testing
|
||||
|
||||
// Eszett
|
||||
VK_MINUS ('ß', '¿', '?', '˙'),
|
||||
VK_EQUALS (KeyChar.dead('´'), KeyChar.ch('\''), KeyChar.dead('`'), KeyChar.ch('˚')),
|
||||
VK_MINUS ('ß', '¿', '?', '˙', 'ß'),
|
||||
VK_EQUALS (KeyChar.dead('´'), KeyChar.ch('\''), KeyChar.dead('`'), KeyChar.ch('˚'), KeyChar.ch('´')),
|
||||
|
||||
VK_OPEN_BRACKET ('ü', '•', 'Ü', '°'),
|
||||
VK_CLOSE_BRACKET ('+', '±', '*', ''),
|
||||
VK_OPEN_BRACKET ('ü', '•', 'Ü', '°', '\u001D'),
|
||||
VK_CLOSE_BRACKET ('+', '±', '*', '', '+'),
|
||||
|
||||
VK_SEMICOLON ('ö', 'œ', 'Ö', 'Œ'),
|
||||
VK_QUOTE ('ä', 'æ', 'Ä', 'Æ'),
|
||||
VK_BACK_SLASH ('#', '‘', '\'', '’'),
|
||||
VK_SEMICOLON ('ö', 'œ', 'Ö', 'Œ', '\u001C'),
|
||||
VK_QUOTE ('ä', 'æ', 'Ä', 'Æ', '\u001B'),
|
||||
VK_BACK_SLASH ('#', '‘', '\'', '’', '#'),
|
||||
|
||||
VK_BACK_QUOTE ('<', '≤', '>', '≥'),
|
||||
VK_COMMA (',', '∞', ';', '˛'),
|
||||
VK_PERIOD ('.', '…', ':', '÷'),
|
||||
VK_SLASH ('-', '–', '_', '—'),
|
||||
VK_BACK_QUOTE ('<', '≤', '>', '≥', '<'),
|
||||
VK_COMMA (',', '∞', ';', '˛', ','),
|
||||
VK_PERIOD ('.', '…', ':', '÷', '.'),
|
||||
VK_SLASH ('-', '–', '_', '—', '-'),
|
||||
|
||||
;
|
||||
|
||||
@@ -52,12 +52,12 @@ public enum Layout_GERMAN implements LayoutKey {
|
||||
|
||||
private final Key key;
|
||||
|
||||
Layout_GERMAN(char no, char alt, char shift, char alt_shift) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift));
|
||||
Layout_GERMAN(char no, char alt, char shift, char alt_shift, char control) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift, control));
|
||||
}
|
||||
|
||||
Layout_GERMAN(KeyChar no, KeyChar alt, KeyChar shift, KeyChar alt_shift) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift));
|
||||
Layout_GERMAN(KeyChar no, KeyChar alt, KeyChar shift, KeyChar alt_shift, KeyChar control) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift, control));
|
||||
}
|
||||
|
||||
public Key getKey() {
|
||||
|
||||
@@ -30,20 +30,20 @@ public enum Layout_SPANISH_ISO implements LayoutKey {
|
||||
// Enum name must be the same as KeyEvent.VK_ constant name corresponding to the key on US keyboard layout
|
||||
// Note that '\u0000' may be used if no char is mapped to a key + modifier or if one wants to skip its testing
|
||||
|
||||
VK_MINUS ('\'', '´', '?', '¸'),
|
||||
VK_EQUALS ('¡', '‚', '¿', '˛'),
|
||||
VK_MINUS ('\'', '´', '?', '¸', '\u001F'),
|
||||
VK_EQUALS ('¡', '‚', '¿', '˛', '='),
|
||||
|
||||
VK_OPEN_BRACKET (KeyChar.dead('`'), KeyChar.ch('['), KeyChar.dead('^'), KeyChar.ch('ˆ')),
|
||||
VK_CLOSE_BRACKET ('+', ']', '*', '±'),
|
||||
VK_OPEN_BRACKET (KeyChar.dead('`'), KeyChar.ch('['), KeyChar.dead('^'), KeyChar.ch('ˆ'), KeyChar.ch('\u001B')),
|
||||
VK_CLOSE_BRACKET ('+', ']', '*', '±', '\u001D'),
|
||||
|
||||
VK_SEMICOLON (KeyChar.ch('ñ'), KeyChar.dead('~'), KeyChar.ch('Ñ'), KeyChar.ch('˜')),
|
||||
VK_QUOTE (KeyChar.dead('´'), KeyChar.ch('{'), KeyChar.dead('¨'), KeyChar.ch('«')),
|
||||
VK_BACK_SLASH ('ç', '}', 'Ç', '»'),
|
||||
VK_SEMICOLON (KeyChar.ch('ñ'), KeyChar.dead('~'), KeyChar.ch('Ñ'), KeyChar.ch('˜'), KeyChar.ch(':')),
|
||||
VK_QUOTE (KeyChar.dead('´'), KeyChar.ch('{'), KeyChar.dead('¨'), KeyChar.ch('«'), KeyChar.ch('"')),
|
||||
VK_BACK_SLASH ('ç', '}', 'Ç', '»', '\u001C'),
|
||||
|
||||
VK_BACK_QUOTE ('<', '≤', '>', '≥'),
|
||||
VK_COMMA (',', '„', ';', '\u0000'),
|
||||
VK_PERIOD ('.', '…', ':', '…'),
|
||||
VK_SLASH ('-', '–', '_', '—'),
|
||||
VK_BACK_QUOTE ('<', '≤', '>', '≥', '`'),
|
||||
VK_COMMA (',', '„', ';', '\u0000', ','),
|
||||
VK_PERIOD ('.', '…', ':', '…', '.'),
|
||||
VK_SLASH ('-', '–', '_', '—', '/'),
|
||||
|
||||
;
|
||||
|
||||
@@ -51,12 +51,12 @@ public enum Layout_SPANISH_ISO implements LayoutKey {
|
||||
|
||||
private final Key key;
|
||||
|
||||
Layout_SPANISH_ISO(char no, char alt, char shift, char alt_shift) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift));
|
||||
Layout_SPANISH_ISO(char no, char alt, char shift, char alt_shift, char control) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift, control));
|
||||
}
|
||||
|
||||
Layout_SPANISH_ISO(KeyChar no, KeyChar alt, KeyChar shift, KeyChar alt_shift) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift));
|
||||
Layout_SPANISH_ISO(KeyChar no, KeyChar alt, KeyChar shift, KeyChar alt_shift, KeyChar control) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift, control));
|
||||
}
|
||||
|
||||
public Key getKey() {
|
||||
|
||||
@@ -30,21 +30,21 @@ public enum Layout_US_INTERNATIONAL_PC implements LayoutKey {
|
||||
// Enum name must be the same as KeyEvent.VK_ constant name corresponding to the key on US keyboard layout
|
||||
// Note that '\u0000' may be used if no char is mapped to a key + modifier or if one wants to skip its testing
|
||||
|
||||
VK_MINUS ('-', '–', '_', '—'),
|
||||
VK_EQUALS ('=', '≠', '+', '±'),
|
||||
VK_MINUS ('-', '–', '_', '—', '\u001F'),
|
||||
VK_EQUALS ('=', '≠', '+', '±', '='),
|
||||
|
||||
VK_OPEN_BRACKET ('[', '“', '{', '”'),
|
||||
VK_CLOSE_BRACKET (']', '‘', '}', '’'),
|
||||
VK_OPEN_BRACKET ('[', '“', '{', '”', '\u001B'),
|
||||
VK_CLOSE_BRACKET (']', '‘', '}', '’', '\u001D'),
|
||||
|
||||
VK_SEMICOLON (';', '…', ':', 'Ú'),
|
||||
VK_SEMICOLON (';', '…', ':', 'Ú', ';'),
|
||||
// ' is a special dead symbol, which may add either acute or cedilla to the next key
|
||||
VK_QUOTE (KeyChar.dead('\''), KeyChar.ch('æ'), KeyChar.dead('\"'), KeyChar.ch('Æ')),
|
||||
VK_BACK_SLASH ('\\', '«', '|', '»'),
|
||||
VK_QUOTE (KeyChar.dead('\''), KeyChar.ch('æ'), KeyChar.dead('\"'), KeyChar.ch('Æ'), KeyChar.ch('\'')),
|
||||
VK_BACK_SLASH ('\\', '«', '|', '»', '\u001C'),
|
||||
|
||||
VK_BACK_QUOTE (KeyChar.dead('`'), KeyChar.dead('`'), KeyChar.dead('~'), KeyChar.ch('`')),
|
||||
VK_COMMA (',', '≤', '<', '¯'),
|
||||
VK_PERIOD ('.', '≥', '>', '˘'),
|
||||
VK_SLASH ('/', '÷', '?', '¿'),
|
||||
VK_BACK_QUOTE (KeyChar.dead('`'), KeyChar.dead('`'), KeyChar.dead('~'), KeyChar.ch('`'), KeyChar.ch('`')),
|
||||
VK_COMMA (',', '≤', '<', '¯', ','),
|
||||
VK_PERIOD ('.', '≥', '>', '˘', '.'),
|
||||
VK_SLASH ('/', '÷', '?', '¿', '/'),
|
||||
|
||||
;
|
||||
|
||||
@@ -52,12 +52,12 @@ public enum Layout_US_INTERNATIONAL_PC implements LayoutKey {
|
||||
|
||||
private final Key key;
|
||||
|
||||
Layout_US_INTERNATIONAL_PC(char no, char alt, char shift, char alt_shift) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift));
|
||||
Layout_US_INTERNATIONAL_PC(char no, char alt, char shift, char alt_shift, char control) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift, control));
|
||||
}
|
||||
|
||||
Layout_US_INTERNATIONAL_PC(KeyChar no, KeyChar alt, KeyChar shift, KeyChar alt_shift) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift));
|
||||
Layout_US_INTERNATIONAL_PC(KeyChar no, KeyChar alt, KeyChar shift, KeyChar alt_shift, KeyChar control) {
|
||||
key = new Key(name(), new MappedKeyChars(no, alt, shift, alt_shift, control));
|
||||
}
|
||||
|
||||
public Key getKey() {
|
||||
|
||||
@@ -23,20 +23,22 @@ public class MappedKeyChars {
|
||||
private final KeyChar alt;
|
||||
private final KeyChar shift;
|
||||
private final KeyChar alt_shift;
|
||||
private final KeyChar control;
|
||||
|
||||
MappedKeyChars(char no_modifier, char alt, char shift, char alt_shift) {
|
||||
MappedKeyChars(char no_modifier, char alt, char shift, char alt_shift, char control) {
|
||||
this.no_modifier = KeyChar.ch(no_modifier);
|
||||
this.alt = KeyChar.ch(alt);
|
||||
this.shift = KeyChar.ch(shift);
|
||||
this.alt_shift = KeyChar.ch(alt_shift);
|
||||
this.control = KeyChar.ch(control);
|
||||
}
|
||||
|
||||
MappedKeyChars(KeyChar no_modifier, KeyChar alt, KeyChar shift, KeyChar alt_shift) {
|
||||
MappedKeyChars(KeyChar no_modifier, KeyChar alt, KeyChar shift, KeyChar alt_shift, KeyChar control) {
|
||||
this.no_modifier = no_modifier;
|
||||
this.alt = alt;
|
||||
this.shift = shift;
|
||||
this.alt_shift = alt_shift;
|
||||
|
||||
this.control = control;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -57,6 +59,9 @@ public class MappedKeyChars {
|
||||
if(modifier.isAltShift()) {
|
||||
return alt_shift;
|
||||
}
|
||||
if(modifier.isControl()) {
|
||||
return control;
|
||||
}
|
||||
return KeyChar.ch(Character.MAX_VALUE);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,10 @@ public enum Modifier {
|
||||
return ((modifiers.length == 2) && list.contains(KeyEvent.VK_ALT) && list.contains(KeyEvent.VK_SHIFT));
|
||||
}
|
||||
|
||||
boolean isControl() {
|
||||
return ((modifiers.length == 1) && (modifiers[0] == KeyEvent.VK_CONTROL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (modifiers.length == 0) {
|
||||
|
||||
@@ -57,7 +57,9 @@ import java.util.stream.Collectors;
|
||||
* - No keyTyped event is expected as the result of pressing dead key + key.
|
||||
* - Pressing "dead key + space" generates corresponding diacritic character,
|
||||
* which may be obtained using inputMethodTextChanged event.
|
||||
* - Cmd, Ctrl and its combinations with other modifiers are considered as a "shortcut",
|
||||
* - Ctrl can be used to type the "control characters" (0th to 31th character inclusively in the ASCII table),
|
||||
* so Ctrl + key can generate keyTyped event.
|
||||
* - Cmd and its combinations with other modifiers are considered as a "shortcut",
|
||||
* no keyTyped event is expected as the result of pressing a shortcut,
|
||||
* no attempts are made to check inputMethodTextChanged event result for a "shortcut".
|
||||
*
|
||||
@@ -182,7 +184,7 @@ public class NationalLayoutTest {
|
||||
for (Modifier modifier : Modifier.values()) {
|
||||
if(!testLayout(layout, modifier)) {
|
||||
failed = true;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
// Provide the test result
|
||||
@@ -253,7 +255,7 @@ public class NationalLayoutTest {
|
||||
// Corresponding latch is released in the typeAreaFocusListener.
|
||||
if(!typeAreaGainedFocus.await(PAUSE, TimeUnit.MILLISECONDS)) {
|
||||
throw new RuntimeException("TEST ERROR: Failed to request focus in the text area for typing");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -305,9 +307,21 @@ public class NationalLayoutTest {
|
||||
// Obtain typed char
|
||||
char keyChar = e.getKeyChar();
|
||||
int keyCode = KeyEvent.getExtendedKeyCodeForChar(keyChar);
|
||||
if ((keyCode != NEXT_MODIFIER) && (keyCode != NEXT_KEY) && (keyCode != TERMINATE_KEY)) {
|
||||
// Store typed char to the corresponding list
|
||||
charsTyped.add(keyChar);
|
||||
|
||||
switch (keyCode) {
|
||||
case NEXT_MODIFIER:
|
||||
case NEXT_KEY:
|
||||
case TERMINATE_KEY:
|
||||
if ((e.getModifiers() & KeyEvent.CTRL_MASK) == 0) {
|
||||
// Do not store the typed char only if it is NEXT_MODIFIER, NEXT_KEY, TERMINATE_KEY generated
|
||||
// without Control modifier: the Control allows to "type" the "control characters"
|
||||
// (0th to 31th character inclusively in the ASCII table).
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Store typed char to the corresponding list
|
||||
charsTyped.add(keyChar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -356,7 +370,7 @@ public class NationalLayoutTest {
|
||||
}
|
||||
if(!nextModifierSet.await(PAUSE*10, TimeUnit.MILLISECONDS)) {
|
||||
throw new RuntimeException("TEST ERROR: User has not proceeded with manual testing");
|
||||
};
|
||||
}
|
||||
|
||||
// Clean up the test text areas
|
||||
inputArea.setText("");
|
||||
@@ -411,7 +425,7 @@ public class NationalLayoutTest {
|
||||
if(!nextKey.await(PAUSE, TimeUnit.MILLISECONDS)) {
|
||||
throw new RuntimeException("TEST ERROR: "
|
||||
+ KeyEvent.getKeyText(NEXT_KEY) + " key pressed event was not received");
|
||||
};
|
||||
}
|
||||
|
||||
// Define array of key codes expected to be pressed as the result of modifiers + key
|
||||
int[] keysPattern = Arrays.copyOf(modifiers, modifiers.length + 1);
|
||||
@@ -426,7 +440,7 @@ public class NationalLayoutTest {
|
||||
// Check if the pressed key codes are equal to the expected ones
|
||||
if(!checkResult(keysPattern, keysResult, null,null)) {
|
||||
result = false;
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Define array of chars expected to be typed as the result of modifiers + key
|
||||
// Do not expect any char typed as the result of shortcut (char is undefined in this case)
|
||||
@@ -440,7 +454,7 @@ public class NationalLayoutTest {
|
||||
// Check if pressed key codes and typed chars are equal to the expected ones
|
||||
if(!checkResult(keysPattern, keysResult, charsPattern, charsResult)) {
|
||||
result = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
// Provide layout + modifier testing result
|
||||
@@ -473,7 +487,7 @@ public class NationalLayoutTest {
|
||||
boolean checkKeys = Arrays.equals(patternKeys, resultKeys);
|
||||
boolean checkChars = Arrays.equals(patternChars, resultChars);
|
||||
|
||||
boolean result = (checkKeys & checkChars);
|
||||
boolean result = (checkKeys && checkChars);
|
||||
|
||||
if(!result) {
|
||||
String[] patternStr = (patternKeys != null) ? intsToStrings(patternKeys) : null;
|
||||
|
||||
@@ -672,6 +672,7 @@ com/sun/nio/sctp/SctpChannel/SocketOptionTests.java 8141694 linux-al
|
||||
|
||||
# jdk_security
|
||||
|
||||
sun/security/pkcs11/Signature/TestDSAKeyLength.java 8279941 generic-all
|
||||
sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8161536 generic-all
|
||||
|
||||
sun/security/tools/keytool/ListKeychainStore.sh 8156889 macosx-all
|
||||
@@ -934,4 +935,7 @@ com/sun/java/swing/plaf/windows/Test8173145.java
|
||||
com/sun/java/swing/plaf/windows/AltFocusIssueTest.java JBR-4197 windows-all
|
||||
|
||||
java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java JBR-4207 windows-all
|
||||
jb/java/awt/keyboard/AltGrMustGenerateAltGrModifierTest4207.java JBR-4207 windows-all
|
||||
jb/java/awt/keyboard/AltGrMustGenerateAltGrModifierTest4207.java JBR-4207 windows-all
|
||||
|
||||
java/awt/Dialog/NonResizableDialogSysMenuResize/NonResizableDialogSysMenuResize.java JBR-4250 windows-all
|
||||
java/awt/Dialog/NestedDialogs/Modeless/NestedModelessDialogTest.java JBR-4250 windows-all
|
||||
@@ -2,4 +2,4 @@
|
||||
sun/java2d/ClassCastExceptionForInvalidSurface.java JBR-3167 linux-all
|
||||
java/awt/Frame/HugeFrame/HugeFrame.java JBR-3167 linux-all
|
||||
java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java 8279256 linux-all
|
||||
sun/security/pkcs11/Signature/TestDSAKeyLength.java 8279941 linux-all
|
||||
java/awt/Frame/FrameSetSizeStressTest/FrameSetSizeStressTest.java JBR-4223 linux-all
|
||||
1
test/jdk/jbcommitProblemList.txt
Normal file
1
test/jdk/jbcommitProblemList.txt
Normal file
@@ -0,0 +1 @@
|
||||
javax/imageio/plugins/external_plugin_tests/TestClassPathPlugin.sh nobug generic-all line 59: /opt/teamcity-agent/work/efb45cc305c2e813/jbr/Contents/Home/bin/jar: No such file or directory
|
||||
Reference in New Issue
Block a user