Compare commits

..

62 Commits

Author SHA1 Message Date
Vitaly Provodin
fe178bde3e update exclude list on results of 25.82.7 test runs 2025-07-18 03:04:43 +04:00
Vladimir Lagunov
d00de81ada JBR-8982 Disable java.io over java.nio.file in JBR25 by default 2025-07-16 06:52:13 +04:00
Vitaly Provodin
8435a559d8 update exclude list on results of 25.80.4 test runs 2025-07-12 02:17:15 +04:00
Vitaly Provodin
8d2d65e21b JBR-8971 replace system CDS with an actual one for IntelliJ 2025-07-12 02:17:15 +04:00
Vitaly Provodin
2d553ab929 update exclude list on results of 25.72.1 test runs 2025-07-12 02:17:15 +04:00
Vitaly Provodin
e131c41a9e update exclude list on results of 25.68 test runs 2025-07-12 02:17:15 +04:00
Vladimir Dvorak
786a51a73c JBR-8850 DCEVM: Enable interface replacement 2025-07-12 02:17:15 +04:00
Vitaly Provodin
c4134682d7 update exclude list on results of 25.63 test runs 2025-07-12 02:17:15 +04:00
Vitaly Provodin
56414a4069 update exclude list after updating agents 2025-07-12 02:17:15 +04:00
Vitaly Provodin
972a528cee update exclude list on results of 25.61 test runs 2025-07-12 02:17:15 +04:00
Vladimir Dvorak
97c0b33628 JBR-8301 - fix compilation issue after changes in JFR 2025-07-12 02:17:15 +04:00
Vladimir Dvorak
6f63a27fd9 JBR-8316 DCEVM: Allow idnum to exceed total method count 2025-07-12 02:17:14 +04:00
Vladimir Dvorak
936d2c86fb JBR-8636 DCEVM: Fix crashes when multiple class redefinitions are processed simultaneously 2025-07-12 02:17:14 +04:00
Vladimir Dvorak
d4de7e69b0 JBR-8609 DCEVM: Fix crash during redefinition of subclass with injected fields 2025-07-12 02:17:14 +04:00
Vladimir Dvorak
c2a949b103 JBR-8575 DCEVM: Fix crash when deleting methods from final classes 2025-07-12 02:17:14 +04:00
Vladimir Dvorak
73619cd94d JBR-8301 serialGC dcevm patch 2025-07-12 02:17:14 +04:00
Vladimir Dvorak
e0995bbf5f JBR-8301 disable VMContinuations in dcevm 2025-07-12 02:17:14 +04:00
Vladimir Dvorak
33d5d9771d JBR-8301 cleanup; nullptr + asserts 2025-07-12 02:17:14 +04:00
Vladimir Dvorak
0932c4e713 JBR-8301 fix find_class + use cld iteration convention 2025-07-12 02:17:14 +04:00
Vladimir Dvorak
252156e3d7 JBR-8301 compilation issues + G1 fix forward 2025-07-12 02:17:14 +04:00
Vladimir Dvorak
b821ee8754 JBR-8301 adjust method ID numbering
Ensure the jmethod_ids array has sufficient initial capacity. This array is not resized since JDK 23.
2025-07-12 02:17:14 +04:00
Vladimir Dvorak
b2ef7e44f9 JBR-8301 clear constant pool cache entries.
java23 has a new implementation of CP cache
2025-07-12 02:17:14 +04:00
Vladimir Dvorak
6a6aa5c3a4 JBR-7649 fix DCEVM crashes on assert() in VM_Exit 2025-07-12 02:17:14 +04:00
Vladimir Dvorak
e855cb936a JBR-7523 fix ClassUnloading support in DCEVM 2025-07-12 02:17:13 +04:00
Vladimir Dvorak
1dab222bf6 JBR-7635 Skip rolled-back classes in search for affected classes 2025-07-12 02:17:13 +04:00
Vladimir Dvorak
52addb4101 JBR-7447 use new method for unregister nmethods in G1
caused by JBR-7219 ("Rebasing JBR21 on top of OpenJDK 21.0.4") and changes in G1 nmethods unregister
2025-07-12 02:17:13 +04:00
Vladimir Dvorak
b5a90dd0f6 JBR-7351 DCEVM: Respect explicit -XX:+ClassUnloading option
Ensure that ClassUnloading is not disabled if the -XX:+ClassUnloading flag is explicitly set by the user. Display a warning about potential instability in this configuration.
2025-07-12 02:17:13 +04:00
Vladimir Dvorak
4fa488c605 JBR-7246 DCEVM: Fix SIGSEGV in method_hash on redefinition 2025-07-12 02:17:13 +04:00
Vladimir Dvorak
4974b5d5d7 JBR-7245 DCEVM: Fix multiple class modification at breakpoint
If an application is paused at a breakpoint in method M of class C and method M is modified N times, each modification triggers N redefinitions of class C. This patch fixes this bug.
2025-07-12 02:17:13 +04:00
Vladimir Dvorak
8be7a5f8a7 JBR-6648 - Fix ObjectCollectedException in enhanced redefineClasses due to stale jvmtiTagMap entries 2025-07-12 02:17:13 +04:00
Vladimir Dvorak
92545f5124 JBR-6746 Fix linux build failing on: "error: 'this' pointer is null" 2025-07-12 02:17:13 +04:00
Vladimir Dvorak
7b136d77f8 JBR-6674 Fix parallel oops iteration in dcevm redefinition
This patch addresses unsynchronized parallel access to ChangePointersObjectClosure._tmp_obj by creating a separate instance for each thread, enhancing thread safety. Additionally, it deems parallel DCEVM iteration in G1 as redundant and removes it.
2025-07-12 02:17:13 +04:00
Vladimir Dvorak
b5755c715f JBR-6647 Disable check for final field access from method $$ha$clinit 2025-07-12 02:17:13 +04:00
Vladimir Dvorak
bbdb27744a JBR-6643 - fix GitHub actions builds 2025-07-12 02:17:13 +04:00
Vladimir Dvorak
c04f7c417c JBR-6419 - fix macos-aarch64 build problem 2025-07-12 02:17:13 +04:00
Vladimir Dvorak
1fc51ef7e8 JBR-6419 - resolve win+macos jdk build issues 2025-07-12 02:17:12 +04:00
Vladimir Dvorak
929d8ac20a JBR-6419 - support for enhanced redefinition of java.lang.Object 2025-07-12 02:17:12 +04:00
Vladimir Dvorak
632dd39f95 JBR-8301 fix compilations issues 2025-07-12 02:17:12 +04:00
Vladimir Dvorak
9e2298e1e3 JBR-5183 as dcevm-23 base
JBR-5183 - ref openjdk/8292818 - special access flags removed

JBR-5183 - add new DeoptimizationScope from openjdk

JBR-5183 clean DCEVM code separation in standard jdk code + typo fix

JBR-5464 Fix native method registration

JBR-5183 - fix compilation on win - using size_t

JBR-5183 - fix error: invalid use of incomplete type 'struct Atomic::StoreImpl

JBR-5183 - fix windows build

JBR-5183 - nullptr in VM_EnhancedRedefineClasses

JBR-5183 - fix compilation locking

JBR-5183 fix G1GC forward pointer check

JBR-5183 fix problem with _first_dead in serial GC

JBR-5183 fix bug from dcevm21 merge resolving

JBR-5183 use sorted static fields in class comparison

JBR-5183 do not use EnhancedRedefineClasses_lock

JBR-5183 fix assert in make_jmethod_id

JBR-5183 remove VM_ThreadsSuspendJVMTI

JBR-5183 fix dcevm21 issues after merge dcevm17 updates

JBR-5183 dcevm17 squashed commits

JBR-3111 Update class in all dictionaries where it was already defined

This patch keeps compatibility with std redefinition, that does not
create a new Klass, but modifies it, then it is modified in all
dictionaries containing this class.

Add ClassLoaderDataGraph_lock to define new class in enhanced
redefiniton

ClassLoaderDataGraph locking for introduced in redefinition in
java.version>11
JBR-3140 - support for modularized HotswapAgent

Add -XX:HotswapAgent=[disabled,fatjar.core]

Support for redefinition of Well Known classses (java.*,jdk.*, sun.*)

Fix fastdebug compilation issues - cast_to_oop
JBR-3458: Skip dynamic proxy classes based on com.sun.proxy
JBR-3459: Fix race condition in ClassLoaderDataGraph::classes_do

InstanceKlass in ClassLoaderData can be uninitialized when
ClassLoaderDataGraph::classes_do is called. Using
ClassLoaderDataGraph::dictionary_classes_do is safe but problem is still
persisting with anonymous classes.

Fix compilation problems

Fix dcevm issues related to refactorization of Thread to JavaThread
Fix init_method_MemberName after Thread to JavaThread refactorization
Fix "implicit conversion of NULL constant to 'bool'"
Fix, pass SystemDictionary::resolve_from_stream cl_info param
Search for affected classes in all initialized classes in cld

Fix also case when lambda interface is redefined. Lambda class is
missing in cld dictionary since it is hidden since j17
Fix compilation issue
Remove duplicated lambdaFormInvokers.cpp

JBR-3867 - update keys of jvmti TAG map after redefinition

jdwp keeps relation class_ptr->class_ref in jvmti tag. class_ptr is used
as a tag key, tag value is refnode. There are new class_ptrs after
redefinition, therefore jdwp redefinition method update all affected
keys in the tag map.
JBR-3867 - fix msvc compilation issue with non const array on stack
Attempt to fix JBR-3887
JBR-3937 Fix crashes in C1/C2 compilers

There is a race condition in enhanced redefinition with C1/C2. Therefore
the patch stops C1/C2 compilation before redefinition and release after
redefinition finishing. There is no performance impact since dcevm
flushes all code cache.

Fix line ending CRLF->LF
G1 fixes, code cleanup
JBR-3867 - fix dcevm redefinition stops due the not updated weak oops

Dcevm must update also oops in weak storage using WeakProcessor. Oops
storage is new concept in java17.
JBR-4018 - fix zero variant compilation issues

JBR-3997 - fix _invokehandle and _invokedynamic race conditions

Old clear mechanism of CpCacheEntry has cleared partially _flags and the
entire _f1, but both values could be later used in interpreter for
invocation. It ended up with various types of crashes. To prevent dcevm
crashes, we keep the old _f1 and _flags values until they are resolved
again. We need a new flag 'is_f1_null_dcevm_shift' indicating that _f1
is NULL (while f1 keeps old value).

