mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:47:36 +00:00
LibGUI: Improve IconView rubberband performance
Rather than invalidating the entire window, which is very expensive on the transparent desktop widget, just invalidate the areas that actually need updating.
This commit is contained in:
parent
cd0a1fa5b0
commit
6cdb657493
5 changed files with 30 additions and 6 deletions
|
@ -258,7 +258,7 @@ void IconView::mouseup_event(MouseEvent& event)
|
|||
m_rubber_banding = false;
|
||||
if (m_out_of_view_timer)
|
||||
m_out_of_view_timer->stop();
|
||||
update();
|
||||
update(to_widget_rect(Gfx::IntRect::from_two_points(m_rubber_band_origin, m_rubber_band_current)));
|
||||
}
|
||||
AbstractView::mouseup_event(event);
|
||||
}
|
||||
|
@ -268,8 +268,15 @@ bool IconView::update_rubber_banding(const Gfx::IntPoint& position)
|
|||
auto adjusted_position = to_content_position(position);
|
||||
if (m_rubber_band_current != adjusted_position) {
|
||||
auto prev_rect = Gfx::IntRect::from_two_points(m_rubber_band_origin, m_rubber_band_current);
|
||||
auto prev_rubber_band_fill_rect = prev_rect.shrunken(1, 1);
|
||||
m_rubber_band_current = adjusted_position;
|
||||
auto rubber_band_rect = Gfx::IntRect::from_two_points(m_rubber_band_origin, m_rubber_band_current);
|
||||
auto rubber_band_fill_rect = rubber_band_rect.shrunken(1, 1);
|
||||
|
||||
for (auto& rect : prev_rubber_band_fill_rect.shatter(rubber_band_fill_rect))
|
||||
update(to_widget_rect(rect.inflated(1, 1)));
|
||||
for (auto& rect : rubber_band_fill_rect.shatter(prev_rubber_band_fill_rect))
|
||||
update(to_widget_rect(rect.inflated(1, 1)));
|
||||
|
||||
// If the rectangle width or height is 0, we still want to be able
|
||||
// to match the items in the path. An easy work-around for this
|
||||
|
@ -302,11 +309,16 @@ bool IconView::update_rubber_banding(const Gfx::IntPoint& position)
|
|||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
// We're changing the selection and invalidating those items, so
|
||||
// no need to trigger a full re-render for each item
|
||||
set_suppress_update_on_selection_change(true);
|
||||
|
||||
// Now toggle all items that are no longer in the selected area, once only
|
||||
for_each_item_intersecting_rects(deselect_area, [&](ItemData& item_data) -> IterationDecision {
|
||||
if (!item_data.selection_toggled && item_data.is_intersecting(prev_rect) && !item_data.is_intersecting(rubber_band_rect)) {
|
||||
item_data.selection_toggled = true;
|
||||
toggle_selection(item_data);
|
||||
update(to_widget_rect(item_data.rect()));
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
@ -315,11 +327,13 @@ bool IconView::update_rubber_banding(const Gfx::IntPoint& position)
|
|||
if (!item_data.selection_toggled && !item_data.is_intersecting(prev_rect) && item_data.is_intersecting(rubber_band_rect)) {
|
||||
item_data.selection_toggled = true;
|
||||
toggle_selection(item_data);
|
||||
update(to_widget_rect(item_data.rect()));
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
update();
|
||||
set_suppress_update_on_selection_change(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -491,8 +505,8 @@ void IconView::paint_event(PaintEvent& event)
|
|||
painter.add_clip_rect(widget_inner_rect());
|
||||
painter.add_clip_rect(event.rect());
|
||||
|
||||
if (fill_with_background_color())
|
||||
painter.fill_rect(event.rect(), widget_background_color);
|
||||
painter.fill_rect(event.rect(), fill_with_background_color() ? widget_background_color : Color::Transparent);
|
||||
|
||||
painter.translate(frame_thickness(), frame_thickness());
|
||||
painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue