2021-10-20 20:45:23 +02:00
|
|
|
// somebar - dwl bar
|
|
|
|
// See LICENSE file for copyright and license details.
|
|
|
|
|
2021-10-22 15:34:19 +02:00
|
|
|
#include <QColor>
|
2021-10-20 21:09:19 +02:00
|
|
|
#include <QImage>
|
2021-10-22 15:34:19 +02:00
|
|
|
#include <QPainter>
|
2021-10-20 20:45:23 +02:00
|
|
|
#include "bar.hpp"
|
|
|
|
#include "config.hpp"
|
|
|
|
|
|
|
|
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<Bar*>(owner)->layerSurfaceConfigure(serial, width, height);
|
|
|
|
}
|
|
|
|
};
|
2021-10-22 16:52:04 +02:00
|
|
|
const wl_callback_listener Bar::_frameListener = {
|
|
|
|
[](void *owner, wl_callback *cb, uint32_t)
|
|
|
|
{
|
|
|
|
static_cast<Bar*>(owner)->render();
|
|
|
|
wl_callback_destroy(cb);
|
|
|
|
}
|
|
|
|
};
|
2021-10-20 20:45:23 +02:00
|
|
|
|
2021-10-22 15:49:09 +02:00
|
|
|
static QFont getFont()
|
|
|
|
{
|
|
|
|
QFont font {fontFamily, fontSizePt};
|
|
|
|
font.setBold(fontBold);
|
|
|
|
return font;
|
|
|
|
}
|
2021-10-25 19:02:35 +02:00
|
|
|
static QFont font = getFont();
|
|
|
|
static QFontMetrics fontMetrics = QFontMetrics {font};
|
2021-10-22 15:49:09 +02:00
|
|
|
|
2021-10-25 20:52:21 +02:00
|
|
|
const wl_surface* Bar::surface() const { return _surface.get(); }
|
|
|
|
|
2021-10-26 11:40:46 +02:00
|
|
|
Bar::Bar(Monitor *mon)
|
2021-10-25 20:52:21 +02:00
|
|
|
{
|
2021-10-26 11:40:46 +02:00
|
|
|
_mon = mon;
|
|
|
|
for (auto i=0u; i<tagNames.size(); i++) {
|
|
|
|
_tags.push_back({ ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_NONE, 0, 0, 0 });
|
2021-10-25 20:52:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bar::create(wl_output *output)
|
2021-10-20 20:45:23 +02:00
|
|
|
{
|
2021-10-25 19:02:35 +02:00
|
|
|
_surface.reset(wl_compositor_create_surface(compositor));
|
|
|
|
_layerSurface.reset(zwlr_layer_shell_v1_get_layer_surface(wlrLayerShell,
|
|
|
|
_surface.get(), nullptr, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "net.tapesoftware.Somebar"));
|
|
|
|
zwlr_layer_surface_v1_add_listener(_layerSurface.get(), &_layerSurfaceListener, this);
|
2021-10-21 08:28:22 +02:00
|
|
|
auto anchor = topbar ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
2021-10-25 19:02:35 +02:00
|
|
|
zwlr_layer_surface_v1_set_anchor(_layerSurface.get(),
|
2021-10-21 08:28:22 +02:00
|
|
|
anchor | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
|
2021-10-22 15:49:09 +02:00
|
|
|
|
2021-10-25 19:02:35 +02:00
|
|
|
auto barSize = fontMetrics.ascent() + fontMetrics.descent() + paddingY * 2;
|
|
|
|
_textY = fontMetrics.ascent() + paddingY;
|
2021-10-22 15:49:09 +02:00
|
|
|
|
2021-10-25 19:02:35 +02:00
|
|
|
zwlr_layer_surface_v1_set_size(_layerSurface.get(), 0, barSize);
|
|
|
|
zwlr_layer_surface_v1_set_exclusive_zone(_layerSurface.get(), barSize);
|
|
|
|
wl_surface_commit(_surface.get());
|
2021-10-20 20:45:23 +02:00
|
|
|
}
|
|
|
|
|
2021-10-26 15:32:25 +02:00
|
|
|
void Bar::click(int x, int, int btn)
|
2021-10-22 17:26:05 +02:00
|
|
|
{
|
2021-10-26 11:40:46 +02:00
|
|
|
Arg arg = {0};
|
|
|
|
Arg *argp = nullptr;
|
2021-10-26 15:32:25 +02:00
|
|
|
int control = ClkNone;
|
2021-10-26 11:40:46 +02:00
|
|
|
if (x > _statusX) {
|
2021-10-26 15:32:25 +02:00
|
|
|
control = ClkStatusText;
|
2021-10-26 11:40:46 +02:00
|
|
|
} else if (x > _titleX) {
|
2021-10-26 15:32:25 +02:00
|
|
|
control = ClkWinTitle;
|
2021-10-26 11:40:46 +02:00
|
|
|
} else if (x > _layoutX) {
|
2021-10-26 15:32:25 +02:00
|
|
|
control = ClkLayoutSymbol;
|
2021-10-26 11:40:46 +02:00
|
|
|
} else for (auto tag = _tags.size()-1; tag >= 0; tag--) {
|
|
|
|
if (x > _tags[tag].x) {
|
2021-10-26 15:32:25 +02:00
|
|
|
control = ClkTagBar;
|
2021-10-26 11:40:46 +02:00
|
|
|
arg.ui = 1<<tag;
|
|
|
|
argp = &arg;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (auto i = 0u; i < sizeof(buttons)/sizeof(buttons[0]); i++) {
|
|
|
|
const auto& button = buttons[i];
|
2021-10-26 15:32:25 +02:00
|
|
|
if (button.control == control && button.btn == btn) {
|
2021-10-26 11:40:46 +02:00
|
|
|
button.func(*_mon, *(argp ? argp : &button.arg));
|
2021-10-22 17:26:05 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-22 16:52:04 +02:00
|
|
|
void Bar::invalidate()
|
|
|
|
{
|
|
|
|
if (_invalid) return;
|
|
|
|
_invalid = true;
|
2021-10-25 19:02:35 +02:00
|
|
|
auto frame = wl_surface_frame(_surface.get());
|
2021-10-22 16:52:04 +02:00
|
|
|
wl_callback_add_listener(frame, &_frameListener, this);
|
2021-10-25 19:02:35 +02:00
|
|
|
wl_surface_commit(_surface.get());
|
2021-10-22 16:52:04 +02:00
|
|
|
}
|
|
|
|
|
2021-10-25 20:52:21 +02:00
|
|
|
void Bar::setTag(int tag, znet_tapesoftware_dwl_wm_monitor_v1_tag_state state, int numClients, int focusedClient)
|
|
|
|
{
|
|
|
|
auto& t = _tags[tag];
|
|
|
|
t.state = state;
|
|
|
|
t.numClients = numClients;
|
|
|
|
t.focusedClient = focusedClient;
|
|
|
|
}
|
|
|
|
|
2021-10-25 21:54:14 +02:00
|
|
|
void Bar::setSelected(bool selected) { _selected = selected; }
|
|
|
|
void Bar::setLayout(int layout) { _layout = layout; }
|
|
|
|
void Bar::setTitle(const char *title) { _title = title; }
|
|
|
|
void Bar::setStatus(const QString &status) { _status = status; }
|
2021-10-22 16:52:04 +02:00
|
|
|
|
2021-10-20 20:45:23 +02:00
|
|
|
void Bar::layerSurfaceConfigure(uint32_t serial, uint32_t width, uint32_t height)
|
|
|
|
{
|
2021-10-25 19:02:35 +02:00
|
|
|
zwlr_layer_surface_v1_ack_configure(_layerSurface.get(), serial);
|
2021-10-20 20:45:23 +02:00
|
|
|
_bufs.emplace(width, height, WL_SHM_FORMAT_XRGB8888);
|
2021-10-20 21:09:19 +02:00
|
|
|
render();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bar::render()
|
|
|
|
{
|
|
|
|
auto img = QImage {
|
|
|
|
_bufs->data(),
|
|
|
|
_bufs->width,
|
|
|
|
_bufs->height,
|
|
|
|
_bufs->stride,
|
2021-10-22 15:34:19 +02:00
|
|
|
QImage::Format_ARGB32
|
2021-10-20 21:09:19 +02:00
|
|
|
};
|
2021-10-22 15:34:19 +02:00
|
|
|
auto painter = QPainter {&img};
|
2021-10-22 15:42:42 +02:00
|
|
|
_painter = &painter;
|
2021-10-22 15:55:29 +02:00
|
|
|
_x = 0;
|
2021-10-25 19:02:35 +02:00
|
|
|
painter.setFont(font);
|
2021-10-22 15:34:19 +02:00
|
|
|
|
2021-10-22 15:55:29 +02:00
|
|
|
renderTags();
|
2021-10-25 21:54:14 +02:00
|
|
|
setColorScheme(_selected ? colorActive : colorInactive);
|
2021-10-26 11:40:46 +02:00
|
|
|
_layoutX = _x;
|
2021-10-25 21:54:14 +02:00
|
|
|
renderText(layoutNames[_layout]);
|
2021-10-26 11:40:46 +02:00
|
|
|
_titleX = _x;
|
2021-10-25 21:54:14 +02:00
|
|
|
renderText(_title);
|
2021-10-22 15:55:29 +02:00
|
|
|
renderStatus();
|
2021-10-22 15:34:19 +02:00
|
|
|
|
2021-10-22 15:42:42 +02:00
|
|
|
_painter = nullptr;
|
2021-10-25 19:02:35 +02:00
|
|
|
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());
|
2021-10-20 21:09:19 +02:00
|
|
|
_bufs->flip();
|
2021-10-22 16:52:04 +02:00
|
|
|
_invalid = false;
|
2021-10-20 20:45:23 +02:00
|
|
|
}
|
2021-10-22 15:34:19 +02:00
|
|
|
|
2021-10-26 16:17:07 +02:00
|
|
|
void Bar::setColorScheme(const ColorScheme &scheme, bool invert)
|
2021-10-22 15:42:42 +02:00
|
|
|
{
|
2021-10-26 16:17:07 +02:00
|
|
|
_painter->setBrush(QBrush {invert ? scheme.fg : scheme.bg});
|
|
|
|
_painter->setPen(QPen {QBrush {invert ? scheme.bg : scheme.fg}, 1});
|
2021-10-22 15:42:42 +02:00
|
|
|
}
|
|
|
|
|
2021-10-22 15:55:29 +02:00
|
|
|
void Bar::renderTags()
|
2021-10-22 15:34:19 +02:00
|
|
|
{
|
2021-10-26 11:40:46 +02:00
|
|
|
for (auto i=0u; i<_tags.size(); i++) {
|
|
|
|
auto& tag = _tags[i];
|
2021-10-22 17:26:05 +02:00
|
|
|
tag.x = _x;
|
2021-10-26 16:17:07 +02:00
|
|
|
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);
|
2021-10-26 11:40:46 +02:00
|
|
|
renderText(tagNames[i]);
|
2021-10-25 20:52:21 +02:00
|
|
|
auto indicators = qMin(tag.numClients, _bufs->height/2);
|
|
|
|
for (auto ind = 0; ind < indicators; ind++) {
|
|
|
|
if (ind == tag.focusedClient) {
|
|
|
|
_painter->drawLine(tag.x, ind*2, tag.x+5, ind*2);
|
|
|
|
} else {
|
|
|
|
_painter->drawPoint(tag.x, ind*2);
|
|
|
|
}
|
|
|
|
}
|
2021-10-22 15:34:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-22 15:55:29 +02:00
|
|
|
void Bar::renderText(const QString &text)
|
|
|
|
{
|
|
|
|
auto size = textWidth(text) + paddingX*2;
|
|
|
|
_painter->fillRect(_x, 0, size, _bufs->height, _painter->brush());
|
|
|
|
_painter->drawText(paddingX+_x, _textY, text);
|
|
|
|
_x += size;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bar::renderStatus()
|
|
|
|
{
|
2021-10-25 20:52:21 +02:00
|
|
|
_painter->fillRect(_x, 0, _bufs->width-_x, _bufs->height, _painter->brush());
|
2021-10-25 21:54:14 +02:00
|
|
|
auto size = textWidth(_status) + paddingX;
|
2021-10-26 16:40:19 +02:00
|
|
|
_statusX = _bufs->width - size;
|
|
|
|
_painter->drawText(paddingX+_statusX, _textY, _status);
|
2021-10-22 15:55:29 +02:00
|
|
|
_x = _bufs->width;
|
|
|
|
}
|
|
|
|
|
2021-10-22 15:34:19 +02:00
|
|
|
int Bar::textWidth(const QString &text)
|
|
|
|
{
|
2021-10-25 19:02:35 +02:00
|
|
|
return fontMetrics.size(Qt::TextSingleLine, text).width();
|
2021-10-22 15:34:19 +02:00
|
|
|
}
|