From 30e2d62c38b30e7023269b5334c7dd101610ca7f Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 10 Apr 2019 13:51:47 +0200 Subject: [PATCH] WindowServer: Factor out some parts of compose(). The main compositing loop was getting pretty unwieldy. Break out some parts into functions so it's more understandable. --- Servers/WindowServer/WSWindowManager.cpp | 144 ++++++++++++----------- Servers/WindowServer/WSWindowManager.h | 4 + SharedGraphics/Painter.cpp | 4 +- SharedGraphics/Painter.h | 4 +- 4 files changed, 85 insertions(+), 71 deletions(-) diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index 2d5ad83db9..145f28bdda 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -719,6 +719,58 @@ void WSWindowManager::clear_resize_candidate() m_resize_candidate = nullptr; } +bool WSWindowManager::any_opaque_window_contains_rect(const Rect& rect) +{ + bool found_containing_window = false; + for_each_window([&] (WSWindow& window) { + if (!window.is_visible()) + return IterationDecision::Continue; + if (window.is_minimized()) + return IterationDecision::Continue; + if (window.opacity() < 1.0f) + return IterationDecision::Continue; + if (window.has_alpha_channel()) { + // FIXME: Just because the window has an alpha channel doesn't mean it's not opaque. + // Maybe there's some way we could know this? + return IterationDecision::Continue; + } + if (window.frame().rect().contains(rect)) { + found_containing_window = true; + return IterationDecision::Abort; + } + return IterationDecision::Continue; + }); + return found_containing_window; +}; + +bool WSWindowManager::any_opaque_window_above_this_one_contains_rect(const WSWindow& a_window, const Rect& rect) +{ + bool found_containing_window = false; + bool checking = false; + for_each_visible_window_from_back_to_front([&] (WSWindow& window) { + if (&window == &a_window) { + checking = true; + return IterationDecision::Continue; + } + if (!checking) + return IterationDecision::Continue; + if (!window.is_visible()) + return IterationDecision::Continue; + if (window.is_minimized()) + return IterationDecision::Continue; + if (window.opacity() < 1.0f) + return IterationDecision::Continue; + if (window.has_alpha_channel()) + return IterationDecision::Continue; + if (window.frame().rect().contains(rect)) { + found_containing_window = true; + return IterationDecision::Abort; + } + return IterationDecision::Continue; + }); + return found_containing_window; +}; + void WSWindowManager::compose() { auto dirty_rects = move(m_dirty_rects); @@ -729,52 +781,6 @@ void WSWindowManager::compose() dbgprintf("[WM] compose #%u (%u rects)\n", ++m_compose_count, dirty_rects.rects().size()); #endif - auto any_opaque_window_contains_rect = [this] (const Rect& r) { - for (auto* window = m_windows_in_order.head(); window; window = window->next()) { - if (!window->is_visible()) - continue; - if (window->is_minimized()) - continue; - if (window->opacity() < 1.0f) - continue; - if (window->has_alpha_channel()) { - // FIXME: Just because the window has an alpha channel doesn't mean it's not opaque. - // Maybe there's some way we could know this? - continue; - } - if (window->frame().rect().contains(r)) - return true; - } - return false; - }; - - auto any_opaque_window_above_this_one_contains_rect = [this] (const WSWindow& a_window, const Rect& rect) -> bool { - bool found = false; - bool checking = false; - for_each_visible_window_from_back_to_front([&] (WSWindow& window) { - if (&window == &a_window) { - checking = true; - return IterationDecision::Continue; - } - if (!checking) - return IterationDecision::Continue; - if (!window.is_visible()) - return IterationDecision::Continue; - if (window.is_minimized()) - return IterationDecision::Continue; - if (window.opacity() < 1.0f) - return IterationDecision::Continue; - if (window.has_alpha_channel()) - return IterationDecision::Continue; - if (window.frame().rect().contains(rect)) { - found = true; - return IterationDecision::Abort; - } - return IterationDecision::Continue; - }); - return found; - }; - auto any_dirty_rect_intersects_window = [&dirty_rects] (const WSWindow& window) { auto window_frame_rect = window.frame().rect(); for (auto& dirty_rect : dirty_rects.rects()) { @@ -794,11 +800,11 @@ void WSWindowManager::compose() } for_each_visible_window_from_back_to_front([&] (WSWindow& window) { - RetainPtr backing_store = window.backing_store(); if (!any_dirty_rect_intersects_window(window)) return IterationDecision::Continue; PainterStateSaver saver(*m_back_painter); m_back_painter->add_clip_rect(window.frame().rect()); + RetainPtr backing_store = window.backing_store(); for (auto& dirty_rect : dirty_rects.rects()) { if (any_opaque_window_above_this_one_contains_rect(window, dirty_rect)) continue; @@ -813,31 +819,12 @@ void WSWindowManager::compose() dirty_rect_in_window_coordinates.move_by(-window.position()); auto dst = window.position(); dst.move_by(dirty_rect_in_window_coordinates.location()); - if (window.opacity() == 1.0f) - m_back_painter->blit(dst, *backing_store, dirty_rect_in_window_coordinates); - else - m_back_painter->blit_with_opacity(dst, *backing_store, dirty_rect_in_window_coordinates, window.opacity()); + m_back_painter->blit(dst, *backing_store, dirty_rect_in_window_coordinates, window.opacity()); } return IterationDecision::Continue; }); - if (auto* window_being_moved_or_resized = m_drag_window ? m_drag_window.ptr() : (m_resize_window ? m_resize_window.ptr() : nullptr)) { - auto geometry_string = window_being_moved_or_resized->rect().to_string(); - if (!window_being_moved_or_resized->size_increment().is_null()) { - int width_steps = (window_being_moved_or_resized->width() - window_being_moved_or_resized->base_size().width()) / window_being_moved_or_resized->size_increment().width(); - int height_steps = (window_being_moved_or_resized->height() - window_being_moved_or_resized->base_size().height()) / window_being_moved_or_resized->size_increment().height(); - geometry_string = String::format("%s (%dx%d)", geometry_string.characters(), width_steps, height_steps); - } - auto geometry_label_rect = Rect { 0, 0, font().width(geometry_string) + 16, font().glyph_height() + 10 }; - geometry_label_rect.center_within(window_being_moved_or_resized->rect()); - m_back_painter->fill_rect(geometry_label_rect, Color::LightGray); - m_back_painter->draw_rect(geometry_label_rect, Color::DarkGray); - m_back_painter->draw_text(geometry_label_rect, geometry_string, TextAlignment::Center); - m_last_geometry_label_rect = geometry_label_rect; - } else { - m_last_geometry_label_rect = { }; - } - + draw_geometry_label(); draw_menubar(); draw_cursor(); @@ -937,6 +924,27 @@ void WSWindowManager::draw_window_switcher() m_switcher.draw(); } +void WSWindowManager::draw_geometry_label() +{ + auto* window_being_moved_or_resized = m_drag_window ? m_drag_window.ptr() : (m_resize_window ? m_resize_window.ptr() : nullptr); + if (!window_being_moved_or_resized) { + m_last_geometry_label_rect = { }; + return; + } + auto geometry_string = window_being_moved_or_resized->rect().to_string(); + if (!window_being_moved_or_resized->size_increment().is_null()) { + int width_steps = (window_being_moved_or_resized->width() - window_being_moved_or_resized->base_size().width()) / window_being_moved_or_resized->size_increment().width(); + int height_steps = (window_being_moved_or_resized->height() - window_being_moved_or_resized->base_size().height()) / window_being_moved_or_resized->size_increment().height(); + geometry_string = String::format("%s (%dx%d)", geometry_string.characters(), width_steps, height_steps); + } + auto geometry_label_rect = Rect { 0, 0, font().width(geometry_string) + 16, font().glyph_height() + 10 }; + geometry_label_rect.center_within(window_being_moved_or_resized->rect()); + m_back_painter->fill_rect(geometry_label_rect, Color::LightGray); + m_back_painter->draw_rect(geometry_label_rect, Color::DarkGray); + m_back_painter->draw_text(geometry_label_rect, geometry_string, TextAlignment::Center); + m_last_geometry_label_rect = geometry_label_rect; +} + void WSWindowManager::draw_cursor() { Rect cursor_rect = current_cursor_rect(); diff --git a/Servers/WindowServer/WSWindowManager.h b/Servers/WindowServer/WSWindowManager.h index ef246537f4..1e9530ff8c 100644 --- a/Servers/WindowServer/WSWindowManager.h +++ b/Servers/WindowServer/WSWindowManager.h @@ -59,6 +59,7 @@ public: void draw_cursor(); void draw_menubar(); void draw_window_switcher(); + void draw_geometry_label(); Rect menubar_rect() const; WSMenuBar* current_menubar() { return m_current_menubar.ptr(); } @@ -107,6 +108,9 @@ public: void set_resize_candidate(WSWindow&, ResizeDirection); void clear_resize_candidate(); + bool any_opaque_window_contains_rect(const Rect&); + bool any_opaque_window_above_this_one_contains_rect(const WSWindow&, const Rect&); + private: void process_mouse_event(const WSMouseEvent&, WSWindow*& event_window); bool process_ongoing_window_resize(const WSMouseEvent&, WSWindow*& event_window); diff --git a/SharedGraphics/Painter.cpp b/SharedGraphics/Painter.cpp index 8e51736c45..69573a6910 100644 --- a/SharedGraphics/Painter.cpp +++ b/SharedGraphics/Painter.cpp @@ -271,8 +271,10 @@ void Painter::blit_with_alpha(const Point& position, const GraphicsBitmap& sourc } } -void Painter::blit(const Point& position, const GraphicsBitmap& source, const Rect& src_rect) +void Painter::blit(const Point& position, const GraphicsBitmap& source, const Rect& src_rect, float opacity) { + if (opacity < 1.0f) + return blit_with_opacity(position, source, src_rect, opacity); if (source.has_alpha_channel()) return blit_with_alpha(position, source, src_rect); auto safe_src_rect = Rect::intersection(src_rect, source.rect()); diff --git a/SharedGraphics/Painter.h b/SharedGraphics/Painter.h index 07ab4283b9..4515e02b7f 100644 --- a/SharedGraphics/Painter.h +++ b/SharedGraphics/Painter.h @@ -26,8 +26,7 @@ public: void draw_line(const Point&, const Point&, Color); void draw_focus_rect(const Rect&); void draw_scaled_bitmap(const Rect& dst_rect, const GraphicsBitmap&, const Rect& src_rect); - void blit(const Point&, const GraphicsBitmap&, const Rect& src_rect); - void blit_with_opacity(const Point&, const GraphicsBitmap&, const Rect& src_rect, float opacity); + void blit(const Point&, const GraphicsBitmap&, const Rect& src_rect, float opacity = 1.0f); void draw_text(const Rect&, const char* text, int length, const Font&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None); void draw_text(const Rect&, const char* text, int length, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None); @@ -61,6 +60,7 @@ protected: void set_pixel_with_draw_op(dword& pixel, const Color&); void fill_rect_with_draw_op(const Rect&, Color); void blit_with_alpha(const Point&, const GraphicsBitmap&, const Rect& src_rect); + void blit_with_opacity(const Point&, const GraphicsBitmap&, const Rect& src_rect, float opacity); struct State { const Font* font;