From 920f1f010284d59bad86f78355ed90ac2f3e1d2c Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Mon, 8 Mar 2021 16:46:22 -0500 Subject: mouse movement in raleigh, with colorpicker dragging example --- src/kernel/idt.c | 3 +- src/kernel/isrs.asm | 2 +- src/kernel/window.c | 16 ++++++++++ src/kernel/window.h | 2 ++ src/shared/include/winact.h | 9 ++++-- src/user/include/cxx/raleigh/w/button.h | 1 + src/user/include/cxx/raleigh/w/colorpicker.h | 3 ++ src/user/include/cxx/raleigh/w/padding.h | 1 + src/user/include/cxx/raleigh/w/vbox.h | 1 + src/user/include/cxx/raleigh/widget.h | 1 + src/user/include/pland/syscall.h | 7 ++++- src/user/raleigh/w/button.cpp | 8 +++++ src/user/raleigh/w/colorpicker.cpp | 46 ++++++++++++++++++++++++++-- src/user/raleigh/w/padding.cpp | 8 +++++ src/user/raleigh/w/vbox.cpp | 11 +++++++ src/user/raleigh/widget.cpp | 1 + src/user/raleigh/window.cpp | 3 ++ 17 files changed, 116 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/kernel/idt.c b/src/kernel/idt.c index f07ef1d..8de5448 100644 --- a/src/kernel/idt.c +++ b/src/kernel/idt.c @@ -208,7 +208,8 @@ void const *syscall_table[] = { &sc_is_task_running, &sc_get_timestamp, &sc_file_write, - &sc_file_set_size + &sc_file_set_size, + &window_wants_mouse_movements }; //these aren't really void ()'s, but gcc complains if we take an address of a void, so we give it a type diff --git a/src/kernel/isrs.asm b/src/kernel/isrs.asm index 70bab19..673e891 100644 --- a/src/kernel/isrs.asm +++ b/src/kernel/isrs.asm @@ -26,7 +26,7 @@ extern exception_halt extern pf_check_stack extern dump -n_syscalls equ 0x1c +n_syscalls equ 0x1d ;section .bss ;_debug_is_start_task resb 1 diff --git a/src/kernel/window.c b/src/kernel/window.c index b1d5f92..4b01bc4 100644 --- a/src/kernel/window.c +++ b/src/kernel/window.c @@ -38,6 +38,7 @@ static struct window { struct window *below; struct task_state *from_task; + bool wants_mouse_movements; } windows[MAX_WINDOWS]; static struct window *bottom_window = 0; @@ -322,6 +323,7 @@ got_window: send_action(top_window, (struct window_action){.action_type = FOCUS_ENTER}); w->from_task = active_task; + w->wants_mouse_movements = false; paint_and_above(w); return w; @@ -544,6 +546,16 @@ void move_mouse_by(int16_t y, int16_t x) { blit(old_x, old_x + MOUSE_WIDTH > VBE_MODE_INFO->width ? VBE_MODE_INFO->width : old_x + MOUSE_WIDTH, old_y, old_y + MOUSE_HEIGHT > VBE_MODE_INFO->height ? VBE_MODE_INFO->height : old_y + MOUSE_HEIGHT); blit_mouse(); + struct window *const moving_over = buffer[mouse_y * VBE_MODE_INFO->width + mouse_x].from_window; + if (moving_over && moving_over->wants_mouse_movements && + (mouse_y >= moving_over->ypos) && (mouse_y < moving_over->ypos + moving_over->height) && + (mouse_x >= moving_over->xpos) && (mouse_x < moving_over->xpos + moving_over->width)) + send_action(moving_over, (struct window_action){ + .action_type = MOUSE_MOVE, .moved_to = { + .x = mouse_x - moving_over->xpos, + .y = mouse_y - moving_over->ypos + } + }); } switch_to_task_cr3(); //logf(LOG_INFO, "new mouse coords: (%d, %d)", mouse_x, mouse_y); @@ -628,4 +640,8 @@ void mouse_button(enum mouse_button which, bool up) { } send_action(clicked_on, (struct window_action){.action_type = up ? MOUSE_UP : MOUSE_DOWN, .as_mouse = {.y = mouse_y - clicked_on->ypos, .x = mouse_x - clicked_on->xpos, .which = which}}); } +} + +void window_wants_mouse_movements(struct window *w) { + w->wants_mouse_movements = true; } \ No newline at end of file diff --git a/src/kernel/window.h b/src/kernel/window.h index a1f9716..a1d6be3 100644 --- a/src/kernel/window.h +++ b/src/kernel/window.h @@ -36,4 +36,6 @@ void show_shutdown(); void move_mouse_by(int16_t y, int16_t x); void mouse_button(enum mouse_button which, bool up); +void window_wants_mouse_movements(struct window *w); + #endif diff --git a/src/shared/include/winact.h b/src/shared/include/winact.h index 9486efc..13e07f5 100644 --- a/src/shared/include/winact.h +++ b/src/shared/include/winact.h @@ -7,7 +7,7 @@ struct mouse_packet { uint16_t y; uint16_t x; enum mouse_button {LEFT, RIGHT, MIDDLE} which; -}; +} __attribute__ ((__packed__)); struct window_action { enum { @@ -17,11 +17,16 @@ struct window_action { FOCUS_ENTER, FOCUS_LEAVE, MOUSE_DOWN, - MOUSE_UP + MOUSE_UP, + MOUSE_MOVE } action_type; union { struct key_packet as_key; struct mouse_packet as_mouse; + struct { + uint32_t y; + uint32_t x; + } moved_to; }; } __attribute__ ((__packed__)); diff --git a/src/user/include/cxx/raleigh/w/button.h b/src/user/include/cxx/raleigh/w/button.h index 71ccae2..0e40f81 100644 --- a/src/user/include/cxx/raleigh/w/button.h +++ b/src/user/include/cxx/raleigh/w/button.h @@ -14,6 +14,7 @@ namespace raleigh { void handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) override; void notify_child_size_change(widget &child, coord old_size) override; void notify_has_opaque_parent(widget *parent) override; + void on_mouse_move(coord window_coords) override; private: widget &inner; void (*on_click)(button &); diff --git a/src/user/include/cxx/raleigh/w/colorpicker.h b/src/user/include/cxx/raleigh/w/colorpicker.h index c33288e..a282c9e 100644 --- a/src/user/include/cxx/raleigh/w/colorpicker.h +++ b/src/user/include/cxx/raleigh/w/colorpicker.h @@ -12,11 +12,14 @@ namespace raleigh { void paint(_pixel_t *pixbuf, uint32_t pitch) override; void handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) override; void notify_has_opaque_parent(widget *parent) override; + void on_mouse_move(coord window_coords) override; private: _pixel_t picked_color; uint8_t resolution; uint8_t inv_res; + + enum {NO, R, G, B} selected; }; } diff --git a/src/user/include/cxx/raleigh/w/padding.h b/src/user/include/cxx/raleigh/w/padding.h index 1bdb9ee..ab732f1 100644 --- a/src/user/include/cxx/raleigh/w/padding.h +++ b/src/user/include/cxx/raleigh/w/padding.h @@ -13,6 +13,7 @@ namespace raleigh { void handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) override; void notify_has_opaque_parent(widget *parent) override; void notify_child_size_change(widget &child, coord old_size) override; + void on_mouse_move(coord window_coords) override; private: widget &inner; uint32_t pad_by; diff --git a/src/user/include/cxx/raleigh/w/vbox.h b/src/user/include/cxx/raleigh/w/vbox.h index f715f95..39f89e9 100644 --- a/src/user/include/cxx/raleigh/w/vbox.h +++ b/src/user/include/cxx/raleigh/w/vbox.h @@ -15,6 +15,7 @@ namespace raleigh { void handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) override; void notify_has_opaque_parent(widget *parent) override; void notify_child_size_change(widget &from, coord old_size) override; + void on_mouse_move(coord window_coords) override; private: dllist widgets; }; diff --git a/src/user/include/cxx/raleigh/widget.h b/src/user/include/cxx/raleigh/widget.h index 1b2cf6f..d499ed4 100644 --- a/src/user/include/cxx/raleigh/widget.h +++ b/src/user/include/cxx/raleigh/widget.h @@ -36,6 +36,7 @@ namespace raleigh { virtual void handle_key(struct key_packet kp); virtual void on_focus(); virtual void on_unfocus(); + virtual void on_mouse_move(coord window_coords); //this next one is not to be called by child widgets //they should call window::notify_widget_size_change(widget &), which will call this if necessary virtual void notify_child_size_change(widget &child, coord old_size); diff --git a/src/user/include/pland/syscall.h b/src/user/include/pland/syscall.h index d7dfd77..1e040f4 100644 --- a/src/user/include/pland/syscall.h +++ b/src/user/include/pland/syscall.h @@ -57,7 +57,8 @@ enum _scn { _SCN_IS_TASK_RUNNING, _SCN_GET_TIMESTAMP, _SCN_FILE_WRITE, - _SCN_SET_FILE_SIZE + _SCN_SET_FILE_SIZE, + _SCN_WANTS_MOUSE_MOVES }; static inline uint32_t _sc0(enum _scn eax) { @@ -254,6 +255,10 @@ static inline void _set_file_size(_file_handle_t handle, uint32_t new_size) { _sc2(_SCN_SET_FILE_SIZE, handle, new_size); } +static inline void _wants_mouse_moves(_window_handle_t window) { + _sc1(_SCN_WANTS_MOUSE_MOVES, (uint32_t)window); +} + #ifdef __cplusplus } #endif diff --git a/src/user/raleigh/w/button.cpp b/src/user/raleigh/w/button.cpp index 2abf9a9..224b930 100644 --- a/src/user/raleigh/w/button.cpp +++ b/src/user/raleigh/w/button.cpp @@ -55,4 +55,12 @@ namespace raleigh { } void button::notify_has_opaque_parent(widget *parent) {} + + void button::on_mouse_move(coord window_coords) { + 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.on_mouse_move(window_coords); + } } \ No newline at end of file diff --git a/src/user/raleigh/w/colorpicker.cpp b/src/user/raleigh/w/colorpicker.cpp index faa720e..4ccd0ce 100644 --- a/src/user/raleigh/w/colorpicker.cpp +++ b/src/user/raleigh/w/colorpicker.cpp @@ -2,7 +2,8 @@ namespace raleigh { colorpicker::colorpicker(_pixel_t default_color, uint8_t resolution) - : picked_color(default_color), resolution(resolution), inv_res(256 / resolution) { + : picked_color(default_color), resolution(resolution), + inv_res(256 / resolution), selected(NO) { size = coord(inv_res * 2, inv_res * 2); closest_opaque = this; } @@ -32,19 +33,26 @@ namespace raleigh { } void colorpicker::handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) { - if (up || (click_type != mouse_packet::LEFT)) + if (click_type != mouse_packet::LEFT) return; + if (up) { + selected = NO; + return; + } window_coords.x -= window_offset.x; window_coords.y -= window_offset.y; if ((window_coords.x < inv_res) && (window_coords.y < inv_res)) { + selected = R; picked_color.g = window_coords.x * resolution; picked_color.b = window_coords.y * resolution; } else if (window_coords.y < inv_res) { + selected = G; picked_color.b = (window_coords.x - inv_res) * resolution; picked_color.r = window_coords.y * resolution; } else if (window_coords.x < inv_res) { + selected = B; picked_color.r = window_coords.x * resolution; picked_color.g = (window_coords.y - inv_res) * resolution; } @@ -52,4 +60,38 @@ namespace raleigh { } void colorpicker::notify_has_opaque_parent(widget *parent) {} + + void colorpicker::on_mouse_move(coord window_coords) { + uint32_t x = window_coords.x - window_offset.x; + uint32_t y = window_coords.y - window_offset.y; + switch (selected) { + case NO: + return; + case R: + if (x >= inv_res) + x = inv_res - 1; + if (y >= inv_res) + y = inv_res - 1; + picked_color.g = x * resolution; + picked_color.b = y * resolution; + break; + case G: + if (x < inv_res) + x = inv_res; + if (y >= inv_res) + y = inv_res - 1; + picked_color.b = x * resolution; + picked_color.r = y * resolution; + break; + case B: + if (x >= inv_res) + x = inv_res - 1; + if (y < inv_res) + y = inv_res; + picked_color.r = x * resolution; + picked_color.g = y * resolution; + break; + } + w->notify_needs_paint(*this); + } } \ No newline at end of file diff --git a/src/user/raleigh/w/padding.cpp b/src/user/raleigh/w/padding.cpp index c1f7b85..782a8a9 100644 --- a/src/user/raleigh/w/padding.cpp +++ b/src/user/raleigh/w/padding.cpp @@ -34,4 +34,12 @@ namespace raleigh { void padding::notify_child_size_change(widget &child, coord old_size) { set_size(coord(inner.size.x + pad_by * 2, inner.size.y + pad_by * 2)); } + + void padding::on_mouse_move(coord window_coords) { + 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.on_mouse_move(window_coords); + } } \ No newline at end of file diff --git a/src/user/raleigh/w/vbox.cpp b/src/user/raleigh/w/vbox.cpp index 263da2a..77ce592 100644 --- a/src/user/raleigh/w/vbox.cpp +++ b/src/user/raleigh/w/vbox.cpp @@ -63,4 +63,15 @@ namespace raleigh { notify_window_change(); } } + + void vbox::on_mouse_move(coord window_coords) { + for (dllist::node *n = widgets.first; n; n = n->next) + if ((window_coords.x >= n->d.window_offset.x) && + (window_coords.y >= n->d.window_offset.y) && + (window_coords.x < n->d.window_offset.x + n->d.size.x) && + (window_coords.y < n->d.window_offset.y + n->d.size.y)) { + n->d.on_mouse_move(window_coords); + return; + } + } } \ No newline at end of file diff --git a/src/user/raleigh/widget.cpp b/src/user/raleigh/widget.cpp index 719cc06..0a47c3b 100644 --- a/src/user/raleigh/widget.cpp +++ b/src/user/raleigh/widget.cpp @@ -11,6 +11,7 @@ namespace raleigh { void widget::handle_key(struct key_packet kp) {} void widget::on_focus() {} void widget::on_unfocus() {} + void widget::on_mouse_move(coord window_coords) {} void widget::notify_child_size_change(widget &child, coord old_size) {} void widget::set_size(coord new_size) { diff --git a/src/user/raleigh/window.cpp b/src/user/raleigh/window.cpp index 5d1a3de..cb9f363 100644 --- a/src/user/raleigh/window.cpp +++ b/src/user/raleigh/window.cpp @@ -57,6 +57,8 @@ namespace raleigh { focussed->on_focus(); else if (wa.action_type == wa.FOCUS_LEAVE) focussed->on_unfocus(); + else if (wa.action_type == wa.MOUSE_MOVE) + root.on_mouse_move(coord(wa.moved_to.x, wa.moved_to.y)); } } @@ -78,6 +80,7 @@ namespace raleigh { if (handle) return; handle = _new_window(size.x, size.y, pixbuf); + _wants_mouse_moves(handle); if (!handle) show_error_and_quitf("Failed to get window handle for requested window."); open_windows.add_front(*this); -- cgit v1.2.3