diff --git a/Servers/WindowServer/WSCompositor.cpp b/Servers/WindowServer/WSCompositor.cpp index 4a9ac744d8..98c16dd5b2 100644 --- a/Servers/WindowServer/WSCompositor.cpp +++ b/Servers/WindowServer/WSCompositor.cpp @@ -151,24 +151,52 @@ void WSCompositor::compose() window.frame().paint(*m_back_painter); if (!backing_store) continue; - Rect dirty_rect_in_window_coordinates = Rect::intersection(dirty_rect, window.rect()); - if (dirty_rect_in_window_coordinates.is_empty()) + + // Decide where we would paint this window's backing store. + // This is subtly different from widow.rect(), because window + // size may be different from its backing store size. This + // happens when the window has been resized and the client + // has not yet attached a new backing store. In this case, + // we want to try to blit the backing store at the same place + // it was previously, and fill the rest of the window with its + // background color. + Rect backing_rect; + backing_rect.set_size(backing_store->size()); + switch (WSWindowManager::the().resize_direction_of_window(window)) { + case ResizeDirection::None: + case ResizeDirection::Right: + case ResizeDirection::Down: + case ResizeDirection::DownRight: + backing_rect.set_location(window.rect().location()); + break; + case ResizeDirection::Left: + case ResizeDirection::Up: + case ResizeDirection::UpLeft: + backing_rect.set_right_without_resize(window.rect().right()); + backing_rect.set_bottom_without_resize(window.rect().bottom()); + break; + case ResizeDirection::UpRight: + backing_rect.set_left(window.rect().left()); + backing_rect.set_bottom_without_resize(window.rect().bottom()); + break; + case ResizeDirection::DownLeft: + backing_rect.set_right_without_resize(window.rect().right()); + backing_rect.set_top(window.rect().top()); + break; + } + + Rect dirty_rect_in_backing_coordinates = dirty_rect + .intersected(window.rect()) + .intersected(backing_rect) + .translated(-backing_rect.location()); + + if (dirty_rect_in_backing_coordinates.is_empty()) continue; - dirty_rect_in_window_coordinates.move_by(-window.position()); - auto dst = window.position(); - dst.move_by(dirty_rect_in_window_coordinates.location()); + auto dst = backing_rect.location().translated(dirty_rect_in_backing_coordinates.location()); - m_back_painter->blit(dst, *backing_store, dirty_rect_in_window_coordinates, window.opacity()); - - if (backing_store->width() < window.width()) { - Rect right_fill_rect { window.x() + backing_store->width(), window.y(), window.width() - backing_store->width(), window.height() }; - m_back_painter->fill_rect(right_fill_rect, window.background_color()); - } - - if (backing_store->height() < window.height()) { - Rect bottom_fill_rect { window.x(), window.y() + backing_store->height(), window.width(), window.height() - backing_store->height() }; - m_back_painter->fill_rect(bottom_fill_rect, window.background_color()); - } + m_back_painter->blit(dst, *backing_store, dirty_rect_in_backing_coordinates, window.opacity()); + for (auto background_rect : window.rect().shatter(backing_rect)) + m_back_painter->fill_rect(background_rect, window.background_color()); } return IterationDecision::Continue; }; diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index 1f1a196ae6..a9ca19f2f9 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -1108,6 +1108,13 @@ void WSWindowManager::set_resize_candidate(WSWindow& window, ResizeDirection dir m_resize_direction = direction; } +ResizeDirection WSWindowManager::resize_direction_of_window(const WSWindow& window) +{ + if (&window != m_resize_window) + return ResizeDirection::None; + return m_resize_direction; +} + Rect WSWindowManager::maximized_window_rect(const WSWindow& window) const { Rect rect = WSScreen::the().rect(); diff --git a/Servers/WindowServer/WSWindowManager.h b/Servers/WindowServer/WSWindowManager.h index 64063a8907..3929adf7df 100644 --- a/Servers/WindowServer/WSWindowManager.h +++ b/Servers/WindowServer/WSWindowManager.h @@ -123,6 +123,7 @@ public: void set_resize_candidate(WSWindow&, ResizeDirection); void clear_resize_candidate(); + ResizeDirection resize_direction_of_window(const WSWindow&); bool any_opaque_window_contains_rect(const Rect&); bool any_opaque_window_above_this_one_contains_rect(const WSWindow&, const Rect&);