我在所有窗口上运行了XQueryTree,并且从数组顶部的最顶部到数组底部的最底部以z顺序获取它们。
然后,我只过滤了每个XGetWindowAttributes
上显示的内容,如果它不是map_state
IsVisible
,则将其删除
对于每个可见窗口,我检查并获取_NET_WM_PID
,_NET_WM_NAME
,x
,y
,height
(height + border_width
) ,和width
(作为width + border_width
)。
我的数据就在这个要点上,也在底部:https://gist.github.com/Noitidart/94562d08f243cd7ca7ec
我的设置是两台显示器。这是他们俩的完整画面:
每个显示器上都有一个透明窗口,即显示器的高度和宽度,它们的标题是" nativeshot_canvas"。
通过查看数据,我发现XQueryTree
窗口被分成多个条目。我的手动分析告诉我:
" nativeshot_canvas"在右侧监视器上
水平菜单栏
左侧监视器上的水平菜单栏
右侧监视器上的垂直停靠
左侧监视器上的垂直停靠
" Javascript Application"窗口
数据图表和我的手动分析如下。
有没有办法以编程方式识别哪个条目与单个窗口相关?在我的手动分析中,我使用了一些我提出的模式,每个窗口组都以_NET_WM_PID
(下面的数据为pid
键)或_NET_WM_NAME
(title
开头。关键数据如下)。我不认为这是一个很好的模式,因为我们看到顶部有一个PID,但它们的宽度和高度都是1.
编辑:仍然坚持如何找到一种保证的方法将这些划分关联到窗口组中。我基本上需要得到所有窗口的所有x,y,宽度和高度,如果有人有任何输入我将是非常好的
var xqRoot = ostypes.TYPE.Window();
var xqParent = ostypes.TYPE.Window();
var xqChildArr = ostypes.TYPE.Window.ptr();
var nChilds = ostypes.TYPE.unsigned_int();
var gpTypeReturned = ostypes.TYPE.Atom();
var gpFormatReturned = ostypes.TYPE.int();
var gpNItemsReturned = ostypes.TYPE.unsigned_long();
var gpBytesAfterReturn = ostypes.TYPE.unsigned_long();
var gpItemsArr = ostypes.TYPE.unsigned_char.ptr();
var geoRoot = ostypes.TYPE.Window();
var geoX = ostypes.TYPE.int();
var geoY = ostypes.TYPE.int();
var geoW = ostypes.TYPE.unsigned_int();
var geoH = ostypes.TYPE.unsigned_int();
var geoBorderWidth = ostypes.TYPE.unsigned_int();
var geoDepth = ostypes.TYPE.unsigned_int();
var wAttr = ostypes.TYPE.XWindowAttributes();
var processWin = function(w) {
if (aOptions.filterVisible) {
var rez_WA = ostypes.API('XGetWindowAttributes')(ostypes.HELPER.cachedXOpenDisplay(), w, wAttr.address());
console.info('wAttr.map_state:', wAttr.map_state.toString());
if (!cutils.jscEqual(wAttr.map_state, ostypes.CONST.IsViewable)) {
return; // continue as this is a hidden window, do not list features, do not dig this window
}
}
var thisWin = {};
// fetch props on thisWin
thisWin.hwndXid = parseInt(cutils.jscGetDeepest(w));
if (aOptions.getPid) {
var rez_pid = ostypes.API('XGetWindowProperty')(ostypes.HELPER.cachedXOpenDisplay(), w, ostypes.HELPER.cachedAtom('_NET_WM_PID'), 0, 1, ostypes.CONST.False, ostypes.CONST.XA_CARDINAL, gpTypeReturned.address(), gpFormatReturned.address(), gpNItemsReturned.address(), gpBytesAfterReturn.address(), gpItemsArr.address());
if (ostypes.HELPER.getWinProp_ReturnStatus(ostypes.CONST.XA_CARDINAL, gpTypeReturned, gpFormatReturned, gpBytesAfterReturn) == 1) {
var jsN = parseInt(cutils.jscGetDeepest(gpNItemsReturned));
if (jsN == 0) {
thisWin.pid = null; // set to null as this window did not have a pid, but i add the key indicating i tested for it and the window had the proerty
} else {
//console.info('gpItemsArr:', gpItemsArr.toString(), 'casted:', ctypes.cast(gpItemsArr, ostypes.TYPE.CARD32).toString(), 'casted to single el:', ctypes.cast(gpItemsArr, ostypes.TYPE.CARD32.array(1).ptr).contents.toString()); // "gpItemsArr:" "ctypes.unsigned_char.ptr(ctypes.UInt64("0x7f229409d710"))" "casted:" "ctypes.unsigned_int(2483672848)" "casted to single el:" "ctypes.unsigned_int.array(1)([2212])" // showing that it must be cast and not just to type cuz its single element, but to array of 1 element
thisWin.pid = parseInt(cutils.jscGetDeepest(ctypes.cast(gpItemsArr, ostypes.TYPE.CARD32.array(1).ptr).contents[0]));
}
ostypes.API('XFree')(gpItemsArr);
} else {
thisWin.pid = undefined; // window didnt even have property
}
}
if (aOptions.getTitle) {
var rez_title = ostypes.API('XGetWindowProperty')(ostypes.HELPER.cachedXOpenDisplay(), w, ostypes.HELPER.cachedAtom('_NET_WM_NAME'), 0, 256 /* this number times 4 is maximum ctypes.char that can be returned*/, ostypes.CONST.False, ostypes.HELPER.cachedAtom('UTF8_STRING'), gpTypeReturned.address(), gpFormatReturned.address(), gpNItemsReturned.address(), gpBytesAfterReturn.address(), gpItemsArr.address());
if (ostypes.HELPER.getWinProp_ReturnStatus(ostypes.HELPER.cachedAtom('UTF8_STRING'), gpTypeReturned, gpFormatReturned, gpBytesAfterReturn) == 1) {
var jsN = parseInt(cutils.jscGetDeepest(gpNItemsReturned));
if (jsN == 0) {
thisWin.title = ''; // window had property but not title
} else {
thisWin.title = ctypes.cast(gpItemsArr, ostypes.TYPE.char.array(jsN).ptr).contents.readString();
}
ostypes.API('XFree')(gpItemsArr);
} else {
thisWin.title = undefined; // window didnt even have property
}
}
if (aOptions.getBounds) {
if (aOptions.filterVisible) {
// then get the info from wAttr as its already available
thisWin.left = parseInt(cutils.jscGetDeepest(wAttr.x));
thisWin.top = parseInt(cutils.jscGetDeepest(wAttr.y));
var borderWidth = parseInt(cutils.jscGetDeepest(wAttr.border_width));
thisWin.borderWidth = borderWidth;
thisWin.width = parseInt(cutils.jscGetDeepest(wAttr.width))/* + borderWidth*/;
thisWin.height = parseInt(cutils.jscGetDeepest(wAttr.height))/* + borderWidth*/;
thisWin.right = thisWin.left + thisWin.width;
thisWin.bottom = thisWin.top + thisWin.height;
} else {
var rez_bounds = ostypes.API('XGetGeometry')(ostypes.HELPER.cachedXOpenDisplay(), w, geoRoot.address(), geoX.address(), geoY.address(), geoW.address(), geoH.address(), geoBorderWidth.address(), geoDepth.address());
thisWin.left = parseInt(cutils.jscGetDeepest(geoX));
thisWin.top = parseInt(cutils.jscGetDeepest(geoY));
var borderWidth = parseInt(cutils.jscGetDeepest(wAttr.border_width));
thisWin.borderWidth = borderWidth;
thisWin.width = parseInt(cutils.jscGetDeepest(wAttr.width))/* + borderWidth*/;
thisWin.height = parseInt(cutils.jscGetDeepest(wAttr.height))/* + borderWidth*/;
thisWin.right = thisWin.left + thisWin.width;
thisWin.bottom = thisWin.top + thisWin.height;
}
}
rezWinArr.splice(0, 0, thisWin);
// dig the win even if it doesnt qualify
var rez_XQ = ostypes.API('XQueryTree')(ostypes.HELPER.cachedXOpenDisplay(), w, xqRoot.address(), xqParent.address(), xqChildArr.address(), nChilds.address()); // interesting note about XQueryTree and workspaces: "The problem with this approach is that it will only return windows on the same virtual desktop. In the case of multiple virtual desktops, windows on other virtual desktops will be ignored." source: http://www.experts-exchange.com/Programming/System/Q_21443252.html
var jsNC = parseInt(cutils.jscGetDeepest(nChilds));
if (jsNC > 0) {
var jsChildArr = ctypes.cast(xqChildArr, ostypes.TYPE.Window.array(jsNC).ptr).contents;
// for (var i=jsNC-1; i>-1; i--) {
for (var i=0; i<jsNC; i++) {
var wChild = jsChildArr[i];
processWin(wChild);
}
ostypes.API('XFree')(xqChildArr);
}
}
processWin(ostypes.HELPER.cachedDefaultRootWindow());