From 862bc800e6cc670466721011facbdcbf8313e886 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 19 2015 16:07:00 +0000 Subject: import plymouth-0.8.9-0.24.20140113.el7 --- diff --git a/SOURCES/activate-new-renderers.patch b/SOURCES/activate-new-renderers.patch new file mode 100644 index 0000000..21f9389 --- /dev/null +++ b/SOURCES/activate-new-renderers.patch @@ -0,0 +1,2176 @@ +From 14bdb7cadcfb2d3aac54b89b91217ef58abd8377 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 24 Sep 2015 09:21:18 -0400 +Subject: [PATCH 1/6] device-manager: activate new renderers after adding to + renderers list + +When a new renderer gets created, we should activate it, if the device +manager is already active. + +At the moment we call create_pixel_displays_for_renderer which would +implicitly activate it (from a callback), except we call it one line +too early, so the renderer isn't in the list of known renderers yet. + +This commit swaps the two lines and also adds an explicit renderer +activation for clarity. For symmetry it makes the same change to +keyboards that it makes to renderers. +--- + src/libply-splash-core/ply-device-manager.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c +index f09448a..14d7616 100644 +--- a/src/libply-splash-core/ply-device-manager.c ++++ b/src/libply-splash-core/ply-device-manager.c +@@ -45,60 +45,62 @@ static void create_devices_for_terminal_and_renderer_type (ply_device_manager_t + const char *device_path, + ply_terminal_t *terminal, + ply_renderer_type_t renderer_type); + struct _ply_device_manager + { + ply_device_manager_flags_t flags; + ply_event_loop_t *loop; + ply_hashtable_t *terminals; + ply_hashtable_t *renderers; + ply_terminal_t *local_console_terminal; + ply_list_t *keyboards; + ply_list_t *text_displays; + ply_list_t *pixel_displays; + struct udev *udev_context; + struct udev_queue *udev_queue; + int udev_queue_fd; + ply_fd_watch_t *udev_queue_fd_watch; + struct udev_monitor *udev_monitor; + + ply_keyboard_added_handler_t keyboard_added_handler; + ply_keyboard_removed_handler_t keyboard_removed_handler; + ply_pixel_display_added_handler_t pixel_display_added_handler; + ply_pixel_display_removed_handler_t pixel_display_removed_handler; + ply_text_display_added_handler_t text_display_added_handler; + ply_text_display_removed_handler_t text_display_removed_handler; + void *event_handler_data; + + uint32_t local_console_managed : 1; + uint32_t local_console_is_text : 1; + uint32_t serial_consoles_detected : 1; ++ uint32_t renderers_activated : 1; ++ uint32_t keyboards_activated : 1; + }; + + static void + detach_from_event_loop (ply_device_manager_t *manager) + { + assert (manager != NULL); + + manager->loop = NULL; + } + + static void + attach_to_event_loop (ply_device_manager_t *manager, + ply_event_loop_t *loop) + { + assert (manager != NULL); + assert (loop != NULL); + assert (manager->loop == NULL); + + manager->loop = loop; + + ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + manager); + } + + static bool + drm_device_in_use (ply_device_manager_t *manager, + const char *device_path) + { + ply_renderer_t *renderer; +@@ -696,85 +698,92 @@ create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, + ply_trace ("ignoring device %s since it's already managed", + device_path); + return; + } + + ply_trace ("creating devices for %s (renderer type: %u) (terminal: %s)", + device_path? : "", renderer_type, terminal? ply_terminal_get_name (terminal): "none"); + + if (renderer_type != PLY_RENDERER_TYPE_NONE) + { + renderer = ply_renderer_new (renderer_type, device_path, terminal); + + if (!ply_renderer_open (renderer)) + { + ply_trace ("could not open renderer for %s", device_path); + ply_renderer_free (renderer); + renderer = NULL; + if (renderer_type != PLY_RENDERER_TYPE_AUTO) + return; + } + } + + if (renderer != NULL) + { + keyboard = ply_keyboard_new_for_renderer (renderer); + ply_list_append_data (manager->keyboards, keyboard); + + if (manager->keyboard_added_handler != NULL) + manager->keyboard_added_handler (manager->event_handler_data, keyboard); + +- create_pixel_displays_for_renderer (manager, renderer); + ply_hashtable_insert (manager->renderers, strdup (device_path), renderer); ++ create_pixel_displays_for_renderer (manager, renderer); ++ ++ if (manager->renderers_activated) ++ { ++ ply_trace ("activating renderer"); ++ ply_renderer_activate (renderer); ++ } + } + else if (terminal != NULL) + { + keyboard = ply_keyboard_new_for_terminal (terminal); + ply_list_append_data (manager->keyboards, keyboard); + + if (manager->keyboard_added_handler != NULL) + manager->keyboard_added_handler (manager->event_handler_data, keyboard); + } + + if (terminal != NULL) + { + create_text_displays_for_terminal (manager, terminal); + + if (terminal == manager->local_console_terminal) + { + manager->local_console_is_text = renderer == NULL; + manager->local_console_managed = true; + } + } + +- if (keyboard != NULL) ++ if (keyboard != NULL && manager->keyboards_activated) + { ++ ply_trace ("activating keyboards"); + ply_keyboard_watch_for_input (keyboard); + } + } + + static void + create_devices_for_terminal (const char *device_path, + ply_terminal_t *terminal, + ply_device_manager_t *manager) + { + create_devices_for_terminal_and_renderer_type (manager, + device_path, + terminal, + PLY_RENDERER_TYPE_NONE); + } + static bool + create_devices_from_terminals (ply_device_manager_t *manager) + { + bool has_serial_consoles; + + ply_trace ("checking for consoles"); + + if (manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES) + { + has_serial_consoles = false; + ply_trace ("ignoring all consoles but default console because explicitly told to."); + } + else + { + has_serial_consoles = add_consoles_from_file (manager, "/sys/class/tty/console/active"); + } +@@ -946,91 +955,98 @@ ply_device_manager_get_text_displays (ply_device_manager_t *manager) + } + + ply_terminal_t * + ply_device_manager_get_default_terminal (ply_device_manager_t *manager) + { + return manager->local_console_terminal; + } + + bool + ply_device_manager_has_serial_consoles (ply_device_manager_t *manager) + { + return manager->serial_consoles_detected; + } + + static void + activate_renderer (char *device_path, + ply_renderer_t *renderer, + ply_device_manager_t *manager) + { + ply_renderer_activate (renderer); + } + + void + ply_device_manager_activate_renderers (ply_device_manager_t *manager) + { + ply_trace ("activating renderers"); + ply_hashtable_foreach (manager->renderers, + (ply_hashtable_foreach_func_t *) + activate_renderer, + manager); ++ ++ manager->renderers_activated = true; + } + + static void + deactivate_renderer (char *device_path, + ply_renderer_t *renderer, + ply_device_manager_t *manager) + { + ply_renderer_deactivate (renderer); + } + + void + ply_device_manager_deactivate_renderers (ply_device_manager_t *manager) + { + ply_trace ("deactivating renderers"); + ply_hashtable_foreach (manager->renderers, + (ply_hashtable_foreach_func_t *) + deactivate_renderer, + manager); ++ manager->renderers_activated = false; + } + + void + ply_device_manager_activate_keyboards (ply_device_manager_t *manager) + { + ply_list_node_t *node; + + ply_trace ("activating keyboards"); + node = ply_list_get_first_node (manager->keyboards); + while (node != NULL) + { + ply_keyboard_t *keyboard; + ply_list_node_t *next_node; + + keyboard = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (manager->keyboards, node); + + ply_keyboard_watch_for_input (keyboard); + + node = next_node; + } ++ ++ manager->keyboards_activated = true; + } + + void + ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager) + { + ply_list_node_t *node; + + ply_trace ("deactivating keyboards"); + node = ply_list_get_first_node (manager->keyboards); + while (node != NULL) + { + ply_keyboard_t *keyboard; + ply_list_node_t *next_node; + + keyboard = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (manager->keyboards, node); + + ply_keyboard_stop_watching_for_input (keyboard); + + node = next_node; + } ++ ++ manager->keyboards_activated = false; + } +-- +2.5.0 + + +From 61ca85cd95de1e467e4996a5563c5f77221e569f Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 24 Sep 2015 15:53:01 -0400 +Subject: [PATCH 2/6] plugins: unset draw handler when freeing view + +If the view is freed, we definitely shouldn't draw +the view's display anymore. +--- + src/plugins/splash/fade-throbber/plugin.c | 4 ++-- + src/plugins/splash/space-flares/plugin.c | 4 ++-- + src/plugins/splash/throbgress/plugin.c | 4 ++-- + src/plugins/splash/two-step/plugin.c | 3 ++- + 4 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/src/plugins/splash/fade-throbber/plugin.c b/src/plugins/splash/fade-throbber/plugin.c +index 4af6cae..7b097c0 100644 +--- a/src/plugins/splash/fade-throbber/plugin.c ++++ b/src/plugins/splash/fade-throbber/plugin.c +@@ -240,60 +240,62 @@ free_stars (view_t *view) + + 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 (); + + view->message_label = ply_label_new (); + + return view; + } + + static void + view_free (view_t *view) + { + + ply_entry_free (view->entry); + ply_label_free (view->message_label); + free_stars (view); + ++ ply_pixel_display_set_draw_handler (view->display, NULL, NULL); ++ + 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); + +@@ -753,62 +755,60 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + view_t *view; + + view = view_new (plugin, display); + + 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 + remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { +- +- ply_pixel_display_set_draw_handler (view->display, NULL, NULL); + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + + static bool + show_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop, + ply_buffer_t *boot_buffer, + ply_boot_splash_mode_t mode) + { + assert (plugin != NULL); + assert (plugin->logo_image != NULL); + + plugin->loop = loop; + plugin->mode = mode; + + ply_trace ("loading logo image"); + if (!ply_image_load (plugin->logo_image)) + return false; + + ply_trace ("loading star image"); + if (!ply_image_load (plugin->star_image)) + return false; + + ply_trace ("loading lock image"); +diff --git a/src/plugins/splash/space-flares/plugin.c b/src/plugins/splash/space-flares/plugin.c +index e31dce8..45863ff 100644 +--- a/src/plugins/splash/space-flares/plugin.c ++++ b/src/plugins/splash/space-flares/plugin.c +@@ -210,60 +210,62 @@ 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->label = ply_label_new (); + view->message_label = ply_label_new (); + + view->sprites = ply_list_new (); + + return view; + } + + static void view_free_sprites (view_t *view); + + static void + view_free (view_t *view) + { + + ply_entry_free (view->entry); + ply_label_free (view->label); + ply_label_free (view->message_label); + view_free_sprites (view); + ply_list_free (view->sprites); + ++ ply_pixel_display_set_draw_handler (view->display, NULL, NULL); ++ + ply_image_free (view->scaled_background_image); + + free (view); + } + + 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); + + node = next_node; + } + + ply_list_free (plugin->views); + plugin->views = NULL; + } + + static bool + view_load (view_t *view) +@@ -1428,62 +1430,60 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + view_t *view; + + view = view_new (plugin, display); + + 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 + remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { +- +- ply_pixel_display_set_draw_handler (view->display, NULL, NULL); + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + + static void + view_setup_scene (view_t *view) + { + ply_boot_splash_plugin_t *plugin; + sprite_t *sprite; + int i; + int x, y; + int width = 360; + int height = 460; + 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); + + { + star_bg_t* star_bg; + if (view->scaled_background_image) + ply_image_free (view->scaled_background_image); + view->scaled_background_image = ply_image_resize (plugin->logo_image, screen_width, screen_height); +diff --git a/src/plugins/splash/throbgress/plugin.c b/src/plugins/splash/throbgress/plugin.c +index fba809b..d669a74 100644 +--- a/src/plugins/splash/throbgress/plugin.c ++++ b/src/plugins/splash/throbgress/plugin.c +@@ -115,60 +115,62 @@ static void become_idle (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->throbber = ply_throbber_new (plugin->image_dir, + "throbber-"); + view->progress_bar = ply_progress_bar_new (); + view->label = ply_label_new (); + view->message_label = ply_label_new (); + + return view; + } + + static void + view_free (view_t *view) + { + + ply_entry_free (view->entry); + ply_throbber_free (view->throbber); + ply_progress_bar_free (view->progress_bar); + ply_label_free (view->label); + ply_label_free (view->message_label); + ++ ply_pixel_display_set_draw_handler (view->display, NULL, NULL); ++ + free (view); + } + + 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 bool + view_load (view_t *view) +@@ -631,62 +633,60 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin, + view_t *view; + + ply_trace ("adding pixel display to plugin"); + view = view_new (plugin, display); + + 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 + remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + ply_list_node_t *node; + + ply_trace ("removing pixel display from plugin"); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { +- +- ply_pixel_display_set_draw_handler (view->display, NULL, NULL); + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + + static bool + show_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop, + ply_buffer_t *boot_buffer, + ply_boot_splash_mode_t mode) + { + assert (plugin != NULL); + assert (plugin->logo_image != NULL); + + plugin->loop = loop; + plugin->mode = mode; + + ply_trace ("loading logo image"); + if (!ply_image_load (plugin->logo_image)) + return false; + + ply_trace ("loading lock image"); + if (!ply_image_load (plugin->lock_image)) + return false; + + ply_trace ("loading box image"); +diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c +index f48b41e..0253aac 100644 +--- a/src/plugins/splash/two-step/plugin.c ++++ b/src/plugins/splash/two-step/plugin.c +@@ -155,60 +155,62 @@ view_new (ply_boot_splash_plugin_t *plugin, + + view->entry = ply_entry_new (plugin->animation_dir); + view->end_animation = ply_animation_new (plugin->animation_dir, + "animation-"); + view->progress_animation = ply_progress_animation_new (plugin->animation_dir, + "progress-"); + + view->throbber = ply_throbber_new (plugin->animation_dir, + "throbber-"); + ply_progress_animation_set_transition (view->progress_animation, + plugin->transition, + plugin->transition_duration); + + view->label = ply_label_new (); + view->message_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_throbber_free (view->throbber); + ply_label_free (view->label); + ply_label_free (view->message_label); + ++ ply_pixel_display_set_draw_handler (view->display, NULL, NULL); ++ + if (view->background_image != NULL) + ply_image_free (view->background_image); + + free (view); + } + + static bool + view_load (view_t *view) + { + unsigned long screen_width, screen_height; + ply_boot_splash_plugin_t *plugin; + + plugin = view->plugin; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + if (plugin->background_tile_image != NULL) + { + ply_trace ("tiling background to %lux%lu", screen_width, screen_height); + view->background_image = ply_image_tile (plugin->background_tile_image, screen_width, screen_height); + } + + if (plugin->watermark_image != NULL) + { + view->watermark_area.width = ply_image_get_width (plugin->watermark_image); + view->watermark_area.height = ply_image_get_height (plugin->watermark_image); + view->watermark_area.x = screen_width * plugin->watermark_horizontal_alignment - ply_image_get_width (plugin->watermark_image) * plugin->watermark_horizontal_alignment; + view->watermark_area.y = screen_height * plugin->watermark_vertical_alignment - ply_image_get_height (plugin->watermark_image) * plugin->watermark_vertical_alignment; + } +@@ -993,61 +995,60 @@ add_pixel_display (ply_boot_splash_plugin_t *plugin, + view_t *view; + + ply_trace ("adding pixel display to plugin"); + view = view_new (plugin, display); + + 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 + remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + ply_list_node_t *node; + + ply_trace ("removing pixel display from plugin"); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { + +- ply_pixel_display_set_draw_handler (view->display, NULL, NULL); + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + + static bool + show_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop, + ply_buffer_t *boot_buffer, + ply_boot_splash_mode_t mode) + { + assert (plugin != NULL); + + plugin->loop = loop; + plugin->mode = mode; + + 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; + + if (plugin->corner_image != NULL) + { +-- +2.5.0 + + +From b849b3edc60cac8d1c1f7a66d103768abdb71666 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 24 Sep 2015 15:55:08 -0400 +Subject: [PATCH 3/6] plugins: free views that can't load + +Trying to use an unloaded view can lead to crashes. +If a view can't be loaded, free it right away. +--- + src/plugins/splash/fade-throbber/plugin.c | 9 ++++++++- + src/plugins/splash/space-flares/plugin.c | 9 ++++++++- + src/plugins/splash/throbgress/plugin.c | 9 ++++++++- + src/plugins/splash/two-step/plugin.c | 9 ++++++++- + 4 files changed, 32 insertions(+), 4 deletions(-) + +diff --git a/src/plugins/splash/fade-throbber/plugin.c b/src/plugins/splash/fade-throbber/plugin.c +index 7b097c0..953186d 100644 +--- a/src/plugins/splash/fade-throbber/plugin.c ++++ b/src/plugins/splash/fade-throbber/plugin.c +@@ -273,61 +273,68 @@ view_free (view_t *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; ++ { ++ view_loaded = true; ++ } ++ else ++ { ++ ply_list_remove_node (plugin->views, node); ++ view_free (view); ++ } + + 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; + +diff --git a/src/plugins/splash/space-flares/plugin.c b/src/plugins/splash/space-flares/plugin.c +index 45863ff..b18f39f 100644 +--- a/src/plugins/splash/space-flares/plugin.c ++++ b/src/plugins/splash/space-flares/plugin.c +@@ -268,61 +268,68 @@ free_views (ply_boot_splash_plugin_t *plugin) + } + + 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; ++ { ++ view_loaded = true; ++ } ++ else ++ { ++ ply_list_remove_node (plugin->views, node); ++ view_free (view); ++ } + + 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; + +diff --git a/src/plugins/splash/throbgress/plugin.c b/src/plugins/splash/throbgress/plugin.c +index d669a74..e3ce91b 100644 +--- a/src/plugins/splash/throbgress/plugin.c ++++ b/src/plugins/splash/throbgress/plugin.c +@@ -177,61 +177,68 @@ view_load (view_t *view) + { + ply_trace ("loading entry"); + if (!ply_entry_load (view->entry)) + return false; + + ply_trace ("loading throbber"); + if (!ply_throbber_load (view->throbber)) + 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; ++ { ++ view_loaded = true; ++ } ++ else ++ { ++ ply_list_remove_node (plugin->views, node); ++ view_free (view); ++ } + + 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; + +diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c +index 0253aac..4612e3f 100644 +--- a/src/plugins/splash/two-step/plugin.c ++++ b/src/plugins/splash/two-step/plugin.c +@@ -257,61 +257,68 @@ view_load (view_t *view) + ply_throbber_free (view->throbber); + view->throbber = NULL; + } + } + else + { + ply_trace ("this theme has no throbber\n"); + } + + 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; ++ { ++ view_loaded = true; ++ } ++ else ++ { ++ ply_list_remove_node (plugin->views, node); ++ view_free (view); ++ } + + 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; + +-- +2.5.0 + + +From a790e8d26d81b978ed2d90a5730c717af9dc673b Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 24 Sep 2015 15:57:59 -0400 +Subject: [PATCH 4/6] plugins: load view of hot plugged displays immediately + +If we're already chugging along, and a new display +gets added make sure to load the view associated with +that display right away. + +Using an unloaded view can lead to crashes. +--- + src/plugins/splash/fade-throbber/plugin.c | 18 ++++++++++++++++-- + src/plugins/splash/space-flares/plugin.c | 13 +++++++++++-- + src/plugins/splash/text/plugin.c | 3 +++ + src/plugins/splash/throbgress/plugin.c | 13 +++++++++++-- + src/plugins/splash/tribar/plugin.c | 7 ++++++- + src/plugins/splash/two-step/plugin.c | 12 +++++++++++- + 6 files changed, 58 insertions(+), 8 deletions(-) + +diff --git a/src/plugins/splash/fade-throbber/plugin.c b/src/plugins/splash/fade-throbber/plugin.c +index 953186d..946a732 100644 +--- a/src/plugins/splash/fade-throbber/plugin.c ++++ b/src/plugins/splash/fade-throbber/plugin.c +@@ -76,60 +76,61 @@ typedef struct + } 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_label_t *message_label; + ply_rectangle_t lock_area; + double logo_opacity; + } view_t; + + struct _ply_boot_splash_plugin + { + ply_event_loop_t *loop; + ply_boot_splash_mode_t mode; + ply_image_t *logo_image; + ply_image_t *star_image; + ply_image_t *lock_image; + char *image_dir; + ply_list_t *views; + + ply_boot_splash_display_type_t state; + + double start_time; + double now; + + uint32_t is_animating : 1; ++ uint32_t is_visible : 1; + }; + + ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void); + + 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; +@@ -741,62 +742,71 @@ on_draw (view_t *view, + int width, + int height) + { + ply_boot_splash_plugin_t *plugin; + + plugin = view->plugin; + + draw_background (view, pixel_buffer, x, y, width, height); + + if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) + draw_normal_view (view, pixel_buffer, x, y, width, height); + else + draw_prompt_view (view, pixel_buffer, x, y, width, height); + + ply_label_draw_area (view->message_label, + pixel_buffer, + x, y, width, height); + } + + static void + add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + view_t *view; + + view = view_new (plugin, display); + + ply_pixel_display_set_draw_handler (view->display, + (ply_pixel_display_draw_handler_t) + on_draw, view); +- +- ply_list_append_data (plugin->views, view); ++ if (plugin->is_visible) ++ { ++ if (view_load (view)) ++ ply_list_append_data (plugin->views, view); ++ else ++ view_free (view); ++ } ++ else ++ { ++ ply_list_append_data (plugin->views, view); ++ } + } + + static void + remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + + static bool + show_splash_screen (ply_boot_splash_plugin_t *plugin, +@@ -805,60 +815,62 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_boot_splash_mode_t mode) + { + assert (plugin != NULL); + assert (plugin->logo_image != NULL); + + plugin->loop = loop; + plugin->mode = mode; + + ply_trace ("loading logo image"); + if (!ply_image_load (plugin->logo_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_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + plugin); + + if (!load_views (plugin)) + { + ply_trace ("couldn't load views"); + return false; + } + ++ plugin->is_visible = true; ++ + ply_trace ("starting boot animation"); + start_animation (plugin); + + return true; + } + + static void + view_add_star (view_t *view) + { + 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 (view != NULL); + + plugin = view->plugin; + + 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 = (screen_width / 2) - (width / 2); + logo_area.y = (screen_height / 2) - (height / 2); + logo_area.width = width; + logo_area.height = height; + +@@ -944,60 +956,62 @@ update_status (ply_boot_splash_plugin_t *plugin, + static void + show_message (ply_boot_splash_plugin_t *plugin, + const char *message) + { + ply_trace ("Showing message '%s'", message); + 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_label_set_text (view->message_label, message); + ply_label_show (view->message_label, view->display, 10, 10); + + ply_pixel_display_draw_area (view->display, 10, 10, + ply_label_get_width (view->message_label), + ply_label_get_height(view->message_label)); + node = next_node; + } + } + + static void + hide_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop) + { + assert (plugin != NULL); + ++ plugin->is_visible = false; ++ + if (plugin->loop != NULL) + { + stop_animation (plugin); + + 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); + } + } + + 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; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_show_prompt (view, text); + ply_entry_set_bullet_count (view->entry, number_of_bullets); + +diff --git a/src/plugins/splash/space-flares/plugin.c b/src/plugins/splash/space-flares/plugin.c +index b18f39f..9e53617 100644 +--- a/src/plugins/splash/space-flares/plugin.c ++++ b/src/plugins/splash/space-flares/plugin.c +@@ -1416,62 +1416,71 @@ draw_background (view_t *view, + image_area.width = ply_image_get_width(plugin->star_image); + image_area.height = ply_image_get_height(plugin->star_image); + + + ply_pixel_buffer_fill_with_argb32_data_with_clip (pixel_buffer, + &image_area, &area, + ply_image_get_data (plugin->star_image)); + + image_area.x = 20; + image_area.y = 20; + image_area.width = ply_image_get_width(plugin->logo_image); + image_area.height = ply_image_get_height(plugin->logo_image); + + + ply_pixel_buffer_fill_with_argb32_data_with_clip (pixel_buffer, + &image_area, &area, + ply_image_get_data (plugin->logo_image)); + } + + static void + add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + view_t *view; + + view = view_new (plugin, display); + + ply_pixel_display_set_draw_handler (view->display, + (ply_pixel_display_draw_handler_t) + on_draw, view); +- +- ply_list_append_data (plugin->views, view); ++ if (plugin->is_visible) ++ { ++ if (view_load (view)) ++ ply_list_append_data (plugin->views, view); ++ else ++ view_free (view); ++ } ++ else ++ { ++ ply_list_append_data (plugin->views, view); ++ } + } + + static void + remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + + static void + view_setup_scene (view_t *view) +diff --git a/src/plugins/splash/text/plugin.c b/src/plugins/splash/text/plugin.c +index fb97c14..69125a2 100644 +--- a/src/plugins/splash/text/plugin.c ++++ b/src/plugins/splash/text/plugin.c +@@ -458,60 +458,63 @@ stop_animation (ply_boot_splash_plugin_t *plugin) + + static void + on_draw (view_t *view, + ply_terminal_t *terminal, + int x, + int y, + int width, + int height) + { + ply_text_display_clear_screen (view->display); + } + + static void + add_text_display (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) + { + view_t *view; + ply_terminal_t *terminal; + + view = view_new (plugin, display); + + terminal = ply_text_display_get_terminal (view->display); + if (ply_terminal_open (terminal)) + ply_terminal_activate_vt (terminal); + + ply_text_display_set_draw_handler (view->display, + (ply_text_display_draw_handler_t) + on_draw, view); + + ply_list_append_data (plugin->views, view); ++ ++ if (plugin->is_animating) ++ view_start_animation (view); + } + + static void + remove_text_display (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) + { + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { + ply_text_display_set_draw_handler (view->display, + NULL, NULL); + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + +diff --git a/src/plugins/splash/throbgress/plugin.c b/src/plugins/splash/throbgress/plugin.c +index e3ce91b..c4d0555 100644 +--- a/src/plugins/splash/throbgress/plugin.c ++++ b/src/plugins/splash/throbgress/plugin.c +@@ -618,62 +618,71 @@ on_draw (view_t *view, + lock_data = ply_image_get_data (plugin->lock_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->lock_area, + lock_data); + } + else + { + draw_logo (view, pixel_buffer); + ply_throbber_draw_area (view->throbber, + pixel_buffer, x, y, width, height); + ply_progress_bar_draw_area (view->progress_bar, + pixel_buffer, x, y, width, height); + } + ply_label_draw_area (view->message_label, + pixel_buffer, + x, y, width, height); + } + + static void + add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + view_t *view; + + ply_trace ("adding pixel display to plugin"); + view = view_new (plugin, display); + + ply_pixel_display_set_draw_handler (view->display, + (ply_pixel_display_draw_handler_t) + on_draw, view); +- +- ply_list_append_data (plugin->views, view); ++ if (plugin->is_visible) ++ { ++ if (view_load (view)) ++ ply_list_append_data (plugin->views, view); ++ else ++ view_free (view); ++ } ++ else ++ { ++ ply_list_append_data (plugin->views, view); ++ } + } + + static void + remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + ply_list_node_t *node; + + ply_trace ("removing pixel display from plugin"); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + + static bool +diff --git a/src/plugins/splash/tribar/plugin.c b/src/plugins/splash/tribar/plugin.c +index 4458bad..5b89cc3 100644 +--- a/src/plugins/splash/tribar/plugin.c ++++ b/src/plugins/splash/tribar/plugin.c +@@ -461,60 +461,63 @@ stop_animation (ply_boot_splash_plugin_t *plugin) + + static void + on_draw (view_t *view, + ply_terminal_t *terminal, + int x, + int y, + int width, + int height) + { + ply_text_display_clear_screen (view->display); + } + + static void + add_text_display (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) + { + view_t *view; + ply_terminal_t *terminal; + + view = view_new (plugin, display); + + terminal = ply_text_display_get_terminal (view->display); + if (ply_terminal_open (terminal)) + ply_terminal_activate_vt (terminal); + + ply_text_display_set_draw_handler (view->display, + (ply_text_display_draw_handler_t) + on_draw, view); + + ply_list_append_data (plugin->views, view); ++ ++ if (plugin->is_animating) ++ view_start_animation (view); + } + + static void + remove_text_display (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) + { + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { + ply_text_display_set_draw_handler (view->display, + NULL, NULL); + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + +@@ -545,61 +548,63 @@ update_status (ply_boot_splash_plugin_t *plugin, + assert (plugin != NULL); + + ply_trace ("status update"); + } + + static void + on_boot_progress (ply_boot_splash_plugin_t *plugin, + double duration, + double percent_done) + { + ply_list_node_t *node; + double total_duration; + + total_duration = duration / percent_done; + + /* Fun made-up smoothing function to make the growth asymptotic: + * 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); + + 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_text_progress_bar_set_percent_done (view->progress_bar, percent_done); +- ply_text_progress_bar_draw (view->progress_bar); ++ ++ if (plugin->is_animating) ++ ply_text_progress_bar_draw (view->progress_bar); + + node = next_node; + } + } + + static void + hide_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop) + { + assert (plugin != NULL); + + ply_trace ("hiding splash screen"); + + if (plugin->loop != NULL) + { + stop_animation (plugin); + + 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); + } + + hide_views (plugin); + ply_show_new_kernel_messages (true); + } + + static void + display_normal (ply_boot_splash_plugin_t *plugin) +diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c +index 4612e3f..a1d1f00 100644 +--- a/src/plugins/splash/two-step/plugin.c ++++ b/src/plugins/splash/two-step/plugin.c +@@ -980,61 +980,71 @@ on_draw (view_t *view, + + if (view->throbber != NULL) + sprite_height = MAX (ply_throbber_get_height (view->throbber), + sprite_height); + + image_area.width = ply_image_get_width (plugin->header_image); + image_area.height = ply_image_get_height (plugin->header_image); + image_area.x = screen_area.width / 2.0 - image_area.width / 2.0; + image_area.y = plugin->animation_vertical_alignment * screen_area.height - sprite_height / 2.0 - image_area.height; + + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &image_area, ply_image_get_data (plugin->header_image)); + } + } + ply_label_draw_area (view->message_label, + pixel_buffer, + x, y, width, height); + } + + static void + add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + view_t *view; + + ply_trace ("adding pixel display to plugin"); + view = view_new (plugin, display); + + ply_pixel_display_set_draw_handler (view->display, + (ply_pixel_display_draw_handler_t) + on_draw, view); +- ply_list_append_data (plugin->views, view); ++ if (plugin->is_visible) ++ { ++ if (view_load (view)) ++ ply_list_append_data (plugin->views, view); ++ else ++ view_free (view); ++ } ++ else ++ { ++ ply_list_append_data (plugin->views, view); ++ } + } + + static void + remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) + { + ply_list_node_t *node; + + ply_trace ("removing pixel display from plugin"); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { + + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + +-- +2.5.0 + + +From 3dc6d04a80329bb97e574c2785f79a684bfdc41b Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 9 Oct 2015 12:46:49 -0400 +Subject: [PATCH 5/6] details: update new views with current boot buffer + +if a view is added after the splash is shown, make sure +to update the view with the current contents of the boot +buffer. +--- + src/plugins/splash/details/plugin.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/src/plugins/splash/details/plugin.c b/src/plugins/splash/details/plugin.c +index aff2f1c..6ddd654 100644 +--- a/src/plugins/splash/details/plugin.c ++++ b/src/plugins/splash/details/plugin.c +@@ -49,61 +49,61 @@ + #include "ply-text-display.h" + #include "ply-trigger.h" + #include "ply-utils.h" + + #include + + #define CLEAR_LINE_SEQUENCE "\033[2K\r" + + typedef enum { + PLY_BOOT_SPLASH_DISPLAY_NORMAL, + PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY, + PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY + } ply_boot_splash_display_type_t; + + typedef struct + { + ply_boot_splash_plugin_t *plugin; + ply_text_display_t *display; + } view_t; + + ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void); + static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin); + + struct _ply_boot_splash_plugin + { + ply_event_loop_t *loop; + ply_boot_splash_mode_t mode; + ply_list_t *views; + ply_boot_splash_display_type_t state; + ply_list_t *messages; +- ++ ply_buffer_t *boot_buffer; + }; + + static view_t * + view_new (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) + { + view_t *view; + + view = calloc (1, sizeof (view_t)); + view->plugin = plugin; + view->display = display; + + return view; + } + + static void + view_free (view_t *view) + { + free (view); + } + + 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) + { +@@ -217,108 +217,119 @@ write_on_views (ply_boot_splash_plugin_t *plugin, + + 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_write (view, text, number_of_bytes); + + node = next_node; + } + + } + + static void + add_text_display (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) + { + view_t *view; + ply_terminal_t *terminal; + + view = view_new (plugin, display); + + terminal = ply_text_display_get_terminal (view->display); + if (ply_terminal_open (terminal)) + ply_terminal_activate_vt (terminal); + + ply_list_append_data (plugin->views, view); ++ ++ if (plugin->boot_buffer != NULL) ++ { ++ size_t size; ++ const char *bytes; ++ ++ size = ply_buffer_get_size (plugin->boot_buffer); ++ bytes = ply_buffer_get_bytes (plugin->boot_buffer); ++ view_write (view, bytes, size); ++ } + } + + static void + remove_text_display (ply_boot_splash_plugin_t *plugin, + ply_text_display_t *display) + { + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) + { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) + { + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } + } + + static bool + show_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop, + ply_buffer_t *boot_buffer, + ply_boot_splash_mode_t mode) + { + size_t size; + + assert (plugin != NULL); + + plugin->loop = loop; + plugin->mode = mode; + + ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + plugin); + + if (boot_buffer) + { +- size = ply_buffer_get_size (boot_buffer); ++ plugin->boot_buffer = boot_buffer; + ++ size = ply_buffer_get_size (boot_buffer); + write_on_views (plugin, ply_buffer_get_bytes (boot_buffer), size); + } + + return true; + } + + static void + update_status (ply_boot_splash_plugin_t *plugin, + const char *status) + { + assert (plugin != NULL); + + ply_trace ("status update"); + } + + static void + on_boot_output (ply_boot_splash_plugin_t *plugin, + const char *output, + size_t size) + { + ply_trace ("writing '%s' to all views (%d bytes)", + output, (int) size); + write_on_views (plugin, output, size); + } + + static void + hide_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop) + { + assert (plugin != NULL); +-- +2.5.0 + + +From 07864d66b30aa37908df83495d3bffc681fb34d3 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 9 Oct 2015 12:48:17 -0400 +Subject: [PATCH 6/6] main: make sure to reshow prompts when new display is + added + +When a display is added, we need to tell the splash plugin +to redisplay any pending questions, so those questions show +up on the new display. +--- + src/main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/main.c b/src/main.c +index 875dd1a..7c4ea3c 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -1022,89 +1022,92 @@ on_keyboard_removed (state_t *state, + (ply_keyboard_escape_handler_t) + on_escape_pressed); + ply_trace ("no longer listening for backspace"); + ply_keyboard_remove_backspace_handler (keyboard, + (ply_keyboard_backspace_handler_t) + on_backspace); + ply_trace ("no longer listening for enter"); + ply_keyboard_remove_enter_handler (keyboard, + (ply_keyboard_enter_handler_t) + on_enter); + + if (state->boot_splash != NULL) + ply_boot_splash_unset_keyboard (state->boot_splash); + } + + static void + on_pixel_display_added (state_t *state, + ply_pixel_display_t *display) + { + if (state->is_shown) + { + if (state->boot_splash == NULL) + { + ply_trace ("pixel display added before splash loaded, so loading splash now"); + show_splash (state); + } + else + { + ply_trace ("pixel display added after splash loaded, so attaching to splash"); + ply_boot_splash_add_pixel_display (state->boot_splash, display); ++ update_display (state); + } + } + } + + static void + on_pixel_display_removed (state_t *state, + ply_pixel_display_t *display) + { + if (state->boot_splash == NULL) + return; + + ply_boot_splash_remove_pixel_display (state->boot_splash, display); + } + + static void + on_text_display_added (state_t *state, + ply_text_display_t *display) + { + if (state->is_shown) + { + if (state->boot_splash == NULL) + { + ply_trace ("text display added before splash loaded, so loading splash now"); + show_splash (state); + } + else + { + ply_trace ("text display added after splash loaded, so attaching to splash"); + ply_boot_splash_add_text_display (state->boot_splash, display); ++ ++ update_display (state); + } + } + } + + static void + on_text_display_removed (state_t *state, + ply_text_display_t *display) + { + if (state->boot_splash == NULL) + return; + + ply_boot_splash_remove_text_display (state->boot_splash, display); + } + + static void + load_devices (state_t *state, + ply_device_manager_flags_t flags) + { + state->device_manager = ply_device_manager_new (state->default_tty, flags); + state->local_console_terminal = ply_device_manager_get_default_terminal (state->device_manager); + + ply_device_manager_watch_devices (state->device_manager, + (ply_keyboard_added_handler_t) + on_keyboard_added, + (ply_keyboard_removed_handler_t) + on_keyboard_removed, + (ply_pixel_display_added_handler_t) + on_pixel_display_added, + (ply_pixel_display_removed_handler_t) + on_pixel_display_removed, +-- +2.5.0 + diff --git a/SOURCES/cursor-fix.patch b/SOURCES/cursor-fix.patch new file mode 100644 index 0000000..e483d71 --- /dev/null +++ b/SOURCES/cursor-fix.patch @@ -0,0 +1,526 @@ +From b96ff001587de11eaf98ace71b196cc5ab4cf007 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 14 Jul 2014 08:04:54 -0400 +Subject: [PATCH 1/5] seat: be a little more forgiving in the case there's no + open terminal + +We can end up in a situation where a seat object doesn't have a terminal +associated with it. In that case we shouldn't crash, but continue on +with no input available for that seat. + +https://bugs.freedesktop.org/show_bug.cgi?id=80553 +--- + src/libply-splash-core/ply-seat.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/src/libply-splash-core/ply-seat.c b/src/libply-splash-core/ply-seat.c +index 2ac8bf7..cd7e5bc 100644 +--- a/src/libply-splash-core/ply-seat.c ++++ b/src/libply-splash-core/ply-seat.c +@@ -127,68 +127,83 @@ ply_seat_open (ply_seat_t *seat, + if (renderer_type != PLY_RENDERER_TYPE_NONE) + { + ply_renderer_t *renderer; + + renderer = ply_renderer_new (renderer_type, device, seat->terminal); + + if (!ply_renderer_open (renderer)) + { + ply_trace ("could not open renderer for %s", device); + ply_renderer_free (renderer); + + seat->renderer = NULL; + seat->renderer_active = false; + + if (renderer_type != PLY_RENDERER_TYPE_AUTO) + return false; + } + else + { + seat->renderer = renderer; + seat->renderer_active = true; + } + } + + if (seat->renderer != NULL) + { + seat->keyboard = ply_keyboard_new_for_renderer (seat->renderer); + add_pixel_displays (seat); + + } +- else ++ else if (seat->terminal != NULL) + { + seat->keyboard = ply_keyboard_new_for_terminal (seat->terminal); + } +- add_text_displays (seat); + +- ply_keyboard_watch_for_input (seat->keyboard); +- seat->keyboard_active = true; ++ if (seat->terminal != NULL) ++ { ++ add_text_displays (seat); ++ } ++ else ++ { ++ ply_trace ("not adding text display for seat, since seat has no associated terminal"); ++ } ++ ++ if (seat->keyboard != NULL) ++ { ++ ply_keyboard_watch_for_input (seat->keyboard); ++ seat->keyboard_active = true; ++ } ++ else ++ { ++ ply_trace ("not watching seat for input"); ++ } + + return true; + } + + bool + ply_seat_is_open (ply_seat_t *seat) + { + return ply_list_get_length (seat->pixel_displays) > 0 || + ply_list_get_length (seat->text_displays) > 0; + } + + void + ply_seat_deactivate_keyboard (ply_seat_t *seat) + { + if (!seat->keyboard_active) + return; + + seat->keyboard_active = false; + + if (seat->keyboard == NULL) + return; + + ply_trace ("deactivating keybord"); + ply_keyboard_stop_watching_for_input (seat->keyboard); + } + + void + ply_seat_deactivate_renderer (ply_seat_t *seat) + { + if (!seat->renderer_active) +-- +2.3.7 + + +From b5ed92bc2efd0b52e901a67ea8e5afa809ca3598 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 3 Jul 2015 09:29:39 -0400 +Subject: [PATCH 2/5] main: show cursor on crash + +--- + src/main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/main.c b/src/main.c +index 77fa96f..db5c281 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -2051,66 +2051,69 @@ on_error_message (ply_buffer_t *debug_buffer, + { + ply_buffer_append_bytes (debug_buffer, bytes, number_of_bytes); + } + + static void + dump_debug_buffer_to_file (void) + { + int fd; + const char *bytes; + size_t size; + + fd = open (debug_buffer_path, + O_WRONLY | O_CREAT | O_TRUNC, 0600); + + if (fd < 0) + return; + + size = ply_buffer_get_size (debug_buffer); + bytes = ply_buffer_get_bytes (debug_buffer); + ply_write (fd, bytes, size); + close (fd); + } + + #include + #include + static void + on_crash (int signum) + { + struct termios term_attributes; + int fd; ++ static const char *show_cursor_sequence = "\033[?25h"; + + fd = open ("/dev/tty1", O_RDWR | O_NOCTTY); + if (fd < 0) fd = open ("/dev/hvc0", O_RDWR | O_NOCTTY); + + ioctl (fd, KDSETMODE, KD_TEXT); + ++ write (fd, show_cursor_sequence, sizeof (show_cursor_sequence) - 1); ++ + tcgetattr (fd, &term_attributes); + + term_attributes.c_iflag |= BRKINT | IGNPAR | ICRNL | IXON; + term_attributes.c_oflag |= OPOST; + term_attributes.c_lflag |= ECHO | ICANON | ISIG | IEXTEN; + + tcsetattr (fd, TCSAFLUSH, &term_attributes); + + close (fd); + + if (debug_buffer != NULL) + { + dump_debug_buffer_to_file (); + sleep (30); + } + + if (pid_file != NULL) + { + unlink (pid_file); + free (pid_file); + pid_file = NULL; + } + + signal (signum, SIG_DFL); + raise(signum); + } + + static void + write_pid_file (const char *filename) + { +-- +2.3.7 + + +From 4278596f4f5a6856aff50e97b7c0ff05aed67372 Mon Sep 17 00:00:00 2001 +From: Frederic Crozat +Date: Thu, 12 Jun 2014 15:01:37 +0200 +Subject: [PATCH 3/5] device-manager: only call ply_terminal_free + +ply_terminal_free will call ply_terminal_close anyway and is guarded +against NULL terminal (ply_terminal_close is not). +--- + src/libply-splash-core/ply-device-manager.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c +index 8f5360c..17607f4 100644 +--- a/src/libply-splash-core/ply-device-manager.c ++++ b/src/libply-splash-core/ply-device-manager.c +@@ -415,61 +415,60 @@ free_seats (ply_device_manager_t *manager) + { + ply_list_node_t *node; + + ply_trace ("removing seats"); + node = ply_list_get_first_node (manager->seats); + while (node != NULL) + { + ply_seat_t *seat; + ply_list_node_t *next_node; + + seat = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (manager->seats, node); + + if (manager->seat_removed_handler != NULL) + manager->seat_removed_handler (manager->seat_event_handler_data, seat); + + ply_seat_free (seat); + ply_list_remove_node (manager->seats, node); + + node = next_node; + } + } + + static void + free_terminal (char *device, + ply_terminal_t *terminal, + ply_device_manager_t *manager) + { + ply_hashtable_remove (manager->terminals, device); + +- ply_terminal_close (terminal); + ply_terminal_free (terminal); + } + + static void + free_terminals (ply_device_manager_t *manager) + { + ply_hashtable_foreach (manager->terminals, + (ply_hashtable_foreach_func_t *) + free_terminal, + manager); + } + + static ply_terminal_t * + get_terminal (ply_device_manager_t *manager, + const char *device_name) + { + char *full_name = NULL; + ply_terminal_t *terminal; + + if (strncmp (device_name, "/dev/", strlen ("/dev/")) == 0) + full_name = strdup (device_name); + else + asprintf (&full_name, "/dev/%s", device_name); + + if (strcmp (full_name, "/dev/tty0") == 0 || + strcmp (full_name, "/dev/tty") == 0 || + strcmp (full_name, ply_terminal_get_name (manager->local_console_terminal)) == 0) + { + terminal = manager->local_console_terminal; + +-- +2.3.7 + + +From e7048fdd1a40ed683fc706a40816cc490a693ba9 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 7 Jan 2015 16:24:57 -0500 +Subject: [PATCH 4/5] device-manager: try fb device if drm device failed + +If the drm device failed to work, then fall back to the fb device. + +Right now, we ignore fb devices that have associated drm devices. + +This may fix vmwgfx. +--- + src/libply-splash-core/ply-device-manager.c | 39 ++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c +index 17607f4..cc153e2 100644 +--- a/src/libply-splash-core/ply-device-manager.c ++++ b/src/libply-splash-core/ply-device-manager.c +@@ -88,95 +88,132 @@ attach_to_event_loop (ply_device_manager_t *manager, + } + + static bool + device_is_for_local_console (ply_device_manager_t *manager, + struct udev_device *device) + { + const char *device_path; + struct udev_device *bus_device; + char *bus_device_path; + const char *boot_vga; + bool for_local_console; + + /* Look at the associated bus device to see if this card is the + * card the kernel is using for its console. */ + device_path = udev_device_get_syspath (device); + asprintf (&bus_device_path, "%s/device", device_path); + bus_device = udev_device_new_from_syspath (manager->udev_context, bus_device_path); + + boot_vga = udev_device_get_sysattr_value (bus_device, "boot_vga"); + free (bus_device_path); + + if (boot_vga != NULL && strcmp (boot_vga, "1") == 0) + for_local_console = true; + else + for_local_console = false; + + return for_local_console; + } + + static bool ++drm_device_in_use (ply_device_manager_t *manager, ++ const char *device_path) ++{ ++ ply_list_node_t *node; ++ ++ node = ply_list_get_first_node (manager->seats); ++ while (node != NULL) ++ { ++ ply_seat_t *seat; ++ ply_renderer_t *renderer; ++ ply_list_node_t *next_node; ++ const char *renderer_device_path; ++ ++ seat = ply_list_node_get_data (node); ++ next_node = ply_list_get_next_node (manager->seats, node); ++ renderer = ply_seat_get_renderer (seat); ++ ++ if (renderer != NULL) ++ { ++ renderer_device_path = ply_renderer_get_device_name (renderer); ++ ++ if (renderer_device_path != NULL) ++ { ++ if (strcmp (device_path, renderer_device_path) == 0) ++ { ++ return true; ++ } ++ } ++ } ++ ++ node = next_node; ++ } ++ ++ return false; ++} ++ ++static bool + fb_device_has_drm_device (ply_device_manager_t *manager, + struct udev_device *fb_device) + { + struct udev_enumerate *card_matches; + struct udev_list_entry *card_entry; + const char *id_path; + bool has_drm_device = false; + + /* We want to see if the framebuffer is associated with a DRM-capable + * graphics card, if it is, we'll use the DRM device */ + card_matches = udev_enumerate_new (manager->udev_context); + udev_enumerate_add_match_is_initialized(card_matches); + udev_enumerate_add_match_parent (card_matches, udev_device_get_parent (fb_device)); + udev_enumerate_add_match_subsystem (card_matches, "drm"); + id_path = udev_device_get_property_value (fb_device, "ID_PATH"); + udev_enumerate_add_match_property (card_matches, "ID_PATH", id_path); + + ply_trace ("trying to find associated drm node for fb device (path: %s)", id_path); + + udev_enumerate_scan_devices (card_matches); + + /* there should only ever be at most one match so we don't iterate through + * the list, but just look at the first entry */ + card_entry = udev_enumerate_get_list_entry (card_matches); + + if (card_entry != NULL) + { + struct udev_device *card_device = NULL; + const char *card_node; + const char *card_path; + + card_path = udev_list_entry_get_name (card_entry); + card_device = udev_device_new_from_syspath (manager->udev_context, card_path); + card_node = udev_device_get_devnode (card_device); +- if (card_node != NULL) ++ if (card_node != NULL && drm_device_in_use (manager, card_node)) + has_drm_device = true; + else + ply_trace ("no card node!"); + + udev_device_unref (card_device); + } + else + { + ply_trace ("no card entry!"); + } + + udev_enumerate_unref (card_matches); + return has_drm_device; + } + + static void + create_seat_for_udev_device (ply_device_manager_t *manager, + struct udev_device *device) + { + bool for_local_console; + const char *device_path; + ply_terminal_t *terminal = NULL; + + for_local_console = device_is_for_local_console (manager, device); + + ply_trace ("device is for local console: %s", for_local_console? "yes" : "no"); + + if (for_local_console) + terminal = manager->local_console_terminal; + +-- +2.3.7 + + +From b9989b912fb394c00d3d4740eb72a25f80a8bc71 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 3 Jul 2015 10:38:47 -0400 +Subject: [PATCH 5/5] device-manager: don't try to load graphical splash after + using text splash + +We only support loading one splash at a time at the moment, so this +commit makes sure we don't load a graphical splash after already loading +a text splash +--- + src/libply-splash-core/ply-device-manager.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c +index cc153e2..a7890d0 100644 +--- a/src/libply-splash-core/ply-device-manager.c ++++ b/src/libply-splash-core/ply-device-manager.c +@@ -379,61 +379,69 @@ create_seats_for_subsystem (ply_device_manager_t *manager, + return found_device; + } + + static void + on_udev_event (ply_device_manager_t *manager) + { + struct udev_device *device; + const char *action; + + device = udev_monitor_receive_device (manager->udev_monitor); + if (device == NULL) + return; + + action = udev_device_get_action (device); + + ply_trace ("got %s event for device %s", action, udev_device_get_sysname (device)); + + if (action == NULL) + return; + + if (strcmp (action, "add") == 0) + { + const char *subsystem; + bool coldplug_complete = manager->udev_queue_fd_watch == NULL; + + subsystem = udev_device_get_subsystem (device); + + if (strcmp (subsystem, SUBSYSTEM_DRM) == 0 || + coldplug_complete) + { +- create_seat_for_udev_device (manager, device); ++ ply_list_t *local_pixel_displays = NULL; ++ ++ if (manager->local_console_seat != NULL) ++ local_pixel_displays = ply_seat_get_pixel_displays (manager->local_console_seat); ++ ++ if (coldplug_complete && manager->local_console_seat != NULL && local_pixel_displays == NULL) ++ ply_trace ("ignoring since we're already using text splash for local console"); ++ else ++ create_seat_for_udev_device (manager, device); + } + else + { + ply_trace ("ignoring since we only handle subsystem %s devices after coldplug completes", subsystem); + } + } + else if (strcmp (action, "remove") == 0) + { + free_seat_for_udev_device (manager, device); + } + + udev_device_unref (device); + } + + static void + watch_for_udev_events (ply_device_manager_t *manager) + { + int fd; + assert (manager != NULL); + assert (manager->udev_monitor == NULL); + + ply_trace ("watching for udev graphics device add and remove events"); + + manager->udev_monitor = udev_monitor_new_from_netlink (manager->udev_context, "udev"); + + udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_DRM, NULL); + udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_FRAME_BUFFER, NULL); + udev_monitor_filter_add_match_tag (manager->udev_monitor, "seat"); + udev_monitor_enable_receiving (manager->udev_monitor); + +-- +2.3.7 + diff --git a/SOURCES/ensure-output-gets-terminal.patch b/SOURCES/ensure-output-gets-terminal.patch new file mode 100644 index 0000000..87e4301 --- /dev/null +++ b/SOURCES/ensure-output-gets-terminal.patch @@ -0,0 +1,5207 @@ +From 6283d0a786d7fec368d33dfeb25c0342cc5168ec Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 22 Jul 2015 10:05:51 -0400 +Subject: [PATCH 1/8] renderer: track activeness + +Right now, ply-seat has to handle tracking +renderer activeness on its own. This commit +moves activeness tracking to ply-renderer +directly. +--- + src/libply-splash-core/ply-renderer.c | 30 ++++++++++++++++++++++++++---- + src/libply-splash-core/ply-renderer.h | 1 + + src/libply-splash-core/ply-seat.c | 15 --------------- + 3 files changed, 27 insertions(+), 19 deletions(-) + +diff --git a/src/libply-splash-core/ply-renderer.c b/src/libply-splash-core/ply-renderer.c +index 04a99ce..3d9aa43 100644 +--- a/src/libply-splash-core/ply-renderer.c ++++ b/src/libply-splash-core/ply-renderer.c +@@ -28,60 +28,61 @@ + #include + #include + #include + #include + #include + #include + #include + #include + + #include "ply-renderer-plugin.h" + #include "ply-buffer.h" + #include "ply-terminal.h" + #include "ply-event-loop.h" + #include "ply-list.h" + #include "ply-logger.h" + #include "ply-utils.h" + + struct _ply_renderer + { + ply_event_loop_t *loop; + ply_module_handle_t *module_handle; + const ply_renderer_plugin_interface_t *plugin_interface; + ply_renderer_backend_t *backend; + + ply_renderer_type_t type; + char *device_name; + ply_terminal_t *terminal; + + uint32_t input_source_is_open : 1; + uint32_t is_mapped : 1; ++ uint32_t is_active : 1; + }; + + typedef const ply_renderer_plugin_interface_t * + (* get_backend_interface_function_t) (void); + + static void ply_renderer_unload_plugin (ply_renderer_t *renderer); + + ply_renderer_t * + ply_renderer_new (ply_renderer_type_t renderer_type, + const char *device_name, + ply_terminal_t *terminal) + { + ply_renderer_t *renderer; + + renderer = calloc (1, sizeof (struct _ply_renderer)); + + renderer->type = renderer_type; + + if (device_name != NULL) + renderer->device_name = strdup (device_name); + + renderer->terminal = terminal; + + return renderer; + } + + void + ply_renderer_free (ply_renderer_t *renderer) + { + if (renderer == NULL) +@@ -247,95 +248,116 @@ ply_renderer_open_plugin (ply_renderer_t *renderer, + if (!ply_renderer_query_device (renderer)) + { + ply_trace ("could not query rendering device for plugin %s", + plugin_path); + ply_renderer_close_device (renderer); + ply_renderer_unload_plugin (renderer); + return false; + } + + ply_trace ("opened renderer plugin %s", plugin_path); + return true; + } + + bool + ply_renderer_open (ply_renderer_t *renderer) + { + int i; + + struct + { + ply_renderer_type_t type; + const char *path; + } known_plugins[] = + { + { PLY_RENDERER_TYPE_X11, PLYMOUTH_PLUGIN_PATH "renderers/x11.so" }, + { PLY_RENDERER_TYPE_DRM, PLYMOUTH_PLUGIN_PATH "renderers/drm.so" }, + { PLY_RENDERER_TYPE_FRAME_BUFFER, PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so" }, + { PLY_RENDERER_TYPE_NONE, NULL } + }; + ++ renderer->is_active = false; + for (i = 0; known_plugins[i].type != PLY_RENDERER_TYPE_NONE; i++) + { + if (renderer->type == known_plugins[i].type || + renderer->type == PLY_RENDERER_TYPE_AUTO) + { + if (ply_renderer_open_plugin (renderer, known_plugins[i].path)) +- return true; ++ { ++ renderer->is_active = true; ++ goto out; ++ } + } + } + + ply_trace ("could not find suitable rendering plugin"); +- return false; ++ ++out: ++ return renderer->is_active; + } + + void + ply_renderer_close (ply_renderer_t *renderer) + { + ply_renderer_unmap_from_device (renderer); + ply_renderer_close_device (renderer); ++ renderer->is_active = false; + } + + void + ply_renderer_activate (ply_renderer_t *renderer) + { + assert (renderer->plugin_interface != NULL); + +- return renderer->plugin_interface->activate (renderer->backend); ++ if (renderer->is_active) ++ return; ++ ++ renderer->plugin_interface->activate (renderer->backend); ++ renderer->is_active = true; + } + + void + ply_renderer_deactivate (ply_renderer_t *renderer) + { + assert (renderer->plugin_interface != NULL); + +- return renderer->plugin_interface->deactivate (renderer->backend); ++ if (!renderer->is_active) ++ return; ++ ++ renderer->plugin_interface->deactivate (renderer->backend); ++ renderer->is_active = false; ++} ++ ++bool ++ply_renderer_is_active (ply_renderer_t *renderer) ++{ ++ return renderer->is_active; + } + + ply_list_t * + ply_renderer_get_heads (ply_renderer_t *renderer) + { + assert (renderer->plugin_interface != NULL); + + return renderer->plugin_interface->get_heads (renderer->backend); + } + + ply_pixel_buffer_t * + ply_renderer_get_buffer_for_head (ply_renderer_t *renderer, + ply_renderer_head_t *head) + { + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + assert (head != NULL); + + return renderer->plugin_interface->get_buffer_for_head (renderer->backend, + head); + } + + void + ply_renderer_flush_head (ply_renderer_t *renderer, + ply_renderer_head_t *head) + { + assert (renderer != NULL); + assert (renderer->plugin_interface != NULL); + assert (head != NULL); + +diff --git a/src/libply-splash-core/ply-renderer.h b/src/libply-splash-core/ply-renderer.h +index 3d48341..a47174a 100644 +--- a/src/libply-splash-core/ply-renderer.h ++++ b/src/libply-splash-core/ply-renderer.h +@@ -30,52 +30,53 @@ + #include "ply-pixel-buffer.h" + #include "ply-terminal.h" + #include "ply-utils.h" + + typedef struct _ply_renderer ply_renderer_t; + typedef struct _ply_renderer_head ply_renderer_head_t; + typedef struct _ply_renderer_input_source ply_renderer_input_source_t; + + typedef enum + { + PLY_RENDERER_TYPE_NONE = -1, + PLY_RENDERER_TYPE_AUTO, + PLY_RENDERER_TYPE_DRM, + PLY_RENDERER_TYPE_FRAME_BUFFER, + PLY_RENDERER_TYPE_X11 + } ply_renderer_type_t; + + typedef void (* ply_renderer_input_source_handler_t) (void *user_data, + ply_buffer_t *key_buffer, + ply_renderer_input_source_t *input_source); + + #ifndef PLY_HIDE_FUNCTION_DECLARATIONS + ply_renderer_t *ply_renderer_new (ply_renderer_type_t renderer_type, + const char *device_name, + ply_terminal_t *terminal); + void ply_renderer_free (ply_renderer_t *renderer); + bool ply_renderer_open (ply_renderer_t *renderer); + void ply_renderer_close (ply_renderer_t *renderer); + void ply_renderer_activate (ply_renderer_t *renderer); + void ply_renderer_deactivate (ply_renderer_t *renderer); ++bool ply_renderer_is_active (ply_renderer_t *renderer); + const char *ply_renderer_get_device_name (ply_renderer_t *renderer); + ply_list_t *ply_renderer_get_heads (ply_renderer_t *renderer); + ply_pixel_buffer_t *ply_renderer_get_buffer_for_head (ply_renderer_t *renderer, + ply_renderer_head_t *head); + + void ply_renderer_flush_head (ply_renderer_t *renderer, + ply_renderer_head_t *head); + + ply_renderer_input_source_t *ply_renderer_get_input_source (ply_renderer_t *renderer); + bool ply_renderer_open_input_source (ply_renderer_t *renderer, + ply_renderer_input_source_t *input_source); + void ply_renderer_set_handler_for_input_source (ply_renderer_t *renderer, + ply_renderer_input_source_t *input_source, + ply_renderer_input_source_handler_t handler, + void *user_data); + + void ply_renderer_close_input_source (ply_renderer_t *renderer, + ply_renderer_input_source_t *input_source); + #endif + + #endif /* PLY_RENDERER_H */ + /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ +diff --git a/src/libply-splash-core/ply-seat.c b/src/libply-splash-core/ply-seat.c +index cd7e5bc..4635889 100644 +--- a/src/libply-splash-core/ply-seat.c ++++ b/src/libply-splash-core/ply-seat.c +@@ -22,61 +22,60 @@ + #include "config.h" + #include "ply-seat.h" + + #include + #include + #include + #include + #include + #include + + #include "ply-boot-splash.h" + #include "ply-event-loop.h" + #include "ply-keyboard.h" + #include "ply-pixel-display.h" + #include "ply-text-display.h" + #include "ply-list.h" + #include "ply-logger.h" + #include "ply-utils.h" + + struct _ply_seat + { + ply_event_loop_t *loop; + + ply_boot_splash_t *splash; + ply_terminal_t *terminal; + ply_renderer_t *renderer; + ply_keyboard_t *keyboard; + ply_list_t *text_displays; + ply_list_t *pixel_displays; + +- uint32_t renderer_active : 1; + uint32_t keyboard_active : 1; + }; + + ply_seat_t * + ply_seat_new (ply_terminal_t *terminal) + { + ply_seat_t *seat; + + seat = calloc (1, sizeof (ply_seat_t)); + + seat->loop = ply_event_loop_get_default (); + seat->terminal = terminal; + seat->text_displays = ply_list_new (); + seat->pixel_displays = ply_list_new (); + + return seat; + } + + static void + add_pixel_displays (ply_seat_t *seat) + { + ply_list_t *heads; + ply_list_node_t *node; + + heads = ply_renderer_get_heads (seat->renderer); + + ply_trace ("Adding displays for %d heads", + ply_list_get_length (heads)); + + node = ply_list_get_first_node (heads); +@@ -108,70 +107,66 @@ add_text_displays (ply_seat_t *seat) + { + ply_trace ("could not add terminal %s: %m", + ply_terminal_get_name (seat->terminal)); + return; + } + } + + ply_trace ("adding text display for terminal %s", + ply_terminal_get_name (seat->terminal)); + + display = ply_text_display_new (seat->terminal); + ply_list_append_data (seat->text_displays, display); + } + + bool + ply_seat_open (ply_seat_t *seat, + ply_renderer_type_t renderer_type, + const char *device) + { + if (renderer_type != PLY_RENDERER_TYPE_NONE) + { + ply_renderer_t *renderer; + + renderer = ply_renderer_new (renderer_type, device, seat->terminal); + + if (!ply_renderer_open (renderer)) + { + ply_trace ("could not open renderer for %s", device); + ply_renderer_free (renderer); + +- seat->renderer = NULL; +- seat->renderer_active = false; +- + if (renderer_type != PLY_RENDERER_TYPE_AUTO) + return false; + } + else + { + seat->renderer = renderer; +- seat->renderer_active = true; + } + } + + if (seat->renderer != NULL) + { + seat->keyboard = ply_keyboard_new_for_renderer (seat->renderer); + add_pixel_displays (seat); + + } + else if (seat->terminal != NULL) + { + seat->keyboard = ply_keyboard_new_for_terminal (seat->terminal); + } + + if (seat->terminal != NULL) + { + add_text_displays (seat); + } + else + { + ply_trace ("not adding text display for seat, since seat has no associated terminal"); + } + + if (seat->keyboard != NULL) + { + ply_keyboard_watch_for_input (seat->keyboard); + seat->keyboard_active = true; + } + else + { +@@ -179,100 +174,90 @@ ply_seat_open (ply_seat_t *seat, + } + + return true; + } + + bool + ply_seat_is_open (ply_seat_t *seat) + { + return ply_list_get_length (seat->pixel_displays) > 0 || + ply_list_get_length (seat->text_displays) > 0; + } + + void + ply_seat_deactivate_keyboard (ply_seat_t *seat) + { + if (!seat->keyboard_active) + return; + + seat->keyboard_active = false; + + if (seat->keyboard == NULL) + return; + + ply_trace ("deactivating keybord"); + ply_keyboard_stop_watching_for_input (seat->keyboard); + } + + void + ply_seat_deactivate_renderer (ply_seat_t *seat) + { +- if (!seat->renderer_active) +- return; +- +- seat->renderer_active = false; +- + if (seat->renderer == NULL) + return; + + ply_trace ("deactivating renderer"); + ply_renderer_deactivate (seat->renderer); + } + + void + ply_seat_activate_keyboard (ply_seat_t *seat) + { + if (seat->keyboard_active) + return; + + if (seat->keyboard == NULL) + return; + + ply_trace ("activating keyboard"); + ply_keyboard_watch_for_input (seat->keyboard); + + seat->keyboard_active = true; + } + + void + ply_seat_activate_renderer (ply_seat_t *seat) + { +- if (seat->renderer_active) +- return; +- + if (seat->renderer == NULL) + return; + + ply_trace ("activating renderer"); + ply_renderer_activate (seat->renderer); +- +- seat->renderer_active = true; + } + + void + ply_seat_refresh_displays (ply_seat_t *seat) + { + ply_list_node_t *node; + + node = ply_list_get_first_node (seat->pixel_displays); + while (node != NULL) + { + ply_pixel_display_t *display; + ply_list_node_t *next_node; + unsigned long width, height; + + display = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (seat->pixel_displays, node); + + width = ply_pixel_display_get_width (display); + height = ply_pixel_display_get_height (display); + + ply_pixel_display_draw_area (display, 0, 0, width, height); + node = next_node; + } + + node = ply_list_get_first_node (seat->text_displays); + while (node != NULL) + { + ply_text_display_t *display; + ply_list_node_t *next_node; + int number_of_columns, number_of_rows; +-- +2.3.7 + + +From fb294aa5fc8ea8236ce91617a229daad9251a2f8 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 22 Jul 2015 10:05:51 -0400 +Subject: [PATCH 2/8] keyboard: track activeness + +Right now, ply-seat has to handle tracking +keyboard activeness on its own. This commit +moves activeness tracking to ply-keyboard +directly. +--- + src/libply-splash-core/ply-keyboard.c | 23 ++++++++++++++++++++--- + src/libply-splash-core/ply-keyboard.h | 1 + + src/libply-splash-core/ply-seat.c | 13 ------------- + 3 files changed, 21 insertions(+), 16 deletions(-) + +diff --git a/src/libply-splash-core/ply-keyboard.c b/src/libply-splash-core/ply-keyboard.c +index 624f906..e2fd814 100644 +--- a/src/libply-splash-core/ply-keyboard.c ++++ b/src/libply-splash-core/ply-keyboard.c +@@ -65,60 +65,62 @@ typedef enum + typedef struct + { + ply_terminal_t *terminal; + ply_buffer_t *key_buffer; + } ply_keyboard_terminal_provider_t; + + typedef struct + { + ply_renderer_t *renderer; + ply_renderer_input_source_t *input_source; + } ply_keyboard_renderer_provider_t; + + typedef union { + ply_keyboard_renderer_provider_t *if_renderer; + ply_keyboard_terminal_provider_t *if_terminal; + } ply_keyboard_provider_t; + + struct _ply_keyboard + { + ply_event_loop_t *loop; + + ply_keyboard_provider_type_t provider_type; + ply_keyboard_provider_t provider; + + ply_buffer_t *line_buffer; + + ply_list_t *keyboard_input_handler_list; + ply_list_t *backspace_handler_list; + ply_list_t *escape_handler_list; + ply_list_t *enter_handler_list; ++ ++ uint32_t is_active : 1; + }; + + static bool ply_keyboard_watch_for_terminal_input (ply_keyboard_t *keyboard); + + ply_keyboard_t * + ply_keyboard_new_for_terminal (ply_terminal_t *terminal) + { + ply_keyboard_t *keyboard; + + keyboard = calloc (1, sizeof (ply_keyboard_t)); + keyboard->line_buffer = ply_buffer_new (); + keyboard->keyboard_input_handler_list = ply_list_new (); + keyboard->backspace_handler_list = ply_list_new (); + keyboard->escape_handler_list = ply_list_new (); + keyboard->enter_handler_list = ply_list_new (); + keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL; + keyboard->provider.if_terminal = calloc (1, sizeof (ply_keyboard_terminal_provider_t)); + keyboard->provider.if_terminal->terminal = terminal; + keyboard->provider.if_terminal->key_buffer = ply_buffer_new (); + + keyboard->loop = ply_event_loop_get_default (); + + return keyboard; + } + + ply_keyboard_t * + ply_keyboard_new_for_renderer (ply_renderer_t *renderer) + { + ply_keyboard_t *keyboard; + ply_renderer_input_source_t *input_source; +@@ -303,135 +305,150 @@ on_key_event (ply_keyboard_t *keyboard, + + static bool + ply_keyboard_watch_for_renderer_input (ply_keyboard_t *keyboard) + { + assert (keyboard != NULL); + + if (!ply_renderer_open_input_source (keyboard->provider.if_renderer->renderer, + keyboard->provider.if_renderer->input_source)) + return false; + + ply_renderer_set_handler_for_input_source (keyboard->provider.if_renderer->renderer, + keyboard->provider.if_renderer->input_source, + (ply_renderer_input_source_handler_t) + on_key_event, + keyboard); + return true; + } + + static void + ply_keyboard_stop_watching_for_renderer_input (ply_keyboard_t *keyboard) + { + ply_renderer_set_handler_for_input_source (keyboard->provider.if_renderer->renderer, + keyboard->provider.if_renderer->input_source, + (ply_renderer_input_source_handler_t) + NULL, NULL); + + ply_renderer_close_input_source (keyboard->provider.if_renderer->renderer, + keyboard->provider.if_renderer->input_source); + } + ++bool ++ply_keyboard_is_active (ply_keyboard_t *keyboard) ++{ ++ return keyboard->is_active; ++} ++ + static void + on_terminal_data (ply_keyboard_t *keyboard) + { + int terminal_fd; + + terminal_fd = ply_terminal_get_fd (keyboard->provider.if_terminal->terminal); + ply_buffer_append_from_fd (keyboard->provider.if_terminal->key_buffer, + terminal_fd); + on_key_event (keyboard, keyboard->provider.if_terminal->key_buffer); + } + + static bool + ply_keyboard_watch_for_terminal_input (ply_keyboard_t *keyboard) + { + int terminal_fd; + + assert (keyboard != NULL); + + terminal_fd = ply_terminal_get_fd (keyboard->provider.if_terminal->terminal); + + if (terminal_fd < 0 || !ply_terminal_is_open (keyboard->provider.if_terminal->terminal)) + { + ply_trace ("terminal associated with keyboard isn't open"); + return false; + } + + ply_terminal_watch_for_input (keyboard->provider.if_terminal->terminal, + (ply_terminal_input_handler_t) on_terminal_data, + keyboard); + + return true; + } + + static void + ply_keyboard_stop_watching_for_terminal_input (ply_keyboard_t *keyboard) + { + ply_terminal_stop_watching_for_input (keyboard->provider.if_terminal->terminal, + (ply_terminal_input_handler_t) + on_terminal_data, + keyboard); + } + + bool + ply_keyboard_watch_for_input (ply_keyboard_t *keyboard) + { + assert (keyboard != NULL); + ++ if (keyboard->is_active) ++ return true; ++ + switch (keyboard->provider_type) + { + case PLY_KEYBOARD_PROVIDER_TYPE_RENDERER: +- return ply_keyboard_watch_for_renderer_input (keyboard); ++ keyboard->is_active = ply_keyboard_watch_for_renderer_input (keyboard); ++ break; + + case PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL: +- return ply_keyboard_watch_for_terminal_input (keyboard); ++ keyboard->is_active = ply_keyboard_watch_for_terminal_input (keyboard); ++ break; + } + +- return false; ++ return keyboard->is_active; + } + + void + ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard) + { + assert (keyboard != NULL); + ++ if (!keyboard->is_active) ++ return; ++ + switch (keyboard->provider_type) + { + case PLY_KEYBOARD_PROVIDER_TYPE_RENDERER: + ply_keyboard_stop_watching_for_renderer_input (keyboard); + break; + + case PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL: + ply_keyboard_stop_watching_for_terminal_input (keyboard); + break; + } + ++ keyboard->is_active = false; + } + + void + ply_keyboard_free (ply_keyboard_t *keyboard) + { + if (keyboard == NULL) + return; + + ply_keyboard_stop_watching_for_input (keyboard); + + ply_buffer_free (keyboard->line_buffer); + + if (keyboard->provider_type == PLY_KEYBOARD_PROVIDER_TYPE_RENDERER) + { + free (keyboard->provider.if_renderer); + } + else + { + ply_buffer_free (keyboard->provider.if_terminal->key_buffer); + free (keyboard->provider.if_terminal); + } + + free (keyboard); + } + + static ply_keyboard_closure_t * + ply_keyboard_closure_new (ply_keyboard_handler_t function, + void *user_data) + { + ply_keyboard_closure_t *closure = calloc (1, sizeof (ply_keyboard_closure_t)); +diff --git a/src/libply-splash-core/ply-keyboard.h b/src/libply-splash-core/ply-keyboard.h +index 74683cf..19e3d85 100644 +--- a/src/libply-splash-core/ply-keyboard.h ++++ b/src/libply-splash-core/ply-keyboard.h +@@ -44,35 +44,36 @@ typedef void (* ply_keyboard_enter_handler_t) (void *user_data, + const char *line); + + #ifndef PLY_HIDE_FUNCTION_DECLARATIONS + ply_keyboard_t *ply_keyboard_new_for_terminal (ply_terminal_t *terminal); + ply_keyboard_t *ply_keyboard_new_for_renderer (ply_renderer_t *renderer); + void ply_keyboard_free (ply_keyboard_t *keyboard); + + void ply_keyboard_add_input_handler (ply_keyboard_t *keyboard, + ply_keyboard_input_handler_t input_handler, + void *user_data); + void ply_keyboard_remove_input_handler (ply_keyboard_t *keyboard, + ply_keyboard_input_handler_t input_handler); + void ply_keyboard_add_backspace_handler (ply_keyboard_t *keyboard, + ply_keyboard_backspace_handler_t backspace_handler, + void *user_data); + void ply_keyboard_remove_backspace_handler (ply_keyboard_t *keyboard, + ply_keyboard_backspace_handler_t backspace_handler); + void ply_keyboard_add_escape_handler (ply_keyboard_t *keyboard, + ply_keyboard_escape_handler_t escape_handler, + void *user_data); + void ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard, + ply_keyboard_escape_handler_t escape_handler); + void ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard, + ply_keyboard_enter_handler_t enter_handler, + void *user_data); + void ply_keyboard_remove_enter_handler (ply_keyboard_t *keyboard, + ply_keyboard_enter_handler_t enter_handler); + + bool ply_keyboard_watch_for_input (ply_keyboard_t *keyboard); + void ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard); ++bool ply_keyboard_is_active (ply_keyboard_t *keyboard); + + #endif + + #endif /* PLY_KEYBOARD_H */ + /* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ +diff --git a/src/libply-splash-core/ply-seat.c b/src/libply-splash-core/ply-seat.c +index 4635889..1c885c2 100644 +--- a/src/libply-splash-core/ply-seat.c ++++ b/src/libply-splash-core/ply-seat.c +@@ -21,62 +21,60 @@ + */ + #include "config.h" + #include "ply-seat.h" + + #include + #include + #include + #include + #include + #include + + #include "ply-boot-splash.h" + #include "ply-event-loop.h" + #include "ply-keyboard.h" + #include "ply-pixel-display.h" + #include "ply-text-display.h" + #include "ply-list.h" + #include "ply-logger.h" + #include "ply-utils.h" + + struct _ply_seat + { + ply_event_loop_t *loop; + + ply_boot_splash_t *splash; + ply_terminal_t *terminal; + ply_renderer_t *renderer; + ply_keyboard_t *keyboard; + ply_list_t *text_displays; + ply_list_t *pixel_displays; +- +- uint32_t keyboard_active : 1; + }; + + ply_seat_t * + ply_seat_new (ply_terminal_t *terminal) + { + ply_seat_t *seat; + + seat = calloc (1, sizeof (ply_seat_t)); + + seat->loop = ply_event_loop_get_default (); + seat->terminal = terminal; + seat->text_displays = ply_list_new (); + seat->pixel_displays = ply_list_new (); + + return seat; + } + + static void + add_pixel_displays (ply_seat_t *seat) + { + ply_list_t *heads; + ply_list_node_t *node; + + heads = ply_renderer_get_heads (seat->renderer); + + ply_trace ("Adding displays for %d heads", + ply_list_get_length (heads)); + + node = ply_list_get_first_node (heads); + while (node != NULL) +@@ -139,115 +137,104 @@ ply_seat_open (ply_seat_t *seat, + } + else + { + seat->renderer = renderer; + } + } + + if (seat->renderer != NULL) + { + seat->keyboard = ply_keyboard_new_for_renderer (seat->renderer); + add_pixel_displays (seat); + + } + else if (seat->terminal != NULL) + { + seat->keyboard = ply_keyboard_new_for_terminal (seat->terminal); + } + + if (seat->terminal != NULL) + { + add_text_displays (seat); + } + else + { + ply_trace ("not adding text display for seat, since seat has no associated terminal"); + } + + if (seat->keyboard != NULL) + { + ply_keyboard_watch_for_input (seat->keyboard); +- seat->keyboard_active = true; + } + else + { + ply_trace ("not watching seat for input"); + } + + return true; + } + + bool + ply_seat_is_open (ply_seat_t *seat) + { + return ply_list_get_length (seat->pixel_displays) > 0 || + ply_list_get_length (seat->text_displays) > 0; + } + + void + ply_seat_deactivate_keyboard (ply_seat_t *seat) + { +- if (!seat->keyboard_active) +- return; +- +- seat->keyboard_active = false; +- + if (seat->keyboard == NULL) + return; + + ply_trace ("deactivating keybord"); + ply_keyboard_stop_watching_for_input (seat->keyboard); + } + + void + ply_seat_deactivate_renderer (ply_seat_t *seat) + { + if (seat->renderer == NULL) + return; + + ply_trace ("deactivating renderer"); + ply_renderer_deactivate (seat->renderer); + } + + void + ply_seat_activate_keyboard (ply_seat_t *seat) + { +- if (seat->keyboard_active) +- return; +- + if (seat->keyboard == NULL) + return; + + ply_trace ("activating keyboard"); + ply_keyboard_watch_for_input (seat->keyboard); +- +- seat->keyboard_active = true; + } + + void + ply_seat_activate_renderer (ply_seat_t *seat) + { + if (seat->renderer == NULL) + return; + + ply_trace ("activating renderer"); + ply_renderer_activate (seat->renderer); + } + + void + ply_seat_refresh_displays (ply_seat_t *seat) + { + ply_list_node_t *node; + + node = ply_list_get_first_node (seat->pixel_displays); + while (node != NULL) + { + ply_pixel_display_t *display; + ply_list_node_t *next_node; + unsigned long width, height; + + display = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (seat->pixel_displays, node); + + width = ply_pixel_display_get_width (display); + height = ply_pixel_display_get_height (display); + +-- +2.3.7 + + +From 2e32a42370048eda7be2ad616dbdf1bbbe785129 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 22 Jul 2015 14:45:05 -0400 +Subject: [PATCH 3/8] pixel-display: add getters for renderer data + +These functions are useful for matching a pixel display +to its renderer. +--- + src/libply-splash-core/ply-pixel-display.c | 12 ++++++++++++ + src/libply-splash-core/ply-pixel-display.h | 2 ++ + 2 files changed, 14 insertions(+) + +diff --git a/src/libply-splash-core/ply-pixel-display.c b/src/libply-splash-core/ply-pixel-display.c +index 3715120..5c5ec69 100644 +--- a/src/libply-splash-core/ply-pixel-display.c ++++ b/src/libply-splash-core/ply-pixel-display.c +@@ -55,60 +55,72 @@ struct _ply_pixel_display + ply_pixel_display_draw_handler_t draw_handler; + void *draw_handler_user_data; + + int pause_count; + + }; + + ply_pixel_display_t * + ply_pixel_display_new (ply_renderer_t *renderer, + ply_renderer_head_t *head) + { + ply_pixel_display_t *display; + ply_pixel_buffer_t *pixel_buffer; + ply_rectangle_t size; + + display = calloc (1, sizeof (ply_pixel_display_t)); + + display->loop = ply_event_loop_get_default (); + display->renderer = renderer; + display->head = head; + + pixel_buffer = ply_renderer_get_buffer_for_head (renderer, head); + ply_pixel_buffer_get_size (pixel_buffer, &size); + + display->width = size.width; + display->height = size.height; + + return display; + } + ++ply_renderer_t * ++ply_pixel_display_get_renderer (ply_pixel_display_t *display) ++{ ++ return display->renderer; ++} ++ ++ply_renderer_head_t * ++ply_pixel_display_get_renderer_head (ply_pixel_display_t *display) ++{ ++ return display->head; ++} ++ + unsigned long + ply_pixel_display_get_width (ply_pixel_display_t *display) + { + return display->width; + } + + unsigned long + ply_pixel_display_get_height (ply_pixel_display_t *display) + { + return display->height; + } + + static void + ply_pixel_display_flush (ply_pixel_display_t *display) + { + if (display->pause_count > 0) + return; + + ply_renderer_flush_head (display->renderer, display->head); + } + + void + ply_pixel_display_pause_updates (ply_pixel_display_t *display) + { + assert (display != NULL); + + display->pause_count++; + } + + void +diff --git a/src/libply-splash-core/ply-pixel-display.h b/src/libply-splash-core/ply-pixel-display.h +index 98a6b3c..92558e9 100644 +--- a/src/libply-splash-core/ply-pixel-display.h ++++ b/src/libply-splash-core/ply-pixel-display.h +@@ -16,53 +16,55 @@ + * 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: Ray Strode + */ + #ifndef PLY_PIXEL_DISPLAY_H + #define PLY_PIXEL_DISPLAY_H + + #include + #include + #include + + #include "ply-event-loop.h" + #include "ply-pixel-buffer.h" + #include "ply-renderer.h" + + typedef struct _ply_pixel_display ply_pixel_display_t; + + typedef void (* ply_pixel_display_draw_handler_t) (void *user_data, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height, + ply_pixel_display_t *pixel_display); + + #ifndef PLY_HIDE_FUNCTION_DECLARATIONS + ply_pixel_display_t *ply_pixel_display_new (ply_renderer_t *renderer, + ply_renderer_head_t *head); ++ply_renderer_t *ply_pixel_display_get_renderer (ply_pixel_display_t *display); ++ply_renderer_head_t *ply_pixel_display_get_renderer_head (ply_pixel_display_t *display); + + void ply_pixel_display_free (ply_pixel_display_t *display); + + unsigned long ply_pixel_display_get_width (ply_pixel_display_t *display); + unsigned long ply_pixel_display_get_height (ply_pixel_display_t *display); + + void ply_pixel_display_set_draw_handler (ply_pixel_display_t *display, + ply_pixel_display_draw_handler_t draw_handler, + void *user_data); + + void ply_pixel_display_draw_area (ply_pixel_display_t *display, + int x, + int y, + int width, + int height); + + void ply_pixel_display_pause_updates (ply_pixel_display_t *display); + void ply_pixel_display_unpause_updates (ply_pixel_display_t *display); + + #endif + + #endif /* PLY_PIXEL_DISPLAY_H */ + /* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ +-- +2.3.7 + + +From d698a677b0007caded1dfb4652d8e8b9928e068b Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 23 Jul 2015 14:16:48 -0400 +Subject: [PATCH 4/8] device-manager: drop seat abstraction + +The seat abstraction isn't really right, since it forces creating a +link between terminal and video output device, which isn't really +necessary (and other reasons). + +This commit drops the abstraction, and moves all the code that was +in ply-seat.c directly to ply-device-manager.c. +--- + src/libply-splash-core/Makefile.am | 2 - + src/libply-splash-core/ply-boot-splash.c | 258 +++++++------- + src/libply-splash-core/ply-boot-splash.h | 17 +- + src/libply-splash-core/ply-device-manager.c | 530 ++++++++++++++++------------ + src/libply-splash-core/ply-device-manager.h | 32 +- + src/libply-splash-core/ply-seat.c | 374 -------------------- + src/libply-splash-core/ply-seat.h | 66 ---- + src/main.c | 235 ++++++++---- + 8 files changed, 615 insertions(+), 899 deletions(-) + delete mode 100644 src/libply-splash-core/ply-seat.c + delete mode 100644 src/libply-splash-core/ply-seat.h + +diff --git a/src/libply-splash-core/Makefile.am b/src/libply-splash-core/Makefile.am +index d07d7f1..7036569 100644 +--- a/src/libply-splash-core/Makefile.am ++++ b/src/libply-splash-core/Makefile.am +@@ -1,53 +1,51 @@ + AM_CPPFLAGS = -I$(top_srcdir) \ + -I$(srcdir) \ + -I$(srcdir)/../libply \ + -I$(srcdir)/../plugins/controls + + if WITH_SYSTEM_ROOT_INSTALL + librarydir = $(libdir:/usr%=%) + else + librarydir = $(libdir) + endif + + library_LTLIBRARIES = libply-splash-core.la + + libply_splash_coredir = $(includedir)/plymouth-1/ply-splash-core + libply_splash_core_HEADERS = \ + ply-boot-splash.h \ + ply-boot-splash-plugin.h \ + ply-device-manager.h \ + ply-keyboard.h \ + ply-pixel-buffer.h \ + ply-pixel-display.h \ + ply-renderer.h \ + ply-renderer-plugin.h \ +- ply-seat.h \ + ply-terminal.h \ + ply-text-display.h \ + ply-text-progress-bar.h \ + ply-text-step-bar.h + + libply_splash_core_la_CFLAGS = $(PLYMOUTH_CFLAGS) $(UDEV_CFLAGS) \ + -DPLYMOUTH_BACKGROUND_COLOR=$(background_color) \ + -DPLYMOUTH_BACKGROUND_END_COLOR=$(background_end_color) \ + -DPLYMOUTH_BACKGROUND_START_COLOR=$(background_start_color) \ + -DPLYMOUTH_PLUGIN_PATH=\"$(PLYMOUTH_PLUGIN_PATH)\" + libply_splash_core_la_LIBADD = $(PLYMOUTH_LIBS) $(UDEV_LIBS) ../libply/libply.la + libply_splash_core_la_LDFLAGS = -export-symbols-regex '^[^_].*' \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -no-undefined + libply_splash_core_la_SOURCES = \ + $(libply_splash_core_HEADERS) \ + ply-device-manager.c \ + ply-keyboard.c \ + ply-pixel-display.c \ + ply-text-display.c \ + ply-text-progress-bar.c \ + ply-text-step-bar.c \ + ply-terminal.c \ + ply-pixel-buffer.c \ + ply-renderer.c \ +- ply-seat.c \ + ply-boot-splash.c + + MAINTAINERCLEANFILES = Makefile.in +diff --git a/src/libply-splash-core/ply-boot-splash.c b/src/libply-splash-core/ply-boot-splash.c +index 160ce45..f7fc70f 100644 +--- a/src/libply-splash-core/ply-boot-splash.c ++++ b/src/libply-splash-core/ply-boot-splash.c +@@ -30,259 +30,196 @@ + #include + #include + #include + #include + #include + + #include "ply-boot-splash-plugin.h" + #include "ply-terminal.h" + #include "ply-event-loop.h" + #include "ply-list.h" + #include "ply-logger.h" + #include "ply-trigger.h" + #include "ply-utils.h" + #include "ply-progress.h" + #include "ply-keyboard.h" + #include "ply-key-file.h" + + #ifndef UPDATES_PER_SECOND + #define UPDATES_PER_SECOND 30 + #endif + + struct _ply_boot_splash + { + ply_event_loop_t *loop; + ply_module_handle_t *module_handle; + const ply_boot_splash_plugin_interface_t *plugin_interface; + ply_boot_splash_plugin_t *plugin; + ply_boot_splash_mode_t mode; + ply_buffer_t *boot_buffer; + ply_trigger_t *idle_trigger; +- ply_list_t *seats; ++ ++ ply_keyboard_t *keyboard; ++ ply_list_t *pixel_displays; ++ ply_list_t *text_displays; + + char *theme_path; + char *plugin_dir; + char *status; + + ply_progress_t *progress; + ply_boot_splash_on_idle_handler_t idle_handler; + void *idle_handler_user_data; + + uint32_t is_loaded : 1; + uint32_t should_force_text_mode : 1; + }; + + typedef const ply_boot_splash_plugin_interface_t * + (* get_plugin_interface_function_t) (void); + + static void ply_boot_splash_update_progress (ply_boot_splash_t *splash); + static void ply_boot_splash_detach_from_event_loop (ply_boot_splash_t *splash); + + ply_boot_splash_t * + ply_boot_splash_new (const char *theme_path, + const char *plugin_dir, + ply_buffer_t *boot_buffer) + { + ply_boot_splash_t *splash; + + assert (theme_path != NULL); + + splash = calloc (1, sizeof (ply_boot_splash_t)); + splash->loop = NULL; + splash->theme_path = strdup (theme_path); + splash->plugin_dir = strdup (plugin_dir); + splash->module_handle = NULL; + splash->mode = PLY_BOOT_SPLASH_MODE_INVALID; + + splash->boot_buffer = boot_buffer; +- splash->seats = ply_list_new (); ++ splash->pixel_displays = ply_list_new (); ++ splash->text_displays = ply_list_new (); + + return splash; + } + +-static void +-detach_from_seat (ply_boot_splash_t *splash, +- ply_seat_t *seat) ++void ++ply_boot_splash_set_keyboard (ply_boot_splash_t *splash, ++ ply_keyboard_t *keyboard) + { +- ply_keyboard_t *keyboard; +- ply_list_t *displays; +- ply_list_node_t *node, *next_node; +- +- ply_trace ("removing keyboard"); +- if (splash->plugin_interface->unset_keyboard != NULL) +- { +- keyboard = ply_seat_get_keyboard (seat); +- splash->plugin_interface->unset_keyboard (splash->plugin, keyboard); +- } +- +- ply_trace ("removing pixel displays"); +- displays = ply_seat_get_pixel_displays (seat); +- +- node = ply_list_get_first_node (displays); +- while (node != NULL) +- { +- ply_pixel_display_t *display; +- ply_list_node_t *next_node; +- unsigned long width, height; +- +- display = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (displays, node); +- +- width = ply_pixel_display_get_width (display); +- height = ply_pixel_display_get_height (display); +- +- ply_trace ("Removing %lux%lu pixel display", width, height); +- +- if (splash->plugin_interface->remove_pixel_display != NULL) +- splash->plugin_interface->remove_pixel_display (splash->plugin, display); +- +- node = next_node; +- } +- +- ply_trace ("removing text displays"); +- displays = ply_seat_get_text_displays (seat); +- +- node = ply_list_get_first_node (displays); +- while (node != NULL) +- { +- ply_text_display_t *display; +- int number_of_columns, number_of_rows; +- +- display = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (displays, node); +- +- number_of_columns = ply_text_display_get_number_of_columns (display); +- number_of_rows = ply_text_display_get_number_of_rows (display); +- +- ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows); +- +- if (splash->plugin_interface->remove_text_display != NULL) +- splash->plugin_interface->remove_text_display (splash->plugin, display); ++ if (splash->plugin_interface->set_keyboard == NULL) ++ return; + +- node = next_node; +- } ++ splash->plugin_interface->set_keyboard (splash->plugin, keyboard); ++ splash->keyboard = keyboard; + } + +-static void +-attach_to_seat (ply_boot_splash_t *splash, +- ply_seat_t *seat) ++void ++ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash) + { +- ply_keyboard_t *keyboard; +- ply_list_t *displays; +- ply_list_node_t *node, *next_node; +- +- if (splash->plugin_interface->set_keyboard != NULL) +- { +- keyboard = ply_seat_get_keyboard (seat); +- splash->plugin_interface->set_keyboard (splash->plugin, keyboard); +- } +- +- if (splash->plugin_interface->add_pixel_display != NULL) +- { +- displays = ply_seat_get_pixel_displays (seat); +- +- ply_trace ("adding pixel displays"); +- node = ply_list_get_first_node (displays); +- while (node != NULL) +- { +- ply_pixel_display_t *display; +- ply_list_node_t *next_node; +- unsigned long width, height; +- +- display = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (displays, node); ++ if (splash->plugin_interface->unset_keyboard == NULL) ++ return; + +- width = ply_pixel_display_get_width (display); +- height = ply_pixel_display_get_height (display); ++ splash->plugin_interface->unset_keyboard (splash->plugin, splash->keyboard); ++} + +- ply_trace ("Adding %lux%lu pixel display", width, height); ++void ++ply_boot_splash_add_pixel_display (ply_boot_splash_t *splash, ++ ply_pixel_display_t *display) ++{ ++ unsigned long width, height; + +- splash->plugin_interface->add_pixel_display (splash->plugin, display); ++ if (splash->plugin_interface->add_pixel_display == NULL) ++ return; + +- node = next_node; +- } +- } ++ width = ply_pixel_display_get_width (display); ++ height = ply_pixel_display_get_height (display); + +- if (splash->plugin_interface->add_text_display != NULL) +- { +- displays = ply_seat_get_text_displays (seat); ++ ply_trace ("Adding %lux%lu pixel display", width, height); + +- ply_trace ("adding text displays"); +- node = ply_list_get_first_node (displays); +- while (node != NULL) +- { +- ply_text_display_t *display; +- int number_of_columns, number_of_rows; ++ splash->plugin_interface->add_pixel_display (splash->plugin, display); ++ ply_list_append_data (splash->pixel_displays, display); ++} + +- display = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (displays, node); ++void ++ply_boot_splash_remove_pixel_display (ply_boot_splash_t *splash, ++ ply_pixel_display_t *display) ++{ ++ unsigned long width, height; + +- number_of_columns = ply_text_display_get_number_of_columns (display); +- number_of_rows = ply_text_display_get_number_of_rows (display); ++ if (splash->plugin_interface->remove_pixel_display == NULL) ++ return; + +- ply_trace ("Adding %dx%d text display", number_of_columns, number_of_rows); ++ width = ply_pixel_display_get_width (display); ++ height = ply_pixel_display_get_height (display); + +- splash->plugin_interface->add_text_display (splash->plugin, display); ++ ply_trace ("Removing %lux%lu pixel display", width, height); + +- node = next_node; +- } +- } ++ splash->plugin_interface->remove_pixel_display (splash->plugin, display); ++ ply_list_remove_data (splash->pixel_displays, display); + } + + void +-ply_boot_splash_attach_to_seat (ply_boot_splash_t *splash, +- ply_seat_t *seat) ++ply_boot_splash_add_text_display (ply_boot_splash_t *splash, ++ ply_text_display_t *display) + { +- ply_list_node_t *node; +- +- node = ply_list_find_node (splash->seats, seat); ++ int number_of_columns, number_of_rows; + +- if (node != NULL) ++ if (splash->plugin_interface->add_text_display == NULL) + return; + +- ply_list_append_data (splash->seats, seat); +- attach_to_seat (splash, seat); ++ number_of_columns = ply_text_display_get_number_of_columns (display); ++ number_of_rows = ply_text_display_get_number_of_rows (display); ++ ++ ply_trace ("Adding %dx%d text display", number_of_columns, number_of_rows); ++ ++ splash->plugin_interface->add_text_display (splash->plugin, display); ++ ply_list_append_data (splash->text_displays, display); + } + + void +-ply_boot_splash_detach_from_seat (ply_boot_splash_t *splash, +- ply_seat_t *seat) ++ply_boot_splash_remove_text_display (ply_boot_splash_t *splash, ++ ply_text_display_t *display) + { +- ply_list_node_t *node; ++ int number_of_columns, number_of_rows; + +- node = ply_list_find_node (splash->seats, seat); +- +- if (node == NULL) ++ if (splash->plugin_interface->remove_text_display == NULL) + return; + +- ply_list_remove_data (splash->seats, seat); +- detach_from_seat (splash, seat); ++ number_of_columns = ply_text_display_get_number_of_columns (display); ++ number_of_rows = ply_text_display_get_number_of_rows (display); ++ ++ ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows); ++ ++ splash->plugin_interface->remove_text_display (splash->plugin, display); ++ ply_list_remove_data (splash->text_displays, display); + } + + bool + ply_boot_splash_load (ply_boot_splash_t *splash) + { + ply_key_file_t *key_file; + char *module_name; + char *module_path; + + assert (splash != NULL); + + get_plugin_interface_function_t get_boot_splash_plugin_interface; + + key_file = ply_key_file_new (splash->theme_path); + + if (!ply_key_file_load (key_file)) + return false; + + module_name = ply_key_file_get_value (key_file, "Plymouth Theme", "ModuleName"); + + asprintf (&module_path, "%s%s.so", + splash->plugin_dir, module_name); + free (module_name); + + splash->module_handle = ply_open_module (module_path); + + free (module_path); + + if (splash->module_handle == NULL) + { +@@ -364,106 +301,149 @@ ply_boot_splash_load_built_in (ply_boot_splash_t *splash) + } + + splash->plugin = splash->plugin_interface->create_plugin (NULL); + + assert (splash->plugin != NULL); + + splash->is_loaded = true; + + return true; + } + + void + ply_boot_splash_unload (ply_boot_splash_t *splash) + { + assert (splash != NULL); + assert (splash->plugin != NULL); + assert (splash->plugin_interface != NULL); + assert (splash->module_handle != NULL); + + splash->plugin_interface->destroy_plugin (splash->plugin); + splash->plugin = NULL; + + ply_close_module (splash->module_handle); + splash->plugin_interface = NULL; + splash->module_handle = NULL; + + splash->is_loaded = false; + } + + static void +-detach_from_seats (ply_boot_splash_t *splash) ++remove_pixel_displays (ply_boot_splash_t *splash) ++{ ++ ply_list_node_t *node; ++ ++ if (splash->plugin_interface->remove_pixel_display == NULL) ++ return; ++ ++ ply_trace ("removing pixel displays"); ++ ++ node = ply_list_get_first_node (splash->pixel_displays); ++ while (node != NULL) ++ { ++ ply_pixel_display_t *display; ++ ply_list_node_t *next_node; ++ unsigned long width, height; ++ ++ display = ply_list_node_get_data (node); ++ next_node = ply_list_get_next_node (splash->pixel_displays, node); ++ ++ width = ply_pixel_display_get_width (display); ++ height = ply_pixel_display_get_height (display); ++ ++ ply_trace ("Removing %lux%lu pixel display", width, height); ++ ++ splash->plugin_interface->remove_pixel_display (splash->plugin, display); ++ ++ node = next_node; ++ } ++} ++ ++static void ++remove_text_displays (ply_boot_splash_t *splash) + { + ply_list_node_t *node; + +- ply_trace ("detaching from seats"); ++ if (splash->plugin_interface->remove_text_display == NULL) ++ return; + +- node = ply_list_get_first_node (splash->seats); ++ ply_trace ("removing text displays"); ++ ++ node = ply_list_get_first_node (splash->text_displays); + while (node != NULL) + { +- ply_seat_t *seat; ++ ply_text_display_t *display; + ply_list_node_t *next_node; ++ int number_of_columns, number_of_rows; + +- seat = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (splash->seats, node); ++ display = ply_list_node_get_data (node); ++ next_node = ply_list_get_next_node (splash->text_displays, node); + +- detach_from_seat (splash, seat); ++ number_of_columns = ply_text_display_get_number_of_columns (display); ++ number_of_rows = ply_text_display_get_number_of_rows (display); + +- ply_list_remove_node (splash->seats, node); ++ ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows); ++ ++ splash->plugin_interface->remove_text_display (splash->plugin, display); + + node = next_node; + } + } + + void + ply_boot_splash_free (ply_boot_splash_t *splash) + { + ply_trace ("freeing splash"); + if (splash == NULL) + return; + + if (splash->loop != NULL) + { + if (splash->plugin_interface->on_boot_progress != NULL) + { + ply_event_loop_stop_watching_for_timeout (splash->loop, + (ply_event_loop_timeout_handler_t) + ply_boot_splash_update_progress, splash); + } + + ply_event_loop_stop_watching_for_exit (splash->loop, (ply_event_loop_exit_handler_t) + ply_boot_splash_detach_from_event_loop, + splash); + } + +- detach_from_seats (splash); +- ply_list_free (splash->seats); ++ ply_boot_splash_unset_keyboard (splash); ++ ++ remove_pixel_displays (splash); ++ ply_list_free (splash->pixel_displays); ++ ++ remove_text_displays (splash); ++ ply_list_free (splash->text_displays); + + if (splash->module_handle != NULL) + ply_boot_splash_unload (splash); + + if (splash->idle_trigger != NULL) + ply_trigger_free (splash->idle_trigger); + + free (splash->theme_path); + free (splash->plugin_dir); + free (splash); + } + + static void + ply_boot_splash_update_progress (ply_boot_splash_t *splash) + { + double percentage=0.0; + double time=0.0; + + assert (splash != NULL); + + if (splash->progress) + { + percentage = ply_progress_get_percentage(splash->progress); + time = ply_progress_get_time(splash->progress); + } + + if (splash->plugin_interface->on_boot_progress != NULL) + splash->plugin_interface->on_boot_progress (splash->plugin, + time, + percentage); +diff --git a/src/libply-splash-core/ply-boot-splash.h b/src/libply-splash-core/ply-boot-splash.h +index 335039b..8937c1f 100644 +--- a/src/libply-splash-core/ply-boot-splash.h ++++ b/src/libply-splash-core/ply-boot-splash.h +@@ -6,81 +6,86 @@ + * 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: Ray Strode + */ + #ifndef PLY_BOOT_SPLASH_H + #define PLY_BOOT_SPLASH_H + + #include + #include + #include + + #include "ply-event-loop.h" + #include "ply-buffer.h" + #include "ply-terminal.h" + #include "ply-keyboard.h" + #include "ply-pixel-display.h" + #include "ply-text-display.h" + #include "ply-progress.h" +-#include "ply-seat.h" + + #include "ply-boot-splash-plugin.h" + + typedef struct _ply_boot_splash ply_boot_splash_t; +-typedef struct _ply_seat ply_seat_t; + + typedef void (* ply_boot_splash_on_idle_handler_t) (void *user_data); + + #ifndef PLY_HIDE_FUNCTION_DECLARATIONS + ply_boot_splash_t *ply_boot_splash_new (const char * theme_path, + const char * plugin_dir, + ply_buffer_t * boot_buffer); + + bool ply_boot_splash_load (ply_boot_splash_t *splash); + bool ply_boot_splash_load_built_in (ply_boot_splash_t *splash); + void ply_boot_splash_unload (ply_boot_splash_t *splash); +-void ply_boot_splash_attach_to_seat (ply_boot_splash_t *splash, +- ply_seat_t *seat); +-void ply_boot_splash_detach_from_seat (ply_boot_splash_t *splash, +- ply_seat_t *seat); ++void ply_boot_splash_set_keyboard (ply_boot_splash_t *splash, ++ ply_keyboard_t *keyboard); ++void ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash); ++void ply_boot_splash_add_pixel_display (ply_boot_splash_t *splash, ++ ply_pixel_display_t *pixel_display); ++void ply_boot_splash_remove_pixel_display (ply_boot_splash_t *splash, ++ ply_pixel_display_t *pixel_display); ++void ply_boot_splash_add_text_display (ply_boot_splash_t *splash, ++ ply_text_display_t *text_display); ++void ply_boot_splash_remove_text_display (ply_boot_splash_t *splash, ++ ply_text_display_t *text_display); + void ply_boot_splash_free (ply_boot_splash_t *splash); + bool ply_boot_splash_show (ply_boot_splash_t *splash, + ply_boot_splash_mode_t mode); + bool ply_boot_splash_system_update (ply_boot_splash_t *splash, + int progress); + void ply_boot_splash_update_status (ply_boot_splash_t *splash, + const char *status); + void ply_boot_splash_update_output (ply_boot_splash_t *splash, + const char *output, + size_t size); + void ply_boot_splash_root_mounted (ply_boot_splash_t *splash); + void ply_boot_splash_display_message (ply_boot_splash_t *splash, + const char *message); + void ply_boot_splash_hide_message (ply_boot_splash_t *splash, + const char *message); + void ply_boot_splash_hide (ply_boot_splash_t *splash); + void ply_boot_splash_display_normal (ply_boot_splash_t *splash); + void ply_boot_splash_display_password (ply_boot_splash_t *splash, + const char *prompt, + int bullets); + void ply_boot_splash_display_question (ply_boot_splash_t *splash, + const char *prompt, + const char *entry_text); + void ply_boot_splash_attach_to_event_loop (ply_boot_splash_t *splash, + ply_event_loop_t *loop); + void ply_boot_splash_attach_progress (ply_boot_splash_t *splash, + ply_progress_t *progress); + void ply_boot_splash_become_idle (ply_boot_splash_t *splash, + ply_boot_splash_on_idle_handler_t idle_handler, + void *user_data); +diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c +index 5766bcb..c7568c1 100644 +--- a/src/libply-splash-core/ply-device-manager.c ++++ b/src/libply-splash-core/ply-device-manager.c +@@ -14,597 +14,580 @@ + * + * 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. + */ + #include "config.h" + #include "ply-device-manager.h" + + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + + #include "ply-logger.h" + #include "ply-event-loop.h" + #include "ply-hashtable.h" + #include "ply-list.h" + #include "ply-utils.h" + + #define SUBSYSTEM_DRM "drm" + #define SUBSYSTEM_FRAME_BUFFER "graphics" + +-static void create_seat_for_terminal_and_renderer_type (ply_device_manager_t *manager, +- const char *device_path, +- ply_terminal_t *terminal, +- ply_renderer_type_t renderer_type); ++static void create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, ++ const char *device_path, ++ ply_terminal_t *terminal, ++ ply_renderer_type_t renderer_type); + struct _ply_device_manager + { + ply_device_manager_flags_t flags; + ply_event_loop_t *loop; + ply_hashtable_t *terminals; ++ ply_hashtable_t *renderers; + ply_terminal_t *local_console_terminal; +- ply_seat_t *local_console_seat; +- ply_list_t *seats; ++ ply_list_t *keyboards; ++ ply_list_t *text_displays; ++ ply_list_t *pixel_displays; + struct udev *udev_context; + struct udev_queue *udev_queue; + int udev_queue_fd; + ply_fd_watch_t *udev_queue_fd_watch; + struct udev_monitor *udev_monitor; + +- ply_seat_added_handler_t seat_added_handler; +- ply_seat_removed_handler_t seat_removed_handler; +- void *seat_event_handler_data; ++ ply_keyboard_added_handler_t keyboard_added_handler; ++ ply_keyboard_removed_handler_t keyboard_removed_handler; ++ ply_pixel_display_added_handler_t pixel_display_added_handler; ++ ply_pixel_display_removed_handler_t pixel_display_removed_handler; ++ ply_text_display_added_handler_t text_display_added_handler; ++ ply_text_display_removed_handler_t text_display_removed_handler; ++ void *event_handler_data; ++ ++ uint32_t local_console_managed : 1; ++ uint32_t local_console_is_text : 1; + }; + + static void + detach_from_event_loop (ply_device_manager_t *manager) + { + assert (manager != NULL); + + manager->loop = NULL; + } + + static void + attach_to_event_loop (ply_device_manager_t *manager, + ply_event_loop_t *loop) + { + assert (manager != NULL); + assert (loop != NULL); + assert (manager->loop == NULL); + + manager->loop = loop; + + ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + manager); + } + + static bool + device_is_for_local_console (ply_device_manager_t *manager, + struct udev_device *device) + { + const char *device_path; + struct udev_device *bus_device; + char *bus_device_path; + const char *boot_vga; + bool for_local_console; + + /* Look at the associated bus device to see if this card is the + * card the kernel is using for its console. */ + device_path = udev_device_get_syspath (device); + asprintf (&bus_device_path, "%s/device", device_path); + bus_device = udev_device_new_from_syspath (manager->udev_context, bus_device_path); + + boot_vga = udev_device_get_sysattr_value (bus_device, "boot_vga"); + free (bus_device_path); + + if (boot_vga != NULL && strcmp (boot_vga, "1") == 0) + for_local_console = true; + else + for_local_console = false; + + return for_local_console; + } + + static bool + drm_device_in_use (ply_device_manager_t *manager, + const char *device_path) + { +- ply_list_node_t *node; +- +- node = ply_list_get_first_node (manager->seats); +- while (node != NULL) +- { +- ply_seat_t *seat; +- ply_renderer_t *renderer; +- ply_list_node_t *next_node; +- const char *renderer_device_path; ++ ply_renderer_t *renderer; + +- seat = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (manager->seats, node); +- renderer = ply_seat_get_renderer (seat); ++ renderer = ply_hashtable_lookup (manager->renderers, (void *) device_path); + +- if (renderer != NULL) +- { +- renderer_device_path = ply_renderer_get_device_name (renderer); +- +- if (renderer_device_path != NULL) +- { +- if (strcmp (device_path, renderer_device_path) == 0) +- { +- return true; +- } +- } +- } +- +- node = next_node; +- } +- +- return false; ++ return renderer != NULL; + } + + static bool + fb_device_has_drm_device (ply_device_manager_t *manager, + struct udev_device *fb_device) + { + struct udev_enumerate *card_matches; + struct udev_list_entry *card_entry; + const char *id_path; + bool has_drm_device = false; + + /* We want to see if the framebuffer is associated with a DRM-capable + * graphics card, if it is, we'll use the DRM device */ + card_matches = udev_enumerate_new (manager->udev_context); + udev_enumerate_add_match_is_initialized(card_matches); + udev_enumerate_add_match_parent (card_matches, udev_device_get_parent (fb_device)); + udev_enumerate_add_match_subsystem (card_matches, "drm"); + id_path = udev_device_get_property_value (fb_device, "ID_PATH"); + udev_enumerate_add_match_property (card_matches, "ID_PATH", id_path); + + ply_trace ("trying to find associated drm node for fb device (path: %s)", id_path); + + udev_enumerate_scan_devices (card_matches); + + /* there should only ever be at most one match so we don't iterate through + * the list, but just look at the first entry */ + card_entry = udev_enumerate_get_list_entry (card_matches); + + if (card_entry != NULL) + { + struct udev_device *card_device = NULL; + const char *card_node; + const char *card_path; + + card_path = udev_list_entry_get_name (card_entry); + card_device = udev_device_new_from_syspath (manager->udev_context, card_path); + card_node = udev_device_get_devnode (card_device); + if (card_node != NULL && drm_device_in_use (manager, card_node)) + has_drm_device = true; + else + ply_trace ("no card node!"); + + udev_device_unref (card_device); + } + else + { + ply_trace ("no card entry!"); + } + + udev_enumerate_unref (card_matches); + return has_drm_device; + } + + static void +-create_seat_for_udev_device (ply_device_manager_t *manager, +- struct udev_device *device) ++create_devices_for_udev_device (ply_device_manager_t *manager, ++ struct udev_device *device) + { + bool for_local_console; + const char *device_path; + ply_terminal_t *terminal = NULL; + + for_local_console = device_is_for_local_console (manager, device); + + ply_trace ("device is for local console: %s", for_local_console? "yes" : "no"); + + if (for_local_console) + terminal = manager->local_console_terminal; + + device_path = udev_device_get_devnode (device); + + if (device_path != NULL) + { + const char *subsystem; + ply_renderer_type_t renderer_type = PLY_RENDERER_TYPE_NONE; + + subsystem = udev_device_get_subsystem (device); + ply_trace ("device subsystem is %s", subsystem); + + if (subsystem != NULL && strcmp (subsystem, SUBSYSTEM_DRM) == 0) + { + ply_trace ("found DRM device %s", device_path); + renderer_type = PLY_RENDERER_TYPE_DRM; + } + else if (strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0) + { + ply_trace ("found frame buffer device %s", device_path); + if (!fb_device_has_drm_device (manager, device)) + { + renderer_type = PLY_RENDERER_TYPE_FRAME_BUFFER; + } + else + { + ply_trace ("ignoring, since there's a DRM device associated with it"); + } + } + + if (renderer_type != PLY_RENDERER_TYPE_NONE) +- create_seat_for_terminal_and_renderer_type (manager, +- device_path, +- terminal, +- renderer_type); ++ create_devices_for_terminal_and_renderer_type (manager, ++ device_path, ++ terminal, ++ renderer_type); + } + } + + static void +-free_seat_from_device_path (ply_device_manager_t *manager, +- const char *device_path) ++free_displays_for_renderer (ply_device_manager_t *manager, ++ ply_renderer_t *renderer) + { + ply_list_node_t *node; + +- node = ply_list_get_first_node (manager->seats); ++ node = ply_list_get_first_node (manager->pixel_displays); + while (node != NULL) + { +- ply_seat_t *seat; +- ply_renderer_t *renderer; + ply_list_node_t *next_node; +- const char *renderer_device_path; ++ ply_pixel_display_t *display; ++ ply_renderer_t *display_renderer; + +- seat = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (manager->seats, node); +- renderer = ply_seat_get_renderer (seat); ++ display = ply_list_node_get_data (node); ++ next_node = ply_list_get_next_node (manager->pixel_displays, node); ++ display_renderer = ply_pixel_display_get_renderer (display); + +- if (renderer != NULL) ++ if (display_renderer == renderer) + { +- renderer_device_path = ply_renderer_get_device_name (renderer); ++ if (manager->pixel_display_removed_handler != NULL) ++ manager->pixel_display_removed_handler (manager->event_handler_data, display); + +- if (renderer_device_path != NULL) +- { +- if (strcmp (device_path, renderer_device_path) == 0) +- { +- ply_trace ("removing seat associated with %s", device_path); +- +- if (manager->seat_removed_handler != NULL) +- manager->seat_removed_handler (manager->seat_event_handler_data, seat); +- +- ply_seat_free (seat); +- ply_list_remove_node (manager->seats, node); +- break; +- } +- } ++ ply_pixel_display_free (display); ++ ply_list_remove_node (manager->pixel_displays, node); + } + + node = next_node; + } + } + + static void +-free_seat_for_udev_device (ply_device_manager_t *manager, +- struct udev_device *device) ++free_devices_from_device_path (ply_device_manager_t *manager, ++ const char *device_path) ++{ ++ char *key = NULL; ++ ply_renderer_t *renderer = NULL; ++ ++ ply_hashtable_lookup_full (manager->renderers, ++ (void *) device_path, ++ (void **) &key, ++ (void **) &renderer); ++ ++ if (renderer == NULL) ++ return; ++ ++ free_displays_for_renderer (manager, renderer); ++ ++ ply_hashtable_remove (manager->renderers, (void *) device_path); ++ free (key); ++ ply_renderer_free (renderer); ++} ++ ++static void ++free_devices_for_udev_device (ply_device_manager_t *manager, ++ struct udev_device *device) + { + const char *device_path; + + device_path = udev_device_get_devnode (device); + + if (device_path != NULL) +- free_seat_from_device_path (manager, device_path); ++ free_devices_from_device_path (manager, device_path); + } + + static bool +-create_seats_for_subsystem (ply_device_manager_t *manager, +- const char *subsystem) ++create_devices_for_subsystem (ply_device_manager_t *manager, ++ const char *subsystem) + { + struct udev_enumerate *matches; + struct udev_list_entry *entry; + bool found_device = false; + +- ply_trace ("creating seats for %s devices", ++ ply_trace ("creating devices for %s devices", + strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0? + "frame buffer": + subsystem); + + matches = udev_enumerate_new (manager->udev_context); + udev_enumerate_add_match_subsystem (matches, subsystem); + udev_enumerate_scan_devices (matches); + + udev_list_entry_foreach (entry, udev_enumerate_get_list_entry (matches)) + { + struct udev_device *device = NULL; + const char *path; + + path = udev_list_entry_get_name (entry); + + if (path == NULL) + { + ply_trace ("path was null!"); + continue; + } + + ply_trace ("found device %s", path); + + device = udev_device_new_from_syspath (manager->udev_context, path); + + /* if device isn't fully initialized, we'll get an add event later + */ + if (udev_device_get_is_initialized (device)) + { + ply_trace ("device is initialized"); + + /* We only care about devices assigned to a (any) seat. Floating + * devices should be ignored. + */ + if (udev_device_has_tag (device, "seat")) + { + const char *node; + node = udev_device_get_devnode (device); + if (node != NULL) + { + ply_trace ("found node %s", node); + found_device = true; +- create_seat_for_udev_device (manager, device); ++ create_devices_for_udev_device (manager, device); + } + } + else + { + ply_trace ("device doesn't have a seat tag"); + } + } + else + { + ply_trace ("it's not initialized"); + } + + udev_device_unref (device); + } + + udev_enumerate_unref (matches); + + return found_device; + } + + static void + on_udev_event (ply_device_manager_t *manager) + { + struct udev_device *device; + const char *action; + + device = udev_monitor_receive_device (manager->udev_monitor); + if (device == NULL) + return; + + action = udev_device_get_action (device); + + ply_trace ("got %s event for device %s", action, udev_device_get_sysname (device)); + + if (action == NULL) + return; + + if (strcmp (action, "add") == 0) + { + const char *subsystem; + bool coldplug_complete = manager->udev_queue_fd_watch == NULL; + + subsystem = udev_device_get_subsystem (device); + + if (strcmp (subsystem, SUBSYSTEM_DRM) == 0 || + coldplug_complete) + { +- ply_list_t *local_pixel_displays = NULL; +- +- if (manager->local_console_seat != NULL) +- local_pixel_displays = ply_seat_get_pixel_displays (manager->local_console_seat); +- +- if (coldplug_complete && manager->local_console_seat != NULL && local_pixel_displays == NULL) ++ if (coldplug_complete && manager->local_console_managed && manager->local_console_is_text) + ply_trace ("ignoring since we're already using text splash for local console"); + else +- create_seat_for_udev_device (manager, device); ++ create_devices_for_udev_device (manager, device); + } + else + { + ply_trace ("ignoring since we only handle subsystem %s devices after coldplug completes", subsystem); + } + } + else if (strcmp (action, "remove") == 0) + { +- free_seat_for_udev_device (manager, device); ++ free_devices_for_udev_device (manager, device); + } + + udev_device_unref (device); + } + + static void + watch_for_udev_events (ply_device_manager_t *manager) + { + int fd; + assert (manager != NULL); + assert (manager->udev_monitor == NULL); + + ply_trace ("watching for udev graphics device add and remove events"); + + manager->udev_monitor = udev_monitor_new_from_netlink (manager->udev_context, "udev"); + + udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_DRM, NULL); + udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_FRAME_BUFFER, NULL); + udev_monitor_filter_add_match_tag (manager->udev_monitor, "seat"); + udev_monitor_enable_receiving (manager->udev_monitor); + + fd = udev_monitor_get_fd (manager->udev_monitor); + ply_event_loop_watch_fd (manager->loop, + fd, + PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, + (ply_event_handler_t) + on_udev_event, + NULL, + manager); + } + + static void +-free_seats (ply_device_manager_t *manager) +-{ +- ply_list_node_t *node; +- +- ply_trace ("removing seats"); +- node = ply_list_get_first_node (manager->seats); +- while (node != NULL) +- { +- ply_seat_t *seat; +- ply_list_node_t *next_node; +- +- seat = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (manager->seats, node); +- +- if (manager->seat_removed_handler != NULL) +- manager->seat_removed_handler (manager->seat_event_handler_data, seat); +- +- ply_seat_free (seat); +- ply_list_remove_node (manager->seats, node); +- +- node = next_node; +- } +-} +- +-static void + free_terminal (char *device, + ply_terminal_t *terminal, + ply_device_manager_t *manager) + { + ply_hashtable_remove (manager->terminals, device); + + ply_terminal_free (terminal); + } + + static void + free_terminals (ply_device_manager_t *manager) + { + ply_hashtable_foreach (manager->terminals, + (ply_hashtable_foreach_func_t *) + free_terminal, + manager); + } + + static ply_terminal_t * + get_terminal (ply_device_manager_t *manager, + const char *device_name) + { + char *full_name = NULL; + ply_terminal_t *terminal; + + if (strncmp (device_name, "/dev/", strlen ("/dev/")) == 0) + full_name = strdup (device_name); + else + asprintf (&full_name, "/dev/%s", device_name); + + if (strcmp (full_name, "/dev/tty0") == 0 || + strcmp (full_name, "/dev/tty") == 0 || + strcmp (full_name, ply_terminal_get_name (manager->local_console_terminal)) == 0) + { + terminal = manager->local_console_terminal; + + ply_hashtable_insert (manager->terminals, + (void *) ply_terminal_get_name (terminal), + terminal); + goto done; + } + + terminal = ply_hashtable_lookup (manager->terminals, full_name); + + if (terminal == NULL) + { + terminal = ply_terminal_new (full_name); + + ply_hashtable_insert (manager->terminals, + (void *) ply_terminal_get_name (terminal), + terminal); + } + + done: + free (full_name); + return terminal; + } + ++static void ++free_renderer (char *device_path, ++ ply_renderer_t *renderer, ++ ply_device_manager_t *manager) ++{ ++ free_devices_from_device_path (manager, device_path); ++} ++ ++static void ++free_renderers (ply_device_manager_t *manager) ++{ ++ ply_hashtable_foreach (manager->renderers, ++ (ply_hashtable_foreach_func_t *) ++ free_renderer, ++ manager); ++} ++ + ply_device_manager_t * + ply_device_manager_new (const char *default_tty, + ply_device_manager_flags_t flags) + { + ply_device_manager_t *manager; + + manager = calloc (1, sizeof (ply_device_manager_t)); + manager->loop = NULL; + manager->terminals = ply_hashtable_new (ply_hashtable_string_hash, ply_hashtable_string_compare); ++ manager->renderers = ply_hashtable_new (ply_hashtable_string_hash, ply_hashtable_string_compare); + manager->local_console_terminal = ply_terminal_new (default_tty); +- manager->seats = ply_list_new (); ++ manager->keyboards = ply_list_new (); ++ manager->text_displays = ply_list_new (); ++ manager->pixel_displays = ply_list_new (); + manager->flags = flags; + + if (!(flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV)) + manager->udev_context = udev_new (); + + attach_to_event_loop (manager, ply_event_loop_get_default ()); + + return manager; + } + + void + ply_device_manager_free (ply_device_manager_t *manager) + { + ply_trace ("freeing device manager"); + + if (manager == NULL) + return; + + ply_event_loop_stop_watching_for_exit (manager->loop, + (ply_event_loop_exit_handler_t) + detach_from_event_loop, + manager); +- free_seats (manager); +- ply_list_free (manager->seats); +- + free_terminals (manager); + ply_hashtable_free (manager->terminals); + ++ free_renderers (manager); ++ ply_hashtable_free (manager->renderers); ++ + if (manager->udev_monitor != NULL) + udev_monitor_unref (manager->udev_monitor); + + if (manager->udev_context != NULL) + udev_unref (manager->udev_context); + + free (manager); + } + + static bool + add_consoles_from_file (ply_device_manager_t *manager, + const char *path) + { + int fd; + char contents[512] = ""; + ssize_t contents_length; + bool has_serial_consoles; + const char *remaining_file_contents; + + ply_trace ("opening %s", path); + fd = open (path, O_RDONLY); + + if (fd < 0) + { + ply_trace ("couldn't open it: %m"); + return false; + } + + ply_trace ("reading file"); + contents_length = read (fd, contents, sizeof (contents) - 1); +@@ -638,343 +621,438 @@ add_consoles_from_file (ply_device_manager_t *manager, + + /* Find trailing whitespace and NUL terminate. If strcspn + * doesn't find whitespace, it gives us the length of the string + * until the next NUL byte, which we'll just overwrite with + * another NUL byte anyway. */ + console_length = strcspn (remaining_file_contents, " \n\t\v"); + console = strndup (remaining_file_contents, console_length); + + terminal = get_terminal (manager, console); + console_device = ply_terminal_get_name (terminal); + + free (console); + + ply_trace ("console %s found!", console_device); + + if (terminal != manager->local_console_terminal) + has_serial_consoles = true; + + /* Move past the parsed console string, and the whitespace we + * may have found above. If we found a NUL above and not whitespace, + * then we're going to jump past the end of the buffer and the loop + * will terminate + */ + remaining_file_contents += console_length + 1; + } + + return has_serial_consoles; + } + + static void +-create_seat_for_terminal_and_renderer_type (ply_device_manager_t *manager, +- const char *device_path, +- ply_terminal_t *terminal, +- ply_renderer_type_t renderer_type) ++create_pixel_displays_for_renderer (ply_device_manager_t *manager, ++ ply_renderer_t *renderer) ++{ ++ ply_list_t *heads; ++ ply_list_node_t *node; ++ ++ heads = ply_renderer_get_heads (renderer); ++ ++ ply_trace ("Adding displays for %d heads", ++ ply_list_get_length (heads)); ++ ++ node = ply_list_get_first_node (heads); ++ while (node != NULL) ++ { ++ ply_list_node_t *next_node; ++ ply_renderer_head_t *head; ++ ply_pixel_display_t *display; ++ ++ head = ply_list_node_get_data (node); ++ next_node = ply_list_get_next_node (heads, node); ++ ++ display = ply_pixel_display_new (renderer, head); ++ ++ ply_list_append_data (manager->pixel_displays, display); ++ ++ if (manager->pixel_display_added_handler != NULL) ++ manager->pixel_display_added_handler (manager->event_handler_data, display); ++ node = next_node; ++ } ++} ++ ++static void ++create_text_displays_for_terminal (ply_device_manager_t *manager, ++ ply_terminal_t *terminal) + { +- ply_seat_t *seat; ++ ply_text_display_t *display; ++ ++ if (!ply_terminal_is_open (terminal)) ++ { ++ if (!ply_terminal_open (terminal)) ++ { ++ ply_trace ("could not add terminal %s: %m", ++ ply_terminal_get_name (terminal)); ++ return; ++ } ++ } ++ ++ ply_trace ("adding text display for terminal %s", ++ ply_terminal_get_name (terminal)); ++ ++ display = ply_text_display_new (terminal); ++ ply_list_append_data (manager->text_displays, display); ++ ++ if (manager->text_display_added_handler != NULL) ++ manager->text_display_added_handler (manager->event_handler_data, display); ++} ++ ++static void ++create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, ++ const char *device_path, ++ ply_terminal_t *terminal, ++ ply_renderer_type_t renderer_type) ++{ ++ ply_renderer_t *renderer = NULL; ++ ply_keyboard_t *keyboard = NULL; ++ + bool is_local_terminal = false; + + if (terminal != NULL && manager->local_console_terminal == terminal) + is_local_terminal = true; + +- if (is_local_terminal && manager->local_console_seat != NULL) ++ if (is_local_terminal && manager->local_console_managed) + { +- ply_trace ("trying to create seat for local console when one already exists"); ++ ply_trace ("trying to create devices for local console when one already exists"); + return; + } + +- ply_trace ("creating seat for %s (renderer type: %u) (terminal: %s)", ++ ply_trace ("creating devices for %s (renderer type: %u) (terminal: %s)", + device_path? : "", renderer_type, terminal? ply_terminal_get_name (terminal): "none"); +- seat = ply_seat_new (terminal); + +- if (!ply_seat_open (seat, renderer_type, device_path)) ++ if (renderer_type != PLY_RENDERER_TYPE_NONE) + { +- ply_trace ("could not create seat"); +- ply_seat_free (seat); +- return; ++ renderer = ply_renderer_new (renderer_type, device_path, terminal); ++ ++ if (!ply_renderer_open (renderer)) ++ { ++ ply_trace ("could not open renderer for %s", device_path); ++ ply_renderer_free (renderer); ++ renderer = NULL; ++ if (renderer_type != PLY_RENDERER_TYPE_AUTO) ++ return; ++ } ++ } ++ ++ if (renderer != NULL) ++ { ++ keyboard = ply_keyboard_new_for_renderer (renderer); ++ ply_list_append_data (manager->keyboards, keyboard); ++ ++ if (manager->keyboard_added_handler != NULL) ++ manager->keyboard_added_handler (manager->event_handler_data, keyboard); ++ ++ create_pixel_displays_for_renderer (manager, renderer); ++ ply_hashtable_insert (manager->renderers, strdup (device_path), renderer); ++ } ++ else if (terminal != NULL) ++ { ++ keyboard = ply_keyboard_new_for_terminal (terminal); ++ ply_list_append_data (manager->keyboards, keyboard); ++ ++ if (manager->keyboard_added_handler != NULL) ++ manager->keyboard_added_handler (manager->event_handler_data, keyboard); ++ } ++ ++ if (terminal != NULL) ++ { ++ create_text_displays_for_terminal (manager, terminal); ++ ++ if (is_local_terminal) ++ { ++ manager->local_console_is_text = true; ++ } + } + +- ply_list_append_data (manager->seats, seat); ++ if (keyboard != NULL) ++ { ++ ply_keyboard_watch_for_input (keyboard); ++ } + + if (is_local_terminal) +- manager->local_console_seat = seat; ++ manager->local_console_managed = true; + +- if (manager->seat_added_handler != NULL) +- manager->seat_added_handler (manager->seat_event_handler_data, seat); + } + + static void +-create_seat_for_terminal (const char *device_path, +- ply_terminal_t *terminal, +- ply_device_manager_t *manager) ++create_devices_for_terminal (const char *device_path, ++ ply_terminal_t *terminal, ++ ply_device_manager_t *manager) + { +- create_seat_for_terminal_and_renderer_type (manager, +- device_path, +- terminal, +- PLY_RENDERER_TYPE_NONE); ++ create_devices_for_terminal_and_renderer_type (manager, ++ device_path, ++ terminal, ++ PLY_RENDERER_TYPE_NONE); + } + static bool +-create_seats_from_terminals (ply_device_manager_t *manager) ++create_devices_from_terminals (ply_device_manager_t *manager) + { + bool has_serial_consoles; + + ply_trace ("checking for consoles"); + + if (manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES) + { + has_serial_consoles = false; + ply_trace ("ignoring all consoles but default console because explicitly told to."); + } + else + { + has_serial_consoles = add_consoles_from_file (manager, "/sys/class/tty/console/active"); + } + + if (has_serial_consoles) + { + ply_trace ("serial consoles detected, managing them with details forced"); + ply_hashtable_foreach (manager->terminals, + (ply_hashtable_foreach_func_t *) +- create_seat_for_terminal, ++ create_devices_for_terminal, + manager); + return true; + } + + return false; + } + + static void +-create_seats_from_udev (ply_device_manager_t *manager) ++create_devices_from_udev (ply_device_manager_t *manager) + { + bool found_drm_device, found_fb_device; + + ply_trace ("Looking for devices from udev"); + +- found_drm_device = create_seats_for_subsystem (manager, SUBSYSTEM_DRM); +- found_fb_device = create_seats_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER); ++ found_drm_device = create_devices_for_subsystem (manager, SUBSYSTEM_DRM); ++ found_fb_device = create_devices_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER); + + if (found_drm_device || found_fb_device) + return; + +- ply_trace ("Creating non-graphical seat, since there's no suitable graphics hardware"); +- create_seat_for_terminal_and_renderer_type (manager, +- ply_terminal_get_name (manager->local_console_terminal), +- manager->local_console_terminal, +- PLY_RENDERER_TYPE_NONE); ++ ply_trace ("Creating non-graphical devices, since there's no suitable graphics hardware"); ++ create_devices_for_terminal_and_renderer_type (manager, ++ ply_terminal_get_name (manager->local_console_terminal), ++ manager->local_console_terminal, ++ PLY_RENDERER_TYPE_NONE); + } + + static void +-create_fallback_seat (ply_device_manager_t *manager) ++create_fallback_devices (ply_device_manager_t *manager) + { +- create_seat_for_terminal_and_renderer_type (manager, +- ply_terminal_get_name (manager->local_console_terminal), +- manager->local_console_terminal, +- PLY_RENDERER_TYPE_AUTO); ++ create_devices_for_terminal_and_renderer_type (manager, ++ ply_terminal_get_name (manager->local_console_terminal), ++ manager->local_console_terminal, ++ PLY_RENDERER_TYPE_AUTO); + } + + static void + on_udev_queue_changed (ply_device_manager_t *manager) + { + + if (!udev_queue_get_queue_is_empty (manager->udev_queue)) + return; + + ply_trace ("udev coldplug complete"); + ply_event_loop_stop_watching_fd (manager->loop, manager->udev_queue_fd_watch); + manager->udev_queue_fd_watch = NULL; + udev_queue_unref (manager->udev_queue); + + close (manager->udev_queue_fd); + manager->udev_queue_fd = -1; + + manager->udev_queue = NULL; + +- create_seats_from_udev (manager); ++ create_devices_from_udev (manager); + } + + static void + watch_for_coldplug_completion (ply_device_manager_t *manager) + { + int fd; + int result; + + manager->udev_queue = udev_queue_new (manager->udev_context); + + if (udev_queue_get_queue_is_empty (manager->udev_queue)) + { + ply_trace ("udev coldplug completed already "); +- create_seats_from_udev (manager); ++ create_devices_from_udev (manager); + return; + } + + fd = inotify_init1 (IN_CLOEXEC); + result = inotify_add_watch (fd, "/run/udev", IN_MOVED_TO| IN_DELETE); + + if (result < 0) + { + ply_trace ("could not watch for udev to show up: %m"); + close (fd); + +- create_fallback_seat (manager); ++ create_fallback_devices (manager); + return; + } + + manager->udev_queue_fd = fd; + + manager->udev_queue_fd_watch = ply_event_loop_watch_fd (manager->loop, + fd, + PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, + (ply_event_handler_t) + on_udev_queue_changed, + NULL, + manager); + + } + + void +-ply_device_manager_watch_seats (ply_device_manager_t *manager, +- ply_seat_added_handler_t seat_added_handler, +- ply_seat_removed_handler_t seat_removed_handler, +- void *data) ++ply_device_manager_watch_devices (ply_device_manager_t *manager, ++ ply_keyboard_added_handler_t keyboard_added_handler, ++ ply_keyboard_removed_handler_t keyboard_removed_handler, ++ ply_pixel_display_added_handler_t pixel_display_added_handler, ++ ply_pixel_display_removed_handler_t pixel_display_removed_handler, ++ ply_text_display_added_handler_t text_display_added_handler, ++ ply_text_display_removed_handler_t text_display_removed_handler, ++ void *data) + { +- bool done_with_initial_seat_setup; ++ bool done_with_initial_devices_setup; + +- manager->seat_added_handler = seat_added_handler; +- manager->seat_removed_handler = seat_removed_handler; +- manager->seat_event_handler_data = data; ++ manager->keyboard_added_handler = keyboard_added_handler; ++ manager->keyboard_removed_handler = keyboard_removed_handler; ++ manager->pixel_display_added_handler = pixel_display_added_handler; ++ manager->pixel_display_removed_handler = pixel_display_removed_handler; ++ manager->text_display_added_handler = text_display_added_handler; ++ manager->text_display_removed_handler = text_display_removed_handler; ++ manager->event_handler_data = data; + +- /* Try to create seats for each serial device right away, if possible ++ /* Try to create devices for each serial device right away, if possible + */ +- done_with_initial_seat_setup = create_seats_from_terminals (manager); ++ done_with_initial_devices_setup = create_devices_from_terminals (manager); + +- if (done_with_initial_seat_setup) ++ if (done_with_initial_devices_setup) + return; + + if ((manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV)) + { +- ply_trace ("udev support disabled, creating fallback seat"); +- create_fallback_seat (manager); ++ ply_trace ("udev support disabled, creating fallback devices"); ++ create_fallback_devices (manager); + return; + } + + watch_for_udev_events (manager); + watch_for_coldplug_completion (manager); + } + + bool +-ply_device_manager_has_open_seats (ply_device_manager_t *manager) ++ply_device_manager_has_displays (ply_device_manager_t *manager) + { +- ply_list_node_t *node; +- +- node = ply_list_get_first_node (manager->seats); +- while (node != NULL) +- { +- ply_seat_t *seat; +- ply_list_node_t *next_node; +- +- seat = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (manager->seats, node); +- +- if (ply_seat_is_open (seat)) +- return true; ++ return ply_list_get_length (manager->pixel_displays) > 0 || ++ ply_list_get_length (manager->text_displays) > 0; ++} + +- node = next_node; +- } ++ply_list_t * ++ply_device_manager_get_keyboards (ply_device_manager_t *manager) ++{ ++ return manager->keyboards; ++} + +- return false; ++ply_list_t * ++ply_device_manager_get_pixel_displays (ply_device_manager_t *manager) ++{ ++ return manager->pixel_displays; + } + + ply_list_t * +-ply_device_manager_get_seats (ply_device_manager_t *manager) ++ply_device_manager_get_text_displays (ply_device_manager_t *manager) + { +- return manager->seats; ++ return manager->text_displays; + } + + ply_terminal_t * + ply_device_manager_get_default_terminal (ply_device_manager_t *manager) + { + return manager->local_console_terminal; + } + ++static void ++activate_renderer (char *device_path, ++ ply_renderer_t *renderer, ++ ply_device_manager_t *manager) ++{ ++ ply_renderer_activate (renderer); ++} ++ + void + ply_device_manager_activate_renderers (ply_device_manager_t *manager) + { +- ply_list_node_t *node; +- + ply_trace ("activating renderers"); +- node = ply_list_get_first_node (manager->seats); +- while (node != NULL) +- { +- ply_seat_t *seat; +- ply_list_node_t *next_node; +- +- seat = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (manager->seats, node); +- +- ply_seat_activate_renderer (seat); ++ ply_hashtable_foreach (manager->renderers, ++ (ply_hashtable_foreach_func_t *) ++ activate_renderer, ++ manager); ++} + +- node = next_node; +- } ++static void ++deactivate_renderer (char *device_path, ++ ply_renderer_t *renderer, ++ ply_device_manager_t *manager) ++{ ++ ply_renderer_deactivate (renderer); + } + + void + ply_device_manager_deactivate_renderers (ply_device_manager_t *manager) + { +- ply_list_node_t *node; +- + ply_trace ("deactivating renderers"); +- node = ply_list_get_first_node (manager->seats); +- while (node != NULL) +- { +- ply_seat_t *seat; +- ply_list_node_t *next_node; +- +- seat = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (manager->seats, node); +- +- ply_seat_deactivate_renderer (seat); +- +- node = next_node; +- } ++ ply_hashtable_foreach (manager->renderers, ++ (ply_hashtable_foreach_func_t *) ++ deactivate_renderer, ++ manager); + } + + void + ply_device_manager_activate_keyboards (ply_device_manager_t *manager) + { + ply_list_node_t *node; + + ply_trace ("activating keyboards"); +- node = ply_list_get_first_node (manager->seats); ++ node = ply_list_get_first_node (manager->keyboards); + while (node != NULL) + { +- ply_seat_t *seat; ++ ply_keyboard_t *keyboard; + ply_list_node_t *next_node; + +- seat = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (manager->seats, node); ++ keyboard = ply_list_node_get_data (node); ++ next_node = ply_list_get_next_node (manager->keyboards, node); + +- ply_seat_activate_keyboard (seat); ++ ply_keyboard_watch_for_input (keyboard); + + node = next_node; + } + } + + void + ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager) + { + ply_list_node_t *node; + + ply_trace ("deactivating keyboards"); +- node = ply_list_get_first_node (manager->seats); ++ node = ply_list_get_first_node (manager->keyboards); + while (node != NULL) + { +- ply_seat_t *seat; ++ ply_keyboard_t *keyboard; + ply_list_node_t *next_node; + +- seat = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (manager->seats, node); ++ keyboard = ply_list_node_get_data (node); ++ next_node = ply_list_get_next_node (manager->keyboards, node); + +- ply_seat_deactivate_keyboard (seat); ++ ply_keyboard_stop_watching_for_input (keyboard); + + node = next_node; + } + } +diff --git a/src/libply-splash-core/ply-device-manager.h b/src/libply-splash-core/ply-device-manager.h +index d9c58e8..b628e41 100644 +--- a/src/libply-splash-core/ply-device-manager.h ++++ b/src/libply-splash-core/ply-device-manager.h +@@ -1,56 +1,70 @@ + /* ply-device-manager.h - udev monitor + * + * Copyright (C) 2013 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 + * 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. + */ + #ifndef PLY_DEVICE_MANAGER_H + #define PLY_DEVICE_MANAGER_H + + #include +-#include "ply-seat.h" ++ ++#include "ply-keyboard.h" ++#include "ply-pixel-display.h" ++#include "ply-renderer.h" ++#include "ply-text-display.h" + + typedef enum + { + PLY_DEVICE_MANAGER_FLAGS_NONE = 0, + PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES = 1 << 0, + PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV = 1 << 1 + } ply_device_manager_flags_t; + + typedef struct _ply_device_manager ply_device_manager_t; +-typedef void (* ply_seat_added_handler_t) (void *, ply_seat_t *); +-typedef void (* ply_seat_removed_handler_t) (void *, ply_seat_t *); ++typedef void (* ply_keyboard_added_handler_t) (void *, ply_keyboard_t *); ++typedef void (* ply_keyboard_removed_handler_t) (void *, ply_keyboard_t *); ++typedef void (* ply_pixel_display_added_handler_t) (void *, ply_pixel_display_t *); ++typedef void (* ply_pixel_display_removed_handler_t) (void *, ply_pixel_display_t *); ++typedef void (* ply_text_display_added_handler_t) (void *, ply_text_display_t *); ++typedef void (* ply_text_display_removed_handler_t) (void *, ply_text_display_t *); + + #ifndef PLY_HIDE_FUNCTION_DECLARATIONS + ply_device_manager_t *ply_device_manager_new (const char *default_tty, + ply_device_manager_flags_t flags); +-void ply_device_manager_watch_seats (ply_device_manager_t *manager, +- ply_seat_added_handler_t seat_added_handler, +- ply_seat_removed_handler_t seat_removed_handler, +- void *data); +-bool ply_device_manager_has_open_seats (ply_device_manager_t *manager); +-ply_list_t *ply_device_manager_get_seats (ply_device_manager_t *manager); ++void ply_device_manager_watch_devices (ply_device_manager_t *manager, ++ ply_keyboard_added_handler_t keyboard_added_handler, ++ ply_keyboard_removed_handler_t keyboard_removed_handler, ++ ply_pixel_display_added_handler_t pixel_display_added_handler, ++ ply_pixel_display_removed_handler_t pixel_display_removed_handler, ++ ply_text_display_added_handler_t text_display_added_handler, ++ ply_text_display_removed_handler_t text_display_removed_handler, ++ void *data); ++bool ply_device_manager_has_displays (ply_device_manager_t *manager); ++ply_list_t *ply_device_manager_get_keyboards (ply_device_manager_t *manager); ++ply_list_t *ply_device_manager_get_pixel_displays (ply_device_manager_t *manager); ++ply_list_t *ply_device_manager_get_text_displays (ply_device_manager_t *manager); + void ply_device_manager_free (ply_device_manager_t *manager); + void ply_device_manager_activate_keyboards (ply_device_manager_t *manager); + void ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager); + void ply_device_manager_activate_renderers (ply_device_manager_t *manager); + void ply_device_manager_deactivate_renderers (ply_device_manager_t *manager); + ply_terminal_t *ply_device_manager_get_default_terminal (ply_device_manager_t *manager); + + #endif + + #endif + /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ +diff --git a/src/libply-splash-core/ply-seat.c b/src/libply-splash-core/ply-seat.c +deleted file mode 100644 +index 1c885c2..0000000 +--- a/src/libply-splash-core/ply-seat.c ++++ /dev/null +@@ -1,374 +0,0 @@ +-/* ply-seat.c - APIs for encapsulating a keyboard and one or more displays +- * +- * Copyright (C) 2013 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 +- * 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: Ray Strode +- */ +-#include "config.h" +-#include "ply-seat.h" +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "ply-boot-splash.h" +-#include "ply-event-loop.h" +-#include "ply-keyboard.h" +-#include "ply-pixel-display.h" +-#include "ply-text-display.h" +-#include "ply-list.h" +-#include "ply-logger.h" +-#include "ply-utils.h" +- +-struct _ply_seat +-{ +- ply_event_loop_t *loop; +- +- ply_boot_splash_t *splash; +- ply_terminal_t *terminal; +- ply_renderer_t *renderer; +- ply_keyboard_t *keyboard; +- ply_list_t *text_displays; +- ply_list_t *pixel_displays; +-}; +- +-ply_seat_t * +-ply_seat_new (ply_terminal_t *terminal) +-{ +- ply_seat_t *seat; +- +- seat = calloc (1, sizeof (ply_seat_t)); +- +- seat->loop = ply_event_loop_get_default (); +- seat->terminal = terminal; +- seat->text_displays = ply_list_new (); +- seat->pixel_displays = ply_list_new (); +- +- return seat; +-} +- +-static void +-add_pixel_displays (ply_seat_t *seat) +-{ +- ply_list_t *heads; +- ply_list_node_t *node; +- +- heads = ply_renderer_get_heads (seat->renderer); +- +- ply_trace ("Adding displays for %d heads", +- ply_list_get_length (heads)); +- +- node = ply_list_get_first_node (heads); +- while (node != NULL) +- { +- ply_list_node_t *next_node; +- ply_renderer_head_t *head; +- ply_pixel_display_t *display; +- +- head = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (heads, node); +- +- display = ply_pixel_display_new (seat->renderer, head); +- +- ply_list_append_data (seat->pixel_displays, display); +- +- node = next_node; +- } +-} +- +-static void +-add_text_displays (ply_seat_t *seat) +-{ +- ply_text_display_t *display; +- +- if (!ply_terminal_is_open (seat->terminal)) +- { +- if (!ply_terminal_open (seat->terminal)) +- { +- ply_trace ("could not add terminal %s: %m", +- ply_terminal_get_name (seat->terminal)); +- return; +- } +- } +- +- ply_trace ("adding text display for terminal %s", +- ply_terminal_get_name (seat->terminal)); +- +- display = ply_text_display_new (seat->terminal); +- ply_list_append_data (seat->text_displays, display); +-} +- +-bool +-ply_seat_open (ply_seat_t *seat, +- ply_renderer_type_t renderer_type, +- const char *device) +-{ +- if (renderer_type != PLY_RENDERER_TYPE_NONE) +- { +- ply_renderer_t *renderer; +- +- renderer = ply_renderer_new (renderer_type, device, seat->terminal); +- +- if (!ply_renderer_open (renderer)) +- { +- ply_trace ("could not open renderer for %s", device); +- ply_renderer_free (renderer); +- +- if (renderer_type != PLY_RENDERER_TYPE_AUTO) +- return false; +- } +- else +- { +- seat->renderer = renderer; +- } +- } +- +- if (seat->renderer != NULL) +- { +- seat->keyboard = ply_keyboard_new_for_renderer (seat->renderer); +- add_pixel_displays (seat); +- +- } +- else if (seat->terminal != NULL) +- { +- seat->keyboard = ply_keyboard_new_for_terminal (seat->terminal); +- } +- +- if (seat->terminal != NULL) +- { +- add_text_displays (seat); +- } +- else +- { +- ply_trace ("not adding text display for seat, since seat has no associated terminal"); +- } +- +- if (seat->keyboard != NULL) +- { +- ply_keyboard_watch_for_input (seat->keyboard); +- } +- else +- { +- ply_trace ("not watching seat for input"); +- } +- +- return true; +-} +- +-bool +-ply_seat_is_open (ply_seat_t *seat) +-{ +- return ply_list_get_length (seat->pixel_displays) > 0 || +- ply_list_get_length (seat->text_displays) > 0; +-} +- +-void +-ply_seat_deactivate_keyboard (ply_seat_t *seat) +-{ +- if (seat->keyboard == NULL) +- return; +- +- ply_trace ("deactivating keybord"); +- ply_keyboard_stop_watching_for_input (seat->keyboard); +-} +- +-void +-ply_seat_deactivate_renderer (ply_seat_t *seat) +-{ +- if (seat->renderer == NULL) +- return; +- +- ply_trace ("deactivating renderer"); +- ply_renderer_deactivate (seat->renderer); +-} +- +-void +-ply_seat_activate_keyboard (ply_seat_t *seat) +-{ +- if (seat->keyboard == NULL) +- return; +- +- ply_trace ("activating keyboard"); +- ply_keyboard_watch_for_input (seat->keyboard); +-} +- +-void +-ply_seat_activate_renderer (ply_seat_t *seat) +-{ +- if (seat->renderer == NULL) +- return; +- +- ply_trace ("activating renderer"); +- ply_renderer_activate (seat->renderer); +-} +- +-void +-ply_seat_refresh_displays (ply_seat_t *seat) +-{ +- ply_list_node_t *node; +- +- node = ply_list_get_first_node (seat->pixel_displays); +- while (node != NULL) +- { +- ply_pixel_display_t *display; +- ply_list_node_t *next_node; +- unsigned long width, height; +- +- display = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (seat->pixel_displays, node); +- +- width = ply_pixel_display_get_width (display); +- height = ply_pixel_display_get_height (display); +- +- ply_pixel_display_draw_area (display, 0, 0, width, height); +- node = next_node; +- } +- +- node = ply_list_get_first_node (seat->text_displays); +- while (node != NULL) +- { +- ply_text_display_t *display; +- ply_list_node_t *next_node; +- int number_of_columns, number_of_rows; +- +- display = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (seat->text_displays, node); +- +- number_of_columns = ply_text_display_get_number_of_columns (display); +- number_of_rows = ply_text_display_get_number_of_rows (display); +- +- ply_text_display_draw_area (display, 0, 0, +- number_of_columns, +- number_of_rows); +- node = next_node; +- } +-} +- +-void +-ply_seat_close (ply_seat_t *seat) +-{ +- if (seat->renderer == NULL) +- return; +- +- ply_trace ("destroying renderer"); +- ply_renderer_close (seat->renderer); +- ply_renderer_free (seat->renderer); +- seat->renderer = NULL; +-} +- +-void +-ply_seat_set_splash (ply_seat_t *seat, +- ply_boot_splash_t *splash) +-{ +- if (seat->splash == splash) +- return; +- +- if (seat->splash != NULL) +- ply_boot_splash_detach_from_seat (splash, seat); +- +- if (splash != NULL) +- ply_boot_splash_attach_to_seat (splash, seat); +- +- seat->splash = splash; +-} +- +-static void +-free_pixel_displays (ply_seat_t *seat) +-{ +- ply_list_node_t *node; +- +- ply_trace ("freeing %d pixel displays", ply_list_get_length (seat->pixel_displays)); +- node = ply_list_get_first_node (seat->pixel_displays); +- while (node != NULL) +- { +- ply_list_node_t *next_node; +- ply_pixel_display_t *display; +- +- next_node = ply_list_get_next_node (seat->pixel_displays, node); +- display = ply_list_node_get_data (node); +- ply_pixel_display_free (display); +- +- ply_list_remove_node (seat->pixel_displays, node); +- +- node = next_node; +- } +-} +- +-static void +-free_text_displays (ply_seat_t *seat) +-{ +- ply_list_node_t *node; +- +- ply_trace ("freeing %d text displays", ply_list_get_length (seat->text_displays)); +- node = ply_list_get_first_node (seat->text_displays); +- while (node != NULL) +- { +- ply_list_node_t *next_node; +- ply_text_display_t *display; +- +- next_node = ply_list_get_next_node (seat->text_displays, node); +- display = ply_list_node_get_data (node); +- ply_text_display_free (display); +- +- ply_list_remove_node (seat->text_displays, node); +- +- node = next_node; +- } +-} +- +-void +-ply_seat_free (ply_seat_t *seat) +-{ +- if (seat == NULL) +- return; +- +- free_pixel_displays (seat); +- free_text_displays (seat); +- ply_keyboard_free (seat->keyboard); +- +- free (seat); +-} +- +-ply_list_t * +-ply_seat_get_pixel_displays (ply_seat_t *seat) +-{ +- return seat->pixel_displays; +-} +- +-ply_list_t * +-ply_seat_get_text_displays (ply_seat_t *seat) +-{ +- return seat->text_displays; +-} +- +-ply_keyboard_t * +-ply_seat_get_keyboard (ply_seat_t *seat) +-{ +- return seat->keyboard; +-} +- +-ply_renderer_t * +-ply_seat_get_renderer (ply_seat_t *seat) +-{ +- return seat->renderer; +-} +- +-/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ +diff --git a/src/libply-splash-core/ply-seat.h b/src/libply-splash-core/ply-seat.h +deleted file mode 100644 +index d5d3397..0000000 +--- a/src/libply-splash-core/ply-seat.h ++++ /dev/null +@@ -1,66 +0,0 @@ +-/* ply-seat.h - APIs for encapsulating a keyboard and one or more displays +- * +- * Copyright (C) 2013 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 +- * 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: Ray Strode +- */ +-#ifndef PLY_SEAT_H +-#define PLY_SEAT_H +- +-#include +-#include +-#include +-#include +- +-#include "ply-boot-splash.h" +-#include "ply-buffer.h" +-#include "ply-event-loop.h" +-#include "ply-keyboard.h" +-#include "ply-list.h" +-#include "ply-pixel-display.h" +-#include "ply-terminal.h" +-#include "ply-text-display.h" +- +-typedef struct _ply_boot_splash ply_boot_splash_t; +-typedef struct _ply_seat ply_seat_t; +- +-#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +-ply_seat_t *ply_seat_new (ply_terminal_t *terminal); +- +-void ply_seat_free (ply_seat_t *seat); +-bool ply_seat_open (ply_seat_t *seat, +- ply_renderer_type_t renderer_type, +- const char *device); +-bool ply_seat_is_open (ply_seat_t *seat); +-void ply_seat_deactivate_keyboard (ply_seat_t *seat); +-void ply_seat_activate_keyboard (ply_seat_t *seat); +-void ply_seat_deactivate_renderer (ply_seat_t *seat); +-void ply_seat_activate_renderer (ply_seat_t *seat); +-void ply_seat_refresh_displays (ply_seat_t *seat); +-void ply_seat_close (ply_seat_t *seat); +-void ply_seat_set_splash (ply_seat_t *seat, +- ply_boot_splash_t *splash); +- +-ply_list_t *ply_seat_get_pixel_displays (ply_seat_t *seat); +-ply_list_t *ply_seat_get_text_displays (ply_seat_t *seat); +-ply_keyboard_t *ply_seat_get_keyboard (ply_seat_t *seat); +-ply_renderer_t *ply_seat_get_renderer (ply_seat_t *seat); +-#endif +- +-#endif /* PLY_SEAT_H */ +-/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ +diff --git a/src/main.c b/src/main.c +index db5c281..ec46199 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -108,62 +108,62 @@ typedef struct + double splash_delay; + + char kernel_command_line[PLY_MAX_COMMAND_LINE_SIZE]; + uint32_t kernel_command_line_is_set : 1; + uint32_t no_boot_log : 1; + uint32_t showing_details : 1; + uint32_t system_initialized : 1; + uint32_t is_redirected : 1; + uint32_t is_attached : 1; + uint32_t should_be_attached : 1; + uint32_t should_retain_splash : 1; + uint32_t is_inactive : 1; + uint32_t is_shown : 1; + uint32_t should_force_details : 1; + + char *override_splash_path; + char *system_default_splash_path; + char *distribution_default_splash_path; + const char *default_tty; + + int number_of_errors; + } state_t; + + static void show_splash (state_t *state); + static ply_boot_splash_t *load_built_in_theme (state_t *state); + static ply_boot_splash_t *load_theme (state_t *state, + const char *theme_path); + static ply_boot_splash_t *show_theme (state_t *state, + const char *theme_path); + +-static void attach_splash_to_seats (state_t *state, +- ply_boot_splash_t *splash); ++static void attach_splash_to_devices (state_t *state, ++ ply_boot_splash_t *splash); + static bool attach_to_running_session (state_t *state); + static void detach_from_running_session (state_t *state); + static void on_escape_pressed (state_t *state); + static void dump_details_and_quit_splash (state_t *state); + static void update_display (state_t *state); + + static void on_error_message (ply_buffer_t *debug_buffer, + const void *bytes, + size_t number_of_bytes); + static ply_buffer_t *debug_buffer; + static char *debug_buffer_path = NULL; + static char *pid_file = NULL; + static void toggle_between_splash_and_details (state_t *state); + #ifdef PLY_ENABLE_SYSTEMD_INTEGRATION + static void tell_systemd_to_print_details (state_t *state); + static void tell_systemd_to_stop_printing_details (state_t *state); + #endif + static const char * get_cache_file_for_mode (ply_mode_t mode); + static void on_escape_pressed (state_t *state); + static void on_enter (state_t *state, + const char *line); + static void on_keyboard_input (state_t *state, + const char *keyboard_input, + size_t character_size); + static void on_backspace (state_t *state); + static void on_quit (state_t *state, + bool retain_splash, + ply_trigger_t *quit_trigger); + static bool sh_is_init (state_t *state); + +@@ -486,69 +486,69 @@ show_default_splash (state_t *state) + update_display (state); + } + + static void + cancel_pending_delayed_show (state_t *state) + { + if (isnan (state->splash_delay)) + return; + + ply_event_loop_stop_watching_for_timeout (state->loop, + (ply_event_loop_timeout_handler_t) + show_splash, + state); + state->splash_delay = NAN; + } + + static void + on_ask_for_password (state_t *state, + const char *prompt, + ply_trigger_t *answer) + { + ply_entry_trigger_t *entry_trigger; + + if (state->boot_splash == NULL) + { + /* Waiting to be shown, boot splash will + * arrive shortly so just sit tight + */ + if (state->is_shown) + { +- bool has_open_seats; ++ bool has_displays; + + cancel_pending_delayed_show (state); + +- has_open_seats = ply_device_manager_has_open_seats (state->device_manager); ++ has_displays = ply_device_manager_has_displays (state->device_manager); + +- if (has_open_seats) ++ if (has_displays) + { +- ply_trace ("seats open now, showing splash immediately"); ++ ply_trace ("displays available now, showing splash immediately"); + show_splash (state); + } + else + { + ply_trace ("splash still coming up, waiting a bit"); + } + } + else + { + /* No splash, client will have to get password */ + ply_trace ("no splash loaded, replying immediately with no password"); + ply_trigger_pull (answer, NULL); + return; + } + } + + entry_trigger = calloc (1, sizeof (ply_entry_trigger_t)); + entry_trigger->type = PLY_ENTRY_TRIGGER_TYPE_PASSWORD; + entry_trigger->prompt = prompt; + entry_trigger->trigger = answer; + ply_trace ("queuing password request with boot splash"); + ply_list_append_data (state->entry_triggers, entry_trigger); + update_display (state); + } + + static void + on_ask_question (state_t *state, + const char *prompt, + ply_trigger_t *answer) + { +@@ -873,224 +873,273 @@ plymouth_should_show_default_splash (state_t *state) + { + ply_trace ("no default splash because kernel command line has option \"splash=verbose\""); + return false; + } + + if (command_line_has_argument (state->kernel_command_line, "rhgb")) + { + ply_trace ("using default splash because kernel command line has option \"rhgb\""); + return true; + } + + if (command_line_has_argument (state->kernel_command_line, "splash")) + { + ply_trace ("using default splash because kernel command line has option \"splash\""); + return true; + } + + if (command_line_has_argument (state->kernel_command_line, "splash=silent")) + { + ply_trace ("using default splash because kernel command line has option \"splash=slient\""); + return true; + } + + ply_trace ("no default splash because kernel command line lacks \"splash\" or \"rhgb\""); + return false; + } + + static void + on_show_splash (state_t *state) + { +- bool has_open_seats; ++ bool has_displays; + + if (state->is_shown) + { + ply_trace ("show splash called while already shown"); + return; + } + + if (state->is_inactive) + { + ply_trace ("show splash called while inactive"); + return; + } + + if (plymouth_should_ignore_show_splash_calls (state)) + { + ply_trace ("show splash called while ignoring show splash calls"); + dump_details_and_quit_splash (state); + return; + } + + state->is_shown = true; +- has_open_seats = ply_device_manager_has_open_seats (state->device_manager); ++ has_displays = ply_device_manager_has_displays (state->device_manager); + +- if (!state->is_attached && state->should_be_attached && has_open_seats) ++ if (!state->is_attached && state->should_be_attached && has_displays) + attach_to_running_session (state); + +- if (has_open_seats) ++ if (has_displays) + { +- ply_trace ("at least one seat already open, so loading splash"); ++ ply_trace ("at least one display already available, so loading splash"); + show_splash (state); + } + else + { +- ply_trace ("no seats available to show splash on, waiting..."); ++ ply_trace ("no displays available to show splash on, waiting..."); + } + } + + static void +-on_seat_removed (state_t *state, +- ply_seat_t *seat) +-{ +- ply_keyboard_t *keyboard; +- +- keyboard = ply_seat_get_keyboard (seat); +- +- ply_trace ("no longer listening for keystrokes"); +- ply_keyboard_remove_input_handler (keyboard, +- (ply_keyboard_input_handler_t) +- on_keyboard_input); +- ply_trace ("no longer listening for escape"); +- ply_keyboard_remove_escape_handler (keyboard, +- (ply_keyboard_escape_handler_t) +- on_escape_pressed); +- ply_trace ("no longer listening for backspace"); +- ply_keyboard_remove_backspace_handler (keyboard, +- (ply_keyboard_backspace_handler_t) +- on_backspace); +- ply_trace ("no longer listening for enter"); +- ply_keyboard_remove_enter_handler (keyboard, +- (ply_keyboard_enter_handler_t) +- on_enter); +- +- if (state->boot_splash != NULL) +- ply_boot_splash_detach_from_seat (state->boot_splash, seat); +-} +- +-static void + show_splash (state_t *state) + { + if (state->boot_splash != NULL) + return; + + if (!isnan (state->splash_delay)) + { + double now, running_time; + + now = ply_get_timestamp (); + running_time = now - state->start_time; + if (state->splash_delay > running_time) + { + double time_left = state->splash_delay - running_time; + + ply_trace ("delaying show splash for %lf seconds", + time_left); + ply_event_loop_stop_watching_for_timeout (state->loop, + (ply_event_loop_timeout_handler_t) + show_splash, + state); + ply_event_loop_watch_for_timeout (state->loop, + time_left, + (ply_event_loop_timeout_handler_t) + show_splash, + state); + return; + } + } + + if (plymouth_should_show_default_splash (state)) + { + show_default_splash (state); + state->showing_details = false; + } + else + { + show_detailed_splash (state); + state->showing_details = true; + } + } + + static void +-on_seat_added (state_t *state, +- ply_seat_t *seat) ++on_keyboard_added (state_t *state, ++ ply_keyboard_t *keyboard) + { +- ply_keyboard_t *keyboard; +- +- if (state->is_shown) +- { +- if (state->boot_splash == NULL) +- { +- ply_trace ("seat added before splash loaded, so loading splash now"); +- show_splash (state); +- } +- else +- { +- ply_trace ("seat added after splash loaded, so attaching to splash"); +- ply_boot_splash_attach_to_seat (state->boot_splash, seat); +- } +- } +- +- keyboard = ply_seat_get_keyboard (seat); +- + ply_trace ("listening for keystrokes"); + ply_keyboard_add_input_handler (keyboard, + (ply_keyboard_input_handler_t) + on_keyboard_input, state); + ply_trace ("listening for escape"); + ply_keyboard_add_escape_handler (keyboard, + (ply_keyboard_escape_handler_t) + on_escape_pressed, state); + ply_trace ("listening for backspace"); + ply_keyboard_add_backspace_handler (keyboard, + (ply_keyboard_backspace_handler_t) + on_backspace, state); + ply_trace ("listening for enter"); + ply_keyboard_add_enter_handler (keyboard, + (ply_keyboard_enter_handler_t) + on_enter, state); + ++ if (state->boot_splash != NULL) ++ { ++ ply_trace ("keyboard set after splash loaded, so attaching to splash"); ++ ply_boot_splash_set_keyboard (state->boot_splash, keyboard); ++ } ++} ++ ++static void ++on_keyboard_removed (state_t *state, ++ ply_keyboard_t *keyboard) ++{ ++ ply_trace ("no longer listening for keystrokes"); ++ ply_keyboard_remove_input_handler (keyboard, ++ (ply_keyboard_input_handler_t) ++ on_keyboard_input); ++ ply_trace ("no longer listening for escape"); ++ ply_keyboard_remove_escape_handler (keyboard, ++ (ply_keyboard_escape_handler_t) ++ on_escape_pressed); ++ ply_trace ("no longer listening for backspace"); ++ ply_keyboard_remove_backspace_handler (keyboard, ++ (ply_keyboard_backspace_handler_t) ++ on_backspace); ++ ply_trace ("no longer listening for enter"); ++ ply_keyboard_remove_enter_handler (keyboard, ++ (ply_keyboard_enter_handler_t) ++ on_enter); ++ ++ if (state->boot_splash != NULL) ++ ply_boot_splash_unset_keyboard (state->boot_splash); ++} ++ ++static void ++on_pixel_display_added (state_t *state, ++ ply_pixel_display_t *display) ++{ ++ if (state->is_shown) ++ { ++ if (state->boot_splash == NULL) ++ { ++ ply_trace ("pixel display added before splash loaded, so loading splash now"); ++ show_splash (state); ++ } ++ else ++ { ++ ply_trace ("pixel display added after splash loaded, so attaching to splash"); ++ ply_boot_splash_add_pixel_display (state->boot_splash, display); ++ } ++ } ++} ++ ++static void ++on_pixel_display_removed (state_t *state, ++ ply_pixel_display_t *display) ++{ ++ if (state->boot_splash == NULL) ++ return; ++ ++ ply_boot_splash_remove_pixel_display (state->boot_splash, display); ++} ++ ++static void ++on_text_display_added (state_t *state, ++ ply_text_display_t *display) ++{ ++ if (state->is_shown) ++ { ++ if (state->boot_splash == NULL) ++ { ++ ply_trace ("text display added before splash loaded, so loading splash now"); ++ show_splash (state); ++ } ++ else ++ { ++ ply_trace ("text display added after splash loaded, so attaching to splash"); ++ ply_boot_splash_add_text_display (state->boot_splash, display); ++ } ++ } ++} ++ ++static void ++on_text_display_removed (state_t *state, ++ ply_text_display_t *display) ++{ ++ if (state->boot_splash == NULL) ++ return; ++ ++ ply_boot_splash_remove_text_display (state->boot_splash, display); + } + + static void + load_devices (state_t *state, + ply_device_manager_flags_t flags) + { + state->device_manager = ply_device_manager_new (state->default_tty, flags); + state->local_console_terminal = ply_device_manager_get_default_terminal (state->device_manager); + +- ply_device_manager_watch_seats (state->device_manager, +- (ply_seat_added_handler_t) +- on_seat_added, +- (ply_seat_removed_handler_t) +- on_seat_removed, +- state); ++ ply_device_manager_watch_devices (state->device_manager, ++ (ply_keyboard_added_handler_t) ++ on_keyboard_added, ++ (ply_keyboard_removed_handler_t) ++ on_keyboard_removed, ++ (ply_pixel_display_added_handler_t) ++ on_pixel_display_added, ++ (ply_pixel_display_removed_handler_t) ++ on_pixel_display_removed, ++ (ply_text_display_added_handler_t) ++ on_text_display_added, ++ (ply_text_display_removed_handler_t) ++ on_text_display_removed, ++ state); + } + + static void + quit_splash (state_t *state) + { + ply_trace ("quiting splash"); + if (state->boot_splash != NULL) + { + ply_trace ("freeing splash"); + ply_boot_splash_free (state->boot_splash); + state->boot_splash = NULL; + } + + ply_device_manager_deactivate_keyboards (state->device_manager); + + if (state->local_console_terminal != NULL) + { + if (!state->should_retain_splash) + { + ply_trace ("Not retaining splash, so deallocating VT"); + ply_terminal_deactivate_vt (state->local_console_terminal); + ply_terminal_close (state->local_console_terminal); + } + } + + detach_from_running_session (state); + } + + static void + hide_splash (state_t *state) +@@ -1548,78 +1597,110 @@ on_enter (state_t *state, + node = ply_list_get_first_node (state->entry_triggers); + if (node) + { + ply_entry_trigger_t* entry_trigger = ply_list_node_get_data (node); + const char* reply_text = ply_buffer_get_bytes (state->entry_buffer); + ply_trigger_pull (entry_trigger->trigger, reply_text); + ply_buffer_clear (state->entry_buffer); + ply_list_remove_node (state->entry_triggers, node); + free (entry_trigger); + update_display (state); + } + else + { + for (node = ply_list_get_first_node (state->keystroke_triggers); node; + node = ply_list_get_next_node (state->keystroke_triggers, node)) + { + ply_keystroke_watch_t* keystroke_trigger = ply_list_node_get_data (node); + if (!keystroke_trigger->keys || strstr(keystroke_trigger->keys, "\n")) /* assume strstr works on utf8 arrays */ + { + ply_trigger_pull (keystroke_trigger->trigger, line); + ply_list_remove_node (state->keystroke_triggers, node); + free(keystroke_trigger); + return; + } + } + return; + } + } + + static void +-attach_splash_to_seats (state_t *state, +- ply_boot_splash_t *splash) ++attach_splash_to_devices (state_t *state, ++ ply_boot_splash_t *splash) + { + +- ply_list_t *seats; ++ ply_list_t *keyboards; ++ ply_list_t *pixel_displays; ++ ply_list_t *text_displays; + ply_list_node_t *node; + +- seats = ply_device_manager_get_seats (state->device_manager); +- node = ply_list_get_first_node (seats); ++ keyboards = ply_device_manager_get_keyboards (state->device_manager); ++ node = ply_list_get_first_node (keyboards); ++ while (node != NULL) ++ { ++ ply_keyboard_t *keyboard; ++ ply_list_node_t *next_node; ++ ++ keyboard = ply_list_node_get_data (node); ++ next_node = ply_list_get_next_node (keyboards, node); ++ ++ ply_boot_splash_set_keyboard (splash, keyboard); ++ ++ node = next_node; ++ } ++ ++ pixel_displays = ply_device_manager_get_pixel_displays (state->device_manager); ++ node = ply_list_get_first_node (pixel_displays); ++ while (node != NULL) ++ { ++ ply_pixel_display_t *pixel_display; ++ ply_list_node_t *next_node; ++ ++ pixel_display = ply_list_node_get_data (node); ++ next_node = ply_list_get_next_node (pixel_displays, node); ++ ++ ply_boot_splash_add_pixel_display (splash, pixel_display); ++ ++ node = next_node; ++ } ++ ++ text_displays = ply_device_manager_get_text_displays (state->device_manager); ++ node = ply_list_get_first_node (text_displays); + while (node != NULL) + { +- ply_seat_t *seat; ++ ply_text_display_t *text_display; + ply_list_node_t *next_node; + +- seat = ply_list_node_get_data (node); +- next_node = ply_list_get_next_node (seats, node); ++ text_display = ply_list_node_get_data (node); ++ next_node = ply_list_get_next_node (text_displays, node); + +- ply_boot_splash_attach_to_seat (splash, seat); ++ ply_boot_splash_add_text_display (splash, text_display); + + node = next_node; + } + } + + #ifdef PLY_ENABLE_SYSTEMD_INTEGRATION + static void + tell_systemd_to_print_details (state_t *state) + { + ply_trace ("telling systemd to start printing details"); + if (kill (1, SIGRTMIN + 20) < 0) + ply_trace ("could not tell systemd to print details: %m"); + } + + static void + tell_systemd_to_stop_printing_details (state_t *state) + { + ply_trace ("telling systemd to stop printing details"); + if (kill (1, SIGRTMIN + 21) < 0) + ply_trace ("could not tell systemd to stop printing details: %m"); + } + #endif + + static ply_boot_splash_t * + load_built_in_theme (state_t *state) + { + ply_boot_splash_t *splash; + bool is_loaded; + + ply_trace ("Loading built-in theme"); +@@ -1668,61 +1749,61 @@ load_theme (state_t *state, + ply_save_errno (); + ply_boot_splash_free (splash); + ply_restore_errno (); + return NULL; + } + + ply_trace ("attaching plugin to event loop"); + ply_boot_splash_attach_to_event_loop (splash, state->loop); + + ply_trace ("attaching progress to plugin"); + ply_boot_splash_attach_progress (splash, state->progress); + + return splash; + } + + static ply_boot_splash_t * + show_theme (state_t *state, + const char *theme_path) + { + ply_boot_splash_mode_t splash_mode; + ply_boot_splash_t *splash; + + if (theme_path != NULL) + splash = load_theme (state, theme_path); + else + splash = load_built_in_theme (state); + + if (splash == NULL) + return NULL; + +- attach_splash_to_seats (state, splash); ++ attach_splash_to_devices (state, splash); + ply_device_manager_activate_renderers (state->device_manager); + + if (state->mode == PLY_MODE_SHUTDOWN) + splash_mode = PLY_BOOT_SPLASH_MODE_SHUTDOWN; + else + splash_mode = PLY_BOOT_SPLASH_MODE_BOOT_UP; + + if (!ply_boot_splash_show (splash, splash_mode)) + { + ply_save_errno (); + ply_boot_splash_free (splash); + ply_restore_errno (); + return NULL; + } + + #ifdef PLY_ENABLE_SYSTEMD_INTEGRATION + if (state->is_attached) + tell_systemd_to_print_details (state); + #endif + + ply_device_manager_activate_keyboards (state->device_manager); + show_messages (state); + + return splash; + } + + static bool + attach_to_running_session (state_t *state) + { + ply_terminal_session_t *session; +-- +2.3.7 + + +From 8ae7a1af26bfdd367c2a926a0050e03db5dfb87e Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 24 Jul 2015 14:12:40 -0400 +Subject: [PATCH 5/8] device-manager: decouple local console from output device + +The code currently does a faulty heuristic to figure out which +drm device is associated with the tty. We shouldn't actually +even need an accurate association, so this commit just makes +sure the terminal gets used for the first device. +--- + src/libply-splash-core/ply-device-manager.c | 73 +++++++++-------------------- + 1 file changed, 21 insertions(+), 52 deletions(-) + +diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c +index c7568c1..b90a0f6 100644 +--- a/src/libply-splash-core/ply-device-manager.c ++++ b/src/libply-splash-core/ply-device-manager.c +@@ -70,87 +70,60 @@ struct _ply_device_manager + void *event_handler_data; + + uint32_t local_console_managed : 1; + uint32_t local_console_is_text : 1; + }; + + static void + detach_from_event_loop (ply_device_manager_t *manager) + { + assert (manager != NULL); + + manager->loop = NULL; + } + + static void + attach_to_event_loop (ply_device_manager_t *manager, + ply_event_loop_t *loop) + { + assert (manager != NULL); + assert (loop != NULL); + assert (manager->loop == NULL); + + manager->loop = loop; + + ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + manager); + } + + static bool +-device_is_for_local_console (ply_device_manager_t *manager, +- struct udev_device *device) +-{ +- const char *device_path; +- struct udev_device *bus_device; +- char *bus_device_path; +- const char *boot_vga; +- bool for_local_console; +- +- /* Look at the associated bus device to see if this card is the +- * card the kernel is using for its console. */ +- device_path = udev_device_get_syspath (device); +- asprintf (&bus_device_path, "%s/device", device_path); +- bus_device = udev_device_new_from_syspath (manager->udev_context, bus_device_path); +- +- boot_vga = udev_device_get_sysattr_value (bus_device, "boot_vga"); +- free (bus_device_path); +- +- if (boot_vga != NULL && strcmp (boot_vga, "1") == 0) +- for_local_console = true; +- else +- for_local_console = false; +- +- return for_local_console; +-} +- +-static bool + drm_device_in_use (ply_device_manager_t *manager, + const char *device_path) + { + ply_renderer_t *renderer; + + renderer = ply_hashtable_lookup (manager->renderers, (void *) device_path); + + return renderer != NULL; + } + + static bool + fb_device_has_drm_device (ply_device_manager_t *manager, + struct udev_device *fb_device) + { + struct udev_enumerate *card_matches; + struct udev_list_entry *card_entry; + const char *id_path; + bool has_drm_device = false; + + /* We want to see if the framebuffer is associated with a DRM-capable + * graphics card, if it is, we'll use the DRM device */ + card_matches = udev_enumerate_new (manager->udev_context); + udev_enumerate_add_match_is_initialized(card_matches); + udev_enumerate_add_match_parent (card_matches, udev_device_get_parent (fb_device)); + udev_enumerate_add_match_subsystem (card_matches, "drm"); + id_path = udev_device_get_property_value (fb_device, "ID_PATH"); + udev_enumerate_add_match_property (card_matches, "ID_PATH", id_path); + + ply_trace ("trying to find associated drm node for fb device (path: %s)", id_path); + +@@ -162,104 +135,105 @@ fb_device_has_drm_device (ply_device_manager_t *manager, + + if (card_entry != NULL) + { + struct udev_device *card_device = NULL; + const char *card_node; + const char *card_path; + + card_path = udev_list_entry_get_name (card_entry); + card_device = udev_device_new_from_syspath (manager->udev_context, card_path); + card_node = udev_device_get_devnode (card_device); + if (card_node != NULL && drm_device_in_use (manager, card_node)) + has_drm_device = true; + else + ply_trace ("no card node!"); + + udev_device_unref (card_device); + } + else + { + ply_trace ("no card entry!"); + } + + udev_enumerate_unref (card_matches); + return has_drm_device; + } + + static void + create_devices_for_udev_device (ply_device_manager_t *manager, + struct udev_device *device) + { +- bool for_local_console; + const char *device_path; +- ply_terminal_t *terminal = NULL; +- +- for_local_console = device_is_for_local_console (manager, device); +- +- ply_trace ("device is for local console: %s", for_local_console? "yes" : "no"); +- +- if (for_local_console) +- terminal = manager->local_console_terminal; + + device_path = udev_device_get_devnode (device); + + if (device_path != NULL) + { + const char *subsystem; ++ + ply_renderer_type_t renderer_type = PLY_RENDERER_TYPE_NONE; + + subsystem = udev_device_get_subsystem (device); + ply_trace ("device subsystem is %s", subsystem); + + if (subsystem != NULL && strcmp (subsystem, SUBSYSTEM_DRM) == 0) + { + ply_trace ("found DRM device %s", device_path); + renderer_type = PLY_RENDERER_TYPE_DRM; + } + else if (strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0) + { + ply_trace ("found frame buffer device %s", device_path); + if (!fb_device_has_drm_device (manager, device)) + { + renderer_type = PLY_RENDERER_TYPE_FRAME_BUFFER; + } + else + { + ply_trace ("ignoring, since there's a DRM device associated with it"); + } + } + + if (renderer_type != PLY_RENDERER_TYPE_NONE) +- create_devices_for_terminal_and_renderer_type (manager, +- device_path, +- terminal, +- renderer_type); ++ { ++ ply_terminal_t *terminal = NULL; ++ ++ if (!manager->local_console_managed) ++ { ++ terminal = manager->local_console_terminal; ++ } ++ ++ create_devices_for_terminal_and_renderer_type (manager, ++ device_path, ++ terminal, ++ renderer_type); ++ } + } + } + + static void + free_displays_for_renderer (ply_device_manager_t *manager, + ply_renderer_t *renderer) + { + ply_list_node_t *node; + + node = ply_list_get_first_node (manager->pixel_displays); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_pixel_display_t *display; + ply_renderer_t *display_renderer; + + display = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (manager->pixel_displays, node); + display_renderer = ply_pixel_display_get_renderer (display); + + if (display_renderer == renderer) + { + if (manager->pixel_display_removed_handler != NULL) + manager->pixel_display_removed_handler (manager->event_handler_data, display); + + ply_pixel_display_free (display); + ply_list_remove_node (manager->pixel_displays, node); + } + + node = next_node; +@@ -687,126 +661,121 @@ create_text_displays_for_terminal (ply_device_manager_t *manager, + + if (!ply_terminal_is_open (terminal)) + { + if (!ply_terminal_open (terminal)) + { + ply_trace ("could not add terminal %s: %m", + ply_terminal_get_name (terminal)); + return; + } + } + + ply_trace ("adding text display for terminal %s", + ply_terminal_get_name (terminal)); + + display = ply_text_display_new (terminal); + ply_list_append_data (manager->text_displays, display); + + if (manager->text_display_added_handler != NULL) + manager->text_display_added_handler (manager->event_handler_data, display); + } + + static void + create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, + const char *device_path, + ply_terminal_t *terminal, + ply_renderer_type_t renderer_type) + { + ply_renderer_t *renderer = NULL; + ply_keyboard_t *keyboard = NULL; + +- bool is_local_terminal = false; +- +- if (terminal != NULL && manager->local_console_terminal == terminal) +- is_local_terminal = true; ++ renderer = ply_hashtable_lookup (manager->renderers, (void *) device_path); + +- if (is_local_terminal && manager->local_console_managed) ++ if (renderer != NULL) + { +- ply_trace ("trying to create devices for local console when one already exists"); ++ ply_trace ("ignoring device %s since it's already managed", ++ device_path); + return; + } + + ply_trace ("creating devices for %s (renderer type: %u) (terminal: %s)", + device_path? : "", renderer_type, terminal? ply_terminal_get_name (terminal): "none"); + + if (renderer_type != PLY_RENDERER_TYPE_NONE) + { + renderer = ply_renderer_new (renderer_type, device_path, terminal); + + if (!ply_renderer_open (renderer)) + { + ply_trace ("could not open renderer for %s", device_path); + ply_renderer_free (renderer); + renderer = NULL; + if (renderer_type != PLY_RENDERER_TYPE_AUTO) + return; + } + } + + if (renderer != NULL) + { + keyboard = ply_keyboard_new_for_renderer (renderer); + ply_list_append_data (manager->keyboards, keyboard); + + if (manager->keyboard_added_handler != NULL) + manager->keyboard_added_handler (manager->event_handler_data, keyboard); + + create_pixel_displays_for_renderer (manager, renderer); + ply_hashtable_insert (manager->renderers, strdup (device_path), renderer); + } + else if (terminal != NULL) + { + keyboard = ply_keyboard_new_for_terminal (terminal); + ply_list_append_data (manager->keyboards, keyboard); + + if (manager->keyboard_added_handler != NULL) + manager->keyboard_added_handler (manager->event_handler_data, keyboard); + } + + if (terminal != NULL) + { + create_text_displays_for_terminal (manager, terminal); + +- if (is_local_terminal) ++ if (terminal == manager->local_console_terminal) + { +- manager->local_console_is_text = true; ++ manager->local_console_is_text = renderer == NULL; ++ manager->local_console_managed = true; + } + } + + if (keyboard != NULL) + { + ply_keyboard_watch_for_input (keyboard); + } +- +- if (is_local_terminal) +- manager->local_console_managed = true; +- + } + + static void + create_devices_for_terminal (const char *device_path, + ply_terminal_t *terminal, + ply_device_manager_t *manager) + { + create_devices_for_terminal_and_renderer_type (manager, + device_path, + terminal, + PLY_RENDERER_TYPE_NONE); + } + static bool + create_devices_from_terminals (ply_device_manager_t *manager) + { + bool has_serial_consoles; + + ply_trace ("checking for consoles"); + + if (manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES) + { + has_serial_consoles = false; + ply_trace ("ignoring all consoles but default console because explicitly told to."); + } + else + { + has_serial_consoles = add_consoles_from_file (manager, "/sys/class/tty/console/active"); + } + + if (has_serial_consoles) +-- +2.3.7 + + +From 595557cfde30b99fc9d1789b305c2f80a576c502 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 24 Jul 2015 16:23:00 -0400 +Subject: [PATCH 6/8] device-manager: force details if serial consoles are used + +it's better to skip trying to load the default splash rather than +relying on it failing and falling back. +--- + src/libply-splash-core/ply-device-manager.c | 9 +++++++++ + src/libply-splash-core/ply-device-manager.h | 1 + + src/main.c | 3 +++ + 3 files changed, 13 insertions(+) + +diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c +index b90a0f6..787e67c 100644 +--- a/src/libply-splash-core/ply-device-manager.c ++++ b/src/libply-splash-core/ply-device-manager.c +@@ -44,60 +44,61 @@ + static void create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, + const char *device_path, + ply_terminal_t *terminal, + ply_renderer_type_t renderer_type); + struct _ply_device_manager + { + ply_device_manager_flags_t flags; + ply_event_loop_t *loop; + ply_hashtable_t *terminals; + ply_hashtable_t *renderers; + ply_terminal_t *local_console_terminal; + ply_list_t *keyboards; + ply_list_t *text_displays; + ply_list_t *pixel_displays; + struct udev *udev_context; + struct udev_queue *udev_queue; + int udev_queue_fd; + ply_fd_watch_t *udev_queue_fd_watch; + struct udev_monitor *udev_monitor; + + ply_keyboard_added_handler_t keyboard_added_handler; + ply_keyboard_removed_handler_t keyboard_removed_handler; + ply_pixel_display_added_handler_t pixel_display_added_handler; + ply_pixel_display_removed_handler_t pixel_display_removed_handler; + ply_text_display_added_handler_t text_display_added_handler; + ply_text_display_removed_handler_t text_display_removed_handler; + void *event_handler_data; + + uint32_t local_console_managed : 1; + uint32_t local_console_is_text : 1; ++ uint32_t serial_consoles_detected : 1; + }; + + static void + detach_from_event_loop (ply_device_manager_t *manager) + { + assert (manager != NULL); + + manager->loop = NULL; + } + + static void + attach_to_event_loop (ply_device_manager_t *manager, + ply_event_loop_t *loop) + { + assert (manager != NULL); + assert (loop != NULL); + assert (manager->loop == NULL); + + manager->loop = loop; + + ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + manager); + } + + static bool + drm_device_in_use (ply_device_manager_t *manager, + const char *device_path) + { + ply_renderer_t *renderer; +@@ -754,60 +755,62 @@ create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager, + static void + create_devices_for_terminal (const char *device_path, + ply_terminal_t *terminal, + ply_device_manager_t *manager) + { + create_devices_for_terminal_and_renderer_type (manager, + device_path, + terminal, + PLY_RENDERER_TYPE_NONE); + } + static bool + create_devices_from_terminals (ply_device_manager_t *manager) + { + bool has_serial_consoles; + + ply_trace ("checking for consoles"); + + if (manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES) + { + has_serial_consoles = false; + ply_trace ("ignoring all consoles but default console because explicitly told to."); + } + else + { + has_serial_consoles = add_consoles_from_file (manager, "/sys/class/tty/console/active"); + } + + if (has_serial_consoles) + { + ply_trace ("serial consoles detected, managing them with details forced"); ++ manager->serial_consoles_detected = true; ++ + ply_hashtable_foreach (manager->terminals, + (ply_hashtable_foreach_func_t *) + create_devices_for_terminal, + manager); + return true; + } + + return false; + } + + static void + create_devices_from_udev (ply_device_manager_t *manager) + { + bool found_drm_device, found_fb_device; + + ply_trace ("Looking for devices from udev"); + + found_drm_device = create_devices_for_subsystem (manager, SUBSYSTEM_DRM); + found_fb_device = create_devices_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER); + + if (found_drm_device || found_fb_device) + return; + + ply_trace ("Creating non-graphical devices, since there's no suitable graphics hardware"); + create_devices_for_terminal_and_renderer_type (manager, + ply_terminal_get_name (manager->local_console_terminal), + manager->local_console_terminal, + PLY_RENDERER_TYPE_NONE); + } + +@@ -921,60 +924,66 @@ bool + ply_device_manager_has_displays (ply_device_manager_t *manager) + { + return ply_list_get_length (manager->pixel_displays) > 0 || + ply_list_get_length (manager->text_displays) > 0; + } + + ply_list_t * + ply_device_manager_get_keyboards (ply_device_manager_t *manager) + { + return manager->keyboards; + } + + ply_list_t * + ply_device_manager_get_pixel_displays (ply_device_manager_t *manager) + { + return manager->pixel_displays; + } + + ply_list_t * + ply_device_manager_get_text_displays (ply_device_manager_t *manager) + { + return manager->text_displays; + } + + ply_terminal_t * + ply_device_manager_get_default_terminal (ply_device_manager_t *manager) + { + return manager->local_console_terminal; + } + ++bool ++ply_device_manager_has_serial_consoles (ply_device_manager_t *manager) ++{ ++ return manager->serial_consoles_detected; ++} ++ + static void + activate_renderer (char *device_path, + ply_renderer_t *renderer, + ply_device_manager_t *manager) + { + ply_renderer_activate (renderer); + } + + void + ply_device_manager_activate_renderers (ply_device_manager_t *manager) + { + ply_trace ("activating renderers"); + ply_hashtable_foreach (manager->renderers, + (ply_hashtable_foreach_func_t *) + activate_renderer, + manager); + } + + static void + deactivate_renderer (char *device_path, + ply_renderer_t *renderer, + ply_device_manager_t *manager) + { + ply_renderer_deactivate (renderer); + } + + void + ply_device_manager_deactivate_renderers (ply_device_manager_t *manager) + { + ply_trace ("deactivating renderers"); +diff --git a/src/libply-splash-core/ply-device-manager.h b/src/libply-splash-core/ply-device-manager.h +index b628e41..558aabe 100644 +--- a/src/libply-splash-core/ply-device-manager.h ++++ b/src/libply-splash-core/ply-device-manager.h +@@ -26,45 +26,46 @@ + #include "ply-pixel-display.h" + #include "ply-renderer.h" + #include "ply-text-display.h" + + typedef enum + { + PLY_DEVICE_MANAGER_FLAGS_NONE = 0, + PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES = 1 << 0, + PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV = 1 << 1 + } ply_device_manager_flags_t; + + typedef struct _ply_device_manager ply_device_manager_t; + typedef void (* ply_keyboard_added_handler_t) (void *, ply_keyboard_t *); + typedef void (* ply_keyboard_removed_handler_t) (void *, ply_keyboard_t *); + typedef void (* ply_pixel_display_added_handler_t) (void *, ply_pixel_display_t *); + typedef void (* ply_pixel_display_removed_handler_t) (void *, ply_pixel_display_t *); + typedef void (* ply_text_display_added_handler_t) (void *, ply_text_display_t *); + typedef void (* ply_text_display_removed_handler_t) (void *, ply_text_display_t *); + + #ifndef PLY_HIDE_FUNCTION_DECLARATIONS + ply_device_manager_t *ply_device_manager_new (const char *default_tty, + ply_device_manager_flags_t flags); + void ply_device_manager_watch_devices (ply_device_manager_t *manager, + ply_keyboard_added_handler_t keyboard_added_handler, + ply_keyboard_removed_handler_t keyboard_removed_handler, + ply_pixel_display_added_handler_t pixel_display_added_handler, + ply_pixel_display_removed_handler_t pixel_display_removed_handler, + ply_text_display_added_handler_t text_display_added_handler, + ply_text_display_removed_handler_t text_display_removed_handler, + void *data); ++bool ply_device_manager_has_serial_consoles (ply_device_manager_t *manager); + bool ply_device_manager_has_displays (ply_device_manager_t *manager); + ply_list_t *ply_device_manager_get_keyboards (ply_device_manager_t *manager); + ply_list_t *ply_device_manager_get_pixel_displays (ply_device_manager_t *manager); + ply_list_t *ply_device_manager_get_text_displays (ply_device_manager_t *manager); + void ply_device_manager_free (ply_device_manager_t *manager); + void ply_device_manager_activate_keyboards (ply_device_manager_t *manager); + void ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager); + void ply_device_manager_activate_renderers (ply_device_manager_t *manager); + void ply_device_manager_deactivate_renderers (ply_device_manager_t *manager); + ply_terminal_t *ply_device_manager_get_default_terminal (ply_device_manager_t *manager); + + #endif + + #endif + /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ +diff --git a/src/main.c b/src/main.c +index ec46199..875dd1a 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -1086,60 +1086,63 @@ static void + on_text_display_removed (state_t *state, + ply_text_display_t *display) + { + if (state->boot_splash == NULL) + return; + + ply_boot_splash_remove_text_display (state->boot_splash, display); + } + + static void + load_devices (state_t *state, + ply_device_manager_flags_t flags) + { + state->device_manager = ply_device_manager_new (state->default_tty, flags); + state->local_console_terminal = ply_device_manager_get_default_terminal (state->device_manager); + + ply_device_manager_watch_devices (state->device_manager, + (ply_keyboard_added_handler_t) + on_keyboard_added, + (ply_keyboard_removed_handler_t) + on_keyboard_removed, + (ply_pixel_display_added_handler_t) + on_pixel_display_added, + (ply_pixel_display_removed_handler_t) + on_pixel_display_removed, + (ply_text_display_added_handler_t) + on_text_display_added, + (ply_text_display_removed_handler_t) + on_text_display_removed, + state); ++ ++ if (ply_device_manager_has_serial_consoles (state->device_manager)) ++ state->should_force_details = true; + } + + static void + quit_splash (state_t *state) + { + ply_trace ("quiting splash"); + if (state->boot_splash != NULL) + { + ply_trace ("freeing splash"); + ply_boot_splash_free (state->boot_splash); + state->boot_splash = NULL; + } + + ply_device_manager_deactivate_keyboards (state->device_manager); + + if (state->local_console_terminal != NULL) + { + if (!state->should_retain_splash) + { + ply_trace ("Not retaining splash, so deallocating VT"); + ply_terminal_deactivate_vt (state->local_console_terminal); + ply_terminal_close (state->local_console_terminal); + } + } + + detach_from_running_session (state); + } + + static void + hide_splash (state_t *state) +-- +2.3.7 + + +From 6c06eb9a42df75b637b7390ef60e06a3f6c7965c Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 28 Jul 2015 10:00:25 -0400 +Subject: [PATCH 7/8] animation,throbber: allow calling stop after animation is + stopped + +Right now if a user calls ply_throbber_stop or ply_animation_stop +after the animation is stopped things malfunction. In the case +of the throbber we end up never calling the stop completion handler +passed in, and in the case of the animation, we end up setting +some state that shouldn't be set. + +This commit checks if the animation and throbber objects are stopped, +and if so does the necessary steps to process the late stop request. +--- + src/libply-splash-graphics/ply-animation.c | 6 ++++++ + src/libply-splash-graphics/ply-throbber.c | 10 ++++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/src/libply-splash-graphics/ply-animation.c b/src/libply-splash-graphics/ply-animation.c +index bba8490..2f24812 100644 +--- a/src/libply-splash-graphics/ply-animation.c ++++ b/src/libply-splash-graphics/ply-animation.c +@@ -348,60 +348,66 @@ ply_animation_start (ply_animation_t *animation, + + ply_event_loop_watch_for_timeout (animation->loop, + 1.0 / FRAMES_PER_SECOND, + (ply_event_loop_timeout_handler_t) + on_timeout, animation); + + return true; + } + + static void + ply_animation_stop_now (ply_animation_t *animation) + { + animation->is_stopped = true; + + ply_trace ("stopping animation now"); + + if (animation->loop != NULL) + { + ply_event_loop_stop_watching_for_timeout (animation->loop, + (ply_event_loop_timeout_handler_t) + on_timeout, animation); + animation->loop = NULL; + } + + animation->display = NULL; + } + + void + ply_animation_stop (ply_animation_t *animation) + { ++ if (animation->is_stopped) ++ { ++ ply_trace ("animation already stopped, ignoring stop request"); ++ return; ++ } ++ + if (animation->stop_trigger == NULL) + { + ply_animation_stop_now (animation); + return; + } + + ply_trace ("stopping animation next time through the loop"); + animation->stop_requested = true; + } + + bool + ply_animation_is_stopped (ply_animation_t *animation) + { + return animation->is_stopped; + } + + void + ply_animation_draw_area (ply_animation_t *animation, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height) + { + ply_pixel_buffer_t * const * frames; + int number_of_frames; + int frame_index; + + if (animation->is_stopped) + return; +diff --git a/src/libply-splash-graphics/ply-throbber.c b/src/libply-splash-graphics/ply-throbber.c +index 42044ba..d4594b8 100644 +--- a/src/libply-splash-graphics/ply-throbber.c ++++ b/src/libply-splash-graphics/ply-throbber.c +@@ -320,60 +320,70 @@ ply_throbber_start (ply_throbber_t *throbber, + (ply_event_loop_timeout_handler_t) + on_timeout, throbber); + + return true; + } + + static void + ply_throbber_stop_now (ply_throbber_t *throbber) + { + throbber->is_stopped = true; + + ply_pixel_display_draw_area (throbber->display, + throbber->x, + throbber->y, + throbber->frame_area.width, + throbber->frame_area.height); + if (throbber->loop != NULL) + { + ply_event_loop_stop_watching_for_timeout (throbber->loop, + (ply_event_loop_timeout_handler_t) + on_timeout, throbber); + throbber->loop = NULL; + } + throbber->display = NULL; + } + + void + ply_throbber_stop (ply_throbber_t *throbber, + ply_trigger_t *stop_trigger) + { ++ if (throbber->is_stopped) ++ { ++ ply_trace ("throbber already stopped"); ++ if (stop_trigger != NULL) ++ { ++ ply_trace ("pulling stop trigger right away"); ++ ply_trigger_pull (stop_trigger, NULL); ++ } ++ return; ++ } + + if (stop_trigger == NULL) + { + ply_throbber_stop_now (throbber); + return; + } + + throbber->stop_trigger = stop_trigger; + } + + bool + ply_throbber_is_stopped (ply_throbber_t *throbber) + { + return throbber->is_stopped; + } + + void + ply_throbber_draw_area (ply_throbber_t *throbber, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height) + { + ply_pixel_buffer_t * const * frames; + + if (throbber->is_stopped) + return; + + frames = (ply_pixel_buffer_t * const *) ply_array_get_pointer_elements (throbber->frames); +-- +2.3.7 + +From 80e71304093c163e338168d27bfdb3552c9aa242 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 10 Aug 2015 10:11:32 -0400 +Subject: [PATCH 8/8] boot-splash: don't crash in free if module not loaded + +ply_boot_splash_free currently calls some code that depends +on a module being loaded. We call ply_boot_splash_free to +clean up the boot splash object if a module can't be loaded, +leading to crash. + +This commit addresses that issue by only calling the module +specific destruction code in ply_boot_splash_free in the case +where a module is loaded. + +https://bugs.freedesktop.org/show_bug.cgi?id=91590 +--- + src/libply-splash-core/ply-boot-splash.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/src/libply-splash-core/ply-boot-splash.c b/src/libply-splash-core/ply-boot-splash.c +index f7fc70f..664acc3 100644 +--- a/src/libply-splash-core/ply-boot-splash.c ++++ b/src/libply-splash-core/ply-boot-splash.c +@@ -383,70 +383,72 @@ remove_text_displays (ply_boot_splash_t *splash) + + ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows); + + splash->plugin_interface->remove_text_display (splash->plugin, display); + + node = next_node; + } + } + + void + ply_boot_splash_free (ply_boot_splash_t *splash) + { + ply_trace ("freeing splash"); + if (splash == NULL) + return; + + if (splash->loop != NULL) + { + if (splash->plugin_interface->on_boot_progress != NULL) + { + ply_event_loop_stop_watching_for_timeout (splash->loop, + (ply_event_loop_timeout_handler_t) + ply_boot_splash_update_progress, splash); + } + + ply_event_loop_stop_watching_for_exit (splash->loop, (ply_event_loop_exit_handler_t) + ply_boot_splash_detach_from_event_loop, + splash); + } + +- ply_boot_splash_unset_keyboard (splash); ++ if (splash->module_handle != NULL) ++ { ++ ply_boot_splash_unset_keyboard (splash); + +- remove_pixel_displays (splash); +- ply_list_free (splash->pixel_displays); ++ remove_pixel_displays (splash); ++ ply_list_free (splash->pixel_displays); + +- remove_text_displays (splash); +- ply_list_free (splash->text_displays); ++ remove_text_displays (splash); ++ ply_list_free (splash->text_displays); + +- if (splash->module_handle != NULL) +- ply_boot_splash_unload (splash); ++ ply_boot_splash_unload (splash); ++ } + + if (splash->idle_trigger != NULL) + ply_trigger_free (splash->idle_trigger); + + free (splash->theme_path); + free (splash->plugin_dir); + free (splash); + } + + static void + ply_boot_splash_update_progress (ply_boot_splash_t *splash) + { + double percentage=0.0; + double time=0.0; + + assert (splash != NULL); + + if (splash->progress) + { + percentage = ply_progress_get_percentage(splash->progress); + time = ply_progress_get_time(splash->progress); + } + + if (splash->plugin_interface->on_boot_progress != NULL) + splash->plugin_interface->on_boot_progress (splash->plugin, + time, + percentage); + + ply_event_loop_watch_for_timeout (splash->loop, + 1.0 / UPDATES_PER_SECOND, +-- +2.5.0 + diff --git a/SOURCES/fix-coldplug-detection.patch b/SOURCES/fix-coldplug-detection.patch new file mode 100644 index 0000000..162c816 --- /dev/null +++ b/SOURCES/fix-coldplug-detection.patch @@ -0,0 +1,81 @@ +From 3d38bbb09383a634c78722c7bf18a3e1a3f36647 Mon Sep 17 00:00:00 2001 +From: Frederic Crozat +Date: Thu, 19 Jun 2014 17:58:50 +0200 +Subject: [PATCH] libply-splash-core: also monitor for file removal in udev + directory + +Ensure plymouth detects coldplug completion with recent udev (>= 213). +--- + src/libply-splash-core/ply-device-manager.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c +index a7890d0..5766bcb 100644 +--- a/src/libply-splash-core/ply-device-manager.c ++++ b/src/libply-splash-core/ply-device-manager.c +@@ -780,61 +780,61 @@ on_udev_queue_changed (ply_device_manager_t *manager) + + ply_trace ("udev coldplug complete"); + ply_event_loop_stop_watching_fd (manager->loop, manager->udev_queue_fd_watch); + manager->udev_queue_fd_watch = NULL; + udev_queue_unref (manager->udev_queue); + + close (manager->udev_queue_fd); + manager->udev_queue_fd = -1; + + manager->udev_queue = NULL; + + create_seats_from_udev (manager); + } + + static void + watch_for_coldplug_completion (ply_device_manager_t *manager) + { + int fd; + int result; + + manager->udev_queue = udev_queue_new (manager->udev_context); + + if (udev_queue_get_queue_is_empty (manager->udev_queue)) + { + ply_trace ("udev coldplug completed already "); + create_seats_from_udev (manager); + return; + } + + fd = inotify_init1 (IN_CLOEXEC); +- result = inotify_add_watch (fd, "/run/udev", IN_MOVED_TO); ++ result = inotify_add_watch (fd, "/run/udev", IN_MOVED_TO| IN_DELETE); + + if (result < 0) + { + ply_trace ("could not watch for udev to show up: %m"); + close (fd); + + create_fallback_seat (manager); + return; + } + + manager->udev_queue_fd = fd; + + manager->udev_queue_fd_watch = ply_event_loop_watch_fd (manager->loop, + fd, + PLY_EVENT_LOOP_FD_STATUS_HAS_DATA, + (ply_event_handler_t) + on_udev_queue_changed, + NULL, + manager); + + } + + void + ply_device_manager_watch_seats (ply_device_manager_t *manager, + ply_seat_added_handler_t seat_added_handler, + ply_seat_removed_handler_t seat_removed_handler, + void *data) + { + bool done_with_initial_seat_setup; + +-- +2.3.7 + diff --git a/SOURCES/ship-label-plugin-in-initrd.patch b/SOURCES/ship-label-plugin-in-initrd.patch new file mode 100644 index 0000000..f2284d6 --- /dev/null +++ b/SOURCES/ship-label-plugin-in-initrd.patch @@ -0,0 +1,146 @@ +From 68f14b8a0163d688ca36541bc1e28173b0b62317 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 20 Jul 2015 09:24:27 -0400 +Subject: [PATCH] populate-initrd: ship label plugin / font in initrd + +Some customers require showing text in the initrd, so +this commit goes ahead and ships label.so (and all its +dependencies) and one font in the initrd. +--- + scripts/plymouth-populate-initrd.in | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/scripts/plymouth-populate-initrd.in b/scripts/plymouth-populate-initrd.in +index d25ab07..da55318 100755 +--- a/scripts/plymouth-populate-initrd.in ++++ b/scripts/plymouth-populate-initrd.in +@@ -1,47 +1,48 @@ + #!/bin/bash + # + # inst bits ruthlessly and viciously stolen from dracut + + [ -z "$DESTDIR" ] || exit 0 + + [ -z "$PLYMOUTH_LIBEXECDIR" ] && PLYMOUTH_LIBEXECDIR="@PLYMOUTH_LIBEXECDIR@" + [ -z "$PLYMOUTH_DATADIR" ] && PLYMOUTH_DATADIR="@PLYMOUTH_DATADIR@" + [ -z "$PLYMOUTH_PLUGIN_PATH" ] && PLYMOUTH_PLUGIN_PATH="$(plymouth --get-splash-plugin-path)" + [ -z "$PLYMOUTH_LOGO_FILE" ] && PLYMOUTH_LOGO_FILE="@PLYMOUTH_LOGO_FILE@" + [ -n "$PLYMOUTH_THEME_NAME" ] && THEME_OVERRIDE=1 + [ -z "$PLYMOUTH_THEME_NAME" ] && PLYMOUTH_THEME_NAME=$(plymouth-set-default-theme) + [ -z "$PLYMOUTH_CONFDIR" ] && PLYMOUTH_CONFDIR="@PLYMOUTH_CONF_DIR@" + [ -z "$PLYMOUTH_POLICYDIR" ] && PLYMOUTH_POLICYDIR="@PLYMOUTH_POLICY_DIR@" + [ -z "$PLYMOUTH_DAEMON_PATH" ] && PLYMOUTH_DAEMON_PATH="@PLYMOUTH_DAEMON_DIR@/plymouthd" + [ -z "$PLYMOUTH_CLIENT_PATH" ] && PLYMOUTH_CLIENT_PATH="@PLYMOUTH_CLIENT_DIR@/plymouth" + [ -z "$SYSTEMD_UNIT_DIR" ] && SYSTEMD_UNIT_DIR="@SYSTEMD_UNIT_DIR@" ++[ -z "$SUPPORTED_LANGUAGES" ] && SUPPORTED_LANGUAGES="pt fr de it ru es en zh ja ko zh as bn gu hi kn ml mr or pa ta te" + + # Generic substring function. If $2 is in $1, return 0. + strstr() { [ "${1#*$2*}" != "$1" ]; } + + ddebug() { + [ "$verbose" = "true" ] && echo "$@" + } + + # normalize_path + # Prints the normalized path, where it removes any duplicated + # and trailing slashes. + # Example: + # $ normalize_path ///test/test// + # /test/test + normalize_path() { + shopt -q -s extglob + set -- "${1//+(\/)//}" + shopt -q -u extglob + echo "${1%/}" + } + + # convert_abs_rel + # Prints the relative path, when creating a symlink to from . + # Example: + # $ convert_abs_rel /usr/bin/test /bin/test-2 + # ../../bin/test-2 + # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test + convert_abs_rel() { + local __current __absolute __abssize __cursize __newpath + local -i __i __level +@@ -387,59 +388,77 @@ inst ${PLYMOUTH_CONFDIR}/plymouthd.conf $INITRDDIR + if [ -z "$PLYMOUTH_THEME_NAME" ]; then + echo "No default plymouth plugin is set" > /dev/stderr + exit 1 + fi + + if [ $THEME_OVERRIDE ]; then + conf=$INITRDDIR/${PLYMOUTH_CONFDIR}/plymouthd.conf + echo "modifying plymouthd.conf: Theme=$PLYMOUTH_THEME_NAME" > /dev/stderr + sed -i "s/^ *Theme *=.*/# theme modified by plymouth-populate-initrd\nTheme=$PLYMOUTH_THEME_NAME/" $conf + fi + + PLYMOUTH_MODULE_NAME=$(grep "ModuleName *= *" ${PLYMOUTH_DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME}/${PLYMOUTH_THEME_NAME}.plymouth | sed 's/ModuleName *= *//') + + if [ ! -f ${PLYMOUTH_PLUGIN_PATH}/${PLYMOUTH_MODULE_NAME}.so ]; then + echo "The default plymouth plugin (${PLYMOUTH_MODULE_NAME}) doesn't exist" > /dev/stderr + exit 1 + fi + + inst ${PLYMOUTH_PLUGIN_PATH}/${PLYMOUTH_MODULE_NAME}.so $INITRDDIR + + [ -f "${PLYMOUTH_PLUGIN_PATH}/renderers/drm.so" ] && inst ${PLYMOUTH_PLUGIN_PATH}/renderers/drm.so $INITRDDIR + inst ${PLYMOUTH_PLUGIN_PATH}/renderers/frame-buffer.so $INITRDDIR + + if [ -d ${PLYMOUTH_DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME} ]; then + for x in ${PLYMOUTH_DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME}/* ; do + [ ! -f "$x" ] && continue + inst $x $INITRDDIR + done + fi + ++fonts="" ++needs_graphics="$(find ${INITRDDIR} -name 'libply-splash-graphics.so*' -print -quit | grep -q libply-splash-graphics.so && echo -n 1)" ++ ++if [ -n "$needs_graphics" ]; then ++ for lang in $SUPPORTED_LANGUAGES; do ++ font=$(fc-match "":lang="$lang" file | awk -F= '{ print $2}') ++ echo $fonts | grep -q "$font" && continue ++ fonts="$fonts $font" ++ done ++ ++ if [ -n "$fonts" ]; then ++ inst ${PLYMOUTH_PLUGIN_PATH}/label.so $INITRDDIR ++ for font in $fonts; do ++ inst $font $INITRDDIR ++ done ++ fi ++fi ++ + if [ -L ${PLYMOUTH_DATADIR}/plymouth/themes/default.plymouth ]; then + cp -a ${PLYMOUTH_DATADIR}/plymouth/themes/default.plymouth $INITRDDIR${PLYMOUTH_DATADIR}/plymouth/themes + fi + + if [ -n "$SYSTEMD_UNIT_DIR" -a -d "$SYSTEMD_UNIT_DIR" ]; then + inst $SYSTEMD_UNIT_DIR/systemd-ask-password-plymouth.path $INITRDDIR + inst $SYSTEMD_UNIT_DIR/systemd-ask-password-plymouth.service $INITRDDIR + + inst $SYSTEMD_UNIT_DIR/plymouth-switch-root.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/plymouth-start.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/plymouth-quit.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/plymouth-quit-wait.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/plymouth-reboot.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/plymouth-kexec.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/plymouth-poweroff.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/plymouth-halt.service $INITRDDIR + + inst $SYSTEMD_UNIT_DIR/initrd-switch-root.target.wants/plymouth-switch-root.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/initrd-switch-root.target.wants/plymouth-start.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/sysinit.target.wants/plymouth-start.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/multi-user.target.wants/plymouth-quit.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/multi-user.target.wants/plymouth-quit-wait.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/reboot.target.wants/plymouth-reboot.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/kexec.target.wants/plymouth-kexec.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/poweroff.target.wants/plymouth-poweroff.service $INITRDDIR + inst $SYSTEMD_UNIT_DIR/halt.target.wants/plymouth-halt.service $INITRDDIR + fi + + # vim:ts=8:sw=4:sts=4:et +-- +2.3.7 + diff --git a/SPECS/plymouth.spec b/SPECS/plymouth.spec index 6f20f37..a2a7ea1 100644 --- a/SPECS/plymouth.spec +++ b/SPECS/plymouth.spec @@ -7,7 +7,7 @@ Summary: Graphical Boot Animation and Logger Name: plymouth Version: 0.8.9 -Release: 0.13.20140113%{?dist} +Release: 0.24.20140113%{?dist} License: GPLv2+ Group: System Environment/Base Source0: http://freedesktop.org/software/plymouth/releases/%{name}-%{version}.tar.bz2 @@ -48,6 +48,11 @@ Patch7: fix-ask-password-race.patch Patch8: serial-console-fixes.patch Patch9: fix-init-bin-sh.patch Patch10: resize-proc-cmdline-buffer.patch +Patch11: cursor-fix.patch +Patch12: ship-label-plugin-in-initrd.patch +Patch13: fix-coldplug-detection.patch +Patch14: ensure-output-gets-terminal.patch +Patch15: activate-new-renderers.patch Patch99: colors.patch %description @@ -226,7 +231,7 @@ Provides: plymouth(system-theme) = %{version}-%{release} %description theme-charge This package contains the "charge" boot splash theme for -Plymouth. It is the default theme for CentOS Linux. +Plymouth. It is the default theme for Red Hat Enterprise Linux. %package plugin-script Summary: Plymouth "script" plugin @@ -275,6 +280,11 @@ Plymouth. It features a small spinner on a dark background. %patch8 -p1 -b .serial-console-fixes %patch9 -p1 -b .fix-init-bin-sh %patch10 -p1 -b .resize-proc-cmdline-buffer +%patch11 -p1 -b .cursor-fix +%patch12 -p1 -b .ship-label-plugin-in-initrd +%patch13 -p1 -b .fix-coldplug-detection +%patch14 -p1 -b .ensure-output-gets-terminal +%patch15 -p1 -b .activate-new-renderers %patch99 -p1 -b .colors # Change the default theme @@ -539,8 +549,57 @@ fi %defattr(-, root, root) %changelog -* Mon Mar 9 2015 Johnny Hughes 0.8.9-0.13.20140113 -- Roll in Branding Change in the SPEC +* Fri Oct 23 2015 Ray Strode 0.8.9-0.24.20140113 +- Fix text plugins in the same way we fixed pixel plugins + Related: #1260705 + Resolves: #1265646 + +* Fri Oct 09 2015 Ray Strode 0.8.9-0.23.20140113 +- Fix details plugin race + Related: #1260705 + Resolves: 1265646 + +* Thu Sep 24 2015 Ray Strode 0.8.9-0.22.20140113 +- Fix password prompt on some machines + Resolves: #1260705 + +* Tue Aug 11 2015 Ray Strode 0.8.9-0.21.20140113 +- Fix crash on minimal install + Related: #1159160 + +* Tue Aug 04 2015 Ray Strode 0.8.9-0.20.20140113 +- Fix crash on s390 + Resolves: 1250171 + Related: #1244858 + +* Tue Jul 28 2015 Ray Strode 0.8.9-0.19.20140113 +- Fix infinite loop at shutdown + Related: #1244858 + Resolves: 1243793 + +* Fri Jul 24 2015 Ray Strode 0.8.9-0.18.20140113 +- Don't instantiate drm renderer twice on some boots + Related: #1097174 1244858 + +* Fri Jul 24 2015 Ray Strode 0.8.9-0.17.20140113 +- Fix up last commit to ensure serial consoles force details mode + Related: #1097174 1244858 + +* Fri Jul 24 2015 Ray Strode 0.8.9-0.16.20140113 +- Ensure graphical special gets terminal even if drm driver isn't + boot_vga (more fixes for hyper-v) + Related: #1097174 1244858 + +* Mon Jul 20 2015 Ray Strode 0.8.9-0.15.20140113 +- Ship label plugin in initrd + Resolves: #801932 +- Backport udev queue detection fix which may help missing password + prompt on hyper-v + Related: #1097174 1244858 + +* Fri Jul 03 2015 Ray Strode 0.8.9-0.14.20140113 +- Fix hidden cursor after boot up on hyper-v + Resolves: #1097174 * Fri Oct 10 2014 Ray Strode 0.8.9-0.13.20140113 - Resize /proc/cmdline buffer to quash coverity message