From d963b3d033ef31e3c0cbcd52f251b12b0e96ef71 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Mon, 30 Mar 2020 17:48:17 +0900 Subject: [PATCH] gsudo: Redesign --- apps/gsudo.c | 182 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 145 insertions(+), 37 deletions(-) diff --git a/apps/gsudo.c b/apps/gsudo.c index 39bf6196..e13815fc 100644 --- a/apps/gsudo.c +++ b/apps/gsudo.c @@ -20,51 +20,118 @@ #include #include #include +#include #define main __main_unused #include "sudo.c" #undef main -#define FONT_SIZE_MAIN 20 +#define FONT_SIZE_TITLE 20 +#define FONT_SIZE_MAIN 16 #define FONT_SIZE_PASSWD 25 +#define FONT_COLOR (rgb(0,0,0)) +#define FONT_RED (rgb(250,0,0)) +#define BUTTON_HEIGHT 28 +#define BUTTON_WIDTH 120 +#define BUTTON_PADDING 18 static yutani_t * yctx; static gfx_context_t * ctx; static yutani_window_t * window; +struct TTKButton _button_cancel = { + 0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "Cancel", 0 +}; + +struct TTKButton _button_authenticate = { + 410 - BUTTON_WIDTH - BUTTON_PADDING, 260, BUTTON_WIDTH, BUTTON_HEIGHT, "Authenticate", 0 +}; + +struct TTKButton * _down_button = NULL; + +static int in_button(struct TTKButton * button, struct yutani_msg_window_mouse_event * me) { + if (me->new_y >= button->y && me->new_y < button->y + button->height) { + if (me->new_x >= button->x && me->new_x < button->x + button->width) { + return 1; + } + } + return 0; +} + +static int set_hilight(struct TTKButton * button, int hilight) { + if (!button && (_button_cancel.hilight || _button_authenticate.hilight)) { + _button_cancel.hilight = 0; + _button_authenticate.hilight = 0; + return 1; + } else if (button && (button->hilight != hilight)) { + _button_cancel.hilight = 0; + _button_authenticate.hilight = 0; + button->hilight = hilight; + return 1; + } + return 0; +} + +static void redraw(char * username, char * password, int fails, char * argv[]) { + + sprite_t * prompt = create_sprite(420, 320, ALPHA_EMBEDDED); + gfx_context_t * myctx = init_graphics_sprite(prompt); + draw_fill(myctx, rgba(0,0,0,0)); + + /* Draw rounded rectangle */ + draw_rounded_rectangle(myctx, 10, 10, prompt->width - 20, prompt->height - 20, 10, rgba(0,0,0,200)); + blur_context_box(myctx, 10); + blur_context_box(myctx, 10); + draw_rounded_rectangle(myctx, 10, 10, prompt->width - 20, prompt->height - 20, 10, rgb(239,238,232)); + + /* Draw prompt messages */ + draw_sdf_string(myctx, 30, 30, "Authentication Required", FONT_SIZE_TITLE, FONT_COLOR, SDF_FONT_THIN); + draw_sdf_string(myctx, 30, 54, "Authentication is required to run the application", FONT_SIZE_MAIN, FONT_COLOR, SDF_FONT_THIN); + draw_sdf_string(myctx, 30, 72, argv[1], FONT_SIZE_MAIN, FONT_COLOR, SDF_FONT_THIN); + + char prompt_message[512]; + sprintf(prompt_message, "Enter password for '%s'", username); + draw_sdf_string(myctx, 30, 100, prompt_message, FONT_SIZE_MAIN, FONT_COLOR, SDF_FONT_THIN); + + if (fails) { + sprintf(prompt_message, "Try again. %d failures.", fails); + draw_sdf_string(myctx, 30, 146, prompt_message, FONT_SIZE_MAIN, FONT_RED, SDF_FONT_THIN); + } + + struct gradient_definition edge = {30, 114, rgb(0,120,220), rgb(0,120,220)}; + draw_rounded_rectangle_pattern(myctx, 30, 120, prompt->width - 70, 26, 4, gfx_vertical_gradient_pattern, &edge); + draw_rounded_rectangle(myctx, 32, 122, prompt->width - 74, 22, 3, rgb(250,250,250)); + + char password_circles[512] = {0};; + strcpy(password_circles, ""); + for (unsigned int i = 0; i < strlen(password) && i < 512/4; ++i) { + strcat(password_circles, "\007"); + } + draw_sdf_string(myctx, 33, 118, password_circles, FONT_SIZE_PASSWD, FONT_COLOR, SDF_FONT_THIN); + + draw_fill(ctx, rgba(0,0,0,200)); + draw_sprite(ctx, prompt, (ctx->width - prompt->width) / 2, (ctx->height - prompt->height) / 2); + + _button_cancel.x = (410 - 2 * (BUTTON_WIDTH + BUTTON_PADDING)) + (ctx->width - prompt->width) / 2; + _button_cancel.y = 260 + (ctx->height - prompt->height) / 2; + _button_authenticate.x = (410 - (BUTTON_WIDTH + BUTTON_PADDING)) + (ctx->width - prompt->width) / 2; + _button_authenticate.y = 260 + (ctx->height - prompt->height) / 2; + ttk_button_draw(ctx, &_button_cancel); + ttk_button_draw(ctx, &_button_authenticate); + + sprite_free(prompt); + free(myctx); + + flip(ctx); + yutani_flip(yctx, window); +} + static int graphical_callback(char * username, char * password, int fails, char * argv[]) { int i = 0; + + redraw(username, password, fails, argv); + while (1) { - draw_fill(ctx, rgba(0,0,0,200)); - int h = ctx->height-1; - int w = ctx->width-1; - draw_line(ctx, 0,0,0,h, rgb(255,0,0)); - draw_line(ctx, w,w,0,h, rgb(255,0,0)); - draw_line(ctx, 0,w,0,0, rgb(255,0,0)); - draw_line(ctx, 0,w,h,h, rgb(255,0,0)); - - char prompt_message[512]; - sprintf(prompt_message, "Enter password for '%s'", username); - draw_sdf_string(ctx, (ctx->width - draw_sdf_string_width(prompt_message, FONT_SIZE_MAIN, SDF_FONT_THIN)) / 2, 20, prompt_message, FONT_SIZE_MAIN, rgb(255, 255, 255), SDF_FONT_THIN); - - sprintf(prompt_message, "requested by %s", argv[1]); - draw_sdf_string(ctx, (ctx->width - draw_sdf_string_width(prompt_message, FONT_SIZE_MAIN, SDF_FONT_THIN)) / 2, 150, prompt_message, FONT_SIZE_MAIN, rgb(255, 255, 255), SDF_FONT_THIN); - - if (fails) { - sprintf(prompt_message, "Try again. %d failures.", fails); - draw_sdf_string(ctx, (ctx->width - draw_sdf_string_width(prompt_message, FONT_SIZE_MAIN, SDF_FONT_THIN)) / 2, 50, prompt_message, FONT_SIZE_MAIN, rgb(255, 0, 0), SDF_FONT_THIN); - - } - - char password_circles[512] = {0};; - strcpy(password_circles, ""); - for (unsigned int i = 0; i < strlen(password) && i < 512/4; ++i) { - strcat(password_circles, "\007"); - } - draw_sdf_string(ctx, (ctx->width - draw_sdf_string_width(password_circles, FONT_SIZE_PASSWD, SDF_FONT_THIN)) / 2, 80, password_circles, FONT_SIZE_PASSWD, rgb(255, 255, 255), SDF_FONT_THIN); - - flip(ctx); - yutani_flip(yctx, window); yutani_msg_t * msg = yutani_poll(yctx); @@ -86,9 +153,53 @@ static int graphical_callback(char * username, char * password, int fails, char password[i+1] = '\0'; i++; } + redraw(username, password, fails, argv); } } break; + case YUTANI_MSG_WINDOW_MOUSE_EVENT: + { + struct yutani_msg_window_mouse_event * me = (void*)msg->data; + int r = 0; + if (me->wid == window->wid) { + if (me->command == YUTANI_MOUSE_EVENT_DOWN) { + if (in_button(&_button_cancel, me)) { + r |= set_hilight(&_button_cancel, 2); + _down_button = &_button_cancel; + } else if (in_button(&_button_authenticate, me)) { + r |= set_hilight(&_button_authenticate, 2); + _down_button = &_button_authenticate; + } + } else if (me->command == YUTANI_MOUSE_EVENT_RAISE || me->command == YUTANI_MOUSE_EVENT_CLICK) { + if (_down_button) { + if (in_button(_down_button, me)) { + /* Handle button presses */ + if (_down_button == &_button_cancel) return 1; + else if (_down_button == &_button_authenticate) return 0; + _down_button->hilight = 0; + } + } + _down_button = NULL; + } + if (!me->buttons & YUTANI_MOUSE_BUTTON_LEFT) { + if (in_button(&_button_cancel, me)) { + r |= set_hilight(&_button_cancel, 1); + } else if (in_button(&_button_authenticate, me)) { + r |= set_hilight(&_button_authenticate, 1); + } else { + r |= set_hilight(NULL, 0); + } + } else if (_down_button) { + if (in_button(_down_button, me)) { + r |= set_hilight(_down_button, 2); + } else { + r |= set_hilight(NULL, 0); + } + } + } + if (r) redraw(username, password, fails, argv); + } + break; case YUTANI_MSG_WINDOW_CLOSE: case YUTANI_MSG_SESSION_END: return 1; @@ -109,14 +220,11 @@ int main(int argc, char ** argv) { return 1; } - int width = 300; - int height = 200; - - int left = (yctx->display_width - width) / 2; - int top = (yctx->display_height - height) / 2; + int width = yctx->display_width; + int height = yctx->display_height; window = yutani_window_create(yctx, width, height); - yutani_window_move(yctx, window, left, top); + yutani_window_move(yctx, window, 0, 0); yutani_window_advertise(yctx, window, "gsudo"); ctx = init_graphics_yutani_double_buffer(window);