Split swaylock into separate project

This commit is contained in:
Drew DeVault 2019-01-13 21:29:12 -05:00
parent 4879d40695
commit 3fca8b8d22
24 changed files with 14 additions and 2255 deletions

View file

@ -45,16 +45,13 @@ Sway съществува в репотата (хранилищата) на мн
* pango
* cairo
* gdk-pixbuf2 *
* pam **
* dbus >= 1.10 ***
* dbus >= 1.10 **
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (Нужен за man страници)
* git
_\*Нужен само за swaybar, swaybg и swaylock_
_\*Нужен само за swaybar, swaybg_
_\*\*Нужен само за swaylock_
_\*\*\*Нужен само за tray_
_\*\*Нужен само за tray_
Изпълнете следните команди:

View file

@ -56,13 +56,10 @@ Abhängigkeiten:
* pango
* cairo
* gdk-pixbuf2 *
* pam **
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (erforderlich für man pages)
* git
_\*Nur erforderlich für swaybar, swaybg, und swaylock_
_\*\*Nur erforderlich für swaylock_
_\*Nur erforderlich für swaybar, swaybg_
Führe diese Befehle aus:

View file

@ -48,13 +48,10 @@ To username μου στο Freenode είναι kon14 και θα με βρείτ
* pango
* cairo
* gdk-pixbuf2 *
* pam **
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (required for man pages)
* git
_\*Απαιτείται μόνο για swaybar, swaybg, and swaylock_
_\*\*Απαιτείται μόνο για swaylock_
_\*Απαιτείται μόνο για swaybar, swaybg_
Εκτελέστε αυτές τις εντολές:

View file

@ -50,13 +50,10 @@ Installez les dépendances :
* pango
* cairo
* gdk-pixbuf2 *
* pam **
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (requis pour les pages man)
* git
_\*Uniquement requis pour swaybar, swaybg, and swaylock_
_\*\*Uniquement requis pour swaylock_
_\*Uniquement requis pour swaybar, swaybg_
Exécutez ces commandes :

View file

@ -50,13 +50,10 @@ Installa queste dipendenze:
* pango
* cairo
* gdk-pixbuf2 *
* pam **
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (rrichiesto per man pages)
* git
_\*Richiesto solo per swaybar, swaybg, e swaylock_
_\*\*Richiesto solo per swaylock_
_\*Richiesto solo per swaybar, swaybg_
Esegui questi comandi:

View file

@ -37,13 +37,12 @@ Swayは沢山のディストリビューションで提供されています。"
* pango
* cairo
* gdk-pixbuf2 \*\*
* pam (オプション: swaylockとPAMで必要)
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (manで必要です) \*
* git \*
_\*コンパイルの時_
_\*\*オプション: swaybgとswaylockでのみ必要です_
_\*\*オプション: swaybgでのみ必要です_
次のコマンドを実行してください:

View file

@ -41,13 +41,12 @@ Install dependencies:
* pango
* cairo
* gdk-pixbuf2 \*\*
* pam (optional: PAM support for swaylock)
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (optional: man pages) \*
* git \*
_\*Compile-time dep_
_\*\*optional: required for swaybg and swaylock_
_\*\*optional: required for swaybg_
Run these commands:

View file

@ -57,13 +57,10 @@ Antes de iniciar a compilação, instale as dependências:
* pango
* cairo
* gdk-pixbuf2 *
* pam **
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (man pages)
* git
_\*Dependência apenas de swaybar, swaybg, e swaylock_
_\*\*Dependência apenas de swaylock_
_\*Dependência apenas de swaybar, swaybg_
Para compilar, execute estes comandos:

View file

@ -50,16 +50,13 @@ Sway доступен во многих дистрибутивах и наход
* pango
* cairo
* gdk-pixbuf2 *
* pam **
* dbus >= 1.10 ***
* dbus >= 1.10 **
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (required for man pages)
* git
_\*Требуется только для swaybar, swaybg и swaylock_
_\*Требуется только для swaybar, swaybg_
_\*\*Требуется только для swaylock_
_\*\*\*Требуется только для tray_
_\*\*Требуется только для tray_
Выполните следующие команды:

View file

@ -57,13 +57,10 @@ Sway доступний у багатьох дистрибутивах Linux (а
* pango
* cairo
* gdk-pixbuf2 *
* pam **
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (required for man pages)
* git
_\*Лише для swaybar, swaybg та swaylock_
_\*\*Лише для swaylock_
_\*Лише для swaybar, swaybg_
Виконайте ці команди:

View file

@ -1,66 +0,0 @@
# swaylock(1) completion
_swaylock()
{
local cur prev
_get_comp_words_by_ref -n : cur prev
short=(
-h
-c
-s
-t
-v
-i
-u
-f
)
long=(
--help
--color
--scaling
--tiling
--version
--image
--no-unlock-indicator
--daemonize
)
scaling=(
'stretch'
'fill'
'fit'
'center'
'tile'
)
case $prev in
-c|--color)
return
;;
--scaling)
COMPREPLY=($(compgen -W "${scaling[*]}" -- "$cur"))
return
;;
-i|--image)
if grep -q : <<< "$cur"; then
output="${cur%%:*}:"
cur="${cur#*:}"
else
output=
fi
COMPREPLY=($(compgen -f -- "$cur"))
return
;;
esac
if [[ $cur == --* ]]; then
COMPREPLY=($(compgen -W "${long[*]}" -- "$cur"))
else
COMPREPLY=($(compgen -W "${short[*]}" -- "$cur"))
COMPREPLY+=($(compgen -W "${long[*]}" -- "$cur"))
fi
} &&
complete -F _swaylock swaylock

