111 lines
2.8 KiB
C++
111 lines
2.8 KiB
C++
/*
|
|
Windows ConPTY-based Pty implementation using ptyqt.
|
|
Replaces the POSIX kpty/kptyprocess stack on Windows.
|
|
*/
|
|
|
|
#if defined(Q_OS_WIN)
|
|
|
|
#include "Pty.h"
|
|
#include <conptyprocess.h> // direct ConPTY backend — avoids WinPty dependency
|
|
#include <QtDebug>
|
|
|
|
using namespace Konsole;
|
|
|
|
Pty::Pty(QObject *parent) : QObject(parent) {}
|
|
|
|
Pty::Pty(int /*ptyMasterFd*/, QObject *parent) : QObject(parent) {}
|
|
|
|
Pty::~Pty()
|
|
{
|
|
if (_ptyProcess) {
|
|
_ptyProcess->stopProcess();
|
|
delete _ptyProcess;
|
|
}
|
|
}
|
|
|
|
int Pty::start(const QString &program,
|
|
const QStringList &arguments,
|
|
const QStringList &environment,
|
|
ulong /*winid*/,
|
|
bool /*addToUtmp*/)
|
|
{
|
|
_ptyProcess = new ConPtyProcess();
|
|
if (!ConPtyProcess::isAvailable()) {
|
|
qWarning() << "Pty: ConPTY not available on this Windows version (requires 10 build 1903+)";
|
|
delete _ptyProcess;
|
|
_ptyProcess = nullptr;
|
|
return -1;
|
|
}
|
|
|
|
connect(_ptyProcess, &IPtyProcess::readyRead, this, &Pty::onReadyRead);
|
|
connect(_ptyProcess, &IPtyProcess::finished, this, &Pty::onProcessFinished);
|
|
|
|
// arguments[0] is a duplicate of program (argv[0]); ptyqt takes args without it
|
|
QStringList args = arguments.size() > 1 ? arguments.mid(1) : QStringList{};
|
|
|
|
bool ok = _ptyProcess->startProcess(program, args, _workingDir, environment,
|
|
static_cast<qint16>(_windowColumns),
|
|
static_cast<qint16>(_windowLines));
|
|
if (!ok) {
|
|
qWarning() << "Pty: failed to start" << program << _ptyProcess->lastError();
|
|
delete _ptyProcess;
|
|
_ptyProcess = nullptr;
|
|
return -1;
|
|
}
|
|
|
|
emit started();
|
|
return 0;
|
|
}
|
|
|
|
void Pty::sendData(const char *buffer, int length)
|
|
{
|
|
if (_ptyProcess && length > 0)
|
|
_ptyProcess->write(QByteArray(buffer, length));
|
|
}
|
|
|
|
void Pty::setWindowSize(int lines, int cols)
|
|
{
|
|
_windowLines = lines;
|
|
_windowColumns = cols;
|
|
if (_ptyProcess)
|
|
_ptyProcess->setSize(static_cast<qint16>(cols), static_cast<qint16>(lines));
|
|
}
|
|
|
|
QSize Pty::windowSize() const
|
|
{
|
|
return {_windowColumns, _windowLines};
|
|
}
|
|
|
|
int Pty::foregroundProcessGroup() const
|
|
{
|
|
return _ptyProcess ? static_cast<int>(_ptyProcess->pid()) : 0;
|
|
}
|
|
|
|
QProcess::ProcessState Pty::state() const
|
|
{
|
|
if (_ptyProcess && _ptyProcess->isRunning())
|
|
return QProcess::Running;
|
|
return QProcess::NotRunning;
|
|
}
|
|
|
|
qint64 Pty::processId() const
|
|
{
|
|
return _ptyProcess ? static_cast<qint64>(_ptyProcess->pid()) : -1;
|
|
}
|
|
|
|
void Pty::onReadyRead()
|
|
{
|
|
if (!_ptyProcess)
|
|
return;
|
|
QByteArray data = _ptyProcess->readAll();
|
|
if (!data.isEmpty())
|
|
emit receivedData(data.constData(), data.size());
|
|
}
|
|
|
|
void Pty::onProcessFinished()
|
|
{
|
|
emit finished(0, QProcess::NormalExit);
|
|
}
|
|
|
|
#endif // Q_OS_WIN
|