Implement keyboard shortcuts for scrolling

This commit is contained in:
Kovid Goyal 2016-11-21 20:48:51 +05:30
parent b1dba240ca
commit b426210e38
5 changed files with 60 additions and 5 deletions

View File

@ -281,4 +281,15 @@ class Boss(Thread):
text = subprocess.check_output(['xsel']) text = subprocess.check_output(['xsel'])
self.paste(text) self.paste(text)
def scroll_line_up(self):
self.queue_action(self.char_grid.scroll, 'line', True)
def scroll_line_down(self):
self.queue_action(self.char_grid.scroll, 'line', False)
def scroll_page_up(self):
self.queue_action(self.char_grid.scroll, 'page', True)
def scroll_page_down(self):
self.queue_action(self.char_grid.scroll, 'page', False)
# }}} # }}}

View File

@ -218,15 +218,25 @@ class CharGrid:
self.render_queue.put(RenderData(clear_color=self.default_bg)) self.render_queue.put(RenderData(clear_color=self.default_bg))
self.clear_count = 4 self.clear_count = 4
def scroll(self, amt, upwards=True):
amt = 1 if amt == 'line' else self.screen.lines - 1 if amt == 'page' else max(0, min(int(amt), self.screen.lines - 1))
if not upwards:
amt *= -1
y = max(0, min(self.scrolled_by + amt, self.screen.historybuf.count))
if y != self.scrolled_by:
self.scrolled_by = y
self.update_cell_data()
def update_cell_data(self, add_viewport_data=False): def update_cell_data(self, add_viewport_data=False):
rd = RenderData(sprite_layout=self.sprites.layout) rd = RenderData(sprite_layout=self.sprites.layout, cell_data_changed=True)
if add_viewport_data: if add_viewport_data:
rd.viewport = Size(self.width, self.height) rd.viewport = Size(self.width, self.height)
rd.screen_geometry = self.screen_geometry rd.screen_geometry = self.screen_geometry
with self.sprites_lock: with self.sprites_lock:
cursor_changed = self.screen.update_cell_data( cursor_changed, history_line_added_count = self.screen.update_cell_data(
self.sprites.backend, self.color_profile, addressof(self.main_sprite_map), self.default_fg, self.default_bg, add_viewport_data) self.sprites.backend, self.color_profile, addressof(self.main_sprite_map), self.default_fg, self.default_bg, add_viewport_data)
if self.scrolled_by: if self.scrolled_by:
self.scrolled_by = min(self.scrolled_by + history_line_added_count, self.screen.historybuf.count)
self.screen.set_scroll_cell_data( self.screen.set_scroll_cell_data(
self.sprites.backend, self.color_profile, addressof(self.main_sprite_map), self.default_fg, self.default_bg, self.sprites.backend, self.color_profile, addressof(self.main_sprite_map), self.default_fg, self.default_bg,
self.scrolled_by, addressof(self.scroll_sprite_map)) self.scrolled_by, addressof(self.scroll_sprite_map))
@ -234,7 +244,6 @@ class CharGrid:
data = self.scroll_sprite_map if self.scrolled_by else self.main_sprite_map data = self.scroll_sprite_map if self.scrolled_by else self.main_sprite_map
with self.buffer_lock: with self.buffer_lock:
memmove(self.render_buf, data, sizeof(type(data))) memmove(self.render_buf, data, sizeof(type(data)))
rd.cell_data_changed = True
if cursor_changed: if cursor_changed:
c = self.screen.cursor c = self.screen.cursor
rd.cursor = Cursor(c.x, c.y, c.hidden, c.shape, c.color, c.blink) rd.cursor = Cursor(c.x, c.y, c.hidden, c.shape, c.color, c.blink)

View File

@ -323,6 +323,7 @@ unsigned int linebuf_char_width_at(LineBuf *self, index_type x, index_type y);
bool historybuf_resize(HistoryBuf *self, index_type lines); bool historybuf_resize(HistoryBuf *self, index_type lines);
void historybuf_add_line(HistoryBuf *self, const Line *line); void historybuf_add_line(HistoryBuf *self, const Line *line);
void historybuf_rewrap(HistoryBuf *self, HistoryBuf *other); void historybuf_rewrap(HistoryBuf *self, HistoryBuf *other);
void historybuf_init_line(HistoryBuf *self, index_type num, Line *l);
void screen_restore_cursor(Screen *); void screen_restore_cursor(Screen *);
void screen_save_cursor(Screen *); void screen_save_cursor(Screen *);

View File

@ -70,6 +70,10 @@ static inline void init_line(HistoryBuf *self, index_type num, Line *l) {
l->combining_chars = (combining_type*)(l->decoration_fg + self->xnum); l->combining_chars = (combining_type*)(l->decoration_fg + self->xnum);
} }
void historybuf_init_line(HistoryBuf *self, index_type lnum, Line *l) {
init_line(self, index_of(self, lnum), l);
}
static inline index_type historybuf_push(HistoryBuf *self) { static inline index_type historybuf_push(HistoryBuf *self) {
index_type idx = (self->start_of_data + self->count) % self->ynum; index_type idx = (self->start_of_data + self->count) % self->ynum;
init_line(self, idx, self->line); init_line(self, idx, self->line);

View File

@ -1029,11 +1029,40 @@ screen_update_cell_data(Screen *self, PyObject *args) {
if (!PyArg_ParseTuple(args, "O!O!O!kkp", &SpriteMap_Type, &spm, &ColorProfile_Type, &color_profile, &PyLong_Type, &dp, &default_fg, &default_bg, &force_screen_refresh)) return NULL; if (!PyArg_ParseTuple(args, "O!O!O!kkp", &SpriteMap_Type, &spm, &ColorProfile_Type, &color_profile, &PyLong_Type, &dp, &default_fg, &default_bg, &force_screen_refresh)) return NULL;
data = PyLong_AsVoidPtr(dp); data = PyLong_AsVoidPtr(dp);
PyObject *cursor_changed = self->change_tracker->cursor_changed ? Py_True : Py_False; PyObject *cursor_changed = self->change_tracker->cursor_changed ? Py_True : Py_False;
unsigned int history_line_added_count = self->change_tracker->history_line_added_count;
if (!tracker_update_cell_data(self->change_tracker, self->linebuf, spm, color_profile, data, default_fg, default_bg, (bool)force_screen_refresh)) return NULL; if (!tracker_update_cell_data(self->change_tracker, self->linebuf, spm, color_profile, data, default_fg, default_bg, (bool)force_screen_refresh)) return NULL;
Py_INCREF(cursor_changed); return Py_BuildValue("OI", cursor_changed, history_line_added_count);
return cursor_changed;
} }
static PyObject*
set_scroll_cell_data(Screen *self, PyObject *args) {
SpriteMap *spm;
ColorProfile *color_profile;
PyObject *dp, *sp;
unsigned int *data, *src, scrolled_by;
unsigned long default_bg, default_fg;
if (!PyArg_ParseTuple(args, "O!O!O!kkIO", &SpriteMap_Type, &spm, &ColorProfile_Type, &color_profile, &PyLong_Type, &sp, &default_fg, &default_bg, &scrolled_by, &dp)) return NULL;
data = PyLong_AsVoidPtr(dp);
src = PyLong_AsVoidPtr(sp);
unsigned int line_size = 9 * self->columns;
scrolled_by = MIN(self->historybuf->count, scrolled_by);
for (index_type y = 0; y < MIN(self->lines, scrolled_by); y++) {
historybuf_init_line(self->historybuf, scrolled_by - y, self->historybuf->line);
self->historybuf->line->ynum = y;
if (!update_cell_range_data(spm, self->historybuf->line, 0, self->columns - 1, color_profile, default_bg, default_fg, data)) return NULL;
}
if (scrolled_by < self->lines) {
// Less than a full screen has been scrolled, copy some lines from the screen buffer to the scroll buffer
index_type num_to_copy = self->lines - scrolled_by;
index_type offset = line_size * scrolled_by;
memcpy(data + offset, src, line_size * num_to_copy * sizeof(unsigned int));
}
Py_RETURN_NONE;
}
static PyObject* is_dirty(Screen *self) { static PyObject* is_dirty(Screen *self) {
PyObject *ans = self->change_tracker->dirty ? Py_True : Py_False; PyObject *ans = self->change_tracker->dirty ? Py_True : Py_False;
Py_INCREF(ans); Py_INCREF(ans);
@ -1096,6 +1125,7 @@ static PyMethodDef methods[] = {
MND(reverse_index, METH_NOARGS) MND(reverse_index, METH_NOARGS)
MND(is_dirty, METH_NOARGS) MND(is_dirty, METH_NOARGS)
MND(resize, METH_VARARGS) MND(resize, METH_VARARGS)
MND(set_scroll_cell_data, METH_VARARGS)
{"update_cell_data", (PyCFunction)screen_update_cell_data, METH_VARARGS, ""}, {"update_cell_data", (PyCFunction)screen_update_cell_data, METH_VARARGS, ""},
{NULL} /* Sentinel */ {NULL} /* Sentinel */