cpp-terminal 1.0.0
Small C++ library for writing multiplatform terminal applications
Loading...
Searching...
No Matches
Term::Private::Input Class Referencefinal

#include <cpp-terminal/private/input.hpp>

Public Member Functions

 Input ()
 
 ~Input ()
 

Static Public Member Functions

static void startReading ()
 
static Term::Event getEvent ()
 
static Term::Event getEventBlocking ()
 

Static Private Member Functions

static void read_event ()
 
static void read_raw ()
 
static void read_windows_key (const std::uint16_t &virtual_key_code, const std::uint32_t &control_key_state, const std::size_t &occurrence)
 
static void init_thread ()
 

Static Private Attributes

static std::thread m_thread {}
 
static Term::Private::BlockingQueue m_events
 
static int m_poll {-1}
 

Detailed Description

Definition at line 25 of file input.hpp.

Constructor & Destructor Documentation

◆ Input()

Term::Private::Input::Input ( )

Definition at line 313 of file input.cpp.

313{}

◆ ~Input()

Term::Private::Input::~Input ( )

Definition at line 80 of file input.cpp.

81{
82 if(m_thread.joinable()) m_thread.join();
83}
static std::thread m_thread
Definition input.hpp:85

Member Function Documentation

◆ getEvent()

Term::Event Term::Private::Input::getEvent ( )
static

Definition at line 326 of file input.cpp.

326{ return m_events.pop(); }
static Term::Private::BlockingQueue m_events
Definition input.hpp:42

◆ getEventBlocking()

Term::Event Term::Private::Input::getEventBlocking ( )
static

Definition at line 328 of file input.cpp.

329{
330 static std::mutex cv_m;
331 static std::unique_lock<std::mutex> lk(cv_m);
333 return m_events.pop();
334}
void wait_for_events(std::unique_lock< std::mutex > &lock)

◆ init_thread()

void Term::Private::Input::init_thread ( )
staticprivate

Definition at line 91 of file input.cpp.

92{
93#if defined(__linux__)
94 m_poll = {::epoll_create1(EPOLL_CLOEXEC)};
95 ::epoll_event signal;
96 signal.events = {EPOLLIN};
97 signal.data.fd = {Term::Private::Sigwinch::get()};
98 ::epoll_ctl(m_poll, EPOLL_CTL_ADD, Term::Private::Sigwinch::get(), &signal);
99 ::epoll_event input;
100 input.events = {EPOLLIN};
101 input.data.fd = {Term::Private::in.fd()};
102 ::epoll_ctl(m_poll, EPOLL_CTL_ADD, Term::Private::in.fd(), &input);
103#endif
104 if(m_thread.joinable()) m_thread.join();
105 std::thread thread(Term::Private::Input::read_event);
106 m_thread.swap(thread);
107}
std::int32_t fd() const noexcept
Definition file.cpp:97
static int m_poll
Definition input.hpp:89
static void read_event()
Definition input.cpp:109
static std::int32_t get() noexcept
Definition sigwinch.cpp:38
InputFileHandler & in
Definition file.cpp:43

◆ read_event()

void Term::Private::Input::read_event ( )
staticprivate

Definition at line 109 of file input.cpp.

110{
111 while(true)
112 {
113#if defined(_WIN32)
114 WaitForSingleObject(Term::Private::in.handle(), INFINITE);
115 read_raw();
116#elif defined(__APPLE__) || defined(__wasm__) || defined(__wasm) || defined(__EMSCRIPTEN__)
118 read_raw();
119#else
120 ::epoll_event ret;
121 if(epoll_wait(m_poll, &ret, 1, -1) == 1)
122 {
124 else
125 read_raw();
126 }
127#endif
128 }
129}
void push(const Term::Event &value, const std::size_t &occurrence=1)
static void read_raw()
Definition input.cpp:211
static bool isSigwinch(const std::int32_t &file_descriptor=-1) noexcept
Definition sigwinch.cpp:85
Screen screen_size()
Definition screen.cpp:24

◆ read_raw()

void Term::Private::Input::read_raw ( )
staticprivate

Definition at line 211 of file input.cpp.

212{
213#ifdef _WIN32
214 DWORD to_read{0};
215 GetNumberOfConsoleInputEvents(Private::in.handle(), &to_read);
216 if(to_read == 0) return;
217 DWORD read{0};
218 std::vector<INPUT_RECORD> events{to_read};
219 if(!ReadConsoleInputW(Private::in.handle(), &events[0], to_read, &read) || read != to_read) Term::Exception("ReadFile() failed");
220 std::wstring ret;
221 bool need_windows_size{false};
222 for(std::size_t i = 0; i != read; ++i)
223 {
224 switch(events[i].EventType)
225 {
226 case KEY_EVENT:
227 {
228 if(events[i].Event.KeyEvent.bKeyDown)
229 {
230 if(events[i].Event.KeyEvent.uChar.UnicodeChar == 0) read_windows_key(events[i].Event.KeyEvent.wVirtualKeyCode, events[i].Event.KeyEvent.dwControlKeyState, events[i].Event.KeyEvent.wRepeatCount);
231 else
232 ret.append(events[i].Event.KeyEvent.wRepeatCount, events[i].Event.KeyEvent.uChar.UnicodeChar == Term::Key::Del ? static_cast<wchar_t>(Key(Term::Key::Value::Backspace)) : static_cast<wchar_t>(events[i].Event.KeyEvent.uChar.UnicodeChar));
233 }
234 break;
235 }
236 case FOCUS_EVENT:
237 {
238 sendString(m_events, ret);
239 m_events.push(Event(Focus(static_cast<Term::Focus::Type>(events[i].Event.FocusEvent.bSetFocus))));
240 break;
241 }
242 case MENU_EVENT:
243 {
244 sendString(m_events, ret);
245 break;
246 }
247 case MOUSE_EVENT:
248 {
249 sendString(m_events, ret);
250 static MOUSE_EVENT_RECORD old_state;
251 if(events[i].Event.MouseEvent.dwEventFlags == MOUSE_WHEELED || events[i].Event.MouseEvent.dwEventFlags == MOUSE_HWHEELED)
252 ;
253 else if(old_state.dwButtonState == events[i].Event.MouseEvent.dwButtonState && old_state.dwMousePosition.X == events[i].Event.MouseEvent.dwMousePosition.X && old_state.dwMousePosition.Y == events[i].Event.MouseEvent.dwMousePosition.Y && old_state.dwEventFlags == events[i].Event.MouseEvent.dwEventFlags)
254 break;
255 std::int32_t state{static_cast<std::int32_t>(events[i].Event.MouseEvent.dwButtonState)};
256 switch(events[i].Event.MouseEvent.dwEventFlags)
257 {
258 case 0:
259 {
260 m_events.push(Term::Mouse(setButton(static_cast<std::int32_t>(old_state.dwButtonState), state), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.Y), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.X)));
261 ;
262 break;
263 }
264 case MOUSE_MOVED:
265 {
266 m_events.push(Term::Mouse(setButton(static_cast<std::int32_t>(old_state.dwButtonState), state), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.Y), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.X)));
267 ;
268 break;
269 }
270 case DOUBLE_CLICK:
271 {
272 m_events.push(Term::Mouse(Term::Button(setButton(static_cast<std::int32_t>(old_state.dwButtonState), state).type(), Term::Button::Action::DoubleClicked), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.Y), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.X)));
273 break;
274 }
275 case MOUSE_WHEELED:
276 {
277 if(state > 0) m_events.push(Term::Mouse(Button(Term::Button::Type::Wheel, Term::Button::Action::RolledUp), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.Y), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.X)));
278 else
279 m_events.push(Term::Mouse(Button(Term::Button::Type::Wheel, Term::Button::Action::RolledDown), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.Y), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.X)));
280 break;
281 }
282 case MOUSE_HWHEELED:
283 {
284 if(state > 0) m_events.push(Term::Mouse(Button(Term::Button::Type::Wheel, Term::Button::Action::ToRight), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.Y), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.X)));
285 else
286 m_events.push(Term::Mouse(Button(Term::Button::Type::Wheel, Term::Button::Action::ToLeft), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.Y), static_cast<std::uint16_t>(events[i].Event.MouseEvent.dwMousePosition.X)));
287 break;
288 }
289 default: break;
290 }
291 old_state = events[i].Event.MouseEvent;
292 break;
293 }
294 case WINDOW_BUFFER_SIZE_EVENT:
295 {
296 need_windows_size = true; // if we send directly it's too much generations
297 sendString(m_events, ret);
298 break;
299 }
300 default: break;
301 }
302 }
303 sendString(m_events, ret);
304 if(need_windows_size == true) { m_events.push(screen_size()); }
305#else
307 std::string ret = Term::Private::in.read();
309 if(!ret.empty()) m_events.push(Event(ret.c_str()));
310#endif
311}
Term::Button::Type type() const noexcept
Definition mouse.cpp:14
@ Backspace
Definition key.hpp:229
std::string read() const
Definition file.cpp:127
static void read_windows_key(const std::uint16_t &virtual_key_code, const std::uint32_t &control_key_state, const std::size_t &occurrence)
Definition input.cpp:132
Term::Button setButton(const std::int32_t &old_state, const std::int32_t &state)
Definition input.cpp:49
void sendString(Term::Private::BlockingQueue &events, std::wstring &str)
Definition input.cpp:70

◆ read_windows_key()

void Term::Private::Input::read_windows_key ( const std::uint16_t & virtual_key_code,
const std::uint32_t & control_key_state,
const std::size_t & occurrence )
staticprivate

Definition at line 132 of file input.cpp.

133{
134 // First check if we have ALT etc (CTRL is already done so skip it)
136 if(((control_key_state & LEFT_ALT_PRESSED) == LEFT_ALT_PRESSED) || ((control_key_state & RIGHT_ALT_PRESSED) == RIGHT_ALT_PRESSED)) toAdd += Term::MetaKey::Value::Alt;
137 if(((control_key_state & LEFT_CTRL_PRESSED) == LEFT_CTRL_PRESSED) || ((control_key_state & RIGHT_CTRL_PRESSED) == RIGHT_CTRL_PRESSED)) toAdd += Term::MetaKey::Value::Ctrl;
138
139 switch(virtual_key_code)
140 {
141 case VK_CANCEL: //??
142 case VK_CLEAR: //??
143 case VK_SHIFT:
144 case VK_CONTROL:
145 case VK_MENU:
146 case VK_PAUSE: //??
147 case VK_CAPITAL:
148 case VK_KANA: //??
149 //case VK_HANGUL: // Same
150 case VK_JUNJA: // ?
151 case VK_FINAL: // ?
152 case VK_HANJA:
153 //case VK_KANJI: // Same
154 case VK_CONVERT: // ?
155 case VK_NONCONVERT: // ?
156 case VK_ACCEPT: // ?
157 case VK_MODECHANGE: // ?
158 break;
159 case VK_PRIOR: m_events.push(std::move(toAdd + Term::Key(Key::Value::PageUp)), occurrence); break;
160 case VK_NEXT: m_events.push(std::move(toAdd + Term::Key(Key::Value::PageDown)), occurrence); break;
161 case VK_END: m_events.push(std::move(toAdd + Term::Key(Key::Value::End)), occurrence); break;
162 case VK_HOME: m_events.push(std::move(toAdd + Term::Key(Key::Value::Home)), occurrence); break;
163 case VK_LEFT: m_events.push(std::move(toAdd + Term::Key(Key::Value::ArrowLeft)), occurrence); break;
164 case VK_UP: m_events.push(std::move(toAdd + Term::Key(Key::Value::ArrowUp)), occurrence); break;
165 case VK_RIGHT: m_events.push(std::move(toAdd + Term::Key(Key::Value::ArrowRight)), occurrence); break;
166 case VK_DOWN: m_events.push(std::move(toAdd + Term::Key(Key::Value::ArrowDown)), occurrence); break;
167 case VK_SELECT: //?
168 case VK_PRINT: //?
169 case VK_EXECUTE: //?
170 break;
171 case VK_SNAPSHOT: m_events.push(std::move(toAdd + Term::Key(Key::Value::PrintScreen)), occurrence); break;
172 case VK_INSERT: m_events.push(std::move(toAdd + Term::Key(Key::Value::Insert)), occurrence); break;
173 case VK_DELETE: m_events.push(std::move(toAdd + Term::Key(Key::Value::Del)), occurrence); break;
174 case VK_HELP: //?
175 case VK_LWIN: //Maybe allow to detect Windows key Left and right
176 case VK_RWIN: //Maybe allow to detect Windows key Left and right
177 case VK_APPS: //?
178 case VK_SLEEP: //?
179 break;
180 case VK_F1: m_events.push(std::move(toAdd + Term::Key(Key::Value::F1)), occurrence); break;
181 case VK_F2: m_events.push(std::move(toAdd + Term::Key(Key::Value::F2)), occurrence); break;
182 case VK_F3: m_events.push(std::move(toAdd + Term::Key(Key::Value::F3)), occurrence); break;
183 case VK_F4: m_events.push(std::move(toAdd + Term::Key(Key::Value::F4)), occurrence); break;
184 case VK_F5: m_events.push(std::move(toAdd + Term::Key(Key::Value::F5)), occurrence); break;
185 case VK_F6: m_events.push(std::move(toAdd + Term::Key(Key::Value::F6)), occurrence); break;
186 case VK_F7: m_events.push(std::move(toAdd + Term::Key(Key::Value::F7)), occurrence); break;
187 case VK_F8: m_events.push(std::move(toAdd + Term::Key(Key::Value::F8)), occurrence); break;
188 case VK_F9: m_events.push(std::move(toAdd + Term::Key(Key::Value::F9)), occurrence); break;
189 case VK_F10: m_events.push(std::move(toAdd + Term::Key(Key::Value::F10)), occurrence); break;
190 case VK_F11: m_events.push(std::move(toAdd + Term::Key(Key::Value::F11)), occurrence); break;
191 case VK_F12: m_events.push(std::move(toAdd + Term::Key(Key::Value::F12)), occurrence); break;
192 case VK_F13: m_events.push(std::move(toAdd + Term::Key(Key::Value::F13)), occurrence); break;
193 case VK_F14: m_events.push(std::move(toAdd + Term::Key(Key::Value::F14)), occurrence); break;
194 case VK_F15: m_events.push(std::move(toAdd + Term::Key(Key::Value::F15)), occurrence); break;
195 case VK_F16: m_events.push(std::move(toAdd + Term::Key(Key::Value::F16)), occurrence); break;
196 case VK_F17: m_events.push(std::move(toAdd + Term::Key(Key::Value::F17)), occurrence); break;
197 case VK_F18: m_events.push(std::move(toAdd + Term::Key(Key::Value::F18)), occurrence); break;
198 case VK_F19: m_events.push(std::move(toAdd + Term::Key(Key::Value::F19)), occurrence); break;
199 case VK_F20: m_events.push(std::move(toAdd + Term::Key(Key::Value::F20)), occurrence); break;
200 case VK_F21: m_events.push(std::move(toAdd + Term::Key(Key::Value::F21)), occurrence); break;
201 case VK_F22: m_events.push(std::move(toAdd + Term::Key(Key::Value::F22)), occurrence); break;
202 case VK_F23: m_events.push(std::move(toAdd + Term::Key(Key::Value::F23)), occurrence); break;
203 case VK_F24: m_events.push(std::move(toAdd + Term::Key(Key::Value::F24)), occurrence); break;
204 case VK_NUMLOCK:
205 case VK_SCROLL:
206 default: break;
207 }
208}
@ ArrowRight
Definition key.hpp:239
@ ArrowLeft
Definition key.hpp:238
@ PageDown
Definition key.hpp:247
@ PageUp
Definition key.hpp:246
@ PrintScreen
Definition key.hpp:272
@ ArrowUp
Definition key.hpp:240
@ ArrowDown
Definition key.hpp:241
@ Insert
Definition key.hpp:244

◆ startReading()

void Term::Private::Input::startReading ( )
static

Definition at line 315 of file input.cpp.

316{
317 static bool activated{false};
318 if(!activated)
319 {
320 init_thread();
321 m_thread.detach();
322 activated = true;
323 }
324}
static void init_thread()
Definition input.cpp:91

Member Data Documentation

◆ m_events

Term::Private::BlockingQueue Term::Private::Input::m_events
staticprivate

Definition at line 42 of file input.hpp.

◆ m_poll

int Term::Private::Input::m_poll {-1}
staticprivate

Definition at line 89 of file input.hpp.

◆ m_thread

std::thread Term::Private::Input::m_thread {}
staticprivate

Definition at line 85 of file input.hpp.

102{
103
104namespace Private
105{
106
107class BlockingQueue;
108
109class Input final
110{
111public:
112 Input();
113 ~Input();
114 static void startReading();
115 static Term::Event getEvent();
116 static Term::Event getEventBlocking();
117
118private:
119 static void read_event();
120 static void read_raw();
121#if defined(_WIN32)
122 static void read_windows_key(const std::uint16_t& virtual_key_code, const std::uint32_t& control_key_state, const std::size_t& occurrence);
123#endif
124 static void init_thread();
125 static std::thread m_thread;
126 static Term::Private::BlockingQueue m_events;
127 static int m_poll; // for linux
128};
129
130} // namespace Private
131
132} // namespace Term
Term::Event read_event()
Definition input.cpp:338

The documentation for this class was generated from the following files: