Akvicor
Akvicor
发布于 2026-09-13 / 1 阅读
0
0

Debian13+i3 X11环境下,Chrome 双屏不同分辨率下渲染错位

  • 环境:Debian 13 (trixie) + i3 (X11) + 双显示器(2560x1440 与 1920x1080)

  • 问题版本:Google Chrome 153.0.8010.36

  • 修复版本:Google Chrome 151.0.7922.173-1

现象

同一个 Chrome 窗口在不同分辨率的屏幕之间出现了渲染表面(drawing surface)尺寸与窗口几何尺寸不一致的问题。

  1. 在 2K(2560x1440)屏幕上最大化 Chrome 后,窗口看起来占满了整块屏幕,但只有左下角有实际内容:上半部分是桌面壁纸,页面内容整体向下偏移;标签栏、地址栏都不可见,只有页面主体渲染在下方约三分之二区域。

  2. 在 1080P(1920x1080)屏幕上,窗口里页面按 2560 宽度居中,标签栏同样不可见,只剩白色背景和居中的搜索框。

环境与布局

$ xrandr --query
Screen 0: minimum 320 x 200, current 4480 x 1440, maximum 16384 x 16384
HDMI-A-0 connected primary 2560x1440+1920+0 (normal)
DisplayPort-1 connected 1920x1080+0+0 (normal)
  • 1080P 屏在左(x = 0..1920),2K 主屏在右(x = 1920..4480)。

  • i3 工作区通过 i3-msg 管理,窗口管理器把窗口最大化到工作区(扣除 i3bar 后为 2560x1419 / 1920x1059)。

$ xdpyinfo | grep -i dimensions
  dimensions:    4480x1440 pixels
$ wmctrl -m
Name: i3

排查过程

把"窗口几何"和"窗口实际绘制表面"分开测量。X11 下窗口的几何由窗口管理器设置,而窗口内容由客户端(Chrome)自行分配 buffer 绘制;两者不一致时,就会出现"占了空间但没画满"。

对比窗口几何与 _NET_WM_OPAQUE_REGION

_NET_WM_OPAQUE_REGION 是客户端上报的"这块区域内的像素完全不透明"的矩形,直接反映客户端认为自己绘制了多大范围。

$ wmctrl -lGx | grep -i chrome
0x01e000bd  5 1920 25   2560 1415 google-chrome.Google-chrome  New Tab - Google Chrome
0x01e0001c  2 1926 27   1273 1411 google-chrome.Google-chrome  ProxyGroupBase.dconf ...
0x01e00025  2 3205 27   1273 1411 google-chrome.Google-chrome  文章 - Akvicor World ...
0x01e00044  0 0    25   1920 1055 google-chrome.Google-chrome  明日方舟仙术杯#9 ...

对问题窗口(0x01e000bd)取属性:

$ xwininfo -id 0x01e000bd | grep -E 'Absolute|Width|Height'
  Absolute upper-left X:  1920
  Absolute upper-left Y:  23
  Width:  2560
  Height: 1415

$ xprop -id 0x01e000bd _NET_WM_OPAQUE_REGION
_NET_WM_OPAQUE_REGION(CARDINAL) = 0, 0, 1920, 1055

关键矛盾:窗口几何是 2560x1415,但客户端上报的不透明区域只有 1920x1055——恰好是 1080P 屏的工作区尺寸

作为对照,同一块 2K 屏上另外两个直接布局的 Chrome 窗口(1273x1411)上报的 opaque region 与几何完全一致,是正常的:

$ xprop -id 0x01e0001c _NET_WM_OPAQUE_REGION
_NET_WM_OPAQUE_REGION(CARDINAL) = 0, 0, 1273, 1411

说明只有"被最大化到整块 2K 屏"的那个窗口尺寸错乱,不是所有窗口都坏。

抓取窗口自身的绘制内容

要确认 Chrome 到底画了多大、画在哪里,直接抓取该窗口的重定向 pixmap,再用 -trim 去掉四周纯色边,得到实际有内容的区域:

$ import -window 0x01e000bd -silent win.png
$ convert win.png -trim info:
win.png PNG 1920x1055 2560x1415+0+360 8-bit ...

结果精确为 1920x1055+0+360:在 2560x1415 的窗口里,只有 x=0..1920, y=360..1415 有内容,其余全黑(未绘制)。这解释了"只有左下角有内容"——内容被锚定在窗口左下角,垂直方向少了 360 像素。

