diff --git a/config/config.lua b/config/config.lua index 59ec301..731d5cf 100644 --- a/config/config.lua +++ b/config/config.lua @@ -109,12 +109,17 @@ local function render_workspaces(displayName) wsbox(label{label=" " .. zen.u.html_escape(workspace.name) .. " "}, boxcolor), wsbox(label{label=zen.u.html_escape(app_name)}, boxcolor), }, + tag = workspace.name } table.insert(workspaces, workspace) end return { type = "flex", direction = "column", padding = { left = 10, bottom = 10 }, items = workspaces } end +local function click_workspace(tag) + os.execute("swaymsg workspace '" .. tag .. "'") +end + local function render_time() local t = os.time() local markup = os.date("%H:%M\n%Y-%m-%d") @@ -192,7 +197,7 @@ return { { anchor = "left", widgets = { - { sources = {'displays'}, padding = {left = 10 }, on_render = render_workspaces }, + { sources = {'displays'}, padding = {left = 10 }, on_render = render_workspaces, on_click = click_workspace }, }, }, { diff --git a/src/Configuration.h b/src/Configuration.h index b6d76a8..2a282c0 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -46,11 +46,16 @@ struct Border { enum class Anchor { Left, Right, Top, Bottom }; +struct Target { + Rect position; + std::string tag; +}; + struct Renderable { Renderable() : computed{} {} virtual ~Renderable() {} virtual void Compute(cairo_t*) {} - virtual void Draw(cairo_t*, int /*x*/, int /*y*/) const {} + virtual void Draw(cairo_t*, int /*x*/, int /*y*/, std::vector& /*targets*/) const {} Size computed; }; @@ -60,7 +65,7 @@ struct Markup : public Renderable { if (m_layout) g_object_unref(m_layout); } void Compute(cairo_t* cr) override; - void Draw(cairo_t* cr, int x, int y) const override; + void Draw(cairo_t* cr, int x, int y, std::vector& targets) const override; private: const std::string string; @@ -71,29 +76,31 @@ struct MarkupBox : public Renderable { MarkupBox(const std::string& string) : Renderable(), markup(string), color({}), border({}), radius(0), padding({}) {} void Compute(cairo_t* cr) override; - void Draw(cairo_t* cr, int x, int y) const override; + void Draw(cairo_t* cr, int x, int y, std::vector& targets) const override; Markup markup; RGBA color; Border border; uint8_t radius; Padding padding; + std::string tag; }; struct FlexContainer : public Renderable { FlexContainer() : Renderable(), isColumn(false), padding({}) {} void Compute(cairo_t* cr) override; - void Draw(cairo_t* cr, int x, int y) const override; + void Draw(cairo_t* cr, int x, int y, std::vector& targets) const override; bool isColumn; Padding padding; std::vector> children; + std::string tag; }; struct WidgetConfig { WidgetConfig() : padding({}) {} std::function(const std::string& outputName)> render; - std::function click; + std::function click; std::set sources; Padding padding; }; @@ -101,7 +108,7 @@ struct WidgetConfig { struct Widget { Widget() : computed({}), m_renderable(nullptr), m_paddingX(0), m_paddingY(0) {} void Compute(const WidgetConfig& config, const std::string& outputName, cairo_t* cr); - void Draw(cairo_t* cr, int x, int y) const; + void Draw(cairo_t* cr, int x, int y, std::vector& targets) const; Size computed; private: diff --git a/src/Draw.cpp b/src/Draw.cpp index 8cabc71..55b2401 100644 --- a/src/Draw.cpp +++ b/src/Draw.cpp @@ -23,7 +23,7 @@ void Markup::Compute(cairo_t* cr) { LogComputed(computed, ("Markup " + string).c_str()); } -void Markup::Draw(cairo_t* cr, int x, int y) const { +void Markup::Draw(cairo_t* cr, int x, int y, std::vector& targets) const { LogDraw("Markup", x, y); cairo_move_to(cr, x, y); pango_cairo_show_layout(cr, m_layout); @@ -54,7 +54,7 @@ void MarkupBox::Compute(cairo_t* cr) { LogComputed(computed, "MarkupBox "); } -void MarkupBox::Draw(cairo_t* cr, int x, int y) const { +void MarkupBox::Draw(cairo_t* cr, int x, int y, std::vector& targets) const { LogDraw("MarkupBox", x, y); BeginRectangleSubPath(cr, x + border.width, y + border.width, computed.cx - (2 * border.width), computed.cy - (2 * border.width), radius); @@ -78,7 +78,11 @@ void MarkupBox::Draw(cairo_t* cr, int x, int y) const { cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); cairo_fill(cr); // Inner - markup.Draw(cr, x + padding.left + border.width, y + padding.top + border.width); + markup.Draw(cr, x + padding.left + border.width, y + padding.top + border.width, targets); + if (tag != "") { + targets.push_back(Target{ + .position = Rect{.x = x, .y = y, .cx = computed.cx, .cy = computed.cy}, .tag = tag}); + } } void FlexContainer::Compute(cairo_t* cr) { @@ -97,23 +101,30 @@ void FlexContainer::Compute(cairo_t* cr) { LogComputed(computed, "FlexContainer"); } -void FlexContainer::Draw(cairo_t* cr, int x, int y) const { +void FlexContainer::Draw(cairo_t* cr, int x, int y, std::vector& targets) const { LogDraw("FlexBox", x, y); + const int startx = x; + const int starty = y; if (isColumn) { for (const auto& r : children) { y += padding.top; - r->Draw(cr, x + padding.left, y); + r->Draw(cr, x + padding.left, y, targets); y += r->computed.cy + padding.bottom; } } else { y += padding.top; for (const auto& r : children) { x += padding.left; - r->Draw(cr, x, y); + r->Draw(cr, x, y, targets); x += r->computed.cx + padding.right; } y += padding.bottom; } + if (tag != "") { + targets.push_back( + Target{.position = Rect{.x = startx, .y = starty, .cx = computed.cx, .cy = computed.cy}, + .tag = tag}); + } } void Widget::Compute(const WidgetConfig& config, const std::string& outputName, cairo_t* cr) { @@ -134,13 +145,13 @@ void Widget::Compute(const WidgetConfig& config, const std::string& outputName, m_renderable = std::move(item); } -void Widget::Draw(cairo_t* cr, int x, int y) const { +void Widget::Draw(cairo_t* cr, int x, int y, std::vector& targets) const { if (!m_renderable) { // Lua render failed previously return; } cairo_save(cr); - m_renderable->Draw(cr, x + m_paddingX, y + m_paddingY); + m_renderable->Draw(cr, x + m_paddingX, y + m_paddingY, targets); cairo_restore(cr); } @@ -171,6 +182,7 @@ bool Draw::Panel(const PanelConfig& panelConfig, const std::string& outputName, cx += widget.computed.cx; cy += widget.computed.cy; } + std::vector targets; Align align; int xfac = 0, yfac = 0; if (panelConfig.isColumn) { @@ -225,9 +237,10 @@ bool Draw::Panel(const PanelConfig& panelConfig, const std::string& outputName, y = (maxCy - widget.computed.cy) / 2; break; } - widget.Draw(cr, x, y); + widget.Draw(cr, x, y, targets); drawn.widgets.push_back( - DrawnWidget{.position = {x, y, widget.computed.cx, widget.computed.cy}}); + DrawnWidget{.position = {x, y, widget.computed.cx, widget.computed.cy}, + .targets = std::move(targets)}); x += widget.computed.cx * xfac; y += widget.computed.cy * yfac; } diff --git a/src/Draw.h b/src/Draw.h index f026b34..74c74ea 100644 --- a/src/Draw.h +++ b/src/Draw.h @@ -10,6 +10,7 @@ struct DrawnWidget { Rect position; + std::vector targets; }; struct DrawnPanel { diff --git a/src/ScriptContext.cpp b/src/ScriptContext.cpp index 1498683..1cb978b 100644 --- a/src/ScriptContext.cpp +++ b/src/ScriptContext.cpp @@ -36,6 +36,11 @@ Padding PaddingFromProperty(const sol::table& t, const char* name) { return o ? PaddingFromTable(*o) : Padding{}; } +std::string TagFromTable(const sol::table& t) { + const sol::optional optionalTag = t["tag"]; + return optionalTag ? *optionalTag : ""; +} + static std::unique_ptr MarkupBoxFromTable(const sol::table& t) { const sol::optional optionalMarkup = t["markup"]; const std::string markup = optionalMarkup ? *optionalMarkup : ""; @@ -44,6 +49,7 @@ static std::unique_ptr MarkupBoxFromTable(const sol::table& t) { box->border = BorderFromProperty(t, "border"); box->color = RGBAFromProperty(t, "color"); box->padding = PaddingFromProperty(t, "padding"); + box->tag = TagFromTable(t); return box; } @@ -71,6 +77,7 @@ static std::unique_ptr FlexContainerFromTable(const sol::table& t) { if (children) { FromChildTable(*children, f.children); } + f.tag = TagFromTable(t); return std::unique_ptr(new FlexContainer(std::move(f))); } @@ -128,7 +135,10 @@ static void ParseWidgetConfig(const sol::table& table, std::vector sol::optional maybeClickFunction = table["on_click"]; if (maybeClickFunction) { auto clickFunction = *maybeClickFunction; - widget.click = [clickFunction]() { clickFunction(); }; + widget.click = [clickFunction](std::string_view tag) { + clickFunction(tag); + return true; + }; } widget.padding = PaddingFromProperty(table, "padding"); widgets.push_back(std::move(widget)); diff --git a/src/ShellSurface.cpp b/src/ShellSurface.cpp index b28c00c..88c64c2 100644 --- a/src/ShellSurface.cpp +++ b/src/ShellSurface.cpp @@ -55,12 +55,21 @@ bool ShellSurface::ClickSurface(wl_surface *surface, int x, int y) { } // Check what widget int i = 0; - for (const auto w : m_drawn.widgets) { + for (const auto &w : m_drawn.widgets) { if (w.position.Contains(x, y)) { - spdlog::trace("Found widget click target"); auto &widget = m_panelConfig.widgets.at(i); if (widget.click) { - widget.click(); + // Widget has a click handler. There might be inner more + // specific targets, find the tag of the correct one. + std::string tag = ""; + for (const auto &t : w.targets) { + if (t.position.Contains(x, y)) { + tag = t.tag; + break; + } + } + spdlog::debug("Click in widget, tag: {}", tag); + widget.click(tag); } break; }