mirror of
https://github.com/RGBCube/serenity
synced 2025-06-01 09:28:13 +00:00
Rework the rendering model so that clients instantiate backing stores.
This makes interactive resizing work a lot better, althought it's still not perfect. There are still glitches and unpleasant flashes of zeroed memory.
This commit is contained in:
parent
e0b81ee4c9
commit
fa02d2a39b
17 changed files with 185 additions and 46 deletions
|
@ -78,8 +78,11 @@ int GEventLoop::exec()
|
|||
for (;;) {
|
||||
if (m_exit_requested)
|
||||
return m_exit_code;
|
||||
if (m_queued_events.is_empty())
|
||||
process_unprocessed_messages();
|
||||
if (m_queued_events.is_empty()) {
|
||||
wait_for_event();
|
||||
process_unprocessed_messages();
|
||||
}
|
||||
Vector<QueuedEvent> events = move(m_queued_events);
|
||||
for (auto& queued_event : events) {
|
||||
auto* receiver = queued_event.receiver;
|
||||
|
@ -223,6 +226,7 @@ void GEventLoop::wait_for_event()
|
|||
struct timeval timeout = { 0, 0 };
|
||||
if (!m_timers.is_empty())
|
||||
get_next_timer_expiration(timeout);
|
||||
ASSERT(m_unprocessed_messages.is_empty());
|
||||
int rc = select(max_fd + 1, &rfds, &wfds, nullptr, (m_queued_events.is_empty() && m_timers.is_empty()) ? nullptr : &timeout);
|
||||
if (rc < 0) {
|
||||
ASSERT_NOT_REACHED();
|
||||
|
@ -260,9 +264,16 @@ void GEventLoop::wait_for_event()
|
|||
|
||||
bool success = drain_messages_from_server();
|
||||
ASSERT(success);
|
||||
}
|
||||
|
||||
void GEventLoop::process_unprocessed_messages()
|
||||
{
|
||||
auto unprocessed_events = move(m_unprocessed_messages);
|
||||
for (auto& event : unprocessed_events) {
|
||||
if (event.type == WSAPI_ServerMessage::Type::Greeting) {
|
||||
m_server_pid = event.greeting.server_pid;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event.type == WSAPI_ServerMessage::Error) {
|
||||
dbgprintf("GEventLoop got error message from server\n");
|
||||
|
@ -315,6 +326,9 @@ void GEventLoop::wait_for_event()
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_unprocessed_messages.is_empty())
|
||||
process_unprocessed_messages();
|
||||
}
|
||||
|
||||
bool GEventLoop::drain_messages_from_server()
|
||||
|
|
|
@ -39,9 +39,12 @@ public:
|
|||
|
||||
WSAPI_ServerMessage sync_request(const WSAPI_ClientMessage& request, WSAPI_ServerMessage::Type response_type);
|
||||
|
||||
pid_t server_pid() const { return m_server_pid; }
|
||||
|
||||
private:
|
||||
void wait_for_event();
|
||||
bool drain_messages_from_server();
|
||||
void process_unprocessed_messages();
|
||||
void handle_paint_event(const WSAPI_ServerMessage&, GWindow&);
|
||||
void handle_resize_event(const WSAPI_ServerMessage&, GWindow&);
|
||||
void handle_mouse_event(const WSAPI_ServerMessage&, GWindow&);
|
||||
|
@ -64,8 +67,8 @@ private:
|
|||
bool m_running { false };
|
||||
bool m_exit_requested { false };
|
||||
int m_exit_code { 0 };
|
||||
|
||||
int m_next_timer_id { 1 };
|
||||
pid_t m_server_pid { 0 };
|
||||
|
||||
struct EventLoopTimer {
|
||||
int timer_id { 0 };
|
||||
|
|
|
@ -28,11 +28,14 @@ void GWidget::set_relative_rect(const Rect& rect)
|
|||
{
|
||||
if (rect == m_relative_rect)
|
||||
return;
|
||||
if (m_relative_rect.size() != rect.size()) {
|
||||
auto event = make<GResizeEvent>(m_relative_rect.size(), rect.size());
|
||||
GEventLoop::main().post_event(this, move(event));
|
||||
}
|
||||
bool size_changed = m_relative_rect.size() != rect.size();
|
||||
m_relative_rect = rect;
|
||||
|
||||
if (size_changed) {
|
||||
GResizeEvent resize_event(m_relative_rect.size(), rect.size());
|
||||
event(resize_event);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
|
|
@ -169,9 +169,36 @@ void GWindow::event(GEvent& event)
|
|||
return;
|
||||
auto& paint_event = static_cast<GPaintEvent&>(event);
|
||||
auto rect = paint_event.rect();
|
||||
if (rect.is_empty())
|
||||
bool created_new_backing_store = !m_backing;
|
||||
if (!m_backing) {
|
||||
// NOTE: size() may change at any time since it's synchronously retrieved from the WindowServer.
|
||||
ASSERT(GEventLoop::main().server_pid());
|
||||
Size new_backing_store_size = size();
|
||||
size_t size_in_bytes = new_backing_store_size.area() * sizeof(RGBA32);
|
||||
void* buffer;
|
||||
int shared_buffer_id = create_shared_buffer(GEventLoop::main().server_pid(), size_in_bytes, (void**)&buffer);
|
||||
ASSERT(shared_buffer_id >= 0);
|
||||
ASSERT(buffer);
|
||||
ASSERT(buffer != (void*)-1);
|
||||
m_backing = GraphicsBitmap::create_with_shared_buffer(
|
||||
m_has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32,
|
||||
shared_buffer_id,
|
||||
new_backing_store_size, (RGBA32*)buffer);
|
||||
}
|
||||
if (rect.is_empty() || created_new_backing_store)
|
||||
rect = m_main_widget->rect();
|
||||
m_main_widget->event(*make<GPaintEvent>(rect));
|
||||
if (created_new_backing_store) {
|
||||
WSAPI_ClientMessage message;
|
||||
message.type = WSAPI_ClientMessage::Type::SetWindowBackingStore;
|
||||
message.window_id = m_window_id;
|
||||
message.backing.bpp = 32;
|
||||
message.backing.pitch = m_backing->pitch();
|
||||
message.backing.shared_buffer_id = m_backing->shared_buffer_id();
|
||||
message.backing.has_alpha_channel = m_backing->has_alpha_channel();
|
||||
message.backing.size = m_backing->size();
|
||||
GEventLoop::main().post_message_to_server(message);
|
||||
}
|
||||
if (m_window_id) {
|
||||
WSAPI_ClientMessage message;
|
||||
message.type = WSAPI_ClientMessage::Type::DidFinishPainting;
|
||||
|
@ -210,6 +237,7 @@ void GWindow::event(GEvent& event)
|
|||
}
|
||||
|
||||
if (event.type() == GEvent::Resize) {
|
||||
m_backing = nullptr;
|
||||
m_pending_paint_event_rects.clear();
|
||||
m_rect_when_windowless = { { }, static_cast<GResizeEvent&>(event).size() };
|
||||
m_main_widget->set_relative_rect({ { }, static_cast<GResizeEvent&>(event).size() });
|
||||
|
@ -233,7 +261,7 @@ void GWindow::update(const Rect& a_rect)
|
|||
#ifdef UPDATE_COALESCING_DEBUG
|
||||
dbgprintf("Ignoring %s since it's contained by pending rect %s\n", a_rect.to_string().characters(), pending_rect.to_string().characters());
|
||||
#endif
|
||||
return;
|
||||
//return;
|
||||
}
|
||||
}
|
||||
m_pending_paint_event_rects.append(a_rect);
|
||||
|
|
|
@ -68,6 +68,8 @@ public:
|
|||
const GWidget* hovered_widget() const { return m_hovered_widget.ptr(); }
|
||||
void set_hovered_widget(GWidget*);
|
||||
|
||||
GraphicsBitmap* backing() { return m_backing.ptr(); }
|
||||
|
||||
private:
|
||||
virtual const char* class_name() const override { return "GWindow"; }
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue