Allow specifying initial window size in number of cells

This commit is contained in:
Kovid Goyal 2018-05-26 09:15:23 +05:30
parent fe8cf46d56
commit 997c244664
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
8 changed files with 84 additions and 41 deletions

View File

@ -12,7 +12,7 @@ from weakref import WeakValueDictionary
from .cli import create_opts, parse_args
from .config import (
MINIMUM_FONT_SIZE, initial_window_size, prepare_config_file_for_editing
MINIMUM_FONT_SIZE, initial_window_size_func, prepare_config_file_for_editing
)
from .config_utils import to_cmdline
from .constants import (
@ -99,11 +99,11 @@ class Boss:
startup_session = create_session(opts, args)
self.add_os_window(startup_session, os_window_id=os_window_id)
def add_os_window(self, startup_session, os_window_id=None, wclass=None, wname=None, size=None, startup_id=None):
def add_os_window(self, startup_session, os_window_id=None, wclass=None, wname=None, opts_for_size=None, startup_id=None):
if os_window_id is None:
w, h = initial_window_size(self.opts, self.cached_values) if size is None else size
opts_for_size = opts_for_size or self.opts
cls = wclass or self.args.cls or appname
os_window_id = create_os_window(w, h, appname, wname or self.args.name or cls, cls)
os_window_id = create_os_window(initial_window_size_func(opts_for_size, self.cached_values), appname, wname or self.args.name or cls, cls)
if startup_id:
ctx = init_startup_notification(os_window_id, startup_id)
show_window(os_window_id)
@ -238,7 +238,7 @@ class Boss:
if not os.path.isabs(args.directory):
args.directory = os.path.join(msg['cwd'], args.directory)
session = create_session(opts, args, respect_cwd=True)
self.add_os_window(session, wclass=args.cls, wname=args.name, size=initial_window_size(opts, self.cached_values), startup_id=startup_id)
self.add_os_window(session, wclass=args.cls, wname=args.name, opts_for_size=opts, startup_id=startup_id)
else:
log_error('Unknown message received from peer, ignoring')

View File

@ -361,6 +361,12 @@ def url_style(x):
return url_style.map.get(x, url_style.map['curly'])
def window_size(val):
val = val.lower()
unit = 'cells' if val.endswith('c') else 'px'
return positive_int(val.rstrip('c')), unit
url_style.map = dict(
((v, i) for i, v in enumerate('none single double curly'.split()))
)
@ -393,8 +399,8 @@ type_map = {
'cursor_stop_blinking_after': positive_float,
'enabled_layouts': to_layout_names,
'remember_window_size': to_bool,
'initial_window_width': positive_int,
'initial_window_height': positive_int,
'initial_window_width': window_size,
'initial_window_height': window_size,
'macos_hide_titlebar': to_bool,
'macos_hide_from_tasks': to_bool,
'macos_option_as_alt': to_bool,
@ -549,15 +555,34 @@ def cached_values_for(name):
err))
def initial_window_size(opts, cached_values):
w, h = opts.initial_window_width, opts.initial_window_height
def initial_window_size_func(opts, cached_values):
if 'window-size' in cached_values and opts.remember_window_size:
ws = cached_values['window-size']
try:
w, h = map(int, ws)
def initial_window_size(*a):
return w, h
return initial_window_size
except Exception:
log_error('Invalid cached window size, ignoring')
return w, h
w, w_unit = opts.initial_window_width
h, h_unit = opts.initial_window_height
def get_window_size(cell_width, cell_height, dpi_x, dpi_y):
if w_unit == 'cells':
width = cell_width * w + (dpi_x / 72) * (opts.window_margin_width + opts.window_padding_width) + 1
else:
width = w
if h_unit == 'cells':
height = cell_height * h + (dpi_y / 72) * (opts.window_margin_width + opts.window_padding_width) + 1
else:
height = h
return width, height
return get_window_size
def commented_out_default_config():

View File

@ -1123,11 +1123,10 @@ initialize_font_group(FontGroup *fg) {
send_prerendered_sprites(fg);
}
void
load_fonts_for_window(OSWindow *w) {
w->fonts_data = NULL;
FontGroup *fg = font_group_for(w->font_sz_in_pts, w->logical_dpi_x, w->logical_dpi_y);
w->fonts_data = (FONTS_DATA_HANDLE)fg;
FONTS_DATA_HANDLE
load_fonts_data(double font_sz_in_pts, double dpi_x, double dpi_y) {
FontGroup *fg = font_group_for(font_sz_in_pts, dpi_x, dpi_y);
return (FONTS_DATA_HANDLE)fg;
}
static void

View File

@ -303,11 +303,10 @@ current_monitor(GLFWwindow *window) {
return bestmonitor;
}
void
set_os_window_dpi(OSWindow *w) {
static inline void
get_window_dpi(GLFWwindow *w, double *x, double *y) {
GLFWmonitor *monitor = NULL;
if (w && w->handle) { monitor = current_monitor(w->handle); }
if (w) monitor = current_monitor(w);
if (monitor == NULL) monitor = glfwGetPrimaryMonitor();
float xscale = 1, yscale = 1;
if (monitor) glfwGetMonitorContentScale(monitor, &xscale, &yscale);
@ -316,8 +315,13 @@ set_os_window_dpi(OSWindow *w) {
#else
double factor = 96.0;
#endif
w->logical_dpi_x = xscale * factor;
w->logical_dpi_y = yscale * factor;
*x = xscale * factor;
*y = yscale * factor;
}
void
set_os_window_dpi(OSWindow *w) {
get_window_dpi(w->handle, &w->logical_dpi_x, &w->logical_dpi_y);
}
static bool is_first_window = true;
@ -341,10 +345,10 @@ set_titlebar_color(OSWindow *w, color_type color) {
static PyObject*
create_os_window(PyObject UNUSED *self, PyObject *args) {
int width, height, x = -1, y = -1;
int x = -1, y = -1;
char *title, *wm_class_class, *wm_class_name;
PyObject *load_programs = NULL;
if (!PyArg_ParseTuple(args, "iisss|Oii", &width, &height, &title, &wm_class_name, &wm_class_class, &load_programs, &x, &y)) return NULL;
PyObject *load_programs = NULL, *get_window_size;
if (!PyArg_ParseTuple(args, "Osss|Oii", &get_window_size, &title, &wm_class_name, &wm_class_class, &load_programs, &x, &y)) return NULL;
if (is_first_window) {
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
@ -379,21 +383,32 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
}
bool want_semi_transparent = (1.0 - OPT(background_opacity) >= 0.01) || OPT(dynamic_background_opacity);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, want_semi_transparent);
GLFWwindow *glfw_window = glfwCreateWindow(width, height, title, NULL, global_state.num_os_windows ? global_state.os_windows[0].handle : NULL);
if (glfw_window == NULL) {
log_error("Failed to create a window at size: %dx%d, using a standard size instead.", width, height);
glfw_window = glfwCreateWindow(640, 400, title, NULL, global_state.num_os_windows ? global_state.os_windows[0].handle : NULL);
// We use a temp window to avoid the need to set the window size after
// creation, which causes a resize event and all the associated processing.
// The temp window is used to get the DPI.
GLFWwindow *temp_window = glfwCreateWindow(640, 480, "temp", NULL, global_state.num_os_windows ? global_state.os_windows[0].handle : NULL);
double dpi_x, dpi_y;
get_window_dpi(temp_window, &dpi_x, &dpi_y);
glfwMakeContextCurrent(temp_window);
if (is_first_window) {
gl_init();
PyObject *ret = PyObject_CallFunction(load_programs, "i", glfwGetWindowAttrib(temp_window, GLFW_TRANSPARENT_FRAMEBUFFER));
if (ret == NULL) return NULL;
Py_DECREF(ret);
}
FONTS_DATA_HANDLE fonts_data = load_fonts_data(global_state.font_sz_in_pts, dpi_x, dpi_y);
PyObject *ret = PyObject_CallFunction(get_window_size, "IIdd", fonts_data->cell_width, fonts_data->cell_height, fonts_data->logical_dpi_x, fonts_data->logical_dpi_y);
if (ret == NULL) return NULL;
int width = PyLong_AsLong(PyTuple_GET_ITEM(ret, 0)), height = PyLong_AsLong(PyTuple_GET_ITEM(ret, 1));
Py_CLEAR(ret);
GLFWwindow *glfw_window = glfwCreateWindow(width, height, title, NULL, temp_window);
glfwDestroyWindow(temp_window); temp_window = NULL;
if (glfw_window == NULL) { PyErr_SetString(PyExc_ValueError, "Failed to create GLFWwindow"); return NULL; }
glfwMakeContextCurrent(glfw_window);
if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y);
current_os_window_ctx = glfw_window;
glfwSwapInterval(OPT(sync_to_monitor) ? 1 : 0); // a value of 1 makes mouse selection laggy
if (is_first_window) {
gl_init();
PyObject *ret = PyObject_CallFunction(load_programs, "i", glfwGetWindowAttrib(glfw_window, GLFW_TRANSPARENT_FRAMEBUFFER));
if (ret == NULL) return NULL;
Py_DECREF(ret);
#ifdef __APPLE__
cocoa_create_global_menu();
// This needs to be done only after the first window has been created, because glfw only sets the activation policy once upon initialization.
@ -413,8 +428,8 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
OSWindow *q = global_state.os_windows + i;
q->is_focused = q == w ? true : false;
}
set_os_window_dpi(w);
load_fonts_for_window(w);
w->logical_dpi_x = dpi_x; w->logical_dpi_y = dpi_y;
w->fonts_data = fonts_data;
if (logo.pixels && logo.width && logo.height) glfwSetWindowIcon(glfw_window, 1, &logo);
glfwSetCursor(glfw_window, standard_cursor);
update_os_window_viewport(w, false);

View File

@ -177,7 +177,8 @@ bell_on_tab yes
# Window layout {{{
# If enabled, the window size will be remembered so that new instances of kitty will have the same
# size as the previous instance. If disabled, the window will initially have size configured
# by initial_window_width/height, in pixels.
# by initial_window_width/height, in pixels. You can use a suffix of "c" on the width/height values
# to have them interpreted as number of cells instead of pixels.
remember_window_size yes
initial_window_width 640
initial_window_height 400

View File

@ -10,7 +10,7 @@ from contextlib import contextmanager
from .borders import load_borders_program
from .boss import Boss
from .cli import create_opts, parse_args
from .config import cached_values_for, initial_window_size
from .config import cached_values_for, initial_window_size_func
from .constants import (
appname, config_dir, glfw_path, is_macos, is_wayland, logo_data_file
)
@ -44,8 +44,10 @@ def run_app(opts, args):
set_options(opts, is_wayland, args.debug_gl, args.debug_font_fallback)
set_font_family(opts)
with cached_values_for(run_app.cached_values_name) as cached_values:
w, h = run_app.initial_window_size(opts, cached_values)
window_id = create_os_window(w, h, appname, args.name or args.cls or appname, args.cls or appname, load_all_shaders)
window_id = create_os_window(
run_app.initial_window_size_func(opts, cached_values),
appname, args.name or args.cls or appname,
args.cls or appname, load_all_shaders)
run_app.first_window_callback(opts, window_id)
startup_ctx = init_startup_notification(window_id)
show_window(window_id)
@ -63,7 +65,7 @@ def run_app(opts, args):
run_app.cached_values_name = 'main'
run_app.first_window_callback = lambda opts, window_id: None
run_app.initial_window_size = initial_window_size
run_app.initial_window_size_func = initial_window_size_func
def ensure_osx_locale():

View File

@ -626,7 +626,8 @@ PYWRAP1(os_window_font_size) {
WITH_OS_WINDOW(os_window_id)
if (new_sz > 0 && (force || new_sz != os_window->font_sz_in_pts)) {
os_window->font_sz_in_pts = new_sz;
load_fonts_for_window(os_window);
os_window->fonts_data = NULL;
os_window->fonts_data = load_fonts_data(os_window->font_sz_in_pts, os_window->logical_dpi_x, os_window->logical_dpi_y);
resize_screen(os_window, os_window->tab_bar_render_data.screen, false);
for (size_t ti = 0; ti < os_window->num_tabs; ti++) {
Tab *tab = os_window->tabs + ti;

View File

@ -186,4 +186,4 @@ void free_texture(uint32_t*);
void send_image_to_gpu(uint32_t*, const void*, int32_t, int32_t, bool, bool);
void send_sprite_to_gpu(FONTS_DATA_HANDLE fg, unsigned int, unsigned int, unsigned int, pixel*);
void set_titlebar_color(OSWindow *w, color_type color);
void load_fonts_for_window(OSWindow*);
FONTS_DATA_HANDLE load_fonts_data(double, double, double);