diff --git a/Widgets/GraphicsBitmap.cpp b/Widgets/GraphicsBitmap.cpp index 480ebc10ff..a8dca6d127 100644 --- a/Widgets/GraphicsBitmap.cpp +++ b/Widgets/GraphicsBitmap.cpp @@ -6,15 +6,30 @@ RetainPtr GraphicsBitmap::create(const Size& size) return adopt(*new GraphicsBitmap(size)); } +RetainPtr GraphicsBitmap::create_wrapper(const Size& size, byte* data) +{ + return adopt(*new GraphicsBitmap(size, data)); +} + GraphicsBitmap::GraphicsBitmap(const Size& size) : m_size(size) { m_data = (byte*)kmalloc(size.width() * size.height() * 4); + m_owned = true; +} + +GraphicsBitmap::GraphicsBitmap(const Size& size, byte* data) + : m_size(size) +{ + m_data = data; + m_owned = false; } GraphicsBitmap::~GraphicsBitmap() { - kfree(m_data); + if (m_owned) + kfree(m_data); + m_data = nullptr; } dword* GraphicsBitmap::scanline(int y) diff --git a/Widgets/GraphicsBitmap.h b/Widgets/GraphicsBitmap.h index a7319368d1..bf09c65623 100644 --- a/Widgets/GraphicsBitmap.h +++ b/Widgets/GraphicsBitmap.h @@ -7,6 +7,7 @@ class GraphicsBitmap : public Retainable { public: static RetainPtr create(const Size&); + static RetainPtr create_wrapper(const Size&, byte*); ~GraphicsBitmap(); dword* scanline(int y); @@ -17,7 +18,9 @@ public: private: explicit GraphicsBitmap(const Size&); + GraphicsBitmap(const Size&, byte*); Size m_size; byte* m_data { nullptr }; + bool m_owned { false }; }; diff --git a/Widgets/RootWidget.cpp b/Widgets/RootWidget.cpp index f28bb16a61..f485e27d06 100644 --- a/Widgets/RootWidget.cpp +++ b/Widgets/RootWidget.cpp @@ -3,11 +3,12 @@ #include "RootWidget.h" #include "Painter.h" #include "WindowManager.h" +#include "FrameBufferSDL.h" #include RootWidget::RootWidget() { - m_backing = GraphicsBitmap::create(AbstractScreen::the().size()); + m_backing = GraphicsBitmap::create_wrapper(FrameBufferSDL::the().size(), (byte*)FrameBufferSDL::the().scanline(0)); } RootWidget::~RootWidget() diff --git a/Widgets/WindowManager.cpp b/Widgets/WindowManager.cpp index 083c8578c6..4c731e7238 100644 --- a/Widgets/WindowManager.cpp +++ b/Widgets/WindowManager.cpp @@ -58,12 +58,6 @@ WindowManager::~WindowManager() { } -void WindowManager::paintWindowFrames() -{ - for (auto* window = m_windows_in_order.head(); window; window = window->next()) - paintWindowFrame(*window); -} - void WindowManager::paintWindowFrame(Window& window) { Painter p(*m_rootWidget); @@ -139,15 +133,17 @@ void WindowManager::repaint() handlePaintEvent(*make()); } -void WindowManager::did_paint(Window&) +void WindowManager::did_paint(Window& window) { auto& framebuffer = FrameBufferSDL::the(); - framebuffer.blit({ 0, 0 }, *m_rootWidget->backing()); - for (auto* window = m_windows_in_order.head(); window; window = window->next()) { - ASSERT(window->backing()); - framebuffer.blit(window->position(), *window->backing()); + if (m_windows_in_order.head() == &window) { + ASSERT(window.backing()); + framebuffer.blit(window.position(), *window.backing()); + return; } - framebuffer.flush(); + + // FIXME: Check if anything overlaps this window, otherwise just blit. + recompose(); } void WindowManager::removeWindow(Window& window) @@ -237,11 +233,12 @@ void WindowManager::processMouseEvent(MouseEvent& event) pos.moveBy(event.x() - m_dragOrigin.x(), event.y() - m_dragOrigin.y()); m_dragWindow->setPositionWithoutRepaint(pos); paintWindowFrame(*m_dragWindow); + FrameBufferSDL::the().flush(); return; } } - for (auto* window = m_windows_in_order.head(); window; window = window->next()) { + for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) { if (titleBarRectForWindow(*window).contains(event.position())) { if (event.type() == Event::MouseDown) { move_to_front(*window); @@ -273,14 +270,21 @@ void WindowManager::handlePaintEvent(PaintEvent& event) } m_rootWidget->event(event); - paintWindowFrames(); for (auto* window = m_windows_in_order.head(); window; window = window->next()) window->event(event); + recompose(); +} + +void WindowManager::recompose() +{ auto& framebuffer = FrameBufferSDL::the(); - framebuffer.blit({ 0, 0 }, *m_rootWidget->backing()); + m_rootWidget->repaint(m_rootWidget->rect()); for (auto* window = m_windows_in_order.head(); window; window = window->next()) { + paintWindowFrame(*window); + if (m_dragWindow.ptr() == window) + continue; ASSERT(window->backing()); framebuffer.blit(window->position(), *window->backing()); } diff --git a/Widgets/WindowManager.h b/Widgets/WindowManager.h index 9b643f000c..1ff26108d3 100644 --- a/Widgets/WindowManager.h +++ b/Widgets/WindowManager.h @@ -17,7 +17,6 @@ public: static WindowManager& the(); void addWindow(Window&); void removeWindow(Window&); - void paintWindowFrames(); void notifyTitleChanged(Window&); void notifyRectChanged(Window&, const Rect& oldRect, const Rect& newRect); @@ -52,6 +51,7 @@ private: Color m_inactiveWindowBorderColor; Color m_inactiveWindowTitleColor; + void recompose(); void paintWindowFrame(Window&); HashTable m_windows; InlineLinkedList m_windows_in_order;