
桌面应用UI组件【免费下载链接】FlatLafFlatLaf - Swing Look and Feel (with Darcula/IntelliJ themes support)项目地址https://gitcode.com/gh_mirrors/fl/FlatLaf点击查看免费下载FlatLaf 是一个为 Swing 提供扁平化外观的 Look and Feel 库其部分高级特性如 Windows 原生窗口边框、Linux 窗口移动与系统菜单依赖操作系统原生 API。为了在 Java 中先行验证这些 API 的调用方式FlatLaf 仓库中保留了一个专门的研发子项目——flatlaf-natives/flatlaf-natives-jna它通过 JNAJava Native Access直接访问 Windows 与 Linux 的系统级接口。阅读本文你将理解这个研发原型子项目的定位、核心源码实现、它与最终 C 原生库之间的演进关系以及如何在开发环境中构建与使用它来验证原生 API 行为。子项目定位为什么 FlatLaf 需要一个JNA 原型库在 flatlaf-natives-jna/README.md 中项目作者对子项目做了三点明确说明该子项目包含使用 JNA 访问原生操作系统 API的源代码关键约束这里的代码并未被 FlatLaf 正式库使用Code in this sub-project is not used in FlatLaf libraries它的实际用途是研发与测试——在 Java 中借助 JNA 验证某些原生操作系统 API 的用法验证通过后再将其转换为 C 实现进入正式的flatlaf-natives-*原生库。也就是说flatlaf-natives-jna是 FlatLaf 原生能力研发流程中的探路者先用 JNA 快速验证 API 参数、结构体布局与消息处理逻辑再以性能与部署更优的 C/JNI 方式落地。理解这一点是阅读本子项目全部代码的前提——它的价值在于研究参考而不是直接依赖。从仓库结构看settings.gradle.kts 将四个原生子项目并列纳入构建flatlaf-natives-windows、flatlaf-natives-macos、flatlaf-natives-linux与flatlaf-natives-jna而 flatlaf-natives/README.md 明确将flatlaf-natives-jna标注为 for development only仅用于开发进一步印证了其研发原型的定位。项目结构与构建配置子项目目录结构非常精简仅包含两个平台下的核心原型类flatlaf-natives/flatlaf-natives-jna/ ├── README.md ├── build.gradle.kts └── src/main/java/com/formdev/flatlaf/natives/jna/ ├── linux/X11WmUtils.java └── windows/FlatWindowsNativeWindowBorder.java其构建脚本 build.gradle.kts 声明了两个依赖implementation( project( :flatlaf-core ) )依赖 FlatLaf 核心模块以便复用SystemInfo、UIScale等工具类以及FlatNativeWindowBorder.Provider接口implementation( libs.jna )与implementation( libs.jna.platform )JNA 及其平台封装库。版本统一由 gradle/libs.versions.toml 管理当前为JNA 5.19.1。其中jna-platform提供了User32、GDI32、Shell32、X11、Advapi32Util等现成的 Win32/X11 声明大幅降低了手写原生函数签名的成本——这正是原型验证阶段选择 JNA 的核心原因之一。Windows 原型FlatWindowsNativeWindowBorder 的窗口过程接管Windows 侧的原型类是 FlatWindowsNativeWindowBorder.java它实现了FlatNativeWindowBorder.Provider接口该接口定义于 FlatNativeWindowBorder.java。其目标是在应用使用自定义装饰时隐藏 Windows 10 标题栏含最小化/最大化/关闭按钮但保留缩放边框与投影且不影响系统的窗口对齐Snap功能。Provider 接口与生命周期管理FlatWindowsNativeWindowBorder以单例方式提供getInstance()内部用IdentityHashMapWindow, WndProc维护窗口 → 自定义窗口过程的映射核心生命周期如下setHasCustomDecoration(window, true)触发install(window)仅当运行于 Windows 10 及以上、窗口是JFrame/JDialog且不是 undecorated时才安装setHasCustomDecoration(window, false)触发uninstall(window)移除自定义窗口过程并恢复原生标题栏updateTitleBarInfo(...)由 Swing 侧告知标题栏高度、应用图标与三个窗口按钮最小化/最大化/关闭的点击区域矩形供命中测试使用showWindow(window, cmd)包装User32.INSTANCE.ShowWindow命令常量SW_MAXIMIZE3、SW_MINIMIZE6、SW_RESTORE9与 Win32 API 保持一致。WndProc替换窗口过程内部类WndProc implements WindowProc是原型的技术核心。它在构造时通过Native.getComponentPointer(window)取得窗口的HWND按架构区分调用SetWindowLongPtrx86_64或SetWindowLongx86替换窗口过程GWLP_WNDPROC -4并保存原始过程defaultWndProc调用updateFrame()通过SetWindowPos(... SWP_FRAMECHANGED ...)触发WM_NCCALCSIZE从而移除系统标题栏根据window.getBackground()用GDI32Ex.CreateSolidBrush创建背景画刷避免窗口缩放/移动时背景闪烁。原型类中定义了完整的 Windows 消息常量包括WM_NCCALCSIZE 0x0083 WM_NCHITTEST 0x0084 WM_ENTERSIZEMOVE 0x0231 WM_EXITSIZEMOVE 0x0232 WM_DPICHANGED 0x02E0 WM_DWMCOLORIZATIONCOLORCHANGED 0x0320 HTCLIENT1 HTCAPTION2 HTSYSMENU3 HTMINBUTTON8 HTMAXBUTTON9 HTTOP12 HTCLOSE20WM_NCCALCSIZE隐藏标题栏与修正客户区WmNcCalcSize处理流程与 Microsoft Terminal 的NonClientIslandWindow::_OnNcCalcSize()思路一致先保存默认窗口过程计算前的原始rgrc[0].top调用默认窗口过程应用系统默认边框把顶部恢复为原始值即让客户区顶到窗口顶部实现标题栏隐藏若窗口处于最大化且非全屏状态将顶部加上缩放手柄高度SM_CXPADDEDBORDER SM_CYSIZEFRAME并处理任务栏自动隐藏ABM_GETAUTOHIDEBAREX情况下的边距修正在 Windows 11 上通过DwmGetWindowAttribute(hwnd, DWMWA_VISIBLE_FRAME_BORDER_THICKNESS37, ...)获取可见边框厚度并加到顶部避免窗口顶部出现黑线。WM_NCHITTEST命中测试与窗口按钮WmNcHitTest决定鼠标所在位置属于哪个窗口区域标题栏、缩放边框、应用图标、窗口按钮等先调用默认窗口过程处理左右下三边若结果不是HTCLIENT则直接返回将屏幕坐标换算为窗口坐标再按GraphicsConfiguration.getDefaultTransform()做降采样scaleDown与 AWT 在 HiDPI 下的坐标处理保持一致顶部缩放边框被限制在UIScale.scale(4)像素内现代 WinUI 应用的标准并根据鼠标位置返回HTTOPLEFT/HTTOPRIGHT/HTTOP依次命中测试应用图标HTSYSMENU、最小化HTMINBUTTON、最大化HTMAXBUTTON、关闭HTCLOSE按钮区域标题栏区域通过captionHitTestCallback回调让 Swing 判断该点是否落在处理鼠标事件的组件上从而返回HTCLIENTSwing 可处理或HTCAPTION可拖动窗口。注释中还记录了平台差异细节Windows 11 上鼠标悬停HTMAXBUTTON会弹出 Snap Layouts 菜单系统菜单HTSYSMENU区域左键单击弹菜单、双击发送WM_CLOSE。DWM 颜色化信息与系统菜单原型还实现了两处系统集成颜色化查询从注册表SOFTWARE\Microsoft\Windows\DWM读取ColorPrevalence、ColorizationColor、ColorizationColorBalance用于计算激活窗口顶边颜色对应 flatlaf-core 中FlatNativeWindowBorder.WindowTopBorder的配色逻辑收到WM_DWMCOLORIZATIONCOLORCHANGED时通过fireStateChangedLaterOnce()在 AWT 事件线程上延迟 300ms 合并触发一次ChangeListener系统菜单右键标题栏/图标时用GetSystemMenu获取系统菜单按窗口状态最大化、有无缩放边框等更新SC_RESTORE/SC_MOVE/SC_SIZE/SC_MINIMIZE/SC_MAXIMIZE/SC_CLOSE的启用状态并将SC_CLOSE设为默认项再以TrackPopupMenu(TPM_RETURNCMD)弹出选中后PostMessage(WM_SYSCOMMAND)执行。Linux 原型X11WmUtils 与窗口管理器协议消息Linux 侧原型类是 X11WmUtils.java目标是通过 X11 客户端消息ClientMessage与窗口管理器通信实现两个功能xMoveOrResizeWindow(window, x, y, direction)发送_NET_WM_MOVERESIZEfreedesktop EWMH 规范定义的协议direction取值 0~7 对应八个缩放方向、8 对应移动xShowWindowMenu(window, x, y)发送_GTK_SHOW_WINDOW_MENUGTK 私有协议请求窗口管理器在指定坐标弹出系统窗口菜单。sendEvent的调用链展示了 JNA 与 X11 交互的完整套路用sun.awt.SunToolkit.awtLock()加 AWT 锁保证与 AWT 的互斥XOpenDisplay(null)打开默认 DisplayXDefaultRootWindow获取根窗口用Native.getComponentPointer(window)取 AWT 窗口的 X11 Window IDXUngrabPointer/XUngrabKeyboard解除指针与键盘捕获让窗口管理器能够接管构造XClientMessageEventmessage_type XInternAtom(display, atom_name, false)format 32data.l[0..4]填入参数移动缩放时含按钮Button1与 source indication1XSendEvent发给根窗口掩码SubstructureNotifyMask | SubstructureRedirectMask随后XFlush与XCloseDisplay。需要特别注意的是源码注释中给出了明确的警告Warning: Although the implementation of this method is (nearly) identical to the C implementation, this one does not work correctly. DO NOT USE.即该 JNA 版本虽然与最终 C 实现逻辑几乎一致但实际不能正常工作原型中保留了大量System.out.println调试输出与// TODO标记可佐证其未完成/仅供研究状态这正是它没有进入正式库的原因之一。从 JNA 原型到 C 实现的演进路径对比 JNA 原型与其对应的正式 C 实现可以清晰还原验证 → 落地的演进过程。Linux 侧正式实现位于 flatlaf-natives-linux/src/main/cpp/X11WmUtils.cpp导出Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_xMoveOrResizeWindow与xShowWindowMenu两个 JNI 方法。与 JNA 版相比C 版补齐了原型缺失的关键环节通过JAWT_GetAWT获取 AWT 接口、getWindowHandle取得Display*与窗口句柄并用awt.Lock/awt.Unlock同步新增isWMHintSupported()读取根窗口的_NET_SUPPORTED属性先检查窗口管理器是否支持该协议不支持则直接返回 false——这是 JNA 原型没有的健壮性处理事件结构体XClientMessageEvent直接栈上初始化无 JNA 结构体往返开销。Java 侧调用方是 FlatNativeLinuxLibrary.java其中moveOrResizeWindow/showWindowMenu的实现体里保留了一段被注释掉的 JNA 反射调用代码对应原型类X11WmUtils实际执行的则是private static native声明的 JNI 方法——这是原型验证后转为 C的最直接证据。Windows 侧正式实现位于 flatlaf-natives-windows/src/main/cpp/FlatWndProc.cpp。FlatWndProc::WindowProc的WM_NCCALCSIZE/WM_NCHITTEST处理与 JNA 原型逻辑一致但采用 C 原生实现 JNI 回调的方式原生代码通过onNcHitTestMIDGetMethodID(cls, onNcHitTest, (IIZ)I)回调 Java 侧的命中测试逻辑将原生窗口消息处理与Swing 坐标/组件判断分离。Windows 正式类 FlatWindowsNativeWindowBorder.java 的getInstance()会检查FlatNativeWindowsLibrary.isLoaded()即原生库是否成功加载而不是直接使用 JNA 类。集成边界为什么正式库不使用 JNA除了 README 的明文说明源码中还能找到多处JNA 已被 C 取代的痕迹FlatNativeWindowBorder.java 的initialize()中反射加载 JNA 类com.formdev.flatlaf.natives.jna.windows.FlatWindowsNativeWindowBorder的代码整体被注释实际改为调用 flatlaf-core 包内的FlatWindowsNativeWindowBorder.getInstance()JNI 版本FlatNativeLinuxLibrary.java 中同样保留了被注释的 JNA 反射分支正式路径走native方法flatlaf-demo/build.gradle.kts 与 flatlaf-testing/build.gradle.kts 中对:flatlaf-natives-jna的依赖均处于注释状态。从工程角度这种演进是合理的正式库需要通过 FlatNativeLibrary.java 按 OS/架构windows-x86_64、linux-arm64等 classifier加载.dll/.so/.dylib并从java.library.path、jar 旁目录或 jar 内临时解压三种途径获取原生库还会校验getApiVersion()的 API 版本号——这套部署与加载机制更适合静态编译的 JNI 库而非运行时绑定 JNA。在开发环境中构建与使用该子项目虽然正式应用不应依赖flatlaf-natives-jna但作为研究工具开发者可以按以下方式在本地构建# 在仓库根目录执行编译该子项目 ./gradlew :flatlaf-natives-jna:compileJava # 查看其依赖确认 JNA 5.19.1 已解析 ./gradlew :flatlaf-natives-jna:dependencies该子项目依赖flatlaf-core复用SystemInfo/UIScale等工具以及 JNA/JNA-Platform 5.19.1见 gradle/libs.versions.toml。若要临时启用它做实验可参照仓库中已被注释的用法在 flatlaf-demo/build.gradle.kts 中放开implementation( project( :flatlaf-natives-jna ) )并加入对应调用。需要强调的注意事项不要在正式应用中使用该子项目README 明确声明其代码不用于 FlatLaf 库Linux 的X11WmUtils源码更直接标注 DO NOT USE平台前提Windows 侧代码依赖 Windows 10 的窗口消息体系与 DWM 注册表键Linux 侧依赖 X11XToolkit与支持 EWMH 协议的窗口管理器GNOME Mutter、KDE KWin 等且部分行为随窗口管理器实现而异研究价值该子项目保留了完整的消息常量、结构体布局如NCCALCSIZE_PARAMS、MENUITEMINFO的FieldOrder声明与注释中的参考链接指向是学习如何用 JNA 与 Win32/X11 交互的高质量示例——包括坐标换算、HiDPI 缩放、注册表读取、系统菜单操作等细节。效果验证与进一步探索FlatLaf 仓库的测试模块提供了与该原生能力直接相关的验证入口FlatNativeWindowBorderTest.java创建JFrame与模态JDialog用于验证原生窗口边框行为FlatWindowDecorationsTest.java提供 FlatLaf window decorations 复选框可交互式开关FlatLaf.setUseNativeWindowDecorations(...)直观对比系统装饰与 FlatLaf 装饰仓库中的实拍截图 Windows 10 decorations.png 与 Windows 11 decorations.png展示了该特性在两种系统上的实际渲染效果。总而言之flatlaf-natives-jna是 FlatLaf 原生窗口能力研发链路中承上启下的一环它用 JNA 在 Java 侧快速验证了 Windows 窗口过程接管、命中测试、DWM 颜色化与 Linux 窗口管理器协议消息等复杂原生交互随后这些验证成果被移植为高性能的 C/JNI 实现并集成进正式库。对研究 Swing 与操作系统原生层互操作的开发者而言它是一份不可多得的、带有完整调试轨迹的活教材。赞分享桌面应用UI组件【免费下载链接】FlatLafFlatLaf - Swing Look and Feel (with Darcula/IntelliJ themes support)项目地址https://gitcode.com/gh_mirrors/fl/FlatLaf点击查看免费下载相关推荐FlatLaf 原生库Native Libraries全解析Windows / Linux / macOS 构建、分发与加载机制FlatLaf 原生库Native Libraries全解析Windows / Linux / macOS 构建、分发与加载机制 FlatLaf 的 fl桌面应用UI组件AppFlowy桌面端开发Windows/macOS/Linux原生体验AppFlowy桌面端开发Windows/macOS/Linux原生体验 AppFlowy作为Notion的开源替代品其桌面端开发采用了Flutter框架结前端后端企业应用内容协同知识管理AI 应用Coco App 在 Windows 系统上实现原生圆角窗口的最佳实践Coco App 在 Windows 系统上实现原生圆角窗口的最佳实践 背景介绍 在现代桌面应用开发中窗口样式是用户体验的重要组成部分。随着 WindowsAI 应用交互助手前端桌面应用搜索引擎上一篇Sphinx 解析器ParserAPI 详解自定义源解析器与 source_suffix 注册机制下一篇Echo Music架构深剖读懂这款开源音乐播放器的15个模块与设计哲学创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考