mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-24 10:19:40 +01:00
Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c86c32c8b5 | ||
|
|
d13b075e7e | ||
|
|
86b7feb77a | ||
|
|
9b5ebaaa5a | ||
|
|
a37db66560 | ||
|
|
39dd2f608c | ||
|
|
890efa0ea8 | ||
|
|
7efb0075bc | ||
|
|
413ff95d63 | ||
|
|
bfa7a36237 | ||
|
|
138596467d | ||
|
|
f7a0716ccd | ||
|
|
bdb9d3f12f | ||
|
|
1e8d2c0873 | ||
|
|
360f8f332c | ||
|
|
13512decff | ||
|
|
28ebc0c2e0 | ||
|
|
9a35ca0b25 | ||
|
|
e424a5bf19 | ||
|
|
ca4d838caf | ||
|
|
6ed5106466 | ||
|
|
098a50d91a | ||
|
|
050990303b | ||
|
|
9f9416a12e | ||
|
|
b6cb489fee | ||
|
|
446535b706 | ||
|
|
c18934bb98 | ||
|
|
e8a6e8bd6e | ||
|
|
4a7241931f | ||
|
|
b45b8c9913 | ||
|
|
f6cf71ce68 | ||
|
|
803039d6db | ||
|
|
436223316f | ||
|
|
9a0ab296fe | ||
|
|
bf4a191246 | ||
|
|
cdfff8f6ac | ||
|
|
6d6de1034a | ||
|
|
2333999906 | ||
|
|
6ffcd2bf91 | ||
|
|
822b4a8c49 | ||
|
|
debc6336c0 | ||
|
|
1f93154f62 | ||
|
|
9f069ca59e | ||
|
|
53f1a647fd | ||
|
|
7d31563471 | ||
|
|
36ded60698 | ||
|
|
d53de90f8a | ||
|
|
6196076b95 | ||
|
|
0ee50cbed6 | ||
|
|
d6e6d315d2 | ||
|
|
0a3f7bd9b1 | ||
|
|
a2636bc8b2 | ||
|
|
11ad455c7a | ||
|
|
4141e567c0 | ||
|
|
8373eeea85 | ||
|
|
9f10f63459 | ||
|
|
0cb7b4565c | ||
|
|
e19109f401 | ||
|
|
c450a40e16 | ||
|
|
fe79f047d0 | ||
|
|
484bc6f18f | ||
|
|
1af965d658 | ||
|
|
d330782b50 | ||
|
|
ff6002ab87 | ||
|
|
ee9fe4ee55 | ||
|
|
b8e1373b53 | ||
|
|
1b9f385336 | ||
|
|
cd9cc5f395 | ||
|
|
54199dc06c | ||
|
|
66ddc58397 | ||
|
|
c5d124735c | ||
|
|
409e4932ad | ||
|
|
3bbd930114 |
@@ -31,6 +31,7 @@ RUN export DEBIAN_FRONTEND=noninteractive \
|
||||
libxt-dev \
|
||||
libxtst-dev \
|
||||
make \
|
||||
rsync \
|
||||
tar \
|
||||
unzip \
|
||||
zip && \
|
||||
|
||||
22
jb/project/docker/Dockerfile.musl_aarch64
Normal file
22
jb/project/docker/Dockerfile.musl_aarch64
Normal file
@@ -0,0 +1,22 @@
|
||||
# NOTE: This Dockerfile is meant to be used from the mkdocker_musl_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"
|
||||
22
jb/project/docker/Dockerfile.musl_x64
Normal file
22
jb/project/docker/Dockerfile.musl_x64
Normal file
@@ -0,0 +1,22 @@
|
||||
# NOTE: This Dockerfile is meant to be used from the mkdocker_musl_x64.sh script.
|
||||
|
||||
# Pull a concrete version of Linux that does NOT recieve updates after it's
|
||||
# been created. This is so that the image is as stable as possible to make
|
||||
# image creation reproducible.
|
||||
# NB: this also means there may be no security-related fixes there, need to
|
||||
# move the version to the next manually.
|
||||
FROM alpine:3.5
|
||||
|
||||
# Install the necessary build tools
|
||||
RUN apk --no-cache add --update bash grep tar zip bzip2 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"
|
||||
26
jb/project/docker/mkdocker_musl_aarch64.sh
Executable file
26
jb/project/docker/mkdocker_musl_aarch64.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# This script creates a Docker image suitable for building musl AArch64 variant
|
||||
# of the JetBrains Runtime version 17.
|
||||
|
||||
BOOT_JDK_REMOTE_FILE=zulu17.32.13-ca-jdk17.0.2-linux_musl_aarch64.tar.gz
|
||||
BOOT_JDK_SHA=6b920559abafbe9bdef386a20ecf3a2f318bc1f0d8359eb1f95aee26606bbc70
|
||||
BOOT_JDK_LOCAL_FILE=boot_jdk_musl_aarch64.tar.gz
|
||||
|
||||
if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then
|
||||
# Obtain "boot JDK" from outside of the container.
|
||||
wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE
|
||||
else
|
||||
echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download"
|
||||
fi
|
||||
|
||||
# Verify that what we've downloaded can be trusted.
|
||||
sha256sum -c - <<EOF
|
||||
$BOOT_JDK_SHA *$BOOT_JDK_LOCAL_FILE
|
||||
EOF
|
||||
|
||||
docker build -t jbr17buildenv -f Dockerfile.musl_aarch64 .
|
||||
|
||||
# NB: the resulting container can (and should) be used without the network
|
||||
# connection (--network none) during build in order to reduce the chance
|
||||
# of build contamination.
|
||||
26
jb/project/docker/mkdocker_musl_x64.sh
Executable file
26
jb/project/docker/mkdocker_musl_x64.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# This script creates a Docker image suitable for building musl-x64 variant
|
||||
# of the JetBrains Runtime version 17.
|
||||
|
||||
BOOT_JDK_REMOTE_FILE=zulu17.32.13-ca-jdk17.0.2-linux_musl_x64.tar.gz
|
||||
BOOT_JDK_SHA=bcc5342011bd9f3643372aadbdfa68d47463ff0d8621668a0bdf2910614d95c6
|
||||
BOOT_JDK_LOCAL_FILE=boot_jdk_musl_amd64.tar.gz
|
||||
|
||||
if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then
|
||||
# Obtain "boot JDK" from outside of the container.
|
||||
wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE
|
||||
else
|
||||
echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download"
|
||||
fi
|
||||
|
||||
# Verify that what we've downloaded can be trusted.
|
||||
sha256sum -c - <<EOF
|
||||
$BOOT_JDK_SHA *$BOOT_JDK_LOCAL_FILE
|
||||
EOF
|
||||
|
||||
docker build -t jbr17buildenv -f Dockerfile.musl_x64 .
|
||||
|
||||
# NB: the resulting container can (and should) be used without the network
|
||||
# connection (--network none) during build in order to reduce the chance
|
||||
# of build contamination.
|
||||
@@ -10,7 +10,9 @@ function do_maketest() {
|
||||
fi
|
||||
}
|
||||
|
||||
tag_prefix="jbr-"
|
||||
function getVersionProp() {
|
||||
grep "^${1}" make/conf/version-numbers.conf | cut -d'=' -f2
|
||||
}
|
||||
|
||||
while getopts ":i?" o; do
|
||||
case "${o}" in
|
||||
@@ -22,30 +24,25 @@ while getopts ":i?" o; do
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [ $# -le $min_parameters_count ]; then
|
||||
build_number=$1
|
||||
bundle_type=$2
|
||||
architecture=$3 # aarch64 or x64
|
||||
else
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
architecture=$5 # aarch64 or x64
|
||||
fi
|
||||
build_number=$1
|
||||
bundle_type=$2
|
||||
architecture=$3 # aarch64 or x64
|
||||
|
||||
bundle_type=$(do_maketest)
|
||||
do_maketest=$?
|
||||
|
||||
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "$tag_prefix" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -g | tail -n 1)
|
||||
JBSDK_VERSION=${JBSDK_VERSION:=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $2}')}
|
||||
tag_prefix="jbr-"
|
||||
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "$tag_prefix" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -g | tail -n 1 | tr -d ",")
|
||||
VERSION_FEATURE=$(getVersionProp "DEFAULT_VERSION_FEATURE")
|
||||
VERSION_INTERIM=$(getVersionProp "DEFAULT_VERSION_INTERIM")
|
||||
VERSION_UPDATE=$(getVersionProp "DEFAULT_VERSION_UPDATE")
|
||||
[[ $VERSION_UPDATE = 0 ]] && JBSDK_VERSION="$VERSION_FEATURE" || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}"
|
||||
echo "##teamcity[setParameter name='env.JBSDK_VERSION' value='${JBSDK_VERSION}']"
|
||||
JDK_BUILD_NUMBER=${JDK_BUILD_NUMBER:=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $3}')}
|
||||
[ -z $JDK_BUILD_NUMBER ] && JDK_BUILD_NUMBER=1
|
||||
echo "##teamcity[setParameter name='env.JDK_UPDATE_NUMBER' value='${JDK_BUILD_NUMBER}']"
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
|
||||
VENDOR_NAME="JetBrains s.r.o."
|
||||
VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION_WITH_DOTS}+${JDK_BUILD_NUMBER}-${build_number}"
|
||||
VENDOR_VERSION_STRING="JBR-${JBSDK_VERSION}+${JDK_BUILD_NUMBER}-${build_number}"
|
||||
[ -z "$bundle_type" ] || VENDOR_VERSION_STRING="${VENDOR_VERSION_STRING}-${bundle_type}"
|
||||
|
||||
do_reset_changes=0
|
||||
@@ -80,15 +77,27 @@ 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 modules.list src/java.desktop/share/classes/module-info.java
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
|
||||
if [ $do_reset_dcevm -eq 1 ]; then
|
||||
[ ! -z $HEAD_REVISION ] && git reset --hard $HEAD_REVISION
|
||||
fi
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
# The following parameter must be specified:
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
#
|
||||
|
||||
min_parameters_count=1
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
function is_musl {
|
||||
libc=$(ldd /bin/ls | grep 'musl' | head -1 | cut -d ' ' -f1)
|
||||
if [ -z $libc ]; then
|
||||
# This is not Musl, return 1 == false
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
LIBC_TYPE_SUFFIX=''
|
||||
|
||||
if is_musl; then LIBC_TYPE_SUFFIX='musl-' ; fi
|
||||
|
||||
sh configure \
|
||||
--with-debug-level=release \
|
||||
--with-vendor-name="${VENDOR_NAME}" \
|
||||
@@ -30,11 +32,12 @@ 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-aarch64-b${build_number}
|
||||
JBSDK=${JBRSDK_BASE_NAME}-linux-${LIBC_TYPE_SUFFIX}aarch64-b${build_number}
|
||||
BASE_DIR=build/linux-aarch64-server-release/images
|
||||
JSDK=${BASE_DIR}/jdk
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
@@ -49,6 +52,8 @@ 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 \
|
||||
@@ -60,8 +65,8 @@ JBR_BUNDLE=jbr
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
rm -rf $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-aarch64-b$build_number
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64
|
||||
JBR=$JBR_BASE_NAME-linux-${LIBC_TYPE_SUFFIX}aarch64-b$build_number
|
||||
grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64
|
||||
echo Running jlink....
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
@@ -76,7 +81,7 @@ tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE}
|
||||
touch -c -d @$SOURCE_DATE_EPOCH $JBR.tar
|
||||
gzip $JBR.tar || exit $?
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-aarch64-b$build_number
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-${LIBC_TYPE_SUFFIX}test-aarch64-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built;possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
# This script makes test-image along with JDK images when bundle_type is set to "jcef".
|
||||
# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images.
|
||||
#
|
||||
# Environment variables:
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument
|
||||
# to configure
|
||||
# By default JDK_BUILD_NUMBER is set zero
|
||||
# JCEF_PATH - specifies the path to the directory with JCEF binaries.
|
||||
# By default JCEF binaries should be located in ./jcef_linux_x64
|
||||
|
||||
min_parameters_count=2
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JCEF_PATH=${JCEF_PATH:=./jcef_linux_x64}
|
||||
@@ -38,17 +33,31 @@ 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-x64-${fastdebug_infix}b${build_number}
|
||||
JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x64-${fastdebug_infix}b${build_number}
|
||||
|
||||
echo Running jlink....
|
||||
[ -d "$IMAGES_DIR"/"$__arch_name" ] && rm -rf "${IMAGES_DIR:?}"/"$__arch_name"
|
||||
@@ -61,6 +70,7 @@ 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)
|
||||
@@ -120,7 +130,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
fi
|
||||
|
||||
# create runtime image bundle
|
||||
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
|
||||
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
|
||||
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
# create sdk image bundle
|
||||
@@ -131,9 +141,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-test-x64-b${build_number}
|
||||
JBRSDK_TEST=${JBRSDK_BUNDLE}-${JBSDK_VERSION}-linux-${libc_type_suffix}test-x64-b${build_number}
|
||||
echo Creating "$JBRSDK_TEST" ...
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
|
||||
make test-image CONF=$RELEASE_NAME || do_exit $?
|
||||
tar -pcf "$JBRSDK_TEST".tar -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
|
||||
[ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz"
|
||||
|
||||
@@ -61,7 +61,7 @@ JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
rm -rf $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-x86-b$build_number
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
echo Running jlink....
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
@@ -77,4 +77,4 @@ gzip $JBR.tar || exit $?
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x86-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' --exclude='test/hotspot/gtest' test || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
|
||||
@@ -1,29 +1,24 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built;possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
# This script makes test-image along with JDK images when bundle_type is set to "jcef".
|
||||
# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images.
|
||||
#
|
||||
# Environment variables:
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument
|
||||
# to configure
|
||||
# By default JDK_BUILD_NUMBER is set zero
|
||||
# JCEF_PATH - specifies the path to the directory with JCEF binaries.
|
||||
# By default JCEF binaries should be located in ./jcef_mac
|
||||
# MACOSX_VERSION_MAX - specifies value for the --with-macosx-version-max parameter. By default it is 10.12.00 for x64
|
||||
# and 11.00.00 for aarch64
|
||||
|
||||
min_parameters_count=3
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
JCEF_PATH=${JCEF_PATH:=./jcef_mac}
|
||||
@@ -50,6 +45,7 @@ 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 \
|
||||
@@ -66,6 +62,7 @@ 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
|
||||
}
|
||||
@@ -95,6 +92,7 @@ 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"
|
||||
@@ -145,10 +143,7 @@ make images CONF=$RELEASE_NAME || do_exit $?
|
||||
|
||||
IMAGES_DIR=build/$RELEASE_NAME/images
|
||||
|
||||
major_version=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $1}')
|
||||
minor_version=$(echo "$JBSDK_VERSION_WITH_DOTS" | awk -F "." '{print $3}')
|
||||
[ -z "$minor_version" -o "$minor_version" = "0" ] && version_dir=$major_version || version_dir=$JBSDK_VERSION_WITH_DOTS
|
||||
JSDK=$IMAGES_DIR/jdk-bundle/jdk-$version_dir.jdk/Contents/Home
|
||||
JSDK=$IMAGES_DIR/jdk-bundle/jdk-$JBSDK_VERSION.jdk/Contents/Home
|
||||
JSDK_MODS_DIR=$IMAGES_DIR/jmods
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
@@ -161,7 +156,7 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
fi
|
||||
|
||||
# create runtime image bundle
|
||||
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
|
||||
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
|
||||
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
# create sdk image bundle
|
||||
@@ -174,7 +169,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 modules.list src/java.desktop/share/classes/module-info.java
|
||||
[ $do_reset_changes -eq 1 ] && git checkout HEAD jb/project/tools/common/modules.list src/java.desktop/share/classes/module-info.java
|
||||
make test-image CONF=$RELEASE_NAME || do_exit $?
|
||||
[ -f "$JBRSDK_TEST.tar.gz" ] && rm "$JBRSDK_TEST.tar.gz"
|
||||
COPYFILE_DISABLE=1 tar -pczf "$JBRSDK_TEST".tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git modules.list modules.list
|
||||
index 054f21d1ee0..d9a121f0273 100644
|
||||
--- modules.list
|
||||
+++ modules.list
|
||||
@@ -49,4 +49,7 @@ jdk.unsupported,
|
||||
diff --git jb/project/tools/common/modules.list jb/project/tools/common/modules.list
|
||||
index 522acb7cb43..c40e689d5de 100644
|
||||
--- jb/project/tools/common/modules.list
|
||||
+++ jb/project/tools/common/modules.list
|
||||
@@ -51,4 +51,7 @@ jdk.unsupported.desktop,
|
||||
jdk.xml.dom,
|
||||
jdk.zipfs,
|
||||
jdk.hotspot.agent,
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
#!/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
|
||||
@@ -7,6 +18,7 @@ TOKEN=$4
|
||||
#
|
||||
# Get the size of new artifact
|
||||
#
|
||||
|
||||
unameOut="$(uname -s)"
|
||||
case "${unameOut}" in
|
||||
Linux*)
|
||||
@@ -16,7 +28,11 @@ case "${unameOut}" in
|
||||
NEWFILESIZE=$(stat -f%z "$NEWFILEPATH")
|
||||
;;
|
||||
CYGWIN*)
|
||||
NEWFILESIZE=$(stat -c%s "$NEWFILEPATH")
|
||||
NEWFILESIZE=$(stat -c%s$4
|
||||
#
|
||||
# Get the size of new artifact
|
||||
#
|
||||
"$NEWFILEPATH")
|
||||
;;
|
||||
MINGW*)
|
||||
NEWFILESIZE=$(stat -c%s "$NEWFILEPATH")
|
||||
@@ -25,32 +41,88 @@ case "${unameOut}" in
|
||||
echo "Unknown machine: ${unameOut}"
|
||||
exit 1
|
||||
esac
|
||||
FILENAME=$(basename ${NEWFILEPATH})
|
||||
|
||||
echo "New size of $NEWFILEPATH = $NEWFILESIZE bytes."
|
||||
#
|
||||
# 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.
|
||||
|
||||
# example: IntellijCustomJdk_Jdk17_Master_LinuxX64jcef
|
||||
BUNDLE_TYPE=jbrsdk
|
||||
OS_ARCH_PATTERN=""
|
||||
FILE_EXTENSION=tar.gz
|
||||
|
||||
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\.]+)\"'
|
||||
|
||||
re='id=\"([0-9]+)\".+number=\"([0-9]+)\"'
|
||||
# ID: Previous successful build id
|
||||
ID=0
|
||||
|
||||
if [[ $CURL_RESPONSE =~ $re ]]; then
|
||||
ID=${BASH_REMATCH[1]}
|
||||
echo "BUILD Number: ${BASH_REMATCH[2]}"
|
||||
else
|
||||
echo "ERROR: can't find previous build"
|
||||
msg="ERROR: can't find previous build"
|
||||
echo $msg
|
||||
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 last pinned build of $CONFIGID :\n"
|
||||
echo "Atrifacts of previous build of $CONFIGID :"
|
||||
echo $CURL_RESPONSE
|
||||
|
||||
# Find size (in response) with reg exp
|
||||
re='name=\"(jbrsdk_jcef[^\"]+\.tar\.gz)\" size=\"([0-9]+)\"'
|
||||
# Find binary size (in response) with reg exp
|
||||
re='name=\"('$BUNDLE_TYPE'[^\"]+'${OS_ARCH_PATTERN}'[^\"]+'${FILE_EXTENSION}')\" size=\"([0-9]+)\"'
|
||||
|
||||
if [[ $CURL_RESPONSE =~ $re ]]; then
|
||||
OLDFILENAME=${BASH_REMATCH[1]}
|
||||
@@ -61,12 +133,20 @@ if [[ $CURL_RESPONSE =~ $re ]]; then
|
||||
let allowedSize=OLDFILESIZE+OLDFILESIZE/20 # use 5% threshold
|
||||
echo "Allowed size = $allowedSize"
|
||||
if [[ "$NEWFILESIZE" -gt "$allowedSize" ]]; then
|
||||
echo "ERROR: new size is significally greater than prev size (need to investigate)"
|
||||
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
|
||||
exit 1
|
||||
else
|
||||
echo "PASSED"
|
||||
test_finished_msg $testname $TC_PRINT
|
||||
fi
|
||||
else
|
||||
echo "ERROR: can't find string with size in xml response:"
|
||||
msg="ERROR: can't find string with size in xml response:"
|
||||
echo $msg
|
||||
echo $CURL_RESPONSE
|
||||
test_failed_msg $testname $msg $TC_PRINT
|
||||
test_finished_msg $testname $TC_PRINT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built;possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
# This script makes test-image along with JDK images when bundle_type is set to "jcef".
|
||||
# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images.
|
||||
#
|
||||
# Environment variables:
|
||||
# JDK_BUILD_NUMBER - specifies update release of OpenJDK build or the value of --with-version-build argument
|
||||
# to configure
|
||||
# By default JDK_BUILD_NUMBER is set zero
|
||||
# JCEF_PATH - specifies the path to the directory with JCEF binaries.
|
||||
# By default JCEF binaries should be located in ./jcef_win_x64
|
||||
|
||||
min_parameters_count=2
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
WORK_DIR=$(pwd)
|
||||
@@ -111,8 +106,9 @@ if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
|
||||
jbr_name_postfix="_${bundle_type}"
|
||||
fi
|
||||
|
||||
# create runtime image bundle
|
||||
modules=$(xargs < modules.list | sed s/" "//g) || do_exit $?
|
||||
# create runtime image bundlef
|
||||
modules=$(xargs < jb/project/tools/common/modules.list | sed s/" "//g) || do_exit $?
|
||||
modules+=",jdk.crypto.mscapi"
|
||||
create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" || do_exit $?
|
||||
|
||||
# create sdk image bundle
|
||||
|
||||
@@ -53,7 +53,8 @@ mv release ${JBRSDK_BUNDLE}/release
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
rm -rf ${JBR_BUNDLE}
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
grep -v javafx jb/project/tools/common/modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
echo ",jdk.crypto.mscapi" >> modules.list.x86
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list.x86 | sed s/" "//g) --output ${JBR_BUNDLE} || exit $?
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies major version of OpenJDK e.g. 11_0_6 (instead of dots '.' underbars "_" are used)
|
||||
# JDK_BUILD_NUMBER - specifies udate release of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built; possible values:
|
||||
# <empty> or nomod - the bundles without any additional modules (jcef)
|
||||
# jcef - the bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to be built;possible values:
|
||||
# <empty> or nomod - the release bundles without any additional modules (jcef)
|
||||
# jcef - the release bundles with jcef
|
||||
# fd - the fastdebug bundles which also include the jcef module
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
# This script packs test-image along with JDK images when bundle_type is set to "jcef".
|
||||
# If the character 't' is added at the end of bundle_type then it also makes test-image along with JDK images.
|
||||
#
|
||||
|
||||
min_parameters_count=2
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
|
||||
[ "$bundle_type" == "jcef" ] && do_maketest=1
|
||||
|
||||
@@ -95,8 +95,24 @@ 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
|
||||
@@ -108,6 +124,11 @@ 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)
|
||||
])
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#
|
||||
# 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"
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -193,7 +193,8 @@ 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 && \
|
||||
$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_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; \
|
||||
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!
|
||||
@@ -212,7 +213,9 @@ define SetupJarArchiveBody
|
||||
| $(SED) 's|$$(src)/|-C $$(src) |g' >> \
|
||||
$$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) )
|
||||
endif
|
||||
$1_SUPDATE_CONTENTS=$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)
|
||||
$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)
|
||||
|
||||
# Use a slightly shorter name for logging, but with enough path to identify this jar.
|
||||
$1_NAME:=$$(subst $$(OUTPUTDIR)/,,$$($1_JAR))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -389,6 +389,12 @@ 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), \
|
||||
@@ -1143,6 +1149,19 @@ 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)
|
||||
|
||||
|
||||
@@ -58,6 +58,9 @@ 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, \
|
||||
|
||||
@@ -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
|
||||
jvmtiClassFileReconstituter.cpp jvmtiTagMapTable.cpp jvmtiEnhancedRedefineClasses.cpp
|
||||
endif
|
||||
|
||||
ifneq ($(call check-jvm-feature, jvmci), true)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -204,6 +204,10 @@ 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);
|
||||
|
||||
@@ -335,16 +335,6 @@ void ClassLoaderData::classes_do(KlassClosure* klass_closure) {
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoaderData::initialized_classes_do(KlassClosure* klass_closure) {
|
||||
// Lock-free access requires load_acquire
|
||||
for (Klass* k = Atomic::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
|
||||
if (k->is_instance_klass() && InstanceKlass::cast(k)->is_initialized()) {
|
||||
klass_closure->do_klass(k);
|
||||
}
|
||||
assert(k != k->next_link(), "no loops!");
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoaderData::classes_do(void f(Klass * const)) {
|
||||
// Lock-free access requires load_acquire
|
||||
for (Klass* k = Atomic::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
|
||||
|
||||
@@ -272,7 +272,6 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
void oops_do(OopClosure* f, int claim_value, bool clear_modified_oops = false);
|
||||
|
||||
void classes_do(KlassClosure* klass_closure);
|
||||
void initialized_classes_do(KlassClosure* klass_closure);
|
||||
Klass* klasses() { return _klasses; }
|
||||
|
||||
JNIMethodBlock* jmethod_ids() const { return _jmethod_ids; }
|
||||
|
||||
@@ -361,13 +361,6 @@ void ClassLoaderDataGraph::classes_do(KlassClosure* klass_closure) {
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoaderDataGraph::initialized_classes_do(KlassClosure* klass_closure) {
|
||||
ClassLoaderDataGraphIterator iter;
|
||||
while (ClassLoaderData* cld = iter.get_next()) {
|
||||
cld->initialized_classes_do(klass_closure);
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoaderDataGraph::classes_do(void f(Klass* const)) {
|
||||
ClassLoaderDataGraphIterator iter;
|
||||
while (ClassLoaderData* cld = iter.get_next()) {
|
||||
|
||||
@@ -79,9 +79,6 @@ class ClassLoaderDataGraph : public AllStatic {
|
||||
// Walking the ClassLoaderDataGraph also includes hidden classes.
|
||||
static void classes_do(KlassClosure* klass_closure);
|
||||
|
||||
// Enhanced class redefinition
|
||||
static void initialized_classes_do(KlassClosure* klass_closure);
|
||||
|
||||
static void classes_do(void f(Klass* const));
|
||||
static void methods_do(void f(Method*));
|
||||
static void modules_do(void f(ModuleEntry*));
|
||||
|
||||
@@ -68,6 +68,7 @@ static bool enable() {
|
||||
}
|
||||
_enabled = FlightRecorder;
|
||||
assert(_enabled, "invariant");
|
||||
AllowEnhancedClassRedefinition = false;
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
|
||||
@@ -341,9 +341,9 @@ void PhaseIdealLoop::clone_skeleton_predicates_to_unswitched_loop(IdealLoopTree*
|
||||
assert(predicate->is_Proj() && predicate->as_Proj()->is_IfProj(), "predicate must be a projection of an if node");
|
||||
IfProjNode* predicate_proj = predicate->as_IfProj();
|
||||
|
||||
ProjNode* fast_proj = clone_skeleton_predicate_for_unswitched_loops(iff, predicate_proj, uncommon_proj, reason, iffast_pred, loop);
|
||||
ProjNode* fast_proj = clone_skeleton_predicate_for_unswitched_loops(iff, predicate_proj, reason, iffast_pred);
|
||||
assert(skeleton_predicate_has_opaque(fast_proj->in(0)->as_If()), "must find skeleton predicate for fast loop");
|
||||
ProjNode* slow_proj = clone_skeleton_predicate_for_unswitched_loops(iff, predicate_proj, uncommon_proj, reason, ifslow_pred, loop);
|
||||
ProjNode* slow_proj = clone_skeleton_predicate_for_unswitched_loops(iff, predicate_proj, reason, ifslow_pred);
|
||||
assert(skeleton_predicate_has_opaque(slow_proj->in(0)->as_If()), "must find skeleton predicate for slow loop");
|
||||
|
||||
// Update control dependent data nodes.
|
||||
@@ -397,10 +397,10 @@ void PhaseIdealLoop::get_skeleton_predicates(Node* predicate, Unique_Node_List&
|
||||
// Clone a skeleton predicate for an unswitched loop. OpaqueLoopInit and OpaqueLoopStride nodes are cloned and uncommon
|
||||
// traps are kept for the predicate (a Halt node is used later when creating pre/main/post loops and copying this cloned
|
||||
// predicate again).
|
||||
ProjNode* PhaseIdealLoop::clone_skeleton_predicate_for_unswitched_loops(Node* iff, ProjNode* predicate, Node* uncommon_proj,
|
||||
Deoptimization::DeoptReason reason, ProjNode* output_proj,
|
||||
IdealLoopTree* loop) {
|
||||
Node* bol = clone_skeleton_predicate_bool(iff, NULL, NULL, predicate, uncommon_proj, output_proj, loop);
|
||||
ProjNode* PhaseIdealLoop::clone_skeleton_predicate_for_unswitched_loops(Node* iff, ProjNode* predicate,
|
||||
Deoptimization::DeoptReason reason,
|
||||
ProjNode* output_proj) {
|
||||
Node* bol = clone_skeleton_predicate_bool(iff, NULL, NULL, output_proj);
|
||||
ProjNode* proj = create_new_if_for_predicate(output_proj, NULL, reason, iff->Opcode(), predicate->is_IfTrue());
|
||||
_igvn.replace_input_of(proj->in(0), 1, bol);
|
||||
_igvn.replace_input_of(output_proj->in(0), 0, proj);
|
||||
|
||||
@@ -1264,10 +1264,12 @@ void PhaseIdealLoop::copy_skeleton_predicates_to_main_loop_helper(Node* predicat
|
||||
// Clone the skeleton predicate twice and initialize one with the initial
|
||||
// value of the loop induction variable. Leave the other predicate
|
||||
// to be initialized when increasing the stride during loop unrolling.
|
||||
prev_proj = clone_skeleton_predicate_for_main_loop(iff, opaque_init, NULL, predicate, uncommon_proj, current_proj, outer_loop, prev_proj);
|
||||
prev_proj = clone_skeleton_predicate_for_main_or_post_loop(iff, opaque_init, NULL, predicate, uncommon_proj,
|
||||
current_proj, outer_loop, prev_proj);
|
||||
assert(skeleton_predicate_has_opaque(prev_proj->in(0)->as_If()), "");
|
||||
|
||||
prev_proj = clone_skeleton_predicate_for_main_loop(iff, init, stride, predicate, uncommon_proj, current_proj, outer_loop, prev_proj);
|
||||
prev_proj = clone_skeleton_predicate_for_main_or_post_loop(iff, init, stride, predicate, uncommon_proj,
|
||||
current_proj, outer_loop, prev_proj);
|
||||
assert(!skeleton_predicate_has_opaque(prev_proj->in(0)->as_If()), "");
|
||||
|
||||
// Rewire any control inputs from the cloned skeleton predicates down to the main and post loop for data nodes that are part of the
|
||||
@@ -1344,8 +1346,7 @@ bool PhaseIdealLoop::skeleton_predicate_has_opaque(IfNode* iff) {
|
||||
// Clone the skeleton predicate bool for a main or unswitched loop:
|
||||
// Main loop: Set new_init and new_stride nodes as new inputs.
|
||||
// Unswitched loop: new_init and new_stride are both NULL. Clone OpaqueLoopInit and OpaqueLoopStride instead.
|
||||
Node* PhaseIdealLoop::clone_skeleton_predicate_bool(Node* iff, Node* new_init, Node* new_stride, Node* predicate, Node* uncommon_proj,
|
||||
Node* control, IdealLoopTree* outer_loop) {
|
||||
Node* PhaseIdealLoop::clone_skeleton_predicate_bool(Node* iff, Node* new_init, Node* new_stride, Node* control) {
|
||||
Node_Stack to_clone(2);
|
||||
to_clone.push(iff->in(1), 1);
|
||||
uint current = C->unique();
|
||||
@@ -1421,9 +1422,9 @@ Node* PhaseIdealLoop::clone_skeleton_predicate_bool(Node* iff, Node* new_init, N
|
||||
|
||||
// Clone a skeleton predicate for the main loop. new_init and new_stride are set as new inputs. Since the predicates cannot fail at runtime,
|
||||
// Halt nodes are inserted instead of uncommon traps.
|
||||
Node* PhaseIdealLoop::clone_skeleton_predicate_for_main_loop(Node* iff, Node* new_init, Node* new_stride, Node* predicate, Node* uncommon_proj,
|
||||
Node* control, IdealLoopTree* outer_loop, Node* input_proj) {
|
||||
Node* result = clone_skeleton_predicate_bool(iff, new_init, new_stride, predicate, uncommon_proj, control, outer_loop);
|
||||
Node* PhaseIdealLoop::clone_skeleton_predicate_for_main_or_post_loop(Node* iff, Node* new_init, Node* new_stride, Node* predicate, Node* uncommon_proj,
|
||||
Node* control, IdealLoopTree* outer_loop, Node* input_proj) {
|
||||
Node* result = clone_skeleton_predicate_bool(iff, new_init, new_stride, control);
|
||||
Node* proj = predicate->clone();
|
||||
Node* other_proj = uncommon_proj->clone();
|
||||
Node* new_iff = iff->clone();
|
||||
@@ -1437,8 +1438,8 @@ Node* PhaseIdealLoop::clone_skeleton_predicate_for_main_loop(Node* iff, Node* ne
|
||||
C->root()->add_req(halt);
|
||||
new_iff->set_req(0, input_proj);
|
||||
|
||||
register_control(new_iff, outer_loop->_parent, input_proj);
|
||||
register_control(proj, outer_loop->_parent, new_iff);
|
||||
register_control(new_iff, outer_loop == _ltree_root ? _ltree_root : outer_loop->_parent, input_proj);
|
||||
register_control(proj, outer_loop == _ltree_root ? _ltree_root : outer_loop->_parent, new_iff);
|
||||
register_control(other_proj, _ltree_root, new_iff);
|
||||
register_control(halt, _ltree_root, other_proj);
|
||||
return proj;
|
||||
@@ -1521,7 +1522,8 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n
|
||||
// Add the post loop
|
||||
const uint idx_before_pre_post = Compile::current()->unique();
|
||||
CountedLoopNode *post_head = NULL;
|
||||
Node *main_exit = insert_post_loop(loop, old_new, main_head, main_end, incr, limit, post_head);
|
||||
Node* post_incr = incr;
|
||||
Node* main_exit = insert_post_loop(loop, old_new, main_head, main_end, post_incr, limit, post_head);
|
||||
const uint idx_after_post_before_pre = Compile::current()->unique();
|
||||
|
||||
//------------------------------
|
||||
@@ -1620,6 +1622,7 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n
|
||||
assert(post_head->in(1)->is_IfProj(), "must be zero-trip guard If node projection of the post loop");
|
||||
copy_skeleton_predicates_to_main_loop(pre_head, castii, stride, outer_loop, outer_main_head, dd_main_head,
|
||||
idx_before_pre_post, idx_after_post_before_pre, min_taken, post_head->in(1), old_new);
|
||||
copy_skeleton_predicates_to_post_loop(outer_main_head, post_head, post_incr, stride);
|
||||
|
||||
// Step B4: Shorten the pre-loop to run only 1 iteration (for now).
|
||||
// RCE and alignment may change this later.
|
||||
@@ -1742,6 +1745,7 @@ void PhaseIdealLoop::insert_vector_post_loop(IdealLoopTree *loop, Node_List &old
|
||||
// In this case we throw away the result as we are not using it to connect anything else.
|
||||
CountedLoopNode *post_head = NULL;
|
||||
insert_post_loop(loop, old_new, main_head, main_end, incr, limit, post_head);
|
||||
copy_skeleton_predicates_to_post_loop(main_head->skip_strip_mined(), post_head, incr, main_head->stride());
|
||||
|
||||
// It's difficult to be precise about the trip-counts
|
||||
// for post loops. They are usually very short,
|
||||
@@ -1788,6 +1792,7 @@ void PhaseIdealLoop::insert_scalar_rced_post_loop(IdealLoopTree *loop, Node_List
|
||||
// In this case we throw away the result as we are not using it to connect anything else.
|
||||
CountedLoopNode *post_head = NULL;
|
||||
insert_post_loop(loop, old_new, main_head, main_end, incr, limit, post_head);
|
||||
copy_skeleton_predicates_to_post_loop(main_head->skip_strip_mined(), post_head, incr, main_head->stride());
|
||||
|
||||
// It's difficult to be precise about the trip-counts
|
||||
// for post loops. They are usually very short,
|
||||
@@ -1804,9 +1809,9 @@ void PhaseIdealLoop::insert_scalar_rced_post_loop(IdealLoopTree *loop, Node_List
|
||||
|
||||
//------------------------------insert_post_loop-------------------------------
|
||||
// Insert post loops. Add a post loop to the given loop passed.
|
||||
Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree *loop, Node_List &old_new,
|
||||
CountedLoopNode *main_head, CountedLoopEndNode *main_end,
|
||||
Node *incr, Node *limit, CountedLoopNode *&post_head) {
|
||||
Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree* loop, Node_List& old_new,
|
||||
CountedLoopNode* main_head, CountedLoopEndNode* main_end,
|
||||
Node*& incr, Node* limit, CountedLoopNode*& post_head) {
|
||||
IfNode* outer_main_end = main_end;
|
||||
IdealLoopTree* outer_loop = loop;
|
||||
if (main_head->is_strip_mined()) {
|
||||
@@ -1890,8 +1895,8 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree *loop, Node_List &old_new,
|
||||
}
|
||||
|
||||
// CastII for the new post loop:
|
||||
Node* castii = cast_incr_before_loop(zer_opaq->in(1), zer_taken, post_head);
|
||||
assert(castii != NULL, "no castII inserted");
|
||||
incr = cast_incr_before_loop(zer_opaq->in(1), zer_taken, post_head);
|
||||
assert(incr != NULL, "no castII inserted");
|
||||
|
||||
return new_main_exit;
|
||||
}
|
||||
@@ -1933,7 +1938,8 @@ void PhaseIdealLoop::update_main_loop_skeleton_predicates(Node* ctrl, CountedLoo
|
||||
_igvn.replace_input_of(iff, 1, iff->in(1)->in(2));
|
||||
} else {
|
||||
// Add back predicates updated for the new stride.
|
||||
prev_proj = clone_skeleton_predicate_for_main_loop(iff, init, max_value, entry, proj, ctrl, outer_loop, prev_proj);
|
||||
prev_proj = clone_skeleton_predicate_for_main_or_post_loop(iff, init, max_value, entry, proj, ctrl, outer_loop,
|
||||
prev_proj);
|
||||
assert(!skeleton_predicate_has_opaque(prev_proj->in(0)->as_If()), "unexpected");
|
||||
}
|
||||
}
|
||||
@@ -1945,6 +1951,34 @@ void PhaseIdealLoop::update_main_loop_skeleton_predicates(Node* ctrl, CountedLoo
|
||||
}
|
||||
}
|
||||
|
||||
void PhaseIdealLoop::copy_skeleton_predicates_to_post_loop(LoopNode* main_loop_head, CountedLoopNode* post_loop_head, Node* init, Node* stride) {
|
||||
// Go over the skeleton predicates of the main loop and make a copy for the post loop with its initial iv value and
|
||||
// stride as inputs.
|
||||
Node* post_loop_entry = post_loop_head->in(LoopNode::EntryControl);
|
||||
Node* main_loop_entry = main_loop_head->in(LoopNode::EntryControl);
|
||||
IdealLoopTree* post_loop = get_loop(post_loop_head);
|
||||
|
||||
Node* ctrl = main_loop_entry;
|
||||
Node* prev_proj = post_loop_entry;
|
||||
while (ctrl != NULL && ctrl->is_Proj() && ctrl->in(0)->is_If()) {
|
||||
IfNode* iff = ctrl->in(0)->as_If();
|
||||
ProjNode* proj = iff->proj_out(1 - ctrl->as_Proj()->_con);
|
||||
if (proj->unique_ctrl_out()->Opcode() != Op_Halt) {
|
||||
break;
|
||||
}
|
||||
if (iff->in(1)->Opcode() == Op_Opaque4 && skeleton_predicate_has_opaque(iff)) {
|
||||
prev_proj = clone_skeleton_predicate_for_main_or_post_loop(iff, init, stride, ctrl, proj, post_loop_entry,
|
||||
post_loop, prev_proj);
|
||||
assert(!skeleton_predicate_has_opaque(prev_proj->in(0)->as_If()), "unexpected");
|
||||
}
|
||||
ctrl = ctrl->in(0)->in(0);
|
||||
}
|
||||
if (prev_proj != post_loop_entry) {
|
||||
_igvn.replace_input_of(post_loop_head, LoopNode::EntryControl, prev_proj);
|
||||
set_idom(post_loop_head, prev_proj, dom_depth(post_loop_head));
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------do_unroll--------------------------------------
|
||||
// Unroll the loop body one step - make each trip do 2 iterations.
|
||||
void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip) {
|
||||
|
||||
@@ -2150,12 +2150,14 @@ Node* CountedLoopNode::skip_predicates_from_entry(Node* ctrl) {
|
||||
}
|
||||
|
||||
Node* CountedLoopNode::skip_predicates() {
|
||||
Node* ctrl = in(LoopNode::EntryControl);
|
||||
if (is_main_loop()) {
|
||||
Node* ctrl = skip_strip_mined()->in(LoopNode::EntryControl);
|
||||
|
||||
ctrl = skip_strip_mined()->in(LoopNode::EntryControl);
|
||||
}
|
||||
if (is_main_loop() || is_post_loop()) {
|
||||
return skip_predicates_from_entry(ctrl);
|
||||
}
|
||||
return in(LoopNode::EntryControl);
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
|
||||
@@ -5351,38 +5353,45 @@ void PhaseIdealLoop::build_loop_late_post_work(Node *n, bool pinned) {
|
||||
}
|
||||
assert(early == legal || legal != C->root(), "bad dominance of inputs");
|
||||
|
||||
if (least != early) {
|
||||
// Move the node above predicates as far up as possible so a
|
||||
// following pass of loop predication doesn't hoist a predicate
|
||||
// that depends on it above that node.
|
||||
Node* new_ctrl = least;
|
||||
for (;;) {
|
||||
if (!new_ctrl->is_Proj()) {
|
||||
break;
|
||||
}
|
||||
CallStaticJavaNode* call = new_ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none);
|
||||
if (call == NULL) {
|
||||
break;
|
||||
}
|
||||
int req = call->uncommon_trap_request();
|
||||
Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req);
|
||||
if (trap_reason != Deoptimization::Reason_loop_limit_check &&
|
||||
trap_reason != Deoptimization::Reason_predicate &&
|
||||
trap_reason != Deoptimization::Reason_profile_predicate) {
|
||||
break;
|
||||
}
|
||||
Node* c = new_ctrl->in(0)->in(0);
|
||||
if (is_dominator(c, early) && c != early) {
|
||||
break;
|
||||
}
|
||||
new_ctrl = c;
|
||||
}
|
||||
least = new_ctrl;
|
||||
}
|
||||
// Try not to place code on a loop entry projection
|
||||
// which can inhibit range check elimination.
|
||||
if (least != early) {
|
||||
Node* ctrl_out = least->unique_ctrl_out();
|
||||
if (ctrl_out && ctrl_out->is_Loop() &&
|
||||
least == ctrl_out->in(LoopNode::EntryControl)) {
|
||||
// Move the node above predicates as far up as possible so a
|
||||
// following pass of loop predication doesn't hoist a predicate
|
||||
// that depends on it above that node.
|
||||
Node* new_ctrl = least;
|
||||
for (;;) {
|
||||
if (!new_ctrl->is_Proj()) {
|
||||
break;
|
||||
}
|
||||
CallStaticJavaNode* call = new_ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none);
|
||||
if (call == NULL) {
|
||||
break;
|
||||
}
|
||||
int req = call->uncommon_trap_request();
|
||||
Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req);
|
||||
if (trap_reason != Deoptimization::Reason_loop_limit_check &&
|
||||
trap_reason != Deoptimization::Reason_predicate &&
|
||||
trap_reason != Deoptimization::Reason_profile_predicate) {
|
||||
break;
|
||||
}
|
||||
Node* c = new_ctrl->in(0)->in(0);
|
||||
if (is_dominator(c, early) && c != early) {
|
||||
break;
|
||||
}
|
||||
new_ctrl = c;
|
||||
least == ctrl_out->in(LoopNode::EntryControl) &&
|
||||
(ctrl_out->is_CountedLoop() || ctrl_out->is_OuterStripMinedLoop())) {
|
||||
Node* least_dom = idom(least);
|
||||
if (get_loop(least_dom)->is_member(get_loop(least))) {
|
||||
least = least_dom;
|
||||
}
|
||||
least = new_ctrl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -915,13 +915,13 @@ private:
|
||||
void copy_skeleton_predicates_to_main_loop(CountedLoopNode* pre_head, Node* init, Node* stride, IdealLoopTree* outer_loop, LoopNode* outer_main_head,
|
||||
uint dd_main_head, const uint idx_before_pre_post, const uint idx_after_post_before_pre,
|
||||
Node* zero_trip_guard_proj_main, Node* zero_trip_guard_proj_post, const Node_List &old_new);
|
||||
Node* clone_skeleton_predicate_for_main_loop(Node* iff, Node* new_init, Node* new_stride, Node* predicate, Node* uncommon_proj, Node* control,
|
||||
IdealLoopTree* outer_loop, Node* input_proj);
|
||||
Node* clone_skeleton_predicate_bool(Node* iff, Node* new_init, Node* new_stride, Node* predicate, Node* uncommon_proj, Node* control,
|
||||
IdealLoopTree* outer_loop);
|
||||
Node* clone_skeleton_predicate_for_main_or_post_loop(Node* iff, Node* new_init, Node* new_stride, Node* predicate, Node* uncommon_proj, Node* control,
|
||||
IdealLoopTree* outer_loop, Node* input_proj);
|
||||
Node* clone_skeleton_predicate_bool(Node* iff, Node* new_init, Node* new_stride, Node* control);
|
||||
static bool skeleton_predicate_has_opaque(IfNode* iff);
|
||||
static void get_skeleton_predicates(Node* predicate, Unique_Node_List& list, bool get_opaque = false);
|
||||
void update_main_loop_skeleton_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, int stride_con);
|
||||
void copy_skeleton_predicates_to_post_loop(LoopNode* main_loop_head, CountedLoopNode* post_loop_head, Node* init, Node* stride);
|
||||
void insert_loop_limit_check(ProjNode* limit_check_proj, Node* cmp_limit, Node* bol);
|
||||
#ifdef ASSERT
|
||||
bool only_has_infinite_loops();
|
||||
@@ -1244,9 +1244,9 @@ public:
|
||||
void insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_new, bool peel_only );
|
||||
|
||||
// Add post loop after the given loop.
|
||||
Node *insert_post_loop(IdealLoopTree *loop, Node_List &old_new,
|
||||
CountedLoopNode *main_head, CountedLoopEndNode *main_end,
|
||||
Node *incr, Node *limit, CountedLoopNode *&post_head);
|
||||
Node *insert_post_loop(IdealLoopTree* loop, Node_List& old_new,
|
||||
CountedLoopNode* main_head, CountedLoopEndNode* main_end,
|
||||
Node*& incr, Node* limit, CountedLoopNode*& post_head);
|
||||
|
||||
// Add an RCE'd post loop which we will multi-version adapt for run time test path usage
|
||||
void insert_scalar_rced_post_loop( IdealLoopTree *loop, Node_List &old_new );
|
||||
@@ -1579,8 +1579,9 @@ private:
|
||||
Node_List* old_new = NULL);
|
||||
void clone_skeleton_predicates_to_unswitched_loop(IdealLoopTree* loop, const Node_List& old_new, Deoptimization::DeoptReason reason,
|
||||
ProjNode* old_predicate_proj, ProjNode* iffast_pred, ProjNode* ifslow_pred);
|
||||
ProjNode* clone_skeleton_predicate_for_unswitched_loops(Node* iff, ProjNode* predicate, Node* uncommon_proj, Deoptimization::DeoptReason reason,
|
||||
ProjNode* output_proj, IdealLoopTree* loop);
|
||||
ProjNode* clone_skeleton_predicate_for_unswitched_loops(Node* iff, ProjNode* predicate,
|
||||
Deoptimization::DeoptReason reason,
|
||||
ProjNode* output_proj);
|
||||
static void check_created_predicate_for_unswitching(const Node* new_entry) PRODUCT_RETURN;
|
||||
|
||||
bool _created_loop_node;
|
||||
|
||||
@@ -2562,6 +2562,7 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
|
||||
assert(n->Opcode() == Op_LoopLimit ||
|
||||
n->Opcode() == Op_Opaque2 ||
|
||||
n->Opcode() == Op_Opaque3 ||
|
||||
n->Opcode() == Op_Opaque4 ||
|
||||
BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(n),
|
||||
"unknown node type in macro list");
|
||||
}
|
||||
@@ -2623,6 +2624,19 @@ bool PhaseMacroExpand::expand_macro_nodes() {
|
||||
_igvn.replace_node(n, repl);
|
||||
success = true;
|
||||
#endif
|
||||
} else if (n->Opcode() == Op_Opaque4) {
|
||||
// With Opaque4 nodes, the expectation is that the test of input 1
|
||||
// is always equal to the constant value of input 2. So we can
|
||||
// remove the Opaque4 and replace it by input 2. In debug builds,
|
||||
// leave the non constant test in instead to sanity check that it
|
||||
// never fails (if it does, that subgraph was constructed so, at
|
||||
// runtime, a Halt node is executed).
|
||||
#ifdef ASSERT
|
||||
_igvn.replace_node(n, n->in(1));
|
||||
#else
|
||||
_igvn.replace_node(n, n->in(2));
|
||||
#endif
|
||||
success = true;
|
||||
} else if (n->Opcode() == Op_OuterStripMinedLoop) {
|
||||
n->as_OuterStripMinedLoop()->adjust_strip_mined_loop(&_igvn);
|
||||
C->remove_macro_node(n);
|
||||
|
||||
@@ -60,25 +60,6 @@ bool Opaque2Node::cmp( const Node &n ) const {
|
||||
return (&n == this); // Always fail except on self
|
||||
}
|
||||
|
||||
Node* Opaque4Node::Identity(PhaseGVN* phase) {
|
||||
if (phase->C->post_loop_opts_phase()) {
|
||||
// With Opaque4 nodes, the expectation is that the test of input 1
|
||||
// is always equal to the constant value of input 2. So we can
|
||||
// remove the Opaque4 and replace it by input 2. In debug builds,
|
||||
// leave the non constant test in instead to sanity check that it
|
||||
// never fails (if it does, that subgraph was constructed so, at
|
||||
// runtime, a Halt node is executed).
|
||||
#ifdef ASSERT
|
||||
return this->in(1);
|
||||
#else
|
||||
return this->in(2);
|
||||
#endif
|
||||
} else {
|
||||
phase->C->record_for_post_loop_opts_igvn(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
const Type* Opaque4Node::Value(PhaseGVN* phase) const {
|
||||
return phase->type(in(1));
|
||||
}
|
||||
|
||||
@@ -114,11 +114,13 @@ class Opaque3Node : public Opaque2Node {
|
||||
// GraphKit::must_be_not_null().
|
||||
class Opaque4Node : public Node {
|
||||
public:
|
||||
Opaque4Node(Compile* C, Node *tst, Node* final_tst) : Node(NULL, tst, final_tst) {}
|
||||
Opaque4Node(Compile* C, Node *tst, Node* final_tst) : Node(NULL, tst, final_tst) {
|
||||
init_flags(Flag_is_macro);
|
||||
C->add_macro_node(this);
|
||||
}
|
||||
|
||||
virtual int Opcode() const;
|
||||
virtual const Type *bottom_type() const { return TypeInt::BOOL; }
|
||||
virtual Node* Identity(PhaseGVN* phase);
|
||||
virtual const Type* Value(PhaseGVN* phase) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -200,6 +200,24 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (n->Opcode() == Op_OpaqueLoopStride || n->Opcode() == Op_OpaqueLoopInit) {
|
||||
Unique_Node_List wq;
|
||||
wq.push(n);
|
||||
for (uint i = 0; i < wq.size(); i++) {
|
||||
Node* m = wq.at(i);
|
||||
if (m->is_If()) {
|
||||
assert(skeleton_predicate_has_opaque(m->as_If()), "opaque node not reachable from if?");
|
||||
Node* bol = clone_skeleton_predicate_bool(m, NULL, NULL, m->in(0));
|
||||
_igvn.replace_input_of(m, 1, bol);
|
||||
} else {
|
||||
assert(!m->is_CFG(), "not CFG expected");
|
||||
for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) {
|
||||
Node* u = m->fast_out(j);
|
||||
wq.push(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if splitting-up a Store. Any anti-dep loads must go up as
|
||||
// well. An anti-dep load might be in the wrong block, because in
|
||||
|
||||
@@ -2129,6 +2129,11 @@ class AffectedKlassClosure : public KlassClosure {
|
||||
void do_klass(Klass* klass) {
|
||||
assert(!_affected_klasses->contains(klass), "must not occur more than once!");
|
||||
|
||||
// allow only loaded classes
|
||||
if (!klass->is_instance_klass() || !InstanceKlass::cast(klass)->is_loaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (klass->new_version() != NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -2185,12 +2190,8 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(TRAPS) {
|
||||
{
|
||||
MutexLocker mcld(ClassLoaderDataGraph_lock);
|
||||
|
||||
// We can't use ClassLoaderDataGraph::classes_do since classes can be uninitialized in cld,
|
||||
// fully initialized class is in system dictionary, but hidden classes are excluded. Therefore
|
||||
// we use special method iterating over initialized classes only
|
||||
// ClassLoaderDataGraph::classes_do(&closure);
|
||||
|
||||
ClassLoaderDataGraph::initialized_classes_do(&closure);
|
||||
// Hidden classes are not in SystemDictionary, so we have to iterate ClassLoaderDataGraph
|
||||
ClassLoaderDataGraph::classes_do(&closure);
|
||||
}
|
||||
|
||||
log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length());
|
||||
|
||||
@@ -372,10 +372,12 @@ public:
|
||||
};
|
||||
|
||||
class AdjustMethodEntriesDcevm : public StackObj {
|
||||
bool* _trace_name_printed;
|
||||
GrowableArray<oop>* _oops_to_add;
|
||||
GrowableArray<oop>* _oops_to_update;
|
||||
GrowableArray<Method*>* _old_methods;
|
||||
public:
|
||||
AdjustMethodEntriesDcevm(GrowableArray<oop>* oops_to_add, bool* trace_name_printed) : _trace_name_printed(trace_name_printed), _oops_to_add(oops_to_add) {};
|
||||
AdjustMethodEntriesDcevm(GrowableArray<oop>* oops_to_update, GrowableArray<Method*>* old_methods) :
|
||||
_oops_to_update(oops_to_update), _old_methods(old_methods) {};
|
||||
|
||||
bool operator()(WeakHandle* entry) {
|
||||
oop mem_name = entry->peek();
|
||||
if (mem_name == NULL) {
|
||||
@@ -386,46 +388,8 @@ public:
|
||||
Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
|
||||
|
||||
if (old_method->is_old()) {
|
||||
|
||||
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());
|
||||
_oops_to_update->append(mem_name);
|
||||
_old_methods->append(old_method);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -440,36 +404,70 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
|
||||
_local_table->do_safepoint_scan(adjust);
|
||||
}
|
||||
|
||||
// It is called at safepoint only for RedefineClasses
|
||||
// It is called at safepoint only for EnhancedRedefineClasses
|
||||
void ResolvedMethodTable::adjust_method_entries_dcevm(bool * trace_name_printed) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
|
||||
// For each entry in RMT, change to new method
|
||||
GrowableArray<oop> oops_to_add(0);
|
||||
AdjustMethodEntriesDcevm adjust(&oops_to_add, trace_name_printed);
|
||||
|
||||
GrowableArray<oop> oops_to_update(0);
|
||||
GrowableArray<Method*> old_methods(0);
|
||||
|
||||
AdjustMethodEntriesDcevm adjust(&oops_to_update, &old_methods);
|
||||
_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);
|
||||
|
||||
// The hash table takes ownership of the WeakHandle, even if it's not inserted.
|
||||
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);
|
||||
|
||||
ResolvedMethodTableLookup lookup(thread, method_hash(method), method);
|
||||
ResolvedMethodGet rmg(thread, method);
|
||||
// 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);
|
||||
|
||||
while (true) {
|
||||
if (_local_table->get(thread, lookup, rmg)) {
|
||||
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;
|
||||
// old method was already adjusted if new method exists in _the_table
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -117,7 +117,7 @@ const char* Abstract_VM_Version::vm_vendor() {
|
||||
#ifdef VENDOR
|
||||
return VENDOR;
|
||||
#else
|
||||
return "Oracle Corporation";
|
||||
return "JetBrains s.r.o.";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1337,6 +1337,7 @@ 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();
|
||||
@@ -2131,7 +2132,8 @@ 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), "unknown module property: '%s'", prop_name);
|
||||
assert(is_internal_module_property(prop_name) ||
|
||||
strcmp(prop_name, "jdk.module.illegalAccess") == 0, "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);
|
||||
@@ -2503,6 +2505,11 @@ 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))) {
|
||||
@@ -4027,9 +4034,9 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
|
||||
// Set object alignment values.
|
||||
set_object_alignment();
|
||||
|
||||
#ifndef ZERO
|
||||
#if INCLUDE_JFR
|
||||
if (FlightRecorder) {
|
||||
if (AllowEnhancedClassRedefinition) {
|
||||
if (AllowEnhancedClassRedefinition || StartFlightRecording != NULL) {
|
||||
warning("EnhancedClassRedefinition was disabled, it is not allowed in FlightRecorder.");
|
||||
AllowEnhancedClassRedefinition = false;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.jetbrains.internal;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@@ -103,9 +105,10 @@ public class JBRApi {
|
||||
JBRApi.outerLookup = outerLookup;
|
||||
try {
|
||||
Class<?> metadataClass = outerLookup.findClass("com.jetbrains.JBR$Metadata");
|
||||
knownServices = Set.of((String[]) outerLookup.findStaticVarHandle(metadataClass,
|
||||
Lookup lookup = MethodHandles.privateLookupIn(metadataClass, outerLookup);
|
||||
knownServices = Set.of((String[]) lookup.findStaticVarHandle(metadataClass,
|
||||
"KNOWN_SERVICES", String[].class).get());
|
||||
knownProxies = Set.of((String[]) outerLookup.findStaticVarHandle(metadataClass,
|
||||
knownProxies = Set.of((String[]) lookup.findStaticVarHandle(metadataClass,
|
||||
"KNOWN_PROXIES", String[].class).get());
|
||||
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
@@ -156,13 +159,52 @@ public class JBRApi {
|
||||
RegisteredProxyInfo info = registeredProxyInfoByTargetName.get(targetName);
|
||||
if (info == null) return null;
|
||||
try {
|
||||
return (info.type() == ProxyInfo.Type.CLIENT_PROXY ? info.apiModule() : outerLookup)
|
||||
return (info.type().isPublicApi() ? outerLookup : info.apiModule())
|
||||
.findClass(info.interfaceName());
|
||||
} catch (ClassNotFoundException | IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static InternalServiceBuilder internalServiceBuilder(Lookup interFace, String target) {
|
||||
return new InternalServiceBuilder(new RegisteredProxyInfo(
|
||||
interFace, interFace.lookupClass().getName(), target, ProxyInfo.Type.INTERNAL_SERVICE, new ArrayList<>()));
|
||||
}
|
||||
|
||||
public static class InternalServiceBuilder {
|
||||
|
||||
private final RegisteredProxyInfo info;
|
||||
|
||||
private InternalServiceBuilder(RegisteredProxyInfo info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public InternalServiceBuilder withStatic(String methodName, String clazz) {
|
||||
return withStatic(methodName, clazz, methodName);
|
||||
}
|
||||
|
||||
public InternalServiceBuilder withStatic(String interfaceMethodName, String clazz, String methodName) {
|
||||
info.staticMethods().add(
|
||||
new RegisteredProxyInfo.StaticMethodMapping(interfaceMethodName, clazz, methodName));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object build() {
|
||||
ProxyInfo info = ProxyInfo.resolve(this.info);
|
||||
if (info == null) return null;
|
||||
ProxyGenerator generator = new ProxyGenerator(info);
|
||||
if (!generator.areAllMethodsImplemented()) return null;
|
||||
generator.defineClasses();
|
||||
MethodHandle constructor = generator.findConstructor();
|
||||
generator.init();
|
||||
try {
|
||||
return constructor.invoke();
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@linkplain com.jetbrains.bootstrap.JBRApiBootstrap#MODULES registry classes}
|
||||
* to register a new mapping for corresponding modules.
|
||||
|
||||
@@ -78,7 +78,7 @@ class ProxyGenerator {
|
||||
*/
|
||||
ProxyGenerator(ProxyInfo info) {
|
||||
this.info = info;
|
||||
generateBridge = info.type != ProxyInfo.Type.CLIENT_PROXY;
|
||||
generateBridge = info.type.isPublicApi();
|
||||
int nameId = nameCounter.getAndIncrement();
|
||||
proxyName = Type.getInternalName(info.interFace) + "$$JBRApiProxy$" + nameId;
|
||||
bridgeName = generateBridge ? info.apiModule.lookupClass().getPackageName().replace('.', '/') + "/" +
|
||||
@@ -153,7 +153,7 @@ class ProxyGenerator {
|
||||
} else {
|
||||
MethodHandle c = generatedProxy.findConstructor(generatedProxy.lookupClass(),
|
||||
MethodType.methodType(void.class, Object.class));
|
||||
if (info.type == ProxyInfo.Type.SERVICE) {
|
||||
if (info.type.isService()) {
|
||||
try {
|
||||
return MethodHandles.foldArguments(c, info.target.findConstructor(info.target.lookupClass(),
|
||||
MethodType.methodType(void.class)).asType(MethodType.methodType(Object.class)));
|
||||
|
||||
@@ -66,7 +66,7 @@ class ProxyInfo {
|
||||
}
|
||||
|
||||
Lookup getInterfaceLookup() {
|
||||
return type == Type.CLIENT_PROXY ? apiModule : JBRApi.outerLookup;
|
||||
return type == Type.CLIENT_PROXY || type == Type.INTERNAL_SERVICE ? apiModule : JBRApi.outerLookup;
|
||||
}
|
||||
|
||||
Lookup getTargetLookup() {
|
||||
@@ -74,12 +74,18 @@ class ProxyInfo {
|
||||
}
|
||||
|
||||
private Lookup lookup(Lookup lookup, String clazz) {
|
||||
try {
|
||||
return MethodHandles.privateLookupIn(lookup.findClass(clazz), lookup);
|
||||
} catch (ClassNotFoundException | IllegalAccessException e) {
|
||||
if (lookup == JBRApi.outerLookup) return null;
|
||||
else throw new RuntimeException(e);
|
||||
String[] nestedClasses = clazz.split("\\$");
|
||||
clazz = "";
|
||||
for (int i = 0; i < nestedClasses.length; i++) {
|
||||
try {
|
||||
if (i != 0) clazz += "$";
|
||||
clazz += nestedClasses[i];
|
||||
lookup = MethodHandles.privateLookupIn(lookup.findClass(clazz), lookup);
|
||||
} catch (ClassNotFoundException | IllegalAccessException ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return lookup;
|
||||
}
|
||||
|
||||
record StaticMethodMapping(Lookup lookup, String methodName) {}
|
||||
@@ -90,6 +96,15 @@ class ProxyInfo {
|
||||
enum Type {
|
||||
PROXY,
|
||||
SERVICE,
|
||||
CLIENT_PROXY
|
||||
CLIENT_PROXY,
|
||||
INTERNAL_SERVICE;
|
||||
|
||||
public boolean isPublicApi() {
|
||||
return this == PROXY || this == SERVICE;
|
||||
}
|
||||
|
||||
public boolean isService() {
|
||||
return this == SERVICE || this == INTERNAL_SERVICE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,4 +68,14 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
@@ -147,7 +147,8 @@ 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.addopens.0") == null && // --add-opens
|
||||
getProperty("jdk.module.illegalAccess") == null; // --jbr-illegal-access
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,6 +189,7 @@ 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");
|
||||
@@ -219,7 +221,8 @@ public final class ModuleBootstrap {
|
||||
&& !haveModulePath
|
||||
&& addModules.isEmpty()
|
||||
&& limitModules.isEmpty()
|
||||
&& !isPatched) {
|
||||
&& !isPatched
|
||||
&& illegalAccess == null) {
|
||||
systemModuleFinder = archivedModuleGraph.finder();
|
||||
hasSplitPackages = archivedModuleGraph.hasSplitPackages();
|
||||
hasIncubatorModules = archivedModuleGraph.hasIncubatorModules();
|
||||
@@ -454,10 +457,19 @@ public final class ModuleBootstrap {
|
||||
checkIncubatingStatus(cf);
|
||||
}
|
||||
|
||||
// --add-reads, --add-exports/--add-opens
|
||||
// --add-reads, --add-exports/--add-opens, and --jbr-illegal-access
|
||||
addExtraReads(bootLayer);
|
||||
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
|
||||
|
||||
if (illegalAccess != null) {
|
||||
assert systemModules != null;
|
||||
addIllegalAccess(illegalAccess,
|
||||
systemModules,
|
||||
upgradeModulePath,
|
||||
bootLayer,
|
||||
extraExportsOrOpens);
|
||||
}
|
||||
|
||||
// add enable native access
|
||||
addEnableNativeAccess(bootLayer);
|
||||
|
||||
@@ -813,6 +825,74 @@ 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.
|
||||
|
||||
@@ -83,4 +83,16 @@ 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();
|
||||
}
|
||||
|
||||
1340
src/java.base/share/classes/jdk/internal/module/jdk8_packages.dat
Normal file
1340
src/java.base/share/classes/jdk/internal/module/jdk8_packages.dat
Normal file
File diff suppressed because it is too large
Load Diff
@@ -188,6 +188,10 @@ 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\
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -59,6 +59,7 @@ 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;
|
||||
@@ -283,6 +284,16 @@ 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) {
|
||||
@@ -291,10 +302,6 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,10 @@ import java.beans.PropertyChangeListener;
|
||||
import java.lang.annotation.Native;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.Arrays;
|
||||
@@ -76,24 +75,41 @@ 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 {
|
||||
AtomicInteger invokeTimeoutSecondsRef = new AtomicInteger();
|
||||
// Need to load the native library for this code.
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
System.loadLibrary("awt");
|
||||
invokeTimeoutSecondsRef.set(
|
||||
// (-1) for the infinite timeout
|
||||
Integer.getInteger("sun.lwawt.macosx.CAccessibility.invokeTimeoutSeconds",
|
||||
INVOKE_TIMEOUT_SECONDS_DEFAULT));
|
||||
return null;
|
||||
}
|
||||
// (-1) for the infinite timeout
|
||||
@SuppressWarnings("removal")
|
||||
int value = java.security.AccessController.doPrivileged(
|
||||
(PrivilegedAction<Integer>) () -> {
|
||||
// Need to load the native library for this code.
|
||||
System.loadLibrary("awt");
|
||||
return Integer.getInteger("sun.lwawt.macosx.CAccessibility.invokeTimeoutSeconds", 1);
|
||||
});
|
||||
INVOKE_TIMEOUT_SECONDS = invokeTimeoutSecondsRef.get();
|
||||
INVOKE_TIMEOUT_SECONDS = value;
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}, c);
|
||||
}
|
||||
|
||||
static CAccessibility sAccessibility;
|
||||
|
||||
@@ -205,8 +205,10 @@ 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) {
|
||||
} else if (thisRole == AccessibleRole.MENU_ITEM ||
|
||||
((parentRole == AccessibleRole.POPUP_MENU) && (thisRole == AccessibleRole.MENU))) {
|
||||
if (newValue != null &&
|
||||
((AccessibleState) newValue) == AccessibleState.FOCUSED) {
|
||||
execute(ptr -> menuItemSelected(ptr));
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
package sun.lwawt.macosx;
|
||||
|
||||
import sun.awt.AWTThreading;
|
||||
import java.awt.Menu;
|
||||
import java.awt.MenuBar;
|
||||
import java.awt.MenuItem;
|
||||
@@ -64,14 +65,14 @@ public class CMenu extends CMenuItem implements MenuPeer {
|
||||
LWCToolkit.targetToPeer(getTarget().getParent());
|
||||
|
||||
if (parent instanceof CMenu) {
|
||||
return parent.executeGet(this::nativeCreateSubMenu);
|
||||
return AWTThreading.executeWaitToolkit(() -> parent.executeGet(this::nativeCreateSubMenu));
|
||||
}
|
||||
if (parent instanceof CMenuBar) {
|
||||
MenuBar parentContainer = (MenuBar)getTarget().getParent();
|
||||
boolean isHelpMenu = parentContainer.getHelpMenu() == getTarget();
|
||||
int insertionLocation = ((CMenuBar)parent).getNextInsertionIndex();
|
||||
return parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
|
||||
insertionLocation));
|
||||
return AWTThreading.executeWaitToolkit(() -> parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
|
||||
insertionLocation)));
|
||||
}
|
||||
throw new InternalError("Parent must be CMenu or CMenuBar");
|
||||
}
|
||||
@@ -84,7 +85,7 @@ public class CMenu extends CMenuItem implements MenuPeer {
|
||||
|
||||
@Override
|
||||
public final void delItem(final int index) {
|
||||
execute(ptr -> nativeDeleteItem(ptr, index));
|
||||
AWTThreading.executeWaitToolkit(() -> execute(ptr -> nativeDeleteItem(ptr, index)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,6 +33,7 @@ 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;
|
||||
|
||||
@@ -61,7 +62,7 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
|
||||
@Override
|
||||
long createModel() {
|
||||
CMenuComponent parent = (CMenuComponent)LWToolkit.targetToPeer(getTarget().getParent());
|
||||
return parent.executeGet(ptr->nativeCreate(ptr, isSeparator()));
|
||||
return AWTThreading.executeWaitToolkit(() -> parent.executeGet(ptr->nativeCreate(ptr, isSeparator())));
|
||||
}
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setLabel(String label, char keyChar, int keyCode, int modifiers) {
|
||||
|
||||
@@ -66,6 +66,7 @@ import sun.awt.AWTAccessor.ComponentAccessor;
|
||||
import sun.awt.AWTAccessor.WindowAccessor;
|
||||
import sun.awt.AWTThreading;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.lwawt.LWComponentPeer;
|
||||
import sun.lwawt.LWLightweightFramePeer;
|
||||
import sun.lwawt.LWToolkit;
|
||||
import sun.lwawt.LWWindowPeer;
|
||||
@@ -105,6 +106,7 @@ 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");
|
||||
@@ -290,7 +292,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
new Property<CPlatformWindow>(WINDOW_TRANSPARENT_TITLE_BAR_HEIGHT) {
|
||||
public void applyProperty(final CPlatformWindow c, final Object value) {
|
||||
if (value != null && (value instanceof Float)) {
|
||||
c.execute(ptr -> nativeSetTransparentTitleBarHeight(ptr, (float) value));
|
||||
c.execute(ptr -> AWTThreading.executeWaitToolkit(wait -> nativeSetTransparentTitleBarHeight(ptr, (float) value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1195,6 +1197,10 @@ 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();
|
||||
@@ -1456,28 +1462,20 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
isFullScreenAnimationOn = false;
|
||||
}
|
||||
|
||||
// called from client via reflection
|
||||
private void setTransparentTitleBarHeight(float height) {
|
||||
execute(ptr -> {
|
||||
nativeSetTransparentTitleBarHeight(ptr, height);
|
||||
});
|
||||
}
|
||||
|
||||
private volatile List<Rectangle> customDecorHitTestSpots;
|
||||
|
||||
// called from client via reflection
|
||||
private void setCustomDecorationHitTestSpots(List<Rectangle> hitTestSpots) {
|
||||
this.customDecorHitTestSpots = new CopyOnWriteArrayList<>(hitTestSpots);
|
||||
}
|
||||
|
||||
// called from native
|
||||
private boolean hitTestCustomDecoration(float x, float y) {
|
||||
List<Rectangle> spots = customDecorHitTestSpots;
|
||||
if (spots == null) return false;
|
||||
for (Rectangle spot : spots) {
|
||||
if (spot.contains(x, y)) return true;
|
||||
// JBR API internals
|
||||
private static void setCustomDecorationTitleBarHeight(Window target, ComponentPeer peer, float height) {
|
||||
if (peer instanceof LWComponentPeer) {
|
||||
PlatformWindow platformWindow = ((LWComponentPeer<?, ?>) peer).getPlatformWindow();
|
||||
if (platformWindow instanceof CPlatformWindow) {
|
||||
((CPlatformWindow) platformWindow).execute(ptr -> {
|
||||
AWTThreading.executeWaitToolkit(wait -> nativeSetTransparentTitleBarHeight(ptr, height));
|
||||
});
|
||||
if (target instanceof javax.swing.RootPaneContainer) {
|
||||
final javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer)target).getRootPane();
|
||||
if (rootpane != null) rootpane.putClientProperty(WINDOW_TRANSPARENT_TITLE_BAR_HEIGHT, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ import java.net.URL;
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@@ -111,6 +112,7 @@ 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
|
||||
@@ -140,6 +142,13 @@ 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();
|
||||
|
||||
@@ -186,7 +195,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
*/
|
||||
private static final boolean inAWT;
|
||||
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.lwawt.macosx.LWCToolkit");
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger(LWCToolkit.class.getName());
|
||||
|
||||
public LWCToolkit() {
|
||||
final String extraButtons = "sun.awt.enableExtraMouseButtons";
|
||||
@@ -495,7 +504,8 @@ public final class LWCToolkit extends LWToolkit {
|
||||
if (!(gd instanceof CGraphicsDevice)) {
|
||||
return AWTThreading.executeWaitToolkit(() -> super.getScreenInsets(gc));
|
||||
}
|
||||
return AWTThreading.executeWaitToolkit(() -> ((CGraphicsDevice)gd).getScreenInsets());
|
||||
CGraphicsDevice cgd = (CGraphicsDevice) gd;
|
||||
return cgd.getScreenInsets();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -675,30 +685,12 @@ public final class LWCToolkit extends LWToolkit {
|
||||
return invokeAndWait(callable, component, -1);
|
||||
}
|
||||
|
||||
static <T> T invokeAndWait(final Callable<T> callable, Component component, int timeoutSeconds) throws Exception {
|
||||
public static <T> T invokeAndWait(final Callable<T> callable, Component component, int timeoutSeconds) throws Exception {
|
||||
final CallableWrapper<T> wrapper = new CallableWrapper<>(callable);
|
||||
invokeAndWait(wrapper, component, false, timeoutSeconds);
|
||||
return wrapper.getResult();
|
||||
}
|
||||
|
||||
static final class CancelableRunnable implements Runnable {
|
||||
volatile Runnable runnable;
|
||||
|
||||
public CancelableRunnable(Runnable runnable) {
|
||||
this.runnable = runnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Runnable r = runnable;
|
||||
if (r != null) r.run();
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
runnable = null;
|
||||
}
|
||||
}
|
||||
|
||||
static final class CallableWrapper<T> implements Runnable {
|
||||
final Callable<T> callable;
|
||||
T object;
|
||||
@@ -728,30 +720,6 @@ 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
|
||||
@@ -776,32 +744,32 @@ public final class LWCToolkit extends LWToolkit {
|
||||
invokeAndWait(runnable, component, false, -1);
|
||||
}
|
||||
|
||||
static void invokeAndWait(Runnable runnable, Component component, boolean processEvents, int timeoutSeconds)
|
||||
public static void invokeAndWait(Runnable runnable, Component component, boolean processEvents, int timeoutSeconds)
|
||||
throws InvocationTargetException
|
||||
{
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine("invokeAndWait started: " + runnable);
|
||||
}
|
||||
|
||||
boolean nonBlockingRunLoop;
|
||||
CancelableRunnable cancelableRunnable = new CancelableRunnable(runnable);
|
||||
|
||||
synchronized (priorityInvocationPending) {
|
||||
nonBlockingRunLoop = priorityInvocationPending.get();
|
||||
if (!nonBlockingRunLoop) blockingRunLoopCounter.incrementAndGet();
|
||||
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;
|
||||
}
|
||||
|
||||
final long mediator = createAWTRunLoopMediator();
|
||||
AWTThreading.TrackedInvocationEvent invocationEvent =
|
||||
AWTThreading.createAndTrackInvocationEvent(component, runnable, true);
|
||||
|
||||
InvocationEvent invocationEvent =
|
||||
AWTThreading.createAndTrackInvocationEvent(component,
|
||||
cancelableRunnable,
|
||||
() -> {
|
||||
if (mediator != 0) {
|
||||
stopAWTRunLoop(mediator);
|
||||
}
|
||||
},
|
||||
true);
|
||||
long mediator = createAWTRunLoopMediator();
|
||||
invocationEvent.onDone(() -> stopAWTRunLoop(mediator));
|
||||
|
||||
if (component != null) {
|
||||
AppContext appContext = SunToolkit.targetToAppContext(component);
|
||||
@@ -815,11 +783,21 @@ public final class LWCToolkit extends LWToolkit {
|
||||
((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent);
|
||||
}
|
||||
|
||||
if (!doAWTRunLoop(mediator, nonBlockingRunLoop, timeoutSeconds)) {
|
||||
new Throwable("Invocation timed out (" + timeoutSeconds + "sec)").printStackTrace();
|
||||
cancelableRunnable.cancel();
|
||||
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 (!nonBlockingRunLoop) blockingRunLoopCounter.decrementAndGet();
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine("invokeAndWait finished: " + runnable);
|
||||
@@ -828,6 +806,8 @@ 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");
|
||||
@@ -870,6 +850,11 @@ 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
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
NSWindowTabbingMode javaWindowTabbingMode;
|
||||
BOOL isEnterFullScreen;
|
||||
CGFloat _transparentTitleBarHeight;
|
||||
id<NSObject> _windowWillEnterFullScreenNotification;
|
||||
id<NSObject> _windowWillExitFullScreenNotification;
|
||||
id<NSObject> _windowDidExitFullScreenNotification;
|
||||
NSMutableArray* _transparentTitleBarConstraints;
|
||||
NSLayoutConstraint *_transparentTitleBarHeightConstraint;
|
||||
NSMutableArray *_transparentTitleBarButtonCenterXConstraints;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <objc/objc-runtime.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include <java_awt_Window_CustomWindowDecoration.h>
|
||||
#import "sun_lwawt_macosx_CPlatformWindow.h"
|
||||
#import "com_apple_eawt_event_GestureHandler.h"
|
||||
#import "com_apple_eawt_FullScreenHandler.h"
|
||||
@@ -775,7 +776,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
|
||||
@@ -784,10 +785,18 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
|
||||
if (platformWindow == NULL) {
|
||||
// TODO: create generic AWT assert
|
||||
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;
|
||||
}
|
||||
|
||||
NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]);
|
||||
|
||||
GET_CPLATFORM_WINDOW_CLASS();
|
||||
DECLARE_METHOD(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIIIZ)V");
|
||||
@@ -1009,7 +1018,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
#ifdef DEBUG
|
||||
NSLog(@"resigned key: %d %@ %@", [self.nsWindow isMainWindow], [self.nsWindow title], [self menuBarForWindow]);
|
||||
#endif
|
||||
if (![self.nsWindow isMainWindow]) {
|
||||
if (![self.nsWindow isMainWindow] || [NSApp keyWindow] == self.nsWindow) {
|
||||
[self deactivateWindow];
|
||||
}
|
||||
}
|
||||
@@ -1038,7 +1047,9 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
NSWindow *keyWindow = [NSApp keyWindow];
|
||||
AWTWindow *opposite = nil;
|
||||
if ([AWTWindow isAWTWindow: keyWindow]) {
|
||||
opposite = (AWTWindow *)[keyWindow delegate];
|
||||
if (keyWindow != self.nsWindow) {
|
||||
opposite = (AWTWindow *)[keyWindow delegate];
|
||||
}
|
||||
[AWTWindow setLastKeyWindow: self];
|
||||
} else {
|
||||
[AWTWindow setLastKeyWindow: nil];
|
||||
@@ -1294,10 +1305,10 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
NSView* titlebarContainer = titlebar.superview;
|
||||
NSView* themeFrame = titlebarContainer.superview;
|
||||
|
||||
NSMutableArray* newConstraints = [[NSMutableArray alloc] init];
|
||||
_transparentTitleBarConstraints = [[NSMutableArray alloc] init];
|
||||
titlebarContainer.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
_transparentTitleBarHeightConstraint = [titlebarContainer.heightAnchor constraintEqualToConstant:_transparentTitleBarHeight];
|
||||
[newConstraints addObjectsFromArray:@[
|
||||
[_transparentTitleBarConstraints addObjectsFromArray:@[
|
||||
[titlebarContainer.leftAnchor constraintEqualToAnchor:themeFrame.leftAnchor],
|
||||
[titlebarContainer.widthAnchor constraintEqualToAnchor:themeFrame.widthAnchor],
|
||||
[titlebarContainer.topAnchor constraintEqualToAnchor:themeFrame.topAnchor],
|
||||
@@ -1310,7 +1321,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
for (NSView* view in @[titlebar, windowDragView])
|
||||
{
|
||||
view.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[newConstraints addObjectsFromArray:@[
|
||||
[_transparentTitleBarConstraints addObjectsFromArray:@[
|
||||
[view.leftAnchor constraintEqualToAnchor:titlebarContainer.leftAnchor],
|
||||
[view.rightAnchor constraintEqualToAnchor:titlebarContainer.rightAnchor],
|
||||
[view.topAnchor constraintEqualToAnchor:titlebarContainer.topAnchor],
|
||||
@@ -1326,7 +1337,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
button.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
NSLayoutConstraint* buttonCenterXConstraint = [button.centerXAnchor constraintEqualToAnchor:titlebarContainer.leftAnchor constant:(_transparentTitleBarHeight/2.0 + (index * horizontalButtonOffset))];
|
||||
[_transparentTitleBarButtonCenterXConstraints addObject:buttonCenterXConstraint];
|
||||
[newConstraints addObjectsFromArray:@[
|
||||
[_transparentTitleBarConstraints addObjectsFromArray:@[
|
||||
[button.widthAnchor constraintLessThanOrEqualToAnchor:titlebarContainer.heightAnchor multiplier:0.5],
|
||||
// Those corrections are required to keep the icons perfectly round because macOS adds a constant 2 px in resulting height to their frame
|
||||
[button.heightAnchor constraintEqualToAnchor: button.widthAnchor multiplier:14.0/12.0 constant:-2.0],
|
||||
@@ -1335,7 +1346,7 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
]];
|
||||
}];
|
||||
|
||||
[NSLayoutConstraint activateConstraints:newConstraints];
|
||||
[NSLayoutConstraint activateConstraints:_transparentTitleBarConstraints];
|
||||
}
|
||||
|
||||
- (void) updateTransparentTitleBarConstraints
|
||||
@@ -1361,20 +1372,22 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
NSView* titlebarContainer = titlebar.superview;
|
||||
NSView* themeFrame = titlebarContainer.superview;
|
||||
|
||||
[NSLayoutConstraint deactivateConstraints:_transparentTitleBarConstraints];
|
||||
|
||||
AWTWindowDragView* windowDragView;
|
||||
for (NSView* view in titlebar.subviews) {
|
||||
if ([view isMemberOfClass:[AWTWindowDragView class]]) {
|
||||
windowDragView = view;
|
||||
}
|
||||
if (view.translatesAutoresizingMaskIntoConstraints == NO) {
|
||||
[view removeConstraints:view.constraints];
|
||||
view.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
}
|
||||
}
|
||||
[windowDragView removeFromSuperview];
|
||||
[titlebarContainer removeConstraints:titlebarContainer.constraints];
|
||||
titlebarContainer.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
titlebar.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
|
||||
_transparentTitleBarConstraints = nil;
|
||||
_transparentTitleBarHeightConstraint = nil;
|
||||
_transparentTitleBarButtonCenterXConstraints = nil;
|
||||
}
|
||||
@@ -1403,23 +1416,44 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
});
|
||||
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
|
||||
NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];
|
||||
[defaultCenter addObserverForName:NSWindowWillEnterFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
_windowWillEnterFullScreenNotification = [defaultCenter addObserverForName:NSWindowWillEnterFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
[self resetTitleBar];
|
||||
}];
|
||||
[defaultCenter addObserverForName:NSWindowWillExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
_windowWillExitFullScreenNotification = [defaultCenter addObserverForName:NSWindowWillExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
[self setWindowControlsHidden:YES];
|
||||
}];
|
||||
[defaultCenter addObserverForName:NSWindowDidExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
_windowDidExitFullScreenNotification = [defaultCenter addObserverForName:NSWindowDidExitFullScreenNotification object:self.nsWindow queue:mainQueue usingBlock:^(NSNotification* notification) {
|
||||
[self setUpTransparentTitleBar];
|
||||
[self setWindowControlsHidden:NO];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) configureWindowAndListenersForDefaultTitleBar
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
[self.nsWindow setTitlebarAppearsTransparent:NO];
|
||||
[self.nsWindow setTitleVisibility:NSWindowTitleVisible];
|
||||
[self.nsWindow setStyleMask:[self.nsWindow styleMask]&(~NSWindowStyleMaskFullSizeContentView)];
|
||||
|
||||
if (!self.isFullScreen) {
|
||||
[self resetTitleBar];
|
||||
}
|
||||
});
|
||||
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
|
||||
[defaultCenter removeObserver:_windowWillEnterFullScreenNotification];
|
||||
[defaultCenter removeObserver:_windowWillExitFullScreenNotification];
|
||||
[defaultCenter removeObserver:_windowDidExitFullScreenNotification];
|
||||
_windowWillEnterFullScreenNotification = _windowWillExitFullScreenNotification = _windowDidExitFullScreenNotification = nil;
|
||||
}
|
||||
|
||||
- (void) setTransparentTitleBarHeight: (CGFloat) transparentTitleBarHeight
|
||||
{
|
||||
if (_transparentTitleBarHeight == transparentTitleBarHeight) return;
|
||||
if (_transparentTitleBarHeight != 0.0f) {
|
||||
_transparentTitleBarHeight = transparentTitleBarHeight;
|
||||
if (_transparentTitleBarHeightConstraint != nil || _transparentTitleBarButtonCenterXConstraints != nil) {
|
||||
if (transparentTitleBarHeight == 0.0f) {
|
||||
[self configureWindowAndListenersForDefaultTitleBar];
|
||||
} else if (_transparentTitleBarHeightConstraint != nil || _transparentTitleBarButtonCenterXConstraints != nil) {
|
||||
[self updateTransparentTitleBarConstraints];
|
||||
}
|
||||
} else {
|
||||
@@ -1455,11 +1489,18 @@ static const CGFloat DefaultHorizontalTitleBarButtonOffset = 20.0;
|
||||
jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow);
|
||||
if (platformWindow != NULL) {
|
||||
GET_CPLATFORM_WINDOW_CLASS_RETURN(YES);
|
||||
DECLARE_METHOD_RETURN(jm_hitTestCustomDecoration, jc_CPlatformWindow, "hitTestCustomDecoration", "(FF)Z", YES);
|
||||
NSRect frame = [self.window frame];
|
||||
float windowHeight = frame.size.height;
|
||||
returnValue = (*env)->CallBooleanMethod(env, platformWindow, jm_hitTestCustomDecoration, point.x, windowHeight - point.y) == JNI_TRUE ? NO : YES;
|
||||
CHECK_EXCEPTION_IN_ENV(env);
|
||||
DECLARE_FIELD_RETURN(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;", YES);
|
||||
DECLARE_CLASS_RETURN(jc_Window, "java/awt/Window", YES);
|
||||
DECLARE_METHOD_RETURN(jm_hitTestCustomDecoration, jc_Window, "hitTestCustomDecoration", "(II)I", YES);
|
||||
jobject awtWindow = (*env)->GetObjectField(env, platformWindow, jf_target);
|
||||
if (awtWindow != NULL) {
|
||||
NSRect frame = [self.window frame];
|
||||
float windowHeight = frame.size.height;
|
||||
returnValue = (*env)->CallIntMethod(env, awtWindow, jm_hitTestCustomDecoration, (jint) point.x, (jint) (windowHeight - point.y)) ==
|
||||
(jint) java_awt_Window_CustomWindowDecoration_NO_HIT_SPOT ? YES : NO;
|
||||
CHECK_EXCEPTION();
|
||||
(*env)->DeleteLocalRef(env, awtWindow);
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, platformWindow);
|
||||
}
|
||||
return returnValue;
|
||||
@@ -1612,7 +1653,15 @@ JNI_COCOA_ENTER(env);
|
||||
|
||||
// resets the NSWindow's style mask if the mask intersects any of those bits
|
||||
if (mask & MASK(_STYLE_PROP_BITMASK)) {
|
||||
[nsWindow setStyleMask:[AWTWindow styleMaskForStyleBits:newBits]];
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
// calls methods on NSWindow to change other properties, based on the mask
|
||||
@@ -2300,4 +2349,18 @@ 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);
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ static BOOL sNeedsEnter;
|
||||
jobject transferer = [self dataTransferer:env];
|
||||
jbyteArray data = nil;
|
||||
|
||||
if (transferer != NULL) {
|
||||
if (transferer != NULL && fComponent != 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);
|
||||
|
||||
@@ -69,6 +69,9 @@ 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,
|
||||
@@ -107,6 +110,20 @@ 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
|
||||
@@ -155,6 +172,8 @@ Java_sun_lwawt_macosx_CRobot_initRobot
|
||||
for (i = 0; i < gNumberOfButtons; ++i) {
|
||||
gsButtonEventNumber[i] = ROBOT_EVENT_NUMBER_START;
|
||||
}
|
||||
|
||||
initKeyFlags();
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -283,6 +302,20 @@ 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
|
||||
@@ -298,6 +331,10 @@ 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);
|
||||
}
|
||||
|
||||
@@ -620,6 +620,17 @@ 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
|
||||
@@ -632,6 +643,8 @@ JNI_COCOA_ENTER(env);
|
||||
|
||||
AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator);
|
||||
|
||||
if (mediatorObject == nil) return;
|
||||
|
||||
[ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO];
|
||||
|
||||
[mediatorObject release];
|
||||
@@ -657,6 +670,23 @@ 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
|
||||
|
||||
@@ -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:51];
|
||||
rolesMap = [[NSMutableDictionary alloc] initWithCapacity:50];
|
||||
|
||||
[rolesMap setObject:@"ButtonAccessibility" forKey:@"pushbutton"];
|
||||
[rolesMap setObject:@"ImageAccessibility" forKey:@"icon"];
|
||||
@@ -158,7 +158,6 @@ 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"];
|
||||
|
||||
@@ -186,10 +185,11 @@ static jobject sAccessibilityClass = NULL;
|
||||
[rolesMap setObject:IgnoreClassName forKey:@"viewport"];
|
||||
[rolesMap setObject:IgnoreClassName forKey:@"window"];
|
||||
|
||||
rowRolesMapForParent = [[NSMutableDictionary alloc] initWithCapacity:2];
|
||||
rowRolesMapForParent = [[NSMutableDictionary alloc] initWithCapacity:3];
|
||||
|
||||
[rowRolesMapForParent setObject:@"ListRowAccessibility" forKey:@"ListAccessibility"];
|
||||
[rowRolesMapForParent setObject:@"OutlineRowAccessibility" forKey:@"OutlineAccessibility"];
|
||||
[rowRolesMapForParent setObject:@"MenuItemAccessibility" forKey:@"MenuAccessibility"];
|
||||
|
||||
/*
|
||||
* Initialize CAccessibility instance
|
||||
@@ -1186,7 +1186,25 @@ 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;
|
||||
@@ -1203,6 +1221,14 @@ 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];
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
- (BOOL)isAccessibilityElement
|
||||
{
|
||||
return YES;
|
||||
return [[[self accessibilityParent] accessibilityRole] isEqualToString:NSAccessibilityComboBoxRole];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -3371,7 +3371,7 @@ JNI_COCOA_ENTER(env);
|
||||
anotherBaseFont = true;
|
||||
}
|
||||
CTFontRef font = (CTFontRef)nsFont;
|
||||
CFArrayRef codes = CFLocaleCopyISOLanguageCodes();
|
||||
CFArrayRef codes = CFLocaleCopyPreferredLanguages();
|
||||
|
||||
CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes);
|
||||
CFRelease(codes);
|
||||
|
||||
@@ -127,6 +127,13 @@ 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;
|
||||
|
||||
@@ -50,6 +50,24 @@ 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,
|
||||
@@ -82,10 +100,10 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
}
|
||||
|
||||
/* This is needed because we can't directly pass a block to
|
||||
* performSelectorOnMainThreadWaiting .. since it expects a selector
|
||||
* performSelectorOnMainThreadWaiting:..waitUntilDone:YES.. since it expects a selector
|
||||
*/
|
||||
+ (void)invokeBlock:(void (^)())block {
|
||||
block();
|
||||
block();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -116,7 +134,19 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
if ([NSThread isMainThread] && wait == YES) {
|
||||
[target performSelector:aSelector withObject:arg];
|
||||
} else {
|
||||
[target performSelectorOnMainThread:aSelector withObject:arg waitUntilDone:wait modes:javaModes];
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,3 +173,16 @@ 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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ public class JBRApiModule {
|
||||
.withStatic("getSubpixelResolution", "sun.font.FontUtilities")
|
||||
.service("com.jetbrains.JBRFileDialogService", null)
|
||||
.withStatic("getFileDialog", "com.jetbrains.desktop.JBRFileDialog", "get")
|
||||
.proxy("com.jetbrains.JBRFileDialog", "com.jetbrains.desktop.JBRFileDialog");
|
||||
.proxy("com.jetbrains.JBRFileDialog", "com.jetbrains.desktop.JBRFileDialog")
|
||||
.service("com.jetbrains.CustomWindowDecoration", "java.awt.Window$CustomWindowDecoration");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.awt.event.WindowEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import sun.awt.AWTThreading;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import sun.awt.dnd.SunDragSourceContextPeer;
|
||||
@@ -86,6 +87,7 @@ class EventDispatchThread extends Thread {
|
||||
}
|
||||
|
||||
public void run() {
|
||||
AWTThreading.getInstance(Thread.currentThread()).notifyEventDispatchThreadStarted();
|
||||
try {
|
||||
pumpEvents(new Conditional() {
|
||||
public boolean evaluate() {
|
||||
@@ -97,6 +99,8 @@ class EventDispatchThread extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
private static native void registerEventDispatchThread();
|
||||
|
||||
void pumpEvents(Conditional cond) {
|
||||
pumpEvents(ANY_EVENT, cond);
|
||||
}
|
||||
|
||||
@@ -358,6 +358,7 @@ public class EventQueue {
|
||||
if (shouldNotify) {
|
||||
if (theEvent.getSource() != AWTAutoShutdown.getInstance()) {
|
||||
AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
|
||||
AWTThreading.getInstance(dispatchThread).notifyEventDispatchThreadBusy();
|
||||
}
|
||||
pushPopCond.signalAll();
|
||||
} else if (notifyID) {
|
||||
@@ -570,6 +571,7 @@ public class EventQueue {
|
||||
return event;
|
||||
}
|
||||
AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
|
||||
AWTThreading.getInstance(dispatchThread).notifyEventDispatchThreadFree();
|
||||
pushPopCond.await();
|
||||
} finally {
|
||||
pushPopLock.unlock();
|
||||
@@ -1128,6 +1130,7 @@ public class EventQueue {
|
||||
t.setPriority(Thread.NORM_PRIORITY + 1);
|
||||
t.setDaemon(false);
|
||||
AWTAutoShutdown.getInstance().notifyThreadBusy(t);
|
||||
AWTThreading.getInstance(t).notifyEventDispatchThreadBusy();
|
||||
return t;
|
||||
}
|
||||
}
|
||||
@@ -1158,6 +1161,7 @@ public class EventQueue {
|
||||
dispatchThread = null;
|
||||
}
|
||||
AWTAutoShutdown.getInstance().notifyThreadFree(edt);
|
||||
AWTThreading.getInstance(edt).notifyEventDispatchThreadFree();
|
||||
/*
|
||||
* Event was posted after EDT events pumping had stopped, so start
|
||||
* another EDT to handle this event
|
||||
|
||||
@@ -46,13 +46,17 @@ import java.io.ObjectOutputStream;
|
||||
import java.io.OptionalDataException;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Native;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.AccessController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
@@ -64,6 +68,7 @@ import javax.accessibility.AccessibleRole;
|
||||
import javax.accessibility.AccessibleState;
|
||||
import javax.accessibility.AccessibleStateSet;
|
||||
|
||||
import com.jetbrains.internal.JBRApi;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AWTPermissions;
|
||||
import sun.awt.AppContext;
|
||||
@@ -4007,7 +4012,66 @@ public class Window extends Container implements Accessible {
|
||||
}
|
||||
|
||||
private volatile boolean hasCustomDecoration;
|
||||
private volatile List<Map.Entry<Shape, Integer>> customDecorHitTestSpots;
|
||||
private volatile int customDecorTitleBarHeight = -1; // 0 can be a legal value when no title bar is expected
|
||||
|
||||
// called from native
|
||||
private int hitTestCustomDecoration(int x, int y) {
|
||||
var spots = customDecorHitTestSpots;
|
||||
if (spots == null) return CustomWindowDecoration.NO_HIT_SPOT;
|
||||
for (var spot : spots) {
|
||||
if (spot.getKey().contains(x, y)) return spot.getValue();
|
||||
}
|
||||
return CustomWindowDecoration.NO_HIT_SPOT;
|
||||
}
|
||||
|
||||
private static class CustomWindowDecoration {
|
||||
|
||||
@Native public static final int
|
||||
NO_HIT_SPOT = 0,
|
||||
OTHER_HIT_SPOT = 1,
|
||||
MINIMIZE_BUTTON = 2,
|
||||
MAXIMIZE_BUTTON = 3,
|
||||
CLOSE_BUTTON = 4,
|
||||
MENU_BAR = 5;
|
||||
|
||||
void setCustomDecorationEnabled(Window window, boolean enabled) {
|
||||
window.hasCustomDecoration = enabled;
|
||||
if (MacOS.INSTANCE != null && window.customDecorTitleBarHeight > 0f) {
|
||||
MacOS.INSTANCE.setTitleBarHeight(window, window.peer, enabled ? window.customDecorTitleBarHeight : 0);
|
||||
}
|
||||
}
|
||||
boolean isCustomDecorationEnabled(Window window) {
|
||||
return window.hasCustomDecoration;
|
||||
}
|
||||
|
||||
void setCustomDecorationHitTestSpots(Window window, List<Map.Entry<Shape, Integer>> spots) {
|
||||
window.customDecorHitTestSpots = List.copyOf(spots);
|
||||
}
|
||||
List<Map.Entry<Shape, Integer>> getCustomDecorationHitTestSpots(Window window) {
|
||||
return window.customDecorHitTestSpots;
|
||||
}
|
||||
|
||||
void setCustomDecorationTitleBarHeight(Window window, int height) {
|
||||
if (height >= 0) {
|
||||
window.customDecorTitleBarHeight = height;
|
||||
if (MacOS.INSTANCE != null && window.hasCustomDecoration) {
|
||||
MacOS.INSTANCE.setTitleBarHeight(window, window.peer, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
int getCustomDecorationTitleBarHeight(Window window) {
|
||||
return window.customDecorTitleBarHeight;
|
||||
}
|
||||
|
||||
private interface MacOS {
|
||||
MacOS INSTANCE = (MacOS) JBRApi.internalServiceBuilder(MethodHandles.lookup(), null)
|
||||
.withStatic("setTitleBarHeight", "sun.lwawt.macosx.CPlatformWindow", "setCustomDecorationTitleBarHeight").build();
|
||||
void setTitleBarHeight(Window target, ComponentPeer peer, float height);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
boolean hasCustomDecoration() {
|
||||
return hasCustomDecoration;
|
||||
}
|
||||
@@ -4015,6 +4079,7 @@ public class Window extends Container implements Accessible {
|
||||
/**
|
||||
* Set via reflection (JB JdkEx API).
|
||||
*/
|
||||
@Deprecated
|
||||
void setHasCustomDecoration() {
|
||||
hasCustomDecoration = true;
|
||||
}
|
||||
|
||||
@@ -5,18 +5,33 @@ 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.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Function;
|
||||
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("sun.awt.AWTThreading");
|
||||
private static final PlatformLogger logger = PlatformLogger.getLogger(AWTThreading.class.getName());
|
||||
|
||||
private static final Runnable EMPTY_RUNNABLE = () -> {};
|
||||
|
||||
private static final AtomicReference<Function<Thread, AWTThreading>> theAWTThreadingFactory =
|
||||
new AtomicReference<>(AWTThreading::new);
|
||||
|
||||
private final Thread eventDispatchThread;
|
||||
|
||||
private ExecutorService executor;
|
||||
// every invokeAndWait() pushes a queue of invocations
|
||||
@@ -24,13 +39,21 @@ public class AWTThreading {
|
||||
|
||||
private int level; // re-entrance level
|
||||
|
||||
private final List<CompletableFuture<Void>> eventDispatchThreadStateNotifiers = new ArrayList<>();
|
||||
private volatile boolean isEventDispatchThreadFree;
|
||||
|
||||
// invocations should be dispatched on proper EDT (per AppContext)
|
||||
private static final Map<Thread, AWTThreading> EDT_TO_INSTANCE_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class TrackingQueue extends LinkedBlockingQueue<InvocationEvent> {}
|
||||
|
||||
private AWTThreading() {}
|
||||
/**
|
||||
* WARNING: for testing purpose, use {@link AWTThreading#getInstance(Thread)} instead.
|
||||
*/
|
||||
public AWTThreading(Thread edt) {
|
||||
eventDispatchThread = edt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a callable from EventDispatch thread (EDT). It's assumed the callable either performs a blocking execution on Toolkit
|
||||
@@ -55,14 +78,25 @@ public class AWTThreading {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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).
|
||||
*/
|
||||
public static void executeWaitToolkit(Task runnable) {
|
||||
public static void executeWaitToolkit(Consumer<Boolean> consumer) {
|
||||
boolean wait = EventQueue.isDispatchThread();
|
||||
executeWaitToolkit(() -> {
|
||||
runnable.run(wait);
|
||||
consumer.accept(wait);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #executeWaitToolkit(Callable).
|
||||
*/
|
||||
public static void executeWaitToolkit(Runnable runnable) {
|
||||
executeWaitToolkit(() -> {
|
||||
runnable.run();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
@@ -82,12 +116,6 @@ 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) {
|
||||
@@ -178,8 +206,15 @@ public class AWTThreading {
|
||||
* <li>If the event is first dispatched from EventQueue - it gets removed from the tracking queue.
|
||||
* <li>If the event is first dispatched from the tracking queue - its dispatching on EventQueue will be noop.
|
||||
* <ul>
|
||||
*
|
||||
* @param source the source of the event
|
||||
* @param onDispatched called back on event dispatching
|
||||
* @param catchThrowables should catch Throwable's or propagate to the EventDispatch thread's loop
|
||||
*/
|
||||
public static InvocationEvent createAndTrackInvocationEvent(Object source, Runnable runnable, Runnable listener, boolean catchThrowables) {
|
||||
public static TrackedInvocationEvent createAndTrackInvocationEvent(Object source,
|
||||
Runnable onDispatched,
|
||||
boolean catchThrowables)
|
||||
{
|
||||
AWTThreading instance = getInstance(source);
|
||||
if (instance != null) {
|
||||
synchronized (instance.invocations) {
|
||||
@@ -187,68 +222,239 @@ public class AWTThreading {
|
||||
instance.invocations.push(new TrackingQueue());
|
||||
}
|
||||
final TrackingQueue queue = instance.invocations.peek();
|
||||
final InvocationEvent[] eventRef = new InvocationEvent[1];
|
||||
final AtomicReference<TrackedInvocationEvent> eventRef = new AtomicReference<>();
|
||||
|
||||
queue.add(eventRef[0] = new InvocationEvent(
|
||||
source,
|
||||
runnable,
|
||||
// Wrap the original completion listener so that it:
|
||||
// - guarantees a single run either from dispatch or dispose
|
||||
// - removes the invocation event from the tracking queue
|
||||
new Runnable() {
|
||||
WeakReference<TrackingQueue> queueRef = new WeakReference<>(queue);
|
||||
eventRef.set(TrackedInvocationEvent.create(
|
||||
source,
|
||||
onDispatched,
|
||||
new Runnable() {
|
||||
final WeakReference<TrackingQueue> queueRef = new WeakReference<>(queue);
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (queueRef != null) {
|
||||
if (listener != null) {
|
||||
listener.run();
|
||||
}
|
||||
TrackingQueue q = queueRef.get();
|
||||
if (q != null) {
|
||||
q.remove(eventRef[0]);
|
||||
}
|
||||
queueRef = null;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
TrackingQueue queue = queueRef.get();
|
||||
queueRef.clear();
|
||||
if (queue != null) {
|
||||
queue.remove(eventRef.get());
|
||||
}
|
||||
},
|
||||
catchThrowables)
|
||||
{
|
||||
@Override
|
||||
public void dispatch() {
|
||||
if (!isDispatched()) {
|
||||
super.dispatch();
|
||||
}
|
||||
}
|
||||
});
|
||||
return eventRef[0];
|
||||
},
|
||||
catchThrowables));
|
||||
|
||||
queue.add(eventRef.get());
|
||||
return eventRef.get();
|
||||
}
|
||||
}
|
||||
return new InvocationEvent(source, runnable, listener, catchThrowables);
|
||||
return TrackedInvocationEvent.create(source, onDispatched, () -> {}, catchThrowables);
|
||||
}
|
||||
|
||||
private static AWTThreading getInstance(Object obj) {
|
||||
if (obj == null) return null;
|
||||
@SuppressWarnings("serial")
|
||||
public static class TrackedInvocationEvent extends InvocationEvent {
|
||||
private final long creationTime = System.currentTimeMillis();
|
||||
private final Throwable throwable = new Throwable();
|
||||
private final CompletableFuture<Void> futureResult = new CompletableFuture<>();
|
||||
|
||||
// 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() {
|
||||
// Should not complete if competion has already started.
|
||||
if (completeIfNotYet(super::dispatch)) {
|
||||
futureResult.complete(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose(String reason) {
|
||||
completeIfNotYet(() -> AWTAccessor.getInvocationEventAccessor().dispose(this));
|
||||
// Should complete exceptionally regardless of whether completetion has alredy started or hasn't.
|
||||
futureResult.completeExceptionally(new Throwable(reason));
|
||||
}
|
||||
|
||||
private boolean completeIfNotYet(Runnable competeRunnable) {
|
||||
if (!isCompletionStarted.getAndSet(true)) {
|
||||
competeRunnable.run();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
AppContext appContext = SunToolkit.targetToAppContext(obj);
|
||||
if (appContext == null) return null;
|
||||
if (appContext == null) {
|
||||
return getInstance(Toolkit.getDefaultToolkit().getSystemEventQueue());
|
||||
}
|
||||
|
||||
return getInstance((EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY));
|
||||
}
|
||||
|
||||
private static AWTThreading getInstance(EventQueue eq) {
|
||||
public static AWTThreading getInstance(EventQueue eq) {
|
||||
if (eq == null) return null;
|
||||
|
||||
return getInstance(AWTAccessor.getEventQueueAccessor().getDispatchThread(eq));
|
||||
}
|
||||
|
||||
private static AWTThreading getInstance(Thread edt) {
|
||||
if (edt == null) return null;
|
||||
public static AWTThreading getInstance(Thread edt) {
|
||||
assert edt != null;
|
||||
|
||||
return EDT_TO_INSTANCE_MAP.computeIfAbsent(edt, key -> new AWTThreading());
|
||||
return EDT_TO_INSTANCE_MAP.computeIfAbsent(edt, key -> theAWTThreadingFactory.get().apply(edt));
|
||||
}
|
||||
|
||||
public interface Task {
|
||||
void run(boolean wait);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,10 +351,26 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
jreFamilyMap.put("Roboto-Light", "Roboto Light");
|
||||
jreFamilyMap.put("Roboto-Thin", "Roboto Thin");
|
||||
|
||||
jreFontMap.put("JetBrainsMono-Bold.ttf", new BundledFontInfo("JetBrainsMono-Bold", 1, 0, 2));
|
||||
jreFontMap.put("JetBrainsMono-Regular.ttf", new BundledFontInfo("JetBrainsMono-Regular", 1, 0, 2));
|
||||
jreFontMap.put("JetBrainsMono-Italic.ttf", new BundledFontInfo("JetBrainsMono-Italic", 1, 0, 2));
|
||||
jreFontMap.put("JetBrainsMono-Bold-Italic.ttf", new BundledFontInfo("JetBrainsMono-BoldItalic", 1, 0, 2));
|
||||
jreFontMap.put("JetBrainsMono-Bold.ttf", new BundledFontInfo("JetBrainsMono-Bold", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-Bold-Italic.ttf", new BundledFontInfo("JetBrainsMono-Bold-Italic", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-BoldItalic.ttf", new BundledFontInfo("JetBrainsMono-BoldItalic", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-ExtraBold.ttf", new BundledFontInfo("JetBrainsMono-ExtraBold", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-ExtraBoldItalic.ttf", new BundledFontInfo("JetBrainsMono-ExtraBoldItalic", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-ExtraLight.ttf", new BundledFontInfo("JetBrainsMono-ExtraLight", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-ExtraLightItalic.ttf", new BundledFontInfo("JetBrainsMono-ExtraLightItalic", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-Italic.ttf", new BundledFontInfo("JetBrainsMono-Italic", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-Light.ttf", new BundledFontInfo("JetBrainsMono-Light", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-LightItalic.ttf", new BundledFontInfo("JetBrainsMono-LightItalic", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-Medium.ttf", new BundledFontInfo("JetBrainsMono-Medium", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-MediumItalic.ttf", new BundledFontInfo("JetBrainsMono-MediumItalic", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-Regular.ttf", new BundledFontInfo("JetBrainsMono-Regular", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-Thin.ttf", new BundledFontInfo("JetBrainsMono-Thin", 2, 225, 0));
|
||||
jreFontMap.put("JetBrainsMono-ThinItalic.ttf", new BundledFontInfo("JetBrainsMono-ThinItalic", 2, 225, 0));
|
||||
|
||||
jreFontMap.put("Inter-Bold.otf", new BundledFontInfo("Inter-Bold", 3, 19, 0));
|
||||
jreFontMap.put("Inter-Regular.otf", new BundledFontInfo("Inter-Regular", 3, 19, 0));
|
||||
jreFontMap.put("Inter-Italic.otf", new BundledFontInfo("Inter-Italic", 3, 19, 0));
|
||||
jreFontMap.put("Inter-BoldItalic.otf", new BundledFontInfo("Inter-BoldItalic", 3, 19, 0));
|
||||
|
||||
jreBundledFontFiles.addAll(jreFontMap.keySet());
|
||||
}
|
||||
|
||||
BIN
src/java.desktop/share/fonts/Inter-Bold.otf
Normal file
BIN
src/java.desktop/share/fonts/Inter-Bold.otf
Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/Inter-BoldItalic.otf
Normal file
BIN
src/java.desktop/share/fonts/Inter-BoldItalic.otf
Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/Inter-Italic.otf
Normal file
BIN
src/java.desktop/share/fonts/Inter-Italic.otf
Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/Inter-Regular.otf
Normal file
BIN
src/java.desktop/share/fonts/Inter-Regular.otf
Normal file
Binary file not shown.
94
src/java.desktop/share/fonts/Inter_LICENSE.txt
Normal file
94
src/java.desktop/share/fonts/Inter_LICENSE.txt
Normal file
@@ -0,0 +1,94 @@
|
||||
Copyright (c) 2016-2020 The Inter Project Authors.
|
||||
"Inter" is trademark of Rasmus Andersson.
|
||||
https://github.com/rsms/inter
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION AND CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
Binary file not shown.
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-BoldItalic.ttf
Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-ExtraBold.ttf
Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-ExtraBold.ttf
Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-ExtraBoldItalic.ttf
Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-ExtraBoldItalic.ttf
Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-ExtraLight.ttf
Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-ExtraLight.ttf
Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-ExtraLightItalic.ttf
Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-ExtraLightItalic.ttf
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-Light.ttf
Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-Light.ttf
Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-LightItalic.ttf
Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-LightItalic.ttf
Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-Medium.ttf
Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-Medium.ttf
Normal file
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-MediumItalic.ttf
Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-MediumItalic.ttf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/java.desktop/share/fonts/JetBrainsMono-ThinItalic.ttf
Normal file
BIN
src/java.desktop/share/fonts/JetBrainsMono-ThinItalic.ttf
Normal file
Binary file not shown.
@@ -781,19 +781,12 @@ 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 (!isReparented() && isVisible() && runningWM != XWM.NO_WM
|
||||
if (ENABLE_REPARENTING_CHECK && !isReparented() && isVisible() && runningWM != XWM.NO_WM
|
||||
&& !XWM.isNonReparentingWM()
|
||||
&& getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
|
||||
insLog.fine("- visible but not reparented, skipping");
|
||||
|
||||
@@ -52,6 +52,8 @@ 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 {
|
||||
|
||||
@@ -61,6 +63,11 @@ 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>();
|
||||
|
||||
@@ -90,6 +97,9 @@ 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
|
||||
*/
|
||||
@@ -154,6 +164,7 @@ 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()));
|
||||
@@ -747,7 +758,8 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
|
||||
int runningWM = XWM.getWMID();
|
||||
Point newLocation = targetBounds.getLocation();
|
||||
if (xe.get_send_event() || runningWM == XWM.NO_WM || XWM.isNonReparentingWM()) {
|
||||
if (xe.get_send_event() ||
|
||||
(ENABLE_REPARENTING_CHECK ? (runningWM == XWM.NO_WM || XWM.isNonReparentingWM()) : !isReparented())) {
|
||||
// Location, Client size + insets
|
||||
newLocation = new Point(scaleDown(xe.get_x()) - leftInset,
|
||||
scaleDown(xe.get_y()) - topInset);
|
||||
@@ -1443,6 +1455,14 @@ 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()) {
|
||||
@@ -1662,7 +1682,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
}
|
||||
modalBlocker = d;
|
||||
|
||||
if (isReparented() || XWM.isNonReparentingWM()) {
|
||||
if (isReparented() || ENABLE_REPARENTING_CHECK && XWM.isNonReparentingWM()) {
|
||||
addToTransientFors(blockerPeer, javaToplevels);
|
||||
} else {
|
||||
delayedModalBlocking = true;
|
||||
@@ -1673,7 +1693,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
}
|
||||
modalBlocker = null;
|
||||
|
||||
if (isReparented() || XWM.isNonReparentingWM()) {
|
||||
if (isReparented() || ENABLE_REPARENTING_CHECK && XWM.isNonReparentingWM()) {
|
||||
removeFromTransientFors();
|
||||
} else {
|
||||
delayedModalBlocking = false;
|
||||
@@ -1716,7 +1736,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
if (!allStates && (window.getWMState() != transientForWindow.getWMState())) {
|
||||
return;
|
||||
}
|
||||
if (window.getScreenNumber() != transientForWindow.getScreenNumber()) {
|
||||
if (screenOrDesktopDiffers(window, transientForWindow)) {
|
||||
return;
|
||||
}
|
||||
long bpw = window.getWindow();
|
||||
@@ -1753,7 +1773,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
void updateTransientFor() {
|
||||
int state = getWMState();
|
||||
XWindowPeer p = prevTransientFor;
|
||||
while ((p != null) && ((p.getWMState() != state) || (p.getScreenNumber() != getScreenNumber()))) {
|
||||
while ((p != null) && ((p.getWMState() != state) || screenOrDesktopDiffers(p, this))) {
|
||||
p = p.prevTransientFor;
|
||||
}
|
||||
if (p != null) {
|
||||
@@ -1762,7 +1782,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
restoreTransientFor(this);
|
||||
}
|
||||
XWindowPeer n = nextTransientFor;
|
||||
while ((n != null) && ((n.getWMState() != state) || (n.getScreenNumber() != getScreenNumber()))) {
|
||||
while ((n != null) && ((n.getWMState() != state) || screenOrDesktopDiffers(n, this))) {
|
||||
n = n.nextTransientFor;
|
||||
}
|
||||
if (n != null) {
|
||||
@@ -1770,6 +1790,43 @@ 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) {
|
||||
if (p1.getScreenNumber() != p2.getScreenNumber()) return true;
|
||||
if (!ENABLE_DESKTOP_CHECK) return false;
|
||||
Long d1 = p1.getDesktopId();
|
||||
if (d1 == null) return false;
|
||||
Long d2 = p2.getDesktopId();
|
||||
if (d2 == null) return false;
|
||||
return !d1.equals(d2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the TRANSIENT_FOR hint from the given top-level window.
|
||||
* If window or transientForWindow are embedded frames, the containing
|
||||
@@ -2149,6 +2206,7 @@ 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() {
|
||||
@@ -2165,6 +2223,18 @@ 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();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -583,6 +583,8 @@ cleanup:
|
||||
XFree (pVI8sg);
|
||||
if (n1sg != 0)
|
||||
XFree (pVI1sg);
|
||||
if (nTrue != 0)
|
||||
XFree (pVITrue);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1430,6 +1432,9 @@ Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env,
|
||||
break;
|
||||
}
|
||||
}
|
||||
AWT_LOCK();
|
||||
XdbeFreeVisualInfo(visScreenInfo);
|
||||
AWT_UNLOCK();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -55,8 +55,11 @@ import java.awt.image.DataBufferInt;
|
||||
import java.awt.peer.WindowPeer;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
@@ -991,31 +994,29 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
|
||||
return err;
|
||||
}
|
||||
|
||||
private volatile List<Rectangle> customDecorHitTestSpots;
|
||||
private volatile int customDecorTitleBarHeight = -1; // 0 can be a legal value when no title bar is expected
|
||||
|
||||
// called from client via reflection
|
||||
@Deprecated
|
||||
private void setCustomDecorationHitTestSpots(List<Rectangle> hitTestSpots) {
|
||||
this.customDecorHitTestSpots = new CopyOnWriteArrayList<>(hitTestSpots);
|
||||
List<Map.Entry<Shape, Integer>> spots = new ArrayList<>();
|
||||
for (Rectangle spot : hitTestSpots) spots.add(Map.entry(spot, 1));
|
||||
try {
|
||||
Field f = Window.class.getDeclaredField("customDecorHitTestSpots");
|
||||
f.setAccessible(true);
|
||||
f.set(target, spots);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
// called from client via reflection
|
||||
@Deprecated
|
||||
private void setCustomDecorationTitleBarHeight(int height) {
|
||||
if (height >= 0) customDecorTitleBarHeight = height;
|
||||
}
|
||||
|
||||
// called from native
|
||||
private boolean hitTestCustomDecoration(int x, int y) {
|
||||
List<Rectangle> spots = customDecorHitTestSpots;
|
||||
if (spots == null) return false;
|
||||
for (Rectangle spot : spots) {
|
||||
if (spot.contains(x, y)) return true;
|
||||
try {
|
||||
Field f = Window.class.getDeclaredField("customDecorTitleBarHeight");
|
||||
f.setAccessible(true);
|
||||
f.set(target, height);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// called from native
|
||||
private int getCustomDecorationTitleBarHeight() {
|
||||
return customDecorTitleBarHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1646,6 +1646,9 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
case WM_NCRBUTTONDOWN:
|
||||
mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), RIGHT_BUTTON);
|
||||
break;
|
||||
case WM_NCMOUSEMOVE:
|
||||
mr = WmNcMouseMove(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
if (ignoreNextLBTNUP) {
|
||||
ignoreNextLBTNUP = FALSE;
|
||||
@@ -2330,6 +2333,9 @@ MsgRouting AwtComponent::WmNcMouseDown(WPARAM hitTest, int x, int y, int button)
|
||||
MsgRouting AwtComponent::WmNcMouseUp(WPARAM hitTest, int x, int y, int button) {
|
||||
return mrDoDefault;
|
||||
}
|
||||
MsgRouting AwtComponent::WmNcMouseMove(WPARAM hitTest, int x, int y) {
|
||||
return mrDoDefault;
|
||||
}
|
||||
|
||||
MsgRouting AwtComponent::WmWindowPosChanging(LPARAM windowPos) {
|
||||
return mrDoDefault;
|
||||
|
||||
@@ -525,6 +525,7 @@ public:
|
||||
int wheelRotation, BOOL isHorizontal);
|
||||
virtual MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button);
|
||||
virtual MsgRouting WmNcMouseUp(WPARAM hitTest, int x, int y, int button);
|
||||
virtual MsgRouting WmNcMouseMove(WPARAM hitTest, int x, int y);
|
||||
virtual MsgRouting WmWindowPosChanging(LPARAM windowPos);
|
||||
virtual MsgRouting WmWindowPosChanged(LPARAM windowPos);
|
||||
virtual void WmTouch(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <dwmapi.h>
|
||||
|
||||
#include <java_lang_Integer.h>
|
||||
#include <java_awt_Window_CustomWindowDecoration.h>
|
||||
#include <sun_awt_windows_WEmbeddedFrame.h>
|
||||
#include <sun_awt_windows_WEmbeddedFramePeer.h>
|
||||
|
||||
@@ -622,6 +623,23 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
|
||||
if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) {
|
||||
m_grabbedWindow->Ungrab();
|
||||
}
|
||||
// For windows with custom decorations, handle caption-related mouse events
|
||||
// Do not handle events from caption itself to preserve native drag behavior
|
||||
if (HasCustomDecoration()) {
|
||||
switch (hitTest) {
|
||||
case HTMINBUTTON:
|
||||
case HTMAXBUTTON:
|
||||
case HTCLOSE:
|
||||
case HTMENU:
|
||||
RECT rcWindow;
|
||||
GetWindowRect(GetHWnd(), &rcWindow);
|
||||
WmMouseDown(GetButtonMK(button),
|
||||
x - rcWindow.left,
|
||||
y - rcWindow.top,
|
||||
button);
|
||||
return mrConsume;
|
||||
}
|
||||
}
|
||||
if (!IsFocusableWindow() && (button & LEFT_BUTTON)) {
|
||||
switch (hitTest) {
|
||||
case HTTOP:
|
||||
@@ -653,6 +671,24 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
|
||||
return AwtWindow::WmNcMouseDown(hitTest, x, y, button);
|
||||
}
|
||||
|
||||
MsgRouting AwtFrame::WmNcMouseMove(WPARAM hitTest, int x, int y) {
|
||||
// For windows with custom decorations, handle caption-related mouse events
|
||||
if (HasCustomDecoration()) {
|
||||
switch (hitTest) {
|
||||
case HTMINBUTTON:
|
||||
case HTMAXBUTTON:
|
||||
case HTCLOSE:
|
||||
case HTMENU:
|
||||
case HTCAPTION:
|
||||
RECT rcWindow;
|
||||
GetWindowRect(GetHWnd(), &rcWindow);
|
||||
WmMouseMove(0, x - rcWindow.left, y - rcWindow.top);
|
||||
if (hitTest != HTCAPTION) return mrConsume; // Preserve default window drag for HTCAPTION
|
||||
}
|
||||
}
|
||||
return AwtWindow::WmNcMouseMove(hitTest, x, y);
|
||||
}
|
||||
|
||||
// Override AwtWindow::Reshape() to handle minimized/maximized
|
||||
// frames (see 6525850, 4065534)
|
||||
void AwtFrame::Reshape(int x, int y, int w, int h)
|
||||
@@ -1670,7 +1706,7 @@ BOOL AwtFrame::HasCustomDecoration()
|
||||
if (!m_pHasCustomDecoration) {
|
||||
m_pHasCustomDecoration = new BOOL;
|
||||
JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
*m_pHasCustomDecoration = JNU_CallMethodByName(env, NULL, GetTarget(env), "hasCustomDecoration", "()Z").z;
|
||||
*m_pHasCustomDecoration = JNU_GetFieldByName(env, NULL, GetTarget(env), "hasCustomDecoration", "Z").z;
|
||||
}
|
||||
return *m_pHasCustomDecoration;
|
||||
}
|
||||
@@ -1712,10 +1748,8 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) {
|
||||
AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL);
|
||||
|
||||
JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
int titleHeight = (int)JNU_CallMethodByName(env, NULL, frame->GetPeer(env),
|
||||
"getCustomDecorationTitleBarHeight", "()I",
|
||||
frame->ScaleDownX(x - rcWindow.left),
|
||||
frame->ScaleDownY(y - rcWindow.top)).i;
|
||||
int titleHeight = (int)JNU_GetFieldByName(env, NULL, frame->GetTarget(env),
|
||||
"customDecorTitleBarHeight", "I").i;
|
||||
if (titleHeight >= 0) {
|
||||
titleHeight = frame->ScaleUpY(titleHeight);
|
||||
insets.top = titleHeight; // otherwise leave default
|
||||
@@ -1728,12 +1762,23 @@ LRESULT HitTestNCA(AwtFrame* frame, int x, int y) {
|
||||
if (y >= rcWindow.top &&
|
||||
y < rcWindow.top + insets.top)
|
||||
{
|
||||
if (JNU_CallMethodByName(env, NULL, frame->GetPeer(env),
|
||||
"hitTestCustomDecoration", "(II)Z",
|
||||
frame->ScaleDownX(x - rcWindow.left),
|
||||
frame->ScaleDownY(y - rcWindow.top)).z)
|
||||
{
|
||||
return HTNOWHERE;
|
||||
jint customSpot = JNU_CallMethodByName(env, NULL, frame->GetTarget(env),
|
||||
"hitTestCustomDecoration", "(II)I",
|
||||
frame->ScaleDownX(x - rcWindow.left),
|
||||
frame->ScaleDownY(y - rcWindow.top)).i;
|
||||
switch (customSpot) {
|
||||
case java_awt_Window_CustomWindowDecoration_NO_HIT_SPOT:
|
||||
break; // Nothing
|
||||
case java_awt_Window_CustomWindowDecoration_MINIMIZE_BUTTON:
|
||||
return HTMINBUTTON;
|
||||
case java_awt_Window_CustomWindowDecoration_MAXIMIZE_BUTTON:
|
||||
return HTMAXBUTTON;
|
||||
case java_awt_Window_CustomWindowDecoration_CLOSE_BUTTON:
|
||||
return HTCLOSE;
|
||||
case java_awt_Window_CustomWindowDecoration_MENU_BAR:
|
||||
return HTMENU;
|
||||
default:
|
||||
return HTNOWHERE;
|
||||
}
|
||||
fOnResizeBorder = (y < (rcWindow.top - rcFrame.top));
|
||||
uRow = 0;
|
||||
|
||||
@@ -111,6 +111,7 @@ public:
|
||||
MsgRouting WmMouseMove(UINT flags, int x, int y);
|
||||
MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button);
|
||||
MsgRouting WmNcMouseUp(WPARAM hitTest, int x, int y, int button);
|
||||
MsgRouting WmNcMouseMove(WPARAM hitTest, int x, int y);
|
||||
MsgRouting WmGetIcon(WPARAM iconType, LRESULT& retVal);
|
||||
MsgRouting WmShowWindow(BOOL show, UINT status);
|
||||
MsgRouting WmWindowPosChanging(LPARAM windowPos);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user