mirror of
https://github.com/polybar/polybar.git
synced 2024-11-18 13:55:11 -05:00
parent
5571095537
commit
891ff6d80a
4 changed files with 55 additions and 15 deletions
|
@ -17,7 +17,7 @@ namespace modules {
|
||||||
* Keyboard module using the X keyboard extension
|
* Keyboard module using the X keyboard extension
|
||||||
*/
|
*/
|
||||||
class xkeyboard_module : public static_module<xkeyboard_module>,
|
class xkeyboard_module : public static_module<xkeyboard_module>,
|
||||||
public xpp::event::sink<evt::xkb_new_keyboard_notify, evt::xkb_indicator_state_notify> {
|
public xpp::event::sink<evt::xkb_new_keyboard_notify, evt::xkb_state_notify, evt::xkb_indicator_state_notify> {
|
||||||
public:
|
public:
|
||||||
xkeyboard_module(const bar_settings& bar, const logger& logger, const config& config, string name);
|
xkeyboard_module(const bar_settings& bar, const logger& logger, const config& config, string name);
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ namespace modules {
|
||||||
bool blacklisted(const string& indicator_name);
|
bool blacklisted(const string& indicator_name);
|
||||||
|
|
||||||
void handle(const evt::xkb_new_keyboard_notify& evt);
|
void handle(const evt::xkb_new_keyboard_notify& evt);
|
||||||
|
void handle(const evt::xkb_state_notify& evt);
|
||||||
void handle(const evt::xkb_indicator_state_notify& evt);
|
void handle(const evt::xkb_indicator_state_notify& evt);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -57,13 +57,14 @@ class keyboard {
|
||||||
vector<string> symbols;
|
vector<string> symbols;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit keyboard(vector<layout>&& layouts_, map<indicator::type, indicator>&& indicators_)
|
explicit keyboard(vector<layout>&& layouts_, map<indicator::type, indicator>&& indicators_, uint8_t group)
|
||||||
: layouts(forward<decltype(layouts)>(layouts_)), indicators(forward<decltype(indicators)>(indicators_)) {}
|
: layouts(forward<decltype(layouts)>(layouts_)), indicators(forward<decltype(indicators)>(indicators_)), current_group(group) {}
|
||||||
|
|
||||||
const indicator& get(const indicator::type& i) const;
|
const indicator& get(const indicator::type& i) const;
|
||||||
void set(uint32_t state);
|
void set(uint32_t state);
|
||||||
bool on(const indicator::type&) const;
|
bool on(const indicator::type&) const;
|
||||||
|
void current(uint8_t group);
|
||||||
|
uint8_t current() const;
|
||||||
const string group_name(size_t index = 0) const;
|
const string group_name(size_t index = 0) const;
|
||||||
const string layout_name(size_t index = 0) const;
|
const string layout_name(size_t index = 0) const;
|
||||||
const string indicator_name(const indicator::type&) const;
|
const string indicator_name(const indicator::type&) const;
|
||||||
|
@ -71,14 +72,16 @@ class keyboard {
|
||||||
private:
|
private:
|
||||||
vector<layout> layouts;
|
vector<layout> layouts;
|
||||||
map<indicator::type, indicator> indicators;
|
map<indicator::type, indicator> indicators;
|
||||||
|
uint8_t current_group{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace xkb_util {
|
namespace xkb_util {
|
||||||
static constexpr const char* LAYOUT_SYMBOL_BLACKLIST{";group;inet;pc;"};
|
static constexpr const char* LAYOUT_SYMBOL_BLACKLIST{";group;inet;pc;"};
|
||||||
|
|
||||||
string parse_layout_symbol(string&& name);
|
uint8_t get_current_group(connection& conn, xcb_xkb_device_spec_t device);
|
||||||
vector<keyboard::layout> get_layouts(connection& conn, xcb_xkb_device_spec_t device);
|
vector<keyboard::layout> get_layouts(connection& conn, xcb_xkb_device_spec_t device);
|
||||||
map<keyboard::indicator::type, keyboard::indicator> get_indicators(connection& conn, xcb_xkb_device_spec_t device);
|
map<keyboard::indicator::type, keyboard::indicator> get_indicators(connection& conn, xcb_xkb_device_spec_t device);
|
||||||
|
string parse_layout_symbol(string&& name);
|
||||||
}
|
}
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
|
|
@ -41,9 +41,11 @@ namespace modules {
|
||||||
m_connection.attach_sink(this, SINK_PRIORITY_MODULE);
|
m_connection.attach_sink(this, SINK_PRIORITY_MODULE);
|
||||||
|
|
||||||
// Setup extension
|
// Setup extension
|
||||||
|
// clang-format off
|
||||||
m_connection.xkb().select_events_checked(XCB_XKB_ID_USE_CORE_KBD,
|
m_connection.xkb().select_events_checked(XCB_XKB_ID_USE_CORE_KBD,
|
||||||
XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY, 0,
|
XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY, 0,
|
||||||
XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY, 0, 0, nullptr);
|
XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY, 0, 0, nullptr);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
// Create keyboard object
|
// Create keyboard object
|
||||||
query_keyboard();
|
query_keyboard();
|
||||||
|
@ -64,8 +66,9 @@ namespace modules {
|
||||||
void xkeyboard_module::update() {
|
void xkeyboard_module::update() {
|
||||||
if (m_layout) {
|
if (m_layout) {
|
||||||
m_layout->reset_tokens();
|
m_layout->reset_tokens();
|
||||||
m_layout->replace_token("%name%", m_keyboard->group_name());
|
m_layout->replace_token("%name%", m_keyboard->group_name(m_keyboard->current()));
|
||||||
m_layout->replace_token("%layout%", m_keyboard->layout_name());
|
m_layout->replace_token("%layout%", m_keyboard->layout_name(m_keyboard->current()));
|
||||||
|
m_layout->replace_token("%number%", to_string(m_keyboard->current()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_indicator) {
|
if (m_indicator) {
|
||||||
|
@ -121,7 +124,8 @@ namespace modules {
|
||||||
try {
|
try {
|
||||||
auto layouts = xkb_util::get_layouts(m_connection, XCB_XKB_ID_USE_CORE_KBD);
|
auto layouts = xkb_util::get_layouts(m_connection, XCB_XKB_ID_USE_CORE_KBD);
|
||||||
auto indicators = xkb_util::get_indicators(m_connection, XCB_XKB_ID_USE_CORE_KBD);
|
auto indicators = xkb_util::get_indicators(m_connection, XCB_XKB_ID_USE_CORE_KBD);
|
||||||
m_keyboard = make_unique<keyboard>(move(layouts), move(indicators));
|
auto current_group = xkb_util::get_current_group(m_connection, XCB_XKB_ID_USE_CORE_KBD);
|
||||||
|
m_keyboard = make_unique<keyboard>(move(layouts), move(indicators), current_group);
|
||||||
return true;
|
return true;
|
||||||
} catch (const exception& err) {
|
} catch (const exception& err) {
|
||||||
throw module_error("Failed to query keyboard, err: " + string{err.what()});
|
throw module_error("Failed to query keyboard, err: " + string{err.what()});
|
||||||
|
@ -152,6 +156,16 @@ namespace modules {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for XCB_XKB_STATE_NOTIFY events
|
||||||
|
*/
|
||||||
|
void xkeyboard_module::handle(const evt::xkb_state_notify& evt) {
|
||||||
|
if (m_keyboard && evt->changed & XCB_XKB_STATE_PART_GROUP_STATE && m_xkbnotify.allow(evt->time)) {
|
||||||
|
m_keyboard->current(evt->group);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for XCB_XKB_INDICATOR_STATE_NOTIFY events
|
* Handler for XCB_XKB_INDICATOR_STATE_NOTIFY events
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -29,6 +29,20 @@ bool keyboard::on(const indicator::type& i) const {
|
||||||
return indicators.at(i).enabled;
|
return indicators.at(i).enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set current group number
|
||||||
|
*/
|
||||||
|
void keyboard::current(uint8_t group) {
|
||||||
|
current_group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current group number
|
||||||
|
*/
|
||||||
|
uint8_t keyboard::current() const {
|
||||||
|
return current_group;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current group name
|
* Get current group name
|
||||||
*/
|
*/
|
||||||
|
@ -43,10 +57,10 @@ const string keyboard::group_name(size_t index) const {
|
||||||
* Get current layout name
|
* Get current layout name
|
||||||
*/
|
*/
|
||||||
const string keyboard::layout_name(size_t index) const {
|
const string keyboard::layout_name(size_t index) const {
|
||||||
if (!layouts.empty() && index < layouts.size() && !layouts[index].symbols.empty()) {
|
if (index >= layouts.size() || index >= layouts[index].symbols.size()) {
|
||||||
return layouts[index].symbols[0];
|
return "";
|
||||||
}
|
}
|
||||||
return "";
|
return layouts[index].symbols[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,6 +71,14 @@ const string keyboard::indicator_name(const indicator::type& i) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace xkb_util {
|
namespace xkb_util {
|
||||||
|
/**
|
||||||
|
* Get current group number
|
||||||
|
*/
|
||||||
|
uint8_t get_current_group(connection& conn, xcb_xkb_device_spec_t device) {
|
||||||
|
auto reply = xcb_xkb_get_state_reply(conn, xcb_xkb_get_state(conn, device), nullptr);
|
||||||
|
return reply ? reply->group : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get keyboard layouts
|
* Get keyboard layouts
|
||||||
*/
|
*/
|
||||||
|
@ -136,8 +158,8 @@ namespace xkb_util {
|
||||||
* Parse symbol name and exclude entries blacklisted entries
|
* Parse symbol name and exclude entries blacklisted entries
|
||||||
*/
|
*/
|
||||||
string parse_layout_symbol(string&& name) {
|
string parse_layout_symbol(string&& name) {
|
||||||
auto pos = name.find('(');
|
size_t pos;
|
||||||
if (pos != string::npos) {
|
while ((pos = name.find_first_of({'(', ':'})) != string::npos) {
|
||||||
name.erase(pos);
|
name.erase(pos);
|
||||||
}
|
}
|
||||||
if (string_util::contains(LAYOUT_SYMBOL_BLACKLIST, ";" + name + ";")) {
|
if (string_util::contains(LAYOUT_SYMBOL_BLACKLIST, ";" + name + ";")) {
|
||||||
|
|
Loading…
Reference in a new issue