mirror of
https://github.com/swaywm/sway.git
synced 2024-11-21 15:31:28 +00:00
Split swaylock into separate project
This commit is contained in:
parent
4879d40695
commit
3fca8b8d22
|
@ -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_
|
||||
|
||||
Изпълнете следните команди:
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
||||
Εκτελέστε αυτές τις εντολές:
|
||||
|
||||
|
|
|
@ -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 :
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -37,13 +37,12 @@ Swayは沢山のディストリビューションで提供されています。"
|
|||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 \*\*
|
||||
* pam (オプション: swaylockとPAMで必要)
|
||||
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (manで必要です) \*
|
||||
* git \*
|
||||
|
||||
_\*コンパイルの時_
|
||||
|
||||
_\*\*オプション: swaybgとswaylockでのみ必要です_
|
||||
_\*\*オプション: swaybgでのみ必要です_
|
||||
|
||||
次のコマンドを実行してください:
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
||||
Выполните следующие команды:
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
||||
Виконайте ці команди:
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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.'
|
|
@ -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:'
|
|
@ -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',
|
||||
)
|
||||
|
|
1057
swaylock/main.c
1057
swaylock/main.c
File diff suppressed because it is too large
Load diff
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
178
swaylock/seat.c
178
swaylock/seat.c
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
Loading…
Reference in a new issue