From 519172b6eca734232e8e1f51efd99f60fc75e2b9 Mon Sep 17 00:00:00 2001 From: Michael Carlberg Date: Fri, 16 Dec 2016 11:26:28 +0100 Subject: [PATCH] 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 --- include/modules/xkeyboard.hpp | 6 ++++++ include/x11/xkb.hpp | 2 ++ src/components/bar.cpp | 1 - src/components/controller.cpp | 2 ++ src/modules/xkeyboard.cpp | 27 +++++++++++++++++++++++++++ src/x11/xkb.cpp | 14 +++++++++++++- 6 files changed, 50 insertions(+), 2 deletions(-) diff --git a/include/modules/xkeyboard.hpp b/include/modules/xkeyboard.hpp index 7f6c9fc7..87d9ae2c 100644 --- a/include/modules/xkeyboard.hpp +++ b/include/modules/xkeyboard.hpp @@ -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{""}; static constexpr const char* FORMAT_DEFAULT{" "}; + static constexpr const char* EVENT_SWITCH{"xkeyboard/switch"}; + connection& m_connection; event_timer m_xkbnotify{}; unique_ptr m_keyboard; diff --git a/include/x11/xkb.hpp b/include/x11/xkb.hpp index 928b0ae9..d53858da 100644 --- a/include/x11/xkb.hpp +++ b/include/x11/xkb.hpp @@ -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 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 get_layouts(connection& conn, xcb_xkb_device_spec_t device); map get_indicators(connection& conn, xcb_xkb_device_spec_t device); diff --git a/src/components/bar.cpp b/src/components/bar.cpp index 982b0901..c6af6ac4 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -478,7 +478,6 @@ void bar::handle(const evt::button_press& evt) { } std::lock_guard guard(m_mutex, std::adopt_lock); - if (m_buttonpress.deny(evt->time)) { return m_log.trace_x("bar: Ignoring button press (throttled)..."); } diff --git a/src/components/controller.cpp b/src/components/controller.cpp index 2646e84f..e62cff66 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -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; } diff --git a/src/modules/xkeyboard.cpp b/src/modules/xkeyboard.cpp index 41815c4c..cfbcedb6 100644 --- a/src/modules/xkeyboard.cpp +++ b/src/modules/xkeyboard.cpp @@ -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; } diff --git a/src/x11/xkb.cpp b/src/x11/xkb.cpp index ada69e49..8bd4a0b7 100644 --- a/src/x11/xkb.cpp +++ b/src/x11/xkb.cpp @@ -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 */