diff --git a/kitty/data_types.py b/kitty/data_types.py index 4a13cfa81..299b2fe48 100644 --- a/kitty/data_types.py +++ b/kitty/data_types.py @@ -27,7 +27,7 @@ get_zeroes.current_size = None class Cursor: - __slots__ = ("x", "y", 'shape', 'blink', "hidden", 'fg', 'bg', 'bold', 'italic', 'reverse', 'strikethrough', 'decoration', 'decoration_fg',) + __slots__ = ("x", "y", 'shape', 'blink', "hidden", 'color', 'fg', 'bg', 'bold', 'italic', 'reverse', 'strikethrough', 'decoration', 'decoration_fg',) def __init__(self, x: int=0, y: int=0): self.x = x @@ -35,6 +35,7 @@ class Cursor: self.hidden = False self.shape = None self.blink = None + self.color = None self.reset_display_attrs() def reset_display_attrs(self): diff --git a/kitty/screen.py b/kitty/screen.py index d9b26800f..e7fd0e8ce 100644 --- a/kitty/screen.py +++ b/kitty/screen.py @@ -982,6 +982,15 @@ class Screen(QObject): else: # DECLL pass + def set_cursor_color(self, color_name): + try: + color_name = color_name.decode('utf-8') if color_name else None + except Exception: + return + old, self.cursor.color = self.cursor.color, color_name + if old != self.cursor.color: + self.cursor_changed(self.cursor) + def normal_keypad_mode(self): pass # Useless for us, since Qt takes care of handling the numpad diff --git a/kitty/term.py b/kitty/term.py index 642cb6433..5adfeb41a 100644 --- a/kitty/term.py +++ b/kitty/term.py @@ -195,6 +195,11 @@ class TerminalWidget(QWidget): r = QRect(self.cell_positions[x], self.line_positions[y], self.cell_width, self.cell_height) self.last_drew_cursor_at = x, y cc = self.cursor_color + if self.cursor.color: + q = QColor(self.cursor.color) + if q.isValid(): + cc = q + cc.setAlphaF(self.opts.cursor_opacity) def width(w=2, vert=True): dpi = self.logicalDpiX() if vert else self.logicalDpiY() diff --git a/pyte/streams.py b/pyte/streams.py index 77b469c1d..6ee6f8995 100644 --- a/pyte/streams.py +++ b/pyte/streams.py @@ -127,7 +127,7 @@ class Stream(object): events = frozenset(itertools.chain( basic.values(), escape.values(), sharp.values(), csi.values(), ["define_charset", "select_other_charset"], - ["set_icon", "set_title"], # OSC. + ["set_icon", "set_title", 'set_cursor_color'], # OSC. ["draw", "debug"])) #: A regular expression pattern matching everything what can be @@ -321,20 +321,31 @@ class Stream(object): csi_dispatch[char](*params) break # CSI is finished. elif char == OSC: - code = yield - param = bytearray() + code = bytearray() while True: char = yield - if char == ST or char == ctrl.BEL: + if char == ST or char == ctrl.BEL or char == b';': break - else: - param.extend(char) + code.extend(char) + code = bytes(code) + param = bytearray() + if char == b';': + while True: + char = yield + if char == ST or char == ctrl.BEL: + break + else: + param.extend(char) - param = bytes(param[1:]) # Drop the ;. + param = bytes(param) if code in b"01": listener.set_icon_name(param) if code in b"02": listener.set_title(param) + elif code == b"12": + listener.set_cursor_color(param) + elif code == b"112": + listener.set_cursor_color(b'') elif char == DCS: # See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Device-Control-functions code = yield