View file

@ -1,39 +0,0 @@
# swaylock(1) completion
complete -c swaylock -s C -l config --description 'The config file to use. Default: $HOME/.swaylock/config, $XDG_CONFIG_HOME/swaylock/config, and SYSCONFDIR/swaylock/config.'
complete -c swaylock -s h -l help --description "Show help message and quit."
complete -c swaylock -s f -l daemonize --description "Fork into the background after spawning. Note: this is the default bahavior of i3lock."
complete -c swaylock -s v -l version --description "Show the version number and quit."
complete -c swaylock -s s -l socket --description "Use the specified socket path. Otherwise, swaymsg will as sway where the socket is (which is the value of $SWAYSOCK, then of $I350CK)."
complete -c swaylock -s e -l ignore-empty-password --description 'When an empty password is provided by the user, do not validate it.'
# Appearance
complete -c swaylock -s u -l no-unlock-indicator --description "Disable the unlock indicator."
complete -c swaylock -s i -l image --description "Display the given image, optionally on the given output. Use -c to set a background color."
complete -c swaylock -s s -l scaling --description "Scaling mode for images: stretch, fill, fit, center, or tile."
complete -c swaylock -s t -l tiling --description "Same as --scaling=tile."
complete -c swaylock -s c -l color --description "Turn the screen into the given color. If -i is used, this sets the background of the image into the given color. Defaults to white (ffffff), or transparent (00000000) if an image is in use."
complete -c swaylock -l bs-hl-color --description 'Sets the color of backspace highlight segments.'
complete -c swaylock -l font --description 'Sets the font of the text inside the indicator.'
complete -c swaylock -l indicator-radius --description 'Sets the radius of the indicator to radius pixels. Default: 50'
complete -c swaylock -l indicator-thickness --description 'Sets the thickness of the indicator to thickness pixels. Default: 10'
complete -c swaylock -l inside-color --description 'Sets the color of the inside of the indicator when typing or idle.'
complete -c swaylock -l inside-clear-color --description 'Sets the color of the inside of the indicator when cleared.'
complete -c swaylock -l inside-ver-color --description 'Sets the color of the inside of the indicator when verifying.'
complete -c swaylock -l inside-wrong-color --description 'Sets the color of the inside of the indicator when invalid.'
complete -c swaylock -l key-hl-color --description 'Sets the color of key press highlight segments.'
complete -c swaylock -l line-color --description 'Sets the color of the lines that separate the inside and outside of the indicator when typing or idle.'
complete -c swaylock -l line-clear-color --description 'Sets the color of the lines that separate the inside and outside of the indicator when cleared.'
complete -c swaylock -l line-ver-color --description 'Sets the color of the lines that separate the inside and outside of the indicator when verifying.'
complete -c swaylock -l line-wrong-color --description 'Sets the color of the lines that separate the inside and outside of the indicator when invalid.'
complete -c swaylock -s n -l line-uses-inside --description 'Use the color of the inside of the indicator for the line separating the inside and outside of the indicator.'
complete -c swaylock -s r -l line-uses-ring --description 'Use the outer ring\'s color for the line separating the inside and outside of the indicator.'
complete -c swaylock -l ring-color --description 'Sets the color of the outside of the indicator when typing or idle.'
complete -c swaylock -l ring-clear-color --description 'Sets the color of the outside of the indicator when cleared.'
complete -c swaylock -l ring-ver-color --description 'Sets the color of the outside of the indicator when verifying.'
complete -c swaylock -l ring-wrong-color --description 'Sets the color of the outside of the indicator when invalid.'
complete -c swaylock -l separator-color --description 'Sets the color of the lines that separate highlight segments.'
complete -c swaylock -l text-color --description 'Sets the color of the text inside the indicator when typing or idle.'
complete -c swaylock -l text-clear-color --description 'Sets the color of the text inside the indicator when cleared.'
complete -c swaylock -l text-ver-color --description 'Sets the color of the text inside the indicator when verifying.'
complete -c swaylock -l text-wrong-color --description 'Sets the color of the text inside the indicator when invalid.'

View file

