2016-11-21 14:07:00 +00:00
|
|
|
#include "components/renderer.hpp"
|
2017-01-19 04:38:42 +00:00
|
|
|
#include "cairo/context.hpp"
|
|
|
|
#include "cairo/font.hpp"
|
|
|
|
#include "cairo/surface.hpp"
|
|
|
|
#include "cairo/types.hpp"
|
|
|
|
#include "cairo/utils.hpp"
|
|
|
|
#include "components/config.hpp"
|
2016-11-21 14:07:00 +00:00
|
|
|
#include "components/logger.hpp"
|
2016-11-25 12:55:15 +00:00
|
|
|
#include "errors.hpp"
|
2016-12-05 19:41:00 +00:00
|
|
|
#include "events/signal.hpp"
|
2016-12-26 09:27:30 +00:00
|
|
|
#include "events/signal_receiver.hpp"
|
2017-01-19 04:38:42 +00:00
|
|
|
#include "utils/color.hpp"
|
2017-01-11 02:07:28 +00:00
|
|
|
#include "utils/factory.hpp"
|
|
|
|
#include "utils/file.hpp"
|
2017-01-19 04:38:42 +00:00
|
|
|
#include "utils/math.hpp"
|
|
|
|
#include "utils/string.hpp"
|
2017-01-15 01:00:33 +00:00
|
|
|
#include "x11/atoms.hpp"
|
2016-11-21 14:07:00 +00:00
|
|
|
#include "x11/connection.hpp"
|
|
|
|
#include "x11/draw.hpp"
|
2016-12-26 09:27:30 +00:00
|
|
|
#include "x11/extensions/all.hpp"
|
2016-12-05 02:49:57 +00:00
|
|
|
#include "x11/generic.hpp"
|
2016-11-25 03:10:26 +00:00
|
|
|
#include "x11/winspec.hpp"
|
2016-11-21 14:07:00 +00:00
|
|
|
|
|
|
|
POLYBAR_NS
|
|
|
|
|
2016-12-09 08:02:47 +00:00
|
|
|
/**
|
|
|
|
* Create instance
|
|
|
|
*/
|
2017-01-19 04:38:42 +00:00
|
|
|
renderer::make_type renderer::make(const bar_settings& bar) {
|
2016-12-09 08:02:47 +00:00
|
|
|
// clang-format off
|
|
|
|
return factory_util::unique<renderer>(
|
|
|
|
connection::make(),
|
|
|
|
signal_emitter::make(),
|
2017-01-19 04:38:42 +00:00
|
|
|
config::make(),
|
2016-12-09 08:02:47 +00:00
|
|
|
logger::make(),
|
2017-01-19 04:38:42 +00:00
|
|
|
forward<decltype(bar)>(bar));
|
2016-12-09 08:02:47 +00:00
|
|
|
// clang-format on
|
|
|
|
}
|
|
|
|
|
2016-11-24 18:24:47 +00:00
|
|
|
/**
|
|
|
|
* Construct renderer instance
|
|
|
|
*/
|
2017-01-19 04:38:42 +00:00
|
|
|
renderer::renderer(
|
|
|
|
connection& conn, signal_emitter& sig, const config& conf, const logger& logger, const bar_settings& bar)
|
2016-11-25 03:10:26 +00:00
|
|
|
: m_connection(conn)
|
2017-01-19 04:38:42 +00:00
|
|
|
, m_sig(sig)
|
|
|
|
, m_conf(conf)
|
2016-11-25 03:10:26 +00:00
|
|
|
, m_log(logger)
|
2016-12-05 19:41:00 +00:00
|
|
|
, m_bar(forward<const bar_settings&>(bar))
|
|
|
|
, m_rect(m_bar.inner_area()) {
|
|
|
|
m_sig.attach(this);
|
2016-11-25 03:10:26 +00:00
|
|
|
m_log.trace("renderer: Get TrueColor visual");
|
2017-01-19 04:38:42 +00:00
|
|
|
{
|
|
|
|
if ((m_visual = m_connection.visual_type(m_connection.screen(), 32)) == nullptr) {
|
|
|
|
m_log.err("No 32-bit TrueColor visual found...");
|
2016-12-15 16:13:15 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
if ((m_visual = m_connection.visual_type(m_connection.screen(), 24)) == nullptr) {
|
|
|
|
m_log.err("No 24-bit TrueColor visual found...");
|
|
|
|
} else {
|
|
|
|
m_depth = 24;
|
|
|
|
}
|
2016-12-15 16:14:56 +00:00
|
|
|
}
|
|
|
|
if (m_visual == nullptr) {
|
2017-01-19 04:38:42 +00:00
|
|
|
throw application_error("No matching TrueColor");
|
2016-12-15 16:14:56 +00:00
|
|
|
}
|
2016-12-15 16:13:15 +00:00
|
|
|
}
|
2016-11-25 03:10:26 +00:00
|
|
|
|
|
|
|
m_log.trace("renderer: Allocate colormap");
|
2017-01-19 04:38:42 +00:00
|
|
|
{
|
|
|
|
m_colormap = m_connection.generate_id();
|
|
|
|
m_connection.create_colormap(XCB_COLORMAP_ALLOC_NONE, m_colormap, m_connection.screen()->root, m_visual->visual_id);
|
|
|
|
}
|
2016-11-21 14:07:00 +00:00
|
|
|
|
2016-11-25 03:10:26 +00:00
|
|
|
m_log.trace("renderer: Allocate output window");
|
2016-11-21 14:07:00 +00:00
|
|
|
{
|
2016-11-25 03:10:26 +00:00
|
|
|
// clang-format off
|
|
|
|
m_window = winspec(m_connection)
|
|
|
|
<< cw_size(m_bar.size)
|
|
|
|
<< cw_pos(m_bar.pos)
|
2016-12-15 16:14:56 +00:00
|
|
|
<< cw_depth(m_depth)
|
2016-11-25 03:10:26 +00:00
|
|
|
<< cw_visual(m_visual->visual_id)
|
|
|
|
<< cw_class(XCB_WINDOW_CLASS_INPUT_OUTPUT)
|
|
|
|
<< cw_params_back_pixel(0)
|
|
|
|
<< cw_params_border_pixel(0)
|
|
|
|
<< cw_params_backing_store(XCB_BACKING_STORE_WHEN_MAPPED)
|
|
|
|
<< cw_params_colormap(m_colormap)
|
|
|
|
<< cw_params_event_mask(XCB_EVENT_MASK_PROPERTY_CHANGE
|
|
|
|
|XCB_EVENT_MASK_EXPOSURE
|
|
|
|
|XCB_EVENT_MASK_BUTTON_PRESS)
|
2016-12-03 22:08:47 +00:00
|
|
|
<< cw_params_override_redirect(m_bar.override_redirect)
|
2016-11-25 03:10:26 +00:00
|
|
|
<< cw_flush(true);
|
|
|
|
// clang-format on
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
|
2016-11-25 03:10:26 +00:00
|
|
|
m_log.trace("renderer: Allocate window pixmap");
|
2016-11-21 14:07:00 +00:00
|
|
|
{
|
2017-01-19 04:38:42 +00:00
|
|
|
m_pixmap = m_connection.generate_id();
|
|
|
|
m_connection.create_pixmap(m_depth, m_pixmap, m_window, m_bar.size.w, m_bar.size.h);
|
|
|
|
}
|
2016-11-24 18:24:47 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
m_log.trace("renderer: Allocate graphic context");
|
|
|
|
{
|
2017-01-19 10:11:28 +00:00
|
|
|
unsigned int mask{0};
|
|
|
|
unsigned int value_list[32]{0};
|
2017-01-19 04:38:42 +00:00
|
|
|
xcb_params_gc_t params{};
|
|
|
|
XCB_AUX_ADD_PARAM(&mask, ¶ms, foreground, m_bar.foreground);
|
|
|
|
XCB_AUX_ADD_PARAM(&mask, ¶ms, graphics_exposures, 0);
|
|
|
|
connection::pack_values(mask, ¶ms, value_list);
|
|
|
|
m_gcontext = m_connection.generate_id();
|
|
|
|
m_connection.create_gc(m_gcontext, m_pixmap, mask, value_list);
|
|
|
|
}
|
2016-11-25 03:10:26 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
m_log.trace("renderer: Allocate cairo components");
|
|
|
|
{
|
|
|
|
m_surface = make_unique<cairo::xcb_surface>(m_connection, m_pixmap, m_visual, m_bar.size.w, m_bar.size.h);
|
|
|
|
m_context = make_unique<cairo::context>(*m_surface.get(), m_log);
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 00:22:47 +00:00
|
|
|
m_log.trace("renderer: Load fonts");
|
2016-11-21 14:07:00 +00:00
|
|
|
{
|
2017-01-19 04:38:42 +00:00
|
|
|
auto fonts = m_conf.get_list<string>(m_conf.section(), "font", {});
|
2016-11-25 12:55:15 +00:00
|
|
|
if (fonts.empty()) {
|
2016-11-21 14:07:00 +00:00
|
|
|
m_log.warn("No fonts specified, using fallback font \"fixed\"");
|
2017-01-19 04:38:42 +00:00
|
|
|
fonts.emplace_back("fixed");
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-21 14:07:00 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
auto fonts_loaded = false;
|
2016-11-25 12:55:15 +00:00
|
|
|
for (const auto& f : fonts) {
|
2016-11-24 18:24:47 +00:00
|
|
|
vector<string> fd{string_util::split(f, ';')};
|
2017-01-19 04:38:42 +00:00
|
|
|
auto font = cairo::make_font(*m_context, string(fd[0]), fd.size() > 1 ? std::atoi(fd[1].c_str()) : 0);
|
|
|
|
m_log.info("Loaded font \"%s\" (name=%s, file=%s)", fd[0], font->name(), font->file());
|
|
|
|
*m_context << move(font);
|
|
|
|
fonts_loaded = true;
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
if (!fonts_loaded) {
|
2016-11-21 14:07:00 +00:00
|
|
|
throw application_error("Unable to load fonts");
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
2017-01-19 04:38:42 +00:00
|
|
|
|
|
|
|
m_compositing_background =
|
|
|
|
cairo::utils::str2operator(m_conf.get("settings", "compositing-background", ""s), CAIRO_OPERATOR_SOURCE);
|
|
|
|
m_compositing_foreground =
|
|
|
|
cairo::utils::str2operator(m_conf.get("settings", "compositing-foreground", ""s), CAIRO_OPERATOR_OVER);
|
|
|
|
m_compositing_overline =
|
|
|
|
cairo::utils::str2operator(m_conf.get("settings", "compositing-overline", ""s), CAIRO_OPERATOR_OVER);
|
|
|
|
m_compositing_underline =
|
|
|
|
cairo::utils::str2operator(m_conf.get("settings", "compositing-underline", ""s), CAIRO_OPERATOR_OVER);
|
|
|
|
m_compositing_borders =
|
|
|
|
cairo::utils::str2operator(m_conf.get("settings", "compositing-border", ""s), CAIRO_OPERATOR_SOURCE);
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
|
2016-11-25 10:41:41 +00:00
|
|
|
/**
|
|
|
|
* Deconstruct instance
|
|
|
|
*/
|
|
|
|
renderer::~renderer() {
|
2016-12-05 19:41:00 +00:00
|
|
|
m_sig.detach(this);
|
2016-11-25 10:41:41 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 18:24:47 +00:00
|
|
|
/**
|
|
|
|
* Get output window
|
|
|
|
*/
|
2016-11-21 14:07:00 +00:00
|
|
|
xcb_window_t renderer::window() const {
|
|
|
|
return m_window;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
/**
|
|
|
|
* Get completed action blocks
|
|
|
|
*/
|
|
|
|
const vector<action_block> renderer::actions() const {
|
|
|
|
return m_actions;
|
|
|
|
}
|
|
|
|
|
2016-11-24 18:24:47 +00:00
|
|
|
/**
|
|
|
|
* Begin render routine
|
|
|
|
*/
|
2016-11-21 14:07:00 +00:00
|
|
|
void renderer::begin() {
|
2016-11-24 18:24:47 +00:00
|
|
|
m_log.trace_x("renderer: begin");
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
// Reset state
|
2016-11-21 14:07:00 +00:00
|
|
|
m_actions.clear();
|
2017-01-19 04:38:42 +00:00
|
|
|
m_attributes.reset();
|
|
|
|
m_alignment = alignment::NONE;
|
|
|
|
m_rect = m_bar.inner_area();
|
|
|
|
m_x = 0.0;
|
|
|
|
|
|
|
|
// Reset colors
|
|
|
|
m_color_background = 0;
|
|
|
|
m_color_foreground = m_bar.foreground;
|
|
|
|
m_color_underline = m_bar.underline.color;
|
|
|
|
m_color_overline = m_bar.overline.color;
|
|
|
|
|
|
|
|
// Clear canvas
|
|
|
|
m_context->save();
|
|
|
|
*m_context << CAIRO_OPERATOR_SOURCE;
|
|
|
|
*m_context << rgba{0.0, 0.0, 0.0, 0.0};
|
|
|
|
m_context->paint();
|
|
|
|
m_context->restore();
|
|
|
|
|
|
|
|
m_context->save();
|
|
|
|
|
|
|
|
fill_background();
|
|
|
|
fill_borders();
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
m_context->clip(cairo::rect{
|
|
|
|
static_cast<double>(m_rect.x),
|
|
|
|
static_cast<double>(m_rect.y),
|
|
|
|
static_cast<double>(m_rect.width),
|
|
|
|
static_cast<double>(m_rect.height)});
|
|
|
|
// clang-format on
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 18:24:47 +00:00
|
|
|
/**
|
|
|
|
* End render routine
|
|
|
|
*/
|
2016-11-21 14:07:00 +00:00
|
|
|
void renderer::end() {
|
2016-11-24 18:24:47 +00:00
|
|
|
m_log.trace_x("renderer: end");
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
highlight_clickable_areas();
|
2016-11-22 00:22:47 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
m_context->restore();
|
|
|
|
m_surface->flush();
|
2016-11-22 00:22:47 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
flush();
|
2016-11-22 00:22:47 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 18:24:47 +00:00
|
|
|
/**
|
2016-12-05 19:41:00 +00:00
|
|
|
* Flush pixmap contents onto the target window
|
2016-11-24 18:24:47 +00:00
|
|
|
*/
|
2017-01-19 04:38:42 +00:00
|
|
|
void renderer::flush() {
|
|
|
|
m_log.trace_x("renderer: flush");
|
2016-11-25 03:10:26 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
#ifdef DEBUG_SHADED
|
2016-12-21 03:50:43 +00:00
|
|
|
if (m_bar.shaded && m_bar.origin == edge::TOP) {
|
2017-01-19 04:38:42 +00:00
|
|
|
m_log.trace_x(
|
|
|
|
"renderer: copy pixmap (shaded=1, geom=%dx%d+%d+%d)", m_rect.width, m_rect.height, m_rect.x, m_rect.y);
|
2016-12-21 03:50:43 +00:00
|
|
|
auto geom = m_connection.get_geometry(m_window);
|
|
|
|
auto x1 = 0;
|
2017-01-19 04:38:42 +00:00
|
|
|
auto y1 = m_rect.height - m_bar.shade_size.h - m_rect.y - geom->height;
|
|
|
|
auto x2 = m_rect.x;
|
|
|
|
auto y2 = m_rect.y;
|
|
|
|
auto w = m_rect.width;
|
|
|
|
auto h = m_rect.height - m_bar.shade_size.h + geom->height;
|
|
|
|
m_connection.copy_area(m_pixmap, m_window, m_gcontext, x1, y1, x2, y2, w, h);
|
2016-12-21 03:50:43 +00:00
|
|
|
m_connection.flush();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
m_log.trace_x("renderer: copy pixmap (geom=%dx%d+%d+%d)", m_rect.width, m_rect.height, m_rect.x, m_rect.y);
|
|
|
|
m_connection.copy_area(m_pixmap, m_window, m_gcontext, 0, 0, 0, 0, m_bar.size.w, m_bar.size.h);
|
2016-11-25 03:10:26 +00:00
|
|
|
m_connection.flush();
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 18:24:47 +00:00
|
|
|
/**
|
|
|
|
* Reserve space at given edge
|
|
|
|
*/
|
2017-01-19 14:05:26 +00:00
|
|
|
void renderer::reserve_space(edge side, unsigned int w) {
|
|
|
|
m_log.trace_x("renderer: reserve_space(%i, %i)", static_cast<int>(side), w);
|
2016-11-25 03:10:26 +00:00
|
|
|
|
2016-12-05 02:49:57 +00:00
|
|
|
m_cleararea.side = side;
|
|
|
|
m_cleararea.size = w;
|
|
|
|
|
2016-11-25 03:10:26 +00:00
|
|
|
switch (side) {
|
|
|
|
case edge::NONE:
|
|
|
|
break;
|
|
|
|
case edge::TOP:
|
|
|
|
m_rect.y += w;
|
|
|
|
m_rect.height -= w;
|
|
|
|
break;
|
|
|
|
case edge::BOTTOM:
|
|
|
|
m_rect.height -= w;
|
|
|
|
break;
|
|
|
|
case edge::LEFT:
|
|
|
|
m_rect.x += w;
|
|
|
|
m_rect.width -= w;
|
|
|
|
break;
|
|
|
|
case edge::RIGHT:
|
|
|
|
m_rect.width -= w;
|
|
|
|
break;
|
|
|
|
case edge::ALL:
|
|
|
|
m_rect.x += w;
|
|
|
|
m_rect.y += w;
|
|
|
|
m_rect.width -= w * 2;
|
|
|
|
m_rect.height -= w * 2;
|
|
|
|
break;
|
|
|
|
}
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 18:24:47 +00:00
|
|
|
/**
|
2016-12-05 19:41:00 +00:00
|
|
|
* Fill background color
|
2016-11-24 18:24:47 +00:00
|
|
|
*/
|
2016-11-21 14:07:00 +00:00
|
|
|
void renderer::fill_background() {
|
2017-01-19 04:38:42 +00:00
|
|
|
m_context->save();
|
|
|
|
*m_context << m_compositing_background;
|
|
|
|
|
2017-01-19 14:05:26 +00:00
|
|
|
if (m_bar.radius != 0.0) {
|
|
|
|
// clang-format off
|
|
|
|
*m_context << cairo::rounded_corners{
|
|
|
|
static_cast<double>(m_rect.x),
|
|
|
|
static_cast<double>(m_rect.y),
|
|
|
|
static_cast<double>(m_rect.width),
|
|
|
|
static_cast<double>(m_rect.height), m_bar.radius};
|
|
|
|
// clang-format on
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
if (!m_bar.background_steps.empty()) {
|
|
|
|
m_log.trace_x("renderer: gradient background (steps=%lu)", m_bar.background_steps.size());
|
|
|
|
*m_context << cairo::linear_gradient{0.0, 0.0 + m_rect.y, 0.0, 0.0 + m_rect.height, m_bar.background_steps};
|
|
|
|
} else {
|
|
|
|
m_log.trace_x("renderer: solid background #%08x", m_bar.background);
|
|
|
|
*m_context << m_bar.background;
|
|
|
|
}
|
|
|
|
|
2017-01-19 14:05:26 +00:00
|
|
|
if (m_bar.radius != 0.0) {
|
|
|
|
m_context->fill();
|
|
|
|
} else {
|
|
|
|
m_context->paint();
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
m_context->restore();
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 18:24:47 +00:00
|
|
|
/**
|
2016-12-05 19:41:00 +00:00
|
|
|
* Fill overline color
|
2016-11-24 18:24:47 +00:00
|
|
|
*/
|
2017-01-19 04:38:42 +00:00
|
|
|
void renderer::fill_overline(double x, double w) {
|
2017-01-19 14:05:26 +00:00
|
|
|
if (m_bar.overline.size && m_attributes.test(static_cast<int>(attribute::OVERLINE))) {
|
|
|
|
m_log.trace_x("renderer: overline(x=%f, w=%f)", x, w);
|
2017-01-19 04:38:42 +00:00
|
|
|
m_context->save();
|
|
|
|
*m_context << m_compositing_overline;
|
|
|
|
*m_context << m_color_overline;
|
|
|
|
*m_context << cairo::rect{x, static_cast<double>(m_rect.y), w, static_cast<double>(m_bar.overline.size)};
|
|
|
|
m_context->fill();
|
|
|
|
m_context->restore();
|
2016-11-24 18:24:47 +00:00
|
|
|
}
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 18:24:47 +00:00
|
|
|
/**
|
2016-12-05 19:41:00 +00:00
|
|
|
* Fill underline color
|
2016-11-24 18:24:47 +00:00
|
|
|
*/
|
2017-01-19 04:38:42 +00:00
|
|
|
void renderer::fill_underline(double x, double w) {
|
2017-01-19 14:05:26 +00:00
|
|
|
if (m_bar.underline.size && m_attributes.test(static_cast<int>(attribute::UNDERLINE))) {
|
|
|
|
m_log.trace_x("renderer: underline(x=%f, w=%f)", x, w);
|
2017-01-19 04:38:42 +00:00
|
|
|
m_context->save();
|
|
|
|
*m_context << m_compositing_underline;
|
|
|
|
*m_context << m_color_underline;
|
|
|
|
*m_context << cairo::rect{x, static_cast<double>(m_rect.y + m_rect.height - m_bar.underline.size), w,
|
|
|
|
static_cast<double>(m_bar.underline.size)};
|
|
|
|
m_context->fill();
|
|
|
|
m_context->restore();
|
2016-11-24 18:24:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-01-19 04:38:42 +00:00
|
|
|
* Fill border colors
|
2016-11-24 18:24:47 +00:00
|
|
|
*/
|
2017-01-19 04:38:42 +00:00
|
|
|
void renderer::fill_borders() {
|
|
|
|
m_context->save();
|
|
|
|
*m_context << m_compositing_borders;
|
2016-11-21 14:07:00 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
cairo::rect top{0.0, 0.0, 0.0, 0.0};
|
|
|
|
top.x += m_bar.borders.at(edge::LEFT).size;
|
|
|
|
top.w += m_bar.size.w - m_bar.borders.at(edge::LEFT).size - m_bar.borders.at(edge::TOP).size;
|
|
|
|
top.h += m_bar.borders.at(edge::TOP).size;
|
|
|
|
m_log.trace_x("renderer: border T(%.0f, #%08x)", top.h, m_bar.borders.at(edge::TOP).color);
|
|
|
|
(*m_context << top << m_bar.borders.at(edge::TOP).color).fill();
|
2016-11-30 21:15:01 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
cairo::rect bottom{0.0, 0.0, 0.0, 0.0};
|
|
|
|
bottom.x += m_bar.borders.at(edge::LEFT).size;
|
|
|
|
bottom.y += m_bar.size.h - m_bar.borders.at(edge::BOTTOM).size;
|
|
|
|
bottom.w += m_bar.size.w - m_bar.borders.at(edge::LEFT).size - m_bar.borders.at(edge::RIGHT).size;
|
|
|
|
bottom.h += m_bar.borders.at(edge::BOTTOM).size;
|
|
|
|
m_log.trace_x("renderer: border B(%.0f, #%08x)", bottom.h, m_bar.borders.at(edge::BOTTOM).color);
|
|
|
|
(*m_context << bottom << m_bar.borders.at(edge::BOTTOM).color).fill();
|
|
|
|
|
|
|
|
cairo::rect left{0.0, 0.0, 0.0, 0.0};
|
|
|
|
left.w += m_bar.borders.at(edge::LEFT).size;
|
|
|
|
left.h += m_bar.size.h;
|
|
|
|
m_log.trace_x("renderer: border L(%.0f, #%08x)", left.w, m_bar.borders.at(edge::LEFT).color);
|
|
|
|
(*m_context << left << m_bar.borders.at(edge::LEFT).color).fill();
|
|
|
|
|
|
|
|
cairo::rect right{0.0, 0.0, 0.0, 0.0};
|
|
|
|
right.x += m_bar.size.w - m_bar.borders.at(edge::RIGHT).size;
|
|
|
|
right.w += m_bar.borders.at(edge::RIGHT).size;
|
|
|
|
right.h += m_bar.size.h;
|
|
|
|
m_log.trace_x("renderer: border R(%.0f, #%08x)", right.w, m_bar.borders.at(edge::RIGHT).color);
|
|
|
|
(*m_context << right << m_bar.borders.at(edge::RIGHT).color).fill();
|
2016-12-15 16:14:56 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
m_context->restore();
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 18:24:47 +00:00
|
|
|
/**
|
2017-01-19 04:38:42 +00:00
|
|
|
* Draw text contents
|
2016-11-24 18:24:47 +00:00
|
|
|
*/
|
2017-01-19 04:38:42 +00:00
|
|
|
void renderer::draw_text(const string& contents) {
|
|
|
|
m_log.trace_x("renderer: text(%s)", contents.c_str());
|
2016-11-21 14:07:00 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
cairo::abspos origin{static_cast<double>(m_rect.x), static_cast<double>(m_rect.y)};
|
2017-01-19 14:05:26 +00:00
|
|
|
origin.y += m_rect.height / 2.0;
|
2016-11-25 03:10:26 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
if (m_alignment == alignment::CENTER) {
|
2017-01-19 14:05:26 +00:00
|
|
|
origin.x += m_rect.width / 2.0;
|
|
|
|
// adjust_clickable_areas(extents.width / 2.0);
|
2017-01-19 04:38:42 +00:00
|
|
|
} else if (m_alignment == alignment::RIGHT) {
|
2017-01-19 14:05:26 +00:00
|
|
|
origin.x += m_rect.width;
|
|
|
|
// adjust_clickable_areas(extents.width);
|
2017-01-19 04:38:42 +00:00
|
|
|
} else {
|
|
|
|
origin.x += m_x;
|
2016-11-24 18:24:47 +00:00
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
// if (m_color_background && m_color_background != m_bar.background) {
|
|
|
|
// m_context->save();
|
|
|
|
// *m_context << m_color_background;
|
|
|
|
// *m_context << m_compositing_background;
|
|
|
|
// *m_context << cairo::rect{origin.x, origin.y, extents.width, static_cast<double>(m_rect.height)};
|
|
|
|
// m_context->fill();
|
|
|
|
// m_context->restore();
|
|
|
|
// }
|
2016-11-24 18:24:47 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
m_context->save();
|
|
|
|
*m_context << origin;
|
|
|
|
*m_context << m_compositing_foreground;
|
|
|
|
*m_context << m_color_foreground;
|
2017-01-19 14:05:26 +00:00
|
|
|
*m_context << cairo::textblock{m_alignment, contents, m_fontindex};
|
2017-01-19 04:38:42 +00:00
|
|
|
m_context->position(&m_x, &m_y);
|
|
|
|
m_context->restore();
|
2016-11-24 18:24:47 +00:00
|
|
|
|
2017-01-19 14:05:26 +00:00
|
|
|
fill_underline(origin.x, m_x - origin.x);
|
|
|
|
fill_overline(origin.x, m_x - origin.x);
|
2016-11-24 18:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-01-19 04:38:42 +00:00
|
|
|
* Move clickable areas position by given delta
|
2016-11-24 18:24:47 +00:00
|
|
|
*/
|
2017-01-19 04:38:42 +00:00
|
|
|
void renderer::adjust_clickable_areas(double delta) {
|
|
|
|
for (auto&& action : m_actions) {
|
|
|
|
if (!action.active && action.align == m_alignment) {
|
|
|
|
action.start_x -= delta;
|
|
|
|
action.end_x -= delta;
|
|
|
|
}
|
|
|
|
}
|
2016-11-24 18:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-12-05 19:41:00 +00:00
|
|
|
* Draw boxes at the location of each created action block
|
2016-11-24 18:24:47 +00:00
|
|
|
*/
|
2017-01-19 04:38:42 +00:00
|
|
|
void renderer::highlight_clickable_areas() {
|
|
|
|
#ifdef DEBUG_HINTS
|
|
|
|
map<alignment, int> hint_num{};
|
2016-11-21 14:07:00 +00:00
|
|
|
for (auto&& action : m_actions) {
|
2017-01-19 04:38:42 +00:00
|
|
|
if (!action.active) {
|
2017-01-19 14:05:26 +00:00
|
|
|
int n = hint_num.find(action.align)->second++;
|
2017-01-19 04:38:42 +00:00
|
|
|
double x = action.start_x + n * DEBUG_HINTS_OFFSET_X;
|
|
|
|
double y = m_bar.pos.y + m_rect.y + n * DEBUG_HINTS_OFFSET_Y;
|
|
|
|
double w = action.width();
|
|
|
|
double h = m_rect.height;
|
|
|
|
|
|
|
|
m_context->save();
|
|
|
|
*m_context << CAIRO_OPERATOR_OVERLAY << (n % 2 ? 0x55FF0000 : 0x5500FF00);
|
|
|
|
*m_context << cairo::rect{x, y, w, h};
|
|
|
|
m_context->fill();
|
|
|
|
m_context->restore();
|
2016-11-21 14:07:00 +00:00
|
|
|
}
|
|
|
|
}
|
2016-11-25 03:10:26 +00:00
|
|
|
#endif
|
2017-01-19 04:38:42 +00:00
|
|
|
}
|
2016-11-21 14:07:00 +00:00
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::change_background& evt) {
|
2017-01-19 10:11:28 +00:00
|
|
|
const unsigned int color{evt.cast()};
|
2017-01-19 04:38:42 +00:00
|
|
|
if (color != m_color_background) {
|
|
|
|
m_color_background = color;
|
2016-12-05 19:41:00 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::change_foreground& evt) {
|
2017-01-19 10:11:28 +00:00
|
|
|
const unsigned int color{evt.cast()};
|
2017-01-19 04:38:42 +00:00
|
|
|
if (color != m_color_foreground) {
|
|
|
|
m_color_foreground = color;
|
2016-12-05 19:41:00 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::change_underline& evt) {
|
2017-01-19 10:11:28 +00:00
|
|
|
const unsigned int color{evt.cast()};
|
2017-01-19 04:38:42 +00:00
|
|
|
if (color != m_color_underline) {
|
|
|
|
m_color_underline = color;
|
2016-12-05 19:41:00 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::change_overline& evt) {
|
2017-01-19 10:11:28 +00:00
|
|
|
const unsigned int color{evt.cast()};
|
2017-01-19 04:38:42 +00:00
|
|
|
if (color != m_color_overline) {
|
|
|
|
m_color_overline = color;
|
2016-12-05 19:41:00 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::change_font& evt) {
|
|
|
|
m_fontindex = evt.cast();
|
2016-12-05 19:41:00 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::change_alignment& evt) {
|
2017-01-01 19:29:38 +00:00
|
|
|
auto align = static_cast<const alignment&>(evt.cast());
|
2017-01-19 04:38:42 +00:00
|
|
|
if (align != m_alignment) {
|
2016-12-05 19:41:00 +00:00
|
|
|
m_alignment = align;
|
2017-01-19 04:38:42 +00:00
|
|
|
m_x = 0.0;
|
2016-12-05 19:41:00 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::offset_pixel& evt) {
|
2017-01-19 14:05:26 +00:00
|
|
|
(void)evt;
|
|
|
|
// m_x += evt.cast();
|
2016-12-05 19:41:00 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::attribute_set& evt) {
|
2017-01-19 14:05:26 +00:00
|
|
|
m_attributes.set(static_cast<int>(evt.cast()), true);
|
2016-12-05 19:41:00 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::attribute_unset& evt) {
|
2017-01-19 14:05:26 +00:00
|
|
|
m_attributes.set(static_cast<int>(evt.cast()), false);
|
2016-12-05 19:41:00 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::attribute_toggle& evt) {
|
2017-01-19 14:05:26 +00:00
|
|
|
m_attributes.flip(static_cast<int>(evt.cast()));
|
2016-12-05 19:41:00 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::action_begin& evt) {
|
2017-01-19 14:05:26 +00:00
|
|
|
(void)evt;
|
2017-01-19 04:38:42 +00:00
|
|
|
// auto a = evt.cast();
|
|
|
|
// action_block action{};
|
|
|
|
// action.button = a.button == mousebtn::NONE ? mousebtn::LEFT : a.button;
|
|
|
|
// action.align = m_alignment;
|
|
|
|
// action.start_x = m_x;
|
|
|
|
// action.command = string_util::replace_all(a.command, ":", "\\:");
|
|
|
|
// action.active = true;
|
|
|
|
// m_actions.emplace_back(action);
|
2016-12-05 19:41:00 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::action_end& evt) {
|
2017-01-19 14:05:26 +00:00
|
|
|
(void)evt;
|
2017-01-19 04:38:42 +00:00
|
|
|
// auto btn = evt.cast();
|
2017-01-19 14:05:26 +00:00
|
|
|
// int clickable_width = 0;
|
2017-01-19 04:38:42 +00:00
|
|
|
// for (auto action = m_actions.rbegin(); action != m_actions.rend(); action++) {
|
|
|
|
// if (action->active && action->align == m_alignment && action->button == btn) {
|
|
|
|
// switch (action->align) {
|
|
|
|
// case alignment::NONE:
|
|
|
|
// break;
|
|
|
|
// case alignment::LEFT:
|
|
|
|
// action->end_x = m_x;
|
|
|
|
// break;
|
|
|
|
// case alignment::CENTER:
|
|
|
|
// clickable_width = m_x - action->start_x;
|
|
|
|
// action->start_x = m_rect.width / 2 - clickable_width / 2 + action->start_x / 2;
|
|
|
|
// action->end_x = action->start_x + clickable_width;
|
|
|
|
// break;
|
|
|
|
// case alignment::RIGHT:
|
|
|
|
// action->start_x = m_rect.width - m_x + action->start_x;
|
|
|
|
// action->end_x = m_rect.width;
|
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
// action->start_x += m_rect.x;
|
|
|
|
// action->end_x += m_rect.x;
|
|
|
|
// action->active = false;
|
|
|
|
// }
|
|
|
|
// }
|
2016-12-05 19:41:00 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-19 04:38:42 +00:00
|
|
|
bool renderer::on(const signals::parser::text& evt) {
|
|
|
|
auto text = evt.cast();
|
|
|
|
draw_text(text);
|
2016-12-05 19:41:00 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-11-21 14:07:00 +00:00
|
|
|
POLYBAR_NS_END
|