// somebar - dwl barbar // See LICENSE file for copyright and license details. #include #include #include "bar.hpp" #include "cairo.h" #include "config.hpp" #include "pango/pango-font.h" #include "pango/pango-fontmap.h" #include "pango/pango-layout.h" const zwlr_layer_surface_v1_listener Bar::_layerSurfaceListener = { [](void *owner, zwlr_layer_surface_v1*, uint32_t serial, uint32_t width, uint32_t height) { static_cast(owner)->layerSurfaceConfigure(serial, width, height); } }; const wl_callback_listener Bar::_frameListener = { [](void *owner, wl_callback *cb, uint32_t) { static_cast(owner)->render(); wl_callback_destroy(cb); } }; struct Font { PangoFontDescription *description; int height {0}; }; static Font getFont() { auto fontMap = pango_cairo_font_map_get_default(); if (!fontMap) die("pango_cairo_font_map_get_default"); auto fontDesc = pango_font_description_from_string(font); if (!fontDesc) die("pango_font_description_from_string"); auto tempContext = pango_font_map_create_context(fontMap); if (!tempContext) die("pango_font_map_create_context"); auto font = pango_font_map_load_font(fontMap, tempContext, fontDesc); if (!font) die("pango_font_map_load_font"); auto metrics = pango_font_get_metrics(font, pango_language_get_default()); if (!metrics) die("pango_font_get_metrics"); auto res = Font {}; res.description = fontDesc; res.height = PANGO_PIXELS(pango_font_metrics_get_height(metrics)); pango_font_metrics_unref(metrics); g_object_unref(font); g_object_unref(tempContext); return res; } static Font barfont = getFont(); BarComponent::BarComponent() { } BarComponent::BarComponent(wl_unique_ptr layout) : pangoLayout {std::move(layout)} {} int BarComponent::width() const { int w, h; pango_layout_get_size(pangoLayout.get(), &w, &h); return PANGO_PIXELS(w); } void BarComponent::setText(const std::string &text) { auto chars = new char[text.size()]; text.copy(chars, text.size()); _text.reset(chars); pango_layout_set_text(pangoLayout.get(), chars, text.size()); } Bar::Bar(Monitor *mon) { _mon = mon; _pangoContext.reset(pango_font_map_create_context(pango_cairo_font_map_get_default())); if (!_pangoContext) die("pango_font_map_create_context"); for (auto i=0u; i _statusCmp.x) { control = ClkStatusText; } else if (x > _titleCmp.x) { control = ClkWinTitle; } else if (x > _layoutCmp.x) { control = ClkLayoutSymbol; } else for (auto tag = _tags.size()-1; tag >= 0; tag--) { if (x > _tags[tag].component.x) { control = ClkTagBar; arg.ui = 1< {cairo_image_surface_create_for_data( _bufs->data(), CAIRO_FORMAT_ARGB32, _bufs->width, _bufs->height, _bufs->stride )}; auto painter = wl_unique_ptr {cairo_create(img.get())}; _painter = painter.get(); pango_cairo_update_context(_painter, _pangoContext.get()); _x = 0; renderTags(); setColorScheme(_selected ? colorActive : colorInactive); renderComponent(_layoutCmp); renderComponent(_titleCmp); renderStatus(); _painter = nullptr; wl_surface_attach(_surface.get(), _bufs->buffer(), 0, 0); wl_surface_damage(_surface.get(), 0, 0, INT_MAX, INT_MAX); wl_surface_commit(_surface.get()); _bufs->flip(); _invalid = false; } void Bar::renderTags() { for (auto &tag : _tags) { setColorScheme( tag.state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_ACTIVE ? colorActive : colorInactive, tag.state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_URGENT); renderComponent(tag.component); auto indicators = std::min(tag.numClients, _bufs->height/2); for (auto ind = 0; ind < indicators; ind++) { auto w = ind == tag.focusedClient ? 7 : 1; cairo_move_to(_painter, tag.component.x, ind*2+0.5); cairo_rel_line_to(_painter, w, 0); cairo_close_path(_painter); cairo_set_line_width(_painter, 1); cairo_stroke(_painter); } } } void Bar::renderStatus() { pango_cairo_update_layout(_painter, _statusCmp.pangoLayout.get()); beginBg(); auto start = _bufs->width - _statusCmp.width() - paddingX*2; cairo_rectangle(_painter, _x, 0, _bufs->width-_x+start, _bufs->height); cairo_fill(_painter); _x = start; renderComponent(_statusCmp); } void Bar::setColorScheme(const ColorScheme &scheme, bool invert) { _colorScheme = invert ? ColorScheme {scheme.bg, scheme.fg} : ColorScheme {scheme.fg, scheme.bg}; } static void setColor(cairo_t *painter, const Color &color) { cairo_set_source_rgba(painter, color.r/255.0, color.g/255.0, color.b/255.0, color.a/255.0); } void Bar::beginFg() { setColor(_painter, _colorScheme.fg); } void Bar::beginBg() { setColor(_painter, _colorScheme.bg); } void Bar::renderComponent(BarComponent &component) { pango_cairo_update_layout(_painter, component.pangoLayout.get()); auto size = component.width() + paddingX*2; component.x = _x; beginBg(); cairo_rectangle(_painter, _x, 0, size, _bufs->height); cairo_fill(_painter); cairo_move_to(_painter, _x+paddingX, paddingY); beginFg(); pango_cairo_show_layout(_painter, component.pangoLayout.get()); _x += size; } BarComponent Bar::createComponent(const std::string &initial) { auto layout = pango_layout_new(_pangoContext.get()); pango_layout_set_font_description(layout, barfont.description); auto res = BarComponent {wl_unique_ptr {layout}}; res.setText(initial); return res; }