summaryrefslogtreecommitdiff
path: root/src/user/raleigh
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/raleigh')
-rw-r--r--src/user/raleigh/w/button.cpp11
-rw-r--r--src/user/raleigh/w/entry.cpp215
-rw-r--r--src/user/raleigh/w/label.cpp9
-rw-r--r--src/user/raleigh/w/padding.cpp16
-rw-r--r--src/user/raleigh/w/vbox.cpp12
-rw-r--r--src/user/raleigh/window.cpp26
6 files changed, 222 insertions, 67 deletions
diff --git a/src/user/raleigh/w/button.cpp b/src/user/raleigh/w/button.cpp
index 06d9c1d..a92167e 100644
--- a/src/user/raleigh/w/button.cpp
+++ b/src/user/raleigh/w/button.cpp
@@ -31,9 +31,9 @@ namespace raleigh {
}
}
- bool button::try_handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {
+ void button::handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {
if (click_type != mouse_packet::LEFT)
- return false;
+ return;
if (up) {
is_pressed = false;
inner.window_offset = coord(window_offset.x + 1, window_offset.y + 1);
@@ -47,8 +47,13 @@ namespace raleigh {
inner.notify_window_change();
w->notify_needs_paint(*this);
}
- return true;
}
void button::notify_has_opaque_parent(widget *parent) {}
+
+ void button::handle_key(struct key_packet kp) {}
+
+ void button::on_focus() {}
+
+ void button::on_unfocus() {}
} \ No newline at end of file
diff --git a/src/user/raleigh/w/entry.cpp b/src/user/raleigh/w/entry.cpp
index de8bd82..1c6f91e 100644
--- a/src/user/raleigh/w/entry.cpp
+++ b/src/user/raleigh/w/entry.cpp
@@ -2,55 +2,76 @@
#include <knob/format.h>
#include <knob/block.h>
#include <knob/heap.h>
+#include <knob/key.h>
namespace raleigh {
entry::entry(uint32_t rows, uint32_t cols, const char *default_text,
const char *font, _pixel_t bg, _pixel_t fg, _pixel_t border_color)
: rows(rows), cols(cols), bg(bg), fg(fg), border_color(border_color),
fi(get_font(font)), data(new char[rows * cols]),
- line_indices(new uint32_t[rows + 1]), first_paint(true) {
- size = coord(fi->space_width * (cols - 1) + fi->char_width + 6, fi->space_height * (rows - 1) + fi->char_height + 6);
+ line_indices(new uint32_t[rows + 1]), first_paint(true),
+ has_focus(false) {
+ size = coord(fi->space_width * (cols - 1) + fi->char_width + 6,
+ fi->space_height * (rows - 1) + fi->char_height + 6);
closest_opaque = this;
- end_x = 0;
- end_y = 0;
+ const uint32_t l = strlen(default_text);
+ const uint32_t cl = l > rows * cols - 1 ? rows * cols - 1 : l;
+ blockcpy(data, default_text, cl);
+ data[cl] = '\0';
+
line_indices[0] = 0;
- for (end_d = 0; default_text[end_d]; ++end_d) {
- if (end_d == rows * cols - 1)
- break;
- data[end_d] = default_text[end_d];
- if ((default_text[end_d] == '\n') || (++end_x == cols)) {
- if (end_y == rows - 1)
- break;
- line_indices[++end_y] = end_d + 1;
- end_x = 0;
- }
- }
- line_indices[end_y + 1] = end_d;
+ get_indices(0, 0, 0);
cur_x = end_x;
cur_y = end_y;
cur_d = end_d;
- data[end_d] = '\0';
}
- void entry::notify_window_change() {}
-
- void entry::paint_text(_pixel_t *pixbuf, uint32_t pitch) {
- uint32_t y = 0;
- uint32_t x = -1;
- for (const char *i = data; *i; ++i) {
- if (*i == '\n') {
- ++y;
- x = -1;
+ void entry::get_indices(uint32_t from_y, uint32_t from_x, uint32_t from_d) {
+ while (1) {
+ const uint32_t ln = str_find_any(data + from_d, " \n");
+ bool quit_after = !data[from_d + ln];
+ if ((from_x + ln <= cols) || (ln >= cols)) {
+ from_x += ln;
+ from_d += ln;
+ if (data[from_d] == '\n') {
+ ++from_y;
+ from_x = 0;
+ line_indices[from_y] = from_d + 1;
+ }
+ else
+ ++from_x;
+ ++from_d;
+ if (from_x >= cols) {
+ ++from_y;
+ from_x = 0;
+ line_indices[from_y] = from_d;
+ }
+ if (quit_after)
+ break;
}
else {
- if (++x == cols) {
- ++y;
- x = 0;
- }
- put_char_no_bg(fi, *i, pixbuf + (window_offset.y + 3 + y * fi->space_height) * pitch + (window_offset.x + 3 + x * fi->space_width), pitch, fg);
+ ++from_y;
+ from_x = 0;
+ line_indices[from_y] = from_d;
}
}
+ line_indices[from_y + 1] = from_d;
+ end_y = from_y;
+ end_x = from_x;
+ end_d = from_d;
+ }
+
+ void entry::notify_window_change() {}
+
+ void entry::paint_text(_pixel_t *pixbuf, uint32_t pitch) {
+ for (uint32_t y = 0; y <= end_y; ++y) {
+ const char *const line = data + line_indices[y];
+ const uint32_t len = line_indices[y + 1] - line_indices[y] >= cols ? cols : line_indices[y + 1] - line_indices[y];
+ for (uint32_t x = 0; x < len; ++x)
+ if ((line[x] != '\n') && line[x])
+ put_char_no_bg(fi, line[x], pixbuf + (window_offset.y + 3 + y * fi->space_height) * pitch + (window_offset.x + 3 + x * fi->space_width), pitch, fg);
+ }
}
void entry::paint(_pixel_t *pixbuf, uint32_t pitch) {
@@ -83,28 +104,40 @@ namespace raleigh {
text_changed_since_last_paint = false;
}
- else {
+ else if (had_focus_last_paint) {
for (uint32_t y = 0; y < fi->char_height; ++y) {
old_cur_ptr[y * pitch] = bg;
old_cur_ptr[y * pitch + 1] = bg;
}
- if (data[cur_d_last_paint] && (data[cur_d_last_paint] != '\n'))
+ if (data[cur_d_last_paint] && (data[cur_d_last_paint] != '\n') && (cur_d_last_paint < line_indices[cur_y_last_paint + 1]))
put_char_no_bg(fi, data[cur_d_last_paint], old_cur_ptr, pitch, fg);
}
- for (uint32_t y = 0; y < fi->char_height; ++y) {
- cur_ptr[y * pitch] = fg;
- cur_ptr[y * pitch + 1] = fg;
- }
+ if (has_focus)
+ for (uint32_t y = 0; y < fi->char_height; ++y) {
+ cur_ptr[y * pitch] = fg;
+ cur_ptr[y * pitch + 1] = fg;
+ }
cur_y_last_paint = cur_y;
cur_x_last_paint = cur_x;
cur_d_last_paint = cur_d;
+ had_focus_last_paint = has_focus;
+ }
+
+ void entry::ensure_cursor_in_line() {
+ cur_d = line_indices[cur_y] + cur_x;
+ if (cur_d >= line_indices[cur_y + 1]) {
+ cur_d = line_indices[cur_y + 1] - 1;
+ if (data[cur_d] && (data[cur_d] != '\n'))
+ ++cur_d;
+ cur_x = cur_d - line_indices[cur_y];
+ }
}
- bool entry::try_handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {
+ void entry::handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {
if (up || (click_type != mouse_packet::LEFT))
- return false;
+ return;
if (window_coords.x - window_offset.x < 3)
window_coords.x = 3 + window_offset.x;
@@ -121,18 +154,110 @@ namespace raleigh {
cur_y = end_y;
cur_x = end_x;
}
+ ensure_cursor_in_line();
+
+ if (has_focus)
+ w->notify_needs_paint(*this);
+ else
+ w->focus(*this);
+ }
+
+ void entry::notify_has_opaque_parent(widget *parent) {}
+
+ bool entry::cursor_left() {
+ if (cur_x) {
+ --cur_x;
+ --cur_d;
+ return true;
+ }
+ if (!cur_y)
+ return false;
+
+ --cur_y;
+ cur_x = line_indices[cur_y + 1] - line_indices[cur_y] - 1;
+ if (cur_x == cols)
+ --cur_x;
cur_d = line_indices[cur_y] + cur_x;
+ return true;
+ }
+
+ bool entry::cursor_right() {
+ if (cur_d >= (end_d - 1))
+ return false;
+
+ ++cur_d;
+ ++cur_x;
if (cur_d >= line_indices[cur_y + 1]) {
- cur_d = line_indices[cur_y + 1] - 1;
- if (data[cur_d] != '\n')
- ++cur_d;
- cur_x = cur_d - line_indices[cur_y];
+ cur_x = 0;
+ ++cur_y;
+ cur_d = line_indices[cur_y];
}
- w->notify_needs_paint(*this);
return true;
}
- void entry::notify_has_opaque_parent(widget *parent) {}
+ bool entry::cursor_up() {
+ if (!cur_y)
+ return false;
+
+ --cur_y;
+ ensure_cursor_in_line();
+ return true;
+ }
+
+ bool entry::cursor_down() {
+ if (cur_y == end_y)
+ return false;
+
+ ++cur_y;
+ ensure_cursor_in_line();
+ return true;
+ }
+
+ void entry::handle_key(struct key_packet kp) {
+ switch (kp.key_id) {
+ case kp.KEY_LEFT_ARROW:
+ if (cursor_left() && has_focus)
+ w->notify_needs_paint(*this);
+ break;
+ case kp.KEY_RIGHT_ARROW:
+ if (cursor_right() && has_focus)
+ w->notify_needs_paint(*this);
+ break;
+ case kp.KEY_DOWN_ARROW:
+ if (cursor_down() && has_focus)
+ w->notify_needs_paint(*this);
+ break;
+ case kp.KEY_UP_ARROW:
+ if (cursor_up() && has_focus)
+ w->notify_needs_paint(*this);
+ break;
+ case kp.KEY_HOME:
+ if (cur_x) {
+ cur_x = 0;
+ if (has_focus)
+ w->notify_needs_paint(*this);
+ }
+ break;
+ case kp.KEY_END:
+ cur_x = cols;
+ ensure_cursor_in_line();
+ if (has_focus)
+ w->notify_needs_paint(*this);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void entry::on_focus() {
+ has_focus = true;
+ w->notify_needs_paint(*this);
+ }
+
+ void entry::on_unfocus() {
+ has_focus = false;
+ w->notify_needs_paint(*this);
+ }
} \ No newline at end of file
diff --git a/src/user/raleigh/w/label.cpp b/src/user/raleigh/w/label.cpp
index 5b74175..046737f 100644
--- a/src/user/raleigh/w/label.cpp
+++ b/src/user/raleigh/w/label.cpp
@@ -23,12 +23,13 @@ namespace raleigh {
}
}
- __attribute__ ((const))
- bool label::try_handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {
- return false;
- }
+ void label::handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) { }
void label::notify_has_opaque_parent(widget *parent) {
closest_opaque = parent;
}
+
+ void label::handle_key(struct key_packet kp) {};
+ void label::on_focus() {};
+ void label::on_unfocus() {};
} \ No newline at end of file
diff --git a/src/user/raleigh/w/padding.cpp b/src/user/raleigh/w/padding.cpp
index 0f93216..87167c3 100644
--- a/src/user/raleigh/w/padding.cpp
+++ b/src/user/raleigh/w/padding.cpp
@@ -17,16 +17,20 @@ namespace raleigh {
inner.paint(pixbuf, pitch);
}
- bool padding::try_handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {
- return (window_coords.x >= inner.window_offset.x) &&
- (window_coords.y >= inner.window_offset.y) &&
- (window_coords.x < inner.window_offset.x + inner.size.x) &&
- (window_coords.y < inner.window_offset.y + inner.size.y) &&
- inner.try_handle_click(window_coords, click_type, up);
+ void padding::handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {
+ if ((window_coords.x >= inner.window_offset.x) &&
+ (window_coords.y >= inner.window_offset.y) &&
+ (window_coords.x < inner.window_offset.x + inner.size.x) &&
+ (window_coords.y < inner.window_offset.y + inner.size.y))
+ inner.handle_click(window_coords, click_type, up);
}
void padding::notify_has_opaque_parent(widget *parent) {
closest_opaque = parent;
inner.notify_has_opaque_parent(parent);
}
+
+ void padding::handle_key(struct key_packet kp) {};
+ void padding::on_focus() {};
+ void padding::on_unfocus() {};
} \ No newline at end of file
diff --git a/src/user/raleigh/w/vbox.cpp b/src/user/raleigh/w/vbox.cpp
index 51b87ed..08c2539 100644
--- a/src/user/raleigh/w/vbox.cpp
+++ b/src/user/raleigh/w/vbox.cpp
@@ -27,16 +27,16 @@ namespace raleigh {
n->d.paint(pixbuf, pitch);
}
- bool vbox::try_handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {
+ void vbox::handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {
uint32_t h = window_offset.y;
dllist<widget &>::node *n = widgets.first;
while (h + n->d.size.y <= window_coords.y) {
h += n->d.size.y;
n = n->next;
}
- return (window_coords.x >= n->d.window_offset.x) &&
- (window_coords.x < n->d.window_offset.x + n->d.size.x) &&
- n->d.try_handle_click(window_coords, click_type, up);
+ if ((window_coords.x >= n->d.window_offset.x) &&
+ (window_coords.x < n->d.window_offset.x + n->d.size.x))
+ n->d.handle_click(window_coords, click_type, up);
}
void vbox::notify_has_opaque_parent(widget *parent) {
@@ -44,4 +44,8 @@ namespace raleigh {
for (dllist<widget &>::node *n = widgets.first; n; n = n->next)
n->d.notify_has_opaque_parent(parent);
}
+
+ void vbox::handle_key(struct key_packet kp) {};
+ void vbox::on_focus() {};
+ void vbox::on_unfocus() {};
} \ No newline at end of file
diff --git a/src/user/raleigh/window.cpp b/src/user/raleigh/window.cpp
index c23545b..052422e 100644
--- a/src/user/raleigh/window.cpp
+++ b/src/user/raleigh/window.cpp
@@ -7,8 +7,8 @@
namespace raleigh {
window::window(widget &root, _pixel_t bg_color, bool (*on_close)(window &))
- : handle(0), size(root.size), root(root), bg_color(bg_color),
- needs_repaint(false), on_close(on_close) {
+ : handle(0), size(root.size), root(root), focussed(&root),
+ bg_color(bg_color), on_close(on_close) {
root.w = this;
root.window_offset = coord(0, 0);
root.notify_window_change();
@@ -18,6 +18,8 @@ namespace raleigh {
show_error_and_quitf("Failed to create %d byte pixel buffer\nfor requested %dx%d pixel window.", size.x * size.y * sizeof(_pixel_t), size.x, size.y);
paint_full();
+ root.on_focus();
+ needs_repaint = false;
}
window::try_actions_return_t window::try_actions() {
@@ -39,9 +41,15 @@ namespace raleigh {
return DELETE;
got = GOOD;
if (wa.action_type == wa.MOUSE_DOWN)
- root.try_handle_click(coord(wa.as_mouse.x, wa.as_mouse.y), wa.as_mouse.which, false);
- if (wa.action_type == wa.MOUSE_UP)
- root.try_handle_click(coord(wa.as_mouse.x, wa.as_mouse.y), wa.as_mouse.which, true);
+ root.handle_click(coord(wa.as_mouse.x, wa.as_mouse.y), wa.as_mouse.which, false);
+ else if (wa.action_type == wa.MOUSE_UP)
+ root.handle_click(coord(wa.as_mouse.x, wa.as_mouse.y), wa.as_mouse.which, true);
+ else if (wa.action_type == wa.KEY_DOWN)
+ focussed->handle_key(wa.as_key);
+ else if (wa.action_type == wa.FOCUS_ENTER)
+ focussed->on_focus();
+ else if (wa.action_type == wa.FOCUS_LEAVE)
+ focussed->on_unfocus();
}
}
@@ -67,4 +75,12 @@ namespace raleigh {
show_error_and_quitf("Failed to get window handle for requested window.");
open_windows.add_front(*this);
}
+
+ void window::focus(widget &w) {
+ if (focussed != &w) {
+ focussed->on_unfocus();
+ focussed = &w;
+ focussed->on_focus();
+ }
+ }
} \ No newline at end of file