Skip to content

Commit c5519c7

Browse files
committed
platform: Add support for keyboard modifiers in GPM events
1 parent 6cb4c85 commit c5519c7

File tree

3 files changed

+42
-16
lines changed

3 files changed

+42
-16
lines changed

include/tvision/internal/linuxcon.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ struct LinuxConsoleInput final : public EventSource
3030
bool getEvent(TEvent &ev) noexcept override;
3131
bool hasPendingEvents() noexcept override;
3232

33-
static ushort getKeyboardModifiers(StdioCtl &io) noexcept;
33+
ushort getKeyboardModifiers() noexcept;
34+
35+
static ushort convertLinuxKeyModifiers(ushort linuxShiftState) noexcept;
3436
};
3537

3638
class LinuxConsoleStrategy : public ConsoleStrategy

source/platform/gpminput.cpp

+11-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <internal/gpminput.h>
88
#include <internal/dispbuff.h>
99
#include <internal/linuxcon.h>
10+
#include <linux/keyboard.h>
1011
#include <stdlib.h>
1112
#include <gpm.h>
1213

@@ -20,11 +21,11 @@ GpmInput *GpmInput::create(DisplayBuffer &displayBuf) noexcept
2021
Gpm_Connect conn = {
2122
.eventMask = GPM_DOWN | GPM_UP | GPM_DRAG | GPM_MOVE,
2223
.defaultMask = 0, // Disable cursor drawing by the server.
23-
/* Disable mouse event reporting when keyboard modifiers are active.
24-
* In such case, GPM text selection and copy/paste will be active. */
24+
// Report keyboard modifiers except Shift, which terminal emulators
25+
// usually reserve for selecting text. Here GPM will do the same.
2526
.minMod = 0,
26-
.maxMod = 0 };
27-
// Because we only instantiate GPM in the Linux console, discard the
27+
.maxMod = (ushort) ~(1 << KG_SHIFT) };
28+
// Because we only instantiate GPM in the Linux console, unset the
2829
// TERM variable during Gpm_Open so that GPM won't assume it is being
2930
// ran under xterm (e.g. if TERM=xterm), and 'gpm_fd' won't be -2.
3031
char *term = newStr(getenv("TERM"));
@@ -82,6 +83,7 @@ bool GpmInput::getEvent(TEvent &ev) noexcept
8283
ev.what = evMouse;
8384
ev.mouse.where.x = gpmEvent.x;
8485
ev.mouse.where.y = gpmEvent.y;
86+
8587
for (const auto &flag : gpmButtonFlags)
8688
if (gpmEvent.buttons & flag.gpm)
8789
{
@@ -91,12 +93,17 @@ bool GpmInput::getEvent(TEvent &ev) noexcept
9193
buttonState &= ~flag.mb;
9294
}
9395
ev.mouse.buttons = buttonState;
96+
9497
if (gpmEvent.wdy)
9598
ev.mouse.wheel = gpmEvent.wdy > 0 ? mwUp : mwDown;
9699
else if (gpmEvent.wdx)
97100
ev.mouse.wheel = gpmEvent.wdx > 0 ? mwRight : mwLeft;
98101
else
99102
ev.mouse.wheel = 0;
103+
104+
ev.mouse.controlKeyState =
105+
LinuxConsoleInput::convertLinuxKeyModifiers(gpmEvent.modifiers);
106+
100107
return true;
101108
}
102109
return false;

source/platform/linuxcon.cpp

+28-11
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ bool LinuxConsoleInput::getEvent(TEvent &ev) noexcept
6262
if (input.getEvent(ev))
6363
{
6464
auto &keyCode = ev.keyDown.keyCode;
65-
ev.keyDown.controlKeyState = getKeyboardModifiers(io);
65+
ev.keyDown.controlKeyState = getKeyboardModifiers();
6666
// Prevent Ctrl+H/Ctrl+I/Ctrl+J/Ctrl+M from being interpreted as
6767
// Ctrl+Back/Ctrl+Tab/Ctrl+Enter.
6868
if (keyCode == kbBack || keyCode == kbTab || keyCode == kbEnter)
@@ -83,20 +83,37 @@ bool LinuxConsoleInput::hasPendingEvents() noexcept
8383
return input.hasPendingEvents();
8484
}
8585

86-
ushort LinuxConsoleInput::getKeyboardModifiers(StdioCtl &io) noexcept
86+
ushort LinuxConsoleInput::getKeyboardModifiers() noexcept
8787
{
8888
char res = 6;
89-
ulong actualModifiers = 0;
9089
if (ioctl(io.in(), TIOCLINUX, &res) != -1)
90+
return convertLinuxKeyModifiers(res);
91+
return 0;
92+
}
93+
94+
ushort LinuxConsoleInput::convertLinuxKeyModifiers(ushort linuxShiftState) noexcept
95+
{
96+
constexpr struct
9197
{
92-
if (res & (1 << KG_SHIFT))
93-
actualModifiers |= kbShift;
94-
if (res & (1 << KG_CTRL))
95-
actualModifiers |= kbLeftCtrl;
96-
if (res & (1 << KG_ALT))
97-
actualModifiers |= kbLeftAlt;
98-
}
99-
return actualModifiers;
98+
uchar kb;
99+
uchar tv;
100+
} linuxModifierFlags[] =
101+
{
102+
{1 << KG_SHIFT, kbShift},
103+
{1 << KG_CTRLL, kbLeftCtrl},
104+
{1 << KG_CTRLR, kbRightCtrl},
105+
{1 << KG_ALT, kbLeftAlt},
106+
{1 << KG_ALTGR, kbRightAlt},
107+
};
108+
109+
ushort modifiers = 0;
110+
for (const auto &flags : linuxModifierFlags)
111+
if (linuxShiftState & flags.kb)
112+
modifiers |= flags.tv;
113+
// It may be that KG_CTRL was detected, but not KG_CTRLL or KG_CTRLR.
114+
if ((linuxShiftState & (1 << KG_CTRL)) && !(modifiers & kbCtrlShift))
115+
modifiers |= kbLeftCtrl;
116+
return modifiers;
100117
}
101118

102119
} // namespace tvision

0 commit comments

Comments
 (0)