Browse Source

Terminal: Support setting the window title using Xterm escape sequences.

Use this in the /bin/sh prompt to keep the window title in sync with the
shell's working directory. :^)
Andreas Kling 6 năm trước cách đây
mục cha
commit
5adaeeaa3b
3 tập tin đã thay đổi với 60 bổ sung1 xóa
  1. 49 0
      Terminal/Terminal.cpp
  2. 8 0
      Terminal/Terminal.h
  3. 3 1
      Userland/sh.cpp

+ 49 - 0
Terminal/Terminal.cpp

@@ -356,6 +356,24 @@ void Terminal::escape$J(const Vector<unsigned>& params)
     }
 }
 
+void Terminal::execute_xterm_command()
+{
+    bool ok;
+    unsigned value = parseUInt(String((const char*)m_xterm_param1.data(), m_xterm_param1.size()), ok);
+    if (ok) {
+        switch (value) {
+        case 0:
+            set_window_title(String((const char*)m_xterm_param2.data(), m_xterm_param2.size()));
+            break;
+        default:
+            notImplemented();
+            break;
+        }
+    }
+    m_xterm_param1.clear_with_capacity();
+    m_xterm_param2.clear_with_capacity();
+}
+
 void Terminal::execute_escape_sequence(byte final)
 {
     auto paramparts = String((const char*)m_parameters.data(), m_parameters.size()).split(';');
@@ -437,9 +455,31 @@ void Terminal::on_char(byte ch)
     case ExpectBracket:
         if (ch == '[')
             m_escape_state = ExpectParameter;
+        else if (ch == ']')
+            m_escape_state = ExpectXtermParameter1;
         else
             m_escape_state = Normal;
         return;
+    case ExpectXtermParameter1:
+        if (ch != ';') {
+            m_xterm_param1.append(ch);
+            return;
+        }
+        m_escape_state = ExpectXtermParameter2;
+        return;
+    case ExpectXtermParameter2:
+        if (ch != '\007') {
+            m_xterm_param2.append(ch);
+            return;
+        }
+        m_escape_state = ExpectXtermFinal;
+        // fall through
+    case ExpectXtermFinal:
+        m_escape_state = Normal;
+        if (ch == '\007')
+            execute_xterm_command();
+        return;
+
     case ExpectParameter:
         if (is_valid_parameter_character(ch)) {
             m_parameters.append(ch);
@@ -640,6 +680,15 @@ void Terminal::invalidate_window(const Rect& a_rect)
     }
 }
 
+void Terminal::set_window_title(const String& title)
+{
+    int rc = gui_set_window_title(m_window_id, title.characters(), title.length());
+    if (rc < 0) {
+        perror("gui_set_window_title");
+        exit(1);
+    }
+}
+
 void Terminal::set_in_active_window(bool b)
 {
     if (m_in_active_window == b)

+ 8 - 0
Terminal/Terminal.h

@@ -26,6 +26,7 @@ private:
     void put_character_at(unsigned row, unsigned column, byte ch);
     void invalidate_cursor();
     void invalidate_window(const Rect& = Rect());
+    void set_window_title(const String&);
 
     void escape$A(const Vector<unsigned>&);
     void escape$B(const Vector<unsigned>&);
@@ -88,6 +89,7 @@ private:
     Attribute& attribute_at(word row, word column);
 
     void execute_escape_sequence(byte final);
+    void execute_xterm_command();
 
     enum EscapeState {
         Normal,
@@ -95,10 +97,16 @@ private:
         ExpectParameter,
         ExpectIntermediate,
         ExpectFinal,
+
+        ExpectXtermParameter1,
+        ExpectXtermParameter2,
+        ExpectXtermFinal,
     };
     EscapeState m_escape_state { Normal };
     Vector<byte> m_parameters;
     Vector<byte> m_intermediates;
+    Vector<byte> m_xterm_param1;
+    Vector<byte> m_xterm_param2;
     byte* m_horizontal_tabs { nullptr };
     bool m_belling { false };
 

+ 3 - 1
Userland/sh.cpp

@@ -26,8 +26,10 @@ static void prompt()
 {
     if (g->uid == 0)
         printf("# ");
-    else
+    else {
+        printf("\033]0;%s@%s:%s\007", g->username.characters(), g->hostname, g->cwd.characters());
         printf("\033[31;1m%s\033[0m@\033[37;1m%s\033[0m:\033[32;1m%s\033[0m$> ", g->username.characters(), g->hostname, g->cwd.characters());
+    }
     fflush(stdout);
 }