#include "xcb/randr.h" #include "xcb/xcb.h" #include "xcb/xcb_aux.h" #include #include #include #include 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 get_crtc_cookies(xcb_randr_get_screen_resources_reply_t* resources) { std::vector 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; } const char* rotation_map(uint16_t rotation) { switch (rotation) { case XCB_RANDR_ROTATION_ROTATE_0: return "normal"; case XCB_RANDR_ROTATION_ROTATE_90: return "portrait"; case XCB_RANDR_ROTATION_ROTATE_180: return "inverted"; case XCB_RANDR_ROTATION_ROTATE_270: return "portrait inverted"; default: return "unknown"; } } 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) << " rotation: " << rotation_map(crtc->rotation) << std::endl; } 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 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 = // bool MyClass::operator!=(const MyClass &other) const { return !(*this == other); } (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; }