Move visual bell tracking into the Screen object
This commit is contained in:
parent
ca5eb4feb5
commit
ccf5391b45
@ -369,7 +369,7 @@ class Boss:
|
|||||||
self.tab_manager.render()
|
self.tab_manager.render()
|
||||||
for window in tab.visible_windows():
|
for window in tab.visible_windows():
|
||||||
if not window.needs_layout:
|
if not window.needs_layout:
|
||||||
window.render_cells()
|
window.char_grid.render_cells()
|
||||||
active = self.active_window
|
active = self.active_window
|
||||||
if active is not None:
|
if active is not None:
|
||||||
draw_cursor = True
|
draw_cursor = True
|
||||||
|
|||||||
@ -42,8 +42,8 @@ def calculate_gl_geometry(window_geometry, viewport_width, viewport_height, cell
|
|||||||
return ScreenGeometry(xstart, ystart, window_geometry.xnum, window_geometry.ynum, dx, dy)
|
return ScreenGeometry(xstart, ystart, window_geometry.xnum, window_geometry.ynum, dx, dy)
|
||||||
|
|
||||||
|
|
||||||
def render_cells(vao_id, sg, screen, invert_colors=False):
|
def render_cells(vao_id, sg, screen):
|
||||||
draw_cells(vao_id, sg.xstart, sg.ystart, sg.dx, sg.dy, invert_colors, screen)
|
draw_cells(vao_id, sg.xstart, sg.ystart, sg.dx, sg.dy, screen)
|
||||||
|
|
||||||
|
|
||||||
class CharGrid:
|
class CharGrid:
|
||||||
@ -172,10 +172,8 @@ class CharGrid:
|
|||||||
def text_for_selection(self):
|
def text_for_selection(self):
|
||||||
return ''.join(self.screen.text_for_selection())
|
return ''.join(self.screen.text_for_selection())
|
||||||
|
|
||||||
def render_cells(self, invert_colors=False):
|
def render_cells(self):
|
||||||
render_cells(
|
render_cells(self.vao_id, self.screen_geometry, self.screen)
|
||||||
self.vao_id, self.screen_geometry,
|
|
||||||
self.screen, invert_colors=invert_colors)
|
|
||||||
|
|
||||||
def render_cursor(self, is_focused):
|
def render_cursor(self, is_focused):
|
||||||
if not self.screen.cursor_visible or self.screen.scrolled_by:
|
if not self.screen.cursor_visible or self.screen.scrolled_by:
|
||||||
|
|||||||
@ -247,6 +247,7 @@ typedef struct {
|
|||||||
bool *tabstops, *main_tabstops, *alt_tabstops;
|
bool *tabstops, *main_tabstops, *alt_tabstops;
|
||||||
ScreenModes modes;
|
ScreenModes modes;
|
||||||
ColorProfile *color_profile;
|
ColorProfile *color_profile;
|
||||||
|
double start_visual_bell_at;
|
||||||
|
|
||||||
uint32_t parser_buf[PARSER_BUF_SZ];
|
uint32_t parser_buf[PARSER_BUF_SZ];
|
||||||
unsigned int parser_state, parser_text_start, parser_buf_pos;
|
unsigned int parser_state, parser_text_start, parser_buf_pos;
|
||||||
@ -286,6 +287,19 @@ typedef struct {
|
|||||||
} ChildMonitor;
|
} ChildMonitor;
|
||||||
PyTypeObject ChildMonitor_Type;
|
PyTypeObject ChildMonitor_Type;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double visual_bell_duration;
|
||||||
|
bool enable_audio_bell;
|
||||||
|
} Options;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Options opts;
|
||||||
|
} GlobalState;
|
||||||
|
|
||||||
|
#ifndef IS_STATE
|
||||||
|
extern GlobalState global_state;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define clear_sprite_position(cell) (cell).sprite_x = 0; (cell).sprite_y = 0; (cell).sprite_z = 0;
|
#define clear_sprite_position(cell) (cell).sprite_x = 0; (cell).sprite_y = 0; (cell).sprite_z = 0;
|
||||||
|
|
||||||
#define left_shift_line(line, at, num) \
|
#define left_shift_line(line, at, num) \
|
||||||
|
|||||||
@ -16,6 +16,9 @@
|
|||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include <structmember.h>
|
#include <structmember.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include "unicode-data.h"
|
#include "unicode-data.h"
|
||||||
#include "modes.h"
|
#include "modes.h"
|
||||||
#include "wcwidth9.h"
|
#include "wcwidth9.h"
|
||||||
@ -911,8 +914,34 @@ screen_use_latin1(Screen *self, bool on) {
|
|||||||
CALLBACK("use_utf8", "O", on ? Py_False : Py_True);
|
CALLBACK("use_utf8", "O", on ? Py_False : Py_True);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
screen_invert_colors(Screen *self) {
|
||||||
|
bool inverted = false;
|
||||||
|
if (self->start_visual_bell_at > 0) {
|
||||||
|
if (monotonic() - self->start_visual_bell_at <= global_state.opts.visual_bell_duration) inverted = true;
|
||||||
|
else self->start_visual_bell_at = 0;
|
||||||
|
}
|
||||||
|
if (self->modes.mDECSCNM) inverted = inverted ? false : true;
|
||||||
|
return inverted;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_bell(Screen UNUSED *self) {
|
screen_bell(Screen UNUSED *self) {
|
||||||
|
if (global_state.opts.enable_audio_bell) {
|
||||||
|
int fd = open("/dev/tty", O_WRONLY | O_CLOEXEC | O_NOCTTY);
|
||||||
|
if (fd > 0) {
|
||||||
|
static const char bell[2] = {7, 0};
|
||||||
|
while(true) {
|
||||||
|
if (write(fd, &bell, sizeof(bell)) == sizeof(bell)) break;
|
||||||
|
if (errno == EINTR) continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (global_state.opts.visual_bell_duration > 0) {
|
||||||
|
self->start_visual_bell_at = monotonic();
|
||||||
|
}
|
||||||
CALLBACK("bell", NULL);
|
CALLBACK("bell", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,6 +61,7 @@ void report_device_status(Screen *self, unsigned int which, bool UNUSED);
|
|||||||
void report_mode_status(Screen *self, unsigned int which, bool);
|
void report_mode_status(Screen *self, unsigned int which, bool);
|
||||||
void screen_apply_selection(Screen *self, void *address, size_t size);
|
void screen_apply_selection(Screen *self, void *address, size_t size);
|
||||||
bool screen_is_selection_dirty(Screen *self);
|
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);
|
void screen_update_cell_data(Screen *self, void *address, size_t sz);
|
||||||
#define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen);
|
#define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen);
|
||||||
DECLARE_CH_SCREEN_HANDLER(bell)
|
DECLARE_CH_SCREEN_HANDLER(bell)
|
||||||
|
|||||||
@ -596,10 +596,10 @@ create_cell_vao() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_cells(ssize_t vao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, bool inverted, Screen *screen) {
|
draw_cells(ssize_t vao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen) {
|
||||||
size_t sz;
|
size_t sz;
|
||||||
void *address;
|
void *address;
|
||||||
if (screen->modes.mDECSCNM) inverted = inverted ? false : true;
|
bool inverted = screen_invert_colors(screen);
|
||||||
if (screen->scroll_changed || screen->is_dirty) {
|
if (screen->scroll_changed || screen->is_dirty) {
|
||||||
sz = sizeof(Cell) * screen->lines * screen->columns;
|
sz = sizeof(Cell) * screen->lines * screen->columns;
|
||||||
address = map_vao_buffer(vao_idx, sz, 0, GL_STREAM_DRAW, GL_WRITE_ONLY);
|
address = map_vao_buffer(vao_idx, sz, 0, GL_STREAM_DRAW, GL_WRITE_ONLY);
|
||||||
@ -839,11 +839,11 @@ NO_ARG(init_cell_program)
|
|||||||
NO_ARG_INT(create_cell_vao)
|
NO_ARG_INT(create_cell_vao)
|
||||||
PYWRAP1(draw_cells) {
|
PYWRAP1(draw_cells) {
|
||||||
float xstart, ystart, dx, dy;
|
float xstart, ystart, dx, dy;
|
||||||
int vao_idx, inverted;
|
int vao_idx;
|
||||||
Screen *screen;
|
Screen *screen;
|
||||||
|
|
||||||
PA("iffffpO", &vao_idx, &xstart, &ystart, &dx, &dy, &inverted, &screen);
|
PA("iffffO", &vao_idx, &xstart, &ystart, &dx, &dy, &screen);
|
||||||
draw_cells(vao_idx, xstart, ystart, dx, dy, inverted & 1, screen);
|
draw_cells(vao_idx, xstart, ystart, dx, dy, screen);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
NO_ARG(destroy_sprite_map)
|
NO_ARG(destroy_sprite_map)
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
* Distributed under terms of the GPL3 license.
|
* Distributed under terms of the GPL3 license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define IS_STATE
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
|
|
||||||
#define PYWRAP0(name) static PyObject* py##name(PyObject UNUSED *self)
|
#define PYWRAP0(name) static PyObject* py##name(PyObject UNUSED *self)
|
||||||
@ -12,21 +13,14 @@
|
|||||||
#define PYWRAP2(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args, PyObject *kw)
|
#define PYWRAP2(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args, PyObject *kw)
|
||||||
#define PA(fmt, ...) if(!PyArg_ParseTuple(args, fmt, __VA_ARGS__)) return NULL;
|
#define PA(fmt, ...) if(!PyArg_ParseTuple(args, fmt, __VA_ARGS__)) return NULL;
|
||||||
|
|
||||||
typedef struct {
|
GlobalState global_state = {{0}};
|
||||||
double visual_bell_duration;
|
|
||||||
} Options;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Options opts;
|
|
||||||
} GlobalState;
|
|
||||||
|
|
||||||
static GlobalState global_state = {{0}};
|
|
||||||
|
|
||||||
|
|
||||||
// Python API {{{
|
// Python API {{{
|
||||||
PYWRAP1(set_options) {
|
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); }
|
||||||
S(visual_bell_duration, PyFloat_AsDouble);
|
S(visual_bell_duration, PyFloat_AsDouble);
|
||||||
|
S(enable_audio_bell, PyObject_IsTrue);
|
||||||
#undef S
|
#undef S
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -117,14 +117,6 @@ class Window:
|
|||||||
print('Failed to write to child %d as it does not exist' % self.id, file=sys.stderr)
|
print('Failed to write to child %d as it does not exist' % self.id, file=sys.stderr)
|
||||||
|
|
||||||
def bell(self):
|
def bell(self):
|
||||||
if self.opts.enable_audio_bell:
|
|
||||||
try:
|
|
||||||
with open('/dev/tty', 'wb') as f:
|
|
||||||
f.write(b'\007')
|
|
||||||
except EnvironmentError:
|
|
||||||
pass # failure to beep is not critical
|
|
||||||
if self.opts.visual_bell_duration > 0:
|
|
||||||
self.start_visual_bell_at = monotonic()
|
|
||||||
get_boss().request_attention()
|
get_boss().request_attention()
|
||||||
glfw_post_empty_event()
|
glfw_post_empty_event()
|
||||||
|
|
||||||
@ -281,14 +273,6 @@ class Window:
|
|||||||
def buf_toggled(self, is_main_linebuf):
|
def buf_toggled(self, is_main_linebuf):
|
||||||
self.screen.scroll(SCROLL_FULL, False)
|
self.screen.scroll(SCROLL_FULL, False)
|
||||||
|
|
||||||
def render_cells(self):
|
|
||||||
invert_colors = False
|
|
||||||
if self.start_visual_bell_at is not None:
|
|
||||||
invert_colors = monotonic() - self.start_visual_bell_at <= self.opts.visual_bell_duration
|
|
||||||
if not invert_colors:
|
|
||||||
self.start_visual_bell_at = None
|
|
||||||
self.char_grid.render_cells(invert_colors)
|
|
||||||
|
|
||||||
# actions {{{
|
# actions {{{
|
||||||
|
|
||||||
def show_scrollback(self):
|
def show_scrollback(self):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user