diff --git a/include/utils/xcb.hpp b/include/utils/xcb.hpp index 6b41f37b..f614d28b 100644 --- a/include/utils/xcb.hpp +++ b/include/utils/xcb.hpp @@ -39,8 +39,16 @@ namespace xcb int index = 0; }; - std::shared_ptr make_monitor(); - std::shared_ptr make_monitor(char *name, size_t name_len, int idx, xcb_rectangle_t *rect); + namespace connection + { + bool check(xcb_connection_t *connection); + } - std::vector> get_monitors(xcb_connection_t *connection, xcb_window_t root); + namespace monitor + { + std::shared_ptr make_object(); + std::shared_ptr make_object(char *name, size_t name_len, int idx, xcb_rectangle_t *rect); + + std::vector> get_list(xcb_connection_t *connection, xcb_window_t root); + } } diff --git a/src/bar.cpp b/src/bar.cpp index 1b12330c..fc04e7a3 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -52,7 +52,7 @@ Bar::Bar() : config_path(config::get_bar_path()), opts(std::make_unique } catch (config::MissingValueException &e) {} auto monitor_name = config::get(this->config_path, "monitor", ""); - auto monitors = xcb::get_monitors(x::connection(), x::connection().root()); + auto monitors = xcb::monitor::get_list(x::connection(), x::connection().root()); // In case we're not connected to X, we'll just ignore the monitor if (!monitors.empty()) { @@ -77,7 +77,7 @@ Bar::Bar() : config_path(config::get_bar_path()), opts(std::make_unique // Create an empty monitor as fallback if (!this->opts->monitor) - this->opts->monitor = xcb::make_monitor(); + this->opts->monitor = xcb::monitor::make_object(); this->opts->offset_x = config::get(this->config_path, "offset_x", defaults.offset_x); this->opts->offset_y = config::get(this->config_path, "offset_y", defaults.offset_y); diff --git a/src/utils/xcb.cpp b/src/utils/xcb.cpp index b9e2752d..cdd5fa90 100644 --- a/src/utils/xcb.cpp +++ b/src/utils/xcb.cpp @@ -1,82 +1,128 @@ #include "utils/xcb.hpp" #include "utils/memory.hpp" +#include "services/logger.hpp" namespace xcb { - std::shared_ptr make_monitor() { - return memory::make_malloc_ptr(); - } - - std::shared_ptr make_monitor(char *name, size_t name_len, int idx, xcb_rectangle_t rect) + namespace connection { - auto mon = make_monitor(); + bool check(xcb_connection_t *connection) + { + int err; - mon->bounds = rect; - mon->index = idx; + if ((err = xcb_connection_has_error(connection)) == 0) + return true; - size_t name_size = name_len + 1; - if (sizeof(mon->name) < name_size) - name_size = sizeof(mon->name); + log_error("xcb: The server closed the connection"); - std::snprintf(mon->name, name_size, "%s", name); - - return mon; - } - - std::vector> get_monitors(xcb_connection_t *connection, xcb_window_t root) - { - std::vector> monitors; - - xcb_randr_get_screen_resources_reply_t *sres = - xcb_randr_get_screen_resources_reply(connection, - xcb_randr_get_screen_resources(connection, root), nullptr); - - if (sres == nullptr) - return monitors; - - int len = xcb_randr_get_screen_resources_outputs_length(sres); - xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(sres); - - for (int i = 0; i < len; i++) { - xcb_randr_get_output_info_cookie_t cookie = - xcb_randr_get_output_info(connection, outputs[i], XCB_CURRENT_TIME); - xcb_randr_get_output_info_reply_t *info = - xcb_randr_get_output_info_reply(connection, cookie, nullptr); - xcb_randr_get_output_info(connection, outputs[i], XCB_CURRENT_TIME); - - if (info == nullptr) - continue; - - if (info->crtc == XCB_NONE) { - free(info); - continue; + switch (err) { + case XCB_CONN_ERROR: + log_error("- socket, pipe or stream error"); + break; + case XCB_CONN_CLOSED_EXT_NOTSUPPORTED: + log_error("- unsupported extension"); + break; + case XCB_CONN_CLOSED_MEM_INSUFFICIENT: + log_error("- not enough memory"); + break; + case XCB_CONN_CLOSED_REQ_LEN_EXCEED: + log_error("- request length exceeded"); + break; + case XCB_CONN_CLOSED_PARSE_ERR: + log_error("- can't parse display string"); + break; + case XCB_CONN_CLOSED_INVALID_SCREEN: + log_error("- invalid screen"); + break; + case XCB_CONN_CLOSED_FDPASSING_FAILED: + log_error("- failed to pass FD"); + break; + default: + log_error("- unknown error"); + break; } - xcb_randr_get_crtc_info_reply_t *cir = - xcb_randr_get_crtc_info_reply(connection, - xcb_randr_get_crtc_info(connection, info->crtc, XCB_CURRENT_TIME), nullptr); + return false; + } + } - if (cir == nullptr) { - free(info); - continue; - } - - char *monitor_name = (char *) xcb_randr_get_output_info_name(info); - monitors.emplace_back(xcb::make_monitor(monitor_name, info->name_len, i, - {cir->x, cir->y, cir->width, cir->height})); - - free(cir); + namespace monitor + { + std::shared_ptr make_object() { + return memory::make_malloc_ptr(); } - std::sort(monitors.begin(), monitors.end(), [](std::shared_ptr m1, std::shared_ptr m2) -> bool + std::shared_ptr make_object(char *name, size_t name_len, int idx, xcb_rectangle_t rect) { - if (m1->bounds.x < m2->bounds.x || m1->bounds.y + m1->bounds.height <= m2->bounds.y) - return 1; - if (m1->bounds.x > m2->bounds.x || m1->bounds.y + m1->bounds.height > m2->bounds.y) - return -1; - return 0; - }); + auto mon = make_object(); - return monitors; + mon->bounds = rect; + mon->index = idx; + + size_t name_size = name_len + 1; + if (sizeof(mon->name) < name_size) + name_size = sizeof(mon->name); + + std::snprintf(mon->name, name_size, "%s", name); + + return mon; + } + + std::vector> get_list(xcb_connection_t *connection, xcb_window_t root) + { + std::vector> monitors; + + xcb_randr_get_screen_resources_reply_t *sres = + xcb_randr_get_screen_resources_reply(connection, + xcb_randr_get_screen_resources(connection, root), nullptr); + + if (sres == nullptr) + return monitors; + + int len = xcb_randr_get_screen_resources_outputs_length(sres); + xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(sres); + + for (int i = 0; i < len; i++) { + xcb_randr_get_output_info_cookie_t cookie = + xcb_randr_get_output_info(connection, outputs[i], XCB_CURRENT_TIME); + xcb_randr_get_output_info_reply_t *info = + xcb_randr_get_output_info_reply(connection, cookie, nullptr); + xcb_randr_get_output_info(connection, outputs[i], XCB_CURRENT_TIME); + + if (info == nullptr) + continue; + + if (info->crtc == XCB_NONE) { + free(info); + continue; + } + + xcb_randr_get_crtc_info_reply_t *cir = + xcb_randr_get_crtc_info_reply(connection, + xcb_randr_get_crtc_info(connection, info->crtc, XCB_CURRENT_TIME), nullptr); + + if (cir == nullptr) { + free(info); + continue; + } + + char *monitor_name = (char *) xcb_randr_get_output_info_name(info); + monitors.emplace_back(make_object(monitor_name, info->name_len, i, + {cir->x, cir->y, cir->width, cir->height})); + + free(cir); + } + + std::sort(monitors.begin(), monitors.end(), [](std::shared_ptr m1, std::shared_ptr m2) -> bool + { + if (m1->bounds.x < m2->bounds.x || m1->bounds.y + m1->bounds.height <= m2->bounds.y) + return 1; + if (m1->bounds.x > m2->bounds.x || m1->bounds.y + m1->bounds.height > m2->bounds.y) + return -1; + return 0; + }); + + return monitors; + } } }