From a7005be82ca38cef388d3b2155174a049fd96548 Mon Sep 17 00:00:00 2001 From: Michael Carlberg Date: Fri, 16 Dec 2016 06:44:55 +0100 Subject: [PATCH] feat: Fade if unfocused and handle double clicks --- include/components/bar.hpp | 5 +++- include/components/types.hpp | 5 +++- include/x11/wm.hpp | 1 + src/components/bar.cpp | 45 +++++++++++++++++++++++++++++++++++- src/x11/wm.cpp | 10 ++++++++ 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/include/components/bar.hpp b/include/components/bar.hpp index 37e7e1f9..67cdc16d 100644 --- a/include/components/bar.hpp +++ b/include/components/bar.hpp @@ -22,7 +22,7 @@ class screen; class tray_manager; class logger; -class bar : public xpp::event::sink { +class bar : public xpp::event::sink { public: using make_type = unique_ptr; static make_type make(); @@ -43,6 +43,8 @@ class bar : public xpp::event::sink actions{}; + bool dimmed{false}; + double dimvalue{1.0}; + const xcb_rectangle_t inner_area(bool abspos = false) const { xcb_rectangle_t rect{0, 0, size.w, size.h}; diff --git a/include/x11/wm.hpp b/include/x11/wm.hpp index d7a131a3..64b16df9 100644 --- a/include/x11/wm.hpp +++ b/include/x11/wm.hpp @@ -13,6 +13,7 @@ namespace wm_util { void set_wm_state(xcb_connection_t* conn, xcb_window_t win, vector states); void set_wm_pid(xcb_connection_t* conn, xcb_window_t win, pid_t pid); void set_wm_desktop(xcb_connection_t* conn, xcb_window_t win, uint32_t desktop = -1u); + void set_wm_window_opacity(xcb_connection_t* conn, xcb_window_t win, uint64_t value); } POLYBAR_NS_END diff --git a/src/components/bar.cpp b/src/components/bar.cpp index e9d3ecaf..4aaf7a42 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -93,6 +93,9 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const m_opts.override_redirect = m_conf.get(bs, "override-redirect", m_opts.override_redirect); } + m_opts.dimvalue = m_conf.get(bs, "dim-value", 1.0); + m_opts.dimvalue = math_util::cap(m_opts.dimvalue, 0.0, 1.0); + // Build WM_NAME m_opts.wmname = m_conf.get(bs, "wm-name", "polybar-" + bs.substr(4) + "_" + m_opts.monitor->name); m_opts.wmname = string_util::replace(m_opts.wmname, " ", "-"); @@ -120,6 +123,7 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const actions.emplace_back(action{mousebtn::RIGHT, m_conf.get(bs, "click-right", "")}); actions.emplace_back(action{mousebtn::SCROLL_UP, m_conf.get(bs, "scroll-up", "")}); actions.emplace_back(action{mousebtn::SCROLL_DOWN, m_conf.get(bs, "scroll-down", "")}); + actions.emplace_back(action{mousebtn::DOUBLE_CLICK, m_conf.get(bs, "click-double", "")}); for (auto&& act : actions) { if (!act.command.empty()) { @@ -217,6 +221,12 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const m_log.info("Bar geometry: %ix%i+%i+%i", m_opts.size.w, m_opts.size.h, m_opts.pos.x, m_opts.pos.y); m_opts.window = m_renderer->window(); + // Subscribe to window enter and leave events + // if we should dim the window + if (m_opts.dimvalue != 1.0) { + m_connection.ensure_event_mask(m_opts.window, XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW); + } + m_log.info("Bar window: %s", m_connection.id(m_opts.window)); restack_window(); @@ -405,6 +415,34 @@ void bar::broadcast_visibility() { } } +/** + * Event handler for XCB_ENTER_NOTIFY events + * + * Used to brighten the window by setting the + * _NET_WM_WINDOW_OPACITY atom value + */ +void bar::handle(const evt::enter_notify&) { + if (m_opts.dimmed) { + window win{m_connection, m_opts.window}; + wm_util::set_wm_window_opacity(m_connection, m_opts.window, 1.0 * 0xFFFFFFFF); + m_opts.dimmed = false; + } +} + +/** + * Event handler for XCB_LEAVE_NOTIFY events + * + * Used to dim the window by setting the + * _NET_WM_WINDOW_OPACITY atom value + */ +void bar::handle(const evt::leave_notify&) { + if (!m_opts.dimmed) { + window win{m_connection, m_opts.window}; + wm_util::set_wm_window_opacity(m_connection, m_opts.window, m_opts.dimvalue * 0xFFFFFFFF); + m_opts.dimmed = true; + } +} + /** * Event handler for XCB_BUTTON_PRESS events * @@ -422,8 +460,13 @@ void bar::handle(const evt::button_press& evt) { } m_log.trace("bar: Received button press: %i at pos(%i, %i)", evt->detail, evt->event_x, evt->event_y); + mousebtn button{static_cast(evt->detail)}; - const mousebtn button{static_cast(evt->detail)}; + // Using the event_timer so if the event gets denied + // we are within the double click time window + if (button == mousebtn::LEFT && m_doubleclick.deny(evt->time)) { + button = mousebtn::DOUBLE_CLICK; + } for (auto&& action : m_renderer->get_actions()) { if (action.active) { diff --git a/src/x11/wm.cpp b/src/x11/wm.cpp index 56b7fa33..7946847f 100644 --- a/src/x11/wm.cpp +++ b/src/x11/wm.cpp @@ -1,6 +1,7 @@ #include #include +#include "utils/math.hpp" #include "x11/atoms.hpp" #include "x11/wm.hpp" @@ -35,6 +36,15 @@ namespace wm_util { const uint32_t value_list[1]{desktop}; xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, _NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, value_list); } + + void set_wm_window_opacity(xcb_connection_t* conn, xcb_window_t win, uint64_t values) { + xcb_intern_atom_reply_t* reply{xcb_intern_atom_reply(conn, xcb_intern_atom(conn, false, 22, "_NET_WM_WINDOW_OPACITY"), nullptr)}; + if (reply) { + xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, reply->atom, XCB_ATOM_CARDINAL, 32, 1, &values); + xcb_flush(conn); + free(reply); + } + } } POLYBAR_NS_END