From 142a9840edf3df6648e293463f14c1b471d4f8da Mon Sep 17 00:00:00 2001 From: sthussky Date: Fri, 16 Jul 2021 17:13:34 +0300 Subject: [PATCH 01/12] Geometry_parser draft --- src/config.hpp | 10 +++++----- src/xcb_util.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/xcb_util.hpp | 12 ++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/config.hpp b/src/config.hpp index 1e8a602..a0204db 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -22,7 +22,7 @@ using keys = std::array; /// Actual window width will be equal to dxp_width + (dxp_padding * 2) /// const uint dxp_width = 0; -const uint dxp_height = 150; +const uint dxp_height = 175; /// /// Name of the monitor to put window on. Will use primary if unset. @@ -48,7 +48,7 @@ const float dxp_y = 0; ///< Y coordinate of window's corner /// If centering is enabled, corresponding coordinate will be ignored /// const bool dxp_center_x = true; ///< Center dxp on the monitor horizontally -const bool dxp_center_y = false; ///< Center dxp on the monitor vertically +const bool dxp_center_y = true; ///< Center dxp on the monitor vertically const uint16_t dxp_padding = 3; ///< Padding around the screenshots @@ -67,7 +67,7 @@ const uint dxp_border_width = 0; ///< dxp window border /// /// NOTE: Setting timeout to values below 5 ms may severely increase CPU load. /// -const auto dxp_screenshot_period = std::chrono::seconds (10); +const auto dxp_screenshot_period = std::chrono::seconds (2); /// /// Desktop viewport: @@ -80,7 +80,7 @@ const auto dxp_screenshot_period = std::chrono::seconds (10); /// /// Otherwise leave empty. /// -const std::vector dxp_viewport = {}; +const std::vector dxp_viewport = {0,0,0,0,0,0,0,0}; /// /// Key bindings: @@ -98,7 +98,7 @@ struct dxp_keys static constexpr keys next = { "Down", "Right", "l", "j" }; static constexpr keys prev = { "Left", "Up", "h", "k" }; static constexpr keys slct = { "Return" }; - static constexpr keys exit = { "Escape" }; + static constexpr keys exit = { "Escape", "Cyrillic_hardsign" }; }; #endif /* ifndef DXP_CONFIG_HPP */ diff --git a/src/xcb_util.cpp b/src/xcb_util.cpp index 611adf4..db1a22a 100644 --- a/src/xcb_util.cpp +++ b/src/xcb_util.cpp @@ -269,3 +269,40 @@ ewmh_change_desktop (xcb_connection_t *c, xcb_window_t root, uint destkop_id) // of this spec, in which case the timestamp field should be ignored. send_xcb_message (c, root, "_NET_CURRENT_DESKTOP", { destkop_id }); } + +std::vector +get_desktop_windows_ids (xcb_connection_t *c, xcb_window_t root, + uint32_t desktop) +{ + std::vector desktop_windows_ids; + auto list = get_property_value (c, root, "_NET_CLIENT_LIST"); + for (uint32_t client : list) + { + bool is_on_desktop + = (desktop + == get_property_value (c, client, "_NET_WINDOW_DESKTOP")[0]); + if (is_on_desktop) + { + desktop_windows_ids.push_back (client); + } + } + return desktop_windows_ids; +} + +std::vector +get_prerenders (xcb_connection_t *c, xcb_window_t root, uint desktop) +{ + std::vector info; + std::vector ids = get_desktop_windows_ids (c, root, desktop); + xcb_generic_error_t *e = nullptr; // TODO(mmskv): Check for memory leak + for (uint32_t id : ids) + { + auto geometry_cookie = xcb_get_geometry (c, id); + auto geometry = xcb_unique_ptr (xcb_get_geometry_reply (c, geometry_cookie, &e)); + check (e, "XCB error while getting geometry reply"); + // auto icons = get_property_value(c, id, "_NET_WM_ICONS"); + render_info id_info={geometry.get()->x, geometry.get()->y, geometry.get()->width, geometry.get()->height}; + info.push_back(id_info); + } + return info; +} \ No newline at end of file diff --git a/src/xcb_util.hpp b/src/xcb_util.hpp index 88dbab1..d70d8d1 100644 --- a/src/xcb_util.hpp +++ b/src/xcb_util.hpp @@ -255,4 +255,16 @@ get_keycodes (xcb_connection_t *c) return keycodes; } +struct render_info{ + uint x; + uint y; + uint width; + uint height; + //xcb_pixmap_t *icon ; TODO(sthussky): implement this +}; + +std::vector get_desktop_windows(xcb_connection_t *c, xcb_window_t root, uint32_t desktop); + +std::vector get_prerenders(xcb_connection_t *c, xcb_window_t root, uint desktop); + #endif /* ifndef DEXPO_XCB_HPP */ From d87858c381dd340b0388d3aa1670579b9310b5f7 Mon Sep 17 00:00:00 2001 From: mmskv Date: Fri, 16 Jul 2021 23:06:24 +0300 Subject: [PATCH 02/12] Add config option to enable desktop layouts Restore config to defaults --- src/config.hpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/config.hpp b/src/config.hpp index a0204db..0c2c94f 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -11,6 +11,15 @@ constexpr std::size_t keys_size = 10; using color = const uint32_t; using keys = std::array; +/// +/// Whether to show desktop screenshots. +/// +/// True: Display desktop screenshots. +/// Display desktop layouts if no screenshots are available. +/// False: Always display desktop layouts. +/// +const bool dxp_do_screenshots = true; + /// /// Dimensions of the screenshots that will be displayed. /// @@ -22,7 +31,7 @@ using keys = std::array; /// Actual window width will be equal to dxp_width + (dxp_padding * 2) /// const uint dxp_width = 0; -const uint dxp_height = 175; +const uint dxp_height = 150; /// /// Name of the monitor to put window on. Will use primary if unset. @@ -48,7 +57,7 @@ const float dxp_y = 0; ///< Y coordinate of window's corner /// If centering is enabled, corresponding coordinate will be ignored /// const bool dxp_center_x = true; ///< Center dxp on the monitor horizontally -const bool dxp_center_y = true; ///< Center dxp on the monitor vertically +const bool dxp_center_y = false; ///< Center dxp on the monitor vertically const uint16_t dxp_padding = 3; ///< Padding around the screenshots @@ -67,7 +76,7 @@ const uint dxp_border_width = 0; ///< dxp window border /// /// NOTE: Setting timeout to values below 5 ms may severely increase CPU load. /// -const auto dxp_screenshot_period = std::chrono::seconds (2); +const auto dxp_screenshot_period = std::chrono::seconds (10); /// /// Desktop viewport: @@ -80,7 +89,7 @@ const auto dxp_screenshot_period = std::chrono::seconds (2); /// /// Otherwise leave empty. /// -const std::vector dxp_viewport = {0,0,0,0,0,0,0,0}; +const std::vector dxp_viewport = {}; /// /// Key bindings: @@ -98,7 +107,7 @@ struct dxp_keys static constexpr keys next = { "Down", "Right", "l", "j" }; static constexpr keys prev = { "Left", "Up", "h", "k" }; static constexpr keys slct = { "Return" }; - static constexpr keys exit = { "Escape", "Cyrillic_hardsign" }; + static constexpr keys exit = { "Escape" }; }; #endif /* ifndef DXP_CONFIG_HPP */ From c05d394f9057a4f95c670c8ca0b19422c7e5e733 Mon Sep 17 00:00:00 2001 From: mmskv Date: Fri, 16 Jul 2021 23:30:47 +0300 Subject: [PATCH 03/12] Use std::string in get_property_value --- src/xcb_util.cpp | 9 ++++----- src/xcb_util.hpp | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/xcb_util.cpp b/src/xcb_util.cpp index db1a22a..a6adcb0 100644 --- a/src/xcb_util.cpp +++ b/src/xcb_util.cpp @@ -24,19 +24,18 @@ check (xcb_generic_error_t *e, const std::string &msg) */ std::vector get_property_value (xcb_connection_t *c, xcb_window_t root, - const char *atom_name) + const std::string &name) { - xcb_generic_error_t *e = nullptr; // TODO(mmskv): Check for memory leak + xcb_generic_error_t *e = nullptr; - auto atom_cookie = xcb_intern_atom (c, 0, strlen (atom_name), atom_name); + auto atom_cookie = xcb_intern_atom (c, 0, name.length (), name.c_str ()); auto atom_reply = xcb_unique_ptr ( xcb_intern_atom_reply (c, atom_cookie, &e)); check (e, "XCB error while getting atom reply"); auto atom = atom_reply ? atom_reply->atom - : throw std::runtime_error ( - std::string ("Could not get atom for ") + atom_name); + : throw std::runtime_error ("Could not get atom for " + name); /* Getting property from atom */ diff --git a/src/xcb_util.hpp b/src/xcb_util.hpp index d70d8d1..e92f451 100644 --- a/src/xcb_util.hpp +++ b/src/xcb_util.hpp @@ -84,8 +84,7 @@ xcb_unique_ptr (T *ptr) * @note vector size is inconsistent so vector may contain other data */ std::vector get_property_value (xcb_connection_t *c, - xcb_window_t root, - const char *atom_name); + xcb_window_t root, std::string &name); /** * Get monitor_info for each connected monitor From 8261d3e4d3946ba46681a634a835b0cf26caf945 Mon Sep 17 00:00:00 2001 From: mmskv Date: Sat, 17 Jul 2021 00:02:47 +0300 Subject: [PATCH 04/12] Add parser for windows geometries This implementation works --- src/dxp.cpp | 10 ++++++++- src/xcb_util.cpp | 53 ++++++++++++++++++++++-------------------------- src/xcb_util.hpp | 32 ++++++++++++++++++----------- 3 files changed, 53 insertions(+), 42 deletions(-) diff --git a/src/dxp.cpp b/src/dxp.cpp index 5740ddf..c59937d 100644 --- a/src/dxp.cpp +++ b/src/dxp.cpp @@ -18,11 +18,19 @@ main () { try { - // Get screenshots from socket + // Get screenshots from socket or create them manually + // if (dxp_do_screenshots) + // { dxp_socket client; auto v = client.get_desktops (); + // } + // else + // { + // auto v = get_desktops (); + // } window w (v); + auto windows = get_windows (window::c, window::root); // Handling incoming events // Freeing it with free() is not specified in the docs, but it works diff --git a/src/xcb_util.cpp b/src/xcb_util.cpp index a6adcb0..21fcee7 100644 --- a/src/xcb_util.cpp +++ b/src/xcb_util.cpp @@ -269,39 +269,34 @@ ewmh_change_desktop (xcb_connection_t *c, xcb_window_t root, uint destkop_id) send_xcb_message (c, root, "_NET_CURRENT_DESKTOP", { destkop_id }); } -std::vector -get_desktop_windows_ids (xcb_connection_t *c, xcb_window_t root, - uint32_t desktop) +std::vector +get_windows (xcb_connection_t *c, xcb_window_t root) { + xcb_generic_error_t *e = nullptr; + std::vector windows; + std::vector desktop_windows_ids; - auto list = get_property_value (c, root, "_NET_CLIENT_LIST"); - for (uint32_t client : list) - { - bool is_on_desktop - = (desktop - == get_property_value (c, client, "_NET_WINDOW_DESKTOP")[0]); - if (is_on_desktop) - { - desktop_windows_ids.push_back (client); - } - } - return desktop_windows_ids; -} + auto ids = get_property_value (c, root, "_NET_CLIENT_LIST"); -std::vector -get_prerenders (xcb_connection_t *c, xcb_window_t root, uint desktop) -{ - std::vector info; - std::vector ids = get_desktop_windows_ids (c, root, desktop); - xcb_generic_error_t *e = nullptr; // TODO(mmskv): Check for memory leak - for (uint32_t id : ids) + windows.reserve (ids.size ()); + for (const auto id : ids) { + /* Get window dimensions */ + auto geometry_cookie = xcb_get_geometry (c, id); - auto geometry = xcb_unique_ptr (xcb_get_geometry_reply (c, geometry_cookie, &e)); + auto geometry = xcb_unique_ptr ( + xcb_get_geometry_reply (c, geometry_cookie, &e)); check (e, "XCB error while getting geometry reply"); - // auto icons = get_property_value(c, id, "_NET_WM_ICONS"); - render_info id_info={geometry.get()->x, geometry.get()->y, geometry.get()->width, geometry.get()->height}; - info.push_back(id_info); + + /* Get window's desktop id */ + + auto desktop_id = get_property_value (c, id, "_NET_WM_DESKTOP"); + + // TODO(sthussky): Get suitable window icon + + windows.emplace_back (desktop_id[0], uint (geometry->x), + uint (geometry->y), geometry->width, + geometry->height); } - return info; -} \ No newline at end of file + return windows; +} diff --git a/src/xcb_util.hpp b/src/xcb_util.hpp index e92f451..a84ca0c 100644 --- a/src/xcb_util.hpp +++ b/src/xcb_util.hpp @@ -45,6 +45,21 @@ struct monitor_info std::string name; }; +/** + * Information about window on a desktop. + * + * Used to draw desktop layouts in place of desktop screenshots + */ +struct window_info +{ + uint id; ///< Id of the desktop the window belongs to + uint x; + uint y; + uint width; + uint height; + // xcb_pixmap_t *icon ; TODO(sthussky): implement this +}; + class xcb_error : public std::runtime_error { public: @@ -114,6 +129,11 @@ uint get_current_desktop (xcb_connection_t *c, xcb_window_t root); void ewmh_change_desktop (xcb_connection_t *c, xcb_window_t root, uint destkop_id); +/** + * Returns an array of window informations + */ +std::vector get_windows (xcb_connection_t *c, xcb_window_t root); + /******************************************************************************* * XKB Related code ******************************************************************************/ @@ -254,16 +274,4 @@ get_keycodes (xcb_connection_t *c) return keycodes; } -struct render_info{ - uint x; - uint y; - uint width; - uint height; - //xcb_pixmap_t *icon ; TODO(sthussky): implement this -}; - -std::vector get_desktop_windows(xcb_connection_t *c, xcb_window_t root, uint32_t desktop); - -std::vector get_prerenders(xcb_connection_t *c, xcb_window_t root, uint desktop); - #endif /* ifndef DEXPO_XCB_HPP */ From 783231e33758cdc2e7e1acbb4a748e030c6746f9 Mon Sep 17 00:00:00 2001 From: mmskv Date: Sun, 18 Jul 2021 01:43:33 +0300 Subject: [PATCH 05/12] Change dxp_desktop resize functions to be members --- src/desktop.cpp | 69 +++++++++++++++++++++---------------------------- src/desktop.hpp | 34 ++++++++---------------- 2 files changed, 40 insertions(+), 63 deletions(-) diff --git a/src/desktop.cpp b/src/desktop.cpp index 5d55f6f..b3daba7 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -71,11 +71,10 @@ dxp_desktop::save_screen () // a low pass filter should be used on the source. int radius = this->width / this->pixmap_width / 2; - box_blur_horizontal (this->image_ptr, this->width, this->height, radius); - box_blur_vertical (this->image_ptr, this->width, this->height, radius); + this->box_blur_horizontal (radius); + this->box_blur_vertical (radius); - nn_resize (this->image_ptr, this->pixmap.data (), this->width, this->height, - this->pixmap_width, this->pixmap_height); + this->nn_resize (); } /** @@ -86,9 +85,9 @@ dxp_desktop::save_screen () * and here https://www.gamasutra.com/view/feature/3102 */ void -box_blur_horizontal (uint8_t *image, int width, int height, uint radius) +dxp_desktop::box_blur_horizontal (uint radius) { - auto *input32 = reinterpret_cast (image); + auto *input32 = reinterpret_cast (image_ptr); class pixmap img (input32, width); // Adds operator[][] constexpr uint32_t a_mask = 0xFF000000; @@ -170,9 +169,9 @@ box_blur_horizontal (uint8_t *image, int width, int height, uint radius) * Apply a vertical box filter (low pass) to the image. */ void -box_blur_vertical (uint8_t *image, int width, int height, uint radius) +dxp_desktop::box_blur_vertical (uint radius) { - auto *input32 = reinterpret_cast (image); + auto *input32 = reinterpret_cast (image_ptr); class pixmap img (input32, width); constexpr uint32_t r_mask = 0x00FF0000; @@ -242,15 +241,10 @@ box_blur_vertical (uint8_t *image, int width, int height, uint radius) * https://stackoverflow.com/questions/28566290 */ void -dxp_desktop::nn_resize (const uint8_t *__restrict input, - uint8_t *__restrict output, - int source_width, /* Source dimensions */ - int source_height, - int target_width, /* Target dimensions */ - int target_height) +dxp_desktop::nn_resize () { - const auto *input32 = reinterpret_cast (input); - auto *output32 = reinterpret_cast (output); + const auto *input32 = reinterpret_cast (image_ptr); + auto *output32 = reinterpret_cast (pixmap.data ()); // // Bitshifts are used to preserve precision in x_ratio and y_ratio. @@ -263,17 +257,17 @@ dxp_desktop::nn_resize (const uint8_t *__restrict input, // constexpr int k_precision_bytes = 16; - const int x_ratio = (source_width << k_precision_bytes) / target_width; - const int y_ratio = (source_height << k_precision_bytes) / target_height; + const int x_ratio = (width << k_precision_bytes) / pixmap_width; + const int y_ratio = (height << k_precision_bytes) / pixmap_height; - for (int y = 0; y < target_height; y++) + for (int y = 0; y < pixmap_height; y++) { - int y_source = ((y * y_ratio) >> k_precision_bytes) * source_width; - int y_dest = y * target_width; + int y_source = ((y * y_ratio) >> k_precision_bytes) * width; + int y_dest = y * pixmap_width; int x_source = 0; const uint32_t *input32_line = input32 + y_source; - for (int x = 0; x < target_width; x++) + for (int x = 0; x < pixmap_width; x++) { x_source += x_ratio; output32[y_dest + x] = input32_line[x_source >> k_precision_bytes]; @@ -287,40 +281,35 @@ dxp_desktop::nn_resize (const uint8_t *__restrict input, * significantly better images. So this resize algorithm is not used. */ void -dxp_desktop::bilinear_resize (const uint8_t *__restrict input, - uint8_t *__restrict output, - int source_width, /* Source dimensions */ - int source_height, - int target_width, /* Target dimensions */ - int target_height) +dxp_desktop::bilinear_resize () { - const float x_ratio = float (source_width) / target_width; - const float y_ratio = float (source_height) / target_height; + const float x_ratio = float (width) / pixmap_width; + const float y_ratio = float (height) / pixmap_height; - for (int y_dst = 0; y_dst < target_height; y_dst++) + for (int y_dst = 0; y_dst < pixmap_height; y_dst++) { float y_src = y_dst * y_ratio; int y = std::floor (y_src); float dy = y_src - y; - for (int x_dst = 0; x_dst < target_width; x_dst++) + for (int x_dst = 0; x_dst < pixmap_width; x_dst++) { float x_src = x_dst * x_ratio; int x = std::floor (x_src); float dx = x_src - x; - int y_offset = y_dst * target_width; + int y_offset = y_dst * pixmap_width; - int y0_offset = y * source_width; - int y1_offset = y0_offset + source_width; + int y0_offset = y * width; + int y1_offset = y0_offset + width; for (int ch = 0; ch < 4; ch++) { - output[(x_dst + y_offset) * 4 + ch] - = (input[(x + y0_offset) * 4 + ch] * (1 - dx) * (1 - dy) - + input[(x + y1_offset) * 4 + ch] * (1 - dx) * dy - + input[(x + 1 + y0_offset) * 4 + ch] * dx * (1 - dy) - + input[(x + 1 + y1_offset) * 4 + ch] * dx * dy); + pixmap[(x_dst + y_offset) * 4 + ch] + = (image_ptr[(x + y0_offset) * 4 + ch] * (1 - dx) * (1 - dy) + + image_ptr[(x + y1_offset) * 4 + ch] * (1 - dx) * dy + + image_ptr[(x + 1 + y0_offset) * 4 + ch] * dx * (1 - dy) + + image_ptr[(x + 1 + y1_offset) * 4 + ch] * dx * dy); } } } diff --git a/src/desktop.hpp b/src/desktop.hpp index 298db8b..7cedff6 100644 --- a/src/desktop.hpp +++ b/src/desktop.hpp @@ -66,36 +66,24 @@ class dxp_desktop : public drawable */ void save_screen (); + /** + * Apply a horizontal box filter (low pass) to the image. + */ + void box_blur_horizontal (uint radius); + /** + * Apply a vertical box filter (low pass) to the image. + */ + void box_blur_vertical (uint radius); + /** * Resize image to specified dimensions with nearest neighbour algorithm */ - static void - nn_resize (const uint8_t *input, ///< Input RGBA 1D array pointer - uint8_t *output, ///< Output RGBA 1D array pointers - int source_width, /* Dimensions of unresized screenshot */ - int source_height, - int target_width, /* Dimensions of screenshot after resize */ - int target_height); + void nn_resize (); /** * Resize image to specified dimensions with bilinear interpolation algorithm */ - static void - bilinear_resize (const uint8_t *input, ///< Input RGBA 1D array pointer - uint8_t *output, ///< Output RGBA 1D array pointers - int source_width, /* Dimensions of unresized screenshot */ - int source_height, - int target_width, /* Dimensions of screenshot after resize */ - int target_height); + void bilinear_resize (); }; -/** - * Apply a horizontal box filter (low pass) to the image. - */ -void box_blur_horizontal (uint8_t *image, int width, int height, uint radius); -/** - * Apply a vertical box filter (low pass) to the image. - */ -void box_blur_vertical (uint8_t *image, int width, int height, uint radius); - #endif /* ifndef DESKTOP_PIXMAP_HPP */ From b322177ae4c72d726df24b285cb584fc92a8b409 Mon Sep 17 00:00:00 2001 From: mmskv Date: Sun, 18 Jul 2021 01:48:53 +0300 Subject: [PATCH 06/12] Add config options for desktop layout --- src/config.hpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/config.hpp b/src/config.hpp index 0c2c94f..2cf89ac 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -61,13 +61,16 @@ const bool dxp_center_y = false; ///< Center dxp on the monitor vertically const uint16_t dxp_padding = 3; ///< Padding around the screenshots -color dxp_background = 0x444444; ///< Window background -color dxp_border_pres = 0xFFFFFF; ///< Desktop preselection -color dxp_border_nopres = 0x808080; ///< Desktop without preselection +color dxp_background = 0x444444; ///< Window background +color dxp_border_pres = 0xFFFFFF; ///< Desktop preselection +color dxp_border_nopres = 0x808080; ///< Desktop without preselection +color dxp_layout_background = 0x000214; ///< TODO(mmskv): Document +color dxp_layout_window_border = 0x2c0069; ///< TODO(mmskv): Document +color dxp_layout_window_background = 0x04001a; ///< TODO(mmskv): Document +const uint dxp_border_width = 0; ///< dxp window border const uint16_t dxp_border_pres_width = 2; ///< Width of the preselection - -const uint dxp_border_width = 0; ///< dxp window border +const uint dxp_desktop_layout_window_border_size = 2; ///< TODO(mmskv): Document /// /// How often to take screenshots. From 665185924b94aa3c4c39ccc98ac9aa9c7695d47e Mon Sep 17 00:00:00 2001 From: mmskv Date: Sun, 18 Jul 2021 01:52:51 +0300 Subject: [PATCH 07/12] Add width and height to dxp_socket_desktop Old with and height are renamed to pixmap_width and pixmap_height --- src/daemon.cpp | 10 +++++++--- src/socket.cpp | 6 +++--- src/socket.hpp | 5 ++++- src/window.cpp | 51 +++++++++++++++++++++++++------------------------- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/daemon.cpp b/src/daemon.cpp index 1396d1a..fcfc1b1 100644 --- a/src/daemon.cpp +++ b/src/daemon.cpp @@ -35,9 +35,12 @@ dxp_daemon::dxp_daemon () dxp_socket_desktop p; p.id = i; + p.active = false; + p.width = desktops[i].width; + p.height = desktops[i].height; p.pixmap_len = desktops[i].pixmap_width * desktops[i].pixmap_height * 4U; - p.width = desktops[i].pixmap_width; - p.height = desktops[i].pixmap_height; + p.pixmap_width = desktops[i].pixmap_width; + p.pixmap_height = desktops[i].pixmap_height; // Copying pixmap from desktops into socket pixmaps p.pixmap = desktops[i].pixmap; // Should be as fast as memcpy @@ -61,7 +64,7 @@ dxp_daemon::run () { throw std::runtime_error ( "The amount of virtual desktops specified in the config does not " - "match the amount of your virtual deskops in your system."); + "match the amount of virtual deskops in your system."); } this->socket_desktops_lock.lock (); @@ -69,6 +72,7 @@ dxp_daemon::run () // Copying pixmap from desktops into socket pixmaps this->socket_desktops[current].pixmap = this->desktops[current].pixmap; + this->socket_desktops[current].active = true; this->socket_desktops_lock.unlock (); diff --git a/src/socket.cpp b/src/socket.cpp index 77f473e..622b08a 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -198,14 +198,14 @@ dxp_socket::send_desktops_on_event ( "Failed to send number of desktops to dxp"); // Writes from second to `num+1` * 2 -- sending desktops - for (const auto &p : desktops) + for (const auto &d : desktops) { // Sending everything except raw pixmap - write_unix (data_fd, &p, offsetof (dxp_socket_desktop, pixmap), + write_unix (data_fd, &d, offsetof (dxp_socket_desktop, pixmap), "Failed to send desktop data to dxp"); // Sending pixmap - write_unix (data_fd, p.pixmap.data (), p.pixmap_len, + write_unix (data_fd, d.pixmap.data (), d.pixmap_len, "Failed to send raw desktop pixmap to dxp"); } } diff --git a/src/socket.hpp b/src/socket.hpp index 70ac5de..1cebc25 100644 --- a/src/socket.hpp +++ b/src/socket.hpp @@ -17,9 +17,12 @@ constexpr const char *k_socket_path = "/tmp/dxp.socket"; */ struct dxp_socket_desktop { - uint id; // _NET_CURRENT_DESKTOP + uint id; // _NET_CURRENT_DESKTOP + bool active; ///< Whether this desktop contains a screenshot in the pixmap uint16_t width; uint16_t height; + uint16_t pixmap_width; + uint16_t pixmap_height; uint32_t pixmap_len; std::vector pixmap; ///< Pixmap in RBGA format }; diff --git a/src/window.cpp b/src/window.cpp index 84f4033..eb7efd9 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -60,7 +60,7 @@ window::set_window_dimensions () for (const auto &d : this->desktops) { - dynamic += dxp_horizontal_stacking ? d.width : d.height; + dynamic += dxp_horizontal_stacking ? d.pixmap_width : d.pixmap_height; dynamic += dxp_padding + 2 * dxp_border_pres_width; } @@ -179,9 +179,9 @@ window::draw_desktops () for (const auto &desktop : this->desktops) { xcb_put_image (window::c, XCB_IMAGE_FORMAT_Z_PIXMAP, - this->xcb_id, /* Pixmap to put image on */ - window::gc, /* Graphic context */ - desktop.width, desktop.height, /* Dimensions */ + this->xcb_id, /* Pixmap to put image on */ + window::gc, /* Graphic context */ + desktop.pixmap_width, desktop.pixmap_height, x, /* Destination X coordinate */ y, /* Destination Y coordinate */ 0, window::screen->root_depth, @@ -189,12 +189,12 @@ window::draw_desktops () desktop.pixmap.data ()); if (dxp_horizontal_stacking) { - x += desktop.width; + x += desktop.pixmap_width; x += dxp_padding + 2 * dxp_border_pres_width; } else if (dxp_vertical_stacking) { - y += desktop.height; + y += desktop.pixmap_height; y += dxp_padding + 2 * dxp_border_pres_width; }; } @@ -218,7 +218,8 @@ window::get_desktop_coord (uint desktop_id) } // Append width for horizontal stacking and height for vertical - pos += dxp_horizontal_stacking ? desktop.width : desktop.height; + pos += dxp_horizontal_stacking ? desktop.pixmap_width + : desktop.pixmap_height; pos += dxp_padding + 2 * dxp_border_pres_width; } return 0; @@ -237,10 +238,10 @@ window::get_hover_desktop (int16_t x, int16_t y) if (dxp_vertical_stacking) { // Check if cursor is inside of the desktop - if (x >= dxp_padding && // Not to the left - x <= d.width + dxp_padding && // Not to the right - y >= d.y && // Not above - y <= d.height + d.y) // Not below + if (x >= dxp_padding && // Not to the left + x <= d.pixmap_width + dxp_padding && // Not to the right + y >= d.y && // Not above + y <= d.pixmap_height + d.y) // Not below { return d.id; } @@ -248,10 +249,10 @@ window::get_hover_desktop (int16_t x, int16_t y) else if (dxp_horizontal_stacking) { // Check if cursor is inside of the desktop - if (x >= d.x && // To the right of left border - x <= d.width + d.x && // To the left of right border - y >= dxp_padding && // Not above - y <= d.height + dxp_padding) // Not below + if (x >= d.x && // To the right of left border + x <= d.pixmap_width + d.x && // To the left of right border + y >= dxp_padding && // Not above + y <= d.pixmap_height + dxp_padding) // Not below { return d.id; } @@ -269,10 +270,10 @@ window::get_hover_desktop (int16_t x, int16_t y) { auto desktop_y = get_desktop_coord (d.id); // Check if cursor is inside of the desktop - if (x >= dxp_padding && // Not to the left - x <= d.width + dxp_padding && // Not to the right - y >= desktop_y && // Not above - y <= d.height + desktop_y) // Not below + if (x >= dxp_padding && // Not to the left + x <= d.pixmap_width + dxp_padding && // Not to the right + y >= desktop_y && // Not above + y <= d.pixmap_height + desktop_y) // Not below { // Cache new desktop recent_hover_desktop = { { d }, 0, desktop_y }; @@ -283,10 +284,10 @@ window::get_hover_desktop (int16_t x, int16_t y) { auto desktop_x = get_desktop_coord (d.id); // Check if cursor is inside of the desktop - if (x >= desktop_x && // To the right of left border - x <= d.width + desktop_x && // To the left of right border - y >= dxp_padding && // Not above - y <= d.height + dxp_padding) // Not below + if (x >= desktop_x && // To the right of left border + x <= d.pixmap_width + desktop_x && // To the left of right border + y >= dxp_padding && // Not above + y <= d.pixmap_height + dxp_padding) // Not below { // Cache new desktop recent_hover_desktop = { { d }, desktop_x, 0 }; @@ -308,8 +309,8 @@ window::draw_desktop_border (uint desktop_id, uint32_t color) int16_t x = 0; int16_t y = 0; - uint16_t width = this->desktops[desktop_id].width; - uint16_t height = this->desktops[desktop_id].height; + uint16_t width = this->desktops[desktop_id].pixmap_width; + uint16_t height = this->desktops[desktop_id].pixmap_height; if (dxp_vertical_stacking) { From 1869117be8a6cd09e8d21376b4aa8b1c9f00b80a Mon Sep 17 00:00:00 2001 From: mmskv Date: Sun, 18 Jul 2021 01:55:24 +0300 Subject: [PATCH 08/12] Remove desktop_id from desktop_info Use emplace_back instead of push_back Fix docs --- src/xcb_util.cpp | 9 ++++----- src/xcb_util.hpp | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/xcb_util.cpp b/src/xcb_util.cpp index 21fcee7..9a28a81 100644 --- a/src/xcb_util.cpp +++ b/src/xcb_util.cpp @@ -18,7 +18,7 @@ check (xcb_generic_error_t *e, const std::string &msg) }; /** - * Get a vector with EWMH property values + * Get a vector with EWMH property values by name * * @note vector size is inconsistent so vector may contain other data */ @@ -208,7 +208,7 @@ get_desktops (xcb_connection_t *c, xcb_window_t root) "`dxp_viewport`."); } - info.push_back (desktop_info{ i, x, y, width, height }); + info.emplace_back (/* i, */ x, y, width, height); } return info; @@ -223,15 +223,14 @@ get_current_desktop (xcb_connection_t *c, xcb_window_t root) return get_property_value (c, root, "_NET_CURRENT_DESKTOP")[0]; }; -constexpr uint8_t k_event_data32_length = 5; +constexpr uint8_t ewmh_event_data32_number = 5; // From EWMH specs /** * Generating and sending client message to the x server */ void send_xcb_message (xcb_connection_t *c, xcb_window_t root, const char *msg, - const std::array &data) + const std::array &data) { - // Making a double pointer to error doesn't look right xcb_generic_error_t *e = nullptr; auto atom_cookie = xcb_intern_atom (c, 0, strlen (msg), msg); diff --git a/src/xcb_util.hpp b/src/xcb_util.hpp index a84ca0c..4c6ecc5 100644 --- a/src/xcb_util.hpp +++ b/src/xcb_util.hpp @@ -24,7 +24,7 @@ */ struct desktop_info { - uint id; // XXX Is it necessary? + // uint id; int x; int y; uint width; @@ -52,7 +52,7 @@ struct monitor_info */ struct window_info { - uint id; ///< Id of the desktop the window belongs to + uint desktop; ///< Id of the desktop the window belongs to uint x; uint y; uint width; From 3d68cabd70f9d0bb26d334fdaf9f7a159b206925 Mon Sep 17 00:00:00 2001 From: mmskv Date: Sun, 18 Jul 2021 02:27:50 +0300 Subject: [PATCH 09/12] Add logic for features #38 and #40 --- src/dxp.cpp | 16 +++++-------- src/window.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/window.hpp | 20 ++++++++++++++++- 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/src/dxp.cpp b/src/dxp.cpp index c59937d..5155e12 100644 --- a/src/dxp.cpp +++ b/src/dxp.cpp @@ -19,18 +19,14 @@ main () try { // Get screenshots from socket or create them manually - // if (dxp_do_screenshots) - // { - dxp_socket client; - auto v = client.get_desktops (); - // } - // else - // { - // auto v = get_desktops (); - // } + std::vector v{}; + if (dxp_do_screenshots) + { + dxp_socket client; + v = client.get_desktops (); + } window w (v); - auto windows = get_windows (window::c, window::root); // Handling incoming events // Freeing it with free() is not specified in the docs, but it works diff --git a/src/window.cpp b/src/window.cpp index eb7efd9..d996a3e 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1,5 +1,6 @@ #include "window.hpp" #include "config.hpp" // for dxp_padding, dxp_border_pres_width, dxp_x +#include "desktop.hpp" // for pixmap #include "drawable.hpp" // for drawable::c, drawable::root, drawable::screen #include "xcb_util.hpp" // for monitor_info, dxp_keycodes, ewmh_change_desktop #include // for array @@ -20,8 +21,17 @@ window::window (const std::vector &desktops) { this->xcb_id = xcb_generate_id (drawable::c); this->desktops = desktops; + this->windows = get_windows (window::c, window::root); this->pres = 0; ///< id of the preselected desktop + if (!dxp_do_screenshots) + { + // TODO(mmskv): Initialize this->desktops + } + + // Draw window geometries over desktops without screenshots + draw_windows_layout (); + // Construct recent_hover_desktop if (dxp_vertical_stacking) { @@ -200,6 +210,57 @@ window::draw_desktops () } } +/** + * Draw windows layout on the desktop + * + * Used when there are no screenshot of the desktop available + */ +void +window::draw_windows_layout () +{ + for (auto &d : desktops) + { + if (d.active) // Ignore desktops for which screenshots exist + { + continue; + } + + auto *pixmap = reinterpret_cast (d.pixmap.data ()); + + for (size_t i = 0; i < d.pixmap_width * d.pixmap_height; i++) + { + pixmap[i] = dxp_layout_background; + } + + class pixmap p (pixmap, width); + + for (const auto &src_w : windows) + { + // Translate coordinates + const float x_ratio = float (d.width) / d.pixmap_width; + const float y_ratio = float (d.height) / d.pixmap_height; + + window_info w{ + 0, + uint (src_w.x / x_ratio), + uint (src_w.y / y_ratio), + uint (src_w.width / x_ratio), + uint (src_w.height / y_ratio), + }; + + // Fill window with dxp_layout_window_background color + + // Draw top border + + // Draw left border + + // Draw right border + + // Draw bottom border + } + } +} + /** * Get coordinate of the displayed desktop relative to the window */ diff --git a/src/window.hpp b/src/window.hpp index 528cc0c..a65a5fe 100644 --- a/src/window.hpp +++ b/src/window.hpp @@ -3,6 +3,7 @@ #include "drawable.hpp" // for drawable #include "socket.hpp" // for dxp_socket_desktop +#include "xcb_util.hpp" // for window_info #include // for int16_t, uint32_t #include // for uint #include // for vector @@ -30,7 +31,8 @@ class window : public drawable uint32_t xcb_id; std::vector desktops; ///< Desktops received from daemon dxp_window_desktop recent_hover_desktop; ///< Recently cached hover desktop - uint pres; ///< id of the preselected desktop + std::vector windows; ///< List window_info for all windows + uint pres; ///< id of the preselected desktop explicit window (const std::vector &desktops); ~window (); @@ -52,6 +54,22 @@ class window : public drawable */ void create_window (); + /** + * Draw windows layout on the desktop + * + * Used to fill a desktop with windows layout when there are no screenshots + * of the desktop available + */ + void draw_windows_layout (); + + /** + * Draw border over window + * + * Used to highlight window when it is preselected + * Or to highlight all windows that are not preselected + */ + void draw_window_border (window_info window, uint32_t color); + /** * Draw desktops on the window */ From 3e7fee8721cba505f987cdc4f7cdbe19319205fe Mon Sep 17 00:00:00 2001 From: sthussky Date: Sun, 18 Jul 2021 15:58:03 +0300 Subject: [PATCH 10/12] Add icons to struct, add docs --- src/xcb_util.cpp | 9 ++++++--- src/xcb_util.hpp | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/xcb_util.cpp b/src/xcb_util.cpp index 9a28a81..4e011e7 100644 --- a/src/xcb_util.cpp +++ b/src/xcb_util.cpp @@ -268,6 +268,10 @@ ewmh_change_desktop (xcb_connection_t *c, xcb_window_t root, uint destkop_id) send_xcb_message (c, root, "_NET_CURRENT_DESKTOP", { destkop_id }); } +/** + * Get information about all windows, including ids, related desktops, + * geometries and icons + */ std::vector get_windows (xcb_connection_t *c, xcb_window_t root) { @@ -291,11 +295,10 @@ get_windows (xcb_connection_t *c, xcb_window_t root) auto desktop_id = get_property_value (c, id, "_NET_WM_DESKTOP"); - // TODO(sthussky): Get suitable window icon - windows.emplace_back (desktop_id[0], uint (geometry->x), uint (geometry->y), geometry->width, - geometry->height); + geometry->height, + get_property_value (c, id, "_NET_WM_ICON")); } return windows; } diff --git a/src/xcb_util.hpp b/src/xcb_util.hpp index 4c6ecc5..40a52be 100644 --- a/src/xcb_util.hpp +++ b/src/xcb_util.hpp @@ -57,7 +57,7 @@ struct window_info uint y; uint width; uint height; - // xcb_pixmap_t *icon ; TODO(sthussky): implement this + std::vector icons; ///< _NET_WM_ICON value }; class xcb_error : public std::runtime_error From dad88177d576fe893b138961718c538dd92b1473 Mon Sep 17 00:00:00 2001 From: mmskv Date: Mon, 19 Jul 2021 22:13:10 +0300 Subject: [PATCH 11/12] Add x and y properties to dxp_socket_desktop --- src/daemon.cpp | 2 ++ src/socket.hpp | 39 ++++++++------------------------------- src/xcb_util.hpp | 26 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/daemon.cpp b/src/daemon.cpp index fcfc1b1..66386af 100644 --- a/src/daemon.cpp +++ b/src/daemon.cpp @@ -36,6 +36,8 @@ dxp_daemon::dxp_daemon () p.id = i; p.active = false; + p.x = desktops[i].x; + p.y = desktops[i].y; p.width = desktops[i].width; p.height = desktops[i].height; p.pixmap_len = desktops[i].pixmap_width * desktops[i].pixmap_height * 4U; diff --git a/src/socket.hpp b/src/socket.hpp index 1cebc25..36ddf69 100644 --- a/src/socket.hpp +++ b/src/socket.hpp @@ -1,40 +1,17 @@ #ifndef DEXPO_SOCKET_HPP #define DEXPO_SOCKET_HPP -#include // for atomic -#include // for uint8_t, uint16_t, uint32_t -#include // for mutex -#include // for runtime_error -#include // for string -#include // for uint -#include // for vector +#include "xcb_util.hpp" // for dxp_socket_desktop, dxp_event +#include // for atomic +#include // for uint8_t, uint16_t, uint32_t +#include // for mutex +#include // for runtime_error +#include // for string +#include // for uint +#include // for vector constexpr const char *k_socket_path = "/tmp/dxp.socket"; -/** - * Dekstop struct that will be transferred over socket - * Contains only necessary data - */ -struct dxp_socket_desktop -{ - uint id; // _NET_CURRENT_DESKTOP - bool active; ///< Whether this desktop contains a screenshot in the pixmap - uint16_t width; - uint16_t height; - uint16_t pixmap_width; - uint16_t pixmap_height; - uint32_t pixmap_len; - std::vector pixmap; ///< Pixmap in RBGA format -}; - -/** - * All commands that can be sent by client to daemon - */ -enum dxp_event -{ - RequestDesktops = 1 // Request all pixmaps -}; - class dxp_socket { public: diff --git a/src/xcb_util.hpp b/src/xcb_util.hpp index 40a52be..ee798bf 100644 --- a/src/xcb_util.hpp +++ b/src/xcb_util.hpp @@ -19,6 +19,32 @@ #include // for xcb_key_symbols_free, xcb_key_symbols_a... #include // for xcb_keycode_t, xcb_window_t, xcb_keysym_t +/** + * Dekstop struct that will be transferred over socket + * Contains only necessary data + */ +struct dxp_socket_desktop +{ + uint id; // _NET_CURRENT_DESKTOP + bool active; ///< Whether this desktop contains a screenshot in the pixmap + int16_t x; ///< Relative to the root + int16_t y; ///< Relative to the root + uint16_t width; + uint16_t height; + uint16_t pixmap_width; + uint16_t pixmap_height; + uint32_t pixmap_len; + std::vector pixmap; ///< Pixmap in RBGA format +}; + +/** + * All commands that can be sent by client to daemon + */ +enum dxp_event +{ + RequestDesktops = 1 // Request all pixmaps +}; + /** * Virtual desktop information */ From 9ee5727e9331c6541e2693ea72f908be2091f794 Mon Sep 17 00:00:00 2001 From: mmskv Date: Mon, 19 Jul 2021 22:14:13 +0300 Subject: [PATCH 12/12] Add draw_window implementation --- src/window.cpp | 144 +++++++++++++++++++++++++++++++++++++++-------- src/xcb_util.cpp | 28 ++++++--- src/xcb_util.hpp | 13 +++-- 3 files changed, 148 insertions(+), 37 deletions(-) diff --git a/src/window.cpp b/src/window.cpp index d996a3e..7676813 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -21,7 +21,7 @@ window::window (const std::vector &desktops) { this->xcb_id = xcb_generate_id (drawable::c); this->desktops = desktops; - this->windows = get_windows (window::c, window::root); + this->windows = get_windows (window::c, window::root, this->desktops); this->pres = 0; ///< id of the preselected desktop if (!dxp_do_screenshots) @@ -210,6 +210,119 @@ window::draw_desktops () } } +unsigned int +blend_alpha (uint colora, uint colorb, uint alpha) +{ + uint rb1 = ((0x100 - alpha) * (colora & 0xFF00FF)) >> 8; + uint rb2 = (alpha * (colorb & 0xFF00FF)) >> 8; + uint g1 = ((0x100 - alpha) * (colora & 0x00FF00)) >> 8; + uint g2 = (alpha * (colorb & 0x00FF00)) >> 8; + return ((rb1 | rb2) & 0xFF00FF) + ((g1 | g2) & 0x00FF00); +} + +void +draw_window (pixmap &p, const dxp_socket_desktop &d, const window_info &src_w) +{ + /* Translate coordinates */ + const float downsize_ratio = float (d.width) / d.pixmap_width; + + window_info w{ + 0, + int (std::round (src_w.x / downsize_ratio)), + int (std::round (src_w.y / downsize_ratio)), + uint (std::round (src_w.width / downsize_ratio)), + uint (std::round (src_w.height / downsize_ratio)), + }; + + /* Cap x, y, width, height so no overflow occurs */ + + // Cap x + if (w.x < 0) + { + w.width = w.width - abs (w.x); // Subtract part that is off-screen + w.x = 0; + } + // Cap width + w.width = w.width + w.x < d.pixmap_width ? w.width : d.pixmap_width; + + // Cap y + if (w.y < 0) + { + w.height = w.height - abs (w.y); // Subtract part that is off-screen + w.y = 0; + } + // Cap height + w.height = w.height + w.y < d.pixmap_height ? w.height : d.pixmap_height; + + // Fill window with dxp_layout_window_background color + for (int y = w.y; y < w.y + w.height; y++) + { + for (int x = w.x; x < w.x + w.width; x++) + { + p[x][y] = dxp_layout_window_background; + } + } + + if (src_w.icons.empty ()) + { + return; + } + + // Get available icon sizes + struct icon_info + { + uint32_t width; + uint32_t height; + uint32_t offset; + }; + + std::vector icon_infos; // x, y, offset + icon_infos.emplace_back (src_w.icons[0], src_w.icons[1]); + uint32_t next_icon_offset + = icon_infos.back ().width * icon_infos.back ().height + 2; + + while (next_icon_offset < src_w.icons.size ()) + { + icon_infos.emplace_back (src_w.icons[next_icon_offset], + src_w.icons[next_icon_offset + 1], + next_icon_offset); + next_icon_offset + += icon_infos.back ().width * icon_infos.back ().height + 2; + } + + // Select icon that fits and does not occupy more than 50% of window space + icon_info best_icon{}; + for (const auto &icon : icon_infos) + { + if (icon.width > w.width || icon.height > w.height) + { + continue; + } + + // TODO(mmskv): Resize icon + best_icon = icon; + break; + } + + constexpr uint32_t a_mask = 0xFF000000; + constexpr uint32_t r_mask = 0x00FF0000; + constexpr uint32_t g_mask = 0x0000FF00; + constexpr uint32_t b_mask = 0x000000FF; + // Draw icon + int icon_x = w.x + w.width / 2 - best_icon.width / 2; // Relative to desktop + int icon_y = w.y + w.height / 2 - best_icon.height / 2; // Relative to desktop + for (int y1 = 0, y = icon_y; y < icon_y + best_icon.height; y++, y1++) + { + for (int x1 = 0, x = icon_x; x < icon_x + best_icon.width; x++, x1++) + { + int xy_offset = y1 * best_icon.width + x1; + uint32_t c = src_w.icons[best_icon.offset + 2 + xy_offset]; + uint8_t alpha = c >> 24; + p[x][y] = blend_alpha (p[x][y], c, alpha); + } + } +} + /** * Draw windows layout on the desktop * @@ -220,7 +333,7 @@ window::draw_windows_layout () { for (auto &d : desktops) { - if (d.active) // Ignore desktops for which screenshots exist + if (d.active) // Ignore desktops for which screenshots already exist { continue; } @@ -232,31 +345,14 @@ window::draw_windows_layout () pixmap[i] = dxp_layout_background; } - class pixmap p (pixmap, width); + class pixmap p (pixmap, d.pixmap_width); for (const auto &src_w : windows) { - // Translate coordinates - const float x_ratio = float (d.width) / d.pixmap_width; - const float y_ratio = float (d.height) / d.pixmap_height; - - window_info w{ - 0, - uint (src_w.x / x_ratio), - uint (src_w.y / y_ratio), - uint (src_w.width / x_ratio), - uint (src_w.height / y_ratio), - }; - - // Fill window with dxp_layout_window_background color - - // Draw top border - - // Draw left border - - // Draw right border - - // Draw bottom border + if (src_w.desktop == d.id) // Check if window is on same desktop + { + draw_window (p, d, src_w); + } } } } diff --git a/src/xcb_util.cpp b/src/xcb_util.cpp index 4e011e7..a84b3a0 100644 --- a/src/xcb_util.cpp +++ b/src/xcb_util.cpp @@ -1,5 +1,6 @@ #include "xcb_util.hpp" -#include "config.hpp" // for dxp_viewport +#include "config.hpp" // for dxp_viewport +#include "socket.hpp" #include // for uint32_t, uint8_t, UINT32_MAX #include // for strlen #include // for xcb_randr_get_crtc_info_reply_t, xcb_randr_ge... @@ -51,7 +52,7 @@ get_property_value (xcb_connection_t *c, xcb_window_t root, // will be freed by prop_reply auto *prop = prop_length ? (reinterpret_cast ( xcb_get_property_value (prop_reply.get ()))) - : throw; + : nullptr; std::vector atom_data; @@ -270,10 +271,14 @@ ewmh_change_desktop (xcb_connection_t *c, xcb_window_t root, uint destkop_id) /** * Get information about all windows, including ids, related desktops, - * geometries and icons + * geometries and icons. + * + * Desktops are used to calculate real window coordinates */ std::vector -get_windows (xcb_connection_t *c, xcb_window_t root) +get_windows (xcb_connection_t *c, xcb_window_t root, + std::vector &desktops) + { xcb_generic_error_t *e = nullptr; std::vector windows; @@ -292,12 +297,17 @@ get_windows (xcb_connection_t *c, xcb_window_t root) check (e, "XCB error while getting geometry reply"); /* Get window's desktop id */ + auto net_wm_desktop = get_property_value (c, id, "_NET_WM_DESKTOP"); + if (net_wm_desktop.empty ()) + { + continue; + } + auto desktop_id = net_wm_desktop[0]; - auto desktop_id = get_property_value (c, id, "_NET_WM_DESKTOP"); - - windows.emplace_back (desktop_id[0], uint (geometry->x), - uint (geometry->y), geometry->width, - geometry->height, + // Get window coordinates relative to the desktop + int x = geometry->x - desktops[desktop_id].x; + int y = geometry->y - desktops[desktop_id].y; + windows.emplace_back (desktop_id, x, y, geometry->width, geometry->height, get_property_value (c, id, "_NET_WM_ICON")); } return windows; diff --git a/src/xcb_util.hpp b/src/xcb_util.hpp index ee798bf..5388232 100644 --- a/src/xcb_util.hpp +++ b/src/xcb_util.hpp @@ -79,8 +79,8 @@ struct monitor_info struct window_info { uint desktop; ///< Id of the desktop the window belongs to - uint x; - uint y; + int x; + int y; uint width; uint height; std::vector icons; ///< _NET_WM_ICON value @@ -156,9 +156,14 @@ void ewmh_change_desktop (xcb_connection_t *c, xcb_window_t root, uint destkop_id); /** - * Returns an array of window informations + * Get information about all windows, including ids, related desktops, + * geometries and icons. + * + * Desktops are used to calculate real window coordinates */ -std::vector get_windows (xcb_connection_t *c, xcb_window_t root); +std::vector +get_windows (xcb_connection_t *c, xcb_window_t root, + std::vector &desktops); /******************************************************************************* * XKB Related code