diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 067c9975..bef9f29c 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { compileOnly(libs.nullabilityAnnotations) compileOnly(libs.swingx) + testImplementation(libs.jna) testImplementation(libs.svgSalamander) testImplementation(libs.bundles.test.miglayout) testImplementation(libs.swingx) diff --git a/core/src/test/java/com/github/weisj/darklaf/PointerUtilTest.java b/core/src/test/java/com/github/weisj/darklaf/PointerUtilTest.java new file mode 100644 index 00000000..8a72c4ff --- /dev/null +++ b/core/src/test/java/com/github/weisj/darklaf/PointerUtilTest.java @@ -0,0 +1,58 @@ +/* + * MIT License + * + * Copyright (c) 2021 Jannis Weis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package com.github.weisj.darklaf; + +import java.awt.Window; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.JWindow; +import javax.swing.SwingUtilities; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; + +import com.github.weisj.darklaf.platform.windows.PointerUtil; +import com.github.weisj.darklaf.platform.windows.WindowsLibrary; +import com.sun.jna.Native; + +class PointerUtilTest { + + @Test + @EnabledOnOs(OS.WINDOWS) + void testCustomImplementationEqualsJNA() throws InterruptedException, InvocationTargetException { + WindowsLibrary.get().updateLibrary(); + Assertions.assertTrue(WindowsLibrary.get().isLoaded()); + for (int i = 0; i < 100; i++) { + Window frame = new JWindow(); + frame.setAutoRequestFocus(false); + SwingUtilities.invokeAndWait(() -> frame.setVisible(true)); + Assertions.assertEquals(Native.getWindowID(frame), PointerUtil.getHWND(frame)); + SwingUtilities.invokeLater(() -> { + frame.setVisible(false); + frame.dispose(); + }); + } + } + +} diff --git a/windows/build.gradle.kts b/windows/build.gradle.kts index 4489cdc7..087cde2d 100644 --- a/windows/build.gradle.kts +++ b/windows/build.gradle.kts @@ -1,3 +1,5 @@ + + plugins { java id("dev.nokee.jni-library") @@ -13,7 +15,6 @@ library { jvmImplementation(projects.darklafPlatformBase) jvmImplementation(projects.darklafTheme) jvmImplementation(projects.darklafPropertyLoader) - jvmLibImplementation(libs.jna) } targetMachines.addAll(machines.windows.x86, machines.windows.x86_64) diff --git a/windows/src/main/cpp/Decorations.cpp b/windows/src/main/cpp/Decorations.cpp index 78e905df..81f57bbb 100644 --- a/windows/src/main/cpp/Decorations.cpp +++ b/windows/src/main/cpp/Decorations.cpp @@ -24,6 +24,8 @@ */ #include "Decorations.h" #include "com_github_weisj_darklaf_platform_windows_JNIDecorationsWindows.h" +#include +#include #ifndef WM_NCUAHDRAWCAPTION #define WM_NCUAHDRAWCAPTION (0x00AE) @@ -459,3 +461,63 @@ Java_com_github_weisj_darklaf_platform_windows_JNIDecorationsWindows_restore(JNI HWND handle = reinterpret_cast(hwnd); ShowWindow(handle, SW_RESTORE); } + +HMODULE _hAWT = 0; + +JNIEXPORT jlong JNICALL +Java_com_github_weisj_darklaf_platform_windows_JNIDecorationsWindows_getWindowHWND(JNIEnv *env, jclass, jobject window) { + HWND hWnd = 0; + typedef jboolean (JNICALL *PJAWT_GETAWT)(JNIEnv*, JAWT*); + JAWT awt; + JAWT_DrawingSurface* ds; + JAWT_DrawingSurfaceInfo* dsi; + JAWT_Win32DrawingSurfaceInfo* dsi_win; + jboolean result; + jint lock; + + //Load AWT Library + if(!_hAWT) { + _hAWT = LoadLibrary("jawt.dll"); + } + if (!_hAWT) { + return -7; + } + + PJAWT_GETAWT JAWT_GetAWT = (PJAWT_GETAWT)GetProcAddress(_hAWT, "JAWT_GetAWT"); + if (!JAWT_GetAWT) { + return -6; + } + + awt.version = JAWT_VERSION_1_4; // Init here with JAWT_VERSION_1_3 or JAWT_VERSION_1_4 + //Get AWT API Interface + result = JAWT_GetAWT(env, &awt); + if (result == JNI_FALSE) { + return -5; + } + + ds = awt.GetDrawingSurface(env, window); + if (ds == NULL) { + return -4; + } + + lock = ds->Lock(ds); + if((lock & JAWT_LOCK_ERROR) == 0) { + dsi = ds->GetDrawingSurfaceInfo(ds); + if(dsi) { + dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo; + if(dsi_win) { + hWnd = dsi_win->hwnd; + } else { + hWnd = (HWND) -1; + } + ds->FreeDrawingSurfaceInfo(dsi); + } else { + hWnd = (HWND) -2; + } + ds->Unlock(ds); + } else { + hWnd = (HWND) -3; + } + awt.FreeDrawingSurface(ds); + return reinterpret_cast(hWnd); +} diff --git a/windows/src/main/java/com/github/weisj/darklaf/platform/windows/JNIDecorationsWindows.java b/windows/src/main/java/com/github/weisj/darklaf/platform/windows/JNIDecorationsWindows.java index de09b0be..f956b09b 100644 --- a/windows/src/main/java/com/github/weisj/darklaf/platform/windows/JNIDecorationsWindows.java +++ b/windows/src/main/java/com/github/weisj/darklaf/platform/windows/JNIDecorationsWindows.java @@ -21,9 +21,13 @@ */ package com.github.weisj.darklaf.platform.windows; +import java.awt.Window; + /** @author Jannis Weis */ public final class JNIDecorationsWindows { + public static native long getWindowHWND(final Window window); + public static native void updateValues(final long hwnd, final int left, final int right, final int height); public static native void setResizable(final long hwnd, final boolean resizable); diff --git a/windows/src/main/java/com/github/weisj/darklaf/platform/windows/PointerUtil.java b/windows/src/main/java/com/github/weisj/darklaf/platform/windows/PointerUtil.java index 6a1cfb9f..71784a81 100644 --- a/windows/src/main/java/com/github/weisj/darklaf/platform/windows/PointerUtil.java +++ b/windows/src/main/java/com/github/weisj/darklaf/platform/windows/PointerUtil.java @@ -25,8 +25,6 @@ import java.awt.*; import javax.swing.*; -import com.sun.jna.Native; - public final class PointerUtil { /** @@ -37,6 +35,6 @@ public final class PointerUtil { */ public static long getHWND(final Component component) { Window window = component instanceof Window ? (Window) component : SwingUtilities.getWindowAncestor(component); - return Native.getWindowID(window); + return JNIDecorationsWindows.getWindowHWND(window); // Native.getWindowID(window); } }