@ -1,40 +0,0 @@
#compdef swaylock
#
# Completion script for swaylock
#
_arguments -s \
'(-C --config)'{-C,--config}'[Path to the config file]:filename:_files' \
'(-c --color)'{-c,--color}'[Turn the screen into the given color instead of white]:color:' \
'(-e --ignore-empty-password)'{-e,--ignore-empty-password}'[When an empty password is provided, do not validate it]' \
'(-f --daemonize)'{-f,--daemonize}'[Detach from the controlling terminal after locking]' \
'(-h --help)'{-h,--help}'[Show help message and quit]' \
'(-i --image)'{-i,--image}'[Display an image]:filename:_files' \
'(-s --scaling)'{-s,--scaling}'[Scaling mode]:mode:(stretch fill fit center tile)' \
'(-t --tiling)'{-t,--tiling}'[Same as --scaling=tile]' \
'(-u --no-unlock-indicator)'{-u,--no-unlock-indicator}'[Disable the unlock indicator]' \
'(-v --version)'{-v,--version}'[Show the version number and quit]' \
'(--bs-hl-color)'--bs-hl-color'[Sets the color of backspace highlights segments]:color:' \
'(--font)'--font'[Sets the font of the text]:font:' \
'(--indicator-radius)'--indicator-radius'[Sets the indicator radius]:radius:' \
'(--indicator-thickness)'--indicator-thickness'[Sets the indicator thickness]:thickness:' \
'(--inside-color)'--inside-color'[Sets the color of the inside of the indicator]:color:' \
'(--inside-clear-color)'--inside-clear-color'[Sets the color of the inside of the indicator when cleared]:color:' \
'(--inside-clear-color)'--inside-clear-color'[Sets the color of the inside of the indicator when verifying]:color:' \
'(--inside-wrong-color)'--inside-wrong-color'[Sets the color of the inside of the indicator when invalid]:color:' \
'(--key-hl-color)'--key-hl-color'[Sets the color of the key press highlight segments]:color:' \
'(--line-color)'--line-color'[Sets the color of the line between the inside and ring]:color:' \
'(--line-clear-color)'--line-clear-color'[Sets the color of the line between the inside and ring when cleared]:color:' \
'(--line-ver-color)'--line-ver-color'[Sets the color of the line between the inside and ring when verifying]:color:' \
'(--line-wrong-color)'--line-wrong-color'[Sets the color of the line between the inside and ring when invalid]:color:' \
'(-n --line-uses-inside)'{-n,--line-uses-inside}'[Use the inside color for the line between the inside and ring]' \
'(-r --line-uses-ring)'{-r,--line--uses-ring}'[Use the ring color for the line between the inside and ring]' \
'(--ring-color)'--ring-color'[Sets the color of the ring of the indicator]:color:' \
'(--ring-clear-color)'--ring-clear-color'[Sets the color of the ring of the indicator when cleared]:color:' \
'(--ring-ver-color)'--ring-ver-color'[Sets the color of the ring of the indicator when verifying]:color:' \
'(--ring-wrong-color)'--ring-wrong-color'[Sets the color of the ring of the indicator when invalid]:color:' \
'(--separator-color)'--separator-color'[Sets the color of the lines that separate highlight segments]:color:' \
'(--text-color)'--text-color'[Sets the color of the text]:color:' \
'(--text-clear-color)'--text-clear-color'[Sets the color of the text when cleared]:color:' \
'(--text-ver-color)'--text-ver-color'[Sets the color of the text when verifying]:color:' \
'(--text-wrong-color)'--text-wrong-color'[Sets the color of the text when invalid]:color:'

View file

@ -84,7 +84,6 @@ if scdoc.found()
'sway/sway-bar.5.scd',
'sway/sway-input.5.scd',
'sway/sway-output.5.scd',
'swaylock/swaylock.1.scd',
'swaymsg/swaymsg.1.scd',
'swaynag/swaynag.1.scd',
'swaynag/swaynag.5.scd',
@ -146,7 +145,6 @@ subdir('client')
subdir('swaybg')
subdir('swaybar')
subdir('swaynag')
subdir('swaylock')
config = configuration_data()
config.set('datadir', join_paths(prefix, datadir))
@ -200,7 +198,6 @@ endif
if (get_option('zsh-completions'))
zsh_files = files(
'completions/zsh/_sway',
'completions/zsh/_swaylock',
'completions/zsh/_swaymsg',
)
zsh_install_dir = datadir + '/zsh/site-functions'
@ -212,7 +209,6 @@ if (get_option('bash-completions'))
bash_files = files(
'completions/bash/sway',
'completions/bash/swaybar',
'completions/bash/swaylock',
'completions/bash/swaymsg',
)
bash_install_dir = datadir + '/bash-completion/completions'
@ -223,7 +219,6 @@ endif
if (get_option('fish-completions'))
fish_files = files(
'completions/fish/sway.fish',
'completions/fish/swaylock.fish',
'completions/fish/swaymsg.fish',
'completions/fish/swaynag.fish',
)

File diff suppressed because it is too large Load diff

View file

@ -1,55 +0,0 @@
sysconfdir = get_option('sysconfdir')
dependencies = [
cairo,
client_protos,
gdk_pixbuf,
math,
pango,
pangocairo,
xkbcommon,
wayland_client,
wlroots,
]
sources = [
'main.c',
'password.c',
'render.c',
'seat.c'
]
if libpam.found()
sources += ['pam.c']
dependencies += [libpam]
else
warning('The swaylock binary must be setuid when compiled without libpam')
warning('You must do this manually post-install: chmod a+s /path/to/swaylock')
sources += ['shadow.c']
if crypt.found()
dependencies += [crypt]
endif
endif
executable('swaylock',
sources,
include_directories: [sway_inc],
dependencies: dependencies,
link_with: [lib_sway_common, lib_sway_client],
install_rpath : rpathdir,
install: true
)
if is_freebsd
install_data(
'pam/swaylock.freebsd',
install_dir: sysconfdir + '/pam.d/',
rename: 'swaylock'
)
else
install_data(
'pam/swaylock.linux',
install_dir: sysconfdir + '/pam.d/',
rename: 'swaylock'
)
endif

View file

@ -1,62 +0,0 @@
#define _POSIX_C_SOURCE 200809L
#include <pwd.h>
#include <security/pam_appl.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wlr/util/log.h>
#include "swaylock/swaylock.h"
void initialize_pw_backend(void) {
// TODO: only call pam_start once. keep the same handle the whole time
}
static int function_conversation(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *data) {
struct swaylock_password *pw = data;
/* PAM expects an array of responses, one for each message */
struct pam_response *pam_reply = calloc(
num_msg, sizeof(struct pam_response));
*resp = pam_reply;
for (int i = 0; i < num_msg; ++i) {
switch (msg[i]->msg_style) {
case PAM_PROMPT_ECHO_OFF:
case PAM_PROMPT_ECHO_ON:
pam_reply[i].resp = strdup(pw->buffer); // PAM clears and frees this
break;
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
break;
}
}
return PAM_SUCCESS;
}
bool attempt_password(struct swaylock_password *pw) {
struct passwd *passwd = getpwuid(getuid());
char *username = passwd->pw_name;
const struct pam_conv local_conversation = {
function_conversation, pw
};
pam_handle_t *local_auth_handle = NULL;
int pam_err;
if ((pam_err = pam_start("swaylock", username,
&local_conversation, &local_auth_handle)) != PAM_SUCCESS) {
wlr_log(WLR_ERROR, "PAM returned error %d", pam_err);
}
if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) {
wlr_log(WLR_ERROR, "pam_authenticate failed");
goto fail;
}
// TODO: only call pam_end once we succeed at authing. refresh tokens beforehand
if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) {
wlr_log(WLR_ERROR, "pam_end failed");
goto fail;
}
clear_password_buffer(pw);
return true;
fail:
clear_password_buffer(pw);
return false;
}

