Skip to content

Commit 98cc172

Browse files
committed
TTYX: introduce TTY/XI mode to better distinguish key events (fix #1140 touch #1126)
1 parent c3db819 commit 98cc172

10 files changed

+278
-123
lines changed

Diff for: WinPort/src/Backend/TTY/TTYBackend.cpp

+63-7
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,48 @@ static TTYBackend * g_vtb = nullptr;
3333

3434
static void OnSigHup(int signo);
3535

36+
static bool IsEnhancedKey(WORD code)
37+
{
38+
return (code==VK_LEFT || code==VK_RIGHT || code==VK_UP || code==VK_DOWN
39+
|| code==VK_HOME || code==VK_END || code==VK_NEXT || code==VK_PRIOR );
40+
}
41+
42+
static WORD WChar2WinVKeyCode(WCHAR wc)
43+
{
44+
if ((wc >= L'0' && wc <= L'9') || (wc >= L'A' && wc <= L'Z')) {
45+
return (WORD)wc;
46+
}
47+
if (wc >= L'a' && wc <= L'z') {
48+
return (WORD)wc - (L'a' - L'A');
49+
}
50+
switch (wc) {
51+
case L' ': return VK_SPACE;
52+
case L'.': return VK_OEM_PERIOD;
53+
case L',': return VK_OEM_COMMA;
54+
case L'_': case L'-': return VK_OEM_MINUS;
55+
case L'+': return VK_OEM_PLUS;
56+
case L';': case L':': return VK_OEM_1;
57+
case L'/': case L'?': return VK_OEM_2;
58+
case L'~': case L'`': return VK_OEM_3;
59+
case L'[': case L'{': return VK_OEM_4;
60+
case L'\\': case L'|': return VK_OEM_5;
61+
case L']': case '}': return VK_OEM_6;
62+
case L'\'': case '\"': return VK_OEM_7;
63+
case L'!': return '1';
64+
case L'@': return '2';
65+
case L'#': return '3';
66+
case L'$': return '4';
67+
case L'%': return '5';
68+
case L'^': return '6';
69+
case L'&': return '7';
70+
case L'*': return '8';
71+
case L'(': return '9';
72+
case L')': return '0';
73+
}
74+
fprintf(stderr, "%s: not translated %u '%lc'\n", __FUNCTION__, (unsigned int)wc, wc);
75+
return VK_UNASSIGNED;
76+
}
77+
3678

3779
TTYBackend::TTYBackend(const char *full_exe_path, int std_in, int std_out, bool far2l_tty, unsigned int esc_expiration, int notify_pipe, int *result) :
3880
_full_exe_path(full_exe_path),
@@ -685,6 +727,26 @@ static void OnFar2lMouse(bool compact, StackSerializer &stk_ser)
685727
}
686728
}
687729

