Move cursor render call to C
This commit is contained in:
parent
6e4b977128
commit
13ac050bf8
@ -3,7 +3,6 @@
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
from gettext import gettext as _
|
||||
from time import monotonic
|
||||
from weakref import WeakValueDictionary
|
||||
|
||||
from .char_grid import load_shader_programs
|
||||
@ -16,7 +15,7 @@ from .fast_data_types import (
|
||||
GLFW_CURSOR, GLFW_CURSOR_HIDDEN, GLFW_CURSOR_NORMAL, GLFW_MOUSE_BUTTON_1,
|
||||
GLFW_PRESS, GLFW_REPEAT, ChildMonitor, Timers as _Timers,
|
||||
destroy_global_data, destroy_sprite_map, glfw_post_empty_event,
|
||||
layout_sprite_map, resize_gl_viewport
|
||||
layout_sprite_map
|
||||
)
|
||||
from .fonts.render import render_cell_wrapper, set_font_family
|
||||
from .keys import (
|
||||
@ -91,7 +90,6 @@ class Boss:
|
||||
def __init__(self, glfw_window, opts, args):
|
||||
self.window_id_map = WeakValueDictionary()
|
||||
startup_session = create_session(opts, args)
|
||||
self.cursor_blink_zero_time = monotonic()
|
||||
self.cursor_blinking = True
|
||||
self.window_is_focused = True
|
||||
self.glfw_window_title = None
|
||||
@ -119,7 +117,6 @@ class Boss:
|
||||
layout_sprite_map(cell_size.width, cell_size.height, render_cell_wrapper)
|
||||
self.glfw_window.set_click_cursor(False)
|
||||
self.show_mouse_cursor()
|
||||
self.start_cursor_blink()
|
||||
|
||||
@property
|
||||
def current_tab_bar_height(self):
|
||||
@ -165,14 +162,8 @@ class Boss:
|
||||
self.io_thread_started = True
|
||||
|
||||
def on_window_resize(self, window, w, h):
|
||||
# debounce resize events
|
||||
if w > 100 and h > 100:
|
||||
viewport_size.width, viewport_size.height = w, h
|
||||
self.tab_manager.resize()
|
||||
resize_gl_viewport(w, h)
|
||||
glfw_post_empty_event()
|
||||
else:
|
||||
safe_print('Ignoring resize request for sizes under 100x100')
|
||||
viewport_size.width, viewport_size.height = w, h
|
||||
self.tab_manager.resize()
|
||||
|
||||
def increase_font_size(self):
|
||||
self.change_font_size(
|
||||
@ -232,8 +223,6 @@ class Boss:
|
||||
|
||||
def on_key(self, window, key, scancode, action, mods):
|
||||
is_key_pressed[key] = action == GLFW_PRESS
|
||||
self.start_cursor_blink()
|
||||
self.cursor_blink_zero_time = monotonic()
|
||||
func = None
|
||||
if action == GLFW_PRESS or action == GLFW_REPEAT:
|
||||
func = get_shortcut(self.opts.keymap, mods, key, scancode)
|
||||
@ -346,16 +335,6 @@ class Boss:
|
||||
except AttributeError:
|
||||
pass # needs glfw 3.3
|
||||
|
||||
def start_cursor_blink(self):
|
||||
self.cursor_blinking = True
|
||||
if self.opts.cursor_stop_blinking_after > 0:
|
||||
self.ui_timers.add(
|
||||
self.opts.cursor_stop_blinking_after,
|
||||
self.stop_cursor_blinking)
|
||||
|
||||
def stop_cursor_blinking(self):
|
||||
self.cursor_blinking = False
|
||||
|
||||
def render(self):
|
||||
tab = self.active_tab
|
||||
if tab is None:
|
||||
@ -365,19 +344,6 @@ class Boss:
|
||||
self.glfw_window.set_title(self.glfw_window_title)
|
||||
if isosx:
|
||||
cocoa_update_title(self.glfw_window_title)
|
||||
active = self.active_window
|
||||
if active is not None:
|
||||
draw_cursor = True
|
||||
if self.cursor_blinking and self.opts.cursor_blink_interval > 0 and self.window_is_focused:
|
||||
now = monotonic() - self.cursor_blink_zero_time
|
||||
t = int(now * 1000)
|
||||
d = int(self.opts.cursor_blink_interval * 1000)
|
||||
n = t // d
|
||||
draw_cursor = n % 2 == 0
|
||||
self.ui_timers.add_if_before(
|
||||
((n + 1) * d / 1000) - now, None)
|
||||
if draw_cursor:
|
||||
active.char_grid.render_cursor(self.window_is_focused)
|
||||
|
||||
def gui_close_window(self, window):
|
||||
window.destroy()
|
||||
|
||||
@ -3,22 +3,16 @@
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import re
|
||||
from collections import namedtuple
|
||||
from enum import Enum
|
||||
|
||||
from .config import build_ansi_color_table
|
||||
from .constants import ScreenGeometry, cell_size, viewport_size
|
||||
from .fast_data_types import (
|
||||
CELL_PROGRAM, CURSOR_BEAM, CURSOR_BLOCK, CURSOR_PROGRAM, CURSOR_UNDERLINE,
|
||||
compile_program, draw_cursor, init_cell_program, init_cursor_program
|
||||
CELL_PROGRAM, CURSOR_PROGRAM, compile_program, init_cell_program,
|
||||
init_cursor_program
|
||||
)
|
||||
from .rgb import to_color
|
||||
from .utils import (
|
||||
color_as_int, get_logical_dpi, load_shaders, open_url,
|
||||
set_primary_selection
|
||||
)
|
||||
|
||||
Cursor = namedtuple('Cursor', 'x y shape blink')
|
||||
from .utils import color_as_int, load_shaders, open_url, set_primary_selection
|
||||
|
||||
|
||||
class DynamicColor(Enum):
|
||||
@ -52,9 +46,7 @@ class CharGrid:
|
||||
self.screen.color_profile.update_ansi_color_table(build_ansi_color_table(opts))
|
||||
self.screen.color_profile.set_configured_colors(*map(color_as_int, (
|
||||
opts.foreground, opts.background, opts.cursor, opts.selection_foreground, opts.selection_background)))
|
||||
self.dpix, self.dpiy = get_logical_dpi()
|
||||
self.opts = opts
|
||||
self.default_cursor = Cursor(0, 0, opts.cursor_shape, opts.cursor_blink_interval > 0)
|
||||
self.opts = opts
|
||||
|
||||
def update_position(self, window_geometry):
|
||||
@ -158,28 +150,3 @@ class CharGrid:
|
||||
|
||||
def text_for_selection(self):
|
||||
return ''.join(self.screen.text_for_selection())
|
||||
|
||||
def render_cursor(self, is_focused):
|
||||
if not self.screen.cursor_visible or self.screen.scrolled_by:
|
||||
return
|
||||
cursor = self.screen.cursor
|
||||
|
||||
def width(w=2, vert=True):
|
||||
dpi = self.dpix if vert else self.dpiy
|
||||
w *= dpi / 72.0 # as pixels
|
||||
factor = 2 / (viewport_size.width if vert else viewport_size.height)
|
||||
return w * factor
|
||||
|
||||
sg = self.screen_geometry
|
||||
left = sg.xstart + cursor.x * sg.dx
|
||||
top = sg.ystart - cursor.y * sg.dy
|
||||
col = self.screen.color_profile.cursor_color
|
||||
shape = cursor.shape or self.default_cursor.shape
|
||||
alpha = self.opts.cursor_opacity
|
||||
mult = self.screen.current_char_width()
|
||||
right = left + (width(1.5) if shape == CURSOR_BEAM else sg.dx * mult)
|
||||
bottom = top - sg.dy
|
||||
if shape == CURSOR_UNDERLINE:
|
||||
top = bottom + width(vert=False)
|
||||
semi_transparent = alpha < 1.0 and shape == CURSOR_BLOCK
|
||||
draw_cursor(semi_transparent, is_focused, col, alpha, left, right, top, bottom)
|
||||
|
||||
@ -16,6 +16,7 @@ extern int pthread_setname_np(const char *name);
|
||||
#undef _GNU_SOURCE
|
||||
#endif
|
||||
#include "state.h"
|
||||
#include "screen.h"
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <float.h>
|
||||
@ -426,6 +427,46 @@ pyset_iutf8(ChildMonitor *self, PyObject *args) {
|
||||
static double last_render_at = -DBL_MAX;
|
||||
draw_borders_func draw_borders = NULL;
|
||||
draw_cells_func draw_cells = NULL;
|
||||
draw_cursor_func draw_cursor = NULL;
|
||||
|
||||
static inline double
|
||||
cursor_width(unsigned int w, bool vert) {
|
||||
double dpi = vert ? global_state.logical_dpi_x : global_state.logical_dpi_y;
|
||||
double ans = w * dpi / 72.0; // as pixels
|
||||
double factor = 2.0 / (vert ? global_state.viewport_width : global_state.viewport_height);
|
||||
return ans * factor;
|
||||
}
|
||||
|
||||
static inline void
|
||||
render_cursor(ChildMonitor *self, Window *w, double now) {
|
||||
ScreenRenderData *rd = &w->render_data;
|
||||
if (rd->screen->scrolled_by || ! screen_is_cursor_visible(rd->screen)) return;
|
||||
double time_since_start_blink = now - global_state.cursor_blink_zero_time;
|
||||
bool cursor_blinking = OPT(cursor_blink_interval) > 0 && global_state.application_focused && time_since_start_blink <= OPT(cursor_stop_blinking_after) ? true : false;
|
||||
bool do_draw_cursor = true;
|
||||
if (cursor_blinking) {
|
||||
int t = (int)(time_since_start_blink * 1000);
|
||||
int d = (int)(OPT(cursor_blink_interval) * 1000);
|
||||
int n = t / d;
|
||||
do_draw_cursor = n % 2 == 0 ? true : false;
|
||||
double delay = MAX(0, ((n + 1) * d / 1000) - time_since_start_blink);
|
||||
timers_add_if_before(self->timers, delay, Py_None, NULL);
|
||||
}
|
||||
if (do_draw_cursor) {
|
||||
Cursor *cursor = rd->screen->cursor;
|
||||
double left = rd->xstart + cursor->x * rd->dx;
|
||||
double top = rd->ystart - cursor->y * rd->dy;
|
||||
int shape = cursor->shape ? cursor->shape : OPT(cursor_shape);
|
||||
unsigned long mult = screen_current_char_width(rd->screen);
|
||||
double right = left + (shape == CURSOR_BEAM ? cursor_width(1.5, true) : rd->dx * mult);
|
||||
double bottom = top - rd->dy;
|
||||
if (shape == CURSOR_UNDERLINE) top = bottom + cursor_width(2.0, false);
|
||||
bool semi_transparent = OPT(cursor_opacity) < 1.0 && shape == CURSOR_BLOCK ? true : false;
|
||||
ColorProfile *cp = rd->screen->color_profile;
|
||||
color_type col = colorprofile_to_color(cp, cp->overridden.cursor_color, cp->configured.cursor_color);
|
||||
draw_cursor(semi_transparent, global_state.application_focused, col, OPT(cursor_opacity), left, right, top, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
render(ChildMonitor *self, double *timeout) {
|
||||
@ -443,8 +484,10 @@ render(ChildMonitor *self, double *timeout) {
|
||||
Window *w = tab->windows + i;
|
||||
#define WD w->render_data
|
||||
if (w->visible && WD.screen) draw_cells(WD.vao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen);
|
||||
#undef WD
|
||||
}
|
||||
Window *w = tab->windows + tab->active_window;
|
||||
if (w->visible && WD.screen) render_cursor(self, w, now);
|
||||
#undef WD
|
||||
}
|
||||
|
||||
ret = PyObject_CallFunctionObjArgs(self->render_func, NULL);
|
||||
|
||||
@ -27,12 +27,15 @@ static int __eq__(Cursor *a, Cursor *b) {
|
||||
return EQ(bold) && EQ(italic) && EQ(strikethrough) && EQ(reverse) && EQ(decoration) && EQ(fg) && EQ(bg) && EQ(decoration_fg) && EQ(x) && EQ(y) && EQ(shape) && EQ(blink);
|
||||
}
|
||||
|
||||
static const char* cursor_names[NUM_OF_CURSOR_SHAPES] = { "NO_SHAPE", "BLOCK", "BEAM", "UNDERLINE" };
|
||||
|
||||
#define BOOL(x) ((x) ? Py_True : Py_False)
|
||||
static PyObject *
|
||||
repr(Cursor *self) {
|
||||
return PyUnicode_FromFormat(
|
||||
"Cursor(x=%u, y=%u, shape=%d, blink=%R, fg=#%08x, bg=#%08x, bold=%R, italic=%R, reverse=%R, strikethrough=%R, decoration=%d, decoration_fg=#%08x)",
|
||||
self->x, self->y, self->shape, BOOL(self->blink), self->fg, self->bg, BOOL(self->bold), BOOL(self->italic), BOOL(self->reverse), BOOL(self->strikethrough), self->decoration, self->decoration_fg
|
||||
"Cursor(x=%u, y=%u, shape=%s, blink=%R, fg=#%08x, bg=#%08x, bold=%R, italic=%R, reverse=%R, strikethrough=%R, decoration=%d, decoration_fg=#%08x)",
|
||||
self->x, self->y, (self->shape < NUM_OF_CURSOR_SHAPES && self->shape >= 0 ? cursor_names[self->shape] : "INVALID"),
|
||||
BOOL(self->blink), self->fg, self->bg, BOOL(self->bold), BOOL(self->italic), BOOL(self->reverse), BOOL(self->strikethrough), self->decoration, self->decoration_fg
|
||||
);
|
||||
}
|
||||
|
||||
@ -51,7 +54,7 @@ reset_display_attrs(Cursor *self) {
|
||||
void cursor_reset(Cursor *self) {
|
||||
cursor_reset_display_attrs(self);
|
||||
self->x = 0; self->y = 0;
|
||||
self->shape = 0; self->blink = false;
|
||||
self->shape = NO_CURSOR_SHAPE; self->blink = false;
|
||||
}
|
||||
|
||||
void cursor_copy_to(Cursor *src, Cursor *dest) {
|
||||
@ -75,7 +78,7 @@ BOOL_GETSET(Cursor, blink)
|
||||
static PyMemberDef members[] = {
|
||||
{"x", T_UINT, offsetof(Cursor, x), 0, "x"},
|
||||
{"y", T_UINT, offsetof(Cursor, y), 0, "y"},
|
||||
{"shape", T_UBYTE, offsetof(Cursor, shape), 0, "shape"},
|
||||
{"shape", T_INT, offsetof(Cursor, shape), 0, "shape"},
|
||||
{"decoration", T_UBYTE, offsetof(Cursor, decoration), 0, "decoration"},
|
||||
{"fg", T_ULONG, offsetof(Cursor, fg), 0, "fg"},
|
||||
{"bg", T_ULONG, offsetof(Cursor, bg), 0, "bg"},
|
||||
|
||||
@ -29,6 +29,7 @@ typedef uint32_t color_type;
|
||||
typedef uint32_t combining_type;
|
||||
typedef unsigned int index_type;
|
||||
typedef uint16_t sprite_index;
|
||||
typedef enum CursorShapes { NO_CURSOR_SHAPE, CURSOR_BLOCK, CURSOR_BEAM, CURSOR_UNDERLINE, NUM_OF_CURSOR_SHAPES } CursorShape;
|
||||
|
||||
#define ERROR_PREFIX "[PARSE ERROR]"
|
||||
#define ANY_MODE 3
|
||||
@ -61,9 +62,6 @@ typedef uint16_t sprite_index;
|
||||
#define DECORATION_FG_CODE 58
|
||||
#define CHAR_IS_BLANK(ch) ((ch & CHAR_MASK) == 32 || (ch & CHAR_MASK) == 0)
|
||||
|
||||
#define CURSOR_BLOCK 1
|
||||
#define CURSOR_BEAM 2
|
||||
#define CURSOR_UNDERLINE 3
|
||||
#define FG 1
|
||||
#define BG 2
|
||||
|
||||
@ -172,7 +170,8 @@ typedef struct {
|
||||
|
||||
bool bold, italic, reverse, strikethrough, blink;
|
||||
unsigned int x, y;
|
||||
uint8_t decoration, shape;
|
||||
uint8_t decoration;
|
||||
CursorShape shape;
|
||||
unsigned long fg, bg, decoration_fg;
|
||||
|
||||
} Cursor;
|
||||
|
||||
13
kitty/glfw.c
13
kitty/glfw.c
@ -39,19 +39,27 @@ typedef struct {
|
||||
|
||||
// callbacks {{{
|
||||
static WindowWrapper* the_window = NULL;
|
||||
update_viewport_size_func update_viewport_size = NULL;
|
||||
|
||||
static void
|
||||
framebuffer_size_callback(GLFWwindow UNUSED *w, int width, int height) {
|
||||
WINDOW_CALLBACK(framebuffer_size_callback, "ii", width, height);
|
||||
if (width > 100 && height > 100) {
|
||||
update_viewport_size(width, height);
|
||||
global_state.viewport_width = width; global_state.viewport_height = height;
|
||||
WINDOW_CALLBACK(framebuffer_size_callback, "ii", width, height);
|
||||
glfwPostEmptyEvent();
|
||||
} else fprintf(stderr, "Ignoring resize request for tiny size: %dx%d\n", width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
char_mods_callback(GLFWwindow UNUSED *w, unsigned int codepoint, int mods) {
|
||||
global_state.cursor_blink_zero_time = monotonic();
|
||||
WINDOW_CALLBACK(char_mods_callback, "Ii", codepoint, mods);
|
||||
}
|
||||
|
||||
static void
|
||||
key_callback(GLFWwindow UNUSED *w, int key, int scancode, int action, int mods) {
|
||||
global_state.cursor_blink_zero_time = monotonic();
|
||||
WINDOW_CALLBACK(key_callback, "iiii", key, scancode, action, mods);
|
||||
}
|
||||
|
||||
@ -67,12 +75,14 @@ scroll_callback(GLFWwindow UNUSED *w, double xoffset, double yoffset) {
|
||||
|
||||
static void
|
||||
cursor_pos_callback(GLFWwindow UNUSED *w, double x, double y) {
|
||||
global_state.cursor_blink_zero_time = monotonic();
|
||||
WINDOW_CALLBACK(cursor_pos_callback, "dd", x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
window_focus_callback(GLFWwindow UNUSED *w, int focused) {
|
||||
global_state.application_focused = focused ? true : false;
|
||||
global_state.cursor_blink_zero_time = monotonic();
|
||||
WINDOW_CALLBACK(window_focus_callback, "O", focused ? Py_True : Py_False);
|
||||
}
|
||||
// }}}
|
||||
@ -90,6 +100,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
||||
the_window = self;
|
||||
self->window = glfwCreateWindow(width, height, title, NULL, NULL);
|
||||
if (self->window == NULL) { Py_CLEAR(self); the_window = NULL; PyErr_SetString(PyExc_ValueError, "Failed to create GLFWwindow"); return NULL; }
|
||||
global_state.viewport_width = width; global_state.viewport_height = height;
|
||||
self->standard_cursor = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
|
||||
self->click_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
|
||||
if (self->standard_cursor == NULL || self->click_cursor == NULL) { Py_CLEAR(self); PyErr_SetString(PyExc_ValueError, "Failed to create standard mouse cursors"); return NULL; }
|
||||
|
||||
@ -23,10 +23,10 @@ from .fast_data_types import (
|
||||
GLFW_STENCIL_BITS, GLFWWindow, change_wcwidth, check_for_extensions,
|
||||
clear_buffers, glewInit, glfw_init, glfw_init_hint_string,
|
||||
glfw_set_error_callback, glfw_swap_interval, glfw_terminate,
|
||||
glfw_window_hint, set_options
|
||||
glfw_window_hint, set_logical_dpi, set_options
|
||||
)
|
||||
from .layout import all_layouts
|
||||
from .utils import color_as_int, detach, safe_print
|
||||
from .utils import color_as_int, detach, get_logical_dpi, safe_print
|
||||
|
||||
try:
|
||||
from .fast_data_types import GLFW_X11_WM_CLASS_NAME, GLFW_X11_WM_CLASS_CLASS
|
||||
@ -186,6 +186,7 @@ def run_app(opts, args):
|
||||
else:
|
||||
with open(logo_data_file, 'rb') as f:
|
||||
window.set_icon(f.read(), 256, 256)
|
||||
set_logical_dpi(*get_logical_dpi())
|
||||
viewport_size.width, viewport_size.height = window.get_framebuffer_size()
|
||||
w, h = window.get_window_size()
|
||||
viewport_size.x_ratio = viewport_size.width / float(w)
|
||||
|
||||
@ -511,6 +511,20 @@ void screen_reset_mode(Screen *self, unsigned int mode) {
|
||||
|
||||
// Cursor {{{
|
||||
|
||||
unsigned long
|
||||
screen_current_char_width(Screen *self) {
|
||||
unsigned long ans = 1;
|
||||
if (self->cursor->x < self->columns - 1 && self->cursor->y < self->lines) {
|
||||
ans = linebuf_char_width_at(self->linebuf, self->cursor->x, self->cursor->y);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
bool
|
||||
screen_is_cursor_visible(Screen *self) {
|
||||
return self->modes.mDECTCEM;
|
||||
}
|
||||
|
||||
void
|
||||
screen_backspace(Screen *self) {
|
||||
screen_cursor_back(self, 1, -1);
|
||||
@ -1443,11 +1457,7 @@ mark_as_dirty(Screen *self) {
|
||||
static PyObject*
|
||||
current_char_width(Screen *self) {
|
||||
#define current_char_width_doc "The width of the character under the cursor"
|
||||
unsigned long ans = 1;
|
||||
if (self->cursor->x < self->columns - 1 && self->cursor->y < self->lines) {
|
||||
ans = linebuf_char_width_at(self->linebuf, self->cursor->x, self->cursor->y);
|
||||
}
|
||||
return PyLong_FromUnsignedLong(ans);
|
||||
return PyLong_FromUnsignedLong(screen_current_char_width(self));
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
|
||||
@ -63,6 +63,8 @@ void screen_apply_selection(Screen *self, void *address, size_t size);
|
||||
bool screen_is_selection_dirty(Screen *self);
|
||||
bool screen_invert_colors(Screen *self);
|
||||
void screen_update_cell_data(Screen *self, void *address, size_t sz);
|
||||
bool screen_is_cursor_visible(Screen *self);
|
||||
unsigned long screen_current_char_width(Screen *self);
|
||||
#define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen);
|
||||
DECLARE_CH_SCREEN_HANDLER(bell)
|
||||
DECLARE_CH_SCREEN_HANDLER(backspace)
|
||||
|
||||
@ -84,6 +84,11 @@ glew_init(PyObject UNUSED *self) {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_viewport_size_impl(int w, int h) {
|
||||
glViewport(0, 0, w, h); check_gl();
|
||||
}
|
||||
// }}}
|
||||
|
||||
// Programs {{{
|
||||
@ -668,7 +673,7 @@ init_cursor_program() {
|
||||
}
|
||||
|
||||
static void
|
||||
draw_cursor(bool semi_transparent, bool is_focused, color_type color, float alpha, float left, float right, float top, float bottom) {
|
||||
draw_cursor_impl(bool semi_transparent, bool is_focused, color_type color, float alpha, float left, float right, float top, float bottom) {
|
||||
if (semi_transparent) { glEnable(GL_BLEND); check_gl(); }
|
||||
bind_program(CURSOR_PROGRAM); bind_vertex_array(cursor_vertex_array);
|
||||
glUniform4f(cursor_uniform_locations[CURSOR_color], ((color >> 16) & 0xff) / 255.0, ((color >> 8) & 0xff) / 255.0, (color & 0xff) / 255.0, alpha);
|
||||
@ -852,12 +857,6 @@ PYWRAP1(layout_sprite_map) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PYWRAP1(resize_gl_viewport) {
|
||||
unsigned int w, h; PA("II", &w, &h);
|
||||
glViewport(0, 0, w, h);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PYWRAP1(clear_buffers) {
|
||||
PyObject *swap_buffers;
|
||||
unsigned int bg;
|
||||
@ -918,7 +917,6 @@ static PyMethodDef module_methods[] = {
|
||||
MW(create_cell_vao, METH_NOARGS),
|
||||
MW(layout_sprite_map, METH_VARARGS),
|
||||
MW(destroy_sprite_map, METH_NOARGS),
|
||||
MW(resize_gl_viewport, METH_VARARGS),
|
||||
MW(clear_buffers, METH_VARARGS),
|
||||
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
@ -962,8 +960,10 @@ init_shaders(PyObject *module) {
|
||||
#undef C
|
||||
PyModule_AddObject(module, "GL_VERSION_REQUIRED", Py_BuildValue("II", REQUIRED_VERSION_MAJOR, REQUIRED_VERSION_MINOR));
|
||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||
update_viewport_size = &update_viewport_size_impl;
|
||||
draw_borders = &draw_borders_impl;
|
||||
draw_cells = &draw_cells_impl;
|
||||
draw_cursor = &draw_cursor_impl;
|
||||
return true;
|
||||
}
|
||||
// }}}
|
||||
|
||||
@ -103,9 +103,13 @@ swap_windows(unsigned int tab_id, unsigned int a, unsigned int b) {
|
||||
#define THREE_UINT(name) PYWRAP1(name) { unsigned int a, b, c; PA("III", &a, &b, &c); name(a, b, c); Py_RETURN_NONE; }
|
||||
|
||||
PYWRAP1(set_options) {
|
||||
#define S(name, convert) { PyObject *ret = PyObject_GetAttrString(args, #name); if (ret == NULL) return NULL; global_state.opts.name = convert(ret); Py_DECREF(ret); }
|
||||
#define S(name, convert) { PyObject *ret = PyObject_GetAttrString(args, #name); if (ret == NULL) return NULL; global_state.opts.name = convert(ret); Py_DECREF(ret); if (PyErr_Occurred()) return NULL; }
|
||||
S(visual_bell_duration, PyFloat_AsDouble);
|
||||
S(enable_audio_bell, PyObject_IsTrue);
|
||||
S(cursor_blink_interval, PyFloat_AsDouble);
|
||||
S(cursor_stop_blinking_after, PyFloat_AsDouble);
|
||||
S(cursor_shape, PyLong_AsLong);
|
||||
S(cursor_opacity, PyFloat_AsDouble);
|
||||
#undef S
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
@ -144,6 +148,11 @@ PYWRAP1(update_window_visibility) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PYWRAP1(set_logical_dpi) {
|
||||
PA("dd", &global_state.logical_dpi_x, &global_state.logical_dpi_y);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PYWRAP0(destroy_global_data) {
|
||||
Py_CLEAR(global_state.tab_bar_render_data.screen);
|
||||
Py_RETURN_NONE;
|
||||
@ -163,6 +172,7 @@ THREE_UINT(swap_windows)
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
MW(set_options, METH_O),
|
||||
MW(set_logical_dpi, METH_VARARGS),
|
||||
MW(add_tab, METH_O),
|
||||
MW(add_window, METH_VARARGS),
|
||||
MW(remove_tab, METH_O),
|
||||
@ -183,6 +193,7 @@ static PyMethodDef module_methods[] = {
|
||||
bool
|
||||
init_state(PyObject *module) {
|
||||
global_state.application_focused = true;
|
||||
global_state.cursor_blink_zero_time = monotonic();
|
||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -7,9 +7,13 @@
|
||||
#pragma once
|
||||
#include "data-types.h"
|
||||
|
||||
#define OPT(name) global_state.opts.name
|
||||
|
||||
typedef struct {
|
||||
double visual_bell_duration;
|
||||
double visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after;
|
||||
bool enable_audio_bell;
|
||||
CursorShape cursor_shape;
|
||||
double cursor_opacity;
|
||||
} Options;
|
||||
|
||||
typedef struct {
|
||||
@ -36,9 +40,14 @@ typedef struct {
|
||||
unsigned int active_tab, num_tabs;
|
||||
ScreenRenderData tab_bar_render_data;
|
||||
bool application_focused;
|
||||
double cursor_blink_zero_time;
|
||||
double logical_dpi_x, logical_dpi_y;
|
||||
int viewport_width, viewport_height;
|
||||
} GlobalState;
|
||||
|
||||
typedef void (*draw_borders_func)();
|
||||
extern draw_borders_func draw_borders;
|
||||
typedef void (*draw_cells_func)(ssize_t, float, float, float, float, Screen *);
|
||||
extern draw_cells_func draw_cells;
|
||||
#define EXTERNAL_FUNC(name, ret, ...) typedef ret (*name##_func)(__VA_ARGS__); extern name##_func name
|
||||
#define EXTERNAL_FUNC0(name, ret) typedef ret (*name##_func)(); extern name##_func name
|
||||
EXTERNAL_FUNC0(draw_borders, void);
|
||||
EXTERNAL_FUNC(draw_cells, void, ssize_t, float, float, float, float, Screen *);
|
||||
EXTERNAL_FUNC(draw_cursor, void, bool, bool, color_type, float, float, float, float, float);
|
||||
EXTERNAL_FUNC(update_viewport_size, void, int, int);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user