Tomas-M / xlunch

Graphical app launcher for X with minimal dependencies
http://xlunch.org
GNU General Public License v3.0
219 stars 37 forks source link

Simple scrolling #69

Closed Tomas-M closed 6 years ago

Tomas-M commented 6 years ago

Sometimes it may be needed to support some simple scrolling, to let user access icons which are beyond the screen (hidden). For example if we use textafter, then the number of entries which fit the creen may be relatively small. I was thinking about the following approach:

Currently there is a list of all icons in memory, and the top X icons is displayed, depending on how many fits the screen, the rest is hidden. I was thinking that instead of this "fixed-top-X" icons we could have a simple int variable, which will store the starting position. Initially 0. And the entries with ID lower than this starting position would be ignored (not displayed).

When user uses mouse scroll, it would simply adjust this starting position by adding or subtracting the number of columns (if there are more icons to scroll to). Similarly when user uses right arrow key on the last element, the starting position would be increased by number of columns. This way, the scrolling would be "by row". So on scroll down, the top-most row would be hidden and the entire list of icons be shifted up, making the next row visible. The only drawback is probably that the entire screen needs to be invalidated (imlib_update_append_rect)

At the moment I think we can make it without any scrollbar. And without any shifting visual effects.

Tomas-M commented 6 years ago

Edited a bit

PMunch commented 6 years ago

Hmm, I agree that scrolling would be cool. And your way seems like a simple solution. Only problem I see is that users could get confused if they scrolled by accident, but that should probably be fine, especially if we reset scroll to 0 when you're writing into the prompt.

Tomas-M commented 6 years ago

Adding scrollbar customized by user wouldn't be so hard, just few new options would be needed - scrollbar position (right offset), scrollbar background image, and scrollbar handle image. And the handle would travel up and down on the railway made of the scrollbar background.

But harder would be probably to implement dragging of the handle.... since we don't have anything in xlunch for dragging.

Furthermore if there is a scrollbar then users would expect perhaps smooth scrolling, that would probably take too much CPU, I am not sure if imlib can handle this.

So I would definitely suggest to start without scrollbar at all :)

We can consider showing some buttons (customizable by user) so once user scrolls down, some button will appear which can be clicked to scroll back. Like this:

image

PMunch commented 6 years ago

Yeah I was thinking about adding the possibility to have a scroll verb instead of a command with buttons. That way you can position them wherever you like. But that led me down the rabbit hole of a better interface with scripts and I realised it would probably be better to just implement scroll-wheel and end of list scrolling for now.

Tomas-M commented 6 years ago

Fair enough :)

Maybe we could add internal commands which start with colon, like :scrolltop or :refresh or similar ... so user could call internal functionality when a button/icon is clicked, without restarting xlunch.

PMunch commented 6 years ago

Yeah, something like that was the idea. And then with the possibility of writing these over stdin as well, instead of just entries. So that if you specify --outputonly you can have a script that communicates with xlunch over stdio.

PMunch commented 6 years ago

Added scrolling in https://github.com/Tomas-M/xlunch/commit/32303bfcaec3c24505bac078c35e815aaa083f60. Also added a code-path for internal commands beginning with :. Currently I've only changed recur to be :recur and not implemented any new ones but I plan on adding at least :scroll <+/-n> as an option. Any ideas for more internal commands?

P.S: Currently it updates the entire screen when you scroll, and mouse scroll events are handled for the entire window. It would be possibly to only update the entries list, and to only handle scroll events within the entries list if we want to.

Tomas-M commented 6 years ago

I guess that we may leave it updating everything, if the user has a screen full of icons so he must scroll, then most of the screen will be updated anyway.

I noticed that when I have 4 items, and I make the screen to display only 2, the scrolling scrolls beyond and there are actually three scrollable pages in this scenario - one with first two items, one with second two items, and one empty. I think we should not reach beyond the list of items, meaning we should not scroll to an empty page.

Similarly, if I use textafter and make only 1 row visible in an xlunch window, scrolling with keyboard (arrow right) goes beyond the last element showing empty page, but then when I want to return back with left arrow, it does not go to the last element, it goes one more element back (so scroll shows: 1, 2, 3, 4, empty, 3). Wheel works fine (expect the fact it goes to a blank page too).

Tomas-M commented 6 years ago

I would add maybe :scrolltop (if user presses Home key, it should go to very top), maybe :scrollbot for End key to go to the end of the list.

Currently xlunch works in a way that it either quits after exec or dontquit. Would be perhaps good if we could make this configurable per icon/button, so maybe :exec <command> would exec the command while keeping xlunch running, while :exec_quit <command> would exec it and quit, and perhaps :print <string> would print the string to stdout only. If we have these we may perhaps remove the special options for --dontquit or --outputonly since those would be confusing when commands handle the behavior.

Tomas-M commented 6 years ago

More note, after a successfull scroll with wheel (not with keyboard), we should higlight the item under cursor without the need to wait for mouse movement.

PMunch commented 6 years ago

Fixed the scrolling past the end issues, it was two simple one-off errors as I expected. I feel like the current behaviour of Home and End is more useful as it takes you to the beginning of a "page", but maybe Shift+Home/End could take you all the way?

Highlighting the item under the coursor would require us to split the event handling out into separate functions. I think we should do this anyways for better readability but haven't had time to do that refactor yet.

I've also implemented some internal commands: :scroll can take an argument top, bottom(Currently does nothing), to go to top and bottom. A number to scroll to that line, and numbers prefixed with a + or - to move that amount relative to the current position. This is a bit of a trial to see how it works, I'm going to refactor the scroll code and move the scrolling into it's own function for all the checking stuff. This means that currently the :scroll command does no checking and can scroll past the end and beginning. :quit quits xlunch :print prints whatever follows it, or whatever is in double quotes. :exec does the same as print but runs it instead of printing. All the commands are chainable so :print "Hello world!" :scroll +3 :quit should be a valid command (as long as print and exec has quotes around their arguments.

I feel like the current --dontquit and --outputonly serves as a good way for defaults, but that the internal commands offers a way to override the default should it be desired.

Tomas-M commented 6 years ago

Nice :)

I tend to disagree regarding the Home key :) In many programs, including Windows Explorer, the behavior is that Home key goes to the first page to the first item. So if you do not mind, please make the Home key go to the first item. Similarly I'd prefer to End to the very end, not page end.

PMunch commented 6 years ago

I've fixed the home/end thing along with cleaning up the code significantly. I also added a new :hover internal command to hover an item, not sure what it would be used for, but it's there if anyone wants to use it.

EDIT: Also added the possibility to run internal commands from the entries source. This means they can both be run from the entries.dsv file but also stdin for scripting purposes.

Tomas-M commented 6 years ago

I noticed that strange things happen with I press PgDn if I have only 4 icons and --scroll enabled. PgDn moves all the icons to the bottom of the screen. Is this intentional? Probably not :)

PMunch commented 6 years ago

Ah, it tries to align the bottom of the entries list with the bottom of the screen. But I forgot to add that it should not do this if there are fewer than columns*row entries.

PMunch commented 6 years ago

Did some more fixes, think everything should work as expected now.

Tomas-M commented 6 years ago

Scrolling seems to be working fine, good work! :)