diff --git a/applications/libwindow/inc/libwindow/component.hpp b/applications/libwindow/inc/libwindow/component.hpp index 9bc3f1b4..6bcc23d8 100644 --- a/applications/libwindow/inc/libwindow/component.hpp +++ b/applications/libwindow/inc/libwindow/component.hpp @@ -41,11 +41,12 @@ class g_component : public g_bounding_component { protected: g_ui_component_id id; + bool destroyed = false; g_user_mutex listenersLock = g_mutex_initialize_r(true); std::unordered_map> listeners; - ~g_component() override = default; + ~g_component() override; template static COMPONENT_TYPE* createComponent() @@ -58,6 +59,7 @@ class g_component : public g_bounding_component request.header.id = G_UI_PROTOCOL_CREATE_COMPONENT; request.type = COMPONENT_CONSTANT; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_create_component_request), tx); + // g_yield_t(g_ui_delegate_tid); size_t bufferSize = sizeof(g_message_header) + sizeof(g_ui_create_component_response); uint8_t buffer[bufferSize]; @@ -96,6 +98,7 @@ class g_component : public g_bounding_component return id; } + void destroy(); bool addChild(g_component* c); bool setBounds(const g_rectangle& rect); diff --git a/applications/libwindow/inc/libwindow/interface.hpp b/applications/libwindow/inc/libwindow/interface.hpp index a6b014f6..135f0b89 100644 --- a/applications/libwindow/inc/libwindow/interface.hpp +++ b/applications/libwindow/inc/libwindow/interface.hpp @@ -79,6 +79,7 @@ typedef uint8_t g_ui_protocol_command_id; #define G_UI_PROTOCOL_SCROLLPANE_SET_CONTENT ((g_ui_protocol_command_id) 18) #define G_UI_PROTOCOL_SCROLLPANE_SET_FIXED ((g_ui_protocol_command_id) 19) #define G_UI_PROTOCOL_SET_PREFERRED_SIZE ((g_ui_protocol_command_id) 20) +#define G_UI_PROTOCOL_DESTROY_COMPONENT ((g_ui_protocol_command_id) 21) /** * Common status for requests @@ -185,6 +186,15 @@ typedef struct g_ui_component_id id; } __attribute__((packed)) g_ui_create_component_response; +/** + * Request sent to destroy a component + */ +typedef struct +{ + g_ui_message_header header; + g_ui_component_id id; +} __attribute__((packed)) g_ui_destroy_component_request; + /** * Request/response to focus */ diff --git a/applications/libwindow/inc/libwindow/metrics/rectangle.hpp b/applications/libwindow/inc/libwindow/metrics/rectangle.hpp index aabfe24f..117dec9e 100644 --- a/applications/libwindow/inc/libwindow/metrics/rectangle.hpp +++ b/applications/libwindow/inc/libwindow/metrics/rectangle.hpp @@ -177,7 +177,7 @@ struct g_rectangle */ void extend(const g_point& p) { - if (width == -1 || height == -1) + if (width <= 0 || height <= 0) { x = p.x; y = p.y; diff --git a/applications/libwindow/src/canvas.cpp b/applications/libwindow/src/canvas.cpp index eabe8409..46a6ba5f 100644 --- a/applications/libwindow/src/canvas.cpp +++ b/applications/libwindow/src/canvas.cpp @@ -124,4 +124,5 @@ void g_canvas::blit(const g_rectangle& rect) request.id = this->id; request.area = rect; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_component_canvas_blit_request), tx); + g_yield_t(g_ui_delegate_tid); } diff --git a/applications/libwindow/src/component.cpp b/applications/libwindow/src/component.cpp index 1b214c32..834f3ed0 100644 --- a/applications/libwindow/src/component.cpp +++ b/applications/libwindow/src/component.cpp @@ -23,6 +23,24 @@ #include "libwindow/component.hpp" #include "libwindow/properties.hpp" +g_component::~g_component() +{ + destroy(); +} + +void g_component::destroy() +{ + if(destroyed) + return; + destroyed = true; + + g_ui_destroy_component_request request; + request.header.id = G_UI_PROTOCOL_DESTROY_COMPONENT; + request.id = this->id; + g_send_message(g_ui_delegate_tid, &request, sizeof(g_ui_destroy_component_request)); + g_yield_t(g_ui_delegate_tid); +} + bool g_component::addChild(g_component* child) { if(!g_ui_initialized) @@ -66,6 +84,7 @@ bool g_component::setBounds(const g_rectangle& rect) request.id = this->id; request.bounds = rect; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_component_set_bounds_request), tx); + g_yield_t(g_ui_delegate_tid); // read response size_t buflen = sizeof(g_message_header) + sizeof(g_ui_simple_response); @@ -90,6 +109,7 @@ g_rectangle g_component::getBounds() request.header.id = G_UI_PROTOCOL_GET_BOUNDS; request.id = this->id; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_component_get_bounds_request), tx); + g_yield_t(g_ui_delegate_tid); // read response size_t bufferSize = sizeof(g_message_header) + sizeof(g_ui_component_get_bounds_response); @@ -120,6 +140,7 @@ bool g_component::setNumericProperty(int property, uint32_t value) request.property = property; request.value = value; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_component_set_numeric_property_request), tx); + g_yield_t(g_ui_delegate_tid); // read response size_t bufferSize = sizeof(g_message_header) + sizeof(g_ui_component_set_numeric_property_response); @@ -149,6 +170,7 @@ bool g_component::getNumericProperty(int property, uint32_t* out) request.id = this->id; request.property = property; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_component_get_numeric_property_request), tx); + g_yield_t(g_ui_delegate_tid); // read response size_t bufferSize = sizeof(g_message_header) + sizeof(g_ui_component_get_numeric_property_response); @@ -294,6 +316,7 @@ bool g_component::setPreferredSize(g_dimension size) request.id = this->id; request.size = size; g_send_message_t(g_ui_delegate_tid, &request, sizeof(request), tx); + g_yield_t(g_ui_delegate_tid); size_t buflen = sizeof(g_message_header) + sizeof(g_ui_simple_response); uint8_t buffer[buflen]; @@ -317,6 +340,7 @@ bool g_component::setFlexOrientation(bool horizontal) request.id = this->id; request.horizontal = horizontal; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_flex_set_orientation_request), tx); + g_yield_t(g_ui_delegate_tid); size_t buflen = sizeof(g_message_header) + sizeof(g_ui_simple_response); uint8_t buffer[buflen]; @@ -343,6 +367,7 @@ bool g_component::setFlexComponentInfo(g_component* child, float grow, float shr request.shrink = shrink; request.basis = basis; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_flex_set_component_info), tx); + g_yield_t(g_ui_delegate_tid); size_t buflen = sizeof(g_message_header) + sizeof(g_ui_simple_response); uint8_t buffer[buflen]; @@ -367,6 +392,7 @@ bool g_component::setFlexPadding(g_insets padding) request.id = this->id; request.insets = padding; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_flex_set_padding), tx); + g_yield_t(g_ui_delegate_tid); size_t buflen = sizeof(g_message_header) + sizeof(g_ui_simple_response); uint8_t buffer[buflen]; diff --git a/applications/libwindow/src/focusable_component.cpp b/applications/libwindow/src/focusable_component.cpp index 3ae43dc4..71f74fe8 100644 --- a/applications/libwindow/src/focusable_component.cpp +++ b/applications/libwindow/src/focusable_component.cpp @@ -42,6 +42,7 @@ bool g_focusable_component::setFocused(bool focused) request.header.id = G_UI_PROTOCOL_FOCUS; request.id = this->id; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_component_focus_request), tx); + g_yield_t(g_ui_delegate_tid); size_t bufferSize = sizeof(g_message_header) + sizeof(g_ui_component_focus_response); uint8_t buffer[bufferSize]; diff --git a/applications/libwindow/src/scrollpane.cpp b/applications/libwindow/src/scrollpane.cpp index c7751cde..d8f57320 100644 --- a/applications/libwindow/src/scrollpane.cpp +++ b/applications/libwindow/src/scrollpane.cpp @@ -38,6 +38,7 @@ bool g_scrollpane::setContent(g_component* content) request.scrollpane = this->id; request.content = content->getId(); g_send_message_t(g_ui_delegate_tid, &request, sizeof(request), tx); + g_yield_t(g_ui_delegate_tid); size_t buflen = sizeof(g_message_header) + sizeof(g_ui_simple_response); uint8_t buffer[buflen]; @@ -62,6 +63,7 @@ bool g_scrollpane::setFixed(bool width, bool height) request.width = width; request.height = height; g_send_message_t(g_ui_delegate_tid, &request, sizeof(request), tx); + g_yield_t(g_ui_delegate_tid); size_t buflen = sizeof(g_message_header) + sizeof(g_ui_simple_response); uint8_t buffer[buflen]; diff --git a/applications/libwindow/src/titled_component.cpp b/applications/libwindow/src/titled_component.cpp index fa6808de..b7d500fb 100644 --- a/applications/libwindow/src/titled_component.cpp +++ b/applications/libwindow/src/titled_component.cpp @@ -52,6 +52,7 @@ bool g_titled_component::setTitle(std::string title) request->title[title_len] = 0; g_send_message_t(g_ui_delegate_tid, request, sizeof(g_ui_component_set_title_request), tx); + g_yield_t(g_ui_delegate_tid); // read response size_t bufferSize = sizeof(g_message_header) + sizeof(g_ui_component_set_title_response); @@ -80,6 +81,7 @@ std::string g_titled_component::getTitle() request.header.id = G_UI_PROTOCOL_GET_TITLE; request.id = this->id; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_component_get_title_request), tx); + g_yield_t(g_ui_delegate_tid); // read response size_t bufferSize = sizeof(g_message_header) + sizeof(g_ui_component_get_title_response); diff --git a/applications/libwindow/src/ui.cpp b/applications/libwindow/src/ui.cpp index 62e1748a..1d398cfa 100644 --- a/applications/libwindow/src/ui.cpp +++ b/applications/libwindow/src/ui.cpp @@ -69,6 +69,7 @@ g_ui_open_status g_ui::open() request.header.id = G_UI_PROTOCOL_INITIALIZATION; request.event_dispatcher = g_ui_event_dispatcher_tid; g_send_message_t(windowServerRegistrationTask, &request, sizeof(g_ui_initialize_request), init_tx); + g_yield_t(g_ui_delegate_tid); // receive initialization response size_t buflen = sizeof(g_message_header) + sizeof(g_ui_initialize_response); @@ -106,6 +107,7 @@ bool g_ui::addListener(g_ui_component_id id, g_ui_component_event_type eventType request.target_thread = g_ui_event_dispatcher_tid; request.event_type = eventType; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_component_add_listener_request), tx); + g_yield_t(g_ui_delegate_tid); size_t bufferSize = sizeof(g_message_header) + sizeof(g_ui_component_add_listener_response); uint8_t buffer[bufferSize]; @@ -169,6 +171,7 @@ bool g_ui::registerDesktopCanvas(g_canvas* c) request.canvas_id = c->getId(); request.target_thread = g_ui_event_dispatcher_tid; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_register_desktop_canvas_request), tx); + g_yield_t(g_ui_delegate_tid); // read response size_t buflen = sizeof(g_message_header) + sizeof(g_ui_register_desktop_canvas_response); @@ -199,6 +202,7 @@ bool g_ui::getScreenDimension(g_dimension& out) g_ui_get_screen_dimension_request request; request.header.id = G_UI_PROTOCOL_GET_SCREEN_DIMENSION; g_send_message_t(g_ui_delegate_tid, &request, sizeof(g_ui_get_screen_dimension_request), tx); + g_yield_t(g_ui_delegate_tid); // read response size_t bufferSize = sizeof(g_message_header) + sizeof(g_ui_get_screen_dimension_response); diff --git a/applications/windowserver/src/components/component.cpp b/applications/windowserver/src/components/component.cpp index 9cb98434..39c8171e 100644 --- a/applications/windowserver/src/components/component.cpp +++ b/applications/windowserver/src/components/component.cpp @@ -170,6 +170,8 @@ void component_t::blit(graphics_t* out, const g_rectangle& parentClip, const g_p if(!this->visible) return; + g_mutex_acquire(lock); + g_rectangle clip = getBounds(); clip.x = screenPosition.x; clip.y = screenPosition.y; @@ -179,6 +181,7 @@ void component_t::blit(graphics_t* out, const g_rectangle& parentClip, const g_p { graphics.blitTo(out, clip, screenPosition); } + g_mutex_release(lock); this->blitChildren(out, clip, screenPosition); } @@ -466,6 +469,7 @@ void component_t::resolveRequirement(component_requirement_t req, int lvl) g_mutex_release(childrenLock); } + g_mutex_acquire(lock); if(requirements & req) { if(req == COMPONENT_REQUIREMENT_UPDATE) @@ -484,6 +488,7 @@ void component_t::resolveRequirement(component_requirement_t req, int lvl) requirements &= ~req; } + g_mutex_release(lock); if((childRequirements & req) && req == COMPONENT_REQUIREMENT_LAYOUT) { diff --git a/applications/windowserver/src/interface/interface_receiver.cpp b/applications/windowserver/src/interface/interface_receiver.cpp index 0622ca37..163292f2 100644 --- a/applications/windowserver/src/interface/interface_receiver.cpp +++ b/applications/windowserver/src/interface/interface_receiver.cpp @@ -33,9 +33,6 @@ #include "interface/interface_receiver.hpp" #include "layout/flex_layout_manager.hpp" -g_user_mutex eventBufferLock = g_mutex_initialize(); -std::vector eventBuffer; - void interfaceReceiverThread() { while(true) @@ -52,20 +49,8 @@ void interfaceReceiverThread() if(stat == G_MESSAGE_RECEIVE_STATUS_SUCCESSFUL) { auto message = (g_message_header*) buf; - auto content = (g_ui_message_header*) G_MESSAGE_CONTENT(message); - if(content->id == G_UI_PROTOCOL_GET_BOUNDS || content->id == G_UI_PROTOCOL_SET_BOUNDS) - { - interfaceReceiverProcessCommand(message); - } - else - { - g_mutex_acquire(eventBufferLock); - eventBuffer.push_back(message); - g_mutex_release(eventBufferLock); - windowserver_t::instance()->requestUpdate(); - deferred = true; - } + interfaceReceiverProcessCommand(message); } else if(stat == G_MESSAGE_RECEIVE_STATUS_EXCEEDS_BUFFER_SIZE) { @@ -81,18 +66,6 @@ void interfaceReceiverThread() } } -void interfaceReceiverProcessBufferedCommands() -{ - g_mutex_acquire(eventBufferLock); - for(auto& entry: eventBuffer) - { - interfaceReceiverProcessCommand(entry); - delete entry; - } - eventBuffer.clear(); - g_mutex_release(eventBufferLock); -} - void interfaceReceiverProcessCommand(g_message_header* requestMessage) { auto requestUiMessage = (g_ui_message_header*) G_MESSAGE_CONTENT(requestMessage); @@ -181,6 +154,19 @@ void interfaceReceiverProcessCommand(g_message_header* requestMessage) responseMessage = response; responseLength = sizeof(g_ui_component_add_child_response); } + else if(requestUiMessage->id == G_UI_PROTOCOL_DESTROY_COMPONENT) + { + auto request = (g_ui_destroy_component_request*) requestUiMessage; + component_t* component = component_registry_t::get(request->id); + + if(component) + { + auto parent = component->getParent(); + if(parent) + parent->removeChild(component); + // TODO deferred component deletion + } + } else if(requestUiMessage->id == G_UI_PROTOCOL_SET_BOUNDS) { auto request = (g_ui_component_set_bounds_request*) requestUiMessage; @@ -540,7 +526,11 @@ void interfaceReceiverProcessCommand(g_message_header* requestMessage) responseLength = sizeof(g_ui_simple_response); } + windowserver_t::instance()->requestUpdate(); if(responseMessage) + { g_send_message_t(requestMessage->sender, responseMessage, responseLength, requestMessage->transaction); + g_yield_t(requestMessage->sender); + } } diff --git a/applications/windowserver/src/interface/interface_receiver.hpp b/applications/windowserver/src/interface/interface_receiver.hpp index 9de67e4f..b44db014 100644 --- a/applications/windowserver/src/interface/interface_receiver.hpp +++ b/applications/windowserver/src/interface/interface_receiver.hpp @@ -25,6 +25,5 @@ void interfaceReceiverThread(); void interfaceReceiverProcessCommand(g_message_header* requestMessage); -void interfaceReceiverProcessBufferedCommands(); #endif diff --git a/applications/windowserver/src/windowserver.cpp b/applications/windowserver/src/windowserver.cpp index 72fcbfb8..a90a0203 100644 --- a/applications/windowserver/src/windowserver.cpp +++ b/applications/windowserver/src/windowserver.cpp @@ -155,24 +155,30 @@ void windowserver_t::updateLoop() { g_task_register_id("windowserver/updater"); + int timesUpdated = 0; + g_mutex_acquire(updateLock); while(true) { + ++timesUpdated; eventProcessor->process(); - interfaceReceiverProcessBufferedCommands(); + screen->resolveRequirement(COMPONENT_REQUIREMENT_UPDATE, 0); screen->resolveRequirement(COMPONENT_REQUIREMENT_LAYOUT, 0); screen->resolveRequirement(COMPONENT_REQUIREMENT_PAINT, 0); requestRender(); - g_mutex_acquire_to(updateLock, 1000); + + if(!g_mutex_acquire_to(updateLock, 1000)) + { + klog("Times updated: %i", timesUpdated); + } } } void windowserver_t::requestUpdate() const { g_mutex_release(updateLock); - g_yield_t(updateTask); } @@ -223,7 +229,11 @@ void windowserver_t::output(graphics_t* graphics) const cairo_save(cr); cairo_set_line_width(cr, 2); cairo_rectangle(cr, invalid.x, invalid.y, invalid.width, invalid.height); - cairo_set_source_rgba(cr, 0, ((double) (debugBorderCycle + 100)) / 255, 0, 1); + cairo_set_source_rgba(cr, + debugBorderCycle % 3 == 0 ? ((double) (debugBorderCycle + 100)) / 255 : 0, + debugBorderCycle % 2 == 0 ? ((double) (debugBorderCycle + 100)) / 255 : 0, + debugBorderCycle % 2 == 1 ? ((double) (debugBorderCycle + 100)) / 255 : 0, + 1); cairo_stroke(cr); cairo_restore(cr); graphics->releaseContext();