View file

@ -1,6 +0,0 @@
#
# PAM configuration file for the swaylock screen locker. By default, it includes
# the 'passwd' configuration file (see /etc/pam.d/passwd)
#
auth include passwd

View file

@ -1,6 +0,0 @@
#
# PAM configuration file for the swaylock screen locker. By default, it includes
# the 'login' configuration file (see /etc/pam.d/login)
#
auth include login

View file

@ -1,190 +0,0 @@
#include <assert.h>
#include <errno.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wlr/util/log.h>
#include <xkbcommon/xkbcommon.h>
#include "swaylock/swaylock.h"
#include "swaylock/seat.h"
#include "loop.h"
#include "unicode.h"
void clear_password_buffer(struct swaylock_password *pw) {
// Use volatile keyword so so compiler can't optimize this out.
volatile char *buffer = pw->buffer;
volatile char zero = '\0';
for (size_t i = 0; i < sizeof(pw->buffer); ++i) {
buffer[i] = zero;
}
pw->len = 0;
}
static bool backspace(struct swaylock_password *pw) {
if (pw->len != 0) {
pw->buffer[--pw->len] = 0;
return true;
}
return false;
}
static void append_ch(struct swaylock_password *pw, uint32_t codepoint) {
size_t utf8_size = utf8_chsize(codepoint);
if (pw->len + utf8_size + 1 >= sizeof(pw->buffer)) {
// TODO: Display error
return;
}
utf8_encode(&pw->buffer[pw->len], codepoint);
pw->buffer[pw->len + utf8_size] = 0;
pw->len += utf8_size;
}
static void clear_indicator(void *data) {
struct swaylock_state *state = data;
state->clear_indicator_timer = NULL;
state->auth_state = AUTH_STATE_IDLE;
damage_state(state);
}
static void schedule_indicator_clear(struct swaylock_state *state) {
if (state->clear_indicator_timer) {
loop_remove_timer(state->eventloop, state->clear_indicator_timer);
}
state->clear_indicator_timer = loop_add_timer(
state->eventloop, 3000, clear_indicator, state);
}
static void clear_password(void *data) {
struct swaylock_state *state = data;
state->clear_password_timer = NULL;
state->auth_state = AUTH_STATE_CLEAR;
clear_password_buffer(&state->password);
damage_state(state);
schedule_indicator_clear(state);
}
static void schedule_password_clear(struct swaylock_state *state) {
if (state->clear_password_timer) {
loop_remove_timer(state->eventloop, state->clear_password_timer);
}
state->clear_password_timer = loop_add_timer(
state->eventloop, 10000, clear_password, state);
}
static void handle_preverify_timeout(void *data) {
struct swaylock_state *state = data;
state->verify_password_timer = NULL;
}
static void submit_password(struct swaylock_state *state) {
if (state->args.ignore_empty && state->password.len == 0) {
return;
}
state->auth_state = AUTH_STATE_VALIDATING;
damage_state(state);
// We generally want to wait until all surfaces are showing the
// "verifying" state before we go and verify the password, because
// verifying it is a blocking operation. However, if the surface is on
// an output with DPMS off then it won't update, so we set a timer.
state->verify_password_timer = loop_add_timer(
state->eventloop, 50, handle_preverify_timeout, state);
while (state->run_display && state->verify_password_timer) {
errno = 0;
if (wl_display_flush(state->display) == -1 && errno != EAGAIN) {
break;
}
loop_poll(state->eventloop);
bool ok = 1;
struct swaylock_surface *surface;
wl_list_for_each(surface, &state->surfaces, link) {
if (surface->dirty) {
ok = 0;
}
}
if (ok) {
break;
}
}
wl_display_flush(state->display);
if (attempt_password(&state->password)) {
state->run_display = false;
return;
}
state->auth_state = AUTH_STATE_INVALID;
damage_state(state);
schedule_indicator_clear(state);
}
void swaylock_handle_key(struct swaylock_state *state,
xkb_keysym_t keysym, uint32_t codepoint) {
switch (keysym) {
case XKB_KEY_KP_Enter: /* fallthrough */
case XKB_KEY_Return:
submit_password(state);
break;
case XKB_KEY_Delete:
case XKB_KEY_BackSpace:
if (backspace(&state->password)) {
state->auth_state = AUTH_STATE_BACKSPACE;
} else {
state->auth_state = AUTH_STATE_CLEAR;
}
damage_state(state);
schedule_indicator_clear(state);
schedule_password_clear(state);
break;
case XKB_KEY_Escape:
clear_password_buffer(&state->password);
state->auth_state = AUTH_STATE_CLEAR;
damage_state(state);
schedule_indicator_clear(state);
break;
case XKB_KEY_Caps_Lock:
case XKB_KEY_Shift_L:
case XKB_KEY_Shift_R:
case XKB_KEY_Control_L:
case XKB_KEY_Control_R:
case XKB_KEY_Meta_L:
case XKB_KEY_Meta_R:
case XKB_KEY_Alt_L:
case XKB_KEY_Alt_R:
case XKB_KEY_Super_L:
case XKB_KEY_Super_R:
state->auth_state = AUTH_STATE_INPUT_NOP;
damage_state(state);
schedule_indicator_clear(state);
schedule_password_clear(state);
break;
case XKB_KEY_d:
if (state->xkb.control) {
submit_password(state);
break;
}
// fallthrough
case XKB_KEY_c: /* fallthrough */
case XKB_KEY_u:
if (state->xkb.control) {
clear_password_buffer(&state->password);
state->auth_state = AUTH_STATE_CLEAR;
damage_state(state);
schedule_indicator_clear(state);
break;
}
// fallthrough
default:
if (codepoint) {
append_ch(&state->password, codepoint);
state->auth_state = AUTH_STATE_INPUT;
damage_state(state);
schedule_indicator_clear(state);
schedule_password_clear(state);
}
break;
}
}

