给应用程序加水印是保护数据的一种方式,window上可以通过给进程通过注入的方法给进程的窗口创建一个同大小的副窗口,在副窗口上绘制水印内容,同时设置副窗口透明同时透传事件,这样就可以达到在源窗口上显示水印的效果且不影响程序使用,借助window的思路想在国产化linux上完成窗口水印,发现创建的副窗口无法对源窗口透明,使用了qt, gtk甚至是x11 api,尝试各个参数都显示黑色,查看x11文档,发现透明效果是通过x11的窗口合成器例如xcompmgr,查看源码发下,窗口合成器在处理窗口的透明效果时仅仅处理toplevel窗口(顶层窗口)间的透明,不处理子窗口的透明属性,我们日常中碰到的子窗口透明,例如使用qt创建的应用,其子窗口透明时qt框架自己渲染出来的,而对应元素的x11窗口句柄,子窗口无法实现透明效果,下面的代码是摘自有xcompmgr源码main函数中的部分,其中的add_win函数添加的窗口是合成器要处理的窗口,XQueryTree获取的只有顶层窗口,因此在国产化linux上实现窗口水印不能单纯的通过创建透明副窗口来实现。
root_width = DisplayWidth (dpy, scr);
root_height = DisplayHeight (dpy, scr);
rootPicture = XRenderCreatePicture (dpy, root,
XRenderFindVisualFormat (dpy,
DefaultVisual (dpy, scr)),
CPSubwindowMode,
&pa);
blackPicture = solid_picture (dpy, True, 1, 0, 0, 0);
if (compMode == CompServerShadows)
transBlackPicture = solid_picture (dpy, True, 0.3, 0, 0, 0);
allDamage = None;
clipChanged = True;
XGrabServer (dpy);
if (autoRedirect)
XCompositeRedirectSubwindows (dpy, root, CompositeRedirectAutomatic);
else
{
XCompositeRedirectSubwindows (dpy, root, CompositeRedirectManual);
XSelectInput (dpy, root,
SubstructureNotifyMask|
ExposureMask|
StructureNotifyMask|
PropertyChangeMask);
XShapeSelectInput (dpy, root, ShapeNotifyMask);
XQueryTree (dpy, root, &root_return, &parent_return, &children, &nchildren);
for (unsigned int i = 0; i < nchildren; i++)
add_win (dpy, children[i], i ? children[i-1] : None);
XFree (children);
}
XUngrabServer (dpy);
ufd.fd = ConnectionNumber (dpy);
ufd.events = POLLIN;
if (!autoRedirect)
paint_all (dpy, None);
for (;;)