diff --git a/kitty/char_grid.py b/kitty/char_grid.py index 0dc7ffbed..7f28bc985 100644 --- a/kitty/char_grid.py +++ b/kitty/char_grid.py @@ -182,12 +182,11 @@ class CharGrid: self.opts = opts self.original_bg = opts.background self.original_fg = opts.foreground - self.default_cursor = Cursor(0, 0, False, opts.cursor_shape, opts.cursor, opts.cursor_blink) self.default_bg = color_as_int(self.original_bg) self.default_fg = color_as_int(self.original_fg) self.dpix, self.dpiy = get_logical_dpi() self.opts = opts - self.default_cursor = self.current_cursor = Cursor(0, 0, False, opts.cursor_shape, opts.cursor, opts.cursor_blink) + self.default_cursor = self.current_cursor = Cursor(0, 0, False, opts.cursor_shape, opts.cursor, opts.cursor_blink_interval > 0) self.opts = opts self.original_bg = opts.background self.original_fg = opts.foreground diff --git a/kitty/config.py b/kitty/config.py index 5e41efdf0..d4c1e99ba 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -42,13 +42,13 @@ type_map = { 'scrollback_lines': int, 'font_size': to_font_size, 'cursor_shape': to_cursor_shape, - 'cursor_blink': to_bool, 'cursor_opacity': to_opacity, 'repaint_delay': int, 'window_border_width': float, 'wheel_scroll_multiplier': float, 'click_interval': float, 'mouse_hide_wait': float, + 'cursor_blink_interval': float, 'cursor_stop_blinking_after': float, } diff --git a/kitty/kitty.conf b/kitty/kitty.conf index 20b7f00a2..74cc246bc 100644 --- a/kitty/kitty.conf +++ b/kitty/kitty.conf @@ -20,8 +20,13 @@ cursor_opacity 0.7 # The cursor shape can be one of (block, beam, underline) cursor_shape block -# Whether to blink the cursor or not -cursor_blink no +# The interval (in seconds) at which to blink the cursor. Set to zero to +# disable blinking. +cursor_blink_interval 0.5 + +# Stop blinking cursor after the specified number of seconds of keyboard inactivity. Set to +# zero or a negative number to never stop blinking. +cursor_stop_blinking_after 15.0 # Font family font_family monospace @@ -47,10 +52,6 @@ repaint_delay 20 # zero or a negative number to disable mouse cursor hiding. mouse_hide_wait 3.0 -# Stop blinking cursor after the specified number of seconds of keyboard inactivity. Set to -# zero or a negative number to never stop blinking. -cursor_stop_blinking_after 5.0 - # The width (in pts) of window borders. Will be rounded to the nearest number of pixels based on screen resolution. window_border_width 2 diff --git a/kitty/tabs.py b/kitty/tabs.py index 3251e4124..a0a78c1fb 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -11,6 +11,7 @@ import inspect from collections import deque from functools import wraps from threading import Thread, current_thread +from time import monotonic from queue import Queue, Empty from .child import Child @@ -129,6 +130,7 @@ class TabManager(Thread): def __init__(self, glfw_window, opts, args): Thread.__init__(self, name='ChildMonitor') + self.cursor_blinking = True self.glfw_window_title = None self.current_tab_bar_height = 0 self.action_queue = Queue() @@ -166,6 +168,7 @@ class TabManager(Thread): self.queue_action(self.active_tab.new_window, False) self.glfw_window.set_click_cursor(False) self.show_mouse_cursor() + self.start_cursor_blink() def signal_received(self): try: @@ -298,6 +301,7 @@ class TabManager(Thread): @callback def on_key(self, window, key, scancode, action, mods): + self.start_cursor_blink() if action == GLFW_PRESS or action == GLFW_REPEAT: func = get_shortcut(self.opts.keymap, mods, key) tab = self.active_tab @@ -381,6 +385,14 @@ class TabManager(Thread): def hide_mouse_cursor(self): self.glfw_window.set_input_mode(GLFW_CURSOR, GLFW_CURSOR_HIDDEN) + def start_cursor_blink(self): + self.cursor_blinking = True + if self.opts.cursor_stop_blinking_after > 0: + self.ui_timers.add(self.opts.cursor_stop_blinking_after, self.stop_cursor_blinking) + + def stop_cursor_blinking(self): + self.cursor_blinking = False + def render(self): if self.pending_resize: return @@ -403,8 +415,17 @@ class TabManager(Thread): window.char_grid.render_cells(rd, self.cell_program, self.sprites) rd = render_data.get(active) if rd is not None: - with self.cursor_program: - active.char_grid.render_cursor(rd, self.cursor_program) + draw_cursor = True + if self.cursor_blinking and self.opts.cursor_blink_interval > 0: + now = monotonic() + t = int(now * 1000) + d = int(self.opts.cursor_blink_interval * 1000) + n = t // d + draw_cursor = n % 2 == 0 + self.ui_timers.add_if_missing(((n + 1) * d / 1000) - now, glfw_post_empty_event) + if draw_cursor: + with self.cursor_program: + active.char_grid.render_cursor(rd, self.cursor_program) def gui_close_window(self, window): for tab in self.tabs: