window moving and focusing
This commit is contained in:
parent
c34b9191f2
commit
6cf7cd267b
7 changed files with 208 additions and 21 deletions
|
@ -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<euler::syscall::mouse_packet>(result)) {
|
||||
auto packet = std::get<euler::syscall::mouse_packet>(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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<window *>::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);
|
||||
|
|
|
@ -17,9 +17,6 @@ class renderer {
|
|||
int cursor_x;
|
||||
int cursor_y;
|
||||
|
||||
//bottom to top
|
||||
std::list<window *> 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<window *> windows;
|
||||
|
||||
renderer(
|
||||
daguerre::image<daguerre::hilbert_color> &&framebuffer,
|
||||
daguerre::image<daguerre::hilbert_color> &&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<window *>::iterator w);
|
||||
|
||||
void add_window(window *w);
|
||||
void remove_window(window *w);
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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<daguerre::hilbert_color>(width + 4, height + 18);
|
||||
contents = daguerre::image<daguerre::hilbert_color>(
|
||||
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;
|
||||
|
||||
|
|
|
@ -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<daguerre::hilbert_color> contents_with_decorations;
|
||||
daguerre::image<daguerre::hilbert_color> 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);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
namespace std {
|
||||
|
||||
template <class T, class Allocator = std::allocator<T>>
|
||||
template <class T>
|
||||
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< T>;
|
||||
using const_iterator = generic_iterator<const T>;
|
||||
|
||||
using reverse_iterator = std::reverse_iterator< iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_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
|
||||
};
|
||||
}
|
||||
|
||||
const_iterator begin() const noexcept { return iterator { .the_node = first_node }; }
|
||||
const_iterator end() const noexcept { return iterator { .the_node = 0 }; }
|
||||
iterator end() noexcept {
|
||||
return iterator {
|
||||
.the_node = 0,
|
||||
.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 begin() const noexcept {
|
||||
return iterator {
|
||||
.the_node = first_node,
|
||||
.last_node = last_node
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
Reference in a new issue