JBR-4053 - Fix fastdebug compilation issue
JBR-4125 - fix wrong addition of java.lang.Object as superclass
JBR-4110 - disable UseEmptySlotsInSupers

dcevm instance transformation expects increasing field's offset when
fields of class are iterated. This ordering is no more valid if
UseEmptySlotsInSupers=true.
JBR-4148 - removed meaningless copying of data to itself
JBR-4312 - fix crash call ResolvedMethodTable from ServiceThread

adjust_metod_entries_dcevm incorrectly changed the hashes of resolved
method oops stored in ResolvedMethodTable. Now all oops of old methods
are first removed, then updated and then added to table again
JBR-4352 - fix AARCH64 compilation issues

- use correct INCLUDE_JFR condition for jfr code
- exclude jvmtiEnhancedRedefineClasses.cpp if INCLUDE_JVMTI=0
Remove version-numbers left over from the merge of dcevm17
JBR-4392 - use only loaded classes when collecting affected classes
JBR-4386 - disable AllowEnhancedClassRedefinition in jfr

JBR-5183 fix dcevm21 compilation issues

JBR-5183 pre-dcevm17 squashed commits

dcevm11 fixes

1. We need to set classRedefinitionCount on new class, not old class.

2.Fix crashes in MetadataOnStackMark::~MetadataOnSta

MetadataOnStackMark should not remove dcevm stuff. It was added
accidentaly in dcevm9 and never was part of doit() in previous versions.

3. Fix problem with nested members

Reported at :
https://stackoverflow.com/questions/53370380/hotswapagent-incompatibleclasschangeerror-type-headerpanel1-is-not-a-nest-mem

4. Use init_mark_raw()

method changed since j8 - it used init_mark()

5. Fix methodHandles and fieldHandles

6. Code cleanup

7. Fix force_forward in dead space

8. Fix check_class

9. increment_class_counter() using orig dcevm code

Probably it is cause of SISEGV on:
_
VM_EnhancedRedefineClasses::redefine_single_class->java_mirror()

10 Fix 11.0.7 compilation issues

11. Refactor ClearCpoolCacheAndUnpatch

12. not nullable oop_store_not_null() method+handle NULL in mem_name in
dmh

13. Use INCLUDE_CDS condition on "UseSharedSpaces" block from master

14. Add codecache flush optimization, but just flush all cache.

15. Cleanup

16. Use original code for adjust_method_entries in standard redefinition

17. iterate old method version only in dcevm

18. Revert code for !AllowEnhancedClassRedefinition

19. Code cleanup

20. Activate cpCache definition asserts for !dcevm

21. Skip GC runs for redefinitions without instance size change

22. This is the 2nd commit message:

23. dcevm15 - Cleanup code related to removed CMS

Fix class cast exception on redefinition of class A, that is superclass
of B that has anonymous class C

Support for Lambda class redefinition

Fix "no original bytecode found" error if method with bkp is missing

Sometimes IDE can deploy class with erroneous method, such method has
n bytecode, but breakpoint position can still exist.

Replace deleted method with Universe::throw_no_such_method_error

+ Change log level in advanced redefinition
- Change log level for "Comparing different class ver.." to debug
- Fix adjust_method_entries_dcevm logging levels and severity
Support for G1 gc

AllowEnhancedClassRedefinition is false (disabled) by default

Set HOTSPOT_VM_DISTRO=Dynamic Code Evolution

Clear dcevm code separation

Fix LoadedClassesClosure - fixes problems with remote debugging

dcevm15 - fix java15 compilation issues
dcevm15 - add ClassLoaderDataGraph_lock on
ClassLoaderDataGraph::classes_do

ClassLoaderDataGraph::classes_do and need safepoint or lock,
find_sorted_affected_classes is not in safepoint therefore it must be
locked
ClassLoaderDataGraph::rollback_redefinition need safepoint too
dcevm15 - fix Universe::root_oops_do

Removed ClassLoaderDataGraph::cld_do was cause of crashes due multiple
oop patching. ClassLoaderDataGraph::cld_do replaced in dcevm15
previously used and removed SystemDictionary:oops_do
dcevm15 - check if has_nestmate_access_to has newest host class
dcevm15 - mark_as_scavengable only alive methods
dcevm15 - fix hidded classes

dcevm15 - DON'T clear F2 in CP cache after indy unevolving

It's not clear why it was cleared in dcevm7-11
Cleanup and review comments
Disable AllowEnhancedClassRedefinition in flight recorder

dcevm17 - fix compilation issues

Fix crash on GrowableArray allocation in C_HEAP
Rename confusing method name old_if_redefined to old_if_redefining
Check InstanceKlass::has_nestmate_access_to with active classes

Dcevm can leave old host in nested class if nested class is not
redefined together with host class
2025-07-12 02:17:12 +04:00
Vitaly Provodin
d08d3bde3c update exclude list on results of 25.57 test runs 2025-07-12 02:17:12 +04:00
Vitaly Provodin
d9d7056643 update exclude list on results of 25.56 test runs 2025-07-12 02:17:12 +04:00
Vitaly Provodin
48901dbed3 update exclude list on results of 25.47 test runs 2025-07-12 02:17:12 +04:00
Vitaly Provodin
ced472737a update exclude list on results of 25.40 test runs 2025-07-12 02:17:12 +04:00
Vitaly Provodin
6ba6f556d7 update exclude list on results of 25.28 test runs 2025-07-12 02:17:12 +04:00
Vitaly Provodin
9246fbc244 update exclude list on results of 25.27 test runs 2025-07-12 02:17:12 +04:00
Vitaly Provodin
290315a5ce update exclude list on results of main.3228 test runs 2025-07-12 02:17:12 +04:00
Vitaly Provodin
035cf124ab update exclude list on results of 25.16.14 test runs 2025-07-12 02:17:11 +04:00
Vitaly Provodin
f609c0bc36 update exclude list on results of 25.14.12 test runs 2025-07-12 02:17:11 +04:00
Vitaly Provodin
decda7a749 update exclude list on results of 25.12.11 test runs 2025-07-12 02:17:11 +04:00
Vitaly Provodin
8d2009cb50 update exclude list on results of 25.12 test runs 2025-07-12 02:17:11 +04:00
Vitaly Provodin
86e36ea6fb update exclude list on results of 25.10.10 test runs 2025-07-12 02:17:11 +04:00
Vitaly Provodin
5bfcd8ad47 update exclude list on results of 25.8.6 test runs 2025-07-12 02:17:11 +04:00
Vitaly Provodin
bfae68d91a update exclude list on results of 25.6.4 test runs 2025-07-12 02:17:11 +04:00
Vitaly Provodin
4c551a4146 update exclude list on results of 25.5.2 test runs 2025-07-12 02:17:11 +04:00
Vitaly Provodin
bd026e77a8 update exclude list on results of 25.5 test runs 2025-07-12 02:17:11 +04:00
Vitaly Provodin
a2979fb92c update exclude list on results of 25.3 test runs 2025-07-12 02:17:11 +04:00
Maxim Kartashev
7ac6509b56 fixup! JBR-6876 Wayland: GTK title bar 2025-07-12 02:17:11 +04:00
Vitaly Provodin
52ade26984 update exclude list on results of main.3451 test runs 2025-07-12 02:17:11 +04:00
Vitaly Provodin
1d3489ff05 JBR-9065 split part4 onto parts 2025-07-11 12:59:43 +04:00
Sergey Shelomentsev
7875eb3b33 JBR-5318 add Github workflow usage for pull requests pre-commit testing
(cherry picked from commit f36aa7f9fa)
2025-07-11 12:59:42 +04:00
Maxim Kartashev
6eb17d80c1 JBR-6876 Wayland: GTK title bar
GTK title bar is displayed iff gtk/gdk/glib libraries are available.
Controlled with -Dsun.awt.wl.WindowDecorationStyle=[gtk|builtin].
2025-07-11 12:58:41 +04:00
Nikita Gubarkov
d895107698 JBR-9070 Vulkan: Add sun.java2d.vulkan=True diagnostics 2025-07-11 12:58:41 +04:00
13 changed files with 1148 additions and 27 deletions

View File

