diff options
author | Tom <tomut@yahoo.com> | 2021-02-07 17:44:04 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-02-08 19:02:04 +0100 |
commit | 8ff34f96b6456787e449a2bf8d89104dc9233c9a (patch) | |
tree | be67dbc0c5b361b6ec3092c55eb7571c04aae10b /Userland/Services | |
parent | f1b5def8fd48cf09704a6d4151f9002b80354430 (diff) | |
download | serenity-8ff34f96b6456787e449a2bf8d89104dc9233c9a.zip |
WindowServer: Calculate transparent frame occlusions
If a window frame has transparency, include these areas in the
transparency rendering area so that we can render them flicker-free.
Diffstat (limited to 'Userland/Services')
-rw-r--r-- | Userland/Services/WindowServer/Compositor.cpp | 74 | ||||
-rw-r--r-- | Userland/Services/WindowServer/WindowFrame.h | 12 |
2 files changed, 67 insertions, 19 deletions
diff --git a/Userland/Services/WindowServer/Compositor.cpp b/Userland/Services/WindowServer/Compositor.cpp index 9231136442..b0353a496a 100644 --- a/Userland/Services/WindowServer/Compositor.cpp +++ b/Userland/Services/WindowServer/Compositor.cpp @@ -920,11 +920,23 @@ void Compositor::recompute_occlusions() Gfx::DisjointRectSet opaque_covering; if (w.is_opaque()) { - visible_opaque = visible_rects.intersected(window_frame_rect); transparency_rects.clear(); + if (w.frame().is_opaque()) { + visible_opaque = visible_rects.intersected(window_frame_rect); + } else { + auto window_rect = w.rect().intersected(screen_rect); + visible_opaque = visible_rects.intersected(window_rect); + transparency_rects.add_many(window_frame_rect.shatter(window_rect)); + } } else { visible_opaque.clear(); - transparency_rects = visible_rects.intersected(window_frame_rect); + if (w.frame().is_opaque()) { + auto window_rect = w.rect().intersected(screen_rect); + visible_opaque.add_many(window_frame_rect.shatter(window_rect)); + transparency_rects = visible_rects.intersected(window_rect); + } else { + transparency_rects = visible_rects.intersected(window_frame_rect); + } } bool found_this_window = false; @@ -942,26 +954,20 @@ void Compositor::recompute_occlusions() if (covering_rect.is_empty()) return IterationDecision::Continue; - if (w2.is_opaque()) { - opaque_covering.add(covering_rect); - if (opaque_covering.contains(window_frame_rect)) { - // This window is entirely covered by another opaque window - visible_opaque.clear(); - transparency_rects.clear(); - return IterationDecision::Break; - } - + auto add_opaque = [&](const Gfx::IntRect& covering) { + opaque_covering.add(covering); if (!visible_opaque.is_empty()) { - auto uncovered_opaque = visible_opaque.shatter(covering_rect); + auto uncovered_opaque = visible_opaque.shatter(covering); visible_opaque = move(uncovered_opaque); } if (!transparency_rects.is_empty()) { - auto uncovered_transparency = transparency_rects.shatter(covering_rect); + auto uncovered_transparency = transparency_rects.shatter(covering); transparency_rects = move(uncovered_transparency); } - } else { - visible_rects.for_each_intersected(covering_rect, [&](const Gfx::IntRect& intersected) { + }; + auto add_transparent = [&](const Gfx::IntRect& covering) { + visible_rects.for_each_intersected(covering, [&](const Gfx::IntRect& intersected) { transparency_rects.add(intersected); if (!visible_opaque.is_empty()) { auto uncovered_opaque = visible_opaque.shatter(intersected); @@ -969,6 +975,31 @@ void Compositor::recompute_occlusions() } return IterationDecision::Continue; }); + }; + if (w2.is_opaque()) { + if (w2.frame().is_opaque()) { + if (opaque_covering.contains(covering_rect)) { + // This window (including frame) is entirely covered by another opaque window + visible_opaque.clear(); + transparency_rects.clear(); + return IterationDecision::Break; + } + add_opaque(covering_rect); + } else { + auto covering_window_rect = covering_rect.intersected(w2.rect()); + add_opaque(covering_window_rect); + for (auto& covering_frame_rect : covering_rect.shatter(covering_window_rect)) + add_transparent(covering_frame_rect); + } + } else { + if (w2.frame().is_opaque()) { + auto covering_window_rect = covering_rect.intersected(w2.rect()); + add_transparent(covering_window_rect); + for (auto& covering_frame_rect : covering_rect.shatter(covering_window_rect)) + add_opaque(covering_frame_rect); + } else { + add_transparent(covering_rect); + } } return IterationDecision::Continue; @@ -979,10 +1010,15 @@ void Compositor::recompute_occlusions() ASSERT(!visible_opaque.intersects(transparency_rects)); + // Determine visible area for the window below if (w.is_opaque()) { - // Determine visible area for the window below - auto visible_rects_below_window = visible_rects.shatter(window_frame_rect); - visible_rects = move(visible_rects_below_window); + if (w.frame().is_opaque()) { + auto visible_rects_below_window = visible_rects.shatter(window_frame_rect); + visible_rects = move(visible_rects_below_window); + } else { + auto visible_rects_below_window = visible_rects.shatter(w.rect().intersected(screen_rect)); + visible_rects = move(visible_rects_below_window); + } } return IterationDecision::Continue; }); @@ -991,7 +1027,7 @@ void Compositor::recompute_occlusions() // Determine what transparent window areas need to render the wallpaper first WindowManager::the().for_each_visible_window_from_back_to_front([&](Window& w) { auto& transparency_wallpaper_rects = w.transparency_wallpaper_rects(); - if (w.is_opaque() || w.is_minimized()) { + if ((w.is_opaque() && w.frame().is_opaque()) || w.is_minimized()) { transparency_wallpaper_rects.clear(); return IterationDecision::Continue; } diff --git a/Userland/Services/WindowServer/WindowFrame.h b/Userland/Services/WindowServer/WindowFrame.h index ace32b8c7c..26d2f6621d 100644 --- a/Userland/Services/WindowServer/WindowFrame.h +++ b/Userland/Services/WindowServer/WindowFrame.h @@ -62,6 +62,17 @@ public: void start_flash_animation(); + float opacity() const { return m_opacity; } + + bool is_opaque() const + { + if (opacity() < 1.0f) + return false; + //if (has_alpha_channel()) + // return false; + return true; + } + private: void paint_notification_frame(Gfx::Painter&); void paint_normal_frame(Gfx::Painter&); @@ -76,6 +87,7 @@ private: RefPtr<Core::Timer> m_flash_timer; size_t m_flash_counter { 0 }; + float m_opacity { 1 }; }; } |