View file

@ -1,189 +0,0 @@
#include <math.h>
#include <stdlib.h>
#include <wayland-client.h>
#include "cairo.h"
#include "background-image.h"
#include "swaylock/swaylock.h"
#define M_PI 3.14159265358979323846
const float TYPE_INDICATOR_RANGE = M_PI / 3.0f;
const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f;
static void set_color_for_state(cairo_t *cairo, struct swaylock_state *state,
struct swaylock_colorset *colorset) {
if (state->auth_state == AUTH_STATE_VALIDATING) {
cairo_set_source_u32(cairo, colorset->verifying);
} else if (state->auth_state == AUTH_STATE_INVALID) {
cairo_set_source_u32(cairo, colorset->wrong);
} else if (state->auth_state == AUTH_STATE_CLEAR) {
cairo_set_source_u32(cairo, colorset->cleared);
} else {
if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) {
cairo_set_source_u32(cairo, colorset->caps_lock);
} else if (state->xkb.caps_lock && !state->args.show_caps_lock_indicator &&
state->args.show_caps_lock_text) {
uint32_t inputtextcolor = state->args.colors.text.input;
state->args.colors.text.input = state->args.colors.text.caps_lock;
cairo_set_source_u32(cairo, colorset->input);
state->args.colors.text.input = inputtextcolor;
} else {
cairo_set_source_u32(cairo, colorset->input);
}
}
}
void render_frame(struct swaylock_surface *surface) {
struct swaylock_state *state = surface->state;
int buffer_width = surface->width * surface->scale;
int buffer_height = surface->height * surface->scale;
if (buffer_width == 0 || buffer_height == 0) {
return; // not yet configured
}
surface->current_buffer = get_next_buffer(state->shm,
surface->buffers, buffer_width, buffer_height);
if (surface->current_buffer == NULL) {
return;
}
cairo_t *cairo = surface->current_buffer->cairo;
cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
cairo_font_options_t *fo = cairo_font_options_create();
cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL);
cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL);
cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(surface->subpixel));
cairo_set_font_options(cairo, fo);
cairo_font_options_destroy(fo);
cairo_identity_matrix(cairo);
cairo_save(cairo);
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR || !surface->image) {
cairo_set_source_u32(cairo, state->args.colors.background);
cairo_paint(cairo);
} else {
render_background_image(cairo, surface->image,
state->args.mode, buffer_width, buffer_height);
}
cairo_restore(cairo);
cairo_identity_matrix(cairo);
int arc_radius = state->args.radius * surface->scale;
int arc_thickness = state->args.thickness * surface->scale;
float type_indicator_border_thickness =
TYPE_INDICATOR_BORDER_THICKNESS * surface->scale;
if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) {
// Draw circle
cairo_set_line_width(cairo, arc_thickness);
cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius,
0, 2 * M_PI);
set_color_for_state(cairo, state, &state->args.colors.inside);
cairo_fill_preserve(cairo);
set_color_for_state(cairo, state, &state->args.colors.ring);
cairo_stroke(cairo);
// Draw a message
char *text = NULL;
set_color_for_state(cairo, state, &state->args.colors.text);
cairo_select_font_face(cairo, state->args.font,
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(cairo, arc_radius / 3.0f);
switch (state->auth_state) {
case AUTH_STATE_VALIDATING:
text = "verifying";
break;
case AUTH_STATE_INVALID:
text = "wrong";
break;
case AUTH_STATE_CLEAR:
text = "cleared";
break;
case AUTH_STATE_INPUT:
case AUTH_STATE_INPUT_NOP:
case AUTH_STATE_BACKSPACE:
if (state->xkb.caps_lock && state->args.show_caps_lock_text) {
text = "Caps Lock";
}
break;
default:
break;
}
if (text) {
cairo_text_extents_t extents;
double x, y;
cairo_text_extents(cairo, text, &extents);
x = (buffer_width / 2) -
(extents.width / 2 + extents.x_bearing);
y = (buffer_height / 2) -
(extents.height / 2 + extents.y_bearing);
cairo_move_to(cairo, x, y);
cairo_show_text(cairo, text);
cairo_close_path(cairo);
cairo_new_sub_path(cairo);
}
// Typing indicator: Highlight random part on keypress
if (state->auth_state == AUTH_STATE_INPUT
|| state->auth_state == AUTH_STATE_BACKSPACE) {
static double highlight_start = 0;
highlight_start +=
(rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5;
cairo_arc(cairo, buffer_width / 2, buffer_height / 2,
arc_radius, highlight_start,
highlight_start + TYPE_INDICATOR_RANGE);
if (state->auth_state == AUTH_STATE_INPUT) {
if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) {
cairo_set_source_u32(cairo, state->args.colors.caps_lock_key_highlight);
} else {
cairo_set_source_u32(cairo, state->args.colors.key_highlight);
}
} else {
if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) {
cairo_set_source_u32(cairo, state->args.colors.caps_lock_bs_highlight);
} else {
cairo_set_source_u32(cairo, state->args.colors.bs_highlight);
}
}
cairo_stroke(cairo);
// Draw borders
cairo_set_source_u32(cairo, state->args.colors.separator);
cairo_arc(cairo, buffer_width / 2, buffer_height / 2,
arc_radius, highlight_start,
highlight_start + type_indicator_border_thickness);
cairo_stroke(cairo);
cairo_arc(cairo, buffer_width / 2, buffer_height / 2,
arc_radius, highlight_start + TYPE_INDICATOR_RANGE,
highlight_start + TYPE_INDICATOR_RANGE +
type_indicator_border_thickness);
cairo_stroke(cairo);
}
// Draw inner + outer border of the circle
set_color_for_state(cairo, state, &state->args.colors.line);
cairo_set_line_width(cairo, 2.0 * surface->scale);
cairo_arc(cairo, buffer_width / 2, buffer_height / 2,
arc_radius - arc_thickness / 2, 0, 2 * M_PI);
cairo_stroke(cairo);
cairo_arc(cairo, buffer_width / 2, buffer_height / 2,
arc_radius + arc_thickness / 2, 0, 2 * M_PI);
cairo_stroke(cairo);
}
wl_surface_set_buffer_scale(surface->surface, surface->scale);
wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0);
wl_surface_damage(surface->surface, 0, 0, surface->width, surface->height);
wl_surface_commit(surface->surface);
}
void render_frames(struct swaylock_state *state) {
struct swaylock_surface *surface;
wl_list_for_each(surface, &state->surfaces, link) {
render_frame(surface);
}
}

