]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
[two-step] Update to use new multihead interface
authorRay Strode <rstrode@redhat.com>
Wed, 16 Sep 2009 20:28:04 +0000 (16:28 -0400)
committerRay Strode <rstrode@redhat.com>
Mon, 28 Sep 2009 15:23:39 +0000 (11:23 -0400)
src/plugins/splash/two-step/plugin.c

index 7b70202bd2b20975da8b07239f9d568ef5f90fc7..d52a8e4beac1b33b2d35058c93708ee81082e9d4 100644 (file)
 #include "ply-label.h"
 #include "ply-list.h"
 #include "ply-logger.h"
-#include "ply-frame-buffer.h"
 #include "ply-image.h"
 #include "ply-key-file.h"
 #include "ply-trigger.h"
+#include "ply-pixel-buffer.h"
+#include "ply-pixel-display.h"
 #include "ply-utils.h"
-#include "ply-window.h"
 
 #include "ply-animation.h"
 #include "ply-progress-animation.h"
@@ -73,21 +73,26 @@ typedef enum {
    PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY
 } ply_boot_splash_display_type_t;
 
+typedef struct
+{
+  ply_boot_splash_plugin_t *plugin;
+  ply_pixel_display_t *display;
+  ply_entry_t *entry;
+  ply_animation_t *end_animation;
+  ply_progress_animation_t *progress_animation;
+  ply_label_t *label;
+  ply_rectangle_t box_area, lock_area;
+} view_t;
+
 struct _ply_boot_splash_plugin
 {
   ply_event_loop_t *loop;
   ply_boot_splash_mode_t mode;
-  ply_frame_buffer_t *frame_buffer;
-  ply_frame_buffer_area_t box_area, lock_area;
   ply_image_t *lock_image;
   ply_image_t *box_image;
   ply_image_t *corner_image;
-  ply_window_t *window;
+  ply_list_t *views;
 
-  ply_entry_t *entry;
-  ply_animation_t *animation;
-  ply_progress_animation_t *progress_animation;
-  ply_label_t *label;
   ply_boot_splash_display_type_t state;
 
   double animation_horizontal_alignment;
@@ -109,12 +114,287 @@ struct _ply_boot_splash_plugin
   uint32_t is_idle : 1;
 };
 
-static void add_handlers (ply_boot_splash_plugin_t *plugin);
-static void remove_handlers (ply_boot_splash_plugin_t *plugin);
 static void stop_animation (ply_boot_splash_plugin_t *plugin);
 
 static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin);
 
