xcb-studies/src/xrandr.cpp

155 lines
5.5 KiB
C++

#include "xcb/randr.h"
#include "xcb/xcb.h"
#include "xcb/xcb_aux.h"
#include <iostream>
#include <memory>
#include <vector>
xcb_randr_get_screen_resources_reply_t* get_screen_resources(xcb_connection_t* connection,
xcb_window_t rootWindow) {
return xcb_randr_get_screen_resources_reply(
connection, xcb_randr_get_screen_resources(connection, rootWindow), nullptr);
}
std::vector<xcb_randr_crtc_t> get_crtc_cookies(xcb_randr_get_screen_resources_reply_t* resources) {
std::vector<xcb_randr_crtc_t> reply;
xcb_randr_crtc_t* crtcs = xcb_randr_get_screen_resources_crtcs(resources);
const int crtcsCount = xcb_randr_get_screen_resources_crtcs_length(resources);
for (int i = 0; i < crtcsCount; ++i) {
reply.push_back(crtcs[i]);
}
return reply;
}
void display_one_crtc(xcb_randr_get_crtc_info_reply_t* crtc) {
std::cout << "(x: " << crtc->x << ", y: " << crtc->y << ") (width: " << crtc->width
<< ", height: " << crtc->height << ") status:" << unsigned(crtc->status) << std::endl;
}
void display_crtc_info(xcb_connection_t* connection, std::vector<xcb_randr_crtc_t>& crtc_cs) {
std::vector<xcb_randr_get_crtc_info_cookie_t> cookies;
xcb_generic_error_t* error = nullptr;
for (const auto& crtc : crtc_cs) {
cookies.push_back(xcb_randr_get_crtc_info(connection, crtc, XCB_CURRENT_TIME));
}
for (const auto& cookie : cookies) {
xcb_randr_get_crtc_info_reply_t* reply =
xcb_randr_get_crtc_info_reply(connection, cookie, &error);
if (error) {
free(error);
} else {
display_one_crtc(reply);
free(reply);
}
}
}
void display_one_output(xcb_connection_t* connection, xcb_randr_get_output_info_reply_t* output,
xcb_timestamp_t timestamp) {
xcb_randr_get_crtc_info_reply_t* crtc = xcb_randr_get_crtc_info_reply(
connection, xcb_randr_get_crtc_info(connection, output->crtc, timestamp), NULL);
if (!crtc) {
return;
}
display_one_crtc(crtc);
free(crtc);
}
void display_outputs(xcb_connection_t* connection,
xcb_randr_get_screen_resources_reply_t* resources, xcb_timestamp_t timestamp) {
std::vector<xcb_randr_get_output_info_cookie_t> cookies;
xcb_generic_error_t* error = nullptr;
int len = xcb_randr_get_screen_resources_outputs_length(resources);
xcb_randr_output_t* randr_outputs = xcb_randr_get_screen_resources_outputs(resources);
for (int i = 0; i < len; ++i) {
cookies.push_back(xcb_randr_get_output_info(connection, randr_outputs[i], timestamp));
}
for (const auto& cookie : cookies) {
xcb_randr_get_output_info_reply_t* reply =
xcb_randr_get_output_info_reply(connection, cookie, &error);
if (error) {
free(error);
continue;
} else {
display_one_output(connection, reply, timestamp);
free(reply);
}
}
}
// Lesson of the day: All _reply_t* objects must be freed.
//
// xcb_randr_rotation_t)
// }
// get_rotation(xcb_connection_t* connection, xcb_randr_crtc_t crtc) {
// xcb_generic_error_t* error = nullptr;
// xcb_randr_get_crtc_info_cookie_t cookie =
// xcb_randr_get_crtc_info(connection, crtc, XCB_CURRENT_TIME);
// xcb_randr_get_crtc_info_reply_t* reply =
// xcb_randr_get_crtc_info_reply(connection, cookie, &error);
// xcb_randr_rotation_t rotation =
// (xcb_randr_rotation_t)reply->rotation; free(reply); return rotation;
// }
//
xcb_randr_query_version_reply_t* getVersion(xcb_connection_t* connection) {
xcb_generic_error_t* error = nullptr;
xcb_randr_query_version_reply_t* version = xcb_randr_query_version_reply(
connection,
xcb_randr_query_version(connection, XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION),
&error);
if (error) {
std::cout << "Error code:" << error->error_code << std::endl;
free(error);
return NULL;
}
if (!version) {
return NULL;
}
return version;
}
void display_screen_info(int screen_id, xcb_screen_t* screen) {
std::cout << "Screen " << screen_id << " (" << screen->width_in_pixels << ", "
<< screen->height_in_pixels << ")" << std::endl;
}
void display_randr_version(xcb_randr_query_version_reply_t* version) {
if (!version) {
std::cout << "Something went wrong retrieving the version number" << std::endl;
exit(0);
}
std::cout << "Server reports RandR version (" << version->major_version << "."
<< version->minor_version << ")" << std::endl;
}
// This gives us a connection and a screen object.
int main(int argc, const char* argv[]) {
int default_screen_id;
xcb_connection_t* xConnection = xcb_connect(nullptr, &default_screen_id);
auto screen = xcb_aux_get_screen(xConnection, default_screen_id);
display_screen_info(default_screen_id, screen);
xcb_randr_query_version_reply_t* version = getVersion(xConnection);
display_randr_version(version);
xcb_randr_get_screen_resources_reply_t* screen_resources =
get_screen_resources(xConnection, screen->root);
xcb_timestamp_t timestamp = screen_resources->config_timestamp;
display_outputs(xConnection, screen_resources, timestamp);
free(screen_resources);
xcb_disconnect(xConnection);
return 0;
}