diff options
24 files changed, 506 insertions, 231 deletions
diff --git a/applications/goldman/source/socket.cpp b/applications/goldman/source/socket.cpp index b175fe9..9ebd644 100644 --- a/applications/goldman/source/socket.cpp +++ b/applications/goldman/source/socket.cpp @@ -8,114 +8,95 @@ struct socket_state { euler::syscall::stream_handle socket; - std::vector<window *> windows; - daguerre::hilbert_color window_bg = euler::syscall::encode_color(0, 0, 0); + window *w; - bool try_open_window() { + bool try_show_window() { - struct [[gnu::packed]] { - uint32_t width; - uint32_t height; - } body; - - if (euler::syscall::read_from_stream(socket, sizeof(body), &body) != - euler::syscall::stream_result::success) + if (w->is_shown) return false; - window *w = new window(body.width, body.height); - w->contents.fill(window_bg); + r->lock(); + r->add_window(w); + r->unlock(); + r->dispatch_render(); + return true; - uint16_t wid = 0; + } - while (wid < windows.size()) - if (windows[wid] != 0) - ++wid; - else - break; + bool try_hide_window() { - if (wid == windows.size()) - windows.push_back(w); - else - windows[wid] = w; + if (!w->is_shown) + return false; r->lock(); - r->add_window(w); + r->remove_window(w); r->unlock(); - - struct [[gnu::packed]] { - uint8_t type; - uint16_t the_window; - } response { - .type = 0x00, - .the_window = wid - }; - - return - euler::syscall::write_to_stream(socket, sizeof(response), &response) == - euler::syscall::stream_result::success; + r->dispatch_render(); + return true; } - bool try_update_window_region() { + bool try_set_window_dimensions() { - struct [[gnu::packed]] { - uint16_t window; - uint32_t start_x; - uint32_t start_y; - uint32_t width; - uint32_t height; - } body_head; - - if (euler::syscall::read_from_stream(socket, sizeof(body_head), &body_head) != + struct [[gnu::packed]] { uint32_t width; uint32_t height; } packet; + if (euler::syscall::read_from_stream(socket, sizeof(packet), &packet) != euler::syscall::stream_result::success) return false; - std::vector<daguerre::hilbert_color> data(body_head.width * body_head.height); - - if (euler::syscall::read_from_stream(socket, data.size() * 4, data.data()) != - euler::syscall::stream_result::success) + if (packet.width > __INT_MAX__ || packet.height > __INT_MAX__) return false; - daguerre::image<daguerre::hilbert_color> - data_as_image(body_head.width, body_head.height, data.data(), body_head.width, false); - - if (body_head.window >= windows.size() || !windows[body_head.window]) - return false; + r->lock(); + w->contents = daguerre::image<daguerre::hilbert_color>( + packet.width, packet.height); + r->unlock(); + return true; - window *w = windows[body_head.window]; + } - r->lock(); + bool try_set_window_title() { - if ((int)body_head.start_x + data_as_image.width > w->contents.width || - (int)body_head.start_y + data_as_image.height > w->contents.height) { - r->unlock(); + uint32_t length; + if (euler::syscall::read_from_stream(socket, 4, &length) != + euler::syscall::stream_result::success) return false; - } - w->contents.copy_from(data_as_image, body_head.start_x, body_head.start_y); + std::string title; + title.resize(length); + if (euler::syscall::read_from_stream(socket, length, title.data()) != + euler::syscall::stream_result::success) + return false; + r->lock(); + w->title = std::move(title); r->unlock(); r->dispatch_render(); return true; } - bool try_close_window() { - - uint16_t wid; + bool try_update_window_region() { - if (euler::syscall::read_from_stream(socket, 2, &wid) != + struct [[gnu::packed]] { + uint32_t start_x; uint32_t start_y; uint32_t width; uint32_t height; + } packet; + if (euler::syscall::read_from_stream(socket, sizeof(packet), &packet) != euler::syscall::stream_result::success) return false; - if (wid >= windows.size() || !windows[wid]) + static_assert(__INT_MAX__ <= __UINT64_MAX__); + if ((uint64_t)packet.start_x + packet. width > (uint64_t)w->contents. width || + (uint64_t)packet.start_y + packet.height > (uint64_t)w->contents.height) return false; - r->lock(); - - r->remove_window(windows[wid]); - windows[wid] = 0; + daguerre::image<daguerre::hilbert_color> content(packet.width, packet.height); + if (euler::syscall::read_from_stream( + socket, packet.width * packet.height * 4, content.buffer) != + euler::syscall::stream_result::success) + return false; + r->lock(); + w->contents.copy_from(content, packet.start_x, packet.start_y); r->unlock(); r->dispatch_render(); return true; @@ -130,9 +111,11 @@ struct socket_state { return false; switch (type) { - case 0x00: return try_open_window(); - case 0x01: return try_update_window_region(); - case 0x02: return try_close_window(); + case 0x00: return try_show_window(); + case 0x01: return try_hide_window(); + case 0x02: return try_set_window_dimensions(); + case 0x03: return try_set_window_title(); + case 0x04: return try_update_window_region(); default: return false; } @@ -144,18 +127,20 @@ struct socket_state { euler::syscall::set_thread_name("socket thread"); + window *w = new window(); socket_state *state = new socket_state { - .socket = socket, .windows = {} }; + .socket = socket, .w = w }; + while (state->try_process_request()) ; - r->lock(); - for (unsigned i = 0; i < state->windows.size(); ++i) { - r->remove_window(state->windows[i]); - delete state->windows[i]; + if (w->is_shown) { + r->lock(); + r->remove_window(w); + r->unlock(); } - r->unlock(); delete state; + delete w; euler::syscall::close_stream(socket); euler::syscall::end_this_thread(0); diff --git a/applications/goldman/source/window.hpp b/applications/goldman/source/window.hpp index 008af2f..4d5b0e1 100644 --- a/applications/goldman/source/window.hpp +++ b/applications/goldman/source/window.hpp @@ -9,6 +9,10 @@ struct window { int x; int y; - window(int width, int height) : contents(width, height), x(0), y(0) {} + bool is_shown; + + std::string title; + + window() : x(0), y(0), is_shown(false) {} }; diff --git a/applications/hello/makefile b/applications/hello/makefile index 5e12644..ea0b09a 100644 --- a/applications/hello/makefile +++ b/applications/hello/makefile @@ -6,7 +6,7 @@ build/%.cpp.o: source/%.cpp $(HILBERT_CC) -c $^ -o $@ build/hello.elf: $(SOURCES:%=build/%.o) - $(HILBERT_CC) $^ -ldaguerre -o $@ + $(HILBERT_CC) $^ -ldaguerre -lpake -o $@ clean: rm -rf build diff --git a/applications/hello/source/main.cpp b/applications/hello/source/main.cpp index 3f132c6..1f45407 100644 --- a/applications/hello/source/main.cpp +++ b/applications/hello/source/main.cpp @@ -1,37 +1,30 @@ -#include <goldman/protocol.hpp> +#include <pake/widgets/fixed-text.hpp> #include <daguerre/psf.hpp> +#include <pake/window.hpp> -template <class color_t> -void overlay(color_t &to, const bool &from, const color_t ¶m) { - if (from) - to = param; -} +daguerre::fixed_font<bool> *font; int main(int, char **) { - auto bg = euler::syscall::encode_color(0xaa, 0xaa, 0xaa); - auto fg = euler::syscall::encode_color(0x00, 0x00, 0x00); - - daguerre::image<daguerre::hilbert_color> image(300, 200); - image.fill(bg); + font = new daguerre::fixed_font<bool>( + daguerre::try_load_psf("/assets/terminus-bold-18x10.psf").value()); - auto font = daguerre::try_load_psf("/assets/terminus-bold-18x10.psf"); - image.render_text(*font, fg, 10, 10, "Hello, world!", &overlay); + pake::widgets::fixed_text *text = + new pake::widgets::fixed_text("Hello, world!", font, + euler::syscall::encode_color(0xaa, 0xaa, 0xaa), + euler::syscall::encode_color(0x00, 0x00, 0x00)); - euler::syscall::stream_handle s; - euler::syscall::connect_to_socket("hilbert.compositor", s); + pake::window w(300, 200, "Hello"); + w.set_root(std::unique_ptr<pake::widget>(text)); + w.render_and_send_to_compositor(); + w.show(); - goldman::protocol::send_open_window(s, 300, 200); + //TODO: call event loop + euler::syscall::stream_handle h1, h2; + euler::syscall::create_private_socket(h1, h2); uint8_t byte; - euler::syscall::read_from_stream(s, 1, &byte); - - auto w = goldman::protocol::get_window_opened_body(s); - - goldman::protocol::send_update_window_region( - s, w, 0, 0, 300, 200, image.buffer, image.buffer_pitch); - - euler::syscall::read_from_stream(s, 1, &byte); - __builtin_unreachable(); + while (1) + euler::syscall::read_from_stream(h1, 1, &byte); } diff --git a/documentation/compositor.txt b/documentation/compositor.txt index 38bd482..8346db7 100644 --- a/documentation/compositor.txt +++ b/documentation/compositor.txt @@ -1,13 +1,9 @@ compositors listen on the socket id "hilbert.compositor". -when a window is opened by an application, that window can only be referred to -on that socket. the opaque value given in the "window opened" message refers to -that window in future messages on that socket. it is guaranteed to be distinct -for different windows on the same socket, and in no way guaranteed to be -distinct for different windows on different sockets. the window is bound -just to the socket, not to the application. if the socket where a window -was created is gifted to a new process, the new process has complete control -over the window, and the compositor does not need to be informed. +there is a one-to-one correspondence between sockets to the compositor and +windows. when a socket is opened, a window is created, and when a socket is +closed, its window is destroyed. this socket can be gifted to another process, +and the other process then becomes the window's owner. data types: @@ -18,32 +14,28 @@ data types: color rectangle: multiple hilbert colors, top to bottom by row, left to right within row - window: - opaque word (given in "window opened" message after "open window" message) - messages from applications to compositor: - open window: + show window: byte: 0x00 - dword: window width - dword: window height - update window region: + hide window: byte: 0x01 - window: the window - dword: start x - dword: start y - dword: width - dword: height - color rectangle: the data - close window: + set window dimensions: byte: 0x02 - window: the window + dword: width + dword: height -messages from compositor to application: + set window title: + byte: 0x03 + dword: length in bytes + bytes: title - window opened: - byte: 0x00 - window: the window - these come in the order the open window requests were received + update window region: + byte: 0x04 + dword: start x + dword: start y + dword: width + dword: height + color rectangle: new content diff --git a/euler/include/cassert b/euler/include/cassert new file mode 100644 index 0000000..415790d --- /dev/null +++ b/euler/include/cassert @@ -0,0 +1,12 @@ +#pragma once + +namespace euler { + + [[noreturn]] inline void assert_failed() { + //TODO: log error and abort + while (1) ; + } + +} + +#define assert(cond) ((cond) ? (void)0 : ::euler::assert_failed()); diff --git a/euler/include/condition_variable b/euler/include/condition_variable new file mode 100644 index 0000000..ec327eb --- /dev/null +++ b/euler/include/condition_variable @@ -0,0 +1,3 @@ +#pragma once + +#include <std/condition-variable.hpp> diff --git a/euler/include/mutex b/euler/include/mutex index 7a03381..7eefb3e 100644 --- a/euler/include/mutex +++ b/euler/include/mutex @@ -1,4 +1,4 @@ #pragma once -#include <std/unique_lock.hpp> +#include <std/unique-lock.hpp> #include <std/mutex.hpp> diff --git a/euler/include/std/condition-variable.hpp b/euler/include/std/condition-variable.hpp new file mode 100644 index 0000000..0568373 --- /dev/null +++ b/euler/include/std/condition-variable.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include <mutex> + +namespace std { + + class condition_variable { + + //TODO + + }; + +} diff --git a/euler/include/std/list.hpp b/euler/include/std/list.hpp index 77eaaec..c0d6e21 100644 --- a/euler/include/std/list.hpp +++ b/euler/include/std/list.hpp @@ -19,11 +19,11 @@ namespace std { node *the_node; - bool operator ==(const generic_iterator &other) { + bool operator ==(const generic_iterator &other) const { return the_node == other.the_node; } - bool operator !=(const generic_iterator &other) { + bool operator !=(const generic_iterator &other) const { return the_node != other.the_node; } @@ -82,13 +82,14 @@ namespace std { return iterator { .the_node = r }; } - iterator begin() const noexcept { - return iterator { .the_node = first_node }; - } + iterator begin() noexcept { return iterator { .the_node = first_node }; } + iterator end() noexcept { return iterator { .the_node = 0 }; } - iterator end() const noexcept { - return iterator { .the_node = 0 }; - } + const_iterator begin() const noexcept { return iterator { .the_node = first_node }; } + const_iterator end() const noexcept { return iterator { .the_node = 0 }; } + + const_iterator cbegin() const noexcept { return iterator { .the_node = first_node }; } + const_iterator cend() const noexcept { return iterator { .the_node = 0 }; } size_t remove(const T &value) { size_t removed = 0; @@ -140,6 +141,7 @@ namespace std { clear(); for (node *n = other.first_node; n; n = n->next) push_back(n->value); + return *this; } list &operator =(list &&other) { @@ -150,6 +152,7 @@ namespace std { other.first_node = 0; other.last_node = 0; other.count = 0; + return *this; } }; diff --git a/euler/include/std/unique_lock.hpp b/euler/include/std/unique-lock.hpp index 14b3645..14b3645 100644 --- a/euler/include/std/unique_lock.hpp +++ b/euler/include/std/unique-lock.hpp diff --git a/euler/include/std/vector.hpp b/euler/include/std/vector.hpp index 1c35d9d..8cd02b4 100644 --- a/euler/include/std/vector.hpp +++ b/euler/include/std/vector.hpp @@ -131,6 +131,12 @@ namespace std { } + void clear() { + for (size_type i = 0; i < _size; ++i) + std::destroy_at(_data + i); + _size = 0; + } + constexpr size_type size() const noexcept { return _size; } @@ -188,6 +194,18 @@ namespace std { ++_size; } + using iterator = T *; + using const_iterator = const T *; + + iterator begin() noexcept { return _data; } + iterator end() noexcept { return _data + _size; } + + const_iterator begin() const noexcept { return _data; } + const_iterator end() const noexcept { return _data + _size; } + + const_iterator cbegin() const noexcept { return _data; } + const_iterator cend() const noexcept { return _data + _size; } + }; } diff --git a/libraries/daguerre/include/daguerre/image.hpp b/libraries/daguerre/include/daguerre/image.hpp index 4c44dd0..a55f43b 100644 --- a/libraries/daguerre/include/daguerre/image.hpp +++ b/libraries/daguerre/include/daguerre/image.hpp @@ -55,6 +55,8 @@ namespace daguerre { ~image(); void fill(const color_t &color); + void fill( + const color_t &color, int start_x, int start_y, int width, int height); //does not check bounds color_t &at(int x, int y); diff --git a/libraries/daguerre/include/daguerre/impl/image.hpp b/libraries/daguerre/include/daguerre/impl/image.hpp index 9160951..6cf2ca9 100644 --- a/libraries/daguerre/include/daguerre/impl/image.hpp +++ b/libraries/daguerre/include/daguerre/impl/image.hpp @@ -104,6 +104,14 @@ namespace daguerre { } template <class color_t> + void image<color_t>::fill( + const color_t &color, int start_x, int start_y, int width, int height) { + for (int y = start_y; y < start_y + height; ++y) + for (int x = 0; x < start_x + width; ++x) + buffer[y * buffer_pitch + x] = color; + } + + template <class color_t> color_t &image<color_t>::at(int x, int y) { return buffer[y * buffer_pitch + x]; } diff --git a/libraries/goldman/include/goldman/protocol.hpp b/libraries/goldman/include/goldman/protocol.hpp deleted file mode 100644 index b7f4d51..0000000 --- a/libraries/goldman/include/goldman/protocol.hpp +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once - -#include <euler/syscall.hpp> -#include <memory> - -//TODO: handle stream errors, make thread safe - -namespace goldman::protocol { - - typedef euler::syscall::encoded_color color; - typedef uint16_t window; - - static inline void send_open_window( - euler::syscall::stream_handle socket, uint32_t width, uint32_t height) { - - struct [[gnu::packed]] { - uint8_t type; - uint32_t width; - uint32_t height; - } packet { - .type = 0x00, - .width = width, - .height = height - }; - - euler::syscall::write_to_stream(socket, sizeof(packet), &packet); - - } - - void send_update_window_region( - euler::syscall::stream_handle socket, window the_window, - uint32_t start_x, uint32_t start_y, uint32_t width, - uint32_t height, const color *the_data, size_t data_pitch) { - - struct [[gnu::packed]] { - uint8_t type; - window the_window; - uint32_t start_x; - uint32_t start_y; - uint32_t width; - uint32_t height; - } packet_head { - .type = 0x01, - .the_window = the_window, - .start_x = start_x, - .start_y = start_y, - .width = width, - .height = height - }; - - euler::syscall::write_to_stream(socket, sizeof(packet_head), &packet_head); - for (uint32_t y = 0; y < height; ++y) - euler::syscall::write_to_stream( - socket, width * sizeof(color), the_data + data_pitch * y); - - } - - void send_close_window( - euler::syscall::stream_handle socket, window the_window) { - - struct [[gnu::packed]] { - uint8_t type; - window the_window; - } packet { - .type = 0x02, - .the_window = the_window - }; - - euler::syscall::write_to_stream(socket, sizeof(packet), &packet); - - } - - enum class response_id : uint8_t { - window_opened - }; - - window get_window_opened_body(euler::syscall::stream_handle socket) { - - window w; - euler::syscall::read_from_stream(socket, sizeof(w), &w); - return w; - - } - -} diff --git a/libraries/pake/include/pake/dirtiable-image.hpp b/libraries/pake/include/pake/dirtiable-image.hpp new file mode 100644 index 0000000..af09ade --- /dev/null +++ b/libraries/pake/include/pake/dirtiable-image.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include <daguerre/image.hpp> +#include <list> + +namespace pake { + + struct region { + int start_x; + int start_y; + int width; + int height; + }; + + struct dirtiable_image { + + daguerre::image<daguerre::hilbert_color> image; + daguerre::image<bool> dirty; + + std::vector<region> get_dirty_regions(); + void clear_dirty(); + + dirtiable_image(int width, int height); + + }; + +} diff --git a/libraries/pake/include/pake/widget.hpp b/libraries/pake/include/pake/widget.hpp new file mode 100644 index 0000000..dad5651 --- /dev/null +++ b/libraries/pake/include/pake/widget.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include <pake/dirtiable-image.hpp> + +namespace pake { + + class widget { + + public: + virtual ~widget() {} + + virtual void render( + dirtiable_image &onto, int x_off, int y_off, bool force) = 0; + + virtual void notify_size(int width, int height) = 0; + + }; + +} diff --git a/libraries/pake/include/pake/widgets/fixed-text.hpp b/libraries/pake/include/pake/widgets/fixed-text.hpp new file mode 100644 index 0000000..c6dafab --- /dev/null +++ b/libraries/pake/include/pake/widgets/fixed-text.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include <daguerre/fixed-font.hpp> +#include <pake/widget.hpp> + +namespace pake::widgets { + + class fixed_text : public widget { + + const daguerre::fixed_font<bool> *font; + daguerre::hilbert_color bg, fg; + std::string text; + + int width, height; + + public: + //TODO: look up font in some kind of catalogue + fixed_text( + std::string &&text, + const daguerre::fixed_font<bool> *font, + daguerre::hilbert_color bg, + daguerre::hilbert_color fg); + + virtual void render( + dirtiable_image &onto, int x_off, int y_off, bool force) override; + + virtual void notify_size(int width, int height) override; + + }; + +} diff --git a/libraries/pake/include/pake/window.hpp b/libraries/pake/include/pake/window.hpp new file mode 100644 index 0000000..bb63b9d --- /dev/null +++ b/libraries/pake/include/pake/window.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include <pake/dirtiable-image.hpp> +#include <pake/widget.hpp> +#include <memory> + +namespace pake { + + class window { + + euler::syscall::stream_handle socket; + + int width; + int height; + + dirtiable_image contents; + std::unique_ptr<widget> root; + + public: + window(int width, int height, const std::string &title); + ~window(); + + void show(); + void hide(); + + void set_root(std::unique_ptr<widget> &&w); + + void render_and_send_to_compositor(); + + }; + +} diff --git a/libraries/pake/makefile b/libraries/pake/makefile new file mode 100644 index 0000000..28e7d37 --- /dev/null +++ b/libraries/pake/makefile @@ -0,0 +1,12 @@ +SOURCES = \ + widgets/fixed-text.cpp dirtiable-image.cpp window.cpp + +build/%.cpp.o: source/%.cpp + @mkdir -p $(@D) + $(HILBERT_CC) -c $^ -o $@ + +build/libpake.a: $(SOURCES:%=build/%.o) + $(HILBERT_AR) rcs $@ $^ + +clean: + rm -rf build diff --git a/libraries/pake/source/dirtiable-image.cpp b/libraries/pake/source/dirtiable-image.cpp new file mode 100644 index 0000000..9e5c979 --- /dev/null +++ b/libraries/pake/source/dirtiable-image.cpp @@ -0,0 +1,80 @@ +#include <pake/dirtiable-image.hpp> + +namespace pake { + + struct dirty_region_builder { + + std::vector<region> regions_not_on_bottom; + std::list<region> regions_on_bottom; + + void add_row(const std::vector<region> &row) { + + std::list<region> new_regions_on_bottom; + + for (auto i = row.begin(); i < row.end(); ++i) { + bool expanded = false; + for (auto j = regions_on_bottom.begin(); j != regions_on_bottom.end(); ++j) + if (i->start_x == j->start_x && i->width == j->width) { + j->height += i->height; + new_regions_on_bottom.push_back(*j); + regions_on_bottom.erase(j); + expanded = true; + break; + } + if (!expanded) + new_regions_on_bottom.push_back(*i); + } + + for (auto i = regions_on_bottom.begin(); i != regions_on_bottom.end(); ++i) + regions_not_on_bottom.push_back(*i); + + regions_on_bottom = std::move(new_regions_on_bottom); + + } + + }; + + std::vector<region> dirtiable_image::get_dirty_regions() { + + dirty_region_builder builder; + + std::vector<region> row; + + for (int y = 0; y < dirty.height; ++y) { + + int r = 0; + for (int x = 0; x < dirty.width; ++x) + if (!dirty.at(x, y)) { + if (r != x) + row.push_back({ + .start_x = r, .start_y = y, + .width = x - r, .height = 1 + }); + r = x + 1; + } + if (r != dirty.width) + row.push_back({ + .start_x = r, .start_y = y, + .width = dirty.width - r, .height = 1 + }); + + builder.add_row(row); + row.clear(); + + } + + builder.add_row(row); + return builder.regions_not_on_bottom; + + } + + void dirtiable_image::clear_dirty() { + dirty.fill(false); + } + + dirtiable_image::dirtiable_image(int width, int height) + : image(width, height), dirty(width, height) { + dirty.fill(false); + } + +} diff --git a/libraries/pake/source/widgets/fixed-text.cpp b/libraries/pake/source/widgets/fixed-text.cpp new file mode 100644 index 0000000..9ae55dc --- /dev/null +++ b/libraries/pake/source/widgets/fixed-text.cpp @@ -0,0 +1,41 @@ +#include <pake/widgets/fixed-text.hpp> + +static void draw_if_true( + daguerre::hilbert_color &out, const bool &in, + const daguerre::hilbert_color ¶m) { + if (in) out = param; +} + +namespace pake::widgets { + + fixed_text::fixed_text( + std::string &&text, + const daguerre::fixed_font<bool> *font, + daguerre::hilbert_color bg, + daguerre::hilbert_color fg) + : font(font), bg(bg), fg(fg), text(std::move(text)) {} + + void fixed_text::render( + dirtiable_image &onto, int x_off, int y_off, bool force) { + + if (force) { + onto.image.fill( bg, x_off, y_off, width, height); + onto.dirty.fill(true, x_off, y_off, width, height); + //TODO: have options for alignment + //TODO: check overflow + onto.image.render_text( + *font, fg, x_off, y_off, + text.data(), draw_if_true); + onto.dirty.fill( + true, x_off, y_off, + font->glyph_width * text.size(), + font->glyph_height); + } + + } + + void fixed_text::notify_size(int width, int height) { + this->width = width; this->height = height; + } + +} diff --git a/libraries/pake/source/window.cpp b/libraries/pake/source/window.cpp new file mode 100644 index 0000000..c1c773f --- /dev/null +++ b/libraries/pake/source/window.cpp @@ -0,0 +1,78 @@ +#include <pake/window.hpp> +#include <cassert> + +//TODO: handle errors on socket connection, read, and write + +namespace pake { + + window::window(int width, int height, const std::string &title) + : width(width), height(height), contents(width, height), root() { + + euler::syscall::connect_to_socket("hilbert.compositor", socket); + + assert(width >= 0 && height >= 0); + + struct [[gnu::packed]] { uint8_t type; uint32_t width; uint32_t height; } + dimensions_pkt = {.type = 0x02, .width = (uint32_t)width, .height = (uint32_t)height }; + euler::syscall::write_to_stream(socket, sizeof(dimensions_pkt), &dimensions_pkt); + + assert(title.size() <= UINT32_MAX); + + struct [[gnu::packed]] { uint8_t type; uint32_t length; } + title_pkt = {.type = 0x03, .length = (uint32_t)title.size() }; + euler::syscall::write_to_stream(socket, sizeof(title_pkt), &title_pkt); + euler::syscall::write_to_stream(socket, title.size(), title.data()); + + } + + window::~window() { + euler::syscall::close_stream(socket); + } + + void window::show() { + uint8_t packet = 0; + euler::syscall::write_to_stream(socket, 1, &packet); + } + + void window::hide() { + uint8_t packet = 1; + euler::syscall::write_to_stream(socket, 1, &packet); + } + + void window::set_root(std::unique_ptr<widget> &&w) { + root = std::move(w); + root->notify_size(width, height); + root->render(contents, 0, 0, true); + } + + void window::render_and_send_to_compositor() { + + root->render(contents, 0, 0, false); + auto dirties = contents.get_dirty_regions(); + + for (auto it = dirties.cbegin(); it != dirties.cend(); ++it) { + + struct [[gnu::packed]] { + uint8_t type; + uint32_t start_x; uint32_t start_y; + uint32_t width; uint32_t height; + } update_pkt = { + .type = 0x04, + .start_x = (uint32_t)it->start_x, .start_y = (uint32_t)it->start_y, + . width = (uint32_t)it-> width, . height = (uint32_t)it-> height + }; + + euler::syscall::write_to_stream(socket, sizeof(update_pkt), &update_pkt); + + for (int y = it->start_y; y < it->start_y + it->height; ++y) + euler::syscall::write_to_stream(socket, + it->width * sizeof(daguerre::hilbert_color), + &contents.image.at(it->start_x, y)); + + } + + contents.clear_dirty(); + + } + +} @@ -8,7 +8,7 @@ HILBERT_NASM = nasm -f elf64 HILBERT_CC = ${TOOLCHAIN_DIR}/usr/bin/x86_64-elf-c++ -std=c++20 \ ${EXTRA_CC_ARGS} -static -mno-sse -I include -I $(abspath euler/include) \ -I $(abspath libraries/daguerre/include) -I ${MINTSUKI_HEADERS_DIR} \ - -I $(abspath libraries/goldman/include) + -I $(abspath libraries/pake/include) HILBERT_AR = ${TOOLCHAIN_DIR}/usr/bin/x86_64-elf-ar HILBERT_LD = ${TOOLCHAIN_DIR}/usr/bin/x86_64-elf-ld -z noexecstack @@ -25,6 +25,7 @@ LIBSTDCPP_DEP = toolchain/.libstdcpp-done EULER_DEP = toolchain/.euler-done DAGUERRE_DEP = toolchain/.daguerre-done +PAKE_DEP = toolchain/.pake-done APP_DEPS = ${EULER_DEP} LIBRARY_DEPS = ${LIBSTDCPP_DEP} @@ -37,13 +38,14 @@ run: build/disk.iso gdb -x qemu.gdb clean: - rm -rf build ${EULER_DEP} ${DAGUERRE_DEP} + rm -rf build ${EULER_DEP} ${DAGUERRE_DEP} ${PAKE_DEP} make -C euler clean make -C kernel clean make -C applications/init clean make -C applications/goldman clean make -C applications/hello clean make -C libraries/daguerre clean + make -C libraries/pake clean clean-dependencies: clean rm -rf toolchain dependencies @@ -110,6 +112,11 @@ ${DAGUERRE_DEP}: ${LIBRARY_DEPS} cp libraries/daguerre/build/libdaguerre.a ${LIB_DIR}/ touch $@ +${PAKE_DEP}: ${LIBRARY_DEPS} + +make -C libraries/pake build/libpake.a + cp libraries/pake/build/libpake.a ${LIB_DIR}/ + touch $@ + kernel/build/kernel.elf: ${GCC_DEP} ${MINTSUKI_HEADERS_DEP} ${LIMINE_DEP} +make -C kernel build/kernel.elf @@ -119,7 +126,7 @@ applications/init/build/init.elf: ${APP_DEPS} applications/goldman/build/goldman.elf: ${APP_DEPS} ${DAGUERRE_DEP} +make -C applications/goldman build/goldman.elf -applications/hello/build/hello.elf: ${APP_DEPS} ${DAGUERRE_DEP} +applications/hello/build/hello.elf: ${APP_DEPS} ${DAGUERRE_DEP} ${PAKE_DEP} +make -C applications/hello build/hello.elf build/initfs.tgz: applications/init/build/init.elf \ |