X11 - Xrandr 给我错误的监视器
X11 - Xrandr giving me false monitors
我试图找到所有显示器及其坐标(宽度 w
、高度 h
、x origin/top-left-most x
和 y origin/top-left-most y
) 并使用此代码,它在某些系统上运行良好。但在其他系统上,我得到错误和重复的条目。如果我测试监视器是否是镜像,我是否能够避免这些 dupilcate/false 监视器条目?如何测试是否镜像?
所以这是我的代码:
// start - get all monitor resolutions
var screen = XRRGetScreenResources(getXOpenDisplay(), getDefaultRootWindow(getXOpenDisplay()));
var noutputs = screen.noutput;
for (var i=noutputs-1; i>=0; i--) {
var info = XRRGetOutputInfo(getXOpenDisplay(), screen, screen.outputs[i]);
if (info.connection == RR_Connected) {
var ncrtcs = info.ncrtc;
for (var j=ncrtcs-1; j>=0; j--) {
var crtc_info = XRRGetCrtcInfo(getXOpenDisplay(), screen, infoCrtcs[j]);
console.info('screen #' + i + ' mon#' + j + ' details:', crtc_info.x, crtc_info.y, crtc_info.width, crtc_info.height);
collMonInfos.push({
x: crtc_info.x,
y: crtc_info.y,
w: crtc_info.width,
h: crtc_info.height
});
XRRFreeCrtcInfo(crtc_info);
}
}
XRRFreeOutputInfo(info);
}
XRRFreeScreenResources(screen);
console.info('JSON:', JSON.stringify(collMonInfos));
// end - get all monitor resolutions
并将其输出到日志:
"screen #4 mon#0 details:" 0 0 0 0
"screen #3 mon#1 details:" 0 0 1920 1200
"screen #3 mon#0 details:" 1920 469 1366 768
"screen #2 mon#1 details:" 0 0 1920 1200
"screen #2 mon#0 details:" 1920 469 1366 768
"screen #1 mon#1 details:" 0 0 1920 1200
"screen #1 mon#0 details:" 1920 469 1366 768
"screen #0 mon#1 details:" 0 0 1920 1200
"screen #0 mon#0 details:" 1920 469 1366 768
这是 JSON 格式:
[{
"x": 0,
"y": 0,
"w": 0,
"h": 0
}, {
"x": 0,
"y": 0,
"w": 1920,
"h": 1200
}, {
"x": 1920,
"y": 469,
"w": 1366,
"h": 768
}, {
"x": 0,
"y": 0,
"w": 1920,
"h": 1200
}, {
"x": 1920,
"y": 469,
"w": 1366,
"h": 768
}, {
"x": 0,
"y": 0,
"w": 1920,
"h": 1200
}, {
"x": 1920,
"y": 469,
"w": 1366,
"h": 768
}, {
"x": 0,
"y": 0,
"w": 1920,
"h": 1200
}, {
"x": 1920,
"y": 469,
"w": 1366,
"h": 768
}]
我真的只有 2 台显示器,1920x1200 一台和 1366x768 一台。为什么会出现所有其他条目以及如何进行测试以避免(而不是根据重复项或 0 h/w 回想起来过滤掉)?
您不必要地遍历每个 output,然后遍历每个 monitor。所以你收到了重复的条目。您不必为每个输出调用 XRRGetOutputInfo
,因为您需要的所有数据(显示器数量)都可以在 XRRGetScreenResources
返回的结构中找到。
这是有效的 C 代码(至少对我而言):
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
int main(void) {
Display *d = XOpenDisplay(getenv("DISPLAY"));
Window w = DefaultRootWindow(d);
XRRScreenResources *xrrr = XRRGetScreenResources(d, w);
XRRCrtcInfo *xrrci;
int i;
int ncrtc = xrrr->ncrtc;
for (i = 0; i < ncrtc; ++i) {
xrrci = XRRGetCrtcInfo(d, xrrr, xrrr->crtcs[i]);
printf("%dx%d+%d+%d\n", xrrci->width, xrrci->height, xrrci->x, xrrci->y);
XRRFreeCrtcInfo(xrrci);
}
XRRFreeScreenResources(xrrr);
return 0;
}
已接受的答案对我不起作用。我发现这样做的正确方法是:
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
int main(void) {
Display *display = XOpenDisplay(NULL);
if (NULL == display) {
perror("No DISPLAY in environment!");
exit(EXIT_FAILURE);
}
Window window = DefaultRootWindow(display);
XRRScreenResources *screenr = XRRGetScreenResources(display, window);
// This is the key right here. Use XRRScreenResources::noutput
int output = screenr->noutput;
for (int i = 0; i < output; ++i) {
XRROutputInfo* out_info = XRRGetOutputInfo(display, screenr, screenr->outputs[i]);
if (NULL != out_info && out_info->connection == RR_Connected) {
XRRCrtcInfo* crt_info = XRRGetCrtcInfo(display, screenr, out_info->crtc);
printf("%s\t%dx%d+%d+%d\n", out_info->name,
crt_info->width,
crt_info->height,
crt_info->x,
crt_info->y);
XRRFreeCrtcInfo(crt_info);
}
XRRFreeOutputInfo(out_info);
}
XRRFreeScreenResources(screenr);
XCloseDisplay(display);
return 0;
}
正如我在代码注释中所说,诀窍是使用 XRRScreenResources::noutput
而不是 XRRScreenResources::ncrtc
我试图找到所有显示器及其坐标(宽度 w
、高度 h
、x origin/top-left-most x
和 y origin/top-left-most y
) 并使用此代码,它在某些系统上运行良好。但在其他系统上,我得到错误和重复的条目。如果我测试监视器是否是镜像,我是否能够避免这些 dupilcate/false 监视器条目?如何测试是否镜像?
所以这是我的代码:
// start - get all monitor resolutions
var screen = XRRGetScreenResources(getXOpenDisplay(), getDefaultRootWindow(getXOpenDisplay()));
var noutputs = screen.noutput;
for (var i=noutputs-1; i>=0; i--) {
var info = XRRGetOutputInfo(getXOpenDisplay(), screen, screen.outputs[i]);
if (info.connection == RR_Connected) {
var ncrtcs = info.ncrtc;
for (var j=ncrtcs-1; j>=0; j--) {
var crtc_info = XRRGetCrtcInfo(getXOpenDisplay(), screen, infoCrtcs[j]);
console.info('screen #' + i + ' mon#' + j + ' details:', crtc_info.x, crtc_info.y, crtc_info.width, crtc_info.height);
collMonInfos.push({
x: crtc_info.x,
y: crtc_info.y,
w: crtc_info.width,
h: crtc_info.height
});
XRRFreeCrtcInfo(crtc_info);
}
}
XRRFreeOutputInfo(info);
}
XRRFreeScreenResources(screen);
console.info('JSON:', JSON.stringify(collMonInfos));
// end - get all monitor resolutions
并将其输出到日志:
"screen #4 mon#0 details:" 0 0 0 0
"screen #3 mon#1 details:" 0 0 1920 1200
"screen #3 mon#0 details:" 1920 469 1366 768
"screen #2 mon#1 details:" 0 0 1920 1200
"screen #2 mon#0 details:" 1920 469 1366 768
"screen #1 mon#1 details:" 0 0 1920 1200
"screen #1 mon#0 details:" 1920 469 1366 768
"screen #0 mon#1 details:" 0 0 1920 1200
"screen #0 mon#0 details:" 1920 469 1366 768
这是 JSON 格式:
[{
"x": 0,
"y": 0,
"w": 0,
"h": 0
}, {
"x": 0,
"y": 0,
"w": 1920,
"h": 1200
}, {
"x": 1920,
"y": 469,
"w": 1366,
"h": 768
}, {
"x": 0,
"y": 0,
"w": 1920,
"h": 1200
}, {
"x": 1920,
"y": 469,
"w": 1366,
"h": 768
}, {
"x": 0,
"y": 0,
"w": 1920,
"h": 1200
}, {
"x": 1920,
"y": 469,
"w": 1366,
"h": 768
}, {
"x": 0,
"y": 0,
"w": 1920,
"h": 1200
}, {
"x": 1920,
"y": 469,
"w": 1366,
"h": 768
}]
我真的只有 2 台显示器,1920x1200 一台和 1366x768 一台。为什么会出现所有其他条目以及如何进行测试以避免(而不是根据重复项或 0 h/w 回想起来过滤掉)?
您不必要地遍历每个 output,然后遍历每个 monitor。所以你收到了重复的条目。您不必为每个输出调用 XRRGetOutputInfo
,因为您需要的所有数据(显示器数量)都可以在 XRRGetScreenResources
返回的结构中找到。
这是有效的 C 代码(至少对我而言):
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
int main(void) {
Display *d = XOpenDisplay(getenv("DISPLAY"));
Window w = DefaultRootWindow(d);
XRRScreenResources *xrrr = XRRGetScreenResources(d, w);
XRRCrtcInfo *xrrci;
int i;
int ncrtc = xrrr->ncrtc;
for (i = 0; i < ncrtc; ++i) {
xrrci = XRRGetCrtcInfo(d, xrrr, xrrr->crtcs[i]);
printf("%dx%d+%d+%d\n", xrrci->width, xrrci->height, xrrci->x, xrrci->y);
XRRFreeCrtcInfo(xrrci);
}
XRRFreeScreenResources(xrrr);
return 0;
}
已接受的答案对我不起作用。我发现这样做的正确方法是:
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
int main(void) {
Display *display = XOpenDisplay(NULL);
if (NULL == display) {
perror("No DISPLAY in environment!");
exit(EXIT_FAILURE);
}
Window window = DefaultRootWindow(display);
XRRScreenResources *screenr = XRRGetScreenResources(display, window);
// This is the key right here. Use XRRScreenResources::noutput
int output = screenr->noutput;
for (int i = 0; i < output; ++i) {
XRROutputInfo* out_info = XRRGetOutputInfo(display, screenr, screenr->outputs[i]);
if (NULL != out_info && out_info->connection == RR_Connected) {
XRRCrtcInfo* crt_info = XRRGetCrtcInfo(display, screenr, out_info->crtc);
printf("%s\t%dx%d+%d+%d\n", out_info->name,
crt_info->width,
crt_info->height,
crt_info->x,
crt_info->y);
XRRFreeCrtcInfo(crt_info);
}
XRRFreeOutputInfo(out_info);
}
XRRFreeScreenResources(screenr);
XCloseDisplay(display);
return 0;
}
正如我在代码注释中所说,诀窍是使用 XRRScreenResources::noutput
而不是 XRRScreenResources::ncrtc