Implement keyboard shortcuts for scrolling
This commit is contained in:
parent
b1dba240ca
commit
b426210e38
@ -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)
|
||||||
# }}}
|
# }}}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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 *);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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 */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user