Skip to content

Commit

Permalink
WindowServer: Factor out some parts of compose().
Browse files Browse the repository at this point in the history
The main compositing loop was getting pretty unwieldy. Break out some parts
into functions so it's more understandable.
  • Loading branch information
awesomekling committed Apr 10, 2019
1 parent f6543c5 commit 30e2d62
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 71 deletions.
144 changes: 76 additions & 68 deletions Servers/WindowServer/WSWindowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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()) {
Expand All @@ -794,11 +800,11 @@ void WSWindowManager::compose()
}

for_each_visible_window_from_back_to_front([&] (WSWindow& window) {
RetainPtr<GraphicsBitmap> 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<GraphicsBitmap> 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;
Expand All @@ -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();

Expand Down Expand Up @@ -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();
Expand Down
4 changes: 4 additions & 0 deletions Servers/WindowServer/WSWindowManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class WSWindowManager : public WSMessageReceiver {
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(); }
Expand Down Expand Up @@ -107,6 +108,9 @@ class WSWindowManager : public WSMessageReceiver {
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);
Expand Down
4 changes: 3 additions & 1 deletion SharedGraphics/Painter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
4 changes: 2 additions & 2 deletions SharedGraphics/Painter.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ class Painter {
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);
Expand Down Expand Up @@ -61,6 +60,7 @@ class Painter {
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;
Expand Down

0 comments on commit 30e2d62

Please sign in to comment.