From c8c6609164fc8b789171f881929da64bb34b136f Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Sun, 20 Sep 2015 13:44:32 +0200 Subject: [PATCH] Implement background color request/response --- src/Emulation.h | 6 ++++++ src/Session.cpp | 24 ++++++++++++++++++++++++ src/Session.h | 13 +++++++++++++ src/SessionController.cpp | 11 +++++++++++ src/SessionController.h | 1 + src/Vt102Emulation.cpp | 22 ++++++++++++++-------- src/Vt102Emulation.h | 3 ++- 7 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/Emulation.h b/src/Emulation.h index 52a34b4..3cf8f76 100644 --- a/src/Emulation.h +++ b/src/Emulation.h @@ -414,6 +414,12 @@ signals: */ void selectionChanged(const QString& text); + /** + * Emitted when terminal code requiring terminal's response received. + * (currently only background color request implemented) + */ + void sessionAttrRequest(int); + protected: virtual void setMode(int mode) = 0; virtual void resetMode(int mode) = 0; diff --git a/src/Session.cpp b/src/Session.cpp index 522f68e..1654a81 100644 --- a/src/Session.cpp +++ b/src/Session.cpp @@ -144,6 +144,8 @@ Session::Session(QObject* parent) : this, SIGNAL(selectionChanged(QString))); connect(_emulation, SIGNAL(imageResizeRequest(QSize)), this, SIGNAL(resizeRequest(QSize))); + connect(_emulation, SIGNAL(sessionAttrRequest(int)), + this, SLOT(sessionAttrRequest(int))); //create new teletype for I/O with shell process openTeletype(-1); @@ -647,6 +649,17 @@ void Session::onPrimaryScreenInUse(bool use) emit primaryScreenInUse(use); } +void Session::sessionAttrRequest(int id) +{ + switch (id) { + case BackgroundColor: + // we need to ask 'TerminalDisplay' (_view) about + // its background color + emit getBackgroundColor(); + break; + } +} + void Session::activityStateSet(int state) { // TODO: should this hardcoded interval be user configurable? @@ -750,6 +763,17 @@ void Session::sendSignal(int signal) } } +void Session::reportBackgroundColor(const QColor& c) +{ + #define to65k(a) (QString("%1").arg((int)(a*0xFFFF), 4, 16, QChar('0'))) + QString msg = "\033]11;rgb:" + + to65k(c.redF()) + "/" + + to65k(c.greenF()) + "/" + + to65k(c.blueF()) + "\a"; + _emulation->sendString(msg.toUtf8()); + #undef to65k +} + bool Session::kill(int signal) { if (_shellProcess->pid() <= 0) diff --git a/src/Session.h b/src/Session.h index 9053191..7781f37 100644 --- a/src/Session.h +++ b/src/Session.h @@ -369,6 +369,8 @@ public: void sendSignal(int signal); + void reportBackgroundColor(const QColor& c); + public slots: /** @@ -662,6 +664,15 @@ signals: */ void selectionChanged(const QString& text); + /** + * Emitted when background request ('\033]11;?\a') terminal code received. + * Terminal is expected send '\033]11;rgb:RRRR/GGGG/BBBB\a' response. + * + * Originally implemented to support vim's background detection feature + * (without explictly setting 'bg=dark' within local/remote vimrc) + */ + void getBackgroundColor(); + private slots: void done(int, QProcess::ExitStatus); @@ -689,6 +700,8 @@ private slots: // signal relayer void onPrimaryScreenInUse(bool use); + void sessionAttrRequest(int id); + private: // checks that the binary 'program' is available and can be executed // returns the binary name if available or an empty string otherwise diff --git a/src/SessionController.cpp b/src/SessionController.cpp index b098d4c..2bca0f9 100644 --- a/src/SessionController.cpp +++ b/src/SessionController.cpp @@ -186,6 +186,11 @@ SessionController::SessionController(Session* session , TerminalDisplay* view, Q // listen for flow control status changes connect(_session, SIGNAL(flowControlEnabledChanged(bool)), _view, SLOT(setFlowControlWarningEnabled(bool))); + + // xterm '11;?' request + connect(_session, SIGNAL(getBackgroundColor()), + this, SLOT(sendBackgroundColor())); + _view->setFlowControlWarningEnabled(_session->flowControlEnabled()); // take a snapshot of the session state every so often when @@ -457,6 +462,12 @@ void SessionController::sendSignal(QAction* action) _session->sendSignal(signal); } +void SessionController::sendBackgroundColor() +{ + QColor c = _view->getBackgroundColor(); + _session->reportBackgroundColor(c); +} + bool SessionController::eventFilter(QObject* watched , QEvent* event) { if (watched == _view) { diff --git a/src/SessionController.h b/src/SessionController.h index dd1f60f..d33f079 100644 --- a/src/SessionController.h +++ b/src/SessionController.h @@ -252,6 +252,7 @@ private slots: void handleWebShortcutAction(); void configureWebShortcuts(); void sendSignal(QAction* action); + void sendBackgroundColor(); // other void prepareSwitchProfileMenu(); diff --git a/src/Vt102Emulation.cpp b/src/Vt102Emulation.cpp index a5f19eb..389d4b9 100644 --- a/src/Vt102Emulation.cpp +++ b/src/Vt102Emulation.cpp @@ -318,7 +318,7 @@ void Vt102Emulation::receiveChar(int cc) if (lec(1,0,ESC)) { return; } if (lec(1,0,ESC+128)) { s[0] = ESC; receiveChar('['); return; } if (les(2,1,GRP)) { return; } - if (Xte ) { processWindowAttributeChange(); resetTokenizer(); return; } + if (Xte ) { processWinAttrRequest(); resetTokenizer(); return; } if (Xpe ) { return; } if (lec(3,2,'?')) { return; } if (lec(3,2,'>')) { return; } @@ -390,17 +390,18 @@ void Vt102Emulation::receiveChar(int cc) return; } } -void Vt102Emulation::processWindowAttributeChange() + +void Vt102Emulation::processWinAttrRequest() { // Describes the window or terminal session attribute to change // See Session::UserTitleChange for possible values - int attributeToChange = 0; + int attribute = 0; int i; for (i = 2; i < tokenBufferPos && tokenBuffer[i] >= '0' && tokenBuffer[i] <= '9'; i++) { - attributeToChange = 10 * attributeToChange + (tokenBuffer[i]-'0'); + attribute = 10 * attribute + (tokenBuffer[i]-'0'); } if (tokenBuffer[i] != ';') @@ -409,12 +410,17 @@ void Vt102Emulation::processWindowAttributeChange() return; } - QString newValue; - newValue.reserve(tokenBufferPos-i-2); + QString value; + value.reserve(tokenBufferPos-i-2); for (int j = 0; j < tokenBufferPos-i-2; j++) - newValue[j] = tokenBuffer[i+1+j]; + value[j] = tokenBuffer[i+1+j]; - _pendingTitleUpdates[attributeToChange] = newValue; + if (value == "?") { + emit sessionAttrRequest(attribute); + return; + } + + _pendingTitleUpdates[attribute] = value; _titleUpdateTimer->start(20); } diff --git a/src/Vt102Emulation.h b/src/Vt102Emulation.h index 8d678e0..6c32ea1 100644 --- a/src/Vt102Emulation.h +++ b/src/Vt102Emulation.h @@ -148,7 +148,8 @@ private: void reportDecodingError(); void processToken(int code, int p, int q); - void processWindowAttributeChange(); + void processWinAttrRequest(); + void requestWinAttr(int); void reportTerminalType(); void reportSecondaryAttributes(); -- 2.1.0