Handle window resizing correctly
This commit is contained in:
parent
cc1a277eeb
commit
7161406ff3
@ -35,14 +35,14 @@ class Boss(Thread):
|
||||
pending_title_change = pending_icon_change = None
|
||||
pending_color_changes = {}
|
||||
|
||||
def __init__(self, window, opts, args):
|
||||
def __init__(self, window, window_width, window_height, opts, args):
|
||||
Thread.__init__(self, name='ChildMonitor')
|
||||
self.window, self.opts = window, opts
|
||||
self.action_queue = Queue()
|
||||
self.read_wakeup_fd, self.write_wakeup_fd = os.pipe2(os.O_NONBLOCK | os.O_CLOEXEC)
|
||||
self.tracker = ChangeTracker(self.mark_dirtied)
|
||||
self.char_grid = CharGrid(opts)
|
||||
self.screen = Screen(self.opts, self.tracker, self)
|
||||
self.char_grid = CharGrid(self.screen, opts, window_width, window_height)
|
||||
sclass = DebugStream if args.dump_commands else Stream
|
||||
self.stream = sclass(self.screen)
|
||||
self.write_buf = memoryview(b'')
|
||||
@ -53,7 +53,23 @@ class Boss(Thread):
|
||||
resize_pty(80, 24)
|
||||
|
||||
def on_window_resize(self, window, w, h):
|
||||
self.char_grid.on_resize(window, w, h)
|
||||
self.queue_action(self.resize_screen, w, h)
|
||||
|
||||
def resize_screen(self, w, h):
|
||||
self.char_grid.resize_screen(w, h)
|
||||
|
||||
def apply_opts(self, opts):
|
||||
self.opts = opts
|
||||
self.queue_action(self.apply_opts_to_screen)
|
||||
|
||||
def apply_opts_to_screen(self):
|
||||
self.screen.apply_opts(self.opts)
|
||||
self.char_grid.apply_opts(self.opts)
|
||||
self.char_grid.dirty_everything()
|
||||
|
||||
def queue_action(self, func, *args):
|
||||
self.action_queue.put((func, args))
|
||||
self.wakeup()
|
||||
|
||||
def render(self):
|
||||
if self.pending_title_change is not None:
|
||||
@ -76,7 +92,7 @@ class Boss(Thread):
|
||||
func, args = self.action_queue.get_nowait()
|
||||
except Empty:
|
||||
break
|
||||
getattr(self, func)(*args)
|
||||
func(*args)
|
||||
|
||||
def run(self):
|
||||
while not self.shutting_down:
|
||||
@ -130,15 +146,13 @@ class Boss(Thread):
|
||||
|
||||
def write_to_child(self, data):
|
||||
if data:
|
||||
self.action_queue.put(('queue_write', data))
|
||||
self.wakeup()
|
||||
self.queue_action(self.queue_write, data)
|
||||
|
||||
def queue_write(self, data):
|
||||
self.write_buf = memoryview(self.write_buf.tobytes() + data)
|
||||
|
||||
def mark_dirtied(self):
|
||||
self.action_queue.put(('update_screen', ()))
|
||||
self.wakeup()
|
||||
self.queue_action(self.update_screen)
|
||||
|
||||
def update_screen(self):
|
||||
changes = self.tracker.consolidate_changes()
|
||||
@ -155,7 +169,7 @@ class Boss(Thread):
|
||||
|
||||
def change_default_color(self, which, value):
|
||||
self.pending_color_changes[which] = value
|
||||
self.action_queue.put(('change_colors', ()))
|
||||
self.queue_action(self.change_colors)
|
||||
|
||||
def change_colors(self):
|
||||
self.char_grid.change_colors(self.pending_color_changes)
|
||||
|
||||
@ -7,66 +7,62 @@ from threading import Lock
|
||||
from .config import build_ansi_color_tables, to_color
|
||||
from .fonts import set_font_family
|
||||
|
||||
from OpenGL.arrays import ArrayDatatype
|
||||
from OpenGL.GL import (
|
||||
GL_ARRAY_BUFFER,
|
||||
GL_COLOR_BUFFER_BIT, GL_COMPILE_STATUS,
|
||||
GL_FALSE, GL_FLOAT, GL_FRAGMENT_SHADER,
|
||||
GL_LINK_STATUS, GL_RENDERER,
|
||||
GL_SHADING_LANGUAGE_VERSION,
|
||||
GL_STATIC_DRAW, GL_TEXTURE_2D, GL_TRIANGLES,
|
||||
GL_TRUE, GL_UNPACK_ALIGNMENT, GL_VENDOR, GL_VERSION,
|
||||
GL_VERTEX_SHADER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T,
|
||||
GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR, GL_RGB, GL_RGBA, GL_UNSIGNED_BYTE, GL_TEXTURE0,
|
||||
GL_REPEAT,
|
||||
glActiveTexture, glAttachShader,
|
||||
glBindBuffer, glBindTexture, glBindVertexArray,
|
||||
glBufferData, glClear, glClearColor,
|
||||
glCompileShader, glCreateProgram,
|
||||
glCreateShader, glDeleteProgram,
|
||||
glDeleteShader, glDrawArrays,
|
||||
glEnableVertexAttribArray, glGenBuffers, glGenTextures,
|
||||
glGenVertexArrays, glGetAttribLocation,
|
||||
glGetProgramInfoLog, glGetProgramiv,
|
||||
glGetShaderInfoLog, glGetShaderiv, glGetString,
|
||||
glGetUniformLocation, glLinkProgram, glPixelStorei,
|
||||
glShaderSource, glTexImage2D, glTexParameteri, glUniform1i, glUseProgram,
|
||||
glVertexAttribPointer, glViewport)
|
||||
import OpenGL.GL as gl
|
||||
|
||||
|
||||
class CharGrid:
|
||||
|
||||
def __init__(self, opts):
|
||||
def __init__(self, screen, opts, window_width, window_height):
|
||||
self.width, self.height = window_width, window_height
|
||||
self.screen = screen
|
||||
self.apply_opts(opts)
|
||||
self.lock = Lock()
|
||||
self.dirty_everything()
|
||||
self.default_bg, self.default_fg = self.original_bg, self.original_fg
|
||||
self.resize_lock = Lock()
|
||||
self.apply_resize_to_screen(self.width, self.height)
|
||||
|
||||
def apply_clear_color(self):
|
||||
bg = self.default_bg
|
||||
glClearColor(bg[0]/255, bg[1]/255, bg[2]/255, 1)
|
||||
def dirty_everything(self):
|
||||
self.cell_resize_pending = True
|
||||
self.clear_color_changed = True
|
||||
self.resize_pending = self.width, self.height
|
||||
|
||||
def apply_opts(self, opts):
|
||||
self.opts = opts
|
||||
build_ansi_color_tables(opts)
|
||||
self.opts = opts
|
||||
self.default_bg = self.original_bg = opts.background
|
||||
self.default_fg = self.original_fg = opts.foreground
|
||||
self.original_bg = opts.background
|
||||
self.original_fg = opts.foreground
|
||||
self.cell_width, self.cell_height = set_font_family(opts.font_family, opts.font_size)
|
||||
self.apply_clear_color()
|
||||
|
||||
def on_resize(self, window, w, h):
|
||||
glViewport(0, 0, w, h)
|
||||
self.do_layout(w, h)
|
||||
def apply_resize_to_screen(self, w, h):
|
||||
cells_per_line = w // self.cell_width
|
||||
lines_per_screen = h // self.cell_height
|
||||
self.screen.resize(lines_per_screen, cells_per_line)
|
||||
|
||||
def resize_screen(self, w, h):
|
||||
' Screen was resized by the user (called in non-UI thread) '
|
||||
with self.resize_lock:
|
||||
self.apply_resize_to_screen(w, h)
|
||||
self.resize_pending = w, h
|
||||
|
||||
def do_layout(self, w, h):
|
||||
pass
|
||||
|
||||
def redraw(self):
|
||||
pass
|
||||
self.width, self.height = w, h
|
||||
self.cells_per_line = w // self.cell_width
|
||||
self.lines_per_screen = h // self.cell_height
|
||||
if self.cell_resize_pending:
|
||||
self.cell_resize_pending = False
|
||||
|
||||
def render(self):
|
||||
with self.lock:
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
with self.resize_lock:
|
||||
if self.resize_pending:
|
||||
self.do_layout(*self.resize_pending)
|
||||
gl.glViewport(0, 0, self.width, self.height)
|
||||
self.resize_pending = None
|
||||
if self.clear_color_changed:
|
||||
bg = self.default_bg
|
||||
self.clear_color_changed = False
|
||||
gl.glClearColor(bg[0]/255, bg[1]/255, bg[2]/255, 1)
|
||||
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
|
||||
|
||||
def change_colors(self, changes):
|
||||
dirtied = False
|
||||
@ -81,8 +77,9 @@ class CharGrid:
|
||||
setattr(self, 'default_' + which, val)
|
||||
dirtied = True
|
||||
if dirtied:
|
||||
self.apply_clear_color()
|
||||
self.redraw()
|
||||
self.clear_color_changed = True
|
||||
self.update_screen()
|
||||
|
||||
def update_screen(self, changes):
|
||||
self.redraw()
|
||||
def update_screen(self, changes=None):
|
||||
if changes is None:
|
||||
changes = {'screen': True}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import os
|
||||
from PyQt5.QtCore import QStandardPaths
|
||||
import threading
|
||||
|
||||
appname = 'kitty'
|
||||
version = (0, 1, 0)
|
||||
@ -15,10 +15,7 @@ def _get_config_dir():
|
||||
if 'KITTY_CONFIG_DIRECTORY' in os.environ:
|
||||
return os.path.abspath(os.path.expanduser(os.environ['VISE_CONFIG_DIRECTORY']))
|
||||
|
||||
candidate = QStandardPaths.writableLocation(QStandardPaths.ConfigLocation)
|
||||
if not candidate:
|
||||
raise RuntimeError(
|
||||
'Failed to find path for application config directory')
|
||||
candidate = os.path.abspath(os.path.expanduser(os.environ.get('XDG_CONFIG_HOME') or '~/.config'))
|
||||
ans = os.path.join(candidate, appname)
|
||||
try:
|
||||
os.makedirs(ans)
|
||||
@ -29,3 +26,4 @@ config_dir = _get_config_dir()
|
||||
del _get_config_dir
|
||||
|
||||
terminfo_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'terminfo')
|
||||
main_thread = threading.current_thread()
|
||||
|
||||
@ -43,15 +43,16 @@ def setup_opengl():
|
||||
|
||||
def run_app(opts, args):
|
||||
setup_opengl()
|
||||
window_width = window_height = 1024
|
||||
window = glfw.glfwCreateWindow(
|
||||
1024, 1024, args.cls.encode('utf-8'), None, None)
|
||||
window_width, window_height, args.cls.encode('utf-8'), None, None)
|
||||
if not window:
|
||||
raise SystemExit("glfwCreateWindow failed")
|
||||
glfw.glfwSetWindowTitle(window, appname.encode('utf-8'))
|
||||
try:
|
||||
glfw.glfwMakeContextCurrent(window)
|
||||
glfw.glfwSwapInterval(1)
|
||||
boss = Boss(window, opts, args)
|
||||
boss = Boss(window, window_width, window_height, opts, args)
|
||||
glfw.glfwSetFramebufferSizeCallback(window, boss.on_window_resize)
|
||||
boss.start()
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user