Needed to adjust this again after applying commit 4e5ecb7
for bug 742281. Now that we also have max content size properties,
pushed the addition of possible scrollbar sizes to after the
clause which clamps the child request size into min/max content
sizes.
This patch causes the scrolled window default behavior to change in
such a way that the natural size request of the child is unconditionally
reported, which probably should have been the case since day 1.
This should not cause significant fallout since a scrolled window is
normally used to expand/fill, eating up remaining space for scrollable
content - it will however cause the scrolled window to compete for
additional space with siblings, proportionally to the size of the
scrolled window's content.
The GtkScrolledWindow has support to set the minimum content size (both
width and height) which controls the minimum space allocated, but does
not exposes any way to control the maximum size the content can grow.
After the introduction of GtkPopover, which always uses the minimum
size of it's children widgets, the lack of max-content-width and -height
properties became a concrete use case.
This patch introduces the GtkScrolledWindow::max-content-width and
-height properties. The properties will alter the minimum size of
the scrolled window, making it grow up to the set value. They also
respect the previously set ::min-content-width and -height.
https://bugzilla.gnome.org/show_bug.cgi?id=742281
GtkScrolledWindow leans towards using the minimum size of its child
widget, unless the scrollbar policy is GTK_POLICY_NEVER. This is
probably fine for most GtkScrollable implementations out there.
Especially when using GTK_SCROLL_MINIMUM, which is the default for all
implementations inside gtk+.
However, this is not good for GTK_SCROLL_NATURAL children. eg.,
VteTerminal's minimum size is 1x1 and natural size is the number of
visible rows and columns requested by the user. We really want to use
the natural size unless the user has resized the window to change that.
https://bugzilla.gnome.org/show_bug.cgi?id=766569
This code tries to add the minimum content size, if one is set, to the
GtkScrolledWindow's size requisition. This is obvious from the check
for non-negative values of min-content-height and min-content-width.
Using MAX needlessly makes the code harder to read by implying that
there is more to it when there actually isn't.
Fall out from 0d9ebb501dhttps://bugzilla.gnome.org/show_bug.cgi?id=766569
When we are beginning to calculate the height, if the vscrollbar_policy
is not GTK_POLICY_NEVER, and there is no min-content-height, then we
need some small non-zero value to get started. The idea is to always
ask for at least enough to fit the horizontal scrollbar.
Simply put, this should be the mirror image of the corresponding width
calculation code.
Those who got used to the buggy behaviour might notice that their
GtkScrolledWindows are not as tall as they used to be.
Fall out from 55196a705fhttps://bugzilla.gnome.org/show_bug.cgi?id=766530
Children tend to call back into the scrolled window while being removed
and that doesn't work too well if the scrolled window is destroyed
already as Christian Hergert found out.
The implicit grab may be finished so the pointer lies on top of the other
scrollbar, in this case one scrollbar should lose the hovering state, and
the other should gain it. So we must check for proximity in both indicators.
We were not taking the scrollable borders into account when
requesting size for the scrolled window, which could lead
to underallocating the scrollbars at size allocation time
when we *did* take the borders into account.
This is most notable with treeviews, where we have the
headers as borders, and was causing the treeview-crash-too-wide
reftest to fail.
And use it to handle kinetic scrolling in the GtkScrolledWindow.
However, dropping the delta check causes the X11-based kinetic
scroll to break since we don't have the stop event here. Correct handling of
xf86-input-libinput-based scroll events is still being discussed.
https://bugzilla.gnome.org/show_bug.cgi?id=756729
Otherwise it's attempted through a timeout, which gets cancelled early after,
and the slider disappears after a while with no mouse activity despite the
ongoing implicit grab.
Once the grab is finished, check_update_scrollbar_proximity() will be called
again on both scrollbars, and the fade out animation will be triggered as a
result.
https://bugzilla.gnome.org/show_bug.cgi?id=754745
These days exposure happens only on the native windows (generally the
toplevel window) and is propagated down recursively. The expose event
is only useful for backwards compat, and in fact, for double buffered
widgets we totally ignore the event (and non-double buffering breaks
on wayland).
So, by not setting the mask we avoid emitting these events and then
later ignoring them.
We still keep it on eventbox, fixed and layout as these are used
in weird ways that want backwards compat.
In order to play along with child widgets that use scroll events for anything
else than scrolling, it will be better to do this in the bubble phase, so
the child widget has an opportunity to GDK_EVENT_STOP the event before we
trigger kinetic scrolling.
This of course won't work for widgets that choose to reimplement scroll event
handling themselves, they should be smart at resorting to GtkScrolledWindow's
scroll event handling.
This fixes kinetic scrolling kicking in too pervasively on widgets that eg.
implement zoom on scroll events.
https://bugzilla.gnome.org/show_bug.cgi?id=753495
The libinput driver will send a 0/0 scroll event on touchpads and other
devices where it knows scrolling stopped for sure. Use these events to
trigger kinetic scrolling from there.
The mechanism is similar to GtkGestureSwipe, we keep a backlog of the
latest dx/dy till a previous point in time, and calculate the final
velocities from there, with the difference we're dealing with scroll
units, and not pixel distances.
https://bugzilla.gnome.org/show_bug.cgi?id=749770
If a GtkScrolledWindow is just unmapped and promptly mapped again, the
indicators are left in a semi-visible state, so the GdkWindow isn't raised
properly above scrolledwindow content. This inconsistent state went away
the next time the indicator is hidden.
So, reset all state about indicator window visibility, animation
progress and conceil timer on ::unmap, this will be enough to make the
indicators start out hidden like on newly created scrolledwindows.
Libinput will use 0.0f on the "scrolling finished" event, so check for this
instead of rounding (<1 values are sort of frequent on touchpads). This
impedes bug #745315 to resurface after commit d563b943ed.
When the scrolledwindow receives scroll events, it ensures the timeout to
maybe start the "snap back to edges" animation is reset, but it does nothing
about the animation source. It must be reset just the same, to maybe be
started after the timeout fires up.
The code managing scrollbars visibility was too pervasively checking for
mouse devices, leaving pen/eraser/cursor devices with no scrollbars at
all. Relax these checks a bit, and actually toggle full-width scrollbars
on pen/eraser devices, so it is an easier target.
https://bugzilla.gnome.org/show_bug.cgi?id=747608
The coordinate translations here were not working properly
for window widgets inside the scrolled window, as can be
seen e.g. for the horizontal scrollbar of the 'Tree View'
example in gtk3-demo.
https://bugzilla.gnome.org/show_bug.cgi?id=747406
When moving over a non-expanded indicator from the outside, we were
not expanding it, due to on_scrollbar being true. This can be seen
e.g. when moving from the content pane over to the sidebar indicator
in gtk3-demo. We must still ensure that the indicator is expanded
when receiving motion events over the indicator.
https://bugzilla.gnome.org/show_bug.cgi?id=747407
This path is only intended to be triggered on events directed towards the
child of the scrolledwindow, so make it explicitly so. This avoids scrollbar
"over" state flashing when dragging finishes within the slider.
https://bugzilla.gnome.org/show_bug.cgi?id=746961
It has been a long-standing request to interpret scroll events
with Shift held down as horizontal instead of vertical, and
some applications are already doing this on their own.
https://bugzilla.gnome.org/show_bug.cgi?id=132197
When the scrollbars are overlayed, the size requisition of the
scrolled window should not depend on whether the scrollbars are
visible or not. This was not quite the case, because we forgot
one case where scrollbar size was still added to the requisition.
This is not specified specifically by the attached controllers, so let
the scrolledwindow set the mask, as motion events with no buttons pressed
are interesting to it.
https://bugzilla.gnome.org/show_bug.cgi?id=745344
If a scrollbar is not shown (because of policies, or because it isn't
necessary), it doesn't make sense to start fade animations on its window
on captured motion events.
gtk_scrolled_window_allocate_scrollbar was calling
gtk_scrolled_window_allocate_child just to get the relative
allocation, overlooking the fact that that function is only
safe to call if the scrolled window _has_ a child. Unfortunately,
gtk_scrolled_window_allocate_scrollbar will sometimes get called
when that is not the case. Since we are really only interested
in the relative allocation, just get that directly. This
fixes a segfault in the style-properties-nth-child reftest.
At the time of creating the indicator window, the scrollbar allocation is
poked and reused as the initial window dimensions. This usually happens
on two circumstances, either initially (so a ::size-allocate is emitted,
relocating the windows in the right places), or post-initialization when
calling set_overlay_scrolling() (so the scrollbars already have a valid
size allocation)
However, if the scrolledwindow is unrealized, and later re-realized again,
the scrollbars will already have a valid allocation, although 0,0 based
due to being contained in the previous indicator window. This comes out
wrong then, and the indicator window is given 0,0 based coordinates too.
Fix this by refactoring the scrollbar allocation code out of size_allocate,
and also use that given size at the time of creating the indicator windows,
this will provide the right widget-relative allocation anytime.
This avoids showing the scrollbars if we are positive the child widget
is being manipulated, regardless of the pointer being close to any of these.
On the next motion event after finishing the operation, the scrollbar will
be shown if necessary.
https://bugzilla.gnome.org/show_bug.cgi?id=743894
In that case the scrolledwindow still gets events through the captured
handler, and can thus still control visibility, so hiding the indicators
in this case can only lead to flashing.
This will be used to just detect when an edge of the scrollable area is
reached - as opposed to the edge-overshot signal that is emitted when
the user scrolls past the edge.
https://bugzilla.gnome.org/show_bug.cgi?id=742848
This was left unmodified when GtkScrolledWindow was made a windowed widget.
Displacing here by the widget allocation is not necessary anymore, since
we are invalidating the window set at these coordinates.
This patch is a simplification of a previous one by Timm Bäder.
https://bugzilla.gnome.org/show_bug.cgi?id=742243
When we get a leave event, we need to remove the over bit,
since we may not get motion events that tell us when we lose
proximity, but we don't have to fade out right away - that
will happen on its on due to inactivity a bit later. Having
the indicator stay visible for a bit feels more relaxed.
This is so we can detect crossing events on the scrolledwindow widget,
which can be useful for toggling certain behaviors or not depending on
whether the mouse is on the widget.
Use the new scrollable API for getting non-scrollable borders
and draw over/undershoot at the right place. In practice, this
means that they now appear below treeview headers.
When overshooting through touchpad kinetic scrolling, the scrollbar remains
mostly static as it already hit a boundary. However, the fade in/out checks
are constantly run during scroll events, causing needless redraws in this
specific case.
The scrollbars are still internal children of the GtkScrolledWindow
and handled in ::forall(), no need to propagate draw here again
after chaining up in ::draw().
This commit adds a mode to GtkScrolledWindow in which it puts
narrow, auto-hiding scrollbars over the content, instead of
allocating room for the scrollbars outside of the content. We
use traditional scrollbars if we find a mouse or if overlay
scrolling has explicitly turned off.
For test purposes, GTK_TEST_TOUCHSCREEN can be used to get
overlay scrolling even in the presence of a mouse. The
environment variable GTK_OVERLAY_SCROLLING can also be used
to force overlay scrolling on or off.
This signal is emitted whenever user scrolling hits the overshoot
edge in the given direction. May be useful to add "reload" or "load
more" behaviors in apps.
https://bugzilla.gnome.org/show_bug.cgi?id=738534
Instead of making assumptions about enum value ordering,
introduce a helper function to determine policy values
for which the scrollbar may be visible.
Add a new policy, GTK_POLICY_EXTERNAL, which hides the scrollbar,
but does not force the scrolled windows size to be determined by
its child. This can be used to keep two scrolled windows in sync,
while sharing a single scrollbar.
https://bugzilla.gnome.org/show_bug.cgi?id=730730