@@ -28,9 +28,7 @@ name: 'OpenJDK GHA Sanity Checks'
on:
push:
branches-ignore:
- master
- pr/*
- jdk*
- main
workflow_dispatch:
inputs:
@@ -44,6 +42,9 @@ on:
make-arguments:
description: 'Additional make arguments'
required: false
dry-run:
description: 'Dry run: skip actual builds and tests'
required: false
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -71,6 +72,7 @@ jobs:
windows-x64: ${{ steps.include.outputs.windows-x64 }}
windows-aarch64: ${{ steps.include.outputs.windows-aarch64 }}
docs: ${{ steps.include.outputs.docs }}
dry-run: ${{ steps.include.outputs.dry-run }}
steps:
- name: 'Checkout the scripts'
@@ -144,6 +146,35 @@ jobs:
echo 'false'
}
function check_dry_run() {
if [[ $GITHUB_EVENT_NAME == workflow_dispatch ]]; then
# Take the user-specified one.
echo '${{ github.event.inputs.dry-run }}'
return
elif [[ $GITHUB_EVENT_NAME == push ]]; then
# Cut out the real branch name
BRANCH=${GITHUB_REF##*/}
# Dry run rebuilds the caches in current branch, so they can be reused
# for any child PR branches. Because of this, we want to trigger this
# workflow in master branch, so that actual PR branches can use the cache.
# This workflow would trigger every time contributors sync their master
# branches in their personal forks.
if [[ $BRANCH == "master" ]]; then
echo 'true'
return
fi
# ...same for stabilization branches
if [[ $BRANCH =~ "jdk(.*)" ]]; then
echo 'true'
return
fi
fi
echo 'false'
}
echo "linux-x64=$(check_platform linux-x64 linux x64)" >> $GITHUB_OUTPUT
echo "linux-x64-variants=$(check_platform linux-x64-variants variants)" >> $GITHUB_OUTPUT
echo "linux-cross-compile=$(check_platform linux-cross-compile cross-compile)" >> $GITHUB_OUTPUT
@@ -153,6 +184,7 @@ jobs:
echo "windows-x64=$(check_platform windows-x64 windows x64)" >> $GITHUB_OUTPUT
echo "windows-aarch64=$(check_platform windows-aarch64 windows aarch64)" >> $GITHUB_OUTPUT
echo "docs=$(check_platform docs)" >> $GITHUB_OUTPUT
echo "dry-run=$(check_dry_run)" >> $GITHUB_OUTPUT
###
### Build jobs
@@ -167,6 +199,7 @@ jobs:
gcc-major-version: '10'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.linux-x64 == 'true'
build-linux-x64-hs-nopch:
@@ -181,6 +214,7 @@ jobs:
extra-conf-options: '--disable-precompiled-headers'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.linux-x64-variants == 'true'
build-linux-x64-hs-zero:
@@ -195,6 +229,7 @@ jobs:
extra-conf-options: '--with-jvm-variants=zero --disable-precompiled-headers'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.linux-x64-variants == 'true'
build-linux-x64-hs-minimal:
@@ -209,6 +244,7 @@ jobs:
extra-conf-options: '--with-jvm-variants=minimal --disable-precompiled-headers'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.linux-x64-variants == 'true'
build-linux-x64-hs-optimized:
@@ -224,6 +260,7 @@ jobs:
extra-conf-options: '--with-debug-level=optimized --disable-precompiled-headers'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.linux-x64-variants == 'true'
build-linux-x64-static:
@@ -239,6 +276,7 @@ jobs:
gcc-major-version: '10'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
static-suffix: "-static"
if: needs.prepare.outputs.linux-x64 == 'true'
@@ -255,6 +293,7 @@ jobs:
gcc-major-version: '10'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
# Upload static libs bundles separately to avoid interference with normal linux-x64 bundle.
# This bundle is not used by testing jobs, but downstreams use it to check that
# dependent projects, e.g. libgraal, builds fine.
@@ -269,6 +308,7 @@ jobs:
gcc-major-version: '10'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.linux-cross-compile == 'true'
build-alpine-linux-x64:
@@ -279,6 +319,7 @@ jobs:
platform: alpine-linux-x64
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.alpine-linux-x64 == 'true'
build-macos-x64:
@@ -291,6 +332,7 @@ jobs:
xcode-toolset-version: '14.3.1'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.macos-x64 == 'true'
build-macos-aarch64:
@@ -303,6 +345,7 @@ jobs:
xcode-toolset-version: '15.4'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.macos-aarch64 == 'true'
build-windows-x64:
@@ -315,6 +358,7 @@ jobs:
msvc-toolset-architecture: 'x86.x64'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.windows-x64 == 'true'
build-windows-aarch64:
@@ -329,6 +373,7 @@ jobs:
extra-conf-options: '--openjdk-target=aarch64-unknown-cygwin'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.windows-aarch64 == 'true'
build-docs:
@@ -345,6 +390,7 @@ jobs:
gcc-major-version: '10'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
if: needs.prepare.outputs.docs == 'true'
###
@@ -354,17 +400,20 @@ jobs:
test-linux-x64:
name: linux-x64
needs:
- prepare
- build-linux-x64
uses: ./.github/workflows/test.yml
with:
platform: linux-x64
bootjdk-platform: linux-x64
runs-on: ubuntu-22.04
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
debug-suffix: -debug
test-linux-x64-static:
name: linux-x64-static
needs:
- prepare
- build-linux-x64
- build-linux-x64-static
uses: ./.github/workflows/test.yml
@@ -372,27 +421,32 @@ jobs:
platform: linux-x64
bootjdk-platform: linux-x64
runs-on: ubuntu-22.04
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
static-suffix: "-static"
test-macos-aarch64:
name: macos-aarch64
needs:
- prepare
- build-macos-aarch64
uses: ./.github/workflows/test.yml
with:
platform: macos-aarch64
bootjdk-platform: macos-aarch64
runs-on: macos-14
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
xcode-toolset-version: '15.4'
debug-suffix: -debug
test-windows-x64:
name: windows-x64
needs:
- prepare
- build-windows-x64
uses: ./.github/workflows/test.yml
with:
platform: windows-x64
bootjdk-platform: windows-x64
runs-on: windows-2025
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
debug-suffix: -debug

View File

@@ -40,7 +40,7 @@ public class IoOverNio {
*/
public static final Debug DEBUG;
public static final boolean IS_ENABLED_IN_GENERAL =
System.getProperty("jbr.java.io.use.nio", "true").equalsIgnoreCase("true");
System.getProperty("jbr.java.io.use.nio", "false").equalsIgnoreCase("true");
private static final ThreadLocal<Integer> ALLOW_IN_THIS_THREAD = new ThreadLocal<>();
static {

View File

@@ -41,8 +41,11 @@ public final class VKEnv {
private static final class Options {
@SuppressWarnings("removal")
private static final boolean vulkan = "true".equalsIgnoreCase(AccessController.doPrivileged(
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan", "")));
private static final String vulkanProperty = AccessController.doPrivileged(
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan", ""));
private static final boolean vulkan = "true".equalsIgnoreCase(vulkanProperty);
private static final boolean verbose = "True".equals(vulkanProperty);
@SuppressWarnings("removal")
private static final boolean accelsd = vulkan && "true".equalsIgnoreCase(AccessController.doPrivileged(
@@ -94,14 +97,23 @@ public final class VKEnv {
}
state = newState;
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (Options.verbose || log.isLoggable(PlatformLogger.Level.FINE)) {
String message;
if (isVulkanEnabled()) {
log.fine("Vulkan rendering enabled: YES" +
"\n presentation enabled: " + (isPresentationEnabled() ? "YES" : "NO") +
"\n accelerated surface data enabled: " + (isSurfaceDataAccelerated() ? "YES" : "NO") +
"\n devices:" + Stream.of(devices).map(d -> (d == defaultDevice ?
"\n *" : "\n ") + d.getName()).collect(Collectors.joining()));
} else log.fine("Vulkan rendering enabled: NO");
message = "Vulkan rendering enabled: YES" +
"\n presentation enabled: " + (isPresentationEnabled() ? "YES" : "NO") +
"\n accelerated surface data enabled: " + (isSurfaceDataAccelerated() ? "YES" : "NO") +
"\n devices:" + Stream.of(devices).map(d -> (d == defaultDevice ?
"\n *" : "\n ") + d.getName()).collect(Collectors.joining());
} else {
message = "Vulkan rendering enabled: NO";
}
if (Options.verbose) {
System.err.println(message);
}
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine(message);
}
}
}

View File

@@ -246,8 +246,7 @@ public abstract class FullFrameDecorationHelper extends FrameDecoration {
if (e.getID() == MouseEvent.MOUSE_PRESSED) {
pressedLocation = point;
} else if (e.getID() == MouseEvent.MOUSE_DRAGGED && pressedInDragStartArea(point) && isSignificantDrag(point)) {
peer.startDrag(WLToolkit.getInputState().pointerButtonSerial());
startDrag();
} else if (e.getID() == MouseEvent.MOUSE_CLICKED && e.getClickCount() == 2 && pressedInDragStartArea(point)
&& peer.isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
toggleMaximizedState();
@@ -258,6 +257,23 @@ public abstract class FullFrameDecorationHelper extends FrameDecoration {
return true;
}
private void startDrag() {
pressedLocation = null;
boolean changed = false;
if (closeButton != null) {
changed |= closeButton.reset();
}
if (maximizeButton != null) {
changed |= maximizeButton.reset();
}
if (minimizeButton != null) {
changed |= minimizeButton.reset();
}
if (changed) peer.notifyClientDecorationsChanged();
peer.startDrag(WLToolkit.getInputState().pointerButtonSerial());
}
private void toggleMaximizedState() {
peer.setExtendedState(peer.getState() == Frame.NORMAL ? Frame.MAXIMIZED_BOTH : Frame.NORMAL);
}
@@ -294,6 +310,13 @@ public abstract class FullFrameDecorationHelper extends FrameDecoration {
this.action = action;
}
private boolean reset() {
boolean changed = hovered | pressed;
hovered = false;
pressed = false;
return changed;
}
private boolean processMouseEvent(MouseEvent e) {
assert EventQueue.isDispatchThread();

View File

@@ -0,0 +1,221 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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 sun.awt.wl;
import sun.awt.image.SunWritableRaster;
import sun.java2d.SunGraphics2D;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBufferInt;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
public class GtkFrameDecoration extends FullFrameDecorationHelper {
private static final int MIN_BUTTON_STATE_HOVERED = 1;
private static final int MIN_BUTTON_STATE_PRESSED = 1 << 1;
private static final int MAX_BUTTON_STATE_HOVERED = 1 << 2;
private static final int MAX_BUTTON_STATE_PRESSED = 1 << 3;
private static final int CLOSE_BUTTON_STATE_HOVERED = 1 << 4;
private static final int CLOSE_BUTTON_STATE_PRESSED = 1 << 5;
private long nativePtr;
private Rectangle minimizeButtonBounds; // set by the native code
private Rectangle maximizeButtonBounds; // set by the native code
private Rectangle closeButtonBounds; // set by the native code
private int titleBarHeight = 37; // set by the native code
private int titleBarMinWidth = 180; // set by the native code
private final int dndThreshold;
static {
initIDs();
nativeLoadGTK();
}
public GtkFrameDecoration(WLDecoratedPeer peer, boolean showMinimize, boolean showMaximize) {
super(peer, showMinimize, showMaximize);
nativePtr = nativeCreateDecoration(showMinimize, showMaximize);
assert nativePtr != 0;
int t = nativeGetIntProperty(nativePtr, "gtk-dnd-drag-threshold");
dndThreshold = t > 0 ? t : 4;
}
@Override
public void paint(Graphics g) {
// Determine buttons' bounds, etc.
nativePrePaint(nativePtr, peer.getWidth());
super.paint(g);
}
@Override
protected void paintTitleBar(Graphics2D g2d) {
int width = peer.getWidth();
int height = titleBarHeight;
double scale = ((WLGraphicsConfig) peer.getGraphicsConfiguration()).getEffectiveScale();
g2d.setBackground(new Color(0, true));
g2d.clearRect(0, 0, width, height);
int nativeW = (int) Math.ceil(width * scale);
int nativeH = (int) Math.ceil(height * scale);
DataBufferInt dataBuffer = new DataBufferInt(nativeW * nativeH);
nativePaintTitleBar(
nativePtr,
SunWritableRaster.stealData(dataBuffer, 0),
width, height, scale, peer.getTitle(), getButtonsState());
SunWritableRaster.markDirty(dataBuffer);
int[] bands = {0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000};
WritableRaster raster = Raster.createPackedRaster(dataBuffer, nativeW, nativeH, nativeW, bands, null);
ColorModel cm = peer.getGraphicsConfiguration().getColorModel(Transparency.TRANSLUCENT);
BufferedImage img = new BufferedImage(cm, raster, true, null);
if (scale != 1.0 && g2d instanceof SunGraphics2D sg2d) {
sg2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
sg2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
sg2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
}
g2d.drawImage(img, 0, 0, width, height, 0, 0, nativeW, nativeH, null);
}
@Override
protected void paintBorder(Graphics2D g2d) {
// No border in this decoration style
}
@Override
public void dispose() {
nativeDestroyDecoration(nativePtr);
nativePtr = 0;
super.dispose();
}
@Override
protected boolean pressedInDragStartArea(Point p) {
if (p.x <= 0 || p.x >= peer.getWidth() || p.y <= 0 || p.y >= titleBarHeight) return false;
var b1 = getMinimizeButtonBounds();
if (b1 != null && b1.contains(p)) return false;
var b2 = getMaximizeButtonBounds();
if (b2 != null && b2.contains(p)) return false;
var b3 = getCloseButtonBounds();
if (b3 != null && b3.contains(p)) return false;
return true;
}
@Override
protected boolean isSignificantDragDistance(Point p1, Point p2) {
return p1.distance(p2) > dndThreshold;
}
@Override
public int getResizeEdgeThickness() {
return 10;
}
@Override
public Insets getContentInsets() {
return new Insets(titleBarHeight, 0, 0, 0);
}
@Override
public Rectangle getTitleBarBounds() {
return new Rectangle(0, 0, peer.getWidth(), titleBarHeight);
}
@Override
public Dimension getMinimumSize() {
return new Dimension(titleBarMinWidth, titleBarHeight);
}
@Override
public void notifyConfigured(boolean active, boolean maximized, boolean fullscreen) {
nativeNotifyConfigured(nativePtr, active, maximized, fullscreen);
super.notifyConfigured(active, maximized, fullscreen);
}
@Override
protected Rectangle getMinimizeButtonBounds() {
if (!hasMinimizeButton()) return null;
return minimizeButtonBounds;
}
@Override
protected Rectangle getMaximizeButtonBounds() {
if (!hasMaximizeButton()) return null;
return maximizeButtonBounds;
}
@Override
protected Rectangle getCloseButtonBounds() {
return closeButtonBounds;
}
@Override
public void notifyThemeChanged() {
nativeSwitchTheme();
}
private int getButtonsState() {
int state = 0;
if (closeButton.hovered) state |= CLOSE_BUTTON_STATE_HOVERED;
if (closeButton.pressed) state |= CLOSE_BUTTON_STATE_PRESSED;
if (hasMinimizeButton()) {
if (minimizeButton.hovered) state |= MIN_BUTTON_STATE_HOVERED;
if (minimizeButton.pressed) state |= MIN_BUTTON_STATE_PRESSED;
}
if (hasMaximizeButton()) {
if (maximizeButton.hovered) state |= MAX_BUTTON_STATE_HOVERED;
if (maximizeButton.pressed) state |= MAX_BUTTON_STATE_PRESSED;
}
return state;
}
private static native void initIDs();
private static native boolean nativeLoadGTK();
private native long nativeCreateDecoration(boolean showMinimize, boolean showMaximize);
private native void nativeDestroyDecoration(long nativePtr);
private native void nativeSwitchTheme();
private native void nativePaintTitleBar(long nativePtr, int[] buffer, int width, int height, double scale,
String title, int buttonsState);
private native int nativeGetIntProperty(long nativePtr, String name);
private native void nativeNotifyConfigured(long nativePtr, boolean active, boolean maximized, boolean fullscreen);
private native void nativePrePaint(long nativePtr, int width);
}

View File

@@ -33,7 +33,6 @@ import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.util.Objects;
public abstract class WLDecoratedPeer extends WLWindowPeer {
private FrameDecoration decoration; // protected by stateLock
@@ -41,12 +40,40 @@ public abstract class WLDecoratedPeer extends WLWindowPeer {
private final boolean showMaximize;
private final boolean showMinimize;
private final static String decorationPreference = System.getProperty("sun.awt.wl.WindowDecorationStyle");
public WLDecoratedPeer(Window target, boolean isUndecorated, boolean showMinimize, boolean showMaximize) {
super(target);
this.isUndecorated = isUndecorated;
this.showMinimize = showMinimize;
this.showMaximize = showMaximize;
decoration = isUndecorated ? new MinimalFrameDecoration(this) : new DefaultFrameDecoration(this, showMinimize, showMaximize);
decoration = determineDecoration(isUndecorated, showMinimize, showMaximize);
}
private FrameDecoration determineDecoration(boolean isUndecorated, boolean showMinimize, boolean showMaximize) {
FrameDecoration d;
if (isUndecorated) {
d = new MinimalFrameDecoration(this);
} else if (decorationPreference != null) {
if ("builtin".equals(decorationPreference)) {
d = new DefaultFrameDecoration(this, showMinimize, showMaximize);
} else if ("gtk".equals(decorationPreference) && isGTKAvailable()) {
d = new GtkFrameDecoration(this, showMinimize, showMaximize);
} else {
d = new DefaultFrameDecoration(this, showMinimize, showMaximize);
}
} else {
if (isGTKAvailable()) {
d = new GtkFrameDecoration(this, showMinimize, showMaximize);
} else {
d = new DefaultFrameDecoration(this, showMinimize, showMaximize);
}
}
return d;
}
private static boolean isGTKAvailable() {
return ((WLToolkit) WLToolkit.getDefaultToolkit()).checkGtkVersion(3, 20, 0);
}
private static native void initIDs();
@@ -70,13 +97,10 @@ public abstract class WLDecoratedPeer extends WLWindowPeer {
return getDecoration().getContentInsets();
}
public final void setDecoration(FrameDecoration newDecoration) {
Objects.requireNonNull(newDecoration);
public final void resetDecoration(boolean isFullscreen) {
synchronized (getStateLock()) {
if (decoration != newDecoration) {
decoration.dispose();
decoration = newDecoration;
}
decoration.dispose();
decoration = determineDecoration(isFullscreen | isUndecorated, showMinimize, showMaximize);
}
// Since the client area of the window may have changed, need to re-validate the target
// to let it re-layout its children.
@@ -150,10 +174,10 @@ public abstract class WLDecoratedPeer extends WLWindowPeer {
if (wasFullscreen != fullscreen) {
if (fullscreen) {
setDecoration(new MinimalFrameDecoration(this));
resetDecoration(true);
} else {
if (!isUndecorated) {
setDecoration(new DefaultFrameDecoration(this, showMinimize, showMaximize));
resetDecoration(false);
}
}
}

View File

@@ -0,0 +1,774 @@
/*
* Copyright (c) 2025, JetBrains s.r.o.. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.
*/
#include "sun_awt_wl_GtkFrameDecoration.h"
#include "JNIUtilities.h"
#include "WLToolkit.h"
#include <jni_util.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
typedef void* gpointer;
typedef char gchar;
typedef int gint;
typedef unsigned int guint;
typedef gint gboolean;
typedef signed short gint16;
typedef double gdouble;
typedef void* GtkWidget;
typedef void* GtkStyleContext;
typedef void* GtkContainer;
typedef void* GtkBin;
typedef void* GtkWindow;
typedef void* GtkHeaderBar;
typedef void* GtkIconInfo;
typedef void* GtkIconTheme;
typedef void* GtkSettings;
typedef void* GdkPixbuf;
typedef void* GdkWindow;
typedef void* GError;
typedef unsigned long GType;
typedef void (*GtkCallback)(GtkWidget *widget, gpointer data);
typedef struct _GValue GValue;
typedef struct _GObject GObject;
typedef struct _GTypeInstance GTypeInstance;
typedef struct _GMainContext GMainContext;
typedef enum {
GTK_ICON_SIZE_INVALID,
GTK_ICON_SIZE_MENU,
GTK_ICON_SIZE_SMALL_TOOLBAR,
GTK_ICON_SIZE_LARGE_TOOLBAR,
GTK_ICON_SIZE_BUTTON,
GTK_ICON_SIZE_DND,
GTK_ICON_SIZE_DIALOG
} GtkIconSize;
typedef enum {
GTK_ICON_LOOKUP_NO_SVG = 1 << 0,
GTK_ICON_LOOKUP_FORCE_SVG = 1 << 1,
GTK_ICON_LOOKUP_USE_BUILTIN = 1 << 2,
GTK_ICON_LOOKUP_GENERIC_FALLBACK = 1 << 3,
GTK_ICON_LOOKUP_FORCE_SIZE = 1 << 4,
GTK_ICON_LOOKUP_FORCE_REGULAR = 1 << 5,
GTK_ICON_LOOKUP_FORCE_SYMBOLIC = 1 << 6,
GTK_ICON_LOOKUP_DIR_LTR = 1 << 7,
GTK_ICON_LOOKUP_DIR_RTL = 1 << 8
} GtkIconLookupFlags;
typedef enum {
GTK_STATE_FLAG_NORMAL = 0,
GTK_STATE_FLAG_ACTIVE = 1 << 0,
GTK_STATE_FLAG_PRELIGHT = 1 << 1,
GTK_STATE_FLAG_SELECTED = 1 << 2,
GTK_STATE_FLAG_INSENSITIVE = 1 << 3,
GTK_STATE_FLAG_INCONSISTENT = 1 << 4,
GTK_STATE_FLAG_FOCUSED = 1 << 5,
GTK_STATE_FLAG_BACKDROP = 1 << 6
} GtkStateFlags;
typedef enum {
GTK_STYLE_CONTEXT_PRINT_NONE = 0,
GTK_STYLE_CONTEXT_PRINT_RECURSE = 1 << 0,
GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE = 1 << 1
} GtkStyleContextPrintFlags;
typedef struct {
gint16 left;
gint16 right;
gint16 top;
gint16 bottom;
} GtkBorder;
typedef struct {
int x;
int y;
int width;
int height;
} GtkAllocation;
#define GTK_STYLE_CLASS_TITLEBAR "titlebar"
#define GTK_TYPE_WIDGET (p_gtk_widget_get_type())
#define GTK_TYPE_CONTAINER (p_gtk_container_get_type())
#define GTK_IS_CONTAINER(obj) p_g_type_check_instance_is_a((obj), GTK_TYPE_CONTAINER)
#define GTK_IS_WIDGET(obj) p_g_type_check_instance_is_a((obj), GTK_TYPE_WIDGET)
#define GTK_CONTAINER(obj) ((GtkContainer)(obj))
#define GTK_BIN(obj) ((GtkBin)(obj))
#define GTK_WINDOW(obj) ((GtkWindow)(obj))
#define GTK_WIDGET(obj) ((GtkWidget)(obj))
#define GTK_HEADER_BAR(obj) ((GtkHeaderBar)(obj))
typedef enum {
CAIRO_FORMAT_ARGB32 = 0
} cairo_format_t;
typedef struct _cairo cairo_t;
typedef struct _cairo_surface cairo_surface_t;
typedef char* (*gtk_style_context_to_string_t)(GtkStyleContext*, GtkStyleContextPrintFlags);
typedef gboolean (*gtk_icon_size_lookup_t)(GtkIconSize, gint*, gint*);
typedef GdkPixbuf* (*gtk_icon_info_load_symbolic_for_context_t)(GtkIconInfo*, GtkStyleContext*, gboolean*, GError**);
typedef GtkIconInfo* (*gtk_icon_theme_lookup_icon_for_scale_t)(GtkIconTheme*, const gchar*, gint, gint, GtkIconLookupFlags);
typedef GtkIconTheme* (*gtk_icon_theme_get_default_t)(void);
typedef GtkSettings* (*gtk_widget_get_settings_t)(GtkWidget*);
typedef GtkStateFlags (*gtk_style_context_get_state_t)(GtkStyleContext *context);
typedef GtkStyleContext* (*gtk_widget_get_style_context_t)(GtkWidget*);
typedef GtkWidget* (*gtk_bin_get_child_t)(GtkBin*);
typedef GtkWidget* (*gtk_header_bar_new_t)(void);
typedef GtkWidget* (*gtk_offscreen_window_new_t)(void);
typedef GType (*gtk_container_get_type_t)(void);
typedef GType (*gtk_widget_get_type_t)(void);
typedef void (*gtk_container_forall_t)(GtkContainer*, GtkCallback, gpointer);
typedef void (*gtk_header_bar_set_show_close_button_t)(GtkHeaderBar*, gboolean);
typedef void (*gtk_header_bar_set_title_t)(GtkHeaderBar*, const gchar*);
typedef void (*gtk_render_background_t)(GtkStyleContext*, cairo_t*, gdouble, gdouble, gdouble, gdouble);
typedef void (*gtk_render_frame_t)(GtkStyleContext*, cairo_t*, gdouble, gdouble, gdouble, gdouble);
typedef void (*gtk_render_icon_surface_t)(GtkStyleContext*, cairo_t*, cairo_surface_t*, gdouble, gdouble);
typedef void (*gtk_style_context_add_class_t)(GtkStyleContext*, const gchar*);
typedef void (*gtk_style_context_get_border_t)(GtkStyleContext*, GtkStateFlags, GtkBorder*);
typedef void (*gtk_style_context_get_padding_t)(GtkStyleContext*, GtkStateFlags, GtkBorder*);
typedef void (*gtk_style_context_get_t)(GtkStyleContext*, GtkStateFlags, const gchar*, ...);
typedef void (*gtk_style_context_remove_class_t)(GtkStyleContext*, const gchar*);
typedef void (*gtk_style_context_restore_t)(GtkStyleContext*);
typedef void (*gtk_style_context_save_t)(GtkStyleContext*);
typedef void (*gtk_style_context_set_state_t)(GtkStyleContext*, GtkStateFlags);
typedef void (*gtk_widget_destroy_t)(GtkWidget*);
typedef void (*gtk_widget_draw_t)(GtkWidget*, cairo_t*);
typedef void (*gtk_widget_get_allocation_t)(GtkWidget*, GtkAllocation*);
typedef void (*gtk_widget_get_clip_t)(GtkWidget*, GtkAllocation*);
typedef void (*gtk_widget_get_preferred_height_t)(GtkWidget*, gint*, gint*);
typedef void (*gtk_widget_get_preferred_width_t)(GtkWidget*, gint*, gint*);
typedef void (*gtk_widget_set_state_flags_t)(GtkWidget*, GtkStateFlags, gboolean);
typedef void (*gtk_widget_show_all_t)(GtkWidget*);
typedef void (*gtk_widget_size_allocate_t)(GtkWidget*, GtkAllocation*);
typedef void (*gtk_widget_unset_state_flags_t)(GtkWidget*, GtkStateFlags);
typedef void (*gtk_window_set_resizable_t)(GtkWindow*, gboolean);
typedef void (*gtk_window_set_titlebar_t)(GtkWindow*, GtkWidget*);
typedef cairo_surface_t* (*gdk_cairo_surface_create_from_pixbuf_t)(const GdkPixbuf*, int, GdkWindow*);
typedef void (*gdk_threads_enter_t)(void);
typedef void (*gdk_threads_leave_t)(void);
typedef cairo_surface_t* (*cairo_image_surface_create_for_data_t)(unsigned char*, cairo_format_t, int, int, int);
typedef cairo_surface_t* (*cairo_surface_create_for_rectangle_t)(cairo_surface_t*, double, double, double, double);
typedef cairo_t* (*cairo_create_t)(cairo_surface_t*);
typedef int (*cairo_format_stride_for_width_t)(cairo_format_t, int);
typedef void (*cairo_destroy_t)(cairo_t*);
typedef void (*cairo_paint_t)(cairo_t*);
typedef void (*cairo_surface_destroy_t)(cairo_surface_t*);
typedef void (*cairo_surface_flush_t)(cairo_surface_t *);
typedef void (*cairo_surface_set_device_scale_t)(cairo_surface_t *, double, double);
typedef void (*g_object_unref_t)(gpointer);
typedef void (*g_object_get_t)(gpointer, const gchar*, ...);
typedef void (*g_object_set_t)(gpointer, const gchar*, ...);
typedef void (*g_object_get_property_t)(GObject*, const gchar*, GValue*);
typedef gboolean (*g_type_check_instance_is_a_t)(void**, GType);
typedef gboolean (*g_main_context_iteration_t)(GMainContext *context, gboolean);
typedef struct GtkFrameDecorationDescr {
GtkWidget *window;
GtkWidget *titlebar;
jboolean show_minimize;
jboolean show_maximize;
jboolean is_active;
jboolean is_maximized;
} GtkFrameDecorationDescr;
struct WidgetCallbackData {
const char *name;
GtkWidget *widget;
};
static jfieldID CloseButtonBoundsFID;
static jfieldID MinButtonBoundsFID;
static jfieldID MaxButtonBoundsFID;
static jfieldID TitleBarHeightFID;
static jfieldID TitleBarMinWidthFID;
static gtk_bin_get_child_t p_gtk_bin_get_child;
static gtk_container_forall_t p_gtk_container_forall;
static gtk_container_get_type_t p_gtk_container_get_type;
static gtk_header_bar_new_t p_gtk_header_bar_new;
static gtk_header_bar_set_show_close_button_t p_gtk_header_bar_set_show_close_button;
static gtk_header_bar_set_title_t p_gtk_header_bar_set_title;
static gtk_icon_info_load_symbolic_for_context_t p_gtk_icon_info_load_symbolic_for_context;
static gtk_icon_size_lookup_t p_gtk_icon_size_lookup;
static gtk_icon_theme_get_default_t p_gtk_icon_theme_get_default;
static gtk_icon_theme_lookup_icon_for_scale_t p_gtk_icon_theme_lookup_icon_for_scale;
static gtk_offscreen_window_new_t p_gtk_offscreen_window_new;
static gtk_render_background_t p_gtk_render_background;
static gtk_render_frame_t p_gtk_render_frame;
static gtk_render_icon_surface_t p_gtk_render_icon_surface;
static gtk_style_context_add_class_t p_gtk_style_context_add_class;
static gtk_style_context_get_border_t p_gtk_style_context_get_border;
static gtk_style_context_get_padding_t p_gtk_style_context_get_padding;
static gtk_style_context_get_state_t p_gtk_style_context_get_state;
static gtk_style_context_get_t p_gtk_style_context_get;
static gtk_style_context_remove_class_t p_gtk_style_context_remove_class;
static gtk_style_context_restore_t p_gtk_style_context_restore;
static gtk_style_context_save_t p_gtk_style_context_save;
static gtk_style_context_set_state_t p_gtk_style_context_set_state;
static gtk_style_context_to_string_t p_gtk_style_context_to_string;
static gtk_widget_destroy_t p_gtk_widget_destroy;
static gtk_widget_draw_t p_gtk_widget_draw;
static gtk_widget_get_allocation_t p_gtk_widget_get_allocation;
static gtk_widget_get_clip_t p_gtk_widget_get_clip;
static gtk_widget_get_preferred_height_t p_gtk_widget_get_preferred_height;
static gtk_widget_get_preferred_width_t p_gtk_widget_get_preferred_width;
static gtk_widget_get_settings_t p_gtk_widget_get_settings;
static gtk_widget_get_style_context_t p_gtk_widget_get_style_context;
static gtk_widget_get_type_t p_gtk_widget_get_type;
static gtk_widget_set_state_flags_t p_gtk_widget_set_state_flags;
static gtk_widget_show_all_t p_gtk_widget_show_all;
static gtk_widget_size_allocate_t p_gtk_widget_size_allocate;
static gtk_widget_unset_state_flags_t p_gtk_widget_unset_state_flags;
static gtk_window_set_resizable_t p_gtk_window_set_resizable;
static gtk_window_set_titlebar_t p_gtk_window_set_titlebar;
static gdk_cairo_surface_create_from_pixbuf_t p_gdk_cairo_surface_create_from_pixbuf;
static gdk_threads_enter_t p_gdk_threads_enter;
static gdk_threads_leave_t p_gdk_threads_leave;
static cairo_create_t p_cairo_create;
static cairo_destroy_t p_cairo_destroy;
static cairo_format_stride_for_width_t p_cairo_format_stride_for_width;
static cairo_image_surface_create_for_data_t p_cairo_image_surface_create_for_data;
static cairo_paint_t p_cairo_paint;
static cairo_surface_create_for_rectangle_t p_cairo_surface_create_for_rectangle;
static cairo_surface_destroy_t p_cairo_surface_destroy;
static cairo_surface_flush_t p_cairo_surface_flush;
static cairo_surface_set_device_scale_t p_cairo_surface_set_device_scale;
static g_object_unref_t p_g_object_unref;
static g_object_get_t p_g_object_get;
static g_object_set_t p_g_object_set;
static g_object_get_property_t p_g_object_get_property;
static g_type_check_instance_is_a_t p_g_type_check_instance_is_a;
static g_main_context_iteration_t p_g_main_context_iteration;
static void* gtk_handle;
static void* gdk_handle;
static void* find_func(JNIEnv* env, void* lib_handle, const char* name) {
void* f = dlsym(lib_handle, name);
if (!f) {
int len = strlen(name) + 128;
char *msg = malloc(len);
if (msg) {
snprintf(msg, len, "Can't find function '%s'", name);
JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg);
free(msg);
} else {
JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", "Can't find some function; also ran out of memory.");
}
}
return f;
}
static jboolean load_gtk(JNIEnv *env) {
gtk_handle = dlopen(VERSIONED_JNI_LIB_NAME("gtk-3", "0"), RTLD_LAZY | RTLD_LOCAL);
if (!gtk_handle) {
gtk_handle = dlopen(JNI_LIB_NAME("gtk-3"), RTLD_LAZY | RTLD_LOCAL);
}
if (!gtk_handle) {
return JNI_FALSE;
}
gdk_handle = dlopen(VERSIONED_JNI_LIB_NAME("gdk-3", "0"), RTLD_LAZY | RTLD_LOCAL);
if (!gdk_handle) {
gdk_handle = dlopen(JNI_LIB_NAME("gdk-3"), RTLD_LAZY | RTLD_LOCAL);
}
if (!gdk_handle) {
dlclose(gtk_handle);
return JNI_FALSE;
}
p_gtk_bin_get_child = find_func(env, gtk_handle, "gtk_bin_get_child");
p_gtk_container_forall = find_func(env, gtk_handle, "gtk_container_forall");
p_gtk_container_get_type = find_func(env, gtk_handle, "gtk_container_get_type");
p_gtk_header_bar_new = find_func(env, gtk_handle, "gtk_header_bar_new");
p_gtk_header_bar_set_show_close_button = find_func(env, gtk_handle, "gtk_header_bar_set_show_close_button");
p_gtk_header_bar_set_title = find_func(env, gtk_handle, "gtk_header_bar_set_title");
p_gtk_icon_info_load_symbolic_for_context = find_func(env, gtk_handle, "gtk_icon_info_load_symbolic_for_context");
p_gtk_icon_size_lookup = find_func(env, gtk_handle, "gtk_icon_size_lookup");
p_gtk_icon_theme_get_default = find_func(env, gtk_handle, "gtk_icon_theme_get_default");
p_gtk_icon_theme_lookup_icon_for_scale = find_func(env, gtk_handle, "gtk_icon_theme_lookup_icon_for_scale");
p_gtk_offscreen_window_new = find_func(env, gtk_handle, "gtk_offscreen_window_new");
p_gtk_widget_destroy = find_func(env, gtk_handle, "gtk_widget_destroy");
p_gtk_render_background = find_func(env, gtk_handle, "gtk_render_background");
p_gtk_render_frame = find_func(env, gtk_handle, "gtk_render_frame");
p_gtk_render_icon_surface = find_func(env, gtk_handle, "gtk_render_icon_surface");
p_gtk_style_context_add_class = find_func(env, gtk_handle, "gtk_style_context_add_class");
p_gtk_style_context_get_border = find_func(env, gtk_handle, "gtk_style_context_get_border");
p_gtk_style_context_get = find_func(env, gtk_handle, "gtk_style_context_get");
p_gtk_style_context_get_padding = find_func(env, gtk_handle, "gtk_style_context_get_padding");
p_gtk_style_context_get_state = find_func(env, gtk_handle, "gtk_style_context_get_state");
p_gtk_style_context_remove_class = find_func(env, gtk_handle, "gtk_style_context_remove_class");
p_gtk_style_context_restore = find_func(env, gtk_handle, "gtk_style_context_restore");
p_gtk_style_context_save = find_func(env, gtk_handle, "gtk_style_context_save");
p_gtk_style_context_set_state = find_func(env, gtk_handle, "gtk_style_context_set_state");
p_gtk_style_context_to_string = find_func(env, gtk_handle, "gtk_style_context_to_string");
p_gtk_widget_draw = find_func(env, gtk_handle, "gtk_widget_draw");
p_gtk_widget_get_allocation = find_func(env, gtk_handle, "gtk_widget_get_allocation");
p_gtk_widget_get_clip = find_func(env, gtk_handle, "gtk_widget_get_clip");
p_gtk_widget_get_preferred_height = find_func(env, gtk_handle, "gtk_widget_get_preferred_height");
p_gtk_widget_get_preferred_width = find_func(env, gtk_handle, "gtk_widget_get_preferred_width");
p_gtk_widget_get_settings = find_func(env, gtk_handle, "gtk_widget_get_settings");
p_gtk_widget_get_style_context = find_func(env, gtk_handle, "gtk_widget_get_style_context");
p_gtk_widget_get_type = find_func(env, gtk_handle, "gtk_widget_get_type");
p_gtk_widget_set_state_flags = find_func(env, gtk_handle, "gtk_widget_set_state_flags");
p_gtk_widget_show_all = find_func(env, gtk_handle, "gtk_widget_show_all");
p_gtk_widget_size_allocate = find_func(env, gtk_handle, "gtk_widget_size_allocate");
p_gtk_widget_unset_state_flags = find_func(env, gtk_handle, "gtk_widget_unset_state_flags");
p_gtk_window_set_resizable = find_func(env, gtk_handle, "gtk_window_set_resizable");
p_gtk_window_set_titlebar = find_func(env, gtk_handle, "gtk_window_set_titlebar");
p_gdk_cairo_surface_create_from_pixbuf = find_func(env, gdk_handle, "gdk_cairo_surface_create_from_pixbuf");
p_gdk_threads_enter = find_func(env, gdk_handle, "gdk_threads_enter");
p_gdk_threads_leave = find_func(env, gdk_handle, "gdk_threads_leave");
p_cairo_surface_create_for_rectangle = find_func(env, gtk_handle, "cairo_surface_create_for_rectangle");
p_cairo_create = find_func(env, gtk_handle, "cairo_create");
p_cairo_destroy = find_func(env, gtk_handle, "cairo_destroy");
p_cairo_surface_destroy = find_func(env, gtk_handle, "cairo_surface_destroy");
p_cairo_paint = find_func(env, gtk_handle, "cairo_paint");
p_cairo_image_surface_create_for_data = find_func(env, gtk_handle, "cairo_image_surface_create_for_data");
p_cairo_surface_set_device_scale = find_func(env, gtk_handle, "cairo_surface_set_device_scale");
p_cairo_format_stride_for_width = find_func(env, gtk_handle, "cairo_format_stride_for_width");
p_cairo_surface_flush = find_func(env, gtk_handle, "cairo_surface_flush");
p_g_object_unref = find_func(env, gtk_handle, "g_object_unref");
p_g_object_get = find_func(env, gtk_handle, "g_object_get");
p_g_object_set = find_func(env, gtk_handle, "g_object_set");
p_g_object_get_property = find_func(env, gtk_handle, "g_object_get_property");
p_g_type_check_instance_is_a = find_func(env, gtk_handle, "g_type_check_instance_is_a");
p_g_main_context_iteration = find_func(env, gtk_handle, "g_main_context_iteration");
// NB: An error had been thrown in case some function was missing
return JNI_TRUE;
}
static void widget_by_name_cb(GtkWidget *widget, void *payload) {
struct WidgetCallbackData *data = payload;
if (GTK_IS_WIDGET(widget)) {
char *style_ctx = p_gtk_style_context_to_string(
p_gtk_widget_get_style_context(widget),
GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE);
if (strstr(style_ctx, data->name)) {
data->widget = widget;
free(style_ctx);
return;
}
free(style_ctx);
}
if (GTK_IS_CONTAINER(widget)) {
p_gtk_container_forall(GTK_CONTAINER(widget), &widget_by_name_cb, data);
}
}
static GtkWidget* widget_by_name(GtkWidget *widget, const char *name) {
struct WidgetCallbackData data = {.name = name, .widget = NULL};
widget_by_name_cb(widget, &data);
return data.widget;
}
static void draw_titlebar_background(GtkFrameDecorationDescr* decor, cairo_t *cr) {
GtkAllocation allocation;
p_gtk_widget_get_allocation(GTK_WIDGET(decor->titlebar), &allocation);
GtkStyleContext* style = p_gtk_widget_get_style_context(decor->titlebar);
p_gtk_render_background(style, cr, allocation.x, allocation.y, allocation.width, allocation.height);
}
static void draw_titlebar_title(GtkFrameDecorationDescr* decor, cairo_surface_t * surface) {
GtkWidget *label = widget_by_name(decor->titlebar, "label.title:");
GtkAllocation allocation;
p_gtk_widget_get_allocation(label, &allocation);
cairo_surface_t *label_surface = p_cairo_surface_create_for_rectangle(
surface, allocation.x, allocation.y, allocation.width, allocation.height);
cairo_t *cr = p_cairo_create(label_surface);
p_gtk_widget_draw(label, cr);
p_cairo_destroy(cr);
p_cairo_surface_destroy(label_surface);
}
static void draw_titlebar_button(GtkFrameDecorationDescr* decor, cairo_surface_t * surface, cairo_t *cr,
double scale,
jboolean hovered, jboolean pressed,
const char *name, const char *icon_name) {
GtkWidget *button = widget_by_name(decor->titlebar, name);
if (!button)
return;
GtkStateFlags style_state = GTK_STATE_FLAG_NORMAL;
if (!decor->is_active) {
style_state |= GTK_STATE_FLAG_BACKDROP;
} else {
style_state |= GTK_STATE_FLAG_FOCUSED;
}
if (hovered) {
style_state |= GTK_STATE_FLAG_PRELIGHT;
}
if (pressed) {
style_state |= GTK_STATE_FLAG_ACTIVE;
}
GtkAllocation allocation;
p_gtk_widget_get_clip(button, &allocation);
GtkStyleContext* button_style = p_gtk_widget_get_style_context(button);
p_gtk_style_context_save(button_style);
p_gtk_style_context_set_state(button_style, style_state);
p_gtk_render_background(button_style, cr,
allocation.x, allocation.y, allocation.width, allocation.height);
p_gtk_render_frame(button_style, cr,
allocation.x, allocation.y, allocation.width, allocation.height);
p_gtk_style_context_restore(button_style);
int icon_width;
int icon_height;
if (!p_gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &icon_width, &icon_height)) {
icon_width = 16;
icon_height = 16;
}
GtkIconInfo* icon_info = p_gtk_icon_theme_lookup_icon_for_scale(
p_gtk_icon_theme_get_default(), icon_name, icon_width, (int) scale, 0);
p_gtk_style_context_save(button_style);
p_gtk_style_context_set_state(button_style, style_state);
GdkPixbuf* icon_pixbuf = p_gtk_icon_info_load_symbolic_for_context(icon_info, button_style, NULL, NULL);
cairo_surface_t* icon_surface = p_gdk_cairo_surface_create_from_pixbuf(icon_pixbuf, (int) scale, NULL);
p_gtk_style_context_restore(button_style);
int width = 0;
int height = 0;
p_gtk_style_context_get(button_style, p_gtk_style_context_get_state(button_style),
"min-width", &width, "min-height", &height, NULL);
if (width < icon_width)
width = icon_width;
if (height < icon_height)
height = icon_height;
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
GtkBorder border;
GtkBorder padding;
p_gtk_style_context_get_border(button_style, p_gtk_style_context_get_state(button_style), &border);
left += border.left;
right += border.right;
top += border.top;
bottom += border.bottom;
p_gtk_style_context_get_padding(button_style, p_gtk_style_context_get_state(button_style), &padding);
left += padding.left;
right += padding.right;
top += padding.top;
bottom += padding.bottom;
width += left + right;
height += top + bottom;
int offset_x = (width - icon_width + 0.5) / 2;
int offset_y = (height - icon_height + 0.5) / 2;
GtkWidget *icon_widget = p_gtk_bin_get_child(GTK_BIN(button));
p_gtk_render_icon_surface(p_gtk_widget_get_style_context(icon_widget),
cr, icon_surface, allocation.x + offset_x, allocation.y + offset_y);
p_cairo_paint(cr);
p_cairo_surface_destroy(icon_surface);
p_g_object_unref(icon_pixbuf);
}
static void draw_titlebar_buttons(GtkFrameDecorationDescr* decor, cairo_surface_t * surface, cairo_t *cr,
double scale, int buttonsState) {
if (decor->show_minimize) {
jboolean hovered = buttonsState & sun_awt_wl_GtkFrameDecoration_MIN_BUTTON_STATE_HOVERED;
jboolean pressed = buttonsState & sun_awt_wl_GtkFrameDecoration_MIN_BUTTON_STATE_PRESSED;
draw_titlebar_button(decor, surface, cr, scale, hovered, pressed,
".minimize", "window-minimize-symbolic");
}
if (decor->show_maximize) {
jboolean hovered = buttonsState & sun_awt_wl_GtkFrameDecoration_MAX_BUTTON_STATE_HOVERED;
jboolean pressed = buttonsState & sun_awt_wl_GtkFrameDecoration_MAX_BUTTON_STATE_PRESSED;
draw_titlebar_button(decor, surface, cr, scale, hovered, pressed,
".maximize",
decor->is_maximized ? "window-restore-symbolic" : "window-maximize-symbolic");
}
jboolean hovered = buttonsState & sun_awt_wl_GtkFrameDecoration_CLOSE_BUTTON_STATE_HOVERED;
jboolean pressed = buttonsState & sun_awt_wl_GtkFrameDecoration_CLOSE_BUTTON_STATE_PRESSED;
draw_titlebar_button(decor, surface, cr, scale, hovered, pressed,
".close", "window-close-symbolic");
}
static void draw_title_bar(GtkFrameDecorationDescr* decor, cairo_surface_t * surface, cairo_t *cr,
int width, int height, double scale, const char *title, int buttonsState) {
GtkStyleContext *style = p_gtk_widget_get_style_context(decor->window);
if (!decor->is_active) {
p_gtk_widget_set_state_flags(decor->window, GTK_STATE_FLAG_BACKDROP, true);
} else {
p_gtk_widget_unset_state_flags(decor->window, GTK_STATE_FLAG_BACKDROP);
}
if (decor->is_maximized) {
p_gtk_style_context_add_class(style, "maximized");
} else {
p_gtk_style_context_remove_class(style, "maximized");
}
p_gtk_widget_show_all(decor->window);
p_gtk_header_bar_set_title(GTK_HEADER_BAR(decor->titlebar), title);
GtkAllocation allocation = {0, 0, width, height};
p_gtk_widget_size_allocate(decor->titlebar, &allocation);
draw_titlebar_background(decor, cr);
draw_titlebar_title(decor, surface);
draw_titlebar_buttons(decor, surface, cr, scale, buttonsState);
}
JNIEXPORT void JNICALL Java_sun_awt_wl_GtkFrameDecoration_initIDs(JNIEnv *env, jclass clazz) {
CHECK_NULL_THROW_IE(env,
CloseButtonBoundsFID = (*env)->GetFieldID(env, clazz, "closeButtonBounds", "Ljava/awt/Rectangle;"),
"Failed to find field closeButtonBounds");
CHECK_NULL_THROW_IE(env,
MinButtonBoundsFID = (*env)->GetFieldID(env, clazz, "minimizeButtonBounds", "Ljava/awt/Rectangle;"),
"Failed to find field minimizeButtonBounds");
CHECK_NULL_THROW_IE(env,
MaxButtonBoundsFID = (*env)->GetFieldID(env, clazz, "maximizeButtonBounds", "Ljava/awt/Rectangle;"),
"Failed to find field maximizeButtonBounds");
CHECK_NULL_THROW_IE(env,
TitleBarHeightFID = (*env)->GetFieldID(env, clazz, "titleBarHeight", "I"),
"Failed to find field titleBarHeightBounds");
CHECK_NULL_THROW_IE(env,
TitleBarMinWidthFID = (*env)->GetFieldID(env, clazz, "titleBarMinWidth", "I"),
"Failed to find field titleBarMinWidth");
}
JNIEXPORT jboolean JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativeLoadGTK(JNIEnv *env, jclass clazz) {
return load_gtk(env);
}
JNIEXPORT jlong JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativeCreateDecoration
(JNIEnv *env, jobject obj, jboolean show_minimize, jboolean show_maximize) {
GtkFrameDecorationDescr *d = calloc(1, sizeof(GtkFrameDecorationDescr));
CHECK_NULL_THROW_OOME_RETURN(env, d, "Failed to allocate GtkFrameDeocration", 0);
p_gdk_threads_enter();
d->show_minimize = show_minimize;
d->show_maximize = show_maximize;
d->window = p_gtk_offscreen_window_new();
d->titlebar = p_gtk_header_bar_new();
p_g_object_set(d->titlebar,
"title", "Default Title",
"has-subtitle", false,
"show-close-button", true,
NULL);
GtkStyleContext *context_hdr = p_gtk_widget_get_style_context(d->titlebar);
p_gtk_style_context_add_class(context_hdr, GTK_STYLE_CLASS_TITLEBAR);
p_gtk_style_context_add_class(context_hdr, "default-decoration");
p_gtk_window_set_titlebar(GTK_WINDOW(d->window), d->titlebar);
p_gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(d->titlebar), true);
p_gtk_window_set_resizable(GTK_WINDOW(d->window), true);
p_gdk_threads_leave();
return ptr_to_jlong(d);
}
JNIEXPORT void JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativeDestroyDecoration
(JNIEnv *env, jobject obj, jlong ptr) {
assert (ptr != 0);
GtkFrameDecorationDescr* decor = jlong_to_ptr(ptr);
p_gdk_threads_enter();
p_gtk_widget_destroy(decor->titlebar);
p_gtk_widget_destroy(decor->window);
p_gdk_threads_leave();
free(decor);
}
JNIEXPORT void JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativePaintTitleBar
(JNIEnv *env, jobject obj, jlong ptr, jintArray dest,
jint width, jint height, jdouble scale, jstring title, jint buttonsState) {
GtkFrameDecorationDescr* decor = jlong_to_ptr(ptr);
jint pixel_width = ceil(width * scale);
jint pixel_height = ceil(height * scale);
unsigned char *buffer = (*env)->GetPrimitiveArrayCritical(env, dest, 0);
if (!buffer) {
JNU_ThrowOutOfMemoryError(env, "Could not get image buffer");
return;
}
p_gdk_threads_enter();
cairo_surface_t *surface = p_cairo_image_surface_create_for_data(
buffer, CAIRO_FORMAT_ARGB32,
pixel_width, pixel_height,
p_cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pixel_width));
p_cairo_surface_set_device_scale(surface, scale, scale);
cairo_t *cr = p_cairo_create(surface);
jboolean is_copy = JNI_FALSE;
const char *title_c_str = "";
if (title) {
title_c_str = JNU_GetStringPlatformChars(env, title, &is_copy);
if (!title_c_str)
return;
}
draw_title_bar(decor, surface, cr, width, height, scale, title_c_str, buttonsState);
if (is_copy) {
JNU_ReleaseStringPlatformChars(env, title, title_c_str);
}
// Make sure pixels have been flush into the underlying buffer
p_cairo_surface_flush(surface);
p_gdk_threads_leave();
(*env)->ReleasePrimitiveArrayCritical(env, dest, buffer, 0);
p_cairo_destroy(cr);
p_cairo_surface_destroy(surface);
}
JNIEXPORT void JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativePrePaint(JNIEnv *env, jobject obj,
jlong ptr, jint width) {
assert (ptr != 0);
GtkFrameDecorationDescr* decor = jlong_to_ptr(ptr);
p_gdk_threads_enter();
if (decor->is_active) {
p_gtk_widget_set_state_flags(decor->window, GTK_STATE_FLAG_BACKDROP, true);
} else {
p_gtk_widget_unset_state_flags(decor->window, GTK_STATE_FLAG_BACKDROP);
}
GtkStyleContext *style = p_gtk_widget_get_style_context(decor->window);
if (decor->is_maximized) {
p_gtk_style_context_add_class(style, "maximized");
} else {
p_gtk_style_context_remove_class(style, "maximized");
}
p_gtk_header_bar_set_title(GTK_HEADER_BAR(decor->titlebar), "Title");
p_gtk_widget_show_all(decor->window);
jint pref_height;
p_gtk_widget_get_preferred_height(decor->titlebar, NULL, &pref_height);
jint min_width;
p_gtk_widget_get_preferred_width(decor->titlebar, &min_width, NULL);
(*env)->SetIntField(env, obj, TitleBarHeightFID, pref_height);
(*env)->SetIntField(env, obj, TitleBarMinWidthFID, min_width);
GtkAllocation ha = {0, 0, width, pref_height};
p_gtk_widget_size_allocate(decor->titlebar, &ha);
GtkWidget *button = widget_by_name(decor->titlebar, ".close");
GtkAllocation ba;
if (button) {
p_gtk_widget_get_clip(button, &ba);
jobject recObj = JNU_NewObjectByName(env, "java/awt/Rectangle", "(IIII)V",
ba.x, ba.y, ba.width, ba.height);
(*env)->SetObjectField(env, obj, CloseButtonBoundsFID, recObj);
}
button = widget_by_name(decor->titlebar, ".minimize");
if (button) {
p_gtk_widget_get_clip(button, &ba);
jobject recObj = JNU_NewObjectByName(env, "java/awt/Rectangle", "(IIII)V",
ba.x, ba.y, ba.width, ba.height);
(*env)->SetObjectField(env, obj, MinButtonBoundsFID, recObj);
}
button = widget_by_name(decor->titlebar, ".maximize");
if (button) {
p_gtk_widget_get_clip(button, &ba);
jobject recObj = JNU_NewObjectByName(env, "java/awt/Rectangle", "(IIII)V",
ba.x, ba.y, ba.width, ba.height);
(*env)->SetObjectField(env, obj, MaxButtonBoundsFID, recObj);
}
p_gdk_threads_leave();
}
JNIEXPORT void JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativeSwitchTheme(JNIEnv *env, jobject obj) {
while ((*p_g_main_context_iteration)(NULL, false));
}
JNIEXPORT jint JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativeGetIntProperty
(JNIEnv *env, jobject obj, jlong ptr, jstring name) {
assert (ptr != 0);
GtkFrameDecorationDescr* decor = jlong_to_ptr(ptr);
jboolean is_copy = JNI_FALSE;
const char *name_c_str = JNU_GetStringPlatformChars(env, name, &is_copy);
if (!name_c_str)
return 0;
jint result;
p_gdk_threads_enter();
p_g_object_get(p_gtk_widget_get_settings(decor->window), name_c_str, &result, NULL);
p_gdk_threads_leave();
if (is_copy) {
JNU_ReleaseStringPlatformChars(env, name, name_c_str);
}
return result;
}
JNIEXPORT void JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativeNotifyConfigured
(JNIEnv *env, jobject obj, jlong ptr, jboolean active, jboolean maximized, jboolean fullscreen) {
assert (ptr != 0);
GtkFrameDecorationDescr* decor = jlong_to_ptr(ptr);
decor->is_active = active;
decor->is_maximized = maximized;
}

View File

@@ -2,6 +2,8 @@
# :hotspot_runtime
containers/cgroup/TestContainerized.java JBR-9076 linux-all
runtime/8176717/TestInheritFD.java JBR-6974 linux-all
runtime/ErrorHandling/CreateCoredumpOnCrash.java JBR-7917 linux-all
runtime/Thread/ThreadCountLimit.java#id0 JBR-7974 linux-all

View File

@@ -170,6 +170,8 @@ runtime/jni/daemonDestroy/TestDaemonDestroy.java JBR-6261 windows-all
runtime/jni/nativeStack/TestNativeStack.java JBR-8521 windows-aarch64
runtime/jni/terminatedThread/TestTerminatedThread.java 8317789 aix-ppc64
runtime/cds/CheckDefaultArchiveFile.java JBR-4227 generic-all
runtime/cds/SharedBaseAddress.java#id2 JBR-9078 windows-aarch64
runtime/cds/SharedBaseAddress.java#id3 JBR-9078 windows-aarch64
runtime/handshake/HandshakeSuspendExitTest.java 8318631 generic-all
runtime/modules/ClassLoaderNoUnnamedModuleTest.java JBR-8516 windows-aarch64
runtime/Monitor/SyncOnValueBasedClassTest.java 8340995,JBR-8517 linux-s390x,windows-aarch64
@@ -222,7 +224,6 @@ runtime/cds/appcds/dynamicArchive/CDSStreamTestDriver.java initial_run generic-a
runtime/ReservedStack/ReservedStackTest.java initial_run windows-aarch64
runtime/cds/appcds/methodHandles/MethodHandlesPermuteArgumentsTest.java initial_run generic-all
runtime/cds/appcds/methodHandles/MethodHandlesAsCollectorTest.java initial_run generic-all
runtime/cds/SharedBaseAddress.java initial_run generic-all
runtime/cds/TestCDSVMCrash.java JBR-6616 windows-aarch64
runtime/cds/TestDefaultArchiveLoading.java#coops_nocoh JBR-6616 windows-aarch64
runtime/cds/TestDefaultArchiveLoading.java#nocoops_nocoh JBR-6616 windows-aarch64

View File

@@ -125,5 +125,6 @@ javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-5952,834
jb/build/ResolveSymbolsTest/ResolveSymbolsRealEnv.java JBR-8544 linux-all
jb/java/awt/Window/UndecoratedDialogInTransientsChain.java JBR-8710 windows-aarch64
jb/javax/swing/JDialog/JDialog1054.java JBR-5004 macosx-aarch64
sun/awt/dnd/8024061/bug8024061.java JBR-9033 windows-all

View File

@@ -21,6 +21,7 @@ java/awt/font/TextLayout/HitTest.java JBR-8764 linux-all
java/awt/font/TextLayout/TestGetPixelBounds.java JBR-8765 linux-all
java/awt/font/TextLayout/VisibleAdvance.java JBR-8766 linux-all
java/awt/FontMetrics/ExtremeFontSizeTest.java JBR-7823 linux-all
java/awt/Graphics2D/DrawString/IgnoredWhitespaceTest.java JBR-9086 linux-all
java/awt/Graphics2D/DrawString/RotTransText.java JBR-8767 linux-all
java/awt/Graphics/XORPaint.java#id2 JBR-7373 linux-x64
java/awt/image/DrawImage/SimpleManagedImage.java JBR-8769 linux-all

View File

@@ -794,6 +794,7 @@ java/beans/XMLEncoder/Test6570354.java 8015593 macosx-all
# jdk_foreign
java/foreign/critical/TestCriticalUpcall.java JBR-8711 windows-aarch64
java/foreign/TestBufferStackStress.java JBR-8930 windows-aarch64
java/foreign/TestMismatch.java 8249684 macosx-all
############################################################################
@@ -1384,6 +1385,13 @@ java/awt/List/HandlingKeyEventIfMousePressedTest.java 6848358 macosx-all,windows
############################################################################
# jdk_since_checks
tools/sincechecker/modules/java.base/JavaBaseCheckSince.java 8358627 generic-all
tools/sincechecker/modules/jdk.management.jfr/JdkManagementJfrCheckSince.java 8354921 generic-all
############################################################################
# various Windows are created spontaneously during test execution
javax/swing/JList/4618767/JListSelectedElementTest.java JBR-4955 windows-all
@@ -1554,7 +1562,7 @@ javax/swing/LookAndFeel/8145547/DemandGTK3.sh JBR-5510,JBR-6908 linux-5.18.2-arc
jb/java/awt/Focus/BrokenTraversalAWT.java JBR-5799 windows-all
jb/java/awt/Focus/ComplexFocusSequence.java JBR-6728 linux-all,windows-x64
jb/java/awt/Focus/ContextMenuAfterPopup.java JBR-5799 windows-all
jb/java/awt/Focus/FileDialogClosing.java JBR-8309 macosx-x64
jb/java/awt/Focus/FileDialogClosing.java JBR-5799,JBR-8309 windows-all,macosx-x64
jb/java/awt/Focus/FocusTraversalOrderTest.java JBR-6060 generic-all
jb/java/awt/Focus/PopupIncomingFocusTest.java JBR-5799 windows-all
jb/java/awt/Focus/TitleBarClickTest.java JBR-6394 linux-5.18.2-arch1-1

View File

@@ -74,7 +74,6 @@ javax/swing/plaf/basic/BasicGraphicsUtils/8132119/bug8132119.java JBR-8357 linux
jb/java/awt/event/MouseEvent/ReleaseAndClickModifiers.java JBR-6589 windows-all
jb/java/awt/Focus/FileDialogClosing.java JBR-5799,JBR-8309 windows-all,macosx-x64
jb/java/awt/Focus/ModalDialogFromMenuTest.java JBR-5799 windows-all
jb/java/awt/Focus/ModalDialogOverSiblingTest.java JBR-5716 windows-all
jb/java/awt/Focus/PopupFromMenuTest.java JBR-5799 windows-all
jb/java/awt/Focus/PopupIncomingFocusTest.java JBR-2651 generic-all
@@ -86,6 +85,7 @@ jb/java/awt/Window/UndecoratedDialogInTransientsChain.java
jdk/editpad/EditPadTest.java JBR-5712 windows-all
sanity/client/SwingSet/src/ColorChooserDemoTest.java JBR-8354,JBR-8933 linux-all,windows-aarch64,windows-10.0
sanity/client/SwingSet/src/EditorPaneDemoTest.java JBR-5510,JBR-6285 linux-5.18.2-arch1-1,linux-all
sanity/client/SwingSet/src/InternalFrameDemoTest.java JBR-6685 linux-all
sanity/client/SwingSet/src/ToolTipDemoTest.java 8293001,JBR-6293 linux-all,windows-all
sun/java2d/GdiRendering/ClipShapeRendering.java JBR-5204 linux-all,macosx-all,windows-all