Compare commits

..

8 Commits

83 changed files with 546 additions and 4179 deletions

View File

@@ -31,7 +31,6 @@ RUN export DEBIAN_FRONTEND=noninteractive \
libxt-dev \
libxtst-dev \
make \
rsync \
tar \
unzip \
zip && \

View File

@@ -1,22 +0,0 @@
# NOTE: This Dockerfile is meant to be used from the mkdocker_musl_aarch64.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 rsync 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"

View File

@@ -1,22 +0,0 @@
# 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 rsync 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"

View File

@@ -1,26 +0,0 @@
#!/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.

View File

@@ -1,26 +0,0 @@
#!/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.

View File

@@ -77,27 +77,15 @@ case "$OS_NAME" in
;;
esac
WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS="--with-native-debug-symbols=zipped"
REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build
--with-source-date=$SOURCE_DATE_EPOCH
--with-hotspot-build-time=$BUILD_TIME
--with-copyright-year=$COPYRIGHT_YEAR
--disable-absolute-paths-in-output"
function zip_native_debug_symbols() {
image_bundle_path=$(echo $1 | cut -d"/" -f-4)
jbr_diz_name=$2
(cd $image_bundle_path && find . -name '*.diz' -exec rsync -R {} ../../../../dizfiles \; )
(cd dizfiles && find . -print0 | COPYFILE_DISABLE=1 \
tar --no-recursion --null -T - -czf ../"$jbr_diz_name".tar.gz) || do_exit $?
}
function do_exit() {
exit_code=$1
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
[ $do_reset_changes -eq 1 ] && git checkout HEAD 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

View File

@@ -6,21 +6,8 @@
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}" \
@@ -32,12 +19,11 @@ sh configure \
--with-boot-jdk=${BOOT_JDK} \
--enable-cds=yes \
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|| exit $?
make clean CONF=linux-aarch64-server-release || exit $?
make images CONF=linux-aarch64-server-release test-image || exit $?
JBSDK=${JBRSDK_BASE_NAME}-linux-${LIBC_TYPE_SUFFIX}aarch64-b${build_number}
JBSDK=${JBRSDK_BASE_NAME}-linux-aarch64-b${build_number}
BASE_DIR=build/linux-aarch64-server-release/images
JSDK=${BASE_DIR}/jdk
JBRSDK_BUNDLE=jbrsdk
@@ -52,8 +38,6 @@ echo Creating $JBSDK.tar.gz ...
sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release
mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release
zip_native_debug_symbols $JSDK "${JBSDK}_diz"
# NB: --sort=name requires tar1.28
tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBSDK.tar \
--exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \
@@ -65,8 +49,8 @@ JBR_BUNDLE=jbr
JBR_BASE_NAME=jbr-$JBSDK_VERSION
rm -rf $BASE_DIR/$JBR_BUNDLE
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
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
echo Running jlink....
${JSDK}/bin/jlink \
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
@@ -81,7 +65,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-${LIBC_TYPE_SUFFIX}test-aarch64-b$build_number
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-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 $?

View File

