Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: GIF playback on input #27

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

LordCMonkey
Copy link

I added a --gif <path> option, which allows for any GIF to be chosen and displayed on the lock screen, where the frames advance only while typing. For regular password input, the GIF advances by one frame per keystroke, backspace reverses one frame, and clearing (Ctrl+C), password rejection (wrong password) aswell as idling resets the GIF to the first frame.

All GIF related variables are stored in the form of struct swaylock_gif from include/swaylock.h in swaylock_state.

The GIF itself is loaded by gdk as an pixbuf animation in main.c, via the function
static void load_gif(char *arg, struct swaylock_state *state) (line 717)
where the arg is the path given in the CLI option.

To advance the GIF by one frame per Keystroke (and currently also once a second when the clock is updated, although this behaviour is not intended), an iterator (state->gif.iter) provided by gdk pixbuf is tricked. The iterator chooses the frame to display based on a timestamp in this function: gdk_pixbuf_animation_iter_advance(state->gif.iter, state->gif.time);, where gif.time is a struct called GTimeVal which contains seconds and microseconds. The timestamp is updated upon every call to void render_frame(struct swaylock_surface *surface) in render.c. The first frame is always shown when the seconds and microseconds in gif.time are set to 0. When the frame should switch to the next frame, the GIF specific delay (found in state->gif.delay) is added to or substracted from the current microseconds.
Thereafter, the new frame is returned as a pixbuf and painted to the current surface using gdk_cairo_set_source_pixbuf(cairo, state->gif.pixbuf, 0, 0); und applied via cairo_paint(cairo);.

Currently, the GIF is painted to the same surface the indicator is on, as i did not entirely catch on to the window/surface handling in the project, and only unsuccesfully fumbled around with it (the struct wl_list link in state->gif is a remnant of this), aswell as #17 (comment).

Since the GIF does not feature its own surface, the indicator radius is set to double its width in line 1498 of main.c. This is necessary to fit the whole gif onto the indicator surface, as they will get clipped and not shown entirely if the radius and thus the surface is too small. This is rather ugly and only works properly (centers) square GIFs.

This feature adds gtk as a dependency to the project.

Anyways, i like the result, especially with this GIF (works well with the clock inside and a long password). For the clock and the datestring to be properly formatted, and the indicator invisible, i use the following swaylock command:
./swaylock --gif ~/Pictures/lockgif.gif --inside-color 00000000 --ring-color 00000000 --line-color 00000000 --indicator-thickness 0 -e --font-size 26 --text-color AAAAAAAA --inside-ver-color 00000000 --inside-clear-color 00000000 --inside-wrong-color FF000044
and changed two options of text handling in render.c, on line 362 and 368 to have the datestring follow the --font-size option and have its y-offset be independent from the indicator radius.

I do invite you to give it a try (maybe with the suggested GIF and command), and would like to hear your opinion.

main.c Outdated
state->gif.width = gdk_pixbuf_get_width(state->gif.pixbuf);

} else {
fprintf(stderr, "ERROR: Animation could not be opened / no loader for the file format exists / not enough memory to allocate image buffer / image contains invalid data\n");
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error message from here

@mortie
Copy link
Owner

mortie commented Sep 21, 2020

Hmm, I'm not sure if I see the need for this feature. I checked out your branch and tried your example command, but it feels like a very niche feature which I can't really see the use case for. It's possible I could be convinced otherwise though if I saw some impressive example uses. If that doesn't happen, feel free to maintain your own fork.

Regardless, some comments about the code:

  • When you push to the branch, even if it's after the pull request has been submitted, the new commits end up as a part of the PR. It's cool that you're branding your fork as swaylock-effects-gif, but it should be on a separate branch from the PR one :p
  • This project uses tabs for indentation, your new code uses spaces.
  • I don't understand the gtk dependency? Everything seems to use glib and gdk-pixbuf.
  • As my compiler says; ‘_GTimeVal’ is deprecated: Use 'GDateTime' instead.
  • The error message printed when gdk_pixbuf_animation_new_from_file fails should probably print error->message, not just the list of things which might lead to the function failing.

@LordCMonkey
Copy link
Author

Hey there, thanks for your feedback!
I will try to change the _GTimeVal usage, and then play around with different settings and gifs to (hopefully) produce some cool lockscreen effects.
The gtk dependency stems from gdk_cairo_set_source_pixbuf(), as cairo paints directly from a pixbuf to a separate surface. This is not needed in the already existing background image option, as there the image does not change and upon loading a new surface gets created, which is later on attached and commited to the buffer swaylock surface using wl_surface functions.
Maybe this behaviour could be copied for the gif though, i'll have a look.

@damianatorrpm
Copy link

would this allow to show password while you type?

@LordCMonkey
Copy link
Author

well, you could create a gif of your password being typed frame by frame.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants