From 6cf7cd267b50fa68d7531655911620f17dde4a63 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Mon, 29 Jul 2024 23:03:57 -0400 Subject: window moving and focusing --- applications/goldman/source/input.cpp | 36 +++++++++ applications/goldman/source/renderer.cpp | 29 +++++-- applications/goldman/source/renderer.hpp | 20 ++++- applications/goldman/source/socket.cpp | 5 +- applications/goldman/source/window.cpp | 5 ++ applications/goldman/source/window.hpp | 6 +- euler/include/std/list.hpp | 128 ++++++++++++++++++++++++++++--- 7 files changed, 208 insertions(+), 21 deletions(-) diff --git a/applications/goldman/source/input.cpp b/applications/goldman/source/input.cpp index 0cd6922..c71068c 100644 --- a/applications/goldman/source/input.cpp +++ b/applications/goldman/source/input.cpp @@ -5,15 +5,51 @@ euler::syscall::set_thread_name("input thread"); + window *window_being_moved = 0; + bool was_mouse_down_before = false; + while (true) { auto result = euler::syscall::get_input_packet(); if (std::holds_alternative(result)) { auto packet = std::get(result); + r->lock(); + + int old_x, old_y; + r->get_cursor(old_x, old_y); r->bump_cursor(packet.x_changed, packet.y_changed); + int new_x, new_y; + r->get_cursor(new_x, new_y); + + if (window_being_moved != 0) { + if (r->windows.size() == 0 || r->windows.back() != window_being_moved) + window_being_moved = 0; + else { + r->windows.back()->x += new_x - old_x; + r->windows.back()->y += new_y - old_y; + if (!packet.left_button_down) + window_being_moved = 0; + } + } + + else if (packet.left_button_down && !was_mouse_down_before) + for (auto it = r->windows.rbegin(); it != r->windows.rend(); ++it) + if (new_x >= (*it)->x && new_y >= (*it)->y && + new_x < (*it)->x + (*it)->contents_with_decorations. width && + new_y < (*it)->y + (*it)->contents_with_decorations.height) { + r->move_window_to_front(--it.base()); + //it is now invalidated, but our window is now r->windows.back() + if (new_y < r->windows.back()->y + window::title_height) + window_being_moved = r->windows.back(); + break; + } + r->unlock(); r->dispatch_render(); + + was_mouse_down_before = packet.left_button_down; + } } diff --git a/applications/goldman/source/renderer.cpp b/applications/goldman/source/renderer.cpp index 7a5e6b5..4d9beda 100644 --- a/applications/goldman/source/renderer.cpp +++ b/applications/goldman/source/renderer.cpp @@ -49,14 +49,15 @@ void renderer::do_render() { double_buffer.copy_from(background, 0, 0); - for (auto it = windows.begin(); it != windows.end(); ++it) - + for (auto it = windows.begin(); it != windows.end(); ++it) { + int tx = (*it)->x, ty = (*it)->y, fx = 0, fy = 0; + int w = (*it)->contents_with_decorations.width; + int h = (*it)->contents_with_decorations.height; + daguerre::make_safe(tx, fx, w, 0, double_buffer.width); + daguerre::make_safe(ty, fy, h, 0, double_buffer.height); double_buffer.copy_from( - (*it)->contents_with_decorations, (*it)->x, (*it)->y, 0, 0, - std::min((*it)->contents_with_decorations.width, - double_buffer.width - (*it)->x), - std::min((*it)->contents_with_decorations.height, - double_buffer.height - (*it)->y)); + (*it)->contents_with_decorations, tx, ty, fx, fy, w, h); + } double_buffer.convert_from( cursor_background, cursor, cursor_x, cursor_y, 0, 0, @@ -79,6 +80,11 @@ void renderer::do_render() { } } +void renderer::get_cursor(int &x_out, int &y_out) { + x_out = cursor_x; + y_out = cursor_y; +} + void renderer::bump_cursor(int x_offset, int y_offset) { cursor_x += x_offset; @@ -95,6 +101,15 @@ void renderer::bump_cursor(int x_offset, int y_offset) { } +void renderer::move_window_to_front(std::list::iterator w) { + window *wp = *w; + windows.erase(w); + if (windows.size() != 0) + windows.back()->draw_decorations(false); + windows.push_back(wp); + wp->draw_decorations(true); +} + void renderer::add_window(window *w) { if (windows.size() != 0) windows.back()->draw_decorations(false); diff --git a/applications/goldman/source/renderer.hpp b/applications/goldman/source/renderer.hpp index 91afe88..c2e82b2 100644 --- a/applications/goldman/source/renderer.hpp +++ b/applications/goldman/source/renderer.hpp @@ -17,9 +17,6 @@ class renderer { int cursor_x; int cursor_y; - //bottom to top - std::list windows; - std::mutex mut; euler::syscall::stream_handle @@ -28,6 +25,12 @@ class renderer { void do_render(); public: + //all of the shown windows, sorted from furthest back to furthest front. + //while the renderer is not locked, the contents of this can change and + //iterators can be invalided. this should not be reordered, added to, or + //have elements removed from outside the renderer. + std::list windows; + renderer( daguerre::image &&framebuffer, daguerre::image &&background, @@ -53,8 +56,19 @@ public: euler::syscall::write_to_stream(dispatcher_handle_1, 1, &byte); } + //gets the current position of the cursor. this should + //only be called while the renderer is locked. + void get_cursor(int &x_out, int &y_out); + + //this adds x_offset and y_offset to the current cursor position, and then + //clamps the cursor position to have its top-left pixel inside the frame. + //this should only be called while the renderer is locked. void bump_cursor(int x_offset, int y_offset); + //moves the pointed to window to the front of the window stack. + //this should only be called while the renderer is locked. + void move_window_to_front(std::list::iterator w); + void add_window(window *w); void remove_window(window *w); diff --git a/applications/goldman/source/socket.cpp b/applications/goldman/source/socket.cpp index aa9b85e..79849df 100644 --- a/applications/goldman/source/socket.cpp +++ b/applications/goldman/source/socket.cpp @@ -129,7 +129,10 @@ struct socket_state { euler::syscall::set_thread_name("socket thread"); - window *w = new window(); + int x, y; + r->get_cursor(x, y); + + window *w = new window(x, y); socket_state *state = new socket_state { .socket = socket, .w = w }; diff --git a/applications/goldman/source/window.cpp b/applications/goldman/source/window.cpp index fe5212a..3f122ca 100644 --- a/applications/goldman/source/window.cpp +++ b/applications/goldman/source/window.cpp @@ -11,12 +11,16 @@ daguerre::hilbert_color border_color_not_top; daguerre::hilbert_color title_color; void window::set_size(int width, int height) { + int center_x = x + contents_with_decorations. width / 2; + int center_y = y + contents_with_decorations.height / 2; contents_with_decorations = daguerre::image(width + 4, height + 18); contents = daguerre::image( width, height, &contents_with_decorations.at(2, 16), contents_with_decorations.buffer_pitch, false); + x = center_x - contents_with_decorations. width / 2; + y = center_y - contents_with_decorations.height / 2; } void title_converter( @@ -40,6 +44,7 @@ void window::draw_decorations(bool top) { static_assert( decorations_extra_width == 4); static_assert(decorations_extra_height == 18); + static_assert( title_height == 16); auto border_color = top ? border_color_top : border_color_not_top; diff --git a/applications/goldman/source/window.hpp b/applications/goldman/source/window.hpp index 5c2d7a0..380e25b 100644 --- a/applications/goldman/source/window.hpp +++ b/applications/goldman/source/window.hpp @@ -6,6 +6,7 @@ struct window { static constexpr int decorations_extra_width = 4; static constexpr int decorations_extra_height = 18; + static constexpr int title_height = 16; daguerre::image contents_with_decorations; daguerre::image contents; @@ -20,7 +21,10 @@ struct window { void set_size(int width, int height); void draw_decorations(bool top); - inline window() : x(0), y(0), is_shown(false) { + inline window(int center_x, int center_y) + : x(center_x - decorations_extra_width / 2), + y(center_y - decorations_extra_height / 2), + is_shown(false) { set_size(0, 0); draw_decorations(false); } diff --git a/euler/include/std/list.hpp b/euler/include/std/list.hpp index 030eccc..cd777b2 100644 --- a/euler/include/std/list.hpp +++ b/euler/include/std/list.hpp @@ -1,10 +1,11 @@ #pragma once +#include #include namespace std { - template > + template class list { public: @@ -18,6 +19,13 @@ namespace std { struct generic_iterator { node *the_node; + node *last_node; + + using iterator_category = std::bidirectional_iterator_tag; + using reference = V &; + using pointer = V *; + using value_type = V; + using difference_type = size_t; bool operator ==(const generic_iterator &other) const { return the_node == other.the_node; @@ -40,11 +48,29 @@ namespace std { return *this; } + generic_iterator &operator --() { + if (the_node == 0) + the_node = last_node; + else + the_node = the_node->prev; + return *this; + } + + generic_iterator operator -(size_t count) const { + generic_iterator it = { .the_node = the_node }; + for (size_t i = 0; i < count; ++i) + --it; + return it; + } + }; - using iterator = generic_iterator; + using iterator = generic_iterator< T>; using const_iterator = generic_iterator; + using reverse_iterator = std::reverse_iterator< iterator>; + using const_reverse_iterator = std::reverse_iterator; + private: node *first_node; node *last_node; @@ -79,17 +105,101 @@ namespace std { if (n->next) n->next->prev = n->prev; else last_node = n->prev; delete n; - return iterator { .the_node = r }; + return iterator { + .the_node = r, + .last_node = last_node + }; } - iterator begin() noexcept { return iterator { .the_node = first_node }; } - iterator end() noexcept { return iterator { .the_node = 0 }; } + iterator begin() noexcept { + return iterator { + .the_node = first_node, + .last_node = last_node + }; + } + + iterator end() noexcept { + return iterator { + .the_node = 0, + .last_node = last_node + }; + } - const_iterator begin() const noexcept { return iterator { .the_node = first_node }; } - const_iterator end() const noexcept { return iterator { .the_node = 0 }; } + const_iterator begin() const noexcept { + return iterator { + .the_node = first_node, + .last_node = last_node + }; + } - const_iterator cbegin() const noexcept { return iterator { .the_node = first_node }; } - const_iterator cend() const noexcept { return iterator { .the_node = 0 }; } + const_iterator end() const noexcept { + return iterator { + .the_node = 0, + .last_node = last_node + }; + } + + const_iterator cbegin() const noexcept { + return iterator { + .the_node = first_node, + .last_node = last_node + }; + } + + const_iterator cend() const noexcept { + return iterator { + .the_node = 0, + .last_node = last_node + }; + } + + reverse_iterator rbegin() noexcept { + return reverse_iterator( + iterator { + .the_node = 0, + .last_node = last_node + }); + } + + reverse_iterator rend() noexcept { + return reverse_iterator( + iterator { + .the_node = first_node, + .last_node = last_node + }); + } + + const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator( + iterator { + .the_node = 0, + .last_node = last_node + }); + } + + const_reverse_iterator rend() const noexcept { + return const_reverse_iterator( + iterator { + .the_node = first_node, + .last_node = last_node + }); + } + + const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator( + iterator { + .the_node = 0, + .last_node = last_node + }); + } + + const_reverse_iterator crend() const noexcept { + return const_reverse_iterator( + iterator { + .the_node = first_node, + .last_node = last_node + }); + } size_t remove(const T &value) { size_t removed = 0; -- cgit v1.2.3