Add a UnixSignalHandler class. It emits a Qt signal when a Unix signal is
handled. Use the UnixSignalHandler to detect terminal resizing. The client doesn't do anything with the terminal size yet. It should send the size to the server.
This commit is contained in:
parent
af5a742e57
commit
b491fd6378
@ -14,7 +14,9 @@ CONFIG -= app_bundle
|
||||
TEMPLATE = app
|
||||
|
||||
SOURCES += main.cc \
|
||||
UnixClient.cc
|
||||
UnixClient.cc \
|
||||
UnixSignalHandler.cc
|
||||
|
||||
HEADERS += \
|
||||
UnixClient.h
|
||||
UnixClient.h \
|
||||
UnixSignalHandler.h
|
||||
|
@ -1,9 +1,12 @@
|
||||
#include "UnixClient.h"
|
||||
#include "UnixSignalHandler.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <QSocketNotifier>
|
||||
#include <QCoreApplication>
|
||||
#include <QTcpSocket>
|
||||
@ -28,6 +31,11 @@ UnixClient::UnixClient(QTcpSocket *socket, QObject *parent) :
|
||||
connect(socket, SIGNAL(readyRead()), SLOT(socketReadyRead()));
|
||||
connect(socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten()));
|
||||
connect(socket, SIGNAL(disconnected()), SLOT(socketDisconnected()));
|
||||
|
||||
// Detect terminal resizing.
|
||||
UnixSignalHandler *ush = new UnixSignalHandler(SIGWINCH, this);
|
||||
connect(ush, SIGNAL(signaled(int)), SLOT(terminalResized()));
|
||||
terminalResized();
|
||||
}
|
||||
|
||||
UnixClient::~UnixClient()
|
||||
@ -72,6 +80,14 @@ void UnixClient::restoreTerminalMode(termios original)
|
||||
qFatal("error restoring terminal mode");
|
||||
}
|
||||
|
||||
void UnixClient::terminalResized()
|
||||
{
|
||||
winsize sz;
|
||||
ioctl(STDIN_FILENO, TIOCGWINSZ, &sz);
|
||||
//printf("%d %d\r\n", sz.ws_col, sz.ws_row);
|
||||
// TODO: Notify the server that the terminal has resized.
|
||||
}
|
||||
|
||||
void UnixClient::socketDisconnected()
|
||||
{
|
||||
printf("Connection terminated\r\n");
|
||||
|
@ -22,6 +22,7 @@ private:
|
||||
signals:
|
||||
|
||||
private slots:
|
||||
void terminalResized();
|
||||
void socketDisconnected();
|
||||
void terminalReadActivated();
|
||||
void socketBytesWritten();
|
||||
|
68
TestNetClient/UnixSignalHandler.cc
Normal file
68
TestNetClient/UnixSignalHandler.cc
Normal file
@ -0,0 +1,68 @@
|
||||
// Handles Unix signals in a Qt program.
|
||||
//
|
||||
|
||||
// TODO: Are Qt programs automatically multi-threaded? I don't think they
|
||||
// are... I wonder if this code works OK in a multi-threaded program.
|
||||
|
||||
#include "UnixSignalHandler.h"
|
||||
#include <QSocketNotifier>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
UnixSignalHandler *UnixSignalHandler::handlers[_NSIG];
|
||||
|
||||
UnixSignalHandler::UnixSignalHandler(int signum, QObject *parent) :
|
||||
QObject(parent), m_signum(signum)
|
||||
{
|
||||
Q_ASSERT(m_signum < _NSIG);
|
||||
|
||||
if (handlers[m_signum] != NULL)
|
||||
qFatal("Signal handler for signal %d is already registered.", m_signum);
|
||||
handlers[m_signum] = this;
|
||||
|
||||
int pipeFd[2];
|
||||
if (pipe2(pipeFd, O_NONBLOCK | O_CLOEXEC) != 0)
|
||||
qFatal("Could not create signal %d pipe", m_signum);
|
||||
m_pipeReadFd = pipeFd[0];
|
||||
m_pipeWriteFd = pipeFd[1];
|
||||
m_sn = new QSocketNotifier(m_pipeReadFd, QSocketNotifier::Read, this);
|
||||
connect(m_sn, SIGNAL(activated(int)), SLOT(pipeReadActivated()));
|
||||
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = UnixSignalHandler::signalHandler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags |= SA_RESTART;
|
||||
|
||||
if (sigaction(m_signum, &sa, &m_oldsa) != 0)
|
||||
qFatal("sigaction for signal %d failed", m_signum);
|
||||
}
|
||||
|
||||
UnixSignalHandler::~UnixSignalHandler()
|
||||
{
|
||||
sigaction(m_signum, &m_oldsa, NULL);
|
||||
// TODO: If there is data on the pipe, maybe we could emit the Qt signal
|
||||
// here.
|
||||
close(m_pipeReadFd);
|
||||
close(m_pipeWriteFd);
|
||||
handlers[m_signum] = NULL;
|
||||
}
|
||||
|
||||
void UnixSignalHandler::pipeReadActivated()
|
||||
{
|
||||
m_sn->setEnabled(false);
|
||||
char dummy;
|
||||
read(m_pipeReadFd, &dummy, 1);
|
||||
emit signaled(m_signum);
|
||||
m_sn->setEnabled(true);
|
||||
}
|
||||
|
||||
void UnixSignalHandler::signalHandler(int signum)
|
||||
{
|
||||
if (handlers[signum] != 0) {
|
||||
char dummy = 0;
|
||||
write(handlers[signum]->m_pipeWriteFd, &dummy, 1);
|
||||
}
|
||||
}
|
35
TestNetClient/UnixSignalHandler.h
Normal file
35
TestNetClient/UnixSignalHandler.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef UNIXSIGNALHANDLER_H
|
||||
#define UNIXSIGNALHANDLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <signal.h>
|
||||
|
||||
class QSocketNotifier;
|
||||
|
||||
class UnixSignalHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit UnixSignalHandler(int signum, QObject *parent = 0);
|
||||
~UnixSignalHandler();
|
||||
|
||||
signals:
|
||||
void signaled(int signum);
|
||||
|
||||
public slots:
|
||||
|
||||
private slots:
|
||||
void pipeReadActivated();
|
||||
|
||||
private:
|
||||
static void signalHandler(int signum);
|
||||
|
||||
static UnixSignalHandler *handlers[_NSIG];
|
||||
QSocketNotifier *m_sn;
|
||||
int m_signum;
|
||||
int m_pipeReadFd;
|
||||
int m_pipeWriteFd;
|
||||
struct sigaction m_oldsa;
|
||||
};
|
||||
|
||||
#endif // UNIXSIGNALHANDLER_H
|
Loading…
Reference in New Issue
Block a user