我试图解决我认为会是一个非常简单的问题。我想用整个屏幕内容更新QPixmap。你可以通过这样做获得这样的像素图:

QDesktopWidget *w = QApplication::desktop();

if (w)

{

QRect r = w->screenGeometry();

QPixmap p = QPixmap::grabWindow(w->winId(), 0, 0, r.width(), r.height())

QByteArray bitmap;

}

这样做的问题是QDesktopWidget每次请求时都会从X11服务器重新抓取整个屏幕像素图,即使没有任何变化。

我需要这个代码很快,所以我自己试着这样做。我的出发点是qx11mirror演示,然而,它基本上做同样的事情。它使用XDamage扩展来解决某些事情发生了变化,但是它不是使用受损的矩形信息来更新缓存的pixmap的那部分,而是设置一个“脏”标志,无论如何都会触发整个刷新。

所以我试图修改qx11mirror示例只是更新窗口的损坏部分,但我似乎无法得到任何工作 - 我得到的只是一个空白(黑色)像素图。我正在使用的代码是:

void QX11Mirror::x11Event(XEvent *event)

{

if (event->type == m_damageEvent + XDamageNotify)

{

XDamageNotifyEvent *e = reinterpret_cast(event);

XWindowAttributes attr;

XGetWindowAttributes(QX11Info::display(), m_window, &attr);

XRenderPictFormat *format = XRenderFindVisualFormat(QX11Info::display(), attr.visual);

bool hasAlpha = ( format->type == PictTypeDirect && format->direct.alphaMask );

int x = attr.x;

int y = attr.y;

int width = attr.width;

int height = attr.height;

// debug output so I can see the window pos vs the damaged area:

qDebug() << "repainting dirty area:" << x << y << width << height << "vs" << e->area.x << e->area.y << e->area.width << e->area.height;

XRenderPictureAttributes pa;

pa.subwindow_mode = IncludeInferiors; // Don't clip child widgets

Picture picture = XRenderCreatePicture(QX11Info::display(),

m_window,

format,

CPSubwindowMode,

&pa);

XserverRegion region = XFixesCreateRegionFromWindow(QX11Info::display(),

m_window, WindowRegionBounding);

XFixesTranslateRegion(QX11Info::display(), region, -x, -y);

XFixesSetPictureClipRegion(QX11Info::display(), picture, 0, 0, region);

XFixesDestroyRegion(QX11Info::display(), region);

//QPixmap dest(width, height);

XRenderComposite(QX11Info::display(), // display

hasAlpha ? PictOpOver : PictOpSrc, // operation mode

picture, // src drawable

None, // src mask

dest.x11PictureHandle(), // dest drawable

e->area.x, // src X

e->area.y, // src Y

0, // mask X

0, // mask Y

e->area.x, // dest X

e->area.y, // dest Y

e->area.width, // width

e->area.height); // height

m_px = dest;

XDamageSubtract(QX11Info::display(), e->damage, None, None);

emit windowChanged();

}

else if (event->type == ConfigureNotify)

{

XConfigureEvent *e = &event->xconfigure;

m_position = QRect(e->x, e->y, e->width, e->height);

emit positionChanged(m_position);

}

}

谁能指出我正确的方向? XRender,XDamage和其他X11扩展的文档非常糟糕。

在XCopyArea上使用XRender的原因

以下文字摘自此处。

如果你想使用核心协议,完全可以为窗口创建一个GC并使用XCopyArea()来复制窗口的内容,但是由于Composite扩展暴露了新的视觉效果(例如带有alpha通道的视觉效果),所以没有保证源drawable的格式与目标的格式相匹配。使用核心协议会导致匹配错误,这是Xrender扩展不会发生的事情。

此外,核心协议不了解alpha通道,这意味着它无法合成使用新ARGB视觉效果的窗口。当源和目标具有相同的格式时,从X11R6.8开始使用核心协议也没有性能优势。该版本也是第一个支持新的Composite扩展。

总而言之,没有任何缺点,只有在这些操作的核心协议上选择Xrender才有优势。

linux通过xrander添加分辨率,使用X11,XDamage,XRender和其他技巧保留屏幕内容的QPixmap副本...相关推荐

  1. linux下无对应分辨率,linux mint 向“显示(display)”面板添加没有提供的分辨率选项,使虚拟机中的linux mint可以全屏显示...

    最近使用VM player安装linux mint,运行后不能铺满全屏.在设置分辨率时,发现没有1440×900.1920x1080等的选项,何其的蛋疼啊. 尝试谷歌一下,看能不能修改.果然找到,有两 ...

  2. Linux图形系统框架 与 X协议 X11 XFree86 Xorg X-Window WM

    文章目录 前言 GUI(Graphical User Interface) Windowing system(窗口系统) X Window System 窗口管理器.GUI工具集.桌面环境及其它 3D ...

  3. linux修改屏幕大小和分辨率,linux手动更改显示器分辨率

    我的一台11寸上网本,装的ubuntu.最近外接了一个19寸显示器.分辨率最多只能是1024x768.显示器设置里显示"未知"显示器. 用下面的命令可以看到显卡的信息: $ lsp ...

  4. linux终端分辨率对应表,Linux下设置终端分辨率,最全的VGA代码和分辨率对照表...

    一般安装完linux后默认的kernel给的tty分辨率是非常有限的,解决的方法就是给kernel传递VGA参数.对应的要修改的配置文件为 /etc/grub.conf,(或者 /boot/grub/ ...

  5. linux自定义刷新率,Linux下设置其分辨率及刷新率

    在Windows下,显示模式是用分辨率和刷新率来设置的. 其设置也是非常简单的. 而在Linux设置就不太方便了,虽然也在各个桌面环境下有相关的工具, 但要完全设置好,都离不开X的配置文件/etc/X ...

  6. 计划任务执行php文件,linux系统下添加计划任务执行php文件方法

    在web开发过程中,经常需要设定一些定期执行的任务,比如商品定时上下架.我们以php文件为例,讲解linux下的计划任务. 方法/步骤 1.打开linux系统命令行界面. 在命令行界面中输入如下命令: ...

  7. linux中ftp用户,linux中怎么添加ftp用户

    Linux下创建用户是很easy的事情了,只不过不经常去做这些操作,时间久了就容易忘记.那么linux中怎么添加ftp用户,下面跟着学习啦小编一起来了解一下吧. linux中怎么添加ftp用户 在li ...

  8. Linux/ubuntu 服务器开启6010端口-X11服务-ssh连接

    此文首发于我的个人博客:Linux/ubuntu 服务器开启6010端口-X11服务-ssh连接 - zhang0peter的个人博客 晚上在检查我的Linux-ubuntu服务器的端口状况时发现开启 ...

  9. 【Linux】无法添加用户,报“useradd: cannot open /etc/passwd”问题解决过程记录

    [Linux]无法添加用户,报"useradd: cannot open /etc/passwd"问题解决过程记录 参考文章: (1)[Linux]无法添加用户,报"us ...

最新文章

  1. Unexpected key(s) in state_dict: module.backbone.bn1.num_batches_tracked
  2. 单片机定时器精准定时_8051单片机(STC89C52)定时器实现10ms精准定时
  3. python写界面进度条程序_Python中如何写控制台进度条的整理
  4. 下面由我来给大家表演个绝活
  5. Html5中新增的表单元素详解
  6. ubuntu所有php扩展php-7.0扩展列表
  7. 腾讯广告算法大赛 | 复赛第二周最佳进步奖得主心得分享
  8. linux根文件分析,Linux根文件系统详解
  9. 脚本中调用别的脚本,如何得到执行结果?
  10. Python:批量修改图片的后缀名(模板)
  11. 天勤2022数据结构(二)栈和队列
  12. CCS之产生两个正弦波的仿真
  13. 全网目前最全python例子
  14. InnoDB中的页合并与分裂
  15. python3查找元素在数组位置_Python:查找数组中元素的位置
  16. 机器学习案例:孕妇吸烟与胎儿健康
  17. 分数换算小数补0法_小学数学概念+知识点顺口溜汇总+常用单位换算汇总
  18. 你真的知道面向过程和面向对象的区别吗?
  19. 网络安全kali渗透学习 web渗透入门 使用msf扫描靶机上mysql服务的空密码
  20. 掌握SQL Monitoring这些特性,SQL优化通通不在话下

热门文章

  1. ios ffmpeg h264 encode
  2. ios录制视频时audio丢失
  3. 计算机基础(八):linux编程规范总结
  4. 深度学习自学(七):腾讯移动端开源框架ncnn学习总结
  5. 阿里云服务器如何快速搭建Docker环境
  6. 订阅号获取openid_小程序订阅消息
  7. python和matlab的区别_我为什么选择Python,不是Matlab和R语言呢?
  8. python多线程queue_python多线程+队列(提高爬虫时效性)
  9. phpcms 指定id范围 调用_Dubbogo 源码笔记(二)客户端调用过程
  10. k8s springboot 文件_用Kubernetes部署Springboot或Nginx,也就一个文件的事