再看具体像素,确认边界:

$ convert win.png -format "%[pixel:p{0,0}]"        info:   # srgb(0,0,0)
$ convert win.png -format "%[pixel:p{0,1414}]"     info:   # srgb(255,255,255)
$ convert win.png -format "%[pixel:p{2000,1000}]"  info:   # srgb(0,0,0)

排除合成器因素

为确认是否由合成器(compositor)按 opaque region 裁剪导致,临时关闭合成器后重新截图对比:现象完全一致,上半部分依旧没有内容(只是原本透出的壁纸变成了黑色)。由此排除合成器,问题出在 Chrome 自身分配的绘制表面。

排除窗口管理器布局

用 i3 直接把窗口换一个输出:

i3-msg '[id=31457284] move container to output DisplayPort-1'

换屏后窗口几何和不透明区域都正确重算1920x1055;再移回 2K 又正确变回 2560x1415

这说明:

  • i3 的布局和跨屏移动没有问题;

  • Chrome 本身具备重算表面的能力,只是在某些创建/恢复路径下没有做。

反向复现:1080P 上的对称错误

在 1080P 屏幕上出现的是完全对称的错误:窗口几何 1920x1055,但 _NET_WM_OPAQUE_REGION = 0,0,2560,1415(2K 尺寸)。抓取 pixmap 后页面内容按 2560 宽居中(搜索框中心落在 x=1280),标签栏在可视区域之外。

在 1080P 聚焦状态下用 Chrome 新建窗口,新窗口却总是落在 2K 主屏上(不跟随聚焦的显示器),且表面正确;而被放到 1080P 的那个窗口表面仍是 2K 尺寸。

根因判断

Chromium 在 X11 下没有根据窗口实际所在的显示器重新分配绘制表面(_NET_WM_OPAQUE_REGION 及内部 buffer),而是沿用了另一块屏幕的尺寸。

  1. Chrome 会把窗口位置(window_placement)持久化到 profile。问题窗口保存的是一个"在 1080P 上最大化"的 placement。

  2. 启动/恢复时,i3 按工作区把窗口放到了 2K 屏并最大化。

  3. Chrome 的窗口管理代码仍按旧屏幕(1080P)计算表面尺寸,于是绘制 buffer 停在 1920x1055,并锚定在窗口左下角。

这属于 Chromium X11 的已知问题族:

  • window.screen does not update on Linux X11 issues.chromium.org/368281197:窗口移动到不同尺寸的屏幕后,window.screen 不更新,仍返回原屏幕尺寸。

  • [regression] Not able to move maximized windows to second display issues.chromium.org/507318377:最近版本出现"最大化窗口无法留在副屏"的回归。

修复

降级 Chrome 并固定版本

由于根因在 Chrome 153 的回归,最终选择降级回升级前的 151。

Google 的 apt 源不再提供历史版本目录,但旧版本 deb 可按版本号直接下载:

文件元数据

  • 文件名:google-chrome-stable_151.0.7922.173-1_amd64.deb

  • 大小:134M

  • SHA-256:878e5ab495b8a694980fca61bc09b37e651ccedce2291c73434d16e48a2646fd

版本号中的 -1 是 Debian 修订号,属于文件名的一部分,不能省略。若需其他版本,把版本号替换为对应值即可(已验证 151.0.7922.173-1151.0.7922.137-1152.0.7977.82-1 均可下载)。

# 1. 下载升级前的版本
$ curl -L -C - --retry 5 \
    -o google-chrome-stable_151.0.7922.173-1_amd64.deb \
    'https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_151.0.7922.173-1_amd64.deb'

# 2. 校验包完整性
$ dpkg-deb -I google-chrome-stable_151.0.7922.173-1_amd64.deb | grep -E 'Package|Version|Architecture'
$ dpkg-deb -c google-chrome-stable_151.0.7922.173-1_amd64.deb >/dev/null && echo OK

# 3. 关闭 Chrome 后降级安装
$ pkill -TERM -x chrome
$ sudo dpkg -i google-chrome-stable_151.0.7922.173-1_amd64.deb

# 4. 固定版本,防止 apt 再升回 153
$ sudo apt-mark hold google-chrome-stable

注意:sudo dpkg -i 会按版本号降级。

若 153 之后的版本修复了该问题,可 apt-mark unhold 后正常升级


评论