Skip to content

JEP 263: HiDPI Graphics on Windows and Linux | 在 Windows 和 Linux 上支持 HiDPI 图形

摘要

在 Windows 和 Linux 上实现 HiDPI 图形。

动机

开发者和用户对在 HiDPI 显示器上运行的应用程序有一些基本期望:

  • Windows 和 GUI 组件应根据平台建议具有适当的大小,

  • 无论 HiDPI 设置的默认缩放如何,文本应保持清晰,且

  • 图标和图像应平滑,并且最好具有适合显示器像素密度的细节。

不幸的是,即使在 HiDPI 显示器上,Java 应用程序仍然基于像素在 Windows 和 Linux 上进行大小和呈现,这些显示器的像素密度可能是传统显示器的 2 到 3 倍。这导致 GUI 组件和窗口小了 2 到 3 倍,因此无法阅读或有效地交互。

JDK 已经支持在 Mac OS X 上的 HiDPI“视网膜显示器”,并以适当的尺寸为显示屏的密度提供清晰的文本和图像。Mac 的“视网膜”支持已经为支持所有平台上的 HiDPI 显示器提供了相当多的基础工作,但是各个平台处理 HiDPI 的方式存在差异,这意味着还需要进一步工作来推广 Mac 上的工作。

现在应该为 Windows 和 Linux 平台提供同样的自动缩放和调整大小功能。

描述

Windows 上的 HiDPI

Windows 控制面板提供了许多途径,让用户在桌面上请求对组件和窗口进行缩放(自 Windows XP 以来以各种形式提供)。某些操作系统版本还提供了自动缩放未声明为“DPI-aware”的应用程序的功能。对于“DPI-unaware”应用程序的默认缩放可能会导致许多视觉伪像,包括模糊的窗口、不准确的布局和被裁剪的文本,因此 Java 运行时长期以来已经声明自己是“DPI-aware”,以避免模糊和布局问题。然而,根据 DPI 进行内容缩放并不是一项简单的任务,而且由于大多数显示器密度只需要进行 25% 的小幅缩放,因此决定忽略推荐的缩放准则和策略,继续以 1:1 像素缩放渲染 AWT 和 Swing 组件,并且 JDK 应用程序稍微小于标准尺寸,但文本和图形清晰。

然而,最近,显示器的像素密度大幅增加,现在很容易找到像素密度是当初做出这些决策时常见显示器密度的 2 到 3 倍的笔记本电脑。因此,这些较新的 Windows 机器上的 Java 应用程序有时可能会非常小,以至于无法使用 - 这不再是“稍微小一点对比模糊窗口”的情况,因此我们需要正确地缩放应用程序窗口。

Windows API 提供了度量、机制和指南来编写 DPI-aware 应用程序,使 UI 在各种 DPI 显示设置下具有一致的外观,并响应用户为使 UI 足够大以便用户可以舒适地与 UI 组件交互的偏好设置。

Windows Direct2D 图形 API 会自动遵循系统 DPI,使用 DIPs(设备无关像素)来表示坐标,使位图具有 DPI,并通过考虑 DPI 正确缩放它们。然而,AWT 和 Swing 库不是基于 Direct2D 图形 API 构建的。

Windows 7 及更高版本提供了许多方法来获取桌面的水平和垂直 DPI,包括GetDesktopDpi方法,在 Windows 8.1 中还有GetDpiForMonitor方法和WM_DPICHANGED消息。这些值可以用于在 AWT/Swing 库中支持 HiDPI 的情况下缩放窗口大小、鼠标坐标和字体。必要的缩放支持已经存在于 Java2D 渲染层中,但我们需要将这些值广告给 Swing 和 AWT,并更新它们的组件以识别和尊重缩放因子。这种支持包括确保期望的渲染比例因子提供给 Java2D Graphics对象,使用适当的缩放因子对中间渲染图像进行渲染,并重新审查关于渲染调用中的坐标如何映射到像素的任何假设。

Linux 上的 HiDPI

GTK+ 3 库已经实现了 HiDPI 支持。在使用 HiDPI 显示器时,GTK 库会自动缩放应用程序。

而 Java2D 和 AWT 使用的是不支持 HiDPI 的 XLib 库。因此,当前的 Java 应用程序在 Linux 上的 HiDPI 显示器上可能会看起来是 2 到 3 倍太小。

此外,任何使用 GTK 外观样式的 Java 应用程序在 GTK 库中获得 HiDPI 支持时,窗口和其他组件的大小可能与已经放大 2-3 倍以满足 HiDPI 要求的 GTK 组件匹配。这可能导致一些问题,比如JDK-8058742中所描述的问题。

替代方案

开发人员在 HiDPI 显示器上运行时可以手动缩放应用程序中的所有 GUI 元素,但这需要对应用程序进行大量的重构工作,并且 Swing 和 AWT 组件不适合从外部尝试缩放它们。

测试

以下测试应在 HiDPI 显示器上进行。最好使用各种屏幕缩放比例 - 192 DPI 和 144 DPI 是一个很好的最小支持矩阵。请注意,可以使用 Windows 控制面板将非常高的 DPI 显示器设置为较低的人工 DPI,因此不一定需要额外的系统,但测试运行之间必须重新配置它们。此外,在 Windows 上更改 DPI 通常需要重新启动以使新的 DPI 对应用程序可见。

在 Windows 上,可以在控制面板中设置 DPI 设置。不同版本的控制面板和允许的设置存在于 Windows 7、Windows 8.1 和较旧的 Windows 版本中,但它们都倾向于向应用程序提供相同类型的信息(X 和 Y 的指定 DPI),因此当前不需要在控制面板的变化下进行额外的测试,这只是影响测试环境配置方式的细节。

在 Linux 上,可以使用 GDK_SCALE 环境变量来模拟 DPI 设置,用于 GTK+ 3,或使用 GNOME 3 的 scaling-factor 设置。

应检查以下内容:

  • 文本不应模糊
  • 组件(标签和按钮)中的文本不应被裁剪
  • AWT/Swing上的UI组件布局应保持合理(即无重叠或奇怪的间隙)
  • 当应用程序或测试用例提供时,应在 AWT/Swing 对话框和组件上使用高分辨率图标
  • 应用程序应正确处理鼠标事件
  • 应用程序的大小应与良好行为的 DPI-aware 本地应用程序类似