+static view_t *
+view_new (ply_boot_splash_plugin_t *plugin,
+          ply_pixel_display_t      *display)
+{
+  view_t *view;
+
+  view = calloc (1, sizeof (view_t));
+  view->plugin = plugin;
+  view->display = display;
+
+  view->entry = ply_entry_new (plugin->animation_dir);
+  view->end_animation = ply_animation_new (plugin->animation_dir,
+                                       "throbber-");
+  view->progress_animation = ply_progress_animation_new (plugin->animation_dir,
+                                                         "progress-");
+  ply_progress_animation_set_transition (view->progress_animation,
+                                         plugin->transition,
+                                         plugin->transition_duration);
+
+  view->label = ply_label_new ();
+
+  return view;
+}
+
+static void
+view_free (view_t *view)
+{
+
+  ply_entry_free (view->entry);
+  ply_animation_free (view->end_animation);
+  ply_progress_animation_free (view->progress_animation);
+  ply_label_free (view->label);
+
+  free (view);
+}
+
+static bool
+view_load (view_t *view)
+{
+  ply_trace ("loading entry");
+  if (!ply_entry_load (view->entry))
+    return false;
+
+  ply_trace ("loading animation");
+  if (!ply_animation_load (view->end_animation))
+    return false;
+
+  ply_trace ("loading progress animation");
+  if (!ply_progress_animation_load (view->progress_animation))
+    return false;
+
+  return true;
+}
+
+static bool
+load_views (ply_boot_splash_plugin_t *plugin)
+{
+  ply_list_node_t *node;
+  bool view_loaded;
+
+  view_loaded = false;
+  node = ply_list_get_first_node (plugin->views);
+
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      view_t *view;
+
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
+
+      if (view_load (view))
+        view_loaded = true;
+
+      node = next_node;
+    }
+
+  return view_loaded;
+}
+
+static void
+view_redraw (view_t *view)
+{
+  unsigned long screen_width, screen_height;
+
+  screen_width = ply_pixel_display_get_width (view->display);
+  screen_height = ply_pixel_display_get_height (view->display);
+
+  ply_pixel_display_draw_area (view->display, 0, 0,
+                               screen_width, screen_height);
+}
+
+static void
+redraw_views (ply_boot_splash_plugin_t *plugin)
+{
+  ply_list_node_t *node;
+
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      view_t *view;
+
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
+
+      view_redraw (view);
+
+      node = next_node;
+    }
+}
+
+static void
+pause_views (ply_boot_splash_plugin_t *plugin)
+{
+  ply_list_node_t *node;
+
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      view_t *view;
+
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
+
+      ply_pixel_display_pause_updates (view->display);
+
+      node = next_node;
+    }
+}
+
+static void
+unpause_views (ply_boot_splash_plugin_t *plugin)
+{
+  ply_list_node_t *node;
+
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      view_t *view;
+
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
+
+      ply_pixel_display_unpause_updates (view->display);
+
+      node = next_node;
+    }
+}
+
+static void
+view_start_end_animation (view_t         *view,
+                          ply_trigger_t  *trigger)
+{
+  ply_boot_splash_plugin_t *plugin;
+
+  long x, y;
+  long width, height;
+  unsigned long screen_width, screen_height;
+
+  plugin = view->plugin;
+
+  screen_width = ply_pixel_display_get_width (view->display);
+  screen_height = ply_pixel_display_get_height (view->display);
+  width = ply_animation_get_width (view->end_animation);
+  height = ply_animation_get_height (view->end_animation);
+  x = plugin->animation_horizontal_alignment * screen_width - width / 2.0;
+  y = plugin->animation_vertical_alignment * screen_height - height / 2.0;
+
+  ply_animation_start (view->end_animation,
+                       plugin->loop,
+                       view->display,
+                       trigger, x, y);
+}
+
+static void
+view_start_progress_animation (view_t *view)
+{
+  ply_boot_splash_plugin_t *plugin;
+
+  long x, y;
+  long width, height;
+  unsigned long screen_width, screen_height;
+
+  assert (view != NULL);
+
+  plugin = view->plugin;
+
+  plugin->is_idle = false;
+
+  screen_width = ply_pixel_display_get_width (view->display);
+  screen_height = ply_pixel_display_get_height (view->display);
+
+  ply_pixel_display_draw_area (view->display, 0, 0,
+                               screen_width, screen_height);
+
+  if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN)
+    {
+      view_start_end_animation (view, NULL);
+      return;
+    }
+
+  width = ply_progress_animation_get_width (view->progress_animation);
+  height = ply_progress_animation_get_height (view->progress_animation);
+  x = plugin->animation_horizontal_alignment * screen_width - width / 2.0;
+  y = plugin->animation_vertical_alignment * screen_height - height / 2.0;
+  ply_progress_animation_show (view->progress_animation,
+                               view->display, x, y);
+
+  ply_pixel_display_draw_area (view->display, x, y, width, height);
+}
+
+static void
+view_show_prompt (view_t     *view,
+                  const char *prompt)
+{
+  ply_boot_splash_plugin_t *plugin;
+  int x, y;
+  int entry_width, entry_height;
+
+  assert (view != NULL);
+
+  plugin = view->plugin;
+
+  if (ply_entry_is_hidden (view->entry))
+    {
+      unsigned long screen_width, screen_height;
+
+      screen_width = ply_pixel_display_get_width (view->display);
+      screen_height = ply_pixel_display_get_height (view->display);
+
+      view->box_area.width = ply_image_get_width (plugin->box_image);
+      view->box_area.height = ply_image_get_height (plugin->box_image);
+      view->box_area.x = screen_width / 2.0 - view->box_area.width / 2.0;
+      view->box_area.y = screen_height / 2.0 - view->box_area.height / 2.0;
+
+      view->lock_area.width = ply_image_get_width (plugin->lock_image);
+      view->lock_area.height = ply_image_get_height (plugin->lock_image);
+
+      entry_width = ply_entry_get_width (view->entry);
+      entry_height = ply_entry_get_height (view->entry);
+
+      x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0 + view->lock_area.width;
+      y = screen_height / 2.0 - entry_height / 2.0;
+
+      view->lock_area.x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0;
+      view->lock_area.y = screen_height / 2.0 - view->lock_area.height / 2.0;
+
+      ply_entry_show (view->entry, plugin->loop, view->display, x, y);
+    }
+
+  if (prompt != NULL)
+    {
+      int label_width, label_height;
+
+      ply_label_set_text (view->label, prompt);
+      label_width = ply_label_get_width (view->label);
+      label_height = ply_label_get_height (view->label);
+
+      x = view->box_area.x + view->lock_area.width / 2;
+      y = view->box_area.y + view->box_area.height;
+
+      ply_label_show (view->label, view->display, x, y);
+    }
+}
+
+static void
+view_hide_prompt (view_t *view)
+{
+  assert (view != NULL);
+
+  ply_entry_hide (view->entry);
+  ply_label_hide (view->label);
+}
+
 static ply_boot_splash_plugin_t *
 create_plugin (ply_key_file_t *key_file)
 {
@@ -142,8 +422,6 @@ create_plugin (ply_key_file_t *key_file)
   plugin->corner_image = ply_image_new (image_path);
   free (image_path);
 
-  plugin->entry = ply_entry_new (image_dir);
-  plugin->label = ply_label_new ();
   plugin->animation_dir = image_dir;
 
   alignment = ply_key_file_get_value (key_file, "two-step", "HorizontalAlignment");
@@ -160,7 +438,6 @@ create_plugin (ply_key_file_t *key_file)
     plugin->animation_vertical_alignment = .5;
   free (alignment);
 
-
   plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_NONE;
   transition = ply_key_file_get_value (key_file, "two-step", "Transition");
   if (transition != NULL)
@@ -199,17 +476,42 @@ create_plugin (ply_key_file_t *key_file)
 
   free (color);
 
+  plugin->views = ply_list_new ();
+
   return plugin;
 }
 
