【问题标题】:X11 - Xrandr giving me false monitorsX11 - Xrandr 给了我假监视器
【发布时间】:2015-07-20 18:11:00
【问题描述】:

我试图找到所有显示器及其坐标(宽度w、高度h、x 原点/最左上角x 和y 原点/最左上角y)和正在使用此代码,它在某些系统上运行良好。但在其他系统上,我得到错误和重复的条目。如果我测试监视器是否为镜像,我能否避免这些重复/错误的监视器条目?如何测试它的镜像?

这是我的代码:

// 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
}]

我真的只有两台显示器,一台 1920x1200 和一台 1366x768。为什么所有其他条目以及如何进行测试以避免(而不是根据重复或 0 h/w 回溯过滤掉)?

【问题讨论】:

  • 为什么你把它标记为'c'?
  • @yatg:“正常”xrandr 命令是什么意思?
  • 只需安装 xrandr(在 Ubuntu 上的 x11-xserver-utils 包中),然后输入 xrandr
  • screenOutputs 来自哪里?我在代码中没有看到它的初始化。
  • 不确定,但另一个原因可能是 X 服务器被配置为默认情况下将(克隆)视频发送到所有可能的输出 - 无论是否连接任何东西。我见过这样配置的系统,以确保无论连接哪个输出,用户都能获得视频。

标签: c x11 xlib xrandr


【解决方案1】:

您不必要地遍历每个 输出,然后遍历每个 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;
}

【讨论】:

  • 非常感谢我还没有测试但它是有道理的,这种方式也会有宽度为0和高度为0的显示器没有?
  • 这种方式不会为您提供那些宽度为 0 和高度为 0 的监视器。很棒的解决方案!
【解决方案2】:

接受的答案对我不起作用。我发现这样做的正确方法是:

#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

【讨论】:

  • 这是一种有效的方法,结果与 xrandr 工具的输出一致。但是,请注意 out_info-&gt;crtc 在某些情况下(例如,当笔记本电脑盖合上时)可能为空 (0),即使 out_info-&gt;connection == RR_Connected 也是如此。强大的解决方案必须处理这种情况,否则会生成 X 服务器错误。
猜你喜欢
  • 2010-10-04
  • 1970-01-01
  • 2022-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-26
相关资源
最近更新 更多