polybar/src/modules/xwindow.cpp

128 lines
3.1 KiB
C++
Raw Normal View History

#include "modules/xwindow.hpp"
#include "drawtypes/label.hpp"
#include "x11/atoms.hpp"
2016-11-20 22:04:31 +00:00
#include "x11/connection.hpp"
#include "x11/graphics.hpp"
2016-11-20 22:04:31 +00:00
#include "modules/meta/base.inl"
#include "modules/meta/static_module.inl"
2016-11-19 05:22:44 +00:00
POLYBAR_NS
namespace modules {
2016-11-20 22:04:31 +00:00
template class module<xwindow_module>;
template class static_module<xwindow_module>;
/**
* Bootstrap the module
*/
void xwindow_module::setup() {
connection& conn{configure_connection().create<decltype(conn)>()};
// Initialize ewmh atoms
2016-11-26 05:13:20 +00:00
if ((m_ewmh = ewmh_util::initialize()) == nullptr) {
throw module_error("Failed to initialize ewmh atoms");
}
// Check if the WM supports _NET_ACTIVE_WINDOW
2016-11-26 05:13:20 +00:00
if (!ewmh_util::supports(m_ewmh.get(), _NET_ACTIVE_WINDOW)) {
throw module_error("The WM does not list _NET_ACTIVE_WINDOW as a supported hint");
}
// Add formats and elements
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL});
if (m_formatter->has(TAG_LABEL)) {
m_label = load_optional_label(m_conf, name(), TAG_LABEL, "%title%");
}
// No need to setup X components if we can't show the title
if (!m_label || !m_label->has_token("%title%")) {
return;
}
// Make sure we get notified when root properties change
window root{conn, conn.root()};
root.ensure_event_mask(XCB_EVENT_MASK_PROPERTY_CHANGE);
// Connect with the event registry
conn.attach_sink(this, 1);
// Trigger the initial draw event
update();
}
/**
* Disconnect from the event registry
*/
void xwindow_module::teardown() {
connection& conn{configure_connection().create<decltype(conn)>()};
conn.detach_sink(this, 1);
}
/**
* Handler for XCB_PROPERTY_NOTIFY events
*/
void xwindow_module::handle(const evt::property_notify& evt) {
2016-11-19 03:34:46 +00:00
if (evt->atom == _NET_ACTIVE_WINDOW) {
update();
} else if (evt->atom == _NET_CURRENT_DESKTOP) {
update();
} else if (evt->atom == _NET_WM_VISIBLE_NAME) {
update();
} else if (evt->atom == _NET_WM_NAME) {
update();
} else {
return;
}
}
/**
* Update the currently active window and query its title
*/
void xwindow_module::update() {
2016-11-26 05:13:20 +00:00
xcb_window_t win{ewmh_util::get_active_window(m_ewmh.get())};
string title;
if (m_active && m_active->match(win)) {
2016-11-26 05:13:20 +00:00
title = m_active->title(m_ewmh.get());
} else if (win != XCB_NONE) {
m_active = make_unique<active_window>(win);
2016-11-26 05:13:20 +00:00
title = m_active->title(m_ewmh.get());
} else {
m_active.reset();
}
if (m_label) {
m_label->reset_tokens();
m_label->replace_token("%title%", title);
}
// Emit notification to trigger redraw
broadcast();
}
/**
* Generate the module output
*/
string xwindow_module::get_output() {
m_builder->append(static_module::get_output());
return m_builder->flush();
}
/**
* Output content as defined in the config
*/
2016-11-25 12:55:15 +00:00
bool xwindow_module::build(builder* builder, const string& tag) const {
if (tag == TAG_LABEL) {
builder->node(m_label);
} else {
return false;
}
return true;
}
}
2016-11-19 05:22:44 +00:00
POLYBAR_NS_END