Move logical DPI calculation into glfw module
Now DPI state is maintained in only one central place.
This commit is contained in:
parent
c7e1a12eb6
commit
684a2e05f4
@ -7,7 +7,7 @@ import os
|
||||
from functools import partial as p
|
||||
from itertools import repeat
|
||||
|
||||
from kitty.utils import get_logical_dpi
|
||||
from kitty.fast_data_types import pt_to_px_ceil
|
||||
|
||||
scale = (0.001, 1, 1.5, 2)
|
||||
|
||||
@ -18,9 +18,8 @@ def set_scale(new_scale):
|
||||
|
||||
|
||||
def thickness(level=1, horizontal=True):
|
||||
dpi = get_logical_dpi()[0 if horizontal else 1]
|
||||
pts = scale[level]
|
||||
return int(math.ceil(pts * dpi / 72.0))
|
||||
return pt_to_px_ceil(pts)
|
||||
|
||||
|
||||
def draw_hline(buf, width, x1, x2, y, level):
|
||||
|
||||
@ -170,7 +170,6 @@ def render_box_drawing(codepoint):
|
||||
|
||||
|
||||
def setup_for_testing(family='monospace', size=11.0, dpi=96.0):
|
||||
from kitty.utils import get_logical_dpi
|
||||
opts = defaults._replace(font_family=family)
|
||||
set_options(opts)
|
||||
sprites = {}
|
||||
@ -181,7 +180,6 @@ def setup_for_testing(family='monospace', size=11.0, dpi=96.0):
|
||||
sprite_map_set_limits(100000, 100)
|
||||
set_send_sprite_to_gpu(send_to_gpu)
|
||||
set_logical_dpi(dpi, dpi)
|
||||
get_logical_dpi((dpi, dpi))
|
||||
cell_width, cell_height = set_font_family(opts, override_font_size=size)
|
||||
prerender()
|
||||
return sprites, cell_width, cell_height
|
||||
|
||||
90
kitty/glfw.c
90
kitty/glfw.c
@ -209,6 +209,60 @@ make_os_window_context_current(OSWindow *w) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static GLFWmonitor*
|
||||
current_monitor(GLFWwindow *window) {
|
||||
// Find the monitor that has the maximum overlap with this window
|
||||
int nmonitors, i;
|
||||
int wx, wy, ww, wh;
|
||||
int mx, my, mw, mh;
|
||||
int overlap = 0, bestoverlap = 0;
|
||||
GLFWmonitor *bestmonitor = NULL;
|
||||
GLFWmonitor **monitors = NULL;
|
||||
const GLFWvidmode *mode;
|
||||
|
||||
glfwGetWindowPos(window, &wx, &wy);
|
||||
glfwGetWindowSize(window, &ww, &wh);
|
||||
monitors = glfwGetMonitors(&nmonitors);
|
||||
if (monitors == NULL || nmonitors < 1) { PyErr_SetString(PyExc_ValueError, "No monitors connected"); return NULL; }
|
||||
|
||||
for (i = 0; i < nmonitors; i++) {
|
||||
mode = glfwGetVideoMode(monitors[i]);
|
||||
glfwGetMonitorPos(monitors[i], &mx, &my);
|
||||
mw = mode->width;
|
||||
mh = mode->height;
|
||||
|
||||
overlap =
|
||||
MAX(0, MIN(wx + ww, mx + mw) - MAX(wx, mx)) *
|
||||
MAX(0, MIN(wy + wh, my + mh) - MAX(wy, my));
|
||||
|
||||
if (bestoverlap < overlap || bestmonitor == NULL) {
|
||||
bestoverlap = overlap;
|
||||
bestmonitor = monitors[i];
|
||||
}
|
||||
}
|
||||
|
||||
return bestmonitor;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
set_dpi_from_window(OSWindow *w) {
|
||||
GLFWmonitor *monitor = NULL;
|
||||
if (w) { monitor = current_monitor(w->handle); }
|
||||
if (monitor == NULL) monitor = glfwGetPrimaryMonitor();
|
||||
float xscale = 1, yscale = 1;
|
||||
if (monitor) glfwGetMonitorContentScale(monitor, &xscale, &yscale);
|
||||
#ifdef __APPLE__
|
||||
double factor = 72.0;
|
||||
#else
|
||||
double factor = 96.0;
|
||||
#endif
|
||||
global_state.logical_dpi_x = xscale * factor;
|
||||
global_state.logical_dpi_y = yscale * factor;
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
create_os_window(PyObject UNUSED *self, PyObject *args) {
|
||||
int width, height, visible = 1, swap_interval = 0, x = -1, y = -1;
|
||||
@ -256,6 +310,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
|
||||
current_os_window_ctx = glfw_window;
|
||||
glfwSwapInterval(swap_interval); // a value of 1 makes mouse selection laggy
|
||||
if (is_first_window) {
|
||||
set_dpi_from_window(NULL);
|
||||
gl_init();
|
||||
PyObject *ret = PyObject_CallFunction(load_programs, "i", glfwGetWindowAttrib(glfw_window, GLFW_TRANSPARENT_FRAMEBUFFER));
|
||||
if (ret == NULL) return NULL;
|
||||
@ -443,41 +498,6 @@ set_clipboard_string(PyObject UNUSED *self, PyObject *args) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static GLFWmonitor*
|
||||
current_monitor(GLFWwindow *window) {
|
||||
// Find the monitor that has the maximum overlap with this window
|
||||
int nmonitors, i;
|
||||
int wx, wy, ww, wh;
|
||||
int mx, my, mw, mh;
|
||||
int overlap = 0, bestoverlap = 0;
|
||||
GLFWmonitor *bestmonitor = NULL;
|
||||
GLFWmonitor **monitors = NULL;
|
||||
const GLFWvidmode *mode;
|
||||
|
||||
glfwGetWindowPos(window, &wx, &wy);
|
||||
glfwGetWindowSize(window, &ww, &wh);
|
||||
monitors = glfwGetMonitors(&nmonitors);
|
||||
if (monitors == NULL || nmonitors < 1) { PyErr_SetString(PyExc_ValueError, "No monitors connected"); return NULL; }
|
||||
|
||||
for (i = 0; i < nmonitors; i++) {
|
||||
mode = glfwGetVideoMode(monitors[i]);
|
||||
glfwGetMonitorPos(monitors[i], &mx, &my);
|
||||
mw = mode->width;
|
||||
mh = mode->height;
|
||||
|
||||
overlap =
|
||||
MAX(0, MIN(wx + ww, mx + mw) - MAX(wx, mx)) *
|
||||
MAX(0, MIN(wy + wh, my + mh) - MAX(wy, my));
|
||||
|
||||
if (bestoverlap < overlap || bestmonitor == NULL) {
|
||||
bestoverlap = overlap;
|
||||
bestmonitor = monitors[i];
|
||||
}
|
||||
}
|
||||
|
||||
return bestmonitor;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
toggle_fullscreen(PyObject UNUSED *self) {
|
||||
GLFWmonitor *monitor;
|
||||
|
||||
@ -15,12 +15,11 @@ from .config import initial_window_size, load_cached_values, save_cached_values
|
||||
from .constants import glfw_path, is_macos, is_wayland, logo_data_file
|
||||
from .fast_data_types import (
|
||||
change_wcwidth, create_os_window, glfw_init, glfw_terminate,
|
||||
install_sigchld_handler, set_default_window_icon, set_logical_dpi,
|
||||
set_options, show_window
|
||||
install_sigchld_handler, set_default_window_icon, set_options, show_window
|
||||
)
|
||||
from .fonts.box_drawing import set_scale
|
||||
from .utils import (
|
||||
detach, encode_wm_class, end_startup_notification, get_logical_dpi,
|
||||
detach, encode_wm_class, end_startup_notification,
|
||||
init_startup_notification, single_instance
|
||||
)
|
||||
from .window import load_shader_programs
|
||||
@ -49,7 +48,6 @@ def run_app(opts, args):
|
||||
if not is_wayland and not is_macos: # no window icons on wayland
|
||||
with open(logo_data_file, 'rb') as f:
|
||||
set_default_window_icon(f.read(), 256, 256)
|
||||
set_logical_dpi(*get_logical_dpi())
|
||||
boss = Boss(window_id, opts, args)
|
||||
boss.start()
|
||||
end_startup_notification(startup_ctx)
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "state.h"
|
||||
#include <math.h>
|
||||
|
||||
GlobalState global_state = {{0}};
|
||||
|
||||
@ -424,7 +425,13 @@ PYWRAP1(set_logical_dpi) {
|
||||
PYWRAP1(pt_to_px) {
|
||||
long pt = PyLong_AsLong(args);
|
||||
double dpi = (global_state.logical_dpi_x + global_state.logical_dpi_y) / 2.f;
|
||||
return PyLong_FromLong((long)(pt * (dpi / 72.0)));
|
||||
return PyLong_FromLong((long)round((pt * (dpi / 72.0))));
|
||||
}
|
||||
|
||||
PYWRAP1(pt_to_px_ceil) {
|
||||
long pt = PyLong_AsLong(args);
|
||||
double dpi = (global_state.logical_dpi_x + global_state.logical_dpi_y) / 2.f;
|
||||
return PyLong_FromLong((long)ceil((pt * (dpi / 72.0))));
|
||||
}
|
||||
|
||||
|
||||
@ -468,6 +475,7 @@ static PyMethodDef module_methods[] = {
|
||||
MW(handle_for_window_id, METH_VARARGS),
|
||||
MW(set_logical_dpi, METH_VARARGS),
|
||||
MW(pt_to_px, METH_O),
|
||||
MW(pt_to_px_ceil, METH_O),
|
||||
MW(add_tab, METH_O),
|
||||
MW(add_window, METH_VARARGS),
|
||||
MW(update_window_title, METH_VARARGS),
|
||||
|
||||
@ -19,8 +19,8 @@ from time import monotonic
|
||||
|
||||
from .constants import appname, is_macos, is_wayland
|
||||
from .fast_data_types import (
|
||||
GLSL_VERSION, glfw_primary_monitor_content_scale,
|
||||
redirect_std_streams, wcwidth as wcwidth_impl, x11_display, x11_window_id
|
||||
GLSL_VERSION, redirect_std_streams, wcwidth as wcwidth_impl, x11_display,
|
||||
x11_window_id
|
||||
)
|
||||
from .rgb import Color, to_color
|
||||
|
||||
@ -65,19 +65,6 @@ def sanitize_title(x):
|
||||
return re.sub(r'\s+', ' ', re.sub(r'[\0-\x19]', '', x))
|
||||
|
||||
|
||||
def get_logical_dpi(override_dpi=None):
|
||||
# See https://github.com/glfw/glfw/issues/1019 for why we cant use
|
||||
# glfw_get_physical_dpi()
|
||||
if override_dpi is not None:
|
||||
get_logical_dpi.ans = override_dpi
|
||||
if not hasattr(get_logical_dpi, 'ans'):
|
||||
factor = 72.0 if is_macos else 96.0
|
||||
xscale, yscale = glfw_primary_monitor_content_scale()
|
||||
xdpi, ydpi = xscale * factor, yscale * factor
|
||||
get_logical_dpi.ans = xdpi, ydpi
|
||||
return get_logical_dpi.ans
|
||||
|
||||
|
||||
def color_as_int(val):
|
||||
return val[0] << 16 | val[1] << 8 | val[2]
|
||||
|
||||
|
||||
@ -14,7 +14,6 @@ from kitty.fonts.box_drawing import box_chars
|
||||
from kitty.fonts.render import (
|
||||
prerender, render_string, set_font_family, shape_string
|
||||
)
|
||||
from kitty.utils import get_logical_dpi
|
||||
|
||||
from . import BaseTest
|
||||
|
||||
@ -30,7 +29,6 @@ class Rendering(BaseTest):
|
||||
|
||||
set_send_sprite_to_gpu(send_to_gpu)
|
||||
set_logical_dpi(96.0, 96.0)
|
||||
get_logical_dpi((96.0, 96.0))
|
||||
self.cell_width, self.cell_height = set_font_family()
|
||||
prerender()
|
||||
self.assertEqual([k[0] for k in self.sprites], [0, 1, 2, 3, 4, 5])
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user