fix(render): support stacked bars
We now take the bar position that the window manager gives us instead of trying to calculate it ourselves. This is more correct when multiple bars are attached to the same edge, as the window manager may move some of them in that case (assuming override redirect is not enabled)
This commit is contained in:
parent
eb742e228b
commit
51d58e7518
@ -51,7 +51,7 @@ inline double geom_format_to_pixels(std::string str, double max) {
|
||||
}
|
||||
|
||||
class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify, evt::enter_notify,
|
||||
evt::leave_notify, evt::motion_notify, evt::destroy_notify, evt::client_message>,
|
||||
evt::leave_notify, evt::motion_notify, evt::destroy_notify, evt::client_message, evt::configure_notify>,
|
||||
public signal_receiver<SIGN_PRIORITY_BAR, signals::eventqueue::start, signals::ui::tick,
|
||||
signals::ui::shade_window, signals::ui::unshade_window, signals::ui::dim_window
|
||||
#if WITH_XCURSOR
|
||||
@ -89,6 +89,7 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
||||
void handle(const evt::button_press& evt);
|
||||
void handle(const evt::expose& evt);
|
||||
void handle(const evt::property_notify& evt);
|
||||
void handle(const evt::configure_notify& evt);
|
||||
|
||||
bool on(const signals::eventqueue::start&);
|
||||
bool on(const signals::ui::unshade_window&);
|
||||
|
@ -123,6 +123,9 @@ namespace signals {
|
||||
struct update_background : public detail::base_signal<update_background> {
|
||||
using base_type::base_type;
|
||||
};
|
||||
struct update_geometry : public detail::base_signal<update_geometry> {
|
||||
using base_type::base_type;
|
||||
};
|
||||
}
|
||||
|
||||
namespace ui_tray {
|
||||
|
@ -39,6 +39,7 @@ namespace signals {
|
||||
struct unshade_window;
|
||||
struct request_snapshot;
|
||||
struct update_background;
|
||||
struct update_geometry;
|
||||
}
|
||||
namespace ui_tray {
|
||||
struct mapped_clients;
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include "common.hpp"
|
||||
#include "events/signal_fwd.hpp"
|
||||
#include "events/signal_receiver.hpp"
|
||||
#include "events/types.hpp"
|
||||
#include "x11/extensions/fwd.hpp"
|
||||
#include "x11/types.hpp"
|
||||
|
||||
@ -14,7 +16,9 @@ namespace cairo {
|
||||
class xcb_surface;
|
||||
}
|
||||
|
||||
class background_manager : public xpp::event::sink<evt::property_notify> {
|
||||
class background_manager : public signal_receiver<SIGN_PRIORITY_SCREEN, signals::ui::update_geometry>,
|
||||
public xpp::event::sink<evt::property_notify>
|
||||
{
|
||||
public:
|
||||
using make_type = background_manager&;
|
||||
static make_type make();
|
||||
@ -28,6 +32,7 @@ class background_manager : public xpp::event::sink<evt::property_notify> {
|
||||
cairo::surface* get_surface() const;
|
||||
|
||||
void handle(const evt::property_notify& evt);
|
||||
bool on(const signals::ui::update_geometry&);
|
||||
private:
|
||||
connection& m_connection;
|
||||
signal_emitter& m_sig;
|
||||
|
@ -761,9 +761,6 @@ void bar::handle(const evt::expose& evt) {
|
||||
* state of the tray container even though the tray
|
||||
* window restacking failed. Used as a fallback for
|
||||
* tedious WM's, like i3.
|
||||
*
|
||||
* - Track the root pixmap atom to update the
|
||||
* pseudo-transparent background when it changes
|
||||
*/
|
||||
void bar::handle(const evt::property_notify& evt) {
|
||||
#ifdef DEBUG_LOGGER_VERBOSE
|
||||
@ -776,6 +773,13 @@ void bar::handle(const evt::property_notify& evt) {
|
||||
}
|
||||
}
|
||||
|
||||
void bar::handle(const evt::configure_notify&) {
|
||||
// The absolute position of the window in the root may be different after configuration is done
|
||||
// (for example, because the parent is not positioned at 0/0 in the root window).
|
||||
// Notify components that the geometry may have changed (used by the background manager for example).
|
||||
m_sig.emit(signals::ui::update_geometry{});
|
||||
}
|
||||
|
||||
bool bar::on(const signals::eventqueue::start&) {
|
||||
m_log.trace("bar: Create renderer");
|
||||
m_renderer = renderer::make(m_opts);
|
||||
@ -789,6 +793,7 @@ bool bar::on(const signals::eventqueue::start&) {
|
||||
if (!m_opts.cursor_click.empty() || !m_opts.cursor_scroll.empty() ) {
|
||||
m_connection.ensure_event_mask(m_opts.window, XCB_EVENT_MASK_POINTER_MOTION);
|
||||
}
|
||||
m_connection.ensure_event_mask(m_opts.window, XCB_EVENT_MASK_STRUCTURE_NOTIFY);
|
||||
|
||||
m_log.info("Bar window: %s", m_connection.id(m_opts.window));
|
||||
restack_window();
|
||||
@ -800,6 +805,10 @@ bool bar::on(const signals::eventqueue::start&) {
|
||||
m_log.trace("bar: Map window");
|
||||
m_connection.map_window_checked(m_opts.window);
|
||||
|
||||
// With the mapping, the absolute position of our window may have changed (due to re-parenting for example).
|
||||
// Notify all components that depend on the absolute bar position (such as the background manager).
|
||||
m_sig.emit(signals::ui::update_geometry{});
|
||||
|
||||
// Reconfigure window position after mapping (required by Openbox)
|
||||
// Required by Openbox
|
||||
reconfigure_pos();
|
||||
|
@ -166,7 +166,7 @@ renderer::renderer(
|
||||
}
|
||||
|
||||
m_log.trace("Activate root background manager");
|
||||
m_background.activate(m_window, m_bar.outer_area(true));
|
||||
m_background.activate(m_window, m_bar.outer_area(false));
|
||||
}
|
||||
|
||||
m_comp_bg = m_conf.get<cairo_operator_t>("settings", "compositing-background", m_comp_bg);
|
||||
|
@ -18,9 +18,11 @@ background_manager::background_manager(
|
||||
: m_connection(conn)
|
||||
, m_sig(sig)
|
||||
, m_log(log) {
|
||||
m_sig.attach(this);
|
||||
}
|
||||
|
||||
background_manager::~background_manager() {
|
||||
m_sig.detach(this);
|
||||
free_resources();
|
||||
}
|
||||
|
||||
@ -110,24 +112,26 @@ void background_manager::fetch_root_pixmap() {
|
||||
xcb_pixmap_t pixmap;
|
||||
xcb_rectangle_t pixmap_geom;
|
||||
|
||||
if (!m_connection.root_pixmap(&pixmap, &pixmap_depth, &pixmap_geom)) {
|
||||
free_resources();
|
||||
return m_log.err("background_manager: Failed to get root pixmap for background (realloc=%i)", realloc);
|
||||
};
|
||||
|
||||
auto src_x = math_util::cap(m_rect.x, pixmap_geom.x, int16_t(pixmap_geom.x + pixmap_geom.width));
|
||||
auto src_y = math_util::cap(m_rect.y, pixmap_geom.y, int16_t(pixmap_geom.y + pixmap_geom.height));
|
||||
auto h = math_util::min(m_rect.height, pixmap_geom.height);
|
||||
auto w = math_util::min(m_rect.width, pixmap_geom.width);
|
||||
|
||||
m_log.trace("background_manager: Copying from root pixmap (%d) %dx%d+%dx%d", pixmap, w, h, src_x, src_y);
|
||||
try {
|
||||
auto translated = m_connection.translate_coordinates(m_window, m_connection.screen()->root, m_rect.x, m_rect.y);
|
||||
if (!m_connection.root_pixmap(&pixmap, &pixmap_depth, &pixmap_geom)) {
|
||||
free_resources();
|
||||
return m_log.err("background_manager: Failed to get root pixmap for background (realloc=%i)", realloc);
|
||||
};
|
||||
|
||||
auto src_x = math_util::cap(translated->dst_x, pixmap_geom.x, int16_t(pixmap_geom.x + pixmap_geom.width));
|
||||
auto src_y = math_util::cap(translated->dst_y, pixmap_geom.y, int16_t(pixmap_geom.y + pixmap_geom.height));
|
||||
auto h = math_util::min(m_rect.height, pixmap_geom.height);
|
||||
auto w = math_util::min(m_rect.width, pixmap_geom.width);
|
||||
|
||||
m_log.trace("background_manager: Copying from root pixmap (%d) %dx%d+%dx%d", pixmap, w, h, src_x, src_y);
|
||||
m_connection.copy_area_checked(pixmap, m_pixmap, m_gcontext, src_x, src_y, 0, 0, w, h);
|
||||
} catch (const exception& err) {
|
||||
} catch(const exception& err) {
|
||||
m_log.err("background_manager: Failed to copy slice of root pixmap (%s)", err.what());
|
||||
free_resources();
|
||||
return;
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void background_manager::handle(const evt::property_notify& evt) {
|
||||
@ -140,4 +144,10 @@ void background_manager::handle(const evt::property_notify& evt) {
|
||||
}
|
||||
}
|
||||
|
||||
bool background_manager::on(const signals::ui::update_geometry&) {
|
||||
fetch_root_pixmap();
|
||||
m_sig.emit(signals::ui::update_background());
|
||||
return false;
|
||||
}
|
||||
|
||||
POLYBAR_NS_END
|
||||
|
Loading…
Reference in New Issue
Block a user