Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/borders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
int main() {
rawterm::enable_raw_mode();
rawterm::enter_alt_screen();
rawterm::enable_signals();
auto signals_thread = rawterm::enable_signals();

rawterm::Cursor::cursor_hide();
rawterm::Cursor cur;
Expand All @@ -29,5 +29,6 @@ int main() {

std::ignore = rawterm::wait_for_input();
rawterm::Cursor::cursor_show();
signals_thread.join();
return 0;
}
5 changes: 4 additions & 1 deletion examples/keys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
int main() {
rawterm::enable_raw_mode();
rawterm::enter_alt_screen();
rawterm::enable_signals();
auto signals_thread = rawterm::enable_signals();

rawterm::clear_screen();

Expand Down Expand Up @@ -42,5 +42,8 @@ int main() {
// Optional explicit call to exit_alt_screen to return to standard screen.
// This will happen even without calling this function explicitly
rawterm::exit_alt_screen();

// Don't forget to join back to the main thread
signals_thread.join();
return 0;
}
66 changes: 37 additions & 29 deletions rawterm/core.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
#include "core.h"

#include <algorithm>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <format>

#include "cursor.h"
#include "exceptions.h"

namespace rawterm {
namespace detail {

[[nodiscard]] bool is_debug() {
auto raw_env_var = std::getenv("RAWTERM_DEBUG");
if (raw_env_var == nullptr) {
Expand All @@ -19,6 +23,7 @@ namespace rawterm {
}

} // namespace detail

rawterm::Mod Key::getMod() {
if (mod.empty()) {
return rawterm::Mod::None;
Expand Down Expand Up @@ -97,44 +102,42 @@ namespace rawterm {
std::cout << "\x1B[?1049l" << std::flush;
}

bool is_signals_enabled = false;
void enable_signals() {
inline bool is_signals_enabled = false;
[[nodiscard]] std::thread enable_signals() {
#if __linux__
is_signals_enabled = true;
#endif
}

void sigtstp_handler(std::function<void(void)> func) {
if (detail::sigtstp_called) {
func();
detail::sigtstp_called = false;
}
std::thread thr([] {
// Backgrounding
std::signal(SIGTSTP, [](int) {
detail::sig_sent = Signal::SIG_TSTP;
rawterm::exit_alt_screen();
std::raise(SIGSTOP);
});

// Foregrounding
std::signal(SIGCONT, [](int) {
detail::sig_sent = Signal::SIG_CONT;
rawterm::enter_alt_screen();
rawterm::enable_raw_mode();
});

// Window resizing
std::signal(SIGWINCH, [](int) { detail::sig_sent = Signal::SIG_WINCH; });
});

return thr;
#endif
}

void sigcont_handler(std::function<void(void)> func) {
if (detail::sigcont_called) {
void signal_handler(Signal sig, std::function<void(void)> func) {
if (detail::sig_sent == sig) {
func();
detail::sigcont_called = false;
detail::sig_sent = Signal::NONE;
}
}

[[nodiscard]] const std::optional<rawterm::Key> process_keypress() {
#if __linux__
// Backgrounding
std::signal(SIGTSTP, [](int) {
detail::sigtstp_called = true;
rawterm::exit_alt_screen();
std::raise(SIGSTOP);
});

// Foregrounding
std::signal(SIGCONT, [](int) {
detail::sigcont_called = true;
rawterm::enter_alt_screen();
rawterm::enable_raw_mode();
});
#endif

std::string characters = std::string(32, '\0');
int pollResult = poll(&detail::fd, 1, 0);

Expand All @@ -148,9 +151,14 @@ namespace rawterm {
} else if (pollResult == 0) {
return {};

// interrupted system call -- SIGWINCH interrupting poll()
} else if (errno == 4) {
return {};

// Error
} else {
throw rawterm::KeypressError("An unknown error occured");
throw rawterm::KeypressError(
std::format("A poll error occured: {} - {}", errno, std::strerror(errno)));
}

std::stringstream ss;
Expand Down
10 changes: 5 additions & 5 deletions rawterm/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <optional>
#include <sstream>
#include <string>
#include <thread>
#include <unordered_set>
#include <utility>
#include <vector>
Expand All @@ -32,13 +33,13 @@
#include "screen.h"

namespace rawterm {
enum class Signal { SIG_TSTP, SIG_CONT, SIG_WINCH, NONE };

namespace detail {
#if __linux__
inline termios orig;
#endif
inline bool sigtstp_called = false;
inline bool sigcont_called = false;
inline Signal sig_sent = Signal::NONE;

// Used for polling in process_keypress()
inline pollfd fd {STDIN_FILENO, POLLIN, POLLOUT};
Expand Down Expand Up @@ -105,9 +106,8 @@ namespace rawterm {
[[maybe_unused]] int enable_raw_mode();
void enter_alt_screen();
void exit_alt_screen();
void enable_signals();
void sigtstp_handler(std::function<void(void)>);
void sigcont_handler(std::function<void(void)>);
[[nodiscard]] std::thread enable_signals();
void signal_handler(Signal, std::function<void(void)>);
[[nodiscard]] const std::optional<rawterm::Key> process_keypress();
const rawterm::Key wait_for_input();
[[nodiscard]] const rawterm::Pos get_term_size();
Expand Down
Loading