Skip to content

Commit 12db80a

Browse files
committed
GPU Display: Correctly handle special cars pressed in the console window
1 parent 6c73580 commit 12db80a

7 files changed

Lines changed: 132 additions & 8 deletions

File tree

‎GPU/GPUTracking/Global/GPUChainTracking.cxx‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -860,10 +860,13 @@ int32_t GPUChainTracking::RunChainFinalize()
860860
usleep(10000);
861861
if (GetProcessingSettings().runsStandalone) {
862862
iKey = kbhit() ? getch() : 0;
863-
if (iKey == 27 && kbhit()) { // Escape sequence (arrow keys, ...), not the ESC key
864-
while (kbhit()) {
865-
getch();
863+
if (iKey == 27 && kbhit()) { // Escape sequence (arrow keys, ...), not the ESC key: the display translates up to 8 characters after the ESC
864+
uint64_t extendedKey = 0;
865+
for (uint32_t i = 0; kbhit(); i++) {
866+
const int32_t c = getch();
867+
extendedKey |= i < 8 ? (uint64_t)(uint8_t)c << (8 * i) : 0;
866868
}
869+
GetProcessingSettings().eventDisplay->sendExternalGUIKey(0, 1, extendedKey);
867870
iKey = 0;
868871
}
869872
if (iKey == 27) {

‎GPU/GPUTracking/display/CMakeLists.txt‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ set(SRCS_NO_H helpers/GPUDisplayLoader.cxx
130130
helpers/GPUDisplayInterpolation.cxx
131131
helpers/GPUDisplayROOT.cxx
132132
frontend/GPUDisplayHelp.cxx
133-
frontend/GPUDisplayFrontendConfig.cxx)
133+
frontend/GPUDisplayFrontendConfig.cxx
134+
frontend/GPUDisplayFrontendKeyTranslation.cxx)
134135

135136
set(HDRS_INSTALL helpers/GPUDisplayMagneticFieldConstants.h frontend/GPUDisplayFrontendKeys.h frontend/GPUDisplayFrontendKeyVars.h GPUDisplayControl.h GPUDisplayTypes.h)
136137

‎GPU/GPUTracking/display/GPUDisplayInterface.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class GPUDisplayFrontendInterface
5959
virtual void StopDisplay() = 0;
6060
virtual int32_t getDisplayControl() const = 0;
6161
virtual void setDisplayControl(int32_t v) = 0;
62-
virtual void sendExternalGUIKey(int32_t v) = 0;
62+
virtual void sendExternalGUIKey(int32_t v, uint32_t translationMode = 0, uint64_t extendedKey = 0) = 0; // translationMode != 0: key from extendedKey (1 = console escape sequence, up to 8 characters after the ESC)
6363
virtual const char* frontendName() const = 0;
6464

6565
protected:

‎GPU/GPUTracking/display/frontend/GPUDisplayFrontend.cxx‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,11 @@ void GPUDisplayFrontend::HandleExternalGUISignals()
160160
}
161161
}
162162

163-
void GPUDisplayFrontend::sendExternalGUIKey(int32_t v)
163+
void GPUDisplayFrontend::sendExternalGUIKey(int32_t v, uint32_t translationMode, uint64_t extendedKey)
164164
{
165+
if (translationMode && (v = translateExternalKey(translationMode, extendedKey)) < 0) {
166+
return;
167+
}
165168
{
166169
std::lock_guard lock(mExternalGUIKeyMutex);
167170
mExternalGUIKeys.emplace_back(v);

‎GPU/GPUTracking/display/frontend/GPUDisplayFrontend.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class GPUDisplayFrontend : public GPUDisplayFrontendInterface, public GPUDisplay
7373

7474
int32_t getDisplayControl() const override;
7575
void setDisplayControl(int32_t v) override;
76-
void sendExternalGUIKey(int32_t v) override;
76+
void sendExternalGUIKey(int32_t v, uint32_t translationMode = 0, uint64_t extendedKey = 0) override;
7777

7878
frontendTypes frontendType() const { return mFrontendType; }
7979
const char* frontendName() const override { return mFrontendName; }
@@ -153,7 +153,8 @@ class GPUDisplayFrontend : public GPUDisplayFrontendInterface, public GPUDisplay
153153
std::unique_ptr<configRTTIInfo, void (*)(configRTTIInfo*)> mConfigRTTI{nullptr, nullptr}; // Deleter set in GPUDisplayFrontendConfig.cxx, the only place where configRTTIInfo is defined
154154

155155
void HandleExternalGUIKeys();
156-
bool mWindowFullScreen = false, mWindowMaximized = false; // Window state last requested or reported by the window system
156+
static int32_t translateExternalKey(uint32_t translationMode, uint64_t extendedKey); // Key code of an encoded key of sendExternalGUIKey (+ SPECIAL_KEYS_SHIFTED with SHIFT), -1 if unknown
157+
bool mWindowFullScreen = false, mWindowMaximized = false; // Window state last requested or reported by the window system
157158
template <typename... Args>
158159
void add_key_binding(Args&&... args); // KEY_LAMBDA(key, ...) entries, the help text, and optionally the keys to show in the help text, only used in GPUDisplayFrontendConfig.cxx
159160
template <typename... Args>

‎GPU/GPUTracking/display/frontend/GPUDisplayFrontendConfig.cxx‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ void GPUDisplay::HandleExternalGUIKey(int32_t key)
187187
// GPUError("key %d '%c'", key, (char) key);
188188

189189
bool shifted = key >= 'A' && key <= 'Z';
190+
if (key >= 256) { // Special key with SHIFT, from translateExternalKey
191+
shifted = true;
192+
key -= mFrontend->SPECIAL_KEYS_SHIFTED;
193+
}
190194
bool oldShift = mFrontend->mKeys[mFrontend->KEY_SHIFT];
191195
mFrontend->mKeys[mFrontend->KEY_SHIFT] = shifted;
192196
HandleKey(key);
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file GPUDisplayFrontendKeyTranslation.cxx
13+
/// \author David Rohr
14+
15+
#include "GPUDisplayFrontend.h"
16+
#include <utility>
17+
18+
using namespace o2::gpu;
19+
20+
static constexpr uint64_t encodeSequence(const char* s) // As encoded by the console: first character in the lowest byte
21+
{
22+
uint64_t retVal = 0;
23+
for (uint32_t i = 0; i < 8 && s[i]; i++) {
24+
retVal |= (uint64_t)(uint8_t)s[i] << (8 * i);
25+
}
26+
return retVal;
27+
}
28+
29+
int32_t GPUDisplayFrontend::translateExternalKey(uint32_t translationMode, uint64_t extendedKey)
30+
{
31+
if (translationMode == 1) {
32+
// Console escape sequences, characters after the ESC: VT100 / xterm, cursor keys also in application mode (O instead of [), F1 to F5 also of rxvt ([11~) and the Linux console ([[A), with SHIFT of xterm (;2) and rxvt ([a, $)
33+
static constexpr std::pair<const char*, int32_t> sequences[] = {
34+
{"[A", KEY_UP},
35+
{"[B", KEY_DOWN},
36+
{"[C", KEY_RIGHT},
37+
{"[D", KEY_LEFT},
38+
{"OA", KEY_UP},
39+
{"OB", KEY_DOWN},
40+
{"OC", KEY_RIGHT},
41+
{"OD", KEY_LEFT},
42+
{"[H", KEY_HOME},
43+
{"[F", KEY_END},
44+
{"OH", KEY_HOME},
45+
{"OF", KEY_END},
46+
{"[1~", KEY_HOME},
47+
{"[4~", KEY_END},
48+
{"[7~", KEY_HOME},
49+
{"[8~", KEY_END},
50+
{"[2~", KEY_INSERT},
51+
{"[5~", KEY_PAGEUP},
52+
{"[6~", KEY_PAGEDOWN},
53+
{"OP", KEY_F1},
54+
{"OQ", KEY_F2},
55+
{"OR", KEY_F3},
56+
{"OS", KEY_F4},
57+
{"[11~", KEY_F1},
58+
{"[12~", KEY_F2},
59+
{"[13~", KEY_F3},
60+
{"[14~", KEY_F4},
61+
{"[[A", KEY_F1},
62+
{"[[B", KEY_F2},
63+
{"[[C", KEY_F3},
64+
{"[[D", KEY_F4},
65+
{"[[E", KEY_F5},
66+
{"[15~", KEY_F5},
67+
{"[17~", KEY_F6},
68+
{"[18~", KEY_F7},
69+
{"[19~", KEY_F8},
70+
{"[20~", KEY_F9},
71+
{"[21~", KEY_F10},
72+
{"[23~", KEY_F11},
73+
{"[24~", KEY_F12},
74+
{"[1;2A", KEY_UP + SPECIAL_KEYS_SHIFTED},
75+
{"[1;2B", KEY_DOWN + SPECIAL_KEYS_SHIFTED},
76+
{"[1;2C", KEY_RIGHT + SPECIAL_KEYS_SHIFTED},
77+
{"[1;2D", KEY_LEFT + SPECIAL_KEYS_SHIFTED},
78+
{"[1;2H", KEY_HOME + SPECIAL_KEYS_SHIFTED},
79+
{"[1;2F", KEY_END + SPECIAL_KEYS_SHIFTED},
80+
{"[2;2~", KEY_INSERT + SPECIAL_KEYS_SHIFTED},
81+
{"[5;2~", KEY_PAGEUP + SPECIAL_KEYS_SHIFTED},
82+
{"[6;2~", KEY_PAGEDOWN + SPECIAL_KEYS_SHIFTED},
83+
{"[a", KEY_UP + SPECIAL_KEYS_SHIFTED},
84+
{"[b", KEY_DOWN + SPECIAL_KEYS_SHIFTED},
85+
{"[c", KEY_RIGHT + SPECIAL_KEYS_SHIFTED},
86+
{"[d", KEY_LEFT + SPECIAL_KEYS_SHIFTED},
87+
{"[7$", KEY_HOME + SPECIAL_KEYS_SHIFTED},
88+
{"[8$", KEY_END + SPECIAL_KEYS_SHIFTED},
89+
{"[2$", KEY_INSERT + SPECIAL_KEYS_SHIFTED},
90+
{"[5$", KEY_PAGEUP + SPECIAL_KEYS_SHIFTED},
91+
{"[6$", KEY_PAGEDOWN + SPECIAL_KEYS_SHIFTED},
92+
{"[1;2P", KEY_F1 + SPECIAL_KEYS_SHIFTED},
93+
{"[1;2Q", KEY_F2 + SPECIAL_KEYS_SHIFTED},
94+
{"[1;2R", KEY_F3 + SPECIAL_KEYS_SHIFTED},
95+
{"[1;2S", KEY_F4 + SPECIAL_KEYS_SHIFTED},
96+
{"[15;2~", KEY_F5 + SPECIAL_KEYS_SHIFTED},
97+
{"[17;2~", KEY_F6 + SPECIAL_KEYS_SHIFTED},
98+
{"[18;2~", KEY_F7 + SPECIAL_KEYS_SHIFTED},
99+
{"[19;2~", KEY_F8 + SPECIAL_KEYS_SHIFTED},
100+
{"[20;2~", KEY_F9 + SPECIAL_KEYS_SHIFTED},
101+
{"[21;2~", KEY_F10 + SPECIAL_KEYS_SHIFTED},
102+
{"[23;2~", KEY_F11 + SPECIAL_KEYS_SHIFTED},
103+
{"[24;2~", KEY_F12 + SPECIAL_KEYS_SHIFTED},
104+
};
105+
for (const auto& [sequence, key] : sequences) {
106+
if (encodeSequence(sequence) == extendedKey) {
107+
return key;
108+
}
109+
}
110+
}
111+
return -1;
112+
}

0 commit comments

Comments
 (0)