mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 06:27:13 -06:00
flatlaf-natives-windows: reworked linking/loading of jawt.dll; now loading jawt.dll when first used (issue #673)
This commit is contained in:
@@ -24,6 +24,9 @@ FlatLaf Change Log
|
|||||||
not visible. (issue #686)
|
not visible. (issue #686)
|
||||||
- "Monocai" theme: Fixed unreadable text color of default buttons. (issue
|
- "Monocai" theme: Fixed unreadable text color of default buttons. (issue
|
||||||
#693)
|
#693)
|
||||||
|
- Native Windows libraries: Fixed crash when running in Java 8 and newer Java
|
||||||
|
version is installed in `PATH` environment variable and using class
|
||||||
|
`SystemInfo` before AWT initialization. (issue #673)
|
||||||
|
|
||||||
|
|
||||||
## 3.1.1
|
## 3.1.1
|
||||||
|
|||||||
@@ -61,13 +61,20 @@ class FlatNativeLibrary
|
|||||||
classifier = SystemInfo.isX86_64 ? "windows-x86_64" : "windows-x86";
|
classifier = SystemInfo.isX86_64 ? "windows-x86_64" : "windows-x86";
|
||||||
ext = "dll";
|
ext = "dll";
|
||||||
|
|
||||||
// In Java 8, load jawt.dll (part of JRE) explicitly because it
|
// Do not load jawt.dll (part of JRE) here explicitly because
|
||||||
// is not found when running application with <jdk>/bin/java.exe.
|
// the FlatLaf native library flatlaf.dll may be loaded very early on Windows
|
||||||
// When using <jdk>/jre/bin/java.exe, it is found.
|
// (e.g. from class com.formdev.flatlaf.util.SystemInfo) and before AWT is
|
||||||
// jawt.dll is located in <jdk>/jre/bin/.
|
// initialized (and awt.dll is loaded). Loading jawt.dll also loads awt.dll.
|
||||||
// Java 9 and later do not have this problem,
|
// In Java 8, loading jawt.dll before AWT is initialized may load
|
||||||
// but load jawt.dll anyway to be on the safe side.
|
// a wrong version of awt.dll if a newer Java version (e.g. 19)
|
||||||
loadJAWT();
|
// is in PATH environment variable. Then Java 19 awt.dll and Java 8 awt.dll
|
||||||
|
// are loaded at same time and calling JAWT_GetAWT() crashes the application.
|
||||||
|
//
|
||||||
|
// To avoid this, flatlaf.dll is not linked to jawt.dll,
|
||||||
|
// which avoids loading jawt.dll when flatlaf.dll is loaded.
|
||||||
|
// Instead flatlaf.dll dynamically loads jawt.dll when first used,
|
||||||
|
// which is guaranteed after AWT initialization.
|
||||||
|
|
||||||
} else if( SystemInfo.isLinux && SystemInfo.isX86_64 ) {
|
} else if( SystemInfo.isLinux && SystemInfo.isX86_64 ) {
|
||||||
// Linux: requires x86_64
|
// Linux: requires x86_64
|
||||||
|
|
||||||
|
|||||||
@@ -71,12 +71,11 @@ tasks {
|
|||||||
val nativesDir = project( ":flatlaf-core" ).projectDir.resolve( "src/main/resources/com/formdev/flatlaf/natives" )
|
val nativesDir = project( ":flatlaf-core" ).projectDir.resolve( "src/main/resources/com/formdev/flatlaf/natives" )
|
||||||
val is64Bit = name.contains( "64" )
|
val is64Bit = name.contains( "64" )
|
||||||
val libraryName = if( is64Bit ) "flatlaf-windows-x86_64.dll" else "flatlaf-windows-x86.dll"
|
val libraryName = if( is64Bit ) "flatlaf-windows-x86_64.dll" else "flatlaf-windows-x86.dll"
|
||||||
val jawt = if( is64Bit ) "lib/jawt-x86_64" else "lib/jawt-x86"
|
|
||||||
|
|
||||||
linkerArgs.addAll( toolChain.map {
|
linkerArgs.addAll( toolChain.map {
|
||||||
when( it ) {
|
when( it ) {
|
||||||
is Gcc, is Clang -> listOf( "-l${jawt}", "-lUser32", "-lGdi32", "-lshell32", "-lAdvAPI32", "-lKernel32", "-lDwmapi" )
|
is Gcc, is Clang -> listOf( "-lUser32", "-lGdi32", "-lshell32", "-lAdvAPI32", "-lKernel32", "-lDwmapi" )
|
||||||
is VisualCpp -> listOf( "${jawt}.lib", "User32.lib", "Gdi32.lib", "shell32.lib", "AdvAPI32.lib", "Kernel32.lib", "Dwmapi.lib", "/NODEFAULTLIB" )
|
is VisualCpp -> listOf( "User32.lib", "Gdi32.lib", "shell32.lib", "AdvAPI32.lib", "Kernel32.lib", "Dwmapi.lib", "/NODEFAULTLIB" )
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
Contains libraries used to compile FlatLaf Windows 10 native libraries (DLLs).
|
|
||||||
|
|
||||||
- `jawt-x86.lib` is `<jdk>/lib/jawt.lib` from AdoptOpenJDK jdk8u282-b08 32-bit,
|
|
||||||
which is required to build 32-bit DLL
|
|
||||||
- `jawt-x86_64.lib` is `<jdk>/lib/jawt.lib` from AdoptOpenJDK jdk8u282-b08
|
|
||||||
64-bit, which is required to build 64-bit DLL
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -542,10 +542,82 @@ void FlatWndProc::setMenuItemState( HMENU systemMenu, int item, bool enabled ) {
|
|||||||
::SetMenuItemInfo( systemMenu, item, FALSE, &mii );
|
::SetMenuItemInfo( systemMenu, item, FALSE, &mii );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- window handle ----------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
#define GETAWT_METHOD_NAME "JAWT_GetAWT"
|
||||||
|
#else
|
||||||
|
#define GETAWT_METHOD_NAME "_JAWT_GetAWT@8"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef jboolean (JNICALL *JAWT_GetAWT_Type)( JNIEnv*, JAWT* );
|
||||||
|
|
||||||
|
static HMODULE jawtModule = NULL;
|
||||||
|
static JAWT_GetAWT_Type pJAWT_GetAWT = NULL;
|
||||||
|
|
||||||
|
|
||||||
HWND getWindowHandle( JNIEnv* env, jobject window ) {
|
HWND getWindowHandle( JNIEnv* env, jobject window ) {
|
||||||
|
|
||||||
|
// flatlaf.dll is not linked to jawt.dll because flatlaf.dll may be loaded
|
||||||
|
// very early on Windows (e.g. from class com.formdev.flatlaf.util.SystemInfo) and
|
||||||
|
// before AWT is initialized (and awt.dll is loaded). Loading jawt.dll also loads awt.dll.
|
||||||
|
// In Java 8, loading jawt.dll before AWT is initialized may load
|
||||||
|
// a wrong version of awt.dll if a newer Java version (e.g. 19)
|
||||||
|
// is in PATH environment variable. Then Java 19 awt.dll and Java 8 awt.dll
|
||||||
|
// are loaded at same time and calling JAWT_GetAWT() crashes the application.
|
||||||
|
//
|
||||||
|
// To avoid this, flatlaf.dll is not linked to jawt.dll,
|
||||||
|
// which avoids loading jawt.dll when flatlaf.dll is loaded.
|
||||||
|
// Instead flatlaf.dll dynamically loads jawt.dll when first used,
|
||||||
|
// which is guaranteed after AWT initialization.
|
||||||
|
//
|
||||||
|
// Load JAWT library from ${java.home}\bin\jawt.dll and use wide chars for path
|
||||||
|
// for the case that Java path uses special characters. (this is similar to JNA)
|
||||||
|
|
||||||
|
// load JAWT library jawt.dll
|
||||||
|
if( jawtModule == NULL ) {
|
||||||
|
// invoke: javaHome = System.getProperty( "java.home" )
|
||||||
|
jclass cls = env->FindClass( "java/lang/System" );
|
||||||
|
jmethodID mid = (cls != NULL) ? env->GetStaticMethodID( cls, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;" ) : NULL;
|
||||||
|
jstring javaHome = (mid != NULL) ? (jstring) env->CallStaticObjectMethod( cls, mid, env->NewStringUTF( "java.home" ) ) : NULL;
|
||||||
|
if( javaHome != NULL ) {
|
||||||
|
// invoke: jawtPath = javaHome.concat( "\\bin\\jawt.dll" )
|
||||||
|
jmethodID mid2 = env->GetMethodID( env->GetObjectClass( javaHome ), "concat", "(Ljava/lang/String;)Ljava/lang/String;" );
|
||||||
|
jstring jawtPath = (mid2 != NULL) ? (jstring) env->CallObjectMethod( javaHome, mid2, env->NewStringUTF( "\\bin\\jawt.dll" ) ) : NULL;
|
||||||
|
if( jawtPath != NULL ) {
|
||||||
|
// convert Java UTF-8 string to Windows wide chars
|
||||||
|
const char* sjawtPath = env->GetStringUTFChars( jawtPath, NULL );
|
||||||
|
int wstr_len = MultiByteToWideChar( CP_UTF8, 0, sjawtPath, -1, NULL, 0 );
|
||||||
|
if( wstr_len > 0 ) {
|
||||||
|
wchar_t* wstr = new wchar_t[wstr_len];
|
||||||
|
if( MultiByteToWideChar( CP_UTF8, 0, sjawtPath, -1, wstr, wstr_len ) == wstr_len ) {
|
||||||
|
// load jawt.dll from Java home
|
||||||
|
jawtModule = LoadLibraryExW( wstr, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
|
||||||
|
}
|
||||||
|
delete[] wstr;
|
||||||
|
}
|
||||||
|
env->ReleaseStringUTFChars( jawtPath, sjawtPath );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback
|
||||||
|
if( jawtModule == NULL )
|
||||||
|
jawtModule = LoadLibraryA( "jawt.dll" );
|
||||||
|
|
||||||
|
if( jawtModule == NULL )
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get address of method JAWT_GetAWT()
|
||||||
|
if( pJAWT_GetAWT == NULL ) {
|
||||||
|
pJAWT_GetAWT = (JAWT_GetAWT_Type) GetProcAddress( jawtModule, GETAWT_METHOD_NAME );
|
||||||
|
if( pJAWT_GetAWT == NULL )
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
JAWT awt;
|
JAWT awt;
|
||||||
awt.version = JAWT_VERSION_1_4;
|
awt.version = JAWT_VERSION_1_4;
|
||||||
if( !JAWT_GetAWT( env, &awt ) )
|
if( !pJAWT_GetAWT( env, &awt ) )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
jawt_DrawingSurface* ds = awt.GetDrawingSurface( env, window );
|
jawt_DrawingSurface* ds = awt.GetDrawingSurface( env, window );
|
||||||
@@ -558,12 +630,15 @@ HWND getWindowHandle( JNIEnv* env, jobject window ) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HWND hwnd = 0;
|
||||||
|
|
||||||
JAWT_DrawingSurfaceInfo* dsi = ds->GetDrawingSurfaceInfo( ds );
|
JAWT_DrawingSurfaceInfo* dsi = ds->GetDrawingSurfaceInfo( ds );
|
||||||
JAWT_Win32DrawingSurfaceInfo* wdsi = (JAWT_Win32DrawingSurfaceInfo*) dsi->platformInfo;
|
if( dsi != NULL ) {
|
||||||
|
JAWT_Win32DrawingSurfaceInfo* wdsi = (JAWT_Win32DrawingSurfaceInfo*) dsi->platformInfo;
|
||||||
|
hwnd = wdsi->hwnd;
|
||||||
|
ds->FreeDrawingSurfaceInfo( dsi );
|
||||||
|
}
|
||||||
|
|
||||||
HWND hwnd = wdsi->hwnd;
|
|
||||||
|
|
||||||
ds->FreeDrawingSurfaceInfo( dsi );
|
|
||||||
ds->Unlock( ds );
|
ds->Unlock( ds );
|
||||||
awt.FreeDrawingSurface( ds );
|
awt.FreeDrawingSurface( ds );
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user