-
Notifications
You must be signed in to change notification settings - Fork 599
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Implement overflow layout #3309
base: master
Are you sure you want to change the base?
Conversation
Codecov Report
@@ Coverage Diff @@
## master #3309 +/- ##
==========================================
+ Coverage 90.66% 90.99% +0.32%
==========================================
Files 852 904 +52
Lines 54440 57502 +3062
==========================================
+ Hits 49358 52323 +2965
- Misses 5082 5179 +97
Flags with carried forward coverage won't be shown. Click here to find out more.
|
d0fabc1
to
89a4e32
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is a first review. I'll do a second pass later...
I have adopted the "nit" notation for "not important changes" (aka dismissable comments) ;)
Here are some oter notes:
I think the position
property name is misleading. It can lead to confusion with the scrollbar_position
property and is not very descriptive to its usage. Maybe something like "scroll_factor" can be better?
I can see you have added inherited documentation from fixed layout. Can you add the ldoc @baseclass wibox.widget.fixed
tag to these blocks waiting for my other PR to be merged? So that, the doc for this module is fully operational by itself. We can do a patch later to add the @supermodule
tag and remove duplicated doc.
BTW, I can't see some methods like fixed:add
and fixed:remove
. I think we are supposed to have access to these methods as well.
Also, in regard to the "use gears magic", I suggest removing the documentation for your getters and setters.
Unless you want to wait my other PR to use @hidden
here...
Examples tests/examples/wibox/layout/overflow/scrollbar_width.lua
and tests/examples/wibox/layout/overflow/scrollbar_widget.lua
don't show scrollbar at all. I have fixed it by adding a fourth widget.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic contribution. Many people, me included, have used many hacky tricks to get this kind of feature. At first I feared it one one of those sub-surface type container, but no, it is implemented very nicely! I really like that it's using a custom widget for the scrollbar. At first I was thinking the slider widget code might have been re-used/shared, but looking into it closer, what you did it better.
One bug I think this has, but I have not tested, is when using this within a mirror or rotate container. This is why the geo.hierarchy:get_matrix_from_device
and matrix:transform_point(mouse.x, mouse.y))
lines from the slider widget are important. There is some legitimate use case for mixing those containers with the overflow one. The main one if people using it to rotate their entire wibox 90 degree and having something like the taskbar in an overflow container. It's one of those annoying corner case, but I would like it to be fixed. It ain't that hard to fix.
|
||
-- Save size for scrolling behavior | ||
self._private.avail_in_dir = avail_in_dir | ||
self._private.used_in_dir = used_in_dir |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the overflow container is shown in more than one place with different sizes? Assigning size-information to "something in self
" sounds like either a bug or a bug-waiting-to-happen to me.
This problem is why the scroll container does all that funky business with weak tables.
(Being able to show a widget in more than one place is great for users, but it brings so many complications...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be a showstopper then. Knowing the exact geometry is pretty much required for (useful) scrolling to work.
I did check out the scroll
container, but can't claim to understand its funky business yet. And even if I did, combining funky business with user input sounds like a "bug-waiting-to-happen" as well.
It would probably require changes to the core of the widget system so that when something attempts to re-use an existing instance, that widget may request to be cloned instead (maybe with custom logic attached to the clone function).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could it be imposed some limitation against multiple instances? (so it will throw a warning and won't attempt to draw more than one instance)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would certainly be an option and I would be fine with imposing such a limitation.
But this would certainly be the first widget to do so, although looking at the rework of wibox.widget.graph
it's not the only one that would benefit from adding widgets with this kind of limitation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
arent wibox/wibar/popup also could have only one instance of a given geometry?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That container works via the context argument that is passed in to widgets. When context.screen
is the expected screen, it works normally. Otherwise, :fit
returns 0, 0
and :layout
does nothing. Anyway, you can still show a widget multiple times on a given screen.
(And I guess this widget does not work correctly when used in a titlebar and you move the client to another screen. Or when used in a wibox and that wibox is moved to another screen. Nothing invalidates the caches or triggers a relayout in these cases.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we could create the new container to accomodate this case, by just storing which parent widget first displayed it, and ignore all other fit/layout request from different parent widgets?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
however, from the second thought, i feel like it should be acomodated here in overflow container - just have internal table for storing data for multiple parent widgets
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
like
self._private.instances[parent_id].avail_in_dir = avail_in_dir
self._private.instances[parent_id].used_in_dir = used_in_dir
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
by just storing which parent widget first displayed it,
Imaginary bug report: Here is some code that first displays a widget in A, then, on a key binding, it moves things to B. However, the widget disappears.
Also, a widget does not really know its parent. The existing caches do not track the parent widget. So, if you once return 0, 0
, the cache will keep returning that also for other parents.
function overflow:before_draw_children(_, cr, width, height) | ||
-- Clip drawing for children to the space we're allowed to draw in | ||
cr:rectangle(0, 0, width, height) | ||
cr:clip() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This clips what is drawn, but the input code does not know that you clipped something. Assuming you place a widget partially outside of the container (I have not yet entirely understood :layout()
yet and am not 100% sure what is done here), it will still be possible to click into the not-visible parts of the widget.
(The scroll container does dark magic that results in no mouse clicks being possible; not really much better.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your assumption is correct. Another user reported this as well, as a general problem with clipped drawing. If I remember them correctly, clicks fire for any non-visible part of a widget inside a container with some cr:clip()
, even if that part doesn't extend outside the container's geometry.
For the specific case here, this patch supposedly helps: xinhaoyuan@384b9ea, but I guess there are other use cases that need things to work like they do currently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If clipping of child widgets is something that is needed... well, I guess it might (in theory) be possible to extend wibox.widget.base.place_widget_*
with a shape
parameter.
However, the result can easily end up being ugly: Doing hit tests against a gears.shape
requires creating a temporary cairo surface and context, applying the shape, and then checking with something like cr:in_fill(x, y)
. This sounds like a "nice" way to end up with high memory usage and/or slow code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we would need a separate clip shape per child widget. A single method widget.clip_shape
on the layout/parent should be enough.
And the special case of widget.clip_shape == gears.rectangle
(or by checking an additional property) could then be optimized to skip the temporary cairo surface and use the patch linked above.
This layout adds overflow behavior: - adds a scrollbar, configurable as a widget - adds scrollbar dragging to scroll - adds mouse scroll behavior - allows children to render at (near) infinite size in scroll direction Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
For some of the examples, the layout's available space was big enough to show all child widgets, and no scrollbar was rendered. Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
176384e
to
580a080
Compare
While it is possible for any widget to clip drawing for its children to prevent drawing outside the widget's boundaries, the widget system would still consider the child widget's full size for mouse clicks. Draw clipping via Cairo supports any arbitrary, complex path. To mirror that for mouse clicks, we would need to create a temporary Cairo surface to do the clipping for us, which is rather expensive. Therefore this patch only adds the very basic, but likely the most common use case where mouse clicks should be clipped to the widget's own size. See awesomeWM#3309 (comment) for the full discussion. Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
707bc18
to
93afe19
Compare
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
While it is possible for any widget to clip drawing for its children to prevent drawing outside the widget's boundaries, the widget system would still consider the child widget's full size for mouse clicks. Draw clipping via Cairo supports any arbitrary, complex path. To mirror that for mouse clicks, we would need to create a temporary Cairo surface to do the clipping for us, which is rather expensive. Therefore this patch only adds the very basic, but likely the most common use case where mouse clicks should be clipped to the widget's own size. See awesomeWM#3309 (comment) for the full discussion. Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Fix mouse movement detection when the widget has been transformed by something like `wibox.container.rotate`. Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Oh, that's bad. I didn't realize until now, but When spacing is involved, it actually makes a difference whether a widget is |
Can't child widgets return a size beyond what's available in the layout to indicate there isn't enough space? I thought |
I don't know if it's relevant, but that reminds me of that bug 83c31f9 The 0x0 widgets are tricky to handle... |
Sure, that might be slightly less ambiguous. But that's still using a return value of two numbers that could be valid to encode information that shouldn't be encoded with numbers. And it wouldn't help at all with the |
I've extracted the discussion about |
I have another instance of unexpected behavior. I know I'm a bit of a thorn in the side of this PR right now, but better to work these things out now rather than later when someone creates an issue right 😁. When I click on the scrollbar without moving the mouse the scrollbar moves and the scroll position changes. As soon as I move the mouse a little the scrollbar and and scroll position seem to snap back to their original location before being clicked on. I would expect the scrollbar to behave in a typical manner where it does not move until the mouse is moved. |
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Just tested again and that last change fixed my issue. |
Improves separation of concerns for individual steps and reworks groups and names for clearer output on error. Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sclu1034, do you think it's now ready? I think we are alright.
I'd like to have the input from other maintainers about the new clip_child_extends
, tho. I really think it should be documented. Worst case scenario : it will be marked as "inherited from widget.base" and the user will ignore it, like they already ignore "children" on most widgets.
Also, to mitigate the concern @psychon pointed that this layout can only be used at one place at a time, as opposed to how the widget system should work. Maybe we should have a mention of this in the module description. (It can be a good excuse to implement some sort of information/alert component in the doc https://getbootstrap.com/docs/4.0/components/alerts/)
That would be up to the reviewers to decide.
That's not a good comparison. Would prefixing it with |
Sorry for the delay, I didn't work on AwesomeWM since xmas. I did some testing and it works. My earlier comments are addressed and the API looks good. Thanks a lot for this. Now, yes, this container has some unfixeable limitations, but it provides a lot of value for people who don't use the more advanced widget system features. Thanks a lot for this contribution! |
Before this gets merged I do want to point out that the changes to |
As far as I can see, we have three options:
Ideally, we would do the first. However, if you do want this PR merged now, the second option would be preferable. |
after using this myself i have noticed 2 problems:
havent used it enough to notice any other problems, besides maybe the default step value being too low in my opinion |
8bb2e68
to
d84dc1e
Compare
I noticed when using two overflow containers (one inside another one) that both get scrolled, when scrolling with the mouse wheel. When scrolling you should probably check which is the nearest overflow widget under the cursor and only scroll that one. |
some other things i recommend adding:
|
For now this is fully blocked on #3531 . |
This layout adds overflow behavior:
TODOs
base.fit_widget
hides information from the parent widget #3531 and adjust:layout
to whatever comes from thatDemonstration
recording-20210331_224618.mp4