]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
[fade-throbber] 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:38 +0000 (11:23 -0400)
src/plugins/splash/fade-throbber/plugin.c

index 64403a4b13c5a9bbfb172f21d938dfc2ac6c03d5..d89a562fd9bdc9418b044f5967b9bf0aa4eff11d 100644 (file)
@@ -1,6 +1,6 @@
 /* fade-throbber.c - boot splash plugin
  *
- * Copyright (C) 2007, 2008 Red Hat, Inc.
+ * Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
  *
  * 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
 #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-key-file.h"
+#include "ply-pixel-buffer.h"
+#include "ply-pixel-display.h"
 #include "ply-trigger.h"
 #include "ply-utils.h"
-#include "ply-window.h"
 
 #include <linux/kd.h>
 
@@ -58,6 +59,7 @@
 #define FRAMES_PER_SECOND 30
 #endif
 
+
 typedef enum {
    PLY_BOOT_SPLASH_DISPLAY_NORMAL,
    PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY,
@@ -70,20 +72,30 @@ typedef struct
   unsigned int y;
   double start_time;
   double speed;
+  double opacity;
 } star_t;
 
+typedef struct
+{
+  ply_boot_splash_plugin_t *plugin;
+  ply_pixel_display_t *display;
+  ply_list_t *stars;
+  ply_entry_t *entry;
+  ply_label_t *label;
+  ply_rectangle_t 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_image_t *logo_image;
   ply_image_t *star_image;
   ply_image_t *lock_image;
-  ply_list_t *stars;
-  ply_window_t *window;
+  char *image_dir;
+  ply_list_t *views;
+  double logo_opacity;
 
-  ply_entry_t *entry;
   ply_boot_splash_display_type_t state;
 
   double start_time;
@@ -92,6 +104,65 @@ struct _ply_boot_splash_plugin
   uint32_t is_animating : 1;
 };
 
+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->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->lock_area.x;
+      y = view->lock_area.y + view->lock_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)
 {
@@ -113,16 +184,15 @@ create_plugin (ply_key_file_t *key_file)
   plugin->lock_image = ply_image_new (image_path);
   free (image_path);
 
-  plugin->entry = ply_entry_new (image_dir);
-  free (image_dir);
+  plugin->image_dir = image_dir;
 
   plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
-  plugin->stars = ply_list_new ();
+  plugin->views = ply_list_new ();
 
   return plugin;
 }
 
-star_t *
+static star_t *
 star_new (int    x,
           int    y,
           double speed)
@@ -145,13 +215,13 @@ star_free (star_t *star)
 }
 
 static void
-free_stars (ply_boot_splash_plugin_t *plugin)
+free_stars (view_t *view)
 {
   ply_list_node_t *node;
 
-  assert (plugin != NULL);
+  assert (view != NULL);
 
-  node = ply_list_get_first_node (plugin->stars);
+  node = ply_list_get_first_node (view->stars);
   while (node != NULL)
     {
       ply_list_node_t *next_node;
@@ -159,29 +229,184 @@ free_stars (ply_boot_splash_plugin_t *plugin)
 
       star = (star_t *) ply_list_node_get_data (node);
 
-      next_node = ply_list_get_next_node (plugin->stars, node);
+      next_node = ply_list_get_next_node (view->stars, node);
 
       star_free (star);
       node = next_node;
     }
 
-  ply_list_free (plugin->stars);
-  plugin->stars = NULL;
+  ply_list_free (view->stars);
+  view->stars = NULL;
 }
 
-static void add_handlers (ply_boot_splash_plugin_t *plugin);
-static void remove_handlers (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->image_dir);
+  view->stars = ply_list_new ();
+  view->label = ply_label_new ();
+
+  return view;
+}
+
+static void
+view_free (view_t *view)
+{
+
+  ply_entry_free (view->entry);
+  free_stars (view);
+
+  free (view);
+}
+
+static bool
+view_load (view_t *view)
+{
+  ply_trace ("loading entry");
+  if (!ply_entry_load (view->entry))
+    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
+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)
     {
       ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t)
@@ -190,100 +415,95 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
       detach_from_event_loop (plugin);
     }
 
-  free_stars (plugin);
+  free_views (plugin);
   ply_image_free (plugin->logo_image);
   ply_image_free (plugin->star_image);
   ply_image_free (plugin->lock_image);
-  ply_entry_free (plugin->entry);
   free (plugin);
 }
 
 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
-animate_at_time (ply_boot_splash_plugin_t *plugin,
-                 double                    time)
+view_animate_at_time (view_t  *view,
+                      double   time)
 {
+  ply_boot_splash_plugin_t *plugin;
   ply_list_node_t *node;
-  ply_frame_buffer_area_t logo_area, star_area;
+  double logo_opacity;
   uint32_t *logo_data, *star_data;
-  long width, height;
-  static double last_opacity = 0.0;
-  double opacity = 0.0;
+  long logo_x, logo_y;
+  long logo_width, logo_height;
+  unsigned long screen_width, screen_height;
+  unsigned long star_width, star_height;
 
-  ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS);
+  plugin = view->plugin;
 
-  ply_frame_buffer_pause_updates (plugin->frame_buffer);
-
-  width = ply_image_get_width (plugin->logo_image);
-  height = ply_image_get_height (plugin->logo_image);
+  logo_width = ply_image_get_width (plugin->logo_image);
+  logo_height = ply_image_get_height (plugin->logo_image);
   logo_data = ply_image_get_data (plugin->logo_image);
-  ply_frame_buffer_get_size (plugin->frame_buffer, &logo_area);
-  logo_area.x = (logo_area.width / 2) - (width / 2);
-  logo_area.y = (logo_area.height / 2) - (height / 2);
-  logo_area.width = width;
-  logo_area.height = height;
+
+  screen_width = ply_pixel_display_get_width (view->display);
+  screen_height = ply_pixel_display_get_height (view->display);
+
+  logo_x = (screen_width / 2) - (logo_width / 2);
+  logo_y = (screen_height / 2) - (logo_height / 2);
 
   star_data = ply_image_get_data (plugin->star_image);
-  star_area.width = ply_image_get_width (plugin->star_image);
-  star_area.height = ply_image_get_height (plugin->star_image);
+  star_width = ply_image_get_width (plugin->star_image);
+  star_height = ply_image_get_height (plugin->star_image);
 
-  node = ply_list_get_first_node (plugin->stars);
+  node = ply_list_get_first_node (view->stars);
   while (node != NULL)
     {
       ply_list_node_t *next_node;
       star_t *star;
 
       star = (star_t *) ply_list_node_get_data (node);
-      next_node = ply_list_get_next_node (plugin->stars, node);
-
-      star_area.x = star->x;
-      star_area.y = star->y;
-
-      opacity = .5 * sin (((plugin->now - star->start_time) / star->speed) * (2 * M_PI)) + .5;
-      opacity = CLAMP (opacity, 0, 1.0);
+      next_node = ply_list_get_next_node (view->stars, node);
 
-      draw_background (plugin, &star_area);
-      ply_frame_buffer_fill_with_argb32_data_at_opacity (plugin->frame_buffer, 
-                                                         &star_area, 0, 0, 
-                                                         star_data, opacity);
+      star->opacity = .5 * sin (((plugin->now - star->start_time) / star->speed) * (2 * M_PI)) + .5;
+      star->opacity = CLAMP (star->opacity, 0, 1.0);
 
+      ply_pixel_display_draw_area (view->display,
+                                   star->x, star->y,
+                                   star_width, star_height);
       node = next_node;
     }
 
-  opacity = .5 * sin ((time / 5) * (2 * M_PI)) + .8;
-  opacity = CLAMP (opacity, 0, 1.0);
+  logo_opacity = .5 * sin ((time / 5) * (2 * M_PI)) + .8;
+  logo_opacity = CLAMP (logo_opacity, 0, 1.0);
 
   if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN)
-    opacity = 1.0;
+    logo_opacity = 1.0;
+
+  if (fabs (logo_opacity - plugin->logo_opacity) <= DBL_MIN)
+    return;
+
+  plugin->logo_opacity = logo_opacity;
+
+  ply_pixel_display_draw_area (view->display,
+                               logo_x, logo_y,
+                               logo_width, logo_height);
+}
 
-  if (fabs (opacity - last_opacity) <= DBL_MIN)
+static void
+animate_at_time (ply_boot_splash_plugin_t *plugin,
+                 double                    time)
+{
+  ply_list_node_t *node;
+
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
     {
-      ply_frame_buffer_unpause_updates (plugin->frame_buffer);
-      return;
-    }
+      ply_list_node_t *next_node;
+      view_t *view;
 
-  last_opacity = opacity;
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
 
-  draw_background (plugin, &logo_area);
-  ply_frame_buffer_fill_with_argb32_data_at_opacity (plugin->frame_buffer,
-                                                     &logo_area, 0, 0,
-                                                     logo_data, opacity);
-  ply_frame_buffer_unpause_updates (plugin->frame_buffer);
+      view_animate_at_time (view, time);
+
+      node = next_node;
+    }
 }
 
 static void
@@ -291,7 +511,6 @@ on_timeout (ply_boot_splash_plugin_t *plugin)
 {
   double sleep_time;
 
-  ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS);
   plugin->now = ply_get_timestamp ();
 
   /* The choice below is between
@@ -326,15 +545,25 @@ on_timeout (ply_boot_splash_plugin_t *plugin)
 }
 
 static void
-start_animation (ply_boot_splash_plugin_t *plugin)
+view_start_animation (view_t *view)
 {
-  assert (plugin != NULL);
+  ply_boot_splash_plugin_t *plugin;
+  unsigned long screen_width, screen_height;
+
+  assert (view != NULL);
+
+  plugin = view->plugin;
+
   assert (plugin->loop != NULL);
-    
+
   if (plugin->is_animating)
      return;
 
-  draw_background (plugin, NULL);
+  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);
 
   plugin->start_time = ply_get_timestamp ();
   animate_at_time (plugin, plugin->start_time);
@@ -351,37 +580,40 @@ start_animation (ply_boot_splash_plugin_t *plugin)
 }
 
 static void
-stop_animation (ply_boot_splash_plugin_t *plugin)
+start_animation (ply_boot_splash_plugin_t *plugin)
 {
-  int i;
-
-  assert (plugin != NULL);
-  assert (plugin->loop != NULL);
+  ply_list_node_t *node;
 
-  if (!plugin->is_animating)
+  if (plugin->is_animating)
      return;
 
-  plugin->is_animating = false;
-
-  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);
+      view_start_animation (view);
+
+      node = next_node;
     }
 
-  ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL,
-                                    0.0, 0.0, 0.0, 1.0);
+  plugin->is_animating = true;
+}
+
+static void
+stop_animation (ply_boot_splash_plugin_t *plugin)
+{
+  assert (plugin != NULL);
+  assert (plugin->loop != NULL);
+
+  if (!plugin->is_animating)
+     return;
+
+  plugin->is_animating = false;
 
   if (plugin->loop != NULL)
     {
@@ -389,6 +621,7 @@ stop_animation (ply_boot_splash_plugin_t *plugin)
                                                 (ply_event_loop_timeout_handler_t)
                                                 on_timeout, plugin);
     }
+  redraw_views (plugin);
 }
 
 static void
@@ -396,121 +629,188 @@ 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
 detach_from_event_loop (ply_boot_splash_plugin_t *plugin)
 {
   plugin->loop = NULL;
-
-  ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT);
 }
 
-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;
+
+  plugin = view->plugin;
+
+  area.x = x;
+  area.y = y;
+  area.width = width;
+  area.height = height;
+
+  ply_pixel_buffer_fill_with_gradient (pixel_buffer, &area,
+                                       PLYMOUTH_BACKGROUND_START_COLOR,
+                                       PLYMOUTH_BACKGROUND_END_COLOR);
 }
 
-void
-on_backspace (ply_boot_splash_plugin_t *plugin)
+static void
+draw_normal_view (view_t             *view,
+                  ply_pixel_buffer_t *pixel_buffer,
+                  int                 x,
+                  int                 y,
+                  int                 width,
+                  int                 height)
 {
+  ply_boot_splash_plugin_t *plugin;
+  ply_list_node_t *node;
+  ply_rectangle_t logo_area;
+  ply_rectangle_t star_area;
+  uint32_t *logo_data, *star_data;
+  unsigned long screen_width, screen_height;
+
+  plugin = view->plugin;
+
+  logo_area.width = ply_image_get_width (plugin->logo_image);
+  logo_area.height = ply_image_get_height (plugin->logo_image);
+  logo_data = ply_image_get_data (plugin->logo_image);
+
+  screen_width = ply_pixel_display_get_width (view->display);
+  screen_height = ply_pixel_display_get_height (view->display);
+
+  logo_area.x = (screen_width / 2) - (logo_area.width / 2);
+  logo_area.y = (screen_height / 2) - (logo_area.height / 2);
+
+  star_data = ply_image_get_data (plugin->star_image);
+  star_area.width = ply_image_get_width (plugin->star_image);
+  star_area.height = ply_image_get_height (plugin->star_image);
+
+  node = ply_list_get_first_node (view->stars);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      star_t *star;
+
+      star = (star_t *) ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (view->stars, node);
+
+      star_area.x = star->x;
+      star_area.y = star->y;
+      ply_pixel_buffer_fill_with_argb32_data_at_opacity (pixel_buffer,
+                                                         &star_area, 0, 0,
+                                                         star_data,
+                                                         star->opacity);
+      node = next_node;
+    }
+
+  ply_pixel_buffer_fill_with_argb32_data_at_opacity (pixel_buffer,
+                                                     &logo_area, 0, 0,
+                                                     logo_data,
+                                                     plugin->logo_opacity);
 }
 
-void
-on_enter (ply_boot_splash_plugin_t *plugin,
-          const char               *text)
+static void
+draw_prompt_view (view_t             *view,
+                  ply_pixel_buffer_t *pixel_buffer,
+                  int                 x,
+                  int                 y,
+                  int                 width,
+                  int                 height)
 {
+  ply_boot_splash_plugin_t *plugin;
+  uint32_t *lock_data;
+
+  plugin = view->plugin;
+
+  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);
 }
 
-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;
+
+  plugin = view->plugin;
 
   area.x = x;
   area.y = y;
   area.width = width;
   area.height = height;
 
-  draw_background (plugin, &area);
+  draw_background (view, pixel_buffer, x, y, width, height);
+
+  if (!plugin->is_animating)
+    return;
 
   if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
-    animate_at_time (plugin, plugin->now);
+    draw_normal_view (view, pixel_buffer, x, y, width, height);
   else
-    ply_entry_draw (plugin->entry);
+    draw_prompt_view (view, pixel_buffer, x, y, width, height);
 }
 
-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);
 
-  ply_frame_buffer_fill_with_gradient (plugin->frame_buffer, &area,
-                                       PLYMOUTH_BACKGROUND_START_COLOR,
-                                       PLYMOUTH_BACKGROUND_END_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_window_set_draw_handler (plugin->window,
-                               (ply_window_draw_handler_t)
-                               on_draw, plugin);
+  ply_list_node_t *node;
 
-  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
@@ -522,8 +822,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
   assert (plugin != NULL);
   assert (plugin->logo_image != NULL);
 
-  add_handlers (plugin);
-
   plugin->loop = loop;
   plugin->mode = mode;
 
@@ -539,16 +837,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
   if (!ply_image_load (plugin->lock_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);
@@ -557,8 +845,11 @@ 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);
+  if (!load_views (plugin))
+    {
+      ply_trace ("couldn't load views");
+      return false;
+    }
 
   ply_trace ("starting boot animation");
   start_animation (plugin);
@@ -567,21 +858,26 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
 }
 
 static void
-add_star (ply_boot_splash_plugin_t *plugin)
+view_add_star (view_t *view)
 {
-  ply_frame_buffer_area_t area, logo_area;
+  ply_boot_splash_plugin_t *plugin;
+  ply_rectangle_t logo_area;
   star_t *star;
   unsigned int x, y;
   unsigned int width, height;
+  unsigned long screen_width, screen_height;
   ply_list_node_t *node;
 
-  assert (plugin != NULL);
+  assert (view != NULL);
+
+  plugin = view->plugin;
 
-  ply_frame_buffer_get_size (plugin->frame_buffer, &area);
+  screen_width = ply_pixel_display_get_width (view->display);
+  screen_height = ply_pixel_display_get_height (view->display);
   width = ply_image_get_width (plugin->logo_image);
   height = ply_image_get_height (plugin->logo_image);
-  logo_area.x = (area.width / 2) - (width / 2);
-  logo_area.y = (area.height / 2) - (height / 2);
+  logo_area.x = (screen_width / 2) - (width / 2);
+  logo_area.y = (screen_height / 2) - (height / 2);
   logo_area.width = width;
   logo_area.height = height;
 
@@ -591,8 +887,8 @@ add_star (ply_boot_splash_plugin_t *plugin)
   node = NULL;
   do
     {
-      x = rand () % area.width;
-      y = rand () % area.height;
+      x = rand () % screen_width;
+      y = rand () % screen_height;
 
       if ((x <= logo_area.x + logo_area.width)
            && (x >= logo_area.x)
@@ -606,13 +902,13 @@ add_star (ply_boot_splash_plugin_t *plugin)
            && (y + height <= logo_area.y + logo_area.height))
           continue;
 
-      node = ply_list_get_first_node (plugin->stars);
+      node = ply_list_get_first_node (view->stars);
       while (node != NULL)
         {
           ply_list_node_t *next_node;
 
           star = (star_t *) ply_list_node_get_data (node);
-          next_node = ply_list_get_next_node (plugin->stars, node);
+          next_node = ply_list_get_next_node (view->stars, node);
 
           if ((x <= star->x + width)
                && (x >= star->x)
@@ -632,7 +928,27 @@ add_star (ply_boot_splash_plugin_t *plugin)
     } while (node != NULL);
 
   star = star_new (x, y, (double) ((rand () % 50) + 1));
-  ply_list_append_data (plugin->stars, star);
+  ply_list_append_data (view->stars, star);
+}
+
+static void
+add_stars (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_add_star (view);
+
+      node = next_node;
+    }
 }
 
 static void
@@ -641,7 +957,7 @@ update_status (ply_boot_splash_plugin_t *plugin,
 {
   assert (plugin != NULL);
 
-  add_star (plugin);
+  add_stars (plugin);
 }
 
 static void
@@ -650,8 +966,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin,
 {
   assert (plugin != NULL);
 
-  remove_handlers (plugin);
-
   if (plugin->loop != NULL)
     {
       stop_animation (plugin);
@@ -661,63 +975,87 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin,
                                              plugin);
       detach_from_event_loop (plugin);
     }
+}
+
+static void
+show_password_prompt (ply_boot_splash_plugin_t *plugin,
+                      const char               *text,
+                      int                       number_of_bullets)
+{
+  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;
 
-  plugin->frame_buffer = NULL;
+      view = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (plugin->views, node);
 
-  ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT);
+      view_show_prompt (view, text);
+      ply_entry_set_bullet_count (view->entry, number_of_bullets);
+
+      node = next_node;
+    }
 }
 
 static void
-show_password_entry (ply_boot_splash_plugin_t *plugin)
+show_prompt (ply_boot_splash_plugin_t *plugin,
+             const char               *prompt,
+             const char               *entry_text)
 {
-  ply_frame_buffer_area_t area;
-  ply_frame_buffer_area_t lock_area;
-  int x, y;
-  int entry_width, entry_height;
-  uint32_t *lock_data;
-
-  assert (plugin != NULL);
+  ply_list_node_t *node;
 
-  if (ply_entry_is_hidden (plugin->entry))
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
     {
-      draw_background (plugin, NULL);
+      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);
 
-      entry_width = ply_entry_get_width (plugin->entry);
-      entry_height = ply_entry_get_height (plugin->entry);
+      view_show_prompt (view, prompt);
+      ply_entry_set_text (view->entry, entry_text);
 
-      lock_area.width = ply_image_get_width (plugin->lock_image);
-      lock_area.height = ply_image_get_height (plugin->lock_image);
-      lock_area.x = area.width / 2.0 - (lock_area.width + entry_width) / 2.0;
-      lock_area.y = area.height / 2.0 - lock_area.height / 2.0;
+      node = next_node;
+    }
+}
 
-      x = area.width / 2.0 - (lock_area.width + entry_width) / 2.0 + lock_area.width;
-      y = area.height / 2.0 - entry_height / 2.0;
+static void
+hide_prompt (ply_boot_splash_plugin_t *plugin)
+{
+  ply_list_node_t *node;
 
-      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,
-                                              &lock_area, 0, 0,
-                                              lock_data);
-    }
-  else
+  node = ply_list_get_first_node (plugin->views);
+  while (node != NULL)
     {
-      ply_entry_draw (plugin->entry);
+      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_QUESTION_ENTRY ||
       plugin->state ==  PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY)
     {
       plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
-      ply_entry_hide (plugin->entry);
-      start_animation(plugin);
+      hide_prompt (plugin);
+      start_animation (plugin);
+      redraw_views (plugin);
     }
+  unpause_views (plugin);
 }
 
 static void
@@ -725,13 +1063,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_entry (plugin);
-  ply_entry_set_bullet_count (plugin->entry, bullets);
+  show_password_prompt (plugin, prompt, bullets);
+  redraw_views (plugin);
+  unpause_views (plugin);
 }
 
 static void
@@ -739,16 +1078,17 @@ 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_entry (plugin);
-  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 *
 ply_boot_splash_plugin_get_interface (void)
 {
@@ -756,8 +1096,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,
       .hide_splash_screen = hide_splash_screen,