mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-28 03:01:57 +02:00
Port tab_manager and miscellaneous cleanups
This commit is contained in:
144
kitty/boss.py
144
kitty/boss.py
@@ -5,12 +5,13 @@
|
|||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
from weakref import WeakValueDictionary
|
from weakref import WeakValueDictionary
|
||||||
|
|
||||||
from .config import MINIMUM_FONT_SIZE, cached_values
|
from .config import MINIMUM_FONT_SIZE, cached_values, initial_window_size
|
||||||
from .constants import set_boss, wakeup
|
from .constants import set_boss, wakeup
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
GLFW_KEY_DOWN, GLFW_KEY_UP, ChildMonitor, destroy_global_data,
|
GLFW_KEY_DOWN, GLFW_KEY_UP, ChildMonitor, create_os_window,
|
||||||
destroy_sprite_map, get_clipboard_string, glfw_post_empty_event,
|
current_os_window, destroy_global_data, destroy_sprite_map,
|
||||||
layout_sprite_map, toggle_fullscreen, viewport_for_window
|
get_clipboard_string, glfw_post_empty_event, layout_sprite_map,
|
||||||
|
mark_os_window_for_close, toggle_fullscreen, viewport_for_window
|
||||||
)
|
)
|
||||||
from .fonts.render import prerender, resize_fonts, set_font_family
|
from .fonts.render import prerender, resize_fonts, set_font_family
|
||||||
from .keys import get_key_map, get_shortcut
|
from .keys import get_key_map, get_shortcut
|
||||||
@@ -59,9 +60,8 @@ class Boss:
|
|||||||
|
|
||||||
def __init__(self, os_window_id, opts, args):
|
def __init__(self, os_window_id, opts, args):
|
||||||
self.window_id_map = WeakValueDictionary()
|
self.window_id_map = WeakValueDictionary()
|
||||||
startup_session = create_session(opts, args)
|
self.os_window_map = {}
|
||||||
self.cursor_blinking = True
|
self.cursor_blinking = True
|
||||||
self.window_is_focused = True
|
|
||||||
self.shutting_down = False
|
self.shutting_down = False
|
||||||
self.child_monitor = ChildMonitor(
|
self.child_monitor = ChildMonitor(
|
||||||
self.on_child_death,
|
self.on_child_death,
|
||||||
@@ -71,17 +71,42 @@ class Boss:
|
|||||||
set_font_family(opts)
|
set_font_family(opts)
|
||||||
self.opts, self.args = opts, args
|
self.opts, self.args = opts, args
|
||||||
initialize_renderer()
|
initialize_renderer()
|
||||||
self.tab_manager = TabManager(opts, args)
|
startup_session = create_session(opts, args)
|
||||||
self.tab_manager.init(startup_session)
|
self.add_os_window(startup_session)
|
||||||
|
|
||||||
|
def add_os_window(self, startup_session, os_window_id=None):
|
||||||
|
if os_window_id is None:
|
||||||
|
w, h = initial_window_size(self.opts)
|
||||||
|
os_window_id = create_os_window(w, h, self.args.cls)
|
||||||
|
tm = TabManager(os_window_id, self.opts, self.args, startup_session)
|
||||||
|
self.os_window_map[os_window_id] = tm
|
||||||
|
|
||||||
def add_child(self, window):
|
def add_child(self, window):
|
||||||
self.child_monitor.add_child(window.id, window.child.pid, window.child.child_fd, window.screen)
|
self.child_monitor.add_child(window.id, window.child.pid, window.child.child_fd, window.screen)
|
||||||
self.window_id_map[window.id] = window
|
self.window_id_map[window.id] = window
|
||||||
|
|
||||||
def on_child_death(self, window_id):
|
def on_child_death(self, window_id):
|
||||||
w = self.window_id_map.pop(window_id, None)
|
window = self.window_id_map.pop(window_id, None)
|
||||||
if w is not None:
|
if window is None:
|
||||||
w.on_child_death()
|
return
|
||||||
|
os_window_id = window.os_window_id
|
||||||
|
window.destroy()
|
||||||
|
tm = self.os_window_map.get(os_window_id)
|
||||||
|
if tm is None:
|
||||||
|
return
|
||||||
|
for tab in tm:
|
||||||
|
if window in tab:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
tab.remove_window(window)
|
||||||
|
if len(tab) == 0:
|
||||||
|
tm.remove(tab)
|
||||||
|
tab.destroy()
|
||||||
|
if len(tm) == 0:
|
||||||
|
if not self.shutting_down:
|
||||||
|
mark_os_window_for_close(os_window_id)
|
||||||
|
glfw_post_empty_event()
|
||||||
|
|
||||||
def close_window(self, window=None):
|
def close_window(self, window=None):
|
||||||
if window is None:
|
if window is None:
|
||||||
@@ -103,12 +128,14 @@ class Boss:
|
|||||||
self.io_thread_started = True
|
self.io_thread_started = True
|
||||||
|
|
||||||
def activate_tab_at(self, os_window_id, x):
|
def activate_tab_at(self, os_window_id, x):
|
||||||
# WIN: Implement this
|
tm = self.os_window_map.get(os_window_id)
|
||||||
pass
|
if tm is not None:
|
||||||
|
tm.activate_tab_at(x)
|
||||||
|
|
||||||
def on_window_resize(self, window, w, h):
|
def on_window_resize(self, os_window_id, w, h):
|
||||||
# WIN: Port this
|
tm = self.os_window_map.get(os_window_id)
|
||||||
self.tab_manager.resize()
|
if tm is not None:
|
||||||
|
tm.resize()
|
||||||
|
|
||||||
def increase_font_size(self):
|
def increase_font_size(self):
|
||||||
self.change_font_size(
|
self.change_font_size(
|
||||||
@@ -136,18 +163,22 @@ class Boss:
|
|||||||
prerender()
|
prerender()
|
||||||
for window in windows:
|
for window in windows:
|
||||||
window.screen.rescale_images(old_cell_width, old_cell_height)
|
window.screen.rescale_images(old_cell_width, old_cell_height)
|
||||||
self.resize_windows_after_font_size_change()
|
|
||||||
for window in windows:
|
|
||||||
window.screen.refresh_sprite_positions()
|
window.screen.refresh_sprite_positions()
|
||||||
self.tab_manager.refresh_sprite_positions()
|
for tm in self.os_window_map.values():
|
||||||
|
tm.resize()
|
||||||
def resize_windows_after_font_size_change(self):
|
tm.refresh_sprite_positions()
|
||||||
self.tab_manager.resize()
|
|
||||||
glfw_post_empty_event()
|
glfw_post_empty_event()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def active_tab_manager(self):
|
||||||
|
os_window_id = current_os_window()
|
||||||
|
return self.os_window_map.get(os_window_id)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def active_tab(self):
|
def active_tab(self):
|
||||||
return self.tab_manager.active_tab
|
tm = self.active_tab_manager
|
||||||
|
if tm is not None:
|
||||||
|
return tm.active_tab
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def active_window(self):
|
def active_window(self):
|
||||||
@@ -186,16 +217,20 @@ class Boss:
|
|||||||
for key_action in actions:
|
for key_action in actions:
|
||||||
self.dispatch_action(key_action)
|
self.dispatch_action(key_action)
|
||||||
|
|
||||||
def on_focus(self, window, focused):
|
def on_focus(self, os_window_id, focused):
|
||||||
# WIN: Port this
|
tm = self.os_window_map.get(os_window_id)
|
||||||
self.window_is_focused = focused
|
if tm is not None:
|
||||||
w = self.active_window
|
w = tm.active_window
|
||||||
if w is not None:
|
if w is not None:
|
||||||
w.focus_changed(focused)
|
w.focus_changed(focused)
|
||||||
|
|
||||||
def on_os_window_closed(self, os_window_id, viewport_width, viewport_height):
|
def on_os_window_closed(self, os_window_id, viewport_width, viewport_height):
|
||||||
# WIN: Implement this
|
|
||||||
cached_values['window-size'] = viewport_width, viewport_height
|
cached_values['window-size'] = viewport_width, viewport_height
|
||||||
|
for window_id in tuple(w.id for w in self.window_id_map.values() if getattr(w, 'os_window_id', None) == os_window_id):
|
||||||
|
self.window_id_map.pop(window_id, None)
|
||||||
|
tm = self.os_window_map.pop(os_window_id, None)
|
||||||
|
if tm is not None:
|
||||||
|
tm.destroy()
|
||||||
|
|
||||||
def display_scrollback(self, data):
|
def display_scrollback(self, data):
|
||||||
if self.opts.scrollback_in_new_tab:
|
if self.opts.scrollback_in_new_tab:
|
||||||
@@ -225,32 +260,16 @@ class Boss:
|
|||||||
if url:
|
if url:
|
||||||
open_url(url, self.opts.open_url_with)
|
open_url(url, self.opts.open_url_with)
|
||||||
|
|
||||||
def gui_close_window(self, window):
|
|
||||||
window.destroy()
|
|
||||||
for tab in self.tab_manager:
|
|
||||||
if window in tab:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
tab.remove_window(window)
|
|
||||||
if len(tab) == 0:
|
|
||||||
self.tab_manager.remove(tab)
|
|
||||||
tab.destroy()
|
|
||||||
if len(self.tab_manager) == 0:
|
|
||||||
if not self.shutting_down:
|
|
||||||
self.glfw_window.set_should_close(True)
|
|
||||||
glfw_post_empty_event()
|
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
self.shutting_down = True
|
self.shutting_down = True
|
||||||
self.child_monitor.shutdown()
|
self.child_monitor.shutdown()
|
||||||
wakeup()
|
wakeup()
|
||||||
self.child_monitor.join()
|
self.child_monitor.join()
|
||||||
self.tab_manager.destroy()
|
for tm in self.os_window_map.values():
|
||||||
|
tm.destroy()
|
||||||
|
self.os_window_map = {}
|
||||||
destroy_sprite_map()
|
destroy_sprite_map()
|
||||||
destroy_global_data()
|
destroy_global_data()
|
||||||
del self.tab_manager
|
|
||||||
del self.glfw_window
|
|
||||||
|
|
||||||
def paste_to_active_window(self, text):
|
def paste_to_active_window(self, text):
|
||||||
if text:
|
if text:
|
||||||
@@ -274,10 +293,14 @@ class Boss:
|
|||||||
set_primary_selection(text)
|
set_primary_selection(text)
|
||||||
|
|
||||||
def next_tab(self):
|
def next_tab(self):
|
||||||
self.tab_manager.next_tab()
|
tm = self.active_tab_manager
|
||||||
|
if tm is not None:
|
||||||
|
tm.next_tab()
|
||||||
|
|
||||||
def previous_tab(self):
|
def previous_tab(self):
|
||||||
self.tab_manager.next_tab(-1)
|
tm = self.active_tab_manager
|
||||||
|
if tm is not None:
|
||||||
|
tm.next_tab(-1)
|
||||||
|
|
||||||
def args_to_special_window(self, args):
|
def args_to_special_window(self, args):
|
||||||
args = list(args)
|
args = list(args)
|
||||||
@@ -311,7 +334,9 @@ class Boss:
|
|||||||
special_window = None
|
special_window = None
|
||||||
if args:
|
if args:
|
||||||
special_window = self.args_to_special_window(args)
|
special_window = self.args_to_special_window(args)
|
||||||
self.tab_manager.new_tab(special_window=special_window)
|
tm = self.active_tab_manager
|
||||||
|
if tm is not None:
|
||||||
|
tm.new_tab(special_window=special_window)
|
||||||
|
|
||||||
def new_window(self, *args):
|
def new_window(self, *args):
|
||||||
tab = self.active_tab
|
tab = self.active_tab
|
||||||
@@ -322,14 +347,17 @@ class Boss:
|
|||||||
tab.new_window()
|
tab.new_window()
|
||||||
|
|
||||||
def move_tab_forward(self):
|
def move_tab_forward(self):
|
||||||
self.tab_manager.move_tab(1)
|
tm = self.active_tab_manager
|
||||||
|
if tm is not None:
|
||||||
|
tm.move_tab(1)
|
||||||
|
|
||||||
def move_tab_backward(self):
|
def move_tab_backward(self):
|
||||||
self.tab_manager.move_tab(-1)
|
tm = self.active_tab_manager
|
||||||
|
if tm is not None:
|
||||||
|
tm.move_tab(-1)
|
||||||
|
|
||||||
def display_scrollback_in_new_tab(self, data):
|
def display_scrollback_in_new_tab(self, data):
|
||||||
self.tab_manager.new_tab(
|
tm = self.active_tab_manager
|
||||||
special_window=SpecialWindow(
|
if tm is not None:
|
||||||
|
tm.new_tab(special_window=SpecialWindow(
|
||||||
self.opts.scrollback_pager, data, _('History')))
|
self.opts.scrollback_pager, data, _('History')))
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|||||||
@@ -422,3 +422,14 @@ def save_cached_values():
|
|||||||
format(err),
|
format(err),
|
||||||
file=sys.stderr
|
file=sys.stderr
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def initial_window_size(opts):
|
||||||
|
w, h = opts.initial_window_width, opts.initial_window_height
|
||||||
|
if 'window-size' in cached_values and opts.remember_window_size:
|
||||||
|
ws = cached_values['window-size']
|
||||||
|
try:
|
||||||
|
w, h = map(int, ws)
|
||||||
|
except Exception:
|
||||||
|
safe_print('Invalid cached window size, ignoring', file=sys.stderr)
|
||||||
|
return w, h
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from gettext import gettext as _
|
|||||||
|
|
||||||
from .boss import Boss
|
from .boss import Boss
|
||||||
from .config import (
|
from .config import (
|
||||||
cached_values, load_cached_values, load_config, save_cached_values
|
initial_window_size, load_cached_values, load_config, save_cached_values
|
||||||
)
|
)
|
||||||
from .constants import (
|
from .constants import (
|
||||||
appname, defconf, isosx, iswayland, logo_data_file, str_version
|
appname, defconf, isosx, iswayland, logo_data_file, str_version
|
||||||
@@ -26,7 +26,7 @@ from .fonts.box_drawing import set_scale
|
|||||||
from .layout import all_layouts
|
from .layout import all_layouts
|
||||||
from .utils import (
|
from .utils import (
|
||||||
detach, end_startup_notification, get_logical_dpi,
|
detach, end_startup_notification, get_logical_dpi,
|
||||||
init_startup_notification, safe_print
|
init_startup_notification
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -142,13 +142,7 @@ def run_app(opts, args):
|
|||||||
set_scale(opts.box_drawing_scale)
|
set_scale(opts.box_drawing_scale)
|
||||||
set_options(opts, iswayland, args.debug_gl)
|
set_options(opts, iswayland, args.debug_gl)
|
||||||
load_cached_values()
|
load_cached_values()
|
||||||
w, h = opts.initial_window_width, opts.initial_window_height
|
w, h = initial_window_size()
|
||||||
if 'window-size' in cached_values and opts.remember_window_size:
|
|
||||||
ws = cached_values['window-size']
|
|
||||||
try:
|
|
||||||
w, h = map(int, ws)
|
|
||||||
except Exception:
|
|
||||||
safe_print('Invalid cached window size, ignoring', file=sys.stderr)
|
|
||||||
window_id = create_os_window(w, h, args.cls)
|
window_id = create_os_window(w, h, args.cls)
|
||||||
startup_ctx = init_startup_notification(window_id)
|
startup_ctx = init_startup_notification(window_id)
|
||||||
if isosx:
|
if isosx:
|
||||||
|
|||||||
@@ -341,6 +341,16 @@ PYWRAP1(viewport_for_window) {
|
|||||||
return Py_BuildValue("iiII", 400, 400, global_state.cell_width, global_state.cell_height);
|
return Py_BuildValue("iiII", 400, 400, global_state.cell_width, global_state.cell_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PYWRAP1(mark_os_window_for_close) {
|
||||||
|
id_type os_window_id;
|
||||||
|
int yes = 1;
|
||||||
|
PA("K|p", &os_window_id, &yes);
|
||||||
|
WITH_OS_WINDOW(os_window_id)
|
||||||
|
mark_os_window_for_close(os_window, yes ? true : false);
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
END_WITH_OS_WINDOW
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
PYWRAP1(set_window_render_data) {
|
PYWRAP1(set_window_render_data) {
|
||||||
#define A(name) &(d.name)
|
#define A(name) &(d.name)
|
||||||
@@ -402,6 +412,7 @@ THREE_ID_OBJ(update_window_title)
|
|||||||
THREE_ID(remove_window)
|
THREE_ID(remove_window)
|
||||||
PYWRAP1(add_tab) { return PyLong_FromUnsignedLongLong(add_tab(PyLong_AsUnsignedLongLong(args))); }
|
PYWRAP1(add_tab) { return PyLong_FromUnsignedLongLong(add_tab(PyLong_AsUnsignedLongLong(args))); }
|
||||||
PYWRAP1(add_window) { PyObject *title; id_type a, b; PA("KKO", &a, &b, &title); return PyLong_FromUnsignedLongLong(add_window(a, b, title)); }
|
PYWRAP1(add_window) { PyObject *title; id_type a, b; PA("KKO", &a, &b, &title); return PyLong_FromUnsignedLongLong(add_window(a, b, title)); }
|
||||||
|
PYWRAP0(current_os_window) { OSWindow *w = current_os_window(); if (!w) Py_RETURN_NONE; return PyLong_FromUnsignedLongLong(w->id); }
|
||||||
TWO_ID(remove_tab)
|
TWO_ID(remove_tab)
|
||||||
KI(set_active_tab)
|
KI(set_active_tab)
|
||||||
KKI(set_active_window)
|
KKI(set_active_window)
|
||||||
@@ -413,6 +424,7 @@ KK5I(add_borders_rect)
|
|||||||
#define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
|
#define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
|
||||||
|
|
||||||
static PyMethodDef module_methods[] = {
|
static PyMethodDef module_methods[] = {
|
||||||
|
MW(current_os_window, METH_NOARGS),
|
||||||
MW(set_options, METH_O),
|
MW(set_options, METH_O),
|
||||||
MW(handle_for_window_id, METH_VARARGS),
|
MW(handle_for_window_id, METH_VARARGS),
|
||||||
MW(set_logical_dpi, METH_VARARGS),
|
MW(set_logical_dpi, METH_VARARGS),
|
||||||
@@ -429,6 +441,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
MW(set_tab_bar_render_data, METH_VARARGS),
|
MW(set_tab_bar_render_data, METH_VARARGS),
|
||||||
MW(set_window_render_data, METH_VARARGS),
|
MW(set_window_render_data, METH_VARARGS),
|
||||||
MW(viewport_for_window, METH_O),
|
MW(viewport_for_window, METH_O),
|
||||||
|
MW(mark_os_window_for_close, METH_VARARGS),
|
||||||
MW(update_window_visibility, METH_VARARGS),
|
MW(update_window_visibility, METH_VARARGS),
|
||||||
MW(set_boss, METH_O),
|
MW(set_boss, METH_O),
|
||||||
MW(set_display_state, METH_VARARGS),
|
MW(set_display_state, METH_VARARGS),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import weakref
|
||||||
from collections import deque, namedtuple
|
from collections import deque, namedtuple
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
@@ -27,32 +28,32 @@ def SpecialWindow(cmd, stdin=None, override_title=None):
|
|||||||
|
|
||||||
class Tab: # {{{
|
class Tab: # {{{
|
||||||
|
|
||||||
def __init__(self, os_window_id, opts, args, on_title_change, session_tab=None, special_window=None):
|
def __init__(self, tab_manager, session_tab=None, special_window=None):
|
||||||
self.os_window_id = os_window_id
|
self.tab_manager_ref = weakref.ref(tab_manager)
|
||||||
self.id = add_tab(os_window_id, self.id)
|
self.os_window_id = tab_manager.os_window_id
|
||||||
|
self.id = add_tab(self.os_window_id, self.id)
|
||||||
if not self.id:
|
if not self.id:
|
||||||
raise Exception('No OS window with id {} found, or tab counter has wrapped'.format(os_window_id))
|
raise Exception('No OS window with id {} found, or tab counter has wrapped'.format(self.os_window_id))
|
||||||
self.opts, self.args = opts, args
|
self.opts, self.args = tab_manager.opts, tab_manager.args
|
||||||
self.name = getattr(session_tab, 'name', '')
|
self.name = getattr(session_tab, 'name', '')
|
||||||
self.on_title_change = on_title_change
|
self.enabled_layouts = list(getattr(session_tab, 'enabled_layouts', None) or self.opts.enabled_layouts)
|
||||||
self.enabled_layouts = list(getattr(session_tab, 'enabled_layouts', None) or opts.enabled_layouts)
|
self.borders = Borders(self.os_window_id, self.id, self.opts)
|
||||||
self.borders = Borders(self.os_window_id, self.id, opts)
|
|
||||||
self.windows = deque()
|
self.windows = deque()
|
||||||
self.active_window_idx = 0
|
self.active_window_idx = 0
|
||||||
for i, which in enumerate('first second third fourth fifth sixth seventh eighth ninth tenth'.split()):
|
for i, which in enumerate('first second third fourth fifth sixth seventh eighth ninth tenth'.split()):
|
||||||
setattr(self, which + '_window', partial(self.nth_window, num=i))
|
setattr(self, which + '_window', partial(self.nth_window, num=i))
|
||||||
if session_tab is None:
|
if session_tab is None:
|
||||||
self.cwd = args.directory
|
self.cwd = self.args.directory
|
||||||
sl = self.enabled_layouts[0]
|
sl = self.enabled_layouts[0]
|
||||||
self.current_layout = all_layouts[sl](opts, self.borders.border_width, self.windows)
|
self.current_layout = all_layouts[sl](self.opts, self.borders.border_width, self.windows)
|
||||||
if special_window is None:
|
if special_window is None:
|
||||||
self.new_window()
|
self.new_window()
|
||||||
else:
|
else:
|
||||||
self.new_special_window(special_window)
|
self.new_special_window(special_window)
|
||||||
else:
|
else:
|
||||||
self.cwd = session_tab.cwd or args.directory
|
self.cwd = session_tab.cwd or self.args.directory
|
||||||
l0 = session_tab.layout
|
l0 = session_tab.layout
|
||||||
self.current_layout = all_layouts[l0](opts, self.borders.border_width, self.windows)
|
self.current_layout = all_layouts[l0](self.opts, self.borders.border_width, self.windows)
|
||||||
self.startup(session_tab)
|
self.startup(session_tab)
|
||||||
|
|
||||||
def startup(self, session_tab):
|
def startup(self, session_tab):
|
||||||
@@ -70,7 +71,9 @@ class Tab: # {{{
|
|||||||
|
|
||||||
def title_changed(self, window):
|
def title_changed(self, window):
|
||||||
if window is self.active_window:
|
if window is self.active_window:
|
||||||
self.on_title_change(window.title)
|
tm = self.tab_manager_ref()
|
||||||
|
if tm is not None:
|
||||||
|
tm.title_changed(window.title)
|
||||||
|
|
||||||
def visible_windows(self):
|
def visible_windows(self):
|
||||||
for w in self.windows:
|
for w in self.windows:
|
||||||
@@ -83,9 +86,10 @@ class Tab: # {{{
|
|||||||
self.relayout_borders()
|
self.relayout_borders()
|
||||||
|
|
||||||
def relayout_borders(self):
|
def relayout_borders(self):
|
||||||
tm = get_boss().tab_manager
|
tm = self.tab_manager_ref()
|
||||||
self.borders(self.windows, self.active_window, self.current_layout,
|
if tm is not None:
|
||||||
tm.blank_rects, self.current_layout.needs_window_borders and len(self.windows) > 1)
|
self.borders(self.windows, self.active_window, self.current_layout,
|
||||||
|
tm.blank_rects, self.current_layout.needs_window_borders and len(self.windows) > 1)
|
||||||
|
|
||||||
def next_layout(self):
|
def next_layout(self):
|
||||||
if len(self.opts.enabled_layouts) > 1:
|
if len(self.opts.enabled_layouts) > 1:
|
||||||
@@ -195,6 +199,8 @@ class Tab: # {{{
|
|||||||
return window in self.windows
|
return window in self.windows
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
|
for w in self.windows:
|
||||||
|
w.destroy()
|
||||||
self.windows = deque()
|
self.windows = deque()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -285,15 +291,24 @@ class TabBar: # {{{
|
|||||||
|
|
||||||
class TabManager: # {{{
|
class TabManager: # {{{
|
||||||
|
|
||||||
def __init__(self, os_window_id, opts, args):
|
def __init__(self, os_window_id, opts, args, startup_session):
|
||||||
self.os_window_id = os_window_id
|
self.os_window_id = os_window_id
|
||||||
self.opts, self.args = opts, args
|
self.opts, self.args = opts, args
|
||||||
self.tabs = []
|
self.tabs = []
|
||||||
self.tab_bar = TabBar(opts)
|
self.tab_bar = TabBar(opts)
|
||||||
self.refresh_sprite_positions = self.tab_bar.screen.refresh_sprite_positions
|
|
||||||
self.tab_bar.layout(*self.tab_bar_layout_data)
|
self.tab_bar.layout(*self.tab_bar_layout_data)
|
||||||
self.active_tab_idx = 0
|
self.active_tab_idx = 0
|
||||||
|
|
||||||
|
for t in startup_session.tabs:
|
||||||
|
self._add_tab(Tab(self, session_tab=t))
|
||||||
|
self._set_active_tab(max(0, min(startup_session.active_tab_idx, len(self.tabs) - 1)))
|
||||||
|
if len(self.tabs) > 1:
|
||||||
|
self.tabbar_visibility_changed()
|
||||||
|
self.update_tab_bar()
|
||||||
|
|
||||||
|
def refresh_sprite_positions(self):
|
||||||
|
self.tab_bar.screen.refresh_sprite_positions()
|
||||||
|
|
||||||
def _add_tab(self, tab):
|
def _add_tab(self, tab):
|
||||||
self.tabs.append(tab)
|
self.tabs.append(tab)
|
||||||
|
|
||||||
@@ -309,14 +324,6 @@ class TabManager: # {{{
|
|||||||
self.resize(only_tabs=True)
|
self.resize(only_tabs=True)
|
||||||
glfw_post_empty_event()
|
glfw_post_empty_event()
|
||||||
|
|
||||||
def init(self, startup_session):
|
|
||||||
for t in startup_session.tabs:
|
|
||||||
self._add_tab(Tab(self.os_window_id, self.opts, self.args, self.title_changed, t))
|
|
||||||
self._set_active_tab(max(0, min(startup_session.active_tab_idx, len(self.tabs) - 1)))
|
|
||||||
if len(self.tabs) > 1:
|
|
||||||
self.tabbar_visibility_changed()
|
|
||||||
self.update_tab_bar()
|
|
||||||
|
|
||||||
def update_tab_bar(self):
|
def update_tab_bar(self):
|
||||||
if len(self.tabs) > 1:
|
if len(self.tabs) > 1:
|
||||||
self.tab_bar.update(self.tab_bar_data)
|
self.tab_bar.update(self.tab_bar_data)
|
||||||
@@ -362,7 +369,7 @@ class TabManager: # {{{
|
|||||||
def new_tab(self, special_window=None):
|
def new_tab(self, special_window=None):
|
||||||
needs_resize = len(self.tabs) == 1
|
needs_resize = len(self.tabs) == 1
|
||||||
idx = len(self.tabs)
|
idx = len(self.tabs)
|
||||||
self._add_tab(Tab(self.os_window_id, self.opts, self.args, self.title_changed, special_window=special_window))
|
self._add_tab(Tab(self, special_window=special_window))
|
||||||
self._set_active_tab(idx)
|
self._set_active_tab(idx)
|
||||||
self.update_tab_bar()
|
self.update_tab_bar()
|
||||||
if needs_resize:
|
if needs_resize:
|
||||||
@@ -400,15 +407,9 @@ class TabManager: # {{{
|
|||||||
def blank_rects(self):
|
def blank_rects(self):
|
||||||
return self.tab_bar.blank_rects if len(self.tabs) > 1 else ()
|
return self.tab_bar.blank_rects if len(self.tabs) > 1 else ()
|
||||||
|
|
||||||
def render(self):
|
|
||||||
if len(self.tabs) < 2:
|
|
||||||
return
|
|
||||||
self.tab_bar.render()
|
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
for t in self:
|
for t in self:
|
||||||
t.destroy()
|
t.destroy()
|
||||||
self.tab_bar.destroy()
|
self.tab_bar.destroy()
|
||||||
del self.tab_bar
|
del self.tab_bar
|
||||||
del self.refresh_sprite_positions
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|||||||
@@ -136,16 +136,6 @@ class Window:
|
|||||||
def close(self):
|
def close(self):
|
||||||
get_boss().close_window(self)
|
get_boss().close_window(self)
|
||||||
|
|
||||||
def on_child_death(self):
|
|
||||||
if self.destroyed:
|
|
||||||
return
|
|
||||||
self.destroyed = True
|
|
||||||
# Remove cycles so that screen is de-allocated immediately
|
|
||||||
boss = get_boss()
|
|
||||||
self.screen.reset_callbacks()
|
|
||||||
boss.gui_close_window(self)
|
|
||||||
self.screen = None
|
|
||||||
|
|
||||||
def send_text(self, *args):
|
def send_text(self, *args):
|
||||||
mode = keyboard_mode_name(self.screen)
|
mode = keyboard_mode_name(self.screen)
|
||||||
required_mode, text = args[-2:]
|
required_mode, text = args[-2:]
|
||||||
@@ -246,7 +236,11 @@ class Window:
|
|||||||
return ''.join(self.screen.text_for_selection())
|
return ''.join(self.screen.text_for_selection())
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
pass
|
self.destroyed = True
|
||||||
|
if self.screen is not None:
|
||||||
|
# Remove cycles so that screen is de-allocated immediately
|
||||||
|
self.screen.reset_callbacks()
|
||||||
|
self.screen = None
|
||||||
|
|
||||||
def buffer_as_ansi(self):
|
def buffer_as_ansi(self):
|
||||||
data = []
|
data = []
|
||||||
|
|||||||
Reference in New Issue
Block a user