mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 13:57:35 +00:00
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.
This commit is contained in:
parent
f6543c5946
commit
30e2d62c38
4 changed files with 85 additions and 71 deletions
|
@ -719,6 +719,58 @@ void WSWindowManager::clear_resize_candidate()
|
||||||
m_resize_candidate = nullptr;
|
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()
|
void WSWindowManager::compose()
|
||||||
{
|
{
|
||||||
auto dirty_rects = move(m_dirty_rects);
|
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());
|
dbgprintf("[WM] compose #%u (%u rects)\n", ++m_compose_count, dirty_rects.rects().size());
|
||||||
#endif
|
#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 any_dirty_rect_intersects_window = [&dirty_rects] (const WSWindow& window) {
|
||||||
auto window_frame_rect = window.frame().rect();
|
auto window_frame_rect = window.frame().rect();
|
||||||
for (auto& dirty_rect : dirty_rects.rects()) {
|
for (auto& dirty_rect : dirty_rects.rects()) {
|
||||||
|
@ -794,11 +800,11 @@ void WSWindowManager::compose()
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_visible_window_from_back_to_front([&] (WSWindow& window) {
|
for_each_visible_window_from_back_to_front([&] (WSWindow& window) {
|
||||||
RetainPtr<GraphicsBitmap> backing_store = window.backing_store();
|
|
||||||
if (!any_dirty_rect_intersects_window(window))
|
if (!any_dirty_rect_intersects_window(window))
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
PainterStateSaver saver(*m_back_painter);
|
PainterStateSaver saver(*m_back_painter);
|
||||||
m_back_painter->add_clip_rect(window.frame().rect());
|
m_back_painter->add_clip_rect(window.frame().rect());
|
||||||
|
RetainPtr<GraphicsBitmap> backing_store = window.backing_store();
|
||||||
for (auto& dirty_rect : dirty_rects.rects()) {
|
for (auto& dirty_rect : dirty_rects.rects()) {
|
||||||
if (any_opaque_window_above_this_one_contains_rect(window, dirty_rect))
|
if (any_opaque_window_above_this_one_contains_rect(window, dirty_rect))
|
||||||
continue;
|
continue;
|
||||||
|
@ -813,31 +819,12 @@ void WSWindowManager::compose()
|
||||||
dirty_rect_in_window_coordinates.move_by(-window.position());
|
dirty_rect_in_window_coordinates.move_by(-window.position());
|
||||||
auto dst = window.position();
|
auto dst = window.position();
|
||||||
dst.move_by(dirty_rect_in_window_coordinates.location());
|
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, window.opacity());
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
return IterationDecision::Continue;
|
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)) {
|
draw_geometry_label();
|
||||||
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_menubar();
|
draw_menubar();
|
||||||
draw_cursor();
|
draw_cursor();
|
||||||
|
|
||||||
|
@ -937,6 +924,27 @@ void WSWindowManager::draw_window_switcher()
|
||||||
m_switcher.draw();
|
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()
|
void WSWindowManager::draw_cursor()
|
||||||
{
|
{
|
||||||
Rect cursor_rect = current_cursor_rect();
|
Rect cursor_rect = current_cursor_rect();
|
||||||
|
|
|
@ -59,6 +59,7 @@ public:
|
||||||
void draw_cursor();
|
void draw_cursor();
|
||||||
void draw_menubar();
|
void draw_menubar();
|
||||||
void draw_window_switcher();
|
void draw_window_switcher();
|
||||||
|
void draw_geometry_label();
|
||||||
|
|
||||||
Rect menubar_rect() const;
|
Rect menubar_rect() const;
|
||||||
WSMenuBar* current_menubar() { return m_current_menubar.ptr(); }
|
WSMenuBar* current_menubar() { return m_current_menubar.ptr(); }
|
||||||
|
@ -107,6 +108,9 @@ public:
|
||||||
void set_resize_candidate(WSWindow&, ResizeDirection);
|
void set_resize_candidate(WSWindow&, ResizeDirection);
|
||||||
void clear_resize_candidate();
|
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:
|
private:
|
||||||
void process_mouse_event(const WSMouseEvent&, WSWindow*& event_window);
|
void process_mouse_event(const WSMouseEvent&, WSWindow*& event_window);
|
||||||
bool process_ongoing_window_resize(const WSMouseEvent&, WSWindow*& event_window);
|
bool process_ongoing_window_resize(const WSMouseEvent&, WSWindow*& event_window);
|
||||||
|
|
|
@ -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())
|
if (source.has_alpha_channel())
|
||||||
return blit_with_alpha(position, source, src_rect);
|
return blit_with_alpha(position, source, src_rect);
|
||||||
auto safe_src_rect = Rect::intersection(src_rect, source.rect());
|
auto safe_src_rect = Rect::intersection(src_rect, source.rect());
|
||||||
|
|
|
@ -26,8 +26,7 @@ public:
|
||||||
void draw_line(const Point&, const Point&, Color);
|
void draw_line(const Point&, const Point&, Color);
|
||||||
void draw_focus_rect(const Rect&);
|
void draw_focus_rect(const Rect&);
|
||||||
void draw_scaled_bitmap(const Rect& dst_rect, const GraphicsBitmap&, const Rect& src_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(const Point&, const GraphicsBitmap&, const Rect& src_rect, float opacity = 1.0f);
|
||||||
void blit_with_opacity(const Point&, const GraphicsBitmap&, const Rect& src_rect, float opacity);
|
|
||||||
|
|
||||||
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, 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);
|
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 set_pixel_with_draw_op(dword& pixel, const Color&);
|
||||||
void fill_rect_with_draw_op(const Rect&, 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_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 {
|
struct State {
|
||||||
const Font* font;
|
const Font* font;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue