feat(xkeyboard): Switch layout group on click

When serveral layout groups are defined for the keyboard
they can be cycled when clicking on the module.

   For example:

   $ setxkbmap -layout us,sv,fr

Ref #84
This commit is contained in:
Michael Carlberg 2016-12-16 11:26:28 +01:00
parent f50f43af02
commit 519172b6ec
6 changed files with 50 additions and 2 deletions

View File

@ -25,6 +25,10 @@ namespace modules {
void teardown();
void update();
bool build(builder* builder, const string& tag) const;
bool handle_event(string cmd);
bool receive_events() const {
return true;
}
protected:
bool query_keyboard();
@ -39,6 +43,8 @@ namespace modules {
static constexpr const char* TAG_LABEL_INDICATOR{"<label-indicator>"};
static constexpr const char* FORMAT_DEFAULT{"<label-layout> <label-indicator>"};
static constexpr const char* EVENT_SWITCH{"xkeyboard/switch"};
connection& m_connection;
event_timer m_xkbnotify{};
unique_ptr<keyboard> m_keyboard;

View File

@ -72,6 +72,7 @@ class keyboard {
const string group_name(size_t index = 0) const;
const string layout_name(size_t index = 0) const;
const string indicator_name(const indicator::type&) const;
size_t size() const;
private:
vector<layout> layouts;
@ -82,6 +83,7 @@ class keyboard {
namespace xkb_util {
static constexpr const char* LAYOUT_SYMBOL_BLACKLIST{";group;inet;pc;"};
void switch_layout(connection& conn, xcb_xkb_device_spec_t device, uint8_t index);
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);
map<keyboard::indicator::type, keyboard::indicator> get_indicators(connection& conn, xcb_xkb_device_spec_t device);

View File

@ -478,7 +478,6 @@ void bar::handle(const evt::button_press& evt) {
}
std::lock_guard<std::mutex> guard(m_mutex, std::adopt_lock);
if (m_buttonpress.deny(evt->time)) {
return m_log.trace_x("bar: Ignoring button press (throttled)...");
}

View File

@ -262,6 +262,8 @@ void controller::wait_for_eventloop() {
}
bool controller::on(const sig_ev::process_update& evt) {
bool force{evt.data()->flag};
if (!m_bar) {
return false;
}

View File

@ -99,6 +99,8 @@ namespace modules {
* Map format tags to content
*/
bool xkeyboard_module::build(builder* builder, const string& tag) const {
builder->cmd(mousebtn::LEFT, EVENT_SWITCH);
if (tag == TAG_LABEL_LAYOUT) {
builder->node(m_layout);
} else if (tag == TAG_LABEL_INDICATOR) {
@ -114,6 +116,31 @@ namespace modules {
return false;
}
builder->cmd_close();
return true;
}
/**
* Handle input command
*/
bool xkeyboard_module::handle_event(string cmd) {
if (cmd.compare(0, strlen(EVENT_SWITCH), EVENT_SWITCH) != 0) {
return false;
}
size_t current_group{m_keyboard->current() + 1UL};
if (current_group >= m_keyboard->size()) {
current_group = 0;
}
printf("%zu\n", current_group);
xkb_util::switch_layout(m_connection, XCB_XKB_ID_USE_CORE_KBD, current_group);
m_keyboard->current(current_group);
m_connection.flush();
return true;
}

View File

@ -7,7 +7,7 @@
POLYBAR_NS
/**
* Get indicator name
* Get next layout index
*/
const keyboard::indicator& keyboard::get(const indicator::type& i) const {
return indicators.at(i);
@ -70,7 +70,19 @@ const string keyboard::indicator_name(const indicator::type& i) const {
return indicators.at(i).name;
}
size_t keyboard::size() const {
return layouts.size();
}
namespace xkb_util {
/**
* Get current group number
*/
void switch_layout(connection& conn, xcb_xkb_device_spec_t device, uint8_t index) {
xcb_xkb_latch_lock_state(conn, device, 0, 0, true, index, 0, 0, 0);
xcb_flush(conn);
}
/**
* Get current group number
*/