From: Ray Strode Date: Mon, 29 Sep 2008 04:02:48 +0000 (-0400) Subject: Add new "solar" plugin by Charlie Brej X-Git-Tag: 0.6.0~104 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2fa348c7765ca0f6769aa1bb4c9b043890f5b33f;p=thirdparty%2Fplymouth.git Add new "solar" plugin by Charlie Brej This one is designed to fit in with the F10 Solar theme. It features a sun with blue flares. --- diff --git a/src/plugins/splash/solar/Makefile.am b/src/plugins/splash/solar/Makefile.am new file mode 100644 index 00000000..d4e5fe3b --- /dev/null +++ b/src/plugins/splash/solar/Makefile.am @@ -0,0 +1,29 @@ +INCLUDES = -I$(top_srcdir) \ + -I$(srcdir)/../../../libply \ + -I$(srcdir)/../../../libplybootsplash \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../.. \ + -I$(srcdir)/.. \ + -I$(srcdir) + +plugindir = $(libdir)/plymouth +plugin_LTLIBRARIES = solar.la + +solar_la_CFLAGS = $(PLYMOUTH_CFLAGS) \ + -DPLYMOUTH_IMAGE_DIR=\"$(datadir)/plymouth/\" \ + -DPLYMOUTH_LOGO_FILE=\"$(logofile)\" \ + -DPLYMOUTH_BACKGROUND_COLOR=$(background_color) \ + -DPLYMOUTH_BACKGROUND_END_COLOR=$(background_end_color) \ + -DPLYMOUTH_BACKGROUND_START_COLOR=$(background_start_color) +solar_la_LDFLAGS = -module -avoid-version -export-dynamic +solar_la_LIBADD = $(PLYMOUTH_LIBS) \ + ../../../libply/libply.la \ + ../../../libplybootsplash/libplybootsplash.la +solar_la_SOURCES = $(srcdir)/plugin.c + +plymouthdir = $(datadir)/plymouth/solar +plymouth_DATA = bullet.png entry.png lock.png \ + background.png star.png box.png + +EXTRA_DIST = $(plymouth_DATA) +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/plugins/splash/solar/background.png b/src/plugins/splash/solar/background.png new file mode 100644 index 00000000..5169ecd9 Binary files /dev/null and b/src/plugins/splash/solar/background.png differ diff --git a/src/plugins/splash/solar/box.png b/src/plugins/splash/solar/box.png new file mode 100644 index 00000000..54876e68 Binary files /dev/null and b/src/plugins/splash/solar/box.png differ diff --git a/src/plugins/splash/solar/bullet.png b/src/plugins/splash/solar/bullet.png new file mode 100644 index 00000000..dd527369 Binary files /dev/null and b/src/plugins/splash/solar/bullet.png differ diff --git a/src/plugins/splash/solar/entry.png b/src/plugins/splash/solar/entry.png new file mode 100644 index 00000000..a9f4157b Binary files /dev/null and b/src/plugins/splash/solar/entry.png differ diff --git a/src/plugins/splash/solar/lock.png b/src/plugins/splash/solar/lock.png new file mode 100644 index 00000000..7ddd3751 Binary files /dev/null and b/src/plugins/splash/solar/lock.png differ diff --git a/src/plugins/splash/solar/plugin.c b/src/plugins/splash/solar/plugin.c new file mode 100644 index 00000000..49d6d3a8 --- /dev/null +++ b/src/plugins/splash/solar/plugin.c @@ -0,0 +1,967 @@ +/* plugin.c - boot splash plugin + * + * Copyright (C) 2007, 2008 Red Hat, Inc. + * 2008 Charlie Brej + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: Charlie Brej + * Ray Strode + */ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ply-boot-splash-plugin.h" +#include "ply-buffer.h" +#include "ply-entry.h" +#include "ply-event-loop.h" +#include "ply-label.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-frame-buffer.h" +#include "ply-image.h" +#include "ply-utils.h" +#include "ply-window.h" + +#include + +#ifndef FRAMES_PER_SECOND +#define FRAMES_PER_SECOND 50 +#endif + +#define FLARE_FRAMES_PER_SECOND 10 +#define FLARE_COUNT 60 +#define FLARE_LINE_COUNT 4 + +typedef enum +{ + SPRITE_TYPE_STATIC, + SPRITE_TYPE_FLARE, +} sprite_type_t; + +typedef struct +{ + int x; + int y; + int z; + int oldx; + int oldy; + int oldz; + int refresh_me; + float opacity; + float brightness; + ply_image_t *image; + sprite_type_t type; + void* data; +} sprite_t; + + +typedef struct +{ + float stretch[FLARE_COUNT]; + float rotate_yz[FLARE_COUNT]; + float rotate_xy[FLARE_COUNT]; + float rotate_xz[FLARE_COUNT]; + float increase_speed[FLARE_COUNT]; + float z_offset_strength[FLARE_COUNT]; + float y_size[FLARE_COUNT]; + ply_image_t *image_a; + ply_image_t *image_b; + int frame_count; +} flare_t; + + +struct _ply_boot_splash_plugin +{ + ply_event_loop_t *loop; + ply_frame_buffer_t *frame_buffer; + ply_frame_buffer_area_t box_area, lock_area, logo_area; + ply_image_t *logo_image; + ply_image_t *lock_image; + ply_image_t *box_image; + ply_image_t *background_image; + ply_image_t *star_image; + + ply_image_t *scaled_background_image; + + ply_window_t *window; + + ply_entry_t *entry; + ply_label_t *label; + + ply_trigger_t *pending_password_answer; + ply_trigger_t *idle_trigger; + + ply_list_t *sprites; + + double now; + + uint32_t root_is_mounted : 1; + uint32_t is_visible : 1; +}; + +static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin); + + + +ply_boot_splash_plugin_t * +create_plugin (void) +{ + ply_boot_splash_plugin_t *plugin; + + srand ((int) ply_get_timestamp ()); + plugin = calloc (1, sizeof (ply_boot_splash_plugin_t)); + + plugin->logo_image = ply_image_new (PLYMOUTH_LOGO_FILE); + plugin->lock_image = ply_image_new (PLYMOUTH_IMAGE_DIR "solar/lock.png"); + plugin->box_image = ply_image_new (PLYMOUTH_IMAGE_DIR "solar/box.png"); + plugin->background_image = ply_image_new (PLYMOUTH_IMAGE_DIR "solar/background.png"); + plugin->star_image = ply_image_new (PLYMOUTH_IMAGE_DIR "solar/star.png"); + plugin->entry = ply_entry_new (PLYMOUTH_IMAGE_DIR "solar"); + plugin->label = ply_label_new (); + plugin->sprites = ply_list_new(); + return plugin; +} + +#ifdef PLY_ENABLE_GDM_TRANSITION +static void +tell_gdm_to_transition (void) +{ + int fd; + + fd = creat ("/var/spool/gdm/force-display-on-active-vt", 0644); + close (fd); +} +#endif + +void +destroy_plugin (ply_boot_splash_plugin_t *plugin) +{ + if (plugin == NULL) + return; + + + if (plugin->loop != NULL) + { + ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + plugin); + detach_from_event_loop (plugin); + } + + ply_image_free (plugin->logo_image); + ply_image_free (plugin->lock_image); + ply_image_free (plugin->box_image); + + ply_image_free (plugin->background_image); + ply_image_free (plugin->star_image); + + ply_entry_free (plugin->entry); + ply_label_free (plugin->label); + ply_list_free (plugin->sprites); + +#ifdef PLY_ENABLE_GDM_TRANSITION + if (plugin->is_visible) + tell_gdm_to_transition (); +#endif + + free (plugin); +} + + +static void +free_sprite (sprite_t* sprite) +{ + if (sprite) + { + switch (sprite->type){ + case SPRITE_TYPE_STATIC: + break; + case SPRITE_TYPE_FLARE: + { + flare_t *flare = sprite->data; + ply_image_free (flare->image_a); + ply_image_free (flare->image_b); + break; + } + } + + if (sprite->data) free(sprite->data); + free(sprite); + } + return; +} + + + +static sprite_t* +add_sprite (ply_boot_splash_plugin_t *plugin, ply_image_t *image, int type, void* data) +{ + sprite_t* new_sprite = calloc (1, sizeof (sprite_t)); + new_sprite->x = 0; + new_sprite->y = 0; + new_sprite->z = 0; + new_sprite->oldx = 0; + new_sprite->oldy = 0; + new_sprite->oldz = 0; + new_sprite->opacity = 1; + new_sprite->refresh_me = 1; + new_sprite->brightness = 1; + new_sprite->image = image; + new_sprite->type = type; + new_sprite->data = data; + ply_list_append_data (plugin->sprites, new_sprite); + return new_sprite; +} + + +static void +draw_background (ply_boot_splash_plugin_t *plugin, + ply_frame_buffer_area_t *area) +{ + ply_frame_buffer_area_t screen_area; + + if (area == NULL) + { + ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area); + area = &screen_area; + } + + ply_window_erase_area (plugin->window, area->x, area->y, + area->width, area->height); +} + +static void +flare_update (sprite_t* sprite, double time); + +static void +sprite_move (ply_boot_splash_plugin_t *plugin, sprite_t* sprite, double time) +{ + sprite->oldx = sprite->x; + sprite->oldy = sprite->y; + sprite->oldz = sprite->z; + switch (sprite->type){ + case SPRITE_TYPE_STATIC: + break; + case SPRITE_TYPE_FLARE: + flare_update (sprite, time); + break; + } +} +int sprite_compare_z(void *data_a, void *data_b) +{ + sprite_t *sprite_a = data_a; + sprite_t *sprite_b = data_b; + return sprite_a->z - sprite_b->z; +} + + +static void +sprite_list_sort (ply_boot_splash_plugin_t *plugin) +{ + ply_list_sort (plugin->sprites, &sprite_compare_z); +} + +static void +flare_reset (flare_t *flare, int index) +{ + flare->rotate_yz[index]=((float)(rand()%1000)/1000)*2*M_PI; + flare->rotate_xy[index]=((float)(rand()%1000)/1000)*2*M_PI; + flare->rotate_xz[index]=((float)(rand()%1000)/1000)*2*M_PI; + flare->y_size[index]=((float)(rand()%1000)/1000)*0.8+0.2; + flare->increase_speed[index] = ((float)(rand()%1000)/1000)*0.08+0.08; + flare->stretch[index]=((float)(rand()%1000)/1000)*0.1+0.3; + flare->z_offset_strength[index]=0.1; +} + +static void +flare_update (sprite_t* sprite, double time) +{ + int width; + int height; + flare_t *flare = sprite->data; + ply_image_t *old_image; + ply_image_t *new_image; + uint32_t * old_image_data; + uint32_t * new_image_data; + + flare->frame_count++; + if (flare->frame_count%(FRAMES_PER_SECOND/FLARE_FRAMES_PER_SECOND)){ + return; + } + + old_image = flare->image_a; + new_image = flare->image_b; + + old_image_data = ply_image_get_data (old_image); + new_image_data = ply_image_get_data (new_image); + + width = ply_image_get_width (new_image); + height = ply_image_get_height (new_image); + + + int b; + static int start=1; + + for (b=0; bstretch[b] += (flare->stretch[b] * flare->increase_speed[b]) * (1-(1/(3.01-flare->stretch[b]))); + flare->increase_speed[b]-=0.003; + flare->z_offset_strength[b]+=0.02; + + if (flare->stretch[b]>2 || flare->stretch[b]<0.2) + { + flare_reset (flare, b); + } + for (flare_line=0; flare_linestretch[b]-0.5)/flare->stretch[b]; + if (lift<0) continue; + lift = 1-lift; + lift *= lift; + lift = sqrt(1-lift); + for (theta =-M_PI_2; theta < M_PI_2; theta+=0.02) + { + int ix; + int iy; + + x=(cos(theta))*flare->stretch[b]; + y=(sin(theta)+lift)*flare->y_size[b]; + z=x*((float)flare_line/FLARE_LINE_COUNT-0.5)*0.2; + float strength = 1.1-(x/2)+flare->increase_speed[b]*3; + x+=4.5; + if ((x*x+y*y+z*z)<25) continue; + + strength = CLAMP(strength, 0, 1); + strength*=255; + + distance = sqrt(x*x+y*y); + angle = atan2 (y, x) + flare->rotate_xy[b]; + x = distance* cos(angle); + y = distance* sin(angle); + + distance = sqrt(z*z+y*y); + angle = atan2 (y, z) + flare->rotate_yz[b]; + z = distance* cos(angle); + y = distance* sin(angle); + + distance = sqrt(x*x+z*z); + angle = atan2 (z, x) + flare->rotate_xz[b]; + x = distance* cos(angle); + z = distance* sin(angle); + + + x*=34.1; + y*=34.1; + + x+=574-640+width; + y+=328-512+height; + + ix=x; + iy=y; + if (ix>=(width-1) || iy>=(height-1) || ix<=0 || iy<=0) continue; + + uint32_t colour = strength; + colour <<= 24; + old_image_data[ix + iy * width] = colour; + + } + } + } + + { + int x, y; + for (y = 1; y < (height-1); y++) + { + for (x = 1; x < (width-1); x++) + { + uint32_t value = 0; + value += (old_image_data[(x-1) + (y-1) * width]>>24)*1; + value += (old_image_data[ x + (y-1) * width]>>24)*2; + value += (old_image_data[(x+1) + (y-1) * width]>>24)*1; + value += (old_image_data[(x-1) + y * width]>>24)*2; + value += (old_image_data[ x + y * width]>>24)*8; + value += (old_image_data[(x+1) + y * width]>>24)*2; + value += (old_image_data[(x-1) + (y+1) * width]>>24)*1; + value += (old_image_data[ x + (y+1) * width]>>24)*2; + value += (old_image_data[(x+1) + (y+1) * width]>>24)*1; + value /=20.5; + value = (value<<24) | ((int)(value*0.7)<<16) | (value<<8) | (value<<0); + new_image_data[x +y * width] = value; + } + } + } + flare->image_a = new_image; + flare->image_b = old_image; + sprite->image = new_image; + sprite->refresh_me = 1; + return; +} + + + + +static void +animate_attime (ply_boot_splash_plugin_t *plugin, double time) +{ + ply_list_node_t *node; + long width, height; + + node = ply_list_get_first_node (plugin->sprites); + while(node) + { + sprite_t* sprite = ply_list_node_get_data (node); + sprite_move (plugin, sprite, time); + node = ply_list_get_next_node (plugin->sprites, node); + } + + sprite_list_sort (plugin); + + for(node = ply_list_get_first_node (plugin->sprites); node; node = ply_list_get_next_node (plugin->sprites, node)) + { + sprite_t* sprite = ply_list_node_get_data (node); + if (sprite->x != sprite->oldx || + sprite->y != sprite->oldy || + sprite->z != sprite->oldz || + sprite->refresh_me) + { + ply_frame_buffer_area_t sprite_area; + sprite->refresh_me=0; + + int width = ply_image_get_width (sprite->image); + int height= ply_image_get_height (sprite->image); + int x = sprite->x - sprite->oldx; + int y = sprite->y - sprite->oldy; + + if (x < width && x > -width && y < height && y > -height) + { + x=MIN(sprite->x, sprite->oldx); + y=MIN(sprite->y, sprite->oldy); + width =(MAX(sprite->x, sprite->oldx)-x)+ply_image_get_width (sprite->image); + height=(MAX(sprite->y, sprite->oldy)-y)+ply_image_get_height (sprite->image); + ply_window_draw_area (plugin->window, x, y, width, height); + } + else + { + ply_window_draw_area (plugin->window, sprite->x, sprite->y, width, height); + ply_window_draw_area (plugin->window, sprite->oldx, sprite->oldy, width, height); + } + } + } +} + +static void draw_password_entry (ply_boot_splash_plugin_t *plugin); +static void +on_timeout (ply_boot_splash_plugin_t *plugin) +{ + double sleep_time; + double now; + + now = ply_get_timestamp (); + + animate_attime (plugin, now); + plugin->now = now; + + sleep_time = 1.0 / FRAMES_PER_SECOND; + + ply_event_loop_watch_for_timeout (plugin->loop, + sleep_time, + (ply_event_loop_timeout_handler_t) + on_timeout, plugin); +} + +void +setup_solar (ply_boot_splash_plugin_t *plugin); + +static void +start_animation (ply_boot_splash_plugin_t *plugin) +{ + + ply_frame_buffer_area_t area; + assert (plugin != NULL); + assert (plugin->loop != NULL); + + ply_frame_buffer_get_size (plugin->frame_buffer, &area); + + plugin->now = ply_get_timestamp (); + ply_event_loop_watch_for_timeout (plugin->loop, + 1.0 / FRAMES_PER_SECOND, + (ply_event_loop_timeout_handler_t) + on_timeout, plugin); + + setup_solar (plugin); + on_timeout (plugin); + ply_window_draw_area (plugin->window, area.x, area.y, area.width, area.height); + +} + +static void +stop_animation (ply_boot_splash_plugin_t *plugin, + ply_trigger_t *trigger) +{ + int i; + ply_list_node_t *node; + + assert (plugin != NULL); + assert (plugin->loop != NULL); + + if (plugin->loop != NULL) + { + ply_event_loop_stop_watching_for_timeout (plugin->loop, + (ply_event_loop_timeout_handler_t) + on_timeout, plugin); + } + + ply_image_free(plugin->scaled_background_image); + for(node = ply_list_get_first_node (plugin->sprites); node; node = ply_list_get_next_node (plugin->sprites, node)) + { + sprite_t* sprite = ply_list_node_get_data (node); + free_sprite (sprite); + } + ply_list_remove_all_nodes (plugin->sprites); + +} + +static void +on_interrupt (ply_boot_splash_plugin_t *plugin) +{ + ply_event_loop_exit (plugin->loop, 1); + stop_animation (plugin, NULL); + ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); +} + +static void +detach_from_event_loop (ply_boot_splash_plugin_t *plugin) +{ + plugin->loop = NULL; +} + +void +on_keyboard_input (ply_boot_splash_plugin_t *plugin, + const char *keyboard_input, + size_t character_size) +{ + if (plugin->pending_password_answer == NULL) + return; + + ply_entry_add_bullet (plugin->entry); +} + +void +on_backspace (ply_boot_splash_plugin_t *plugin) +{ + ply_entry_remove_bullet (plugin->entry); +} + +void +on_enter (ply_boot_splash_plugin_t *plugin, + const char *text) +{ + if (plugin->pending_password_answer == NULL) + return; + + ply_trigger_pull (plugin->pending_password_answer, text); + plugin->pending_password_answer = NULL; + + ply_entry_hide (plugin->entry); + ply_entry_remove_all_bullets (plugin->entry); + start_animation (plugin); +} + +void +on_draw (ply_boot_splash_plugin_t *plugin, + int x, + int y, + int width, + int height) +{ + ply_frame_buffer_area_t clip_area; + clip_area.x = x; + clip_area.y = y; + clip_area.width = width; + clip_area.height = height; + + ply_frame_buffer_pause_updates (plugin->frame_buffer); + + if (plugin->pending_password_answer != NULL) + { + draw_background (plugin, &clip_area); + ply_entry_draw (plugin->entry); + ply_label_draw (plugin->label); + } + else { + ply_list_node_t *node; + for(node = ply_list_get_first_node (plugin->sprites); node; node = ply_list_get_next_node (plugin->sprites, node)){ + sprite_t* sprite = ply_list_node_get_data (node); + ply_frame_buffer_area_t sprite_area; + + sprite_area.x = sprite->x; + sprite_area.y = sprite->y; + sprite_area.width = ply_image_get_width (sprite->image); + sprite_area.height = ply_image_get_height (sprite->image); + + ply_frame_buffer_fill_with_argb32_data_at_opacity_with_clip (plugin->frame_buffer, + &sprite_area, &clip_area, 0, 0, + ply_image_get_data (sprite->image), sprite->opacity); + } + } + ply_frame_buffer_unpause_updates (plugin->frame_buffer); +} + +void +on_erase (ply_boot_splash_plugin_t *plugin, + int x, + int y, + int width, + int height) +{ + ply_frame_buffer_area_t area; + + area.x = x; + area.y = y; + area.width = width; + area.height = height; + + ply_frame_buffer_fill_with_gradient (plugin->frame_buffer, &area, + PLYMOUTH_BACKGROUND_START_COLOR, + PLYMOUTH_BACKGROUND_END_COLOR); +} + +void +add_window (ply_boot_splash_plugin_t *plugin, + ply_window_t *window) +{ + plugin->window = window; +} + +void +remove_window (ply_boot_splash_plugin_t *plugin, + ply_window_t *window) +{ + plugin->window = NULL; +} + +void +setup_solar (ply_boot_splash_plugin_t *plugin) +{ + ply_frame_buffer_area_t screen_area; + sprite_t *sprite; + int i; + float scalar; + int sword_width; + int star_size; + int offset_x; + int x, y; + int width = 290; + int height = 410; + + ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area); + plugin->scaled_background_image = ply_image_resize (plugin->background_image, screen_area.width, screen_area.height); + sprite = add_sprite (plugin, plugin->scaled_background_image, SPRITE_TYPE_STATIC, NULL); + sprite->z=-2000; + + sprite = add_sprite (plugin, plugin->logo_image, SPRITE_TYPE_STATIC, NULL); + sprite->z=-900; + + sprite = add_sprite (plugin, plugin->star_image, SPRITE_TYPE_STATIC, NULL); + sprite->x=screen_area.width-ply_image_get_width(plugin->star_image); + sprite->y=screen_area.height-ply_image_get_height(plugin->star_image); + sprite->z=-1001; + + flare_t *flare = malloc(sizeof(flare_t)); + + flare->image_a = ply_image_resize (plugin->star_image, width, height); + flare->image_b = ply_image_resize (plugin->star_image, width, height); + + sprite = add_sprite (plugin, flare->image_a, SPRITE_TYPE_FLARE, flare); + sprite->x=screen_area.width-width; + sprite->y=screen_area.height-height; + sprite->z=-1000; + + sprite_list_sort (plugin); + + uint32_t * old_image_data = ply_image_get_data (flare->image_a); + uint32_t * new_image_data = ply_image_get_data (flare->image_b); + + + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + new_image_data[x + y * width] = 0x0; + old_image_data[x + y * width] = 0x0; + } + } + + for (i=0; iframe_count=0; + flare_update(sprite, i); +} + +bool +show_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop, + ply_buffer_t *boot_buffer) +{ + assert (plugin != NULL); + assert (plugin->logo_image != NULL); + + ply_window_set_keyboard_input_handler (plugin->window, + (ply_window_keyboard_input_handler_t) + on_keyboard_input, plugin); + ply_window_set_backspace_handler (plugin->window, + (ply_window_backspace_handler_t) + on_backspace, plugin); + ply_window_set_enter_handler (plugin->window, + (ply_window_enter_handler_t) + on_enter, plugin); + + ply_window_set_draw_handler (plugin->window, + (ply_window_draw_handler_t) + on_draw, plugin); + + ply_window_set_erase_handler (plugin->window, + (ply_window_erase_handler_t) + on_erase, plugin); + + plugin->loop = loop; + + ply_trace ("loading logo image"); + if (!ply_image_load (plugin->logo_image)) + return false; + + ply_trace ("loading background image"); + if (!ply_image_load (plugin->background_image)) + return false; + + ply_trace ("loading star image"); + if (!ply_image_load (plugin->star_image)) + return false; + + ply_trace ("loading lock image"); + if (!ply_image_load (plugin->lock_image)) + return false; + + ply_trace ("loading box image"); + if (!ply_image_load (plugin->box_image)) + return false; + + ply_trace ("loading entry"); + if (!ply_entry_load (plugin->entry)) + return false; + + ply_trace ("setting graphics mode"); + if (!ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS)) + return false; + + plugin->frame_buffer = ply_window_get_frame_buffer (plugin->window); + + ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + plugin); + + ply_event_loop_watch_signal (plugin->loop, + SIGINT, + (ply_event_handler_t) + on_interrupt, plugin); + + ply_trace ("starting boot animation"); + + start_animation (plugin); + + plugin->is_visible = true; + + return true; +} + +void +update_status (ply_boot_splash_plugin_t *plugin, + const char *status) +{ + assert (plugin != NULL); +} + +void +hide_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop) +{ + assert (plugin != NULL); + + if (plugin->pending_password_answer != NULL) + { + ply_trigger_pull (plugin->pending_password_answer, ""); + plugin->pending_password_answer = NULL; + } + + ply_window_set_keyboard_input_handler (plugin->window, NULL, NULL); + ply_window_set_backspace_handler (plugin->window, NULL, NULL); + ply_window_set_enter_handler (plugin->window, NULL, NULL); + ply_window_set_draw_handler (plugin->window, NULL, NULL); + ply_window_set_erase_handler (plugin->window, NULL, NULL); + + if (plugin->loop != NULL) + { + stop_animation (plugin, NULL); + + ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + plugin); + detach_from_event_loop (plugin); + } + + plugin->frame_buffer = NULL; + plugin->is_visible = false; + + ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT); +} + +static void +show_password_prompt (ply_boot_splash_plugin_t *plugin, + const char *prompt) +{ + ply_frame_buffer_area_t area; + int x, y; + int entry_width, entry_height; + + uint32_t *box_data, *lock_data; + + assert (plugin != NULL); + + draw_background (plugin, NULL); + + ply_frame_buffer_get_size (plugin->frame_buffer, &area); + plugin->box_area.width = ply_image_get_width (plugin->box_image); + plugin->box_area.height = ply_image_get_height (plugin->box_image); + plugin->box_area.x = area.width / 2.0 - plugin->box_area.width / 2.0; + plugin->box_area.y = area.height / 2.0 - plugin->box_area.height / 2.0; + + plugin->lock_area.width = ply_image_get_width (plugin->lock_image); + plugin->lock_area.height = ply_image_get_height (plugin->lock_image); + + entry_width = ply_entry_get_width (plugin->entry); + entry_height = ply_entry_get_height (plugin->entry); + + x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0 + plugin->lock_area.width; + y = area.height / 2.0 - entry_height / 2.0; + + plugin->lock_area.x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0; + plugin->lock_area.y = area.height / 2.0 - plugin->lock_area.height / 2.0; + + box_data = ply_image_get_data (plugin->box_image); + ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, + &plugin->box_area, 0, 0, + box_data); + + ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y); + + lock_data = ply_image_get_data (plugin->lock_image); + ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, + &plugin->lock_area, 0, 0, + lock_data); + + if (prompt != NULL) + { + int label_width, label_height; + + ply_label_set_text (plugin->label, prompt); + label_width = ply_label_get_width (plugin->label); + label_height = ply_label_get_height (plugin->label); + + x = plugin->box_area.x + plugin->lock_area.width / 2; + y = plugin->box_area.y + plugin->box_area.height + label_height; + + ply_label_show (plugin->label, plugin->window, x, y); + } + +} + +void +ask_for_password (ply_boot_splash_plugin_t *plugin, + const char *prompt, + ply_trigger_t *answer) +{ + plugin->pending_password_answer = answer; + + if (ply_entry_is_hidden (plugin->entry)) + { + stop_animation (plugin, NULL); + show_password_prompt (plugin, prompt); + } + else + { + ply_entry_draw (plugin->entry); + ply_label_draw (plugin->label); + } +} + +void +on_root_mounted (ply_boot_splash_plugin_t *plugin) +{ + plugin->root_is_mounted = true; +} + +void +become_idle (ply_boot_splash_plugin_t *plugin, + ply_trigger_t *idle_trigger) +{ + stop_animation (plugin, idle_trigger); +} + +ply_boot_splash_plugin_interface_t * +ply_boot_splash_plugin_get_interface (void) +{ + static ply_boot_splash_plugin_interface_t plugin_interface = + { + .create_plugin = create_plugin, + .destroy_plugin = destroy_plugin, + .add_window = add_window, + .remove_window = remove_window, + .show_splash_screen = show_splash_screen, + .update_status = update_status, + .hide_splash_screen = hide_splash_screen, + .ask_for_password = ask_for_password, + .on_root_mounted = on_root_mounted, + .become_idle = become_idle + }; + + return &plugin_interface; +} + +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/plugins/splash/solar/star.png b/src/plugins/splash/solar/star.png new file mode 100644 index 00000000..797b5186 Binary files /dev/null and b/src/plugins/splash/solar/star.png differ