Migrate child-monitor.c to use OSWindow
This commit is contained in:
parent
f0003f223a
commit
141a08ec7c
@ -24,11 +24,9 @@ extern int pthread_setname_np(const char *name);
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
extern PyTypeObject Screen_Type;
|
||||
|
||||
#define EXTRA_FDS 2
|
||||
#define wakeup_main_loop glfwPostEmptyEvent
|
||||
|
||||
static void (*parse_func)(Screen*, PyObject*);
|
||||
|
||||
@ -58,7 +56,6 @@ static bool signal_received = false;
|
||||
static ChildMonitor *the_monitor = NULL;
|
||||
static uint8_t drain_buf[1024];
|
||||
static int signal_fds[2], wakeup_fds[2];
|
||||
static void *glfw_window_id = NULL;
|
||||
|
||||
|
||||
static inline void
|
||||
@ -120,12 +117,11 @@ self_pipe(int fds[2]) {
|
||||
static PyObject *
|
||||
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
||||
ChildMonitor *self;
|
||||
PyObject *dump_callback, *death_notify, *wid;
|
||||
PyObject *dump_callback, *death_notify;
|
||||
int ret;
|
||||
|
||||
if (the_monitor) { PyErr_SetString(PyExc_RuntimeError, "Can have only a single ChildMonitor instance"); return NULL; }
|
||||
if (!PyArg_ParseTuple(args, "OOO", &wid, &death_notify, &dump_callback)) return NULL;
|
||||
glfw_window_id = PyLong_AsVoidPtr(wid);
|
||||
if (!PyArg_ParseTuple(args, "OO", &death_notify, &dump_callback)) return NULL;
|
||||
if ((ret = pthread_mutex_init(&children_lock, NULL)) != 0) {
|
||||
PyErr_Format(PyExc_RuntimeError, "Failed to create children_lock mutex: %s", strerror(ret));
|
||||
return NULL;
|
||||
@ -313,7 +309,7 @@ parse_input(ChildMonitor *self) {
|
||||
}
|
||||
|
||||
if (UNLIKELY(signal_received)) {
|
||||
glfwSetWindowShouldClose(glfw_window_id, true);
|
||||
global_state.close_all_windows = true;
|
||||
} else {
|
||||
count = self->count;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
@ -436,24 +432,26 @@ pyset_iutf8(ChildMonitor *self, PyObject *args) {
|
||||
static double last_render_at = -DBL_MAX;
|
||||
|
||||
static inline double
|
||||
cursor_width(double w, bool vert) {
|
||||
cursor_width(double w, bool vert, OSWindow *os_window) {
|
||||
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);
|
||||
double factor = 2.0 / (vert ? os_window->viewport_width : os_window->viewport_height);
|
||||
return ans * factor;
|
||||
}
|
||||
|
||||
extern void cocoa_update_title(PyObject*);
|
||||
|
||||
static inline void
|
||||
collect_cursor_info(CursorRenderInfo *ans, Window *w, double now) {
|
||||
collect_cursor_info(CursorRenderInfo *ans, Window *w, double now, OSWindow *os_window) {
|
||||
ScreenRenderData *rd = &w->render_data;
|
||||
Cursor *cursor = rd->screen->cursor;
|
||||
ans->x = cursor->x; ans->y = cursor->y;
|
||||
ans->is_visible = false;
|
||||
if (rd->screen->scrolled_by || !screen_is_cursor_visible(rd->screen)) {
|
||||
ans->is_visible = false;
|
||||
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;
|
||||
double time_since_start_blink = now - os_window->cursor_blink_zero_time;
|
||||
bool cursor_blinking = OPT(cursor_blink_interval) > 0 && os_window->is_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);
|
||||
@ -467,28 +465,29 @@ collect_cursor_info(CursorRenderInfo *ans, Window *w, double now) {
|
||||
if (!do_draw_cursor) { ans->is_visible = false; return; }
|
||||
ans->is_visible = true;
|
||||
ColorProfile *cp = rd->screen->color_profile;
|
||||
Cursor *cursor = rd->screen->cursor;
|
||||
ans->shape = cursor->shape ? cursor->shape : OPT(cursor_shape);
|
||||
ans->color = colorprofile_to_color(cp, cp->overridden.cursor_color, cp->configured.cursor_color);
|
||||
if (ans->shape == CURSOR_BLOCK) return;
|
||||
double left = rd->xstart + cursor->x * rd->dx;
|
||||
double top = rd->ystart - cursor->y * rd->dy;
|
||||
unsigned long mult = MAX(1, screen_current_char_width(rd->screen));
|
||||
double right = left + (ans->shape == CURSOR_BEAM ? cursor_width(1.5, true) : rd->dx * mult);
|
||||
double right = left + (ans->shape == CURSOR_BEAM ? cursor_width(1.5, true, os_window) : rd->dx * mult);
|
||||
double bottom = top - rd->dy;
|
||||
if (ans->shape == CURSOR_UNDERLINE) top = bottom + cursor_width(2.0, false);
|
||||
if (ans->shape == CURSOR_UNDERLINE) top = bottom + cursor_width(2.0, false, os_window);
|
||||
ans->left = left; ans->right = right; ans->top = top; ans->bottom = bottom;
|
||||
}
|
||||
|
||||
static inline void
|
||||
update_window_title(Window *w) {
|
||||
if (w->title && w->title != global_state.application_title) {
|
||||
global_state.application_title = w->title;
|
||||
glfwSetWindowTitle(glfw_window_id, PyUnicode_AsUTF8(w->title));
|
||||
static inline bool
|
||||
update_window_title(Window *w, OSWindow *os_window) {
|
||||
if (w->title && w->title != os_window->window_title) {
|
||||
os_window->window_title = w->title;
|
||||
set_os_window_title(os_window, PyUnicode_AsUTF8(w->title));
|
||||
#ifdef __APPLE__
|
||||
cocoa_update_title(w->title);
|
||||
if (os_window == global_state.focussed_os_window) cocoa_update_title(w->title);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
@ -498,34 +497,23 @@ simple_render_screen(PyObject UNUSED *self, PyObject *args) {
|
||||
ssize_t vao_idx, gvao_idx;
|
||||
float xstart, ystart, dx, dy;
|
||||
if (!PyArg_ParseTuple(args, "O!nnffff", &Screen_Type, &screen, &vao_idx, &gvao_idx, &xstart, &ystart, &dx, &dy)) return NULL;
|
||||
static CursorRenderInfo cursor_info = {0};
|
||||
draw_cells(vao_idx, gvao_idx, xstart, ystart, dx, dy, screen, &cursor_info);
|
||||
Py_RETURN_NONE;
|
||||
PyObject *ret = draw_cells(vao_idx, gvao_idx, xstart, ystart, dx, dy, screen, current_os_window()) ? Py_True : Py_False;
|
||||
Py_INCREF(ret); return ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
render(double now) {
|
||||
double time_since_last_render = now - last_render_at;
|
||||
static CursorRenderInfo cursor_info;
|
||||
if (time_since_last_render < OPT(repaint_delay)) {
|
||||
set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
|
||||
return;
|
||||
}
|
||||
|
||||
draw_borders();
|
||||
cursor_info.is_visible = false;
|
||||
#define TD global_state.tab_bar_render_data
|
||||
if (TD.screen && global_state.num_tabs > 1) draw_cells(TD.vao_idx, 0, TD.xstart, TD.ystart, TD.dx, TD.dy, TD.screen, &cursor_info);
|
||||
#undef TD
|
||||
if (global_state.num_tabs) {
|
||||
Tab *tab = global_state.tabs + global_state.active_tab;
|
||||
static inline bool
|
||||
render_os_window(OSWindow *os_window, double now, unsigned int *active_window_id) {
|
||||
bool dirtied = false;
|
||||
if (OPT(mouse_hide_wait) > 0 && now - os_window->last_mouse_activity_at > OPT(mouse_hide_wait)) hide_mouse(os_window);
|
||||
if (os_window->num_tabs) {
|
||||
Tab *tab = os_window->tabs + os_window->active_tab;
|
||||
for (unsigned int i = 0; i < tab->num_windows; i++) {
|
||||
Window *w = tab->windows + i;
|
||||
#define WD w->render_data
|
||||
if (w->visible && WD.screen) {
|
||||
if (w->last_drag_scroll_at > 0) {
|
||||
if (now - w->last_drag_scroll_at >= 0.02) {
|
||||
if (drag_scroll(w)) {
|
||||
if (drag_scroll(w, os_window)) {
|
||||
w->last_drag_scroll_at = now;
|
||||
set_maximum_wait(0.02);
|
||||
} else w->last_drag_scroll_at = 0;
|
||||
@ -533,24 +521,55 @@ render(double now) {
|
||||
}
|
||||
bool is_active_window = i == tab->active_window;
|
||||
if (is_active_window) {
|
||||
collect_cursor_info(&cursor_info, w, now);
|
||||
update_window_title(w);
|
||||
} else cursor_info.is_visible = false;
|
||||
draw_cells(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen, &cursor_info);
|
||||
if (is_active_window && cursor_info.is_visible && cursor_info.shape != CURSOR_BLOCK) draw_cursor(&cursor_info);
|
||||
*active_window_id = w->id;
|
||||
collect_cursor_info(&WD.screen->current_cursor_render_info, w, now, os_window);
|
||||
if (update_window_title(w, os_window)) dirtied = true;
|
||||
} else WD.screen->current_cursor_render_info.is_visible = false;
|
||||
if (draw_cells(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen, os_window)) {
|
||||
if (is_active_window && WD.screen->current_cursor_render_info.is_visible && WD.screen->current_cursor_render_info.shape != CURSOR_BLOCK) {
|
||||
draw_cursor(&WD.screen->current_cursor_render_info, os_window == global_state.focussed_os_window);
|
||||
}
|
||||
dirtied = true;
|
||||
}
|
||||
if (WD.screen->start_visual_bell_at != 0) {
|
||||
double bell_left = global_state.opts.visual_bell_duration - (now - WD.screen->start_visual_bell_at);
|
||||
set_maximum_wait(bell_left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef WD
|
||||
}
|
||||
glfwSwapBuffers(glfw_window_id);
|
||||
last_render_at = now;
|
||||
return dirtied;
|
||||
}
|
||||
|
||||
static inline void
|
||||
render(double now) {
|
||||
double time_since_last_render = now - last_render_at;
|
||||
if (time_since_last_render < OPT(repaint_delay)) {
|
||||
set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
|
||||
return;
|
||||
}
|
||||
#define TD w->tab_bar_render_data
|
||||
|
||||
for (size_t i = 0; i < global_state.num_os_windows; i++) {
|
||||
OSWindow *w = global_state.os_windows + i;
|
||||
if (!should_os_window_be_rendered(w)) continue;
|
||||
make_window_context_current(w);
|
||||
unsigned int active_window_id = 0;
|
||||
bool window_rendered = render_os_window(w, now, &active_window_id);
|
||||
bool tab_bar_changed = w->num_tabs > 1 && (w->last_active_tab != w->active_tab || w->last_num_tabs != w->num_tabs);
|
||||
if (window_rendered || tab_bar_changed || active_window_id != w->last_active_window_id) {
|
||||
draw_borders();
|
||||
if (TD.screen && w->num_tabs > 1) draw_cells(TD.vao_idx, 0, TD.xstart, TD.ystart, TD.dx, TD.dy, TD.screen, w);
|
||||
swap_window_buffers(w);
|
||||
w->last_active_tab = w->active_tab; w->last_num_tabs = w->num_tabs; w->last_active_window_id = active_window_id;
|
||||
}
|
||||
}
|
||||
last_render_at = now;
|
||||
#undef TD
|
||||
}
|
||||
|
||||
|
||||
typedef struct { int fd; uint8_t *buf; size_t sz; } ThreadWriteData;
|
||||
|
||||
static inline ThreadWriteData*
|
||||
@ -599,18 +618,9 @@ cm_thread_write(PyObject UNUSED *self, PyObject *args) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hide_mouse(double now) {
|
||||
if (glfwGetInputMode(glfw_window_id, GLFW_CURSOR) == GLFW_CURSOR_NORMAL && OPT(mouse_hide_wait) > 0 && now - global_state.last_mouse_activity_at > OPT(mouse_hide_wait)) {
|
||||
glfwSetInputMode(glfw_window_id, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
wait_for_events() {
|
||||
if (maximum_wait < 0) glfwWaitEvents();
|
||||
else if (maximum_wait > 0) glfwWaitEventsTimeout(maximum_wait);
|
||||
event_loop_wait(maximum_wait);
|
||||
maximum_wait = -1;
|
||||
}
|
||||
|
||||
@ -618,12 +628,24 @@ wait_for_events() {
|
||||
static PyObject*
|
||||
main_loop(ChildMonitor *self) {
|
||||
#define main_loop_doc "The main thread loop"
|
||||
while (!glfwWindowShouldClose(glfw_window_id)) {
|
||||
bool has_open_windows = true;
|
||||
while (has_open_windows) {
|
||||
double now = monotonic();
|
||||
render(now);
|
||||
hide_mouse(now);
|
||||
wait_for_events();
|
||||
parse_input(self);
|
||||
if (global_state.close_all_windows) {
|
||||
for (size_t w = 0; w < global_state.num_os_windows; w++) mark_os_window_for_close(&global_state.os_windows[w], true);
|
||||
global_state.close_all_windows = false;
|
||||
}
|
||||
has_open_windows = false;
|
||||
for (size_t w = 0; w < global_state.num_os_windows; w++) {
|
||||
if (!should_os_window_close(&global_state.os_windows[w])) {
|
||||
has_open_windows = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (PyErr_Occurred()) return NULL;
|
||||
Py_RETURN_NONE;
|
||||
|
||||
@ -172,6 +172,14 @@ typedef struct {
|
||||
|
||||
} Cursor;
|
||||
|
||||
typedef struct {
|
||||
bool is_visible;
|
||||
CursorShape shape;
|
||||
unsigned int x, y;
|
||||
double left, right, top, bottom;
|
||||
color_type color;
|
||||
} CursorRenderInfo;
|
||||
|
||||
typedef struct {
|
||||
color_type default_fg, default_bg, cursor_color, highlight_fg, highlight_bg;
|
||||
} DynamicColor;
|
||||
|
||||
51
kitty/glfw.c
51
kitty/glfw.c
@ -182,7 +182,7 @@ create_new_os_window(PyObject UNUSED *self, PyObject *args) {
|
||||
glfwSetWindowUserPointer(glfw_window, w);
|
||||
w->handle = glfw_window;
|
||||
glfwSetCursor(glfw_window, standard_cursor);
|
||||
global_state.callback_os_window->viewport_size_dirty = true;
|
||||
w->viewport_size_dirty = true;
|
||||
update_viewport(w);
|
||||
glfwSetFramebufferSizeCallback(glfw_window, framebuffer_size_callback);
|
||||
glfwSetCharModsCallback(glfw_window, char_mods_callback);
|
||||
@ -394,6 +394,55 @@ request_window_attention(unsigned int kitty_window_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_os_window_title(OSWindow *w, const char *title) {
|
||||
glfwSetWindowTitle(w->handle, title);
|
||||
}
|
||||
|
||||
void
|
||||
hide_mouse(OSWindow *w) {
|
||||
glfwSetInputMode(w->handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
}
|
||||
|
||||
void
|
||||
make_window_context_current(OSWindow *w) {
|
||||
glfwMakeContextCurrent(w->handle);
|
||||
if (w->viewport_size_dirty) update_viewport_size(w->viewport_width, w->viewport_height);
|
||||
}
|
||||
|
||||
void
|
||||
swap_window_buffers(OSWindow *w) {
|
||||
glfwSwapBuffers(w->handle);
|
||||
}
|
||||
|
||||
void
|
||||
event_loop_wait(double timeout) {
|
||||
if (timeout < 0) glfwWaitEvents();
|
||||
else if (timeout > 0) glfwWaitEventsTimeout(timeout);
|
||||
}
|
||||
|
||||
void
|
||||
wakeup_main_loop() {
|
||||
glfwPostEmptyEvent();
|
||||
}
|
||||
|
||||
void
|
||||
mark_os_window_for_close(OSWindow* w, bool yes) {
|
||||
glfwSetWindowShouldClose(w->handle, yes);
|
||||
}
|
||||
|
||||
bool
|
||||
should_os_window_be_rendered(OSWindow* w) {
|
||||
if (glfwGetWindowAttrib(w->handle, GLFW_ICONIFIED)) return false;
|
||||
if (!glfwGetWindowAttrib(w->handle, GLFW_VISIBLE)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
should_os_window_close(OSWindow* w) {
|
||||
return glfwWindowShouldClose(w->handle) ? true : false;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
primary_monitor_size(PyObject UNUSED *self) {
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
|
||||
@ -55,6 +55,10 @@ typedef struct {
|
||||
size_t read_buf_sz, write_buf_sz, write_buf_used;
|
||||
pthread_mutex_t read_buf_lock, write_buf_lock;
|
||||
|
||||
CursorRenderInfo last_cursor_render_info, current_cursor_render_info;
|
||||
bool colors_inverted_at_last_render;
|
||||
float last_render_x_start, last_render_y_start;
|
||||
|
||||
} Screen;
|
||||
|
||||
|
||||
|
||||
@ -203,7 +203,7 @@ create_graphics_vao() {
|
||||
}
|
||||
|
||||
static inline void
|
||||
cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, CursorRenderInfo *cursor) {
|
||||
cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, CursorRenderInfo *cursor, bool inverted) {
|
||||
struct CellRenderData {
|
||||
GLfloat xstart, ystart, dx, dy, sprite_dx, sprite_dy;
|
||||
|
||||
@ -215,7 +215,6 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, G
|
||||
};
|
||||
static struct CellRenderData *rd;
|
||||
|
||||
bool inverted = screen_invert_colors(screen);
|
||||
// Send the uniform data
|
||||
rd = (struct CellRenderData*)map_vao_buffer(vao_idx, uniform_buffer, GL_WRITE_ONLY);
|
||||
if (UNLIKELY(screen->color_profile->dirty)) {
|
||||
@ -246,11 +245,12 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, G
|
||||
unmap_vao_buffer(vao_idx, uniform_buffer); rd = NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
cell_prepare_to_render(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, CursorRenderInfo *cursor) {
|
||||
static inline bool
|
||||
cell_prepare_to_render(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy) {
|
||||
size_t sz;
|
||||
CELL_BUFFERS;
|
||||
void *address;
|
||||
bool needs_render = false;
|
||||
|
||||
ensure_sprite_map();
|
||||
|
||||
@ -259,6 +259,7 @@ cell_prepare_to_render(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, GLfloa
|
||||
address = alloc_and_map_vao_buffer(vao_idx, sz, cell_data_buffer, GL_STREAM_DRAW, GL_WRITE_ONLY);
|
||||
screen_update_cell_data(screen, address, sz);
|
||||
unmap_vao_buffer(vao_idx, cell_data_buffer); address = NULL;
|
||||
needs_render = true;
|
||||
}
|
||||
|
||||
if (screen_is_selection_dirty(screen)) {
|
||||
@ -266,6 +267,7 @@ cell_prepare_to_render(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, GLfloa
|
||||
address = alloc_and_map_vao_buffer(vao_idx, sz, selection_buffer, GL_STREAM_DRAW, GL_WRITE_ONLY);
|
||||
screen_apply_selection(screen, address, sz);
|
||||
unmap_vao_buffer(vao_idx, selection_buffer); address = NULL;
|
||||
needs_render = true;
|
||||
}
|
||||
|
||||
if (gvao_idx && grman_update_layers(screen->grman, screen->scrolled_by, xstart, ystart, dx, dy, screen->columns, screen->lines)) {
|
||||
@ -273,12 +275,28 @@ cell_prepare_to_render(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, GLfloa
|
||||
GLfloat *a = alloc_and_map_vao_buffer(gvao_idx, sz, 0, GL_STREAM_DRAW, GL_WRITE_ONLY);
|
||||
for (size_t i = 0; i < screen->grman->count; i++, a += 16) memcpy(a, screen->grman->render_data[i].vertices, sizeof(screen->grman->render_data[0].vertices));
|
||||
unmap_vao_buffer(gvao_idx, 0); a = NULL;
|
||||
needs_render = true;
|
||||
}
|
||||
bool inverted = screen_invert_colors(screen);
|
||||
if (inverted != screen->colors_inverted_at_last_render) needs_render = true;
|
||||
|
||||
cell_update_uniform_block(vao_idx, screen, uniform_buffer, xstart, ystart, dx, dy, cursor);
|
||||
if (!needs_render && (screen->last_render_x_start != xstart || screen->last_render_y_start != ystart)) needs_render = true;
|
||||
#define CC(attr) (screen->last_cursor_render_info.attr != screen->current_cursor_render_info.attr)
|
||||
if (!needs_render && (CC(is_visible) || CC(shape) || CC(x) || CC(y) || CC(color))) needs_render = true;
|
||||
#undef CC
|
||||
|
||||
bind_vao_uniform_buffer(vao_idx, uniform_buffer, cell_program_layouts[CELL_PROGRAM].render_data.index);
|
||||
bind_vertex_array(vao_idx);
|
||||
if (needs_render) {
|
||||
cell_update_uniform_block(vao_idx, screen, uniform_buffer, xstart, ystart, dx, dy, &screen->current_cursor_render_info, inverted);
|
||||
|
||||
bind_vao_uniform_buffer(vao_idx, uniform_buffer, cell_program_layouts[CELL_PROGRAM].render_data.index);
|
||||
bind_vertex_array(vao_idx);
|
||||
screen->colors_inverted_at_last_render = inverted;
|
||||
screen->last_render_x_start = xstart; screen->last_render_y_start = ystart;
|
||||
#define CC(attr) screen->last_cursor_render_info.attr = screen->current_cursor_render_info.attr
|
||||
CC(is_visible); CC(shape); CC(x); CC(y); CC(color);
|
||||
#undef CC
|
||||
}
|
||||
return needs_render;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -336,10 +354,12 @@ draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
|
||||
if (screen->grman->num_of_positive_refs) draw_graphics(vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_negative_refs, screen->grman->num_of_positive_refs);
|
||||
}
|
||||
|
||||
void
|
||||
draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen, CursorRenderInfo *cursor) {
|
||||
bool
|
||||
draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen, OSWindow *os_window) {
|
||||
bool needs_render = cell_prepare_to_render(vao_idx, gvao_idx, screen, xstart, ystart, dx, dy);
|
||||
if (!needs_render) return false;
|
||||
GLfloat h = (GLfloat)screen->lines * dy;
|
||||
#define SCALE(w, x) ((GLfloat)(global_state.viewport_##w) * (GLfloat)(x))
|
||||
#define SCALE(w, x) ((GLfloat)(os_window->viewport_##w) * (GLfloat)(x))
|
||||
glScissor(
|
||||
(GLint)(SCALE(width, (xstart + 1.0f) / 2.0f)),
|
||||
(GLint)(SCALE(height, ((ystart - h) + 1.0f) / 2.0f)),
|
||||
@ -347,9 +367,9 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL
|
||||
(GLsizei)(ceilf(SCALE(height, h / 2.0f)))
|
||||
);
|
||||
#undef SCALE
|
||||
cell_prepare_to_render(vao_idx, gvao_idx, screen, xstart, ystart, dx, dy, cursor);
|
||||
if (screen->grman->num_of_negative_refs) draw_cells_interleaved(vao_idx, gvao_idx, screen);
|
||||
else draw_all_cells(vao_idx, gvao_idx, screen);
|
||||
return true;
|
||||
}
|
||||
// }}}
|
||||
|
||||
@ -374,11 +394,11 @@ init_cursor_program() {
|
||||
}
|
||||
|
||||
void
|
||||
draw_cursor(CursorRenderInfo *cursor) {
|
||||
draw_cursor(CursorRenderInfo *cursor, bool is_focused) {
|
||||
bind_program(CURSOR_PROGRAM); bind_vertex_array(cursor_vertex_array);
|
||||
glUniform3f(cursor_uniform_locations[CURSOR_color], ((cursor->color >> 16) & 0xff) / 255.0, ((cursor->color >> 8) & 0xff) / 255.0, (cursor->color & 0xff) / 255.0);
|
||||
glUniform4f(cursor_uniform_locations[CURSOR_pos], cursor->left, cursor->top, cursor->right, cursor->bottom);
|
||||
glDrawArrays(global_state.application_focused ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 4);
|
||||
glDrawArrays(is_focused ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 4);
|
||||
unbind_vertex_array(); unbind_program();
|
||||
}
|
||||
// }}}
|
||||
|
||||
@ -76,7 +76,7 @@ typedef struct {
|
||||
int viewport_width, viewport_height;
|
||||
double viewport_x_ratio, viewport_y_ratio;
|
||||
Tab tabs[MAX_CHILDREN];
|
||||
unsigned int active_tab, num_tabs;
|
||||
unsigned int active_tab, num_tabs, last_active_tab, last_num_tabs, last_active_window_id;
|
||||
ScreenRenderData tab_bar_render_data;
|
||||
bool is_focused;
|
||||
double cursor_blink_zero_time, last_mouse_activity_at;
|
||||
@ -85,6 +85,7 @@ typedef struct {
|
||||
PyObject *window_title;
|
||||
bool is_key_pressed[MAX_KEY_COUNT];
|
||||
bool viewport_size_dirty;
|
||||
bool needs_render;
|
||||
} OSWindow;
|
||||
|
||||
|
||||
@ -99,29 +100,32 @@ typedef struct {
|
||||
OSWindow os_windows[MAX_CHILDREN];
|
||||
size_t num_os_windows;
|
||||
OSWindow *callback_os_window, *focussed_os_window;
|
||||
bool close_all_windows;
|
||||
} GlobalState;
|
||||
|
||||
extern GlobalState global_state;
|
||||
|
||||
typedef struct {
|
||||
bool is_visible;
|
||||
CursorShape shape;
|
||||
double left, right, top, bottom;
|
||||
color_type color;
|
||||
} CursorRenderInfo;
|
||||
|
||||
#define call_boss(name, ...) { \
|
||||
PyObject *cret_ = PyObject_CallMethod(global_state.boss, #name, __VA_ARGS__); \
|
||||
if (cret_ == NULL) { PyErr_Print(); } \
|
||||
else Py_DECREF(cret_); \
|
||||
}
|
||||
|
||||
void mark_os_window_for_close(OSWindow* w, bool yes);
|
||||
bool should_os_window_close(OSWindow* w);
|
||||
bool should_os_window_be_rendered(OSWindow* w);
|
||||
void wakeup_main_loop();
|
||||
void event_loop_wait(double timeout);
|
||||
void swap_window_buffers(OSWindow *w);
|
||||
void make_window_context_current(OSWindow *w);
|
||||
void hide_mouse(OSWindow *w);
|
||||
void set_os_window_title(OSWindow *w, const char *title);
|
||||
OSWindow* os_window_for_kitty_window(unsigned int);
|
||||
OSWindow* current_os_window();
|
||||
bool drag_scroll(Window *, OSWindow*);
|
||||
void draw_borders();
|
||||
void draw_cells(ssize_t, ssize_t, float, float, float, float, Screen *, CursorRenderInfo *);
|
||||
void draw_cursor(CursorRenderInfo *);
|
||||
bool draw_cells(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *);
|
||||
void draw_cursor(CursorRenderInfo *, bool);
|
||||
void update_viewport_size(int, int);
|
||||
void free_texture(uint32_t*);
|
||||
void send_image_to_gpu(uint32_t*, const void*, int32_t, int32_t, bool, bool);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user