#pragma once #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" POLYBAR_NS class logger; namespace cairo { class surface; class xcb_surface; } /** * \brief Class to keep track of the desktop background used to support pseudo-transparency * * For pseudo-transparency that bar needs access to the desktop background. * We only need to store the slice of the background image which is covered by the bar window, * so this class takes a rectangle that limits what part of the background is stored. */ class background_manager : public signal_receiver, public xpp::event::sink { public: using make_type = background_manager&; static make_type make(); /** * Initializes a new background_manager that by default does not observe anything. * * To observe a slice of the background you need to call background_manager::activate. */ explicit background_manager(connection& conn, signal_emitter& sig, const logger& log); ~background_manager(); /** * Starts observing a rectangular slice of the desktop background. * * After calling this function, you can obtain the current slice of the desktop background * with background_manager::get_surface. Whenever the background slice changes (for example, * due to bar position changes or because the user changed the desktop background) the class * emits a signals::ui::update_background event. * * \param window This should be set to the bar window. * \param rect Slice of the background to observe (coordinates relative to window). * Typically set to the outer area of the bar. */ void activate(xcb_window_t window, xcb_rectangle_t rect); /** * Stops observing the desktop background and frees all resources. */ void deactivate(); /** * Retrieve the current desktop background slice. * * This function returns a slice of the desktop background that has the size of the rectangle * given to background_manager::activate. As the slice is cached by the manager, this function * is fast. */ cairo::surface* get_surface() const; void handle(const evt::property_notify& evt); bool on(const signals::ui::update_geometry&); private: // references to standard components connection& m_connection; signal_emitter& m_sig; const logger& m_log; // these are set by activate xcb_window_t m_window; xcb_rectangle_t m_rect{0, 0, 0U, 0U}; // required values for fetching the root window's background xcb_visualtype_t* m_visual{nullptr}; xcb_gcontext_t m_gcontext{XCB_NONE}; xcb_pixmap_t m_pixmap{XCB_NONE}; unique_ptr m_surface; // true if we are currently attached as a listener for desktop background changes bool m_attached{false}; void allocate_resources(); void free_resources(); void fetch_root_pixmap(); }; POLYBAR_NS_END