+static void
+free_views (ply_boot_splash_plugin_t *plugin)
+{
+  ply_list_node_t *node;
+
+  node = ply_list_get_first_node (plugin->views);
+
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      view_t *view;
+
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
+
+      view_free (view);
+      ply_list_remove_node (plugin->views, node);
+
+      node = next_node;
+    }
+
+  ply_list_free (plugin->views);
+  plugin->views = NULL;
+}
+
 static void
 destroy_plugin (ply_boot_splash_plugin_t *plugin)
 {
   if (plugin == NULL)
     return;
 
-  remove_handlers (plugin);
-
   if (plugin->loop != NULL)
     {
       stop_animation (plugin);
@@ -226,86 +528,66 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
   if (plugin->corner_image != NULL)
     ply_image_free (plugin->corner_image);
 
-  ply_entry_free (plugin->entry);
-  ply_animation_free (plugin->animation);
-  ply_progress_animation_free (plugin->progress_animation);
-  ply_label_free (plugin->label);
+  free_views (plugin);
 
   free (plugin);
 }
 
 static void
-draw_background (ply_boot_splash_plugin_t *plugin,
-                 ply_frame_buffer_area_t  *area)
+start_end_animation (ply_boot_splash_plugin_t *plugin,
+                     ply_trigger_t            *trigger)
 {
-  ply_frame_buffer_area_t screen_area;
 
-  if (area == NULL)
+  ply_list_node_t *node;
+
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
     {
-      ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area);
-      area = &screen_area;
-    }
+      ply_list_node_t *next_node;
+      view_t *view;
 
-  ply_window_erase_area (plugin->window, area->x, area->y,
-                         area->width, area->height);
-}
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
 