730+
void TTYBackend::OnInspectKeyEvent(KEY_EVENT_RECORD &event)
731+
{
732+
if (_ttyx) {
733+
_ttyx->InspectKeyEvent(event);
734+
735+
} else {
736+
event.dwControlKeyState|= QueryControlKeys();
737+
}
738+
if (!event.wVirtualKeyCode) {
739+
if (event.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED | LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
740+
event.wVirtualKeyCode = WChar2WinVKeyCode(event.uChar.UnicodeChar);
741+
} else {
742+
event.wVirtualKeyCode = VK_UNASSIGNED;
743+
}
744+
}
745+
if (!event.uChar.UnicodeChar && IsEnhancedKey(event.wVirtualKeyCode)) {
746+
event.dwControlKeyState|= ENHANCED_KEY;
747+
}
748+
}
749+
688750
void TTYBackend::OnFar2lEvent(StackSerializer &stk_ser)
689751
{
690752
if (!_far2l_tty) {
@@ -743,16 +805,10 @@ void TTYBackend::OnInputBroken()
743805
_far2l_interracts_sent.clear();
744806
}
745807

746-
DWORD TTYBackend::OnQueryControlKeys()
808+
DWORD TTYBackend::QueryControlKeys()
747809
{
748810
DWORD out = 0;
749811

750-
if (_ttyx) {
751-
out = _ttyx->GetModifiers();
752-
if (out != 0)
753-
return out;
754-
}
755-
756812
#ifdef __linux__
757813
unsigned char state = 6;
758814
/* #ifndef KG_SHIFT

Diff for: WinPort/src/Backend/TTY/TTYBackend.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,12 @@ class TTYBackend : IConsoleOutputBackend, ITTYInputSpecialSequenceHandler, IFar2
112112
virtual bool OnConsoleSetFKeyTitles(const char **titles);
113113

114114
// ITTYInputSpecialSequenceHandler
115+
virtual void OnInspectKeyEvent(KEY_EVENT_RECORD &event);
115116
virtual void OnFar2lEvent(StackSerializer &stk_ser);
116117
virtual void OnFar2lReply(StackSerializer &stk_ser);
117118
virtual void OnInputBroken();
118-
virtual DWORD OnQueryControlKeys();
119119

120+
DWORD QueryControlKeys();
120121

121122
public:
122123
TTYBackend(const char *full_exe_path, int std_in, int std_out, bool far2l_tty, unsigned int esc_expiration, int notify_pipe, int *result);

Diff for: WinPort/src/Backend/TTY/TTYInput.cpp

+2-44
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,6 @@
55
#include "WinPort.h"
66
#include <utils.h>
77

8-
static WORD WChar2WinVKeyCode(WCHAR wc)
9-
{
10-
if ((wc >= L'0' && wc <= L'9') || (wc >= L'A' && wc <= L'Z')) {
11-
return (WORD)wc;
12-
}
13-
if (wc >= L'a' && wc <= L'z') {
14-
return (WORD)wc - (L'a' - L'A');
15-
}
16-
switch (wc) {
17-
case L' ': return VK_SPACE;
18-
case L'.': return VK_OEM_PERIOD;
19-
case L',': return VK_OEM_COMMA;
20-
case L'_': case L'-': return VK_OEM_MINUS;
21-
case L'+': return VK_OEM_PLUS;
22-
case L';': case L':': return VK_OEM_1;
23-
case L'/': case L'?': return VK_OEM_2;
24-
case L'~': case L'`': return VK_OEM_3;
25-
case L'[': case L'{': return VK_OEM_4;
26-
case L'\\': case L'|': return VK_OEM_5;
27-
case L']': case '}': return VK_OEM_6;
28-
case L'\'': case '\"': return VK_OEM_7;
29-
case L'!': return '1';
30-
case L'@': return '2';
31-
case L'#': return '3';
32-
case L'$': return '4';
33-
case L'%': return '5';
34-
case L'^': return '6';
35-
case L'&': return '7';
36-
case L'*': return '8';
37-
case L'(': return '9';
38-
case L')': return '0';
39-
}
40-
fprintf(stderr, "%s: not translated %u '%lc'\n", __FUNCTION__, (unsigned int)wc, wc);
41-
return VK_UNASSIGNED;
42-
}
43-
448

459
TTYInput::TTYInput(ITTYInputSpecialSequenceHandler *handler) :
4610
_parser(handler), _handler(handler)
@@ -51,20 +15,14 @@ void TTYInput::PostCharEvent(wchar_t ch)
5115
{
5216
INPUT_RECORD ir = {};
5317
ir.EventType = KEY_EVENT;
18+
ir.Event.KeyEvent.bKeyDown = TRUE;
5419
ir.Event.KeyEvent.wRepeatCount = 1;
5520
ir.Event.KeyEvent.uChar.UnicodeChar = ch;
5621

5722
if (_handler) {
58-
ir.Event.KeyEvent.dwControlKeyState|= _handler->OnQueryControlKeys();
23+
_handler->OnInspectKeyEvent(ir.Event.KeyEvent);
5924
}
6025

61-
if (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED | LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
62-
ir.Event.KeyEvent.wVirtualKeyCode = WChar2WinVKeyCode(ch);
63-
} else {
64-
ir.Event.KeyEvent.wVirtualKeyCode = VK_UNASSIGNED;
65-
}
66-
67-
ir.Event.KeyEvent.bKeyDown = TRUE;
6826
g_winport_con_in->Enqueue(&ir, 1);
6927
ir.Event.KeyEvent.bKeyDown = FALSE;
7028
g_winport_con_in->Enqueue(&ir, 1);

Diff for: WinPort/src/Backend/TTY/TTYInputSequenceParser.cpp

+8-17
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,6 @@
1212
// http://www.manmrk.net/tutorials/ISPF/XE/xehelp/html/HID00000579.htm
1313
// http://www.leonerd.org.uk/hacks/fixterms/
1414

15-
static bool IsEnhancedKey(WORD code)
16-
{
17-
return (code==VK_LEFT || code==VK_RIGHT || code==VK_UP || code==VK_DOWN
18-
|| code==VK_HOME || code==VK_END || code==VK_NEXT || code==VK_PRIOR );
19-
}
20-
21-
22-
2315
#if 1 // change to 1 to enable self-contradiction check on startup
2416

2517
template <typename Last> static void AssertNoConflictsBetween(const Last &last) { }
@@ -285,9 +277,11 @@ size_t TTYInputSequenceParser::ParseNChars2Key(const char *s, size_t l)
285277
ir.EventType = KEY_EVENT;
286278
ir.Event.KeyEvent.wRepeatCount = 1;
287279
ir.Event.KeyEvent.uChar.UnicodeChar = wc;
288-
ir.Event.KeyEvent.wVirtualKeyCode = VK_OEM_PERIOD;
289280
ir.Event.KeyEvent.dwControlKeyState|= LEFT_ALT_PRESSED;
290281
ir.Event.KeyEvent.bKeyDown = TRUE;
282+
if (_handler) {
283+
_handler->OnInspectKeyEvent(ir.Event.KeyEvent);
284+
}
291285
_ir_pending.emplace_back(ir); // g_winport_con_in->Enqueue(&ir, 1);
292286
ir.Event.KeyEvent.bKeyDown = FALSE;
293287
_ir_pending.emplace_back(ir); // g_winport_con_in->Enqueue(&ir, 1);
@@ -461,21 +455,18 @@ void TTYInputSequenceParser::AddPendingKeyEvent(const TTYInputKey &k)
461455
{
462456
INPUT_RECORD ir = {};
463457
ir.EventType = KEY_EVENT;
458+
ir.Event.KeyEvent.bKeyDown = TRUE;
464459
ir.Event.KeyEvent.wRepeatCount = 1;
465460
// ir.Event.KeyEvent.uChar.UnicodeChar = i.second.unicode_char;
466-
if (k.vk == VK_SPACE)
467-
{
461+
if (k.vk == VK_SPACE) {
468462
ir.Event.KeyEvent.uChar.UnicodeChar = L' ';
469463
}
470464
ir.Event.KeyEvent.wVirtualKeyCode = k.vk;
471465
ir.Event.KeyEvent.dwControlKeyState = k.control_keys | _extra_control_keys;
472466
ir.Event.KeyEvent.wVirtualScanCode = WINPORT(MapVirtualKey)(k.vk,MAPVK_VK_TO_VSC);
473-
if (IsEnhancedKey(k.vk))
474-
ir.Event.KeyEvent.dwControlKeyState|= ENHANCED_KEY;
475-
if (_handler)
476-
ir.Event.KeyEvent.dwControlKeyState|= _handler->OnQueryControlKeys();
477-
478-
ir.Event.KeyEvent.bKeyDown = TRUE;
467+
if (_handler) {
468+
_handler->OnInspectKeyEvent(ir.Event.KeyEvent);
469+
}
479470
_ir_pending.emplace_back(ir); // g_winport_con_in->Enqueue(&ir, 1);
480471
ir.Event.KeyEvent.bKeyDown = FALSE;
481472
_ir_pending.emplace_back(ir); // g_winport_con_in->Enqueue(&ir, 1);

Diff for: WinPort/src/Backend/TTY/TTYInputSequenceParser.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ template <size_t N> using NChars2Key = NCharsMap<N, TTYInputKey>;
6464

6565
struct ITTYInputSpecialSequenceHandler
6666
{
67+
virtual void OnInspectKeyEvent(KEY_EVENT_RECORD &event) = 0;
6768
virtual void OnFar2lEvent(StackSerializer &stk_ser) = 0;
6869
virtual void OnFar2lReply(StackSerializer &stk_ser) = 0;
6970
virtual void OnInputBroken() = 0;
70-
virtual DWORD OnQueryControlKeys() = 0;
7171
};
7272

7373
#define TTY_PARSED_WANTMORE ((size_t)0)

Diff for: WinPort/src/Backend/TTY/TTYX/CMakeLists.txt

+26-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,33 @@ target_include_directories(far2l_ttyx PRIVATE ../../../..)
1212
target_include_directories(far2l_ttyx PRIVATE ../../../../../utils/include)
1313

1414
find_package(X11 REQUIRED)
15-
include_directories(${X11_INCLUDE_DIR})
15+
1616
link_directories(${X11_LIBRARIES})
17-
target_link_libraries(far2l_ttyx utils ${X11_LIBRARIES})
17+
18+
if (NOT DEFINED TTYXI)
19+
if(${X11_Xi_LIB} STREQUAL "")
20+
message(STATUS "Building without TTY backend XI support due to Xi library not found")
21+
else()
22+
set(TTYXI "YES")
23+
message(STATUS "Building with TTY backend XI support due to Xi library found at ${X11_Xi_LIB}")
24+
endif()
25+
# message(STATUS "Building without TTY backend XI support, configure with -DTTYXI=YES if you want it")
26+
27+
elseif(NOT TTYXI)
28+
message(STATUS "Building without TTY backend XI support due to TTYXI=${TTYXI}")
29+
elseif(${X11_Xi_LIB} STREQUAL "")
30+
message(FATAL_ERROR "${ColorRed}TTYXI requested but Xi lib not found, please install it or configure with -DTTYXI=NO.${ColorNormal}")
31+
endif()
32+
33+
if (TTYXI)
34+
include_directories(${X11_INCLUDE_DIR} ${X11_Xi_INCLUDE_PATH})
35+
target_link_libraries(far2l_ttyx utils ${X11_LIBRARIES} ${X11_Xi_LIB})
36+
target_compile_options(far2l_ttyx PUBLIC -DTTYXI)
37+
38+
else()
39+
include_directories(${X11_INCLUDE_DIR})
40+
target_link_libraries(far2l_ttyx utils ${X11_LIBRARIES})
41+
endif()
1842

1943
set_target_properties(far2l_ttyx PROPERTIES
2044
RUNTIME_OUTPUT_DIRECTORY "${INSTALL_DIR}"

0 commit comments

Comments
 (0)