Move logical DPI calculation into glfw module

Now DPI state is maintained in only one central place.
This commit is contained in:
Kovid Goyal 2017-12-14 18:30:53 +05:30
parent c7e1a12eb6
commit 684a2e05f4
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
7 changed files with 70 additions and 62 deletions

View File

@ -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):

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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),

View File

@ -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]

View File

@ -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])