Skip to content

fix: Implement X11 screenshot workaround for Qt6#773

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:develop/snipefrom
dengzhongyuan365-dev:commit20251209
Dec 11, 2025
Merged

fix: Implement X11 screenshot workaround for Qt6#773
deepin-bot[bot] merged 1 commit into
linuxdeepin:develop/snipefrom
dengzhongyuan365-dev:commit20251209

Conversation

@dengzhongyuan365-dev

Copy link
Copy Markdown
Member
  • Added a workaround using XGetImage for capturing screenshots in X11 environments with Qt6 to address issues with QScreen::grabWindow under high DPI settings.
  • Updated ScreenGrabber class to include conditional compilation for X11 support and integrated the new screenshot method.
  • Modified main application logic to disable high DPI scaling when using the X11 workaround, ensuring consistent behavior across different display setups.

This update improves screenshot reliability in multi-screen and high DPI scenarios on X11.

bug: https://pms.uniontech.com/bug-view-342909.html

- Added a workaround using XGetImage for capturing screenshots in X11 environments with Qt6 to address issues with QScreen::grabWindow under high DPI settings.
- Updated ScreenGrabber class to include conditional compilation for X11 support and integrated the new screenshot method.
- Modified main application logic to disable high DPI scaling when using the X11 workaround, ensuring consistent behavior across different display setups.

This update improves screenshot reliability in multi-screen and high DPI scenarios on X11.

bug: https://pms.uniontech.com/bug-view-342909.html
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

我来对这个代码变更进行详细审查:

  1. 代码逻辑和功能分析:
  • 这个变更主要是为了解决 Qt6 在 X11 环境下的一个 bug,即在多屏+高DPI+非对齐布局时 QScreen::grabWindow 返回的截图会出现花屏/错乱的问题
  • 解决方案是:在 Qt6 X11 环境下禁用高 DPI 缩放,并使用 X11 原生 API XGetImage 直接抓取根窗口
  • 代码通过条件编译宏 USE_X11_GETIMAGE 来控制是否使用新的解决方案
  1. 代码质量评价:
    优点:
  • 代码结构清晰,通过条件编译很好地隔离了 Qt5 和 Qt6 的不同实现
  • 添加了详细的注释说明了问题和解决方案
  • 日志记录完善,便于调试
  • 错误处理完善,包括 X11 Display 打开失败、XGetImage 失败等情况

可以改进的地方:

  • grabWithXGetImage 函数较长,可以考虑将 XImage 到 QImage 的转换逻辑抽取为独立函数
  • 缺少对 XGetImage 返回图像格式的验证,直接假设是 32 位 RGB 格式可能不够安全
  1. 性能考虑:
  • XGetImage 抓取整个根窗口然后裁剪的方式在请求小区域时可能效率不高
  • XImage 到 QImage 的逐像素转换较慢,可以考虑使用更高效的内存拷贝方式
  1. 安全性建议:
  • XOpenDisplay 没有指定具体的 display,可能存在安全隐患
  • 缺少对 XGetImage 返回数据的验证,可能导致内存访问越界
  • 建议添加对图像格式和深度的检查

具体改进建议:

  1. 在 grabWithXGetImage 中添加图像格式验证:
// 验证图像格式
if (ximg->bits_per_pixel != 32 && ximg->bits_per_pixel != 24) {
    qCWarning(dsrApp) << "[XGetImage] Unsupported image format:" << ximg->bits_per_pixel;
    XDestroyImage(ximg);
    XCloseDisplay(dpy);
    ok = false;
    return QPixmap();
}
  1. 优化 XImage 到 QImage 的转换:
// 使用内存拷贝代替逐像素操作
if (ximg->bits_per_pixel == 32 && ximg->byte_order == LSBFirst) {
    memcpy(qimg.bits(), ximg->data, ximg->height * ximg->bytes_per_line);
} else {
    // 回退到逐像素转换
    for (int row = 0; row < ximg->height; ++row) {
        for (int col = 0; col < ximg->width; ++col) {
            // ... 原有转换逻辑
        }
    }
}
  1. 添加对 X11 Display 的安全检查:
Display *dpy = XOpenDisplay(NULL);
if (!dpy) {
    qCWarning(dsrApp) << "[XGetImage] Failed to open X11 Display";
    ok = false;
    return QPixmap();
}

// 验证 display 的能力
int major, minor;
if (!XShmQueryVersion(dpy, &major, &minor, NULL)) {
    qCWarning(dsrApp) << "[XGetImage] X11 display does not support required features";
    XCloseDisplay(dpy);
    ok = false;
    return QPixmap();
}
  1. 优化小区域截图的性能:
// 如果请求的区域远小于整个屏幕,直接抓取指定区域
if (rect.width() * rect.height() < rootAttr.width * rootAttr.height / 4) {
    ximg = XGetImage(dpy, root, rect.x(), rect.y(), rect.width(), rect.height(), AllPlanes, ZPixmap);
    // 直接返回,无需裁剪
} else {
    // 抓取整个屏幕然后裁剪
    ximg = XGetImage(dpy, root, 0, 0, rootAttr.width, rootAttr.height, AllPlanes, ZPixmap);
}
  1. 在 .gitignore 中:
  • 建议将 AI config 改为注释格式保持一致性
  • 可以考虑添加更具体的规则,如 *.x11_paint_demo/

总体来说,这是一个合理的解决方案,但可以在性能和安全性方面做一些改进。建议在实施这些改进时,先在测试环境中验证效果。

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: dengzhongyuan365-dev, lzwind

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@dengzhongyuan365-dev

Copy link
Copy Markdown
Member Author

/forcemerge

@deepin-bot deepin-bot Bot merged commit 7c9cb05 into linuxdeepin:develop/snipe Dec 11, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants