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/ioctl.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
extern PyTypeObject Screen_Type;
|
extern PyTypeObject Screen_Type;
|
||||||
|
|
||||||
#define EXTRA_FDS 2
|
#define EXTRA_FDS 2
|
||||||
#define wakeup_main_loop glfwPostEmptyEvent
|
|
||||||
|
|
||||||
static void (*parse_func)(Screen*, PyObject*);
|
static void (*parse_func)(Screen*, PyObject*);
|
||||||
|
|
||||||
@ -58,7 +56,6 @@ static bool signal_received = false;
|
|||||||
static ChildMonitor *the_monitor = NULL;
|
static ChildMonitor *the_monitor = NULL;
|
||||||
static uint8_t drain_buf[1024];
|
static uint8_t drain_buf[1024];
|
||||||
static int signal_fds[2], wakeup_fds[2];
|
static int signal_fds[2], wakeup_fds[2];
|
||||||
static void *glfw_window_id = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -120,12 +117,11 @@ self_pipe(int fds[2]) {
|
|||||||
static PyObject *
|
static PyObject *
|
||||||
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
||||||
ChildMonitor *self;
|
ChildMonitor *self;
|
||||||
PyObject *dump_callback, *death_notify, *wid;
|
PyObject *dump_callback, *death_notify;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (the_monitor) { PyErr_SetString(PyExc_RuntimeError, "Can have only a single ChildMonitor instance"); return NULL; }
|
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;
|
if (!PyArg_ParseTuple(args, "OO", &death_notify, &dump_callback)) return NULL;
|
||||||
glfw_window_id = PyLong_AsVoidPtr(wid);
|
|
||||||
if ((ret = pthread_mutex_init(&children_lock, NULL)) != 0) {
|
if ((ret = pthread_mutex_init(&children_lock, NULL)) != 0) {
|
||||||
PyErr_Format(PyExc_RuntimeError, "Failed to create children_lock mutex: %s", strerror(ret));
|
PyErr_Format(PyExc_RuntimeError, "Failed to create children_lock mutex: %s", strerror(ret));
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -313,7 +309,7 @@ parse_input(ChildMonitor *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (UNLIKELY(signal_received)) {
|
if (UNLIKELY(signal_received)) {
|
||||||
glfwSetWindowShouldClose(glfw_window_id, true);
|
global_state.close_all_windows = true;
|
||||||
} else {
|
} else {
|
||||||
count = self->count;
|
count = self->count;
|
||||||
for (size_t i = 0; i < count; i++) {
|
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 double last_render_at = -DBL_MAX;
|
||||||
|
|
||||||
static inline double
|
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 dpi = vert ? global_state.logical_dpi_x : global_state.logical_dpi_y;
|
||||||
double ans = w * dpi / 72.0; // as pixels
|
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;
|
return ans * factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void cocoa_update_title(PyObject*);
|
extern void cocoa_update_title(PyObject*);
|
||||||
|
|
||||||
static inline void
|
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;
|
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)) {
|
if (rd->screen->scrolled_by || !screen_is_cursor_visible(rd->screen)) {
|
||||||
ans->is_visible = false;
|
ans->is_visible = false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
double time_since_start_blink = now - global_state.cursor_blink_zero_time;
|
double time_since_start_blink = now - os_window->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 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;
|
bool do_draw_cursor = true;
|
||||||
if (cursor_blinking) {
|
if (cursor_blinking) {
|
||||||
int t = (int)(time_since_start_blink * 1000);
|
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; }
|
if (!do_draw_cursor) { ans->is_visible = false; return; }
|
||||||
ans->is_visible = true;
|
ans->is_visible = true;
|
||||||
ColorProfile *cp = rd->screen->color_profile;
|
ColorProfile *cp = rd->screen->color_profile;
|
||||||
Cursor *cursor = rd->screen->cursor;
|
|
||||||
ans->shape = cursor->shape ? cursor->shape : OPT(cursor_shape);
|
ans->shape = cursor->shape ? cursor->shape : OPT(cursor_shape);
|
||||||
ans->color = colorprofile_to_color(cp, cp->overridden.cursor_color, cp->configured.cursor_color);
|
ans->color = colorprofile_to_color(cp, cp->overridden.cursor_color, cp->configured.cursor_color);
|
||||||
if (ans->shape == CURSOR_BLOCK) return;
|
if (ans->shape == CURSOR_BLOCK) return;
|
||||||
double left = rd->xstart + cursor->x * rd->dx;
|
double left = rd->xstart + cursor->x * rd->dx;
|
||||||
double top = rd->ystart - cursor->y * rd->dy;
|
double top = rd->ystart - cursor->y * rd->dy;
|
||||||
unsigned long mult = MAX(1, screen_current_char_width(rd->screen));
|
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;
|
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;
|
ans->left = left; ans->right = right; ans->top = top; ans->bottom = bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline bool
|
||||||
update_window_title(Window *w) {
|
update_window_title(Window *w, OSWindow *os_window) {
|
||||||
if (w->title && w->title != global_state.application_title) {
|
if (w->title && w->title != os_window->window_title) {
|
||||||
global_state.application_title = w->title;
|
os_window->window_title = w->title;
|
||||||
glfwSetWindowTitle(glfw_window_id, PyUnicode_AsUTF8(w->title));
|
set_os_window_title(os_window, PyUnicode_AsUTF8(w->title));
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
cocoa_update_title(w->title);
|
if (os_window == global_state.focussed_os_window) cocoa_update_title(w->title);
|
||||||
#endif
|
#endif
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
@ -498,34 +497,23 @@ simple_render_screen(PyObject UNUSED *self, PyObject *args) {
|
|||||||
ssize_t vao_idx, gvao_idx;
|
ssize_t vao_idx, gvao_idx;
|
||||||
float xstart, ystart, dx, dy;
|
float xstart, ystart, dx, dy;
|
||||||
if (!PyArg_ParseTuple(args, "O!nnffff", &Screen_Type, &screen, &vao_idx, &gvao_idx, &xstart, &ystart, &dx, &dy)) return NULL;
|
if (!PyArg_ParseTuple(args, "O!nnffff", &Screen_Type, &screen, &vao_idx, &gvao_idx, &xstart, &ystart, &dx, &dy)) return NULL;
|
||||||
static CursorRenderInfo cursor_info = {0};
|
PyObject *ret = draw_cells(vao_idx, gvao_idx, xstart, ystart, dx, dy, screen, current_os_window()) ? Py_True : Py_False;
|
||||||
draw_cells(vao_idx, gvao_idx, xstart, ystart, dx, dy, screen, &cursor_info);
|
Py_INCREF(ret); return ret;
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline bool
|
||||||
render(double now) {
|
render_os_window(OSWindow *os_window, double now, unsigned int *active_window_id) {
|
||||||
double time_since_last_render = now - last_render_at;
|
bool dirtied = false;
|
||||||
static CursorRenderInfo cursor_info;
|
if (OPT(mouse_hide_wait) > 0 && now - os_window->last_mouse_activity_at > OPT(mouse_hide_wait)) hide_mouse(os_window);
|
||||||
if (time_since_last_render < OPT(repaint_delay)) {
|
if (os_window->num_tabs) {
|
||||||
set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
|
Tab *tab = os_window->tabs + os_window->active_tab;
|
||||||
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;
|
|
||||||
for (unsigned int i = 0; i < tab->num_windows; i++) {
|
for (unsigned int i = 0; i < tab->num_windows; i++) {
|
||||||
Window *w = tab->windows + i;
|
Window *w = tab->windows + i;
|
||||||
#define WD w->render_data
|
#define WD w->render_data
|
||||||
if (w->visible && WD.screen) {
|
if (w->visible && WD.screen) {
|
||||||
if (w->last_drag_scroll_at > 0) {
|
if (w->last_drag_scroll_at > 0) {
|
||||||
if (now - w->last_drag_scroll_at >= 0.02) {
|
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;
|
w->last_drag_scroll_at = now;
|
||||||
set_maximum_wait(0.02);
|
set_maximum_wait(0.02);
|
||||||
} else w->last_drag_scroll_at = 0;
|
} else w->last_drag_scroll_at = 0;
|
||||||
@ -533,24 +521,55 @@ render(double now) {
|
|||||||
}
|
}
|
||||||
bool is_active_window = i == tab->active_window;
|
bool is_active_window = i == tab->active_window;
|
||||||
if (is_active_window) {
|
if (is_active_window) {
|
||||||
collect_cursor_info(&cursor_info, w, now);
|
*active_window_id = w->id;
|
||||||
update_window_title(w);
|
collect_cursor_info(&WD.screen->current_cursor_render_info, w, now, os_window);
|
||||||
} else cursor_info.is_visible = false;
|
if (update_window_title(w, os_window)) dirtied = true;
|
||||||
draw_cells(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen, &cursor_info);
|
} else WD.screen->current_cursor_render_info.is_visible = false;
|
||||||
if (is_active_window && cursor_info.is_visible && cursor_info.shape != CURSOR_BLOCK) draw_cursor(&cursor_info);
|
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) {
|
if (WD.screen->start_visual_bell_at != 0) {
|
||||||
double bell_left = global_state.opts.visual_bell_duration - (now - WD.screen->start_visual_bell_at);
|
double bell_left = global_state.opts.visual_bell_duration - (now - WD.screen->start_visual_bell_at);
|
||||||
set_maximum_wait(bell_left);
|
set_maximum_wait(bell_left);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef WD
|
#undef WD
|
||||||
}
|
}
|
||||||
glfwSwapBuffers(glfw_window_id);
|
return dirtied;
|
||||||
last_render_at = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
typedef struct { int fd; uint8_t *buf; size_t sz; } ThreadWriteData;
|
||||||
|
|
||||||
static inline ThreadWriteData*
|
static inline ThreadWriteData*
|
||||||
@ -599,18 +618,9 @@ cm_thread_write(PyObject UNUSED *self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
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
|
static inline void
|
||||||
wait_for_events() {
|
wait_for_events() {
|
||||||
if (maximum_wait < 0) glfwWaitEvents();
|
event_loop_wait(maximum_wait);
|
||||||
else if (maximum_wait > 0) glfwWaitEventsTimeout(maximum_wait);
|
|
||||||
maximum_wait = -1;
|
maximum_wait = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,12 +628,24 @@ wait_for_events() {
|
|||||||
static PyObject*
|
static PyObject*
|
||||||
main_loop(ChildMonitor *self) {
|
main_loop(ChildMonitor *self) {
|
||||||
#define main_loop_doc "The main thread loop"
|
#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();
|
double now = monotonic();
|
||||||
render(now);
|
render(now);
|
||||||
hide_mouse(now);
|
|
||||||
wait_for_events();
|
wait_for_events();
|
||||||
parse_input(self);
|
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;
|
if (PyErr_Occurred()) return NULL;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
|||||||
@ -172,6 +172,14 @@ typedef struct {
|
|||||||
|
|
||||||
} Cursor;
|
} Cursor;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool is_visible;
|
||||||
|
CursorShape shape;
|
||||||
|
unsigned int x, y;
|
||||||
|
double left, right, top, bottom;
|
||||||
|
color_type color;
|
||||||
|
} CursorRenderInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
color_type default_fg, default_bg, cursor_color, highlight_fg, highlight_bg;
|
color_type default_fg, default_bg, cursor_color, highlight_fg, highlight_bg;
|
||||||
} DynamicColor;
|
} 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);
|
glfwSetWindowUserPointer(glfw_window, w);
|
||||||
w->handle = glfw_window;
|
w->handle = glfw_window;
|
||||||
glfwSetCursor(glfw_window, standard_cursor);
|
glfwSetCursor(glfw_window, standard_cursor);
|
||||||
global_state.callback_os_window->viewport_size_dirty = true;
|
w->viewport_size_dirty = true;
|
||||||
update_viewport(w);
|
update_viewport(w);
|
||||||
glfwSetFramebufferSizeCallback(glfw_window, framebuffer_size_callback);
|
glfwSetFramebufferSizeCallback(glfw_window, framebuffer_size_callback);
|
||||||
glfwSetCharModsCallback(glfw_window, char_mods_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*
|
static PyObject*
|
||||||
primary_monitor_size(PyObject UNUSED *self) {
|
primary_monitor_size(PyObject UNUSED *self) {
|
||||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||||
|
|||||||
@ -55,6 +55,10 @@ typedef struct {
|
|||||||
size_t read_buf_sz, write_buf_sz, write_buf_used;
|
size_t read_buf_sz, write_buf_sz, write_buf_used;
|
||||||
pthread_mutex_t read_buf_lock, write_buf_lock;
|
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;
|
} Screen;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -203,7 +203,7 @@ create_graphics_vao() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
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 {
|
struct CellRenderData {
|
||||||
GLfloat xstart, ystart, dx, dy, sprite_dx, sprite_dy;
|
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;
|
static struct CellRenderData *rd;
|
||||||
|
|
||||||
bool inverted = screen_invert_colors(screen);
|
|
||||||
// Send the uniform data
|
// Send the uniform data
|
||||||
rd = (struct CellRenderData*)map_vao_buffer(vao_idx, uniform_buffer, GL_WRITE_ONLY);
|
rd = (struct CellRenderData*)map_vao_buffer(vao_idx, uniform_buffer, GL_WRITE_ONLY);
|
||||||
if (UNLIKELY(screen->color_profile->dirty)) {
|
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;
|
unmap_vao_buffer(vao_idx, uniform_buffer); rd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
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, CursorRenderInfo *cursor) {
|
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;
|
size_t sz;
|
||||||
CELL_BUFFERS;
|
CELL_BUFFERS;
|
||||||
void *address;
|
void *address;
|
||||||
|
bool needs_render = false;
|
||||||
|
|
||||||
ensure_sprite_map();
|
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);
|
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);
|
screen_update_cell_data(screen, address, sz);
|
||||||
unmap_vao_buffer(vao_idx, cell_data_buffer); address = NULL;
|
unmap_vao_buffer(vao_idx, cell_data_buffer); address = NULL;
|
||||||
|
needs_render = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (screen_is_selection_dirty(screen)) {
|
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);
|
address = alloc_and_map_vao_buffer(vao_idx, sz, selection_buffer, GL_STREAM_DRAW, GL_WRITE_ONLY);
|
||||||
screen_apply_selection(screen, address, sz);
|
screen_apply_selection(screen, address, sz);
|
||||||
unmap_vao_buffer(vao_idx, selection_buffer); address = NULL;
|
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)) {
|
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);
|
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));
|
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;
|
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);
|
if (needs_render) {
|
||||||
bind_vertex_array(vao_idx);
|
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
|
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);
|
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
|
bool
|
||||||
draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen, CursorRenderInfo *cursor) {
|
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;
|
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(
|
glScissor(
|
||||||
(GLint)(SCALE(width, (xstart + 1.0f) / 2.0f)),
|
(GLint)(SCALE(width, (xstart + 1.0f) / 2.0f)),
|
||||||
(GLint)(SCALE(height, ((ystart - h) + 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)))
|
(GLsizei)(ceilf(SCALE(height, h / 2.0f)))
|
||||||
);
|
);
|
||||||
#undef SCALE
|
#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);
|
if (screen->grman->num_of_negative_refs) draw_cells_interleaved(vao_idx, gvao_idx, screen);
|
||||||
else draw_all_cells(vao_idx, gvao_idx, screen);
|
else draw_all_cells(vao_idx, gvao_idx, screen);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
@ -374,11 +394,11 @@ init_cursor_program() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
draw_cursor(CursorRenderInfo *cursor) {
|
draw_cursor(CursorRenderInfo *cursor, bool is_focused) {
|
||||||
bind_program(CURSOR_PROGRAM); bind_vertex_array(cursor_vertex_array);
|
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);
|
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);
|
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();
|
unbind_vertex_array(); unbind_program();
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|||||||
@ -76,7 +76,7 @@ typedef struct {
|
|||||||
int viewport_width, viewport_height;
|
int viewport_width, viewport_height;
|
||||||
double viewport_x_ratio, viewport_y_ratio;
|
double viewport_x_ratio, viewport_y_ratio;
|
||||||
Tab tabs[MAX_CHILDREN];
|
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;
|
ScreenRenderData tab_bar_render_data;
|
||||||
bool is_focused;
|
bool is_focused;
|
||||||
double cursor_blink_zero_time, last_mouse_activity_at;
|
double cursor_blink_zero_time, last_mouse_activity_at;
|
||||||
@ -85,6 +85,7 @@ typedef struct {
|
|||||||
PyObject *window_title;
|
PyObject *window_title;
|
||||||
bool is_key_pressed[MAX_KEY_COUNT];
|
bool is_key_pressed[MAX_KEY_COUNT];
|
||||||
bool viewport_size_dirty;
|
bool viewport_size_dirty;
|
||||||
|
bool needs_render;
|
||||||
} OSWindow;
|
} OSWindow;
|
||||||
|
|
||||||
|
|
||||||
@ -99,29 +100,32 @@ typedef struct {
|
|||||||
OSWindow os_windows[MAX_CHILDREN];
|
OSWindow os_windows[MAX_CHILDREN];
|
||||||
size_t num_os_windows;
|
size_t num_os_windows;
|
||||||
OSWindow *callback_os_window, *focussed_os_window;
|
OSWindow *callback_os_window, *focussed_os_window;
|
||||||
|
bool close_all_windows;
|
||||||
} GlobalState;
|
} GlobalState;
|
||||||
|
|
||||||
extern GlobalState global_state;
|
extern GlobalState global_state;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool is_visible;
|
|
||||||
CursorShape shape;
|
|
||||||
double left, right, top, bottom;
|
|
||||||
color_type color;
|
|
||||||
} CursorRenderInfo;
|
|
||||||
|
|
||||||
#define call_boss(name, ...) { \
|
#define call_boss(name, ...) { \
|
||||||
PyObject *cret_ = PyObject_CallMethod(global_state.boss, #name, __VA_ARGS__); \
|
PyObject *cret_ = PyObject_CallMethod(global_state.boss, #name, __VA_ARGS__); \
|
||||||
if (cret_ == NULL) { PyErr_Print(); } \
|
if (cret_ == NULL) { PyErr_Print(); } \
|
||||||
else Py_DECREF(cret_); \
|
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* os_window_for_kitty_window(unsigned int);
|
||||||
OSWindow* current_os_window();
|
OSWindow* current_os_window();
|
||||||
bool drag_scroll(Window *, OSWindow*);
|
bool drag_scroll(Window *, OSWindow*);
|
||||||
void draw_borders();
|
void draw_borders();
|
||||||
void draw_cells(ssize_t, ssize_t, float, float, float, float, Screen *, CursorRenderInfo *);
|
bool draw_cells(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *);
|
||||||
void draw_cursor(CursorRenderInfo *);
|
void draw_cursor(CursorRenderInfo *, bool);
|
||||||
void update_viewport_size(int, int);
|
void update_viewport_size(int, int);
|
||||||
void free_texture(uint32_t*);
|
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);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user