@@ -33,31 +33,17 @@ function do_configure {
--with-boot-jdk="$BOOT_JDK" \
--enable-cds=yes \
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|| 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-${libc_type_suffix}x64-${fastdebug_infix}b${build_number}
JBR=${__bundle_name}-${JBSDK_VERSION}-linux-x64-${fastdebug_infix}b${build_number}
echo Running jlink....
[ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name"
@@ -70,7 +56,6 @@ function create_image_bundle {
sed 's/JBR/JBRSDK/g' "$IMAGES_DIR"/"$__arch_name"/release > release
mv release "$IMAGES_DIR"/"$__arch_name"/release
copy_jmods "$__modules" "$__modules_path" "$IMAGES_DIR"/"$__arch_name"/jmods
zip_native_debug_symbols $IMAGES_DIR/jdk "${JBR}_diz"
fi
# jmod does not preserve file permissions (JDK-8173610)
@@ -130,7 +115,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
fi
# create runtime image bundle
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
modules=$(xargs < 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
@@ -141,9 +126,9 @@ fi
create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $?
if [ $do_maketest -eq 1 ]; then
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-${libc_type_suffix}test-x64-b${build_number}
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-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
[ $do_reset_changes -eq 1 ] && git checkout HEAD 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"

View File

@@ -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 jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
grep -v javafx 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 $?

View File

@@ -45,7 +45,6 @@ function do_configure {
--with-extra-cxxflags="-F$(pwd)/Frameworks" \
--with-extra-ldflags="-F$(pwd)/Frameworks" \
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|| do_exit $?
else
sh configure \
@@ -62,7 +61,6 @@ function do_configure {
--with-macosx-version-max="${MACOSX_VERSION_MAX:="10.12.00"}" \
--enable-cds=yes \
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|| do_exit $?
fi
}
@@ -92,7 +90,6 @@ function create_image_bundle {
sed 's/JBR/JBRSDK/g' $JRE_CONTENTS/Home/release > release
mv release $JRE_CONTENTS/Home/release
copy_jmods "$__modules" "$__modules_path" "$JRE_CONTENTS"/Home/jmods
zip_native_debug_symbols $IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk "${JBR}_diz"
fi
cp -R "$JSDK"/../MacOS "$JRE_CONTENTS"
@@ -156,7 +153,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
fi
# create runtime image bundle
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
modules=$(xargs < 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
@@ -169,7 +166,7 @@ create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" "$JBRSDK_BUNDLE" "$JSDK_
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
[ $do_reset_changes -eq 1 ] && git checkout HEAD 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 $?

View File

@@ -1,8 +1,8 @@
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,
diff --git modules.list modules.list
index 054f21d1ee0..d9a121f0273 100644
--- modules.list
+++ modules.list
@@ -49,4 +49,7 @@ jdk.unsupported,
jdk.xml.dom,
jdk.zipfs,
jdk.hotspot.agent,

View File

@@ -1,16 +1,5 @@
#!/bin/bash
while getopts ":t" o; do
case "${o}" in
t)
t="With Teamcity tests info"
TC_PRINT=1
;;
esac
done
shift $((OPTIND-1))
NEWFILEPATH=$1
CONFIGID=$2
BUILDID=$3
@@ -18,7 +7,6 @@ TOKEN=$4
#
# Get the size of new artifact
#
unameOut="$(uname -s)"
case "${unameOut}" in
Linux*)
@@ -28,11 +16,7 @@ case "${unameOut}" in
NEWFILESIZE=$(stat -f%z "$NEWFILEPATH")
;;
CYGWIN*)
NEWFILESIZE=$(stat -c%s$4
#
# Get the size of new artifact
#
"$NEWFILEPATH")
NEWFILESIZE=$(stat -c%s "$NEWFILEPATH")
;;
MINGW*)
NEWFILESIZE=$(stat -c%s "$NEWFILEPATH")
@@ -41,88 +25,32 @@ case "${unameOut}" in
echo "Unknown machine: ${unameOut}"
exit 1
esac
FILENAME=$(basename ${NEWFILEPATH})
#
# Get pattern of artifact name
# Base filename pattern: <BUNDLE_TYPE>-<JDK_VERSION>-<OS>-<ARCH>-b<BUILD>.tar.gz: jbr_dcevm-17.0.2-osx-x64-b1234.tar.gz
# BUNDLE_TYPE: jbr, jbrsdk, jbr_dcevm, jbrsdk_jcef etc.
# OS_ARCH_PATTERN - <os_architecture>: osx-x64, linux-aarch64, windows-x64 etc.
echo "New size of $NEWFILEPATH = $NEWFILESIZE bytes."
BUNDLE_TYPE=jbrsdk
OS_ARCH_PATTERN=""
FILE_EXTENSION=tar.gz
# example: IntellijCustomJdk_Jdk17_Master_LinuxX64jcef
re='(jbr[a-z_]*).*-[0-9_\.]+-(.+)-b[0-9]+(.+)'
if [[ $FILENAME =~ $re ]]; then
BUNDLE_TYPE=${BASH_REMATCH[1]}
OS_ARCH_PATTERN=${BASH_REMATCH[2]}
FILE_EXTENSION=${BASH_REMATCH[3]}
fi
if [ $TC_PRINT -eq 1 ]; then
testname_file_ext=`echo $FILE_EXTENSION | sed 's/\./_/g'`
testname=$BUNDLE_TYPE"_"$OS_ARCH_PATTERN$testname_file_ext
echo \#\#teamcity[testStarted name=\'$testname\']
fi
echo "BUNDLE_TYPE: " $BUNDLE_TYPE
echo "OS_ARCH_PATTERN: " $OS_ARCH_PATTERN
echo "FILE_EXTENSION: " $FILE_EXTENSION
echo "New size of $FILENAME = $NEWFILESIZE bytes."
function test_failed_msg() {
if [ $3 -eq 1 ]; then
echo \#\#teamcity[testFailed name=\'$1\' message=\'$2\']
fi
}
function test_finished_msg() {
if [ $2 -eq 1 ]; then
echo \#\#teamcity[testFinished name=\'$1\']
fi
}
#
# Get previous successful build ID
# Example:
# CONFIGID=IntellijCustomJdk_Jdk17_Master_LinuxX64jcef
# BUILDID=12345678
#
# expected return value
# id="123".number="567"
#
CURL_RESPONSE=$(curl --header "Authorization: Bearer $TOKEN" "https://buildserver.labs.intellij.net/app/rest/builds/?locator=buildType:(id:$CONFIGID),status:success,count:1,finishDate:(build:$BUILDID,condition:before)")
re='id=\"([0-9]+)\".+number=\"([0-9\.]+)\"'
# ID: Previous successful build id
re='id=\"([0-9]+)\".+number=\"([0-9]+)\"'
ID=0
if [[ $CURL_RESPONSE =~ $re ]]; then
ID=${BASH_REMATCH[1]}
echo "BUILD Number: ${BASH_REMATCH[2]}"
else
msg="ERROR: can't find previous build"
echo $msg
echo "ERROR: can't find previous build"
echo $CURL_RESPONSE
test_failed_msg $testname $msg $TC_PRINT
test_finished_msg $testname $TC_PRINT
exit 1
fi
#
# Get artifacts from previous successful build
#
# expected return value
# name="jbrsdk_jcef*.tar.gz size="123'
#
CURL_RESPONSE=$(curl --header "Authorization: Bearer $TOKEN" "https://buildserver.labs.intellij.net/app/rest/builds/$ID?fields=id,number,artifacts(file(name,size))")
echo "Atrifacts of previous build of $CONFIGID :"
echo "Atrifacts of last pinned build of $CONFIGID :\n"
echo $CURL_RESPONSE
# Find binary size (in response) with reg exp
re='name=\"('$BUNDLE_TYPE'[^\"]+'${OS_ARCH_PATTERN}'[^\"]+'${FILE_EXTENSION}')\" size=\"([0-9]+)\"'
# Find size (in response) with reg exp
re='name=\"(jbrsdk_jcef[^\"]+\.tar\.gz)\" size=\"([0-9]+)\"'
if [[ $CURL_RESPONSE =~ $re ]]; then
OLDFILENAME=${BASH_REMATCH[1]}
@@ -133,20 +61,12 @@ if [[ $CURL_RESPONSE =~ $re ]]; then
let allowedSize=OLDFILESIZE+OLDFILESIZE/20 # use 5% threshold
echo "Allowed size = $allowedSize"
if [[ "$NEWFILESIZE" -gt "$allowedSize" ]]; then
msg="ERROR: new size is significally greater than prev size (need to investigate)"
echo $msg
test_failed_msg $testname $msg $TC_PRINT
test_finished_msg $testname $TC_PRINT
echo "ERROR: new size is significally greater than prev size (need to investigate)"
exit 1
else
echo "PASSED"
test_finished_msg $testname $TC_PRINT
fi
else
msg="ERROR: can't find string with size in xml response:"
echo $msg
echo "ERROR: can't find string with size in xml response:"
echo $CURL_RESPONSE
test_failed_msg $testname $msg $TC_PRINT
test_finished_msg $testname $TC_PRINT
exit 1
fi

View File

@@ -107,8 +107,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
fi
# create runtime image bundlef
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
modules+=",jdk.crypto.mscapi"
modules=$(xargs < 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

View File

@@ -53,8 +53,7 @@ mv release ${JBRSDK_BUNDLE}/release
JBR_BUNDLE=jbr
rm -rf ${JBR_BUNDLE}
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
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > 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 $?

View File

@@ -95,24 +95,8 @@ AC_DEFUN([FLAGS_SETUP_DEBUG_SYMBOLS],
# info flags for toolchains unless we know they work.
# See JDK-8207057.
ASFLAGS_DEBUG_SYMBOLS=""
# Debug prefix mapping if supported by compiler
DEBUG_PREFIX_CFLAGS=
# Debug symbols
if test "x$TOOLCHAIN_TYPE" = xgcc; then
if test "x$ALLOW_ABSOLUTE_PATHS_IN_OUTPUT" = "xfalse"; then
# Check if compiler supports -fdebug-prefix-map. If so, use that to make
# the debug symbol paths resolve to paths relative to the workspace root.
workspace_root_trailing_slash="${WORKSPACE_ROOT%/}/"
DEBUG_PREFIX_CFLAGS="-fdebug-prefix-map=${workspace_root_trailing_slash}="
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${DEBUG_PREFIX_CFLAGS}],
IF_FALSE: [
DEBUG_PREFIX_CFLAGS=
]
)
fi
CFLAGS_DEBUG_SYMBOLS="-g"
ASFLAGS_DEBUG_SYMBOLS="-g"
elif test "x$TOOLCHAIN_TYPE" = xclang; then
@@ -124,11 +108,6 @@ AC_DEFUN([FLAGS_SETUP_DEBUG_SYMBOLS],
CFLAGS_DEBUG_SYMBOLS="-Z7"
fi
if test "x$DEBUG_PREFIX_CFLAGS" != x; then
CFLAGS_DEBUG_SYMBOLS="$CFLAGS_DEBUG_SYMBOLS $DEBUG_PREFIX_CFLAGS"
ASFLAGS_DEBUG_SYMBOLS="$ASFLAGS_DEBUG_SYMBOLS $DEBUG_PREFIX_CFLAGS"
fi
AC_SUBST(CFLAGS_DEBUG_SYMBOLS)
AC_SUBST(ASFLAGS_DEBUG_SYMBOLS)
])

View File

@@ -0,0 +1,55 @@
#
# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# Default version, product, and vendor information to use,
# unless overridden by configure
DEFAULT_VERSION_FEATURE=15
DEFAULT_VERSION_INTERIM=0
DEFAULT_VERSION_UPDATE=0
DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0
DEFAULT_VERSION_DATE=2020-09-15
DEFAULT_VERSION_CLASSFILE_MAJOR=59 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="14 15"
DEFAULT_JDK_SOURCE_TARGET_VERSION=15
DEFAULT_PROMOTED_VERSION_PRE=
LAUNCHER_NAME=openjdk
PRODUCT_NAME=OpenJDK
PRODUCT_SUFFIX="Runtime Environment"
JDK_RC_PLATFORM_NAME=Platform
COMPANY_NAME=N/A
HOTSPOT_VM_DISTRO="Dynamic Code Evolution"
VENDOR_URL=https://openjdk.java.net/
VENDOR_URL_BUG=https://bugreport.java.com/bugreport/
VENDOR_URL_VM_BUG=https://bugreport.java.com/bugreport/crash.jsp
# Might need better names for these
MACOSX_BUNDLE_NAME_BASE="OpenJDK"
MACOSX_BUNDLE_ID_BASE="net.java.openjdk"

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 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
@@ -193,8 +193,7 @@ define SetupJarArchiveBody
$1_UPDATE_CONTENTS=\
if [ "`$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'`" -gt "0" ]; then \
$(ECHO) " updating" `$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \
$(SORT) $$($1_BIN)/_the.$$($1_JARNAME)_contents > $$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted && \
$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted; \
$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents; \
fi $$(NEWLINE)
# The s-variants of the above macros are used when the jar is created from scratch.
# NOTICE: please leave the parentheses space separated otherwise the AIX build will break!
@@ -213,9 +212,7 @@ define SetupJarArchiveBody
| $(SED) 's|$$(src)/|-C $$(src) |g' >> \
$$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) )
endif
$1_SUPDATE_CONTENTS=\
$(SORT) $$($1_BIN)/_the.$$($1_JARNAME)_contents > $$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted && \
$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted $$(NEWLINE)
$1_SUPDATE_CONTENTS=$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)
# Use a slightly shorter name for logging, but with enough path to identify this jar.
$1_NAME:=$$(subst $$(OUTPUTDIR)/,,$$($1_JAR))

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 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
@@ -389,12 +389,6 @@ define SetupCompileNativeFileBody
$1_OBJ_DEPS := $$($1_SRC_FILE) $$($$($1_BASE)_COMPILE_VARDEPS_FILE) \
$$($$($1_BASE)_EXTRA_DEPS) $$($1_VARDEPS_FILE)
$1_COMPILE_OPTIONS := $$($1_FLAGS) $(CC_OUT_OPTION)$$($1_OBJ) $$($1_SRC_FILE)
# For reproducible builds with gcc ensure random symbol generation is seeded deterministically
ifeq ($(TOOLCHAIN_TYPE), gcc)
ifeq ($$(ENABLE_REPRODUCIBLE_BUILD), true)
$1_COMPILE_OPTIONS += -frandom-seed="$$($1_FILENAME)"
endif
endif
$$($1_OBJ_JSON): $$($1_OBJ_DEPS)
$$(call WriteCompileCommandsFragment, $$@, $$(PWD), $$($1_SRC_FILE), \
@@ -1149,19 +1143,6 @@ define SetupNativeCompilationBody
endif
endif
# Debuginfo of ASM objects always embeds the absolute object path,
# as ASM debuginfo paths do not get prefix mapped.
# So for reproducible builds use relative paths to ensure a reproducible
# debuginfo and libs, when creating debug symbols.
ifeq ($$(ENABLE_REPRODUCIBLE_BUILD), true)
ifeq ($(call isTargetOs, linux), true)
ifeq ($$($1_COMPILE_WITH_DEBUG_SYMBOLS), true)
$1_LINK_OBJS_RELATIVE := true
$1_ALL_OBJS_RELATIVE := $$(patsubst $$(OUTPUTDIR)/%, %, $$($1_ALL_OBJS))
endif
endif
endif
$1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \
$$($1_REAL_MAPFILE) $$($1_VARDEPS_FILE)

View File

@@ -58,9 +58,6 @@ ifeq ($(call check-jvm-feature, compiler2), true)
ADLC_CFLAGS += -I$(TOPDIR)/src/hotspot/share
# Add file macro mappings
ADLC_CFLAGS += $(FILE_MACRO_CFLAGS)
$(eval $(call SetupNativeCompilation, BUILD_ADLC, \
NAME := adlc, \
TYPE := EXECUTABLE, \

View File

@@ -84,7 +84,7 @@ ifneq ($(call check-jvm-feature, jvmti), true)
jvmtiImpl.cpp jvmtiManageCapabilities.cpp jvmtiRawMonitor.cpp jvmtiUtil.cpp jvmtiTrace.cpp \
jvmtiCodeBlobEvents.cpp jvmtiEnv.cpp jvmtiRedefineClasses.cpp jvmtiEnvBase.cpp jvmtiEnvThreadState.cpp \
jvmtiTagMap.cpp jvmtiEventController.cpp evmCompat.cpp jvmtiEnter.xsl jvmtiExport.cpp \
jvmtiClassFileReconstituter.cpp jvmtiTagMapTable.cpp jvmtiEnhancedRedefineClasses.cpp
jvmtiClassFileReconstituter.cpp jvmtiTagMapTable.cpp
endif
ifneq ($(call check-jvm-feature, jvmci), true)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 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
@@ -204,10 +204,6 @@ public class MakeZipReproducible {
entry.setTimeLocal(timestamp);
}
// Ensure "extra" field is not set from original ZipEntry info that may be not deterministic
// eg.may contain specific UID/GID
entry.setExtra(null);
zos.putNextEntry(entry);
if (entry.getSize() > 0 && entryInputStream != null) {
entryInputStream.transferTo(zos);

View File

@@ -372,12 +372,10 @@ public:
};
class AdjustMethodEntriesDcevm : public StackObj {
GrowableArray<oop>* _oops_to_update;
GrowableArray<Method*>* _old_methods;
bool* _trace_name_printed;
GrowableArray<oop>* _oops_to_add;
public:
AdjustMethodEntriesDcevm(GrowableArray<oop>* oops_to_update, GrowableArray<Method*>* old_methods) :
_oops_to_update(oops_to_update), _old_methods(old_methods) {};
AdjustMethodEntriesDcevm(GrowableArray<oop>* oops_to_add, bool* trace_name_printed) : _trace_name_printed(trace_name_printed), _oops_to_add(oops_to_add) {};
bool operator()(WeakHandle* entry) {
oop mem_name = entry->peek();
if (mem_name == NULL) {
@@ -388,8 +386,46 @@ public:
Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
if (old_method->is_old()) {
_oops_to_update->append(mem_name);
_old_methods->append(old_method);
InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
Method* newer_method;
// Method* new_method;
if (old_method->is_deleted()) {
newer_method = Universe::throw_no_such_method_error();
} else {
newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
log_debug(redefine, class, update)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string());
assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts");
assert(newer_method != NULL, "method_with_idnum() should not be NULL");
assert(old_method != newer_method, "sanity check");
Thread* thread = Thread::current();
ResolvedMethodTableLookup lookup(thread, method_hash(newer_method), newer_method);
ResolvedMethodGet rmg(thread, newer_method);
if (_local_table->get(thread, lookup, rmg)) {
// old method was already adjusted if new method exists in _the_table
return true;
}
}
java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method);
java_lang_invoke_ResolvedMethodName::set_vmholder(mem_name, newer_method->method_holder()->java_mirror());
newer_klass->set_has_resolved_methods();
_oops_to_add->append(mem_name);
ResourceMark rm;
if (!(*_trace_name_printed)) {
log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
*_trace_name_printed = true;
}
log_debug(redefine, class, update, constantpool)
("ResolvedMethod method update: %s(%s)",
newer_method->name()->as_C_string(), newer_method->signature()->as_C_string());
}
return true;
@@ -404,70 +440,36 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
_local_table->do_safepoint_scan(adjust);
}
// It is called at safepoint only for EnhancedRedefineClasses
// It is called at safepoint only for RedefineClasses
void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
GrowableArray<oop> oops_to_update(0);
GrowableArray<Method*> old_methods(0);
AdjustMethodEntriesDcevm adjust(&oops_to_update, &old_methods);
// For each entry in RMT, change to new method
GrowableArray<oop> oops_to_add(0);
AdjustMethodEntriesDcevm adjust(&oops_to_add, trace_name_printed);
_local_table->do_safepoint_scan(adjust);
Thread* thread = Thread::current();
for (int i = 0; i < oops_to_add.length(); i++) {
oop mem_name = oops_to_add.at(i);
Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
for (int i = 0; i < oops_to_update.length(); i++) {
oop mem_name = oops_to_update.at(i);
Method *old_method = old_methods.at(i);
// The hash table takes ownership of the WeakHandle, even if it's not inserted.
// 1. Remove old method, since we are going to update class that could be used for hash evaluation in parallel running ServiceThread
ResolvedMethodTableLookup lookup(thread, method_hash(old_method), old_method);
_local_table->remove(thread, lookup);
InstanceKlass* newer_klass = InstanceKlass::cast(old_method->method_holder()->new_version());
Method* newer_method;
// Method* new_method;
if (old_method->is_deleted()) {
newer_method = Universe::throw_no_such_method_error();
} else {
newer_method = newer_klass->method_with_idnum(old_method->orig_method_idnum());
assert(newer_method != NULL, "method_with_idnum() should not be NULL");
assert(newer_klass == newer_method->method_holder(), "call after swapping redefined guts");
assert(old_method != newer_method, "sanity check");
Thread* thread = Thread::current();
ResolvedMethodTableLookup lookup(thread, method_hash(newer_method), newer_method);
ResolvedMethodGet rmg(thread, newer_method);
ResolvedMethodTableLookup lookup(thread, method_hash(method), method);
ResolvedMethodGet rmg(thread, method);
while (true) {
if (_local_table->get(thread, lookup, rmg)) {
// old method was already adjusted if new method exists in _the_table
continue;
break;
}
WeakHandle wh(_oop_storage, mem_name);
// The hash table takes ownership of the WeakHandle, even if it's not inserted.
if (_local_table->insert(thread, lookup, wh)) {
log_insert(method);
wh.resolve();
break;
}
}
log_debug(redefine, class, update)("Adjusting method: '%s' of new class %s", newer_method->name_and_sig_as_C_string(), newer_klass->name()->as_C_string());
// 2. Update method
java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, newer_method);
java_lang_invoke_ResolvedMethodName::set_vmholder(mem_name, newer_method->method_holder()->java_mirror());
newer_klass->set_has_resolved_methods();
ResourceMark rm;
if (!(*trace_name_printed)) {
log_debug(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
*trace_name_printed = true;
}
log_debug(redefine, class, update, constantpool)
("ResolvedMethod method update: %s(%s)",
newer_method->name()->as_C_string(), newer_method->signature()->as_C_string());
// 3. add updated method to table again
add_method(newer_method, Handle(thread, mem_name));
}
}
#endif // INCLUDE_JVMTI

View File

@@ -117,7 +117,7 @@ const char* Abstract_VM_Version::vm_vendor() {
#ifdef VENDOR
return VENDOR;
#else
return "JetBrains s.r.o.";
return "Oracle Corporation";
#endif
}

View File

@@ -1337,7 +1337,6 @@ bool Arguments::add_property(const char* prop, PropertyWriteable writeable, Prop
log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value);
}
if (strcmp(key, "jdk.module.showModuleResolution") == 0 ||
strcmp(key, "jdk.module.illegalAccess") == 0 ||
strcmp(key, "jdk.module.validation") == 0 ||
strcmp(key, "java.system.class.loader") == 0) {
MetaspaceShared::disable_full_module_graph();
@@ -2132,8 +2131,7 @@ bool Arguments::parse_uintx(const char* value,
}
bool Arguments::create_module_property(const char* prop_name, const char* prop_value, PropertyInternal internal) {
assert(is_internal_module_property(prop_name) ||
strcmp(prop_name, "jdk.module.illegalAccess") == 0, "unknown module property: '%s'", prop_name);
assert(is_internal_module_property(prop_name), "unknown module property: '%s'", prop_name);
size_t prop_len = strlen(prop_name) + strlen(prop_value) + 2;
char* property = AllocateHeap(prop_len, mtArguments);
int ret = jio_snprintf(property, prop_len, "%s=%s", prop_name, prop_value);
@@ -2505,11 +2503,6 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m
char version[256];
JDK_Version::jdk(17).to_string(version, sizeof(version));
warning("Ignoring option %s; support was removed in %s", option->optionString, version);
} else if (match_option(option, "--jbr-illegal-access", &tail)) {
warning("Option --jbr-illegal-access is deprecated and will be removed in a future release.");
if (!create_module_property("jdk.module.illegalAccess", "permit", ExternalProperty)) {
return JNI_ENOMEM;
}
// -agentlib and -agentpath
} else if (match_option(option, "-agentlib:", &tail) ||
(is_absolute_path = match_option(option, "-agentpath:", &tail))) {
@@ -4034,7 +4027,7 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
// Set object alignment values.
set_object_alignment();
#if INCLUDE_JFR
#ifndef ZERO
if (FlightRecorder) {
if (AllowEnhancedClassRedefinition) {
warning("EnhancedClassRedefinition was disabled, it is not allowed in FlightRecorder.");

View File

@@ -16,8 +16,6 @@
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;
@@ -105,10 +103,9 @@ public class JBRApi {
JBRApi.outerLookup = outerLookup;
try {
Class<?> metadataClass = outerLookup.findClass("com.jetbrains.JBR$Metadata");
Lookup lookup = MethodHandles.privateLookupIn(metadataClass, outerLookup);
knownServices = Set.of((String[]) lookup.findStaticVarHandle(metadataClass,
knownServices = Set.of((String[]) outerLookup.findStaticVarHandle(metadataClass,
"KNOWN_SERVICES", String[].class).get());
knownProxies = Set.of((String[]) lookup.findStaticVarHandle(metadataClass,
knownProxies = Set.of((String[]) outerLookup.findStaticVarHandle(metadataClass,
"KNOWN_PROXIES", String[].class).get());
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
@@ -159,52 +156,13 @@ public class JBRApi {
RegisteredProxyInfo info = registeredProxyInfoByTargetName.get(targetName);
if (info == null) return null;
try {
return (info.type().isPublicApi() ? outerLookup : info.apiModule())
return (info.type() == ProxyInfo.Type.CLIENT_PROXY ? info.apiModule() : outerLookup)
.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.

View File

@@ -78,7 +78,7 @@ class ProxyGenerator {
*/
ProxyGenerator(ProxyInfo info) {
this.info = info;
generateBridge = info.type.isPublicApi();
generateBridge = info.type != ProxyInfo.Type.CLIENT_PROXY;
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.isService()) {
if (info.type == ProxyInfo.Type.SERVICE) {
try {
return MethodHandles.foldArguments(c, info.target.findConstructor(info.target.lookupClass(),
MethodType.methodType(void.class)).asType(MethodType.methodType(Object.class)));

View File

@@ -66,7 +66,7 @@ class ProxyInfo {
}
Lookup getInterfaceLookup() {
return type == Type.CLIENT_PROXY || type == Type.INTERNAL_SERVICE ? apiModule : JBRApi.outerLookup;
return type == Type.CLIENT_PROXY ? apiModule : JBRApi.outerLookup;
}
Lookup getTargetLookup() {
@@ -74,18 +74,12 @@ class ProxyInfo {
}
private Lookup lookup(Lookup lookup, String clazz) {
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;
}
try {
return MethodHandles.privateLookupIn(lookup.findClass(clazz), lookup);
} catch (ClassNotFoundException | IllegalAccessException e) {
if (lookup == JBRApi.outerLookup) return null;
else throw new RuntimeException(e);
}
return lookup;
}
record StaticMethodMapping(Lookup lookup, String methodName) {}
@@ -96,15 +90,6 @@ class ProxyInfo {
enum Type {
PROXY,
SERVICE,
CLIENT_PROXY,
INTERNAL_SERVICE;
public boolean isPublicApi() {
return this == PROXY || this == SERVICE;
}
public boolean isService() {
return this == SERVICE || this == INTERNAL_SERVICE;
}
CLIENT_PROXY
}
}

View File

@@ -68,14 +68,4 @@ class ExplodedSystemModules implements SystemModules {
public Map<String, Set<String>> moduleReads() {
throw new InternalError();
}
@Override
public Map<String, Set<String>> concealedPackagesToOpen() {
return Map.of();
}
@Override
public Map<String, Set<String>> exportedPackagesToOpen() {
return Map.of();
}
}

View File

@@ -1,130 +0,0 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.module;
import sun.nio.cs.UTF_8;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Generates the maps of concealed and exported packages to open at run-time.
*
* This is used at run-time for exploded builds, and at link-time to generate
* the maps for the system modules in the run-time image.
*/
public class IllegalAccessMaps {
private final Map<String, Set<String>> concealedPackagesToOpen;
private final Map<String, Set<String>> exportedPackagesToOpen;
private IllegalAccessMaps(Map<String, Set<String>> map1,
Map<String, Set<String>> map2) {
this.concealedPackagesToOpen = map1;
this.exportedPackagesToOpen = map2;
}
/**
* Returns the map of concealed packages to open. The map key is the
* module name, the value is the set of concealed packages to open.
*/
public Map<String, Set<String>> concealedPackagesToOpen() {
return concealedPackagesToOpen;
}
/**
* Returns the map of exported packages to open. The map key is the
* module name, the value is the set of exported packages to open.
*/
public Map<String, Set<String>> exportedPackagesToOpen() {
return exportedPackagesToOpen;
}
/**
* Generate the maps of module to concealed and exported packages for
* the system modules that are observable with the given module finder.
*/
public static IllegalAccessMaps generate(ModuleFinder finder) {
Map<String, ModuleDescriptor> map = new HashMap<>();
finder.findAll().stream()
.map(ModuleReference::descriptor)
.forEach(md -> md.packages().forEach(pn -> map.putIfAbsent(pn, md)));
Map<String, Set<String>> concealedPackagesToOpen = new HashMap<>();
Map<String, Set<String>> exportedPackagesToOpen = new HashMap<>();
String rn = "jdk8_packages.dat";
InputStream in = IllegalAccessMaps.class.getResourceAsStream(rn);
if (in == null) {
throw new InternalError(rn + " not found");
}
try (BufferedReader br = new BufferedReader(
new InputStreamReader(in, UTF_8.INSTANCE)))
{
br.lines()
.filter(line -> !line.isEmpty() && !line.startsWith("#"))
.forEach(pn -> {
ModuleDescriptor descriptor = map.get(pn);
if (descriptor != null && !isOpen(descriptor, pn)) {
String name = descriptor.name();
if (isExported(descriptor, pn)) {
exportedPackagesToOpen.computeIfAbsent(name,
k -> new HashSet<>()).add(pn);
} else {
concealedPackagesToOpen.computeIfAbsent(name,
k -> new HashSet<>()).add(pn);
}
}
});
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
return new IllegalAccessMaps(concealedPackagesToOpen, exportedPackagesToOpen);
}
private static boolean isExported(ModuleDescriptor descriptor, String pn) {
return descriptor.exports()
.stream()
.anyMatch(e -> e.source().equals(pn) && !e.isQualified());
}
private static boolean isOpen(ModuleDescriptor descriptor, String pn) {
return descriptor.opens()
.stream()
.anyMatch(e -> e.source().equals(pn) && !e.isQualified());
}
}

View File

@@ -147,8 +147,7 @@ public final class ModuleBootstrap {
getProperty("jdk.module.limitmods") == null && // --limit-modules
getProperty("jdk.module.addreads.0") == null && // --add-reads
getProperty("jdk.module.addexports.0") == null && // --add-exports
getProperty("jdk.module.addopens.0") == null && // --add-opens
getProperty("jdk.module.illegalAccess") == null; // --jbr-illegal-access
getProperty("jdk.module.addopens.0") == null; // --add-opens
}
/**
@@ -189,7 +188,6 @@ public final class ModuleBootstrap {
String mainModule = System.getProperty("jdk.module.main");
Set<String> addModules = addModules();
Set<String> limitModules = limitModules();
String illegalAccess = getAndRemoveProperty("jdk.module.illegalAccess");
PrintStream traceOutput = null;
String trace = getAndRemoveProperty("jdk.module.showModuleResolution");
@@ -221,8 +219,7 @@ public final class ModuleBootstrap {
&& !haveModulePath
&& addModules.isEmpty()
&& limitModules.isEmpty()
&& !isPatched
&& illegalAccess == null) {
&& !isPatched) {
systemModuleFinder = archivedModuleGraph.finder();
hasSplitPackages = archivedModuleGraph.hasSplitPackages();
hasIncubatorModules = archivedModuleGraph.hasIncubatorModules();
@@ -457,19 +454,10 @@ public final class ModuleBootstrap {
checkIncubatingStatus(cf);
}
// --add-reads, --add-exports/--add-opens, and --jbr-illegal-access
// --add-reads, --add-exports/--add-opens
addExtraReads(bootLayer);
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
if (illegalAccess != null) {
assert systemModules != null;
addIllegalAccess(illegalAccess,
systemModules,
upgradeModulePath,
bootLayer,
extraExportsOrOpens);
}
// add enable native access
addEnableNativeAccess(bootLayer);
@@ -825,74 +813,6 @@ public final class ModuleBootstrap {
return modules;
}
/**
* Process the --jbr-illegal-access option to open packages of system modules
* in the boot layer to code in unnamed modules.
*/
private static void addIllegalAccess(String illegalAccess,
SystemModules systemModules,
ModuleFinder upgradeModulePath,
ModuleLayer bootLayer,
boolean extraExportsOrOpens) {
Map<String, Set<String>> concealedPackagesToOpen = systemModules.concealedPackagesToOpen();
Map<String, Set<String>> exportedPackagesToOpen = systemModules.exportedPackagesToOpen();
if (concealedPackagesToOpen.isEmpty() && exportedPackagesToOpen.isEmpty()) {
// need to generate (exploded build)
IllegalAccessMaps maps = IllegalAccessMaps.generate(limitedFinder());
concealedPackagesToOpen = maps.concealedPackagesToOpen();
exportedPackagesToOpen = maps.exportedPackagesToOpen();
}
// open specific packages in the system modules
Set<String> emptySet = Set.of();
for (Module m : bootLayer.modules()) {
ModuleDescriptor descriptor = m.getDescriptor();
String name = m.getName();
// skip open modules
if (descriptor.isOpen()) {
continue;
}
// skip modules loaded from the upgrade module path
if (upgradeModulePath != null
&& upgradeModulePath.find(name).isPresent()) {
continue;
}
Set<String> concealedPackages = concealedPackagesToOpen.getOrDefault(name, emptySet);
Set<String> exportedPackages = exportedPackagesToOpen.getOrDefault(name, emptySet);
// refresh the set of concealed and exported packages if needed
if (extraExportsOrOpens) {
concealedPackages = new HashSet<>(concealedPackages);
exportedPackages = new HashSet<>(exportedPackages);
Iterator<String> iterator = concealedPackages.iterator();
while (iterator.hasNext()) {
String pn = iterator.next();
if (m.isExported(pn, BootLoader.getUnnamedModule())) {
// concealed package is exported to ALL-UNNAMED
iterator.remove();
exportedPackages.add(pn);
}
}
iterator = exportedPackages.iterator();
while (iterator.hasNext()) {
String pn = iterator.next();
if (m.isOpen(pn, BootLoader.getUnnamedModule())) {
// exported package is opened to ALL-UNNAMED
iterator.remove();
}
}
}
// open the packages to unnamed modules
JLA.addOpensToAllUnnamed(m, concealedPackages, exportedPackages);
}
}
/**
* Decodes the values of --add-reads, -add-exports, --add-opens or
* --patch-modules options that are encoded in system properties.

View File

@@ -83,16 +83,4 @@ interface SystemModules {
* by this SystemModules object.
*/
Map<String, Set<String>> moduleReads();
/**
* Returns the map of module concealed packages to open. The map key is the
* module name, the value is the set of concealed packages to open.
*/
Map<String, Set<String>> concealedPackagesToOpen();
/**
* Returns the map of module exported packages to open. The map key is the
* module name, the value is the set of exported packages to open.
*/
Map<String, Set<String>> exportedPackagesToOpen();
}

View File

@@ -188,10 +188,6 @@ java.launcher.X.usage=\n\
\ --add-opens <module>/<package>=<target-module>(,<target-module>)*\n\
\ updates <module> to open <package> to\n\
\ <target-module>, regardless of module declaration.\n\
\ --jbr-illegal-access\n\
\ permit access to members of types in named modules\n\
\ by code in unnamed modules.\n\
\ This option will be removed in a future release.\n\
\ --limit-modules <module name>[,<module name>...]\n\
\ limit the universe of observable modules\n\
\ --patch-module <module>=<file>({0}<file>)*\n\

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,6 @@ import java.awt.peer.KeyboardFocusManagerPeer;
import java.awt.peer.WindowPeer;
import java.util.List;
import java.util.Objects;
import javax.swing.JComponent;
import sun.awt.AWTAccessor;
@@ -284,16 +283,6 @@ public class LWWindowPeer
super.disposeImpl();
}
@Override
public void setBackground(final Color c) {
Color oldBg = getBackground();
if (Objects.equals(oldBg, c)) {
return;
}
super.setBackground(c);
updateOpaque();
}
@Override
protected void setVisibleImpl(final boolean visible) {
if (!visible && warningWindow != null) {
@@ -302,6 +291,10 @@ public class LWWindowPeer
updateFocusableWindowState();
super.setVisibleImpl(visible);
// TODO: update graphicsConfig, see 4868278
if (visible) {
// Set correct background for a window before making it visible
platformWindow.setOpaque(!isTranslucent());
}
platformWindow.setVisible(visible);
}

View File

@@ -38,10 +38,11 @@ import java.beans.PropertyChangeListener;
import java.lang.annotation.Native;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.PrivilegedAction;
import java.lang.reflect.Method;
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;
@@ -75,41 +76,24 @@ 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;
private static final boolean ENABLE_SHOW_CONTEXT_MENU_EVENT;
static {
// (-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 = value;
@SuppressWarnings("removal")
boolean enableShowContextMenuEvent = java.security.AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> {
return Boolean.getBoolean("sun.lwawt.macosx.CAccessibility.enableShowContextMenuEvent");
});
ENABLE_SHOW_CONTEXT_MENU_EVENT = enableShowContextMenuEvent;
}
private static boolean isEnableShowContextMenuEvent() {
return ENABLE_SHOW_CONTEXT_MENU_EVENT;
}
private static void accessibleShowContextMenuEvent(Accessible a, Component c) {
if (a == null) return;
invokeLater(new Runnable() {
@Override
public void run() {
AccessibleContext ac = a.getAccessibleContext();
if (ac != null) {
ac.firePropertyChange("accessibleContextMenuShow", null, null);
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;
}
}
}, c);
});
INVOKE_TIMEOUT_SECONDS = invokeTimeoutSecondsRef.get();
}
static CAccessibility sAccessibility;

View File

@@ -205,10 +205,8 @@ class CAccessible extends CFRetainedResource implements Accessible {
} else if (oldValue != null &&
((AccessibleState) oldValue) == AccessibleState.VISIBLE) {
execute(ptr -> menuClosed(ptr));
execute(ptr -> unregisterFromCocoaAXSystem(ptr));
}
} else if (thisRole == AccessibleRole.MENU_ITEM ||
((parentRole == AccessibleRole.POPUP_MENU) && (thisRole == AccessibleRole.MENU))) {
} else if (thisRole == AccessibleRole.MENU_ITEM) {
if (newValue != null &&
((AccessibleState) newValue) == AccessibleState.FOCUSED) {
execute(ptr -> menuItemSelected(ptr));

View File

@@ -25,7 +25,6 @@
package sun.lwawt.macosx;
import sun.awt.AWTThreading;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
@@ -65,14 +64,14 @@ public class CMenu extends CMenuItem implements MenuPeer {
LWCToolkit.targetToPeer(getTarget().getParent());
if (parent instanceof CMenu) {
return AWTThreading.executeWaitToolkit(() -> parent.executeGet(this::nativeCreateSubMenu));
return parent.executeGet(this::nativeCreateSubMenu);
}
if (parent instanceof CMenuBar) {
MenuBar parentContainer = (MenuBar)getTarget().getParent();
boolean isHelpMenu = parentContainer.getHelpMenu() == getTarget();
int insertionLocation = ((CMenuBar)parent).getNextInsertionIndex();
return AWTThreading.executeWaitToolkit(() -> parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
insertionLocation)));
return parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
insertionLocation));
}
throw new InternalError("Parent must be CMenu or CMenuBar");
}
@@ -85,7 +84,7 @@ public class CMenu extends CMenuItem implements MenuPeer {
@Override
public final void delItem(final int index) {
AWTThreading.executeWaitToolkit(() -> execute(ptr -> nativeDeleteItem(ptr, index)));
execute(ptr -> nativeDeleteItem(ptr, index));
}
@Override

View File

@@ -33,7 +33,6 @@ import java.awt.event.KeyEvent;
import java.awt.peer.MenuItemPeer;
import java.util.concurrent.atomic.AtomicBoolean;
import sun.awt.AWTThreading;
import sun.awt.SunToolkit;
import sun.lwawt.LWToolkit;
@@ -62,7 +61,7 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
@Override
long createModel() {
CMenuComponent parent = (CMenuComponent)LWToolkit.targetToPeer(getTarget().getParent());
return AWTThreading.executeWaitToolkit(() -> parent.executeGet(ptr->nativeCreate(ptr, isSeparator())));
return parent.executeGet(ptr->nativeCreate(ptr, isSeparator()));
}
@SuppressWarnings("deprecation")
public void setLabel(String label, char keyChar, int keyCode, int modifiers) {

View File

@@ -66,7 +66,6 @@ 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;
@@ -106,7 +105,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
private static native boolean nativeDelayShowing(long nsWindowPtr);
private static native void nativeRaiseLevel(long nsWindowPtr, boolean popup, boolean onlyIfParentIsActive);
private static native void nativeSetTransparentTitleBarHeight(long nsWindowPtr, float height);
private static native void nativeCallDeliverMoveResizeEvent(long nsWindowPtr);
// Loger to report issues happened during execution but that do not affect functionality
private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
@@ -292,7 +290,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 -> AWTThreading.executeWaitToolkit(wait -> nativeSetTransparentTitleBarHeight(ptr, (float) value)));
c.execute(ptr -> nativeSetTransparentTitleBarHeight(ptr, (float) value));
}
}
}
@@ -1197,10 +1195,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
responder.handleWindowFocusEvent(gained, oppositePeer);
}
public void doDeliverMoveResizeEvent() {
execute(ptr -> nativeCallDeliverMoveResizeEvent(ptr));
}
protected void deliverMoveResizeEvent(int x, int y, int width, int height,
boolean byUser) {
AtomicBoolean ref = new AtomicBoolean();
@@ -1462,20 +1456,28 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
isFullScreenAnimationOn = false;
}
// 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);
}
}
// 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;
}
return false;
}
}

View File

@@ -89,7 +89,6 @@ 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;
@@ -112,7 +111,6 @@ import sun.lwawt.PlatformComponent;
import sun.lwawt.PlatformDropTarget;
import sun.lwawt.PlatformWindow;
import sun.lwawt.SecurityWarningWindow;
import sun.security.action.GetBooleanAction;
import sun.util.logging.PlatformLogger;
@SuppressWarnings("serial") // JDK implementation class
@@ -142,13 +140,6 @@ public final class LWCToolkit extends LWToolkit {
private static CInputMethodDescriptor sInputMethodDescriptor;
// Listens to EDT state in invokeAndWait() and disposes the invocation event
// when EDT becomes free but the invocation event is not yet dispatched (considered lost).
// This prevents a deadlock and makes the invocation return some default result.
@SuppressWarnings("removal")
private static final boolean DISPOSE_INVOCATION_ON_EDT_FREE =
AccessController.doPrivileged(new GetBooleanAction("sun.lwawt.macosx.LWCToolkit.invokeAndWait.disposeOnEDTFree"));
static {
System.err.flush();
@@ -195,7 +186,7 @@ public final class LWCToolkit extends LWToolkit {
*/
private static final boolean inAWT;
private static final PlatformLogger log = PlatformLogger.getLogger(LWCToolkit.class.getName());
private static final PlatformLogger log = PlatformLogger.getLogger("sun.lwawt.macosx.LWCToolkit");
public LWCToolkit() {
final String extraButtons = "sun.awt.enableExtraMouseButtons";
@@ -504,8 +495,7 @@ public final class LWCToolkit extends LWToolkit {
if (!(gd instanceof CGraphicsDevice)) {
return AWTThreading.executeWaitToolkit(() -> super.getScreenInsets(gc));
}
CGraphicsDevice cgd = (CGraphicsDevice) gd;
return cgd.getScreenInsets();
return AWTThreading.executeWaitToolkit(() -> ((CGraphicsDevice)gd).getScreenInsets());
}
@Override
@@ -685,12 +675,30 @@ public final class LWCToolkit extends LWToolkit {
return invokeAndWait(callable, component, -1);
}
public static <T> T invokeAndWait(final Callable<T> callable, Component component, int timeoutSeconds) throws Exception {
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;
@@ -720,6 +728,30 @@ public final class LWCToolkit extends LWToolkit {
}
}
private static final AtomicInteger blockingRunLoopCounter = new AtomicInteger(0);
private static final AtomicBoolean priorityInvocationPending = new AtomicBoolean(false);
@Override
public void unsafeNonblockingExecute(Runnable runnable) {
if (!EventQueue.isDispatchThread()) {
throw new Error("the method must be called on the Event Dispatching thread");
}
if (runnable == null) return;
synchronized (priorityInvocationPending) {
priorityInvocationPending.set(true);
}
AWTAccessor.getEventQueueAccessor().createSecondaryLoop(
getSystemEventQueue(),
() -> blockingRunLoopCounter.get() > 0).enter();
try {
runnable.run();
} finally {
priorityInvocationPending.set(false);
}
}
/**
* Kicks an event over to the appropriate eventqueue and waits for it to
* finish To avoid deadlocking, we manually run the NSRunLoop while waiting
@@ -744,32 +776,32 @@ public final class LWCToolkit extends LWToolkit {
invokeAndWait(runnable, component, false, -1);
}
public static void invokeAndWait(Runnable runnable, Component component, boolean processEvents, int timeoutSeconds)
static void invokeAndWait(Runnable runnable, Component component, boolean processEvents, int timeoutSeconds)
throws InvocationTargetException
{
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("invokeAndWait started: " + runnable);
}
if (isBlockingEventDispatchThread()) {
String msg = "invokeAndWait is discarded as the EventDispatch thread is currently blocked";
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine(msg, new Throwable());
log.fine(AWTThreading.getInstance(component).printEventDispatchThreadStackTrace().toString());
} else if (log.isLoggable(PlatformLogger.Level.INFO)) {
StackTraceElement[] stack = new Throwable().getStackTrace();
log.info(msg + ". Originated at " + stack[stack.length - 1]);
Thread dispatchThread = AWTThreading.getInstance(component).getEventDispatchThread();
log.info(dispatchThread.getName() + " at: " + dispatchThread.getStackTrace()[0].toString());
}
return;
boolean nonBlockingRunLoop;
CancelableRunnable cancelableRunnable = new CancelableRunnable(runnable);
synchronized (priorityInvocationPending) {
nonBlockingRunLoop = priorityInvocationPending.get();
if (!nonBlockingRunLoop) blockingRunLoopCounter.incrementAndGet();
}
AWTThreading.TrackedInvocationEvent invocationEvent =
AWTThreading.createAndTrackInvocationEvent(component, runnable, true);
final long mediator = createAWTRunLoopMediator();
long mediator = createAWTRunLoopMediator();
invocationEvent.onDone(() -> stopAWTRunLoop(mediator));
InvocationEvent invocationEvent =
AWTThreading.createAndTrackInvocationEvent(component,
cancelableRunnable,
() -> {
if (mediator != 0) {
stopAWTRunLoop(mediator);
}
},
true);
if (component != null) {
AppContext appContext = SunToolkit.targetToAppContext(component);
@@ -783,21 +815,11 @@ public final class LWCToolkit extends LWToolkit {
((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent);
}
if (DISPOSE_INVOCATION_ON_EDT_FREE) {
CompletableFuture<Void> eventDispatchThreadFreeFuture =
AWTThreading.getInstance(component).onEventDispatchThreadFree(() -> {
if (!invocationEvent.isCompleted(true)) {
// 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, false, timeoutSeconds)) {
invocationEvent.dispose("InvocationEvent has timed out");
if (!doAWTRunLoop(mediator, nonBlockingRunLoop, timeoutSeconds)) {
new Throwable("Invocation timed out (" + timeoutSeconds + "sec)").printStackTrace();
cancelableRunnable.cancel();
}
if (!nonBlockingRunLoop) blockingRunLoopCounter.decrementAndGet();
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("invokeAndWait finished: " + runnable);
@@ -806,8 +828,6 @@ public final class LWCToolkit extends LWToolkit {
checkException(invocationEvent);
}
private static native boolean isBlockingEventDispatchThread();
public static void invokeLater(Runnable event, Component component)
throws InvocationTargetException {
Objects.requireNonNull(component, "Null component provided to invokeLater");
@@ -850,11 +870,6 @@ public final class LWCToolkit extends LWToolkit {
*/
static native void performOnMainThreadAfterDelay(Runnable r, long delay);
/**
* Schedules a {@code Runnable} execution on the Appkit thread and waits for completion.
*/
public static native void performOnMainThreadAndWait(Runnable r);
// DnD support
@Override

View File

@@ -50,10 +50,6 @@
NSWindowTabbingMode javaWindowTabbingMode;
BOOL isEnterFullScreen;
CGFloat _transparentTitleBarHeight;
id<NSObject> _windowWillEnterFullScreenNotification;
id<NSObject> _windowWillExitFullScreenNotification;
id<NSObject> _windowDidExitFullScreenNotification;
NSMutableArray* _transparentTitleBarConstraints;
NSLayoutConstraint *_transparentTitleBarHeightConstraint;
NSMutableArray *_transparentTitleBarButtonCenterXConstraints;
}

View File

@@ -26,7 +26,6 @@
#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"
@@ -776,7 +775,7 @@ AWT_ASSERT_APPKIT_THREAD;
// NSWindowDelegate methods
- (void) _deliverMoveResizeEvent {
AWT_ASSERT_APPKIT_THREAD;
AWT_ASSERT_APPKIT_THREAD;
// deliver the event if this is a user-initiated live resize or as a side-effect
// of a Java initiated resize, because AppKit can override the bounds and force
@@ -785,19 +784,11 @@ AWT_ASSERT_APPKIT_THREAD;
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
if (platformWindow == NULL) {
NSLog(@"[AWTWindow _deliverMoveResizeEvent]: platformWindow == NULL");
return;
}
NSRect frame;
@try {
frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
} @catch (NSException *e) {
NSLog(@"WARNING: suppressed exception from ConvertNSScreenRect() in [AWTWindow _deliverMoveResizeEvent]");
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
[NSApplicationAWT logException:e forProcess:processInfo];
return;
// TODO: create generic AWT assert
}
NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
GET_CPLATFORM_WINDOW_CLASS();
DECLARE_METHOD(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIIIZ)V");
(*env)->CallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent,
@@ -1018,7 +1009,7 @@ AWT_ASSERT_APPKIT_THREAD;
#ifdef DEBUG
NSLog(@"resigned key: %d %@ %@", [self.nsWindow isMainWindow], [self.nsWindow title], [self menuBarForWindow]);
#endif
if (![self.nsWindow isMainWindow] || [NSApp keyWindow] == self.nsWindow) {
if (![self.nsWindow isMainWindow]) {
[self deactivateWindow];
}
}
@@ -1047,9 +1038,7 @@ AWT_ASSERT_APPKIT_THREAD;
NSWindow *keyWindow = [NSApp keyWindow];
AWTWindow *opposite = nil;
if ([AWTWindow isAWTWindow: keyWindow]) {
if (keyWindow != self.nsWindow) {
opposite = (AWTWindow *)[keyWindow delegate];
}
opposite = (AWTWindow *)[keyWindow delegate];
[AWTWindow setLastKeyWindow: self];
} else {
[AWTWindow setLastKeyWindow: nil];
@@ -1305,10 +1294,10 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
NSView* titlebarContainer = titlebar.superview;
NSView* themeFrame = titlebarContainer.superview;
_transparentTitleBarConstraints = [[NSMutableArray alloc] init];
NSMutableArray* newConstraints = [[NSMutableArray alloc] init];
titlebarContainer.translatesAutoresizingMaskIntoConstraints = NO;
_transparentTitleBarHeightConstraint = [titlebarContainer.heightAnchor constraintEqualToConstant:_transparentTitleBarHeight];
[_transparentTitleBarConstraints addObjectsFromArray:@[
[newConstraints addObjectsFromArray:@[
[titlebarContainer.leftAnchor constraintEqualToAnchor:themeFrame.leftAnchor],
[titlebarContainer.widthAnchor constraintEqualToAnchor:themeFrame.widthAnchor],
[titlebarContainer.topAnchor constraintEqualToAnchor:themeFrame.topAnchor],
@@ -1321,7 +1310,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
for (NSView* view in @[titlebar, windowDragView])
{
view.translatesAutoresizingMaskIntoConstraints = NO;
[_transparentTitleBarConstraints addObjectsFromArray:@[
[newConstraints addObjectsFromArray:@[
[view.leftAnchor constraintEqualToAnchor:titlebarContainer.leftAnchor],
[view.rightAnchor constraintEqualToAnchor:titlebarContainer.rightAnchor],
[view.topAnchor constraintEqualToAnchor:titlebarContainer.topAnchor],
@@ -1337,7 +1326,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];
[_transparentTitleBarConstraints addObjectsFromArray:@[
[newConstraints 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],
@@ -1346,7 +1335,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
]];
}];
[NSLayoutConstraint activateConstraints:_transparentTitleBarConstraints];
[NSLayoutConstraint activateConstraints:newConstraints];
}
- (void) updateTransparentTitleBarConstraints
@@ -1372,22 +1361,20 @@ 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;
}
@@ -1416,44 +1403,23 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
});
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];
_windowWillEnterFullScreenNotification = [defaultCenter addObserverForName:NSWindowWillEnterFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
[defaultCenter addObserverForName:NSWindowWillEnterFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
[self resetTitleBar];
}];
_windowWillExitFullScreenNotification = [defaultCenter addObserverForName:NSWindowWillExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
[defaultCenter addObserverForName:NSWindowWillExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
[self setWindowControlsHidden:YES];
}];
_windowDidExitFullScreenNotification = [defaultCenter addObserverForName:NSWindowDidExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
[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 (transparentTitleBarHeight == 0.0f) {
[self configureWindowAndListenersForDefaultTitleBar];
} else if (_transparentTitleBarHeightConstraint != nil || _transparentTitleBarButtonCenterXConstraints != nil) {
if (_transparentTitleBarHeightConstraint != nil || _transparentTitleBarButtonCenterXConstraints != nil) {
[self updateTransparentTitleBarConstraints];
}
} else {
@@ -1489,18 +1455,11 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
if (platformWindow != NULL) {
GET_CPLATFORM_WINDOW_CLASS_RETURN(YES);
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);
}
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);
(*env)->DeleteLocalRef(env, platformWindow);
}
return returnValue;
@@ -1653,15 +1612,7 @@ JNI_COCOA_ENTER(env);
// resets the NSWindow's style mask if the mask intersects any of those bits
if (mask & MASK(_STYLE_PROP_BITMASK)) {
NSWindowStyleMask styleMask = [AWTWindow styleMaskForStyleBits:newBits];
@try {
[nsWindow setStyleMask:styleMask];
} @catch (NSException *e) {
NSLog(@"WARNING: suppressed exception from [NSWindow setStyleMask] in CPlatformWindow"
".nativeSetNSWindowStyleBits");
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
[NSApplicationAWT logException:e forProcess:processInfo];
}
[nsWindow setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
}
// calls methods on NSWindow to change other properties, based on the mask
@@ -2349,18 +2300,4 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetTransparen
[window setTransparentTitleBarHeight:((CGFloat) transparentTitleBarHeight)];
JNI_COCOA_EXIT(env);
}
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeCallDeliverMoveResizeEvent
(JNIEnv *env, jclass clazz, jlong windowPtr)
{
JNI_COCOA_ENTER(env);
NSWindow *nsWindow = (NSWindow *)jlong_to_ptr(windowPtr);
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
AWTWindow *window = (AWTWindow*)[nsWindow delegate];
[window _deliverMoveResizeEvent];
}];
JNI_COCOA_EXIT(env);
}
}

View File

@@ -237,7 +237,7 @@ static BOOL sNeedsEnter;
jobject transferer = [self dataTransferer:env];
jbyteArray data = nil;
if (transferer != NULL && fComponent != NULL) {
if (transferer != NULL) {
GET_DT_CLASS_RETURN(NULL);
DECLARE_METHOD_RETURN(convertDataMethod, DataTransfererClass, "convertData", "(Ljava/lang/Object;Ljava/awt/datatransfer/Transferable;JLjava/util/Map;Z)[B", NULL);
data = (*env)->CallObjectMethod(env, transferer, convertDataMethod, fComponent, fTransferable, format, fFormatMap, (jboolean) TRUE);

View File

@@ -69,9 +69,6 @@ static int* gsButtonEventNumber;
static NSTimeInterval gNextKeyEventTime;
static NSTimeInterval safeDelay;
#define KEY_CODE_COUNT 128
static CGEventFlags keyOwnFlags[KEY_CODE_COUNT];
static inline CGKeyCode GetCGKeyCode(jint javaKeyCode);
static void PostMouseEvent(const CGPoint point, CGMouseButton button,
@@ -110,20 +107,6 @@ static inline void autoDelay(BOOL isMove) {
gNextKeyEventTime = [[NSDate date] timeIntervalSinceReferenceDate] + safeDelay;
}
static void initKeyFlags() {
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStatePrivate);
for (CGKeyCode keyCode = 0; keyCode < KEY_CODE_COUNT; keyCode++) {
CGEventRef event = CGEventCreateKeyboardEvent(source, keyCode, true);
if (event != NULL) {
keyOwnFlags[keyCode] = CGEventGetFlags(event);
CFRelease(event);
}
}
if (source != NULL) {
CFRelease(source);
}
}
/*
* Class: sun_lwawt_macosx_CRobot
* Method: initRobot
@@ -172,8 +155,6 @@ Java_sun_lwawt_macosx_CRobot_initRobot
for (i = 0; i < gNumberOfButtons; ++i) {
gsButtonEventNumber[i] = ROBOT_EVENT_NUMBER_START;
}
initKeyFlags();
}];
}
}
@@ -302,20 +283,6 @@ Java_sun_lwawt_macosx_CRobot_mouseWheel
}];
}
// CGEventCreateKeyboardEvent incorrectly handles flags pertinent to non-modifier keys
// (e.g. F1-F12 keys always Fn flag set, while arrow keys always have Fn and NumPad flags set).
// Those flags are not cleared for following key presses automatically, so we need to do it ourselves.
// See JBR-4306 for details.
static void clearStickyFlags(CGEventRef event, CGKeyCode keyCode, CGEventFlags flagToCheck) {
if (keyCode < KEY_CODE_COUNT && (keyOwnFlags[keyCode] & flagToCheck) == 0) {
CGEventFlags flags = CGEventGetFlags(event);
CGEventFlags updatedFlags = flags & ~flagToCheck;
if (updatedFlags != flags) {
CGEventSetFlags(event, updatedFlags);
}
}
}
/*
* Class: sun_lwawt_macosx_CRobot
* Method: keyEvent
@@ -331,10 +298,6 @@ Java_sun_lwawt_macosx_CRobot_keyEvent
CGKeyCode keyCode = GetCGKeyCode(javaKeyCode);
CGEventRef event = CGEventCreateKeyboardEvent(source, keyCode, keyPressed);
if (event != NULL) {
// this assumes Robot isn't used to generate Fn key presses
clearStickyFlags(event, keyCode, kCGEventFlagMaskSecondaryFn);
// there is no NumPad key, so this won't hurt in any case
clearStickyFlags(event, keyCode, kCGEventFlagMaskNumericPad);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}

View File

@@ -620,17 +620,6 @@ JNI_COCOA_EXIT(env);
return result;
}
/*
* Class: sun_lwawt_macosx_LWCToolkit
* Method: isBlockingEventDispatchThread
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isBlockingEventDispatchThread
(JNIEnv *env, jclass clz)
{
return ThreadUtilities.blockingEventDispatchThread;
}
/*
* Class: sun_lwawt_macosx_LWCToolkit
* Method: stopAWTRunLoop
@@ -643,8 +632,6 @@ 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];
@@ -670,23 +657,6 @@ JNI_COCOA_ENTER(env);
JNI_COCOA_EXIT(env);
}
/*
* Class: sun_lwawt_macosx_LWCToolkit
* Method: performOnMainThreadAndWait
* Signature: (Ljava/lang/Runnable)V
*/
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_performOnMainThreadAndWait
(JNIEnv *env, jclass clz, jobject runnable)
{
JNI_COCOA_ENTER(env);
jobject gRunnable = (*env)->NewGlobalRef(env, runnable);
CHECK_NULL(gRunnable);
[ThreadUtilities performOnMainThreadWaiting:YES block:^() {
JavaRunnable* performer = [[JavaRunnable alloc] initWithRunnable:gRunnable];
[performer perform];
}];
JNI_COCOA_EXIT(env);
}
/*
* Class: sun_lwawt_macosx_LWCToolkit

View File

@@ -126,7 +126,7 @@ static jobject sAccessibilityClass = NULL;
/*
* Here we should keep all the mapping between the accessibility roles and implementing classes
*/
rolesMap = [[NSMutableDictionary alloc] initWithCapacity:50];
rolesMap = [[NSMutableDictionary alloc] initWithCapacity:51];
[rolesMap setObject:@"ButtonAccessibility" forKey:@"pushbutton"];
[rolesMap setObject:@"ImageAccessibility" forKey:@"icon"];
@@ -158,6 +158,7 @@ static jobject sAccessibilityClass = NULL;
[rolesMap setObject:@"TableAccessibility" forKey:@"table"];
[rolesMap setObject:@"MenuBarAccessibility" forKey:@"menubar"];
[rolesMap setObject:@"MenuAccessibility" forKey:@"menu"];
[rolesMap setObject:@"MenuItemAccessibility" forKey:@"menuitem"];
[rolesMap setObject:@"MenuAccessibility" forKey:@"popupmenu"];
[rolesMap setObject:@"ProgressIndicatorAccessibility" forKey:@"progressbar"];
@@ -185,11 +186,10 @@ static jobject sAccessibilityClass = NULL;
[rolesMap setObject:IgnoreClassName forKey:@"viewport"];
[rolesMap setObject:IgnoreClassName forKey:@"window"];
rowRolesMapForParent = [[NSMutableDictionary alloc] initWithCapacity:3];
rowRolesMapForParent = [[NSMutableDictionary alloc] initWithCapacity:2];
[rowRolesMapForParent setObject:@"ListRowAccessibility" forKey:@"ListAccessibility"];
[rowRolesMapForParent setObject:@"OutlineRowAccessibility" forKey:@"OutlineAccessibility"];
[rowRolesMapForParent setObject:@"MenuItemAccessibility" forKey:@"MenuAccessibility"];
/*
* Initialize CAccessibility instance
@@ -1186,25 +1186,7 @@ static jobject sAccessibilityClass = NULL;
// NSAccessibilityActions methods
- (BOOL)isEnableShowMenuEvent
{
static NSNumber *sEnableShowContextMenuEvent = nil;
if (sEnableShowContextMenuEvent == nil) {
JNIEnv *env = [ThreadUtilities getJNIEnv];
GET_CACCESSIBILITY_CLASS_RETURN(NO);
DECLARE_STATIC_METHOD_RETURN(sjm_enableShowMenuEvent, sjc_CAccessibility, "isEnableShowContextMenuEvent", "()Z", NO);
sEnableShowContextMenuEvent = [[NSNumber alloc] initWithBool:(*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, sjm_enableShowMenuEvent)];
CHECK_EXCEPTION();
}
return sEnableShowContextMenuEvent.boolValue;
}
- (BOOL)isAccessibilitySelectorAllowed:(SEL)selector {
if ([self isEnableShowMenuEvent] &&
[NSStringFromSelector(selector) isEqualToString:@"accessibilityPerformShowMenu"]) {
return YES;
}
if ([sAllActionSelectors containsObject:NSStringFromSelector(selector)] &&
![[self actionSelectors] containsObject:NSStringFromSelector(selector)]) {
return NO;
@@ -1221,14 +1203,6 @@ static jobject sAccessibilityClass = NULL;
}
- (BOOL)accessibilityPerformShowMenu {
if ([self isEnableShowMenuEvent]) {
JNIEnv *env = [ThreadUtilities getJNIEnv];
GET_CACCESSIBILITY_CLASS_RETURN(NO);
DECLARE_STATIC_METHOD_RETURN(sjm_accessibleShowContextMenuEvent, sjc_CAccessibility, "accessibleShowContextMenuEvent", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)V", NO);
(*env)->CallStaticVoidMethod(env, sjc_CAccessibility, sjm_accessibleShowContextMenuEvent, fAccessible, fComponent);
CHECK_EXCEPTION();
return YES;
}
return [self accessiblePerformAction:NSAccessibilityShowMenuAction];
}

View File

@@ -39,7 +39,7 @@
- (BOOL)isAccessibilityElement
{
return [[[self accessibilityParent] accessibilityRole] isEqualToString:NSAccessibilityComboBoxRole];
return YES;
}
@end

View File

@@ -3371,7 +3371,7 @@ JNI_COCOA_ENTER(env);
anotherBaseFont = true;
}
CTFontRef font = (CTFontRef)nsFont;
CFArrayRef codes = CFLocaleCopyPreferredLanguages();
CFArrayRef codes = CFLocaleCopyISOLanguageCodes();
CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes);
CFRelease(codes);

View File

@@ -127,13 +127,6 @@ do { \
__attribute__((visibility("default")))
@interface ThreadUtilities : NSObject { } /* Extend NSObject so can call performSelectorOnMainThread */
/*
* When a blocking performSelectorOnMainThread is executed from the EventDispatch thread,
* and the executed code triggers an opposite blocking a11y call (via LWCToolkit.invokeAndWait)
* this is a deadlock case, and then this property is used to discard LWCToolkit.invokeAndWait.
*/
@property (class, nonatomic, readonly) BOOL blockingEventDispatchThread;
+ (JNIEnv*)getJNIEnv;
+ (JNIEnv*)getJNIEnvUncached;
+ (void)detachCurrentThread;

View File

@@ -50,24 +50,6 @@ static inline void attachCurrentThread(void** env) {
@implementation ThreadUtilities
static BOOL _blockingEventDispatchThread = NO;
static long eventDispatchThreadPtr = (long)nil;
static BOOL isEventDispatchThread() {
return (long)[NSThread currentThread] == eventDispatchThreadPtr;
}
// The [blockingEventDispatchThread] property is readonly, so we implement a private setter
static void setBlockingEventDispatchThread(BOOL value) {
assert([NSThread isMainThread]);
_blockingEventDispatchThread = value;
}
+ (BOOL) blockingEventDispatchThread {
assert([NSThread isMainThread]);
return _blockingEventDispatchThread;
}
+ (void)initialize {
/* All the standard modes plus ours */
javaModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode,
@@ -100,10 +82,10 @@ AWT_ASSERT_APPKIT_THREAD;
}
/* This is needed because we can't directly pass a block to
* performSelectorOnMainThreadWaiting:..waitUntilDone:YES.. since it expects a selector
* performSelectorOnMainThreadWaiting .. since it expects a selector
*/
+ (void)invokeBlock:(void (^)())block {
block();
block();
}
/*
@@ -134,19 +116,7 @@ AWT_ASSERT_APPKIT_THREAD;
if ([NSThread isMainThread] && wait == YES) {
[target performSelector:aSelector withObject:arg];
} else {
if (wait && isEventDispatchThread()) {
void (^block)(void) = ^{
setBlockingEventDispatchThread(YES);
@try {
[target performSelector:aSelector withObject:arg];
} @finally {
setBlockingEventDispatchThread(NO);
}
};
[self performSelectorOnMainThread:@selector(invokeBlock:) withObject:block waitUntilDone:YES modes:javaModes];
} else {
[target performSelectorOnMainThread:aSelector withObject:arg waitUntilDone:wait modes:javaModes];
}
[target performSelectorOnMainThread:aSelector withObject:arg waitUntilDone:wait modes:javaModes];
}
}
@@ -173,16 +143,3 @@ JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CThreading_isMainThread
return [NSThread isMainThread];
}
/*
* Class: sun_awt_AWTThreading
* Method: notifyEventDispatchThreadStartedNative
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_AWTThreading_notifyEventDispatchThreadStartedNative
(JNIEnv *env, jclass c)
{
@synchronized([ThreadUtilities class]) {
eventDispatchThreadPtr = (long)[NSThread currentThread];
}
}

View File

@@ -30,7 +30,6 @@ 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")
.service("com.jetbrains.CustomWindowDecoration", "java.awt.Window$CustomWindowDecoration");
.proxy("com.jetbrains.JBRFileDialog", "com.jetbrains.desktop.JBRFileDialog");
}
}

View File

@@ -31,7 +31,6 @@ import java.awt.event.WindowEvent;
import java.util.ArrayList;
import sun.awt.AWTThreading;
import sun.util.logging.PlatformLogger;
import sun.awt.dnd.SunDragSourceContextPeer;
@@ -87,7 +86,6 @@ class EventDispatchThread extends Thread {
}
public void run() {
AWTThreading.getInstance(Thread.currentThread()).notifyEventDispatchThreadStarted();
try {
pumpEvents(new Conditional() {
public boolean evaluate() {
@@ -99,8 +97,6 @@ class EventDispatchThread extends Thread {
}
}
private static native void registerEventDispatchThread();
void pumpEvents(Conditional cond) {
pumpEvents(ANY_EVENT, cond);
}

View File

@@ -358,7 +358,6 @@ public class EventQueue {
if (shouldNotify) {
if (theEvent.getSource() != AWTAutoShutdown.getInstance()) {
AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
AWTThreading.getInstance(dispatchThread).notifyEventDispatchThreadBusy();
}
pushPopCond.signalAll();
} else if (notifyID) {
@@ -571,7 +570,6 @@ public class EventQueue {
return event;
}
AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
AWTThreading.getInstance(dispatchThread).notifyEventDispatchThreadFree();
pushPopCond.await();
} finally {
pushPopLock.unlock();
@@ -1130,7 +1128,6 @@ public class EventQueue {
t.setPriority(Thread.NORM_PRIORITY + 1);
t.setDaemon(false);
AWTAutoShutdown.getInstance().notifyThreadBusy(t);
AWTThreading.getInstance(t).notifyEventDispatchThreadBusy();
return t;
}
}
@@ -1161,7 +1158,6 @@ 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

View File

@@ -46,17 +46,13 @@ 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;
@@ -68,7 +64,6 @@ 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;
@@ -4012,66 +4007,7 @@ 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;
}
@@ -4079,7 +4015,6 @@ public class Window extends Container implements Accessible {
/**
* Set via reflection (JB JdkEx API).
*/
@Deprecated
void setHasCustomDecoration() {
hasCustomDecoration = true;
}

View File

@@ -5,33 +5,18 @@ import sun.util.logging.PlatformLogger;
import java.awt.*;
import java.awt.event.InvocationEvent;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Consumer;
/**
* 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(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 static final PlatformLogger logger = PlatformLogger.getLogger("sun.awt.AWTThreading");
private ExecutorService executor;
// every invokeAndWait() pushes a queue of invocations
@@ -39,21 +24,13 @@ 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> {}
/**
* WARNING: for testing purpose, use {@link AWTThreading#getInstance(Thread)} instead.
*/
public AWTThreading(Thread edt) {
eventDispatchThread = edt;
}
private AWTThreading() {}
/**
* Executes a callable from EventDispatch thread (EDT). It's assumed the callable either performs a blocking execution on Toolkit
@@ -78,25 +55,14 @@ public class AWTThreading {
}
/**
* A boolean value passed to the consumer indicates whether the consumer should perform
* a synchronous invocation on the Toolkit thread and wait, or return immediately.
*
* @see #executeWaitToolkit(Callable).
* Same as {@link #executeWaitToolkit(Callable)}, but without returning a value. If requested (as indicated by
* the passed parameter), the invoked native method is supposed to wait for the result of invocation on AppKit
* thread, and vice versa.
*/
public static void executeWaitToolkit(Consumer<Boolean> consumer) {
public static void executeWaitToolkit(Task runnable) {
boolean wait = EventQueue.isDispatchThread();
executeWaitToolkit(() -> {
consumer.accept(wait);
return null;
});
}
/**
* @see #executeWaitToolkit(Callable).
*/
public static void executeWaitToolkit(Runnable runnable) {
executeWaitToolkit(() -> {
runnable.run();
runnable.run(wait);
return null;
});
}
@@ -116,6 +82,12 @@ public class AWTThreading {
}
}
if (!isEDT && logger.isLoggable(PlatformLogger.Level.FINE)) {
// this can cause deadlock if calling thread is holding a lock which EDT might require (e.g. AWT tree lock)
logger.fine("AWTThreading.executeWaitToolkit invoked from non-EDT thread", new Throwable());
}
// fallback to default
try {
return callable.call();
} catch (Exception e) {
@@ -206,15 +178,8 @@ 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 TrackedInvocationEvent createAndTrackInvocationEvent(Object source,
Runnable onDispatched,
boolean catchThrowables)
{
public static InvocationEvent createAndTrackInvocationEvent(Object source, Runnable runnable, Runnable listener, boolean catchThrowables) {
AWTThreading instance = getInstance(source);
if (instance != null) {
synchronized (instance.invocations) {
@@ -222,234 +187,68 @@ public class AWTThreading {
instance.invocations.push(new TrackingQueue());
}
final TrackingQueue queue = instance.invocations.peek();
final AtomicReference<TrackedInvocationEvent> eventRef = new AtomicReference<>();
final InvocationEvent[] eventRef = new InvocationEvent[1];
eventRef.set(TrackedInvocationEvent.create(
source,
onDispatched,
new Runnable() {
final WeakReference<TrackingQueue> queueRef = new WeakReference<>(queue);
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);
@Override
public void run() {
TrackingQueue queue = queueRef.get();
queueRef.clear();
if (queue != null) {
queue.remove(eventRef.get());
@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;
}
}
},
catchThrowables)
{
@Override
public void dispatch() {
if (!isDispatched()) {
super.dispatch();
}
},
catchThrowables));
queue.add(eventRef.get());
return eventRef.get();
}
});
return eventRef[0];
}
}
return TrackedInvocationEvent.create(source, onDispatched, () -> {}, catchThrowables);
return new InvocationEvent(source, runnable, listener, catchThrowables);
}
@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<>();
// dispatch or dispose has been started or already completed
private final AtomicBoolean isCompletionStarted = 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.completeIfNotYet(() ->
// 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() {
completeIfNotYet(super::dispatch);
futureResult.complete(null);
}
public void dispose(String reason) {
completeIfNotYet(() -> AWTAccessor.getInvocationEventAccessor().dispose(this));
futureResult.completeExceptionally(new Throwable(reason));
}
private void completeIfNotYet(Runnable competeRunnable) {
if (!isCompletionStarted.getAndSet(true)) {
competeRunnable.run();
}
}
/**
* Returns whether the event is dispatched or disposed.
*/
public boolean isCompleted() {
return futureResult.isDone();
}
/**
* Returns whether the event is dispatched or disposed.
* If {@code isCompletionInProgress} is true then also checks whether the event
* dispatching or disposal is in progress and if so returns true.
*/
public boolean isCompleted(boolean isCompletionInProgress) {
return isCompleted() || (isCompletionInProgress && isCompletionStarted.get());
}
/**
* 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());
}
private static AWTThreading getInstance(Object obj) {
if (obj == null) return null;
AppContext appContext = SunToolkit.targetToAppContext(obj);
if (appContext == null) {
return getInstance(Toolkit.getDefaultToolkit().getSystemEventQueue());
}
if (appContext == null) return null;
return getInstance((EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY));
}
public static AWTThreading getInstance(EventQueue eq) {
private static AWTThreading getInstance(EventQueue eq) {
if (eq == null) return null;
return getInstance(AWTAccessor.getEventQueueAccessor().getDispatchThread(eq));
}
public static AWTThreading getInstance(Thread edt) {
assert edt != null;
private static AWTThreading getInstance(Thread edt) {
if (edt == null) return null;
return EDT_TO_INSTANCE_MAP.computeIfAbsent(edt, key -> theAWTThreadingFactory.get().apply(edt));
return EDT_TO_INSTANCE_MAP.computeIfAbsent(edt, key -> new AWTThreading());
}
public Thread getEventDispatchThread() {
return eventDispatchThread;
}
public StringWriter printEventDispatchThreadStackTrace() {
return printEventDispatchThreadStackTrace(new StringWriter());
}
public StringWriter printEventDispatchThreadStackTrace(StringWriter writer) {
assert writer != null;
var printer = new PrintWriter(writer);
Thread dispatchThread = getEventDispatchThread();
printer.println(dispatchThread.getName());
Arrays.asList(dispatchThread.getStackTrace()).forEach(frame -> printer.append("\tat ").println(frame));
return writer;
}
/**
* Sets {@code AWTThreading} instance factory.
* WARNING: for testing purpose.
*/
public static void setAWTThreadingFactory(Function<Thread, AWTThreading> factory) {
theAWTThreadingFactory.set(factory);
}
/**
* Must be called on the EventDispatch thread.
*/
public void notifyEventDispatchThreadStarted() {
if (FontUtilities.isMacOSX) notifyEventDispatchThreadStartedNative();
}
private static native void notifyEventDispatchThreadStartedNative();
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 {
void run(boolean wait);
}
}

View File

@@ -781,12 +781,19 @@ abstract class XDecoratedPeer extends XWindowPeer {
return;
}
/*
* Some window managers configure before we are reparented and
* the send event flag is set! ugh... (Enlighetenment for one,
* possibly MWM as well). If we haven't been reparented yet
* this is just the WM shuffling us into position. Ignore
* it!!!! or we wind up in a bogus location.
*/
int runningWM = XWM.getWMID();
if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
insLog.fine("reparented={0}, visible={1}, WM={2}, decorations={3}",
isReparented(), isVisible(), runningWM, getDecorations());
}
if (ENABLE_REPARENTING_CHECK && !isReparented() && isVisible() && runningWM != XWM.NO_WM
if (!isReparented() && isVisible() && runningWM != XWM.NO_WM
&& !XWM.isNonReparentingWM()
&& getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
insLog.fine("- visible but not reparented, skipping");

View File

@@ -52,8 +52,6 @@ import sun.awt.X11GraphicsEnvironment;
import sun.java2d.pipe.Region;
import sun.util.logging.PlatformLogger;
import sun.security.action.GetPropertyAction;
class XWindowPeer extends XPanelPeer implements WindowPeer,
DisplayChangedListener {
@@ -63,11 +61,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
private static final PlatformLogger grabLog = PlatformLogger.getLogger("sun.awt.X11.grab.XWindowPeer");
private static final PlatformLogger iconLog = PlatformLogger.getLogger("sun.awt.X11.icon.XWindowPeer");
static final boolean ENABLE_REPARENTING_CHECK
= "true".equals(GetPropertyAction.privilegedGetProperty("reparenting.check"));
private static final boolean ENABLE_DESKTOP_CHECK
= "true".equals(GetPropertyAction.privilegedGetProperty("transients.desktop.check", "true"));
// should be synchronized on awtLock
private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>();
@@ -97,9 +90,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
private static final AtomicBoolean isStartupNotificationRemoved = new AtomicBoolean();
private Long desktopId; // guarded by AWT lock
private boolean desktopIdInvalid; // guarded by AWT lock
/*
* Focus related flags
*/
@@ -164,7 +154,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
params.put(EVENT_MASK, eventMask);
XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE");
XA_NET_WM_DESKTOP = XAtom.get("_NET_WM_DESKTOP");
params.put(OVERRIDE_REDIRECT, Boolean.valueOf(isOverrideRedirect()));
@@ -758,8 +747,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
int runningWM = XWM.getWMID();
Point newLocation = targetBounds.getLocation();
if (xe.get_send_event() ||
(ENABLE_REPARENTING_CHECK ? (runningWM == XWM.NO_WM || XWM.isNonReparentingWM()) : !isReparented())) {
if (xe.get_send_event() || runningWM == XWM.NO_WM || XWM.isNonReparentingWM()) {
// Location, Client size + insets
newLocation = new Point(scaleDown(xe.get_x()) - leftInset,
scaleDown(xe.get_y()) - topInset);
@@ -1455,14 +1443,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
isUnhiding |= isWMStateNetHidden();
super.handleMapNotifyEvent(xev);
if (!ENABLE_REPARENTING_CHECK && delayedModalBlocking) {
// case of non-re-parenting WM
// (for a re-parenting WM this should have been already done on ReparentNotify processing)
addToTransientFors(AWTAccessor.getComponentAccessor().getPeer(modalBlocker));
delayedModalBlocking = false;
}
if (isBeforeFirstMapNotify && !winAttr.initialFocus && shouldSuppressWmTakeFocus()) {
suppressWmTakeFocus(false); // restore the protocol.
if (!XWM.isKDE2()) {
@@ -1682,7 +1662,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
}
modalBlocker = d;
if (isReparented() || ENABLE_REPARENTING_CHECK && XWM.isNonReparentingWM()) {
if (isReparented() || XWM.isNonReparentingWM()) {
addToTransientFors(blockerPeer, javaToplevels);
} else {
delayedModalBlocking = true;
@@ -1693,7 +1673,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
}
modalBlocker = null;
if (isReparented() || ENABLE_REPARENTING_CHECK && XWM.isNonReparentingWM()) {
if (isReparented() || XWM.isNonReparentingWM()) {
removeFromTransientFors();
} else {
delayedModalBlocking = false;
@@ -1736,7 +1716,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
if (!allStates && (window.getWMState() != transientForWindow.getWMState())) {
return;
}
if (screenOrDesktopDiffers(window, transientForWindow)) {
if (window.getScreenNumber() != transientForWindow.getScreenNumber()) {
return;
}
long bpw = window.getWindow();
@@ -1773,7 +1753,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
void updateTransientFor() {
int state = getWMState();
XWindowPeer p = prevTransientFor;
while ((p != null) && ((p.getWMState() != state) || screenOrDesktopDiffers(p, this))) {
while ((p != null) && ((p.getWMState() != state) || (p.getScreenNumber() != getScreenNumber()))) {
p = p.prevTransientFor;
}
if (p != null) {
@@ -1782,7 +1762,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
restoreTransientFor(this);
}
XWindowPeer n = nextTransientFor;
while ((n != null) && ((n.getWMState() != state) || screenOrDesktopDiffers(n, this))) {
while ((n != null) && ((n.getWMState() != state) || (n.getScreenNumber() != getScreenNumber()))) {
n = n.nextTransientFor;
}
if (n != null) {
@@ -1790,38 +1770,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
}
}
private Long getDesktopId() {
XToolkit.awtLock();
try {
if (desktopIdInvalid) {
desktopIdInvalid = false;
desktopId = null;
WindowPropertyGetter getter =
new WindowPropertyGetter(window, XA_NET_WM_DESKTOP, 0, 1, false, XAtom.XA_CARDINAL);
try {
if (getter.execute() == XConstants.Success &&
getter.getActualType() == XAtom.XA_CARDINAL &&
getter.getActualFormat() == 32) {
long ptr = getter.getData();
if (ptr != 0) {
desktopId = Native.getCard32(ptr);
}
}
} finally {
getter.dispose();
}
}
return desktopId;
} finally {
XToolkit.awtUnlock();
}
}
private static boolean screenOrDesktopDiffers(XWindowPeer p1, XWindowPeer p2) {
return p1.getScreenNumber() != p2.getScreenNumber() ||
ENABLE_DESKTOP_CHECK && !Objects.equals(p1.getDesktopId(), p2.getDesktopId());
}
/*
* Removes the TRANSIENT_FOR hint from the given top-level window.
* If window or transientForWindow are embedded frames, the containing
@@ -2201,7 +2149,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
cachedFocusableWindow = isFocusableWindow();
}
XAtom XA_NET_WM_DESKTOP;
XAtom XA_NET_WM_STATE;
XAtomList net_wm_state;
public XAtomList getNETWMState() {
@@ -2218,18 +2165,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
}
}
@Override
public void handlePropertyNotify(XEvent xev) {
super.handlePropertyNotify(xev);
XPropertyEvent ev = xev.get_xproperty();
if (ev.get_atom() == XA_NET_WM_DESKTOP.getAtom()) {
desktopIdInvalid = true;
if (ENABLE_DESKTOP_CHECK) {
updateTransientFor();
}
}
}
public PropMwmHints getMWMHints() {
if (mwm_hints == null) {
mwm_hints = new PropMwmHints();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -583,8 +583,6 @@ cleanup:
XFree (pVI8sg);
if (n1sg != 0)
XFree (pVI1sg);
if (nTrue != 0)
XFree (pVITrue);
}
/*
@@ -1432,9 +1430,6 @@ Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env,
break;
}
}
AWT_LOCK();
XdbeFreeVisualInfo(visScreenInfo);
AWT_UNLOCK();
}
/*

View File

@@ -55,11 +55,8 @@ 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;
@@ -994,29 +991,31 @@ 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) {
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);
}
this.customDecorHitTestSpots = new CopyOnWriteArrayList<>(hitTestSpots);
}
// called from client via reflection
@Deprecated
private void setCustomDecorationTitleBarHeight(int height) {
try {
Field f = Window.class.getDeclaredField("customDecorTitleBarHeight");
f.setAccessible(true);
f.set(target, height);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new Error(e);
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;
}
return false;
}
// called from native
private int getCustomDecorationTitleBarHeight() {
return customDecorTitleBarHeight;
}
}

View File

@@ -1646,9 +1646,6 @@ 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;
@@ -2333,9 +2330,6 @@ 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;

View File

@@ -525,7 +525,6 @@ 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);

View File

@@ -37,7 +37,6 @@
#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>
@@ -623,23 +622,6 @@ 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:
@@ -671,24 +653,6 @@ 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)
@@ -1706,7 +1670,7 @@ BOOL AwtFrame::HasCustomDecoration()
if (!m_pHasCustomDecoration) {
m_pHasCustomDecoration = new BOOL;
JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
*m_pHasCustomDecoration = JNU_GetFieldByName(env, NULL, GetTarget(env), "hasCustomDecoration", "Z").z;
*m_pHasCustomDecoration = JNU_CallMethodByName(env, NULL, GetTarget(env), "hasCustomDecoration", "()Z").z;
}
return *m_pHasCustomDecoration;
}
@@ -1748,8 +1712,10 @@ 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_GetFieldByName(env, NULL, frame->GetTarget(env),
"customDecorTitleBarHeight", "I").i;
int titleHeight = (int)JNU_CallMethodByName(env, NULL, frame->GetPeer(env),
"getCustomDecorationTitleBarHeight", "()I",
frame->ScaleDownX(x - rcWindow.left),
frame->ScaleDownY(y - rcWindow.top)).i;
if (titleHeight >= 0) {
titleHeight = frame->ScaleUpY(titleHeight);
insets.top = titleHeight; // otherwise leave default
@@ -1762,23 +1728,12 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) {
if (y >= rcWindow.top &&
y < rcWindow.top + insets.top)
{
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;
if (JNU_CallMethodByName(env, NULL, frame->GetPeer(env),
"hitTestCustomDecoration", "(II)Z",
frame->ScaleDownX(x - rcWindow.left),
frame->ScaleDownY(y - rcWindow.top)).z)
{
return HTNOWHERE;
}
fOnResizeBorder = (y < (rcWindow.top - rcFrame.top));
uRow = 0;

View File

@@ -111,7 +111,6 @@ 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);

View File

@@ -60,7 +60,6 @@ import java.util.stream.Collectors;
import jdk.internal.module.Checks;
import jdk.internal.module.DefaultRoots;
import jdk.internal.module.IllegalAccessMaps;
import jdk.internal.module.Modules;
import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleInfo.Attributes;
@@ -622,9 +621,6 @@ public final class SystemModulesPlugin extends AbstractPlugin {
// generate moduleReads
genModuleReads(cw, cf);
// generate concealedPackagesToOpen and exportedPackagesToOpen
genXXXPackagesToOpenMethods(cw);
return cw;
}
@@ -855,16 +851,6 @@ public final class SystemModulesPlugin extends AbstractPlugin {
generate(cw, "moduleReads", map, true);
}
/**
* Generate concealedPackagesToOpen and exportedPackagesToOpen methods.
*/
private void genXXXPackagesToOpenMethods(ClassWriter cw) {
ModuleFinder finder = finderOf(moduleInfos);
IllegalAccessMaps maps = IllegalAccessMaps.generate(finder);
generate(cw, "concealedPackagesToOpen", maps.concealedPackagesToOpen(), false);
generate(cw, "exportedPackagesToOpen", maps.exportedPackagesToOpen(), false);
}
/**
* Generate method to return {@code Map<String, Set<String>>}.
*

View File

@@ -1,117 +0,0 @@
/*
* 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;
}
}
}

View File

@@ -66,15 +66,6 @@ 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);
}
@@ -103,11 +94,6 @@ public class JBR {
<T> T getService(Class<T> interFace);
}
@FunctionalInterface
private interface FallbackSupplier<T> {
T get() throws Throwable;
}
// ========================== Generated metadata ==========================
/**

View File

@@ -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,23 +102,15 @@ 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("\\*", "\\\\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*")
);
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+([^;]+);");
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(",")) {
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 + ";");
if (!namePattern.matcher(s).find()) continue;
statements.add("public static final " + statementMatcher.group(2) + " " + s.strip() + ";");
}
}
break;
@@ -172,7 +164,7 @@ public class Gensrc {
}
private static Service[] findPublicServiceInterfaces() {
Pattern javadocPattern = Pattern.compile("/\\*\\*((?:.|\n)*?)\\s*\\*/");
Pattern javadocPattern = Pattern.compile("/\\*\\*((?:.|\n)*?)(\s|\n)*\\*/");
return modules.services.stream()
.map(fullName -> {
if (fullName.indexOf('$') != -1) return null; // Only top level services can be public
@@ -194,8 +186,7 @@ public class Gensrc {
javadocEnd = 0;
}
return new Service(name, javadoc,
content.substring(javadocEnd, indexOfDeclaration).contains("@Deprecated"),
content.contains("__Fallback"));
content.substring(javadocEnd, indexOfDeclaration).contains("@Deprecated"));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
@@ -206,7 +197,7 @@ public class Gensrc {
private static String generateMethodsForService(Service service) {
return """
private static class $__Holder {<DEPRECATED>
private static final $ INSTANCE = getService($.class, <FALLBACK>);
private static final $ INSTANCE = api != null ? api.getService($.class) : null;
}
/**
* @return true if current runtime has implementation for all methods in {@link $}
@@ -223,13 +214,12 @@ 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, boolean hasFallback) {}
private record Service(String name, String javadoc, boolean deprecated) {}
}
/**
@@ -250,7 +240,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);

View File

@@ -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.4
VERSION = 0.0.2
# 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 = 74417FA361EA554F9C90873A3FF354
HASH = 814F29888E5EB6C23DF27B53636E9F94

View File

@@ -1,104 +0,0 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, JetBrains s.r.o.. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @summary Test implementation of NSAccessibilityMenu and NSAccessibilityMenuItem roles peer
* @author Artem.Semenov@jetbrains.com
* @run main/manual AccessibleJPopupMenuTest
* @requires (os.family == "mac")
*/
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.concurrent.CountDownLatch;
public class AccessibleJPopupMenuTest extends AccessibleComponentTest {
@Override
public CountDownLatch createCountDownLatch() {
return new CountDownLatch(1);
}
private static JPopupMenu createPopup() {
JPopupMenu popup = new JPopupMenu("MENU");
popup.add("One");
popup.add("Two");
popup.add("Three");
popup.addSeparator();
JMenu menu = new JMenu("For submenu");
menu.add("subOne");
menu.add("subTwo");
menu.add("subThree");
popup.add(menu);
return popup;
}
public void createTest() {
INSTRUCTIONS = "INSTRUCTIONS:\n"
+ "Check a11y of JPopupMenu.\n\n"
+ "Turn screen reader on, and Tab to the show button and press space.\n"
+ "Press the up and down arrow buttons to move through the menu, and open submenu.\n\n"
+ "If you can hear popup menu items tab further and press PASS, otherwise press FAIL.\n";
JPanel frame = new JPanel();
JButton button = new JButton("show");
button.setPreferredSize(new Dimension(100, 35));
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
createPopup().show(button, button.getX(), button.getY());
}
});
frame.setLayout(new FlowLayout());
frame.add(button);
exceptionString = "Accessible JPopupMenu test failed!";
super.createUI(frame, "Accessible JPopupMenu test");
}
public static void main(String[] args) throws Exception {
AccessibleJPopupMenuTest a11yTest = new AccessibleJPopupMenuTest();
CountDownLatch countDownLatch = a11yTest.createCountDownLatch();
SwingUtilities.invokeLater(a11yTest::createTest);
countDownLatch.await();
if (!testResult) {
throw new RuntimeException(a11yTest.exceptionString);
}
}
}

View File

@@ -1,106 +0,0 @@
/*
* 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);
}
}

View File

@@ -1,53 +0,0 @@
/*
* 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);
}
}

View File

@@ -35,13 +35,13 @@ public class ProxyInfoResolvingTest {
JBRApi.ModuleRegistry r = init();
// No mapping defined -> null
requireNull(getProxy(ProxyInfoResolvingTest.class));
// Invalid JBR-side target class -> null
// Invalid JBR-side target class -> error
r.proxy(InterfaceWithoutImplementation.class.getName(), "absentImpl");
requireNull(getProxy(InterfaceWithoutImplementation.class));
// Invalid JBR-side target static method mapping -> null
mustFail(() -> getProxy(InterfaceWithoutImplementation.class), RuntimeException.class, ClassNotFoundException.class);
// Invalid JBR-side target static method mapping -> error
r.service(ServiceWithoutImplementation.class.getName(), null)
.withStatic("someMethod", "NoClass");
requireNull(getProxy(ServiceWithoutImplementation.class));
mustFail(() -> getProxy(ServiceWithoutImplementation.class), RuntimeException.class, ClassNotFoundException.class);
// Service without target class or static method mapping -> null
r.service(EmptyService.class.getName(), null);
requireNull(getProxy(EmptyService.class));

View File

@@ -1,85 +0,0 @@
/*
* 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 javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
/**
* @test
* @summary Regression test for JBR-4281 Window losing focus isn't detected in some cases on macOS
* @key headful
* @requires (os.family == "mac")
*/
public class MacSpecialFocusLostCase {
private static Robot robot;
private static JFrame frame;
public static void main(String[] args) throws Exception {
robot = new Robot();
robot.setAutoDelay(50);
try {
SwingUtilities.invokeAndWait(MacSpecialFocusLostCase::initUI);
checkFocusedStatus(true);
pressCmdSpace(); // open Spotlight popup
checkFocusedStatus(false);
pressEsc(); // close Spotlight popup
checkFocusedStatus(true);
} finally {
pressEsc(); // make sure popup is closed in any case
SwingUtilities.invokeAndWait(MacSpecialFocusLostCase::disposeUI);
}
}
private static void initUI() {
frame = new JFrame("MacSpecialFocusLostCase");
frame.setBounds(200, 200, 300, 200);
frame.setVisible(true);
}
private static void disposeUI() {
if (frame != null) frame.dispose();
}
private static void checkFocusedStatus(boolean expected) throws Exception {
robot.delay(1000);
boolean[] result = new boolean[1];
SwingUtilities.invokeAndWait(() -> result[0] = frame.isFocused());
if (result[0] != expected) {
throw new RuntimeException(expected ? "Frame isn't focused" : "Frame is still focused");
}
}
private static void pressCmdSpace() {
robot.keyPress(KeyEvent.VK_META);
robot.keyPress(KeyEvent.VK_SPACE);
robot.keyRelease(KeyEvent.VK_SPACE);
robot.keyRelease(KeyEvent.VK_META);
}
private static void pressEsc() {
robot.keyPress(KeyEvent.VK_ESCAPE);
robot.keyRelease(KeyEvent.VK_ESCAPE);
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright 2000-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.
*/
/*
@test
@key headful
@summary a regression test for JBR-4303.
@run main GetPointerInfoTest
*/
import java.awt.*;
/**
* The test checks <code>MouseInfo.getPointerInfo()</code> for all locations with the steps <code>X_STEP</code> and
* <code>Y_STEP</code> on all graphic devices.
* It moves mouse to the current location via <code>Robot.mouseMove()</code> and checks that
* <code>MouseInfo.getPointerInfo()</code> is not NULL.
* It also checks <code>MouseInfo.getPointerInfo().getLocation()</code> returns expected values.
*/
public class GetPointerInfoTest {
public static int X_STEP = 100;
public static int Y_STEP = 100;
static boolean isPassed = true;
public static void main(String[] args) throws Exception {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] graphicsDevices = ge.getScreenDevices();
for (GraphicsDevice gd : graphicsDevices) {
String name = gd.getIDstring();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();
System.out.println("Check for device: " + name + " " + width + "x" + height);
Robot robot = new Robot(gd);
robot.setAutoDelay(0);
robot.setAutoWaitForIdle(true);
robot.delay(10);
robot.waitForIdle();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
Rectangle bounds = gc.getBounds();
for (double y = bounds.getY(); y < bounds.getY() + bounds.getHeight(); y += Y_STEP) {
for (double x = bounds.getX(); x < bounds.getX() + bounds.getWidth(); x += X_STEP) {
Point p = new Point((int)x, (int)y);
System.out.println("\tmouse move to x=" + p.x + " y=" + p.y);
robot.mouseMove(p.x, p.y);
System.out.print("\t\tMouseInfo.getPointerInfo.getLocation");
PointerInfo pi = MouseInfo.getPointerInfo();
if (pi == null) {
throw new RuntimeException("Test failed. getPointerInfo() returned null value.");
}
Point piLocation = pi.getLocation();
if (piLocation.x != p.x || piLocation.y != p.y) {
System.out.println(" - ***FAILED*** x=" + piLocation.x + " y=" + piLocation.y);
isPassed = false;
} else {
System.out.println(" x=" + p.x + ", y=" + p.y + " - passed");
}
}
}
}
if ( !isPassed )
throw new RuntimeException("PointerInfo.getLocation() returns unexpected value(s).");
System.out.println("Test PASSED.");
}
}

View File

@@ -1,71 +0,0 @@
// Copyright 2000-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
import javax.swing.*;
import java.util.function.Consumer;
import static helper.ToolkitTestHelper.*;
import static helper.ToolkitTestHelper.TestCase.*;
/*
* @test
* @summary tests that CMenu/CMenuItem methods wrapped with {AWTThreading.executeWaitToolkit} are normally callable
* @requires (os.family == "mac")
* @modules java.desktop/sun.lwawt.macosx java.desktop/sun.awt
* @run main/othervm -Dapple.laf.useScreenMenuBar=true AWTThreadingCMenuTest
* @author Anton Tarasov
*/
public class AWTThreadingCMenuTest {
public static void main(String[] args) {
initTest(AWTThreadingCMenuTest.class);
testCase().
withCaption("populate Menu").
withRunnable(AWTThreadingCMenuTest::test1, true).
withExpectedInLog("discarded", false).
withCompletionTimeout(1).
run();
testCase().
withCaption("de-populate Menu").
withRunnable(AWTThreadingCMenuTest::test2, true).
withExpectedInLog("discarded", false).
withCompletionTimeout(1).
run();
System.out.println("Test PASSED");
}
@SuppressWarnings("deprecation")
private static void test1() {
var bar = new JMenuBar();
FRAME.setJMenuBar(bar);
var menu = new JMenu("Menu");
Consumer<String> addItem = text -> {
var item = new JMenuItem(text);
item.setLabel("label " + text);
menu.add(item);
menu.addSeparator();
};
addItem.accept("one");
addItem.accept("two");
addItem.accept("three");
bar.add(menu);
TEST_CASE_RESULT.complete(true);
}
private static void test2() {
var bar = FRAME.getJMenuBar();
var menu = bar.getMenu(0);
for (int i = 0; i < FRAME.getJMenuBar().getMenuCount(); i++) {
menu.remove(i);
}
TEST_CASE_RESULT.complete(true);
}
}

View File

@@ -1,134 +1,140 @@
// Copyright 2000-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
import java.awt.*;
import java.util.Arrays;
import java.util.concurrent.*;
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;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
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 sun.awt.AWTThreading;
import static helper.ToolkitTestHelper.*;
import static helper.ToolkitTestHelper.TestCase.*;
import javax.swing.*;
/*
* @test
* @summary tests that AWTThreading can manage cross EDT/AppKit blocking invocation requests
* @summary tests that AWTThreading can manage a stream of cross EDT/AppKit invocation requests
* @requires (os.family == "mac")
* @modules java.desktop/sun.lwawt.macosx java.desktop/sun.awt
* @run main AWTThreadingTest
* @compile --add-exports=java.desktop/sun.lwawt.macosx=ALL-UNNAMED --add-exports=java.desktop/sun.awt=ALL-UNNAMED AWTThreadingTest.java
* @run main/othervm --add-exports=java.desktop/sun.lwawt.macosx=ALL-UNNAMED --add-exports=java.desktop/sun.awt=ALL-UNNAMED AWTThreadingTest
* @author Anton Tarasov
*/
@SuppressWarnings("ConstantConditions")
public class AWTThreadingTest {
static final int TIMEOUT_SECONDS = 1;
static final ReentrantLock LOCK = new ReentrantLock();
static final Condition COND = LOCK.newCondition();
static final CountDownLatch LATCH = new CountDownLatch(1);
static final AtomicInteger ITER_COUNTER = new AtomicInteger();
static final AtomicBoolean DUMP_STACK = new AtomicBoolean(false);
static JFrame frame;
static Thread thread;
static volatile Thread THREAD;
final static AtomicBoolean passed = new AtomicBoolean(true);
final static AtomicInteger counter = new AtomicInteger(0);
public static void main(String[] args) {
DUMP_STACK.set(args.length > 0 && "dumpStack".equals(args[0]));
public static void main(String[] args) throws InterruptedException {
EventQueue.invokeLater(AWTThreadingTest::runGui);
initTest(AWTThreadingTest.class);
LATCH.await(5, TimeUnit.SECONDS);
testCase().
withCaption("certain threads superposition").
withRunnable(AWTThreadingTest::test, false).
run();
testCase().
withCaption("random threads superposition").
withRunnable(AWTThreadingTest::test, false).
run();
frame.dispose();
thread.interrupt();
if (!passed.get()) {
throw new RuntimeException("Test FAILED!");
}
System.out.println("Test PASSED");
}
static void test() {
ITER_COUNTER.set(0);
var timer = new TestTimer(TIMEOUT_SECONDS * 3, TimeUnit.SECONDS);
EventQueue.invokeLater(() -> startThread(() ->
TEST_CASE_RESULT.isDone() ||
timer.hasFinished()));
waitTestCaseCompletion(TIMEOUT_SECONDS * 4);
tryRun(THREAD::join);
System.out.println(ITER_COUNTER + " iterations passed");
static void runGui() {
frame = new JFrame("frame");
frame.setLocationRelativeTo(null);
frame.setSize(200, 200);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
startThread();
}
});
frame.setVisible(true);
}
static void startThread(Supplier<Boolean> shouldExitLoop) {
THREAD = new Thread(() -> {
while (!shouldExitLoop.get()) {
ITER_COUNTER.incrementAndGet();
var point_1 = new CountDownLatch(1);
var point_2 = new CountDownLatch(1);
var point_3 = new CountDownLatch(1);
var invocations = new CountDownLatch(2);
static void startThread() {
thread = new Thread(() -> {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
//
// 1. Blocking invocation from AppKit to EDT
// 1. Execute invokeAndWait() from AppKit to EDT
//
CThreading.executeOnAppKit(() -> {
// We're on AppKit, wait for the 2nd invocation to be on the AWTThreading-pool thread.
if (TEST_CASE_NUM == 1) await(point_1, TIMEOUT_SECONDS);
tryRun(() -> LWCToolkit.invokeAndWait(() -> {
// We're being dispatched on EDT.
if (TEST_CASE_NUM == 1) point_2.countDown();
// Wait for the 2nd invocation to be executed on AppKit.
if (TEST_CASE_NUM == 1) await(point_3, TIMEOUT_SECONDS);
}, FRAME));
invocations.countDown();
try {
LWCToolkit.invokeAndWait(counter::incrementAndGet, Window.getWindows()[0]);
} catch (Exception e) {
fail(e);
}
});
//
// 2. Blocking invocation from EDT to AppKit
// 2. Execute invokeAndBlock() from EDT to AppKit
//
EventQueue.invokeLater(() -> AWTThreading.executeWaitToolkit(() -> {
// We're on the AWTThreading-pool thread.
if (TEST_CASE_NUM == 1) point_1.countDown();
EventQueue.invokeLater(() -> {
passed.set(false);
// Wait for the 1st invocation to start NSRunLoop and be dispatched
if (TEST_CASE_NUM == 1) await(point_2, TIMEOUT_SECONDS);
// Perform in JavaRunLoopMode to be accepted by NSRunLoop started by LWCToolkit.invokeAndWait.
LWCToolkit.performOnMainThreadAndWait(() -> {
if (DUMP_STACK.get()) {
dumpAllThreads();
Boolean success = InvokeOnToolkitHelper.invokeAndBlock(() -> {
try {
return CThreading.executeOnAppKit(() -> Boolean.TRUE);
} catch (Throwable e) {
fail(e);
}
// We're being executed on AppKit.
if (TEST_CASE_NUM == 1) point_3.countDown();
return null;
});
System.out.println("Success: " + counter.get() + ": " + success);
invocations.countDown();
}));
passed.set(Boolean.TRUE.equals(success));
await(invocations, TIMEOUT_SECONDS * 2);
} // while
if (passed.get()) {
lock(COND::signal);
}
else {
fail(null);
}
});
TEST_CASE_RESULT.complete(true);
lock(COND::await);
}
});
THREAD.setDaemon(true);
THREAD.start();
thread.setDaemon(true);
thread.start();
}
static void dumpAllThreads() {
Thread.getAllStackTraces().keySet().forEach(t -> {
System.out.printf("%s\t%s\t%d\t%s\n", t.getName(), t.getState(), t.getPriority(), t.isDaemon() ? "Daemon" : "Normal");
Arrays.asList(t.getStackTrace()).forEach(frame -> System.out.println("\tat " + frame));
});
System.out.println("\n\n");
static void lock(MyRunnable runnable) {
LOCK.lock();
try {
try {
runnable.run();
} catch (Exception e) {
e.printStackTrace();
}
} finally {
LOCK.unlock();
}
}
interface MyRunnable {
void run() throws Exception;
}
static void fail(Throwable e) {
if (e != null) e.printStackTrace();
passed.set(false);
LATCH.countDown();
}
}

View File

@@ -1,193 +0,0 @@
// Copyright 2000-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
import java.awt.*;
import java.awt.event.InvocationEvent;
import java.util.concurrent.*;
import java.util.function.Consumer;
import sun.awt.AWTAccessor;
import sun.awt.AWTThreading;
import sun.lwawt.macosx.CThreading;
import sun.lwawt.macosx.LWCToolkit;
import static helper.ToolkitTestHelper.*;
import static helper.ToolkitTestHelper.TestCase.*;
/*
* @test
* @summary Tests different scenarios for LWCToolkit.invokeAndWait().
* @requires (os.family == "mac")
* @modules java.desktop/sun.lwawt.macosx java.desktop/sun.awt
* @run main/othervm -Dsun.lwawt.macosx.LWCToolkit.invokeAndWait.disposeOnEDTFree=true LWCToolkitInvokeAndWaitTest
* @run main/othervm -Dlog.level.FINER=true -Dsun.lwawt.macosx.LWCToolkit.invokeAndWait.disposeOnEDTFree=true LWCToolkitInvokeAndWaitTest
* @author Anton Tarasov
*/
@SuppressWarnings("ConstantConditions")
public class LWCToolkitInvokeAndWaitTest {
// This property is used in {CAccessibility}
static final int INVOKE_TIMEOUT_SECONDS = Integer.getInteger("sun.lwawt.macosx.CAccessibility.invokeTimeoutSeconds", 1);
static final Runnable CONSUME_DISPATCHING = () -> TEST_CASE_RESULT.completeExceptionally(new Throwable("Unexpected dispatching!"));
static volatile CountDownLatch EDT_FAST_FREE_LATCH;
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
tryRun(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) {
initTest(LWCToolkitInvokeAndWaitTest.class);
Consumer<InvocationEvent> noop = e -> {};
testCase().
withCaption("InvocationEvent is normally dispatched").
withRunnable(() -> test1(noop, () -> System.out.println("I'm dispatched")), true).
withCompletionTimeout(INVOKE_TIMEOUT_SECONDS * 2).
run();
testCase().
withCaption("InvocationEvent is lost").
withRunnable(() -> test1(noop, CONSUME_DISPATCHING), true).
withCompletionTimeout(INVOKE_TIMEOUT_SECONDS * 2).
withExpectedInLog("lost", true).
run();
EDT_FAST_FREE_LATCH = new CountDownLatch(2);
testCase().
withCaption("InvocationEvent is lost (EDT becomes fast free)").
withRunnable(() -> test1(invocationEvent -> EDT_FAST_FREE_LATCH.countDown(), CONSUME_DISPATCHING), true).
withCompletionTimeout(INVOKE_TIMEOUT_SECONDS * 2).
withExpectedInLog("lost", true).
run();
testCase().
withCaption("InvocationEvent is disposed").
withRunnable(() -> test1(invocationEvent -> AWTAccessor.getInvocationEventAccessor().dispose(invocationEvent), CONSUME_DISPATCHING), true).
withCompletionTimeout(INVOKE_TIMEOUT_SECONDS * 2).
withExpectedInLog("disposed", true).
run();
testCase().
withCaption("InvocationEvent is timed out (delayed before dispatching)").
withRunnable(() -> test1(invocationEvent -> sleep(INVOKE_TIMEOUT_SECONDS * 4), CONSUME_DISPATCHING), true).
withCompletionTimeout(INVOKE_TIMEOUT_SECONDS * 2).
withExpectedInLog("timed out", true).
run();
testCase().
withCaption("InvocationEvent is timed out (delayed during dispatching)").
withRunnable(() -> test1(noop, () -> sleep(INVOKE_TIMEOUT_SECONDS * 4)), true).
withCompletionTimeout(INVOKE_TIMEOUT_SECONDS * 2).
withExpectedInLog("timed out", true).
run();
testCase().
withCaption("invokeAndWait is discarded").
withRunnable(LWCToolkitInvokeAndWaitTest::test2, true).
withCompletionTimeout(INVOKE_TIMEOUT_SECONDS * 2).
withExpectedInLog("discarded", true).
run();
testCase().
withCaption("invokeAndWait is passed").
withRunnable(LWCToolkitInvokeAndWaitTest::test3, true).
withCompletionTimeout(INVOKE_TIMEOUT_SECONDS * 2).
run();
System.out.println("Test PASSED");
}
static void test1(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(() -> tryRun(() -> {
//
// Post an invocation from AppKit.
//
LWCToolkit.invokeAndWait(onDispatching, FRAME, false, INVOKE_TIMEOUT_SECONDS);
TEST_CASE_RESULT.complete(true);
}));
}
static void test2() {
EventQueue.invokeLater(() ->
//
// Blocking EDT.
//
LWCToolkit.performOnMainThreadAndWait(() -> {
//
// The invocation from AppKit should be discarded.
//
tryRun(() -> LWCToolkit.invokeAndWait(EMPTY_RUNNABLE, FRAME, false, INVOKE_TIMEOUT_SECONDS * 4));
TEST_CASE_RESULT.complete(true);
}));
}
static void test3() {
var point = new CountDownLatch(1);
EventQueue.invokeLater(() -> {
// We're on EDT, wait for the second invocation to perform on AppKit.
await(point, INVOKE_TIMEOUT_SECONDS * 2);
// This should be dispatched in the RunLoop started by LWCToolkit.invokeAndWait from the second invocation.
LWCToolkit.performOnMainThreadAndWait(() -> TEST_CASE_RESULT.complete(true));
});
LWCToolkit.performOnMainThreadAndWait(() -> {
// Notify we're on AppKit.
point.countDown();
// The LWCToolkit.invokeAndWait call starts a native RunLoop.
tryRun(() -> LWCToolkit.invokeAndWait(EMPTY_RUNNABLE, FRAME));
});
}
static void check(String expectedInLog) {
tryRun(() -> {
if (!TEST_CASE_RESULT.get(INVOKE_TIMEOUT_SECONDS * 2L, TimeUnit.SECONDS)) {
throw new RuntimeException("Test FAILED! (negative result)");
}
});
}
}

View File

@@ -1,239 +0,0 @@
// Copyright 2000-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package helper;
import sun.awt.AWTThreading;
import sun.lwawt.macosx.CThreading;
import sun.lwawt.macosx.LWCToolkit;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.logging.*;
@SuppressWarnings("ConstantConditions")
public class ToolkitTestHelper {
public static final Runnable EMPTY_RUNNABLE = () -> {};
public static final TestLogHandler LOG_HANDLER = new TestLogHandler();
public static volatile CompletableFuture<Boolean> TEST_CASE_RESULT;
public static volatile int TEST_CASE_NUM;
public static volatile JFrame FRAME;
private static volatile JLabel LABEL;
private static volatile Thread MAIN_THREAD;
private static final Runnable UPDATE_LABEL = new Runnable() {
final Random rand = new Random();
@Override
public void run() {
LABEL.setForeground(new Color(rand.nextFloat(), 0, rand.nextFloat()));
LABEL.setText("(" + TEST_CASE_NUM + ")");
}
};
public static void initTest(Class<?> testClass) {
MAIN_THREAD = Thread.currentThread();
assert MAIN_THREAD.getName().toLowerCase().contains("main");
loop(); // init the event threads
tryRun(() -> {
Consumer<Class<?>> setLog = cls -> {
Logger log = LogManager.getLogManager().getLogger(cls.getName());
log.setUseParentHandlers(false);
log.addHandler(LOG_HANDLER);
if (Boolean.getBoolean("log.level.FINER")) {
log.setLevel(Level.FINER);
}
};
setLog.accept(AWTThreading.class);
setLog.accept(LWCToolkit.class);
});
Thread.UncaughtExceptionHandler handler = MAIN_THREAD.getUncaughtExceptionHandler();
MAIN_THREAD.setUncaughtExceptionHandler((t, e) -> {
if (FRAME != null) FRAME.dispose();
handler.uncaughtException(t, e);
});
tryRun(() -> EventQueue.invokeAndWait(() -> {
FRAME = new JFrame(testClass.getSimpleName());
LABEL = new JLabel("0");
LABEL.setFont(LABEL.getFont().deriveFont((float)30));
LABEL.setHorizontalAlignment(SwingConstants.CENTER);
FRAME.add(LABEL, BorderLayout.CENTER);
FRAME.getContentPane().setBackground(Color.green);
FRAME.setLocationRelativeTo(null);
FRAME.setSize(200, 200);
FRAME.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
FRAME.setVisible(true);
}));
Timer timer = new Timer(100, e -> UPDATE_LABEL.run());
timer.setRepeats(true);
timer.start();
new Thread(() -> {
try {
MAIN_THREAD.join();
} catch (InterruptedException ignored) {
}
if (FRAME != null) FRAME.dispose();
timer.stop();
}).start();
}
public static void waitTestCaseCompletion(int seconds) {
tryRun(() -> {
if (!TEST_CASE_RESULT.get(seconds, TimeUnit.SECONDS)) {
throw new RuntimeException("Test FAILED! (negative result)");
}
});
loop(); // wait for the logging to be printed
}
public static class TestCase {
volatile String caption = "";
volatile Runnable testRunnable = EMPTY_RUNNABLE;
volatile int completionTimeoutSeconds = -1;
volatile String expectedInLog = "";
volatile boolean expectedIncludedInLog = true;
public static TestCase testCase() {
return new TestCase();
}
public TestCase withCaption(String caption) {
this.caption = caption;
return this;
}
public TestCase withRunnable(Runnable testRunnable, boolean invokeOnEdt) {
this.testRunnable = invokeOnEdt ? () -> EventQueue.invokeLater(testRunnable) : testRunnable;
return this;
}
public TestCase withCompletionTimeout(int seconds) {
this.completionTimeoutSeconds = seconds;
return this;
}
public TestCase withExpectedInLog(String expectedInLog, boolean included) {
this.expectedInLog = expectedInLog;
this.expectedIncludedInLog = included;
return this;
}
public void run() {
TEST_CASE_RESULT = new CompletableFuture<>();
TEST_CASE_RESULT.whenComplete((r, e) -> Optional.of(e).ifPresent(Throwable::printStackTrace));
//noinspection NonAtomicOperationOnVolatileField
String prefix = "(" + (++TEST_CASE_NUM) + ")";
System.out.println("\n" + prefix + " TEST: " + caption);
UPDATE_LABEL.run();
testRunnable.run();
if (completionTimeoutSeconds >= 0) {
waitTestCaseCompletion(completionTimeoutSeconds);
if (expectedIncludedInLog && !LOG_HANDLER.testContains(expectedInLog)) {
throw new RuntimeException("Test FAILED! (not found in the log: \"" + expectedInLog + "\")");
} else if (!expectedIncludedInLog && LOG_HANDLER.testContains(expectedInLog)) {
throw new RuntimeException("Test FAILED! (found in the log: \"" + expectedInLog + "\")");
}
}
System.out.println(prefix + " SUCCEEDED\n");
}
}
public static void tryRun(ThrowableRunnable runnable) {
tryCall(() -> {
runnable.run();
return null;
}, null);
}
public static <T> T tryCall(Callable<T> callable, T defValue) {
try {
return callable.call();
} catch (Exception e) {
if (Thread.currentThread() == MAIN_THREAD) {
throw new RuntimeException("Test FAILED!", e);
} else {
TEST_CASE_RESULT.completeExceptionally(e);
}
}
return defValue;
}
public static void await(CountDownLatch latch, int seconds) {
if (!tryCall(() -> latch.await(seconds, TimeUnit.SECONDS), false)) {
TEST_CASE_RESULT.completeExceptionally(new Throwable("Awaiting has timed out"));
}
}
public static void sleep(int seconds) {
tryRun(() -> Thread.sleep(seconds * 1000L));
}
private static void loop() {
tryRun(() -> EventQueue.invokeAndWait(EMPTY_RUNNABLE));
var latch = new CountDownLatch(1);
CThreading.executeOnAppKit(latch::countDown);
tryRun(latch::await);
}
public interface ThrowableRunnable {
void run() throws Exception;
}
public static class TestTimer {
private final long finishTime;
public TestTimer(long timeFromNow, TimeUnit unit) {
finishTime = System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(timeFromNow, unit);
}
public boolean hasFinished() {
return System.currentTimeMillis() >= finishTime;
}
}
public 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;
}
}
}

View File

@@ -33,7 +33,7 @@ public class MacSpacesUtil {
return Runtime.getRuntime().exec(new String[]{
"plutil",
"-extract",
"SpacesDisplayConfiguration.Management Data.Monitors.0.Spaces.1",
"SpacesDisplayConfiguration.Space Properties.1",
"json",
"-o",
"-",
@@ -45,15 +45,13 @@ public class MacSpacesUtil {
toggleMissionControl();
// press button at top right corner to add a new space
Rectangle screenBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
.getDefaultConfiguration().getBounds();
int rightX = screenBounds.x + screenBounds.width;
int topY = screenBounds.y;
int screenWidth = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
.getDefaultConfiguration().getBounds().width;
Robot robot = new Robot();
robot.setAutoDelay(50);
robot.mouseMove(rightX, topY);
robot.mouseMove(rightX - 5, topY + 5);
robot.mouseMove(rightX - 10, topY + 10);
robot.mouseMove(screenWidth, 0);
robot.mouseMove(screenWidth - 5, 5);
robot.mouseMove(screenWidth - 10, 10);
robot.delay(1000);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

View File

@@ -1,59 +0,0 @@
/*
* Copyright (c) 2017, 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
* 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 8266851
* @library /test/lib
* @build JbrIllegalAccessTest
* @run testng JbrIllegalAccessTest
* @summary Make sure that --jbr-illegal-access is working.
*/
import jdk.test.lib.process.*;
import org.testng.annotations.*;
/**
* Make sure that --jbr-illegal-access is working as expected.
*/
@Test
public class JbrIllegalAccessTest {
void run(String text, String... vmopts)
throws Exception
{
var outputAnalyzer = ProcessTools
.executeTestJava(vmopts)
.outputTo(System.out)
.errorTo(System.out);
outputAnalyzer.shouldContain(text);
}
public void testObsolete() throws Exception {
run("Option --jbr-illegal-access is deprecated",
"-XX:-IgnoreUnrecognizedVMOptions",
"--jbr-illegal-access", "--version");
}
}

View File

@@ -524,7 +524,6 @@ java/awt/image/VolatileImage/BitmaskVolatileImage.java 8133102 linux-all
java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java 8134231 windows-all,linux-all,macosx-all
java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java 8203004 linux-all
java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all
java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java 8282232 windows-all
java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java 8080676 linux-all
java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersInKeyEvent.java 8157147 linux-all,windows-all,macosx-all
java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java 8148041 linux-all
@@ -593,7 +592,6 @@ javax/management/monitor/DerivedGaugeMonitorTest.java 8042211 generic-al
# jdk_io
java/io/pathNames/GeneralWin32.java 8180264 windows-all
java/io/File/createTempFile/SpecialTempFile.java 8274122 windows11
############################################################################
@@ -735,7 +733,6 @@ javax/sound/midi/Sequencer/MetaCallback.java 8178698 linux-all
# jdk_swing
javax/swing/plaf/basic/BasicComboPopup/JComboBoxPopupLocation/JComboBoxPopupLocation.java 8194945 macosx-all
javax/swing/plaf/basic/BasicMenuUI/4983388/bug4983388.java 8253184 windows-all
javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java 8233177 linux-all,windows-all
javax/swing/border/TestTitledBorderLeak.java 8213531 linux-all,windows-all
@@ -940,5 +937,5 @@ com/sun/java/swing/plaf/windows/AltFocusIssueTest.java
java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.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
java/awt/Dialog/NonResizableDialogSysMenuResize/NonResizableDialogSysMenuResize.java TBD windows-all
java/awt/Dialog/NestedDialogs/Modeless/NestedModelessDialogTest.java TBD windows-all

View File

@@ -1,4 +1,3 @@
java/awt/dnd/DragInterceptorAppletTest/DragInterceptorAppletTest.java JBR-890 generic-all
java/awt/dnd/FileListBetweenJVMsTest/FileListBetweenJVMsTest.java JBR-1011 generic-all
java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java 8279190 linux-all,windows-all,macosx-all
java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java 8282232 windows-all
java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java 8279190 linux-all,windows-all,macosx-all