View file

@ -1,178 +0,0 @@
#include <assert.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <wlr/util/log.h>
#include <xkbcommon/xkbcommon.h>
#include "swaylock/swaylock.h"
#include "swaylock/seat.h"
static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
uint32_t format, int32_t fd, uint32_t size) {
struct swaylock_state *state = data;
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
close(fd);
wlr_log(WLR_ERROR, "Unknown keymap format %d, aborting", format);
exit(1);
}
char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (map_shm == MAP_FAILED) {
close(fd);
wlr_log(WLR_ERROR, "Unable to initialize keymap shm, aborting");
exit(1);
}
struct xkb_keymap *keymap = xkb_keymap_new_from_string(
state->xkb.context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
munmap(map_shm, size);
close(fd);
assert(keymap);
struct xkb_state *xkb_state = xkb_state_new(keymap);
assert(xkb_state);
xkb_keymap_unref(state->xkb.keymap);
xkb_state_unref(state->xkb.state);
state->xkb.keymap = keymap;
state->xkb.state = xkb_state;
}
static void keyboard_enter(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, struct wl_surface *surface, struct wl_array *keys) {
// Who cares
}
static void keyboard_leave(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, struct wl_surface *surface) {
// Who cares
}
static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, uint32_t time, uint32_t key, uint32_t _key_state) {
struct swaylock_state *state = data;
enum wl_keyboard_key_state key_state = _key_state;
xkb_keysym_t sym = xkb_state_key_get_one_sym(state->xkb.state, key + 8);
uint32_t keycode = key_state == WL_KEYBOARD_KEY_STATE_PRESSED ?
key + 8 : 0;
uint32_t codepoint = xkb_state_key_get_utf32(state->xkb.state, keycode);
if (key_state == WL_KEYBOARD_KEY_STATE_PRESSED) {
swaylock_handle_key(state, sym, codepoint);
}
}
static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
uint32_t mods_locked, uint32_t group) {
struct swaylock_state *state = data;
xkb_state_update_mask(state->xkb.state,
mods_depressed, mods_latched, mods_locked, 0, 0, group);
int caps_lock = xkb_state_mod_name_is_active(state->xkb.state,
XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED);
if (caps_lock != state->xkb.caps_lock) {
state->xkb.caps_lock = caps_lock;
damage_state(state);
}
state->xkb.control = xkb_state_mod_name_is_active(state->xkb.state,
XKB_MOD_NAME_CTRL,
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
}
static void keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
int32_t rate, int32_t delay) {
// TODO
}
static const struct wl_keyboard_listener keyboard_listener = {
.keymap = keyboard_keymap,
.enter = keyboard_enter,
.leave = keyboard_leave,
.key = keyboard_key,
.modifiers = keyboard_modifiers,
.repeat_info = keyboard_repeat_info,
};
static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, struct wl_surface *surface,
wl_fixed_t surface_x, wl_fixed_t surface_y) {
wl_pointer_set_cursor(wl_pointer, serial, NULL, 0, 0);
}
static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, struct wl_surface *surface) {
// Who cares
}
static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) {
// Who cares
}
static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, uint32_t time, uint32_t button, uint32_t state) {
// Who cares
}
static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
uint32_t time, uint32_t axis, wl_fixed_t value) {
// Who cares
}
static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) {
// Who cares
}
static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer,
uint32_t axis_source) {
// Who cares
}
static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer,
uint32_t time, uint32_t axis) {
// Who cares
}
static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
uint32_t axis, int32_t discrete) {
// Who cares
}
static const struct wl_pointer_listener pointer_listener = {
.enter = wl_pointer_enter,
.leave = wl_pointer_leave,
.motion = wl_pointer_motion,
.button = wl_pointer_button,
.axis = wl_pointer_axis,
.frame = wl_pointer_frame,
.axis_source = wl_pointer_axis_source,
.axis_stop = wl_pointer_axis_stop,
.axis_discrete = wl_pointer_axis_discrete,
};
static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
enum wl_seat_capability caps) {
struct swaylock_seat *seat = data;
if (seat->pointer) {
wl_pointer_release(seat->pointer);
seat->pointer = NULL;
}
if (seat->keyboard) {
wl_keyboard_release(seat->keyboard);
seat->keyboard = NULL;
}
if ((caps & WL_SEAT_CAPABILITY_POINTER)) {
seat->pointer = wl_seat_get_pointer(wl_seat);
wl_pointer_add_listener(seat->pointer, &pointer_listener, NULL);
}
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) {
seat->keyboard = wl_seat_get_keyboard(wl_seat);
wl_keyboard_add_listener(seat->keyboard, &keyboard_listener, seat->state);
}
}
static void seat_handle_name(void *data, struct wl_seat *wl_seat,
const char *name) {
// Who cares
}
const struct wl_seat_listener seat_listener = {
.capabilities = seat_handle_capabilities,
.name = seat_handle_name,
};

View file

@ -1,155 +0,0 @@
#define _XOPEN_SOURCE // for crypt
#include <pwd.h>
#include <shadow.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <wlr/util/log.h>
#include "swaylock/swaylock.h"
#ifdef __GLIBC__
// GNU, you damn slimy bastard
#include <crypt.h>
#endif
static int comm[2][2];
static void clear_buffer(void *buf, size_t bytes) {
volatile char *buffer = buf;
volatile char zero = '\0';
for (size_t i = 0; i < bytes; ++i) {
buffer[i] = zero;
}
}
void run_child(void) {
/* This code runs as root */
struct passwd *pwent = getpwuid(getuid());
if (!pwent) {
wlr_log_errno(WLR_ERROR, "failed to getpwuid");
exit(EXIT_FAILURE);
}
char *encpw = pwent->pw_passwd;
if (strcmp(encpw, "x") == 0) {
struct spwd *swent = getspnam(pwent->pw_name);
if (!swent) {
wlr_log_errno(WLR_ERROR, "failed to getspnam");
exit(EXIT_FAILURE);
}
encpw = swent->sp_pwdp;
}
/* We don't need any additional logging here because the parent process will
* also fail here and will handle logging for us. */
if (setgid(getgid()) != 0) {
exit(EXIT_FAILURE);
}
if (setuid(getuid()) != 0) {
exit(EXIT_FAILURE);
}
/* This code does not run as root */
wlr_log(WLR_DEBUG, "prepared to authorize user %s", pwent->pw_name);
size_t size;
char *buf;
while (1) {
ssize_t amt;
amt = read(comm[0][0], &size, sizeof(size));
if (amt == 0) {
break;
} else if (amt < 0) {
wlr_log_errno(WLR_ERROR, "read pw request");
}
wlr_log(WLR_DEBUG, "received pw check request");
buf = malloc(size);
if (!buf) {
wlr_log_errno(WLR_ERROR, "failed to malloc pw buffer");
exit(EXIT_FAILURE);
}
size_t offs = 0;
do {
amt = read(comm[0][0], &buf[offs], size - offs);
if (amt <= 0) {
wlr_log_errno(WLR_ERROR, "failed to read pw");
exit(EXIT_FAILURE);
}
offs += (size_t)amt;
} while (offs < size);
bool result = false;
char *c = crypt(buf, encpw);
if (c == NULL) {
wlr_log_errno(WLR_ERROR, "crypt");
}
result = strcmp(c, encpw) == 0;
if (write(comm[1][1], &result, sizeof(result)) != sizeof(result)) {
wlr_log_errno(WLR_ERROR, "failed to write pw check result");
clear_buffer(buf, size);
exit(EXIT_FAILURE);
}
clear_buffer(buf, size);
free(buf);
}
clear_buffer(encpw, strlen(encpw));
exit(EXIT_SUCCESS);
}
void initialize_pw_backend(void) {
if (geteuid() != 0) {
wlr_log(WLR_ERROR, "swaylock needs to be setuid to read /etc/shadow");
exit(EXIT_FAILURE);
}
if (pipe(comm[0]) != 0) {
wlr_log_errno(WLR_ERROR, "failed to create pipe");
exit(EXIT_FAILURE);
}
if (pipe(comm[1]) != 0) {
wlr_log_errno(WLR_ERROR, "failed to create pipe");
exit(EXIT_FAILURE);
}
pid_t child = fork();
if (child == 0) {
close(comm[0][1]);
close(comm[1][0]);
run_child();
} else if (child < 0) {
wlr_log_errno(WLR_ERROR, "failed to fork");
exit(EXIT_FAILURE);
}
close(comm[0][0]);
close(comm[1][1]);
if (setgid(getgid()) != 0) {
wlr_log_errno(WLR_ERROR, "Unable to drop root");
exit(EXIT_FAILURE);
}
if (setuid(getuid()) != 0) {
wlr_log_errno(WLR_ERROR, "Unable to drop root");
exit(EXIT_FAILURE);
}
}
bool attempt_password(struct swaylock_password *pw) {
bool result = false;
size_t len = pw->len + 1;
size_t offs = 0;
if (write(comm[0][1], &len, sizeof(len)) < 0) {
wlr_log_errno(WLR_ERROR, "Failed to request pw check");
goto ret;
}
do {
ssize_t amt = write(comm[0][1], &pw->buffer[offs], len - offs);
if (amt < 0) {
wlr_log_errno(WLR_ERROR, "Failed to write pw buffer");
goto ret;
}
offs += amt;
} while (offs < len);
if (read(comm[1][0], &result, sizeof(result)) != sizeof(result)) {
wlr_log_errno(WLR_ERROR, "Failed to read pw result");
goto ret;
}
wlr_log(WLR_DEBUG, "pw result: %d", result);
ret:
clear_password_buffer(pw);
return result;
}

