From 90e2b03662847fda9843d2ed73369653a3bcbea6 Mon Sep 17 00:00:00 2001 From: James Magahern Date: Sun, 27 Jan 2019 22:39:30 -0800 Subject: Some code cleanup --- src/animation.c | 34 ++++++++++++++++++++++++--------- src/animation.h | 21 +++++++++++++++----- src/main.c | 44 +++++++++++++++++++++++++++++++----------- src/render.c | 59 +++++++++++++++++++-------------------------------------- 4 files changed, 93 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/animation.c b/src/animation.c index 15093d3..ecefb97 100644 --- a/src/animation.c +++ b/src/animation.c @@ -7,15 +7,6 @@ #include "animation.h" #include -anim_time_interval_t anim_now() -{ - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC_RAW, &ts); - - long ms = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); - return (ms / 1000.0); -} - /* * Easing functions */ @@ -31,4 +22,29 @@ double anim_quad_ease_out(double p) return -(p * (p - 2.0)); } +/* + * Convenience calculation functions + */ + +anim_time_interval_t anim_now() +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + + long ms = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); + return (ms / 1000.0); +} + +double anim_progress(animation_t *anim, const double duration) +{ + const anim_time_interval_t now = anim_now(); + double progress = (now - anim->start_time) / duration; + return (anim->direction == IN) ? progress : (1.0 - progress); +} + +bool anim_complete(animation_t *anim, const double progress) +{ + return (anim->direction == IN) ? progress >= 1.0 : progress <= 0.0; +} + diff --git a/src/animation.h b/src/animation.h index 108fbe2..54adb70 100644 --- a/src/animation.h +++ b/src/animation.h @@ -26,20 +26,21 @@ typedef enum { ASpinnerAnimation, } AnimationType; +// Cursor flash animation typedef struct { - bool cursor_animating; - double cursor_fade_direction; + bool cursor_animating; } CursorAnimation; +// Logo transition in/out animation typedef struct { - AnimationDirection direction; } LogoAnimation; +// Red flash for incorrect password typedef struct { - AnimationDirection direction; unsigned flash_count; } RedFlashAnimation; +// Spinner shown when checking password typedef struct { double rotation; } SpinnerAnimation; @@ -58,13 +59,23 @@ typedef struct { bool completed; anim_time_interval_t start_time; + AnimationDirection direction; + AnimationCompletion completion_func; void *completion_func_context; } animation_t; -// Convenience: returns current time as anim_time_interval_t +// Convenience functions + +// returns current time as anim_time_interval_t anim_time_interval_t anim_now(); +// Returns normalized progress based on start time of `anim` and `duration` +double anim_progress(animation_t *anim, const double duration); + +// Returns true if `anim` is complete depending on direction +bool anim_complete(animation_t *anim, const double progress); + // Easing functions double anim_qubic_ease_out(double p); double anim_quad_ease_out(double p); diff --git a/src/main.c b/src/main.c index f7b75d3..3eebc55 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,8 @@ static const int kXSecureLockCharFD = 0; static const int kDefaultWidth = 1024; static const int kDefaultHeight = 768; +static const char *kDefaultFont = "Input Mono 22"; + static inline saver_state_t* saver_state(void *c) { return (saver_state_t *)c; @@ -28,6 +30,25 @@ static inline saver_state_t* saver_state(void *c) static void clear_password(saver_state_t *state); static void accept_password(saver_state_t *state); +static int poll_events(saver_state_t *state); + +static void handle_key_event(saver_state_t *state, XKeyEvent *event); +static void handle_xsl_key_input(saver_state_t *state, const char c); +static void window_changed_size(saver_state_t *state, XConfigureEvent *event); + +static void ending_animation_completed(struct animation_t *animation, void *context); +static void authentication_accepted(saver_state_t *state); +static void authentication_rejected(saver_state_t *state); + +static void update(saver_state_t *state); +static void draw(saver_state_t *state); +static int runloop(cairo_surface_t *surface); + +void callback_show_info(const char *info_msg, void *context); +void callback_show_error(const char *error_msg, void *context); +void callback_prompt_user(const char *prompt, void *context); +void callback_authentication_result(int result, void *context); + /* * Event handling */ @@ -40,6 +61,11 @@ static void window_changed_size(saver_state_t *state, XConfigureEvent *event) cairo_xlib_surface_set_size(state->surface, event->width, event->height); } +// The following two methods are separate methods for processing input: +// The first one `handle_xsl_key_input` is for handling input via the XSecureLock +// file descriptor, which basically gives us TTY keycodes. The second handles +// input via X11, which is really only used for testing (when the locker is being +// run inside a window during development). static void handle_xsl_key_input(saver_state_t *state, const char c) { if (!state->input_allowed) return; @@ -76,6 +102,8 @@ static void handle_xsl_key_input(saver_state_t *state, const char c) } } +// This input handler is only when the locker is being run in "X11 mode" for development +// (See comment above for why this is separate) static void handle_key_event(saver_state_t *state, XKeyEvent *event) { if (!state->input_allowed) return; @@ -195,9 +223,7 @@ static void authentication_accepted(saver_state_t *state) .type = ALogoAnimation, .completion_func = ending_animation_completed, .completion_func_context = state, - .anim.logo_anim = { - .direction = true - } + .direction = OUT, }; schedule_animation(state, out_animation); } @@ -206,9 +232,7 @@ static void authentication_rejected(saver_state_t *state) { animation_t flash_animation = { .type = ARedFlashAnimation, - .anim.redflash_anim = { - .direction = IN - } + .direction = IN, }; schedule_animation(state, flash_animation); @@ -271,7 +295,7 @@ static int runloop(cairo_surface_t *surface) // Initialize pango context PangoLayout *pango_layout = pango_cairo_create_layout(cr); - PangoFontDescription *status_font = pango_font_description_from_string("Input Mono 22"); + PangoFontDescription *status_font = pango_font_description_from_string(kDefaultFont); saver_state_t state = { 0 }; state.ctx = cr; @@ -288,8 +312,8 @@ static int runloop(cairo_surface_t *surface) // Cursor animation -- repeats indefinitely animation_t cursor_animation = { .type = ACursorAnimation, + .direction = OUT, .anim.cursor_anim = { - .cursor_fade_direction = -1.0, .cursor_animating = true } }; @@ -298,9 +322,7 @@ static int runloop(cairo_surface_t *surface) // Logo incoming animation animation_t logo_animation = { .type = ALogoAnimation, - .anim.logo_anim = { - .direction = IN - } + .direction = IN, }; schedule_animation(&state, logo_animation); diff --git a/src/render.c b/src/render.c index 908238e..b6a70d4 100644 --- a/src/render.c +++ b/src/render.c @@ -46,17 +46,14 @@ static void update_single_animation(saver_state_t *state, animation_t *anim) if (ca->cursor_animating) { if (!state->is_processing) { - const double cursor_fade_speed = 0.05; - if (ca->cursor_fade_direction > 0) { - state->cursor_opacity += cursor_fade_speed; - if (state->cursor_opacity > 1.0) { - ca->cursor_fade_direction *= -1; - } - } else { - state->cursor_opacity -= cursor_fade_speed; - if (state->cursor_opacity <= 0.0) { - ca->cursor_fade_direction *= -1; - } + const double fade_duration = 0.5; + double progress = anim_progress(anim, fade_duration); + + state->cursor_opacity = progress; + + if (anim_complete(anim, progress)) { + anim->direction = !anim->direction; + anim->start_time = anim_now(); } } else { state->cursor_opacity = 1.0; @@ -68,49 +65,27 @@ static void update_single_animation(saver_state_t *state, animation_t *anim) else if (anim->type == ALogoAnimation) { const double logo_duration = 0.6; - anim_time_interval_t now = anim_now(); - double progress = (now - anim->start_time) / logo_duration; + double progress = anim_progress(anim, logo_duration); progress = anim_qubic_ease_out(progress); - // Check for reverse direction - if (anim->anim.logo_anim.direction) { - progress = 1.0 - progress; - } - state->logo_fill_progress = progress; state->password_opacity = progress; - bool completed = (progress >= 1.0); - if (anim->anim.logo_anim.direction) { - completed = (progress <= 0.0); - } - - anim->completed = completed; + anim->completed = anim_complete(anim, progress); } // Background red flash animation else if (anim->type == ARedFlashAnimation) { const double duration = 0.1; - anim_time_interval_t now = anim_now(); - double progress = (now - anim->start_time) / duration; + double progress = anim_progress(anim, duration); progress = anim_qubic_ease_out(progress); - // Check for reverse direction - if (anim->anim.redflash_anim.direction == OUT) { - progress = 1.0 - progress; - } - - AnimationDirection direction = anim->anim.redflash_anim.direction; - bool finished = (progress >= 1.0); - if (anim->anim.redflash_anim.direction) { - finished = (progress <= 0.0); - } - bool completed = false; - if (finished) { + if (anim_complete(anim, progress)) { + AnimationDirection direction = anim->direction; + anim->direction = !direction; anim->anim.redflash_anim.flash_count++; - anim->anim.redflash_anim.direction = !direction; anim->start_time = anim_now(); if (anim->anim.redflash_anim.flash_count > 3) { completed = true; @@ -231,12 +206,14 @@ void draw_logo(saver_state_t *state) cairo_t *cr = state->ctx; + // Draw bar background cairo_save(cr); cairo_set_source_rgb(cr, (208.0 / 255.0), (69.0 / 255.0), (255.0 / 255.0)); double fill_height = (state->canvas_height * state->logo_fill_progress); cairo_rectangle(cr, 0, 0, kLogoBackgroundWidth, fill_height); cairo_fill(cr); + // Common color -- transparent for logo cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); // Scale and draw logo @@ -305,6 +282,7 @@ void draw_password_field(saver_state_t *state) cairo_translate(cr, field_x, field_y - line_height - 8.0); + // Translate, rotate, translate; so rotation is happening about the center. double tr_amount = (spinner_dimensions.width * spinner_scale_factor) / 2.0; cairo_translate(cr, tr_amount, tr_amount); cairo_rotate(cr, spinner_anim.rotation); @@ -332,6 +310,7 @@ void draw_password_field(saver_state_t *state) double scale_factor = (asterisk_height / dimensions.height); double scaled_width = (dimensions.width * scale_factor); + // Asterisks are all rendered in a single group so their opacity can change (password_opacity) cairo_push_group(cr); for (unsigned i = 0; i < strlen(state->password_buffer); i++) { cairo_save(cr); @@ -350,7 +329,7 @@ void draw_password_field(saver_state_t *state) cairo_paint_with_alpha(cr, state->password_opacity); cairo_restore(cr); cairo_pattern_destroy(asterisk_pattern); - + // Draw cursor cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, MIN(state->password_opacity, state->cursor_opacity)); if (!state->is_processing) { -- cgit v1.2.3