From 8b7f2b72689c2d670d0399915ae58857f1a5f4af Mon Sep 17 00:00:00 2001 From: Michael Carlberg Date: Thu, 23 Jun 2016 22:26:19 +0200 Subject: [PATCH] refactor: Replace X11 handling with xpp+xcb xrandr 1.5 is no longer required for the monitor handling to work fixes jaagr/lemonbuddy#12 fixes jaagr/lemonbuddy#24 --- .ycm_extra_conf.py | 1 + CMakeLists.txt | 24 ++-- cmake/modules/FindX11_XCB.cmake | 31 ++++ cmake/modules/FindXCB.cmake | 244 ++++++++++++++++++++++++++++++++ include/bar.hpp | 7 +- include/utils/memory.hpp | 10 ++ include/utils/xcb.hpp | 40 ++++++ include/utils/xlib.hpp | 31 ---- src/bar.cpp | 22 ++- src/lemonbuddy.cpp | 1 - src/utils/xcb.cpp | 87 ++++++++++++ src/utils/xlib.cpp | 95 ------------- 12 files changed, 443 insertions(+), 150 deletions(-) create mode 100644 cmake/modules/FindX11_XCB.cmake create mode 100644 cmake/modules/FindXCB.cmake create mode 100644 include/utils/xcb.hpp delete mode 100644 include/utils/xlib.hpp create mode 100644 src/utils/xcb.cpp delete mode 100644 src/utils/xlib.cpp diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py index 652b4bbe..03d586fb 100644 --- a/.ycm_extra_conf.py +++ b/.ycm_extra_conf.py @@ -50,6 +50,7 @@ def DirectoryOfThisScript(): flags.append('-I'+ DirectoryOfThisScript() +'/src') flags.append('-I'+ DirectoryOfThisScript() +'/include') flags.append('-I'+ DirectoryOfThisScript() +'/contrib/i3ipcpp/include') +flags.append('-I'+ DirectoryOfThisScript() +'/contrib/xpp/include') def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): if not working_directory: diff --git a/CMakeLists.txt b/CMakeLists.txt index 493883e9..abd334c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,16 +73,11 @@ endif() # find_package("Boost" REQUIRED) find_package("Threads" REQUIRED) -find_package("X11" REQUIRED "X11_Xrandr") set(PROJECT_INCL_DIRS "${PROJECT_SOURCE_DIR}/include" - ${Boost_INCLUDE_DIRS} - ${X11_INCLUDE_DIR}) - + ${BOOST_INCLUDE_DIR}) set(PROJECT_LINK_LIBS - ${Boost_LIBRARIES} - ${X11_LIBRARIES} - ${X11_Xrandr_LIB} + ${BOOST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) if(ENABLE_I3) @@ -126,6 +121,14 @@ if(ENABLE_NETWORK) endif() endif() +# +# Load the xpp library +# +set(XCB_PROTOS xproto randr) +add_subdirectory("${PROJECT_SOURCE_DIR}/contrib/xpp") +set(PROJECT_INCL_DIRS ${PROJECT_INCL_DIRS} ${XPP_INCLUDE_DIRS}) +set(PROJECT_LINK_LIBS ${PROJECT_LINK_LIBS} ${XPP_LIBRARIES}) + # # Install executable and wrapper # @@ -141,8 +144,11 @@ message(STATUS " Enable mpd support ${ENABLE_MPD}") message(STATUS " Enable network support ${ENABLE_NETWORK}") message(STATUS "---------------------------") -add_subdirectory("${PROJECT_SOURCE_DIR}/src") -add_executable(${PROJECT_NAME} ${SOURCE_FILES} +add_subdirectory("${PROJECT_SOURCE_DIR}/src" EXCLUDE_FROM_ALL) +link_directories(${PROJECT_LINK_DIRS}) +include_directories(${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR} ${PROJECT_INCL_DIRS}) +link_libraries(${PROJECT_LINK_LIBS}) +add_executable(${PROJECT_NAME} ${FILES} "examples/config" "examples/config.bspwm" "examples/config.i3") diff --git a/cmake/modules/FindX11_XCB.cmake b/cmake/modules/FindX11_XCB.cmake new file mode 100644 index 00000000..7611b088 --- /dev/null +++ b/cmake/modules/FindX11_XCB.cmake @@ -0,0 +1,31 @@ +# - Try to find libX11-xcb +# Once done this will define +# +# X11_XCB_FOUND - system has libX11-xcb +# X11_XCB_LIBRARIES - Link these to use libX11-xcb +# X11_XCB_INCLUDE_DIR - the libX11-xcb include dir +# X11_XCB_DEFINITIONS - compiler switches required for using libX11-xcb + +# Copyright (c) 2011 Fredrik Höglund +# Copyright (c) 2008 Helio Chissini de Castro, +# Copyright (c) 2007 Matthias Kretz, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +IF (NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + FIND_PACKAGE(PkgConfig) + PKG_CHECK_MODULES(PKG_X11_XCB QUIET x11-xcb) + + SET(X11_XCB_DEFINITIONS ${PKG_X11_XCB_CFLAGS}) + + FIND_PATH(X11_XCB_INCLUDE_DIR NAMES X11/Xlib-xcb.h HINTS ${PKG_X11_XCB_INCLUDE_DIRS}) + FIND_LIBRARY(X11_XCB_LIBRARIES NAMES X11-xcb HINTS ${PKG_X11_XCB_LIBRARY_DIRS}) + + include(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(X11_XCB DEFAULT_MSG X11_XCB_LIBRARIES X11_XCB_INCLUDE_DIR) + + MARK_AS_ADVANCED(X11_XCB_INCLUDE_DIR X11_XCB_LIBRARIES) +ENDIF (NOT WIN32) diff --git a/cmake/modules/FindXCB.cmake b/cmake/modules/FindXCB.cmake new file mode 100644 index 00000000..efeea58a --- /dev/null +++ b/cmake/modules/FindXCB.cmake @@ -0,0 +1,244 @@ +# Try to find XCB on a Unix system +# +# This will define: +# +# XCB_FOUND - True if xcb is available +# XCB_LIBRARIES - Link these to use xcb +# XCB_INCLUDE_DIRS - Include directory for xcb +# XCB_DEFINITIONS - Compiler flags for using xcb +# +# In addition the following more fine grained variables will be defined: +# +# XCB_XCB_FOUND XCB_XCB_INCLUDE_DIR XCB_XCB_LIBRARY +# XCB_UTIL_FOUND XCB_UTIL_INCLUDE_DIR XCB_UTIL_LIBRARY +# XCB_COMPOSITE_FOUND XCB_COMPOSITE_INCLUDE_DIR XCB_COMPOSITE_LIBRARY +# XCB_DAMAGE_FOUND XCB_DAMAGE_INCLUDE_DIR XCB_DAMAGE_LIBRARY +# XCB_XFIXES_FOUND XCB_XFIXES_INCLUDE_DIR XCB_XFIXES_LIBRARY +# XCB_RENDER_FOUND XCB_RENDER_INCLUDE_DIR XCB_RENDER_LIBRARY +# XCB_RANDR_FOUND XCB_RANDR_INCLUDE_DIR XCB_RANDR_LIBRARY +# XCB_SHAPE_FOUND XCB_SHAPE_INCLUDE_DIR XCB_SHAPE_LIBRARY +# XCB_DRI2_FOUND XCB_DRI2_INCLUDE_DIR XCB_DRI2_LIBRARY +# XCB_GLX_FOUND XCB_GLX_INCLUDE_DIR XCB_GLX_LIBRARY +# XCB_SHM_FOUND XCB_SHM_INCLUDE_DIR XCB_SHM_LIBRARY +# XCB_XV_FOUND XCB_XV_INCLUDE_DIR XCB_XV_LIBRARY +# XCB_SYNC_FOUND XCB_SYNC_INCLUDE_DIR XCB_SYNC_LIBRARY +# XCB_XTEST_FOUND XCB_XTEST_INCLUDE_DIR XCB_XTEST_LIBRARY +# XCB_ICCCM_FOUND XCB_ICCCM_INCLUDE_DIR XCB_ICCCM_LIBRARY +# XCB_EWMH_FOUND XCB_EWMH_INCLUDE_DIR XCB_EWMH_LIBRARY +# XCB_IMAGE_FOUND XCB_IMAGE_INCLUDE_DIR XCB_IMAGE_LIBRARY +# XCB_RENDERUTIL_FOUND XCB_RENDERUTIL_INCLUDE_DIR XCB_RENDERUTIL_LIBRARY +# XCB_KEYSYMS_FOUND XCB_KEYSYMS_INCLUDE_DIR XCB_KEYSYMS_LIBRARY +# +# Copyright (c) 2011 Fredrik Höglund +# Copyright (c) 2013 Martin Gräßlin +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +set(knownComponents XCB + COMPOSITE + DAMAGE + DRI2 + EWMH + GLX + ICCCM + IMAGE + KEYSYMS + RANDR + RENDER + RENDERUTIL + SHAPE + SHM + SYNC + UTIL + XFIXES + XTEST + XV + XINERAMA) + +unset(unknownComponents) + +set(pkgConfigModules) +set(requiredComponents) + +if (XCB_FIND_COMPONENTS) + set(comps ${XCB_FIND_COMPONENTS}) +else() + set(comps ${knownComponents}) +endif() + +# iterate through the list of requested components, and check that we know them all. +# If not, fail. +foreach(comp ${comps}) + list(FIND knownComponents ${comp} index ) + if("${index}" STREQUAL "-1") + list(APPEND unknownComponents "${comp}") + else() + if("${comp}" STREQUAL "XCB") + list(APPEND pkgConfigModules "xcb") + elseif("${comp}" STREQUAL "COMPOSITE") + list(APPEND pkgConfigModules "xcb-composite") + elseif("${comp}" STREQUAL "DAMAGE") + list(APPEND pkgConfigModules "xcb-damage") + elseif("${comp}" STREQUAL "DRI2") + list(APPEND pkgConfigModules "xcb-dri2") + elseif("${comp}" STREQUAL "EWMH") + list(APPEND pkgConfigModules "xcb-ewmh") + elseif("${comp}" STREQUAL "GLX") + list(APPEND pkgConfigModules "xcb-glx") + elseif("${comp}" STREQUAL "ICCCM") + list(APPEND pkgConfigModules "xcb-icccm") + elseif("${comp}" STREQUAL "IMAGE") + list(APPEND pkgConfigModules "xcb-image") + elseif("${comp}" STREQUAL "KEYSYMS") + list(APPEND pkgConfigModules "xcb-keysyms") + elseif("${comp}" STREQUAL "RANDR") + list(APPEND pkgConfigModules "xcb-randr") + elseif("${comp}" STREQUAL "RENDER") + list(APPEND pkgConfigModules "xcb-render") + elseif("${comp}" STREQUAL "RENDERUTIL") + list(APPEND pkgConfigModules "xcb-renderutil") + elseif("${comp}" STREQUAL "SHAPE") + list(APPEND pkgConfigModules "xcb-shape") + elseif("${comp}" STREQUAL "SHM") + list(APPEND pkgConfigModules "xcb-shm") + elseif("${comp}" STREQUAL "SYNC") + list(APPEND pkgConfigModules "xcb-sync") + elseif("${comp}" STREQUAL "UTIL") + list(APPEND pkgConfigModules "xcb-util") + elseif("${comp}" STREQUAL "XFIXES") + list(APPEND pkgConfigModules "xcb-xfixes") + elseif("${comp}" STREQUAL "XTEST") + list(APPEND pkgConfigModules "xcb-xtest") + elseif("${comp}" STREQUAL "XV") + list(APPEND pkgConfigModules "xcb-xv") + elseif("${comp}" STREQUAL "XINERAMA") + list(APPEND pkgConfigModules "xcb-xinerama") + endif() + endif() +endforeach() + + +if(DEFINED unknownComponents) + set(msgType STATUS) + if(XCB_FIND_REQUIRED) + set(msgType FATAL_ERROR) + endif() + if(NOT XCB_FIND_QUIETLY) + message(${msgType} "XCB: requested unknown components ${unknownComponents}") + endif() + return() +endif() + +macro(_XCB_HANDLE_COMPONENT _comp) + set(_header ) + set(_lib ) + if("${_comp}" STREQUAL "XCB") + set(_header "xcb/xcb.h") + set(_lib "xcb") + elseif("${_comp}" STREQUAL "COMPOSITE") + set(_header "xcb/composite.h") + set(_lib "xcb-composite") + elseif("${_comp}" STREQUAL "DAMAGE") + set(_header "xcb/damage.h") + set(_lib "xcb-damage") + elseif("${_comp}" STREQUAL "DRI2") + set(_header "xcb/dri2.h") + set(_lib "xcb-dri2") + elseif("${_comp}" STREQUAL "EWMH") + set(_header "xcb/xcb_ewmh.h") + set(_lib "xcb-ewmh") + elseif("${_comp}" STREQUAL "GLX") + set(_header "xcb/glx.h") + set(_lib "xcb-glx") + elseif("${_comp}" STREQUAL "ICCCM") + set(_header "xcb/xcb_icccm.h") + set(_lib "xcb-icccm") + elseif("${_comp}" STREQUAL "IMAGE") + set(_header "xcb/xcb_image.h") + set(_lib "xcb-image") + elseif("${_comp}" STREQUAL "KEYSYMS") + set(_header "xcb/xcb_keysyms.h") + set(_lib "xcb-keysyms") + elseif("${_comp}" STREQUAL "RANDR") + set(_header "xcb/randr.h") + set(_lib "xcb-randr") + elseif("${_comp}" STREQUAL "RENDER") + set(_header "xcb/render.h") + set(_lib "xcb-render") + elseif("${_comp}" STREQUAL "RENDERUTIL") + set(_header "xcb/xcb_renderutil.h") + set(_lib "xcb-render-util") + elseif("${_comp}" STREQUAL "SHAPE") + set(_header "xcb/shape.h") + set(_lib "xcb-shape") + elseif("${_comp}" STREQUAL "SHM") + set(_header "xcb/shm.h") + set(_lib "xcb-shm") + elseif("${_comp}" STREQUAL "SYNC") + set(_header "xcb/sync.h") + set(_lib "xcb-sync") + elseif("${_comp}" STREQUAL "UTIL") + set(_header "xcb/xcb_util.h") + set(_lib "xcb-util") + elseif("${_comp}" STREQUAL "XFIXES") + set(_header "xcb/xfixes.h") + set(_lib "xcb-xfixes") + elseif("${_comp}" STREQUAL "XTEST") + set(_header "xcb/xtest.h") + set(_lib "xcb-xtest") + elseif("${_comp}" STREQUAL "XV") + set(_header "xcb/xv.h") + set(_lib "xcb-xv") + elseif("${_comp}" STREQUAL "XINERAMA") + set(_header "xcb/xinerama.h") + set(_lib "xcb-xinerama") + endif() + + find_path(XCB_${_comp}_INCLUDE_DIR NAMES ${_header} HINTS ${PKG_XCB_INCLUDE_DIRS}) + find_library(XCB_${_comp}_LIBRARY NAMES ${_lib} HINTS ${PKG_XCB_LIBRARY_DIRS}) + + if(XCB_${_comp}_INCLUDE_DIR AND XCB_${_comp}_LIBRARY) + list(APPEND XCB_INCLUDE_DIRS ${XCB_${_comp}_INCLUDE_DIR}) + list(APPEND XCB_LIBRARIES ${XCB_${_comp}_LIBRARY}) + if (NOT XCB_FIND_QUIETLY) + message(STATUS "XCB[${_comp}]: Found component ${_comp}") + endif() + endif() + + if(XCB_FIND_REQUIRED_${_comp}) + list(APPEND requiredComponents XCB_${_comp}_FOUND) + endif() + + find_package_handle_standard_args(XCB_${_comp} DEFAULT_MSG XCB_${_comp}_LIBRARY XCB_${_comp}_INCLUDE_DIR) + + mark_as_advanced(XCB_${_comp}_LIBRARY XCB_${_comp}_INCLUDE_DIR) + + # compatibility for old variable naming + set(XCB_${_comp}_INCLUDE_DIRS ${XCB_${_comp}_INCLUDE_DIR}) + set(XCB_${_comp}_LIBRARIES ${XCB_${_comp}_LIBRARY}) +endmacro() + +IF (NOT WIN32) + include(FindPackageHandleStandardArgs) + # Use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + pkg_check_modules(PKG_XCB QUIET ${pkgConfigModules}) + + set(XCB_DEFINITIONS ${PKG_XCB_CFLAGS}) + + foreach(comp ${comps}) + _xcb_handle_component(${comp}) + endforeach() + + if(XCB_INCLUDE_DIRS) + list(REMOVE_DUPLICATES XCB_INCLUDE_DIRS) + endif() + + find_package_handle_standard_args(XCB DEFAULT_MSG XCB_LIBRARIES XCB_INCLUDE_DIRS ${requiredComponents}) + + # compatibility for old variable naming + set(XCB_INCLUDE_DIR ${XCB_INCLUDE_DIRS}) + +ENDIF (NOT WIN32) diff --git a/include/bar.hpp b/include/bar.hpp index bdd9124a..3de4c9f9 100644 --- a/include/bar.hpp +++ b/include/bar.hpp @@ -2,10 +2,12 @@ #include #include +#include +#include #include "config.hpp" #include "exception.hpp" -#include "utils/xlib.hpp" +#include "utils/xcb.hpp" DefineBaseException(ConfigurationError); @@ -35,7 +37,8 @@ enum Cmd struct Options { - std::unique_ptr monitor; + std::shared_ptr monitor; + std::string wm_name; std::string locale; diff --git a/include/utils/memory.hpp b/include/utils/memory.hpp index d9f223e5..47ec267c 100644 --- a/include/utils/memory.hpp +++ b/include/utils/memory.hpp @@ -1,5 +1,7 @@ #pragma once +#include + // Swap the two ints without the need of creating another tmp variable #define int_memswap(one, two) one += two; \ two = one ? two; \ @@ -11,3 +13,11 @@ #define repeat_with(n, m) for (m = n; m--;) #define repeat_i i #define repeat_i_rev(n) (n - i - 1) + +namespace memory +{ + template + std::shared_ptr make_malloc_ptr() { + return std::shared_ptr(static_cast(malloc(sizeof(T))), free); + } +} diff --git a/include/utils/xcb.hpp b/include/utils/xcb.hpp new file mode 100644 index 00000000..f8b41e82 --- /dev/null +++ b/include/utils/xcb.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace x +{ + typedef xpp::connection<> connection; + typedef xpp::event::registry registry; + typedef xpp::window window; + typedef xpp::window xcb_window; +} + +namespace xcb +{ + typedef struct monitor_t monitor_t; + struct monitor_t + { + char name[32] = "NONAME"; + int index = 0; + int width = 0; + int height = 0; + int x = 0; + int y = 0; + }; + + std::shared_ptr make_monitor(); + std::shared_ptr make_monitor(char *name, size_t name_len, int idx, xcb_rectangle_t *rect); + + std::vector> get_monitors(xcb_connection_t *connection, xcb_window_t root); +} diff --git a/include/utils/xlib.hpp b/include/utils/xlib.hpp deleted file mode 100644 index f03aa124..00000000 --- a/include/utils/xlib.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace xlib -{ - struct Monitor - { - std::string name; - int index = 0; - int width = 0; - int height = 0; - int x = 0; - int y = 0; - - std::string str() { - return this->name + ": "+ this->geom(); - } - - std::string geom() { - return std::to_string(width) +"x"+ std::to_string(height) +"+"+ - std::to_string(x) +"+"+ std::to_string(y); - } - }; - - // std::unique_ptr get_monitor(std::string monitor_name); - - std::vector> get_sorted_monitorlist(); -} diff --git a/src/bar.cpp b/src/bar.cpp index 7668422a..97be5973 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -51,9 +51,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", ""); - this->opts->monitor = std::make_unique(); - - auto monitors = xlib::get_sorted_monitorlist(); + auto monitors = xcb::get_monitors(x::connection(), x::connection().root()); // In case we're not connected to X, we'll just ignore the monitor if (!monitors.empty()) { @@ -62,24 +60,24 @@ Bar::Bar() : config_path(config::get_bar_path()), opts(std::make_unique for (auto &&monitor : monitors) { if (monitor_name.compare(monitor->name) == 0) { - this->opts->monitor->name = monitor->name; - this->opts->monitor->index = monitor->index; - this->opts->monitor->width = monitor->width; - this->opts->monitor->height = monitor->height; - this->opts->monitor->x = monitor->x; - this->opts->monitor->y = monitor->y; + this->opts->monitor = monitor; + break; } } - if (this->opts->monitor->name.empty()) + if (!this->opts->monitor) throw ConfigurationError("Could not find monitor: "+ monitor_name); } this->opts->wm_name = "lemonbuddy-"+ this->config_path.substr(4); - if (!this->opts->monitor->name.empty()) - this->opts->wm_name += "_"+ this->opts->monitor->name; + if (this->opts->monitor) + this->opts->wm_name += "_"+ std::string(this->opts->monitor->name); this->opts->wm_name = string::replace(config::get(this->config_path, "wm_name", this->opts->wm_name), " ", "-"); + // Create an empty monitor as fallback + if (!this->opts->monitor) + this->opts->monitor = xcb::make_monitor(); + 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/lemonbuddy.cpp b/src/lemonbuddy.cpp index c3ff82b6..c14b2ab1 100644 --- a/src/lemonbuddy.cpp +++ b/src/lemonbuddy.cpp @@ -17,7 +17,6 @@ #include "utils/macros.hpp" #include "utils/proc.hpp" #include "utils/string.hpp" -#include "utils/xlib.hpp" /** * TODO: Reload config on USR1 diff --git a/src/utils/xcb.cpp b/src/utils/xcb.cpp new file mode 100644 index 00000000..7e2050d2 --- /dev/null +++ b/src/utils/xcb.cpp @@ -0,0 +1,87 @@ +#include "utils/xcb.hpp" +#include "utils/memory.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) + { + auto mon = make_monitor(); + + mon->x = rect->x; + mon->y = rect->y; + mon->width = rect->width; + mon->height = rect->height; + 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_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; + } + + 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 *name = (char *) xcb_randr_get_output_info_name(info); + + xcb_rectangle_t rect = {cir->x, cir->y, cir->width, cir->height}; + + monitors.emplace_back(xcb::make_monitor(name, info->name_len, i, &rect)); + + free(cir); + } + + std::sort(monitors.begin(), monitors.end(), [](std::shared_ptr m1, std::shared_ptr m2) -> bool + { + if (m1->x < m2->x || m1->y + m1->height <= m2->y) + return 1; + if (m1->x > m2->x || m1->y + m1->height > m2->y) + return -1; + return 0; + }); + + return monitors; + } +} diff --git a/src/utils/xlib.cpp b/src/utils/xlib.cpp deleted file mode 100644 index d349f55a..00000000 --- a/src/utils/xlib.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -#include "utils/memory.hpp" -#include "utils/xlib.hpp" -#include "services/logger.hpp" - -namespace xlib -{ - std::vector> get_sorted_monitorlist() - { - std::vector> monitors; - int n_monitors; - - Display *display = XOpenDisplay(nullptr); - - if (display == nullptr) { - get_logger()->error("Could not open display"); - return monitors; - } - - int screen = XDefaultScreen(display); - Window root = XRootWindow(display, screen); - XRRMonitorInfo *info = XRRGetMonitors(display, root, 1, &n_monitors); - - repeat(n_monitors) - { - char *name = XGetAtomName(display, info[repeat_i_rev(n_monitors)].name); - - auto monitor = std::make_unique(); - monitor->name = std::string(name); - monitor->width = info[repeat_i_rev(n_monitors)].width; - monitor->height = info[repeat_i_rev(n_monitors)].height; - monitor->x = info[repeat_i_rev(n_monitors)].x; - monitor->y = info[repeat_i_rev(n_monitors)].y; - monitors.emplace_back(std::move(monitor)); - - std::free(name); - } - - std::free(info); - - XCloseDisplay(display); - - std::sort(monitors.begin(), monitors.end(), [](std::unique_ptr &m1, std::unique_ptr &m2) -> bool{ - if (m1->x < m2->x || m1->y + m1->height <= m2->y) - return 1; - if (m1->x > m2->x || m1->y + m1->height > m2->y) - return -1; - return 0; - }); - - int idx = 0; - - for (auto &mon : monitors) { - mon->index = idx++; - } - - return monitors; - } - - // std::unique_ptr get_monitor(std::string n_monitorsame) - // { - // auto monitor = std::make_unique(); - // int n_monitors; - // - // Display *display = XOpenDisplay(nullptr); - // int screen = XDefaultScreen(display); - // Window root = XRootWindow(display, screen); - // XRRMonitorInfo *info = XRRGetMonitors(display, root, 1, &n_monitors); - // - // repeat(n_monitors) - // { - // char *name = XGetAtomName(display, info[repeat_i_rev(n_monitors)].name); - // - // if (std::strcmp(name, n_monitorsame.c_str()) != 0) { - // continue; - // } - // - // monitor->name = std::string(name); - // monitor->width = info[repeat_i_rev(n_monitors)].width; - // monitor->height = info[repeat_i_rev(n_monitors)].height; - // monitor->x = info[repeat_i_rev(n_monitors)].x; - // monitor->y = info[repeat_i_rev(n_monitors)].y; - // - // std::free(name); - // } - // - // std::free(info); - // - // XCloseDisplay(display); - // - // return monitor; - // } -}