View file

@ -1,167 +0,0 @@
swaylock(1)
# NAME
swaylock - Screen locker for Wayland
# SYNOPSIS
_swaylock_ [options...]
Locks your Wayland session.
# OPTIONS
*-C, --config* <path>
The config file to use. By default, the following paths are checked:
_$HOME/.swaylock/config_, _$XDG\_CONFIG\_HOME/swaylock/config_, and
_SYSCONFDIR/swaylock/config_. All flags aside from this one are valid
options in the configuration file using the format _long-option=value_.
For options such as _ignore-empty-password_, just supply the _long-option_.
All leading dashes should be omitted and the equals sign is required for
flags that take an argument.
*-e, --ignore-empty-password*
When an empty password is provided by the user, do not validate it.
*-f, --daemonize*
Detach from the controlling terminal after locking.
Note: this is the default behavior of i3lock.
*-h, --help*
Show help message and quit.
*-v, --version*
Show the version number and quit.
# APPEARANCE
*-u, --no-unlock-indicator*
Disable the unlock indicator.
*-i, --image* [<output>:]<path>
Display the given image, optionally only on the given output. Use -c to set
a background color.
*-L, --disable-caps-lock-text*
Disable the Caps Lock Text.
*-l, --indicator-caps-lock*
Show the current Caps Lock state also on the indicator.
*-s, --scaling*
Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_.
*-t, --tiling*
Same as --scaling=tile.
*-c, --color* <rrggbb[aa]>
Turn the screen into the given color. If -i is used, this sets the
background of the image to the given color. Defaults to white (FFFFFF), or
transparent (00000000) if an image is in use.
*--bs-hl-color* <rrggbb[aa]>
Sets the color of backspace highlight segments.
*--caps-lock-bs-hl-color* <rrggbb[aa]>
Sets the color of backspace highlight segments when Caps Lock is active.
*--caps-lock-bs-hl-color* <rrggbb[aa]>
Sets the color of the key press highlight segments when Caps Lock is active.
*--font* <font>
Sets the font of the text inside the indicator.
*--indicator-radius* <radius>
Sets the radius of the indicator to _radius_ pixels. The default value is
50.
*--indicator-thickness* <thickness>
Sets the thickness of the indicator to _thickness_ pixels. The default value
is 10.
*--inside-color* <rrggbb[aa]>
Sets the color of the inside of the indicator when typing or idle.
*--inside-clear-color* <rrggbb[aa]>
Sets the color of the inside of the indicator when cleared.
*--inside-caps-lock-color* <rrggbb[aa]>
Sets the color of the inside of the indicator when Caps Lock is active.
*--inside-ver-color* <rrggbb[aa]>
Sets the color of the inside of the indicator when verifying.
*--inside-wrong-color* <rrggbb[aa]>
Sets the color of the inside of the indicator when invalid.
*--key-hl-color* <rrggbb[aa]>
Sets the color of key press highlight segments.
*--line-color* <rrggbb[aa]>
Sets the color of the lines that separate the inside and outside of the
indicator when typing or idle.
*--line-clear-color* <rrggbb[aa]>
Sets the color of the lines that separate the inside and outside of the
indicator when cleared.
*--line-caps-lock-color* <rrggbb[aa]>
Sets the color of the line between the inside and ring when Caps Lock
is active.
*--line-ver-color* <rrggbb[aa]>
Sets the color of the lines that separate the inside and outside of the
indicator when verifying.
*--line-wrong-color* <rrggbb[aa]>
Sets the color of the lines that separate the inside and outside of the
indicator when invalid.
*-n, --line-uses-inside*
Use the color of the inside of the indicator for the line separating the
inside and outside of the indicator.
*-r, --line-uses-ring*
Use the outer ring's color for the line separating the inside and outside of
the indicator.
*--ring-color* <rrggbb[aa]>
Sets the color of the outside of the indicator when typing or idle.
*--ring-clear-color* <rrggbb[aa]>
Sets the color of the outside of the indicator when cleared.
*--ring-caps-lock-color* <rrggbb[aa]>
Sets the color of the ring of the indicator when Caps Lock is active.
*--ring-ver-color* <rrggbb[aa]>
Sets the color of the outside of the indicator when verifying.
*--ring-wrong-color* <rrggbb[aa]>
Sets the color of the outside of the indicator when invalid.
*--separator-color* <rrggbb[aa]>
Sets the color of the lines that separate highlight segments.
*--text-color* <rrggbb[aa]>
Sets the color of the text inside the indicator when typing or idle.
*--text-clear-color* <rrggbb[aa]>
Sets the color of the text inside the indicator when cleared.
*--text-caps-lock-color* <rrggbb[aa]>
Sets the color of the text when Caps Lock is active.
*--text-ver-color* <rrggbb[aa]>
Sets the color of the text inside the indicator when verifying.
*--text-wrong-color* <rrggbb[aa]>
Sets the color of the text inside the indicator when invalid.
# AUTHORS
Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
source contributors. For more information about sway development, see
https://github.com/swaywm/sway.