From c8c6609164fc8b789171f881929da64bb34b136f Mon Sep 17 00:00:00 2001
From: Pavel Raiskup <praiskup@redhat.com>
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