mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-10 13:00:29 +03:00
LibGUI: Fix flickering scrollbars in AbstractScrollableWidget
The new min_content_size value is to be set by the subclasses, it is then used to determine if the scrollbars should be shown after a resize, but before the content size will be calculated by the following layout pass.
This commit is contained in:
parent
6f9777d35b
commit
d0a418540e
Notes:
sideshowbarker
2024-07-18 01:43:16 +09:00
Author: https://github.com/frhun Commit: https://github.com/SerenityOS/serenity/commit/d0a418540e Pull-request: https://github.com/SerenityOS/serenity/pull/14426 Reviewed-by: https://github.com/sppmacd
@ -106,6 +106,7 @@ void AbstractScrollableWidget::custom_layout()
|
||||
void AbstractScrollableWidget::resize_event(ResizeEvent& event)
|
||||
{
|
||||
Frame::resize_event(event);
|
||||
update_scrollbar_visibility();
|
||||
update_scrollbar_ranges();
|
||||
}
|
||||
|
||||
@ -125,26 +126,22 @@ Gfx::IntSize AbstractScrollableWidget::excess_size() const
|
||||
return { excess_width, excess_height };
|
||||
}
|
||||
|
||||
void AbstractScrollableWidget::set_should_hide_unnecessary_scrollbars(bool should_hide_unnecessary_scrollbars)
|
||||
{
|
||||
if (m_should_hide_unnecessary_scrollbars == should_hide_unnecessary_scrollbars)
|
||||
return;
|
||||
|
||||
m_should_hide_unnecessary_scrollbars = should_hide_unnecessary_scrollbars;
|
||||
if (should_hide_unnecessary_scrollbars)
|
||||
update_scrollbar_ranges();
|
||||
else {
|
||||
m_horizontal_scrollbar->set_visible(true);
|
||||
m_vertical_scrollbar->set_visible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractScrollableWidget::update_scrollbar_ranges()
|
||||
{
|
||||
if (should_hide_unnecessary_scrollbars()) {
|
||||
if (excess_size().height() - height_occupied_by_horizontal_scrollbar() <= 0 && excess_size().width() - width_occupied_by_vertical_scrollbar() <= 0) {
|
||||
m_horizontal_scrollbar->set_visible(false);
|
||||
m_vertical_scrollbar->set_visible(false);
|
||||
} else {
|
||||
auto vertical_initial_visibility = m_vertical_scrollbar->is_visible();
|
||||
auto horizontal_initial_visibility = m_horizontal_scrollbar->is_visible();
|
||||
|
||||
m_vertical_scrollbar->set_visible(excess_size().height() > 0);
|
||||
m_horizontal_scrollbar->set_visible(excess_size().width() > 0);
|
||||
|
||||
if (m_vertical_scrollbar->is_visible() != vertical_initial_visibility)
|
||||
m_horizontal_scrollbar->set_visible(excess_size().width() > 0);
|
||||
if (m_horizontal_scrollbar->is_visible() != horizontal_initial_visibility)
|
||||
m_vertical_scrollbar->set_visible(excess_size().height() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
m_horizontal_scrollbar->set_range(0, excess_size().width());
|
||||
m_horizontal_scrollbar->set_page_step(visible_content_rect().width() - m_horizontal_scrollbar->step());
|
||||
|
||||
@ -152,6 +149,29 @@ void AbstractScrollableWidget::update_scrollbar_ranges()
|
||||
m_vertical_scrollbar->set_page_step(visible_content_rect().height() - m_vertical_scrollbar->step());
|
||||
}
|
||||
|
||||
void AbstractScrollableWidget::update_scrollbar_visibility()
|
||||
{
|
||||
if (should_hide_unnecessary_scrollbars()) {
|
||||
// If there has not been a min_size set, the content_size can be used as a substitute
|
||||
auto effective_min_content_size = m_min_content_size;
|
||||
if (m_min_content_size == Gfx::IntSize {})
|
||||
effective_min_content_size = m_content_size;
|
||||
int horizontal_buffer = rect().width() - 2 * frame_thickness() - effective_min_content_size.width();
|
||||
int vertical_buffer = rect().height() - 2 * frame_thickness() - effective_min_content_size.height();
|
||||
bool horizontal_scrollbar_should_be_visible = false, vertical_scrollbar_should_be_visible = false;
|
||||
vertical_scrollbar_should_be_visible = vertical_buffer < 0;
|
||||
if (vertical_scrollbar_should_be_visible)
|
||||
horizontal_buffer -= m_vertical_scrollbar->width();
|
||||
horizontal_scrollbar_should_be_visible = horizontal_buffer < 0;
|
||||
if (horizontal_scrollbar_should_be_visible)
|
||||
vertical_buffer -= m_horizontal_scrollbar->height();
|
||||
vertical_scrollbar_should_be_visible = vertical_buffer < 0;
|
||||
|
||||
m_horizontal_scrollbar->set_visible(horizontal_scrollbar_should_be_visible);
|
||||
m_vertical_scrollbar->set_visible(vertical_scrollbar_should_be_visible);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractScrollableWidget::set_content_size(Gfx::IntSize const& size)
|
||||
{
|
||||
if (m_content_size == size)
|
||||
@ -160,6 +180,14 @@ void AbstractScrollableWidget::set_content_size(Gfx::IntSize const& size)
|
||||
update_scrollbar_ranges();
|
||||
}
|
||||
|
||||
void AbstractScrollableWidget::set_min_content_size(Gfx::IntSize const& min_size)
|
||||
{
|
||||
if (m_min_content_size == min_size)
|
||||
return;
|
||||
m_min_content_size = min_size;
|
||||
update_scrollbar_ranges();
|
||||
}
|
||||
|
||||
void AbstractScrollableWidget::set_size_occupied_by_fixed_elements(Gfx::IntSize const& size)
|
||||
{
|
||||
if (m_size_occupied_by_fixed_elements == size)
|
||||
|
@ -21,6 +21,7 @@ public:
|
||||
Gfx::IntSize content_size() const { return m_content_size; }
|
||||
int content_width() const { return m_content_size.width(); }
|
||||
int content_height() const { return m_content_size.height(); }
|
||||
Gfx::IntSize min_content_size() const { return m_min_content_size; }
|
||||
|
||||
Gfx::IntRect visible_content_rect() const;
|
||||
|
||||
@ -60,7 +61,7 @@ public:
|
||||
|
||||
virtual Margins content_margins() const override;
|
||||
|
||||
void set_should_hide_unnecessary_scrollbars(bool b) { m_should_hide_unnecessary_scrollbars = b; }
|
||||
void set_should_hide_unnecessary_scrollbars(bool);
|
||||
bool should_hide_unnecessary_scrollbars() const { return m_should_hide_unnecessary_scrollbars; }
|
||||
|
||||
Gfx::IntPoint to_content_position(Gfx::IntPoint const& widget_position) const;
|
||||
@ -76,9 +77,12 @@ protected:
|
||||
virtual void mousewheel_event(MouseEvent&) override;
|
||||
virtual void did_scroll() { }
|
||||
void set_content_size(Gfx::IntSize const&);
|
||||
void set_min_content_size(Gfx::IntSize const&);
|
||||
void set_size_occupied_by_fixed_elements(Gfx::IntSize const&);
|
||||
virtual void on_automatic_scrolling_timer_fired() {};
|
||||
int autoscroll_threshold() const { return m_autoscroll_threshold; }
|
||||
void update_scrollbar_visibility();
|
||||
void update_scrollbar_ranges();
|
||||
|
||||
private:
|
||||
class AbstractScrollableWidgetScrollbar final : public Scrollbar {
|
||||
@ -100,13 +104,13 @@ private:
|
||||
};
|
||||
friend class ScrollableWidgetScrollbar;
|
||||
|
||||
void update_scrollbar_ranges();
|
||||
void handle_wheel_event(MouseEvent&, Widget&);
|
||||
|
||||
RefPtr<AbstractScrollableWidgetScrollbar> m_vertical_scrollbar;
|
||||
RefPtr<AbstractScrollableWidgetScrollbar> m_horizontal_scrollbar;
|
||||
RefPtr<Widget> m_corner_widget;
|
||||
Gfx::IntSize m_content_size;
|
||||
Gfx::IntSize m_min_content_size;
|
||||
Gfx::IntSize m_size_occupied_by_fixed_elements;
|
||||
bool m_scrollbars_enabled { true };
|
||||
bool m_should_hide_unnecessary_scrollbars { false };
|
||||
|
Loading…
Reference in New Issue
Block a user