mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 07:48:11 +00:00
Refactor GUI rendering model to be two-phased.
Instead of clients painting whenever they feel like it, we now ask that they paint in response to a paint message. After finishing painting, clients notify the WindowServer about the rect(s) they painted into and then flush eventually happens, etc. This stuff leaves us with a lot of badly named things. Need to fix that.
This commit is contained in:
parent
3a401d5249
commit
7cf3c7461c
16 changed files with 117 additions and 40 deletions
|
@ -201,6 +201,7 @@ public:
|
||||||
int gui$get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*);
|
int gui$get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*);
|
||||||
int gui$release_window_backing_store(void* backing_store_id);
|
int gui$release_window_backing_store(void* backing_store_id);
|
||||||
int gui$invalidate_window(int window_id, const GUI_Rect*);
|
int gui$invalidate_window(int window_id, const GUI_Rect*);
|
||||||
|
int gui$notify_paint_finished(int window_id, const GUI_Rect*);
|
||||||
int gui$get_window_title(int window_id, char* buffer, size_t size);
|
int gui$get_window_title(int window_id, char* buffer, size_t size);
|
||||||
int gui$set_window_title(int window_id, const char* title, size_t size);
|
int gui$set_window_title(int window_id, const char* title, size_t size);
|
||||||
int gui$get_window_rect(int window_id, GUI_Rect*);
|
int gui$get_window_rect(int window_id, GUI_Rect*);
|
||||||
|
|
|
@ -126,28 +126,50 @@ int Process::gui$release_window_backing_store(void* backing_store_id)
|
||||||
return -EBADBACKING;
|
return -EBADBACKING;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::gui$invalidate_window(int window_id, const GUI_Rect* rect)
|
int Process::gui$invalidate_window(int window_id, const GUI_Rect* a_rect)
|
||||||
{
|
{
|
||||||
if (window_id < 0)
|
if (window_id < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (rect && !validate_read_typed(rect))
|
if (a_rect && !validate_read_typed(a_rect))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
auto it = m_windows.find(window_id);
|
auto it = m_windows.find(window_id);
|
||||||
if (it == m_windows.end())
|
if (it == m_windows.end())
|
||||||
return -EBADWINDOW;
|
return -EBADWINDOW;
|
||||||
#ifdef LOG_GUI_SYSCALLS
|
#ifdef LOG_GUI_SYSCALLS
|
||||||
if (!rect)
|
if (!a_rect)
|
||||||
dbgprintf("%s<%u> gui$invalidate_window (window_id=%d, rect=(entire))\n", name().characters(), pid(), window_id);
|
dbgprintf("%s<%u> gui$invalidate_window (window_id=%d, rect=(entire))\n", name().characters(), pid(), window_id);
|
||||||
else
|
else
|
||||||
dbgprintf("%s<%u> gui$invalidate_window (window_id=%d, rect={%d,%d %dx%d})\n", name().characters(), pid(), window_id, rect->location.x, rect->location.y, rect->size.width, rect->size.height);
|
dbgprintf("%s<%u> gui$invalidate_window (window_id=%d, rect={%d,%d %dx%d})\n", name().characters(), pid(), window_id, a_rect->location.x, a_rect->location.y, a_rect->size.width, a_rect->size.height);
|
||||||
#endif
|
#endif
|
||||||
auto& window = *(*it).value;
|
auto& window = *(*it).value;
|
||||||
Rect invalidation_rect;
|
Rect rect;
|
||||||
if (rect) {
|
if (a_rect)
|
||||||
WSWindowLocker locker(window);
|
rect = *a_rect;
|
||||||
invalidation_rect = *rect;
|
WSEventLoop::the().post_event(&window, make<WSPaintEvent>(rect));
|
||||||
}
|
WSEventLoop::the().server_process().request_wakeup();
|
||||||
WSEventLoop::the().post_event(&window, make<WSWindowInvalidationEvent>(invalidation_rect));
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Process::gui$notify_paint_finished(int window_id, const GUI_Rect* a_rect)
|
||||||
|
{
|
||||||
|
if (window_id < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (a_rect && !validate_read_typed(a_rect))
|
||||||
|
return -EFAULT;
|
||||||
|
auto it = m_windows.find(window_id);
|
||||||
|
if (it == m_windows.end())
|
||||||
|
return -EBADWINDOW;
|
||||||
|
#ifdef LOG_GUI_SYSCALLS
|
||||||
|
if (!a_rect)
|
||||||
|
dbgprintf("%s<%u> gui$notify_paint_finished (window_id=%d, rect=(entire))\n", name().characters(), pid(), window_id);
|
||||||
|
else
|
||||||
|
dbgprintf("%s<%u> gui$notify_paint_finished (window_id=%d, rect={%d,%d %dx%d})\n", name().characters(), pid(), window_id, a_rect->location.x, a_rect->location.y, a_rect->size.width, a_rect->size.height);
|
||||||
|
#endif
|
||||||
|
auto& window = *(*it).value;
|
||||||
|
Rect rect;
|
||||||
|
if (a_rect)
|
||||||
|
rect = *a_rect;
|
||||||
|
WSEventLoop::the().post_event(&window, make<WSWindowInvalidationEvent>(rect));
|
||||||
WSEventLoop::the().server_process().request_wakeup();
|
WSEventLoop::the().server_process().request_wakeup();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,6 +215,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
|
||||||
return current->gui$get_window_rect((int)arg1, (GUI_Rect*)arg2);
|
return current->gui$get_window_rect((int)arg1, (GUI_Rect*)arg2);
|
||||||
case Syscall::SC_read_tsc:
|
case Syscall::SC_read_tsc:
|
||||||
return current->sys$read_tsc((dword*)arg1, (dword*)arg2);
|
return current->sys$read_tsc((dword*)arg1, (dword*)arg2);
|
||||||
|
case Syscall::SC_gui_notify_paint_finished:
|
||||||
|
return current->gui$notify_paint_finished((int)arg1, (const GUI_Rect*)arg2);
|
||||||
default:
|
default:
|
||||||
kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
|
kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
__ENUMERATE_SYSCALL(gui_set_window_title) \
|
__ENUMERATE_SYSCALL(gui_set_window_title) \
|
||||||
__ENUMERATE_SYSCALL(gui_get_window_rect) \
|
__ENUMERATE_SYSCALL(gui_get_window_rect) \
|
||||||
__ENUMERATE_SYSCALL(gui_set_window_rect) \
|
__ENUMERATE_SYSCALL(gui_set_window_rect) \
|
||||||
|
__ENUMERATE_SYSCALL(gui_notify_paint_finished) \
|
||||||
|
|
||||||
|
|
||||||
#ifdef SERENITY
|
#ifdef SERENITY
|
||||||
|
|
|
@ -50,3 +50,9 @@ int gui_set_window_rect(int window_id, const GUI_Rect* rect)
|
||||||
int rc = syscall(SC_gui_set_window_rect, window_id, rect);
|
int rc = syscall(SC_gui_set_window_rect, window_id, rect);
|
||||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gui_notify_paint_finished(int window_id, const GUI_Rect* rect)
|
||||||
|
{
|
||||||
|
int rc = syscall(SC_gui_notify_paint_finished, window_id, rect);
|
||||||
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
int gui_create_window(const GUI_WindowParameters*);
|
int gui_create_window(const GUI_WindowParameters*);
|
||||||
int gui_invalidate_window(int window_id, const GUI_Rect*);
|
int gui_invalidate_window(int window_id, const GUI_Rect*);
|
||||||
|
int gui_notify_paint_finished(int window_id, const GUI_Rect*);
|
||||||
int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*);
|
int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*);
|
||||||
int gui_release_window_backing_store(void* backing_store_id);
|
int gui_release_window_backing_store(void* backing_store_id);
|
||||||
int gui_get_window_title(int window_id, char*, size_t);
|
int gui_get_window_title(int window_id, char*, size_t);
|
||||||
|
|
|
@ -134,7 +134,7 @@ void GEventLoop::wait_for_event()
|
||||||
}
|
}
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case GUI_Event::Type::Paint:
|
case GUI_Event::Type::Paint:
|
||||||
dbgprintf("WID=%x Paint [%d,%d %dx%d]\n", event.window_id, event.paint.rect.location.x, event.paint.rect.location.y, event.paint.rect.size.width, event.paint.rect.size.height); break;
|
dbgprintf("WID=%x Paint [%d,%d %dx%d]\n", event.window_id, event.paint.rect.location.x, event.paint.rect.location.y, event.paint.rect.size.width, event.paint.rect.size.height);
|
||||||
handle_paint_event(event, *window);
|
handle_paint_event(event, *window);
|
||||||
break;
|
break;
|
||||||
case GUI_Event::Type::MouseDown:
|
case GUI_Event::Type::MouseDown:
|
||||||
|
|
|
@ -106,7 +106,7 @@ void GWidget::update()
|
||||||
if (m_has_pending_paint_event)
|
if (m_has_pending_paint_event)
|
||||||
return;
|
return;
|
||||||
m_has_pending_paint_event = true;
|
m_has_pending_paint_event = true;
|
||||||
GEventLoop::main().post_event(w, make<GPaintEvent>(relative_rect()));
|
w->update(relative_rect());
|
||||||
}
|
}
|
||||||
|
|
||||||
GWidget::HitTestResult GWidget::hit_test(int x, int y)
|
GWidget::HitTestResult GWidget::hit_test(int x, int y)
|
||||||
|
|
|
@ -49,11 +49,18 @@ GWindow::~GWindow()
|
||||||
void GWindow::set_title(String&& title)
|
void GWindow::set_title(String&& title)
|
||||||
{
|
{
|
||||||
dbgprintf("GWindow::set_title \"%s\"\n", title.characters());
|
dbgprintf("GWindow::set_title \"%s\"\n", title.characters());
|
||||||
GUI_WindowParameters params;
|
|
||||||
int rc = gui_set_window_title(m_window_id, title.characters(), title.length());
|
int rc = gui_set_window_title(m_window_id, title.characters(), title.length());
|
||||||
ASSERT(rc == 0);
|
ASSERT(rc == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String GWindow::title() const
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
int rc = gui_get_window_title(m_window_id, buffer, sizeof(buffer));
|
||||||
|
ASSERT(rc >= 0);
|
||||||
|
return String(buffer, rc);
|
||||||
|
}
|
||||||
|
|
||||||
void GWindow::set_rect(const Rect& a_rect)
|
void GWindow::set_rect(const Rect& a_rect)
|
||||||
{
|
{
|
||||||
dbgprintf("GWindow::set_rect! %d,%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height());
|
dbgprintf("GWindow::set_rect! %d,%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height());
|
||||||
|
@ -85,7 +92,7 @@ void GWindow::event(GEvent& event)
|
||||||
rect = m_main_widget->rect();
|
rect = m_main_widget->rect();
|
||||||
m_main_widget->event(*make<GPaintEvent>(rect));
|
m_main_widget->event(*make<GPaintEvent>(rect));
|
||||||
GUI_Rect gui_rect = rect;
|
GUI_Rect gui_rect = rect;
|
||||||
int rc = gui_invalidate_window(m_window_id, &gui_rect);
|
int rc = gui_notify_paint_finished(m_window_id, &gui_rect);
|
||||||
ASSERT(rc == 0);
|
ASSERT(rc == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +112,11 @@ void GWindow::show()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void GWindow::update()
|
void GWindow::update(const Rect& a_rect)
|
||||||
{
|
{
|
||||||
GEventLoop::main().post_event(this, make<GPaintEvent>());
|
GUI_Rect rect = a_rect;
|
||||||
|
int rc = gui_invalidate_window(m_window_id, a_rect.is_null() ? nullptr : &rect);
|
||||||
|
ASSERT(rc == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GWindow::set_main_widget(GWidget* widget)
|
void GWindow::set_main_widget(GWidget* widget)
|
||||||
|
|
|
@ -16,6 +16,7 @@ public:
|
||||||
|
|
||||||
int window_id() const { return m_window_id; }
|
int window_id() const { return m_window_id; }
|
||||||
|
|
||||||
|
String title() const;
|
||||||
void set_title(String&&);
|
void set_title(String&&);
|
||||||
|
|
||||||
int x() const { return rect().x(); }
|
int x() const { return rect().x(); }
|
||||||
|
@ -40,7 +41,7 @@ public:
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
|
|
||||||
void update();
|
void update(const Rect& = Rect());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RetainPtr<GraphicsBitmap> m_backing;
|
RetainPtr<GraphicsBitmap> m_backing;
|
||||||
|
|
|
@ -18,18 +18,16 @@ GraphicsBitmap::GraphicsBitmap(Process& process, const Size& size)
|
||||||
, m_pitch(size.width() * sizeof(RGBA32))
|
, m_pitch(size.width() * sizeof(RGBA32))
|
||||||
, m_client_process(&process)
|
, m_client_process(&process)
|
||||||
{
|
{
|
||||||
|
InterruptDisabler disabler;
|
||||||
size_t size_in_bytes = size.width() * size.height() * sizeof(RGBA32);
|
size_t size_in_bytes = size.width() * size.height() * sizeof(RGBA32);
|
||||||
auto vmo = VMObject::create_anonymous(size_in_bytes);
|
auto vmo = VMObject::create_anonymous(size_in_bytes);
|
||||||
m_client_region = process.allocate_region_with_vmo(LinearAddress(), size_in_bytes, vmo.copyRef(), 0, "GraphicsBitmap (client)", true, true);
|
m_client_region = process.allocate_region_with_vmo(LinearAddress(), size_in_bytes, vmo.copyRef(), 0, "GraphicsBitmap (client)", true, true);
|
||||||
m_client_region->set_shared(true);
|
m_client_region->set_shared(true);
|
||||||
m_client_region->commit();
|
m_client_region->commit();
|
||||||
|
auto& server = WSEventLoop::the().server_process();
|
||||||
|
m_server_region = server.allocate_region_with_vmo(LinearAddress(), size_in_bytes, move(vmo), 0, "GraphicsBitmap (server)", true, false);
|
||||||
|
m_server_region->set_shared(true);
|
||||||
|
|
||||||
{
|
|
||||||
auto& server = WSEventLoop::the().server_process();
|
|
||||||
InterruptDisabler disabler;
|
|
||||||
m_server_region = server.allocate_region_with_vmo(LinearAddress(), size_in_bytes, move(vmo), 0, "GraphicsBitmap (server)", true, false);
|
|
||||||
m_server_region->set_shared(true);
|
|
||||||
}
|
|
||||||
m_data = (RGBA32*)m_server_region->laddr().as_ptr();
|
m_data = (RGBA32*)m_server_region->laddr().as_ptr();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -88,7 +88,7 @@ Terminal::Line::Line(word columns)
|
||||||
{
|
{
|
||||||
characters = new byte[length];
|
characters = new byte[length];
|
||||||
attributes = new Attribute[length];
|
attributes = new Attribute[length];
|
||||||
needs_invalidation = false;
|
did_paint = false;
|
||||||
memset(characters, ' ', length);
|
memset(characters, ' ', length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,7 +603,7 @@ void Terminal::paint()
|
||||||
Painter painter(*m_backing);
|
Painter painter(*m_backing);
|
||||||
|
|
||||||
for (size_t i = 0; i < rows(); ++i)
|
for (size_t i = 0; i < rows(); ++i)
|
||||||
line(i).needs_invalidation = false;
|
line(i).did_paint = false;
|
||||||
|
|
||||||
if (m_rows_to_scroll_backing_store && m_rows_to_scroll_backing_store < m_rows) {
|
if (m_rows_to_scroll_backing_store && m_rows_to_scroll_backing_store < m_rows) {
|
||||||
int first_scanline = m_inset;
|
int first_scanline = m_inset;
|
||||||
|
@ -630,7 +630,7 @@ void Terminal::paint()
|
||||||
painter.fill_rect(row_rect(row), line.attributes[0].background_color);
|
painter.fill_rect(row_rect(row), line.attributes[0].background_color);
|
||||||
for (word column = 0; column < m_columns; ++column) {
|
for (word column = 0; column < m_columns; ++column) {
|
||||||
auto& attribute = line.attributes[column];
|
auto& attribute = line.attributes[column];
|
||||||
line.needs_invalidation = true;
|
line.did_paint = true;
|
||||||
char ch = line.characters[column];
|
char ch = line.characters[column];
|
||||||
auto character_rect = glyph_rect(row, column);
|
auto character_rect = glyph_rect(row, column);
|
||||||
if (!has_only_one_background_color) {
|
if (!has_only_one_background_color) {
|
||||||
|
@ -649,7 +649,7 @@ void Terminal::paint()
|
||||||
else
|
else
|
||||||
painter.draw_rect(cursor_rect, Color::MidGray);
|
painter.draw_rect(cursor_rect, Color::MidGray);
|
||||||
|
|
||||||
line(m_cursor_row).needs_invalidation = true;
|
line(m_cursor_row).did_paint = true;
|
||||||
|
|
||||||
if (m_belling) {
|
if (m_belling) {
|
||||||
m_need_full_invalidation = true;
|
m_need_full_invalidation = true;
|
||||||
|
@ -657,23 +657,38 @@ void Terminal::paint()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_need_full_invalidation) {
|
if (m_need_full_invalidation) {
|
||||||
invalidate_window();
|
did_paint();
|
||||||
m_need_full_invalidation = false;
|
m_need_full_invalidation = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect invalidation_rect;
|
Rect painted_rect;
|
||||||
for (int i = 0; i < m_rows; ++i) {
|
for (int i = 0; i < m_rows; ++i) {
|
||||||
if (line(i).needs_invalidation)
|
if (line(i).did_paint)
|
||||||
invalidation_rect = invalidation_rect.united(row_rect(i));
|
painted_rect = painted_rect.united(row_rect(i));
|
||||||
}
|
}
|
||||||
invalidate_window(invalidation_rect);
|
did_paint(painted_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::invalidate_window(const Rect& a_rect)
|
void Terminal::did_paint(const Rect& a_rect)
|
||||||
{
|
{
|
||||||
GUI_Rect rect = a_rect;
|
GUI_Rect rect = a_rect;
|
||||||
int rc = gui_invalidate_window(m_window_id, a_rect.is_null() ? nullptr : &rect);
|
int rc = gui_notify_paint_finished(m_window_id, a_rect.is_null() ? nullptr : &rect);
|
||||||
|
if (rc < 0) {
|
||||||
|
perror("gui_notify_paint_finished");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::update()
|
||||||
|
{
|
||||||
|
Rect rect;
|
||||||
|
for (int i = 0; i < m_rows; ++i) {
|
||||||
|
if (line(i).did_paint)
|
||||||
|
rect = rect.united(row_rect(i));
|
||||||
|
}
|
||||||
|
GUI_Rect gui_rect = rect;
|
||||||
|
int rc = gui_invalidate_window(m_window_id, rect.is_null() ? nullptr : &gui_rect);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("gui_invalidate_window");
|
perror("gui_invalidate_window");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -695,7 +710,7 @@ void Terminal::set_in_active_window(bool b)
|
||||||
return;
|
return;
|
||||||
m_in_active_window = b;
|
m_in_active_window = b;
|
||||||
invalidate_cursor();
|
invalidate_cursor();
|
||||||
paint();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::invalidate_cursor()
|
void Terminal::invalidate_cursor()
|
||||||
|
|
|
@ -18,6 +18,7 @@ public:
|
||||||
void on_char(byte);
|
void on_char(byte);
|
||||||
|
|
||||||
void set_in_active_window(bool);
|
void set_in_active_window(bool);
|
||||||
|
void update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Font& font() { return *m_font; }
|
Font& font() { return *m_font; }
|
||||||
|
@ -25,6 +26,7 @@ private:
|
||||||
void set_cursor(unsigned row, unsigned column);
|
void set_cursor(unsigned row, unsigned column);
|
||||||
void put_character_at(unsigned row, unsigned column, byte ch);
|
void put_character_at(unsigned row, unsigned column, byte ch);
|
||||||
void invalidate_cursor();
|
void invalidate_cursor();
|
||||||
|
void did_paint(const Rect& = Rect());
|
||||||
void invalidate_window(const Rect& = Rect());
|
void invalidate_window(const Rect& = Rect());
|
||||||
void set_window_title(const String&);
|
void set_window_title(const String&);
|
||||||
|
|
||||||
|
@ -67,7 +69,7 @@ private:
|
||||||
bool has_only_one_background_color() const;
|
bool has_only_one_background_color() const;
|
||||||
byte* characters { nullptr };
|
byte* characters { nullptr };
|
||||||
Attribute* attributes { nullptr };
|
Attribute* attributes { nullptr };
|
||||||
bool needs_invalidation { false };
|
bool did_paint { false };
|
||||||
bool dirty { false };
|
bool dirty { false };
|
||||||
word length { 0 };
|
word length { 0 };
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,7 +77,7 @@ int main(int, char**)
|
||||||
|
|
||||||
Terminal terminal;
|
Terminal terminal;
|
||||||
terminal.create_window();
|
terminal.create_window();
|
||||||
terminal.paint();
|
terminal.update();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
|
@ -100,7 +100,7 @@ int main(int, char**)
|
||||||
assert(nread != 0);
|
assert(nread != 0);
|
||||||
for (ssize_t i = 0; i < nread; ++i)
|
for (ssize_t i = 0; i < nread; ++i)
|
||||||
terminal.on_char(buffer[i]);
|
terminal.on_char(buffer[i]);
|
||||||
terminal.paint();
|
terminal.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FD_ISSET(event_fd, &rfds)) {
|
if (FD_ISSET(event_fd, &rfds)) {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <Kernel/Syscall.h>
|
#include <Kernel/Syscall.h>
|
||||||
#include <SharedGraphics/GraphicsBitmap.h>
|
#include <SharedGraphics/GraphicsBitmap.h>
|
||||||
#include <SharedGraphics/Painter.h>
|
#include <SharedGraphics/Painter.h>
|
||||||
#include "gui.h"
|
#include <LibC/gui.h>
|
||||||
|
|
||||||
static void paint(GraphicsBitmap& bitmap, int width, int height);
|
static void paint(GraphicsBitmap& bitmap, int width, int height);
|
||||||
|
|
||||||
|
@ -68,8 +68,12 @@ int main(int argc, char** argv)
|
||||||
case GUI_Event::Type::WindowDeactivated: dbgprintf("WID=%x WindowDeactivated\n", event.window_id); break;
|
case GUI_Event::Type::WindowDeactivated: dbgprintf("WID=%x WindowDeactivated\n", event.window_id); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.type == GUI_Event::Type::MouseDown) {
|
if (event.type == GUI_Event::Type::Paint) {
|
||||||
paint(*bitmap, backing.size.width, backing.size.height);
|
paint(*bitmap, backing.size.width, backing.size.height);
|
||||||
|
gui_notify_paint_finished(window_id, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type == GUI_Event::Type::MouseDown) {
|
||||||
gui_invalidate_window(window_id, nullptr);
|
gui_invalidate_window(window_id, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,21 @@ void WSEventLoop::post_event(WSEventReceiver* receiver, OwnPtr<WSEvent>&& event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event->type() == WSEvent::Paint) {
|
||||||
|
auto& invalidation_event = static_cast<WSPaintEvent&>(*event);
|
||||||
|
for (auto& queued_event : m_queued_events) {
|
||||||
|
if (receiver == queued_event.receiver && queued_event.event->type() == WSEvent::Paint) {
|
||||||
|
auto& queued_invalidation_event = static_cast<WSPaintEvent&>(*queued_event.event);
|
||||||
|
if (queued_invalidation_event.rect().is_empty() || queued_invalidation_event.rect().contains(invalidation_event.rect())) {
|
||||||
|
#ifdef WSEVENTLOOP_DEBUG
|
||||||
|
dbgprintf("Swallow WM_Paint\n");
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_queued_events.append({ receiver, move(event) });
|
m_queued_events.append({ receiver, move(event) });
|
||||||
|
|
||||||
if (current != m_server_process)
|
if (current != m_server_process)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue