mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-22 16:28:19 +02:00
More refactoring
This commit is contained in:
@@ -8,14 +8,13 @@ import select
|
|||||||
import signal
|
import signal
|
||||||
import struct
|
import struct
|
||||||
import inspect
|
import inspect
|
||||||
from collections import deque
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from threading import Thread, current_thread
|
from threading import Thread, current_thread
|
||||||
from time import monotonic
|
from time import monotonic
|
||||||
from queue import Queue, Empty
|
from queue import Queue, Empty
|
||||||
|
|
||||||
from .constants import (
|
from .constants import (
|
||||||
viewport_size, set_tab_manager, wakeup, cell_size, MODIFIER_KEYS,
|
viewport_size, set_boss, wakeup, cell_size, MODIFIER_KEYS,
|
||||||
main_thread, mouse_button_pressed, mouse_cursor_pos
|
main_thread, mouse_button_pressed, mouse_cursor_pos
|
||||||
)
|
)
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
@@ -29,7 +28,7 @@ from .char_grid import cursor_shader, cell_shader
|
|||||||
from .constants import is_key_pressed
|
from .constants import is_key_pressed
|
||||||
from .keys import interpret_text_event, interpret_key_event, get_shortcut
|
from .keys import interpret_text_event, interpret_key_event, get_shortcut
|
||||||
from .shaders import Sprites, ShaderProgram
|
from .shaders import Sprites, ShaderProgram
|
||||||
from .tabs import Tab
|
from .tabs import TabManager
|
||||||
from .timers import Timers
|
from .timers import Timers
|
||||||
from .utils import handle_unix_signals
|
from .utils import handle_unix_signals
|
||||||
|
|
||||||
@@ -82,7 +81,7 @@ class Boss(Thread):
|
|||||||
self.ui_timers = Timers()
|
self.ui_timers = Timers()
|
||||||
self.pending_ui_thread_calls = Queue()
|
self.pending_ui_thread_calls = Queue()
|
||||||
self.write_dispatch_map = {}
|
self.write_dispatch_map = {}
|
||||||
set_tab_manager(self)
|
set_boss(self)
|
||||||
cell_size.width, cell_size.height = set_font_family(opts.font_family, opts.font_size)
|
cell_size.width, cell_size.height = set_font_family(opts.font_family, opts.font_size)
|
||||||
self.opts, self.args = opts, args
|
self.opts, self.args = opts, args
|
||||||
self.glfw_window = glfw_window
|
self.glfw_window = glfw_window
|
||||||
@@ -93,8 +92,7 @@ class Boss(Thread):
|
|||||||
glfw_window.scroll_callback = self.on_mouse_scroll
|
glfw_window.scroll_callback = self.on_mouse_scroll
|
||||||
glfw_window.cursor_pos_callback = self.on_mouse_move
|
glfw_window.cursor_pos_callback = self.on_mouse_move
|
||||||
glfw_window.window_focus_callback = self.on_focus
|
glfw_window.window_focus_callback = self.on_focus
|
||||||
self.tabs = deque()
|
self.tab_manager = TabManager(opts, args)
|
||||||
self.tabs.append(Tab(opts, args))
|
|
||||||
self.sprites = Sprites()
|
self.sprites = Sprites()
|
||||||
self.cell_program = ShaderProgram(*cell_shader)
|
self.cell_program = ShaderProgram(*cell_shader)
|
||||||
self.cursor_program = ShaderProgram(*cursor_shader)
|
self.cursor_program = ShaderProgram(*cursor_shader)
|
||||||
@@ -119,7 +117,7 @@ class Boss(Thread):
|
|||||||
glfw_post_empty_event()
|
glfw_post_empty_event()
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
yield from iter(self.tabs)
|
return iter(self.tab_manager)
|
||||||
|
|
||||||
def iterwindows(self):
|
def iterwindows(self):
|
||||||
for t in self:
|
for t in self:
|
||||||
@@ -218,7 +216,7 @@ class Boss(Thread):
|
|||||||
|
|
||||||
def apply_pending_resize(self, w, h):
|
def apply_pending_resize(self, w, h):
|
||||||
viewport_size.width, viewport_size.height = w, h
|
viewport_size.width, viewport_size.height = w, h
|
||||||
for tab in self.tabs:
|
for tab in self.tab_manager:
|
||||||
tab.relayout()
|
tab.relayout()
|
||||||
self.resize_gl_viewport = True
|
self.resize_gl_viewport = True
|
||||||
self.pending_resize = False
|
self.pending_resize = False
|
||||||
@@ -226,7 +224,7 @@ class Boss(Thread):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def active_tab(self):
|
def active_tab(self):
|
||||||
return self.tabs[0] if self.tabs else None
|
return self.tab_manager.active_tab
|
||||||
|
|
||||||
def is_tab_visible(self, tab):
|
def is_tab_visible(self, tab):
|
||||||
return self.active_tab is tab
|
return self.active_tab is tab
|
||||||
@@ -387,16 +385,16 @@ class Boss(Thread):
|
|||||||
if window.char_grid.buffer_id is not None:
|
if window.char_grid.buffer_id is not None:
|
||||||
self.sprites.destroy_sprite_map(window.char_grid.buffer_id)
|
self.sprites.destroy_sprite_map(window.char_grid.buffer_id)
|
||||||
window.char_grid.buffer_id = None
|
window.char_grid.buffer_id = None
|
||||||
for tab in self.tabs:
|
for tab in self.tab_manager:
|
||||||
if window in tab:
|
if window in tab:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
tab.remove_window(window)
|
tab.remove_window(window)
|
||||||
if len(tab) == 0:
|
if len(tab) == 0:
|
||||||
self.tabs.remove(tab)
|
self.tab_manager.remove(tab)
|
||||||
tab.destroy()
|
tab.destroy()
|
||||||
if len(self.tabs) == 0:
|
if len(self.tab_manager) == 0:
|
||||||
if not self.shutting_down:
|
if not self.shutting_down:
|
||||||
self.glfw_window.set_should_close(True)
|
self.glfw_window.set_should_close(True)
|
||||||
glfw_post_empty_event()
|
glfw_post_empty_event()
|
||||||
@@ -408,9 +406,9 @@ class Boss(Thread):
|
|||||||
self.shutting_down = True
|
self.shutting_down = True
|
||||||
wakeup()
|
wakeup()
|
||||||
self.join()
|
self.join()
|
||||||
for t in self.tabs:
|
for t in self.tab_manager:
|
||||||
t.destroy()
|
t.destroy()
|
||||||
del self.tabs
|
del self.tab_manager
|
||||||
self.sprites.destroy()
|
self.sprites.destroy()
|
||||||
del self.sprites
|
del self.sprites
|
||||||
del self.glfw_window
|
del self.glfw_window
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from ctypes import addressof, memmove, sizeof
|
|||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
from .config import build_ansi_color_table
|
from .config import build_ansi_color_table
|
||||||
from .constants import tab_manager, viewport_size, cell_size, ScreenGeometry, GLuint
|
from .constants import get_boss, viewport_size, cell_size, ScreenGeometry, GLuint
|
||||||
from .utils import get_logical_dpi, to_color, set_primary_selection, open_url
|
from .utils import get_logical_dpi, to_color, set_primary_selection, open_url
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
glUniform2ui, glUniform4f, glUniform1i, glUniform2f, glDrawArraysInstanced,
|
glUniform2ui, glUniform4f, glUniform1i, glUniform2f, glDrawArraysInstanced,
|
||||||
@@ -281,7 +281,7 @@ class CharGrid:
|
|||||||
self.update_cell_data()
|
self.update_cell_data()
|
||||||
|
|
||||||
def update_cell_data(self, force_full_refresh=False):
|
def update_cell_data(self, force_full_refresh=False):
|
||||||
sprites = tab_manager().sprites
|
sprites = get_boss().sprites
|
||||||
is_dirty = self.screen.is_dirty()
|
is_dirty = self.screen.is_dirty()
|
||||||
with sprites.lock:
|
with sprites.lock:
|
||||||
cursor_changed, history_line_added_count = self.screen.update_cell_data(
|
cursor_changed, history_line_added_count = self.screen.update_cell_data(
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ named_keys = {"'": 'APOSTROPHE', ',': 'COMMA', '-': 'MINUS', '.': 'PERIOD',
|
|||||||
|
|
||||||
def parse_key(val, keymap):
|
def parse_key(val, keymap):
|
||||||
sc, action = val.partition(' ')[::2]
|
sc, action = val.partition(' ')[::2]
|
||||||
|
action = action.strip()
|
||||||
|
sc = sc.strip()
|
||||||
if not sc or not action:
|
if not sc or not action:
|
||||||
return
|
return
|
||||||
parts = sc.split('+')
|
parts = sc.split('+')
|
||||||
|
|||||||
@@ -49,20 +49,20 @@ class ViewportSize:
|
|||||||
return '(width={}, height={})'.format(self.width, self.height)
|
return '(width={}, height={})'.format(self.width, self.height)
|
||||||
|
|
||||||
|
|
||||||
def tab_manager():
|
def get_boss():
|
||||||
return tab_manager.manager
|
return get_boss.boss
|
||||||
|
|
||||||
|
|
||||||
def set_tab_manager(m):
|
def set_boss(m):
|
||||||
tab_manager.manager = m
|
get_boss.boss = m
|
||||||
|
|
||||||
|
|
||||||
def wakeup():
|
def wakeup():
|
||||||
os.write(tab_manager.manager.write_wakeup_fd, b'1')
|
os.write(get_boss.boss.write_wakeup_fd, b'1')
|
||||||
|
|
||||||
|
|
||||||
def queue_action(func, *args):
|
def queue_action(func, *args):
|
||||||
tab_manager.manager.queue_action(func, *args)
|
get_boss.boss.queue_action(func, *args)
|
||||||
|
|
||||||
|
|
||||||
is_key_pressed = defaultdict(lambda: False)
|
is_key_pressed = defaultdict(lambda: False)
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
from itertools import islice
|
from itertools import islice
|
||||||
|
|
||||||
from .constants import WindowGeometry, viewport_size, cell_size, tab_manager
|
from .constants import WindowGeometry, viewport_size, cell_size, get_boss
|
||||||
|
|
||||||
|
|
||||||
def available_height():
|
def available_height():
|
||||||
return viewport_size.height - tab_manager().current_tab_bar_height
|
return viewport_size.height - get_boss().current_tab_bar_height
|
||||||
|
|
||||||
|
|
||||||
def layout_dimension(length, cell_length, number_of_windows=1, border_length=0, left_align=False):
|
def layout_dimension(length, cell_length, number_of_windows=1, border_length=0, left_align=False):
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
from .child import Child
|
from .child import Child
|
||||||
from .constants import tab_manager, appname, shell_path
|
from .constants import get_boss, appname, shell_path
|
||||||
from .fast_data_types import glfw_post_empty_event
|
from .fast_data_types import glfw_post_empty_event
|
||||||
from .layout import all_layouts
|
from .layout import all_layouts
|
||||||
from .borders import Borders
|
from .borders import Borders
|
||||||
@@ -30,7 +30,7 @@ class Tab:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_visible(self):
|
def is_visible(self):
|
||||||
return tab_manager().is_tab_visible(self)
|
return get_boss().is_tab_visible(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def active_window(self):
|
def active_window(self):
|
||||||
@@ -71,7 +71,7 @@ class Tab:
|
|||||||
def new_window(self, use_shell=True):
|
def new_window(self, use_shell=True):
|
||||||
child = self.launch_child(use_shell=use_shell)
|
child = self.launch_child(use_shell=use_shell)
|
||||||
window = Window(self, child, self.opts, self.args)
|
window = Window(self, child, self.opts, self.args)
|
||||||
tab_manager().add_child_fd(child.child_fd, window.read_ready, window.write_ready)
|
get_boss().add_child_fd(child.child_fd, window.read_ready, window.write_ready)
|
||||||
self.active_window_idx = self.current_layout.add_window(self.windows, window, self.active_window_idx)
|
self.active_window_idx = self.current_layout.add_window(self.windows, window, self.active_window_idx)
|
||||||
self.borders(self.windows, self.active_window, self.current_layout.needs_window_borders and len(self.windows) > 1)
|
self.borders(self.windows, self.active_window, self.current_layout.needs_window_borders and len(self.windows) > 1)
|
||||||
glfw_post_empty_event()
|
glfw_post_empty_event()
|
||||||
@@ -123,4 +123,26 @@ class Tab:
|
|||||||
del self.windows
|
del self.windows
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
self.borders.render(tab_manager().borders_program)
|
self.borders.render(get_boss().borders_program)
|
||||||
|
|
||||||
|
|
||||||
|
class TabManager:
|
||||||
|
|
||||||
|
def __init__(self, opts, args):
|
||||||
|
self.opts, self.args = opts, args
|
||||||
|
self.tabs = [Tab(opts, args)]
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self.tabs)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.tabs)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def active_tab(self):
|
||||||
|
return self.tabs[0] if self.tabs else None
|
||||||
|
|
||||||
|
def remove(self, tab):
|
||||||
|
' Must be called in the GUI thread '
|
||||||
|
self.tabs.remove(tab)
|
||||||
|
tab.destroy()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from functools import partial
|
|||||||
from time import monotonic
|
from time import monotonic
|
||||||
|
|
||||||
from .char_grid import CharGrid
|
from .char_grid import CharGrid
|
||||||
from .constants import wakeup, tab_manager, appname, WindowGeometry, is_key_pressed, mouse_button_pressed, cell_size
|
from .constants import wakeup, get_boss, appname, WindowGeometry, is_key_pressed, mouse_button_pressed, cell_size
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
BRACKETED_PASTE_START, BRACKETED_PASTE_END, Screen, read_bytes_dump,
|
BRACKETED_PASTE_START, BRACKETED_PASTE_END, Screen, read_bytes_dump,
|
||||||
read_bytes, GLFW_MOD_SHIFT, GLFW_MOUSE_BUTTON_1, GLFW_PRESS,
|
read_bytes, GLFW_MOD_SHIFT, GLFW_MOUSE_BUTTON_1, GLFW_PRESS,
|
||||||
@@ -73,7 +73,7 @@ class Window:
|
|||||||
return g.left <= x <= g.right and g.top <= y <= g.bottom
|
return g.left <= x <= g.right and g.top <= y <= g.bottom
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
tab_manager().close_window(self)
|
get_boss().close_window(self)
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
self.destroyed = True
|
self.destroyed = True
|
||||||
@@ -201,8 +201,8 @@ class Window:
|
|||||||
is_key_pressed[GLFW_KEY_LEFT_SHIFT] or is_key_pressed[GLFW_KEY_RIGHT_SHIFT])
|
is_key_pressed[GLFW_KEY_LEFT_SHIFT] or is_key_pressed[GLFW_KEY_RIGHT_SHIFT])
|
||||||
x, y = max(0, x - self.geometry.left), max(0, y - self.geometry.top)
|
x, y = max(0, x - self.geometry.left), max(0, y - self.geometry.top)
|
||||||
self.last_mouse_cursor_pos = x, y
|
self.last_mouse_cursor_pos = x, y
|
||||||
tm = tab_manager()
|
tm = get_boss()
|
||||||
tm.queue_ui_action(tab_manager().change_mouse_cursor, self.char_grid.has_url_at(x, y))
|
tm.queue_ui_action(get_boss().change_mouse_cursor, self.char_grid.has_url_at(x, y))
|
||||||
if send_event:
|
if send_event:
|
||||||
x, y = self.char_grid.cell_for_pos(x, y)
|
x, y = self.char_grid.cell_for_pos(x, y)
|
||||||
if x is not None:
|
if x is not None:
|
||||||
@@ -215,11 +215,11 @@ class Window:
|
|||||||
self.char_grid.update_drag(None, x, y)
|
self.char_grid.update_drag(None, x, y)
|
||||||
margin = cell_size.height // 2
|
margin = cell_size.height // 2
|
||||||
if y <= margin or y >= self.geometry.bottom - margin:
|
if y <= margin or y >= self.geometry.bottom - margin:
|
||||||
tab_manager().timers.add(0.02, self.drag_scroll)
|
get_boss().timers.add(0.02, self.drag_scroll)
|
||||||
|
|
||||||
def drag_scroll(self):
|
def drag_scroll(self):
|
||||||
x, y = self.last_mouse_cursor_pos
|
x, y = self.last_mouse_cursor_pos
|
||||||
tm = tab_manager()
|
tm = get_boss()
|
||||||
margin = cell_size.height // 2
|
margin = cell_size.height // 2
|
||||||
if y <= margin or y >= self.geometry.bottom - margin:
|
if y <= margin or y >= self.geometry.bottom - margin:
|
||||||
self.scroll_line_up() if y < 50 else self.scroll_line_down()
|
self.scroll_line_up() if y < 50 else self.scroll_line_down()
|
||||||
@@ -272,7 +272,7 @@ class Window:
|
|||||||
def copy_to_clipboard(self):
|
def copy_to_clipboard(self):
|
||||||
text = self.char_grid.text_for_selection()
|
text = self.char_grid.text_for_selection()
|
||||||
if text:
|
if text:
|
||||||
tm = tab_manager()
|
tm = get_boss()
|
||||||
tm.queue_ui_action(tm.glfw_window.set_clipboard_string, text)
|
tm.queue_ui_action(tm.glfw_window.set_clipboard_string, text)
|
||||||
|
|
||||||
def scroll_line_up(self):
|
def scroll_line_up(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user