Allow specifying initial window size in number of cells
This commit is contained in:
parent
fe8cf46d56
commit
997c244664
@ -12,7 +12,7 @@ from weakref import WeakValueDictionary
|
|||||||
|
|
||||||
from .cli import create_opts, parse_args
|
from .cli import create_opts, parse_args
|
||||||
from .config import (
|
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 .config_utils import to_cmdline
|
||||||
from .constants import (
|
from .constants import (
|
||||||
@ -99,11 +99,11 @@ class Boss:
|
|||||||
startup_session = create_session(opts, args)
|
startup_session = create_session(opts, args)
|
||||||
self.add_os_window(startup_session, os_window_id=os_window_id)
|
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:
|
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
|
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:
|
if startup_id:
|
||||||
ctx = init_startup_notification(os_window_id, startup_id)
|
ctx = init_startup_notification(os_window_id, startup_id)
|
||||||
show_window(os_window_id)
|
show_window(os_window_id)
|
||||||
@ -238,7 +238,7 @@ class Boss:
|
|||||||
if not os.path.isabs(args.directory):
|
if not os.path.isabs(args.directory):
|
||||||
args.directory = os.path.join(msg['cwd'], args.directory)
|
args.directory = os.path.join(msg['cwd'], args.directory)
|
||||||
session = create_session(opts, args, respect_cwd=True)
|
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:
|
else:
|
||||||
log_error('Unknown message received from peer, ignoring')
|
log_error('Unknown message received from peer, ignoring')
|
||||||
|
|
||||||
|
|||||||
@ -361,6 +361,12 @@ def url_style(x):
|
|||||||
return url_style.map.get(x, url_style.map['curly'])
|
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(
|
url_style.map = dict(
|
||||||
((v, i) for i, v in enumerate('none single double curly'.split()))
|
((v, i) for i, v in enumerate('none single double curly'.split()))
|
||||||
)
|
)
|
||||||
@ -393,8 +399,8 @@ type_map = {
|
|||||||
'cursor_stop_blinking_after': positive_float,
|
'cursor_stop_blinking_after': positive_float,
|
||||||
'enabled_layouts': to_layout_names,
|
'enabled_layouts': to_layout_names,
|
||||||
'remember_window_size': to_bool,
|
'remember_window_size': to_bool,
|
||||||
'initial_window_width': positive_int,
|
'initial_window_width': window_size,
|
||||||
'initial_window_height': positive_int,
|
'initial_window_height': window_size,
|
||||||
'macos_hide_titlebar': to_bool,
|
'macos_hide_titlebar': to_bool,
|
||||||
'macos_hide_from_tasks': to_bool,
|
'macos_hide_from_tasks': to_bool,
|
||||||
'macos_option_as_alt': to_bool,
|
'macos_option_as_alt': to_bool,
|
||||||
@ -549,15 +555,34 @@ def cached_values_for(name):
|
|||||||
err))
|
err))
|
||||||
|
|
||||||
|
|
||||||
def initial_window_size(opts, cached_values):
|
def initial_window_size_func(opts, cached_values):
|
||||||
w, h = opts.initial_window_width, opts.initial_window_height
|
|
||||||
if 'window-size' in cached_values and opts.remember_window_size:
|
if 'window-size' in cached_values and opts.remember_window_size:
|
||||||
ws = cached_values['window-size']
|
ws = cached_values['window-size']
|
||||||
try:
|
try:
|
||||||
w, h = map(int, ws)
|
w, h = map(int, ws)
|
||||||
|
|
||||||
|
def initial_window_size(*a):
|
||||||
|
return w, h
|
||||||
|
return initial_window_size
|
||||||
except Exception:
|
except Exception:
|
||||||
log_error('Invalid cached window size, ignoring')
|
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():
|
def commented_out_default_config():
|
||||||
|
|||||||
@ -1123,11 +1123,10 @@ initialize_font_group(FontGroup *fg) {
|
|||||||
send_prerendered_sprites(fg);
|
send_prerendered_sprites(fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
FONTS_DATA_HANDLE
|
||||||
load_fonts_for_window(OSWindow *w) {
|
load_fonts_data(double font_sz_in_pts, double dpi_x, double dpi_y) {
|
||||||
w->fonts_data = NULL;
|
FontGroup *fg = font_group_for(font_sz_in_pts, dpi_x, dpi_y);
|
||||||
FontGroup *fg = font_group_for(w->font_sz_in_pts, w->logical_dpi_x, w->logical_dpi_y);
|
return (FONTS_DATA_HANDLE)fg;
|
||||||
w->fonts_data = (FONTS_DATA_HANDLE)fg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
53
kitty/glfw.c
53
kitty/glfw.c
@ -303,11 +303,10 @@ current_monitor(GLFWwindow *window) {
|
|||||||
return bestmonitor;
|
return bestmonitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
void
|
get_window_dpi(GLFWwindow *w, double *x, double *y) {
|
||||||
set_os_window_dpi(OSWindow *w) {
|
|
||||||
GLFWmonitor *monitor = NULL;
|
GLFWmonitor *monitor = NULL;
|
||||||
if (w && w->handle) { monitor = current_monitor(w->handle); }
|
if (w) monitor = current_monitor(w);
|
||||||
if (monitor == NULL) monitor = glfwGetPrimaryMonitor();
|
if (monitor == NULL) monitor = glfwGetPrimaryMonitor();
|
||||||
float xscale = 1, yscale = 1;
|
float xscale = 1, yscale = 1;
|
||||||
if (monitor) glfwGetMonitorContentScale(monitor, &xscale, &yscale);
|
if (monitor) glfwGetMonitorContentScale(monitor, &xscale, &yscale);
|
||||||
@ -316,8 +315,13 @@ set_os_window_dpi(OSWindow *w) {
|
|||||||
#else
|
#else
|
||||||
double factor = 96.0;
|
double factor = 96.0;
|
||||||
#endif
|
#endif
|
||||||
w->logical_dpi_x = xscale * factor;
|
*x = xscale * factor;
|
||||||
w->logical_dpi_y = yscale * 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;
|
static bool is_first_window = true;
|
||||||
@ -341,10 +345,10 @@ set_titlebar_color(OSWindow *w, color_type color) {
|
|||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
create_os_window(PyObject UNUSED *self, PyObject *args) {
|
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;
|
char *title, *wm_class_class, *wm_class_name;
|
||||||
PyObject *load_programs = NULL;
|
PyObject *load_programs = NULL, *get_window_size;
|
||||||
if (!PyArg_ParseTuple(args, "iisss|Oii", &width, &height, &title, &wm_class_name, &wm_class_class, &load_programs, &x, &y)) return NULL;
|
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) {
|
if (is_first_window) {
|
||||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
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);
|
bool want_semi_transparent = (1.0 - OPT(background_opacity) >= 0.01) || OPT(dynamic_background_opacity);
|
||||||
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, want_semi_transparent);
|
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);
|
// We use a temp window to avoid the need to set the window size after
|
||||||
if (glfw_window == NULL) {
|
// creation, which causes a resize event and all the associated processing.
|
||||||
log_error("Failed to create a window at size: %dx%d, using a standard size instead.", width, height);
|
// The temp window is used to get the DPI.
|
||||||
glfw_window = glfwCreateWindow(640, 400, title, NULL, global_state.num_os_windows ? global_state.os_windows[0].handle : NULL);
|
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; }
|
if (glfw_window == NULL) { PyErr_SetString(PyExc_ValueError, "Failed to create GLFWwindow"); return NULL; }
|
||||||
glfwMakeContextCurrent(glfw_window);
|
glfwMakeContextCurrent(glfw_window);
|
||||||
if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y);
|
if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y);
|
||||||
current_os_window_ctx = glfw_window;
|
current_os_window_ctx = glfw_window;
|
||||||
glfwSwapInterval(OPT(sync_to_monitor) ? 1 : 0); // a value of 1 makes mouse selection laggy
|
glfwSwapInterval(OPT(sync_to_monitor) ? 1 : 0); // a value of 1 makes mouse selection laggy
|
||||||
if (is_first_window) {
|
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__
|
#ifdef __APPLE__
|
||||||
cocoa_create_global_menu();
|
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.
|
// 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;
|
OSWindow *q = global_state.os_windows + i;
|
||||||
q->is_focused = q == w ? true : false;
|
q->is_focused = q == w ? true : false;
|
||||||
}
|
}
|
||||||
set_os_window_dpi(w);
|
w->logical_dpi_x = dpi_x; w->logical_dpi_y = dpi_y;
|
||||||
load_fonts_for_window(w);
|
w->fonts_data = fonts_data;
|
||||||
if (logo.pixels && logo.width && logo.height) glfwSetWindowIcon(glfw_window, 1, &logo);
|
if (logo.pixels && logo.width && logo.height) glfwSetWindowIcon(glfw_window, 1, &logo);
|
||||||
glfwSetCursor(glfw_window, standard_cursor);
|
glfwSetCursor(glfw_window, standard_cursor);
|
||||||
update_os_window_viewport(w, false);
|
update_os_window_viewport(w, false);
|
||||||
|
|||||||
@ -177,7 +177,8 @@ bell_on_tab yes
|
|||||||
# Window layout {{{
|
# Window layout {{{
|
||||||
# If enabled, the window size will be remembered so that new instances of kitty will have the same
|
# 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
|
# 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
|
remember_window_size yes
|
||||||
initial_window_width 640
|
initial_window_width 640
|
||||||
initial_window_height 400
|
initial_window_height 400
|
||||||
|
|||||||
@ -10,7 +10,7 @@ from contextlib import contextmanager
|
|||||||
from .borders import load_borders_program
|
from .borders import load_borders_program
|
||||||
from .boss import Boss
|
from .boss import Boss
|
||||||
from .cli import create_opts, parse_args
|
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 (
|
from .constants import (
|
||||||
appname, config_dir, glfw_path, is_macos, is_wayland, logo_data_file
|
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_options(opts, is_wayland, args.debug_gl, args.debug_font_fallback)
|
||||||
set_font_family(opts)
|
set_font_family(opts)
|
||||||
with cached_values_for(run_app.cached_values_name) as cached_values:
|
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(
|
||||||
window_id = create_os_window(w, h, appname, args.name or args.cls or appname, args.cls or appname, load_all_shaders)
|
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)
|
run_app.first_window_callback(opts, window_id)
|
||||||
startup_ctx = init_startup_notification(window_id)
|
startup_ctx = init_startup_notification(window_id)
|
||||||
show_window(window_id)
|
show_window(window_id)
|
||||||
@ -63,7 +65,7 @@ def run_app(opts, args):
|
|||||||
|
|
||||||
run_app.cached_values_name = 'main'
|
run_app.cached_values_name = 'main'
|
||||||
run_app.first_window_callback = lambda opts, window_id: None
|
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():
|
def ensure_osx_locale():
|
||||||
|
|||||||
@ -626,7 +626,8 @@ PYWRAP1(os_window_font_size) {
|
|||||||
WITH_OS_WINDOW(os_window_id)
|
WITH_OS_WINDOW(os_window_id)
|
||||||
if (new_sz > 0 && (force || new_sz != os_window->font_sz_in_pts)) {
|
if (new_sz > 0 && (force || new_sz != os_window->font_sz_in_pts)) {
|
||||||
os_window->font_sz_in_pts = new_sz;
|
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);
|
resize_screen(os_window, os_window->tab_bar_render_data.screen, false);
|
||||||
for (size_t ti = 0; ti < os_window->num_tabs; ti++) {
|
for (size_t ti = 0; ti < os_window->num_tabs; ti++) {
|
||||||
Tab *tab = os_window->tabs + ti;
|
Tab *tab = os_window->tabs + ti;
|
||||||
|
|||||||
@ -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_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 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 set_titlebar_color(OSWindow *w, color_type color);
|
||||||
void load_fonts_for_window(OSWindow*);
|
FONTS_DATA_HANDLE load_fonts_data(double, double, double);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user