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; }