diff --git a/kitty/boss.py b/kitty/boss.py index 5f98093ff..6f853b755 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -296,12 +296,20 @@ class Boss(Thread): if w.is_visible_in_layout and w.contains(x, y): return w + def in_tab_bar(self, y): + th = self.current_tab_bar_height + return th > 0 and y >= viewport_size.height - th + @callback def on_mouse_button(self, window, button, action, mods): mouse_button_pressed[button] = action == GLFW_PRESS self.show_mouse_cursor() - w = self.window_for_pos(*mouse_cursor_pos) + x, y = mouse_cursor_pos + w = self.window_for_pos(x, y) if w is None: + if self.in_tab_bar(y): + if button == GLFW_MOUSE_BUTTON_1 and action == GLFW_PRESS: + self.tab_manager.activate_tab_at(x) return focus_moved = False old_focus = self.active_window @@ -324,6 +332,8 @@ class Boss(Thread): if w is not None: yield w w.on_mouse_move(xpos, ypos) + else: + self.change_mouse_cursor(self.in_tab_bar(ypos)) @callback def on_mouse_scroll(self, window, x, y): diff --git a/kitty/tabs.py b/kitty/tabs.py index 5b775f065..7dbd91e22 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -171,6 +171,7 @@ class TabManager: self.opts, self.args = opts, args self.buffer_id = None self.tabs = [Tab(opts, args, self.title_changed, t) for t in startup_session.tabs] + self.cell_ranges = [] self.active_tab_idx = startup_session.active_tab_idx self.tabbar_lock = Lock() self.tabbar_dirty = True @@ -207,12 +208,15 @@ class TabManager: self.screen = s self.can_render = True + def set_active_tab(self, idx): + self.active_tab_idx = idx + self.tabbar_dirty = True + self.active_tab.relayout_borders() + glfw_post_empty_event() + def next_tab(self, delta=1): if len(self.tabs) > 1: - self.active_tab_idx = (self.active_tab_idx + len(self.tabs) + delta) % len(self.tabs) - self.tabbar_dirty = True - self.active_tab.relayout_borders() - glfw_post_empty_event() + self.set_active_tab((self.active_tab_idx + len(self.tabs) + delta) % len(self.tabs)) def __iter__(self): return iter(self.tabs) @@ -252,6 +256,7 @@ class TabManager: s.erase_in_line(2, False) at = self.active_tab max_title_length = (self.screen_geometry.xnum // len(self.tabs)) - 1 + self.cell_ranges = [] for t in self.tabs: title = (t.name or t.title or appname) + ' ' @@ -264,6 +269,7 @@ class TabManager: if extra > 0: s.cursor.x -= extra + 1 s.draw('…') + self.cell_ranges.append((before, s.cursor.x)) s.cursor.bold = s.cursor.italic = False s.cursor.fg = s.cursor.bg = 0 s.draw('┇') @@ -277,6 +283,13 @@ class TabManager: self.buffer_id = sprites.add_sprite_map() sprites.set_sprite_map(self.buffer_id, self.sprite_map) + def activate_tab_at(self, x): + x = (x - self.window_geometry.left) // cell_size.width + for i, (a, b) in enumerate(self.cell_ranges): + if a <= x <= b: + queue_action(self.set_active_tab, i) + return + def render(self, cell_program, sprites): if not self.can_render or len(self.tabs) < 2: return