From b8c275d6ac85b449e16715cd68e9ae03c2b1ec22 Mon Sep 17 00:00:00 2001
From: patrick96
Date: Wed, 16 Mar 2022 18:37:34 +0100
Subject: [PATCH] Fix BadMatch error for wrapper window
The wrapper window must define a border background if the depth doesn't
match the parent window.
---
src/x11/tray_client.cpp | 28 ++++++++++++++++++----------
src/x11/tray_manager.cpp | 38 ++++++++++++++++++++------------------
2 files changed, 38 insertions(+), 28 deletions(-)
diff --git a/src/x11/tray_client.cpp b/src/x11/tray_client.cpp
index 9a6c1ce5..a11ef96e 100644
--- a/src/x11/tray_client.cpp
+++ b/src/x11/tray_client.cpp
@@ -9,33 +9,41 @@
POLYBAR_NS
-// TODO create wrapper window
tray_client::tray_client(const logger& log, connection& conn, xcb_window_t tray, xcb_window_t win, size s)
: m_log(log), m_connection(conn), m_client(win), m_size(s) {
auto geom = conn.get_geometry(win);
auto attrs = conn.get_window_attributes(win);
- int depth = geom->depth;
- xcb_visualid_t visual = attrs->visual;
- m_log.trace("tray(%s): depth: %u, width: %u, height: %u, visual: 0x%x", conn.id(win), depth, geom->width, geom->height, visual);
+ int client_depth = geom->depth;
+ auto client_visual = attrs->visual;
+ auto client_colormap = attrs->colormap;
+ m_log.trace("tray(%s): depth: %u, width: %u, height: %u", conn.id(win), client_depth, geom->width, geom->height);
+
+ /*
+ * Create embedder window for tray icon
+ *
+ * The embedder window inherits the depth, visual and color map from the icon window in order for reparenting to
+ * always work, even if the icon window uses ParentRelative for some of its pixmaps (back pixmap or border pixmap).
+ */
// clang-format off
m_wrapper = winspec(conn)
<< cw_size(s.h, s.w)
<< cw_pos(0, 0)
- // TODO fix BadMatch error for redshift-gtk window
- // << cw_depth(depth)
- // << cw_visual(visual)
+ << cw_depth(client_depth)
+ << cw_visual(client_visual)
<< cw_parent(tray)
+ << cw_class(XCB_WINDOW_CLASS_INPUT_OUTPUT)
// TODO add proper pixmap
<< cw_params_back_pixmap(XCB_PIXMAP_NONE)
- // << cw_class(XCB_WINDOW_CLASS_INPUT_OUTPUT)
+ // The X server requires the border pixel to be defined if the depth doesn't match the parent window
+ << cw_params_border_pixel(conn.screen()->black_pixel)
<< cw_params_backing_store(XCB_BACKING_STORE_WHEN_MAPPED)
+ << cw_params_save_under(true)
<< cw_params_event_mask(XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
| XCB_EVENT_MASK_PROPERTY_CHANGE
| XCB_EVENT_MASK_STRUCTURE_NOTIFY
| XCB_EVENT_MASK_EXPOSURE)
- // << cw_flush(false);
- // TODO Make unchecked
+ << cw_params_colormap(client_colormap)
<< cw_flush(true);
// clang-format on
}
diff --git a/src/x11/tray_manager.cpp b/src/x11/tray_manager.cpp
index 6dfc9800..664160c1 100644
--- a/src/x11/tray_manager.cpp
+++ b/src/x11/tray_manager.cpp
@@ -475,13 +475,14 @@ void tray_manager::create_window() {
auto win = winspec(m_connection)
<< cw_size(calculate_w(), calculate_h())
<< cw_pos(calculate_x(calculate_w()), calculate_y())
+ << cw_depth(XCB_COPY_FROM_PARENT)
+ << cw_visual(XCB_COPY_FROM_PARENT)
+ << cw_params_colormap(XCB_COPY_FROM_PARENT)
<< cw_class(XCB_WINDOW_CLASS_INPUT_OUTPUT)
<< cw_params_backing_store(XCB_BACKING_STORE_WHEN_MAPPED)
<< cw_params_event_mask(XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
|XCB_EVENT_MASK_STRUCTURE_NOTIFY
|XCB_EVENT_MASK_EXPOSURE)
- // TODO
- // << cw_params_override_redirect(true)
<< cw_parent(m_opts.bar_window);
// clang-format on
@@ -700,22 +701,22 @@ void tray_manager::track_selection_owner(xcb_window_t owner) {
void tray_manager::process_docking_request(xcb_window_t win) {
m_log.info("Processing docking request from '%s' (%s)", ewmh_util::get_wm_name(win), m_connection.id(win));
- tray_client client(m_log, m_connection, m_tray, win, m_opts.client_size);
-
try {
- client.query_xembed();
- } catch (const xpp::x::error::window& err) {
- m_log.err("Failed to query _XEMBED_INFO, removing client... (%s)", err.what());
- return;
- }
+ tray_client client(m_log, m_connection, m_tray, win, m_opts.client_size);
- m_log.trace("tray: xembed = %s", client.is_xembed_supported() ? "true" : "false");
- if (client.is_xembed_supported()) {
- m_log.trace("tray: version = 0x%x, flags = 0x%x, XEMBED_MAPPED = %s", client.get_xembed().get_version(),
- client.get_xembed().get_flags(), client.get_xembed().is_mapped() ? "true" : "false");
- }
+ try {
+ client.query_xembed();
+ } catch (const xpp::x::error::window& err) {
+ m_log.err("Failed to query _XEMBED_INFO, removing client... (%s)", err.what());
+ return;
+ }
+
+ m_log.trace("tray: xembed = %s", client.is_xembed_supported() ? "true" : "false");
+ if (client.is_xembed_supported()) {
+ m_log.trace("tray: version = 0x%x, flags = 0x%x, XEMBED_MAPPED = %s", client.get_xembed().get_version(),
+ client.get_xembed().get_flags(), client.get_xembed().is_mapped() ? "true" : "false");
+ }
- try {
const uint32_t mask = XCB_CW_EVENT_MASK;
const uint32_t value = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
@@ -746,13 +747,13 @@ void tray_manager::process_docking_request(xcb_window_t win) {
m_connection.map_window_checked(client.client());
m_connection.map_window_checked(client.embedder());
}
+
+ m_clients.emplace_back(std::move(client));
} catch (const std::exception& err) {
m_log.err("Failed to setup tray client '%s' (%s) removing... (%s)", ewmh_util::get_wm_name(win),
m_connection.id(win), err.what());
return;
}
-
- m_clients.emplace_back(std::move(client));
}
/**
@@ -976,7 +977,8 @@ void tray_manager::handle(const evt::property_notify& evt) {
}
// React an wallpaper change, if bar has transparency
- if (m_opts.transparent && (evt->atom == _XROOTPMAP_ID || evt->atom == _XSETROOT_ID || evt->atom == ESETROOT_PMAP_ID)) {
+ if (m_opts.transparent &&
+ (evt->atom == _XROOTPMAP_ID || evt->atom == _XSETROOT_ID || evt->atom == ESETROOT_PMAP_ID)) {
redraw_window();
return;
}