如何通过xcb RandR扩展获得RandR输出的分辨率?

我正在使用一个已经使用xcb的项目,需要获得单个输出的分辨率,而不是组合屏幕的分辨率。 我可以用xRb的RandR扩展来做到这一点吗? 如果是这样,我怎样才能使用我的xcb_connection_t对象来做到这一点。

我也在寻找答案。 我不知道你是否成功,但由于你没有回答这个问题,我猜你没有。

对于那些正在寻找如何做到这一点,你必须了解XCB一般如何工作。 RandR XCB扩展尤其重要。 正如您可能知道从X服务器获取一些信息,您需要首先查询它的请求 。 在XCB发送请求后,您将得到一个存储已发送请求的IDcookie 。 为什么你需要这样的cookie? 原因很简单,很明显 – 要从X服务器获得答复 ,我们需要用我们发送的请求的ID来请求它(所以服务器知道你想要哪个请求的答案)。

为了更清楚地说明这个问题,从日常生活中可以看出一个简单的例子 – 设想一个记忆极其短暂的调酒师,所以这样做是这样的:

 client : "I'd like to order a beer." bartender: "OK, I'll get you a beer." *bartender handles a ticket with an ID of the beer order to the client* *client waits and waits and then he approaches bartender* client : "Dude, give me my beer finally, here's your damn ticket" *client handles the ticket to bartender, who looks for the order from the ticket in his order book and when he finds it he replies* bartender: "Here's your beer, enjoy." 

好的,为什么不让XCB只发一个请求,一口气回答呢? 那么,这就是Xlib的工作原理,事实证明XCB在某些情况下的速度已经高达117倍。 如果您想了解更多信息,请阅读XCB教程中的基本XCB概念 。

回到问题 – 如何获得输出的分辨率(或CRTCs)? 以下是我如何做到的最小化版本:

 #include <cstdio> #include <xcb/xcb.h> #include <xcb/randr.h> int main() { //Open connection to X server xcb_connection_t* XConnection = xcb_connect(0, 0); //Get the first X screen xcb_screen_t* XFirstScreen = xcb_setup_roots_iterator( xcb_get_setup(XConnection)).data; //Generate ID for the X window xcb_window_t XWindowDummy = xcb_generate_id(XConnection); //Create dummy X window xcb_create_window(XConnection, 0, XWindowDummy, XFirstScreen->root, 0, 0, 1, 1, 0, 0, 0, 0, 0); //Flush pending requests to the X server xcb_flush(XConnection); //Send a request for screen resources to the X server xcb_randr_get_screen_resources_cookie_t screenResCookie = {}; screenResCookie = xcb_randr_get_screen_resources(XConnection, XWindowDummy); //Receive reply from X server xcb_randr_get_screen_resources_reply_t* screenResReply = {}; screenResReply = xcb_randr_get_screen_resources_reply(XConnection, screenResCookie, 0); int crtcs_num = 0; xcb_randr_crtc_t* firstCRTC; //Get a pointer to the first CRTC and number of CRTCs //It is crucial to notice that you are in fact getting //an array with firstCRTC being the first element of //this array and crtcs_length - length of this array if(screenResReply) { crtcs_num = xcb_randr_get_screen_resources_crtcs_length(screenResReply); firstCRTC = xcb_randr_get_screen_resources_crtcs(screenResReply); } else return -1; //Array of requests to the X server for CRTC info xcb_randr_get_crtc_info_cookie_t* crtcResCookie = new xcb_randr_get_crtc_info_cookie_t[crtcs_num]; for(int i = 0; i < crtcs_num; i++) crtcResCookie[i] = xcb_randr_get_crtc_info(XConnection, *(firstCRTC+i), 0); //Array of pointers to replies from X server xcb_randr_get_crtc_info_reply_t** crtcResReply = new xcb_randr_get_crtc_info_reply_t*[crtcs_num]; for(int i = 0; i < crtcs_num; i++) crtcResReply[i] = xcb_randr_get_crtc_info_reply(XConnection, crtcResCookie[i], 0); //Self-explanatory for(int i = 0; i < crtcs_num; i++) { if(crtcResReply[i]) { printf("CRTC[%i] INFO:\n", i); printf("x-off\t: %i\n", crtcResReply[i]->x); printf("y-off\t: %i\n", crtcResReply[i]->y); printf("width\t: %i\n", crtcResReply[i]->width); printf("height\t: %i\n\n", crtcResReply[i]->height); } } xcb_disconnect(XConnection); return 0; } 

示例输出:

 CRTC[0] INFO: x-off : 1920 y-off : 0 width : 1920 height : 1200 CRTC[1] INFO: x-off : 0 y-off : 0 width : 1920 height : 1200 CRTC[2] INFO: x-off : 0 y-off : 0 width : 0 height : 0 CRTC[3] INFO: x-off : 0 y-off : 0 width : 0 height : 0 

如果你想要,你可以提高代码的可读性,而不是使用指针动态分配,但我不认为这是很难理解。

我对XCB编程还不熟悉,可能是更好的方法,但这种方法看起来并不糟糕。 我花了很多时间去了解这个,所以我希望它能帮助别人。

有用的链接:

  • XCB教程 (建议寻找你的方法)
  • XCB API (极其有用,在这种情况下尤其是RandR API)