Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qfbvthandler.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qfbvthandler_p.h"
5#include <QtCore/QSocketNotifier>
6#include <QtCore/private/qglobal_p.h>
7
8#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && (QT_CONFIG(evdev) || QT_CONFIG(libinput))
9
10#define VTH_ENABLED
11
12#include <private/qcore_unix_p.h>
13#include <unistd.h>
14#include <signal.h>
15#include <errno.h>
16#include <fcntl.h>
17#include <sys/ioctl.h>
18#include <linux/kd.h>
19
20#ifndef KDSKBMUTE
21#define KDSKBMUTE 0x4B51
22#endif
23
24#ifdef K_OFF
25#define KBD_OFF_MODE K_OFF
26#else
27#define KBD_OFF_MODE K_RAW
28#endif
29
30#endif
31
33
34#ifdef VTH_ENABLED
35static void setTTYCursor(bool enable)
36{
37 static bool ignore = qEnvironmentVariableIntValue("QT_QPA_PRESERVE_CONSOLE_STATE");
38 if (ignore)
39 return;
40
41 const char * const devs[] = { "/dev/tty0", "/dev/tty", "/dev/console", 0 };
42 int fd = -1;
43 for (const char * const *dev = devs; *dev; ++dev) {
44 fd = QT_OPEN(*dev, O_RDWR);
45 if (fd != -1) {
46 // Enable/disable screen blanking and the blinking cursor.
47 const char *termctl = enable ? "\033[9;15]\033[?33h\033[?25h\033[?0c" : "\033[9;0]\033[?33l\033[?25l\033[?1c";
48 QT_WRITE(fd, termctl, strlen(termctl) + 1);
49 QT_CLOSE(fd);
50 return;
51 }
52 }
53}
54#endif
55
56#ifdef VTH_ENABLED
57static QFbVtHandler *vth;
58
59void QFbVtHandler::signalHandler(int sigNo)
60{
61 char a = sigNo;
62 QT_WRITE(vth->m_sigFd[0], &a, sizeof(a));
63}
64#endif
65
67 : QObject(parent),
68 m_tty(-1),
69 m_signalNotifier(0)
70{
71#ifdef VTH_ENABLED
72 if (isatty(0))
73 m_tty = 0;
74
75 if (::socketpair(AF_UNIX, SOCK_STREAM, 0, m_sigFd)) {
76 qErrnoWarning(errno, "QFbVtHandler: socketpair() failed");
77 return;
78 }
79
80 vth = this;
81 setTTYCursor(false);
82 setKeyboardEnabled(false);
83
84 m_signalNotifier = new QSocketNotifier(m_sigFd[1], QSocketNotifier::Read, this);
85 connect(m_signalNotifier, &QSocketNotifier::activated, this, &QFbVtHandler::handleSignal);
86
87 if (!qEnvironmentVariableIntValue("QT_QPA_NO_SIGNAL_HANDLER")) {
88 struct sigaction sa;
89 sa.sa_flags = 0;
90 sa.sa_handler = signalHandler;
91 sigemptyset(&sa.sa_mask);
92 sigaction(SIGINT, &sa, 0); // Ctrl+C
93 sigaction(SIGTSTP, &sa, 0); // Ctrl+Z
94 sigaction(SIGCONT, &sa, 0);
95 sigaction(SIGTERM, &sa, 0); // default signal used by kill
96 }
97#endif
98}
99
101{
102#ifdef VTH_ENABLED
103 setKeyboardEnabled(true);
104 setTTYCursor(true);
105
106 if (m_signalNotifier) {
107 close(m_sigFd[0]);
108 close(m_sigFd[1]);
109 }
110#endif
111}
112
113void QFbVtHandler::setKeyboardEnabled(bool enable)
114{
115#ifdef VTH_ENABLED
116 if (m_tty == -1)
117 return;
118
119 if (enable) {
120 ::ioctl(m_tty, KDSKBMUTE, 0);
121 ::ioctl(m_tty, KDSKBMODE, m_oldKbdMode);
122 } else {
123 ::ioctl(m_tty, KDGKBMODE, &m_oldKbdMode);
124 if (!qEnvironmentVariableIntValue("QT_QPA_ENABLE_TERMINAL_KEYBOARD")) {
125 ::ioctl(m_tty, KDSKBMUTE, 1);
126 ::ioctl(m_tty, KDSKBMODE, KBD_OFF_MODE);
127 }
128 }
129#else
131#endif
132}
133
134void QFbVtHandler::handleSignal()
135{
136#ifdef VTH_ENABLED
137 m_signalNotifier->setEnabled(false);
138
139 char sigNo;
140 if (QT_READ(m_sigFd[1], &sigNo, sizeof(sigNo)) == sizeof(sigNo)) {
141 switch (sigNo) {
142 case SIGINT:
143 case SIGTERM:
144 handleInt();
145 break;
146 case SIGTSTP:
148 setKeyboardEnabled(true);
149 setTTYCursor(true);
150 ::kill(getpid(), SIGSTOP);
151 break;
152 case SIGCONT:
153 setTTYCursor(false);
154 setKeyboardEnabled(false);
155 emit resumed();
156 break;
157 default:
158 break;
159 }
160 }
161
162 m_signalNotifier->setEnabled(true);
163#endif
164}
165
166void QFbVtHandler::handleInt()
167{
168#ifdef VTH_ENABLED
170 setKeyboardEnabled(true);
171 setTTYCursor(true);
172 _exit(1);
173#endif
174}
175
177
178#include "moc_qfbvthandler_p.cpp"
void interrupted()
QFbVtHandler(QObject *parent=nullptr)
void resumed()
void aboutToSuspend()
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtCore
void activated(QSocketDescriptor socket, QSocketNotifier::Type activationEvent, QPrivateSignal)
void setEnabled(bool)
If enable is true, the notifier is enabled; otherwise the notifier is disabled.
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
#define QT_READ
#define QT_OPEN
#define QT_CLOSE
#define QT_WRITE
GLboolean GLboolean GLboolean GLboolean a
[7]
GLboolean enable
GLuint64 GLenum GLint fd
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define emit
#define Q_UNUSED(x)