-static void
-begin_animation (ply_boot_splash_plugin_t *plugin,
-                 ply_trigger_t            *trigger)
-{
-  long width, height;
-  ply_frame_buffer_area_t area;
-  ply_frame_buffer_get_size (plugin->frame_buffer, &area);
-  width = ply_animation_get_width (plugin->animation);
-  height = ply_animation_get_height (plugin->animation);
-  ply_animation_start (plugin->animation,
-                       plugin->loop,
-                       plugin->window,
-                       trigger,
-                       plugin->animation_horizontal_alignment * area.width - width / 2.0,
-                       plugin->animation_vertical_alignment * area.height - height / 2.0);
+      ply_progress_animation_hide (view->progress_animation);
+      ply_trigger_ignore_next_pull (trigger);
+      view_start_end_animation (view, trigger);
+
+      node = next_node;
+    }
+  ply_trigger_pull (trigger, NULL);
 }
 
 static void
-start_animation (ply_boot_splash_plugin_t *plugin)
+start_progress_animation (ply_boot_splash_plugin_t *plugin)
 {
-
-  long width, height;
-  ply_frame_buffer_area_t area;
-  assert (plugin != NULL);
-  assert (plugin->loop != NULL);
+  ply_list_node_t *node;
 
   if (plugin->is_animating)
      return;
 
-  plugin->is_idle = false;
-
-  draw_background (plugin, NULL);
-
-  if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN)
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
     {
-      begin_animation (plugin, NULL);
-      return;
-    }
+      ply_list_node_t *next_node;
+      view_t *view;
 
-  ply_frame_buffer_get_size (plugin->frame_buffer, &area);
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
 
-  width = ply_progress_animation_get_width (plugin->progress_animation);
-  height = ply_progress_animation_get_height (plugin->progress_animation);
-  ply_progress_animation_show (plugin->progress_animation,
-                               plugin->window,
-                               plugin->animation_horizontal_alignment * area.width - width / 2.0,
-                               plugin->animation_vertical_alignment * area.height - height / 2.0);
+      view_start_progress_animation (view);
 
-  plugin->is_animating = true;
+      node = next_node;
+    }
 
-  ply_window_draw_area (plugin->window, 0, 0, area.width, area.height);
+  plugin->is_animating = true;
 }
 
 static void
 stop_animation (ply_boot_splash_plugin_t *plugin)
 {
+  ply_list_node_t *node;
+
   assert (plugin != NULL);
   assert (plugin->loop != NULL);
 
@@ -314,29 +596,20 @@ stop_animation (ply_boot_splash_plugin_t *plugin)
 
   plugin->is_animating = false;
 
-  ply_progress_animation_hide (plugin->progress_animation);
-  ply_animation_stop (plugin->animation);
-
-#ifdef ENABLE_FADE_OUT
-  for (i = 0; i < 10; i++)
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
     {
-      ply_frame_buffer_fill_with_hex_color_at_opacity (plugin->frame_buffer, NULL,
-                                                       PLYMOUTH_BACKGROUND_COLOR,
-                                                       .1 + .1 * i);
-    }
+      ply_list_node_t *next_node;
+      view_t *view;
 
-  ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, NULL,
-                                        PLYMOUTH_BACKGROUND_COLOR);
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
 
-  for (i = 0; i < 20; i++)
-    {
-      ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL,
-                                        0.0, 0.0, 0.0, .05 + .05 * i);
-    }
+      ply_progress_animation_hide (view->progress_animation);
+      ply_animation_stop (view->end_animation);
 
