Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 98 additions & 4 deletions lib/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ Session::Session(QObject* parent) :

connect( _shellProcess,SIGNAL(receivedData(const char *,int)),this,
SLOT(onReceiveBlock(const char *,int)) );
connect( _emulation,SIGNAL(sendData(const char *,int)),_shellProcess,
SLOT(sendData(const char *,int)) );
connect( _emulation,SIGNAL(sendData(const char *,int)),this,
SLOT(sendToShellProcess(const char *,int)) );
connect( _emulation,SIGNAL(lockPtyRequest(bool)),_shellProcess,SLOT(lockPty(bool)) );
connect( _emulation,SIGNAL(useUtf8Request(bool)),_shellProcess,SLOT(setUtf8Mode(bool)) );

Expand All @@ -124,6 +124,15 @@ Session::Session(QObject* parent) :
_monitorTimer = new QTimer(this);
_monitorTimer->setSingleShot(true);
connect(_monitorTimer, SIGNAL(timeout()), this, SLOT(monitorTimerDone()));

//setup baud rate throttle timers
_outputThrottleTimer = new QTimer(this);
_outputThrottleTimer->setSingleShot(true);
connect(_outputThrottleTimer, &QTimer::timeout, this, &Session::_flushOutputBuffer);

_inputThrottleTimer = new QTimer(this);
_inputThrottleTimer->setSingleShot(true);
connect(_inputThrottleTimer, &QTimer::timeout, this, &Session::_flushInputBuffer);
}

WId Session::windowId() const
Expand Down Expand Up @@ -942,8 +951,93 @@ void Session::zmodemFinished()
*/
void Session::onReceiveBlock( const char * buf, int len )
{
_emulation->receiveData( buf, len );
emit receivedData( QString::fromLatin1( buf, len ) );
if (_baudIsOff() || !_baudAffectsDisplay()) {
_emulation->receiveData( buf, len );
emit receivedData( QString::fromLatin1( buf, len ) );
return;
}
_outputBuffer.append(buf, len);
if (!_outputThrottleTimer->isActive())
_outputThrottleTimer->start(_baudCharIntervalMs());
}

void Session::_flushOutputBuffer()
{
if (_outputBuffer.isEmpty()) return;
const char ch = _outputBuffer.at(0);
_outputBuffer.remove(0, 1);
_emulation->receiveData(&ch, 1);
emit receivedData(QString::fromLatin1(&ch, 1));
if (!_outputBuffer.isEmpty())
_outputThrottleTimer->start(_baudCharIntervalMs());
}

void Session::sendToShellProcess( const char * data, int len )
{
if (_baudIsOff() || !_baudAffectsInput() || !_baudIsAuthentic()) {
_shellProcess->sendData( data, len );
return;
}
_inputBuffer.append(data, len);
if (!_inputThrottleTimer->isActive())
_inputThrottleTimer->start(_baudCharIntervalMs());
}

void Session::_flushInputBuffer()
{
if (_inputBuffer.isEmpty()) return;
const char ch = _inputBuffer.at(0);
_inputBuffer.remove(0, 1);
_shellProcess->sendData(&ch, 1);
if (!_inputBuffer.isEmpty())
_inputThrottleTimer->start(_baudCharIntervalMs());
}

bool Session::_baudAffectsDisplay() const
{
return _baudRateMode.startsWith(QLatin1String("display-")) || _baudRateMode.startsWith(QLatin1String("both-"));
}
bool Session::_baudAffectsInput() const
{
return _baudRateMode.startsWith(QLatin1String("input-")) || _baudRateMode.startsWith(QLatin1String("both-"));
}
bool Session::_baudIsAuthentic() const
{
return _baudRateMode.endsWith(QLatin1String("-authentic"));
}
bool Session::_baudIsOff() const
{
return _baudRateMode == QLatin1String("off") || _baudRate <= 0;
}
int Session::_baudCharIntervalMs() const
{
return qMax(1, 8000 / _baudRate);
}

void Session::setBaudRate(int bps)
{
if (_baudRate == bps) return;
_baudRate = bps;
emit baudRateChanged(bps);
}

void Session::setBaudRateMode(const QString &mode)
{
if (_baudRateMode == mode) return;
_baudRateMode = mode;
if (_baudIsOff()) {
// Drain buffers immediately when throttling is disabled
if (!_outputBuffer.isEmpty()) {
_emulation->receiveData(_outputBuffer.constData(), _outputBuffer.size());
emit receivedData(QString::fromLatin1(_outputBuffer));
_outputBuffer.clear();
}
if (!_inputBuffer.isEmpty()) {
_shellProcess->sendData(_inputBuffer.constData(), _inputBuffer.size());
_inputBuffer.clear();
}
}
emit baudRateModeChanged(mode);
}

QSize Session::size()
Expand Down
36 changes: 35 additions & 1 deletion lib/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
#ifndef SESSION_H
#define SESSION_H

#include <QByteArray>
#include <QProcess>
#include <QStringList>
#include <QTimer>

#include "Emulation.h"
#include "History.h"
Expand Down Expand Up @@ -60,6 +62,8 @@ class Session : public QObject {
Q_PROPERTY(int processId READ processId)
Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings)
Q_PROPERTY(QSize size READ size WRITE setSize)
Q_PROPERTY(int baudRate READ baudRate WRITE setBaudRate NOTIFY baudRateChanged)
Q_PROPERTY(QString baudRateMode READ baudRateMode WRITE setBaudRateMode NOTIFY baudRateModeChanged)

/**
* Constructs a new session.
Expand Down Expand Up @@ -365,6 +369,12 @@ class Session : public QObject {
*/
bool hasDarkBackground() const;

// Baud rate emulation
int baudRate() const { return _baudRate; }
void setBaudRate(int bps);
QString baudRateMode() const { return _baudRateMode; }
void setBaudRateMode(const QString &mode);

/**
* Attempts to get the shell program to redraw the current display area.
* This can be used after clearing the screen, for example, to get the
Expand Down Expand Up @@ -428,6 +438,9 @@ public slots:
*/
void receivedData( const QString & text );

void baudRateChanged(int newRate);
void baudRateModeChanged(const QString &newMode);

/** Emitted when the session's title has changed. */
void titleChanged();

Expand Down Expand Up @@ -501,7 +514,6 @@ private slots:

// void fireZModemDetected();

void onReceiveBlock( const char * buffer, int len );
void monitorTimerDone();

void onViewSizeChange(int height, int width);
Expand All @@ -512,6 +524,14 @@ private slots:
//automatically detach views from sessions when view is destroyed
void viewDestroyed(QObject * view);

protected slots:
void onReceiveBlock( const char * buffer, int len );
void sendToShellProcess( const char * data, int len );

private slots:
void _flushOutputBuffer();
void _flushInputBuffer();

// void zmodemReadStatus();
// void zmodemReadAndSendBlock();
// void zmodemRcvBlock(const char *data, int len);
Expand Down Expand Up @@ -575,6 +595,20 @@ private slots:

bool _hasDarkBackground;

// Baud rate throttling
int _baudRate = 0;
QString _baudRateMode = QStringLiteral("off");
QByteArray _outputBuffer;
QByteArray _inputBuffer;
QTimer *_outputThrottleTimer = nullptr;
QTimer *_inputThrottleTimer = nullptr;

bool _baudAffectsDisplay() const;
bool _baudAffectsInput() const;
bool _baudIsAuthentic() const;
bool _baudIsOff() const;
int _baudCharIntervalMs() const;

ProcessInfo *_foregroundProcessInfo;
int _foregroundPid;
static int lastSessionId;
Expand Down
22 changes: 22 additions & 0 deletions lib/ksession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ KSession::KSession(QObject *parent) :
connect(m_session, SIGNAL(started()), this, SIGNAL(started()));
connect(m_session, SIGNAL(finished()), this, SLOT(sessionFinished()));
connect(m_session, SIGNAL(titleChanged()), this, SIGNAL(titleChanged()));
connect(m_session, SIGNAL(baudRateChanged(int)), this, SIGNAL(baudRateChanged(int)));
connect(m_session, SIGNAL(baudRateModeChanged(QString)), this, SIGNAL(baudRateModeChanged(QString)));
}

KSession::~KSession()
Expand Down Expand Up @@ -242,6 +244,26 @@ QString KSession::getHistory() const
return history;
}

int KSession::getBaudRate() const
{
return m_session->baudRate();
}

void KSession::setBaudRate(int bps)
{
m_session->setBaudRate(bps);
}

QString KSession::getBaudRateMode() const
{
return m_session->baudRateMode();
}

void KSession::setBaudRateMode(const QString &mode)
{
m_session->setBaudRateMode(mode);
}

void KSession::sendText(QString text)
{
m_session->sendText(text);
Expand Down
14 changes: 11 additions & 3 deletions lib/ksession.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

namespace Konsole {
class TerminalDisplay;
class Session;
}

class KSession : public QObject
Expand All @@ -45,6 +44,8 @@ class KSession : public QObject
Q_PROPERTY(bool hasActiveProcess READ hasActiveProcess)
Q_PROPERTY(QString foregroundProcessName READ foregroundProcessName)
Q_PROPERTY(QString currentDir READ currentDir)
Q_PROPERTY(int baudRate READ getBaudRate WRITE setBaudRate NOTIFY baudRateChanged)
Q_PROPERTY(QString baudRateMode READ getBaudRateMode WRITE setBaudRateMode NOTIFY baudRateModeChanged)

public:
KSession(QObject *parent = 0);
Expand Down Expand Up @@ -76,6 +77,12 @@ class KSession : public QObject

QString getHistory() const;

// Baud rate emulation
int getBaudRate() const;
void setBaudRate(int bps);
QString getBaudRateMode() const;
void setBaudRateMode(const QString &mode);

// Sets whether flow control is enabled
void setFlowControlEnabled(bool enabled);

Expand Down Expand Up @@ -134,6 +141,9 @@ class KSession : public QObject
void matchFound(int startColumn, int startLine, int endColumn, int endLine);
void noMatchFound();

void baudRateChanged(int newRate);
void baudRateModeChanged(const QString &newMode);

public slots:
/*! Set named key binding for given widget
*/
Expand Down Expand Up @@ -169,10 +179,8 @@ protected slots:

private slots:
Konsole::Session* createSession(QString name);
//Konsole::KTerminalDisplay* createTerminalDisplay(Konsole::Session *session, QQuickItem* parent);

private:
//Konsole::KTerminalDisplay *m_terminalDisplay;
QString _initialWorkingDirectory;
QString m_shellProgram;
QStringList m_shellArgs;
Expand Down