The child process handling PAM authentication can have multiple requests
queued up. As the first success will unlock the screen, there is no
point in processing anything afterwards.
The few places that required a surface commit relied on render_frame and
render_frame_background to form it form them after they had set up frame
callback events. This would fail if render_frame ran out of buffers and
exited early, as the caller would still wait indefinitely on the frame
callback.
swaylock would quite consistently run out of buffers when rendering
immediately after a configure event, such as when the keypress causing
render also caused outputs to be enabled from idle.
Restructure the render and commit handling slightly so that the whole
frame callback and commit setup is handled by the render code, which now
has a single render entrypoint. This both avoids stalls from lacking
commits, but also fixes the case the configure path to respect frame
callbacks so we do not run out of buffers in the first place.
PEG and other image formats may include an EXIF orientation tag
which indicates in what orientation (rotation and mirroring)
the image should be displayed. libgdk-pixbuf does not correct for this
when loading an image, but provides a function to apply the transform
after the fact, which this commit uses.
Pulled from https://github.com/swaywm/swaybg/pull/68
Calling wl_display_roundtrip() from an event handler is a bad
practice in general because it nests multiple dispatches.
We don't need to block here anyways.
When setting an image with `--image <output>:<path>`, the image used to
fail to apply if the relevant output appears some time after swaylock
executes.
Co-authored-by: Alexander Bakker <ab@alexbakker.me>
If mlock() fails with errno EAGAIN, it should be retried up to five
times, which is tracked in the retries variable. However, the `return
false` statement after the switch case makes the function return false
after the first failed mlock() call.
Remove this statement to actually retry up to five times.
Signed-off-by: Max Kunzelmann <maxdev@posteo.de>
If a large number of signals is sent, it is possible to fill the
buffer for sigusr_fds[1] before the main loop has a chance to read
from it; then the signal handler do_sigusr() will block on write.
If signal() is used to set a signal handler, only the first signal
received will use the handler; any later signals use the default
behavior (making swaylock terminate immediately, without unlocking).
Using sigaction() ensures that the handler will be used every time.
Just send a singular newline like s6 expects.
systemd doesn't support spawning a process with an FD to send
readiness notifications to, instead it provides a socket name. IOW,
this cannot be used directly with systemd after all.
Closes: https://github.com/swaywm/swaylock/issues/312
This commit establishes separate state machines for auth state (whether
the password submitted is being verified or is wrong) and input state
(typing indicators and clear message -- things relevant to the state of
the password being typed in, before it is submitted.) This makes it
possible to display the auth state while updating the input state (for
example, show that the previously submitted password is 'verifying' or
'wrong' while typing another.)
The two state machines interact only when submitting a password. There
is some interference with the rendering code -- a 'cleared' message
from the input state machine supersedes verifying/wrong messages from
the auth state machine; although since the 'clear' state has a shorter
timeout than the auth 'invalid' state, this is unlikely to hide the 'wrong'
message.
Allow typing new input while the previous one is validating. Can be
tested with:
ninja -C build && sway -c sway.conf
Where sway.config is:
exec ./build/swaylock
Fixes: https://github.com/swaywm/swaylock/issues/241
This change has the additional benefit of ensuring that the position
of the highlight only changes in reaction to a letter key or
backspace being pressed, and not when the compositor sends a new
configure event or the output needs to be redrawn for some other
reason.
The wl_buffers for the background surface only need to be updated
when the output dimensions change. Using the fixed pool of two
buffers to cache these buffers does not help, since if a new buffer
is needed, it will have a different size than whatever buffers were
cached. Furthermore, because the pool has fixed size, it is possible
to run out of buffers if configure events arrive faster than
pool buffers are marked not busy, which can lead to protocol errors
when the background surface is committed after acknowledging a new
size, but without attaching a buffer that matches that size.
The size of the surface used to draw the indicator depends on
the extents of the text being drawn on and under the indicator.
This commit refactors the `render_frame` function so that the surface
size is computed before drawing; before, `render_frame` drew onto a
buffer, estimated the size the buffer should have had, and recursively
called itself to try again with the estimated size, if necessary. This
was done because Cairo's methods to estimate font and text size
require that a cairo_t context object and an associated cairo_surface
already have been set up. Since the surface size depends on the text
size, the natural way to use Cairo would have a circular dependency.
In order to compute sizes _before_ the buffer is created, this commit
adds a 1x1 surface and a matching `test_cairo` context which is set to
the same font and drawing parameters as the buffer that will be
created. Font/text extent measurements should give the same results as
for the final buffer.
From getopt manual page:
> By default, getopt() permutes the contents of argv as it scans, so that eventually all the nonoptions are at the end. Two other scanning modes are also implemented. [...] If the first character of optstring is '-', then each nonoption argv-element is handled as if it were the argument of an option with character code 1.
> If the first character (following any optional '+' or '-' described above) of optstring is a colon (':'), then getopt() likewise does not print an error message. In addition, it returns ':' instead of '?' to indicate a missing option argument. This allows the caller to distinguish the two different types of errors.
When the screen is locked using ext_session_lock, killing swaylock will
leave the session locked. This is normally desirable if the kill is due
to the OOM killer or swaylock crashing, but can be undesirable if an
unlock is desired. This adds a signal handler for SIGUSR1 if using
ext_session_lock.