-  ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL,
-                                    0.0, 0.0, 0.0, 1.0);
-#endif
+      node = next_node;
+    }
 }
 
 static void
@@ -344,7 +617,6 @@ on_interrupt (ply_boot_splash_plugin_t *plugin)
 {
   ply_event_loop_exit (plugin->loop, 1);
   stop_animation (plugin);
-  ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT);
 }
 
 static void
@@ -353,138 +625,144 @@ 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)
+static void
+draw_background (view_t             *view,
+                 ply_pixel_buffer_t *pixel_buffer,
+                 int                 x,
+                 int                 y,
+                 int                 width,
+                 int                 height)
 {
-}
+  ply_boot_splash_plugin_t *plugin;
+  ply_rectangle_t area;
 
-void
-on_backspace (ply_boot_splash_plugin_t *plugin)
-{
-}
+  plugin = view->plugin;
 
-void
-on_enter (ply_boot_splash_plugin_t *plugin,
-          const char               *text)
-{
+  area.x = x;
+  area.y = y;
+  area.width = width;
+  area.height = height;
+
+  if (plugin->background_start_color != plugin->background_end_color)
+    ply_pixel_buffer_fill_with_gradient (pixel_buffer, &area,
+                                         plugin->background_start_color,
+                                         plugin->background_end_color);
+  else
+    ply_pixel_buffer_fill_with_hex_color (pixel_buffer, &area,
+                                          plugin->background_start_color);
 }
 
-void
-on_draw (ply_boot_splash_plugin_t *plugin,
+static void
+on_draw (view_t                   *view,
+         ply_pixel_buffer_t       *pixel_buffer,
          int                       x,
          int                       y,
          int                       width,
          int                       height)
 {
-  ply_frame_buffer_area_t area;
+  ply_boot_splash_plugin_t *plugin;
+  ply_rectangle_t area;
 
   area.x = x;
   area.y = y;
   area.width = width;
   area.height = height;
 
-  ply_frame_buffer_pause_updates (plugin->frame_buffer);
-  draw_background (plugin, &area);
+  plugin = view->plugin;
+
+  draw_background (view, pixel_buffer, x, y, width, height);
 
   if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY ||
       plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY  )
     {
-      ply_entry_draw (plugin->entry);
-      ply_label_draw (plugin->label);
+      uint32_t *box_data, *lock_data;
+
+      box_data = ply_image_get_data (plugin->box_image);
+      ply_pixel_buffer_fill_with_argb32_data (pixel_buffer,
+                                              &view->box_area, 0, 0,
+                                              box_data);
+
+      ply_entry_draw_area (view->entry,
+                           pixel_buffer,
+                           x, y, width, height);
+      ply_label_draw_area (view->label,
+                           pixel_buffer,
+                           x, y, width, height);
+
+      lock_data = ply_image_get_data (plugin->lock_image);
+      ply_pixel_buffer_fill_with_argb32_data (pixel_buffer,
+                                              &view->lock_area, 0, 0,
+                                              lock_data);
     }
   else
     {
-      ply_progress_animation_draw (plugin->progress_animation);
+      if (!ply_progress_animation_is_hidden (view->progress_animation))
+        ply_progress_animation_draw_area (view->progress_animation,
+                                          pixel_buffer,
+                                          x, y, width, height);
+      else if (!ply_animation_is_stopped (view->end_animation))
+        ply_animation_draw_area (view->end_animation,
+                                 pixel_buffer,
+                                 x, y, width, height);
 
       if (plugin->corner_image != NULL)
         {
-          ply_frame_buffer_area_t screen_area;
-          ply_frame_buffer_area_t image_area;
+          ply_rectangle_t screen_area;
+          ply_rectangle_t image_area;
 
-          ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area);
+          ply_pixel_buffer_get_size (pixel_buffer, &screen_area);
 
           image_area.width = ply_image_get_width (plugin->corner_image);
           image_area.height = ply_image_get_height (plugin->corner_image);
           image_area.x = screen_area.width - image_area.width - 20;
           image_area.y = screen_area.height - image_area.height - 20;
 
-          ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer, &image_area, 0, 0, ply_image_get_data (plugin->corner_image));
+          ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &image_area, 0, 0, ply_image_get_data (plugin->corner_image));
 
         }
     }
-  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)
+static void
+add_pixel_display (ply_boot_splash_plugin_t *plugin,
+                   ply_pixel_display_t      *display)
 {
-  ply_frame_buffer_area_t area;
+  view_t *view;
 
-  area.x = x;
-  area.y = y;
-  area.width = width;
-  area.height = height;
+  view = view_new (plugin, display);
 
-  if (plugin->background_start_color != plugin->background_end_color)
-    ply_frame_buffer_fill_with_gradient (plugin->frame_buffer, &area,
-                                         plugin->background_start_color,
-                                         plugin->background_end_color);
-  else
-    ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, &area,
-                                          plugin->background_start_color);
+  ply_pixel_display_set_draw_handler (view->display,
+                                      (ply_pixel_display_draw_handler_t)
+                                      on_draw, view);
+  ply_list_append_data (plugin->views, view);
 }
 
 static void
-add_handlers (ply_boot_splash_plugin_t *plugin)
+remove_pixel_display (ply_boot_splash_plugin_t *plugin,
+                      ply_pixel_display_t      *display)
 {
-  ply_window_add_keyboard_input_handler (plugin->window,
-                                         (ply_window_keyboard_input_handler_t)
-                                         on_keyboard_input, plugin);
-  ply_window_add_backspace_handler (plugin->window,
-                                    (ply_window_backspace_handler_t)
-                                    on_backspace, plugin);
-  ply_window_add_enter_handler (plugin->window,
-                                (ply_window_enter_handler_t)
-                                on_enter, plugin);
+  ply_list_node_t *node;
 
-  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);
-}
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
+    {
+      view_t *view;
+      ply_list_node_t *next_node;
 
-static void
-remove_handlers (ply_boot_splash_plugin_t *plugin)
-{
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
 
-  ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input);
-  ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace);
-  ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter);
-  ply_window_set_draw_handler (plugin->window, NULL, NULL);
-  ply_window_set_erase_handler (plugin->window, NULL, NULL);
-}
+      if (view->display == display)
+        {
 
-static void
-add_window (ply_boot_splash_plugin_t *plugin,
-            ply_window_t             *window)
-{
-  plugin->window = window;
-}
+          ply_pixel_display_set_draw_handler (view->display, NULL, NULL);
+          view_free (view);
+          ply_list_remove_node (plugin->views, node);
+          return;
+        }
 
-static void
-remove_window (ply_boot_splash_plugin_t *plugin,
-               ply_window_t             *window)
-{
-  plugin->window = NULL;
+      node = next_node;
+    }
 }
 
 static bool
@@ -495,19 +773,9 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
 {
   assert (plugin != NULL);
 
-  add_handlers (plugin);
-
   plugin->loop = loop;
   plugin->mode = mode;
 
-  plugin->animation = ply_animation_new (plugin->animation_dir,
-                                         "throbber-");
-  plugin->progress_animation = ply_progress_animation_new (plugin->animation_dir,
-                                                           "progress-");
-  ply_progress_animation_set_transition (plugin->progress_animation,
-                                         plugin->transition,
-                                         plugin->transition_duration);
-
   ply_trace ("loading lock image");
   if (!ply_image_load (plugin->lock_image))
     return false;
@@ -527,23 +795,11 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
         }
     }
 
-  ply_trace ("loading entry");
-  if (!ply_entry_load (plugin->entry))
-    return false;
-
-  ply_trace ("loading animation");
-  if (!ply_animation_load (plugin->animation))
-    return false;
-
-  ply_trace ("loading progress animation");
-  if (!ply_progress_animation_load (plugin->progress_animation))
-    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);
+  if (!load_views (plugin))
+    {
+      ply_trace ("couldn't load views");
+      return false;
+    }
 
   ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
                                  detach_from_event_loop,
@@ -554,11 +810,8 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
                                (ply_event_handler_t)
                                on_interrupt, plugin);
 
-  ply_window_clear_screen (plugin->window);
-  ply_window_hide_text_cursor (plugin->window);
-
   ply_trace ("starting boot animation");
-  start_animation (plugin);
+  start_progress_animation (plugin);
 
   plugin->is_visible = true;
 
@@ -583,6 +836,28 @@ on_animation_stopped (ply_boot_splash_plugin_t *plugin)
   plugin->is_idle = true;
 }
 
+static void
+update_progress_animation (ply_boot_splash_plugin_t *plugin,
+                           double                    percent_done)
+{
+  ply_list_node_t *node;
+
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      view_t *view;
+
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
+
+      ply_progress_animation_set_percent_done (view->progress_animation,
+                                               percent_done);
+
+      node = next_node;
+    }
+}
+
 static void
 on_boot_progress (ply_boot_splash_plugin_t *plugin,
                   double                    duration,
@@ -592,15 +867,14 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin,
 
   if (percent_done >= SHOW_ANIMATION_PERCENT)
     {
-      if (ply_animation_is_stopped (plugin->animation))
+      if (plugin->stop_trigger == NULL)
         {
           plugin->stop_trigger = ply_trigger_new (&plugin->stop_trigger);
           ply_trigger_add_handler (plugin->stop_trigger,
                                    (ply_trigger_handler_t)
                                    on_animation_stopped,
                                    plugin);
-          ply_progress_animation_hide (plugin->progress_animation);
-          begin_animation (plugin, plugin->stop_trigger);
+          start_end_animation (plugin, plugin->stop_trigger);
         }
     }
   else
@@ -614,11 +888,8 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin,
        * fraction(time,estimate)=1-2^(-(time^1.45)/estimate) */
       percent_done = 1.0 - pow (2.0, -pow (duration, 1.45) / total_duration) * (1.0 - percent_done);
 
-      ply_progress_animation_set_percent_done (plugin->progress_animation,
-                                               percent_done);
+      update_progress_animation (plugin, percent_done);
     }
-
-  ply_progress_animation_draw (plugin->progress_animation);
 }
 
 static void
@@ -627,8 +898,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin,
 {
   assert (plugin != NULL);
 
-  remove_handlers (plugin);
-
   if (plugin->loop != NULL)
     {
       stop_animation (plugin);
@@ -639,74 +908,52 @@ hide_splash_screen (ply_boot_splash_plugin_t *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)
+                      const char               *text,
+                      int                       number_of_bullets)
 {
-  ply_frame_buffer_area_t area;
-  int x, y;
-  int entry_width, entry_height;
-
-  uint32_t *box_data, *lock_data;
+  ply_list_node_t *node;
 
-  assert (plugin != NULL);
-
-  if (ply_entry_is_hidden (plugin->entry))
+  node = ply_list_get_first_node (plugin->views);
+  while (node != 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;
+      ply_list_node_t *next_node;
+      view_t *view;
 
-      plugin->lock_area.width = ply_image_get_width (plugin->lock_image);
-      plugin->lock_area.height = ply_image_get_height (plugin->lock_image);
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
 
-      entry_width = ply_entry_get_width (plugin->entry);
-      entry_height = ply_entry_get_height (plugin->entry);
+      view_show_prompt (view, text);
+      ply_entry_set_bullet_count (view->entry, number_of_bullets);
 
-      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);
+      node = next_node;
+    }
+}
 
-      ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y);
+static void
+show_prompt (ply_boot_splash_plugin_t *plugin,
+             const char               *prompt,
+             const char               *entry_text)
+{
+  ply_list_node_t *node;
 
-      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);
-    }
-  else
-    {
-      ply_entry_draw (plugin->entry);
-    }
-  if (prompt != NULL)
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
     {
-      int label_width, label_height;
+      ply_list_node_t *next_node;
+      view_t *view;
 
-      ply_label_set_text (plugin->label, prompt);
-      label_width = ply_label_get_width (plugin->label);
-      label_height = ply_label_get_height (plugin->label);
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
 
-      x = plugin->box_area.x + plugin->lock_area.width / 2;
-      y = plugin->box_area.y + plugin->box_area.height;
+      view_show_prompt (view, prompt);
+      ply_entry_set_text (view->entry, entry_text);
 
-      ply_label_show (plugin->label, plugin->window, x, y);
+      node = next_node;
     }
 }
 
@@ -728,27 +975,50 @@ become_idle (ply_boot_splash_plugin_t *plugin,
 
   plugin->idle_trigger = idle_trigger;
 
-  if (ply_animation_is_stopped (plugin->animation))
+  if (plugin->stop_trigger == NULL)
     {
       plugin->stop_trigger = ply_trigger_new (&plugin->stop_trigger);
       ply_trigger_add_handler (plugin->stop_trigger,
                                (ply_trigger_handler_t)
                                on_animation_stopped,
                                plugin);
-      ply_progress_animation_hide (plugin->progress_animation);
-      begin_animation (plugin, plugin->stop_trigger);
+      start_end_animation (plugin, plugin->stop_trigger);
+    }
+}
+
+static void
+hide_prompt (ply_boot_splash_plugin_t *plugin)
+{
+  ply_list_node_t *node;
+
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      view_t *view;
+
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
+
+      view_hide_prompt (view);
+
+      node = next_node;
     }
 }
 
 static void
 display_normal (ply_boot_splash_plugin_t *plugin)
 {
+  pause_views (plugin);
   if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL)
     {
       plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
-      ply_entry_hide (plugin->entry);
-      start_animation (plugin);
+      hide_prompt (plugin);
+      start_progress_animation (plugin);
+
+      redraw_views (plugin);
     }
+  unpause_views (plugin);
 }
 
 static void
@@ -756,13 +1026,14 @@ display_password (ply_boot_splash_plugin_t *plugin,
                   const char               *prompt,
                   int                       bullets)
 {
+  pause_views (plugin);
   if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
-    {
-      stop_animation (plugin);
-    }
+    stop_animation (plugin);
+
   plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY;
-  show_password_prompt (plugin, prompt);
-  ply_entry_set_bullet_count (plugin->entry, bullets);
+  show_password_prompt (plugin, prompt, bullets);
+  redraw_views (plugin);
+  unpause_views (plugin);
 }
 
 static void
@@ -770,14 +1041,14 @@ display_question (ply_boot_splash_plugin_t *plugin,
                   const char               *prompt,
                   const char               *entry_text)
 {
+  pause_views (plugin);
   if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
-    {
-      stop_animation (plugin);
-    }
+    stop_animation (plugin);
 
   plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY;
-  show_password_prompt (plugin, prompt);
-  ply_entry_set_text (plugin->entry, entry_text);
+  show_prompt (plugin, prompt, entry_text);
+  redraw_views (plugin);
+  unpause_views (plugin);
 }
 
 ply_boot_splash_plugin_interface_t *
@@ -787,8 +1058,8 @@ ply_boot_splash_plugin_get_interface (void)
     {
       .create_plugin = create_plugin,
       .destroy_plugin = destroy_plugin,
-      .add_window = add_window,
-      .remove_window = remove_window,
+      .add_pixel_display = add_pixel_display,
+      .remove_pixel_display = remove_pixel_display,
       .show_splash_screen = show_splash_screen,
       .update_status = update_status,
       .on_boot_progress = on_boot_progress,
@@ -803,4 +1074,4 @@ ply_boot_splash_plugin_get_interface (void)
   return &plugin_interface;
 }
 
-/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
+/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */