From 17dafd8c50d828a3334586dd558a12270ba6bdc0 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 26 Apr 2024 20:07:47 +0200 Subject: [PATCH] close #239 (enable keyboard handling in command handlers on linux) --- CHANGELOG.md | 1 + include/cli/detail/inputdevice.h | 2 ++ include/cli/detail/inputhandler.h | 8 ++++++-- include/cli/detail/linuxkeyboard.h | 26 ++++++++++++++++++++++++-- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8418fe0..566faa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Parent menus does not chain (issue [#234](https://github.com/daniele77/cli/issues/234)) - Parent menu shortcut (issue [#233](https://github.com/daniele77/cli/issues/233)) - Integer overflow warning detected by clang++ (issue [#236](https://github.com/daniele77/cli/issues/236)) + - Enable Keyboard Handling in Command Handlers on Linux Platform (issue [#239](https://github.com/daniele77/cli/issues/239)) ## [2.1.0] - 2023-06-29 diff --git a/include/cli/detail/inputdevice.h b/include/cli/detail/inputdevice.h index 5655ed8..bb536e3 100644 --- a/include/cli/detail/inputdevice.h +++ b/include/cli/detail/inputdevice.h @@ -48,6 +48,8 @@ class InputDevice explicit InputDevice(Scheduler& _scheduler) : scheduler(_scheduler) {} virtual ~InputDevice() = default; + virtual void ActivateInput() {} + virtual void DeactivateInput() {} template void Register(H&& h) { handler = std::forward(h); } diff --git a/include/cli/detail/inputhandler.h b/include/cli/detail/inputhandler.h index ac9170e..5f0310e 100644 --- a/include/cli/detail/inputhandler.h +++ b/include/cli/detail/inputhandler.h @@ -45,9 +45,10 @@ namespace detail class InputHandler { public: - InputHandler(CliSession& _session, InputDevice& kb) : + InputHandler(CliSession& _session, InputDevice& _kb) : session(_session), - terminal(session.OutStream()) + terminal(session.OutStream()), + kb(_kb) { kb.Register( [this](auto key){ this->Keypressed(key); } ); } @@ -75,8 +76,10 @@ class InputHandler } case Symbol::command: { + kb.DeactivateInput(); session.Feed(s.second); session.Prompt(); + kb.ActivateInput(); break; } case Symbol::down: @@ -124,6 +127,7 @@ class InputHandler CliSession& session; Terminal terminal; + InputDevice& kb; }; } // namespace detail diff --git a/include/cli/detail/linuxkeyboard.h b/include/cli/detail/linuxkeyboard.h index 72ec901..d58e396 100644 --- a/include/cli/detail/linuxkeyboard.h +++ b/include/cli/detail/linuxkeyboard.h @@ -32,13 +32,14 @@ #include #include +#include #include #include #include #include #include - +#include #include "inputdevice.h" @@ -106,9 +107,10 @@ class LinuxKeyboard : public InputDevice public: explicit LinuxKeyboard(Scheduler& _scheduler) : InputDevice(_scheduler), + enabled(false), servant( [this]() noexcept { Read(); } ) { - ToManualMode(); + ActivateInput(); } ~LinuxKeyboard() override { @@ -116,6 +118,19 @@ class LinuxKeyboard : public InputDevice is.Stop(); servant.join(); } + void ActivateInput() override + { + ToManualMode(); + std::lock_guard lock(mtx); + enabled = true; + cv.notify_one(); + } + void DeactivateInput() override + { + ToStandardMode(); + std::lock_guard lock(mtx); + enabled = false; + } private: @@ -125,6 +140,10 @@ class LinuxKeyboard : public InputDevice { while (true) { + { + std::unique_lock lock(mtx); + cv.wait(lock, [this]{ return enabled; }); // release mtx, suspend thread execution until enabled becomes true + } auto k = Get(); Notify(k); } @@ -205,10 +224,13 @@ class LinuxKeyboard : public InputDevice tcsetattr(STDIN_FILENO, TCSANOW, &oldt); } + bool enabled; termios oldt; termios newt; InputSource is; std::thread servant; + std::mutex mtx; + std::condition_variable cv; }; } // namespace detail