mirror of
https://gitlab.freedesktop.org/plymouth/plymouth.git
synced 2026-05-07 04:58:00 +02:00
Merge branch 'parsekmsg' into 'main'
Support for displaying logs from /dev/kmsg and the console on the screen, instead of relying on the text on the VT See merge request plymouth/plymouth!224
This commit is contained in:
commit
44a2c8e452
23 changed files with 3924 additions and 123 deletions
|
|
@ -29,7 +29,7 @@ find -name '*.[ch]' -exec git diff -- {} \; >> before
|
|||
|
||||
interdiff -B --no-revert-omitted before after > diff
|
||||
|
||||
if [ -n "$(cat diff)" ]; then
|
||||
if [ -n "$(cat diff | grep -vE '^only in patch[12]:')" ]; then
|
||||
echo "Uncrustify found style abnormalities" 2>&1
|
||||
cat diff
|
||||
exit 1
|
||||
|
|
|
|||
|
|
@ -545,6 +545,35 @@ fi
|
|||
PLYMOUTH_MODULE_NAME=$(grep "ModuleName *= *" ${PLYMOUTH_SYSROOT}${PLYMOUTH_THEME_DIR}/${PLYMOUTH_THEME_NAME}.plymouth | sed 's/ModuleName *= *//')
|
||||
PLYMOUTH_IMAGE_DIR=$(grep "ImageDir *= *" ${PLYMOUTH_SYSROOT}${PLYMOUTH_THEME_DIR}/${PLYMOUTH_THEME_NAME}.plymouth | sed 's/ImageDir *= *//')
|
||||
|
||||
|
||||
PLYMOUTH_FONT_PATH=""
|
||||
PLYMOUTH_FONT=$(grep "\bFont *= *" ${PLYMOUTH_SYSROOT}${PLYMOUTH_THEME_DIR}/${PLYMOUTH_THEME_NAME}.plymouth | sed 's/Font *= *//' | head -1)
|
||||
if [ ! -z "$PLYMOUTH_FONT" ]; then
|
||||
PLYMOUTH_FONT_PATH=$(fc-match -f %{file} "$PLYMOUTH_FONT")
|
||||
if [ ! -z "$PLYMOUTH_FONT_PATH" ]; then
|
||||
inst "$PLYMOUTH_FONT_PATH" $INITRDDIR
|
||||
fi
|
||||
fi
|
||||
|
||||
PLYMOUTH_TITLE_FONT_PATH=""
|
||||
PLYMOUTH_TITLE_FONT=$(grep "\bTitleFont *= *" ${PLYMOUTH_SYSROOT}${PLYMOUTH_THEME_DIR}/${PLYMOUTH_THEME_NAME}.plymouth | sed 's/TitleFont *= *//' | head -1)
|
||||
if [ ! -z "$PLYMOUTH_TITLE_FONT" ]; then
|
||||
PLYMOUTH_TITLE_FONT_PATH=$(fc-match -f %{file} "$PLYMOUTH_TITLE_FONT")
|
||||
if [ ! -z "$PLYMOUTH_TITLE_FONT_PATH" ]; then
|
||||
inst "$PLYMOUTH_TITLE_FONT_PATH" $INITRDDIR
|
||||
fi
|
||||
fi
|
||||
|
||||
PLYMOUTH_MONOSPACE_FONT_PATH=""
|
||||
PLYMOUTH_MONOSPACE_FONT=$(grep "\bMonospaceFont *= *" ${PLYMOUTH_SYSROOT}${PLYMOUTH_THEME_DIR}/${PLYMOUTH_THEME_NAME}.plymouth | sed 's/MonospaceFont *= *//' | head -1)
|
||||
if [ ! -z "$PLYMOUTH_MONOSPACE_FONT" ]; then
|
||||
PLYMOUTH_MONOSPACE_FONT_PATH=$(fc-match -f %{file} "$PLYMOUTH_MONOSPACE_FONT")
|
||||
if [ ! -z "$PLYMOUTH_MONOSPACE_FONT_PATH" ]; then
|
||||
inst "$PLYMOUTH_MONOSPACE_FONT_PATH" $INITRDDIR
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -f ${PLYMOUTH_SYSROOT}${PLYMOUTH_PLUGIN_PATH}/${PLYMOUTH_MODULE_NAME}.so ]; then
|
||||
echo "The default plymouth plugin (${PLYMOUTH_MODULE_NAME}) doesn't exist" >&2
|
||||
exit 1
|
||||
|
|
@ -563,13 +592,17 @@ if [ "${PLYMOUTH_IMAGE_DIR}" != "${PLYMOUTH_THEME_DIR}" -a -d "${PLYMOUTH_SYSROO
|
|||
inst_recur "${PLYMOUTH_IMAGE_DIR}"
|
||||
fi
|
||||
|
||||
DefaultFont=$(fc-match -f %{file})
|
||||
inst "$DefaultFont" $INITRDDIR
|
||||
DefaultMonospaceFont=$(fc-match -f %{file} monospace)
|
||||
inst "$DefaultMonospaceFont" $INITRDDIR
|
||||
|
||||
if [ -f "${PLYMOUTH_PLUGIN_PATH}/label-freetype.so" ]; then
|
||||
inst ${PLYMOUTH_PLUGIN_PATH}/label-freetype.so $INITRDDIR
|
||||
font=$(fc-match -f %{file})
|
||||
inst "$font" $INITRDDIR
|
||||
# The label-freetype plugin expects it at this location
|
||||
mkdir -p $INITRDDIR/usr/share/fonts
|
||||
ln -s "$font" $INITRDDIR/usr/share/fonts/Plymouth.ttf
|
||||
ln -s "$DefaultFont" $INITRDDIR/usr/share/fonts/Plymouth.ttf
|
||||
ln -s "$DefaultMonospaceFont" $INITRDDIR/usr/share/fonts/Plymouth-monospace.ttf
|
||||
fi
|
||||
|
||||
if [ -L ${PLYMOUTH_SYSROOT}${PLYMOUTH_DATADIR}/plymouth/themes/default.plymouth ]; then
|
||||
|
|
|
|||
|
|
@ -2,11 +2,14 @@ libply_splash_core_sources = files(
|
|||
'ply-boot-splash.c',
|
||||
'ply-device-manager.c',
|
||||
'ply-input-device.c',
|
||||
'ply-kmsg-reader.c',
|
||||
'ply-keyboard.c',
|
||||
'ply-pixel-buffer.c',
|
||||
'ply-pixel-display.c',
|
||||
'ply-renderer.c',
|
||||
'ply-rich-text.c',
|
||||
'ply-terminal.c',
|
||||
'ply-terminal-emulator.c',
|
||||
'ply-text-display.c',
|
||||
'ply-text-progress-bar.c',
|
||||
'ply-text-step-bar.c',
|
||||
|
|
@ -54,12 +57,15 @@ libply_splash_core_headers = files(
|
|||
'ply-boot-splash.h',
|
||||
'ply-device-manager.h',
|
||||
'ply-input-device.h',
|
||||
'ply-kmsg-reader.h',
|
||||
'ply-keyboard.h',
|
||||
'ply-pixel-buffer.h',
|
||||
'ply-pixel-display.h',
|
||||
'ply-renderer-plugin.h',
|
||||
'ply-renderer.h',
|
||||
'ply-rich-text.h',
|
||||
'ply-terminal.h',
|
||||
'ply-terminal-emulator.h',
|
||||
'ply-text-display.h',
|
||||
'ply-text-progress-bar.h',
|
||||
'ply-text-step-bar.h',
|
||||
|
|
|
|||
236
src/libply-splash-core/ply-kmsg-reader.c
Normal file
236
src/libply-splash-core/ply-kmsg-reader.c
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
/* ply-kmsg-reader.c - kernel log message reader
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ply-list.h"
|
||||
#include "ply-kmsg-reader.h"
|
||||
#include "ply-terminal-emulator.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-utils.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef LOG_LINE_MAX
|
||||
#define LOG_LINE_MAX 8192
|
||||
#endif
|
||||
|
||||
#define from_hex(c) (isdigit (c) ? c - '0' : tolower (c) - 'a' + 10)
|
||||
|
||||
size_t
|
||||
unhexmangle_to_buffer (const char *s,
|
||||
char *buf,
|
||||
size_t len)
|
||||
{
|
||||
size_t sz = 0;
|
||||
const char *buf0 = buf;
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
|
||||
while (*s && sz < len - 1) {
|
||||
if (*s == '\\' && sz + 3 < len - 1 && s[1] == 'x' &&
|
||||
isxdigit (s[2]) && isxdigit (s[3])) {
|
||||
*buf++ = from_hex (s[2]) << 4 | from_hex (s[3]);
|
||||
s += 4;
|
||||
sz += 4;
|
||||
} else {
|
||||
*buf++ = *s++;
|
||||
sz++;
|
||||
}
|
||||
}
|
||||
*buf = '\0';
|
||||
return buf - buf0 + 1;
|
||||
}
|
||||
|
||||
int
|
||||
handle_kmsg_message (ply_kmsg_reader_t *kmsg_reader,
|
||||
int fd)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
char read_buffer[LOG_LINE_MAX] = "";
|
||||
int current_log_level = LOG_ERR, default_log_level = LOG_WARNING;
|
||||
|
||||
ply_get_kmsg_log_levels (¤t_log_level,
|
||||
&default_log_level);
|
||||
|
||||
bytes_read = read (fd, read_buffer, sizeof(read_buffer) - 1);
|
||||
if (bytes_read > 0) {
|
||||
ply_terminal_style_attributes_t bold_enabled = PLY_TERMINAL_ATTRIBUTE_NO_BOLD;
|
||||
ply_terminal_color_t color = PLY_TERMINAL_ATTRIBUTE_FOREGROUND_COLOR_OFFSET + PLY_TERMINAL_COLOR_DEFAULT;
|
||||
char *fields, *field_prefix, *field_sequence, *field_timestamp, *message, *message_substr, *msgptr, *saveptr, *format_begin, *new_message;
|
||||
int prefix, priority, facility;
|
||||
uint64_t sequence;
|
||||
unsigned long long timestamp;
|
||||
kmsg_message_t *kmsg_message;
|
||||
|
||||
fields = strtok_r (read_buffer, ";", &message);
|
||||
|
||||
/* Messages end in \n, any following lines are machine readable. Actual multiline messages are expanded with unhexmangle_to_buffer */
|
||||
msgptr = strchr (message, '\n');
|
||||
if (*msgptr && *msgptr != '\n')
|
||||
msgptr--;
|
||||
|
||||
unhexmangle_to_buffer (message, (char *) message, msgptr - message + 1);
|
||||
|
||||
field_prefix = strtok_r (fields, ",", &fields);
|
||||
field_sequence = strtok_r (fields, ",", &fields);
|
||||
field_timestamp = strtok_r (fields, ",", &fields);
|
||||
|
||||
prefix = atoi (field_prefix);
|
||||
sequence = strtoull (field_sequence, NULL, 0);
|
||||
timestamp = strtoull (field_timestamp, NULL, 0);
|
||||
|
||||
if (prefix > 0) {
|
||||
priority = LOG_PRI (prefix);
|
||||
facility = LOG_FAC (prefix);
|
||||
} else {
|
||||
priority = default_log_level;
|
||||
facility = LOG_USER;
|
||||
}
|
||||
|
||||
if (priority > current_log_level)
|
||||
return 0;
|
||||
|
||||
if (priority < LOG_ALERT)
|
||||
bold_enabled = PLY_TERMINAL_ATTRIBUTE_BOLD;
|
||||
|
||||
switch (priority) {
|
||||
case LOG_EMERG:
|
||||
case LOG_ALERT:
|
||||
case LOG_CRIT:
|
||||
case LOG_ERR:
|
||||
color = PLY_TERMINAL_ATTRIBUTE_FOREGROUND_COLOR_OFFSET + PLY_TERMINAL_COLOR_RED;
|
||||
break;
|
||||
case LOG_WARNING:
|
||||
color = PLY_TERMINAL_ATTRIBUTE_FOREGROUND_COLOR_OFFSET + PLY_TERMINAL_COLOR_BROWN;
|
||||
break;
|
||||
case LOG_NOTICE:
|
||||
color = PLY_TERMINAL_ATTRIBUTE_FOREGROUND_COLOR_OFFSET + PLY_TERMINAL_COLOR_GREEN;
|
||||
break;
|
||||
}
|
||||
asprintf (&format_begin, "\033[0;%i;%im", bold_enabled, color);
|
||||
|
||||
message_substr = strtok_r (message, "\n", &saveptr);
|
||||
while (message_substr != NULL) {
|
||||
kmsg_message = calloc (1, sizeof(kmsg_message_t));
|
||||
|
||||
kmsg_message->priority = priority;
|
||||
kmsg_message->facility = facility;
|
||||
kmsg_message->sequence = sequence;
|
||||
kmsg_message->timestamp = timestamp;
|
||||
|
||||
asprintf (&new_message, "%s%s%s", format_begin, message_substr, "\033[0m");
|
||||
kmsg_message->message = strndup (new_message, strlen (new_message));
|
||||
|
||||
ply_trigger_pull (kmsg_reader->kmsg_trigger, kmsg_message);
|
||||
ply_list_append_data (kmsg_reader->kmsg_messages, kmsg_message);
|
||||
free (new_message);
|
||||
|
||||
message_substr = strtok_r (NULL, "\n", &saveptr);
|
||||
}
|
||||
free (format_begin);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
ply_event_loop_stop_watching_fd (ply_event_loop_get_default (), kmsg_reader->fd_watch);
|
||||
close (kmsg_reader->kmsg_fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ply_kmsg_reader_t *
|
||||
ply_kmsg_reader_new (void)
|
||||
{
|
||||
ply_kmsg_reader_t *kmsg_reader = calloc (1, sizeof(ply_kmsg_reader_t));
|
||||
kmsg_reader->kmsg_trigger = ply_trigger_new (NULL);
|
||||
kmsg_reader->kmsg_messages = ply_list_new ();
|
||||
|
||||
return kmsg_reader;
|
||||
}
|
||||
|
||||
void
|
||||
ply_kmsg_message_free (kmsg_message_t *kmsg_message)
|
||||
{
|
||||
if (kmsg_message == NULL)
|
||||
return;
|
||||
|
||||
free (kmsg_message->message);
|
||||
free (kmsg_message);
|
||||
}
|
||||
|
||||
void
|
||||
ply_kmsg_reader_free (ply_kmsg_reader_t *kmsg_reader)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
kmsg_message_t *kmsg_message;
|
||||
|
||||
if (kmsg_reader == NULL)
|
||||
return;
|
||||
|
||||
ply_list_foreach (kmsg_reader->kmsg_messages, node) {
|
||||
kmsg_message = ply_list_node_get_data (node);
|
||||
ply_kmsg_message_free (kmsg_message);
|
||||
}
|
||||
|
||||
ply_trigger_free (kmsg_reader->kmsg_trigger);
|
||||
free (kmsg_reader);
|
||||
}
|
||||
|
||||
void
|
||||
ply_kmsg_reader_start (ply_kmsg_reader_t *kmsg_reader)
|
||||
{
|
||||
kmsg_reader->kmsg_fd = open ("/dev/kmsg", O_RDWR | O_NONBLOCK);
|
||||
if (kmsg_reader->kmsg_fd < 0)
|
||||
return;
|
||||
|
||||
kmsg_reader->fd_watch = ply_event_loop_watch_fd (ply_event_loop_get_default (), kmsg_reader->kmsg_fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
|
||||
(ply_event_handler_t) handle_kmsg_message,
|
||||
NULL,
|
||||
kmsg_reader);
|
||||
}
|
||||
|
||||
void
|
||||
ply_kmsg_reader_stop (ply_kmsg_reader_t *kmsg_reader)
|
||||
{
|
||||
if (kmsg_reader->kmsg_fd < 0)
|
||||
return;
|
||||
|
||||
ply_event_loop_stop_watching_fd (ply_event_loop_get_default (),
|
||||
kmsg_reader->fd_watch);
|
||||
kmsg_reader->fd_watch = NULL;
|
||||
|
||||
close (kmsg_reader->kmsg_fd);
|
||||
kmsg_reader->kmsg_fd = -1;
|
||||
}
|
||||
|
||||
void
|
||||
ply_kmsg_reader_watch_for_messages (ply_kmsg_reader_t *kmsg_reader,
|
||||
ply_kmsg_reader_message_handler_t message_handler,
|
||||
void *user_data)
|
||||
{
|
||||
ply_trigger_add_handler (kmsg_reader->kmsg_trigger,
|
||||
(ply_trigger_handler_t)
|
||||
message_handler,
|
||||
user_data);
|
||||
}
|
||||
64
src/libply-splash-core/ply-kmsg-reader.h
Normal file
64
src/libply-splash-core/ply-kmsg-reader.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* ply-kmsg-reader.h - kernel log message reader
|
||||
*
|
||||
* 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_KMSG_READER_H
|
||||
#define PLY_KMSG_READER_H
|
||||
|
||||
#include "ply-list.h"
|
||||
#include "ply-boot-splash.h"
|
||||
#include <sys/syslog.h>
|
||||
|
||||
typedef struct _ply_kmsg_reader ply_kmsg_reader_t;
|
||||
|
||||
struct dmesg_name
|
||||
{
|
||||
const char *name;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int priority;
|
||||
int facility;
|
||||
unsigned long sequence;
|
||||
unsigned long long timestamp;
|
||||
char *message;
|
||||
} kmsg_message_t;
|
||||
|
||||
struct _ply_kmsg_reader
|
||||
{
|
||||
int kmsg_fd;
|
||||
ply_fd_watch_t *fd_watch;
|
||||
ply_trigger_t *kmsg_trigger;
|
||||
ply_list_t *kmsg_messages;
|
||||
};
|
||||
|
||||
typedef void (* ply_kmsg_reader_message_handler_t) (void *,
|
||||
kmsg_message_t *);
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_kmsg_reader_t *ply_kmsg_reader_new (void);
|
||||
void ply_kmsg_reader_free (ply_kmsg_reader_t *kmsg_reader);
|
||||
void ply_kmsg_reader_start (ply_kmsg_reader_t *kmsg_reader);
|
||||
void ply_kmsg_reader_stop (ply_kmsg_reader_t *kmsg_reader);
|
||||
void ply_kmsg_reader_watch_for_messages (ply_kmsg_reader_t *kmsg_reader,
|
||||
ply_kmsg_reader_message_handler_t message_handler,
|
||||
void *user_data);
|
||||
|
||||
#endif //PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
|
||||
#endif //PLY_KMSG_READER_H
|
||||
254
src/libply-splash-core/ply-rich-text.c
Normal file
254
src/libply-splash-core/ply-rich-text.c
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
/* ply-rich-text.c - Text with colors and styles
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ply-array.h"
|
||||
#include "ply-rich-text.h"
|
||||
#include "ply-logger.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
struct _ply_rich_text_t
|
||||
{
|
||||
ply_array_t *characters;
|
||||
size_t reference_count;
|
||||
};
|
||||
|
||||
ply_rich_text_t *
|
||||
ply_rich_text_new (void)
|
||||
{
|
||||
ply_rich_text_t *rich_text;
|
||||
|
||||
rich_text = calloc (1, sizeof(ply_rich_text_t));
|
||||
rich_text->characters = ply_array_new (PLY_ARRAY_ELEMENT_TYPE_POINTER);
|
||||
rich_text->reference_count = 1;
|
||||
|
||||
return rich_text;
|
||||
}
|
||||
|
||||
void
|
||||
ply_rich_text_take_reference (ply_rich_text_t *rich_text)
|
||||
{
|
||||
rich_text->reference_count++;
|
||||
}
|
||||
|
||||
void
|
||||
ply_rich_text_drop_reference (ply_rich_text_t *rich_text)
|
||||
{
|
||||
rich_text->reference_count--;
|
||||
|
||||
if (rich_text->reference_count == 0)
|
||||
ply_rich_text_free (rich_text);
|
||||
}
|
||||
|
||||
void
|
||||
ply_rich_text_free (ply_rich_text_t *rich_text)
|
||||
{
|
||||
ply_rich_text_character_t **characters;
|
||||
|
||||
if (rich_text == NULL)
|
||||
return;
|
||||
|
||||
characters = ply_rich_text_get_characters (rich_text);
|
||||
characters = (ply_rich_text_character_t **) ply_array_get_pointer_elements (rich_text->characters);
|
||||
for (size_t i = 0; characters[i] != NULL; i++) {
|
||||
ply_rich_text_character_free (characters[i]);
|
||||
}
|
||||
|
||||
ply_array_free (rich_text->characters);
|
||||
free (rich_text);
|
||||
}
|
||||
|
||||
char *
|
||||
ply_rich_text_get_string (ply_rich_text_t *rich_text,
|
||||
ply_rich_text_span_t *span)
|
||||
{
|
||||
char *string = NULL;
|
||||
ply_buffer_t *buffer;
|
||||
ply_rich_text_character_t **characters;
|
||||
|
||||
characters = ply_rich_text_get_characters (rich_text);
|
||||
|
||||
buffer = ply_buffer_new ();
|
||||
for (size_t i = span->offset; characters[i] != NULL; i++) {
|
||||
if (span->range >= 0) {
|
||||
if (i >= span->offset + span->range)
|
||||
break;
|
||||
}
|
||||
|
||||
ply_buffer_append_bytes (buffer,
|
||||
characters[i]->bytes,
|
||||
characters[i]->length);
|
||||
}
|
||||
|
||||
string = ply_buffer_steal_bytes (buffer);
|
||||
|
||||
ply_buffer_free (buffer);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
void
|
||||
ply_rich_text_remove_characters (ply_rich_text_t *rich_text)
|
||||
{
|
||||
ply_rich_text_character_t **characters;
|
||||
|
||||
if (rich_text == NULL)
|
||||
return;
|
||||
|
||||
characters = ply_rich_text_get_characters (rich_text);
|
||||
characters = (ply_rich_text_character_t **) ply_array_get_pointer_elements (rich_text->characters);
|
||||
for (size_t i = 0; characters[i] != NULL; i++) {
|
||||
ply_rich_text_character_free (characters[i]);
|
||||
}
|
||||
|
||||
ply_array_free (rich_text->characters);
|
||||
rich_text->characters = ply_array_new (PLY_ARRAY_ELEMENT_TYPE_POINTER);
|
||||
}
|
||||
|
||||
size_t
|
||||
ply_rich_text_get_length (ply_rich_text_t *rich_text)
|
||||
{
|
||||
ply_rich_text_character_t **characters;
|
||||
size_t length = 0;
|
||||
|
||||
characters = ply_rich_text_get_characters (rich_text);
|
||||
|
||||
for (length = 0; characters[length] != NULL; length++) {
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
ply_rich_text_character_t *
|
||||
ply_rich_text_character_new (void)
|
||||
{
|
||||
ply_rich_text_character_t *character = calloc (1, sizeof(ply_rich_text_character_t));
|
||||
character->bytes = NULL;
|
||||
character->length = 0;
|
||||
|
||||
return character;
|
||||
}
|
||||
|
||||
void
|
||||
ply_rich_text_character_free (ply_rich_text_character_t *character)
|
||||
{
|
||||
free (character->bytes);
|
||||
free (character);
|
||||
}
|
||||
|
||||
ply_rich_text_character_t **
|
||||
ply_rich_text_get_characters (ply_rich_text_t *rich_text)
|
||||
{
|
||||
ply_rich_text_character_t **characters;
|
||||
|
||||
characters = (ply_rich_text_character_t **) ply_array_get_pointer_elements (rich_text->characters);
|
||||
return characters;
|
||||
}
|
||||
|
||||
void
|
||||
ply_rich_text_remove_character (ply_rich_text_t *rich_text,
|
||||
size_t character_index)
|
||||
{
|
||||
ply_rich_text_character_t **characters;
|
||||
|
||||
characters = ply_rich_text_get_characters (rich_text);
|
||||
|
||||
if (characters[character_index] == NULL)
|
||||
return;
|
||||
|
||||
ply_rich_text_character_free (characters[character_index]);
|
||||
characters[character_index] = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ply_rich_text_move_character (ply_rich_text_t *rich_text,
|
||||
size_t old_index,
|
||||
size_t new_index)
|
||||
{
|
||||
ply_rich_text_character_t **characters = ply_rich_text_get_characters (rich_text);
|
||||
characters[new_index] = characters[old_index];
|
||||
characters[old_index] = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ply_rich_text_set_character (ply_rich_text_t *rich_text,
|
||||
ply_rich_text_character_style_t style,
|
||||
size_t character_index,
|
||||
const char *character_string,
|
||||
size_t length)
|
||||
{
|
||||
ply_rich_text_character_t **characters;
|
||||
ply_rich_text_character_t *character;
|
||||
|
||||
characters = ply_rich_text_get_characters (rich_text);
|
||||
|
||||
if (characters[character_index] == NULL) {
|
||||
character = ply_rich_text_character_new ();
|
||||
ply_array_add_pointer_element (rich_text->characters, character);
|
||||
characters = (ply_rich_text_character_t **) ply_array_get_pointer_elements (rich_text->characters);
|
||||
} else {
|
||||
character = characters[character_index];
|
||||
if (character->bytes) {
|
||||
free (character->bytes);
|
||||
character->bytes = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
characters[character_index] = character;
|
||||
character->bytes = strdup (character_string);
|
||||
character->length = length;
|
||||
character->style = style;
|
||||
}
|
||||
|
||||
void
|
||||
ply_rich_text_iterator_init (ply_rich_text_iterator_t *iterator,
|
||||
ply_rich_text_t *rich_text,
|
||||
ply_rich_text_span_t *span)
|
||||
{
|
||||
iterator->rich_text = rich_text;
|
||||
iterator->span = *span;
|
||||
iterator->current_offset = span->offset;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_rich_text_iterator_next (ply_rich_text_iterator_t *iterator,
|
||||
ply_rich_text_character_t **character)
|
||||
{
|
||||
ply_rich_text_t *rich_text = iterator->rich_text;
|
||||
ply_rich_text_span_t *span = &iterator->span;
|
||||
ply_rich_text_character_t **characters = ply_rich_text_get_characters (rich_text);
|
||||
|
||||
if (iterator->current_offset >= span->offset + span->range) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (characters[iterator->current_offset] == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*character = characters[iterator->current_offset];
|
||||
|
||||
iterator->current_offset++;
|
||||
|
||||
return true;
|
||||
}
|
||||
94
src/libply-splash-core/ply-rich-text.h
Normal file
94
src/libply-splash-core/ply-rich-text.h
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/* ply-rich-text.h - Text with colors and styles
|
||||
*
|
||||
* 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_RICH_TEXT_H
|
||||
#define PLY_RICH_TEXT_H
|
||||
|
||||
#include "ply-array.h"
|
||||
#include "ply-terminal.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#define PLY_UTF8_CHARACTER_MAX_SIZE 5
|
||||
|
||||
typedef struct _ply_rich_text_t ply_rich_text_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_terminal_color_t foreground_color;
|
||||
ply_terminal_color_t background_color;
|
||||
uint32_t bold_enabled : 1;
|
||||
uint32_t dim_enabled : 1;
|
||||
uint32_t italic_enabled : 1;
|
||||
uint32_t underline_enabled : 1;
|
||||
uint32_t reverse_enabled : 1;
|
||||
} ply_rich_text_character_style_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *bytes;
|
||||
size_t length;
|
||||
|
||||
ply_rich_text_character_style_t style;
|
||||
} ply_rich_text_character_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ssize_t offset;
|
||||
ssize_t range;
|
||||
} ply_rich_text_span_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_rich_text_t *rich_text;
|
||||
ply_rich_text_span_t span;
|
||||
ssize_t current_offset;
|
||||
} ply_rich_text_iterator_t;
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_rich_text_t *ply_rich_text_new (void);
|
||||
void ply_rich_text_take_reference (ply_rich_text_t *rich_text);
|
||||
void ply_rich_text_drop_reference (ply_rich_text_t *rich_text);
|
||||
char *ply_rich_text_get_string (ply_rich_text_t *rich_text,
|
||||
ply_rich_text_span_t *span);
|
||||
size_t ply_rich_text_get_length (ply_rich_text_t *rich_text);
|
||||
void ply_rich_text_set_character (ply_rich_text_t *rich_text,
|
||||
ply_rich_text_character_style_t style,
|
||||
size_t index,
|
||||
const char *bytes,
|
||||
size_t length);
|
||||
void ply_rich_text_move_character (ply_rich_text_t *rich_text,
|
||||
size_t old_index,
|
||||
size_t new_index);
|
||||
void ply_rich_text_remove_character (ply_rich_text_t *rich_text,
|
||||
size_t character_index);
|
||||
|
||||
void ply_rich_text_remove_characters (ply_rich_text_t *rich_text);
|
||||
ply_rich_text_character_t **ply_rich_text_get_characters (ply_rich_text_t *rich_text);
|
||||
void ply_rich_text_free (ply_rich_text_t *rich_text);
|
||||
|
||||
ply_rich_text_character_t *ply_rich_text_character_new (void);
|
||||
void ply_rich_text_character_free (ply_rich_text_character_t *character);
|
||||
|
||||
void ply_rich_text_iterator_init (ply_rich_text_iterator_t *iterator,
|
||||
ply_rich_text_t *rich_text,
|
||||
ply_rich_text_span_t *span);
|
||||
bool ply_rich_text_iterator_next (ply_rich_text_iterator_t *iterator,
|
||||
ply_rich_text_character_t **character);
|
||||
|
||||
#endif //PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
#endif //PLY_RICH_TEXT_H
|
||||
1288
src/libply-splash-core/ply-terminal-emulator.c
Normal file
1288
src/libply-splash-core/ply-terminal-emulator.c
Normal file
File diff suppressed because it is too large
Load diff
70
src/libply-splash-core/ply-terminal-emulator.h
Normal file
70
src/libply-splash-core/ply-terminal-emulator.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* ply-terminal-emulator.h - Minimal Terminal Emulator
|
||||
*
|
||||
* 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_TERMINAL_EMULATOR_H
|
||||
#define PLY_TERMINAL_EMULATOR_H
|
||||
|
||||
#include "ply-boot-splash.h"
|
||||
#include "ply-rich-text.h"
|
||||
#include <sys/syslog.h>
|
||||
|
||||
/* Terminal attribute values are determined from the "ECMA-48 Select Graphic Rendition" section from
|
||||
* https://man7.org/linux/man-pages/man4/console_codes.4.html
|
||||
*/
|
||||
#define PLY_TERMINAL_ATTRIBUTE_FOREGROUND_COLOR_OFFSET 30
|
||||
#define PLY_TERMINAL_ATTRIBUTE_BACKGROUND_COLOR_OFFSET 40
|
||||
#define PLY_TERMINAL_ATTRIBUTE_FOREGROUND_BRIGHT_OFFSET 90
|
||||
#define PLY_TERMINAL_ATTRIBUTE_BACKGROUND_BRIGHT_OFFSET 100
|
||||
|
||||
typedef struct _ply_terminal_emulator ply_terminal_emulator_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLY_TERMINAL_ATTRIBUTE_RESET,
|
||||
PLY_TERMINAL_ATTRIBUTE_BOLD,
|
||||
PLY_TERMINAL_ATTRIBUTE_DIM,
|
||||
PLY_TERMINAL_ATTRIBUTE_ITALIC,
|
||||
PLY_TERMINAL_ATTRIBUTE_UNDERLINE,
|
||||
PLY_TERMINAL_ATTRIBUTE_REVERSE = 7,
|
||||
PLY_TERMINAL_ATTRIBUTE_NO_BOLD = 21,
|
||||
PLY_TERMINAL_ATTRIBUTE_NO_DIM,
|
||||
PLY_TERMINAL_ATTRIBUTE_NO_ITALIC,
|
||||
PLY_TERMINAL_ATTRIBUTE_NO_UNDERLINE,
|
||||
PLY_TERMINAL_ATTRIBUTE_NO_REVERSE = 27
|
||||
} ply_terminal_style_attributes_t;
|
||||
|
||||
typedef void (*ply_terminal_emulator_output_handler_t) (void *user_data,
|
||||
const char *output);
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_terminal_emulator_t *ply_terminal_emulator_new (size_t maximum_line_count);
|
||||
void ply_terminal_emulator_free (ply_terminal_emulator_t *terminal_emulator);
|
||||
void ply_terminal_emulator_parse_lines (ply_terminal_emulator_t *terminal_emulator,
|
||||
const char *text,
|
||||
size_t size);
|
||||
ply_rich_text_t *ply_terminal_emulator_get_nth_line (ply_terminal_emulator_t *terminal_emulator,
|
||||
int line_number);
|
||||
int ply_terminal_emulator_get_line_count (ply_terminal_emulator_t *terminal_emulator);
|
||||
void ply_terminal_emulator_convert_boot_buffer (ply_terminal_emulator_t *terminal_emulator,
|
||||
ply_buffer_t *boot_buffer);
|
||||
void ply_terminal_emulator_watch_for_output (ply_terminal_emulator_t *terminal_emulator,
|
||||
ply_terminal_emulator_output_handler_t handler,
|
||||
void *user_data);
|
||||
|
||||
#endif //PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
#endif //PLY_TERMINAL_EMULATOR_H
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
libply_splash_graphics_sources = files(
|
||||
'ply-animation.c',
|
||||
'ply-capslock-icon.c',
|
||||
'ply-console-viewer.c',
|
||||
'ply-entry.c',
|
||||
'ply-image.c',
|
||||
'ply-keymap-icon.c',
|
||||
|
|
@ -40,6 +41,7 @@ libply_splash_graphics_dep = declare_dependency(
|
|||
libply_splash_graphics_headers = files(
|
||||
'ply-animation.h',
|
||||
'ply-capslock-icon.h',
|
||||
'ply-console-viewer.h',
|
||||
'ply-entry.h',
|
||||
'ply-image.h',
|
||||
'ply-keymap-icon.h',
|
||||
|
|
|
|||
324
src/libply-splash-graphics/ply-console-viewer.c
Normal file
324
src/libply-splash-graphics/ply-console-viewer.c
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
/* ply-console-view.c - console message viewer
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ply-label.h"
|
||||
#include "ply-array.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-image.h"
|
||||
#include "ply-kmsg-reader.h"
|
||||
#include "ply-console-viewer.h"
|
||||
#include "ply-rich-text.h"
|
||||
|
||||
#define TERMINAL_OUTPUT_UPDATE_INTERVAL (1.0 / 60)
|
||||
|
||||
struct _ply_console_viewer
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
|
||||
ply_terminal_emulator_t *terminal_emulator;
|
||||
|
||||
ply_pixel_display_t *display;
|
||||
ply_rectangle_t area;
|
||||
|
||||
ply_list_t *message_labels;
|
||||
|
||||
uint32_t is_hidden : 1;
|
||||
uint32_t output_queued : 1;
|
||||
uint32_t needs_redraw : 1;
|
||||
|
||||
char *font;
|
||||
long font_height;
|
||||
long font_width;
|
||||
int line_max_chars;
|
||||
|
||||
uint32_t text_color;
|
||||
};
|
||||
|
||||
static void update_console_messages (ply_console_viewer_t *console_viewer);
|
||||
static void on_terminal_emulator_output (ply_console_viewer_t *console_viewer);
|
||||
|
||||
bool ply_console_viewer_preferred (void)
|
||||
{
|
||||
return !ply_kernel_command_line_has_argument ("plymouth.prefer-fbcon");
|
||||
}
|
||||
|
||||
ply_console_viewer_t *
|
||||
ply_console_viewer_new (ply_pixel_display_t *display,
|
||||
const char *font)
|
||||
{
|
||||
ply_console_viewer_t *console_viewer;
|
||||
ply_label_t *console_message_label, *measure_label;
|
||||
size_t line_count;
|
||||
|
||||
console_viewer = calloc (1, sizeof(struct _ply_console_viewer));
|
||||
|
||||
console_viewer->message_labels = ply_list_new ();
|
||||
console_viewer->is_hidden = true;
|
||||
|
||||
console_viewer->font = strdup (font);
|
||||
|
||||
measure_label = ply_label_new ();
|
||||
ply_label_set_text (measure_label, " ");
|
||||
ply_label_set_font (measure_label, console_viewer->font);
|
||||
|
||||
console_viewer->text_color = PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR;
|
||||
|
||||
console_viewer->font_height = ply_label_get_height (measure_label);
|
||||
console_viewer->font_width = ply_label_get_width (measure_label);
|
||||
/* Allow the label to be the size of how many characters can fit in the width of the screeen, minus one for larger fonts that have some size overhead */
|
||||
console_viewer->line_max_chars = ply_pixel_display_get_width (display) / console_viewer->font_width - 1;
|
||||
line_count = ply_pixel_display_get_height (display) / console_viewer->font_height;
|
||||
|
||||
/* Display at least one line */
|
||||
if (line_count < 0)
|
||||
line_count = 1;
|
||||
|
||||
ply_label_free (measure_label);
|
||||
|
||||
for (size_t label_index = 0; label_index < line_count; label_index++) {
|
||||
console_message_label = ply_label_new ();
|
||||
ply_label_set_font (console_message_label, console_viewer->font);
|
||||
ply_list_append_data (console_viewer->message_labels, console_message_label);
|
||||
}
|
||||
|
||||
console_viewer->terminal_emulator = ply_terminal_emulator_new (line_count);
|
||||
|
||||
ply_terminal_emulator_watch_for_output (console_viewer->terminal_emulator,
|
||||
(ply_terminal_emulator_output_handler_t)
|
||||
on_terminal_emulator_output,
|
||||
console_viewer);
|
||||
|
||||
return console_viewer;
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_viewer_free (ply_console_viewer_t *console_viewer)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
ply_label_t *console_message_label;
|
||||
|
||||
ply_list_foreach (console_viewer->message_labels, node) {
|
||||
console_message_label = ply_list_node_get_data (node);
|
||||
ply_label_free (console_message_label);
|
||||
}
|
||||
ply_list_free (console_viewer->message_labels);
|
||||
ply_terminal_emulator_free (console_viewer->terminal_emulator);
|
||||
|
||||
free (console_viewer->font);
|
||||
free (console_viewer);
|
||||
}
|
||||
|
||||
static void
|
||||
update_console_messages (ply_console_viewer_t *console_viewer)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
ply_label_t *console_message_label;
|
||||
size_t message_number;
|
||||
ssize_t characters_left;
|
||||
ply_rich_text_span_t span;
|
||||
|
||||
console_viewer->output_queued = false;
|
||||
|
||||
if (console_viewer->terminal_emulator == NULL)
|
||||
return;
|
||||
|
||||
if (console_viewer->display == NULL)
|
||||
return;
|
||||
|
||||
message_number = ply_terminal_emulator_get_line_count (console_viewer->terminal_emulator) - 1;
|
||||
|
||||
if (message_number < 0)
|
||||
return;
|
||||
|
||||
ply_pixel_display_pause_updates (console_viewer->display);
|
||||
node = ply_list_get_first_node (console_viewer->message_labels);
|
||||
while (node != NULL) {
|
||||
ply_rich_text_t *line = NULL;
|
||||
|
||||
characters_left = 0;
|
||||
if (message_number >= 0) {
|
||||
line = ply_terminal_emulator_get_nth_line (console_viewer->terminal_emulator, message_number);
|
||||
|
||||
if (line != NULL) {
|
||||
ply_rich_text_take_reference (line);
|
||||
characters_left = ply_rich_text_get_length (line);
|
||||
}
|
||||
}
|
||||
|
||||
span.offset = characters_left;
|
||||
while (characters_left >= 0) {
|
||||
console_message_label = ply_list_node_get_data (node);
|
||||
|
||||
span.range = span.offset % console_viewer->line_max_chars;
|
||||
if (span.range == 0)
|
||||
span.range = console_viewer->line_max_chars;
|
||||
|
||||
characters_left = span.offset - span.range - 1;
|
||||
|
||||
if (span.offset - span.range >= 0)
|
||||
span.offset -= span.range;
|
||||
else
|
||||
span.offset = 0;
|
||||
|
||||
if (line != NULL) {
|
||||
ply_label_set_rich_text (console_message_label, line, &span);
|
||||
} else {
|
||||
ply_label_set_text (console_message_label, "");
|
||||
}
|
||||
|
||||
node = ply_list_get_next_node (console_viewer->message_labels, node);
|
||||
if (node == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (line != NULL)
|
||||
ply_rich_text_drop_reference (line);
|
||||
|
||||
if (message_number <= 0)
|
||||
break;
|
||||
|
||||
message_number--;
|
||||
}
|
||||
console_viewer->needs_redraw = true;
|
||||
ply_pixel_display_draw_area (console_viewer->display, 0, 0,
|
||||
ply_pixel_display_get_width (console_viewer->display),
|
||||
ply_pixel_display_get_height (console_viewer->display));
|
||||
ply_pixel_display_unpause_updates (console_viewer->display);
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_viewer_show (ply_console_viewer_t *console_viewer,
|
||||
ply_pixel_display_t *display)
|
||||
{
|
||||
uint32_t label_color;
|
||||
size_t label_index;
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (console_viewer != NULL);
|
||||
|
||||
console_viewer->display = display;
|
||||
console_viewer->is_hidden = false;
|
||||
|
||||
label_color = console_viewer->text_color;
|
||||
|
||||
label_index = 0;
|
||||
ply_list_foreach (console_viewer->message_labels, node) {
|
||||
ply_label_t *console_message_label;
|
||||
console_message_label = ply_list_node_get_data (node);
|
||||
ply_label_show (console_message_label, console_viewer->display,
|
||||
console_viewer->font_width / 2,
|
||||
(ply_pixel_display_get_height (console_viewer->display) - (console_viewer->font_height * label_index) - console_viewer->font_height));
|
||||
ply_label_set_hex_color (console_message_label, label_color);
|
||||
label_index++;
|
||||
}
|
||||
|
||||
update_console_messages (console_viewer);
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_viewer_draw_area (ply_console_viewer_t *console_viewer,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
size_t label_index;
|
||||
ply_label_t *console_message_label;
|
||||
|
||||
if (!console_viewer->needs_redraw)
|
||||
return;
|
||||
|
||||
if (console_viewer->is_hidden)
|
||||
return;
|
||||
|
||||
label_index = 0;
|
||||
ply_list_foreach (console_viewer->message_labels, node) {
|
||||
console_message_label = ply_list_node_get_data (node);
|
||||
ply_label_draw_area (console_message_label, buffer,
|
||||
MAX (x, console_viewer->font_width / 2),
|
||||
MAX (y, (ply_pixel_display_get_height (console_viewer->display) - (console_viewer->font_height * label_index) - console_viewer->font_height)),
|
||||
MIN (ply_label_get_width (console_message_label), width),
|
||||
MIN (height, console_viewer->font_height));
|
||||
label_index++;
|
||||
}
|
||||
|
||||
console_viewer->needs_redraw = false;
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_viewer_hide (ply_console_viewer_t *console_viewer)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
ply_label_t *console_message_label;
|
||||
|
||||
if (console_viewer->is_hidden)
|
||||
return;
|
||||
|
||||
console_viewer->is_hidden = true;
|
||||
|
||||
ply_list_foreach (console_viewer->message_labels, node) {
|
||||
console_message_label = ply_list_node_get_data (node);
|
||||
ply_label_hide (console_message_label);
|
||||
}
|
||||
|
||||
console_viewer->display = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_terminal_emulator_output (ply_console_viewer_t *console_viewer)
|
||||
{
|
||||
if (console_viewer->output_queued)
|
||||
return;
|
||||
|
||||
if (console_viewer->is_hidden)
|
||||
return;
|
||||
|
||||
ply_event_loop_watch_for_timeout (ply_event_loop_get_default (),
|
||||
TERMINAL_OUTPUT_UPDATE_INTERVAL,
|
||||
(ply_event_loop_timeout_handler_t)
|
||||
update_console_messages, console_viewer);
|
||||
console_viewer->output_queued = true;
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_viewer_set_text_color (ply_console_viewer_t *console_viewer,
|
||||
uint32_t hex_color)
|
||||
{
|
||||
console_viewer->text_color = hex_color;
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_viewer_convert_boot_buffer (ply_console_viewer_t *console_viewer,
|
||||
ply_buffer_t *boot_buffer)
|
||||
{
|
||||
ply_terminal_emulator_convert_boot_buffer (console_viewer->terminal_emulator, boot_buffer);
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_viewer_parse_lines (ply_console_viewer_t *console_viewer,
|
||||
const char *text,
|
||||
size_t size)
|
||||
{
|
||||
ply_terminal_emulator_parse_lines (console_viewer->terminal_emulator, text, size);
|
||||
}
|
||||
55
src/libply-splash-graphics/ply-console-viewer.h
Normal file
55
src/libply-splash-graphics/ply-console-viewer.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* ply-console-viewer.h - console message viewer
|
||||
*
|
||||
* 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_CONSOLE_VIEWER_H
|
||||
#define PLY_CONSOLE_VIEWER_H
|
||||
|
||||
#include "ply-key-file.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-terminal-emulator.h"
|
||||
|
||||
typedef struct _ply_console_viewer ply_console_viewer_t;
|
||||
|
||||
#define PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR 0xffffffff /* white */
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
bool ply_console_viewer_preferred (void);
|
||||
ply_console_viewer_t *ply_console_viewer_new (ply_pixel_display_t *display,
|
||||
const char *fontdesc);
|
||||
void ply_console_viewer_free (ply_console_viewer_t *console_viewer);
|
||||
void ply_console_viewer_show (ply_console_viewer_t *console_viewer,
|
||||
ply_pixel_display_t *display);
|
||||
void ply_console_viewer_draw_area (ply_console_viewer_t *console_viewer,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height);
|
||||
void ply_console_viewer_hide (ply_console_viewer_t *console_viewer);
|
||||
void ply_console_viewer_set_text_color (ply_console_viewer_t *console_viewer,
|
||||
uint32_t hex_color);
|
||||
void ply_console_viewer_convert_boot_buffer (ply_console_viewer_t *console_viewer,
|
||||
ply_buffer_t *boot_buffer);
|
||||
void ply_console_viewer_parse_lines (ply_console_viewer_t *console_viewer,
|
||||
const char *text,
|
||||
size_t size);
|
||||
#endif //PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
|
||||
#endif //PLY_CONSOLE_VIEWER_H
|
||||
|
|
@ -36,7 +36,7 @@ typedef struct _ply_label_plugin_control ply_label_plugin_control_t;
|
|||
|
||||
typedef struct
|
||||
{
|
||||
ply_label_plugin_control_t * (*create_control)(void);
|
||||
ply_label_plugin_control_t *(*create_control)(void);
|
||||
void (*destroy_control)(ply_label_plugin_control_t *label);
|
||||
bool (*show_control)(ply_label_plugin_control_t *label,
|
||||
ply_pixel_display_t *display,
|
||||
|
|
@ -53,6 +53,9 @@ typedef struct
|
|||
|
||||
void (*set_text_for_control)(ply_label_plugin_control_t *label,
|
||||
const char *text);
|
||||
void (*set_rich_text_for_control)(ply_label_plugin_control_t *label,
|
||||
ply_rich_text_t *rich_text,
|
||||
ply_rich_text_span_t *span);
|
||||
void (*set_font_for_control)(ply_label_plugin_control_t *label,
|
||||
const char *fontdesc);
|
||||
void (*set_color_for_control)(ply_label_plugin_control_t *label,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-array.h"
|
||||
|
||||
struct _ply_label
|
||||
{
|
||||
|
|
@ -46,9 +47,13 @@ struct _ply_label
|
|||
ply_label_plugin_control_t *control;
|
||||
|
||||
char *text;
|
||||
|
||||
ply_rich_text_t *rich_text;
|
||||
ply_rich_text_span_t span;
|
||||
|
||||
ply_label_alignment_t alignment;
|
||||
long width;
|
||||
char *fontdesc;
|
||||
char *font;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
|
|
@ -86,6 +91,14 @@ ply_label_free (ply_label_t *label)
|
|||
ply_label_unload_plugin (label);
|
||||
}
|
||||
|
||||
free (label->text);
|
||||
free (label->font);
|
||||
|
||||
if (label->rich_text) {
|
||||
ply_rich_text_drop_reference (label->rich_text);
|
||||
label->rich_text = NULL;
|
||||
}
|
||||
|
||||
free (label);
|
||||
}
|
||||
|
||||
|
|
@ -98,7 +111,7 @@ ply_label_load_plugin (ply_label_t *label)
|
|||
|
||||
label->module_handle = ply_open_module (PLYMOUTH_PLUGIN_PATH "label-pango.so");
|
||||
|
||||
/* ...and the FreeType based one after that, it is not a complete substitute (yet). */
|
||||
/* and the FreeType based one after that, it is not a complete substitute (yet). */
|
||||
if (label->module_handle == NULL)
|
||||
label->module_handle = ply_open_module (PLYMOUTH_PLUGIN_PATH "label-freetype.so");
|
||||
|
||||
|
|
@ -138,17 +151,24 @@ ply_label_load_plugin (ply_label_t *label)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (label->text != NULL)
|
||||
label->plugin_interface->set_text_for_control (label->control,
|
||||
label->text);
|
||||
if (label->font != NULL)
|
||||
label->plugin_interface->set_font_for_control (label->control,
|
||||
label->font);
|
||||
|
||||
if (label->text != NULL) {
|
||||
if (label->rich_text == NULL) {
|
||||
label->plugin_interface->set_text_for_control (label->control,
|
||||
label->text);
|
||||
} else {
|
||||
label->plugin_interface->set_rich_text_for_control (label->control,
|
||||
label->rich_text,
|
||||
&label->span);
|
||||
}
|
||||
}
|
||||
label->plugin_interface->set_alignment_for_control (label->control,
|
||||
label->alignment);
|
||||
label->plugin_interface->set_width_for_control (label->control,
|
||||
label->width);
|
||||
if (label->fontdesc != NULL)
|
||||
label->plugin_interface->set_font_for_control (label->control,
|
||||
label->fontdesc);
|
||||
|
||||
label->plugin_interface->set_color_for_control (label->control,
|
||||
label->red,
|
||||
label->green,
|
||||
|
|
@ -231,6 +251,11 @@ ply_label_set_text (ply_label_t *label,
|
|||
free (label->text);
|
||||
label->text = strdup (text);
|
||||
|
||||
if (label->rich_text) {
|
||||
ply_rich_text_drop_reference (label->rich_text);
|
||||
label->rich_text = NULL;
|
||||
}
|
||||
|
||||
if (label->plugin_interface == NULL)
|
||||
return;
|
||||
|
||||
|
|
@ -238,6 +263,29 @@ ply_label_set_text (ply_label_t *label,
|
|||
text);
|
||||
}
|
||||
|
||||
void
|
||||
ply_label_set_rich_text (ply_label_t *label,
|
||||
ply_rich_text_t *rich_text,
|
||||
ply_rich_text_span_t *span)
|
||||
{
|
||||
free (label->text);
|
||||
label->text = ply_rich_text_get_string (rich_text, span);
|
||||
|
||||
if (label->rich_text)
|
||||
ply_rich_text_drop_reference (label->rich_text);
|
||||
label->rich_text = rich_text;
|
||||
ply_rich_text_take_reference (rich_text);
|
||||
|
||||
label->span = *span;
|
||||
|
||||
if (label->plugin_interface == NULL)
|
||||
return;
|
||||
|
||||
label->plugin_interface->set_rich_text_for_control (label->control,
|
||||
label->rich_text,
|
||||
&label->span);
|
||||
}
|
||||
|
||||
void
|
||||
ply_label_set_alignment (ply_label_t *label,
|
||||
ply_label_alignment_t alignment)
|
||||
|
|
@ -265,25 +313,49 @@ ply_label_set_width (ply_label_t *label,
|
|||
}
|
||||
|
||||
/*
|
||||
* Please see pango documentation, for fontdesc format:
|
||||
* Please see pango documentation, for font format:
|
||||
* http://library.gnome.org/devel/pango/stable/pango-Fonts.html#pango-font-description-from-string
|
||||
* If you pass NULL, it will use default font.
|
||||
*/
|
||||
void
|
||||
ply_label_set_font (ply_label_t *label,
|
||||
const char *fontdesc)
|
||||
const char *font)
|
||||
{
|
||||
free (label->fontdesc);
|
||||
if (fontdesc)
|
||||
label->fontdesc = strdup (fontdesc);
|
||||
free (label->font);
|
||||
if (font)
|
||||
label->font = strdup (font);
|
||||
else
|
||||
label->fontdesc = NULL;
|
||||
label->font = NULL;
|
||||
|
||||
if (label->plugin_interface == NULL)
|
||||
return;
|
||||
|
||||
label->plugin_interface->set_font_for_control (label->control,
|
||||
fontdesc);
|
||||
font);
|
||||
}
|
||||
|
||||
void
|
||||
ply_label_set_hex_color (ply_label_t *label,
|
||||
uint32_t hex_color)
|
||||
{
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
double alpha;
|
||||
|
||||
red = ((double) (hex_color & 0xff000000) / 0xff000000);
|
||||
green = ((double) (hex_color & 0x00ff0000) / 0x00ff0000);
|
||||
blue = ((double) (hex_color & 0x0000ff00) / 0x0000ff00);
|
||||
alpha = ((double) (hex_color & 0x000000ff) / 0x000000ff);
|
||||
|
||||
if (label->plugin_interface == NULL)
|
||||
return;
|
||||
|
||||
label->plugin_interface->set_color_for_control (label->control,
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
alpha);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "ply-event-loop.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-rich-text.h"
|
||||
|
||||
typedef struct _ply_label ply_label_t;
|
||||
|
||||
|
|
@ -60,12 +61,19 @@ bool ply_label_is_hidden (ply_label_t *label);
|
|||
|
||||
void ply_label_set_text (ply_label_t *label,
|
||||
const char *text);
|
||||
|
||||
void ply_label_set_rich_text (ply_label_t *label,
|
||||
ply_rich_text_t *rich_text,
|
||||
ply_rich_text_span_t *span);
|
||||
|
||||
void ply_label_set_alignment (ply_label_t *label,
|
||||
ply_label_alignment_t alignment);
|
||||
void ply_label_set_width (ply_label_t *label,
|
||||
long width);
|
||||
void ply_label_set_font (ply_label_t *label,
|
||||
const char *fontdesc);
|
||||
void ply_label_set_hex_color (ply_label_t *label,
|
||||
uint32_t hex_color);
|
||||
void ply_label_set_color (ply_label_t *label,
|
||||
float red,
|
||||
float green,
|
||||
|
|
|
|||
|
|
@ -776,6 +776,64 @@ ply_utf8_string_get_length (const char *string,
|
|||
return count;
|
||||
}
|
||||
|
||||
size_t
|
||||
ply_utf8_string_get_byte_offset_from_character_offset (const char *string,
|
||||
size_t character_offset)
|
||||
{
|
||||
size_t byte_offset = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < character_offset && string[byte_offset] != '\0'; i++) {
|
||||
byte_offset += ply_utf8_character_get_size (string + byte_offset, PLY_UTF8_CHARACTER_SIZE_MAX);
|
||||
}
|
||||
|
||||
return byte_offset;
|
||||
}
|
||||
|
||||
void
|
||||
ply_utf8_string_iterator_init (ply_utf8_string_iterator_t *iterator,
|
||||
const char *string,
|
||||
ssize_t starting_offset,
|
||||
ssize_t range)
|
||||
{
|
||||
size_t byte_offset;
|
||||
|
||||
iterator->character_range = range;
|
||||
iterator->string = string;
|
||||
|
||||
byte_offset = ply_utf8_string_get_byte_offset_from_character_offset (string, starting_offset);
|
||||
iterator->current_byte_offset = byte_offset;
|
||||
iterator->number_characters_iterated = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_utf8_string_iterator_next (ply_utf8_string_iterator_t *iterator,
|
||||
const char **character,
|
||||
size_t *size)
|
||||
{
|
||||
size_t size_of_current_character;
|
||||
|
||||
if (iterator->number_characters_iterated >= iterator->character_range)
|
||||
return false;
|
||||
|
||||
if (iterator->string[iterator->current_byte_offset] == '\0')
|
||||
return false;
|
||||
|
||||
size_of_current_character = ply_utf8_character_get_size (iterator->string + iterator->current_byte_offset,
|
||||
PLY_UTF8_CHARACTER_SIZE_MAX);
|
||||
|
||||
if (size_of_current_character == 0)
|
||||
return false;
|
||||
|
||||
*character = &iterator->string[iterator->current_byte_offset];
|
||||
*size = size_of_current_character;
|
||||
|
||||
iterator->current_byte_offset += size_of_current_character;
|
||||
iterator->number_characters_iterated++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char *
|
||||
ply_get_process_command_line (pid_t pid)
|
||||
{
|
||||
|
|
@ -939,6 +997,66 @@ int ply_guess_device_scale (uint32_t width,
|
|||
return get_device_scale (width, height, 0, 0, true);
|
||||
}
|
||||
|
||||
void
|
||||
ply_get_kmsg_log_levels (int *current_log_level,
|
||||
int *default_log_level)
|
||||
{
|
||||
static double last_update_time = 0;
|
||||
static int cached_current_log_level = 0;
|
||||
static int cached_default_log_level = 0;
|
||||
char log_levels[4096] = "";
|
||||
double current_time;
|
||||
char *field, *fields;
|
||||
int fd;
|
||||
|
||||
current_time = ply_get_timestamp ();
|
||||
|
||||
if ((current_time - last_update_time) < 1.0) {
|
||||
*current_log_level = cached_current_log_level;
|
||||
*default_log_level = cached_default_log_level;
|
||||
return;
|
||||
}
|
||||
|
||||
ply_trace ("opening /proc/sys/kernel/printk");
|
||||
fd = open ("/proc/sys/kernel/printk", O_RDONLY);
|
||||
|
||||
if (fd < 0) {
|
||||
ply_trace ("couldn't open it: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
ply_trace ("reading kmsg log levels");
|
||||
if (read (fd, log_levels, sizeof(log_levels) - 1) < 0) {
|
||||
ply_trace ("couldn't read it: %m");
|
||||
close (fd);
|
||||
return;
|
||||
}
|
||||
close (fd);
|
||||
|
||||
field = strtok_r (log_levels, " \t", &fields);
|
||||
|
||||
if (field == NULL) {
|
||||
ply_trace ("Couldn't parse current log level: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
*current_log_level = atoi (field);
|
||||
|
||||
field = strtok_r (NULL, " \t", &fields);
|
||||
|
||||
if (field == NULL) {
|
||||
ply_trace ("Couldn't parse default log level: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
*default_log_level = atoi (field);
|
||||
|
||||
cached_current_log_level = *current_log_level;
|
||||
cached_default_log_level = *default_log_level;
|
||||
|
||||
last_update_time = current_time;
|
||||
}
|
||||
|
||||
static const char *
|
||||
ply_get_kernel_command_line (void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -55,6 +55,14 @@ typedef enum
|
|||
PLY_UNIX_SOCKET_TYPE_TRIMMED_ABSTRACT
|
||||
} ply_unix_socket_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *string;
|
||||
ssize_t character_range;
|
||||
ssize_t current_byte_offset;
|
||||
ssize_t number_characters_iterated;
|
||||
} ply_utf8_string_iterator_t;
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
|
||||
#define ply_round_to_multiple(n, m) (((n) + (((m) - 1))) & ~((m) - 1))
|
||||
|
|
@ -117,6 +125,16 @@ int ply_utf8_character_get_size (const char *string,
|
|||
int ply_utf8_string_get_length (const char *string,
|
||||
size_t n);
|
||||
|
||||
size_t ply_utf8_string_get_byte_offset_from_character_offset (const char *string,
|
||||
size_t character_offset);
|
||||
void ply_utf8_string_iterator_init (ply_utf8_string_iterator_t *iterator,
|
||||
const char *string,
|
||||
ssize_t starting_offset,
|
||||
ssize_t range);
|
||||
bool ply_utf8_string_iterator_next (ply_utf8_string_iterator_t *iterator,
|
||||
const char **character,
|
||||
size_t *size);
|
||||
|
||||
char *ply_get_process_command_line (pid_t pid);
|
||||
pid_t ply_get_process_parent_pid (pid_t pid);
|
||||
|
||||
|
|
@ -130,6 +148,9 @@ int ply_get_device_scale (uint32_t width,
|
|||
int ply_guess_device_scale (uint32_t width,
|
||||
uint32_t height);
|
||||
|
||||
void ply_get_kmsg_log_levels (int *current_log_level,
|
||||
int *default_log_level);
|
||||
|
||||
const char *ply_kernel_command_line_get_string_after_prefix (const char *prefix);
|
||||
bool ply_kernel_command_line_has_argument (const char *argument);
|
||||
void ply_kernel_command_line_override (const char *command_line);
|
||||
|
|
|
|||
43
src/main.c
43
src/main.c
|
|
@ -55,6 +55,7 @@
|
|||
#include "ply-trigger.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-progress.h"
|
||||
#include "ply-kmsg-reader.h"
|
||||
|
||||
#define BOOT_DURATION_FILE PLYMOUTH_TIME_DIRECTORY "/boot-duration"
|
||||
#define SHUTDOWN_DURATION_FILE PLYMOUTH_TIME_DIRECTORY "/shutdown-duration"
|
||||
|
|
@ -79,6 +80,7 @@ typedef struct
|
|||
ply_event_loop_t *loop;
|
||||
ply_boot_server_t *boot_server;
|
||||
ply_boot_splash_t *boot_splash;
|
||||
ply_kmsg_reader_t *kmsg_reader;
|
||||
ply_terminal_session_t *session;
|
||||
ply_buffer_t *boot_buffer;
|
||||
ply_progress_t *progress;
|
||||
|
|
@ -93,6 +95,7 @@ typedef struct
|
|||
|
||||
ply_trigger_t *deactivate_trigger;
|
||||
ply_trigger_t *quit_trigger;
|
||||
ply_trigger_t *kmsg_trigger;
|
||||
|
||||
double start_time;
|
||||
double splash_delay;
|
||||
|
|
@ -157,6 +160,8 @@ static void on_backspace (state_t *state);
|
|||
static void on_quit (state_t *state,
|
||||
bool retain_splash,
|
||||
ply_trigger_t *quit_trigger);
|
||||
static void on_new_kmsg_message (state_t *state,
|
||||
kmsg_message_t *kmsg_message);
|
||||
static bool sh_is_init (state_t *state);
|
||||
static void cancel_pending_delayed_show (state_t *state);
|
||||
static void prepare_logging (state_t *state);
|
||||
|
|
@ -1455,6 +1460,22 @@ on_quit (state_t *state,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
on_new_kmsg_message (state_t *state,
|
||||
kmsg_message_t *kmsg_message)
|
||||
{
|
||||
long size = strlen (kmsg_message->message) + 1;
|
||||
char output[size];
|
||||
|
||||
strcpy (output, kmsg_message->message);
|
||||
strcat (output, "\n");
|
||||
|
||||
ply_buffer_append_bytes (state->boot_buffer, output, size);
|
||||
|
||||
if (state->boot_splash != NULL)
|
||||
ply_boot_splash_update_output (state->boot_splash, output, size);
|
||||
}
|
||||
|
||||
static bool
|
||||
on_has_active_vt (state_t *state)
|
||||
{
|
||||
|
|
@ -1578,15 +1599,16 @@ static void
|
|||
on_escape_pressed (state_t *state)
|
||||
{
|
||||
ply_trace ("escape key pressed");
|
||||
bool has_vt_consoles = true;
|
||||
|
||||
if (state->local_console_terminal != NULL) {
|
||||
if (!ply_terminal_is_vt (state->local_console_terminal))
|
||||
return;
|
||||
has_vt_consoles = false;
|
||||
} else {
|
||||
return;
|
||||
has_vt_consoles = false;
|
||||
}
|
||||
|
||||
if (validate_input (state, "", "\e"))
|
||||
if (validate_input (state, "", "\e") && has_vt_consoles == true)
|
||||
toggle_between_splash_and_details (state);
|
||||
}
|
||||
|
||||
|
|
@ -1891,6 +1913,18 @@ attach_to_running_session (state_t *state)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (state->kmsg_reader == NULL) {
|
||||
ply_trace ("Creating new kmsg reader");
|
||||
state->kmsg_reader = ply_kmsg_reader_new ();
|
||||
|
||||
ply_kmsg_reader_watch_for_messages (state->kmsg_reader,
|
||||
(ply_kmsg_reader_message_handler_t)
|
||||
on_new_kmsg_message,
|
||||
state);
|
||||
}
|
||||
|
||||
ply_kmsg_reader_start (state->kmsg_reader);
|
||||
|
||||
#ifdef PLY_ENABLE_SYSTEMD_INTEGRATION
|
||||
tell_systemd_to_print_details (state);
|
||||
#endif
|
||||
|
|
@ -1915,6 +1949,9 @@ detach_from_running_session (state_t *state)
|
|||
tell_systemd_to_stop_printing_details (state);
|
||||
#endif
|
||||
|
||||
ply_trace ("stopping kmsg reader");
|
||||
ply_kmsg_reader_stop (state->kmsg_reader);
|
||||
|
||||
ply_trace ("detaching from terminal session");
|
||||
ply_terminal_session_detach (state->session);
|
||||
state->is_redirected = false;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
|
@ -39,6 +40,7 @@
|
|||
|
||||
/* This is used if fontconfig (fc-match) is not available, like in the initrd. */
|
||||
#define FONT_FALLBACK "/usr/share/fonts/Plymouth.ttf"
|
||||
#define MONOSPACE_FONT_FALLBACK "/usr/share/fonts/Plymouth-monospace.ttf"
|
||||
|
||||
struct _ply_label_plugin_control
|
||||
{
|
||||
|
|
@ -52,12 +54,15 @@ struct _ply_label_plugin_control
|
|||
FT_Face face;
|
||||
|
||||
char *text;
|
||||
ply_rich_text_t *rich_text;
|
||||
ply_rich_text_span_t span;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
float alpha;
|
||||
|
||||
uint32_t is_hidden : 1;
|
||||
uint32_t is_monospaced : 1;
|
||||
};
|
||||
|
||||
ply_label_plugin_interface_t *ply_label_plugin_get_interface (void);
|
||||
|
|
@ -80,10 +85,45 @@ query_fc_match ()
|
|||
return fc_match_out;
|
||||
}
|
||||
|
||||
/* Query fontconfig, if available, for the default monospace font. */
|
||||
static const char *
|
||||
query_fc_match_monospace ()
|
||||
{
|
||||
FILE *fp;
|
||||
static char fc_match_out[PATH_MAX];
|
||||
|
||||
fp = popen ("/usr/bin/fc-match -f %{file} monospace", "r");
|
||||
if (!fp)
|
||||
return NULL;
|
||||
|
||||
fgets (fc_match_out, sizeof(fc_match_out), fp);
|
||||
|
||||
pclose (fp);
|
||||
|
||||
return fc_match_out;
|
||||
}
|
||||
|
||||
static FT_Error
|
||||
set_font_with_fallback (ply_label_plugin_control_t *label,
|
||||
const char *primary_font_path,
|
||||
const char *fallback_font_path)
|
||||
{
|
||||
FT_Error error;
|
||||
if (primary_font_path)
|
||||
error = FT_New_Face (label->library, primary_font_path, 0, &label->face);
|
||||
|
||||
if (!fallback_font_path || error) {
|
||||
printf ("label-ft: trying font fallback\n");
|
||||
error = FT_New_Face (label->library, fallback_font_path, 0, &label->face);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static ply_label_plugin_control_t *
|
||||
create_control (void)
|
||||
{
|
||||
FT_Error error;
|
||||
int error;
|
||||
ply_label_plugin_control_t *label;
|
||||
const char *font_path;
|
||||
|
||||
|
|
@ -100,19 +140,11 @@ create_control (void)
|
|||
}
|
||||
|
||||
font_path = query_fc_match ();
|
||||
if (font_path)
|
||||
error = FT_New_Face (label->library, font_path, 0, &label->face);
|
||||
|
||||
if (!font_path || error) {
|
||||
printf ("label-ft: trying font fallback\n");
|
||||
font_path = FONT_FALLBACK;
|
||||
error = FT_New_Face (label->library, font_path, 0, &label->face);
|
||||
|
||||
if (error) {
|
||||
FT_Done_FreeType (label->library);
|
||||
free (label);
|
||||
return NULL;
|
||||
}
|
||||
error = set_font_with_fallback (label, font_path, FONT_FALLBACK);
|
||||
if (error) {
|
||||
FT_Done_FreeType (label->library);
|
||||
free (label);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 12pt/96dpi as default */
|
||||
|
|
@ -152,26 +184,44 @@ get_height_of_control (ply_label_plugin_control_t *label)
|
|||
return label->area.height;
|
||||
}
|
||||
|
||||
static FT_Int
|
||||
width_of_line (ply_label_plugin_control_t *label,
|
||||
const char *text)
|
||||
static bool
|
||||
load_character (ply_label_plugin_control_t *label,
|
||||
const char **text)
|
||||
{
|
||||
FT_Error error;
|
||||
size_t character_size;
|
||||
wchar_t character;
|
||||
const char *input_text = *text;
|
||||
|
||||
character_size = mbrtowc (&character, input_text, PLY_UTF8_CHARACTER_SIZE_MAX, NULL);
|
||||
|
||||
if (character_size <= 0) {
|
||||
character = (wchar_t) *input_text;
|
||||
character_size = 1;
|
||||
}
|
||||
|
||||
error = FT_Load_Char (label->face, (FT_ULong) character, FT_LOAD_RENDER | FT_LOAD_TARGET_LIGHT);
|
||||
|
||||
*text = input_text + character_size;
|
||||
|
||||
return !error;
|
||||
}
|
||||
|
||||
static FT_Int
|
||||
width_of_string (ply_label_plugin_control_t *label,
|
||||
const char *text)
|
||||
{
|
||||
FT_Int width = 0;
|
||||
FT_Int left_bearing = 0;
|
||||
|
||||
while (*text != '\0' && *text != '\n') {
|
||||
error = FT_Load_Char (label->face, *text, FT_LOAD_RENDER | FT_LOAD_TARGET_LIGHT);
|
||||
|
||||
if (!error) {
|
||||
if (load_character (label, &text)) {
|
||||
width += label->face->glyph->advance.x >> 6;
|
||||
left_bearing = label->face->glyph->bitmap_left;
|
||||
/* We don't "go back" when drawing, so when left bearing is
|
||||
* negative (like for 'j'), we simply add to the width. */
|
||||
if (left_bearing < 0)
|
||||
width += -left_bearing;
|
||||
|
||||
++text;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,29 +231,65 @@ width_of_line (ply_label_plugin_control_t *label,
|
|||
static void
|
||||
size_control (ply_label_plugin_control_t *label)
|
||||
{
|
||||
FT_Int width;
|
||||
const char *text = label->text;
|
||||
FT_Int character_width, line_width;
|
||||
ply_rich_text_iterator_t rich_text_iterator;
|
||||
ply_utf8_string_iterator_t utf8_string_iterator;
|
||||
bool should_stop = false;
|
||||
|
||||
if (label->is_hidden)
|
||||
if (label->rich_text == NULL && label->text == NULL) {
|
||||
label->area.width = 0;
|
||||
label->area.height = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (label->rich_text != NULL) {
|
||||
ply_rich_text_iterator_init (&rich_text_iterator,
|
||||
label->rich_text,
|
||||
&label->span);
|
||||
} else {
|
||||
ply_utf8_string_iterator_init (&utf8_string_iterator,
|
||||
label->text,
|
||||
0,
|
||||
ply_utf8_string_get_length (label->text, strlen (label->text)));
|
||||
}
|
||||
label->area.width = 0;
|
||||
label->area.height = 0;
|
||||
|
||||
line_width = 0;
|
||||
|
||||
/* Go through each line */
|
||||
while (text && *text) {
|
||||
width = width_of_line (label, text);
|
||||
if ((uint32_t) width > label->area.width)
|
||||
label->area.width = width;
|
||||
do {
|
||||
const char *current_character;
|
||||
|
||||
label->area.height += (label->face->size->metrics.ascender
|
||||
- label->face->size->metrics.descender) >> 6;
|
||||
if (label->rich_text != NULL) {
|
||||
ply_rich_text_character_t *rich_text_character;
|
||||
should_stop = !ply_rich_text_iterator_next (&rich_text_iterator,
|
||||
&rich_text_character);
|
||||
if (!should_stop)
|
||||
current_character = rich_text_character->bytes;
|
||||
} else {
|
||||
size_t character_size;
|
||||
|
||||
text = strchr (text, '\n');
|
||||
/* skip newline character */
|
||||
if (text)
|
||||
++text;
|
||||
}
|
||||
should_stop = !ply_utf8_string_iterator_next (&utf8_string_iterator,
|
||||
¤t_character,
|
||||
&character_size);
|
||||
}
|
||||
|
||||
if (!should_stop) {
|
||||
character_width = width_of_string (label, current_character);
|
||||
line_width += character_width;
|
||||
}
|
||||
|
||||
if (should_stop || character_width == 0) {
|
||||
if ((uint32_t) line_width > label->area.width)
|
||||
label->area.width = line_width;
|
||||
|
||||
line_width = 0;
|
||||
|
||||
label->area.height += (label->face->size->metrics.ascender
|
||||
- label->face->size->metrics.descender) >> 6;
|
||||
}
|
||||
} while (!should_stop);
|
||||
|
||||
/* If centered, area.x is not the origin anymore */
|
||||
if ((long) label->area.width < label->width)
|
||||
|
|
@ -216,12 +302,12 @@ trigger_redraw (ply_label_plugin_control_t *label,
|
|||
{
|
||||
ply_rectangle_t dirty_area = label->area;
|
||||
|
||||
if (label->is_hidden || label->display == NULL)
|
||||
return;
|
||||
|
||||
if (adjust_size)
|
||||
size_control (label);
|
||||
|
||||
if (label->is_hidden || label->display == NULL)
|
||||
return;
|
||||
|
||||
ply_pixel_display_draw_area (label->display,
|
||||
dirty_area.x, dirty_area.y,
|
||||
dirty_area.width, dirty_area.height);
|
||||
|
|
@ -233,7 +319,10 @@ draw_bitmap (ply_label_plugin_control_t *label,
|
|||
ply_rectangle_t target_size,
|
||||
FT_Bitmap *source,
|
||||
FT_Int x_start,
|
||||
FT_Int y_start)
|
||||
FT_Int y_start,
|
||||
uint8_t rs,
|
||||
uint8_t gs,
|
||||
uint8_t bs)
|
||||
{
|
||||
FT_Int x, y, xs, ys;
|
||||
FT_Int x_end = MIN (x_start + source->width, target_size.width);
|
||||
|
|
@ -243,10 +332,7 @@ draw_bitmap (ply_label_plugin_control_t *label,
|
|||
(uint32_t) y_start >= target_size.height)
|
||||
return;
|
||||
|
||||
uint8_t rs, gs, bs, rd, gd, bd, ad;
|
||||
rs = 255 * label->red;
|
||||
gs = 255 * label->green;
|
||||
bs = 255 * label->blue;
|
||||
uint8_t rd, gd, bd, ad;
|
||||
|
||||
for (y = y_start, ys = 0; y < y_end; ++y, ++ys) {
|
||||
for (x = x_start, xs = 0; x < x_end; ++x, ++xs) {
|
||||
|
|
@ -273,6 +359,67 @@ draw_bitmap (ply_label_plugin_control_t *label,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
look_up_rgb_color_from_terminal_color (ply_label_plugin_control_t *label,
|
||||
ply_terminal_color_t color,
|
||||
uint8_t *red,
|
||||
uint8_t *green,
|
||||
uint8_t *blue)
|
||||
{
|
||||
switch (color) {
|
||||
case PLY_TERMINAL_COLOR_BLACK:
|
||||
*red = 0x00;
|
||||
*green = 0x00;
|
||||
*blue = 0x00;
|
||||
break;
|
||||
/* Linux VT Color: 0xaa0000 */
|
||||
case PLY_TERMINAL_COLOR_RED:
|
||||
*red = 0xaa;
|
||||
*green = 0x00;
|
||||
*blue = 0x00;
|
||||
break;
|
||||
/* Linux VT Color: 0x00aa00 */
|
||||
case PLY_TERMINAL_COLOR_GREEN:
|
||||
*red = 0x00;
|
||||
*green = 0xaa;
|
||||
*blue = 0x00;
|
||||
break;
|
||||
/* Linux VT Color: 0xaa5500 */
|
||||
case PLY_TERMINAL_COLOR_BROWN:
|
||||
*red = 0xaa;
|
||||
*green = 0x55;
|
||||
*blue = 0x00;
|
||||
break;
|
||||
/* Linux VT Color: 0x0000aa */
|
||||
case PLY_TERMINAL_COLOR_BLUE:
|
||||
*red = 0x00;
|
||||
*green = 0x00;
|
||||
*blue = 0xaa;
|
||||
break;
|
||||
/* Linux VT Color: 0xaa00aa */
|
||||
case PLY_TERMINAL_COLOR_MAGENTA:
|
||||
*red = 0xaa;
|
||||
*green = 0x00;
|
||||
*blue = 0xaa;
|
||||
break;
|
||||
/* Linux VT Color: 0x00aaaa */
|
||||
case PLY_TERMINAL_COLOR_CYAN:
|
||||
*red = 0x00;
|
||||
*green = 0xaa;
|
||||
*blue = 0xaa;
|
||||
break;
|
||||
/* Linux VT Color: 0xaaaaaa */
|
||||
case PLY_TERMINAL_COLOR_WHITE:
|
||||
break;
|
||||
|
||||
default:
|
||||
*red = 255 * label->red;
|
||||
*green = 255 * label->green;
|
||||
*blue = 255 * label->blue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_control (ply_label_plugin_control_t *label,
|
||||
ply_pixel_buffer_t *pixel_buffer,
|
||||
|
|
@ -281,16 +428,19 @@ draw_control (ply_label_plugin_control_t *label,
|
|||
unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Vector pen;
|
||||
FT_GlyphSlot slot;
|
||||
const char *cur_c;
|
||||
ply_rich_text_iterator_t rich_text_iterator;
|
||||
ply_utf8_string_iterator_t utf8_string_iterator;
|
||||
uint32_t *target;
|
||||
ply_rectangle_t target_size;
|
||||
|
||||
if (label->is_hidden)
|
||||
return;
|
||||
|
||||
if (label->rich_text == NULL &&
|
||||
label->text == NULL)
|
||||
return;
|
||||
|
||||
/* Check for overlap.
|
||||
* TODO: Don't redraw everything if only a part should be drawn! */
|
||||
if (label->area.x > x + (long) width || label->area.y > y + (long) height
|
||||
|
|
@ -300,7 +450,16 @@ draw_control (ply_label_plugin_control_t *label,
|
|||
|
||||
slot = label->face->glyph;
|
||||
|
||||
cur_c = label->text;
|
||||
if (label->rich_text != NULL) {
|
||||
ply_rich_text_iterator_init (&rich_text_iterator,
|
||||
label->rich_text,
|
||||
&label->span);
|
||||
} else {
|
||||
ply_utf8_string_iterator_init (&utf8_string_iterator,
|
||||
label->text,
|
||||
0,
|
||||
ply_utf8_string_get_length (label->text, strlen (label->text)));
|
||||
}
|
||||
|
||||
target = ply_pixel_buffer_get_argb32_data (pixel_buffer);
|
||||
ply_pixel_buffer_get_size (pixel_buffer, &target_size);
|
||||
|
|
@ -315,50 +474,77 @@ draw_control (ply_label_plugin_control_t *label,
|
|||
pen.y += label->face->size->metrics.ascender;
|
||||
|
||||
/* Go through each line */
|
||||
while (*cur_c) {
|
||||
do {
|
||||
bool should_stop;
|
||||
const char *current_character;
|
||||
uint8_t red, green, blue;
|
||||
|
||||
FT_Int extraAdvance = 0, positiveBearingX = 0;
|
||||
ply_rich_text_character_t *rich_text_character;
|
||||
|
||||
red = 255 * label->red;
|
||||
green = 255 * label->green;
|
||||
blue = 255 * label->blue;
|
||||
|
||||
if (label->rich_text != NULL) {
|
||||
should_stop = !ply_rich_text_iterator_next (&rich_text_iterator,
|
||||
&rich_text_character);
|
||||
if (should_stop)
|
||||
break;
|
||||
|
||||
current_character = rich_text_character->bytes;
|
||||
|
||||
look_up_rgb_color_from_terminal_color (label,
|
||||
rich_text_character->style.foreground_color,
|
||||
&red,
|
||||
&green,
|
||||
&blue);
|
||||
} else {
|
||||
size_t character_size;
|
||||
|
||||
should_stop = !ply_utf8_string_iterator_next (&utf8_string_iterator,
|
||||
¤t_character,
|
||||
&character_size);
|
||||
}
|
||||
|
||||
if (*current_character == '\n')
|
||||
continue;
|
||||
|
||||
pen.x = label->area.x << 6;
|
||||
|
||||
/* Start at start position (alignment) */
|
||||
if (label->alignment == PLY_LABEL_ALIGN_CENTER)
|
||||
pen.x += (label->area.width - width_of_line (label, cur_c)) << 5;
|
||||
pen.x += (label->area.width - width_of_string (label, current_character)) << 5;
|
||||
else if (label->alignment == PLY_LABEL_ALIGN_RIGHT)
|
||||
pen.x += (label->area.width - width_of_line (label, cur_c)) << 6;
|
||||
pen.x += (label->area.width - width_of_string (label, current_character)) << 6;
|
||||
|
||||
while (*cur_c && *cur_c != '\n') {
|
||||
FT_Int extraAdvance = 0, positiveBearingX = 0;
|
||||
/* TODO: Unicode support. */
|
||||
error = FT_Load_Char (label->face, *cur_c,
|
||||
FT_LOAD_RENDER | FT_LOAD_TARGET_LIGHT);
|
||||
if (error)
|
||||
continue;
|
||||
if (!load_character (label, ¤t_character))
|
||||
continue;
|
||||
|
||||
/* We consider negative left bearing an increment in size,
|
||||
* as we draw full character boxes and don't "go back" in
|
||||
* this plugin. Positive left bearing is treated as usual.
|
||||
* For definitions see
|
||||
* https://freetype.org/freetype2/docs/glyphs/glyphs-3.html
|
||||
*/
|
||||
if (slot->bitmap_left < 0) {
|
||||
extraAdvance = -slot->bitmap_left;
|
||||
} else {
|
||||
positiveBearingX = slot->bitmap_left;
|
||||
}
|
||||
draw_bitmap (label, target, target_size, &slot->bitmap,
|
||||
(pen.x >> 6) + positiveBearingX,
|
||||
(pen.y >> 6) - slot->bitmap_top);
|
||||
/* We consider negative left bearing an increment in size,
|
||||
* as we draw full character boxes and don't "go back" in
|
||||
* this plugin. Positive left bearing is treated as usual.
|
||||
* For definitions see
|
||||
* https://freetype.org/freetype2/docs/glyphs/glyphs-3.html
|
||||
*/
|
||||
if (slot->bitmap_left < 0)
|
||||
extraAdvance = -slot->bitmap_left;
|
||||
else
|
||||
positiveBearingX = slot->bitmap_left;
|
||||
|
||||
pen.x += slot->advance.x + extraAdvance;
|
||||
pen.y += slot->advance.y;
|
||||
draw_bitmap (label, target, target_size, &slot->bitmap,
|
||||
(pen.x >> 6) + positiveBearingX,
|
||||
(pen.y >> 6) - slot->bitmap_top,
|
||||
red,
|
||||
green,
|
||||
blue);
|
||||
|
||||
++cur_c;
|
||||
}
|
||||
/* skip newline character */
|
||||
if (*cur_c)
|
||||
++cur_c;
|
||||
pen.x += slot->advance.x + extraAdvance;
|
||||
pen.y += slot->advance.y;
|
||||
|
||||
/* Next line */
|
||||
pen.y += label->face->size->metrics.height;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -381,28 +567,73 @@ set_width_for_control (ply_label_plugin_control_t *label,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_text (ply_label_plugin_control_t *label)
|
||||
{
|
||||
free (label->text);
|
||||
label->text = NULL;
|
||||
|
||||
if (label->rich_text != NULL) {
|
||||
ply_rich_text_drop_reference (label->rich_text);
|
||||
label->rich_text = NULL;
|
||||
label->span.offset = 0;
|
||||
label->span.range = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_text_for_control (ply_label_plugin_control_t *label,
|
||||
const char *text)
|
||||
{
|
||||
if (label->text != text) {
|
||||
free (label->text);
|
||||
clear_text (label);
|
||||
label->text = strdup (text);
|
||||
trigger_redraw (label, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_rich_text_for_control (ply_label_plugin_control_t *label,
|
||||
ply_rich_text_t *rich_text,
|
||||
ply_rich_text_span_t *span)
|
||||
{
|
||||
clear_text (label);
|
||||
|
||||
label->rich_text = rich_text;
|
||||
ply_rich_text_take_reference (rich_text);
|
||||
label->span = *span;
|
||||
|
||||
trigger_redraw (label, true);
|
||||
}
|
||||
|
||||
static void
|
||||
set_font_for_control (ply_label_plugin_control_t *label,
|
||||
const char *fontdesc)
|
||||
{
|
||||
/* Only able to set size */
|
||||
/* Only able to set size and monospaced/nonmonospaced */
|
||||
|
||||
int error = 0;
|
||||
char *size_str_after;
|
||||
const char *size_str;
|
||||
const char *size_str, *font_path;
|
||||
unsigned long size;
|
||||
bool size_in_pixels;
|
||||
|
||||
if (strstr (fontdesc, "Mono") || strstr (fontdesc, "mono")) {
|
||||
if (label->is_monospaced == false) {
|
||||
FT_Done_Face (label->face);
|
||||
font_path = query_fc_match_monospace ();
|
||||
error = set_font_with_fallback (label, font_path, MONOSPACE_FONT_FALLBACK);
|
||||
}
|
||||
} else {
|
||||
if (label->is_monospaced == true) {
|
||||
FT_Done_Face (label->face);
|
||||
font_path = query_fc_match ();
|
||||
error = set_font_with_fallback (label, font_path, FONT_FALLBACK);
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
FT_Done_Face (label->face);
|
||||
|
||||
size = 25; /* Default, if not set. */
|
||||
size_in_pixels = false;
|
||||
|
||||
|
|
@ -500,6 +731,7 @@ ply_label_plugin_get_interface (void)
|
|||
.draw_control = draw_control,
|
||||
.is_control_hidden = is_control_hidden,
|
||||
.set_text_for_control = set_text_for_control,
|
||||
.set_rich_text_for_control = set_rich_text_for_control,
|
||||
.set_alignment_for_control = set_alignment_for_control,
|
||||
.set_width_for_control = set_width_for_control,
|
||||
.set_font_for_control = set_font_for_control,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include <cairo.h>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#include "ply-terminal.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-utils.h"
|
||||
|
|
@ -56,9 +57,10 @@ struct _ply_label_plugin_control
|
|||
ply_rectangle_t area;
|
||||
|
||||
char *text;
|
||||
char *fontdesc;
|
||||
char *font;
|
||||
|
||||
PangoAlignment alignment;
|
||||
PangoAttrList *attribute_list;
|
||||
long width;
|
||||
float red;
|
||||
float green;
|
||||
|
|
@ -81,6 +83,7 @@ create_control (void)
|
|||
label->is_hidden = true;
|
||||
label->alignment = PANGO_ALIGN_LEFT;
|
||||
label->width = -1;
|
||||
label->attribute_list = pango_attr_list_new ();
|
||||
|
||||
return label;
|
||||
}
|
||||
|
|
@ -88,9 +91,19 @@ create_control (void)
|
|||
static void
|
||||
destroy_control (ply_label_plugin_control_t *label)
|
||||
{
|
||||
GSList *attributes, *attribute;
|
||||
|
||||
if (label == NULL)
|
||||
return;
|
||||
|
||||
if (label->attribute_list) {
|
||||
attributes = pango_attr_list_get_attributes (label->attribute_list);
|
||||
for (attribute = attributes; attribute; attribute = attribute->next) {
|
||||
pango_attribute_destroy (attribute->data);
|
||||
}
|
||||
pango_attr_list_unref (label->attribute_list);
|
||||
g_slist_free (attributes);
|
||||
}
|
||||
free (label);
|
||||
}
|
||||
|
||||
|
|
@ -164,11 +177,114 @@ get_cairo_context_for_sizing (ply_label_plugin_control_t *label)
|
|||
return cairo_context;
|
||||
}
|
||||
|
||||
void
|
||||
remove_hexboxes_from_pango_layout (PangoLayout *pango_layout)
|
||||
{
|
||||
PangoLayoutIter *iter;
|
||||
bool hexbox_removed = false;
|
||||
ply_buffer_t *buffer = ply_buffer_new ();
|
||||
const char *old_string = pango_layout_get_text (pango_layout);
|
||||
|
||||
iter = pango_layout_get_iter (pango_layout);
|
||||
|
||||
do {
|
||||
PangoLayoutRun *run;
|
||||
PangoGlyphItem *glyph_items;
|
||||
PangoGlyphString *glyph_string;
|
||||
|
||||
run = pango_layout_iter_get_run_readonly (iter);
|
||||
if (!run)
|
||||
continue;
|
||||
|
||||
glyph_items = (PangoGlyphItem *) run;
|
||||
glyph_string = glyph_items->glyphs;
|
||||
|
||||
if (glyph_string->num_glyphs == 0)
|
||||
continue;
|
||||
|
||||
for (size_t i = 0; i < glyph_string->num_glyphs; i++) {
|
||||
if (glyph_string->glyphs[i].glyph & PANGO_GLYPH_UNKNOWN_FLAG) {
|
||||
hexbox_removed = true;
|
||||
ply_buffer_append (buffer, "%c", '?');
|
||||
} else {
|
||||
ply_buffer_append_bytes (buffer, old_string + glyph_items->item->offset, glyph_items->item->length);
|
||||
}
|
||||
}
|
||||
} while (pango_layout_iter_next_run (iter));
|
||||
pango_layout_iter_free (iter);
|
||||
|
||||
if (hexbox_removed) {
|
||||
const char *new_string = ply_buffer_get_bytes (buffer);
|
||||
pango_layout_set_text (pango_layout, new_string, -1);
|
||||
}
|
||||
|
||||
ply_buffer_free (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
look_up_rgb_color_from_terminal_color (ply_terminal_color_t color,
|
||||
uint16_t *red,
|
||||
uint16_t *green,
|
||||
uint16_t *blue)
|
||||
{
|
||||
switch (color) {
|
||||
case PLY_TERMINAL_COLOR_BLACK:
|
||||
*red = 0x0000;
|
||||
*green = 0x0000;
|
||||
*blue = 0x0000;
|
||||
break;
|
||||
/* Linux VT Color: 0xaa0000 */
|
||||
case PLY_TERMINAL_COLOR_RED:
|
||||
*red = 0xaa00;
|
||||
*green = 0x0000;
|
||||
*blue = 0x0000;
|
||||
break;
|
||||
/* Linux VT Color: 0x00aa00 */
|
||||
case PLY_TERMINAL_COLOR_GREEN:
|
||||
*red = 0x0000;
|
||||
*green = 0xaa00;
|
||||
*blue = 0x0000;
|
||||
break;
|
||||
/* Linux VT Color: 0xaa5500 */
|
||||
case PLY_TERMINAL_COLOR_BROWN:
|
||||
*red = 0xaa00;
|
||||
*green = 0x5500;
|
||||
*blue = 0x0000;
|
||||
break;
|
||||
/* Linux VT Color: 0x0000aa */
|
||||
case PLY_TERMINAL_COLOR_BLUE:
|
||||
*red = 0x0000;
|
||||
*green = 0x0000;
|
||||
*blue = 0xaa00;
|
||||
break;
|
||||
/* Linux VT Color: 0xaa00aa */
|
||||
case PLY_TERMINAL_COLOR_MAGENTA:
|
||||
*red = 0xaa00;
|
||||
*green = 0x0000;
|
||||
*blue = 0xaa00;
|
||||
break;
|
||||
/* Linux VT Color: 0x00aaaa */
|
||||
case PLY_TERMINAL_COLOR_CYAN:
|
||||
*red = 0x0000;
|
||||
*green = 0xaa00;
|
||||
*blue = 0xaa00;
|
||||
break;
|
||||
/* Linux VT Color: 0xaaaaaa */
|
||||
case PLY_TERMINAL_COLOR_WHITE:
|
||||
default:
|
||||
*red = 0xaa00;
|
||||
*green = 0xaa00;
|
||||
*blue = 0xaa00;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static PangoLayout *
|
||||
init_pango_text_layout (cairo_t *cairo_context,
|
||||
char *text,
|
||||
char *font_description,
|
||||
PangoAlignment alignment,
|
||||
PangoAttrList *attribute_list,
|
||||
long width)
|
||||
{
|
||||
PangoLayout *pango_layout;
|
||||
|
|
@ -189,6 +305,7 @@ init_pango_text_layout (cairo_t *cairo_context,
|
|||
pango_layout_set_width (pango_layout, width * PANGO_SCALE);
|
||||
|
||||
pango_layout_set_text (pango_layout, text ?: "", -1);
|
||||
pango_layout_set_attributes (pango_layout, attribute_list);
|
||||
pango_cairo_update_layout (cairo_context, pango_layout);
|
||||
|
||||
return pango_layout;
|
||||
|
|
@ -213,7 +330,7 @@ size_control (ply_label_plugin_control_t *label,
|
|||
|
||||
cairo_context = get_cairo_context_for_sizing (label);
|
||||
|
||||
pango_layout = init_pango_text_layout (cairo_context, label->text, label->fontdesc, label->alignment, label->width);
|
||||
pango_layout = init_pango_text_layout (cairo_context, label->text, label->font, label->alignment, label->attribute_list, label->width);
|
||||
|
||||
pango_layout_get_size (pango_layout, &text_width, &text_height);
|
||||
label->area.width = (long) ((double) text_width / PANGO_SCALE);
|
||||
|
|
@ -244,7 +361,8 @@ draw_control (ply_label_plugin_control_t *label,
|
|||
|
||||
cairo_context = get_cairo_context_for_pixel_buffer (label, pixel_buffer, ¢er_x, ¢er_y);
|
||||
|
||||
pango_layout = init_pango_text_layout (cairo_context, label->text, label->fontdesc, label->alignment, label->width);
|
||||
pango_layout = init_pango_text_layout (cairo_context, label->text, label->font, label->alignment, label->attribute_list, label->width);
|
||||
remove_hexboxes_from_pango_layout (pango_layout);
|
||||
|
||||
pango_layout_get_size (pango_layout, &text_width, &text_height);
|
||||
label->area.width = (long) ((double) text_width / PANGO_SCALE);
|
||||
|
|
@ -316,8 +434,24 @@ set_width_for_control (ply_label_plugin_control_t *label,
|
|||
}
|
||||
|
||||
static void
|
||||
set_text_for_control (ply_label_plugin_control_t *label,
|
||||
const char *text)
|
||||
clear_text (ply_label_plugin_control_t *label)
|
||||
{
|
||||
GSList *attributes, *attribute;
|
||||
|
||||
if (label->attribute_list) {
|
||||
attributes = pango_attr_list_get_attributes (label->attribute_list);
|
||||
for (attribute = attributes; attribute; attribute = attribute->next) {
|
||||
pango_attribute_destroy (attribute->data);
|
||||
}
|
||||
pango_attr_list_unref (label->attribute_list);
|
||||
g_slist_free (attributes);
|
||||
label->attribute_list = pango_attr_list_new ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_text (ply_label_plugin_control_t *label,
|
||||
const char *text)
|
||||
{
|
||||
ply_rectangle_t dirty_area;
|
||||
|
||||
|
|
@ -333,19 +467,241 @@ set_text_for_control (ply_label_plugin_control_t *label,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_text_for_control (ply_label_plugin_control_t *label,
|
||||
const char *text)
|
||||
{
|
||||
clear_text (label);
|
||||
set_text (label, text);
|
||||
}
|
||||
|
||||
static void
|
||||
stage_pango_attribute_for_list (PangoAttrList *attribute_list,
|
||||
PangoAttribute **staged_attributes,
|
||||
PangoAttribute *new_attribute)
|
||||
{
|
||||
PangoAttrType attribute_type = new_attribute->klass->type;
|
||||
|
||||
if (staged_attributes[attribute_type] != NULL) {
|
||||
if (!pango_attribute_equal (staged_attributes[attribute_type], new_attribute)) {
|
||||
pango_attr_list_insert (attribute_list, staged_attributes[attribute_type]);
|
||||
staged_attributes[attribute_type] = new_attribute;
|
||||
} else {
|
||||
staged_attributes[attribute_type]->end_index = new_attribute->end_index;
|
||||
pango_attribute_destroy (new_attribute);
|
||||
}
|
||||
} else {
|
||||
staged_attributes[attribute_type] = new_attribute;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
flush_pango_attributes_to_list (PangoAttrList *attribute_list,
|
||||
PangoAttribute **staged_attributes)
|
||||
{
|
||||
for (size_t i = 0; i <= PANGO_ATTR_FONT_SCALE; i++) {
|
||||
if (staged_attributes[i] == NULL)
|
||||
continue;
|
||||
|
||||
pango_attr_list_insert (attribute_list, staged_attributes[i]);
|
||||
staged_attributes[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_rich_text_for_control (ply_label_plugin_control_t *label,
|
||||
ply_rich_text_t *rich_text,
|
||||
ply_rich_text_span_t *span)
|
||||
{
|
||||
int i;
|
||||
size_t start_index = 0;
|
||||
size_t length;
|
||||
char *string;
|
||||
PangoAttribute *staged_attributes[PANGO_ATTR_FONT_SCALE + 1] = { NULL };
|
||||
ply_rich_text_character_t **characters;
|
||||
|
||||
clear_text (label);
|
||||
if (label->attribute_list) {
|
||||
pango_attr_list_unref (label->attribute_list);
|
||||
label->attribute_list = pango_attr_list_new ();
|
||||
}
|
||||
|
||||
characters = ply_rich_text_get_characters (rich_text);
|
||||
for (i = span->offset; characters[i] != NULL; i++) {
|
||||
PangoAttribute *pango_attribute = NULL;
|
||||
uint16_t foreground_red, background_red;
|
||||
uint16_t foreground_green, background_green;
|
||||
uint16_t foreground_blue, background_blue;
|
||||
|
||||
length = characters[i]->length;
|
||||
|
||||
PangoWeight bold_style = PANGO_WEIGHT_NORMAL;
|
||||
PangoStyle italic_style = PANGO_STYLE_NORMAL;
|
||||
PangoUnderline underline_style = PANGO_UNDERLINE_NONE;
|
||||
|
||||
ply_terminal_color_t foreground_color = PLY_TERMINAL_COLOR_DEFAULT;
|
||||
ply_terminal_color_t background_color = PLY_TERMINAL_COLOR_DEFAULT;
|
||||
|
||||
if (!characters[i]->style.reverse_enabled) {
|
||||
foreground_color = characters[i]->style.foreground_color;
|
||||
background_color = characters[i]->style.background_color;
|
||||
} else {
|
||||
foreground_color = characters[i]->style.background_color;
|
||||
background_color = characters[i]->style.foreground_color;
|
||||
|
||||
/* if no background color is specified, the label is transparent.
|
||||
* When reversed, and the background color is default
|
||||
*/
|
||||
if (background_color == PLY_TERMINAL_COLOR_DEFAULT) {
|
||||
background_color = PLY_TERMINAL_COLOR_WHITE;
|
||||
|
||||
if (foreground_color == PLY_TERMINAL_COLOR_DEFAULT)
|
||||
foreground_color = PLY_TERMINAL_COLOR_BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Default to a black background when none is set so bright text is readable on bright backgrounds */
|
||||
if (background_color == PLY_TERMINAL_COLOR_DEFAULT)
|
||||
background_color = PLY_TERMINAL_COLOR_BLACK;
|
||||
|
||||
look_up_rgb_color_from_terminal_color (foreground_color,
|
||||
&foreground_red,
|
||||
&foreground_green,
|
||||
&foreground_blue);
|
||||
|
||||
look_up_rgb_color_from_terminal_color (background_color,
|
||||
&background_red,
|
||||
&background_green,
|
||||
&background_blue);
|
||||
|
||||
if (characters[i]->style.bold_enabled && characters[i]->style.dim_enabled) {
|
||||
/* xterm subtracts 0x44 when bold and dim*/
|
||||
if (foreground_red > 0x4400) {
|
||||
foreground_red -= 0x4400;
|
||||
} else {
|
||||
foreground_red = 0;
|
||||
}
|
||||
|
||||
if (foreground_green > 0x4400) {
|
||||
foreground_green -= 0x4400;
|
||||
} else {
|
||||
foreground_green = 0;
|
||||
}
|
||||
|
||||
if (foreground_blue > 0x4400) {
|
||||
foreground_blue -= 0x4400;
|
||||
} else {
|
||||
foreground_blue = 0;
|
||||
}
|
||||
bold_style = PANGO_WEIGHT_SEMIBOLD;
|
||||
} else {
|
||||
if (characters[i]->style.bold_enabled) {
|
||||
/* Linux VT adds 0x55 when bold */
|
||||
if (foreground_red + 0x55ff < 0xffff) {
|
||||
foreground_red += 0x55ff;
|
||||
} else {
|
||||
foreground_red = 0xffff;
|
||||
}
|
||||
|
||||
if (foreground_green + 0x55ff < 0xffff) {
|
||||
foreground_green += 0x55ff;
|
||||
} else {
|
||||
foreground_green = 0xffff;
|
||||
}
|
||||
|
||||
if (foreground_blue + 0x55ff < 0xffff) {
|
||||
foreground_blue += 0x55ff;
|
||||
} else {
|
||||
foreground_blue = 0xffff;
|
||||
}
|
||||
bold_style = PANGO_WEIGHT_BOLD;
|
||||
}
|
||||
|
||||
if (characters[i]->style.dim_enabled) {
|
||||
/* xterm subtracts 0x23 when dim */
|
||||
if (foreground_red > 0x2300) {
|
||||
foreground_red -= 0x2300;
|
||||
} else {
|
||||
foreground_red = 0;
|
||||
}
|
||||
|
||||
if (foreground_green > 0x2300) {
|
||||
foreground_green -= 0x2300;
|
||||
} else {
|
||||
foreground_green = 0;
|
||||
}
|
||||
|
||||
if (foreground_blue > 0x2300) {
|
||||
foreground_blue -= 0x2300;
|
||||
} else {
|
||||
foreground_blue = 0;
|
||||
}
|
||||
bold_style = PANGO_WEIGHT_LIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
if (foreground_color != PLY_TERMINAL_COLOR_DEFAULT) {
|
||||
pango_attribute = pango_attr_foreground_new (foreground_red, foreground_green, foreground_blue);
|
||||
pango_attribute->start_index = start_index;
|
||||
pango_attribute->end_index = start_index + length;
|
||||
|
||||
stage_pango_attribute_for_list (label->attribute_list, staged_attributes, pango_attribute);
|
||||
}
|
||||
|
||||
if (background_color != PLY_TERMINAL_COLOR_DEFAULT) {
|
||||
pango_attribute = pango_attr_background_new (background_red, background_green, background_blue);
|
||||
pango_attribute->start_index = start_index;
|
||||
pango_attribute->end_index = start_index + length;
|
||||
stage_pango_attribute_for_list (label->attribute_list, staged_attributes, pango_attribute);
|
||||
}
|
||||
|
||||
pango_attribute = pango_attr_weight_new (bold_style);
|
||||
pango_attribute->start_index = start_index;
|
||||
pango_attribute->end_index = start_index + length;
|
||||
stage_pango_attribute_for_list (label->attribute_list, staged_attributes, pango_attribute);
|
||||
|
||||
|
||||
if (characters[i]->style.italic_enabled == true)
|
||||
italic_style = PANGO_STYLE_ITALIC;
|
||||
|
||||
pango_attribute = pango_attr_style_new (italic_style);
|
||||
pango_attribute->start_index = start_index;
|
||||
pango_attribute->end_index = start_index + length;
|
||||
stage_pango_attribute_for_list (label->attribute_list, staged_attributes, pango_attribute);
|
||||
|
||||
if (characters[i]->style.underline_enabled == true)
|
||||
underline_style = PANGO_UNDERLINE_SINGLE;
|
||||
|
||||
pango_attribute = pango_attr_underline_new (underline_style);
|
||||
pango_attribute->start_index = start_index;
|
||||
pango_attribute->end_index = start_index + length;
|
||||
stage_pango_attribute_for_list (label->attribute_list, staged_attributes, pango_attribute);
|
||||
|
||||
start_index += length;
|
||||
|
||||
if (i >= span->offset + span->range)
|
||||
break;
|
||||
}
|
||||
flush_pango_attributes_to_list (label->attribute_list, staged_attributes);
|
||||
|
||||
string = ply_rich_text_get_string (rich_text, span);
|
||||
set_text (label, string);
|
||||
free (string);
|
||||
}
|
||||
|
||||
static void
|
||||
set_font_for_control (ply_label_plugin_control_t *label,
|
||||
const char *fontdesc)
|
||||
const char *font)
|
||||
{
|
||||
ply_rectangle_t dirty_area;
|
||||
|
||||
if (label->fontdesc != fontdesc) {
|
||||
if (label->font != font) {
|
||||
dirty_area = label->area;
|
||||
free (label->fontdesc);
|
||||
if (fontdesc)
|
||||
label->fontdesc = strdup (fontdesc);
|
||||
free (label->font);
|
||||
if (font)
|
||||
label->font = strdup (font);
|
||||
else
|
||||
label->fontdesc = NULL;
|
||||
label->font = NULL;
|
||||
size_control (label, false);
|
||||
if (!label->is_hidden && label->display != NULL)
|
||||
ply_pixel_display_draw_area (label->display,
|
||||
|
|
@ -444,6 +800,7 @@ ply_label_plugin_get_interface (void)
|
|||
.draw_control = draw_control,
|
||||
.is_control_hidden = is_control_hidden,
|
||||
.set_text_for_control = set_text_for_control,
|
||||
.set_rich_text_for_control = set_rich_text_for_control,
|
||||
.set_alignment_for_control = set_alignment_for_control,
|
||||
.set_width_for_control = set_width_for_control,
|
||||
.set_font_for_control = set_font_for_control,
|
||||
|
|
@ -454,4 +811,3 @@ ply_label_plugin_get_interface (void)
|
|||
|
||||
return &plugin_interface;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
#include "ply-pixel-display.h"
|
||||
#include "ply-trigger.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-console-viewer.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
|
|
@ -59,7 +60,6 @@
|
|||
#define FRAMES_PER_SECOND 30
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLY_BOOT_SPLASH_DISPLAY_NORMAL,
|
||||
|
|
@ -86,6 +86,8 @@ typedef struct
|
|||
ply_label_t *message_label;
|
||||
ply_rectangle_t lock_area;
|
||||
double logo_opacity;
|
||||
|
||||
ply_console_viewer_t *console_viewer;
|
||||
} view_t;
|
||||
|
||||
struct _ply_boot_splash_plugin
|
||||
|
|
@ -105,9 +107,25 @@ struct _ply_boot_splash_plugin
|
|||
|
||||
uint32_t is_animating : 1;
|
||||
uint32_t is_visible : 1;
|
||||
|
||||
char *monospace_font;
|
||||
uint32_t plugin_console_messages_updating : 1;
|
||||
uint32_t should_show_console_messages : 1;
|
||||
ply_buffer_t *boot_buffer;
|
||||
uint32_t console_text_color;
|
||||
};
|
||||
|
||||
ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void);
|
||||
static bool validate_input (ply_boot_splash_plugin_t *plugin,
|
||||
const char *entry_text,
|
||||
const char *add_text);
|
||||
static void on_boot_output (ply_boot_splash_plugin_t *plugin,
|
||||
const char *output,
|
||||
size_t size);
|
||||
static void toggle_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
static void display_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
static void hide_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
static void unhide_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
|
||||
static void
|
||||
view_show_prompt (view_t *view,
|
||||
|
|
@ -183,6 +201,20 @@ create_plugin (ply_key_file_t *key_file)
|
|||
plugin->lock_image = ply_image_new (image_path);
|
||||
free (image_path);
|
||||
|
||||
plugin->plugin_console_messages_updating = false;
|
||||
plugin->should_show_console_messages = false;
|
||||
|
||||
/* Likely only able to set the font if the font is in the initrd */
|
||||
plugin->monospace_font = ply_key_file_get_value (key_file, "two-step", "MonospaceFont");
|
||||
|
||||
if (plugin->monospace_font == NULL)
|
||||
plugin->monospace_font = strdup ("monospace 10");
|
||||
|
||||
plugin->console_text_color =
|
||||
ply_key_file_get_long (key_file, "two-step",
|
||||
"ConsoleLogTextColor",
|
||||
PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR);
|
||||
|
||||
plugin->image_dir = image_dir;
|
||||
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
|
||||
|
|
@ -255,6 +287,16 @@ view_new (ply_boot_splash_plugin_t *plugin,
|
|||
|
||||
view->message_label = ply_label_new ();
|
||||
|
||||
if (ply_console_viewer_preferred ()) {
|
||||
view->console_viewer = ply_console_viewer_new (view->display, plugin->monospace_font);
|
||||
ply_console_viewer_set_text_color (view->console_viewer, plugin->console_text_color);
|
||||
|
||||
if (plugin->boot_buffer)
|
||||
ply_console_viewer_convert_boot_buffer (view->console_viewer, plugin->boot_buffer);
|
||||
} else {
|
||||
view->console_viewer = NULL;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
@ -265,6 +307,9 @@ view_free (view_t *view)
|
|||
ply_label_free (view->message_label);
|
||||
free_stars (view);
|
||||
|
||||
if (view->console_viewer)
|
||||
ply_console_viewer_free (view->console_viewer);
|
||||
|
||||
ply_pixel_display_set_draw_handler (view->display, NULL, NULL);
|
||||
|
||||
free (view);
|
||||
|
|
@ -419,6 +464,7 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
ply_image_free (plugin->logo_image);
|
||||
ply_image_free (plugin->star_image);
|
||||
ply_image_free (plugin->lock_image);
|
||||
free (plugin->monospace_font);
|
||||
free (plugin);
|
||||
}
|
||||
|
||||
|
|
@ -740,6 +786,10 @@ on_draw (view_t *view,
|
|||
ply_label_draw_area (view->message_label,
|
||||
pixel_buffer,
|
||||
x, y, width, height);
|
||||
|
||||
if (plugin->plugin_console_messages_updating == false && view->console_viewer) {
|
||||
ply_console_viewer_draw_area (view->console_viewer, pixel_buffer, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -794,12 +844,31 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
ply_buffer_t *boot_buffer,
|
||||
ply_boot_splash_mode_t mode)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->logo_image != NULL);
|
||||
|
||||
plugin->loop = loop;
|
||||
plugin->mode = mode;
|
||||
|
||||
if (boot_buffer && ply_console_viewer_preferred ()) {
|
||||
plugin->boot_buffer = boot_buffer;
|
||||
|
||||
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);
|
||||
|
||||
ply_console_viewer_convert_boot_buffer (view->console_viewer, plugin->boot_buffer);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
ply_trace ("loading logo image");
|
||||
if (!ply_image_load (plugin->logo_image))
|
||||
return false;
|
||||
|
|
@ -965,6 +1034,7 @@ hide_splash_screen (ply_boot_splash_plugin_t *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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1040,7 +1110,12 @@ display_normal (ply_boot_splash_plugin_t *plugin)
|
|||
hide_prompt (plugin);
|
||||
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
|
||||
start_animation (plugin);
|
||||
if (!plugin->should_show_console_messages) {
|
||||
start_animation (plugin);
|
||||
} else {
|
||||
unhide_console_messages (plugin);
|
||||
}
|
||||
|
||||
redraw_views (plugin);
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
|
@ -1083,6 +1158,101 @@ display_message (ply_boot_splash_plugin_t *plugin,
|
|||
show_message (plugin, message);
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_input (ply_boot_splash_plugin_t *plugin,
|
||||
const char *entry_text,
|
||||
const char *add_text)
|
||||
{
|
||||
if (!ply_console_viewer_preferred ())
|
||||
return true;
|
||||
|
||||
if (strcmp (add_text, "\e") == 0) {
|
||||
toggle_console_messages (plugin);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
toggle_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
if (plugin->should_show_console_messages) {
|
||||
plugin->should_show_console_messages = false;
|
||||
hide_console_messages (plugin);
|
||||
} else {
|
||||
unhide_console_messages (plugin);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
view_t *view;
|
||||
|
||||
pause_views (plugin);
|
||||
|
||||
plugin->plugin_console_messages_updating = true;
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL) {
|
||||
view = ply_list_node_get_data (node);
|
||||
ply_console_viewer_show (view->console_viewer, view->display);
|
||||
node = ply_list_get_next_node (plugin->views, node);
|
||||
}
|
||||
plugin->plugin_console_messages_updating = false;
|
||||
|
||||
redraw_views (plugin);
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
unhide_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
plugin->should_show_console_messages = true;
|
||||
stop_animation (plugin);
|
||||
display_console_messages (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
hide_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
view_t *view;
|
||||
|
||||
plugin->should_show_console_messages = false;
|
||||
|
||||
plugin->plugin_console_messages_updating = true;
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL) {
|
||||
view = ply_list_node_get_data (node);
|
||||
ply_console_viewer_hide (view->console_viewer);
|
||||
node = ply_list_get_next_node (plugin->views, node);
|
||||
}
|
||||
plugin->plugin_console_messages_updating = false;
|
||||
if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
|
||||
start_animation (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
on_boot_output (ply_boot_splash_plugin_t *plugin,
|
||||
const char *output,
|
||||
size_t size)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
view_t *view;
|
||||
|
||||
if (!ply_console_viewer_preferred ())
|
||||
return;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL) {
|
||||
view = ply_list_node_get_data (node);
|
||||
ply_console_viewer_parse_lines (view->console_viewer, output, size);
|
||||
node = ply_list_get_next_node (plugin->views, node);
|
||||
}
|
||||
}
|
||||
|
||||
ply_boot_splash_plugin_interface_t *
|
||||
ply_boot_splash_plugin_get_interface (void)
|
||||
{
|
||||
|
|
@ -1099,6 +1269,8 @@ ply_boot_splash_plugin_get_interface (void)
|
|||
.display_password = display_password,
|
||||
.display_question = display_question,
|
||||
.display_message = display_message,
|
||||
.on_boot_output = on_boot_output,
|
||||
.validate_input = validate_input,
|
||||
};
|
||||
|
||||
return &plugin_interface;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
#include "ply-pixel-display.h"
|
||||
#include "ply-trigger.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-console-viewer.h"
|
||||
|
||||
#ifndef FRAMES_PER_SECOND
|
||||
#define FRAMES_PER_SECOND 40
|
||||
|
|
@ -168,6 +169,8 @@ typedef struct
|
|||
ply_list_t *sprites;
|
||||
ply_rectangle_t box_area, lock_area, logo_area;
|
||||
ply_image_t *scaled_background_image;
|
||||
|
||||
ply_console_viewer_t *console_viewer;
|
||||
} view_t;
|
||||
|
||||
struct _ply_boot_splash_plugin
|
||||
|
|
@ -202,10 +205,26 @@ struct _ply_boot_splash_plugin
|
|||
uint32_t root_is_mounted : 1;
|
||||
uint32_t is_visible : 1;
|
||||
uint32_t is_animating : 1;
|
||||
|
||||
char *monospace_font;
|
||||
uint32_t plugin_console_messages_updating : 1;
|
||||
uint32_t should_show_console_messages : 1;
|
||||
ply_buffer_t *boot_buffer;
|
||||
uint32_t console_text_color;
|
||||
};
|
||||
|
||||
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);
|
||||
static bool validate_input (ply_boot_splash_plugin_t *plugin,
|
||||
const char *entry_text,
|
||||
const char *add_text);
|
||||
static void on_boot_output (ply_boot_splash_plugin_t *plugin,
|
||||
const char *output,
|
||||
size_t size);
|
||||
static void toggle_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
static void display_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
static void hide_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
static void unhide_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
|
||||
static view_t *
|
||||
view_new (ply_boot_splash_plugin_t *plugin,
|
||||
|
|
@ -223,6 +242,16 @@ view_new (ply_boot_splash_plugin_t *plugin,
|
|||
|
||||
view->sprites = ply_list_new ();
|
||||
|
||||
if (ply_console_viewer_preferred ()) {
|
||||
view->console_viewer = ply_console_viewer_new (view->display, plugin->monospace_font);
|
||||
ply_console_viewer_set_text_color (view->console_viewer, plugin->console_text_color);
|
||||
|
||||
if (plugin->boot_buffer)
|
||||
ply_console_viewer_convert_boot_buffer (view->console_viewer, plugin->boot_buffer);
|
||||
} else {
|
||||
view->console_viewer = NULL;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
@ -237,6 +266,9 @@ view_free (view_t *view)
|
|||
view_free_sprites (view);
|
||||
ply_list_free (view->sprites);
|
||||
|
||||
if (view->console_viewer)
|
||||
ply_console_viewer_free (view->console_viewer);
|
||||
|
||||
ply_image_free (view->scaled_background_image);
|
||||
|
||||
free (view);
|
||||
|
|
@ -541,6 +573,21 @@ create_plugin (ply_key_file_t *key_file)
|
|||
plugin->progress_barimage = ply_image_new (image_path);
|
||||
free (image_path);
|
||||
#endif
|
||||
|
||||
plugin->plugin_console_messages_updating = false;
|
||||
plugin->should_show_console_messages = false;
|
||||
|
||||
/* Likely only able to set the font if the font is in the initrd */
|
||||
plugin->monospace_font = ply_key_file_get_value (key_file, "two-step", "MonospaceFont");
|
||||
|
||||
if (plugin->monospace_font == NULL)
|
||||
plugin->monospace_font = strdup ("monospace 10");
|
||||
|
||||
plugin->console_text_color =
|
||||
ply_key_file_get_long (key_file, "two-step",
|
||||
"ConsoleLogTextColor",
|
||||
PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR);
|
||||
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
|
||||
plugin->progress = 0;
|
||||
plugin->progress_target = -1;
|
||||
|
|
@ -564,6 +611,7 @@ destroy_plugin (ply_boot_splash_plugin_t *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);
|
||||
}
|
||||
|
||||
|
|
@ -583,6 +631,8 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
ply_image_free (plugin->progress_barimage);
|
||||
#endif
|
||||
|
||||
free (plugin->monospace_font);
|
||||
|
||||
free_views (plugin);
|
||||
|
||||
free (plugin);
|
||||
|
|
@ -1346,6 +1396,10 @@ on_draw (view_t *view,
|
|||
ply_label_draw_area (view->message_label,
|
||||
pixel_buffer,
|
||||
x, y, width, height);
|
||||
|
||||
if (plugin->plugin_console_messages_updating == false && view->console_viewer) {
|
||||
ply_console_viewer_draw_area (view->console_viewer, pixel_buffer, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1623,12 +1677,31 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
ply_buffer_t *boot_buffer,
|
||||
ply_boot_splash_mode_t mode)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->logo_image != NULL);
|
||||
|
||||
plugin->loop = loop;
|
||||
plugin->mode = mode;
|
||||
|
||||
if (boot_buffer && ply_console_viewer_preferred ()) {
|
||||
plugin->boot_buffer = boot_buffer;
|
||||
|
||||
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);
|
||||
|
||||
ply_console_viewer_convert_boot_buffer (view->console_viewer, plugin->boot_buffer);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
ply_trace ("loading logo image");
|
||||
if (!ply_image_load (plugin->logo_image))
|
||||
return false;
|
||||
|
|
@ -1795,7 +1868,12 @@ display_normal (ply_boot_splash_plugin_t *plugin)
|
|||
hide_prompt (plugin);
|
||||
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
|
||||
start_animation (plugin);
|
||||
if (!plugin->should_show_console_messages) {
|
||||
start_animation (plugin);
|
||||
} else {
|
||||
unhide_console_messages (plugin);
|
||||
}
|
||||
|
||||
redraw_views (plugin);
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
|
@ -1837,6 +1915,101 @@ display_message (ply_boot_splash_plugin_t *plugin,
|
|||
show_message (plugin, message);
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_input (ply_boot_splash_plugin_t *plugin,
|
||||
const char *entry_text,
|
||||
const char *add_text)
|
||||
{
|
||||
if (!ply_console_viewer_preferred ())
|
||||
return true;
|
||||
|
||||
if (strcmp (add_text, "\e") == 0) {
|
||||
toggle_console_messages (plugin);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
toggle_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
if (plugin->should_show_console_messages) {
|
||||
plugin->should_show_console_messages = false;
|
||||
hide_console_messages (plugin);
|
||||
} else {
|
||||
unhide_console_messages (plugin);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
view_t *view;
|
||||
|
||||
pause_views (plugin);
|
||||
|
||||
plugin->plugin_console_messages_updating = true;
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL) {
|
||||
view = ply_list_node_get_data (node);
|
||||
ply_console_viewer_show (view->console_viewer, view->display);
|
||||
node = ply_list_get_next_node (plugin->views, node);
|
||||
}
|
||||
plugin->plugin_console_messages_updating = false;
|
||||
|
||||
redraw_views (plugin);
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
unhide_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
plugin->should_show_console_messages = true;
|
||||
stop_animation (plugin);
|
||||
display_console_messages (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
hide_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
view_t *view;
|
||||
|
||||
plugin->should_show_console_messages = false;
|
||||
|
||||
plugin->plugin_console_messages_updating = true;
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL) {
|
||||
view = ply_list_node_get_data (node);
|
||||
ply_console_viewer_hide (view->console_viewer);
|
||||
node = ply_list_get_next_node (plugin->views, node);
|
||||
}
|
||||
plugin->plugin_console_messages_updating = false;
|
||||
if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
|
||||
start_animation (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
on_boot_output (ply_boot_splash_plugin_t *plugin,
|
||||
const char *output,
|
||||
size_t size)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
view_t *view;
|
||||
|
||||
if (!ply_console_viewer_preferred ())
|
||||
return;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL) {
|
||||
view = ply_list_node_get_data (node);
|
||||
ply_console_viewer_parse_lines (view->console_viewer, output, size);
|
||||
node = ply_list_get_next_node (plugin->views, node);
|
||||
}
|
||||
}
|
||||
|
||||
ply_boot_splash_plugin_interface_t *
|
||||
ply_boot_splash_plugin_get_interface (void)
|
||||
{
|
||||
|
|
@ -1856,6 +2029,8 @@ ply_boot_splash_plugin_get_interface (void)
|
|||
.display_password = display_password,
|
||||
.display_question = display_question,
|
||||
.display_message = display_message,
|
||||
.on_boot_output = on_boot_output,
|
||||
.validate_input = validate_input,
|
||||
};
|
||||
|
||||
return &plugin_interface;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#include "ply-progress-animation.h"
|
||||
#include "ply-throbber.h"
|
||||
#include "ply-progress-bar.h"
|
||||
#include "ply-console-viewer.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
|
|
@ -113,6 +114,8 @@ typedef struct
|
|||
ply_trigger_t *end_trigger;
|
||||
ply_pixel_buffer_t *background_buffer;
|
||||
int animation_bottom;
|
||||
|
||||
ply_console_viewer_t *console_viewer;
|
||||
} view_t;
|
||||
|
||||
typedef struct
|
||||
|
|
@ -192,6 +195,12 @@ struct _ply_boot_splash_plugin
|
|||
uint32_t background_image_is_scaled : 1;
|
||||
uint32_t dialog_clears_firmware_background : 1;
|
||||
uint32_t message_below_animation : 1;
|
||||
|
||||
char *monospace_font;
|
||||
uint32_t plugin_console_messages_updating : 1;
|
||||
uint32_t should_show_console_messages : 1;
|
||||
ply_buffer_t *boot_buffer;
|
||||
uint32_t console_text_color;
|
||||
};
|
||||
|
||||
ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void);
|
||||
|
|
@ -204,6 +213,16 @@ static void become_idle (ply_boot_splash_plugin_t *plugin,
|
|||
ply_trigger_t *idle_trigger);
|
||||
static void view_show_message (view_t *view,
|
||||
const char *message);
|
||||
static bool validate_input (ply_boot_splash_plugin_t *plugin,
|
||||
const char *entry_text,
|
||||
const char *add_text);
|
||||
static void on_boot_output (ply_boot_splash_plugin_t *plugin,
|
||||
const char *output,
|
||||
size_t size);
|
||||
static void toggle_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
static void display_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
static void hide_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
static void unhide_console_messages (ply_boot_splash_plugin_t *plugin);
|
||||
|
||||
static view_t *
|
||||
view_new (ply_boot_splash_plugin_t *plugin,
|
||||
|
|
@ -244,6 +263,16 @@ view_new (ply_boot_splash_plugin_t *plugin,
|
|||
view->subtitle_label = ply_label_new ();
|
||||
ply_label_set_font (view->subtitle_label, plugin->font);
|
||||
|
||||
if (ply_console_viewer_preferred ()) {
|
||||
view->console_viewer = ply_console_viewer_new (view->display, plugin->monospace_font);
|
||||
ply_console_viewer_set_text_color (view->console_viewer, plugin->console_text_color);
|
||||
|
||||
if (plugin->boot_buffer)
|
||||
ply_console_viewer_convert_boot_buffer (view->console_viewer, plugin->boot_buffer);
|
||||
} else {
|
||||
view->console_viewer = NULL;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
@ -262,6 +291,9 @@ view_free (view_t *view)
|
|||
ply_label_free (view->title_label);
|
||||
ply_label_free (view->subtitle_label);
|
||||
|
||||
if (view->console_viewer)
|
||||
ply_console_viewer_free (view->console_viewer);
|
||||
|
||||
if (view->background_buffer != NULL)
|
||||
ply_pixel_buffer_free (view->background_buffer);
|
||||
|
||||
|
|
@ -1191,6 +1223,21 @@ create_plugin (ply_key_file_t *key_file)
|
|||
}
|
||||
free (transition);
|
||||
|
||||
plugin->plugin_console_messages_updating = false;
|
||||
plugin->should_show_console_messages = false;
|
||||
|
||||
/* Likely only able to set the font if the font is in the initrd */
|
||||
plugin->monospace_font = ply_key_file_get_value (key_file, "two-step", "MonospaceFont");
|
||||
|
||||
if (plugin->monospace_font == NULL)
|
||||
plugin->monospace_font = strdup ("monospace 10");
|
||||
|
||||
|
||||
plugin->console_text_color =
|
||||
ply_key_file_get_long (key_file, "two-step",
|
||||
"ConsoleLogTextColor",
|
||||
PLY_CONSOLE_VIEWER_LOG_TEXT_COLOR);
|
||||
|
||||
plugin->transition_duration =
|
||||
ply_key_file_get_double (key_file, "two-step",
|
||||
"TransitionDuration", 0.0);
|
||||
|
|
@ -1314,6 +1361,7 @@ destroy_plugin (ply_boot_splash_plugin_t *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);
|
||||
}
|
||||
|
||||
|
|
@ -1347,6 +1395,7 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
|
||||
free (plugin->font);
|
||||
free (plugin->title_font);
|
||||
free (plugin->monospace_font);
|
||||
free (plugin->animation_dir);
|
||||
free_views (plugin);
|
||||
free (plugin);
|
||||
|
|
@ -1514,6 +1563,9 @@ draw_background (view_t *view,
|
|||
using_fw_background && plugin->dialog_clears_firmware_background)
|
||||
use_black_background = true;
|
||||
|
||||
if (plugin->should_show_console_messages)
|
||||
use_black_background = true;
|
||||
|
||||
if (use_black_background)
|
||||
ply_pixel_buffer_fill_with_hex_color (pixel_buffer, &area, 0);
|
||||
else if (view->background_buffer != NULL)
|
||||
|
|
@ -1526,6 +1578,9 @@ draw_background (view_t *view,
|
|||
ply_pixel_buffer_fill_with_hex_color (pixel_buffer, &area,
|
||||
plugin->background_start_color);
|
||||
|
||||
if (plugin->should_show_console_messages)
|
||||
return;
|
||||
|
||||
if (plugin->watermark_image != NULL) {
|
||||
uint32_t *data;
|
||||
|
||||
|
|
@ -1648,6 +1703,10 @@ on_draw (view_t *view,
|
|||
ply_label_draw_area (view->message_label,
|
||||
pixel_buffer,
|
||||
x, y, width, height);
|
||||
|
||||
if (!plugin->plugin_console_messages_updating && view->console_viewer) {
|
||||
ply_console_viewer_draw_area (view->console_viewer, pixel_buffer, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1707,11 +1766,30 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
ply_buffer_t *boot_buffer,
|
||||
ply_boot_splash_mode_t mode)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (plugin != NULL);
|
||||
|
||||
plugin->loop = loop;
|
||||
plugin->mode = mode;
|
||||
|
||||
if (boot_buffer && ply_console_viewer_preferred ()) {
|
||||
plugin->boot_buffer = boot_buffer;
|
||||
|
||||
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);
|
||||
|
||||
ply_console_viewer_convert_boot_buffer (view->console_viewer, plugin->boot_buffer);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
ply_trace ("loading lock image");
|
||||
if (!ply_image_load (plugin->lock_image))
|
||||
return false;
|
||||
|
|
@ -2053,7 +2131,13 @@ display_normal (ply_boot_splash_plugin_t *plugin)
|
|||
hide_prompt (plugin);
|
||||
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
|
||||
start_progress_animation (plugin);
|
||||
|
||||
if (!plugin->should_show_console_messages) {
|
||||
start_progress_animation (plugin);
|
||||
} else {
|
||||
unhide_console_messages (plugin);
|
||||
}
|
||||
|
||||
redraw_views (plugin);
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
|
@ -2095,6 +2179,101 @@ display_message (ply_boot_splash_plugin_t *plugin,
|
|||
show_message (plugin, message);
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_input (ply_boot_splash_plugin_t *plugin,
|
||||
const char *entry_text,
|
||||
const char *add_text)
|
||||
{
|
||||
if (!ply_console_viewer_preferred ())
|
||||
return true;
|
||||
|
||||
if (strcmp (add_text, "\e") == 0) {
|
||||
toggle_console_messages (plugin);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
toggle_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
if (plugin->should_show_console_messages) {
|
||||
plugin->should_show_console_messages = false;
|
||||
hide_console_messages (plugin);
|
||||
} else {
|
||||
unhide_console_messages (plugin);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
view_t *view;
|
||||
|
||||
pause_views (plugin);
|
||||
|
||||
plugin->plugin_console_messages_updating = true;
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL) {
|
||||
view = ply_list_node_get_data (node);
|
||||
ply_console_viewer_show (view->console_viewer, view->display);
|
||||
node = ply_list_get_next_node (plugin->views, node);
|
||||
}
|
||||
plugin->plugin_console_messages_updating = false;
|
||||
|
||||
redraw_views (plugin);
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
unhide_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
plugin->should_show_console_messages = true;
|
||||
stop_animation (plugin);
|
||||
display_console_messages (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
hide_console_messages (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
view_t *view;
|
||||
|
||||
plugin->should_show_console_messages = false;
|
||||
|
||||
plugin->plugin_console_messages_updating = true;
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL) {
|
||||
view = ply_list_node_get_data (node);
|
||||
ply_console_viewer_hide (view->console_viewer);
|
||||
node = ply_list_get_next_node (plugin->views, node);
|
||||
}
|
||||
plugin->plugin_console_messages_updating = false;
|
||||
if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
|
||||
start_progress_animation (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
on_boot_output (ply_boot_splash_plugin_t *plugin,
|
||||
const char *output,
|
||||
size_t size)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
view_t *view;
|
||||
|
||||
if (!ply_console_viewer_preferred ())
|
||||
return;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL) {
|
||||
view = ply_list_node_get_data (node);
|
||||
ply_console_viewer_parse_lines (view->console_viewer, output, size);
|
||||
node = ply_list_get_next_node (plugin->views, node);
|
||||
}
|
||||
}
|
||||
|
||||
ply_boot_splash_plugin_interface_t *
|
||||
ply_boot_splash_plugin_get_interface (void)
|
||||
{
|
||||
|
|
@ -2115,6 +2294,8 @@ ply_boot_splash_plugin_get_interface (void)
|
|||
.display_question = display_question,
|
||||
.display_message = display_message,
|
||||
.system_update = system_update,
|
||||
.on_boot_output = on_boot_output,
|
||||
.validate_input = validate_input,
|
||||
};
|
||||
|
||||
return &plugin_interface;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue