From 22cf0ca995ff13015856a3801d1aa962fe0786de Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 29 Jun 2025 20:45:48 +0800 Subject: [PATCH 001/128] refactor: use glfw mouse passthrough --- core/src/cn/harryh/arkpets/ArkPets.java | 3 ++- .../cn/harryh/arkpets/platform/HWndCtrl.java | 21 +++++++++++++------ .../harryh/arkpets/platform/NullHWndCtrl.java | 8 ------- .../arkpets/platform/User32HWndCtrl.java | 16 -------------- 4 files changed, 17 insertions(+), 31 deletions(-) diff --git a/core/src/cn/harryh/arkpets/ArkPets.java b/core/src/cn/harryh/arkpets/ArkPets.java index 37c77c54..a07a8b50 100644 --- a/core/src/cn/harryh/arkpets/ArkPets.java +++ b/core/src/cn/harryh/arkpets/ArkPets.java @@ -14,6 +14,7 @@ import cn.harryh.arkpets.utils.*; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Pixmap; @@ -100,7 +101,7 @@ public void create() { // 5.Window style setup hWndMine = WindowSystem.findWindow(null, APP_TITLE); - hWndMine.setLayered(true); + hWndMine.attachGLFWWindow((Lwjgl3Graphics) Gdx.graphics); if (config.window_style_topmost) hWndMine.setTopmost(true); updateWindow(); diff --git a/core/src/cn/harryh/arkpets/platform/HWndCtrl.java b/core/src/cn/harryh/arkpets/platform/HWndCtrl.java index 83f2e62f..83bf60de 100644 --- a/core/src/cn/harryh/arkpets/platform/HWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/HWndCtrl.java @@ -3,6 +3,9 @@ */ package cn.harryh.arkpets.platform; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics; +import org.lwjgl.glfw.GLFW; + import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -15,6 +18,7 @@ public abstract class HWndCtrl { public final int posRight; public final int windowWidth; public final int windowHeight; + protected long glfwHandle; public HWndCtrl(String windowText, WindowRect windowRect) { this.windowText = windowText; @@ -77,11 +81,6 @@ public float getCenterY() { */ public abstract void setTaskbar(boolean enable); - /** Sets the window's layered style. - * @param enable Whether to enable the window's layered style. - */ - public abstract void setLayered(boolean enable); - /** Sets the window's topmost style. * @param enable Whether to enable the topmost style. */ @@ -90,7 +89,10 @@ public float getCenterY() { /** Sets the window's ability to be passed through. * @param enable Whether the window can be passed through. */ - public abstract void setTransparent(boolean enable); + public void setTransparent(boolean enable) { + if (glfwHandle == 0) return; + GLFW.glfwSetWindowAttrib(glfwHandle, GLFW.GLFW_MOUSE_PASSTHROUGH, enable ? 1 : 0); + } /** Sends a mouse event message to the window. * @param msg The window message value. @@ -99,6 +101,13 @@ public float getCenterY() { */ public abstract void sendMouseEvent(MouseEvent msg, int x, int y); + /** Attach a GLFW window handle to the window. + * @param graphics The Lwjgl3Graphics instance. + */ + public void attachGLFWWindow(Lwjgl3Graphics graphics) { + this.glfwHandle = graphics.getWindow().getWindowHandle(); + } + @Override public abstract boolean equals(Object o); diff --git a/core/src/cn/harryh/arkpets/platform/NullHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/NullHWndCtrl.java index b191f343..79d5160f 100644 --- a/core/src/cn/harryh/arkpets/platform/NullHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/NullHWndCtrl.java @@ -41,18 +41,10 @@ public void setWindowPosition(HWndCtrl insertAfter, int x, int y, int w, int h) public void setTaskbar(boolean enable) { } - @Override - public void setLayered(boolean enable) { - } - @Override public void setTopmost(boolean enable) { } - @Override - public void setTransparent(boolean enable) { - } - @Override public void sendMouseEvent(MouseEvent msg, int x, int y) { } diff --git a/core/src/cn/harryh/arkpets/platform/User32HWndCtrl.java b/core/src/cn/harryh/arkpets/platform/User32HWndCtrl.java index 46b26b4a..ac061d1b 100644 --- a/core/src/cn/harryh/arkpets/platform/User32HWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/User32HWndCtrl.java @@ -95,14 +95,6 @@ public void setTaskbar(boolean enable) { setWindowExStyle((getWindowExStyle() | User32HWndCtrl.WS_EX_TOOLWINDOW) & ~User32HWndCtrl.WS_EX_APPWINDOW); } - @Override - public void setLayered(boolean enable) { - if (enable) - setWindowExStyle(getWindowExStyle() | User32HWndCtrl.WS_EX_LAYERED); - else - setWindowExStyle(getWindowExStyle() & ~User32HWndCtrl.WS_EX_LAYERED); - } - @Override public void setTopmost(boolean enable) { if (enable) @@ -111,14 +103,6 @@ public void setTopmost(boolean enable) { setWindowExStyle(getWindowExStyle() & ~User32HWndCtrl.WS_EX_TOPMOST); } - @Override - public void setTransparent(boolean enable) { - if (enable) - setWindowExStyle(getWindowExStyle() | User32HWndCtrl.WS_EX_TRANSPARENT); - else - setWindowExStyle(getWindowExStyle() & ~User32HWndCtrl.WS_EX_TRANSPARENT); - } - @Override public void sendMouseEvent(MouseEvent msg, int x, int y) { int wmsg = switch (msg) { From 61a7359ad9a2b200af27d678d6f4c55588515374 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 8 Jun 2025 12:36:17 +0800 Subject: [PATCH 002/128] refactor: QuartzHWndCtrl update --- .../arkpets/platform/QuartzHWndCtrl.java | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java index 4ed2f5e5..17358e85 100644 --- a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java @@ -3,7 +3,8 @@ import cn.harryh.arkpets.Const; import cn.harryh.arkpets.natives.CoreGraphics; import cn.harryh.arkpets.natives.ObjCHelper; -import com.sun.jna.Platform; +import com.sun.jna.Memory; +import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.platform.mac.CoreFoundation; import com.sun.jna.platform.mac.CoreFoundation.CFArrayRef; @@ -26,7 +27,7 @@ public class QuartzHWndCtrl extends HWndCtrl { private final long windowID; private Pointer nsWin; - private Pointer nsScreen; + private CGRect currentScreenRect; private final long layer; // 0:Uncheck 1:Checked,Available -1:Checked,Unavailable private byte nsWinUnavailable; @@ -58,19 +59,22 @@ public boolean close(int timeout) { @Override public HWndCtrl updated() { - //todo - /*QuartzHWndCtrl hwnd = null; - CFIndex index = new CFIndex(1); - LongByReference wid = new LongByReference(windowID); - CFArrayRef arr = CFExt.INSTANCE.CFArrayCreate(null,new Pointer[] {wid.getPointer()},index,null); + QuartzHWndCtrl hwnd; + CoreFoundation.CFIndex index = new CoreFoundation.CFIndex(1); + Memory carr = new Memory(Native.getNativeSize(Integer.class)); + carr.write(0,new int[] {(int) windowID},0,1); + CFArrayRef arr = CoreFoundation.INSTANCE.CFArrayCreate(null,carr,index,null); if (arr != null) { CFArrayRef win = CoreGraphics.INSTANCE.CGWindowListCreateDescriptionFromArray(arr); arr.release(); CFDictionaryRef dict = new CFDictionaryRef(win.getValueAtIndex(0)); hwnd=new QuartzHWndCtrl(dict); win.release(); - }*/ - return new NullHWndCtrl(); + carr.close(); + return hwnd; + } else { + return new NullHWndCtrl(); + } } @Override @@ -85,9 +89,8 @@ public void setForeground() { @Override public void setWindowPosition(HWndCtrl insertAfter, int x, int y, int w, int h) { getNSWindow(windowID); - CGRect rect = getScreenSize(); newRect.origin.x = x; - newRect.origin.y = rect.size.height - y - h; + newRect.origin.y = currentScreenRect.size.height - y - h; newRect.size.width = w; newRect.size.height = h; ObjCHelper.msgSend.invokeVoid(new Object[]{ @@ -242,6 +245,7 @@ private void getNSWindow(long CGWindowId) { this.nsWin = nswin; nsWinUnavailable = 1; registerMethods(nsWin); + currentScreenRect = getScreenSize(); } } @@ -261,14 +265,6 @@ private void registerMethods(Pointer nsWin) { }); } - private void getNSScreen() { - if (this.nsWinUnavailable != 1 || this.nsScreen != null) return; - this.nsScreen = ObjCHelper.msgSend.invokePointer(new Object[]{ - nsWin, - ObjCHelper.sel("screen") - }); - } - private static String getWindowName(Pointer value) { return value == null ? "" : new CFStringRef(value).stringValue(); } @@ -299,7 +295,10 @@ private static WindowRect getWindowRect(Pointer value) { } private CGRect getScreenSize() { - getNSScreen(); + Pointer nsScreen = ObjCHelper.msgSend.invokePointer(new Object[]{ + nsWin, + ObjCHelper.sel("screen") + }); if (Const.isARM) { return (CGRect.ByValue) ObjCHelper.msgSend.invoke(CGRect.ByValue.class, new Object[]{ nsScreen, From 7bfa8d2a76578a78c74ad9308eb8cab9a39d8ac3 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 8 Jun 2025 13:16:01 +0800 Subject: [PATCH 003/128] chore: QuartzHWndCtrl foreground --- core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java index 17358e85..b05b5ae9 100644 --- a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java @@ -42,8 +42,11 @@ public QuartzHWndCtrl(CFDictionaryRef dict) { @Override public boolean isForeground() { - //todo - return true; + getNSWindow(windowID); + return ObjCHelper.msgSend.invokeInt(new Object[]{ + nsWin, + ObjCHelper.sel("isKeyWindow") + }) == 1; } @Override From 4867ade175e4e9a1c45e648bdf0f14a91f2ee42f Mon Sep 17 00:00:00 2001 From: litwak913 Date: Mon, 9 Jun 2025 21:50:03 +0800 Subject: [PATCH 004/128] docs: add platform support --- docs/Platforms.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 docs/Platforms.md diff --git a/docs/Platforms.md b/docs/Platforms.md new file mode 100644 index 00000000..d5be142a --- /dev/null +++ b/docs/Platforms.md @@ -0,0 +1,12 @@ +# 平台支持情况 + +图例:✅: 支持 ❌️: 不支持 + +| 平台/功能 | 基本功能渲染 | 窗口感知 | 窗口移动 | 窗口属性 | 事件穿透 | 后台模式 | +|-------------------|--------|------|------|------|------|------| +| Windows | ✅️ | ✅️ | ✅️ | ✅️ | ✅️ | ✅️ | +| macOS (Quartz) | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ✅️ | +| X11 | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ✅️ | +| GNOME (Mutter) | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ❌️ | +| KDE Plasma (KWin) | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ✅️ | + From c12e5542d13da9d295bd4cfca6100d0fb8a34747 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 15 Jun 2025 20:48:56 +0800 Subject: [PATCH 005/128] feat: wayland transparent mode --- core/src/cn/harryh/arkpets/ArkPets.java | 8 +++ .../harryh/arkpets/natives/WaylandClient.java | 34 ++++++++++ .../harryh/arkpets/natives/WaylandHelper.java | 68 +++++++++++++++++++ .../harryh/arkpets/platform/KWinHWndCtrl.java | 16 ++++- .../arkpets/platform/MutterHWndCtrl.java | 16 ++++- .../harryh/arkpets/platform/WaylandHWnd.java | 8 +++ docs/Platforms.md | 14 ++-- 7 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 core/src/cn/harryh/arkpets/natives/WaylandClient.java create mode 100644 core/src/cn/harryh/arkpets/natives/WaylandHelper.java create mode 100644 core/src/cn/harryh/arkpets/platform/WaylandHWnd.java diff --git a/core/src/cn/harryh/arkpets/ArkPets.java b/core/src/cn/harryh/arkpets/ArkPets.java index 37c77c54..4c55f8a7 100644 --- a/core/src/cn/harryh/arkpets/ArkPets.java +++ b/core/src/cn/harryh/arkpets/ArkPets.java @@ -8,16 +8,19 @@ import cn.harryh.arkpets.animations.GeneralBehavior; import cn.harryh.arkpets.concurrent.SocketClient; import cn.harryh.arkpets.platform.HWndCtrl; +import cn.harryh.arkpets.platform.WaylandHWnd; import cn.harryh.arkpets.platform.WindowSystem; import cn.harryh.arkpets.transitions.TransitionVector2; import cn.harryh.arkpets.tray.MemberTrayImpl; import cn.harryh.arkpets.utils.*; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.PixmapIO; +import com.sun.jna.Pointer; import java.util.HashMap; import java.util.List; @@ -25,6 +28,7 @@ import java.util.regex.Pattern; import static cn.harryh.arkpets.Const.coreTitleManager; +import static org.lwjgl.glfw.GLFWNativeWayland.glfwGetWaylandWindow; public class ArkPets extends InputApplicationAdaptor { @@ -104,6 +108,10 @@ public void create() { if (config.window_style_topmost) hWndMine.setTopmost(true); updateWindow(); + if (hWndMine instanceof WaylandHWnd wlHWnd) { + long glfwHandle = ((Lwjgl3Graphics) (Gdx.graphics)).getWindow().getWindowHandle(); + wlHWnd.setSurface(new Pointer(glfwGetWaylandWindow(glfwHandle))); + } // 6.Tray icon setup tray = new MemberTrayImpl(this, new SocketClient()); diff --git a/core/src/cn/harryh/arkpets/natives/WaylandClient.java b/core/src/cn/harryh/arkpets/natives/WaylandClient.java new file mode 100644 index 00000000..2e48fb34 --- /dev/null +++ b/core/src/cn/harryh/arkpets/natives/WaylandClient.java @@ -0,0 +1,34 @@ +package cn.harryh.arkpets.natives; + +import com.sun.jna.*; + + +public interface WaylandClient extends Library { + WaylandClient INSTANCE = Native.load("wayland-client", WaylandClient.class); + + int wl_display_dispatch(Pointer display); + + int wl_display_roundtrip(Pointer display); + + int wl_proxy_get_version(Pointer proxy); + + Pointer wl_proxy_marshal_flags(Pointer proxy, int opcode, Pointer iface, int version, int flags, Object... obj); + + int wl_proxy_add_listener(Pointer proxy, Pointer implementation, Pointer data); + + void wl_proxy_destroy(Pointer compositor); + + @Structure.FieldOrder({"global", "global_remove"}) + class wl_registry_listener extends Structure { + public GlobalCallback global; + public GlobalRemoveCallback global_remove; + } + + interface GlobalCallback extends Callback { + void callback(Pointer data, Pointer registry, int name, String iface, int version); + } + + interface GlobalRemoveCallback extends Callback { + void callback(Pointer data, Pointer registry, int name); + } +} diff --git a/core/src/cn/harryh/arkpets/natives/WaylandHelper.java b/core/src/cn/harryh/arkpets/natives/WaylandHelper.java new file mode 100644 index 00000000..7a6bbbc7 --- /dev/null +++ b/core/src/cn/harryh/arkpets/natives/WaylandHelper.java @@ -0,0 +1,68 @@ +package cn.harryh.arkpets.natives; + +import cn.harryh.arkpets.utils.Logger; +import com.sun.jna.NativeLibrary; +import com.sun.jna.Pointer; +import org.lwjgl.glfw.GLFWNativeWayland; + + +public class WaylandHelper { + private static boolean ready; + private static boolean unavailable; + private static WaylandClient.wl_registry_listener listener; // Prevent callback + private static Pointer compositor; + private static int compositorVer; + + private static Pointer wl_compositor_interface; + private static Pointer wl_region_interface; + + private static void init() { + NativeLibrary lib = NativeLibrary.getInstance("wayland-client"); + Pointer wl_registry_interface = lib.getGlobalVariableAddress("wl_registry_interface"); + wl_compositor_interface = lib.getGlobalVariableAddress("wl_compositor_interface"); + wl_region_interface = lib.getGlobalVariableAddress("wl_region_interface"); + Pointer display = new Pointer(GLFWNativeWayland.glfwGetWaylandDisplay()); + int ver = WaylandClient.INSTANCE.wl_proxy_get_version(display); + Pointer reg = WaylandClient.INSTANCE.wl_proxy_marshal_flags(display, 1, wl_registry_interface, ver, 0, (Object) null); + listener = new WaylandClient.wl_registry_listener(); + listener.global = (data, registry, name, iface, version) -> { + if (iface.equals("wl_compositor")) { + compositor = WaylandClient.INSTANCE.wl_proxy_marshal_flags(registry, 0, + wl_compositor_interface, 4, 0, name, "wl_compositor", 4, null); + compositorVer = WaylandClient.INSTANCE.wl_proxy_get_version(compositor); + } + }; + listener.global_remove = (data, registry, name) -> { + if (compositor != null) { + WaylandClient.INSTANCE.wl_proxy_destroy(compositor); + compositor = null; + } + }; + listener.write(); + WaylandClient.INSTANCE.wl_proxy_add_listener(reg, listener.getPointer(), null); + WaylandClient.INSTANCE.wl_display_dispatch(display); + WaylandClient.INSTANCE.wl_display_roundtrip(display); + if (compositor == null) { + Logger.warn("System", "Failed to bind wl_compositor"); + unavailable = true; + return; + } + ready = true; + } + + public static void setTransparent(Pointer surface, boolean enable) { + if (unavailable) return; + if (!ready) init(); + int surfaceVer = WaylandClient.INSTANCE.wl_proxy_get_version(surface); + if (enable) { + Pointer region = WaylandClient.INSTANCE.wl_proxy_marshal_flags(compositor, 1, wl_region_interface, compositorVer, 0, (Object) null); + int regionVer = WaylandClient.INSTANCE.wl_proxy_get_version(region); + WaylandClient.INSTANCE.wl_proxy_marshal_flags(surface, 5, null, surfaceVer, 0, region); + WaylandClient.INSTANCE.wl_proxy_marshal_flags(surface, 6, null, surfaceVer, 0); + WaylandClient.INSTANCE.wl_proxy_marshal_flags(region, 0, null, regionVer, 1); + } else { + WaylandClient.INSTANCE.wl_proxy_marshal_flags(surface, 5, null, surfaceVer, 0, (Object) null); + WaylandClient.INSTANCE.wl_proxy_marshal_flags(surface, 6, null, surfaceVer, 0); + } + } +} diff --git a/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java index 7cc41d2b..2cb62632 100644 --- a/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java @@ -3,7 +3,9 @@ import cn.harryh.arkpets.Const; import cn.harryh.arkpets.natives.KWinInterface; import cn.harryh.arkpets.natives.KWinPluginInterface; +import cn.harryh.arkpets.natives.WaylandHelper; import cn.harryh.arkpets.utils.Logger; +import com.sun.jna.Pointer; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder; import org.freedesktop.dbus.exceptions.DBusException; @@ -15,12 +17,15 @@ import java.util.List; -public class KWinHWndCtrl extends HWndCtrl { +public class KWinHWndCtrl extends HWndCtrl implements WaylandHWnd { protected final String hWnd; protected KWinInterface.DetailsStruct details; private static DBusConnection dBusConnection; private static KWinInterface dBusInterface; + private boolean isTransparent; + private Pointer surface; + protected KWinHWndCtrl(KWinInterface.DetailsStruct details) { super(details.title, new WindowRect(details.y, details.y + details.h.intValue(), details.x, details.x + details.w.intValue())); this.hWnd = details.id; @@ -59,7 +64,10 @@ public void setWindowPosition(HWndCtrl insertAfter, int x, int y, int w, int h) @Override public void setTransparent(boolean enable) { - + if (isTransparent != enable) { + WaylandHelper.setTransparent(surface, enable); + isTransparent = enable; + } } @Override @@ -82,6 +90,10 @@ public void sendMouseEvent(MouseEvent msg, int x, int y) { } + public void setSurface(Pointer surface) { + this.surface = surface; + } + protected static void init() { try { dBusConnection = DBusConnectionBuilder.forSessionBus().build(); diff --git a/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java index 872e35f3..c148865c 100644 --- a/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java @@ -3,7 +3,9 @@ import cn.harryh.arkpets.Const; import cn.harryh.arkpets.natives.MutterInterface; import cn.harryh.arkpets.natives.MutterPluginInterface; +import cn.harryh.arkpets.natives.WaylandHelper; import cn.harryh.arkpets.utils.Logger; +import com.sun.jna.Pointer; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder; import org.freedesktop.dbus.exceptions.DBusException; @@ -17,12 +19,15 @@ import java.util.Map; -public class MutterHWndCtrl extends HWndCtrl { +public class MutterHWndCtrl extends HWndCtrl implements WaylandHWnd{ protected final UInt32 hWnd; protected MutterInterface.DetailsStruct details; private static DBusConnection dBusConnection; private static MutterInterface dBusInterface; + private boolean isTransparent; + private Pointer surface; + protected MutterHWndCtrl(MutterInterface.DetailsStruct details) { super(details.title, new WindowRect(details.y, details.y + details.h.intValue(), details.x, details.x + details.w.intValue())); this.hWnd = details.id; @@ -61,7 +66,10 @@ public void setWindowPosition(HWndCtrl insertAfter, int x, int y, int w, int h) @Override public void setTransparent(boolean enable) { - + if (isTransparent != enable) { + WaylandHelper.setTransparent(surface, enable); + isTransparent = enable; + } } @Override @@ -84,6 +92,10 @@ public void sendMouseEvent(MouseEvent msg, int x, int y) { } + public void setSurface(Pointer surface) { + this.surface = surface; + } + protected static void init() { try { dBusConnection = DBusConnectionBuilder.forSessionBus().build(); diff --git a/core/src/cn/harryh/arkpets/platform/WaylandHWnd.java b/core/src/cn/harryh/arkpets/platform/WaylandHWnd.java new file mode 100644 index 00000000..2f5881c3 --- /dev/null +++ b/core/src/cn/harryh/arkpets/platform/WaylandHWnd.java @@ -0,0 +1,8 @@ +package cn.harryh.arkpets.platform; + +import com.sun.jna.Pointer; + + +public interface WaylandHWnd { + void setSurface(Pointer surface); +} diff --git a/docs/Platforms.md b/docs/Platforms.md index d5be142a..de35a6a4 100644 --- a/docs/Platforms.md +++ b/docs/Platforms.md @@ -2,11 +2,11 @@ 图例:✅: 支持 ❌️: 不支持 -| 平台/功能 | 基本功能渲染 | 窗口感知 | 窗口移动 | 窗口属性 | 事件穿透 | 后台模式 | -|-------------------|--------|------|------|------|------|------| -| Windows | ✅️ | ✅️ | ✅️ | ✅️ | ✅️ | ✅️ | -| macOS (Quartz) | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ✅️ | -| X11 | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ✅️ | -| GNOME (Mutter) | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ❌️ | -| KDE Plasma (KWin) | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ✅️ | +| 平台/功能 | 基本渲染 | 窗口感知 | 窗口移动 | 窗口属性 | 事件穿透 | 透明模式 | 后台模式 | +|-------------------|------|------|------|------|------|------|------| +| Windows | ✅️ | ✅️ | ✅️ | ✅️ | ✅️ | ✅️ | ✅️ | +| macOS (Quartz) | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ✅️ | ✅️ | +| X11 | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ✅️ | ✅️ | +| GNOME (Mutter) | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ✅️ | ❌️ | +| KDE Plasma (KWin) | ✅️ | ✅️ | ✅️ | ✅️ | ❌️ | ✅️ | ✅️ | From b719ab6db07b7f7c41a8a4d278d7d66561d1e4be Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 15 Jun 2025 23:11:06 +0800 Subject: [PATCH 006/128] refactor: init surface --- core/src/cn/harryh/arkpets/ArkPets.java | 7 +------ core/src/cn/harryh/arkpets/platform/WaylandHWnd.java | 8 ++++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/src/cn/harryh/arkpets/ArkPets.java b/core/src/cn/harryh/arkpets/ArkPets.java index 4c55f8a7..ae199639 100644 --- a/core/src/cn/harryh/arkpets/ArkPets.java +++ b/core/src/cn/harryh/arkpets/ArkPets.java @@ -20,7 +20,6 @@ import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.PixmapIO; -import com.sun.jna.Pointer; import java.util.HashMap; import java.util.List; @@ -28,7 +27,6 @@ import java.util.regex.Pattern; import static cn.harryh.arkpets.Const.coreTitleManager; -import static org.lwjgl.glfw.GLFWNativeWayland.glfwGetWaylandWindow; public class ArkPets extends InputApplicationAdaptor { @@ -108,10 +106,7 @@ public void create() { if (config.window_style_topmost) hWndMine.setTopmost(true); updateWindow(); - if (hWndMine instanceof WaylandHWnd wlHWnd) { - long glfwHandle = ((Lwjgl3Graphics) (Gdx.graphics)).getWindow().getWindowHandle(); - wlHWnd.setSurface(new Pointer(glfwGetWaylandWindow(glfwHandle))); - } + if (hWndMine instanceof WaylandHWnd wlHWnd) wlHWnd.initSurface((Lwjgl3Graphics) Gdx.graphics); // 6.Tray icon setup tray = new MemberTrayImpl(this, new SocketClient()); diff --git a/core/src/cn/harryh/arkpets/platform/WaylandHWnd.java b/core/src/cn/harryh/arkpets/platform/WaylandHWnd.java index 2f5881c3..08d56da1 100644 --- a/core/src/cn/harryh/arkpets/platform/WaylandHWnd.java +++ b/core/src/cn/harryh/arkpets/platform/WaylandHWnd.java @@ -1,8 +1,16 @@ package cn.harryh.arkpets.platform; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics; import com.sun.jna.Pointer; +import static org.lwjgl.glfw.GLFWNativeWayland.glfwGetWaylandWindow; + public interface WaylandHWnd { + default void initSurface(Lwjgl3Graphics graphics) { + long glfwHandle = graphics.getWindow().getWindowHandle(); + setSurface(new Pointer(glfwGetWaylandWindow(glfwHandle))); + } void setSurface(Pointer surface); } + From 61f40c6f8c60b8cf1307627e3a05b01904c9b103 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sat, 21 Jun 2025 23:53:13 +0800 Subject: [PATCH 007/128] refactor: screen height --- core/src/cn/harryh/arkpets/natives/CoreGraphics.java | 4 ++++ core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/src/cn/harryh/arkpets/natives/CoreGraphics.java b/core/src/cn/harryh/arkpets/natives/CoreGraphics.java index 813ab7df..1db393ca 100644 --- a/core/src/cn/harryh/arkpets/natives/CoreGraphics.java +++ b/core/src/cn/harryh/arkpets/natives/CoreGraphics.java @@ -31,6 +31,10 @@ public interface CoreGraphics extends Library { CFDictionaryRef CGSessionCopyCurrentDictionary(); + int CGMainDisplayID(); + + CGRect.ByValue CGDisplayBounds(int display); + @Structure.FieldOrder({"origin", "size"}) class CGRect extends Structure { diff --git a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java index b05b5ae9..ebf452e1 100644 --- a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java @@ -298,7 +298,7 @@ private static WindowRect getWindowRect(Pointer value) { } private CGRect getScreenSize() { - Pointer nsScreen = ObjCHelper.msgSend.invokePointer(new Object[]{ + /*Pointer nsScreen = ObjCHelper.msgSend.invokePointer(new Object[]{ nsWin, ObjCHelper.sel("screen") }); @@ -315,7 +315,8 @@ private CGRect getScreenSize() { ObjCHelper.sel("frame") }); return rect; - } + }*/ + return CoreGraphics.INSTANCE.CGDisplayBounds(CoreGraphics.INSTANCE.CGMainDisplayID()); } private class IgnoreMouseCallback implements ObjCHelper.ThreadCallback { From e47842bb6bc37038d7b23925a5ef9cc229d65976 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 22 Jun 2025 00:28:21 +0800 Subject: [PATCH 008/128] refactor: wayland client --- .../harryh/arkpets/natives/WaylandClient.java | 17 +++++++++++ .../harryh/arkpets/natives/WaylandHelper.java | 28 ++++++------------- .../arkpets/natives/WaylandInterface.java | 18 ++++++++++++ 3 files changed, 43 insertions(+), 20 deletions(-) create mode 100644 core/src/cn/harryh/arkpets/natives/WaylandInterface.java diff --git a/core/src/cn/harryh/arkpets/natives/WaylandClient.java b/core/src/cn/harryh/arkpets/natives/WaylandClient.java index 2e48fb34..6b3bea1a 100644 --- a/core/src/cn/harryh/arkpets/natives/WaylandClient.java +++ b/core/src/cn/harryh/arkpets/natives/WaylandClient.java @@ -18,6 +18,23 @@ public interface WaylandClient extends Library { void wl_proxy_destroy(Pointer compositor); + default void wl_region_destroy(Pointer wl_region) { + wl_proxy_marshal_flags(wl_region, 0, null, wl_proxy_get_version(wl_region), 1); + } + + default void wl_surface_set_input_region(Pointer wl_surface, Pointer wl_region) { + wl_proxy_marshal_flags(wl_surface, 5, null, wl_proxy_get_version(wl_surface), 0, wl_region); + } + + default void wl_surface_commit(Pointer wl_surface) { + WaylandClient.INSTANCE.wl_proxy_marshal_flags(wl_surface, 6, null, wl_proxy_get_version(wl_surface), 0); + } + + default Pointer wl_compositor_create_region(Pointer wl_compositor) { + Pointer reg = wl_proxy_marshal_flags(wl_compositor, 1, WaylandInterface.wl_region_interface, wl_proxy_get_version(wl_compositor), 0, (Object) null); + return reg; + } + @Structure.FieldOrder({"global", "global_remove"}) class wl_registry_listener extends Structure { public GlobalCallback global; diff --git a/core/src/cn/harryh/arkpets/natives/WaylandHelper.java b/core/src/cn/harryh/arkpets/natives/WaylandHelper.java index 7a6bbbc7..c1b1eb59 100644 --- a/core/src/cn/harryh/arkpets/natives/WaylandHelper.java +++ b/core/src/cn/harryh/arkpets/natives/WaylandHelper.java @@ -1,7 +1,6 @@ package cn.harryh.arkpets.natives; import cn.harryh.arkpets.utils.Logger; -import com.sun.jna.NativeLibrary; import com.sun.jna.Pointer; import org.lwjgl.glfw.GLFWNativeWayland; @@ -11,25 +10,16 @@ public class WaylandHelper { private static boolean unavailable; private static WaylandClient.wl_registry_listener listener; // Prevent callback private static Pointer compositor; - private static int compositorVer; - - private static Pointer wl_compositor_interface; - private static Pointer wl_region_interface; private static void init() { - NativeLibrary lib = NativeLibrary.getInstance("wayland-client"); - Pointer wl_registry_interface = lib.getGlobalVariableAddress("wl_registry_interface"); - wl_compositor_interface = lib.getGlobalVariableAddress("wl_compositor_interface"); - wl_region_interface = lib.getGlobalVariableAddress("wl_region_interface"); Pointer display = new Pointer(GLFWNativeWayland.glfwGetWaylandDisplay()); int ver = WaylandClient.INSTANCE.wl_proxy_get_version(display); - Pointer reg = WaylandClient.INSTANCE.wl_proxy_marshal_flags(display, 1, wl_registry_interface, ver, 0, (Object) null); + Pointer reg = WaylandClient.INSTANCE.wl_proxy_marshal_flags(display, 1, WaylandInterface.wl_registry_interface, ver, 0, (Object) null); listener = new WaylandClient.wl_registry_listener(); listener.global = (data, registry, name, iface, version) -> { if (iface.equals("wl_compositor")) { compositor = WaylandClient.INSTANCE.wl_proxy_marshal_flags(registry, 0, - wl_compositor_interface, 4, 0, name, "wl_compositor", 4, null); - compositorVer = WaylandClient.INSTANCE.wl_proxy_get_version(compositor); + WaylandInterface.wl_compositor_interface, version, 0, name, "wl_compositor", version, null); } }; listener.global_remove = (data, registry, name) -> { @@ -53,16 +43,14 @@ private static void init() { public static void setTransparent(Pointer surface, boolean enable) { if (unavailable) return; if (!ready) init(); - int surfaceVer = WaylandClient.INSTANCE.wl_proxy_get_version(surface); if (enable) { - Pointer region = WaylandClient.INSTANCE.wl_proxy_marshal_flags(compositor, 1, wl_region_interface, compositorVer, 0, (Object) null); - int regionVer = WaylandClient.INSTANCE.wl_proxy_get_version(region); - WaylandClient.INSTANCE.wl_proxy_marshal_flags(surface, 5, null, surfaceVer, 0, region); - WaylandClient.INSTANCE.wl_proxy_marshal_flags(surface, 6, null, surfaceVer, 0); - WaylandClient.INSTANCE.wl_proxy_marshal_flags(region, 0, null, regionVer, 1); + Pointer region = WaylandClient.INSTANCE.wl_compositor_create_region(compositor); + WaylandClient.INSTANCE.wl_surface_set_input_region(surface, null); + WaylandClient.INSTANCE.wl_surface_commit(surface); + WaylandClient.INSTANCE.wl_region_destroy(region); } else { - WaylandClient.INSTANCE.wl_proxy_marshal_flags(surface, 5, null, surfaceVer, 0, (Object) null); - WaylandClient.INSTANCE.wl_proxy_marshal_flags(surface, 6, null, surfaceVer, 0); + WaylandClient.INSTANCE.wl_surface_set_input_region(surface, null); + WaylandClient.INSTANCE.wl_surface_commit(surface); } } } diff --git a/core/src/cn/harryh/arkpets/natives/WaylandInterface.java b/core/src/cn/harryh/arkpets/natives/WaylandInterface.java new file mode 100644 index 00000000..57eb4cc3 --- /dev/null +++ b/core/src/cn/harryh/arkpets/natives/WaylandInterface.java @@ -0,0 +1,18 @@ +package cn.harryh.arkpets.natives; + +import com.sun.jna.NativeLibrary; +import com.sun.jna.Pointer; + + +public class WaylandInterface { + public static final Pointer wl_registry_interface; + public static final Pointer wl_compositor_interface; + public static final Pointer wl_region_interface; + + static { + NativeLibrary lib = NativeLibrary.getInstance("wayland-client"); + wl_registry_interface = lib.getGlobalVariableAddress("wl_registry_interface"); + wl_compositor_interface = lib.getGlobalVariableAddress("wl_compositor_interface"); + wl_region_interface = lib.getGlobalVariableAddress("wl_region_interface"); + } +} From f4c994cb8ff573ea73880756faddba62b1f103e9 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 22 Jun 2025 15:00:59 +0800 Subject: [PATCH 009/128] refactor: wayland client and region --- core/src/cn/harryh/arkpets/natives/WaylandClient.java | 9 ++++++--- core/src/cn/harryh/arkpets/natives/WaylandHelper.java | 9 ++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/core/src/cn/harryh/arkpets/natives/WaylandClient.java b/core/src/cn/harryh/arkpets/natives/WaylandClient.java index 6b3bea1a..17662076 100644 --- a/core/src/cn/harryh/arkpets/natives/WaylandClient.java +++ b/core/src/cn/harryh/arkpets/natives/WaylandClient.java @@ -27,12 +27,15 @@ default void wl_surface_set_input_region(Pointer wl_surface, Pointer wl_region) } default void wl_surface_commit(Pointer wl_surface) { - WaylandClient.INSTANCE.wl_proxy_marshal_flags(wl_surface, 6, null, wl_proxy_get_version(wl_surface), 0); + wl_proxy_marshal_flags(wl_surface, 6, null, wl_proxy_get_version(wl_surface), 0); } default Pointer wl_compositor_create_region(Pointer wl_compositor) { - Pointer reg = wl_proxy_marshal_flags(wl_compositor, 1, WaylandInterface.wl_region_interface, wl_proxy_get_version(wl_compositor), 0, (Object) null); - return reg; + return wl_proxy_marshal_flags(wl_compositor, 1, WaylandInterface.wl_region_interface, wl_proxy_get_version(wl_compositor), 0, (Object) null); + } + + default Pointer wl_display_get_registry(Pointer wl_display) { + return wl_proxy_marshal_flags(wl_display, 1, WaylandInterface.wl_registry_interface, wl_proxy_get_version(wl_display), 0, (Object) null); } @Structure.FieldOrder({"global", "global_remove"}) diff --git a/core/src/cn/harryh/arkpets/natives/WaylandHelper.java b/core/src/cn/harryh/arkpets/natives/WaylandHelper.java index c1b1eb59..88a89d70 100644 --- a/core/src/cn/harryh/arkpets/natives/WaylandHelper.java +++ b/core/src/cn/harryh/arkpets/natives/WaylandHelper.java @@ -10,11 +10,11 @@ public class WaylandHelper { private static boolean unavailable; private static WaylandClient.wl_registry_listener listener; // Prevent callback private static Pointer compositor; + private static Pointer region; private static void init() { Pointer display = new Pointer(GLFWNativeWayland.glfwGetWaylandDisplay()); - int ver = WaylandClient.INSTANCE.wl_proxy_get_version(display); - Pointer reg = WaylandClient.INSTANCE.wl_proxy_marshal_flags(display, 1, WaylandInterface.wl_registry_interface, ver, 0, (Object) null); + Pointer reg = WaylandClient.INSTANCE.wl_display_get_registry(display); listener = new WaylandClient.wl_registry_listener(); listener.global = (data, registry, name, iface, version) -> { if (iface.equals("wl_compositor")) { @@ -37,6 +37,7 @@ private static void init() { unavailable = true; return; } + region = WaylandClient.INSTANCE.wl_compositor_create_region(compositor); ready = true; } @@ -44,10 +45,8 @@ public static void setTransparent(Pointer surface, boolean enable) { if (unavailable) return; if (!ready) init(); if (enable) { - Pointer region = WaylandClient.INSTANCE.wl_compositor_create_region(compositor); - WaylandClient.INSTANCE.wl_surface_set_input_region(surface, null); + WaylandClient.INSTANCE.wl_surface_set_input_region(surface, region); WaylandClient.INSTANCE.wl_surface_commit(surface); - WaylandClient.INSTANCE.wl_region_destroy(region); } else { WaylandClient.INSTANCE.wl_surface_set_input_region(surface, null); WaylandClient.INSTANCE.wl_surface_commit(surface); From dafb17dd990853c67a6f1ed122397fdde062bb24 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 22 Jun 2025 15:06:45 +0800 Subject: [PATCH 010/128] refactor: wayland hwndctrl --- core/src/cn/harryh/arkpets/ArkPets.java | 4 +-- .../harryh/arkpets/platform/KWinHWndCtrl.java | 19 +----------- .../arkpets/platform/MutterHWndCtrl.java | 19 +----------- .../harryh/arkpets/platform/WaylandHWnd.java | 16 ---------- .../arkpets/platform/WaylandHWndCtrl.java | 31 +++++++++++++++++++ 5 files changed, 35 insertions(+), 54 deletions(-) delete mode 100644 core/src/cn/harryh/arkpets/platform/WaylandHWnd.java create mode 100644 core/src/cn/harryh/arkpets/platform/WaylandHWndCtrl.java diff --git a/core/src/cn/harryh/arkpets/ArkPets.java b/core/src/cn/harryh/arkpets/ArkPets.java index ae199639..146de45b 100644 --- a/core/src/cn/harryh/arkpets/ArkPets.java +++ b/core/src/cn/harryh/arkpets/ArkPets.java @@ -8,7 +8,7 @@ import cn.harryh.arkpets.animations.GeneralBehavior; import cn.harryh.arkpets.concurrent.SocketClient; import cn.harryh.arkpets.platform.HWndCtrl; -import cn.harryh.arkpets.platform.WaylandHWnd; +import cn.harryh.arkpets.platform.WaylandHWndCtrl; import cn.harryh.arkpets.platform.WindowSystem; import cn.harryh.arkpets.transitions.TransitionVector2; import cn.harryh.arkpets.tray.MemberTrayImpl; @@ -106,7 +106,7 @@ public void create() { if (config.window_style_topmost) hWndMine.setTopmost(true); updateWindow(); - if (hWndMine instanceof WaylandHWnd wlHWnd) wlHWnd.initSurface((Lwjgl3Graphics) Gdx.graphics); + if (hWndMine instanceof WaylandHWndCtrl wlHWnd) wlHWnd.attachSurface((Lwjgl3Graphics) Gdx.graphics); // 6.Tray icon setup tray = new MemberTrayImpl(this, new SocketClient()); diff --git a/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java index 2cb62632..de8c5960 100644 --- a/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java @@ -3,9 +3,7 @@ import cn.harryh.arkpets.Const; import cn.harryh.arkpets.natives.KWinInterface; import cn.harryh.arkpets.natives.KWinPluginInterface; -import cn.harryh.arkpets.natives.WaylandHelper; import cn.harryh.arkpets.utils.Logger; -import com.sun.jna.Pointer; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder; import org.freedesktop.dbus.exceptions.DBusException; @@ -17,15 +15,12 @@ import java.util.List; -public class KWinHWndCtrl extends HWndCtrl implements WaylandHWnd { +public class KWinHWndCtrl extends WaylandHWndCtrl { protected final String hWnd; protected KWinInterface.DetailsStruct details; private static DBusConnection dBusConnection; private static KWinInterface dBusInterface; - private boolean isTransparent; - private Pointer surface; - protected KWinHWndCtrl(KWinInterface.DetailsStruct details) { super(details.title, new WindowRect(details.y, details.y + details.h.intValue(), details.x, details.x + details.w.intValue())); this.hWnd = details.id; @@ -62,14 +57,6 @@ public void setWindowPosition(HWndCtrl insertAfter, int x, int y, int w, int h) dBusInterface.MoveResize(hWnd, x, y, new UInt32(w), new UInt32(h)); } - @Override - public void setTransparent(boolean enable) { - if (isTransparent != enable) { - WaylandHelper.setTransparent(surface, enable); - isTransparent = enable; - } - } - @Override public void setTaskbar(boolean enable) { dBusInterface.Stick(hWnd, enable); @@ -90,10 +77,6 @@ public void sendMouseEvent(MouseEvent msg, int x, int y) { } - public void setSurface(Pointer surface) { - this.surface = surface; - } - protected static void init() { try { dBusConnection = DBusConnectionBuilder.forSessionBus().build(); diff --git a/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java index c148865c..2a3a7ec5 100644 --- a/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java @@ -3,9 +3,7 @@ import cn.harryh.arkpets.Const; import cn.harryh.arkpets.natives.MutterInterface; import cn.harryh.arkpets.natives.MutterPluginInterface; -import cn.harryh.arkpets.natives.WaylandHelper; import cn.harryh.arkpets.utils.Logger; -import com.sun.jna.Pointer; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder; import org.freedesktop.dbus.exceptions.DBusException; @@ -19,15 +17,12 @@ import java.util.Map; -public class MutterHWndCtrl extends HWndCtrl implements WaylandHWnd{ +public class MutterHWndCtrl extends WaylandHWndCtrl { protected final UInt32 hWnd; protected MutterInterface.DetailsStruct details; private static DBusConnection dBusConnection; private static MutterInterface dBusInterface; - private boolean isTransparent; - private Pointer surface; - protected MutterHWndCtrl(MutterInterface.DetailsStruct details) { super(details.title, new WindowRect(details.y, details.y + details.h.intValue(), details.x, details.x + details.w.intValue())); this.hWnd = details.id; @@ -64,14 +59,6 @@ public void setWindowPosition(HWndCtrl insertAfter, int x, int y, int w, int h) dBusInterface.MoveResize(hWnd, x, y, new UInt32(w), new UInt32(h)); } - @Override - public void setTransparent(boolean enable) { - if (isTransparent != enable) { - WaylandHelper.setTransparent(surface, enable); - isTransparent = enable; - } - } - @Override public void setTaskbar(boolean enable) { dBusInterface.Stick(hWnd, !enable); @@ -92,10 +79,6 @@ public void sendMouseEvent(MouseEvent msg, int x, int y) { } - public void setSurface(Pointer surface) { - this.surface = surface; - } - protected static void init() { try { dBusConnection = DBusConnectionBuilder.forSessionBus().build(); diff --git a/core/src/cn/harryh/arkpets/platform/WaylandHWnd.java b/core/src/cn/harryh/arkpets/platform/WaylandHWnd.java deleted file mode 100644 index 08d56da1..00000000 --- a/core/src/cn/harryh/arkpets/platform/WaylandHWnd.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.harryh.arkpets.platform; - -import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics; -import com.sun.jna.Pointer; - -import static org.lwjgl.glfw.GLFWNativeWayland.glfwGetWaylandWindow; - - -public interface WaylandHWnd { - default void initSurface(Lwjgl3Graphics graphics) { - long glfwHandle = graphics.getWindow().getWindowHandle(); - setSurface(new Pointer(glfwGetWaylandWindow(glfwHandle))); - } - void setSurface(Pointer surface); -} - diff --git a/core/src/cn/harryh/arkpets/platform/WaylandHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/WaylandHWndCtrl.java new file mode 100644 index 00000000..6f45092c --- /dev/null +++ b/core/src/cn/harryh/arkpets/platform/WaylandHWndCtrl.java @@ -0,0 +1,31 @@ +package cn.harryh.arkpets.platform; + +import cn.harryh.arkpets.natives.WaylandHelper; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics; +import com.sun.jna.Pointer; + +import static org.lwjgl.glfw.GLFWNativeWayland.glfwGetWaylandWindow; + + +public abstract class WaylandHWndCtrl extends HWndCtrl { + private boolean isTransparent; + private Pointer surface; + + public WaylandHWndCtrl(String windowText, WindowRect windowRect) { + super(windowText, windowRect); + } + + public void attachSurface(Lwjgl3Graphics graphics) { + long glfwHandle = graphics.getWindow().getWindowHandle(); + surface = new Pointer(glfwGetWaylandWindow(glfwHandle)); + } + + @Override + public void setTransparent(boolean enable) { + if (isTransparent != enable) { + WaylandHelper.setTransparent(surface, enable); + isTransparent = enable; + } + } +} + From add1200f1222deef2ac0a670788e54b3b7af4676 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 29 Jun 2025 22:21:03 +0800 Subject: [PATCH 011/128] refactor: attach window --- core/src/cn/harryh/arkpets/ArkPets.java | 2 + .../arkpets/platform/QuartzHWndCtrl.java | 54 +++++++++---------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/core/src/cn/harryh/arkpets/ArkPets.java b/core/src/cn/harryh/arkpets/ArkPets.java index 146de45b..c1452bb9 100644 --- a/core/src/cn/harryh/arkpets/ArkPets.java +++ b/core/src/cn/harryh/arkpets/ArkPets.java @@ -8,6 +8,7 @@ import cn.harryh.arkpets.animations.GeneralBehavior; import cn.harryh.arkpets.concurrent.SocketClient; import cn.harryh.arkpets.platform.HWndCtrl; +import cn.harryh.arkpets.platform.QuartzHWndCtrl; import cn.harryh.arkpets.platform.WaylandHWndCtrl; import cn.harryh.arkpets.platform.WindowSystem; import cn.harryh.arkpets.transitions.TransitionVector2; @@ -106,6 +107,7 @@ public void create() { if (config.window_style_topmost) hWndMine.setTopmost(true); updateWindow(); + if (hWndMine instanceof QuartzHWndCtrl qHWnd) qHWnd.attachNSWindow((Lwjgl3Graphics) Gdx.graphics); if (hWndMine instanceof WaylandHWndCtrl wlHWnd) wlHWnd.attachSurface((Lwjgl3Graphics) Gdx.graphics); // 6.Tray icon setup diff --git a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java index ebf452e1..f455b352 100644 --- a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java @@ -1,8 +1,9 @@ package cn.harryh.arkpets.platform; -import cn.harryh.arkpets.Const; import cn.harryh.arkpets.natives.CoreGraphics; import cn.harryh.arkpets.natives.ObjCHelper; +import cn.harryh.arkpets.utils.Cached; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics; import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.Pointer; @@ -17,6 +18,7 @@ import java.util.Objects; import static cn.harryh.arkpets.natives.CoreGraphics.*; +import static org.lwjgl.glfw.GLFWNativeCocoa.glfwGetCocoaWindow; public class QuartzHWndCtrl extends HWndCtrl { @@ -27,10 +29,9 @@ public class QuartzHWndCtrl extends HWndCtrl { private final long windowID; private Pointer nsWin; - private CGRect currentScreenRect; + private static Cached currentScreenRect; private final long layer; // 0:Uncheck 1:Checked,Available -1:Checked,Unavailable - private byte nsWinUnavailable; private boolean trans; private final CGRect.ByValue newRect = new CGRect.ByValue(); @@ -42,7 +43,7 @@ public QuartzHWndCtrl(CFDictionaryRef dict) { @Override public boolean isForeground() { - getNSWindow(windowID); + if (nsWin == null) return false; return ObjCHelper.msgSend.invokeInt(new Object[]{ nsWin, ObjCHelper.sel("isKeyWindow") @@ -82,7 +83,7 @@ public HWndCtrl updated() { @Override public void setForeground() { - getNSWindow(windowID); + if (nsWin == null) return; ObjCHelper.msgSend.invokeVoid(new Object[]{ nsWin, ObjCHelper.sel("orderFrontRegardless:") @@ -91,9 +92,9 @@ public void setForeground() { @Override public void setWindowPosition(HWndCtrl insertAfter, int x, int y, int w, int h) { - getNSWindow(windowID); + if (nsWin == null) return; newRect.origin.x = x; - newRect.origin.y = currentScreenRect.size.height - y - h; + newRect.origin.y = currentScreenRect.getValue().size.height - y - h; newRect.size.width = w; newRect.size.height = h; ObjCHelper.msgSend.invokeVoid(new Object[]{ @@ -122,7 +123,7 @@ public void setLayered(boolean enable) { @Override public void setTopmost(boolean enable) { - getNSWindow(windowID); + if(nsWin == null) return; ObjCHelper.msgSend.invokeVoid(new Object[]{ nsWin, ObjCHelper.sel("setLevel:"), @@ -132,8 +133,8 @@ public void setTopmost(boolean enable) { @Override public void setTransparent(boolean enable) { + if (nsWin == null) return; if (trans == enable) return; - getNSWindow(windowID); trans = enable; ObjCHelper.msgSend.invokeVoid(new Object[]{ nsWin, @@ -149,6 +150,12 @@ public void sendMouseEvent(MouseEvent msg, int x, int y) { } + public void attachNSWindow(Lwjgl3Graphics graphics) { + long glfwHandle = graphics.getWindow().getWindowHandle(); + nsWin = new Pointer(glfwGetCocoaWindow(glfwHandle)); + registerMethods(nsWin); + } + protected static void init() { CFDictionaryRef server = CoreGraphics.INSTANCE.CGSessionCopyCurrentDictionary(); if (server == null) { @@ -157,6 +164,17 @@ protected static void init() { CoreFoundation.INSTANCE.CFRelease(server); } ObjCHelper.init(); + currentScreenRect = new Cached<>() { + @Override + protected CGRect.ByValue produce() { + return CoreGraphics.INSTANCE.CGDisplayBounds(CoreGraphics.INSTANCE.CGMainDisplayID()); + } + + @Override + protected double cacheAge() { + return 1; + } + }; } protected static void free() { @@ -234,24 +252,6 @@ private void checkNSApp() { } } - private void getNSWindow(long CGWindowId) { - checkNSApp(); - if (nsWinUnavailable == 0) { - Pointer nswin = ObjCHelper.msgSend.invokePointer(new Object[]{ - nsApp, - ObjCHelper.sel("windowWithWindowNumber:"), - CGWindowId - }); - if (nswin == null) { - nsWinUnavailable = -1; - } - this.nsWin = nswin; - nsWinUnavailable = 1; - registerMethods(nsWin); - currentScreenRect = getScreenSize(); - } - } - private void registerMethods(Pointer nsWin) { Pointer cls = ObjCHelper.msgSend.invokePointer(new Object[]{ nsWin, From 43bcff4ce8b943dbfea3f974600a5d88d86e0bd2 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 29 Jun 2025 22:21:16 +0800 Subject: [PATCH 012/128] build: jpackage app bundle --- desktop/build.gradle | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/desktop/build.gradle b/desktop/build.gradle index 6d7a6300..2ec047c1 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -61,6 +61,7 @@ ext { issFileRel = "docs/scripts/ExePacking.iss" distDir = "${buildDir}/dist" distName = "${project.ext.appName}-v${project.version}" + copyrightText = "Copyright (C) 2022-2025 Harry Huang" } // Generates a distributable JAR file for the app. @@ -129,7 +130,8 @@ task jpackage(dependsOn: jlink, type: Exec, group: 'dist') { '--app-version', project.version, '--main-class', project.mainClassName, '--main-jar', jar.archiveFile.get().asFile.getName(), - '--runtime-image', jlinkRuntimeImg + '--runtime-image', jlinkRuntimeImg, + '--copyright', project.copyrightText ] if (osName.contains('windows')) { commands << '--icon' @@ -138,8 +140,10 @@ task jpackage(dependsOn: jlink, type: Exec, group: 'dist') { commands << '--icon' commands << "${project.assetsDir}/icons/icon.png" } else if (osName.contains('mac')) { - commands << '--java-options' - commands << "-XstartOnFirstThread" + commands << '--icon' + commands << "${project.assetsDir}/icons/icon.icns" + commands << '--mac-app-category' + commands << 'entertainment' } commandLine = commands } From 79610f36f0a246f220428749534b2ff6d8425364 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 6 Jul 2025 15:41:19 +0800 Subject: [PATCH 013/128] fix: minimize window --- .../cn/harryh/arkpets/controllers/Titlebar.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/desktop/src/cn/harryh/arkpets/controllers/Titlebar.java b/desktop/src/cn/harryh/arkpets/controllers/Titlebar.java index 7c3b8208..e1131a04 100644 --- a/desktop/src/cn/harryh/arkpets/controllers/Titlebar.java +++ b/desktop/src/cn/harryh/arkpets/controllers/Titlebar.java @@ -11,8 +11,7 @@ import javafx.scene.layout.HBox; import javafx.scene.text.Text; -import static cn.harryh.arkpets.Const.appName; -import static cn.harryh.arkpets.Const.durationFast; +import static cn.harryh.arkpets.Const.*; public class Titlebar implements Controller { @@ -44,7 +43,7 @@ public class Titlebar implements Controller { @Override public void initializeWith(ArkHomeFX app) { this.app = app; - if (forceUiStyle.equals("mac") || Const.isMac) { + if (forceUiStyle.equals("mac") || isMac) { initMacTitlebar(); } else if (forceUiStyle.equals("win") || Const.isWindows){ @@ -65,10 +64,12 @@ public void titleBarDragged(MouseEvent event) { @FXML public void windowMinimize(MouseEvent event) { - GuiPrefabs.fadeOutWindow(app.stage, durationFast, e -> { - app.stage.hide(); - app.stage.setIconified(true); - }); + if (!isMac) { + GuiPrefabs.fadeOutWindow(app.stage, durationFast, e -> { + app.stage.hide(); + }); + } + app.stage.setIconified(true); } @FXML From 252389be3a670d59d5e60cd326f6fb664f21f111 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 6 Jul 2025 22:53:32 +0800 Subject: [PATCH 014/128] feat: check accessibility --- .../cn/harryh/arkpets/natives/HIServices.java | 14 ++++++ .../envchecker/AccessibilityCheckTask.java | 44 +++++++++++++++++++ .../guitasks/envchecker/EnvCheckTask.java | 3 ++ 3 files changed, 61 insertions(+) create mode 100644 core/src/cn/harryh/arkpets/natives/HIServices.java create mode 100644 desktop/src/cn/harryh/arkpets/guitasks/envchecker/AccessibilityCheckTask.java diff --git a/core/src/cn/harryh/arkpets/natives/HIServices.java b/core/src/cn/harryh/arkpets/natives/HIServices.java new file mode 100644 index 00000000..a7702b01 --- /dev/null +++ b/core/src/cn/harryh/arkpets/natives/HIServices.java @@ -0,0 +1,14 @@ +package cn.harryh.arkpets.natives; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Pointer; + + +public interface HIServices extends Library { + HIServices INSTANCE = Native.load("ApplicationServices", HIServices.class); + + Pointer AXUIElementCreateSystemWide(); + + boolean AXIsProcessTrusted(); +} diff --git a/desktop/src/cn/harryh/arkpets/guitasks/envchecker/AccessibilityCheckTask.java b/desktop/src/cn/harryh/arkpets/guitasks/envchecker/AccessibilityCheckTask.java new file mode 100644 index 00000000..164e6c73 --- /dev/null +++ b/desktop/src/cn/harryh/arkpets/guitasks/envchecker/AccessibilityCheckTask.java @@ -0,0 +1,44 @@ +package cn.harryh.arkpets.guitasks.envchecker; + +import cn.harryh.arkpets.natives.HIServices; +import cn.harryh.arkpets.utils.Logger; + +import java.awt.*; +import java.net.URI; + + +public class AccessibilityCheckTask extends EnvCheckTask{ + @Override + public String getFailureReason() { + return "启用辅助功能"; + } + + @Override + public String getFailureDetail() { + return "ArkPets 的部分功能需要启用辅助功能权限才能使用。\n请在打开的“辅助功能”窗口中找到 ArkPets,并启用辅助功能权限。"; + } + + @Override + public boolean tryFix() { + return false; + } + + @Override + public boolean canFix() { + return false; + } + + @Override + public boolean run() { + if (!HIServices.INSTANCE.AXIsProcessTrusted()) { + try { + Desktop.getDesktop().browse(new URI("x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility")); + } catch (Exception e) { + Logger.error("Launcher", "Failed to open System Preferences Page"); + } + return false; + } else { + return true; + } + } +} diff --git a/desktop/src/cn/harryh/arkpets/guitasks/envchecker/EnvCheckTask.java b/desktop/src/cn/harryh/arkpets/guitasks/envchecker/EnvCheckTask.java index a9634475..39204862 100644 --- a/desktop/src/cn/harryh/arkpets/guitasks/envchecker/EnvCheckTask.java +++ b/desktop/src/cn/harryh/arkpets/guitasks/envchecker/EnvCheckTask.java @@ -54,6 +54,9 @@ public static List getAvailableTasks() { } } } + if (Const.isMac) { + list.add(new AccessibilityCheckTask()); + } return list; } } From ea2872d6d30abcae10f88bf514e05a741f57b96a Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 6 Jul 2025 22:53:56 +0800 Subject: [PATCH 015/128] build: add dmg build --- desktop/build.gradle | 9 +++++++++ docs/scripts/macLaunch.sh | 26 ++++++++++++++++++++++++++ docs/scripts/macPackage.sh | 12 ++++++++++++ 3 files changed, 47 insertions(+) create mode 100755 docs/scripts/macLaunch.sh create mode 100755 docs/scripts/macPackage.sh diff --git a/desktop/build.gradle b/desktop/build.gradle index 2ec047c1..5fa40b9e 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -59,6 +59,7 @@ ext { jlinkLocalesList = "en-US,zh-CN" jpackageDir = "${buildDir}/jpackage" issFileRel = "docs/scripts/ExePacking.iss" + macPackage = "docs/scripts/macPackage.sh" distDir = "${buildDir}/dist" distName = "${project.ext.appName}-v${project.version}" copyrightText = "Copyright (C) 2022-2025 Harry Huang" @@ -168,6 +169,14 @@ task distExe(dependsOn: jpackage, type: Exec, group: 'dist') { commandLine = commands } +// Generates a distributable DMG file for the app, using create-dmg. +// Note that you must install create-dmg in your environment and add it to PATH before running this task. +task distDmg(dependsOn: jpackage,type: Exec,group: 'dist') { + workingDir project.rootDir + def commands = [macPackage,project.version] + commandLine = commands +} + // Generates ALL kinds of distributing files. task distAll(dependsOn: [distJar, distZip, distExe], group: 'dist') { doLast() { diff --git a/docs/scripts/macLaunch.sh b/docs/scripts/macLaunch.sh new file mode 100755 index 00000000..b1503db7 --- /dev/null +++ b/docs/scripts/macLaunch.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +show_err() { + osascript -e "display alert \"Start Failed\" as critical message \"$1\"" + exit 1 +} + +SCRIPT_PATH=$(cd "$(dirname "$0")" && pwd) +APP_ROOT=$(dirname "$SCRIPT_PATH") +ICON_PATH="$APP_ROOT/Resources/ArkPets.icns" + +JAVA_EXEC="$APP_ROOT/runtime/Contents/Home/bin/java" +JAR_PATH=$(find "$APP_ROOT/app" -name "desktop*.jar" 2>/dev/null | head -n 1) + +if [ -z "$JAR_PATH" ]; then + show_err "Cannot found main jar." +fi + +mkdir -p ~/Library/Application\ Support/ArkPets/ +cd ~/Library/Application\ Support/ArkPets/ || show_err "Failed to prepare working dir" + +if [ ! -x "$JAVA_EXEC" ]; then + show_err "Java executable not found at $JAVA_EXEC" +fi + +"$JAVA_EXEC" -Xdock:icon="$ICON_PATH" -Xdock:name="ArkPets Launcher" -jar "$JAR_PATH" diff --git a/docs/scripts/macPackage.sh b/docs/scripts/macPackage.sh new file mode 100755 index 00000000..d01a89c1 --- /dev/null +++ b/docs/scripts/macPackage.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +echo $1 +cp -v ./docs/scripts/macLaunch.sh ./desktop/build/jpackage/ArkPets.app/Contents/MacOS/ArkPets + +create-dmg --volname ArkPets \ +--app-drop-link 300 50 \ +--icon "ArkPets.app" 100 50 \ +--icon "LICENSE" 500 50 \ +--window-size 700 60 \ +--icon-size 100 \ +"./desktop/build/dist/ArkPets-$1-mac-$(uname -m).dmg" ./desktop/build/jpackage/ \ No newline at end of file From 733571232f767a8c28de781d99bd1ea21d4fa17f Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 6 Jul 2025 22:57:20 +0800 Subject: [PATCH 016/128] chore: rename package --- core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java | 4 ++-- core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java | 4 ++-- .../src/cn/harryh/arkpets/{natives => rpc}/KWinInterface.java | 2 +- .../harryh/arkpets/{natives => rpc}/KWinPluginInterface.java | 2 +- .../cn/harryh/arkpets/{natives => rpc}/MutterInterface.java | 2 +- .../arkpets/{natives => rpc}/MutterPluginInterface.java | 2 +- .../arkpets/guitasks/envchecker/GNOMEPluginCheckTask.java | 2 +- .../arkpets/guitasks/envchecker/KWinPluginCheckTask.java | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) rename core/src/cn/harryh/arkpets/{natives => rpc}/KWinInterface.java (97%) rename core/src/cn/harryh/arkpets/{natives => rpc}/KWinPluginInterface.java (95%) rename core/src/cn/harryh/arkpets/{natives => rpc}/MutterInterface.java (97%) rename core/src/cn/harryh/arkpets/{natives => rpc}/MutterPluginInterface.java (93%) diff --git a/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java index de8c5960..6e017ea4 100644 --- a/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java @@ -1,8 +1,8 @@ package cn.harryh.arkpets.platform; import cn.harryh.arkpets.Const; -import cn.harryh.arkpets.natives.KWinInterface; -import cn.harryh.arkpets.natives.KWinPluginInterface; +import cn.harryh.arkpets.rpc.KWinInterface; +import cn.harryh.arkpets.rpc.KWinPluginInterface; import cn.harryh.arkpets.utils.Logger; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder; diff --git a/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java index 2a3a7ec5..083d7d7a 100644 --- a/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java @@ -1,8 +1,8 @@ package cn.harryh.arkpets.platform; import cn.harryh.arkpets.Const; -import cn.harryh.arkpets.natives.MutterInterface; -import cn.harryh.arkpets.natives.MutterPluginInterface; +import cn.harryh.arkpets.rpc.MutterInterface; +import cn.harryh.arkpets.rpc.MutterPluginInterface; import cn.harryh.arkpets.utils.Logger; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder; diff --git a/core/src/cn/harryh/arkpets/natives/KWinInterface.java b/core/src/cn/harryh/arkpets/rpc/KWinInterface.java similarity index 97% rename from core/src/cn/harryh/arkpets/natives/KWinInterface.java rename to core/src/cn/harryh/arkpets/rpc/KWinInterface.java index 425590b2..a70cafec 100644 --- a/core/src/cn/harryh/arkpets/natives/KWinInterface.java +++ b/core/src/cn/harryh/arkpets/rpc/KWinInterface.java @@ -1,4 +1,4 @@ -package cn.harryh.arkpets.natives; +package cn.harryh.arkpets.rpc; import org.freedesktop.dbus.Struct; import org.freedesktop.dbus.annotations.DBusInterfaceName; diff --git a/core/src/cn/harryh/arkpets/natives/KWinPluginInterface.java b/core/src/cn/harryh/arkpets/rpc/KWinPluginInterface.java similarity index 95% rename from core/src/cn/harryh/arkpets/natives/KWinPluginInterface.java rename to core/src/cn/harryh/arkpets/rpc/KWinPluginInterface.java index 76a61cb9..8d19718f 100644 --- a/core/src/cn/harryh/arkpets/natives/KWinPluginInterface.java +++ b/core/src/cn/harryh/arkpets/rpc/KWinPluginInterface.java @@ -1,4 +1,4 @@ -package cn.harryh.arkpets.natives; +package cn.harryh.arkpets.rpc; import org.freedesktop.dbus.TypeRef; import org.freedesktop.dbus.annotations.DBusBoundProperty; diff --git a/core/src/cn/harryh/arkpets/natives/MutterInterface.java b/core/src/cn/harryh/arkpets/rpc/MutterInterface.java similarity index 97% rename from core/src/cn/harryh/arkpets/natives/MutterInterface.java rename to core/src/cn/harryh/arkpets/rpc/MutterInterface.java index 766fba7e..6c7b490a 100644 --- a/core/src/cn/harryh/arkpets/natives/MutterInterface.java +++ b/core/src/cn/harryh/arkpets/rpc/MutterInterface.java @@ -1,4 +1,4 @@ -package cn.harryh.arkpets.natives; +package cn.harryh.arkpets.rpc; import org.freedesktop.dbus.Struct; import org.freedesktop.dbus.annotations.DBusInterfaceName; diff --git a/core/src/cn/harryh/arkpets/natives/MutterPluginInterface.java b/core/src/cn/harryh/arkpets/rpc/MutterPluginInterface.java similarity index 93% rename from core/src/cn/harryh/arkpets/natives/MutterPluginInterface.java rename to core/src/cn/harryh/arkpets/rpc/MutterPluginInterface.java index 931bdd62..c1314085 100644 --- a/core/src/cn/harryh/arkpets/natives/MutterPluginInterface.java +++ b/core/src/cn/harryh/arkpets/rpc/MutterPluginInterface.java @@ -1,4 +1,4 @@ -package cn.harryh.arkpets.natives; +package cn.harryh.arkpets.rpc; import org.freedesktop.dbus.annotations.DBusBoundProperty; import org.freedesktop.dbus.annotations.DBusInterfaceName; diff --git a/desktop/src/cn/harryh/arkpets/guitasks/envchecker/GNOMEPluginCheckTask.java b/desktop/src/cn/harryh/arkpets/guitasks/envchecker/GNOMEPluginCheckTask.java index b775d6ff..4eb2df86 100644 --- a/desktop/src/cn/harryh/arkpets/guitasks/envchecker/GNOMEPluginCheckTask.java +++ b/desktop/src/cn/harryh/arkpets/guitasks/envchecker/GNOMEPluginCheckTask.java @@ -1,7 +1,7 @@ package cn.harryh.arkpets.guitasks.envchecker; import cn.harryh.arkpets.Const; -import cn.harryh.arkpets.natives.MutterPluginInterface; +import cn.harryh.arkpets.rpc.MutterPluginInterface; import cn.harryh.arkpets.utils.IOUtils; import cn.harryh.arkpets.utils.Logger; import org.freedesktop.dbus.connections.impl.DBusConnection; diff --git a/desktop/src/cn/harryh/arkpets/guitasks/envchecker/KWinPluginCheckTask.java b/desktop/src/cn/harryh/arkpets/guitasks/envchecker/KWinPluginCheckTask.java index 5030da48..f8b3df03 100644 --- a/desktop/src/cn/harryh/arkpets/guitasks/envchecker/KWinPluginCheckTask.java +++ b/desktop/src/cn/harryh/arkpets/guitasks/envchecker/KWinPluginCheckTask.java @@ -1,7 +1,7 @@ package cn.harryh.arkpets.guitasks.envchecker; import cn.harryh.arkpets.Const; -import cn.harryh.arkpets.natives.KWinPluginInterface; +import cn.harryh.arkpets.rpc.KWinPluginInterface; import cn.harryh.arkpets.utils.IOUtils; import cn.harryh.arkpets.utils.Logger; import org.freedesktop.dbus.connections.impl.DBusConnection; From 3dbea3ad6da4ba04d544aa458b56483f0c7ed094 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 6 Jul 2025 23:00:17 +0800 Subject: [PATCH 017/128] fix: cache screen rect --- .../cn/harryh/arkpets/platform/QuartzHWndCtrl.java | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java index f455b352..8e06d847 100644 --- a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java @@ -164,17 +164,9 @@ protected static void init() { CoreFoundation.INSTANCE.CFRelease(server); } ObjCHelper.init(); - currentScreenRect = new Cached<>() { - @Override - protected CGRect.ByValue produce() { - return CoreGraphics.INSTANCE.CGDisplayBounds(CoreGraphics.INSTANCE.CGMainDisplayID()); - } - - @Override - protected double cacheAge() { - return 1; - } - }; + currentScreenRect = new Cached<>(); + currentScreenRect.setCacheAge(1.0); + currentScreenRect.setValueProducer(() -> CoreGraphics.INSTANCE.CGDisplayBounds(CoreGraphics.INSTANCE.CGMainDisplayID())); } protected static void free() { From bd44f8676675bff9fdd4b5c6dd9bf323d64974d1 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 6 Jul 2025 23:10:31 +0800 Subject: [PATCH 018/128] build: AppImage Package --- desktop/build.gradle | 9 +++++++++ docs/scripts/appImagePackage.sh | 14 ++++++++++++++ 2 files changed, 23 insertions(+) create mode 100755 docs/scripts/appImagePackage.sh diff --git a/desktop/build.gradle b/desktop/build.gradle index 5fa40b9e..7d5e8053 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -60,6 +60,7 @@ ext { jpackageDir = "${buildDir}/jpackage" issFileRel = "docs/scripts/ExePacking.iss" macPackage = "docs/scripts/macPackage.sh" + appImagePackage = "docs/scripts/appImagePackage.sh" distDir = "${buildDir}/dist" distName = "${project.ext.appName}-v${project.version}" copyrightText = "Copyright (C) 2022-2025 Harry Huang" @@ -177,6 +178,14 @@ task distDmg(dependsOn: jpackage,type: Exec,group: 'dist') { commandLine = commands } +// Generates a distributable AppImage file for the app, using create-dmg. +// Note that you must install linuxdeploy and in your environment and add it to PATH before running this task. +task distAppImage(dependsOn: jpackage,type: Exec,group: 'dist') { + workingDir project.rootDir + def commands = [appImagePackage,project.version] + commandLine = commands +} + // Generates ALL kinds of distributing files. task distAll(dependsOn: [distJar, distZip, distExe], group: 'dist') { doLast() { diff --git a/docs/scripts/appImagePackage.sh b/docs/scripts/appImagePackage.sh new file mode 100755 index 00000000..17e268b4 --- /dev/null +++ b/docs/scripts/appImagePackage.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +cd desktop/build || exit + +NO_STRIP=true linuxdeploy --appdir=ArkPets.AppDir \ +-e "jpackage/ArkPets/bin/ArkPets" \ +--icon-file="jpackage/ArkPets/lib/ArkPets.png" \ +--create-desktop-file + +cp -rv jpackage/ArkPets/lib/* "ArkPets.AppDir/usr/lib" + +appimagetool ArkPets.AppDir/ "dist/ArkPets-v$1-linux-$(uname -m).AppImage" + +rm -rv ArkPets.AppDir \ No newline at end of file From 43218442684925975561fd83274d2c3822e6c94e Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 6 Jul 2025 23:15:31 +0800 Subject: [PATCH 019/128] chore: style and fix jlink --- desktop/build.gradle | 14 +++++++------- docs/scripts/macPackage.sh | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/desktop/build.gradle b/desktop/build.gradle index 7d5e8053..9ce43ee6 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -55,7 +55,7 @@ ext { jarLibName = "${project.name}-${project.version}" jlinkRuntimeDir = "${buildDir}/jlink" jlinkRuntimeImg = "${jlinkRuntimeDir}/runtime" - jlinkModuleList = "java.base,java.desktop,java.logging,java.management,java.scripting,jdk.crypto.ec,jdk.localedata,jdk.unsupported" + jlinkModuleList = "java.base,java.desktop,java.logging,java.management,java.scripting,jdk.crypto.ec,jdk.localedata,jdk.security.auth,jdk.unsupported" jlinkLocalesList = "en-US,zh-CN" jpackageDir = "${buildDir}/jpackage" issFileRel = "docs/scripts/ExePacking.iss" @@ -172,17 +172,17 @@ task distExe(dependsOn: jpackage, type: Exec, group: 'dist') { // Generates a distributable DMG file for the app, using create-dmg. // Note that you must install create-dmg in your environment and add it to PATH before running this task. -task distDmg(dependsOn: jpackage,type: Exec,group: 'dist') { +task distDmg(dependsOn: jpackage, type: Exec, group: 'dist') { workingDir project.rootDir - def commands = [macPackage,project.version] + def commands = [macPackage, project.version] commandLine = commands } -// Generates a distributable AppImage file for the app, using create-dmg. -// Note that you must install linuxdeploy and in your environment and add it to PATH before running this task. -task distAppImage(dependsOn: jpackage,type: Exec,group: 'dist') { +// Generates a distributable AppImage file for the app, using linuxdeploy and appimagetool. +// Note that you must install linuxdeploy and appimagetool in your environment and add it to PATH before running this task. +task distAppImage(dependsOn: jpackage, type: Exec, group: 'dist') { workingDir project.rootDir - def commands = [appImagePackage,project.version] + def commands = [appImagePackage, project.version] commandLine = commands } diff --git a/docs/scripts/macPackage.sh b/docs/scripts/macPackage.sh index d01a89c1..547aaf7b 100755 --- a/docs/scripts/macPackage.sh +++ b/docs/scripts/macPackage.sh @@ -9,4 +9,4 @@ create-dmg --volname ArkPets \ --icon "LICENSE" 500 50 \ --window-size 700 60 \ --icon-size 100 \ -"./desktop/build/dist/ArkPets-$1-mac-$(uname -m).dmg" ./desktop/build/jpackage/ \ No newline at end of file +"./desktop/build/dist/ArkPets-v$1-mac-$(uname -m).dmg" ./desktop/build/jpackage/ \ No newline at end of file From 3fdad5db3f677b8289452ffd2a2079731b0a8185 Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 29 Jun 2025 21:27:39 +0800 Subject: [PATCH 020/128] refactor: lazy window operation --- core/src/cn/harryh/arkpets/ArkPets.java | 24 +++++++++++++++---- .../cn/harryh/arkpets/platform/HWndCtrl.java | 4 ++++ core/src/cn/harryh/arkpets/utils/Cached.java | 1 + 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/core/src/cn/harryh/arkpets/ArkPets.java b/core/src/cn/harryh/arkpets/ArkPets.java index a07a8b50..75776333 100644 --- a/core/src/cn/harryh/arkpets/ArkPets.java +++ b/core/src/cn/harryh/arkpets/ArkPets.java @@ -40,6 +40,8 @@ public class ArkPets extends InputApplicationAdaptor { private HWndCtrl hWndMine; private List hWndList; private final Cached hWndTopmostGetter; + private final Cached hWndTransparentSetter; + private final Cached hWndPosSetter; private final String APP_TITLE; private int offsetY = 0; @@ -57,6 +59,9 @@ public ArkPets(String title) { isFocused = new Cached<>(); isFocused.setValueProducer(() -> hWndMine.isForeground()); isFocused.setCacheAgeProducer(() -> 4.0 / getReducedFPS()); + + hWndTransparentSetter = new Cached<>(); + hWndPosSetter = new Cached<>(); } @Override @@ -337,11 +342,22 @@ private void updateWindow() { } } // Transparent style - hWndMine.setTransparent(isAlwaysTransparent); + hWndTransparentSetter.setValue(isAlwaysTransparent); + if (hWndTransparentSetter.isChanged()) { + hWndMine.setTransparent(hWndTransparentSetter.getValue()); + } // Window position - hWndMine.setWindowPosition(hWndTopmostGetter.getValue(), - (int) windowPosition.now().x, (int) windowPosition.now().y, - cha.camera.getWidth(), cha.camera.getHeight()); + HWndCtrl.WindowRect rect = new HWndCtrl.WindowRect( + (int) windowPosition.now().y, + (int) windowPosition.now().y + cha.camera.getHeight(), + (int) windowPosition.now().x, + (int) windowPosition.now().x + cha.camera.getWidth()); + hWndPosSetter.setValue(rect); + if (hWndPosSetter.isChanged()) { + rect = hWndPosSetter.getValue(); + hWndMine.setWindowPosition(hWndTopmostGetter.getValue(), + rect.left(), rect.top(), rect.width(), rect.height()); + } } private RelativeWindowPosition getRelativeWindowPositionAt(int x, int y) { diff --git a/core/src/cn/harryh/arkpets/platform/HWndCtrl.java b/core/src/cn/harryh/arkpets/platform/HWndCtrl.java index 83bf60de..eefb134f 100644 --- a/core/src/cn/harryh/arkpets/platform/HWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/HWndCtrl.java @@ -168,6 +168,10 @@ public record WindowRect(int top, int bottom, int left, int right) { public WindowRect() { this(0, 0, 0, 0); } + + public int width() { return right - left; } + + public int height() { return bottom - top; } } public enum MouseEvent { diff --git a/core/src/cn/harryh/arkpets/utils/Cached.java b/core/src/cn/harryh/arkpets/utils/Cached.java index c26b9729..dbee4839 100644 --- a/core/src/cn/harryh/arkpets/utils/Cached.java +++ b/core/src/cn/harryh/arkpets/utils/Cached.java @@ -47,6 +47,7 @@ public T getValue() { if (valueProducer != null && isExpired()) { setValue(valueProducer.get()); } + valueChangedFlag = false; return cachedValue; } } From bdf3ba9f4f7a30a8eb297345069a4b8794d6730c Mon Sep 17 00:00:00 2001 From: litwak913 Date: Fri, 4 Jul 2025 23:21:56 +0800 Subject: [PATCH 021/128] feat: get mouse position --- core/src/cn/harryh/arkpets/platform/HWndCtrl.java | 3 +++ .../cn/harryh/arkpets/platform/User32HWndCtrl.java | 7 +++++++ .../cn/harryh/arkpets/platform/WindowSystem.java | 14 ++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/core/src/cn/harryh/arkpets/platform/HWndCtrl.java b/core/src/cn/harryh/arkpets/platform/HWndCtrl.java index eefb134f..33bcdf4e 100644 --- a/core/src/cn/harryh/arkpets/platform/HWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/HWndCtrl.java @@ -184,4 +184,7 @@ public enum MouseEvent { MBUTTONDOWN, MBUTTONUP, } + + public record MousePoint(int x, int y) { + } } diff --git a/core/src/cn/harryh/arkpets/platform/User32HWndCtrl.java b/core/src/cn/harryh/arkpets/platform/User32HWndCtrl.java index ac061d1b..0052391c 100644 --- a/core/src/cn/harryh/arkpets/platform/User32HWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/User32HWndCtrl.java @@ -155,6 +155,13 @@ public static ArrayList getWindowList(boolean only_visible, long return windowList; } + public static MousePoint getMousePos() { + WinDef.POINT point = new WinDef.POINT(); + boolean result = User32.INSTANCE.GetCursorPos(point); + if (!result) return new MousePoint(0, 0); + return new MousePoint(point.x, point.y); + } + /** Gets the value of the window's extended styles. * @return EX_STYLE value. * @see WinUser diff --git a/core/src/cn/harryh/arkpets/platform/WindowSystem.java b/core/src/cn/harryh/arkpets/platform/WindowSystem.java index abfa11c6..410a2d5d 100644 --- a/core/src/cn/harryh/arkpets/platform/WindowSystem.java +++ b/core/src/cn/harryh/arkpets/platform/WindowSystem.java @@ -92,6 +92,20 @@ public static HWndCtrl getTopmostWindow() { } } + /** Gets the mouse position. + * @return The MousePoint record. + */ + public static HWndCtrl.MousePoint getMousePos() { + switch (PLATFORM) { + case USER32 -> { + return User32HWndCtrl.getMousePos(); + } + default -> { + return new HWndCtrl.MousePoint(0, 0); + } + } + } + /** Frees all the resources. */ public static void free() { From 742249362f339904450f2cfc2353dd26f407916d Mon Sep 17 00:00:00 2001 From: litwak913 Date: Sun, 13 Jul 2025 13:44:41 +0800 Subject: [PATCH 022/128] refactor: transparent and layer window --- core/src/cn/harryh/arkpets/ArkPets.java | 4 -- .../harryh/arkpets/natives/XextExtension.java | 15 ------- .../harryh/arkpets/platform/KWinHWndCtrl.java | 5 --- .../arkpets/platform/MutterHWndCtrl.java | 5 --- .../arkpets/platform/QuartzHWndCtrl.java | 45 ++----------------- .../arkpets/platform/WaylandHWndCtrl.java | 17 ++----- .../harryh/arkpets/platform/WindowSystem.java | 14 ------ .../harryh/arkpets/platform/X11HWndCtrl.java | 35 --------------- 8 files changed, 7 insertions(+), 133 deletions(-) delete mode 100644 core/src/cn/harryh/arkpets/natives/XextExtension.java diff --git a/core/src/cn/harryh/arkpets/ArkPets.java b/core/src/cn/harryh/arkpets/ArkPets.java index 93f8d703..75776333 100644 --- a/core/src/cn/harryh/arkpets/ArkPets.java +++ b/core/src/cn/harryh/arkpets/ArkPets.java @@ -8,8 +8,6 @@ import cn.harryh.arkpets.animations.GeneralBehavior; import cn.harryh.arkpets.concurrent.SocketClient; import cn.harryh.arkpets.platform.HWndCtrl; -import cn.harryh.arkpets.platform.QuartzHWndCtrl; -import cn.harryh.arkpets.platform.WaylandHWndCtrl; import cn.harryh.arkpets.platform.WindowSystem; import cn.harryh.arkpets.transitions.TransitionVector2; import cn.harryh.arkpets.tray.MemberTrayImpl; @@ -112,8 +110,6 @@ public void create() { if (config.window_style_topmost) hWndMine.setTopmost(true); updateWindow(); - if (hWndMine instanceof QuartzHWndCtrl qHWnd) qHWnd.attachNSWindow((Lwjgl3Graphics) Gdx.graphics); - if (hWndMine instanceof WaylandHWndCtrl wlHWnd) wlHWnd.attachSurface((Lwjgl3Graphics) Gdx.graphics); // 6.Tray icon setup tray = new MemberTrayImpl(this, new SocketClient()); diff --git a/core/src/cn/harryh/arkpets/natives/XextExtension.java b/core/src/cn/harryh/arkpets/natives/XextExtension.java deleted file mode 100644 index c9cd5efb..00000000 --- a/core/src/cn/harryh/arkpets/natives/XextExtension.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.harryh.arkpets.natives; - -import com.sun.jna.Native; -import com.sun.jna.Pointer; -import com.sun.jna.platform.unix.X11; -import com.sun.jna.ptr.IntByReference; - - -public interface XextExtension extends X11.Xext { - XextExtension INSTANCE = Native.load("Xext", XextExtension.class); - - void XShapeCombineRegion(X11.Display dpy, X11.Window dest, int destKind, int xOff, int yOff, Pointer r, int op); - - boolean XShapeQueryExtension(X11.Display dpy, IntByReference event_basep,IntByReference error_basep); -} \ No newline at end of file diff --git a/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java index 6e017ea4..d11178af 100644 --- a/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/KWinHWndCtrl.java @@ -62,11 +62,6 @@ public void setTaskbar(boolean enable) { dBusInterface.Stick(hWnd, enable); } - @Override - public void setLayered(boolean enable) { - - } - @Override public void setTopmost(boolean enable) { dBusInterface.Above(hWnd, enable); diff --git a/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java index 083d7d7a..ce525936 100644 --- a/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/MutterHWndCtrl.java @@ -64,11 +64,6 @@ public void setTaskbar(boolean enable) { dBusInterface.Stick(hWnd, !enable); } - @Override - public void setLayered(boolean enable) { - - } - @Override public void setTopmost(boolean enable) { dBusInterface.Above(hWnd, enable); diff --git a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java index 8e06d847..b94ad743 100644 --- a/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/QuartzHWndCtrl.java @@ -24,7 +24,6 @@ public class QuartzHWndCtrl extends HWndCtrl { private static Pointer nsApp; - private final IgnoreMouseCallback igcb = new IgnoreMouseCallback(); private final FrameCallback fcb = new FrameCallback(); private final long windowID; @@ -32,7 +31,6 @@ public class QuartzHWndCtrl extends HWndCtrl { private static Cached currentScreenRect; private final long layer; // 0:Uncheck 1:Checked,Available -1:Checked,Unavailable - private boolean trans; private final CGRect.ByValue newRect = new CGRect.ByValue(); public QuartzHWndCtrl(CFDictionaryRef dict) { @@ -116,11 +114,6 @@ public void setTaskbar(boolean enable) { }); } - @Override - public void setLayered(boolean enable) { - // not necessary in macOS. - } - @Override public void setTopmost(boolean enable) { if(nsWin == null) return; @@ -131,27 +124,14 @@ public void setTopmost(boolean enable) { }); } - @Override - public void setTransparent(boolean enable) { - if (nsWin == null) return; - if (trans == enable) return; - trans = enable; - ObjCHelper.msgSend.invokeVoid(new Object[]{ - nsWin, - ObjCHelper.sel("performSelectorOnMainThread:withObject:waitUntilDone:"), - ObjCHelper.sel("apRunOnAppKitIgnoreMouse"), - null, - 1 - }); - } - @Override public void sendMouseEvent(MouseEvent msg, int x, int y) { } - public void attachNSWindow(Lwjgl3Graphics graphics) { - long glfwHandle = graphics.getWindow().getWindowHandle(); + @Override + public void attachGLFWWindow(Lwjgl3Graphics graphics) { + super.attachGLFWWindow(graphics); nsWin = new Pointer(glfwGetCocoaWindow(glfwHandle)); registerMethods(nsWin); } @@ -250,14 +230,6 @@ private void registerMethods(Pointer nsWin) { ObjCHelper.sel("class") }); ObjCHelper.addRunOnAppKitMethod(cls, fcb, "Frame"); - ObjCHelper.addRunOnAppKitMethod(cls, igcb, "IgnoreMouse"); - ObjCHelper.msgSend.invokeVoid(new Object[]{ - nsWin, - ObjCHelper.sel("performSelectorOnMainThread:withObject:waitUntilDone:"), - ObjCHelper.sel("apRunOnAppKitIgnoreMouse"), - null, - 1 - }); } private static String getWindowName(Pointer value) { @@ -311,17 +283,6 @@ private CGRect getScreenSize() { return CoreGraphics.INSTANCE.CGDisplayBounds(CoreGraphics.INSTANCE.CGMainDisplayID()); } - private class IgnoreMouseCallback implements ObjCHelper.ThreadCallback { - @Override - public void callback(Pointer id, Pointer _cmd) { - ObjCHelper.msgSend.invokeVoid(new Object[]{ - id, - ObjCHelper.sel("setIgnoresMouseEvents:"), - trans ? 1 : 0 - }); - } - } - private class FrameCallback implements ObjCHelper.ThreadCallback { @Override public void callback(Pointer id, Pointer _cmd) { diff --git a/core/src/cn/harryh/arkpets/platform/WaylandHWndCtrl.java b/core/src/cn/harryh/arkpets/platform/WaylandHWndCtrl.java index 6f45092c..32a26b8b 100644 --- a/core/src/cn/harryh/arkpets/platform/WaylandHWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/WaylandHWndCtrl.java @@ -1,6 +1,5 @@ package cn.harryh.arkpets.platform; -import cn.harryh.arkpets.natives.WaylandHelper; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics; import com.sun.jna.Pointer; @@ -8,24 +7,16 @@ public abstract class WaylandHWndCtrl extends HWndCtrl { - private boolean isTransparent; - private Pointer surface; + protected Pointer surface; public WaylandHWndCtrl(String windowText, WindowRect windowRect) { super(windowText, windowRect); } - public void attachSurface(Lwjgl3Graphics graphics) { - long glfwHandle = graphics.getWindow().getWindowHandle(); - surface = new Pointer(glfwGetWaylandWindow(glfwHandle)); - } - @Override - public void setTransparent(boolean enable) { - if (isTransparent != enable) { - WaylandHelper.setTransparent(surface, enable); - isTransparent = enable; - } + public void attachGLFWWindow(Lwjgl3Graphics graphics) { + super.attachGLFWWindow(graphics); + surface = new Pointer(glfwGetWaylandWindow(glfwHandle)); } } diff --git a/core/src/cn/harryh/arkpets/platform/WindowSystem.java b/core/src/cn/harryh/arkpets/platform/WindowSystem.java index 5f952275..c91583bd 100644 --- a/core/src/cn/harryh/arkpets/platform/WindowSystem.java +++ b/core/src/cn/harryh/arkpets/platform/WindowSystem.java @@ -5,7 +5,6 @@ import cn.harryh.arkpets.Const; import cn.harryh.arkpets.utils.Logger; -import com.sun.jna.Platform; import java.util.ArrayList; import java.util.List; @@ -190,17 +189,4 @@ public static boolean needResize() { public static boolean needDecorated() { return PLATFORM == NULL; } - - /** Return current WindowSystem information request rate. - */ - public static int getRequestRate() { - switch (PLATFORM) { - case MUTTER,KWIN,X11,QUARTZ -> { // IPC - return 6; - } - default -> { - return 4; - } - } - } } diff --git a/core/src/cn/harryh/arkpets/platform/X11HWndCtrl.java b/core/src/cn/harryh/arkpets/platform/X11HWndCtrl.java index 9d216e8b..6ffca461 100644 --- a/core/src/cn/harryh/arkpets/platform/X11HWndCtrl.java +++ b/core/src/cn/harryh/arkpets/platform/X11HWndCtrl.java @@ -2,9 +2,7 @@ import cn.harryh.arkpets.natives.X11Extension; import cn.harryh.arkpets.natives.X11Helper; -import cn.harryh.arkpets.natives.XextExtension; import cn.harryh.arkpets.utils.Logger; -import com.sun.jna.Pointer; import com.sun.jna.platform.unix.X11; import com.sun.jna.ptr.IntByReference; @@ -16,12 +14,8 @@ public class X11HWndCtrl extends HWndCtrl { private static X11.Display display; private static final X11Extension x11 = X11Extension.INSTANCE; - private static final XextExtension xext = XextExtension.INSTANCE; protected final X11.Window hWnd; - private static boolean shapeAvailable; - private boolean transparentEnable; - public static final int STATE_REMOVE = 0; public static final int STATE_ADD = 1; @@ -38,15 +32,6 @@ public static void init() { } else { Logger.info("System", "Connected to X display"); } - IntByReference evt = new IntByReference(); - IntByReference err = new IntByReference(); - boolean xshape = xext.XShapeQueryExtension(display, evt, err); - if (!xshape) { - Logger.warn("System", "No XShape extension"); - shapeAvailable = false; - } else { - shapeAvailable = true; - } } public static HWndCtrl find(String className, String windowName) { @@ -160,21 +145,6 @@ public void setWindowPosition(HWndCtrl insertAfter, int x, int y, int w, int h) x11.XMoveResizeWindow(display, hWnd, x, y, w, h); } - @Override - public void setTransparent(boolean transparent) { - if (!shapeAvailable) return; - if (transparentEnable != transparent) { - if (transparent) { - Pointer reg = x11.XCreateRegion(); - xext.XShapeCombineRegion(display,hWnd, X11.Xext.ShapeInput,0,0,reg, X11.Xext.ShapeSet); - x11.XDestroyRegion(reg); - } else { - xext.XShapeCombineMask(display,hWnd, X11.Xext.ShapeInput,0,0,null, X11.Xext.ShapeSet); - } - transparentEnable = transparent; - } - } - @Override public void setTaskbar(boolean enable) { if (!enable) { @@ -186,11 +156,6 @@ public void setTaskbar(boolean enable) { } } - @Override - public void setLayered(boolean enable) { - // unnecessary in X11. - } - @Override public void setTopmost(boolean enable) { if (enable) { From 08974f145645671073287e9607f1e236c3105f30 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Sat, 5 Jul 2025 20:39:39 +0800 Subject: [PATCH 023/128] refactor: generalize fx elements --- .../arkpets/controllers/AnnounceDialog.java | 22 +++---- .../arkpets/controllers/BehaviorModule.java | 12 ++-- .../arkpets/controllers/DownloadDialog.java | 11 ++-- .../harryh/arkpets/controllers/LogDialog.java | 14 ++--- .../arkpets/controllers/RootModule.java | 15 +++-- .../arkpets/controllers/SettingsModule.java | 62 +++++++++---------- .../harryh/arkpets/utils/GuiComponents.java | 13 ++-- .../cn/harryh/arkpets/utils/GuiPrefabs.java | 2 +- 8 files changed, 75 insertions(+), 76 deletions(-) diff --git a/desktop/src/cn/harryh/arkpets/controllers/AnnounceDialog.java b/desktop/src/cn/harryh/arkpets/controllers/AnnounceDialog.java index 872501eb..571c41c1 100644 --- a/desktop/src/cn/harryh/arkpets/controllers/AnnounceDialog.java +++ b/desktop/src/cn/harryh/arkpets/controllers/AnnounceDialog.java @@ -40,12 +40,12 @@ public final class AnnounceDialog implements DialogController { @FXML private AnchorPane dialog; @FXML - private JFXButton dialogReturn; + private Button dialogReturn; @FXML - private JFXListView> annoListView; + private ListView> annoListView; @FXML - private JFXButton annoRefetch; + private Button annoRefetch; @FXML private Label annoTitle; @FXML @@ -59,7 +59,7 @@ public final class AnnounceDialog implements DialogController { @FXML private VBox annoContainer; - private JFXListCell selectedAnnoCell; + private ListCell selectedAnnoCell; private AnnounceReadHandler announceReadHandler; @@ -70,8 +70,8 @@ public void initializeWith(ArkHomeFX app) { this.app = app; annoListView.getSelectionModel().getSelectedItems().addListener( - (ListChangeListener>) (observable -> observable.getList().forEach( - (Consumer>) this::selectCell) + (ListChangeListener>) (observable -> observable.getList().forEach( + (Consumer>) this::selectCell) ) ); @@ -86,7 +86,7 @@ public AnchorPane getDialogPane() { } @Override - public JFXButton getReturnButton() { + public Button getReturnButton() { return dialogReturn; } @@ -118,10 +118,10 @@ public void fetchAnnounce(boolean doPopNotice, Runnable onNeedImmediateShow) { }); } - private JFXListCell createCell(AnnounceItem anno) { + private ListCell createCell(AnnounceItem anno) { double width = annoListView.getPrefWidth() * 0.75; double offset = width * 0.175; - JFXListCell cell = new JFXListCell<>(); + ListCell cell = new JFXListCell<>(); cell.getStyleClass().addAll("list-item"); cell.setPrefWidth(width); cell.setItem(anno); @@ -138,7 +138,7 @@ private JFXListCell createCell(AnnounceItem anno) { return cell; } - private void refreshCellGraphic(JFXListCell cell) { + private void refreshCellGraphic(ListCell cell) { double width = annoListView.getPrefWidth() * 0.75; double offset = width * 0.175; SVGPath dot = (SVGPath) ((Group) (cell.getGraphic())).getChildrenUnmodifiable().get(0); @@ -147,7 +147,7 @@ private void refreshCellGraphic(JFXListCell cell) { name.setPrefWidth(width - (announceReadHandler.isRead(cell.getItem()) ? 0 : offset)); } - private void selectCell(JFXListCell cell) { + private void selectCell(ListCell cell) { // Reset if (selectedAnnoCell != null) { selectedAnnoCell.getStyleClass().setAll("list-item"); diff --git a/desktop/src/cn/harryh/arkpets/controllers/BehaviorModule.java b/desktop/src/cn/harryh/arkpets/controllers/BehaviorModule.java index 6eee5cda..21e7f500 100644 --- a/desktop/src/cn/harryh/arkpets/controllers/BehaviorModule.java +++ b/desktop/src/cn/harryh/arkpets/controllers/BehaviorModule.java @@ -59,7 +59,7 @@ public final class BehaviorModule implements Controller { @FXML private Label configDeployMarginBottomValue; @FXML - private JFXButton toggleConfigDeployPosition; + private Button toggleConfigDeployPosition; @FXML private HBox wrapperConfigDeployPosition; @FXML @@ -68,21 +68,21 @@ public final class BehaviorModule implements Controller { @FXML private Label configTransitionAnimationLabel; @FXML - private JFXComboBox> configTransitionAnimation; + private ComboBox> configTransitionAnimation; @FXML private JFXButton configTransitionAnimationHelp; @FXML private Label configTransitionDurationLabel; @FXML - private JFXComboBox> configTransitionDuration; + private ComboBox> configTransitionDuration; @FXML private JFXButton configTransitionDurationHelp; @FXML private Label configTransitionFunctionLabel; @FXML - private JFXComboBox> configTransitionFunction; + private ComboBox> configTransitionFunction; @FXML - private JFXButton configTransitionFunctionHelp; + private Button configTransitionFunctionHelp; @FXML private JFXSlider configPhysicGravity; @@ -253,7 +253,7 @@ public String getContent() { app.config.transition_type = newValue.value(); app.config.save(); }); - new HelpHandbookEntrance(app.body, configTransitionFunctionHelp) { + new HelpHandbookEntrance(app.body, (JFXButton) configTransitionFunctionHelp) { @Override public Handbook getHandbook() { return new ControlHelpHandbook(configTransitionFunctionLabel) { diff --git a/desktop/src/cn/harryh/arkpets/controllers/DownloadDialog.java b/desktop/src/cn/harryh/arkpets/controllers/DownloadDialog.java index d960c852..a99796fa 100644 --- a/desktop/src/cn/harryh/arkpets/controllers/DownloadDialog.java +++ b/desktop/src/cn/harryh/arkpets/controllers/DownloadDialog.java @@ -12,7 +12,6 @@ import cn.harryh.arkpets.utils.Logger; import cn.harryh.arkpets.utils.StringUtils; import com.alibaba.fastjson.JSONObject; -import com.jfoenix.controls.*; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.event.ActionEvent; @@ -29,20 +28,20 @@ public final class DownloadDialog implements DialogController { @FXML private AnchorPane dialog; @FXML - private JFXButton dialogReturn; + private Button dialogReturn; @FXML private Label mcIndicator; @FXML private Label mcPurchase; @FXML - private JFXTextField mcCdkInput; + private TextField mcCdkInput; @FXML - private JFXButton mcConfirm; + private Button mcConfirm; @FXML private Label psIndicator; @FXML - private JFXButton psConfirm; + private Button psConfirm; private ArkHomeFX app; @@ -68,7 +67,7 @@ public AnchorPane getDialogPane() { } @Override - public JFXButton getReturnButton() { + public Button getReturnButton() { return dialogReturn; } diff --git a/desktop/src/cn/harryh/arkpets/controllers/LogDialog.java b/desktop/src/cn/harryh/arkpets/controllers/LogDialog.java index 7258cb66..60596c6c 100644 --- a/desktop/src/cn/harryh/arkpets/controllers/LogDialog.java +++ b/desktop/src/cn/harryh/arkpets/controllers/LogDialog.java @@ -42,14 +42,14 @@ public final class LogDialog implements DialogController { @FXML private AnchorPane dialog; @FXML - private JFXButton dialogReturn; + private Button dialogReturn; @FXML private TreeTableView logView; @FXML - private JFXButton logRefetch; + private Button logRefetch; @FXML - private JFXButton logExplore; + private Button logExplore; @FXML private Label logName; @@ -64,11 +64,11 @@ public final class LogDialog implements DialogController { @FXML private Label logSelectedCount; @FXML - public JFXButton quickSelectAll; + public Button quickSelectAll; @FXML - public JFXButton quickSelectRecent; + public Button quickSelectRecent; @FXML - private JFXButton exportSelected; + private Button exportSelected; private ObservableList coreLogList; private ObservableList desktopLogList; @@ -96,7 +96,7 @@ public AnchorPane getDialogPane() { } @Override - public JFXButton getReturnButton() { + public Button getReturnButton() { return dialogReturn; } diff --git a/desktop/src/cn/harryh/arkpets/controllers/RootModule.java b/desktop/src/cn/harryh/arkpets/controllers/RootModule.java index bd94da48..6ba83f0a 100644 --- a/desktop/src/cn/harryh/arkpets/controllers/RootModule.java +++ b/desktop/src/cn/harryh/arkpets/controllers/RootModule.java @@ -17,7 +17,6 @@ import cn.harryh.arkpets.utils.GuiComponents.Toast; import cn.harryh.arkpets.utils.GuiPrefabs; import cn.harryh.arkpets.utils.Logger; -import com.jfoenix.controls.*; import javafx.application.Platform; import javafx.concurrent.ScheduledService; import javafx.concurrent.Task; @@ -74,24 +73,24 @@ public final class RootModule implements Controller { @FXML private Pane sidebar; @FXML - private JFXButton annoEntrance; + private Button annoEntrance; @FXML - private JFXButton menuBtn1; + private Button menuBtn1; @FXML - private JFXButton menuBtn2; + private Button menuBtn2; @FXML - private JFXButton menuBtn3; + private Button menuBtn3; @FXML - public JFXButton launchBtn; + public Button launchBtn; @FXML public AnchorPane titleBar; @FXML public Text titleText; @FXML - private JFXButton titleMinimizeBtn; + private Button titleMinimizeBtn; @FXML - private JFXButton titleCloseBtn; + private Button titleCloseBtn; @FXML private HBox toast; diff --git a/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java b/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java index 8944bbe7..4bdda439 100644 --- a/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java +++ b/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java @@ -47,74 +47,74 @@ public final class SettingsModule implements Controller { private Pane noticeBox; @FXML - private JFXComboBox> configDisplayScale; + private ComboBox> configDisplayScale; @FXML - private JFXButton configDisplayScaleHelp; + private Button configDisplayScaleHelp; @FXML - private JFXComboBox> configDisplayFps; + private ComboBox> configDisplayFps; @FXML - private JFXButton configDisplayFpsHelp; + private Button configDisplayFpsHelp; @FXML - private JFXTabPane configRenderTabPane; + private TabPane configRenderTabPane; @FXML - private JFXComboBox> configCanvasColor; + private ComboBox> configCanvasColor; @FXML - private JFXComboBox> configCanvasCoverage; + private ComboBox> configCanvasCoverage; @FXML - private JFXButton configCanvasCoverageHelp; + private Button configCanvasCoverageHelp; @FXML - private JFXComboBox> configCanvasSamplingInterval; + private ComboBox> configCanvasSamplingInterval; @FXML - private JFXComboBox> configRenderOutline; + private ComboBox> configRenderOutline; @FXML - private JFXComboBox> configRenderOutlineEmphasis; + private ComboBox> configRenderOutlineEmphasis; @FXML - private JFXComboBox> configRenderOutlineColor; + private ComboBox> configRenderOutlineColor; @FXML - private JFXComboBox> configRenderOutlineColorEmphasis; + private ComboBox> configRenderOutlineColorEmphasis; @FXML - private JFXComboBox> configRenderOutlineWidth; + private ComboBox> configRenderOutlineWidth; @FXML - private JFXSlider configRenderOpacityNormal; + private Slider configRenderOpacityNormal; @FXML private Label configRenderOpacityNormalValue; @FXML - private JFXSlider configRenderOpacityDim; + private Slider configRenderOpacityDim; @FXML private Label configRenderOpacityDimValue; @FXML - private JFXComboBox> configRenderShadowColor; + private ComboBox> configRenderShadowColor; @FXML - private JFXCheckBox configEnableAngle; + private CheckBox configEnableAngle; @FXML - private JFXButton configEnableAngleHelp; + private Button configEnableAngleHelp; @FXML - private JFXCheckBox configEnableMipMap; + private CheckBox configEnableMipMap; @FXML - private JFXButton configEnableMipMapHelp; + private Button configEnableMipMapHelp; @FXML - private JFXCheckBox configWindowTopmost; + private CheckBox configWindowTopmost; @FXML - private JFXComboBox configLoggingLevel; + private ComboBox configLoggingLevel; @FXML - private JFXButton exportLog; + private Button exportLog; @FXML - private JFXCheckBox configAutoStartup; + private CheckBox configAutoStartup; @FXML - private JFXCheckBox configSolidExit; + private CheckBox configSolidExit; @FXML - private JFXCheckBox configWindowToolwindow; + private CheckBox configWindowToolwindow; @FXML - private JFXButton configWindowToolwindowHelp; + private Button configWindowToolwindowHelp; @FXML - private JFXCheckBox configEcoMode; + private CheckBox configEcoMode; @FXML - private JFXTextField configNetworkSource; + private TextField configNetworkSource; @FXML - private JFXTextField configNetworkProxy; + private TextField configNetworkProxy; @FXML private Label configNetworkProxyStatus; diff --git a/desktop/src/cn/harryh/arkpets/utils/GuiComponents.java b/desktop/src/cn/harryh/arkpets/utils/GuiComponents.java index 055d93ee..19d752c2 100644 --- a/desktop/src/cn/harryh/arkpets/utils/GuiComponents.java +++ b/desktop/src/cn/harryh/arkpets/utils/GuiComponents.java @@ -567,10 +567,10 @@ protected SVGPath getIcon() { abstract public static class HandbookEntrance { private static final double scale = 2.0 / 3; protected final StackPane root; - protected final JFXButton target; + protected final ButtonBase target; protected final Handbook handbook; - public HandbookEntrance(StackPane root, JFXButton target) { + public HandbookEntrance(StackPane root, ButtonBase target) { this.root = root; this.target = target; handbook = getHandbook(); @@ -580,7 +580,8 @@ public HandbookEntrance(StackPane root, JFXButton target) { graphic.setScaleY(scale); target.setText(""); target.setGraphic(graphic); - target.setRipplerFill(Color.GRAY); + if (target instanceof JFXButton jfxButton) + jfxButton.setRipplerFill(Color.GRAY); target.setOnAction(e -> getHandbook().show(root)); } @@ -591,7 +592,7 @@ public HandbookEntrance(StackPane root, JFXButton target) { abstract public static class DangerHandbookEntrance extends HandbookEntrance { - public DangerHandbookEntrance(StackPane root, JFXButton target) { + public DangerHandbookEntrance(StackPane root, ButtonBase target) { super(root, target); refresh(); } @@ -616,7 +617,7 @@ protected SVGPath getIcon() { abstract public static class WarningHandbookEntrance extends HandbookEntrance { - public WarningHandbookEntrance(StackPane root, JFXButton target) { + public WarningHandbookEntrance(StackPane root, ButtonBase target) { super(root, target); refresh(); } @@ -641,7 +642,7 @@ protected SVGPath getIcon() { abstract public static class HelpHandbookEntrance extends HandbookEntrance { - public HelpHandbookEntrance(StackPane root, JFXButton target) { + public HelpHandbookEntrance(StackPane root, ButtonBase target) { super(root, target); } diff --git a/desktop/src/cn/harryh/arkpets/utils/GuiPrefabs.java b/desktop/src/cn/harryh/arkpets/utils/GuiPrefabs.java index 9ec28f31..948c3d10 100644 --- a/desktop/src/cn/harryh/arkpets/utils/GuiPrefabs.java +++ b/desktop/src/cn/harryh/arkpets/utils/GuiPrefabs.java @@ -139,7 +139,7 @@ public static void deblurNode(Node node, Duration duration, EventHandler { if (wrapper.isVisible()) GuiPrefabs.fadeOutNode(wrapper, duration, null); From ae17135a752c0295d4d32032fe3371b4a4b866d3 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Sat, 5 Jul 2025 23:03:13 +0800 Subject: [PATCH 024/128] chore(dep): upgrade javafx lib to 17.0.15 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 14470627..352caf54 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath "org.openjfx:javafx-plugin:0.0.13" + classpath "org.openjfx:javafx-plugin:0.1.0" } } @@ -30,7 +30,7 @@ allprojects { // Prefabs gdxVersion = "1.11.0" jnaVersion = "5.12.1" - javaFXVersion = "17.0.8" + javaFXVersion = "17.0.15" } repositories { From c3d8bceb4844d46091bf6fe925f047ea3ff709b2 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Sun, 13 Jul 2025 23:15:51 +0800 Subject: [PATCH 025/128] refactor: generalize fx elements part 2 --- assets/UI/ModelsModule.fxml | 2 +- .../arkpets/controllers/BehaviorModule.java | 37 ++--- .../arkpets/controllers/ModelsModule.java | 73 ++++---- .../arkpets/controllers/SettingsModule.java | 20 ++- .../cn/harryh/arkpets/guitasks/GuiTask.java | 7 +- .../cn/harryh/arkpets/utils/GuiPrefabs.java | 157 +++++++++++++----- 6 files changed, 186 insertions(+), 110 deletions(-) diff --git a/assets/UI/ModelsModule.fxml b/assets/UI/ModelsModule.fxml index 9b1e7a73..8ef84449 100644 --- a/assets/UI/ModelsModule.fxml +++ b/assets/UI/ModelsModule.fxml @@ -131,7 +131,7 @@ { private ScrollPane moduleScroll; @FXML - private JFXCheckBox configBehaviorAllowWalk; + private CheckBox configBehaviorAllowWalk; @FXML - private JFXCheckBox configBehaviorAllowSit; + private CheckBox configBehaviorAllowSit; @FXML - private JFXCheckBox configBehaviorAllowSleep; + private CheckBox configBehaviorAllowSleep; @FXML - private JFXCheckBox configBehaviorAllowSpecial; + private CheckBox configBehaviorAllowSpecial; @FXML - private JFXSlider configBehaviorAiActivation; + private Slider configBehaviorAiActivation; @FXML private Label configBehaviorAiActivationValue; @FXML - private JFXSlider configBehaviorWalkSpeed; + private Slider configBehaviorWalkSpeed; @FXML private Label configBehaviorSpeedWalkValue; @FXML - private JFXCheckBox configBehaviorAllowInteract; + private CheckBox configBehaviorAllowInteract; @FXML - private JFXCheckBox configBehaviorDoPeerRepulsion; + private CheckBox configBehaviorDoPeerRepulsion; @FXML - private JFXCheckBox configDeployMultiMonitors; + private CheckBox configDeployMultiMonitors; @FXML private Label configDeployMultiMonitorsStatus; @FXML - private JFXSlider configDeployMarginBottom; + private Slider configDeployMarginBottom; @FXML private Label configDeployMarginBottomValue; @FXML @@ -70,13 +69,13 @@ public final class BehaviorModule implements Controller { @FXML private ComboBox> configTransitionAnimation; @FXML - private JFXButton configTransitionAnimationHelp; + private Button configTransitionAnimationHelp; @FXML private Label configTransitionDurationLabel; @FXML private ComboBox> configTransitionDuration; @FXML - private JFXButton configTransitionDurationHelp; + private Button configTransitionDurationHelp; @FXML private Label configTransitionFunctionLabel; @FXML @@ -85,23 +84,23 @@ public final class BehaviorModule implements Controller { private Button configTransitionFunctionHelp; @FXML - private JFXSlider configPhysicGravity; + private Slider configPhysicGravity; @FXML private Label configPhysicGravityValue; @FXML - private JFXSlider configPhysicAirFriction; + private Slider configPhysicAirFriction; @FXML private Label configPhysicAirFrictionValue; @FXML - private JFXSlider configPhysicStaticFriction; + private Slider configPhysicStaticFriction; @FXML private Label configPhysicStaticFrictionValue; @FXML - private JFXSlider configPhysicSpeedLimitX; + private Slider configPhysicSpeedLimitX; @FXML private Label configPhysicSpeedLimitXValue; @FXML - private JFXSlider configPhysicSpeedLimitY; + private Slider configPhysicSpeedLimitY; @FXML private Label configPhysicSpeedLimitYValue; @FXML @@ -253,7 +252,7 @@ public String getContent() { app.config.transition_type = newValue.value(); app.config.save(); }); - new HelpHandbookEntrance(app.body, (JFXButton) configTransitionFunctionHelp) { + new HelpHandbookEntrance(app.body, configTransitionFunctionHelp) { @Override public Handbook getHandbook() { return new ControlHelpHandbook(configTransitionFunctionLabel) { diff --git a/desktop/src/cn/harryh/arkpets/controllers/ModelsModule.java b/desktop/src/cn/harryh/arkpets/controllers/ModelsModule.java index 37886f17..69f517f7 100644 --- a/desktop/src/cn/harryh/arkpets/controllers/ModelsModule.java +++ b/desktop/src/cn/harryh/arkpets/controllers/ModelsModule.java @@ -60,19 +60,19 @@ public final class ModelsModule implements Controller { @FXML private Pane loadFailureTip; @FXML - private JFXButton searchModelConfirm; + private Button searchModelConfirm; @FXML - private JFXButton searchModelReset; + private Button searchModelReset; @FXML - private JFXButton searchModelRandom; + private Button searchModelRandom; @FXML - private JFXButton searchModelReload; + private Button searchModelReload; @FXML - private JFXTextField searchModelInput; + private TextField searchModelInput; @FXML private Label searchModelStatus; @FXML - private JFXListView> modelListView; + private ListView> modelListView; @FXML private Label selectedModelName; @FXML @@ -82,9 +82,9 @@ public final class ModelsModule implements Controller { @FXML private Label selectedModelType; @FXML - private JFXButton modelFavorite; + private Button modelFavorite; @FXML - private JFXButton topFavorite; + private Button topFavorite; @FXML private AnchorPane infoPane; @@ -93,9 +93,9 @@ public final class ModelsModule implements Controller { @FXML private AnchorPane managePane; @FXML - private JFXButton toggleFilterPane; + private Button toggleFilterPane; @FXML - private JFXButton toggleManagePane; + private Button toggleManagePane; @FXML private ScrollPane infoPaneTagScroll; @FXML @@ -110,17 +110,17 @@ public final class ModelsModule implements Controller { @FXML private VBox noticeBox; @FXML - private JFXButton modelUpdate; + private Button modelUpdate; @FXML - private JFXButton modelFetch; + private Button modelFetch; @FXML - private JFXButton modelVerify; + private Button modelVerify; @FXML - private JFXButton modelReFetch; + private Button modelReFetch; @FXML - private JFXButton modelImport; + private Button modelImport; @FXML - private JFXButton modelExport; + private Button modelExport; @FXML private Label modelHelp; @@ -441,7 +441,6 @@ private void initModelFavorite() { } modelFavorite.setGraphic(favIcon); - modelFavorite.setRipplerFill(Color.GRAY); modelFavorite.setOnAction(e -> { String key = selectedModelCell.getItem().key; if (app.config.character_favorites.containsKey(key)) { @@ -560,7 +559,7 @@ public void modelReload(boolean doPopNotice) { String s = change.getElementAdded() == null ? change.getElementRemoved() : change.getElementAdded(); String t = app.modelsDataset.sortTags == null ? s : app.modelsDataset.sortTags.getOrDefault(s, s); for (Node node : filterPaneTagFlow.getChildren()) - if (node instanceof JFXButton tag && t.equals(tag.getText())) { + if (node instanceof Button tag && t.equals(tag.getText())) { String styleFrom = change.getElementAdded() == null ? "info-tag-badge-active" : "info-tag-badge"; String styleTo = change.getElementAdded() == null ? "info-tag-badge" : "info-tag-badge-active"; GuiPrefabs.replaceStyleClass(tag, styleFrom, styleTo); @@ -572,15 +571,17 @@ public void modelReload(boolean doPopNotice) { sortTags.sort(Comparator.naturalOrder()); sortTags.forEach(s -> { String t = app.modelsDataset.sortTags == null ? s : app.modelsDataset.sortTags.getOrDefault(s, s); - JFXButton tag = new JFXButton(t); - tag.getStyleClass().add("info-tag-badge"); - tag.setOnAction(ev -> { - if (filterTagSet.contains(s)) - filterTagSet.remove(s); - else - filterTagSet.add(s); - modelSearch(searchModelInput.getText()); - }); + Button tag = new GuiPrefabs.ButtonBuilder() + .setText(t) + .setAdditionalStyleClass("info-tag-badge") + .setOnAction(ev -> { + if (filterTagSet.contains(s)) + filterTagSet.remove(s); + else + filterTagSet.add(s); + modelSearch(searchModelInput.getText()); + }) + .build(); filterPaneTagFlow.getChildren().add(tag); }); } @@ -671,14 +672,16 @@ private void selectCell(JFXListCell cell) { String s = o.toString(); String t = app.modelsDataset.sortTags == null ? s : app.modelsDataset.sortTags.getOrDefault(s, s); - JFXButton tag = new JFXButton(t); - tag.getStyleClass().add("info-tag-badge-active"); - tag.setOnAction(e -> { - filterTagSet.clear(); - filterTagSet.add(s); - infoPaneComposer.activate(1); - modelSearch(searchModelInput.getText()); - }); + Button tag = new GuiPrefabs.ButtonBuilder() + .setText(t) + .setAdditionalStyleClass("info-tag-badge-active") + .setOnAction(e -> { + filterTagSet.clear(); + filterTagSet.add(s); + infoPaneComposer.activate(1); + modelSearch(searchModelInput.getText()); + }) + .build(); infoPaneTagFlow.getChildren().add(tag); }); // Switch info pane diff --git a/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java b/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java index 4bdda439..37d6d64c 100644 --- a/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java +++ b/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java @@ -486,8 +486,10 @@ protected void onHasNewStableVersion(Version stableVersion) { "检测到软件有新的版本!", "当前版本 " + appVersion + " 可更新到 " + stableVersion + "\n是否要现在进行更新?", () -> executeAppUpdate()); - JFXButton gotoButton = new JFXButton("访问官网"); - gotoButton.setOnAction(e -> app.popBrowser(PathConfig.urlDownload)); + Button gotoButton = new GuiPrefabs.ButtonBuilder() + .setText("访问官网") + .setOnAction(e -> app.popBrowser(PathConfig.urlDownload)) + .build(); GuiPrefabs.Dialogs.attachAction(dialog, gotoButton, 0); dialog.show(); } @@ -502,12 +504,14 @@ protected void onUpToDated(Version stableVersion) { "尚未发现新的正式版本。", "当前版本 " + appVersion + " 已是最新", null); - JFXButton forceBtn = new JFXButton("强制重装"); - forceBtn.setOnAction(e -> { - executeAppUpdate(); - GuiPrefabs.Dialogs.disposeDialog(dialog); - }); - GuiPrefabs.Dialogs.attachAction(dialog, forceBtn, 0); + Button forceButton = new GuiPrefabs.ButtonBuilder() + .setText("强制重装") + .setOnAction(e -> { + executeAppUpdate(); + GuiPrefabs.Dialogs.disposeDialog(dialog); + }) + .build(); + GuiPrefabs.Dialogs.attachAction(dialog, forceButton, 0); dialog.show(); } diff --git a/desktop/src/cn/harryh/arkpets/guitasks/GuiTask.java b/desktop/src/cn/harryh/arkpets/guitasks/GuiTask.java index 865cfea1..7d4dc240 100644 --- a/desktop/src/cn/harryh/arkpets/guitasks/GuiTask.java +++ b/desktop/src/cn/harryh/arkpets/guitasks/GuiTask.java @@ -136,12 +136,11 @@ private JFXDialog getDialog(StackPane parent, Task boundTask, boolean c JFXDialogLayout layout = new JFXDialogLayout(); layout.setHeading(bar); layout.setBody(content); - layout.setActions(GuiPrefabs.Dialogs.getOkayButton(dialog)); dialog.setContent(layout); + + // Set the actions of the dialog if (cancelable) { - JFXButton cancel = GuiPrefabs.Dialogs.getCancelButton(dialog); - cancel.setOnAction(e -> boundTask.cancel()); - layout.setActions(cancel); + layout.setActions(GuiPrefabs.Dialogs.getCancelButton(dialog, e -> boundTask.cancel())); } else { layout.setActions(List.of()); } diff --git a/desktop/src/cn/harryh/arkpets/utils/GuiPrefabs.java b/desktop/src/cn/harryh/arkpets/utils/GuiPrefabs.java index 948c3d10..6a0c6191 100644 --- a/desktop/src/cn/harryh/arkpets/utils/GuiPrefabs.java +++ b/desktop/src/cn/harryh/arkpets/utils/GuiPrefabs.java @@ -29,6 +29,7 @@ import javafx.scene.text.Text; import javafx.stage.FileChooser; import javafx.stage.Window; +import javafx.util.Builder; import javafx.util.Duration; import javax.net.ssl.SSLException; @@ -187,6 +188,82 @@ public static void disableScrollPaneCache(ScrollPane scrollPane) { } + public static class ButtonBuilder implements Builder