Move visual bell tracking into the Screen object

This commit is contained in:
Kovid Goyal 2017-09-12 14:40:30 +05:30
parent ca5eb4feb5
commit ccf5391b45
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
8 changed files with 57 additions and 37 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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