mirror of
https://gitlab.freedesktop.org/plymouth/plymouth.git
synced 2026-05-08 13:38:45 +02:00
[branch-merge] Support multi-head renderering
This merges the "seat-rework" branch to master. Instead of talking to /dev/fb, we now use libdrm to set up the drawing area. This gives us the functionality we need for querying the user's monitor layout. There are cases where /dev/fb works when the new interfaces don't. For those cases we fall back to /dev/fb.
This commit is contained in:
commit
3fe3aabc7b
85 changed files with 11846 additions and 5544 deletions
|
|
@ -56,6 +56,10 @@ PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.12.0 ])
|
|||
AC_SUBST(GTK_CFLAGS)
|
||||
AC_SUBST(GTK_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES(DRM, [libdrm libdrm_intel libdrm_radeon libdrm_nouveau])
|
||||
AC_SUBST(DRM_CFLAGS)
|
||||
AC_SUBST(DRM_LIBS)
|
||||
|
||||
AC_ARG_ENABLE(tracing, AS_HELP_STRING([--enable-tracing],[enable verbose tracing code]),enable_tracing=$enableval,enable_tracing=yes)
|
||||
|
||||
if test x$enable_tracing = xyes; then
|
||||
|
|
@ -209,6 +213,9 @@ AC_OUTPUT([Makefile
|
|||
src/libplybootsplash/Makefile
|
||||
src/plymouth-1.pc
|
||||
src/plugins/Makefile
|
||||
src/plugins/renderers/Makefile
|
||||
src/plugins/renderers/frame-buffer/Makefile
|
||||
src/plugins/renderers/drm/Makefile
|
||||
src/plugins/splash/Makefile
|
||||
src/plugins/splash/throbgress/Makefile
|
||||
src/plugins/splash/fade-throbber/Makefile
|
||||
|
|
|
|||
|
|
@ -93,6 +93,9 @@ fi
|
|||
|
||||
inst ${PLYMOUTH_PLUGIN_PATH}/${PLYMOUTH_MODULE_NAME}.so $INITRDDIR
|
||||
|
||||
inst ${PLYMOUTH_PLUGIN_PATH}/renderers/drm.so $INITRDDIR
|
||||
inst ${PLYMOUTH_PLUGIN_PATH}/renderers/frame-buffer.so $INITRDDIR
|
||||
|
||||
if [ -d ${DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME} ]; then
|
||||
for x in ${DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME}/* ; do
|
||||
[ ! -f "$x" ] && break
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ libplydir = $(includedir)/plymouth-1/ply
|
|||
libply_HEADERS = \
|
||||
ply-event-loop.h \
|
||||
ply-command-parser.h \
|
||||
ply-frame-buffer.h \
|
||||
ply-buffer.h \
|
||||
ply-array.h \
|
||||
ply-bitarray.h \
|
||||
|
|
@ -23,7 +22,8 @@ libply_HEADERS = \
|
|||
ply-logger.h \
|
||||
ply-key-file.h \
|
||||
ply-progress.h \
|
||||
ply-terminal.h \
|
||||
ply-rectangle.h \
|
||||
ply-region.h \
|
||||
ply-terminal-session.h \
|
||||
ply-trigger.h \
|
||||
ply-utils.h
|
||||
|
|
@ -36,7 +36,6 @@ libply_la_LDFLAGS = -export-symbols-regex '^[^_].*' \
|
|||
libply_la_SOURCES = ply-event-loop.c \
|
||||
$(libply_HEADERS) \
|
||||
ply-command-parser.c \
|
||||
ply-frame-buffer.c \
|
||||
ply-buffer.c \
|
||||
ply-array.c \
|
||||
ply-bitarray.c \
|
||||
|
|
@ -45,7 +44,8 @@ libply_la_SOURCES = ply-event-loop.c \
|
|||
ply-logger.c \
|
||||
ply-key-file.c \
|
||||
ply-progress.c \
|
||||
ply-terminal.c \
|
||||
ply-rectangle.c \
|
||||
ply-region.c \
|
||||
ply-terminal-session.c \
|
||||
ply-trigger.c \
|
||||
ply-utils.c
|
||||
|
|
|
|||
|
|
@ -489,6 +489,17 @@ ply_event_loop_new (void)
|
|||
return loop;
|
||||
}
|
||||
|
||||
ply_event_loop_t *
|
||||
ply_event_loop_get_default (void)
|
||||
{
|
||||
static ply_event_loop_t *loop = NULL;
|
||||
|
||||
if (loop == NULL)
|
||||
loop = ply_event_loop_new ();
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_event_loop_free_exit_closures (ply_event_loop_t *loop)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ typedef void (* ply_event_loop_timeout_handler_t) (void *user_data,
|
|||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_event_loop_t *ply_event_loop_new (void);
|
||||
void ply_event_loop_free (ply_event_loop_t *loop);
|
||||
ply_event_loop_t *ply_event_loop_get_default (void);
|
||||
ply_fd_watch_t *ply_event_loop_watch_fd (ply_event_loop_t *loop,
|
||||
int fd,
|
||||
ply_event_loop_fd_status_t status,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,112 +0,0 @@
|
|||
/* ply-frame-buffer.h - framebuffer abstraction
|
||||
*
|
||||
* Copyright (C) 2007 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_FRAME_BUFFER_H
|
||||
#define PLY_FRAME_BUFFER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ply-utils.h"
|
||||
|
||||
typedef struct _ply_frame_buffer ply_frame_buffer_t;
|
||||
typedef struct _ply_frame_buffer_area ply_frame_buffer_area_t;
|
||||
|
||||
struct _ply_frame_buffer_area
|
||||
{
|
||||
long x;
|
||||
long y;
|
||||
unsigned long width;
|
||||
unsigned long height;
|
||||
};
|
||||
|
||||
#define PLY_FRAME_BUFFER_COLOR_TO_PIXEL_VALUE(r,g,b,a) \
|
||||
(((uint8_t) (CLAMP (a * 255.0, 0.0, 255.0)) << 24) \
|
||||
| ((uint8_t) (CLAMP (r * 255.0, 0.0, 255.0)) << 16) \
|
||||
| ((uint8_t) (CLAMP (g * 255.0, 0.0, 255.0)) << 8) \
|
||||
| ((uint8_t) (CLAMP (b * 255.0, 0.0, 255.0))))
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_frame_buffer_t *ply_frame_buffer_new (const char *device_name);
|
||||
void ply_frame_buffer_free (ply_frame_buffer_t *buffer);
|
||||
bool ply_frame_buffer_open (ply_frame_buffer_t *buffer);
|
||||
void ply_frame_buffer_pause_updates (ply_frame_buffer_t *buffer);
|
||||
bool ply_frame_buffer_unpause_updates (ply_frame_buffer_t *buffer);
|
||||
bool ply_frame_buffer_device_is_open (ply_frame_buffer_t *buffer);
|
||||
char *ply_frame_buffer_get_device_name (ply_frame_buffer_t *buffer);
|
||||
void ply_frame_buffer_set_device_name (ply_frame_buffer_t *buffer,
|
||||
const char *device_name);
|
||||
void ply_frame_buffer_close (ply_frame_buffer_t *buffer);
|
||||
void ply_frame_buffer_get_size (ply_frame_buffer_t *buffer,
|
||||
ply_frame_buffer_area_t *size);
|
||||
bool ply_frame_buffer_fill_with_color (ply_frame_buffer_t *buffer,
|
||||
ply_frame_buffer_area_t *area,
|
||||
double red,
|
||||
double green,
|
||||
double blue,
|
||||
double alpha);
|
||||
bool ply_frame_buffer_fill_with_hex_color (ply_frame_buffer_t *buffer,
|
||||
ply_frame_buffer_area_t *area,
|
||||
uint32_t hex_color);
|
||||
|
||||
bool ply_frame_buffer_fill_with_hex_color_at_opacity (ply_frame_buffer_t *buffer,
|
||||
ply_frame_buffer_area_t *area,
|
||||
uint32_t hex_color,
|
||||
double opacity);
|
||||
|
||||
bool ply_frame_buffer_fill_with_gradient (ply_frame_buffer_t *buffer,
|
||||
ply_frame_buffer_area_t *area,
|
||||
uint32_t start,
|
||||
uint32_t end);
|
||||
|
||||
bool ply_frame_buffer_fill_with_argb32_data (ply_frame_buffer_t *buffer,
|
||||
ply_frame_buffer_area_t *area,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data);
|
||||
bool ply_frame_buffer_fill_with_argb32_data_at_opacity (ply_frame_buffer_t *buffer,
|
||||
ply_frame_buffer_area_t *area,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data,
|
||||
double opacity);
|
||||
|
||||
bool ply_frame_buffer_fill_with_argb32_data_with_clip (ply_frame_buffer_t *buffer,
|
||||
ply_frame_buffer_area_t *area,
|
||||
ply_frame_buffer_area_t *clip,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data);
|
||||
bool ply_frame_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_frame_buffer_t *buffer,
|
||||
ply_frame_buffer_area_t *area,
|
||||
ply_frame_buffer_area_t *clip,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data,
|
||||
double opacity);
|
||||
|
||||
const char *ply_frame_buffer_get_bytes (ply_frame_buffer_t *buffer);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PLY_FRAME_BUFFER_H */
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
294
src/libply/ply-rectangle.c
Normal file
294
src/libply/ply-rectangle.c
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
/* ply-rectangle.c
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* Based in part on some work by:
|
||||
* Copyright (C) 2009 Charlie Brej <cbrej@cs.man.ac.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Charlie Brej <cbrej@cs.man.ac.uk>
|
||||
* Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-rectangle.h"
|
||||
|
||||
bool
|
||||
ply_rectangle_contains_point (ply_rectangle_t *rectangle,
|
||||
long x,
|
||||
long y)
|
||||
{
|
||||
long top_edge;
|
||||
long left_edge;
|
||||
long right_edge;
|
||||
long bottom_edge;
|
||||
|
||||
top_edge = rectangle->y;
|
||||
left_edge = rectangle->x;
|
||||
right_edge = rectangle->x + rectangle->width - 1;
|
||||
bottom_edge = rectangle->y + rectangle->height - 1;
|
||||
|
||||
if (x < left_edge)
|
||||
return false;
|
||||
|
||||
if (y < top_edge)
|
||||
return false;
|
||||
|
||||
if (x > right_edge)
|
||||
return false;
|
||||
|
||||
if (y > bottom_edge)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_rectangle_is_empty (ply_rectangle_t *rectangle)
|
||||
{
|
||||
return rectangle->width == 0 || rectangle->height == 0;
|
||||
}
|
||||
|
||||
ply_rectangle_overlap_t
|
||||
ply_rectangle_find_overlap (ply_rectangle_t *rectangle1,
|
||||
ply_rectangle_t *rectangle2)
|
||||
{
|
||||
ply_rectangle_overlap_t overlap;
|
||||
|
||||
long rectangle1_top_edge;
|
||||
long rectangle1_left_edge;
|
||||
long rectangle1_right_edge;
|
||||
long rectangle1_bottom_edge;
|
||||
long rectangle2_top_edge;
|
||||
long rectangle2_left_edge;
|
||||
long rectangle2_right_edge;
|
||||
long rectangle2_bottom_edge;
|
||||
|
||||
rectangle1_top_edge = rectangle1->y;
|
||||
rectangle1_left_edge = rectangle1->x;
|
||||
rectangle1_right_edge = rectangle1->x + rectangle1->width - 1;
|
||||
rectangle1_bottom_edge = rectangle1->y + rectangle1->height - 1;
|
||||
|
||||
rectangle2_top_edge = rectangle2->y;
|
||||
rectangle2_left_edge = rectangle2->x;
|
||||
rectangle2_right_edge = rectangle2->x + rectangle2->width - 1;
|
||||
rectangle2_bottom_edge = rectangle2->y + rectangle2->height - 1;
|
||||
|
||||
overlap = 0;
|
||||
|
||||
/* 1111111
|
||||
* 1122211
|
||||
* 1122211
|
||||
* 1111111
|
||||
*/
|
||||
if (ply_rectangle_contains_point (rectangle1,
|
||||
rectangle2_left_edge,
|
||||
rectangle2_top_edge) &&
|
||||
ply_rectangle_contains_point (rectangle1,
|
||||
rectangle2_right_edge,
|
||||
rectangle2_bottom_edge))
|
||||
return PLY_RECTANGLE_OVERLAP_NO_EDGES;
|
||||
|
||||
/* 2222222
|
||||
* 2211122
|
||||
* 2211122
|
||||
* 2222222
|
||||
*/
|
||||
if (ply_rectangle_contains_point (rectangle2,
|
||||
rectangle1_left_edge,
|
||||
rectangle1_top_edge) &&
|
||||
ply_rectangle_contains_point (rectangle2,
|
||||
rectangle1_right_edge,
|
||||
rectangle1_bottom_edge))
|
||||
return PLY_RECTANGLE_OVERLAP_ALL_EDGES;
|
||||
|
||||
/* 1111111
|
||||
* 11112222
|
||||
* 11112222
|
||||
* 1111111
|
||||
*/
|
||||
if (ply_rectangle_contains_point (rectangle2,
|
||||
rectangle1_right_edge,
|
||||
rectangle2_top_edge) &&
|
||||
ply_rectangle_contains_point (rectangle2,
|
||||
rectangle1_right_edge,
|
||||
rectangle2_bottom_edge))
|
||||
overlap |= PLY_RECTANGLE_OVERLAP_RIGHT_EDGE;
|
||||
|
||||
/* 222222
|
||||
* 11112222
|
||||
* 11112222
|
||||
* 222222
|
||||
*/
|
||||
if (ply_rectangle_contains_point (rectangle1,
|
||||
rectangle2_left_edge,
|
||||
rectangle1_top_edge) &&
|
||||
ply_rectangle_contains_point (rectangle1,
|
||||
rectangle2_left_edge,
|
||||
rectangle1_bottom_edge))
|
||||
overlap |= PLY_RECTANGLE_OVERLAP_RIGHT_EDGE;
|
||||
|
||||
/* 1111111
|
||||
* 22221111
|
||||
* 22221111
|
||||
* 1111111
|
||||
*/
|
||||
if (ply_rectangle_contains_point (rectangle2,
|
||||
rectangle1_left_edge,
|
||||
rectangle2_top_edge) &&
|
||||
ply_rectangle_contains_point (rectangle2,
|
||||
rectangle1_left_edge,
|
||||
rectangle2_bottom_edge))
|
||||
overlap |= PLY_RECTANGLE_OVERLAP_LEFT_EDGE;
|
||||
|
||||
/* 222222
|
||||
* 22221111
|
||||
* 22221111
|
||||
* 222222
|
||||
*/
|
||||
if (ply_rectangle_contains_point (rectangle1,
|
||||
rectangle2_right_edge,
|
||||
rectangle1_top_edge) &&
|
||||
ply_rectangle_contains_point (rectangle1,
|
||||
rectangle2_right_edge,
|
||||
rectangle1_bottom_edge))
|
||||
overlap |= PLY_RECTANGLE_OVERLAP_LEFT_EDGE;
|
||||
|
||||
/*
|
||||
* 2222
|
||||
* 122221
|
||||
* 111111
|
||||
* 111111
|
||||
*/
|
||||
if (ply_rectangle_contains_point (rectangle2,
|
||||
rectangle2_left_edge,
|
||||
rectangle1_top_edge) &&
|
||||
ply_rectangle_contains_point (rectangle2,
|
||||
rectangle2_right_edge,
|
||||
rectangle1_top_edge))
|
||||
overlap |= PLY_RECTANGLE_OVERLAP_TOP_EDGE;
|
||||
|
||||
/*
|
||||
* 2222222
|
||||
* 2211122
|
||||
* 111
|
||||
*/
|
||||
if (ply_rectangle_contains_point (rectangle1,
|
||||
rectangle1_left_edge,
|
||||
rectangle2_bottom_edge) &&
|
||||
ply_rectangle_contains_point (rectangle1,
|
||||
rectangle1_right_edge,
|
||||
rectangle2_bottom_edge))
|
||||
overlap |= PLY_RECTANGLE_OVERLAP_TOP_EDGE;
|
||||
|
||||
/*
|
||||
* 111111
|
||||
* 111111
|
||||
* 122221
|
||||
* 2222
|
||||
*/
|
||||
if (ply_rectangle_contains_point (rectangle1,
|
||||
rectangle1_left_edge,
|
||||
rectangle2_top_edge) &&
|
||||
ply_rectangle_contains_point (rectangle1,
|
||||
rectangle1_right_edge,
|
||||
rectangle2_top_edge))
|
||||
overlap |= PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE;
|
||||
|
||||
/*
|
||||
* 111
|
||||
* 2211122
|
||||
* 2222222
|
||||
*/
|
||||
if (ply_rectangle_contains_point (rectangle2,
|
||||
rectangle2_left_edge,
|
||||
rectangle1_bottom_edge) &&
|
||||
ply_rectangle_contains_point (rectangle2,
|
||||
rectangle2_right_edge,
|
||||
rectangle1_bottom_edge))
|
||||
overlap |= PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE;
|
||||
|
||||
return overlap;
|
||||
}
|
||||
|
||||
void
|
||||
ply_rectangle_intersect (ply_rectangle_t *rectangle1,
|
||||
ply_rectangle_t *rectangle2,
|
||||
ply_rectangle_t *result)
|
||||
{
|
||||
|
||||
long rectangle1_top_edge;
|
||||
long rectangle1_left_edge;
|
||||
long rectangle1_right_edge;
|
||||
long rectangle1_bottom_edge;
|
||||
long rectangle2_top_edge;
|
||||
long rectangle2_left_edge;
|
||||
long rectangle2_right_edge;
|
||||
long rectangle2_bottom_edge;
|
||||
long result_top_edge;
|
||||
long result_left_edge;
|
||||
long result_right_edge;
|
||||
long result_bottom_edge;
|
||||
|
||||
if (ply_rectangle_is_empty (rectangle1))
|
||||
{
|
||||
*result = *rectangle1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ply_rectangle_is_empty (rectangle2))
|
||||
{
|
||||
*result = *rectangle2;
|
||||
return;
|
||||
}
|
||||
|
||||
rectangle1_top_edge = rectangle1->y;
|
||||
rectangle1_left_edge = rectangle1->x;
|
||||
rectangle1_right_edge = rectangle1->x + rectangle1->width - 1;
|
||||
rectangle1_bottom_edge = rectangle1->y + rectangle1->height - 1;
|
||||
|
||||
rectangle2_top_edge = rectangle2->y;
|
||||
rectangle2_left_edge = rectangle2->x;
|
||||
rectangle2_right_edge = rectangle2->x + rectangle2->width - 1;
|
||||
rectangle2_bottom_edge = rectangle2->y + rectangle2->height - 1;
|
||||
|
||||
result_top_edge = MAX (rectangle1_top_edge, rectangle2_top_edge);
|
||||
result_left_edge = MAX (rectangle1_left_edge, rectangle2_left_edge);
|
||||
result_right_edge = MIN (rectangle1_right_edge, rectangle2_right_edge);
|
||||
result_bottom_edge = MIN (rectangle1_bottom_edge, rectangle2_bottom_edge);
|
||||
|
||||
result->x = result_left_edge;
|
||||
result->y = result_top_edge;
|
||||
|
||||
if (result_right_edge >= result_left_edge)
|
||||
result->width = result_right_edge - result_left_edge + 1;
|
||||
else
|
||||
result->width = 0;
|
||||
|
||||
if (result_bottom_edge >= result_top_edge)
|
||||
result->height = result_bottom_edge - result_top_edge + 1;
|
||||
else
|
||||
result->height = 0;
|
||||
|
||||
if (ply_rectangle_is_empty (result))
|
||||
{
|
||||
result->width = 0;
|
||||
result->height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
105
src/libply/ply-rectangle.h
Normal file
105
src/libply/ply-rectangle.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/* ply-rectangle.h
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_RECTANGLE_H
|
||||
#define PLY_RECTANGLE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ply-utils.h"
|
||||
|
||||
typedef struct _ply_rectangle ply_rectangle_t;
|
||||
|
||||
struct _ply_rectangle
|
||||
{
|
||||
long x;
|
||||
long y;
|
||||
unsigned long width;
|
||||
unsigned long height;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLY_RECTANGLE_OVERLAP_NONE = 0,
|
||||
PLY_RECTANGLE_OVERLAP_TOP_EDGE = 1 << 0,
|
||||
PLY_RECTANGLE_OVERLAP_LEFT_EDGE = 1 << 1,
|
||||
PLY_RECTANGLE_OVERLAP_RIGHT_EDGE = 1 << 2,
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE = 1 << 3,
|
||||
PLY_RECTANGLE_OVERLAP_TOP_AND_LEFT_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_TOP_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_LEFT_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_TOP_AND_RIGHT_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_TOP_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_RIGHT_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_TOP_AND_SIDE_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_TOP_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_LEFT_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_RIGHT_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_AND_LEFT_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_LEFT_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_AND_RIGHT_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_RIGHT_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_AND_SIDE_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_LEFT_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_RIGHT_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_SIDE_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_LEFT_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_RIGHT_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_TOP_AND_BOTTOM_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_TOP_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_TOP_LEFT_AND_BOTTOM_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_TOP_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_LEFT_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_TOP_RIGHT_AND_BOTTOM_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_TOP_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_RIGHT_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_ALL_EDGES =
|
||||
PLY_RECTANGLE_OVERLAP_TOP_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_LEFT_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE |
|
||||
PLY_RECTANGLE_OVERLAP_RIGHT_EDGE,
|
||||
PLY_RECTANGLE_OVERLAP_NO_EDGES = 1 << 4,
|
||||
} ply_rectangle_overlap_t;
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
bool ply_rectangle_contains_point (ply_rectangle_t *rectangle,
|
||||
long x,
|
||||
long y);
|
||||
|
||||
bool ply_rectangle_is_empty (ply_rectangle_t *rectangle);
|
||||
|
||||
ply_rectangle_overlap_t ply_rectangle_find_overlap (ply_rectangle_t *rectangle1,
|
||||
ply_rectangle_t *rectangle2);
|
||||
|
||||
void ply_rectangle_intersect (ply_rectangle_t *rectangle1,
|
||||
ply_rectangle_t *rectangle2,
|
||||
ply_rectangle_t *result);
|
||||
#endif
|
||||
|
||||
#endif /* PLY_RECTANGLE_H */
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
390
src/libply/ply-region.c
Normal file
390
src/libply/ply-region.c
Normal file
|
|
@ -0,0 +1,390 @@
|
|||
/* ply-region.c
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* Based in part on some work by:
|
||||
* Copyright (C) 2009 Charlie Brej <cbrej@cs.man.ac.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Charlie Brej <cbrej@cs.man.ac.uk>
|
||||
* Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ply-region.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ply-list.h"
|
||||
#include "ply-rectangle.h"
|
||||
|
||||
struct _ply_region
|
||||
{
|
||||
ply_list_t *rectangle_list;
|
||||
};
|
||||
|
||||
ply_region_t *
|
||||
ply_region_new (void)
|
||||
{
|
||||
ply_region_t *region;
|
||||
|
||||
region = calloc (1, sizeof (ply_region_t));
|
||||
|
||||
region->rectangle_list = ply_list_new ();
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
void
|
||||
ply_region_clear (ply_region_t *region)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (region->rectangle_list);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
ply_rectangle_t *rectangle;
|
||||
|
||||
rectangle = (ply_rectangle_t *) ply_list_node_get_data (node);
|
||||
|
||||
next_node = ply_list_get_next_node (region->rectangle_list, node);
|
||||
|
||||
free (rectangle);
|
||||
ply_list_remove_node (region->rectangle_list, node);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ply_region_free (ply_region_t *region)
|
||||
{
|
||||
|
||||
ply_region_clear (region);
|
||||
ply_list_free (region->rectangle_list);
|
||||
free (region);
|
||||
}
|
||||
|
||||
static ply_rectangle_t *
|
||||
copy_rectangle (ply_rectangle_t *rectangle)
|
||||
{
|
||||
ply_rectangle_t *new_rectangle;
|
||||
|
||||
new_rectangle = malloc (sizeof (*rectangle));
|
||||
*new_rectangle = *rectangle;
|
||||
|
||||
return new_rectangle;
|
||||
}
|
||||
|
||||
static void
|
||||
merge_rectangle_with_sub_list (ply_region_t *region,
|
||||
ply_rectangle_t *new_area,
|
||||
ply_list_node_t *node)
|
||||
{
|
||||
|
||||
if (ply_rectangle_is_empty (new_area))
|
||||
return;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
ply_rectangle_t *old_area;
|
||||
ply_rectangle_overlap_t overlap;
|
||||
|
||||
old_area = (ply_rectangle_t *) ply_list_node_get_data (node);
|
||||
|
||||
next_node = ply_list_get_next_node (region->rectangle_list, node);
|
||||
|
||||
overlap = ply_rectangle_find_overlap (old_area, new_area);
|
||||
|
||||
switch (overlap)
|
||||
{
|
||||
/* NNNN The new rectangle and node rectangle don't touch,
|
||||
* NNNN OOOO so let's move on to the next one.
|
||||
* OOOO
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_NONE:
|
||||
break;
|
||||
|
||||
/* NNNNN We need to split the new rectangle into
|
||||
* NNOOOOO two rectangles: The top row of Ns and
|
||||
* NNOOOOO the left side of Ns.
|
||||
* OOOOO
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_TOP_AND_LEFT_EDGES:
|
||||
{
|
||||
ply_rectangle_t *rectangle;
|
||||
|
||||
rectangle = copy_rectangle (new_area);
|
||||
rectangle->y = old_area->y;
|
||||
rectangle->width = old_area->x - new_area->x;
|
||||
rectangle->height = (new_area->y + new_area->height) - old_area->y;
|
||||
|
||||
merge_rectangle_with_sub_list (region, rectangle, node);
|
||||
|
||||
new_area->height = old_area->y - new_area->y;
|
||||
}
|
||||
break;
|
||||
|
||||
/* NNNNN We need to split the new rectangle into
|
||||
* OOOOONN two rectangles: The top row of Ns and
|
||||
* OOOOONN the right side of Ns.
|
||||
* OOOOO
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_TOP_AND_RIGHT_EDGES:
|
||||
{
|
||||
ply_rectangle_t *rectangle;
|
||||
|
||||
rectangle = copy_rectangle (new_area);
|
||||
rectangle->x = new_area->x + old_area->width;
|
||||
rectangle->y = old_area->y;
|
||||
rectangle->width = (old_area->x + new_area->width) - (old_area->x + old_area->width);
|
||||
rectangle->height = (new_area->y + new_area->height) - old_area->y;
|
||||
|
||||
merge_rectangle_with_sub_list (region, rectangle, node);
|
||||
|
||||
new_area->height = old_area->y - new_area->y;
|
||||
}
|
||||
break;
|
||||
|
||||
/* NNNNNNN We need to trim out the part of
|
||||
* NOOOOON old rectangle that overlaps the new
|
||||
* NOOOOON rectangle by shrinking and moving it
|
||||
* OOOOO and then we need to add the new rectangle.
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_TOP_AND_SIDE_EDGES:
|
||||
{
|
||||
old_area->height = (old_area->y + old_area->height)
|
||||
- (new_area->y + new_area->height);
|
||||
old_area->y = new_area->y + new_area->height;
|
||||
}
|
||||
|
||||
/* NNN We only care about the top row of Ns,
|
||||
* ONNNO everything below that is already handled by
|
||||
* ONNNO the old rectangle.
|
||||
* OOOOO
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_TOP_EDGE:
|
||||
new_area->height = old_area->y - new_area->y;
|
||||
break;
|
||||
|
||||
/* OOOOO We need to split the new rectangle into
|
||||
* NNOOOOO two rectangles: The left side of Ns and
|
||||
* NNOOOOO the bottom row of Ns.
|
||||
* NNOOOOO
|
||||
* NNNNN
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_LEFT_EDGES:
|
||||
{
|
||||
ply_rectangle_t *rectangle;
|
||||
|
||||
rectangle = copy_rectangle (new_area);
|
||||
|
||||
rectangle->y = old_area->y;
|
||||
rectangle->width = old_area->x - new_area->x;
|
||||
rectangle->height = (old_area->y + old_area->height) - new_area->y;
|
||||
|
||||
merge_rectangle_with_sub_list (region, rectangle, node);
|
||||
|
||||
new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
|
||||
new_area->width = new_area->width;
|
||||
new_area->y = old_area->y + old_area->height;
|
||||
}
|
||||
break;
|
||||
|
||||
/* OOOOO We need to split the new rectangle into
|
||||
* OOOOONN two rectangles: The right side of Ns and
|
||||
* OOOOONN the bottom row of Ns.
|
||||
* OOOOONN
|
||||
* NNNNN
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_RIGHT_EDGES:
|
||||
{
|
||||
ply_rectangle_t *rectangle;
|
||||
|
||||
rectangle = copy_rectangle (new_area);
|
||||
|
||||
rectangle->x = old_area->x + old_area->width;
|
||||
rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width);
|
||||
rectangle->height = (old_area->y + old_area->height) - new_area->y;
|
||||
|
||||
merge_rectangle_with_sub_list (region, rectangle, node);
|
||||
|
||||
new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
|
||||
new_area->y = old_area->y + old_area->height;
|
||||
}
|
||||
break;
|
||||
|
||||
/* OOOOO We need to trim out the part of
|
||||
* NOOOOON old rectangle that overlaps the new
|
||||
* NOOOOON rectangle by shrinking it
|
||||
* NNNNNNN and then we need to add the new rectangle.
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_SIDE_EDGES:
|
||||
{
|
||||
old_area->height = (new_area->y + new_area->height)
|
||||
- (old_area->y + old_area->height);
|
||||
}
|
||||
break;
|
||||
|
||||
/* OOOOO We only care about the bottom row of Ns,
|
||||
* ONNNO everything above that is already handled by
|
||||
* ONNNO the old rectangle.
|
||||
* NNN
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE:
|
||||
{
|
||||
new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
|
||||
new_area->y = old_area->y + old_area->height;
|
||||
}
|
||||
break;
|
||||
|
||||
/* NNNN We need to trim out the part of
|
||||
* NNNNO old rectangle that overlaps the new
|
||||
* NNNNO rectangle by shrinking it and moving it
|
||||
* NNNN and then we need to add the new rectangle.
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_TOP_LEFT_AND_BOTTOM_EDGES:
|
||||
{
|
||||
old_area->width = (old_area->x + old_area->width)
|
||||
- (new_area->x + new_area->width);
|
||||
old_area->x = new_area->x + new_area->width;
|
||||
}
|
||||
break;
|
||||
|
||||
/* NNNN We need to trim out the part of
|
||||
* ONNNN old rectangle that overlaps the new
|
||||
* ONNNN rectangle by shrinking it and then we
|
||||
* NNNN need to add the new rectangle.
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_TOP_RIGHT_AND_BOTTOM_EDGES:
|
||||
old_area->width = new_area->x - old_area->x;
|
||||
break;
|
||||
|
||||
/* NNNNNNN The old rectangle is completely inside the new rectangle
|
||||
* NOOOOON so replace the old rectangle with the new rectangle.
|
||||
* NOOOOON
|
||||
* NNNNNNN
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_ALL_EDGES:
|
||||
free (old_area);
|
||||
ply_list_remove_node (region->rectangle_list, node);
|
||||
break;
|
||||
|
||||
/* NNN We need to split the new rectangle into
|
||||
* ONNNO two rectangles: the top and bottom row of Ns
|
||||
* ONNNO
|
||||
* NNN
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_TOP_AND_BOTTOM_EDGES:
|
||||
{
|
||||
ply_rectangle_t *rectangle;
|
||||
|
||||
rectangle = copy_rectangle (new_area);
|
||||
rectangle->y = old_area->y + old_area->height;
|
||||
rectangle->width = new_area->width;
|
||||
rectangle->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
|
||||
merge_rectangle_with_sub_list (region, rectangle, node);
|
||||
|
||||
new_area->height = old_area->y - new_area->y;
|
||||
}
|
||||
break;
|
||||
|
||||
/* OOOOO We only care about the side row of Ns,
|
||||
* NNNNOO everything rigth of that is already handled by
|
||||
* NNNNOO the old rectangle.
|
||||
* OOOOO
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_LEFT_EDGE:
|
||||
new_area->width = old_area->x - new_area->x;
|
||||
break;
|
||||
|
||||
/* OOOOO We only care about the side row of Ns,
|
||||
* NNNNNN everything left of that is already handled by
|
||||
* NNNNNN the old rectangle.
|
||||
* OOOOO
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_RIGHT_EDGE:
|
||||
{
|
||||
new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width);
|
||||
new_area->x = old_area->x + old_area->width;
|
||||
}
|
||||
break;
|
||||
|
||||
/* OOOOO We need to split the new rectangle into
|
||||
* NNNNNNN two rectangles: the side columns of Ns
|
||||
* NNNNNNN
|
||||
* OOOOO
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_SIDE_EDGES:
|
||||
{
|
||||
ply_rectangle_t *rectangle;
|
||||
|
||||
rectangle = copy_rectangle (new_area);
|
||||
|
||||
rectangle->x = old_area->x + old_area->width;
|
||||
rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width);
|
||||
|
||||
merge_rectangle_with_sub_list (region, rectangle, node);
|
||||
|
||||
new_area->width = old_area->x - new_area->x;
|
||||
}
|
||||
break;
|
||||
|
||||
/* OOOOOOO The new rectangle is completely inside an old rectangle
|
||||
* ONNNNNO so return early without adding the new rectangle.
|
||||
* ONNNNNO
|
||||
* OOOOOOO
|
||||
*/
|
||||
case PLY_RECTANGLE_OVERLAP_NO_EDGES:
|
||||
free (new_area);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
ply_list_append_data (region->rectangle_list, new_area);
|
||||
}
|
||||
|
||||
void
|
||||
ply_region_add_rectangle (ply_region_t *region,
|
||||
ply_rectangle_t *rectangle)
|
||||
{
|
||||
ply_list_node_t *first_node;
|
||||
ply_rectangle_t *rectangle_copy;
|
||||
|
||||
assert (region != NULL);
|
||||
assert (rectangle != NULL);
|
||||
|
||||
first_node = ply_list_get_first_node (region->rectangle_list);
|
||||
|
||||
rectangle_copy = copy_rectangle (rectangle);
|
||||
merge_rectangle_with_sub_list (region,
|
||||
rectangle_copy,
|
||||
first_node);
|
||||
}
|
||||
|
||||
ply_list_t *
|
||||
ply_region_get_rectangle_list (ply_region_t *region)
|
||||
{
|
||||
return region->rectangle_list;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/* ply-terminal.h - psuedoterminal abstraction
|
||||
/* ply-region.h
|
||||
*
|
||||
* Copyright (C) 2007 Red Hat, Inc.
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -19,25 +19,29 @@
|
|||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_TERMINAL_H
|
||||
#define PLY_TERMINAL_H
|
||||
#ifndef PLY_REGION_H
|
||||
#define PLY_REGION_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct _ply_terminal ply_terminal_t;
|
||||
#include "ply-list.h"
|
||||
#include "ply-rectangle.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
typedef struct _ply_region ply_region_t;
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_terminal_t *ply_terminal_new (void);
|
||||
void ply_terminal_free (ply_terminal_t *terminal);
|
||||
bool ply_terminal_create_device (ply_terminal_t *terminal);
|
||||
bool ply_terminal_has_device (ply_terminal_t *terminal);
|
||||
void ply_terminal_destroy_device (ply_terminal_t *terminal);
|
||||
int ply_terminal_get_fd (ply_terminal_t *terminal);
|
||||
void ply_terminal_set_fd (ply_terminal_t *terminal, int fd);
|
||||
const char *ply_terminal_get_device_name (ply_terminal_t *terminal);
|
||||
ply_region_t *ply_region_new (void);
|
||||
void ply_region_free (ply_region_t *region);
|
||||
void ply_region_add_rectangle (ply_region_t *region,
|
||||
ply_rectangle_t *rectangle);
|
||||
void ply_region_clear (ply_region_t *region);
|
||||
ply_list_t *ply_region_get_rectangle_list (ply_region_t *region);
|
||||
|
||||
bool ply_region_is_empty (ply_region_t *region);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PLY_TERMINAL_H */
|
||||
#endif /* PLY_REGION_H */
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
|
|
@ -39,12 +39,11 @@
|
|||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-terminal.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
struct _ply_terminal_session
|
||||
{
|
||||
ply_terminal_t *terminal;
|
||||
int pseudoterminal_master_fd;
|
||||
ply_logger_t *logger;
|
||||
ply_event_loop_t *loop;
|
||||
char **argv;
|
||||
|
|
@ -71,7 +70,7 @@ ply_terminal_session_open_console (ply_terminal_session_t *session)
|
|||
int fd;
|
||||
const char *terminal_name;
|
||||
|
||||
terminal_name = ply_terminal_get_device_name (session->terminal);
|
||||
terminal_name = ptsname (session->pseudoterminal_master_fd);
|
||||
|
||||
fd = open (terminal_name, O_RDONLY);
|
||||
|
||||
|
|
@ -128,8 +127,8 @@ ply_terminal_session_new (const char * const *argv)
|
|||
assert (argv == NULL || argv[0] != NULL);
|
||||
|
||||
session = calloc (1, sizeof (ply_terminal_session_t));
|
||||
session->pseudoterminal_master_fd = -1;
|
||||
session->argv = argv == NULL ? NULL : ply_copy_string_array (argv);
|
||||
session->terminal = ply_terminal_new ();
|
||||
session->logger = ply_logger_new ();
|
||||
session->is_running = false;
|
||||
session->console_is_redirected = false;
|
||||
|
|
@ -147,7 +146,8 @@ ply_terminal_session_free (ply_terminal_session_t *session)
|
|||
ply_logger_free (session->logger);
|
||||
|
||||
ply_free_string_array (session->argv);
|
||||
ply_terminal_free (session->terminal);
|
||||
|
||||
close (session->pseudoterminal_master_fd);
|
||||
free (session);
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ ply_terminal_session_redirect_console (ply_terminal_session_t *session)
|
|||
|
||||
assert (session != NULL);
|
||||
|
||||
terminal_name = ply_terminal_get_device_name (session->terminal);
|
||||
terminal_name = ptsname (session->pseudoterminal_master_fd);
|
||||
|
||||
assert (terminal_name != NULL);
|
||||
|
||||
|
|
@ -218,6 +218,49 @@ ply_terminal_session_unredirect_console (ply_terminal_session_t *session)
|
|||
session->console_is_redirected = false;
|
||||
}
|
||||
|
||||
static void
|
||||
close_pseudoterminal (ply_terminal_session_t *session)
|
||||
{
|
||||
close (session->pseudoterminal_master_fd);
|
||||
session->pseudoterminal_master_fd = -1;
|
||||
}
|
||||
|
||||
static bool
|
||||
open_pseudoterminal (ply_terminal_session_t *session)
|
||||
{
|
||||
ply_trace ("opening device '/dev/ptmx'");
|
||||
session->pseudoterminal_master_fd = posix_openpt (O_RDWR | O_NOCTTY);
|
||||
|
||||
if (session->pseudoterminal_master_fd < 0)
|
||||
return false;
|
||||
|
||||
ply_trace (" opened device '/dev/ptmx'");
|
||||
|
||||
ply_trace ("creating pseudoterminal");
|
||||
if (grantpt (session->pseudoterminal_master_fd) < 0)
|
||||
{
|
||||
ply_save_errno ();
|
||||
ply_trace ("could not create psuedoterminal: %m");
|
||||
close_pseudoterminal (session);
|
||||
ply_restore_errno ();
|
||||
return false;
|
||||
}
|
||||
ply_trace ("done creating pseudoterminal");
|
||||
|
||||
ply_trace ("unlocking pseudoterminal");
|
||||
if (unlockpt (session->pseudoterminal_master_fd) < 0)
|
||||
{
|
||||
ply_save_errno ();
|
||||
close_pseudoterminal (session);
|
||||
ply_restore_errno ();
|
||||
return false;
|
||||
}
|
||||
ply_trace ("unlocked pseudoterminal");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ply_terminal_session_run (ply_terminal_session_t *session,
|
||||
ply_terminal_session_flags_t flags,
|
||||
|
|
@ -240,7 +283,7 @@ ply_terminal_session_run (ply_terminal_session_t *session,
|
|||
(flags & PLY_TERMINAL_SESSION_FLAGS_REDIRECT_CONSOLE) != 0;
|
||||
|
||||
ply_trace ("creating terminal device");
|
||||
if (!ply_terminal_create_device (session->terminal))
|
||||
if (!open_pseudoterminal (session))
|
||||
return false;
|
||||
ply_trace ("done creating terminal device");
|
||||
|
||||
|
|
@ -250,7 +293,7 @@ ply_terminal_session_run (ply_terminal_session_t *session,
|
|||
!ply_terminal_session_redirect_console (session))
|
||||
{
|
||||
ply_save_errno ();
|
||||
ply_terminal_destroy_device (session->terminal);
|
||||
close_pseudoterminal (session);
|
||||
ply_restore_errno ();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -264,7 +307,7 @@ ply_terminal_session_run (ply_terminal_session_t *session,
|
|||
{
|
||||
ply_save_errno ();
|
||||
ply_terminal_session_unredirect_console (session);
|
||||
ply_terminal_destroy_device (session->terminal);
|
||||
close_pseudoterminal (session);
|
||||
ply_restore_errno ();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -316,12 +359,12 @@ ply_terminal_session_attach (ply_terminal_session_t *session,
|
|||
if (ptmx >= 0)
|
||||
{
|
||||
ply_trace ("ptmx passed in, using it");
|
||||
ply_terminal_set_fd(session->terminal, ptmx);
|
||||
session->pseudoterminal_master_fd = ptmx;
|
||||
}
|
||||
else
|
||||
{
|
||||
ply_trace ("ptmx not passed in, creating one");
|
||||
if (!ply_terminal_create_device (session->terminal))
|
||||
if (!open_pseudoterminal (session))
|
||||
{
|
||||
ply_trace ("could not create pseudo-terminal: %m");
|
||||
return false;
|
||||
|
|
@ -336,7 +379,7 @@ ply_terminal_session_attach (ply_terminal_session_t *session,
|
|||
!ply_terminal_session_redirect_console (session))
|
||||
{
|
||||
ply_save_errno ();
|
||||
ply_terminal_destroy_device (session->terminal);
|
||||
close_pseudoterminal (session);
|
||||
ply_restore_errno ();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -370,7 +413,7 @@ ply_terminal_session_detach (ply_terminal_session_t *session)
|
|||
if (session->created_terminal_device)
|
||||
{
|
||||
ply_trace ("ptmx wasn't originally passed in, destroying created one");
|
||||
ply_terminal_destroy_device (session->terminal);
|
||||
close_pseudoterminal (session);
|
||||
session->created_terminal_device = false;
|
||||
}
|
||||
|
||||
|
|
@ -386,7 +429,7 @@ ply_terminal_session_get_fd (ply_terminal_session_t *session)
|
|||
{
|
||||
assert (session != NULL);
|
||||
|
||||
return ply_terminal_get_fd (session->terminal);
|
||||
return session->pseudoterminal_master_fd;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -1,201 +0,0 @@
|
|||
/* ply-terminal.c - psuedoterminal abstraction
|
||||
*
|
||||
* Copyright (C) 2006, 2007 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Kristian Høgsberg <krh@redhat.com>
|
||||
* Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ply-terminal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ply-logger.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
struct _ply_terminal
|
||||
{
|
||||
char *name;
|
||||
int fd;
|
||||
};
|
||||
|
||||
ply_terminal_t *
|
||||
ply_terminal_new (void)
|
||||
{
|
||||
ply_terminal_t *terminal;
|
||||
|
||||
terminal = calloc (1, sizeof (ply_terminal_t));
|
||||
terminal->fd = -1;
|
||||
|
||||
return terminal;
|
||||
}
|
||||
|
||||
void
|
||||
ply_terminal_free (ply_terminal_t *terminal)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
|
||||
ply_terminal_destroy_device (terminal);
|
||||
free (terminal);
|
||||
}
|
||||
|
||||
bool
|
||||
ply_terminal_create_device (ply_terminal_t *terminal)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
assert (!ply_terminal_has_device (terminal));
|
||||
|
||||
ply_trace ("opening device '/dev/ptmx'");
|
||||
terminal->fd = posix_openpt (O_RDWR | O_NOCTTY);
|
||||
|
||||
if (terminal->fd < 0)
|
||||
return false;
|
||||
|
||||
ply_trace (" opened device '/dev/ptmx'");
|
||||
|
||||
ply_trace ("creating pseudoterminal");
|
||||
if (grantpt (terminal->fd) < 0)
|
||||
{
|
||||
ply_save_errno ();
|
||||
ply_trace ("could not create psuedoterminal: %m");
|
||||
ply_terminal_destroy_device (terminal);
|
||||
ply_restore_errno ();
|
||||
return false;
|
||||
}
|
||||
ply_trace ("done creating pseudoterminal");
|
||||
|
||||
ply_trace ("unlocking pseudoterminal");
|
||||
if (unlockpt (terminal->fd) < 0)
|
||||
{
|
||||
ply_save_errno ();
|
||||
ply_terminal_destroy_device (terminal);
|
||||
ply_restore_errno ();
|
||||
return false;
|
||||
}
|
||||
ply_trace ("unlocked pseudoterminal");
|
||||
|
||||
terminal->name = strdup (ptsname (terminal->fd));
|
||||
ply_trace ("pseudoterminal '%s' ready for action", terminal->name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_terminal_has_device (ply_terminal_t *terminal)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
|
||||
return terminal->fd >= 0;
|
||||
}
|
||||
|
||||
void
|
||||
ply_terminal_destroy_device (ply_terminal_t *terminal)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
|
||||
free (terminal->name);
|
||||
terminal->name = NULL;
|
||||
|
||||
close (terminal->fd);
|
||||
terminal->fd = -1;
|
||||
}
|
||||
|
||||
int
|
||||
ply_terminal_get_fd (ply_terminal_t *terminal)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
|
||||
return terminal->fd;
|
||||
}
|
||||
|
||||
void
|
||||
ply_terminal_set_fd (ply_terminal_t *terminal, int fd)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
|
||||
terminal->fd = fd;
|
||||
|
||||
if (terminal->name)
|
||||
{
|
||||
free(terminal->name);
|
||||
terminal->name = NULL;
|
||||
}
|
||||
|
||||
if (terminal->fd >= 0)
|
||||
terminal->name = strdup (ptsname (terminal->fd));
|
||||
}
|
||||
|
||||
const char *
|
||||
ply_terminal_get_device_name (ply_terminal_t *terminal)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
assert (ply_terminal_has_device (terminal));
|
||||
|
||||
assert (terminal->name != NULL);
|
||||
return terminal->name;
|
||||
}
|
||||
|
||||
#ifdef PLY_TERMINAL_ENABLE_TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
ply_terminal_t *terminal;
|
||||
const char *name;
|
||||
uint8_t byte;
|
||||
int exit_code;
|
||||
|
||||
exit_code = 0;
|
||||
|
||||
terminal = ply_terminal_new ();
|
||||
|
||||
if (!ply_terminal_create_device (terminal))
|
||||
{
|
||||
exit_code = errno;
|
||||
perror ("could not open new terminal");
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
name = ply_terminal_get_device_name (terminal);
|
||||
printf ("terminal name is '%s'\n", name);
|
||||
|
||||
while (read (ply_terminal_get_fd (terminal),
|
||||
&byte, sizeof (byte)) == 1)
|
||||
printf ("%c", byte);
|
||||
|
||||
ply_terminal_free (terminal);
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
#endif /* PLY_TERMINAL_ENABLE_TEST */
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
|
|
@ -41,6 +41,7 @@ struct _ply_trigger
|
|||
ply_list_t *closures;
|
||||
|
||||
ply_trigger_t **free_address;
|
||||
int ignore_count;
|
||||
};
|
||||
|
||||
ply_trigger_t *
|
||||
|
|
@ -51,6 +52,7 @@ ply_trigger_new (ply_trigger_t **free_address)
|
|||
trigger = calloc (1, sizeof (ply_trigger_t));
|
||||
trigger->free_address = free_address;
|
||||
trigger->closures = ply_list_new ();
|
||||
trigger->ignore_count = 0;
|
||||
|
||||
return trigger;
|
||||
}
|
||||
|
|
@ -131,6 +133,12 @@ ply_trigger_remove_handler (ply_trigger_t *trigger,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ply_trigger_ignore_next_pull (ply_trigger_t *trigger)
|
||||
{
|
||||
trigger->ignore_count++;
|
||||
}
|
||||
|
||||
void
|
||||
ply_trigger_pull (ply_trigger_t *trigger,
|
||||
const void *data)
|
||||
|
|
@ -138,6 +146,13 @@ ply_trigger_pull (ply_trigger_t *trigger,
|
|||
ply_list_node_t *node;
|
||||
|
||||
assert (trigger != NULL);
|
||||
assert (trigger->ignore_count >= 0);
|
||||
|
||||
if (trigger->ignore_count > 0)
|
||||
{
|
||||
trigger->ignore_count--;
|
||||
return;
|
||||
}
|
||||
|
||||
node = ply_list_get_first_node (trigger->closures);
|
||||
while (node != NULL)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ void ply_trigger_remove_handler (ply_trigger_t *trigger,
|
|||
void *user_data);
|
||||
void ply_trigger_free (ply_trigger_t *trigger);
|
||||
|
||||
void ply_trigger_ignore_next_pull (ply_trigger_t *trigger);
|
||||
void ply_trigger_pull (ply_trigger_t *trigger,
|
||||
const void *data);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -894,25 +894,4 @@ ply_utf8_string_get_length (const char *string,
|
|||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
ply_switch_to_vt (int vt_number)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
|
||||
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
if (ioctl (fd, VT_ACTIVATE, vt_number) < 0)
|
||||
{
|
||||
close (fd);
|
||||
return;
|
||||
}
|
||||
|
||||
ioctl (fd, VT_WAITACTIVE, vt_number);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ typedef void (* ply_module_function_t) (void);
|
|||
typedef intptr_t ply_daemon_handle_t;
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
|
||||
#define ply_round_to_multiple(n, m) (((n) + (((m) - 1))) & ~((m) - 1))
|
||||
|
||||
bool ply_open_unidirectional_pipe (int *sender_fd,
|
||||
int *receiver_fd);
|
||||
int ply_connect_to_unix_socket (const char *path,
|
||||
|
|
@ -104,8 +107,6 @@ int ply_utf8_character_get_size (const char *string,
|
|||
int ply_utf8_string_get_length (const char *string,
|
||||
size_t n);
|
||||
|
||||
void ply_switch_to_vt (int vt_number);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PLY_UTILS_H */
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ INCLUDES = \
|
|||
TESTS =
|
||||
|
||||
if ENABLE_TESTS
|
||||
include $(srcdir)/ply-frame-buffer-test.am
|
||||
include $(srcdir)/ply-terminal-test.am
|
||||
include $(srcdir)/ply-terminal-session-test.am
|
||||
include $(srcdir)/ply-logger-test.am
|
||||
include $(srcdir)/ply-array-test.am
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
TESTS += ply-frame-buffer-test
|
||||
|
||||
ply_frame_buffer_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_FRAME_BUFFER_ENABLE_TEST
|
||||
ply_frame_buffer_test_LDADD = $(PLYMOUTH_LIBS)
|
||||
ply_frame_buffer_test_SOURCES = \
|
||||
$(srcdir)/../ply-utils.h \
|
||||
$(srcdir)/../ply-frame-buffer.h \
|
||||
$(srcdir)/../ply-frame-buffer.c \
|
||||
$(srcdir)/../ply-list.h \
|
||||
$(srcdir)/../ply-list.c \
|
||||
$(srcdir)/../ply-logger.h \
|
||||
$(srcdir)/../ply-logger.c \
|
||||
$(srcdir)/../ply-utils.h \
|
||||
$(srcdir)/../ply-utils.c
|
||||
|
|
@ -14,7 +14,5 @@ ply_terminal_session_test_SOURCES =
|
|||
$(srcdir)/../ply-list.c \
|
||||
$(srcdir)/../ply-event-loop.h \
|
||||
$(srcdir)/../ply-event-loop.c \
|
||||
$(srcdir)/../ply-terminal.h \
|
||||
$(srcdir)/../ply-terminal.c \
|
||||
$(srcdir)/../ply-terminal-session.h \
|
||||
$(srcdir)/../ply-terminal-session.c
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
TESTS += ply-terminal-test
|
||||
|
||||
ply_terminal_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_TERMINAL_ENABLE_TEST
|
||||
ply_terminal_test_LDADD = $(PLYMOUTH_LIBS)
|
||||
|
||||
ply_terminal_test_SOURCES = \
|
||||
$(srcdir)/../ply-list.h \
|
||||
$(srcdir)/../ply-list.c \
|
||||
$(srcdir)/../ply-logger.h \
|
||||
$(srcdir)/../ply-logger.c \
|
||||
$(srcdir)/../ply-utils.h \
|
||||
$(srcdir)/../ply-utils.c \
|
||||
$(srcdir)/../ply-terminal.h \
|
||||
$(srcdir)/../ply-terminal.c
|
||||
|
|
@ -10,15 +10,22 @@ libplybootsplash_HEADERS = \
|
|||
ply-animation.h \
|
||||
ply-boot-splash.h \
|
||||
ply-boot-splash-plugin.h \
|
||||
ply-console.h \
|
||||
ply-entry.h \
|
||||
ply-image.h \
|
||||
ply-keyboard.h \
|
||||
ply-label.h \
|
||||
ply-label-plugin.h \
|
||||
ply-pixel-buffer.h \
|
||||
ply-pixel-display.h \
|
||||
ply-progress-animation.h \
|
||||
ply-progress-bar.h \
|
||||
ply-renderer.h \
|
||||
ply-renderer-plugin.h \
|
||||
ply-terminal.h \
|
||||
ply-text-display.h \
|
||||
ply-text-progress-bar.h \
|
||||
ply-throbber.h \
|
||||
ply-window.h
|
||||
ply-throbber.h
|
||||
|
||||
libplybootsplash_la_CFLAGS = $(PLYMOUTH_CFLAGS) \
|
||||
$(IMAGE_CFLAGS) \
|
||||
|
|
@ -32,15 +39,21 @@ libplybootsplash_la_LDFLAGS = -export-symbols-regex '^[^_].*' \
|
|||
-no-undefined
|
||||
libplybootsplash_la_SOURCES = \
|
||||
$(libplybootsplash_HEADERS) \
|
||||
ply-console.c \
|
||||
ply-entry.c \
|
||||
ply-image.c \
|
||||
ply-keyboard.c \
|
||||
ply-label.c \
|
||||
ply-progress-bar.c \
|
||||
ply-throbber.c \
|
||||
ply-animation.c \
|
||||
ply-pixel-display.c \
|
||||
ply-progress-animation.c \
|
||||
ply-text-display.c \
|
||||
ply-text-progress-bar.c \
|
||||
ply-window.c \
|
||||
ply-terminal.c \
|
||||
ply-pixel-buffer.c \
|
||||
ply-renderer.c \
|
||||
ply-boot-splash.c
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
|
|
|||
|
|
@ -44,10 +44,9 @@
|
|||
#include "ply-event-loop.h"
|
||||
#include "ply-array.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-image.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
|
|
@ -62,9 +61,8 @@ struct _ply_animation
|
|||
char *image_dir;
|
||||
char *frames_prefix;
|
||||
|
||||
ply_window_t *window;
|
||||
ply_frame_buffer_t *frame_buffer;
|
||||
ply_frame_buffer_area_t frame_area;
|
||||
ply_pixel_display_t *display;
|
||||
ply_rectangle_t frame_area;
|
||||
ply_trigger_t *stop_trigger;
|
||||
|
||||
int frame_number;
|
||||
|
|
@ -128,26 +126,14 @@ ply_animation_free (ply_animation_t *animation)
|
|||
free (animation);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_background (ply_animation_t *animation)
|
||||
{
|
||||
ply_window_erase_area (animation->window,
|
||||
animation->x, animation->y,
|
||||
animation->frame_area.width,
|
||||
animation->frame_area.height);
|
||||
}
|
||||
|
||||
static bool
|
||||
animate_at_time (ply_animation_t *animation,
|
||||
double time)
|
||||
{
|
||||
int number_of_frames;
|
||||
ply_image_t * const * frames;
|
||||
uint32_t *frame_data;
|
||||
bool should_continue;
|
||||
|
||||
ply_window_set_mode (animation->window, PLY_WINDOW_MODE_GRAPHICS);
|
||||
|
||||
number_of_frames = ply_array_get_size (animation->frames);
|
||||
|
||||
if (number_of_frames == 0)
|
||||
|
|
@ -161,22 +147,17 @@ animate_at_time (ply_animation_t *animation,
|
|||
if (animation->stop_requested)
|
||||
should_continue = false;
|
||||
|
||||
ply_frame_buffer_pause_updates (animation->frame_buffer);
|
||||
if (animation->frame_area.width > 0)
|
||||
draw_background (animation);
|
||||
|
||||
frames = (ply_image_t * const *) ply_array_get_elements (animation->frames);
|
||||
|
||||
animation->frame_area.x = animation->x;
|
||||
animation->frame_area.y = animation->y;
|
||||
animation->frame_area.width = ply_image_get_width (frames[animation->frame_number]);
|
||||
animation->frame_area.height = ply_image_get_height (frames[animation->frame_number]);
|
||||
frame_data = ply_image_get_data (frames[animation->frame_number]);
|
||||
|
||||
ply_frame_buffer_fill_with_argb32_data (animation->frame_buffer,
|
||||
&animation->frame_area, 0, 0,
|
||||
frame_data);
|
||||
ply_frame_buffer_unpause_updates (animation->frame_buffer);
|
||||
ply_pixel_display_draw_area (animation->display,
|
||||
animation->x, animation->y,
|
||||
animation->frame_area.width,
|
||||
animation->frame_area.height);
|
||||
|
||||
animation->frame_number++;
|
||||
|
||||
|
|
@ -313,19 +294,19 @@ ply_animation_load (ply_animation_t *animation)
|
|||
|
||||
bool
|
||||
ply_animation_start (ply_animation_t *animation,
|
||||
ply_event_loop_t *loop,
|
||||
ply_window_t *window,
|
||||
ply_pixel_display_t *display,
|
||||
ply_trigger_t *stop_trigger,
|
||||
long x,
|
||||
long y)
|
||||
{
|
||||
assert (animation != NULL);
|
||||
assert (animation->loop == NULL);
|
||||
|
||||
animation->loop = loop;
|
||||
animation->window = window;
|
||||
if (!animation->is_stopped)
|
||||
return true;
|
||||
|
||||
animation->loop = ply_event_loop_get_default ();
|
||||
animation->display = display;
|
||||
animation->stop_trigger = stop_trigger;
|
||||
animation->frame_buffer = ply_window_get_frame_buffer (window);;
|
||||
animation->is_stopped = false;
|
||||
animation->stop_requested = false;
|
||||
|
||||
|
|
@ -345,8 +326,6 @@ ply_animation_start (ply_animation_t *animation,
|
|||
static void
|
||||
ply_animation_stop_now (ply_animation_t *animation)
|
||||
{
|
||||
animation->frame_buffer = NULL;
|
||||
animation->window = NULL;
|
||||
animation->is_stopped = true;
|
||||
|
||||
if (animation->loop != NULL)
|
||||
|
|
@ -356,6 +335,8 @@ ply_animation_stop_now (ply_animation_t *animation)
|
|||
on_timeout, animation);
|
||||
animation->loop = NULL;
|
||||
}
|
||||
|
||||
animation->display = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -376,6 +357,28 @@ ply_animation_is_stopped (ply_animation_t *animation)
|
|||
return animation->is_stopped;
|
||||
}
|
||||
|
||||
void
|
||||
ply_animation_draw_area (ply_animation_t *animation,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
ply_image_t * const * frames;
|
||||
uint32_t *frame_data;
|
||||
|
||||
if (animation->is_stopped)
|
||||
return;
|
||||
|
||||
frames = (ply_image_t * const *) ply_array_get_elements (animation->frames);
|
||||
frame_data = ply_image_get_data (frames[animation->frame_number]);
|
||||
|
||||
ply_pixel_buffer_fill_with_argb32_data (buffer,
|
||||
&animation->frame_area, 0, 0,
|
||||
frame_data);
|
||||
}
|
||||
|
||||
long
|
||||
ply_animation_get_width (ply_animation_t *animation)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,9 +27,8 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-trigger.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
typedef struct _ply_animation ply_animation_t;
|
||||
|
||||
|
|
@ -40,14 +39,20 @@ void ply_animation_free (ply_animation_t *animation);
|
|||
|
||||
bool ply_animation_load (ply_animation_t *animation);
|
||||
bool ply_animation_start (ply_animation_t *animation,
|
||||
ply_event_loop_t *loop,
|
||||
ply_window_t *window,
|
||||
ply_pixel_display_t *display,
|
||||
ply_trigger_t *stop_trigger,
|
||||
long x,
|
||||
long y);
|
||||
void ply_animation_stop (ply_animation_t *animation);
|
||||
bool ply_animation_is_stopped (ply_animation_t *animation);
|
||||
|
||||
void ply_animation_draw_area (ply_animation_t *animation,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height);
|
||||
|
||||
long ply_animation_get_width (ply_animation_t *animation);
|
||||
long ply_animation_get_height (ply_animation_t *animation);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,9 +28,11 @@
|
|||
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-keyboard.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-text-display.h"
|
||||
#include "ply-trigger.h"
|
||||
#include "ply-key-file.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
@ -47,11 +49,18 @@ typedef struct
|
|||
ply_boot_splash_plugin_t * (* create_plugin) (ply_key_file_t *key_file);
|
||||
void (* destroy_plugin) (ply_boot_splash_plugin_t *plugin);
|
||||
|
||||
void (* add_window) (ply_boot_splash_plugin_t *plugin,
|
||||
ply_window_t *window);
|
||||
|
||||
void (* remove_window) (ply_boot_splash_plugin_t *plugin,
|
||||
ply_window_t *window);
|
||||
void (* set_keyboard) (ply_boot_splash_plugin_t *plugin,
|
||||
ply_keyboard_t *keyboard);
|
||||
void (* unset_keyboard) (ply_boot_splash_plugin_t *plugin,
|
||||
ply_keyboard_t *keyboard);
|
||||
void (* add_pixel_display) (ply_boot_splash_plugin_t *plugin,
|
||||
ply_pixel_display_t *display);
|
||||
void (* remove_pixel_display) (ply_boot_splash_plugin_t *plugin,
|
||||
ply_pixel_display_t *display);
|
||||
void (* add_text_display) (ply_boot_splash_plugin_t *plugin,
|
||||
ply_text_display_t *display);
|
||||
void (* remove_text_display) (ply_boot_splash_plugin_t *plugin,
|
||||
ply_text_display_t *display);
|
||||
bool (* show_splash_screen) (ply_boot_splash_plugin_t *plugin,
|
||||
ply_event_loop_t *loop,
|
||||
ply_buffer_t *boot_buffer,
|
||||
|
|
|
|||
|
|
@ -34,18 +34,23 @@
|
|||
#include <wchar.h>
|
||||
|
||||
#include "ply-boot-splash-plugin.h"
|
||||
#include "ply-console.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-trigger.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-progress.h"
|
||||
#include "ply-keyboard.h"
|
||||
#include "ply-key-file.h"
|
||||
|
||||
#ifndef UPDATES_PER_SECOND
|
||||
#define UPDATES_PER_SECOND 30
|
||||
#endif
|
||||
|
||||
#define KEY_CTRL_L ('\100' ^'L')
|
||||
#define KEY_CTRL_T ('\100' ^'T')
|
||||
#define KEY_CTRL_V ('\100' ^'V')
|
||||
|
||||
struct _ply_boot_splash
|
||||
{
|
||||
|
|
@ -53,8 +58,12 @@ struct _ply_boot_splash
|
|||
ply_module_handle_t *module_handle;
|
||||
const ply_boot_splash_plugin_interface_t *plugin_interface;
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
ply_console_t *console;
|
||||
ply_keyboard_t *keyboard;
|
||||
ply_buffer_t *boot_buffer;
|
||||
ply_trigger_t *idle_trigger;
|
||||
ply_list_t *pixel_displays;
|
||||
ply_list_t *text_displays;
|
||||
|
||||
char *theme_path;
|
||||
char *plugin_dir;
|
||||
|
|
@ -66,6 +75,7 @@ struct _ply_boot_splash
|
|||
|
||||
uint32_t is_loaded : 1;
|
||||
uint32_t is_shown : 1;
|
||||
uint32_t should_force_text_mode : 1;
|
||||
};
|
||||
|
||||
typedef const ply_boot_splash_plugin_interface_t *
|
||||
|
|
@ -77,7 +87,8 @@ static void ply_boot_splash_detach_from_event_loop (ply_boot_splash_t *splash);
|
|||
ply_boot_splash_t *
|
||||
ply_boot_splash_new (const char *theme_path,
|
||||
const char *plugin_dir,
|
||||
ply_buffer_t *boot_buffer)
|
||||
ply_buffer_t *boot_buffer,
|
||||
ply_console_t *console)
|
||||
{
|
||||
ply_boot_splash_t *splash;
|
||||
|
||||
|
|
@ -91,22 +102,162 @@ ply_boot_splash_new (const char *theme_path,
|
|||
splash->is_shown = false;
|
||||
|
||||
splash->boot_buffer = boot_buffer;
|
||||
splash->console = console;
|
||||
splash->pixel_displays = ply_list_new ();
|
||||
splash->text_displays = ply_list_new ();
|
||||
|
||||
return splash;
|
||||
}
|
||||
|
||||
void
|
||||
ply_boot_splash_add_window (ply_boot_splash_t *splash,
|
||||
ply_window_t *window)
|
||||
static void
|
||||
refresh_displays (ply_boot_splash_t *splash)
|
||||
{
|
||||
splash->plugin_interface->add_window (splash->plugin, window);
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (splash->pixel_displays);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_pixel_display_t *display;
|
||||
ply_list_node_t *next_node;
|
||||
unsigned long width, height;
|
||||
|
||||
display = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (splash->pixel_displays, node);
|
||||
|
||||
width = ply_pixel_display_get_width (display);
|
||||
height = ply_pixel_display_get_height (display);
|
||||
|
||||
ply_pixel_display_draw_area (display, 0, 0, width, height);
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
node = ply_list_get_first_node (splash->text_displays);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_text_display_t *display;
|
||||
ply_list_node_t *next_node;
|
||||
int number_of_columns, number_of_rows;
|
||||
|
||||
display = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (splash->text_displays, node);
|
||||
|
||||
number_of_columns = ply_text_display_get_number_of_columns (display);
|
||||
number_of_rows = ply_text_display_get_number_of_rows (display);
|
||||
|
||||
ply_text_display_draw_area (display, 0, 0,
|
||||
number_of_columns,
|
||||
number_of_rows);
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_keyboard_input (ply_boot_splash_t *splash,
|
||||
const char *keyboard_input,
|
||||
size_t character_size)
|
||||
{
|
||||
wchar_t key;
|
||||
|
||||
if ((ssize_t) mbrtowc (&key, keyboard_input, character_size, NULL) > 0)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case KEY_CTRL_L:
|
||||
refresh_displays (splash);
|
||||
return;
|
||||
|
||||
case KEY_CTRL_T:
|
||||
ply_trace ("toggle text mode!");
|
||||
splash->should_force_text_mode = !splash->should_force_text_mode;
|
||||
ply_console_force_text_mode (splash->console,
|
||||
splash->should_force_text_mode);
|
||||
ply_trace ("text mode toggled!");
|
||||
return;
|
||||
|
||||
case KEY_CTRL_V:
|
||||
ply_trace ("toggle verbose mode!");
|
||||
ply_toggle_tracing ();
|
||||
ply_trace ("verbose mode toggled!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ply_boot_splash_remove_window (ply_boot_splash_t *splash,
|
||||
ply_window_t *window)
|
||||
ply_boot_splash_set_keyboard (ply_boot_splash_t *splash,
|
||||
ply_keyboard_t *keyboard)
|
||||
{
|
||||
splash->plugin_interface->remove_window (splash->plugin, window);
|
||||
splash->keyboard = keyboard;
|
||||
|
||||
ply_keyboard_add_input_handler (keyboard,
|
||||
(ply_keyboard_input_handler_t)
|
||||
on_keyboard_input, splash);
|
||||
|
||||
if (splash->plugin_interface->set_keyboard == NULL)
|
||||
return;
|
||||
|
||||
splash->plugin_interface->set_keyboard (splash->plugin, keyboard);
|
||||
}
|
||||
|
||||
void
|
||||
ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash)
|
||||
{
|
||||
ply_keyboard_remove_input_handler (splash->keyboard,
|
||||
(ply_keyboard_input_handler_t)
|
||||
on_keyboard_input);
|
||||
|
||||
if (splash->plugin_interface->set_keyboard == NULL)
|
||||
return;
|
||||
|
||||
splash->plugin_interface->unset_keyboard (splash->plugin, splash->keyboard);
|
||||
}
|
||||
|
||||
void
|
||||
ply_boot_splash_add_pixel_display (ply_boot_splash_t *splash,
|
||||
ply_pixel_display_t *display)
|
||||
{
|
||||
ply_list_append_data (splash->pixel_displays, display);
|
||||
|
||||
if (splash->plugin_interface->add_pixel_display == NULL)
|
||||
return;
|
||||
|
||||
splash->plugin_interface->add_pixel_display (splash->plugin, display);
|
||||
}
|
||||
|
||||
void
|
||||
ply_boot_splash_remove_pixel_display (ply_boot_splash_t *splash,
|
||||
ply_pixel_display_t *display)
|
||||
{
|
||||
ply_list_remove_data (splash->pixel_displays, display);
|
||||
|
||||
if (splash->plugin_interface->remove_pixel_display == NULL)
|
||||
return;
|
||||
|
||||
splash->plugin_interface->remove_pixel_display (splash->plugin, display);
|
||||
}
|
||||
|
||||
void
|
||||
ply_boot_splash_add_text_display (ply_boot_splash_t *splash,
|
||||
ply_text_display_t *display)
|
||||
{
|
||||
ply_list_append_data (splash->text_displays, display);
|
||||
|
||||
if (splash->plugin_interface->add_text_display == NULL)
|
||||
return;
|
||||
|
||||
splash->plugin_interface->add_text_display (splash->plugin, display);
|
||||
}
|
||||
|
||||
void
|
||||
ply_boot_splash_remove_text_display (ply_boot_splash_t *splash,
|
||||
ply_text_display_t *display)
|
||||
{
|
||||
ply_list_remove_data (splash->text_displays, display);
|
||||
|
||||
if (splash->plugin_interface->remove_pixel_display == NULL)
|
||||
return;
|
||||
|
||||
splash->plugin_interface->remove_text_display (splash->plugin, display);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -223,6 +374,8 @@ ply_boot_splash_free (ply_boot_splash_t *splash)
|
|||
if (splash->idle_trigger != NULL)
|
||||
ply_trigger_free (splash->idle_trigger);
|
||||
|
||||
ply_list_free (splash->pixel_displays);
|
||||
ply_list_free (splash->text_displays);
|
||||
free (splash->theme_path);
|
||||
free (splash->plugin_dir);
|
||||
free (splash);
|
||||
|
|
@ -354,6 +507,8 @@ ply_boot_splash_hide (ply_boot_splash_t *splash)
|
|||
splash->plugin_interface->hide_splash_screen (splash->plugin,
|
||||
splash->loop);
|
||||
|
||||
ply_console_set_mode (splash->console, PLY_CONSOLE_MODE_TEXT);
|
||||
|
||||
splash->is_shown = false;
|
||||
|
||||
if (splash->loop != NULL)
|
||||
|
|
@ -479,7 +634,6 @@ typedef struct test_state test_state_t;
|
|||
struct test_state {
|
||||
ply_event_loop_t *loop;
|
||||
ply_boot_splash_t *splash;
|
||||
ply_window_t *window;
|
||||
ply_buffer_t *buffer;
|
||||
};
|
||||
|
||||
|
|
@ -501,6 +655,33 @@ on_quit (test_state_t *state)
|
|||
ply_event_loop_exit (state->loop, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
add_displays_to_splash_from_renderer (test_state_t *state,
|
||||
ply_renderer_t *renderer)
|
||||
{
|
||||
ply_list_t *heads;
|
||||
ply_list_node_t *node;
|
||||
|
||||
heads = ply_renderer_get_heads (renderer);
|
||||
|
||||
node = ply_list_get_first_node (heads);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
ply_renderer_head_t *head;
|
||||
ply_pixel_display_t *display;
|
||||
|
||||
head = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (heads, node);
|
||||
|
||||
display = ply_pixel_display_new (renderer, head);
|
||||
|
||||
ply_boot_splash_add_pixel_display (state->splash, display);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
|
|
@ -509,6 +690,11 @@ main (int argc,
|
|||
test_state_t state;
|
||||
char *tty_name;
|
||||
const char *theme_path;
|
||||
ply_text_display_t *text_display;
|
||||
ply_renderer_t *renderer;
|
||||
ply_console_t *console;
|
||||
ply_terminal_t *terminal;
|
||||
ply_keyboard_t *keyboard;
|
||||
|
||||
exit_code = 0;
|
||||
|
||||
|
|
@ -524,29 +710,51 @@ main (int argc,
|
|||
else
|
||||
tty_name = strdup("tty0");
|
||||
|
||||
state.window = ply_window_new (tty_name);
|
||||
free(tty_name);
|
||||
ply_window_attach_to_event_loop (state.window, state.loop);
|
||||
console = ply_console_new ();
|
||||
|
||||
if (!ply_window_open (state.window))
|
||||
if (!ply_console_open (console))
|
||||
{
|
||||
perror ("could not open terminal");
|
||||
perror ("could not open console");
|
||||
return errno;
|
||||
}
|
||||
|
||||
ply_window_attach_to_event_loop (state.window, state.loop);
|
||||
ply_window_add_escape_handler (state.window,
|
||||
(ply_window_escape_handler_t) on_quit, &state);
|
||||
terminal = ply_terminal_new (tty_name);
|
||||
|
||||
if (!ply_terminal_open (terminal))
|
||||
{
|
||||
perror ("could not open tty");
|
||||
return errno;
|
||||
}
|
||||
|
||||
renderer = ply_renderer_new (NULL, terminal, console);
|
||||
free(tty_name);
|
||||
|
||||
if (!ply_renderer_open (renderer))
|
||||
{
|
||||
perror ("could not open renderer /dev/fb");
|
||||
ply_renderer_free (renderer);
|
||||
return errno;
|
||||
}
|
||||
|
||||
keyboard = ply_keyboard_new_for_renderer (renderer);
|
||||
ply_keyboard_add_escape_handler (keyboard,
|
||||
(ply_keyboard_escape_handler_t) on_quit, &state);
|
||||
|
||||
state.buffer = ply_buffer_new ();
|
||||
state.splash = ply_boot_splash_new (theme_path, PLYMOUTH_PLUGIN_PATH, state.buffer);
|
||||
state.splash = ply_boot_splash_new (theme_path, PLYMOUTH_PLUGIN_PATH, state.buffer, console);
|
||||
|
||||
if (!ply_boot_splash_load (state.splash))
|
||||
{
|
||||
perror ("could not load splash screen");
|
||||
return errno;
|
||||
}
|
||||
|
||||
ply_boot_splash_add_window (state.splash, state.window);
|
||||
ply_boot_splash_set_keyboard (state.splash, keyboard);
|
||||
add_displays_to_splash_from_renderer (&state, renderer);
|
||||
|
||||
text_display = ply_text_display_new (terminal, console);
|
||||
ply_boot_splash_add_text_display (state.splash, text_display);
|
||||
|
||||
ply_boot_splash_attach_to_event_loop (state.splash, state.loop);
|
||||
|
||||
if (!ply_boot_splash_show (state.splash, PLY_BOOT_SPLASH_MODE_BOOT_UP))
|
||||
|
|
@ -561,7 +769,6 @@ main (int argc,
|
|||
on_timeout,
|
||||
state.splash);
|
||||
exit_code = ply_event_loop_run (state.loop);
|
||||
ply_window_free (state.window);
|
||||
ply_boot_splash_free (state.splash);
|
||||
ply_buffer_free (state.buffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,13 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-window.h"
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-console.h"
|
||||
#include "ply-keyboard.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-text-display.h"
|
||||
#include "ply-progress.h"
|
||||
|
||||
#include "ply-boot-splash-plugin.h"
|
||||
|
||||
typedef struct _ply_boot_splash ply_boot_splash_t;
|
||||
|
|
@ -39,13 +43,21 @@ typedef void (* ply_boot_splash_on_idle_handler_t) (void *user_data);
|
|||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_boot_splash_t *ply_boot_splash_new (const char *theme_path,
|
||||
const char *plugin_dir,
|
||||
ply_buffer_t *boot_buffer);
|
||||
ply_buffer_t *boot_buffer,
|
||||
ply_console_t *console);
|
||||
bool ply_boot_splash_load (ply_boot_splash_t *splash);
|
||||
void ply_boot_splash_unload (ply_boot_splash_t *splash);
|
||||
void ply_boot_splash_add_window (ply_boot_splash_t *splash,
|
||||
ply_window_t *window);
|
||||
void ply_boot_splash_remove_window (ply_boot_splash_t *splash,
|
||||
ply_window_t *window);
|
||||
void ply_boot_splash_set_keyboard (ply_boot_splash_t *splash,
|
||||
ply_keyboard_t *keyboard);
|
||||
void ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash);
|
||||
void ply_boot_splash_add_pixel_display (ply_boot_splash_t *splash,
|
||||
ply_pixel_display_t *display);
|
||||
void ply_boot_splash_remove_pixel_display (ply_boot_splash_t *splash,
|
||||
ply_pixel_display_t *display);
|
||||
void ply_boot_splash_add_text_display (ply_boot_splash_t *splash,
|
||||
ply_text_display_t *display);
|
||||
void ply_boot_splash_remove_text_display (ply_boot_splash_t *splash,
|
||||
ply_text_display_t *display);
|
||||
void ply_boot_splash_free (ply_boot_splash_t *splash);
|
||||
bool ply_boot_splash_show (ply_boot_splash_t *splash,
|
||||
ply_boot_splash_mode_t mode);
|
||||
|
|
|
|||
406
src/libplybootsplash/ply-console.c
Normal file
406
src/libplybootsplash/ply-console.c
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
/* ply-console.c - console APIs
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ply-console.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <linux/kd.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/vt.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
#ifndef TEXT_PALETTE_SIZE
|
||||
#define TEXT_PALETTE_SIZE 48
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_console_active_vt_changed_handler_t handler;
|
||||
void *user_data;
|
||||
} ply_console_active_vt_changed_closure_t;
|
||||
|
||||
struct _ply_console
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
|
||||
int fd;
|
||||
int active_vt;
|
||||
int next_active_vt;
|
||||
|
||||
ply_list_t *vt_change_closures;
|
||||
ply_fd_watch_t *fd_watch;
|
||||
|
||||
uint32_t is_open : 1;
|
||||
uint32_t is_watching_for_vt_changes : 1;
|
||||
uint32_t should_force_text_mode : 1;
|
||||
};
|
||||
|
||||
static bool ply_console_open_device (ply_console_t *console);
|
||||
|
||||
ply_console_t *
|
||||
ply_console_new (void)
|
||||
{
|
||||
ply_console_t *console;
|
||||
|
||||
console = calloc (1, sizeof (ply_console_t));
|
||||
|
||||
console->loop = ply_event_loop_get_default ();
|
||||
console->vt_change_closures = ply_list_new ();
|
||||
console->fd = -1;
|
||||
|
||||
return console;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_console_look_up_active_vt (ply_console_t *console)
|
||||
{
|
||||
struct vt_stat console_state = { 0 };
|
||||
|
||||
if (ioctl (console->fd, VT_GETSTATE, &console_state) < 0)
|
||||
return;
|
||||
|
||||
console->active_vt = console_state.v_active;
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_set_mode (ply_console_t *console,
|
||||
ply_console_mode_t mode)
|
||||
{
|
||||
|
||||
assert (console != NULL);
|
||||
assert (mode == PLY_CONSOLE_MODE_TEXT || mode == PLY_CONSOLE_MODE_GRAPHICS);
|
||||
|
||||
if (console->should_force_text_mode)
|
||||
mode = PLY_CONSOLE_MODE_TEXT;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case PLY_CONSOLE_MODE_TEXT:
|
||||
if (ioctl (console->fd, KDSETMODE, KD_TEXT) < 0)
|
||||
return;
|
||||
break;
|
||||
|
||||
case PLY_CONSOLE_MODE_GRAPHICS:
|
||||
if (ioctl (console->fd, KDSETMODE, KD_GRAPHICS) < 0)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_force_text_mode (ply_console_t *console,
|
||||
bool should_force)
|
||||
{
|
||||
console->should_force_text_mode = should_force;
|
||||
}
|
||||
|
||||
static void
|
||||
on_tty_disconnected (ply_console_t *console)
|
||||
{
|
||||
ply_trace ("console tty disconnected (fd %d)", console->fd);
|
||||
console->fd_watch = NULL;
|
||||
console->fd = -1;
|
||||
|
||||
ply_trace ("trying to reopen console");
|
||||
ply_console_open_device (console);
|
||||
}
|
||||
|
||||
static void
|
||||
do_active_vt_changed (ply_console_t *console)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (console->vt_change_closures);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_console_active_vt_changed_closure_t *closure;
|
||||
ply_list_node_t *next_node;
|
||||
|
||||
closure = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (console->vt_change_closures, node);
|
||||
|
||||
if (closure->handler != NULL)
|
||||
closure->handler (closure->user_data, console);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_leave_vt (ply_console_t *console)
|
||||
{
|
||||
ioctl (console->fd, VT_RELDISP, 1);
|
||||
|
||||
if (console->next_active_vt > 0)
|
||||
{
|
||||
ioctl (console->fd, VT_WAITACTIVE, console->next_active_vt);
|
||||
console->next_active_vt = 0;
|
||||
}
|
||||
|
||||
ply_console_look_up_active_vt (console);
|
||||
do_active_vt_changed (console);
|
||||
}
|
||||
|
||||
static void
|
||||
on_enter_vt (ply_console_t *console)
|
||||
{
|
||||
ioctl (console->fd, VT_RELDISP, VT_ACKACQ);
|
||||
|
||||
ply_console_look_up_active_vt (console);
|
||||
do_active_vt_changed (console);
|
||||
}
|
||||
|
||||
static void
|
||||
ply_console_watch_for_vt_changes (ply_console_t *console)
|
||||
{
|
||||
assert (console != NULL);
|
||||
assert (console->fd >= 0);
|
||||
|
||||
struct vt_mode mode = { 0 };
|
||||
|
||||
if (console->is_watching_for_vt_changes)
|
||||
return;
|
||||
|
||||
mode.mode = VT_PROCESS;
|
||||
mode.relsig = SIGUSR1;
|
||||
mode.acqsig = SIGUSR2;
|
||||
|
||||
if (!ioctl (console->fd, VT_SETMODE, &mode) < 0)
|
||||
return;
|
||||
|
||||
ply_event_loop_watch_signal (console->loop,
|
||||
SIGUSR1,
|
||||
(ply_event_handler_t)
|
||||
on_leave_vt, console);
|
||||
|
||||
ply_event_loop_watch_signal (console->loop,
|
||||
SIGUSR2,
|
||||
(ply_event_handler_t)
|
||||
on_enter_vt, console);
|
||||
|
||||
console->is_watching_for_vt_changes = true;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_console_stop_watching_for_vt_changes (ply_console_t *console)
|
||||
{
|
||||
struct vt_mode mode = { 0 };
|
||||
|
||||
if (!console->is_watching_for_vt_changes)
|
||||
return;
|
||||
|
||||
console->is_watching_for_vt_changes = false;
|
||||
|
||||
ply_event_loop_stop_watching_signal (console->loop, SIGUSR1);
|
||||
ply_event_loop_stop_watching_signal (console->loop, SIGUSR2);
|
||||
|
||||
mode.mode = VT_AUTO;
|
||||
ioctl (console->fd, VT_SETMODE, &mode);
|
||||
}
|
||||
|
||||
static bool
|
||||
ply_console_open_device (ply_console_t *console)
|
||||
{
|
||||
assert (console != NULL);
|
||||
assert (console->fd < 0);
|
||||
assert (console->fd_watch == NULL);
|
||||
|
||||
console->fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
|
||||
|
||||
if (console->fd < 0)
|
||||
return false;
|
||||
|
||||
console->fd_watch = ply_event_loop_watch_fd (console->loop, console->fd,
|
||||
PLY_EVENT_LOOP_FD_STATUS_NONE,
|
||||
(ply_event_handler_t) NULL,
|
||||
(ply_event_handler_t) on_tty_disconnected,
|
||||
console);
|
||||
|
||||
ply_console_look_up_active_vt (console);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_console_open (ply_console_t *console)
|
||||
{
|
||||
assert (console != NULL);
|
||||
|
||||
if (!ply_console_open_device (console))
|
||||
{
|
||||
ply_trace ("could not open console: %m");
|
||||
return false;
|
||||
}
|
||||
|
||||
ply_console_watch_for_vt_changes (console);
|
||||
|
||||
console->is_open = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ply_console_get_fd (ply_console_t *console)
|
||||
{
|
||||
return console->fd;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_console_is_open (ply_console_t *console)
|
||||
{
|
||||
return console->is_open;
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_close (ply_console_t *console)
|
||||
{
|
||||
console->is_open = false;
|
||||
|
||||
ply_console_stop_watching_for_vt_changes (console);
|
||||
|
||||
if (console->fd_watch != NULL)
|
||||
{
|
||||
ply_trace ("stop watching tty fd");
|
||||
ply_event_loop_stop_watching_fd (console->loop, console->fd_watch);
|
||||
console->fd_watch = NULL;
|
||||
}
|
||||
|
||||
close (console->fd);
|
||||
console->fd = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
free_vt_change_closures (ply_console_t *console)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (console->vt_change_closures);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_console_active_vt_changed_closure_t *closure;
|
||||
ply_list_node_t *next_node;
|
||||
|
||||
closure = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (console->vt_change_closures, node);
|
||||
|
||||
free (closure);
|
||||
node = next_node;
|
||||
}
|
||||
ply_list_free (console->vt_change_closures);
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_free (ply_console_t *console)
|
||||
{
|
||||
if (console == NULL)
|
||||
return;
|
||||
|
||||
ply_console_close (console);
|
||||
|
||||
free_vt_change_closures (console);
|
||||
free (console);
|
||||
}
|
||||
|
||||
int
|
||||
ply_console_get_active_vt (ply_console_t *console)
|
||||
{
|
||||
return console->active_vt;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_console_set_active_vt (ply_console_t *console,
|
||||
int vt_number)
|
||||
{
|
||||
assert (console != NULL);
|
||||
assert (vt_number > 0);
|
||||
|
||||
if (vt_number == console->active_vt)
|
||||
return true;
|
||||
|
||||
if (ioctl (console->fd, VT_ACTIVATE, vt_number) < 0)
|
||||
return false;
|
||||
|
||||
console->next_active_vt = vt_number;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_watch_for_active_vt_change (ply_console_t *console,
|
||||
ply_console_active_vt_changed_handler_t active_vt_changed_handler,
|
||||
void *user_data)
|
||||
{
|
||||
ply_console_active_vt_changed_closure_t *closure;
|
||||
|
||||
closure = calloc (1, sizeof (*closure));
|
||||
closure->handler = active_vt_changed_handler;
|
||||
closure->user_data = user_data;
|
||||
|
||||
ply_list_append_data (console->vt_change_closures, closure);
|
||||
}
|
||||
|
||||
void
|
||||
ply_console_stop_watching_for_active_vt_change (ply_console_t *console,
|
||||
ply_console_active_vt_changed_handler_t active_vt_changed_handler,
|
||||
void *user_data)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (console->vt_change_closures);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_console_active_vt_changed_closure_t *closure;
|
||||
ply_list_node_t *next_node;
|
||||
|
||||
closure = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (console->vt_change_closures, node);
|
||||
|
||||
if (closure->handler == active_vt_changed_handler &&
|
||||
closure->user_data == user_data)
|
||||
{
|
||||
free (closure);
|
||||
ply_list_remove_node (console->vt_change_closures, node);
|
||||
}
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
70
src/libplybootsplash/ply-console.h
Normal file
70
src/libplybootsplash/ply-console.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* ply-console.h - APIs for consoleing text
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_CONSOLE_H
|
||||
#define PLY_CONSOLE_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct _ply_console ply_console_t;
|
||||
typedef void (* ply_console_active_vt_changed_handler_t) (void *user_data,
|
||||
ply_console_t *console);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLY_CONSOLE_MODE_TEXT,
|
||||
PLY_CONSOLE_MODE_GRAPHICS
|
||||
} ply_console_mode_t;
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_console_t *ply_console_new (void);
|
||||
|
||||
void ply_console_free (ply_console_t *console);
|
||||
|
||||
bool ply_console_open (ply_console_t *console);
|
||||
bool ply_console_is_open (ply_console_t *console);
|
||||
void ply_console_close (ply_console_t *console);
|
||||
|
||||
void ply_console_set_mode (ply_console_t *console,
|
||||
ply_console_mode_t mode);
|
||||
|
||||
void ply_console_force_text_mode (ply_console_t *console,
|
||||
bool should_force);
|
||||
|
||||
int ply_console_get_fd (ply_console_t *console);
|
||||
int ply_console_get_active_vt (ply_console_t *console);
|
||||
bool ply_console_set_active_vt (ply_console_t *console,
|
||||
int vt_number);
|
||||
|
||||
void ply_console_watch_for_active_vt_change (ply_console_t *console,
|
||||
ply_console_active_vt_changed_handler_t active_vt_changed_handler,
|
||||
void *user_data);
|
||||
void ply_console_stop_watching_for_active_vt_change (ply_console_t *console,
|
||||
ply_console_active_vt_changed_handler_t active_vt_changed_handler,
|
||||
void *user_data);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PLY_CONSOLE_H */
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
|
|
@ -45,10 +45,10 @@
|
|||
#include "ply-array.h"
|
||||
#include "ply-label.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-image.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
|
|
@ -60,9 +60,8 @@ struct _ply_entry
|
|||
{
|
||||
ply_event_loop_t *loop;
|
||||
|
||||
ply_window_t *window;
|
||||
ply_frame_buffer_t *frame_buffer;
|
||||
ply_frame_buffer_area_t area;
|
||||
ply_pixel_display_t *display;
|
||||
ply_rectangle_t area;
|
||||
ply_image_t *text_field_image;
|
||||
ply_image_t *bullet_image;
|
||||
ply_label_t *label;
|
||||
|
|
@ -148,33 +147,36 @@ ply_entry_load (ply_entry_t *entry)
|
|||
}
|
||||
|
||||
static void
|
||||
erase_entry_area (ply_entry_t *entry)
|
||||
ply_entry_draw (ply_entry_t *entry)
|
||||
{
|
||||
ply_window_erase_area (entry->window,
|
||||
entry->area.x, entry->area.y,
|
||||
entry->area.width, entry->area.height);
|
||||
ply_pixel_display_draw_area (entry->display,
|
||||
entry->area.x,
|
||||
entry->area.y,
|
||||
entry->area.width,
|
||||
entry->area.height);
|
||||
}
|
||||
|
||||
void
|
||||
ply_entry_draw (ply_entry_t *entry)
|
||||
ply_entry_draw_area (ply_entry_t *entry,
|
||||
ply_pixel_buffer_t *pixel_buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
ply_frame_buffer_area_t bullet_area;
|
||||
ply_rectangle_t bullet_area;
|
||||
uint32_t *text_field_data, *bullet_data;
|
||||
int i, number_of_visible_bullets;
|
||||
|
||||
if (entry->is_hidden)
|
||||
return;
|
||||
|
||||
ply_frame_buffer_pause_updates (entry->frame_buffer);
|
||||
|
||||
text_field_data = ply_image_get_data (entry->text_field_image);
|
||||
|
||||
erase_entry_area (entry);
|
||||
|
||||
ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer,
|
||||
ply_pixel_buffer_fill_with_argb32_data (pixel_buffer,
|
||||
&entry->area, 0, 0,
|
||||
text_field_data);
|
||||
|
||||
|
||||
if (entry->is_password)
|
||||
{
|
||||
bullet_data = ply_image_get_data (entry->bullet_image);
|
||||
|
|
@ -193,7 +195,7 @@ ply_entry_draw (ply_entry_t *entry)
|
|||
bullet_area.x = entry->area.x;
|
||||
bullet_area.y = entry->area.y + entry->area.height / 2.0 - bullet_area.height / 2.0;
|
||||
|
||||
ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer,
|
||||
ply_pixel_buffer_fill_with_argb32_data (pixel_buffer,
|
||||
&bullet_area, bullet_area.width / 2.0, 0,
|
||||
bullet_data);
|
||||
}
|
||||
|
|
@ -203,7 +205,7 @@ ply_entry_draw (ply_entry_t *entry)
|
|||
bullet_area.x = entry->area.x + i * bullet_area.width + bullet_area.width / 2.0;
|
||||
bullet_area.y = entry->area.y + entry->area.height / 2.0 - bullet_area.height / 2.0;
|
||||
|
||||
ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer,
|
||||
ply_pixel_buffer_fill_with_argb32_data (pixel_buffer,
|
||||
&bullet_area, 0, 0,
|
||||
bullet_data);
|
||||
}
|
||||
|
|
@ -211,10 +213,10 @@ ply_entry_draw (ply_entry_t *entry)
|
|||
else
|
||||
{
|
||||
ply_label_set_text (entry->label, entry->text);
|
||||
ply_label_show (entry->label, entry->window, entry->area.x, entry->area.y);
|
||||
|
||||
ply_label_draw_area (entry->label, pixel_buffer,
|
||||
entry->area.x, entry->area.y,
|
||||
entry->area.width, entry->area.height);
|
||||
}
|
||||
ply_frame_buffer_unpause_updates (entry->frame_buffer);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -266,18 +268,17 @@ ply_entry_set_text (ply_entry_t *entry, const char* text)
|
|||
}
|
||||
|
||||
void
|
||||
ply_entry_show (ply_entry_t *entry,
|
||||
ply_event_loop_t *loop,
|
||||
ply_window_t *window,
|
||||
long x,
|
||||
long y)
|
||||
ply_entry_show (ply_entry_t *entry,
|
||||
ply_event_loop_t *loop,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y)
|
||||
{
|
||||
assert (entry != NULL);
|
||||
assert (entry->loop == NULL);
|
||||
|
||||
entry->loop = loop;
|
||||
entry->window = window;
|
||||
entry->frame_buffer = ply_window_get_frame_buffer (window);;
|
||||
entry->display = display;
|
||||
|
||||
entry->area.x = x;
|
||||
entry->area.y = y;
|
||||
|
|
@ -290,13 +291,11 @@ ply_entry_show (ply_entry_t *entry,
|
|||
void
|
||||
ply_entry_hide (ply_entry_t *entry)
|
||||
{
|
||||
erase_entry_area (entry);
|
||||
|
||||
entry->frame_buffer = NULL;
|
||||
entry->window = NULL;
|
||||
entry->loop = NULL;
|
||||
|
||||
entry->is_hidden = true;
|
||||
ply_entry_draw (entry);
|
||||
|
||||
entry->display = NULL;
|
||||
entry->loop = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-window.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
|
||||
typedef struct _ply_entry ply_entry_t;
|
||||
|
||||
|
|
@ -39,11 +39,16 @@ bool ply_entry_load (ply_entry_t *entry);
|
|||
|
||||
void ply_entry_show (ply_entry_t *entry,
|
||||
ply_event_loop_t *loop,
|
||||
ply_window_t *window,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y);
|
||||
void ply_entry_hide (ply_entry_t *entry);
|
||||
void ply_entry_draw (ply_entry_t *entry);
|
||||
void ply_entry_draw_area (ply_entry_t *entry,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height);
|
||||
bool ply_entry_is_hidden (ply_entry_t *entry);
|
||||
|
||||
long ply_entry_get_width (ply_entry_t *entry);
|
||||
|
|
|
|||
|
|
@ -400,150 +400,4 @@ ply_image_rotate (ply_image_t *image,
|
|||
return new_image;
|
||||
}
|
||||
|
||||
#ifdef PLY_IMAGE_ENABLE_TEST
|
||||
|
||||
#include "ply-frame-buffer.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <values.h>
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
#ifndef FRAMES_PER_SECOND
|
||||
#define FRAMES_PER_SECOND 50
|
||||
#endif
|
||||
|
||||
static int console_fd;
|
||||
|
||||
static bool
|
||||
hide_cursor (void)
|
||||
{
|
||||
static const char invisible_cursor[] = "\033[?25l\033[?1c";
|
||||
|
||||
if (write (STDOUT_FILENO, invisible_cursor,
|
||||
sizeof (invisible_cursor) - 1) != sizeof (invisible_cursor) - 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static double
|
||||
get_current_time (void)
|
||||
{
|
||||
const double microseconds_per_second = 1000000.0;
|
||||
double timestamp;
|
||||
struct timeval now = { 0L, /* zero-filled */ };
|
||||
|
||||
gettimeofday (&now, NULL);
|
||||
timestamp = ((microseconds_per_second * now.tv_sec) + now.tv_usec) /
|
||||
microseconds_per_second;
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
double start_time = 0.0;
|
||||
int num_frames = 0;
|
||||
|
||||
static void
|
||||
animate_at_time (ply_frame_buffer_t *buffer,
|
||||
ply_image_t *image,
|
||||
double time)
|
||||
{
|
||||
ply_frame_buffer_area_t area;
|
||||
uint32_t *data;
|
||||
long width, height;
|
||||
static double last_opacity = 0.0;
|
||||
double opacity = 0.0;
|
||||
|
||||
data = ply_image_get_data (image);
|
||||
width = ply_image_get_width (image);
|
||||
height = ply_image_get_height (image);
|
||||
|
||||
ply_frame_buffer_get_size (buffer, &area);
|
||||
area.x = (area.width / 2) - (width / 2);
|
||||
area.y = (area.height / 2) - (height / 2);
|
||||
area.width = width;
|
||||
area.height = height;
|
||||
|
||||
opacity = .5 * sin ((time / 4) * (2 * M_PI)) + .8;
|
||||
opacity = CLAMP (opacity, 0, 1.0);
|
||||
|
||||
num_frames++;
|
||||
if (fabs (opacity - last_opacity) <= DBL_MIN)
|
||||
return;
|
||||
|
||||
last_opacity = opacity;
|
||||
|
||||
ply_frame_buffer_pause_updates (buffer);
|
||||
ply_frame_buffer_fill_with_color (buffer, &area, 0.1, 0.1, .7, 1.0);
|
||||
ply_frame_buffer_fill_with_argb32_data_at_opacity (buffer, &area,
|
||||
0, 0, data, opacity);
|
||||
ply_frame_buffer_unpause_updates (buffer);
|
||||
|
||||
if (time > 10.0)
|
||||
ioctl (console_fd, KDSETMODE, KD_TEXT);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
ply_image_t *image;
|
||||
ply_frame_buffer_t *buffer;
|
||||
int exit_code;
|
||||
|
||||
exit_code = 0;
|
||||
|
||||
hide_cursor ();
|
||||
|
||||
if (argc == 1)
|
||||
image = ply_image_new ("booting.png");
|
||||
else
|
||||
image = ply_image_new (argv[1]);
|
||||
|
||||
if (!ply_image_load (image))
|
||||
{
|
||||
exit_code = errno;
|
||||
perror ("could not load image");
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
console_fd = open ("/dev/tty0", O_RDWR);
|
||||
|
||||
buffer = ply_frame_buffer_new (NULL);
|
||||
|
||||
if (!ply_frame_buffer_open (buffer))
|
||||
{
|
||||
exit_code = errno;
|
||||
perror ("could not open framebuffer");
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
start_time = get_current_time ();
|
||||
ply_frame_buffer_fill_with_color (buffer, NULL, 0.1, 0.1, .7, 1.0);
|
||||
while ("we want to see ad-hoc animations")
|
||||
{
|
||||
long sleep_time;
|
||||
double now;
|
||||
|
||||
now = get_current_time ();
|
||||
animate_at_time (buffer, image, now - start_time);
|
||||
sleep_time = 1000000 / FRAMES_PER_SECOND;
|
||||
sleep_time = MAX (sleep_time - ((get_current_time () - now) / 1000000),
|
||||
10000);
|
||||
usleep (sleep_time);
|
||||
}
|
||||
ply_frame_buffer_close (buffer);
|
||||
ply_frame_buffer_free (buffer);
|
||||
|
||||
ply_image_free (image);
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
#endif /* PLY_IMAGE_ENABLE_TEST */
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
|
|
|
|||
583
src/libplybootsplash/ply-keyboard.c
Normal file
583
src/libplybootsplash/ply-keyboard.c
Normal file
|
|
@ -0,0 +1,583 @@
|
|||
/* ply-keyboard.h - APIs for putting up a keyboard screen
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ply-keyboard.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-renderer.h"
|
||||
#include "ply-terminal.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
#define KEY_CTRL_U ('\100' ^'U')
|
||||
#define KEY_CTRL_W ('\100' ^'W')
|
||||
#define KEY_CTRL_V ('\100' ^'V')
|
||||
#define KEY_ESCAPE ('\100' ^'[')
|
||||
#define KEY_RETURN '\r'
|
||||
#define KEY_BACKSPACE '\177'
|
||||
|
||||
typedef void (* ply_keyboard_handler_t) (void *);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_keyboard_handler_t function;
|
||||
void *user_data;
|
||||
} ply_keyboard_closure_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL,
|
||||
PLY_KEYBOARD_PROVIDER_TYPE_RENDERER
|
||||
} ply_keyboard_provider_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_terminal_t *terminal;
|
||||
ply_fd_watch_t *input_watch;
|
||||
ply_buffer_t *key_buffer;
|
||||
} ply_keyboard_terminal_provider_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_renderer_t *renderer;
|
||||
ply_renderer_input_source_t *input_source;
|
||||
} ply_keyboard_renderer_provider_t;
|
||||
|
||||
typedef union {
|
||||
ply_keyboard_renderer_provider_t *if_renderer;
|
||||
ply_keyboard_terminal_provider_t *if_terminal;
|
||||
} ply_keyboard_provider_t;
|
||||
|
||||
struct _ply_keyboard
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
|
||||
ply_keyboard_provider_type_t provider_type;
|
||||
ply_keyboard_provider_t provider;
|
||||
|
||||
ply_buffer_t *line_buffer;
|
||||
|
||||
ply_list_t *keyboard_input_handler_list;
|
||||
ply_list_t *backspace_handler_list;
|
||||
ply_list_t *escape_handler_list;
|
||||
ply_list_t *enter_handler_list;
|
||||
};
|
||||
|
||||
ply_keyboard_t *
|
||||
ply_keyboard_new_for_terminal (ply_terminal_t *terminal)
|
||||
{
|
||||
ply_keyboard_t *keyboard;
|
||||
|
||||
keyboard = calloc (1, sizeof (ply_keyboard_t));
|
||||
keyboard->line_buffer = ply_buffer_new ();
|
||||
keyboard->keyboard_input_handler_list = ply_list_new ();
|
||||
keyboard->backspace_handler_list = ply_list_new ();
|
||||
keyboard->escape_handler_list = ply_list_new ();
|
||||
keyboard->enter_handler_list = ply_list_new ();
|
||||
keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL;
|
||||
keyboard->provider.if_terminal = calloc (1, sizeof (ply_keyboard_terminal_provider_t));
|
||||
keyboard->provider.if_terminal->terminal = terminal;
|
||||
keyboard->provider.if_terminal->key_buffer = ply_buffer_new ();
|
||||
|
||||
keyboard->loop = ply_event_loop_get_default ();
|
||||
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
ply_keyboard_t *
|
||||
ply_keyboard_new_for_renderer (ply_renderer_t *renderer)
|
||||
{
|
||||
ply_keyboard_t *keyboard;
|
||||
ply_renderer_input_source_t *input_source;
|
||||
|
||||
keyboard = calloc (1, sizeof (ply_keyboard_t));
|
||||
keyboard->line_buffer = ply_buffer_new ();
|
||||
keyboard->keyboard_input_handler_list = ply_list_new ();
|
||||
keyboard->backspace_handler_list = ply_list_new ();
|
||||
keyboard->escape_handler_list = ply_list_new ();
|
||||
keyboard->enter_handler_list = ply_list_new ();
|
||||
keyboard->provider_type = PLY_KEYBOARD_PROVIDER_TYPE_RENDERER;
|
||||
keyboard->provider.if_renderer = calloc (1, sizeof (ply_keyboard_renderer_provider_t));
|
||||
keyboard->provider.if_renderer->renderer = renderer;
|
||||
|
||||
input_source = ply_renderer_get_input_source (renderer);
|
||||
|
||||
keyboard->provider.if_renderer->input_source = input_source;
|
||||
|
||||
keyboard->loop = ply_event_loop_get_default ();
|
||||
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
static void
|
||||
process_backspace (ply_keyboard_t *keyboard)
|
||||
{
|
||||
size_t bytes_to_remove;
|
||||
ssize_t previous_character_size;
|
||||
const char *bytes;
|
||||
size_t size;
|
||||
ply_list_node_t *node;
|
||||
|
||||
bytes = ply_buffer_get_bytes (keyboard->line_buffer);
|
||||
size = ply_buffer_get_size (keyboard->line_buffer);
|
||||
|
||||
bytes_to_remove = MIN (size, PLY_UTF8_CHARACTER_SIZE_MAX);
|
||||
while ((previous_character_size = ply_utf8_character_get_size (bytes + size - bytes_to_remove, bytes_to_remove)) < (ssize_t) bytes_to_remove)
|
||||
{
|
||||
if (previous_character_size > 0)
|
||||
bytes_to_remove -= previous_character_size;
|
||||
else
|
||||
bytes_to_remove--;
|
||||
}
|
||||
|
||||
if (bytes_to_remove <= size)
|
||||
ply_buffer_remove_bytes_at_end (keyboard->line_buffer, bytes_to_remove);
|
||||
|
||||
for (node = ply_list_get_first_node(keyboard->backspace_handler_list);
|
||||
node; node = ply_list_get_next_node(keyboard->backspace_handler_list, node))
|
||||
{
|
||||
ply_keyboard_closure_t *closure = ply_list_node_get_data (node);
|
||||
ply_keyboard_backspace_handler_t backspace_handler =
|
||||
(ply_keyboard_backspace_handler_t) closure->function;
|
||||
backspace_handler (closure->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_line_erase (ply_keyboard_t *keyboard)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
while ((size = ply_buffer_get_size (keyboard->line_buffer)) > 0)
|
||||
process_backspace (keyboard);
|
||||
}
|
||||
|
||||
static void
|
||||
process_keyboard_input (ply_keyboard_t *keyboard,
|
||||
const char *keyboard_input,
|
||||
size_t character_size)
|
||||
{
|
||||
wchar_t key;
|
||||
ply_list_node_t *node;
|
||||
|
||||
if ((ssize_t) mbrtowc (&key, keyboard_input, character_size, NULL) > 0)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case KEY_CTRL_U:
|
||||
case KEY_CTRL_W:
|
||||
ply_trace ("erase line!");
|
||||
process_line_erase (keyboard);
|
||||
return;
|
||||
|
||||
case KEY_CTRL_V:
|
||||
ply_trace ("toggle verbose mode!");
|
||||
ply_toggle_tracing ();
|
||||
ply_trace ("verbose mode toggled!");
|
||||
return;
|
||||
|
||||
case KEY_ESCAPE:
|
||||
ply_trace ("escape key!");
|
||||
for (node = ply_list_get_first_node(keyboard->escape_handler_list);
|
||||
node; node = ply_list_get_next_node(keyboard->escape_handler_list, node))
|
||||
{
|
||||
ply_keyboard_closure_t *closure = ply_list_node_get_data (node);
|
||||
ply_keyboard_escape_handler_t escape_handler = (ply_keyboard_escape_handler_t) closure->function;
|
||||
escape_handler (closure->user_data);
|
||||
}
|
||||
|
||||
ply_trace ("end escape key handler");
|
||||
return;
|
||||
|
||||
case KEY_BACKSPACE:
|
||||
ply_trace ("backspace key!");
|
||||
process_backspace (keyboard);
|
||||
return;
|
||||
|
||||
case KEY_RETURN:
|
||||
ply_trace ("return key!");
|
||||
|
||||
for (node = ply_list_get_first_node(keyboard->enter_handler_list);
|
||||
node; node = ply_list_get_next_node(keyboard->enter_handler_list, node))
|
||||
{
|
||||
ply_keyboard_closure_t *closure = ply_list_node_get_data (node);
|
||||
ply_keyboard_enter_handler_t enter_handler = (ply_keyboard_enter_handler_t) closure->function;
|
||||
enter_handler (closure->user_data, ply_buffer_get_bytes (keyboard->line_buffer));
|
||||
}
|
||||
ply_buffer_clear (keyboard->line_buffer);
|
||||
return;
|
||||
|
||||
default:
|
||||
ply_buffer_append_bytes (keyboard->line_buffer,
|
||||
keyboard_input, character_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (node = ply_list_get_first_node(keyboard->keyboard_input_handler_list);
|
||||
node; node = ply_list_get_next_node(keyboard->keyboard_input_handler_list, node))
|
||||
{
|
||||
ply_keyboard_closure_t *closure = ply_list_node_get_data (node);
|
||||
ply_keyboard_input_handler_t keyboard_input_handler =
|
||||
(ply_keyboard_input_handler_t) closure->function;
|
||||
|
||||
keyboard_input_handler (closure->user_data,
|
||||
keyboard_input, character_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_key_event (ply_keyboard_t *keyboard,
|
||||
ply_buffer_t *buffer)
|
||||
{
|
||||
const char *bytes;
|
||||
size_t size, i;
|
||||
|
||||
bytes = ply_buffer_get_bytes (buffer);
|
||||
size = ply_buffer_get_size (buffer);
|
||||
|
||||
i = 0;
|
||||
while (i < size)
|
||||
{
|
||||
ssize_t character_size;
|
||||
char *keyboard_input;
|
||||
|
||||
character_size = (ssize_t) ply_utf8_character_get_size (bytes + i, size - i);
|
||||
|
||||
if (character_size < 0)
|
||||
break;
|
||||
|
||||
/* If we're at a NUL character walk through it
|
||||
*/
|
||||
if (character_size == 0)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
keyboard_input = strndup (bytes + i, character_size);
|
||||
|
||||
process_keyboard_input (keyboard, keyboard_input, character_size);
|
||||
|
||||
i += character_size;
|
||||
|
||||
free (keyboard_input);
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
ply_buffer_remove_bytes (buffer, i);
|
||||
}
|
||||
|
||||
static bool
|
||||
ply_keyboard_watch_for_renderer_input (ply_keyboard_t *keyboard)
|
||||
{
|
||||
assert (keyboard != NULL);
|
||||
|
||||
if (!ply_renderer_open_input_source (keyboard->provider.if_renderer->renderer,
|
||||
keyboard->provider.if_renderer->input_source))
|
||||
return false;
|
||||
|
||||
ply_renderer_set_handler_for_input_source (keyboard->provider.if_renderer->renderer,
|
||||
keyboard->provider.if_renderer->input_source,
|
||||
(ply_renderer_input_source_handler_t)
|
||||
on_key_event,
|
||||
keyboard);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_keyboard_stop_watching_for_renderer_input (ply_keyboard_t *keyboard)
|
||||
{
|
||||
ply_renderer_set_handler_for_input_source (keyboard->provider.if_renderer->renderer,
|
||||
keyboard->provider.if_renderer->input_source,
|
||||
(ply_renderer_input_source_handler_t)
|
||||
NULL, NULL);
|
||||
|
||||
ply_renderer_close_input_source (keyboard->provider.if_renderer->renderer,
|
||||
keyboard->provider.if_renderer->input_source);
|
||||
}
|
||||
|
||||
static void
|
||||
on_terminal_data (ply_keyboard_t *keyboard)
|
||||
{
|
||||
int terminal_fd;
|
||||
|
||||
terminal_fd = ply_terminal_get_fd (keyboard->provider.if_terminal->terminal);
|
||||
ply_buffer_append_from_fd (keyboard->provider.if_terminal->key_buffer,
|
||||
terminal_fd);
|
||||
on_key_event (keyboard, keyboard->provider.if_terminal->key_buffer);
|
||||
}
|
||||
|
||||
static bool
|
||||
ply_keyboard_watch_for_terminal_input (ply_keyboard_t *keyboard)
|
||||
{
|
||||
int terminal_fd;
|
||||
|
||||
assert (keyboard != NULL);
|
||||
|
||||
terminal_fd = ply_terminal_get_fd (keyboard->provider.if_terminal->terminal);
|
||||
keyboard->provider.if_terminal->input_watch = ply_event_loop_watch_fd (keyboard->loop, terminal_fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
|
||||
(ply_event_handler_t) on_terminal_data, NULL, keyboard);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_keyboard_stop_watching_for_terminal_input (ply_keyboard_t *keyboard)
|
||||
{
|
||||
ply_event_loop_stop_watching_fd (keyboard->loop,
|
||||
keyboard->provider.if_terminal->input_watch);
|
||||
keyboard->provider.if_terminal->input_watch = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_keyboard_watch_for_input (ply_keyboard_t *keyboard)
|
||||
{
|
||||
assert (keyboard != NULL);
|
||||
|
||||
switch (keyboard->provider_type)
|
||||
{
|
||||
case PLY_KEYBOARD_PROVIDER_TYPE_RENDERER:
|
||||
return ply_keyboard_watch_for_renderer_input (keyboard);
|
||||
|
||||
case PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL:
|
||||
return ply_keyboard_watch_for_terminal_input (keyboard);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard)
|
||||
{
|
||||
assert (keyboard != NULL);
|
||||
|
||||
switch (keyboard->provider_type)
|
||||
{
|
||||
case PLY_KEYBOARD_PROVIDER_TYPE_RENDERER:
|
||||
ply_keyboard_stop_watching_for_renderer_input (keyboard);
|
||||
break;
|
||||
|
||||
case PLY_KEYBOARD_PROVIDER_TYPE_TERMINAL:
|
||||
ply_keyboard_stop_watching_for_terminal_input (keyboard);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ply_keyboard_free (ply_keyboard_t *keyboard)
|
||||
{
|
||||
if (keyboard == NULL)
|
||||
return;
|
||||
|
||||
ply_keyboard_stop_watching_for_input (keyboard);
|
||||
|
||||
ply_buffer_free (keyboard->line_buffer);
|
||||
|
||||
if (keyboard->provider_type == PLY_KEYBOARD_PROVIDER_TYPE_RENDERER)
|
||||
{
|
||||
free (keyboard->provider.if_renderer);
|
||||
}
|
||||
else
|
||||
{
|
||||
ply_buffer_free (keyboard->provider.if_terminal->key_buffer);
|
||||
free (keyboard->provider.if_terminal);
|
||||
}
|
||||
|
||||
free (keyboard);
|
||||
}
|
||||
|
||||
static ply_keyboard_closure_t *
|
||||
ply_keyboard_closure_new (ply_keyboard_handler_t function,
|
||||
void *user_data)
|
||||
{
|
||||
ply_keyboard_closure_t *closure = calloc (1, sizeof (ply_keyboard_closure_t));
|
||||
closure->function = function;
|
||||
closure->user_data = user_data;
|
||||
return closure;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ply_keyboard_closure_free (ply_keyboard_closure_t *closure)
|
||||
{
|
||||
free (closure);
|
||||
}
|
||||
|
||||
void
|
||||
ply_keyboard_add_input_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_input_handler_t input_handler,
|
||||
void *user_data)
|
||||
{
|
||||
ply_keyboard_closure_t *closure;
|
||||
|
||||
assert (keyboard != NULL);
|
||||
|
||||
closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) input_handler,
|
||||
user_data);
|
||||
ply_list_append_data (keyboard->keyboard_input_handler_list, closure);
|
||||
}
|
||||
|
||||
void
|
||||
ply_keyboard_remove_input_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_input_handler_t input_handler)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (keyboard != NULL);
|
||||
|
||||
for (node = ply_list_get_first_node(keyboard->keyboard_input_handler_list);
|
||||
node; node = ply_list_get_next_node(keyboard->keyboard_input_handler_list, node))
|
||||
{
|
||||
ply_keyboard_closure_t *closure = ply_list_node_get_data (node);
|
||||
if ((ply_keyboard_input_handler_t) closure->function == input_handler)
|
||||
{
|
||||
ply_keyboard_closure_free (closure);
|
||||
ply_list_remove_node (keyboard->keyboard_input_handler_list, node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ply_keyboard_add_backspace_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_backspace_handler_t backspace_handler,
|
||||
void *user_data)
|
||||
{
|
||||
ply_keyboard_closure_t *closure;
|
||||
|
||||
assert (keyboard != NULL);
|
||||
|
||||
closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) backspace_handler,
|
||||
user_data);
|
||||
ply_list_append_data (keyboard->backspace_handler_list, closure);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ply_keyboard_remove_backspace_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_backspace_handler_t backspace_handler)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (keyboard != NULL);
|
||||
|
||||
for (node = ply_list_get_first_node(keyboard->backspace_handler_list);
|
||||
node; node = ply_list_get_next_node(keyboard->backspace_handler_list, node))
|
||||
{
|
||||
ply_keyboard_closure_t *closure = ply_list_node_get_data (node);
|
||||
if ((ply_keyboard_backspace_handler_t) closure->function == backspace_handler)
|
||||
{
|
||||
ply_keyboard_closure_free (closure);
|
||||
ply_list_remove_node (keyboard->backspace_handler_list, node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ply_keyboard_add_escape_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_escape_handler_t escape_handler,
|
||||
void *user_data)
|
||||
{
|
||||
ply_keyboard_closure_t *closure;
|
||||
|
||||
assert (keyboard != NULL);
|
||||
|
||||
closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) escape_handler,
|
||||
user_data);
|
||||
ply_list_append_data (keyboard->escape_handler_list, closure);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_escape_handler_t escape_handler)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (keyboard != NULL);
|
||||
|
||||
for (node = ply_list_get_first_node(keyboard->escape_handler_list);
|
||||
node; node = ply_list_get_next_node(keyboard->escape_handler_list, node))
|
||||
{
|
||||
ply_keyboard_closure_t *closure = ply_list_node_get_data (node);
|
||||
if ((ply_keyboard_escape_handler_t) closure->function == escape_handler)
|
||||
{
|
||||
ply_keyboard_closure_free (closure);
|
||||
ply_list_remove_node (keyboard->escape_handler_list, node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_enter_handler_t enter_handler,
|
||||
void *user_data)
|
||||
{
|
||||
ply_keyboard_closure_t *closure;
|
||||
|
||||
assert (keyboard != NULL);
|
||||
|
||||
closure = ply_keyboard_closure_new ((ply_keyboard_handler_t) enter_handler,
|
||||
user_data);
|
||||
|
||||
ply_list_append_data (keyboard->enter_handler_list, closure);
|
||||
}
|
||||
|
||||
void
|
||||
ply_keyboard_remove_enter_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_enter_handler_t enter_handler)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (keyboard != NULL);
|
||||
|
||||
for (node = ply_list_get_first_node(keyboard->enter_handler_list);
|
||||
node; node = ply_list_get_next_node(keyboard->enter_handler_list, node))
|
||||
{
|
||||
ply_keyboard_closure_t *closure = ply_list_node_get_data (node);
|
||||
if ((ply_keyboard_enter_handler_t) closure->function == enter_handler)
|
||||
{
|
||||
ply_keyboard_closure_free (closure);
|
||||
ply_list_remove_node (keyboard->enter_handler_list, node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
78
src/libplybootsplash/ply-keyboard.h
Normal file
78
src/libplybootsplash/ply-keyboard.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/* ply-keyboard.h - APIs for putting up a splash screen
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_KEYBOARD_H
|
||||
#define PLY_KEYBOARD_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-renderer.h"
|
||||
|
||||
typedef struct _ply_keyboard ply_keyboard_t;
|
||||
|
||||
typedef void (* ply_keyboard_input_handler_t) (void *user_data,
|
||||
const char *keyboard_input,
|
||||
size_t character_size);
|
||||
|
||||
typedef void (* ply_keyboard_backspace_handler_t) (void *user_data);
|
||||
|
||||
typedef void (* ply_keyboard_escape_handler_t) (void *user_data);
|
||||
|
||||
typedef void (* ply_keyboard_enter_handler_t) (void *user_data,
|
||||
const char *line);
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_keyboard_t *ply_keyboard_new_for_terminal (ply_terminal_t *terminal);
|
||||
ply_keyboard_t *ply_keyboard_new_for_renderer (ply_renderer_t *renderer);
|
||||
void ply_keyboard_free (ply_keyboard_t *keyboard);
|
||||
|
||||
void ply_keyboard_add_input_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_input_handler_t input_handler,
|
||||
void *user_data);
|
||||
void ply_keyboard_remove_input_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_input_handler_t input_handler);
|
||||
void ply_keyboard_add_backspace_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_backspace_handler_t backspace_handler,
|
||||
void *user_data);
|
||||
void ply_keyboard_remove_backspace_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_backspace_handler_t backspace_handler);
|
||||
void ply_keyboard_add_escape_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_escape_handler_t escape_handler,
|
||||
void *user_data);
|
||||
void ply_keyboard_remove_escape_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_escape_handler_t escape_handler);
|
||||
void ply_keyboard_add_enter_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_enter_handler_t enter_handler,
|
||||
void *user_data);
|
||||
void ply_keyboard_remove_enter_handler (ply_keyboard_t *keyboard,
|
||||
ply_keyboard_enter_handler_t enter_handler);
|
||||
|
||||
bool ply_keyboard_watch_for_input (ply_keyboard_t *keyboard);
|
||||
void ply_keyboard_stop_watching_for_input (ply_keyboard_t *keyboard);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PLY_KEYBOARD_H */
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
|
|
@ -27,7 +27,8 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-window.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
|
||||
typedef struct _ply_label_plugin ply_label_plugin_t;
|
||||
typedef struct _ply_label_plugin_control ply_label_plugin_control_t;
|
||||
|
|
@ -37,11 +38,16 @@ typedef struct
|
|||
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_window_t *window,
|
||||
long x,
|
||||
long y);
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y);
|
||||
void (* hide_control) (ply_label_plugin_control_t *label);
|
||||
void (* draw_control) (ply_label_plugin_control_t *label);
|
||||
void (* draw_control) (ply_label_plugin_control_t *label,
|
||||
ply_pixel_buffer_t *pixel_buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height);
|
||||
bool (* is_control_hidden) (ply_label_plugin_control_t *label);
|
||||
|
||||
void (* set_text_for_control) (ply_label_plugin_control_t *label,
|
||||
|
|
|
|||
|
|
@ -136,10 +136,10 @@ ply_label_unload_plugin (ply_label_t *label)
|
|||
}
|
||||
|
||||
bool
|
||||
ply_label_show (ply_label_t *label,
|
||||
ply_window_t *window,
|
||||
long x,
|
||||
long y)
|
||||
ply_label_show (ply_label_t *label,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y)
|
||||
{
|
||||
if (label->plugin_interface == NULL)
|
||||
{
|
||||
|
|
@ -148,7 +148,7 @@ ply_label_show (ply_label_t *label,
|
|||
}
|
||||
|
||||
return label->plugin_interface->show_control (label->control,
|
||||
window, x, y);
|
||||
display, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -156,8 +156,22 @@ ply_label_draw (ply_label_t *label)
|
|||
{
|
||||
if (label->plugin_interface == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
label->plugin_interface->draw_control (label->control);
|
||||
void
|
||||
ply_label_draw_area (ply_label_t *label,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
if (label->plugin_interface == NULL)
|
||||
return;
|
||||
|
||||
label->plugin_interface->draw_control (label->control,
|
||||
buffer,
|
||||
x, y, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-window.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
|
||||
typedef struct _ply_label ply_label_t;
|
||||
|
||||
|
|
@ -35,13 +36,19 @@ typedef struct _ply_label ply_label_t;
|
|||
ply_label_t *ply_label_new (void);
|
||||
void ply_label_free (ply_label_t *label);
|
||||
|
||||
bool ply_label_show (ply_label_t *label,
|
||||
ply_window_t *window,
|
||||
long x,
|
||||
long y);
|
||||
bool ply_label_show (ply_label_t *label,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y);
|
||||
|
||||
void ply_label_hide (ply_label_t *label);
|
||||
void ply_label_draw (ply_label_t *label);
|
||||
void ply_label_draw_area (ply_label_t *label,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height);
|
||||
bool ply_label_is_hidden (ply_label_t *label);
|
||||
|
||||
void ply_label_set_text (ply_label_t *label,
|
||||
|
|
|
|||
602
src/libplybootsplash/ply-pixel-buffer.c
Normal file
602
src/libplybootsplash/ply-pixel-buffer.c
Normal file
|
|
@ -0,0 +1,602 @@
|
|||
/* ply-pixel-buffer.c - pixelbuffer abstraction
|
||||
*
|
||||
* Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc.
|
||||
* 2008 Charlie Brej <cbrej@cs.man.ac.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Charlie Brej <cbrej@cs.man.ac.uk>
|
||||
* Kristian Høgsberg <krh@redhat.com>
|
||||
* Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-logger.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct _ply_pixel_buffer
|
||||
{
|
||||
uint32_t *bytes;
|
||||
|
||||
ply_rectangle_t area;
|
||||
ply_list_t *clip_areas;
|
||||
|
||||
ply_region_t *updated_areas;
|
||||
};
|
||||
|
||||
static inline void ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
|
||||
int x,
|
||||
int y,
|
||||
uint32_t pixel_value);
|
||||
|
||||
static void ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
uint32_t pixel_value);
|
||||
|
||||
__attribute__((__pure__))
|
||||
static inline uint32_t
|
||||
blend_two_pixel_values (uint32_t pixel_value_1,
|
||||
uint32_t pixel_value_2)
|
||||
{
|
||||
if ((pixel_value_2 & 0xff000000) == 0xff000000)
|
||||
{
|
||||
uint8_t alpha_1, red_1, green_1, blue_1;
|
||||
uint8_t red_2, green_2, blue_2;
|
||||
uint_least16_t red, green, blue;
|
||||
|
||||
alpha_1 = (uint8_t) (pixel_value_1 >> 24);
|
||||
red_1 = (uint8_t) (pixel_value_1 >> 16);
|
||||
green_1 = (uint8_t) (pixel_value_1 >> 8);
|
||||
blue_1 = (uint8_t) pixel_value_1;
|
||||
|
||||
red_2 = (uint8_t) (pixel_value_2 >> 16);
|
||||
green_2 = (uint8_t) (pixel_value_2 >> 8);
|
||||
blue_2 = (uint8_t) pixel_value_2;
|
||||
|
||||
red = red_1 * 255 + red_2 * (255 - alpha_1);
|
||||
green = green_1 * 255 + green_2 * (255 - alpha_1);
|
||||
blue = blue_1 * 255 + blue_2 * (255 - alpha_1);
|
||||
|
||||
red = (uint8_t) ((red + (red >> 8) + 0x80) >> 8);
|
||||
green = (uint8_t) ((green + (green >> 8) + 0x80) >> 8);
|
||||
blue = (uint8_t) ((blue + (blue >> 8) + 0x80) >> 8);
|
||||
|
||||
return 0xff000000 | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t alpha_1, red_1, green_1, blue_1;
|
||||
uint8_t alpha_2, red_2, green_2, blue_2;
|
||||
uint_least32_t alpha, red, green, blue;
|
||||
|
||||
alpha_1 = (uint8_t) (pixel_value_1 >> 24);
|
||||
red_1 = (uint8_t) (pixel_value_1 >> 16);
|
||||
green_1 = (uint8_t) (pixel_value_1 >> 8);
|
||||
blue_1 = (uint8_t) pixel_value_1;
|
||||
|
||||
alpha_2 = (uint8_t) (pixel_value_2 >> 24);
|
||||
red_2 = (uint8_t) (pixel_value_2 >> 16);
|
||||
green_2 = (uint8_t) (pixel_value_2 >> 8);
|
||||
blue_2 = (uint8_t) pixel_value_2;
|
||||
|
||||
red = red_1 * alpha_1 + red_2 * alpha_2 * (255 - alpha_1);
|
||||
green = green_1 * alpha_1 + green_2 * alpha_2 * (255 - alpha_1);
|
||||
blue = blue_1 * alpha_1 + blue_2 * alpha_2 * (255 - alpha_1);
|
||||
alpha = alpha_1 * 255 + alpha_2 * (255 - alpha_1);
|
||||
|
||||
red = (red + (red >> 8) + 0x80) >> 8;
|
||||
red = MIN (red, 0xff);
|
||||
|
||||
green = (green + (green >> 8) + 0x80) >> 8;
|
||||
green = MIN (green, 0xff);
|
||||
|
||||
blue = (blue + (blue >> 8) + 0x80) >> 8;
|
||||
blue = MIN (blue, 0xff);
|
||||
|
||||
alpha = (alpha + (alpha >> 8) + 0x80) >> 8;
|
||||
alpha = MIN (alpha, 0xff);
|
||||
|
||||
return (alpha << 24) | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((__pure__))
|
||||
static inline uint32_t
|
||||
make_pixel_value_translucent (uint32_t pixel_value,
|
||||
uint8_t opacity)
|
||||
{
|
||||
uint_least16_t alpha, red, green, blue;
|
||||
|
||||
if (opacity == 255)
|
||||
return pixel_value;
|
||||
|
||||
alpha = (uint8_t) (pixel_value >> 24);
|
||||
red = (uint8_t) (pixel_value >> 16);
|
||||
green = (uint8_t) (pixel_value >> 8);
|
||||
blue = (uint8_t) pixel_value;
|
||||
|
||||
red *= opacity;
|
||||
green *= opacity;
|
||||
blue *= opacity;
|
||||
alpha *= opacity;
|
||||
|
||||
red = (uint8_t) ((red + (red >> 8) + 0x80) >> 8);
|
||||
green = (uint8_t) ((green + (green >> 8) + 0x80) >> 8);
|
||||
blue = (uint8_t) ((blue + (blue >> 8) + 0x80) >> 8);
|
||||
alpha = (uint8_t) ((alpha + (alpha >> 8) + 0x80) >> 8);
|
||||
|
||||
return (alpha << 24) | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
|
||||
int x,
|
||||
int y,
|
||||
uint32_t pixel_value)
|
||||
{
|
||||
uint32_t old_pixel_value;
|
||||
|
||||
if ((pixel_value >> 24) != 0xff)
|
||||
{
|
||||
old_pixel_value = buffer->bytes[y * buffer->area.width + x];
|
||||
|
||||
pixel_value = blend_two_pixel_values (pixel_value, old_pixel_value);
|
||||
}
|
||||
|
||||
buffer->bytes[y * buffer->area.width + x] = pixel_value;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_pixel_buffer_crop_area_to_clip_area (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *area,
|
||||
ply_rectangle_t *cropped_area)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
*cropped_area = *area;
|
||||
|
||||
node = ply_list_get_first_node (buffer->clip_areas);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
ply_rectangle_t *clip_rectangle;
|
||||
|
||||
clip_rectangle = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (buffer->clip_areas, node);
|
||||
|
||||
ply_rectangle_intersect (cropped_area, clip_rectangle, cropped_area);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
uint32_t pixel_value)
|
||||
{
|
||||
unsigned long row, column;
|
||||
ply_rectangle_t cropped_area;
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
|
||||
|
||||
for (row = cropped_area.y; row < cropped_area.y + cropped_area.height; row++)
|
||||
{
|
||||
for (column = cropped_area.x; column < cropped_area.x + cropped_area.width; column++)
|
||||
{
|
||||
ply_pixel_buffer_blend_value_at_pixel (buffer,
|
||||
column, row,
|
||||
pixel_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_push_clip_area (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *clip_area)
|
||||
{
|
||||
ply_rectangle_t *new_clip_area;
|
||||
|
||||
new_clip_area = malloc (sizeof (*new_clip_area));
|
||||
|
||||
*new_clip_area = *clip_area;
|
||||
ply_list_append_data (buffer->clip_areas, new_clip_area);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_pop_clip_area (ply_pixel_buffer_t *buffer)
|
||||
{
|
||||
ply_list_node_t *last_node;
|
||||
|
||||
last_node = ply_list_get_last_node (buffer->clip_areas);
|
||||
free (ply_list_node_get_data (last_node));
|
||||
ply_list_remove_node (buffer->clip_areas, last_node);
|
||||
}
|
||||
|
||||
ply_pixel_buffer_t *
|
||||
ply_pixel_buffer_new (unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
ply_pixel_buffer_t *buffer;
|
||||
|
||||
buffer = calloc (1, sizeof (ply_pixel_buffer_t));
|
||||
|
||||
buffer->updated_areas = ply_region_new ();
|
||||
buffer->bytes = (uint32_t *) calloc (height, width * sizeof (uint32_t));
|
||||
buffer->area.width = width;
|
||||
buffer->area.height = height;
|
||||
|
||||
buffer->clip_areas = ply_list_new ();
|
||||
ply_pixel_buffer_push_clip_area (buffer, &buffer->area);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
free_clip_areas (ply_pixel_buffer_t *buffer)
|
||||
{
|
||||
while (ply_list_get_length (buffer->clip_areas) > 0)
|
||||
ply_pixel_buffer_pop_clip_area (buffer);
|
||||
|
||||
ply_list_free (buffer->clip_areas);
|
||||
buffer->clip_areas = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_free (ply_pixel_buffer_t *buffer)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
free_clip_areas (buffer);
|
||||
free (buffer->bytes);
|
||||
ply_region_free (buffer->updated_areas);
|
||||
free (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *size)
|
||||
{
|
||||
assert (buffer != NULL);
|
||||
assert (size != NULL);
|
||||
|
||||
*size = buffer->area;
|
||||
}
|
||||
|
||||
ply_region_t *
|
||||
ply_pixel_buffer_get_updated_areas (ply_pixel_buffer_t *buffer)
|
||||
{
|
||||
return buffer->updated_areas;
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
uint32_t start,
|
||||
uint32_t end)
|
||||
{
|
||||
/* The gradient produced is a linear interpolation of the two passed
|
||||
* in color stops: start and end.
|
||||
*
|
||||
* In order to prevent banding when the color stops are too close
|
||||
* together, or are stretched over too large an area, we slightly
|
||||
* perturb the intermediate colors as we generate them.
|
||||
*
|
||||
* Before we do this, we store the interpolated color values in a
|
||||
* fixed point number with lots of fractional bits. This is so
|
||||
* we don't add noise after the values have been clamped to 8-bits
|
||||
*
|
||||
* We add random noise to all of the fractional bits of each color
|
||||
* channel and also NOISE_BITS worth of noise to the non-fractional
|
||||
* part of the color. By default NOISE_BITS is 1.
|
||||
*
|
||||
* We incorporate the noise by filling the bottom 24 bits of an
|
||||
* integer with random bits and then shifting the color channels
|
||||
* to the left such that the top 8 bits of the channel overlap
|
||||
* the noise by NOISE_BITS. E.g., if NOISE_BITS is 1, then the top
|
||||
* 7 bits of each channel won't overlap with the noise, and the 8th
|
||||
* bit + fractional bits will. When the noise and color channel
|
||||
* are properly aligned, we add them together, drop the precision
|
||||
* of the resulting channels back to 8 bits and stuff the results
|
||||
* into a pixel in the pixel buffer.
|
||||
*/
|
||||
#define NOISE_BITS 1
|
||||
/* In the color stops, red is 8 bits starting at position 24
|
||||
* (since they're argb32 pixels).
|
||||
* We want to move those 8 bits such that the bottom NOISE_BITS
|
||||
* of them overlap the top of the 24 bits of generated noise.
|
||||
* Of course, green and blue are 8 bits away from red and each
|
||||
* other, respectively.
|
||||
*/
|
||||
#define RED_SHIFT (32 - (24 + NOISE_BITS))
|
||||
#define GREEN_SHIFT (RED_SHIFT + 8)
|
||||
#define BLUE_SHIFT (GREEN_SHIFT + 8)
|
||||
#define NOISE_MASK (0x00ffffff)
|
||||
|
||||
/* Once, we've lined up the color channel we're interested in with
|
||||
* the noise, we need to mask out the other channels.
|
||||
*/
|
||||
#define COLOR_MASK (0xff << (24 - NOISE_BITS))
|
||||
|
||||
uint32_t red, green, blue, red_step, green_step, blue_step, t, pixel;
|
||||
uint32_t x, y;
|
||||
/* we use a fixed seed so that the dithering doesn't change on repaints
|
||||
* of the same area.
|
||||
*/
|
||||
uint32_t noise = 0x100001;
|
||||
ply_rectangle_t cropped_area;
|
||||
|
||||
if (fill_area == NULL)
|
||||
fill_area = &buffer->area;
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
|
||||
|
||||
red = (start << RED_SHIFT) & COLOR_MASK;
|
||||
green = (start << GREEN_SHIFT) & COLOR_MASK;
|
||||
blue = (start << BLUE_SHIFT) & COLOR_MASK;
|
||||
|
||||
t = (end << RED_SHIFT) & COLOR_MASK;
|
||||
red_step = (int32_t) (t - red) / (int32_t) buffer->area.height;
|
||||
t = (end << GREEN_SHIFT) & COLOR_MASK;
|
||||
green_step = (int32_t) (t - green) / (int32_t) buffer->area.height;
|
||||
t = (end << BLUE_SHIFT) & COLOR_MASK;
|
||||
blue_step = (int32_t) (t - blue) / (int32_t) buffer->area.height;
|
||||
|
||||
|
||||
#define RANDOMIZE(num) (num = (num + (num << 1)) & NOISE_MASK)
|
||||
#define UNROLLED_PIXEL_COUNT 8
|
||||
|
||||
for (y = buffer->area.y; y < buffer->area.y + buffer->area.height; y++)
|
||||
{
|
||||
if (cropped_area.y <= y && y < cropped_area.y + cropped_area.height)
|
||||
{
|
||||
if (cropped_area.width < UNROLLED_PIXEL_COUNT)
|
||||
{
|
||||
for (x = cropped_area.x; x < cropped_area.x + cropped_area.width; x++)
|
||||
{
|
||||
pixel = 0xff000000;
|
||||
RANDOMIZE(noise);
|
||||
pixel |= (((red + noise) & COLOR_MASK) >> RED_SHIFT);
|
||||
RANDOMIZE(noise);
|
||||
pixel |= (((green + noise) & COLOR_MASK) >> GREEN_SHIFT);
|
||||
RANDOMIZE(noise);
|
||||
pixel |= (((blue + noise) & COLOR_MASK) >> BLUE_SHIFT);
|
||||
|
||||
buffer->bytes[y * buffer->area.width + x] = pixel;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t shaded_set[UNROLLED_PIXEL_COUNT];
|
||||
uint32_t *ptr = &buffer->bytes[y * buffer->area.width + cropped_area.x];
|
||||
for (x = 0; x < UNROLLED_PIXEL_COUNT; x++)
|
||||
{
|
||||
shaded_set[x] = 0xff000000;
|
||||
RANDOMIZE(noise);
|
||||
shaded_set[x] |= (((red + noise) & COLOR_MASK) >> RED_SHIFT);
|
||||
RANDOMIZE(noise);
|
||||
shaded_set[x] |= (((green + noise) & COLOR_MASK) >> GREEN_SHIFT);
|
||||
RANDOMIZE(noise);
|
||||
shaded_set[x] |= (((blue + noise) & COLOR_MASK) >> BLUE_SHIFT);
|
||||
}
|
||||
for (x = cropped_area.width; x >=UNROLLED_PIXEL_COUNT; x-= UNROLLED_PIXEL_COUNT)
|
||||
{
|
||||
memcpy (ptr, (void *) shaded_set, UNROLLED_PIXEL_COUNT * sizeof (uint32_t));
|
||||
ptr += UNROLLED_PIXEL_COUNT;
|
||||
}
|
||||
|
||||
memcpy (ptr, (void *) shaded_set, x * sizeof (uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
red += red_step;
|
||||
green += green_step;
|
||||
blue += blue_step;
|
||||
}
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_color (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
double red,
|
||||
double green,
|
||||
double blue,
|
||||
double alpha)
|
||||
{
|
||||
uint32_t pixel_value;
|
||||
ply_rectangle_t cropped_area;
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
if (fill_area == NULL)
|
||||
fill_area = &buffer->area;
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
|
||||
|
||||
red *= alpha;
|
||||
green *= alpha;
|
||||
blue *= alpha;
|
||||
|
||||
pixel_value = PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha);
|
||||
|
||||
ply_pixel_buffer_fill_area_with_pixel_value (buffer, &cropped_area, pixel_value);
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
uint32_t hex_color,
|
||||
double opacity)
|
||||
{
|
||||
ply_rectangle_t cropped_area;
|
||||
uint32_t pixel_value;
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
double alpha;
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
if (fill_area == NULL)
|
||||
fill_area = &buffer->area;
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
|
||||
|
||||
/* if they only gave an rgb hex number, assume an alpha of 0xff
|
||||
*/
|
||||
if ((hex_color & 0xff000000) == 0)
|
||||
hex_color = (hex_color << 8) | 0xff;
|
||||
|
||||
red = ((double) (hex_color & 0xff000000) / 0xff000000);
|
||||
green = ((double) (hex_color & 0x00ff0000) / 0x00ff0000);
|
||||
blue = ((double) (hex_color & 0x0000ff00) / 0x0000ff00);
|
||||
alpha = ((double) (hex_color & 0x000000ff) / 0x000000ff);
|
||||
|
||||
alpha *= opacity;
|
||||
|
||||
red *= alpha;
|
||||
green *= alpha;
|
||||
blue *= alpha;
|
||||
|
||||
pixel_value = PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha);
|
||||
|
||||
ply_pixel_buffer_fill_area_with_pixel_value (buffer, &cropped_area, pixel_value);
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_hex_color (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
uint32_t hex_color)
|
||||
{
|
||||
return ply_pixel_buffer_fill_with_hex_color_at_opacity (buffer, fill_area,
|
||||
hex_color, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
ply_rectangle_t *clip_area,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data,
|
||||
double opacity)
|
||||
{
|
||||
unsigned long row, column;
|
||||
uint8_t opacity_as_byte;
|
||||
ply_rectangle_t cropped_area;
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
if (fill_area == NULL)
|
||||
fill_area = &buffer->area;
|
||||
|
||||
ply_pixel_buffer_crop_area_to_clip_area (buffer, fill_area, &cropped_area);
|
||||
|
||||
if (clip_area)
|
||||
ply_rectangle_intersect (&cropped_area, clip_area, &cropped_area);
|
||||
|
||||
if (cropped_area.width == 0 || cropped_area.height == 0)
|
||||
return;
|
||||
|
||||
x += cropped_area.x - fill_area->x;
|
||||
y += cropped_area.y - fill_area->y;
|
||||
opacity_as_byte = (uint8_t) (opacity * 255.0);
|
||||
|
||||
for (row = y; row < y + cropped_area.height; row++)
|
||||
{
|
||||
for (column = x; column < x + cropped_area.width; column++)
|
||||
{
|
||||
uint32_t pixel_value;
|
||||
|
||||
pixel_value = data[fill_area->width * row + column];
|
||||
if ((pixel_value >> 24) == 0x00)
|
||||
continue;
|
||||
|
||||
pixel_value = make_pixel_value_translucent (pixel_value, opacity_as_byte);
|
||||
ply_pixel_buffer_blend_value_at_pixel (buffer,
|
||||
cropped_area.x + (column - x),
|
||||
cropped_area.y + (row - y),
|
||||
pixel_value);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data,
|
||||
double opacity)
|
||||
{
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
|
||||
fill_area,
|
||||
NULL, x, y,
|
||||
data, opacity);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_argb32_data (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data)
|
||||
{
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
|
||||
fill_area,
|
||||
NULL, x, y,
|
||||
data, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_buffer_fill_with_argb32_data_with_clip (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
ply_rectangle_t *clip_area,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data)
|
||||
{
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (buffer,
|
||||
fill_area,
|
||||
clip_area, x, y,
|
||||
data, 1.0);
|
||||
}
|
||||
|
||||
uint32_t *
|
||||
ply_pixel_buffer_get_argb32_data (ply_pixel_buffer_t *buffer)
|
||||
{
|
||||
return buffer->bytes;
|
||||
}
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
103
src/libplybootsplash/ply-pixel-buffer.h
Normal file
103
src/libplybootsplash/ply-pixel-buffer.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/* ply-pixel-buffer.h - pixel buffer abstraction
|
||||
*
|
||||
* Copyright (C) 2007, 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_PIXEL_BUFFER_H
|
||||
#define PLY_PIXEL_BUFFER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ply-rectangle.h"
|
||||
#include "ply-region.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
typedef struct _ply_pixel_buffer ply_pixel_buffer_t;
|
||||
|
||||
#define PLY_PIXEL_BUFFER_COLOR_TO_PIXEL_VALUE(r,g,b,a) \
|
||||
(((uint8_t) (CLAMP (a * 255.0, 0.0, 255.0)) << 24) \
|
||||
| ((uint8_t) (CLAMP (r * 255.0, 0.0, 255.0)) << 16) \
|
||||
| ((uint8_t) (CLAMP (g * 255.0, 0.0, 255.0)) << 8) \
|
||||
| ((uint8_t) (CLAMP (b * 255.0, 0.0, 255.0))))
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_pixel_buffer_t *ply_pixel_buffer_new (unsigned long width,
|
||||
unsigned long height);
|
||||
void ply_pixel_buffer_free (ply_pixel_buffer_t *buffer);
|
||||
void ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *size);
|
||||
ply_region_t *ply_pixel_buffer_get_updated_areas (ply_pixel_buffer_t *buffer);
|
||||
|
||||
void ply_pixel_buffer_fill_with_color (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
double red,
|
||||
double green,
|
||||
double blue,
|
||||
double alpha);
|
||||
void ply_pixel_buffer_fill_with_hex_color (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
uint32_t hex_color);
|
||||
|
||||
void ply_pixel_buffer_fill_with_hex_color_at_opacity (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
uint32_t hex_color,
|
||||
double opacity);
|
||||
|
||||
void ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
uint32_t start,
|
||||
uint32_t end);
|
||||
|
||||
void ply_pixel_buffer_fill_with_argb32_data (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data);
|
||||
void ply_pixel_buffer_fill_with_argb32_data_at_opacity (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data,
|
||||
double opacity);
|
||||
|
||||
void ply_pixel_buffer_fill_with_argb32_data_with_clip (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
ply_rectangle_t *clip_area,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data);
|
||||
void ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
ply_rectangle_t *clip_area,
|
||||
unsigned long x,
|
||||
unsigned long y,
|
||||
uint32_t *data,
|
||||
double opacity);
|
||||
|
||||
void ply_pixel_buffer_push_clip_area (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *clip_area);
|
||||
void ply_pixel_buffer_pop_clip_area (ply_pixel_buffer_t *buffer);
|
||||
|
||||
uint32_t *ply_pixel_buffer_get_argb32_data (ply_pixel_buffer_t *buffer);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PLY_PIXEL_BUFFER_H */
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
175
src/libplybootsplash/ply-pixel-display.c
Normal file
175
src/libplybootsplash/ply-pixel-display.c
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/* ply-pixel-display.c - APIs for putting up a pixel
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ply-pixel-display.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-renderer.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
struct _ply_pixel_display
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
|
||||
ply_renderer_t *renderer;
|
||||
ply_renderer_head_t *head;
|
||||
|
||||
unsigned long width;
|
||||
unsigned long height;
|
||||
|
||||
ply_pixel_display_draw_handler_t draw_handler;
|
||||
void *draw_handler_user_data;
|
||||
|
||||
int pause_count;
|
||||
|
||||
};
|
||||
|
||||
ply_pixel_display_t *
|
||||
ply_pixel_display_new (ply_renderer_t *renderer,
|
||||
ply_renderer_head_t *head)
|
||||
{
|
||||
ply_pixel_display_t *display;
|
||||
ply_pixel_buffer_t *pixel_buffer;
|
||||
ply_rectangle_t size;
|
||||
|
||||
display = calloc (1, sizeof (ply_pixel_display_t));
|
||||
|
||||
display->loop = ply_event_loop_get_default ();
|
||||
display->renderer = renderer;
|
||||
display->head = head;
|
||||
|
||||
pixel_buffer = ply_renderer_get_buffer_for_head (renderer, head);
|
||||
ply_pixel_buffer_get_size (pixel_buffer, &size);
|
||||
|
||||
display->width = size.width;
|
||||
display->height = size.height;
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
ply_pixel_display_get_width (ply_pixel_display_t *display)
|
||||
{
|
||||
return display->width;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
ply_pixel_display_get_height (ply_pixel_display_t *display)
|
||||
{
|
||||
return display->height;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_pixel_display_flush (ply_pixel_display_t *display)
|
||||
{
|
||||
if (display->pause_count > 0)
|
||||
return;
|
||||
|
||||
ply_renderer_flush_head (display->renderer, display->head);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_display_pause_updates (ply_pixel_display_t *display)
|
||||
{
|
||||
assert (display != NULL);
|
||||
|
||||
display->pause_count++;
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_display_unpause_updates (ply_pixel_display_t *display)
|
||||
{
|
||||
assert (display != NULL);
|
||||
|
||||
display->pause_count--;
|
||||
|
||||
ply_pixel_display_flush (display);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_display_draw_area (ply_pixel_display_t *display,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
|
||||
ply_pixel_buffer_t *pixel_buffer;
|
||||
|
||||
pixel_buffer = ply_renderer_get_buffer_for_head (display->renderer,
|
||||
display->head);
|
||||
|
||||
if (display->draw_handler != NULL)
|
||||
{
|
||||
ply_rectangle_t clip_area;
|
||||
|
||||
clip_area.x = x;
|
||||
clip_area.y = y;
|
||||
clip_area.width = width;
|
||||
clip_area.height = height;
|
||||
ply_pixel_buffer_push_clip_area (pixel_buffer, &clip_area);
|
||||
display->draw_handler (display->draw_handler_user_data,
|
||||
pixel_buffer,
|
||||
x, y, width, height, display);
|
||||
ply_pixel_buffer_pop_clip_area (pixel_buffer);
|
||||
}
|
||||
|
||||
ply_pixel_display_flush (display);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_display_free (ply_pixel_display_t *display)
|
||||
{
|
||||
if (display == NULL)
|
||||
return;
|
||||
|
||||
free (display);
|
||||
}
|
||||
|
||||
void
|
||||
ply_pixel_display_set_draw_handler (ply_pixel_display_t *display,
|
||||
ply_pixel_display_draw_handler_t draw_handler,
|
||||
void *user_data)
|
||||
{
|
||||
assert (display != NULL);
|
||||
|
||||
display->draw_handler = draw_handler;
|
||||
display->draw_handler_user_data = user_data;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
68
src/libplybootsplash/ply-pixel-display.h
Normal file
68
src/libplybootsplash/ply-pixel-display.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* ply-pixel-display.h - APIs for displaying pixels
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_PIXEL_DISPLAY_H
|
||||
#define PLY_PIXEL_DISPLAY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-renderer.h"
|
||||
|
||||
typedef struct _ply_pixel_display ply_pixel_display_t;
|
||||
|
||||
typedef void (* ply_pixel_display_draw_handler_t) (void *user_data,
|
||||
ply_pixel_buffer_t *pixel_buffer,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
ply_pixel_display_t *pixel_display);
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_pixel_display_t *ply_pixel_display_new (ply_renderer_t *renderer,
|
||||
ply_renderer_head_t *head);
|
||||
|
||||
void ply_pixel_display_free (ply_pixel_display_t *display);
|
||||
|
||||
unsigned long ply_pixel_display_get_width (ply_pixel_display_t *display);
|
||||
unsigned long ply_pixel_display_get_height (ply_pixel_display_t *display);
|
||||
|
||||
void ply_pixel_display_set_draw_handler (ply_pixel_display_t *display,
|
||||
ply_pixel_display_draw_handler_t draw_handler,
|
||||
void *user_data);
|
||||
|
||||
void ply_pixel_display_draw_area (ply_pixel_display_t *display,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void ply_pixel_display_pause_updates (ply_pixel_display_t *display);
|
||||
void ply_pixel_display_unpause_updates (ply_pixel_display_t *display);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PLY_PIXEL_DISPLAY_H */
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
|
|
@ -44,10 +44,8 @@
|
|||
#include "ply-progress-animation.h"
|
||||
#include "ply-array.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-image.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
|
|
@ -60,16 +58,17 @@ struct _ply_progress_animation
|
|||
ply_progress_animation_transition_t transition;
|
||||
double transition_duration;
|
||||
|
||||
ply_window_t *window;
|
||||
ply_frame_buffer_t *frame_buffer;
|
||||
ply_frame_buffer_area_t area;
|
||||
ply_frame_buffer_area_t frame_area;
|
||||
ply_pixel_display_t *display;
|
||||
ply_rectangle_t area;
|
||||
ply_rectangle_t frame_area;
|
||||
|
||||
double percent_done;
|
||||
int previous_frame_number;
|
||||
|
||||
double transition_start_time;
|
||||
|
||||
ply_pixel_buffer_t *last_rendered_frame;
|
||||
|
||||
uint32_t is_hidden : 1;
|
||||
uint32_t is_transitioning : 1;
|
||||
};
|
||||
|
|
@ -99,6 +98,7 @@ ply_progress_animation_new (const char *image_dir,
|
|||
progress_animation->frame_area.width = 0;
|
||||
progress_animation->frame_area.height = 0;
|
||||
progress_animation->previous_frame_number = 0;
|
||||
progress_animation->last_rendered_frame = NULL;
|
||||
|
||||
return progress_animation;
|
||||
}
|
||||
|
|
@ -139,16 +139,12 @@ ply_progress_animation_free (ply_progress_animation_t *progress_animation)
|
|||
}
|
||||
|
||||
static void
|
||||
draw_background (ply_progress_animation_t *progress_animation)
|
||||
{
|
||||
ply_window_erase_area (progress_animation->window,
|
||||
progress_animation->area.x, progress_animation->area.y,
|
||||
progress_animation->frame_area.width,
|
||||
progress_animation->frame_area.height);
|
||||
}
|
||||
|
||||
static uint32_t*
|
||||
image_fade_merge(ply_image_t* frame0, ply_image_t* frame1, float fade, int width, int height)
|
||||
image_fade_merge (ply_image_t* frame0,
|
||||
ply_image_t* frame1,
|
||||
float fade,
|
||||
int width,
|
||||
int height,
|
||||
uint32_t *reply_data)
|
||||
{
|
||||
int frame0_width = ply_image_get_width (frame0);
|
||||
int frame0_height = ply_image_get_height (frame0);
|
||||
|
|
@ -158,10 +154,8 @@ image_fade_merge(ply_image_t* frame0, ply_image_t* frame1, float fade, int width
|
|||
uint32_t *frame0_data = ply_image_get_data (frame0);
|
||||
uint32_t *frame1_data = ply_image_get_data (frame1);
|
||||
|
||||
uint32_t *reply_data = malloc (width * height * sizeof (uint32_t));
|
||||
int x, y, i;
|
||||
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
|
|
@ -189,7 +183,26 @@ image_fade_merge(ply_image_t* frame0, ply_image_t* frame1, float fade, int width
|
|||
reply_data[y*width+x] = pixelout;
|
||||
}
|
||||
}
|
||||
return reply_data;
|
||||
}
|
||||
|
||||
void
|
||||
ply_progress_animation_draw_area (ply_progress_animation_t *progress_animation,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
uint32_t *frame_data;
|
||||
|
||||
if (progress_animation->is_hidden)
|
||||
return;
|
||||
|
||||
frame_data = ply_pixel_buffer_get_argb32_data (progress_animation->last_rendered_frame);
|
||||
|
||||
ply_pixel_buffer_fill_with_argb32_data (buffer,
|
||||
&progress_animation->frame_area, 0, 0,
|
||||
frame_data);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -203,8 +216,6 @@ ply_progress_animation_draw (ply_progress_animation_t *progress_animation)
|
|||
if (progress_animation->is_hidden)
|
||||
return;
|
||||
|
||||
ply_window_set_mode (progress_animation->window, PLY_WINDOW_MODE_GRAPHICS);
|
||||
|
||||
number_of_frames = ply_array_get_size (progress_animation->frames);
|
||||
|
||||
if (number_of_frames == 0)
|
||||
|
|
@ -212,10 +223,6 @@ ply_progress_animation_draw (ply_progress_animation_t *progress_animation)
|
|||
|
||||
frame_number = progress_animation->percent_done * (number_of_frames - 1);
|
||||
|
||||
ply_frame_buffer_pause_updates (progress_animation->frame_buffer);
|
||||
if (progress_animation->frame_area.width > 0)
|
||||
draw_background (progress_animation);
|
||||
|
||||
if (progress_animation->previous_frame_number != frame_number &&
|
||||
progress_animation->transition != PLY_PROGRESS_ANIMATION_TRANSITION_NONE &&
|
||||
progress_animation->transition_duration > 0.0)
|
||||
|
|
@ -245,7 +252,6 @@ ply_progress_animation_draw (ply_progress_animation_t *progress_animation)
|
|||
progress_animation->is_transitioning = false;
|
||||
fade_percentage = CLAMP (fade_percentage, 0.0, 1.0);
|
||||
|
||||
previous_frame_data = ply_image_get_data (frames[frame_number - 1]);
|
||||
if (progress_animation->transition == PLY_PROGRESS_ANIMATION_TRANSITION_MERGE_FADE)
|
||||
{
|
||||
width = MAX(ply_image_get_width (frames[frame_number]), ply_image_get_width (frames[frame_number - 1]));
|
||||
|
|
@ -253,30 +259,62 @@ ply_progress_animation_draw (ply_progress_animation_t *progress_animation)
|
|||
progress_animation->frame_area.width = width;
|
||||
progress_animation->frame_area.height = height;
|
||||
|
||||
faded_data = image_fade_merge(frames[frame_number - 1], frames[frame_number], fade_percentage, width, height);
|
||||
ply_pixel_buffer_free (progress_animation->last_rendered_frame);
|
||||
progress_animation->last_rendered_frame = ply_pixel_buffer_new (width, height);
|
||||
faded_data = ply_pixel_buffer_get_argb32_data (progress_animation->last_rendered_frame);
|
||||
|
||||
ply_frame_buffer_fill_with_argb32_data_at_opacity (progress_animation->frame_buffer,
|
||||
&progress_animation->frame_area, 0, 0,
|
||||
faded_data, 1.0);
|
||||
free(faded_data);
|
||||
image_fade_merge (frames[frame_number - 1], frames[frame_number], fade_percentage, width, height, faded_data);
|
||||
|
||||
ply_pixel_display_draw_area (progress_animation->display,
|
||||
progress_animation->frame_area.x,
|
||||
progress_animation->frame_area.y,
|
||||
progress_animation->frame_area.width,
|
||||
progress_animation->frame_area.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (progress_animation->transition == PLY_PROGRESS_ANIMATION_TRANSITION_FADE_OVER)
|
||||
fade_out_opacity = 1.0;
|
||||
else
|
||||
fade_out_opacity = 1.0 - fade_percentage;
|
||||
ply_rectangle_t fill_area;
|
||||
|
||||
progress_animation->frame_area.width = ply_image_get_width (frames[frame_number - 1]);
|
||||
progress_animation->frame_area.height = ply_image_get_height (frames[frame_number - 1]);
|
||||
ply_frame_buffer_fill_with_argb32_data_at_opacity (progress_animation->frame_buffer,
|
||||
&progress_animation->frame_area, 0, 0,
|
||||
previous_frame_data, fade_out_opacity);
|
||||
previous_frame_data = ply_image_get_data (frames[frame_number - 1]);
|
||||
if (progress_animation->transition == PLY_PROGRESS_ANIMATION_TRANSITION_FADE_OVER)
|
||||
{
|
||||
ply_pixel_buffer_free (progress_animation->last_rendered_frame);
|
||||
progress_animation->frame_area.width = ply_image_get_width (frames[frame_number - 1]);
|
||||
progress_animation->frame_area.height = ply_image_get_height (frames[frame_number - 1]);
|
||||
|
||||
progress_animation->last_rendered_frame = ply_pixel_buffer_new (progress_animation->frame_area.width,
|
||||
progress_animation->frame_area.height);
|
||||
fill_area.x = 0;
|
||||
fill_area.y = 0;
|
||||
fill_area.width = progress_animation->frame_area.width;
|
||||
fill_area.height = progress_animation->frame_area.height;
|
||||
ply_pixel_buffer_fill_with_argb32_data (progress_animation->last_rendered_frame,
|
||||
&fill_area, 0, 0,
|
||||
previous_frame_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
fade_out_opacity = 1.0 - fade_percentage;
|
||||
progress_animation->frame_area.width = ply_image_get_width (frames[frame_number - 1]);
|
||||
progress_animation->frame_area.height = ply_image_get_height (frames[frame_number - 1]);
|
||||
|
||||
fill_area.x = 0;
|
||||
fill_area.y = 0;
|
||||
fill_area.width = progress_animation->frame_area.width;
|
||||
fill_area.height = progress_animation->frame_area.height;
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity (progress_animation->last_rendered_frame,
|
||||
&fill_area, 0, 0,
|
||||
previous_frame_data, fade_out_opacity);
|
||||
}
|
||||
|
||||
progress_animation->frame_area.width = ply_image_get_width (frames[frame_number]);
|
||||
progress_animation->frame_area.height = ply_image_get_height (frames[frame_number]);
|
||||
ply_frame_buffer_fill_with_argb32_data_at_opacity (progress_animation->frame_buffer,
|
||||
&progress_animation->frame_area, 0, 0,
|
||||
fill_area.x = 0;
|
||||
fill_area.y = 0;
|
||||
fill_area.width = progress_animation->frame_area.width;
|
||||
fill_area.height = progress_animation->frame_area.height;
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity (progress_animation->last_rendered_frame,
|
||||
&fill_area, 0, 0,
|
||||
frame_data, fade_percentage);
|
||||
|
||||
width = MAX(ply_image_get_width (frames[frame_number]), ply_image_get_width (frames[frame_number - 1]));
|
||||
|
|
@ -284,20 +322,33 @@ ply_progress_animation_draw (ply_progress_animation_t *progress_animation)
|
|||
progress_animation->frame_area.width = width;
|
||||
progress_animation->frame_area.height = height;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ply_rectangle_t fill_area;
|
||||
|
||||
ply_pixel_buffer_free (progress_animation->last_rendered_frame);
|
||||
progress_animation->frame_area.width = ply_image_get_width (frames[frame_number]);
|
||||
progress_animation->frame_area.height = ply_image_get_height (frames[frame_number]);
|
||||
ply_frame_buffer_fill_with_argb32_data (progress_animation->frame_buffer,
|
||||
&progress_animation->frame_area, 0, 0,
|
||||
progress_animation->last_rendered_frame = ply_pixel_buffer_new (progress_animation->frame_area.width,
|
||||
progress_animation->frame_area.height);
|
||||
|
||||
fill_area.x = 0;
|
||||
fill_area.y = 0;
|
||||
fill_area.width = progress_animation->frame_area.width;
|
||||
fill_area.height = progress_animation->frame_area.height;
|
||||
ply_pixel_buffer_fill_with_argb32_data (progress_animation->last_rendered_frame,
|
||||
&fill_area, 0, 0,
|
||||
frame_data);
|
||||
}
|
||||
|
||||
ply_frame_buffer_unpause_updates (progress_animation->frame_buffer);
|
||||
|
||||
progress_animation->previous_frame_number = frame_number;
|
||||
|
||||
ply_pixel_display_draw_area (progress_animation->display,
|
||||
progress_animation->frame_area.x,
|
||||
progress_animation->frame_area.y,
|
||||
progress_animation->frame_area.width,
|
||||
progress_animation->frame_area.height);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -392,14 +443,13 @@ ply_progress_animation_load (ply_progress_animation_t *progress_animation)
|
|||
|
||||
void
|
||||
ply_progress_animation_show (ply_progress_animation_t *progress_animation,
|
||||
ply_window_t *window,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y)
|
||||
{
|
||||
assert (progress_animation != NULL);
|
||||
|
||||
progress_animation->window = window;
|
||||
progress_animation->frame_buffer = ply_window_get_frame_buffer (window);;
|
||||
progress_animation->display = display;
|
||||
|
||||
progress_animation->area.x = x;
|
||||
progress_animation->area.y = y;
|
||||
|
|
@ -414,13 +464,16 @@ ply_progress_animation_hide (ply_progress_animation_t *progress_animation)
|
|||
if (progress_animation->is_hidden)
|
||||
return;
|
||||
|
||||
if (progress_animation->frame_area.width > 0)
|
||||
draw_background (progress_animation);
|
||||
|
||||
progress_animation->frame_buffer = NULL;
|
||||
progress_animation->window = NULL;
|
||||
|
||||
progress_animation->is_hidden = true;
|
||||
if (progress_animation->frame_area.width > 0)
|
||||
{
|
||||
ply_pixel_display_draw_area (progress_animation->display,
|
||||
progress_animation->area.x, progress_animation->area.y,
|
||||
progress_animation->frame_area.width,
|
||||
progress_animation->frame_area.height);
|
||||
}
|
||||
|
||||
progress_animation->display = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -443,9 +496,10 @@ ply_progress_animation_get_height (ply_progress_animation_t *progress_animation)
|
|||
|
||||
void
|
||||
ply_progress_animation_set_percent_done (ply_progress_animation_t *progress_animation,
|
||||
double percent_done)
|
||||
double percent_done)
|
||||
{
|
||||
progress_animation->percent_done = percent_done;
|
||||
ply_progress_animation_draw (progress_animation);
|
||||
}
|
||||
|
||||
double
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@
|
|||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-window.h"
|
||||
#include "ply-pixel-display.h"
|
||||
|
||||
typedef struct _ply_progress_animation ply_progress_animation_t;
|
||||
|
||||
|
|
@ -49,11 +48,17 @@ void ply_progress_animation_set_transition (ply_progress_animation_t *progress_a
|
|||
ply_progress_animation_transition_t transition,
|
||||
double duration);
|
||||
void ply_progress_animation_show (ply_progress_animation_t *progress_animation,
|
||||
ply_window_t *window,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y);
|
||||
void ply_progress_animation_hide (ply_progress_animation_t *progress_animation);
|
||||
void ply_progress_animation_draw (ply_progress_animation_t *progress_animation);
|
||||
void ply_progress_animation_draw_area (ply_progress_animation_t *progress_animation,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height);
|
||||
bool ply_progress_animation_is_hidden (ply_progress_animation_t *progress_animation);
|
||||
|
||||
long ply_progress_animation_get_width (ply_progress_animation_t *progress_animation);
|
||||
|
|
|
|||
|
|
@ -45,12 +45,10 @@
|
|||
#include "ply-event-loop.h"
|
||||
#include "ply-array.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-image.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
#ifndef FRAMES_PER_SECOND
|
||||
#define FRAMES_PER_SECOND 30
|
||||
|
|
@ -62,9 +60,8 @@
|
|||
|
||||
struct _ply_progress_bar
|
||||
{
|
||||
ply_window_t *window;
|
||||
ply_frame_buffer_t *frame_buffer;
|
||||
ply_frame_buffer_area_t area;
|
||||
ply_pixel_display_t *display;
|
||||
ply_rectangle_t area;
|
||||
|
||||
double percent_done;
|
||||
|
||||
|
|
@ -96,55 +93,68 @@ ply_progress_bar_free (ply_progress_bar_t *progress_bar)
|
|||
free (progress_bar);
|
||||
}
|
||||
|
||||
static void
|
||||
erase_progress_bar_area (ply_progress_bar_t *progress_bar)
|
||||
{
|
||||
ply_window_erase_area (progress_bar->window,
|
||||
progress_bar->area.x, progress_bar->area.y,
|
||||
progress_bar->area.width, progress_bar->area.height);
|
||||
}
|
||||
|
||||
static void
|
||||
ply_progress_bar_update_area (ply_progress_bar_t *progress_bar,
|
||||
long x,
|
||||
long y)
|
||||
{
|
||||
|
||||
ply_frame_buffer_get_size (progress_bar->frame_buffer, &progress_bar->area);
|
||||
unsigned long display_width;
|
||||
|
||||
progress_bar->area.x = x;
|
||||
progress_bar->area.y = y;
|
||||
progress_bar->area.height = BAR_HEIGHT;
|
||||
|
||||
progress_bar->area.width = (long) (progress_bar->area.width * progress_bar->percent_done);
|
||||
display_width = ply_pixel_display_get_width (progress_bar->display);
|
||||
progress_bar->area.width = (long) (display_width * progress_bar->percent_done);
|
||||
}
|
||||
|
||||
void
|
||||
ply_progress_bar_draw_area (ply_progress_bar_t *progress_bar,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
ply_rectangle_t paint_area;
|
||||
|
||||
if (progress_bar->is_hidden)
|
||||
return;
|
||||
|
||||
paint_area.x = x;
|
||||
paint_area.y = y;
|
||||
paint_area.width = width;
|
||||
paint_area.height = height;
|
||||
|
||||
ply_rectangle_intersect (&progress_bar->area, &paint_area, &paint_area);
|
||||
ply_pixel_buffer_fill_with_hex_color (buffer,
|
||||
&paint_area,
|
||||
0xffffff); /* white */
|
||||
}
|
||||
|
||||
void
|
||||
ply_progress_bar_draw (ply_progress_bar_t *progress_bar)
|
||||
{
|
||||
|
||||
if (progress_bar->is_hidden)
|
||||
return;
|
||||
|
||||
ply_frame_buffer_pause_updates (progress_bar->frame_buffer);
|
||||
erase_progress_bar_area (progress_bar);
|
||||
ply_progress_bar_update_area (progress_bar, progress_bar->area.x, progress_bar->area.y);
|
||||
ply_frame_buffer_fill_with_hex_color (progress_bar->frame_buffer,
|
||||
&progress_bar->area,
|
||||
0xffffff); /* white */
|
||||
ply_frame_buffer_unpause_updates (progress_bar->frame_buffer);
|
||||
ply_pixel_display_draw_area (progress_bar->display,
|
||||
progress_bar->area.x,
|
||||
progress_bar->area.y,
|
||||
progress_bar->area.width,
|
||||
progress_bar->area.height);
|
||||
}
|
||||
|
||||
void
|
||||
ply_progress_bar_show (ply_progress_bar_t *progress_bar,
|
||||
ply_window_t *window,
|
||||
long x,
|
||||
long y)
|
||||
ply_progress_bar_show (ply_progress_bar_t *progress_bar,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y)
|
||||
{
|
||||
assert (progress_bar != NULL);
|
||||
|
||||
progress_bar->window = window;
|
||||
progress_bar->frame_buffer = ply_window_get_frame_buffer (window);;
|
||||
progress_bar->display = display;
|
||||
|
||||
ply_progress_bar_update_area (progress_bar, x, y);
|
||||
|
||||
|
|
@ -155,12 +165,16 @@ ply_progress_bar_show (ply_progress_bar_t *progress_bar,
|
|||
void
|
||||
ply_progress_bar_hide (ply_progress_bar_t *progress_bar)
|
||||
{
|
||||
erase_progress_bar_area (progress_bar);
|
||||
|
||||
progress_bar->frame_buffer = NULL;
|
||||
progress_bar->window = NULL;
|
||||
if (progress_bar->is_hidden)
|
||||
return;
|
||||
|
||||
progress_bar->is_hidden = true;
|
||||
ply_pixel_display_draw_area (progress_bar->display,
|
||||
progress_bar->area.x, progress_bar->area.y,
|
||||
progress_bar->area.width, progress_bar->area.height);
|
||||
|
||||
progress_bar->display = NULL;
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-window.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
|
||||
typedef struct _ply_progress_bar ply_progress_bar_t;
|
||||
|
||||
|
|
@ -38,11 +38,17 @@ ply_progress_bar_t *ply_progress_bar_new (void);
|
|||
void ply_progress_bar_free (ply_progress_bar_t *bar);
|
||||
|
||||
void ply_progress_bar_show (ply_progress_bar_t *bar,
|
||||
ply_window_t *window,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y);
|
||||
void ply_progress_bar_hide (ply_progress_bar_t *bar);
|
||||
void ply_progress_bar_draw (ply_progress_bar_t *bar);
|
||||
void ply_progress_bar_draw_area (ply_progress_bar_t *bar,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height);
|
||||
bool ply_progress_bar_is_hidden (ply_progress_bar_t *bar);
|
||||
|
||||
long ply_progress_bar_get_width (ply_progress_bar_t *bar);
|
||||
|
|
|
|||
71
src/libplybootsplash/ply-renderer-plugin.h
Normal file
71
src/libplybootsplash/ply-renderer-plugin.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* ply-renderer-plugin.h - plugin interface for ply_renderer_t
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_RENDERER_PLUGIN_H
|
||||
#define PLY_RENDERER_PLUGIN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ply-console.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-region.h"
|
||||
#include "ply-renderer.h"
|
||||
|
||||
typedef struct _ply_renderer_plugin ply_renderer_plugin_t;
|
||||
typedef struct _ply_renderer_backend ply_renderer_backend_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_renderer_backend_t * (* create_backend) (const char *device_name,
|
||||
ply_terminal_t *terminal,
|
||||
ply_console_t *console);
|
||||
void (* destroy_backend) (ply_renderer_backend_t *backend);
|
||||
bool (* open_device) (ply_renderer_backend_t *backend);
|
||||
void (* close_device) (ply_renderer_backend_t *backend);
|
||||
bool (* query_device) (ply_renderer_backend_t *backend);
|
||||
bool (* map_to_device) (ply_renderer_backend_t *backend);
|
||||
void (* unmap_from_device) (ply_renderer_backend_t *backend);
|
||||
void (* flush_head) (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head);
|
||||
|
||||
ply_list_t * (* get_heads) (ply_renderer_backend_t *backend);
|
||||
|
||||
ply_pixel_buffer_t * (* get_buffer_for_head) (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head);
|
||||
|
||||
ply_renderer_input_source_t * (* get_input_source) (ply_renderer_backend_t *backend);
|
||||
bool (* open_input_source) (ply_renderer_backend_t *backend,
|
||||
ply_renderer_input_source_t *input_source);
|
||||
|
||||
void (* set_handler_for_input_source) (ply_renderer_backend_t *backend,
|
||||
ply_renderer_input_source_t *input_source,
|
||||
ply_renderer_input_source_handler_t handler,
|
||||
void *user_data);
|
||||
|
||||
void (* close_input_source) (ply_renderer_backend_t *backend,
|
||||
ply_renderer_input_source_t *input_source);
|
||||
} ply_renderer_plugin_interface_t;
|
||||
|
||||
#endif /* PLY_RENDERER_PLUGIN_H */
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
355
src/libplybootsplash/ply-renderer.c
Normal file
355
src/libplybootsplash/ply-renderer.c
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
/* ply-renderer.c - renderer abstraction
|
||||
*
|
||||
* Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc.
|
||||
* 2008 Charlie Brej <cbrej@cs.man.ac.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Charlie Brej <cbrej@cs.man.ac.uk>
|
||||
* Kristian Høgsberg <krh@redhat.com>
|
||||
* Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ply-renderer.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ply-renderer-plugin.h"
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-console.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
struct _ply_renderer
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
ply_module_handle_t *module_handle;
|
||||
const ply_renderer_plugin_interface_t *plugin_interface;
|
||||
ply_renderer_backend_t *backend;
|
||||
|
||||
char *device_name;
|
||||
ply_terminal_t *terminal;
|
||||
ply_console_t *console;
|
||||
};
|
||||
|
||||
typedef const ply_renderer_plugin_interface_t *
|
||||
(* get_backend_interface_function_t) (void);
|
||||
|
||||
static void ply_renderer_unload_plugin (ply_renderer_t *renderer);
|
||||
|
||||
ply_renderer_t *
|
||||
ply_renderer_new (const char *device_name,
|
||||
ply_terminal_t *terminal,
|
||||
ply_console_t *console)
|
||||
{
|
||||
ply_renderer_t *renderer;
|
||||
|
||||
renderer = calloc (1, sizeof (struct _ply_renderer));
|
||||
|
||||
if (device_name != NULL)
|
||||
renderer->device_name = strdup (device_name);
|
||||
|
||||
renderer->terminal = terminal;
|
||||
renderer->console = console;
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void
|
||||
ply_renderer_free (ply_renderer_t *renderer)
|
||||
{
|
||||
if (renderer == NULL)
|
||||
return;
|
||||
|
||||
if (renderer->plugin_interface != NULL)
|
||||
{
|
||||
ply_trace ("Unloading renderer backend plugin");
|
||||
ply_renderer_unload_plugin (renderer);
|
||||
}
|
||||
|
||||
free (renderer->device_name);
|
||||
free (renderer);
|
||||
}
|
||||
|
||||
static bool
|
||||
ply_renderer_load_plugin (ply_renderer_t *renderer,
|
||||
const char *module_path)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
|
||||
get_backend_interface_function_t get_renderer_backend_interface;
|
||||
|
||||
renderer->module_handle = ply_open_module (module_path);
|
||||
|
||||
if (renderer->module_handle == NULL)
|
||||
return false;
|
||||
|
||||
get_renderer_backend_interface = (get_backend_interface_function_t)
|
||||
ply_module_look_up_function (renderer->module_handle,
|
||||
"ply_renderer_backend_get_interface");
|
||||
|
||||
if (get_renderer_backend_interface == NULL)
|
||||
{
|
||||
ply_save_errno ();
|
||||
ply_trace ("module '%s' is not a renderer plugin",
|
||||
module_path);
|
||||
ply_close_module (renderer->module_handle);
|
||||
renderer->module_handle = NULL;
|
||||
ply_restore_errno ();
|
||||
return false;
|
||||
}
|
||||
|
||||
renderer->plugin_interface = get_renderer_backend_interface ();
|
||||
|
||||
if (renderer->plugin_interface == NULL)
|
||||
{
|
||||
ply_trace ("module '%s' is not a valid renderer plugin",
|
||||
module_path);
|
||||
ply_save_errno ();
|
||||
ply_close_module (renderer->module_handle);
|
||||
renderer->module_handle = NULL;
|
||||
ply_restore_errno ();
|
||||
return false;
|
||||
}
|
||||
|
||||
renderer->backend = renderer->plugin_interface->create_backend (renderer->device_name,
|
||||
renderer->terminal,
|
||||
renderer->console);
|
||||
|
||||
if (renderer->backend == NULL)
|
||||
{
|
||||
ply_save_errno ();
|
||||
ply_trace ("module '%s' renderer backend could not be created",
|
||||
module_path);
|
||||
ply_close_module (renderer->module_handle);
|
||||
renderer->module_handle = NULL;
|
||||
ply_restore_errno ();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_renderer_unload_plugin (ply_renderer_t *renderer)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (renderer->plugin_interface != NULL);
|
||||
assert (renderer->module_handle != NULL);
|
||||
|
||||
ply_close_module (renderer->module_handle);
|
||||
renderer->plugin_interface = NULL;
|
||||
renderer->module_handle = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
ply_renderer_open_device (ply_renderer_t *renderer)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (renderer->plugin_interface != NULL);
|
||||
|
||||
return renderer->plugin_interface->open_device (renderer->backend);
|
||||
}
|
||||
|
||||
static void
|
||||
ply_renderer_close_device (ply_renderer_t *renderer)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (renderer->plugin_interface != NULL);
|
||||
|
||||
renderer->plugin_interface->close_device (renderer->backend);
|
||||
}
|
||||
|
||||
static bool
|
||||
ply_renderer_query_device (ply_renderer_t *renderer)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (renderer->plugin_interface != NULL);
|
||||
|
||||
return renderer->plugin_interface->query_device (renderer->backend);
|
||||
}
|
||||
|
||||
static bool
|
||||
ply_renderer_map_to_device (ply_renderer_t *renderer)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (renderer->plugin_interface != NULL);
|
||||
|
||||
return renderer->plugin_interface->map_to_device (renderer->backend);
|
||||
}
|
||||
|
||||
static void
|
||||
ply_renderer_unmap_from_device (ply_renderer_t *renderer)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (renderer->plugin_interface != NULL);
|
||||
|
||||
renderer->plugin_interface->unmap_from_device (renderer->backend);
|
||||
}
|
||||
|
||||
bool
|
||||
ply_renderer_open (ply_renderer_t *renderer)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* FIXME: at some point we may want to make this
|
||||
* part more dynamic (so you don't have to edit this
|
||||
* list to add a new renderer)
|
||||
*/
|
||||
const char *known_plugins[] =
|
||||
{
|
||||
PLYMOUTH_PLUGIN_PATH "renderers/drm.so",
|
||||
PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so",
|
||||
NULL
|
||||
};
|
||||
|
||||
for (i = 0; known_plugins[i] != NULL; i++)
|
||||
{
|
||||
const char *plugin_path;
|
||||
|
||||
plugin_path = known_plugins[i];
|
||||
|
||||
if (!ply_renderer_load_plugin (renderer, plugin_path))
|
||||
continue;
|
||||
|
||||
if (!ply_renderer_open_device (renderer))
|
||||
{
|
||||
ply_trace ("could not open rendering device for plugin %s",
|
||||
plugin_path);
|
||||
ply_renderer_unload_plugin (renderer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ply_renderer_query_device (renderer))
|
||||
{
|
||||
ply_trace ("could not query rendering device for plugin %s",
|
||||
plugin_path);
|
||||
ply_renderer_unload_plugin (renderer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ply_renderer_map_to_device (renderer))
|
||||
{
|
||||
ply_trace ("could not map renderer to device for plugin %s",
|
||||
plugin_path);
|
||||
ply_renderer_unload_plugin (renderer);
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ply_trace ("could not find suitable rendering plugin");
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ply_renderer_close (ply_renderer_t *renderer)
|
||||
{
|
||||
ply_renderer_unmap_from_device (renderer);
|
||||
ply_renderer_close_device (renderer);
|
||||
}
|
||||
|
||||
ply_list_t *
|
||||
ply_renderer_get_heads (ply_renderer_t *renderer)
|
||||
{
|
||||
assert (renderer->plugin_interface != NULL);
|
||||
|
||||
return renderer->plugin_interface->get_heads (renderer->backend);
|
||||
}
|
||||
|
||||
ply_pixel_buffer_t *
|
||||
ply_renderer_get_buffer_for_head (ply_renderer_t *renderer,
|
||||
ply_renderer_head_t *head)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (renderer->plugin_interface != NULL);
|
||||
assert (head != NULL);
|
||||
|
||||
return renderer->plugin_interface->get_buffer_for_head (renderer->backend,
|
||||
head);
|
||||
}
|
||||
|
||||
void
|
||||
ply_renderer_flush_head (ply_renderer_t *renderer,
|
||||
ply_renderer_head_t *head)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (renderer->plugin_interface != NULL);
|
||||
assert (head != NULL);
|
||||
|
||||
if (ply_console_get_active_vt (renderer->console) !=
|
||||
ply_terminal_get_vt_number (renderer->terminal))
|
||||
return;
|
||||
|
||||
renderer->plugin_interface->flush_head (renderer->backend, head);
|
||||
}
|
||||
|
||||
ply_renderer_input_source_t *
|
||||
ply_renderer_get_input_source (ply_renderer_t *renderer)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (renderer->plugin_interface != NULL);
|
||||
|
||||
return renderer->plugin_interface->get_input_source (renderer->backend);
|
||||
}
|
||||
|
||||
bool
|
||||
ply_renderer_open_input_source (ply_renderer_t *renderer,
|
||||
ply_renderer_input_source_t *input_source)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (input_source != NULL);
|
||||
|
||||
return renderer->plugin_interface->open_input_source (renderer->backend,
|
||||
input_source);
|
||||
}
|
||||
|
||||
void
|
||||
ply_renderer_set_handler_for_input_source (ply_renderer_t *renderer,
|
||||
ply_renderer_input_source_t *input_source,
|
||||
ply_renderer_input_source_handler_t handler,
|
||||
void *user_data)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (input_source != NULL);
|
||||
|
||||
renderer->plugin_interface->set_handler_for_input_source (renderer->backend,
|
||||
input_source,
|
||||
handler,
|
||||
user_data);
|
||||
}
|
||||
|
||||
void
|
||||
ply_renderer_close_input_source (ply_renderer_t *renderer,
|
||||
ply_renderer_input_source_t *input_source)
|
||||
{
|
||||
assert (renderer != NULL);
|
||||
assert (input_source != NULL);
|
||||
|
||||
renderer->plugin_interface->close_input_source (renderer->backend,
|
||||
input_source);
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
70
src/libplybootsplash/ply-renderer.h
Normal file
70
src/libplybootsplash/ply-renderer.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* ply-renderer.h - rendering abstraction
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_RENDERER_H
|
||||
#define PLY_RENDERER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-console.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-terminal.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
typedef struct _ply_renderer ply_renderer_t;
|
||||
typedef struct _ply_renderer_head ply_renderer_head_t;
|
||||
typedef struct _ply_renderer_input_source ply_renderer_input_source_t;
|
||||
|
||||
typedef void (* ply_renderer_input_source_handler_t) (void *user_data,
|
||||
ply_buffer_t *key_buffer,
|
||||
ply_renderer_input_source_t *input_source);
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_renderer_t *ply_renderer_new (const char *device_name,
|
||||
ply_terminal_t *terminal,
|
||||
ply_console_t *console);
|
||||
void ply_renderer_free (ply_renderer_t *renderer);
|
||||
bool ply_renderer_open (ply_renderer_t *renderer);
|
||||
void ply_renderer_close (ply_renderer_t *renderer);
|
||||
ply_list_t *ply_renderer_get_heads (ply_renderer_t *renderer);
|
||||
ply_pixel_buffer_t *ply_renderer_get_buffer_for_head (ply_renderer_t *renderer,
|
||||
ply_renderer_head_t *head);
|
||||
|
||||
void ply_renderer_flush_head (ply_renderer_t *renderer,
|
||||
ply_renderer_head_t *head);
|
||||
|
||||
ply_renderer_input_source_t *ply_renderer_get_input_source (ply_renderer_t *renderer);
|
||||
bool ply_renderer_open_input_source (ply_renderer_t *renderer,
|
||||
ply_renderer_input_source_t *input_source);
|
||||
void ply_renderer_set_handler_for_input_source (ply_renderer_t *renderer,
|
||||
ply_renderer_input_source_t *input_source,
|
||||
ply_renderer_input_source_handler_t handler,
|
||||
void *user_data);
|
||||
|
||||
void ply_renderer_close_input_source (ply_renderer_t *renderer,
|
||||
ply_renderer_input_source_t *input_source);
|
||||
#endif
|
||||
|
||||
#endif /* PLY_RENDERER_H */
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
513
src/libplybootsplash/ply-terminal.c
Normal file
513
src/libplybootsplash/ply-terminal.c
Normal file
|
|
@ -0,0 +1,513 @@
|
|||
/* ply-terminal.c - APIs for terminaling text
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ply-terminal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <linux/kd.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/vt.h>
|
||||
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
#ifndef TEXT_PALETTE_SIZE
|
||||
#define TEXT_PALETTE_SIZE 48
|
||||
#endif
|
||||
|
||||
struct _ply_terminal
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
|
||||
struct termios original_term_attributes;
|
||||
|
||||
char *name;
|
||||
int fd;
|
||||
int vt_number;
|
||||
|
||||
ply_fd_watch_t *fd_watch;
|
||||
ply_terminal_color_t foreground_color;
|
||||
ply_terminal_color_t background_color;
|
||||
|
||||
uint8_t original_color_palette[TEXT_PALETTE_SIZE];
|
||||
uint8_t color_palette[TEXT_PALETTE_SIZE];
|
||||
|
||||
int number_of_rows;
|
||||
int number_of_columns;
|
||||
|
||||
uint32_t original_term_attributes_saved : 1;
|
||||
uint32_t supports_text_color : 1;
|
||||
uint32_t is_open : 1;
|
||||
};
|
||||
|
||||
static bool ply_terminal_open_device (ply_terminal_t *terminal);
|
||||
|
||||
ply_terminal_t *
|
||||
ply_terminal_new (const char *device_name)
|
||||
{
|
||||
ply_terminal_t *terminal;
|
||||
|
||||
terminal = calloc (1, sizeof (ply_terminal_t));
|
||||
|
||||
terminal->loop = ply_event_loop_get_default ();
|
||||
if (device_name != NULL)
|
||||
{
|
||||
if (strncmp (device_name, "/dev/", strlen ("/dev/")) == 0)
|
||||
terminal->name = strdup (device_name);
|
||||
else
|
||||
asprintf (&terminal->name, "/dev/%s", device_name);
|
||||
}
|
||||
terminal->fd = -1;
|
||||
terminal->vt_number = -1;
|
||||
|
||||
return terminal;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_terminal_look_up_color_palette (ply_terminal_t *terminal)
|
||||
{
|
||||
if (ioctl (terminal->fd, GIO_CMAP, terminal->color_palette) < 0)
|
||||
terminal->supports_text_color = false;
|
||||
else
|
||||
terminal->supports_text_color = true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ply_terminal_change_color_palette (ply_terminal_t *terminal)
|
||||
{
|
||||
if (!terminal->supports_text_color)
|
||||
return true;
|
||||
|
||||
if (ioctl (terminal->fd, PIO_CMAP, terminal->color_palette) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_terminal_save_color_palette (ply_terminal_t *terminal)
|
||||
{
|
||||
if (!terminal->supports_text_color)
|
||||
return;
|
||||
|
||||
memcpy (terminal->original_color_palette, terminal->color_palette,
|
||||
TEXT_PALETTE_SIZE);
|
||||
}
|
||||
|
||||
static void
|
||||
ply_terminal_restore_color_palette (ply_terminal_t *terminal)
|
||||
{
|
||||
if (!terminal->supports_text_color)
|
||||
return;
|
||||
|
||||
memcpy (terminal->color_palette, terminal->original_color_palette,
|
||||
TEXT_PALETTE_SIZE);
|
||||
|
||||
ply_terminal_change_color_palette (terminal);
|
||||
}
|
||||
|
||||
void
|
||||
ply_terminal_reset_colors (ply_terminal_t *terminal)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
|
||||
ply_terminal_restore_color_palette (terminal);
|
||||
}
|
||||
|
||||
bool
|
||||
ply_terminal_set_unbuffered_input (ply_terminal_t *terminal)
|
||||
{
|
||||
struct termios term_attributes;
|
||||
|
||||
tcgetattr (terminal->fd, &term_attributes);
|
||||
|
||||
if (!terminal->original_term_attributes_saved)
|
||||
{
|
||||
terminal->original_term_attributes = term_attributes;
|
||||
terminal->original_term_attributes_saved = true;
|
||||
}
|
||||
|
||||
cfmakeraw (&term_attributes);
|
||||
|
||||
/* Make \n return go to the beginning of the next line */
|
||||
term_attributes.c_oflag |= ONLCR;
|
||||
|
||||
if (tcsetattr (terminal->fd, TCSAFLUSH, &term_attributes) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_terminal_set_buffered_input (ply_terminal_t *terminal)
|
||||
{
|
||||
struct termios term_attributes;
|
||||
|
||||
tcgetattr (terminal->fd, &term_attributes);
|
||||
|
||||
/* If someone already messed with the terminal settings,
|
||||
* and they seem good enough, bail
|
||||
*/
|
||||
if (term_attributes.c_lflag & ICANON)
|
||||
return true;
|
||||
|
||||
/* If we don't know the original term attributes, or they were originally sucky,
|
||||
* then invent some that are probably good enough.
|
||||
*/
|
||||
if (!terminal->original_term_attributes_saved || !(terminal->original_term_attributes.c_lflag & ICANON))
|
||||
{
|
||||
term_attributes.c_iflag |= IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON;
|
||||
term_attributes.c_oflag |= OPOST;
|
||||
term_attributes.c_lflag |= ECHO | ECHONL | ICANON | ISIG | IEXTEN;
|
||||
|
||||
if (tcsetattr (terminal->fd, TCSAFLUSH, &term_attributes) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tcsetattr (terminal->fd, TCSAFLUSH, &terminal->original_term_attributes) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ply_terminal_write (ply_terminal_t *terminal,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
char *string;
|
||||
|
||||
assert (terminal != NULL);
|
||||
assert (format != NULL);
|
||||
|
||||
string = NULL;
|
||||
va_start (args, format);
|
||||
vasprintf (&string, format, args);
|
||||
va_end (args);
|
||||
|
||||
write (terminal->fd, string, strlen (string));
|
||||
free (string);
|
||||
}
|
||||
|
||||
static void
|
||||
on_tty_disconnected (ply_terminal_t *terminal)
|
||||
{
|
||||
ply_trace ("tty disconnected (fd %d)", terminal->fd);
|
||||
terminal->fd_watch = NULL;
|
||||
terminal->fd = -1;
|
||||
|
||||
if (terminal->name != NULL)
|
||||
{
|
||||
ply_trace ("trying to reopen terminal '%s'", terminal->name);
|
||||
ply_terminal_open_device (terminal);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
get_active_vt (void)
|
||||
{
|
||||
int console_fd;
|
||||
struct vt_stat console_state = { 0 };
|
||||
|
||||
console_fd = open ("/dev/tty0", O_RDONLY | O_NOCTTY);
|
||||
|
||||
if (console_fd < 0)
|
||||
goto out;
|
||||
|
||||
if (ioctl (console_fd, VT_GETSTATE, &console_state) < 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (console_fd >= 0)
|
||||
close (console_fd);
|
||||
|
||||
return console_state.v_active;
|
||||
}
|
||||
|
||||
static bool
|
||||
ply_terminal_look_up_geometry (ply_terminal_t *terminal)
|
||||
{
|
||||
struct winsize terminal_size;
|
||||
|
||||
ply_trace ("looking up terminal text geometry");
|
||||
|
||||
if (ioctl (terminal->fd, TIOCGWINSZ, &terminal_size) < 0)
|
||||
{
|
||||
ply_trace ("could not read terminal text geometry: %m");
|
||||
terminal->number_of_columns = 80;
|
||||
terminal->number_of_rows = 24;
|
||||
return false;
|
||||
}
|
||||
|
||||
terminal->number_of_rows = terminal_size.ws_row;
|
||||
terminal->number_of_columns = terminal_size.ws_col;
|
||||
|
||||
ply_trace ("terminal is now %dx%d text cells",
|
||||
terminal->number_of_columns,
|
||||
terminal->number_of_rows);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_terminal_check_for_vt (ply_terminal_t *terminal)
|
||||
{
|
||||
int major_number, minor_number;
|
||||
struct stat file_attributes;
|
||||
|
||||
assert (terminal != NULL);
|
||||
assert (terminal->fd >= 0);
|
||||
|
||||
if (fstat (terminal->fd, &file_attributes) != 0)
|
||||
return;
|
||||
|
||||
major_number = major (file_attributes.st_rdev);
|
||||
minor_number = minor (file_attributes.st_rdev);
|
||||
|
||||
if (major_number == TTY_MAJOR)
|
||||
terminal->vt_number = minor_number;
|
||||
else
|
||||
terminal->vt_number = -1;
|
||||
}
|
||||
|
||||
static bool
|
||||
ply_terminal_open_device (ply_terminal_t *terminal)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
assert (terminal->name != NULL);
|
||||
assert (terminal->fd < 0);
|
||||
assert (terminal->fd_watch == NULL);
|
||||
|
||||
terminal->fd = open (terminal->name, O_RDWR | O_NOCTTY);
|
||||
|
||||
if (terminal->fd < 0)
|
||||
return false;
|
||||
|
||||
terminal->fd_watch = ply_event_loop_watch_fd (terminal->loop, terminal->fd,
|
||||
PLY_EVENT_LOOP_FD_STATUS_NONE,
|
||||
(ply_event_handler_t) NULL,
|
||||
(ply_event_handler_t) on_tty_disconnected,
|
||||
terminal);
|
||||
|
||||
ply_terminal_check_for_vt (terminal);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_terminal_open (ply_terminal_t *terminal)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
|
||||
if (terminal->name == NULL)
|
||||
{
|
||||
char tty_name[512] = "";
|
||||
|
||||
terminal->vt_number = get_active_vt ();
|
||||
|
||||
if (readlink ("/proc/self/fd/0", tty_name, sizeof (tty_name) - 1) < 0)
|
||||
{
|
||||
ply_trace ("could not read tty name of fd 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
terminal->name = strdup (tty_name);
|
||||
}
|
||||
|
||||
ply_trace ("trying to open terminal '%s'", terminal->name);
|
||||
|
||||
if (!ply_terminal_open_device (terminal))
|
||||
{
|
||||
ply_trace ("could not open %s : %m", terminal->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ply_terminal_set_unbuffered_input (terminal))
|
||||
ply_trace ("terminal '%s' will be line buffered", terminal->name);
|
||||
|
||||
ply_terminal_look_up_geometry (terminal);
|
||||
|
||||
ply_terminal_look_up_color_palette (terminal);
|
||||
ply_terminal_save_color_palette (terminal);
|
||||
|
||||
ply_event_loop_watch_signal (terminal->loop,
|
||||
SIGWINCH,
|
||||
(ply_event_handler_t)
|
||||
ply_terminal_look_up_geometry,
|
||||
terminal);
|
||||
|
||||
terminal->is_open = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
ply_terminal_get_fd (ply_terminal_t *terminal)
|
||||
{
|
||||
return terminal->fd;
|
||||
}
|
||||
|
||||
bool
|
||||
ply_terminal_is_open (ply_terminal_t *terminal)
|
||||
{
|
||||
return terminal->is_open;
|
||||
}
|
||||
|
||||
void
|
||||
ply_terminal_close (ply_terminal_t *terminal)
|
||||
{
|
||||
terminal->is_open = false;
|
||||
|
||||
ply_trace ("restoring color palette");
|
||||
ply_terminal_restore_color_palette (terminal);
|
||||
|
||||
if (terminal->fd_watch != NULL)
|
||||
{
|
||||
ply_trace ("stop watching tty fd");
|
||||
ply_event_loop_stop_watching_fd (terminal->loop, terminal->fd_watch);
|
||||
terminal->fd_watch = NULL;
|
||||
}
|
||||
|
||||
if (terminal->loop != NULL)
|
||||
{
|
||||
ply_trace ("stop watching SIGWINCH signal");
|
||||
ply_event_loop_stop_watching_signal (terminal->loop, SIGWINCH);
|
||||
}
|
||||
|
||||
ply_trace ("setting buffered input");
|
||||
ply_terminal_set_buffered_input (terminal);
|
||||
|
||||
close (terminal->fd);
|
||||
terminal->fd = -1;
|
||||
}
|
||||
|
||||
int
|
||||
ply_terminal_get_number_of_columns (ply_terminal_t *terminal)
|
||||
{
|
||||
return terminal->number_of_columns;
|
||||
}
|
||||
|
||||
int
|
||||
ply_terminal_get_number_of_rows (ply_terminal_t *terminal)
|
||||
{
|
||||
return terminal->number_of_rows;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ply_terminal_get_color_hex_value (ply_terminal_t *terminal,
|
||||
ply_terminal_color_t color)
|
||||
{
|
||||
uint8_t red, green, blue;
|
||||
uint32_t hex_value;
|
||||
|
||||
assert (terminal != NULL);
|
||||
assert (color <= PLY_TERMINAL_COLOR_WHITE);
|
||||
|
||||
red = (uint8_t) *(terminal->color_palette + 3 * color);
|
||||
green = (uint8_t) *(terminal->color_palette + 3 * color + 1);
|
||||
blue = (uint8_t) *(terminal->color_palette + 3 * color + 2);
|
||||
|
||||
hex_value = red << 16 | green << 8 | blue;
|
||||
|
||||
return hex_value;
|
||||
}
|
||||
|
||||
void
|
||||
ply_terminal_set_color_hex_value (ply_terminal_t *terminal,
|
||||
ply_terminal_color_t color,
|
||||
uint32_t hex_value)
|
||||
{
|
||||
uint8_t red, green, blue;
|
||||
|
||||
assert (terminal != NULL);
|
||||
assert (color <= PLY_TERMINAL_COLOR_WHITE);
|
||||
|
||||
red = (uint8_t) ((hex_value >> 16) & 0xff);
|
||||
green = (uint8_t) ((hex_value >> 8) & 0xff);
|
||||
blue = (uint8_t) (hex_value & 0xff);
|
||||
|
||||
*(terminal->color_palette + 3 * color) = red;
|
||||
*(terminal->color_palette + 3 * color + 1) = green;
|
||||
*(terminal->color_palette + 3 * color + 2) = blue;
|
||||
|
||||
ply_terminal_change_color_palette (terminal);
|
||||
}
|
||||
|
||||
bool
|
||||
ply_terminal_supports_color (ply_terminal_t *terminal)
|
||||
{
|
||||
return terminal->supports_text_color;
|
||||
}
|
||||
|
||||
static void
|
||||
ply_terminal_detach_from_event_loop (ply_terminal_t *terminal)
|
||||
{
|
||||
assert (terminal != NULL);
|
||||
terminal->loop = NULL;
|
||||
terminal->fd_watch = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ply_terminal_free (ply_terminal_t *terminal)
|
||||
{
|
||||
if (terminal == NULL)
|
||||
return;
|
||||
|
||||
free (terminal->name);
|
||||
|
||||
if (terminal->loop != NULL)
|
||||
ply_event_loop_stop_watching_for_exit (terminal->loop,
|
||||
(ply_event_loop_exit_handler_t)
|
||||
ply_terminal_detach_from_event_loop,
|
||||
terminal);
|
||||
|
||||
ply_terminal_close (terminal);
|
||||
|
||||
free (terminal);
|
||||
}
|
||||
|
||||
int
|
||||
ply_terminal_get_vt_number (ply_terminal_t *terminal)
|
||||
{
|
||||
return terminal->vt_number;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
82
src/libplybootsplash/ply-terminal.h
Normal file
82
src/libplybootsplash/ply-terminal.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/* ply-terminal.h - APIs for terminaling text
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_TERMINAL_H
|
||||
#define PLY_TERMINAL_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-event-loop.h"
|
||||
|
||||
typedef struct _ply_terminal ply_terminal_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLY_TERMINAL_COLOR_BLACK = 0,
|
||||
PLY_TERMINAL_COLOR_RED,
|
||||
PLY_TERMINAL_COLOR_GREEN,
|
||||
PLY_TERMINAL_COLOR_BROWN,
|
||||
PLY_TERMINAL_COLOR_BLUE,
|
||||
PLY_TERMINAL_COLOR_MAGENTA,
|
||||
PLY_TERMINAL_COLOR_CYAN,
|
||||
PLY_TERMINAL_COLOR_WHITE,
|
||||
PLY_TERMINAL_COLOR_DEFAULT = PLY_TERMINAL_COLOR_WHITE + 2
|
||||
} ply_terminal_color_t;
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_terminal_t *ply_terminal_new (const char *device_name);
|
||||
|
||||
void ply_terminal_free (ply_terminal_t *terminal);
|
||||
|
||||
bool ply_terminal_open (ply_terminal_t *terminal);
|
||||
int ply_terminal_get_fd (ply_terminal_t *terminal);
|
||||
bool ply_terminal_is_open (ply_terminal_t *terminal);
|
||||
void ply_terminal_close (ply_terminal_t *terminal);
|
||||
void ply_terminal_reset_colors (ply_terminal_t *terminal);
|
||||
|
||||
bool ply_terminal_set_unbuffered_input (ply_terminal_t *terminal);
|
||||
bool ply_terminal_set_buffered_input (ply_terminal_t *terminal);
|
||||
|
||||
__attribute__((__format__ (__printf__, 2, 3)))
|
||||
void ply_terminal_write (ply_terminal_t *terminal,
|
||||
const char *format,
|
||||
...);
|
||||
int ply_terminal_get_number_of_columns (ply_terminal_t *terminal);
|
||||
int ply_terminal_get_number_of_rows (ply_terminal_t *terminal);
|
||||
|
||||
bool ply_terminal_supports_color (ply_terminal_t *terminal);
|
||||
uint32_t ply_terminal_get_color_hex_value (ply_terminal_t *terminal,
|
||||
ply_terminal_color_t color);
|
||||
|
||||
void ply_terminal_set_color_hex_value (ply_terminal_t *terminal,
|
||||
ply_terminal_color_t color,
|
||||
uint32_t hex_value);
|
||||
|
||||
int ply_terminal_get_vt_number (ply_terminal_t *terminal);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PLY_TERMINAL_H */
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
343
src/libplybootsplash/ply-text-display.c
Normal file
343
src/libplybootsplash/ply-text-display.c
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
/* ply-text-display.c - APIs for displaying text
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "ply-text-display.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-console.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-terminal.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
#ifndef CLEAR_SCREEN_SEQUENCE
|
||||
#define CLEAR_SCREEN_SEQUENCE "\033[2J"
|
||||
#endif
|
||||
|
||||
#ifndef CLEAR_LINE_SEQUENCE
|
||||
#define CLEAR_LINE_SEQUENCE "\033[2K\r\n"
|
||||
#endif
|
||||
|
||||
#ifndef BACKSPACE
|
||||
#define BACKSPACE "\b\033[0K"
|
||||
#endif
|
||||
|
||||
#ifndef MOVE_CURSOR_SEQUENCE
|
||||
#define MOVE_CURSOR_SEQUENCE "\033[%d;%df"
|
||||
#endif
|
||||
|
||||
#ifndef HIDE_CURSOR_SEQUENCE
|
||||
#define HIDE_CURSOR_SEQUENCE "\033[?25l"
|
||||
#endif
|
||||
|
||||
#ifndef SHOW_CURSOR_SEQUENCE
|
||||
#define SHOW_CURSOR_SEQUENCE "\033[?25h"
|
||||
#endif
|
||||
|
||||
#ifndef COLOR_SEQUENCE_FORMAT
|
||||
#define COLOR_SEQUENCE_FORMAT "\033[%dm"
|
||||
#endif
|
||||
|
||||
#ifndef PAUSE_SEQUENCE
|
||||
#define PAUSE_SEQUENCE "\023"
|
||||
#endif
|
||||
|
||||
#ifndef UNPAUSE_SEQUENCE
|
||||
#define UNPAUSE_SEQUENCE "\021"
|
||||
#endif
|
||||
|
||||
#ifndef FOREGROUND_COLOR_BASE
|
||||
#define FOREGROUND_COLOR_BASE 30
|
||||
#endif
|
||||
|
||||
#ifndef BACKGROUND_COLOR_BASE
|
||||
#define BACKGROUND_COLOR_BASE 40
|
||||
#endif
|
||||
|
||||
#ifndef TEXT_PALETTE_SIZE
|
||||
#define TEXT_PALETTE_SIZE 48
|
||||
#endif
|
||||
|
||||
struct _ply_text_display
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
|
||||
ply_terminal_t *terminal;
|
||||
ply_console_t *console;
|
||||
|
||||
ply_terminal_color_t foreground_color;
|
||||
ply_terminal_color_t background_color;
|
||||
|
||||
ply_text_display_draw_handler_t draw_handler;
|
||||
void *draw_handler_user_data;
|
||||
};
|
||||
|
||||
ply_text_display_t *
|
||||
ply_text_display_new (ply_terminal_t *terminal,
|
||||
ply_console_t *console)
|
||||
{
|
||||
ply_text_display_t *display;
|
||||
|
||||
display = calloc (1, sizeof (ply_text_display_t));
|
||||
|
||||
display->loop = NULL;
|
||||
display->terminal = terminal;
|
||||
display->console = console;
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
int
|
||||
ply_text_display_get_number_of_columns (ply_text_display_t *display)
|
||||
{
|
||||
return ply_terminal_get_number_of_columns (display->terminal);
|
||||
}
|
||||
|
||||
int
|
||||
ply_text_display_get_number_of_rows (ply_text_display_t *display)
|
||||
{
|
||||
return ply_terminal_get_number_of_rows (display->terminal);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_set_cursor_position (ply_text_display_t *display,
|
||||
int column,
|
||||
int row)
|
||||
{
|
||||
int number_of_columns;
|
||||
int number_of_rows;
|
||||
|
||||
number_of_columns = ply_text_display_get_number_of_columns (display);
|
||||
number_of_rows = ply_text_display_get_number_of_rows (display);
|
||||
|
||||
column = CLAMP (column, 0, number_of_columns - 1);
|
||||
row = CLAMP (row, 0, number_of_rows - 1);
|
||||
|
||||
ply_terminal_write (display->terminal,
|
||||
MOVE_CURSOR_SEQUENCE,
|
||||
row, column);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_clear_screen (ply_text_display_t *display)
|
||||
{
|
||||
if (ply_is_tracing ())
|
||||
return;
|
||||
|
||||
ply_terminal_write (display->terminal,
|
||||
CLEAR_SCREEN_SEQUENCE);
|
||||
|
||||
ply_text_display_set_cursor_position (display, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_clear_line (ply_text_display_t *display)
|
||||
{
|
||||
|
||||
ply_terminal_write (display->terminal,
|
||||
CLEAR_LINE_SEQUENCE);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_remove_character (ply_text_display_t *display)
|
||||
{
|
||||
ply_terminal_write (display->terminal,
|
||||
BACKSPACE);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_set_background_color (ply_text_display_t *display,
|
||||
ply_terminal_color_t color)
|
||||
{
|
||||
|
||||
ply_terminal_write (display->terminal,
|
||||
COLOR_SEQUENCE_FORMAT,
|
||||
BACKGROUND_COLOR_BASE + color);
|
||||
|
||||
display->background_color = color;
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_set_foreground_color (ply_text_display_t *display,
|
||||
ply_terminal_color_t color)
|
||||
{
|
||||
ply_terminal_write (display->terminal,
|
||||
COLOR_SEQUENCE_FORMAT,
|
||||
FOREGROUND_COLOR_BASE + color);
|
||||
|
||||
display->foreground_color = color;
|
||||
}
|
||||
|
||||
ply_terminal_color_t
|
||||
ply_text_display_get_background_color (ply_text_display_t *display)
|
||||
{
|
||||
return display->background_color;
|
||||
}
|
||||
|
||||
ply_terminal_color_t
|
||||
ply_text_display_get_foreground_color (ply_text_display_t *display)
|
||||
{
|
||||
return display->foreground_color;
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_draw_area (ply_text_display_t *display,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (display->draw_handler != NULL)
|
||||
display->draw_handler (display->draw_handler_user_data,
|
||||
display->terminal,
|
||||
x, y, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_hide_cursor (ply_text_display_t *display)
|
||||
{
|
||||
ply_terminal_write (display->terminal,
|
||||
HIDE_CURSOR_SEQUENCE);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_write (ply_text_display_t *display,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
int fd;
|
||||
|
||||
va_list args;
|
||||
char *string;
|
||||
|
||||
assert (display != NULL);
|
||||
assert (format != NULL);
|
||||
|
||||
fd = ply_terminal_get_fd (display->terminal);
|
||||
|
||||
string = NULL;
|
||||
va_start (args, format);
|
||||
vasprintf (&string, format, args);
|
||||
va_end (args);
|
||||
|
||||
if (ply_terminal_get_vt_number (display->terminal) > 0)
|
||||
ply_console_set_mode (display->console, PLY_CONSOLE_MODE_TEXT);
|
||||
write (fd, string, strlen (string));
|
||||
free (string);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_show_cursor (ply_text_display_t *display)
|
||||
{
|
||||
ply_terminal_write (display->terminal,
|
||||
SHOW_CURSOR_SEQUENCE);
|
||||
}
|
||||
|
||||
bool
|
||||
ply_text_display_supports_color (ply_text_display_t *display)
|
||||
{
|
||||
return ply_terminal_supports_color (display->terminal);
|
||||
}
|
||||
|
||||
static void
|
||||
ply_text_display_detach_from_event_loop (ply_text_display_t *display)
|
||||
{
|
||||
assert (display != NULL);
|
||||
display->loop = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_free (ply_text_display_t *display)
|
||||
{
|
||||
if (display == NULL)
|
||||
return;
|
||||
|
||||
if (display->loop != NULL)
|
||||
ply_event_loop_stop_watching_for_exit (display->loop,
|
||||
(ply_event_loop_exit_handler_t)
|
||||
ply_text_display_detach_from_event_loop,
|
||||
display);
|
||||
|
||||
free (display);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_set_draw_handler (ply_text_display_t *display,
|
||||
ply_text_display_draw_handler_t draw_handler,
|
||||
void *user_data)
|
||||
{
|
||||
assert (display != NULL);
|
||||
|
||||
display->draw_handler = draw_handler;
|
||||
display->draw_handler_user_data = user_data;
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_pause_updates (ply_text_display_t *display)
|
||||
{
|
||||
ply_terminal_write (display->terminal,
|
||||
PAUSE_SEQUENCE);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_unpause_updates (ply_text_display_t *display)
|
||||
{
|
||||
ply_terminal_write (display->terminal,
|
||||
UNPAUSE_SEQUENCE);
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_display_attach_to_event_loop (ply_text_display_t *display,
|
||||
ply_event_loop_t *loop)
|
||||
{
|
||||
assert (display != NULL);
|
||||
assert (loop != NULL);
|
||||
assert (display->loop == NULL);
|
||||
|
||||
display->loop = loop;
|
||||
|
||||
ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
|
||||
ply_text_display_detach_from_event_loop,
|
||||
display);
|
||||
}
|
||||
|
||||
ply_terminal_t *
|
||||
ply_text_display_get_terminal (ply_text_display_t *display)
|
||||
{
|
||||
return display->terminal;
|
||||
}
|
||||
|
||||
/* vim: set ts= 4 sw= 4 et ai ci cino= {.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
91
src/libplybootsplash/ply-text-display.h
Normal file
91
src/libplybootsplash/ply-text-display.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/* ply-text-display.h - APIs for displaying text
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_TEXT_DISPLAY_H
|
||||
#define PLY_TEXT_DISPLAY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-console.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-terminal.h"
|
||||
|
||||
typedef struct _ply_text_display ply_text_display_t;
|
||||
|
||||
typedef void (* ply_text_display_draw_handler_t) (void *user_data,
|
||||
ply_terminal_t *terminal,
|
||||
int column,
|
||||
int row,
|
||||
int number_of_columns,
|
||||
int number_of_rows);
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_text_display_t *ply_text_display_new (ply_terminal_t *terminal,
|
||||
ply_console_t *console);
|
||||
|
||||
void ply_text_display_free (ply_text_display_t *display);
|
||||
|
||||
void ply_text_display_attach_to_event_loop (ply_text_display_t *display,
|
||||
ply_event_loop_t *loop);
|
||||
|
||||
ply_terminal_t *ply_text_display_get_terminal (ply_text_display_t *display);
|
||||
|
||||
int ply_text_display_get_number_of_rows (ply_text_display_t *display);
|
||||
int ply_text_display_get_number_of_columns (ply_text_display_t *display);
|
||||
void ply_text_display_set_cursor_position (ply_text_display_t *display,
|
||||
int column,
|
||||
int row);
|
||||
__attribute__((__format__ (__printf__, 2, 3)))
|
||||
void ply_text_display_write (ply_text_display_t *display,
|
||||
const char *format,
|
||||
...);
|
||||
void ply_text_display_hide_cursor (ply_text_display_t *display);
|
||||
void ply_text_display_show_cursor (ply_text_display_t *display);
|
||||
void ply_text_display_clear_screen (ply_text_display_t *display);
|
||||
void ply_text_display_clear_line (ply_text_display_t *display);
|
||||
void ply_text_display_remove_character (ply_text_display_t *display);
|
||||
bool ply_text_display_supports_color (ply_text_display_t *display);
|
||||
void ply_text_display_set_background_color (ply_text_display_t *display,
|
||||
ply_terminal_color_t color);
|
||||
void ply_text_display_set_foreground_color (ply_text_display_t *display,
|
||||
ply_terminal_color_t color);
|
||||
ply_terminal_color_t ply_text_display_get_background_color (ply_text_display_t *display);
|
||||
ply_terminal_color_t ply_text_display_get_foreground_color (ply_text_display_t *display);
|
||||
|
||||
void ply_text_display_draw_area (ply_text_display_t *display,
|
||||
int column,
|
||||
int row,
|
||||
int number_of_columns,
|
||||
int number_of_rows);
|
||||
|
||||
void ply_text_display_set_draw_handler (ply_text_display_t *display,
|
||||
ply_text_display_draw_handler_t draw_handler,
|
||||
void *user_data);
|
||||
void ply_text_display_pause_updates (ply_text_display_t *display);
|
||||
void ply_text_display_unpause_updates (ply_text_display_t *display);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PLY_TEXT_DISPLAY_H */
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
|
|
@ -43,11 +43,11 @@
|
|||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "ply-text-display.h"
|
||||
#include "ply-text-progress-bar.h"
|
||||
#include "ply-array.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ static char *os_string;
|
|||
|
||||
struct _ply_text_progress_bar
|
||||
{
|
||||
ply_window_t *window;
|
||||
ply_text_display_t *display;
|
||||
|
||||
int column, row;
|
||||
int number_of_rows;
|
||||
|
|
@ -124,16 +124,15 @@ out:
|
|||
void
|
||||
ply_text_progress_bar_draw (ply_text_progress_bar_t *progress_bar)
|
||||
{
|
||||
int i, width = progress_bar->number_of_columns - 2 - strlen(os_string);
|
||||
int i, width = progress_bar->number_of_columns - 2 - strlen (os_string);
|
||||
double brown_fraction, blue_fraction, white_fraction;
|
||||
|
||||
if (progress_bar->is_hidden)
|
||||
return;
|
||||
|
||||
ply_window_set_mode (progress_bar->window, PLY_WINDOW_MODE_TEXT);
|
||||
ply_window_set_text_cursor_position(progress_bar->window,
|
||||
progress_bar->column,
|
||||
progress_bar->row);
|
||||
ply_text_display_set_cursor_position (progress_bar->display,
|
||||
progress_bar->column,
|
||||
progress_bar->row);
|
||||
|
||||
brown_fraction = - (progress_bar->percent_done * progress_bar->percent_done) + 2 * progress_bar->percent_done;
|
||||
blue_fraction = progress_bar->percent_done;
|
||||
|
|
@ -144,56 +143,56 @@ ply_text_progress_bar_draw (ply_text_progress_bar_t *progress_bar)
|
|||
|
||||
f = (double) i / (double) width;
|
||||
if (f < white_fraction)
|
||||
ply_window_set_background_color (progress_bar->window,
|
||||
PLY_WINDOW_COLOR_WHITE);
|
||||
ply_text_display_set_background_color (progress_bar->display,
|
||||
PLY_TERMINAL_COLOR_WHITE);
|
||||
else if (f < blue_fraction)
|
||||
ply_window_set_background_color (progress_bar->window,
|
||||
PLY_WINDOW_COLOR_BLUE);
|
||||
ply_text_display_set_background_color (progress_bar->display,
|
||||
PLY_TERMINAL_COLOR_BLUE);
|
||||
else if (f < brown_fraction)
|
||||
ply_window_set_background_color (progress_bar->window,
|
||||
PLY_WINDOW_COLOR_BROWN);
|
||||
ply_text_display_set_background_color (progress_bar->display,
|
||||
PLY_TERMINAL_COLOR_BROWN);
|
||||
else
|
||||
break;
|
||||
|
||||
write (STDOUT_FILENO, " ", strlen (" "));
|
||||
ply_text_display_write (progress_bar->display, "%c", ' ');
|
||||
}
|
||||
|
||||
ply_window_set_background_color (progress_bar->window, PLY_WINDOW_COLOR_BLACK);
|
||||
ply_text_display_set_background_color (progress_bar->display,
|
||||
PLY_TERMINAL_COLOR_BLACK);
|
||||
|
||||
if (brown_fraction > 0.5) {
|
||||
if (white_fraction > 0.875)
|
||||
ply_window_set_foreground_color (progress_bar->window,
|
||||
PLY_WINDOW_COLOR_WHITE);
|
||||
ply_text_display_set_foreground_color (progress_bar->display,
|
||||
PLY_TERMINAL_COLOR_WHITE);
|
||||
else if (blue_fraction > 0.66)
|
||||
ply_window_set_foreground_color (progress_bar->window,
|
||||
PLY_WINDOW_COLOR_BLUE);
|
||||
ply_text_display_set_foreground_color (progress_bar->display,
|
||||
PLY_TERMINAL_COLOR_BLUE);
|
||||
else
|
||||
ply_window_set_foreground_color (progress_bar->window,
|
||||
PLY_WINDOW_COLOR_BROWN);
|
||||
ply_text_display_set_foreground_color (progress_bar->display,
|
||||
PLY_TERMINAL_COLOR_BROWN);
|
||||
|
||||
ply_window_set_text_cursor_position(progress_bar->window,
|
||||
progress_bar->column + width,
|
||||
progress_bar->row);
|
||||
ply_text_display_set_cursor_position (progress_bar->display,
|
||||
progress_bar->column + width,
|
||||
progress_bar->row);
|
||||
|
||||
ply_text_display_write (progress_bar->display, "%s", os_string);
|
||||
|
||||
write (STDOUT_FILENO, os_string, strlen(os_string));
|
||||
|
||||
ply_window_set_foreground_color (progress_bar->window,
|
||||
PLY_WINDOW_COLOR_DEFAULT);
|
||||
ply_text_display_set_foreground_color (progress_bar->display,
|
||||
PLY_TERMINAL_COLOR_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ply_text_progress_bar_show (ply_text_progress_bar_t *progress_bar,
|
||||
ply_window_t *window)
|
||||
ply_text_display_t *display)
|
||||
{
|
||||
assert (progress_bar != NULL);
|
||||
|
||||
progress_bar->window = window;
|
||||
progress_bar->display = display;
|
||||
|
||||
progress_bar->number_of_rows = ply_window_get_number_of_text_rows(window);
|
||||
progress_bar->number_of_rows = ply_text_display_get_number_of_rows (display);
|
||||
progress_bar->row = progress_bar->number_of_rows - 1;
|
||||
progress_bar->number_of_columns = ply_window_get_number_of_text_columns(window);
|
||||
progress_bar->number_of_columns = ply_text_display_get_number_of_columns (display);
|
||||
progress_bar->column = 2;
|
||||
|
||||
get_os_string ();
|
||||
|
|
@ -206,7 +205,7 @@ ply_text_progress_bar_show (ply_text_progress_bar_t *progress_bar,
|
|||
void
|
||||
ply_text_progress_bar_hide (ply_text_progress_bar_t *progress_bar)
|
||||
{
|
||||
progress_bar->window = NULL;
|
||||
progress_bar->display = NULL;
|
||||
progress_bar->is_hidden = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-window.h"
|
||||
#include "ply-text-display.h"
|
||||
|
||||
typedef struct _ply_text_progress_bar ply_text_progress_bar_t;
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ void ply_text_progress_bar_free (ply_text_progress_bar_t *progress_bar);
|
|||
|
||||
void ply_text_progress_bar_draw (ply_text_progress_bar_t *progress_bar);
|
||||
void ply_text_progress_bar_show (ply_text_progress_bar_t *progress_bar,
|
||||
ply_window_t *window);
|
||||
ply_text_display_t *display);
|
||||
void ply_text_progress_bar_hide (ply_text_progress_bar_t *progress_bar);
|
||||
|
||||
void ply_text_progress_bar_set_percent_done (ply_text_progress_bar_t *progress_bar,
|
||||
|
|
|
|||
|
|
@ -42,12 +42,12 @@
|
|||
|
||||
#include "ply-throbber.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-array.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-image.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
|
|
@ -62,14 +62,15 @@ struct _ply_throbber
|
|||
char *image_dir;
|
||||
char *frames_prefix;
|
||||
|
||||
ply_window_t *window;
|
||||
ply_frame_buffer_t *frame_buffer;
|
||||
ply_frame_buffer_area_t frame_area;
|
||||
ply_pixel_display_t *display;
|
||||
ply_rectangle_t frame_area;
|
||||
ply_trigger_t *stop_trigger;
|
||||
|
||||
long x, y;
|
||||
long width, height;
|
||||
double start_time, previous_time, now;
|
||||
double start_time, now;
|
||||
|
||||
int frame_number;
|
||||
uint32_t is_stopped : 1;
|
||||
};
|
||||
|
||||
|
|
@ -94,6 +95,7 @@ ply_throbber_new (const char *image_dir,
|
|||
throbber->frame_area.height = 0;
|
||||
throbber->frame_area.x = 0;
|
||||
throbber->frame_area.y = 0;
|
||||
throbber->frame_number = 0;
|
||||
|
||||
return throbber;
|
||||
}
|
||||
|
|
@ -124,27 +126,14 @@ ply_throbber_free (ply_throbber_t *throbber)
|
|||
free (throbber);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_background (ply_throbber_t *throbber)
|
||||
{
|
||||
ply_window_erase_area (throbber->window,
|
||||
throbber->x, throbber->y,
|
||||
throbber->frame_area.width,
|
||||
throbber->frame_area.height);
|
||||
}
|
||||
|
||||
static bool
|
||||
animate_at_time (ply_throbber_t *throbber,
|
||||
double time)
|
||||
{
|
||||
int number_of_frames;
|
||||
int frame_number;
|
||||
ply_image_t * const * frames;
|
||||
uint32_t *frame_data;
|
||||
bool should_continue;
|
||||
|
||||
ply_window_set_mode (throbber->window, PLY_WINDOW_MODE_GRAPHICS);
|
||||
|
||||
number_of_frames = ply_array_get_size (throbber->frames);
|
||||
|
||||
if (number_of_frames == 0)
|
||||
|
|
@ -152,31 +141,24 @@ animate_at_time (ply_throbber_t *throbber,
|
|||
|
||||
should_continue = true;
|
||||
|
||||
frame_number = (.5 * sin (time) + .5) * number_of_frames;
|
||||
throbber->frame_number = (.5 * sin (time) + .5) * number_of_frames;
|
||||
|
||||
if (throbber->stop_trigger != NULL)
|
||||
{
|
||||
if ((time - throbber->previous_time) >= 2 * M_PI)
|
||||
frame_number = number_of_frames - 1;
|
||||
should_continue = false;
|
||||
if (throbber->frame_number == number_of_frames - 1)
|
||||
should_continue = false;
|
||||
}
|
||||
|
||||
ply_frame_buffer_pause_updates (throbber->frame_buffer);
|
||||
if (throbber->frame_area.width > 0)
|
||||
draw_background (throbber);
|
||||
|
||||
frames = (ply_image_t * const *) ply_array_get_elements (throbber->frames);
|
||||
|
||||
throbber->frame_area.x = throbber->x;
|
||||
throbber->frame_area.y = throbber->y;
|
||||
throbber->frame_area.width = ply_image_get_width (frames[frame_number]);
|
||||
throbber->frame_area.height = ply_image_get_height (frames[frame_number]);
|
||||
frame_data = ply_image_get_data (frames[frame_number]);
|
||||
|
||||
ply_frame_buffer_fill_with_argb32_data (throbber->frame_buffer,
|
||||
&throbber->frame_area, 0, 0,
|
||||
frame_data);
|
||||
ply_frame_buffer_unpause_updates (throbber->frame_buffer);
|
||||
throbber->frame_area.width = ply_image_get_width (frames[throbber->frame_number]);
|
||||
throbber->frame_area.height = ply_image_get_height (frames[throbber->frame_number]);
|
||||
ply_pixel_display_draw_area (throbber->display,
|
||||
throbber->x, throbber->y,
|
||||
throbber->frame_area.width,
|
||||
throbber->frame_area.height);
|
||||
|
||||
return should_continue;
|
||||
}
|
||||
|
|
@ -186,7 +168,6 @@ on_timeout (ply_throbber_t *throbber)
|
|||
{
|
||||
double sleep_time;
|
||||
bool should_continue;
|
||||
throbber->previous_time = throbber->now;
|
||||
throbber->now = ply_get_timestamp ();
|
||||
|
||||
#ifdef REAL_TIME_ANIMATION
|
||||
|
|
@ -204,9 +185,6 @@ on_timeout (ply_throbber_t *throbber)
|
|||
|
||||
if (!should_continue)
|
||||
{
|
||||
|
||||
draw_background (throbber);
|
||||
|
||||
if (throbber->stop_trigger != NULL)
|
||||
{
|
||||
ply_trigger_pull (throbber->stop_trigger, NULL);
|
||||
|
|
@ -313,18 +291,17 @@ ply_throbber_load (ply_throbber_t *throbber)
|
|||
}
|
||||
|
||||
bool
|
||||
ply_throbber_start (ply_throbber_t *throbber,
|
||||
ply_event_loop_t *loop,
|
||||
ply_window_t *window,
|
||||
long x,
|
||||
long y)
|
||||
ply_throbber_start (ply_throbber_t *throbber,
|
||||
ply_event_loop_t *loop,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y)
|
||||
{
|
||||
assert (throbber != NULL);
|
||||
assert (throbber->loop == NULL);
|
||||
|
||||
throbber->loop = loop;
|
||||
throbber->window = window;
|
||||
throbber->frame_buffer = ply_window_get_frame_buffer (window);;
|
||||
throbber->display = display;
|
||||
throbber->is_stopped = false;
|
||||
|
||||
throbber->x = x;
|
||||
|
|
@ -343,13 +320,13 @@ ply_throbber_start (ply_throbber_t *throbber,
|
|||
static void
|
||||
ply_throbber_stop_now (ply_throbber_t *throbber)
|
||||
{
|
||||
if (throbber->frame_area.width > 0)
|
||||
draw_background (throbber);
|
||||
|
||||
throbber->frame_buffer = NULL;
|
||||
throbber->window = NULL;
|
||||
throbber->is_stopped = true;
|
||||
|
||||
ply_pixel_display_draw_area (throbber->display,
|
||||
throbber->x,
|
||||
throbber->y,
|
||||
throbber->frame_area.width,
|
||||
throbber->frame_area.height);
|
||||
if (throbber->loop != NULL)
|
||||
{
|
||||
ply_event_loop_stop_watching_for_timeout (throbber->loop,
|
||||
|
|
@ -357,6 +334,7 @@ ply_throbber_stop_now (ply_throbber_t *throbber)
|
|||
on_timeout, throbber);
|
||||
throbber->loop = NULL;
|
||||
}
|
||||
throbber->display = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -379,6 +357,28 @@ ply_throbber_is_stopped (ply_throbber_t *throbber)
|
|||
return throbber->is_stopped;
|
||||
}
|
||||
|
||||
void
|
||||
ply_throbber_draw_area (ply_throbber_t *throbber,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
ply_image_t * const * frames;
|
||||
uint32_t *frame_data;
|
||||
|
||||
if (throbber->is_stopped)
|
||||
return;
|
||||
|
||||
frames = (ply_image_t * const *) ply_array_get_elements (throbber->frames);
|
||||
frame_data = ply_image_get_data (frames[throbber->frame_number]);
|
||||
|
||||
ply_pixel_buffer_fill_with_argb32_data (buffer,
|
||||
&throbber->frame_area, 0, 0,
|
||||
frame_data);
|
||||
}
|
||||
|
||||
long
|
||||
ply_throbber_get_width (ply_throbber_t *throbber)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-trigger.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
typedef struct _ply_throbber ply_throbber_t;
|
||||
|
||||
|
|
@ -40,14 +40,21 @@ void ply_throbber_free (ply_throbber_t *throbber);
|
|||
|
||||
bool ply_throbber_load (ply_throbber_t *throbber);
|
||||
bool ply_throbber_start (ply_throbber_t *throbber,
|
||||
ply_event_loop_t *loop,
|
||||
ply_window_t *window,
|
||||
long x,
|
||||
long y);
|
||||
ply_event_loop_t *loop,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y);
|
||||
void ply_throbber_stop (ply_throbber_t *throbber,
|
||||
ply_trigger_t *stop_trigger);
|
||||
bool ply_throbber_is_stopped (ply_throbber_t *throbber);
|
||||
|
||||
void ply_throbber_draw_area (ply_throbber_t *throbber,
|
||||
ply_pixel_buffer_t *buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height);
|
||||
|
||||
long ply_throbber_get_width (ply_throbber_t *throbber);
|
||||
long ply_throbber_get_height (ply_throbber_t *throbber);
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,165 +0,0 @@
|
|||
/* ply-window.h - APIs for putting up a splash screen
|
||||
*
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_WINDOW_H
|
||||
#define PLY_WINDOW_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
|
||||
typedef struct _ply_window ply_window_t;
|
||||
|
||||
typedef void (* ply_window_keyboard_input_handler_t) (void *user_data,
|
||||
const char *keyboard_input,
|
||||
size_t character_size);
|
||||
|
||||
typedef void (* ply_window_backspace_handler_t) (void *user_data);
|
||||
typedef void (* ply_window_escape_handler_t) (void *user_data);
|
||||
typedef void (* ply_window_enter_handler_t) (void *user_data,
|
||||
const char *line);
|
||||
|
||||
typedef void (* ply_window_draw_handler_t) (void *user_data,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
typedef void (* ply_window_erase_handler_t) (void *user_data,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLY_WINDOW_MODE_TEXT,
|
||||
PLY_WINDOW_MODE_GRAPHICS
|
||||
} ply_window_mode_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLY_WINDOW_COLOR_BLACK = 0,
|
||||
PLY_WINDOW_COLOR_RED,
|
||||
PLY_WINDOW_COLOR_GREEN,
|
||||
PLY_WINDOW_COLOR_BROWN,
|
||||
PLY_WINDOW_COLOR_BLUE,
|
||||
PLY_WINDOW_COLOR_MAGENTA,
|
||||
PLY_WINDOW_COLOR_CYAN,
|
||||
PLY_WINDOW_COLOR_WHITE,
|
||||
PLY_WINDOW_COLOR_DEFAULT = PLY_WINDOW_COLOR_WHITE + 2
|
||||
} ply_window_color_t;
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_window_t *ply_window_new (const char *name);
|
||||
void ply_window_free (ply_window_t *window);
|
||||
|
||||
void ply_window_add_keyboard_input_handler (ply_window_t *window,
|
||||
ply_window_keyboard_input_handler_t input_handler,
|
||||
void *user_data);
|
||||
void ply_window_remove_keyboard_input_handler (ply_window_t *window,
|
||||
ply_window_keyboard_input_handler_t input_handler);
|
||||
void ply_window_add_backspace_handler (ply_window_t *window,
|
||||
ply_window_backspace_handler_t backspace_handler,
|
||||
void *user_data);
|
||||
void ply_window_remove_backspace_handler (ply_window_t *window,
|
||||
ply_window_backspace_handler_t backspace_handler);
|
||||
void ply_window_add_escape_handler (ply_window_t *window,
|
||||
ply_window_escape_handler_t escape_handler,
|
||||
void *user_data);
|
||||
void ply_window_remove_escape_handler (ply_window_t *window,
|
||||
ply_window_escape_handler_t escape_handler);
|
||||
void ply_window_add_enter_handler (ply_window_t *window,
|
||||
ply_window_enter_handler_t enter_handler,
|
||||
void *user_data);
|
||||
void ply_window_remove_enter_handler (ply_window_t *window,
|
||||
ply_window_enter_handler_t enter_handler);
|
||||
void ply_window_add_draw_handler (ply_window_t *window,
|
||||
ply_window_draw_handler_t draw_handler,
|
||||
void *user_data);
|
||||
void ply_window_remove_draw_handler (ply_window_t *window,
|
||||
ply_window_draw_handler_t draw_handler);
|
||||
void ply_window_add_erase_handler (ply_window_t *window,
|
||||
ply_window_erase_handler_t erase_handler,
|
||||
void *user_data);
|
||||
void ply_window_remove_erase_handler (ply_window_t *window,
|
||||
ply_window_erase_handler_t erase_handler);
|
||||
|
||||
bool ply_window_open (ply_window_t *window);
|
||||
bool ply_window_is_open (ply_window_t *window);
|
||||
void ply_window_close (ply_window_t *window);
|
||||
bool ply_window_set_mode (ply_window_t *window,
|
||||
ply_window_mode_t mode);
|
||||
int ply_window_get_tty_fd (ply_window_t *window);
|
||||
int ply_window_get_number_of_text_rows (ply_window_t *window);
|
||||
int ply_window_get_number_of_text_columns (ply_window_t *window);
|
||||
void ply_window_set_text_cursor_position (ply_window_t *window,
|
||||
int column,
|
||||
int row);
|
||||
void ply_window_hide_text_cursor (ply_window_t *window);
|
||||
void ply_window_show_text_cursor (ply_window_t *window);
|
||||
void ply_window_clear_screen (ply_window_t *window);
|
||||
void ply_window_clear_text_line (ply_window_t *window);
|
||||
void ply_window_clear_text_character (ply_window_t *window);
|
||||
bool ply_window_supports_text_color (ply_window_t *window);
|
||||
void ply_window_set_background_color (ply_window_t *window,
|
||||
ply_window_color_t color);
|
||||
void ply_window_set_foreground_color (ply_window_t *window,
|
||||
ply_window_color_t color);
|
||||
ply_window_color_t ply_window_get_background_color (ply_window_t *window);
|
||||
ply_window_color_t ply_window_get_foreground_color (ply_window_t *window);
|
||||
|
||||
void ply_window_draw_area (ply_window_t *window,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void ply_window_erase_area (ply_window_t *window,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
uint32_t ply_window_get_color_hex_value (ply_window_t *window,
|
||||
ply_window_color_t color);
|
||||
void ply_window_set_color_hex_value (ply_window_t *window,
|
||||
ply_window_color_t color,
|
||||
uint32_t hex_value);
|
||||
void ply_window_reset_colors (ply_window_t *window);
|
||||
|
||||
void ply_window_set_draw_handler (ply_window_t *window,
|
||||
ply_window_draw_handler_t draw_handler,
|
||||
void *user_data);
|
||||
void ply_window_set_erase_handler (ply_window_t *window,
|
||||
ply_window_erase_handler_t erase_handler,
|
||||
void *user_data);
|
||||
void ply_window_attach_to_event_loop (ply_window_t *window,
|
||||
ply_event_loop_t *loop);
|
||||
ply_frame_buffer_t *ply_window_get_frame_buffer (ply_window_t *window);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PLY_WINDOW_H */
|
||||
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
|
||||
349
src/main.c
349
src/main.c
|
|
@ -79,8 +79,11 @@ typedef struct
|
|||
typedef struct
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
ply_console_t *console;
|
||||
ply_boot_server_t *boot_server;
|
||||
ply_list_t *windows;
|
||||
ply_list_t *pixel_displays;
|
||||
ply_list_t *text_displays;
|
||||
ply_keyboard_t *keyboard;
|
||||
ply_boot_splash_t *boot_splash;
|
||||
ply_terminal_session_t *session;
|
||||
ply_buffer_t *boot_buffer;
|
||||
|
|
@ -90,6 +93,7 @@ typedef struct
|
|||
ply_buffer_t *entry_buffer;
|
||||
ply_command_parser_t *command_parser;
|
||||
ply_mode_t mode;
|
||||
ply_renderer_t *renderer;
|
||||
|
||||
ply_trigger_t *quit_trigger;
|
||||
|
||||
|
|
@ -104,6 +108,7 @@ typedef struct
|
|||
|
||||
char *kernel_console_tty;
|
||||
char *override_splash_path;
|
||||
const char *default_tty;
|
||||
|
||||
int number_of_errors;
|
||||
} state_t;
|
||||
|
|
@ -111,8 +116,10 @@ typedef struct
|
|||
static ply_boot_splash_t *start_boot_splash (state_t *state,
|
||||
const char *theme_path);
|
||||
|
||||
static ply_window_t *create_window (state_t *state,
|
||||
const char *tty_name);
|
||||
static void add_display_and_keyboard_for_terminal (state_t *state,
|
||||
const char *tty_name);
|
||||
|
||||
static void add_default_displays_and_keyboard (state_t *state);
|
||||
|
||||
static bool attach_to_running_session (state_t *state);
|
||||
static void on_escape_pressed (state_t *state);
|
||||
|
|
@ -460,47 +467,6 @@ on_error (state_t *state)
|
|||
state->number_of_errors++;
|
||||
}
|
||||
|
||||
static bool
|
||||
has_open_window (state_t *state)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
ply_trace ("checking for open windows");
|
||||
|
||||
node = ply_list_get_first_node (state->windows);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
ply_window_t *window;
|
||||
|
||||
next_node = ply_list_get_next_node (state->windows, node);
|
||||
|
||||
window = ply_list_node_get_data (node);
|
||||
|
||||
if (ply_window_is_open (window))
|
||||
{
|
||||
int fd;
|
||||
const char *name;
|
||||
|
||||
fd = ply_window_get_tty_fd (window);
|
||||
|
||||
if (fd >= 0)
|
||||
name = ttyname (fd);
|
||||
else
|
||||
name = NULL;
|
||||
|
||||
ply_trace ("window %s%sis open",
|
||||
name != NULL? name : "",
|
||||
name != NULL? " " : "");
|
||||
return true;
|
||||
}
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
plymouth_should_ignore_show_splash_calls (state_t *state)
|
||||
{
|
||||
|
|
@ -526,9 +492,6 @@ plymouth_should_show_default_splash (state_t *state)
|
|||
if (state->kernel_console_tty != NULL)
|
||||
return false;
|
||||
|
||||
if (!has_open_window (state))
|
||||
return false;
|
||||
|
||||
for (i = 0; strings[i] != NULL; i++)
|
||||
{
|
||||
int cmp;
|
||||
|
|
@ -549,53 +512,47 @@ plymouth_should_show_default_splash (state_t *state)
|
|||
}
|
||||
|
||||
static void
|
||||
open_windows (state_t *state)
|
||||
remove_displays_and_keyboard (state_t *state)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (state->windows);
|
||||
node = ply_list_get_first_node (state->pixel_displays);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
ply_window_t *window;
|
||||
ply_pixel_display_t *display;
|
||||
|
||||
next_node = ply_list_get_next_node (state->windows, node);
|
||||
next_node = ply_list_get_next_node (state->pixel_displays, node);
|
||||
display = ply_list_node_get_data (node);
|
||||
ply_pixel_display_free (display);
|
||||
|
||||
window = ply_list_node_get_data (node);
|
||||
|
||||
if (!ply_window_is_open (window))
|
||||
ply_window_open (window);
|
||||
ply_list_remove_node (state->pixel_displays, node);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
close_windows (state_t *state)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (state->windows);
|
||||
node = ply_list_get_first_node (state->text_displays);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
ply_window_t *window;
|
||||
ply_text_display_t *display;
|
||||
|
||||
next_node = ply_list_get_next_node (state->windows, node);
|
||||
next_node = ply_list_get_next_node (state->text_displays, node);
|
||||
display = ply_list_node_get_data (node);
|
||||
ply_text_display_free (display);
|
||||
|
||||
window = ply_list_node_get_data (node);
|
||||
|
||||
if (ply_window_is_open (window))
|
||||
ply_window_close (window);
|
||||
ply_list_remove_node (state->text_displays, node);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
state->keyboard = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_show_splash (state_t *state)
|
||||
{
|
||||
bool has_window;
|
||||
bool has_display;
|
||||
|
||||
if (plymouth_should_ignore_show_splash_calls (state))
|
||||
{
|
||||
|
|
@ -603,16 +560,15 @@ on_show_splash (state_t *state)
|
|||
return;
|
||||
}
|
||||
|
||||
open_windows (state);
|
||||
has_display = ply_list_get_length (state->pixel_displays) > 0 ||
|
||||
ply_list_get_length (state->text_displays) > 0;
|
||||
|
||||
has_window = has_open_window (state);
|
||||
|
||||
if (!state->is_attached && state->should_be_attached && has_window)
|
||||
if (!state->is_attached && state->should_be_attached && has_display)
|
||||
attach_to_running_session (state);
|
||||
|
||||
if (!has_window && state->is_attached)
|
||||
if (!has_display && state->is_attached)
|
||||
{
|
||||
ply_trace ("no open windows, detaching session");
|
||||
ply_trace ("no open seats, detaching session");
|
||||
ply_terminal_session_detach (state->session);
|
||||
state->is_redirected = false;
|
||||
state->is_attached = false;
|
||||
|
|
@ -641,8 +597,15 @@ quit_splash (state_t *state)
|
|||
state->boot_splash = NULL;
|
||||
}
|
||||
|
||||
ply_trace ("closing windows");
|
||||
close_windows (state);
|
||||
ply_trace ("removing displays and keyboard");
|
||||
remove_displays_and_keyboard (state);
|
||||
|
||||
if (state->renderer != NULL)
|
||||
{
|
||||
ply_renderer_close (state->renderer);
|
||||
ply_renderer_free (state->renderer);
|
||||
state->renderer = NULL;
|
||||
}
|
||||
|
||||
if (state->session != NULL)
|
||||
{
|
||||
|
|
@ -927,43 +890,166 @@ on_enter (state_t *state,
|
|||
}
|
||||
}
|
||||
|
||||
static ply_window_t *
|
||||
create_window (state_t *state,
|
||||
const char *tty_name)
|
||||
static void
|
||||
set_keyboard (state_t *state,
|
||||
ply_keyboard_t *keyboard)
|
||||
{
|
||||
ply_window_t *window;
|
||||
state->keyboard = keyboard;
|
||||
|
||||
ply_trace ("creating window on %s", tty_name != NULL? tty_name : "active vt");
|
||||
window = ply_window_new (tty_name);
|
||||
ply_keyboard_add_escape_handler (keyboard, (ply_keyboard_escape_handler_t)
|
||||
on_escape_pressed, state);
|
||||
ply_trace ("listening for keystrokes");
|
||||
ply_keyboard_add_input_handler (keyboard,
|
||||
(ply_keyboard_input_handler_t)
|
||||
on_keyboard_input, state);
|
||||
ply_trace ("listening for backspace");
|
||||
ply_keyboard_add_backspace_handler (keyboard,
|
||||
(ply_keyboard_backspace_handler_t)
|
||||
on_backspace, state);
|
||||
ply_trace ("listening for enter");
|
||||
ply_keyboard_add_enter_handler (keyboard,
|
||||
(ply_keyboard_enter_handler_t)
|
||||
on_enter, state);
|
||||
ply_keyboard_watch_for_input (keyboard);
|
||||
}
|
||||
static void
|
||||
add_display_and_keyboard_for_terminal (state_t *state,
|
||||
const char *tty_name)
|
||||
{
|
||||
ply_terminal_t *terminal;
|
||||
ply_text_display_t *display;
|
||||
ply_keyboard_t *keyboard;
|
||||
|
||||
ply_window_attach_to_event_loop (window, state->loop);
|
||||
ply_trace ("adding display and keyboard for %s", tty_name);
|
||||
|
||||
return window;
|
||||
terminal = ply_terminal_new (tty_name);
|
||||
|
||||
if (!ply_terminal_open (terminal))
|
||||
{
|
||||
ply_trace ("could not open terminal '%s': %m", tty_name);
|
||||
ply_terminal_free (terminal);
|
||||
return;
|
||||
}
|
||||
|
||||
ply_console_set_active_vt (state->console,
|
||||
ply_terminal_get_vt_number (terminal));
|
||||
|
||||
keyboard = ply_keyboard_new_for_terminal (terminal);
|
||||
display = ply_text_display_new (terminal, state->console);
|
||||
|
||||
ply_list_append_data (state->text_displays, display);
|
||||
state->keyboard = keyboard;
|
||||
set_keyboard (state, keyboard);
|
||||
}
|
||||
|
||||
static void
|
||||
add_windows_to_boot_splash (state_t *state,
|
||||
ply_boot_splash_t *splash)
|
||||
add_pixel_displays_from_renderer (state_t *state,
|
||||
ply_renderer_t *renderer)
|
||||
{
|
||||
ply_list_t *heads;
|
||||
ply_list_node_t *node;
|
||||
|
||||
ply_trace ("There are %d windows in list",
|
||||
ply_list_get_length (state->windows));
|
||||
node = ply_list_get_first_node (state->windows);
|
||||
heads = ply_renderer_get_heads (renderer);
|
||||
|
||||
node = ply_list_get_first_node (heads);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
ply_window_t *window;
|
||||
ply_renderer_head_t *head;
|
||||
ply_pixel_display_t *display;
|
||||
|
||||
next_node = ply_list_get_next_node (state->windows, node);
|
||||
head = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (heads, node);
|
||||
|
||||
window = ply_list_node_get_data (node);
|
||||
display = ply_pixel_display_new (renderer, head);
|
||||
|
||||
ply_list_append_data (state->pixel_displays, display);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
add_default_displays_and_keyboard (state_t *state)
|
||||
{
|
||||
ply_renderer_t *renderer;
|
||||
ply_keyboard_t *keyboard;
|
||||
ply_terminal_t *terminal;
|
||||
ply_text_display_t *text_display;
|
||||
|
||||
ply_trace ("adding default displays and keyboard");
|
||||
|
||||
terminal = ply_terminal_new (state->default_tty);
|
||||
|
||||
if (!ply_terminal_open (terminal))
|
||||
{
|
||||
ply_trace ("could not open terminal '%s': %m", state->default_tty);
|
||||
ply_terminal_free (terminal);
|
||||
return;
|
||||
}
|
||||
|
||||
ply_console_set_active_vt (state->console,
|
||||
ply_terminal_get_vt_number (terminal));
|
||||
|
||||
renderer = ply_renderer_new (NULL, terminal, state->console);
|
||||
|
||||
if (!ply_renderer_open (renderer))
|
||||
{
|
||||
ply_trace ("could not open renderer /dev/fb");
|
||||
ply_renderer_free (renderer);
|
||||
ply_terminal_free (terminal);
|
||||
|
||||
add_display_and_keyboard_for_terminal (state, state->default_tty);
|
||||
return;
|
||||
}
|
||||
|
||||
keyboard = ply_keyboard_new_for_renderer (renderer);
|
||||
set_keyboard (state, keyboard);
|
||||
|
||||
add_pixel_displays_from_renderer (state, renderer);
|
||||
|
||||
text_display = ply_text_display_new (terminal, state->console);
|
||||
ply_list_append_data (state->text_displays, text_display);
|
||||
|
||||
state->renderer = renderer;
|
||||
}
|
||||
|
||||
static void
|
||||
add_displays_and_keyboard_to_boot_splash (state_t *state,
|
||||
ply_boot_splash_t *splash)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
ply_trace ("setting keyboard on boot splash");
|
||||
ply_boot_splash_set_keyboard (splash, state->keyboard);
|
||||
|
||||
node = ply_list_get_first_node (state->pixel_displays);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_pixel_display_t *display;
|
||||
ply_list_node_t *next_node;
|
||||
|
||||
display = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (state->pixel_displays, node);
|
||||
ply_trace ("adding pixel display on boot splash");
|
||||
ply_boot_splash_add_pixel_display (splash, display);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
node = ply_list_get_first_node (state->text_displays);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_text_display_t *display;
|
||||
ply_list_node_t *next_node;
|
||||
|
||||
display = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (state->text_displays, node);
|
||||
|
||||
ply_trace ("adding text display on boot splash");
|
||||
ply_boot_splash_add_text_display (splash, display);
|
||||
|
||||
if (ply_window_is_open (window))
|
||||
{
|
||||
ply_trace ("adding window to boot splash");
|
||||
ply_boot_splash_add_window (splash, window);
|
||||
}
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
|
@ -978,7 +1064,10 @@ start_boot_splash (state_t *state,
|
|||
ply_trace ("Loading boot splash theme '%s'",
|
||||
theme_path);
|
||||
|
||||
splash = ply_boot_splash_new (theme_path, PLYMOUTH_PLUGIN_PATH, state->boot_buffer);
|
||||
splash = ply_boot_splash_new (theme_path,
|
||||
PLYMOUTH_PLUGIN_PATH,
|
||||
state->boot_buffer,
|
||||
state->console);
|
||||
|
||||
if (!ply_boot_splash_load (splash))
|
||||
{
|
||||
|
|
@ -994,8 +1083,8 @@ start_boot_splash (state_t *state,
|
|||
ply_trace ("attaching progress to plugin");
|
||||
ply_boot_splash_attach_progress (splash, state->progress);
|
||||
|
||||
ply_trace ("adding windows to boot splash");
|
||||
add_windows_to_boot_splash (state, splash);
|
||||
add_displays_and_keyboard_to_boot_splash (state, splash);
|
||||
|
||||
ply_trace ("showing plugin");
|
||||
if (state->mode == PLY_MODE_SHUTDOWN)
|
||||
splash_mode = PLY_BOOT_SPLASH_MODE_SHUTDOWN;
|
||||
|
|
@ -1179,6 +1268,16 @@ check_for_consoles (state_t *state,
|
|||
|
||||
ply_trace ("checking if splash screen should be disabled");
|
||||
|
||||
state->console = ply_console_new ();
|
||||
|
||||
if (!ply_console_open (state->console))
|
||||
{
|
||||
ply_trace ("could not open /dev/tty0");
|
||||
ply_console_free (state->console);
|
||||
state->console = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
remaining_command_line = state->kernel_command_line;
|
||||
while ((console_key = strstr (remaining_command_line, " console=")) != NULL)
|
||||
{
|
||||
|
|
@ -1204,11 +1303,11 @@ check_for_consoles (state_t *state,
|
|||
state->kernel_console_tty = strdup (default_tty);
|
||||
}
|
||||
|
||||
ply_list_append_data (state->windows, create_window (state, state->kernel_console_tty));
|
||||
add_display_and_keyboard_for_terminal (state, state->kernel_console_tty);
|
||||
}
|
||||
|
||||
if (ply_list_get_length (state->windows) == 0)
|
||||
ply_list_append_data (state->windows, create_window (state, default_tty));
|
||||
if (ply_list_get_length (state->text_displays) == 0)
|
||||
add_default_displays_and_keyboard (state);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -1241,10 +1340,7 @@ redirect_standard_io_to_device (const char *device)
|
|||
static bool
|
||||
initialize_environment (state_t *state)
|
||||
{
|
||||
const char *default_tty;
|
||||
|
||||
ply_trace ("initializing minimal work environment");
|
||||
ply_list_node_t *node;
|
||||
|
||||
if (!get_kernel_command_line (state))
|
||||
return false;
|
||||
|
|
@ -1252,46 +1348,27 @@ initialize_environment (state_t *state)
|
|||
check_verbosity (state);
|
||||
check_logging (state);
|
||||
|
||||
state->windows = ply_list_new ();
|
||||
state->keystroke_triggers = ply_list_new ();
|
||||
state->entry_triggers = ply_list_new ();
|
||||
state->entry_buffer = ply_buffer_new();
|
||||
state->pixel_displays = ply_list_new ();
|
||||
state->text_displays = ply_list_new ();
|
||||
state->keyboard = NULL;
|
||||
|
||||
if (state->mode == PLY_MODE_SHUTDOWN)
|
||||
{
|
||||
default_tty = "tty63";
|
||||
ply_switch_to_vt (63);
|
||||
state->default_tty = "tty63";
|
||||
}
|
||||
else
|
||||
default_tty = "tty1";
|
||||
state->default_tty = "tty1";
|
||||
|
||||
check_for_consoles (state, default_tty);
|
||||
check_for_consoles (state, state->default_tty);
|
||||
|
||||
if (state->kernel_console_tty != NULL)
|
||||
redirect_standard_io_to_device (state->kernel_console_tty);
|
||||
else
|
||||
redirect_standard_io_to_device (default_tty);
|
||||
redirect_standard_io_to_device (state->default_tty);
|
||||
|
||||
for (node = ply_list_get_first_node (state->windows); node;
|
||||
node = ply_list_get_next_node (state->windows, node))
|
||||
{
|
||||
ply_window_t *window = ply_list_node_get_data (node);
|
||||
|
||||
ply_trace ("listening for escape key");
|
||||
ply_window_add_escape_handler (window, (ply_window_escape_handler_t)
|
||||
on_escape_pressed, state);
|
||||
ply_trace ("listening for keystrokes");
|
||||
ply_window_add_keyboard_input_handler (window,
|
||||
(ply_window_keyboard_input_handler_t) on_keyboard_input, state);
|
||||
ply_trace ("listening for backspace");
|
||||
ply_window_add_backspace_handler (window,
|
||||
(ply_window_backspace_handler_t) on_backspace, state);
|
||||
ply_trace ("listening for enter");
|
||||
ply_window_add_enter_handler (window,
|
||||
(ply_window_enter_handler_t) on_enter, state);
|
||||
}
|
||||
|
||||
|
||||
ply_trace ("initialized minimal work environment");
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1359,7 +1436,7 @@ main (int argc,
|
|||
|
||||
state.command_parser = ply_command_parser_new ("plymouthd", "Boot splash control server");
|
||||
|
||||
state.loop = ply_event_loop_new ();
|
||||
state.loop = ply_event_loop_get_default ();
|
||||
|
||||
ply_command_parser_add_options (state.command_parser,
|
||||
"help", "This help message", PLY_COMMAND_OPTION_TYPE_FLAG,
|
||||
|
|
@ -1515,7 +1592,6 @@ main (int argc,
|
|||
state.boot_splash = NULL;
|
||||
|
||||
ply_command_parser_free (state.command_parser);
|
||||
ply_list_free (state.windows);
|
||||
|
||||
ply_boot_server_free (state.boot_server);
|
||||
state.boot_server = NULL;
|
||||
|
|
@ -1526,9 +1602,6 @@ main (int argc,
|
|||
ply_buffer_free (state.boot_buffer);
|
||||
ply_progress_free (state.progress);
|
||||
|
||||
ply_trace ("freeing event loop");
|
||||
ply_event_loop_free (state.loop);
|
||||
|
||||
ply_trace ("exiting with code %d", exit_code);
|
||||
|
||||
if (debug_buffer != NULL)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
SUBDIRS = controls splash
|
||||
SUBDIRS = controls splash renderers
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
|
|
|||
|
|
@ -43,22 +43,18 @@
|
|||
#include <cairo.h>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include "ply-label-plugin.h"
|
||||
|
||||
struct _ply_label_plugin_control
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
ply_window_t *window;
|
||||
ply_frame_buffer_t *frame_buffer;
|
||||
ply_frame_buffer_area_t area;
|
||||
ply_pixel_display_t *display;
|
||||
ply_rectangle_t area;
|
||||
|
||||
PangoLayout *pango_layout;
|
||||
cairo_t *cairo_context;
|
||||
cairo_surface_t *cairo_surface;
|
||||
char *text;
|
||||
|
||||
uint32_t is_hidden : 1;
|
||||
|
|
@ -82,64 +78,135 @@ destroy_control (ply_label_plugin_control_t *label)
|
|||
if (label == NULL)
|
||||
return;
|
||||
|
||||
cairo_destroy (label->cairo_context);
|
||||
cairo_surface_destroy (label->cairo_surface);
|
||||
g_object_unref (label->pango_layout);
|
||||
|
||||
free (label);
|
||||
}
|
||||
|
||||
long
|
||||
get_width_of_control (ply_label_plugin_control_t *label)
|
||||
{
|
||||
int width;
|
||||
|
||||
pango_layout_get_size (label->pango_layout, &width, NULL);
|
||||
|
||||
return (long) ((double) width / PANGO_SCALE)+1;
|
||||
return label->area.width;
|
||||
}
|
||||
|
||||
long
|
||||
get_height_of_control (ply_label_plugin_control_t *label)
|
||||
{
|
||||
int height;
|
||||
return label->area.height;
|
||||
}
|
||||
|
||||
pango_layout_get_size (label->pango_layout, NULL, &height);
|
||||
static cairo_t *
|
||||
get_cairo_context_for_pixel_buffer (ply_label_plugin_control_t *label,
|
||||
ply_pixel_buffer_t *pixel_buffer)
|
||||
{
|
||||
cairo_surface_t *cairo_surface;
|
||||
cairo_t *cairo_context;
|
||||
unsigned char *data;
|
||||
ply_rectangle_t size;
|
||||
|
||||
return (long) ((double) height / PANGO_SCALE)+1;
|
||||
data = (unsigned char *) ply_pixel_buffer_get_argb32_data (pixel_buffer);
|
||||
ply_pixel_buffer_get_size (pixel_buffer, &size);
|
||||
|
||||
cairo_surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
size.width,
|
||||
size.height,
|
||||
size.width * 4);
|
||||
cairo_context = cairo_create (cairo_surface);
|
||||
cairo_surface_destroy (cairo_surface);
|
||||
|
||||
return cairo_context;
|
||||
}
|
||||
|
||||
static cairo_t *
|
||||
get_cairo_context_for_sizing (ply_label_plugin_control_t *label)
|
||||
{
|
||||
cairo_surface_t *cairo_surface;
|
||||
cairo_t *cairo_context;
|
||||
|
||||
cairo_surface = cairo_image_surface_create_for_data (NULL, CAIRO_FORMAT_ARGB32, 0, 0, 0);
|
||||
cairo_context = cairo_create (cairo_surface);
|
||||
cairo_surface_destroy (cairo_surface);
|
||||
|
||||
return cairo_context;
|
||||
}
|
||||
|
||||
static void
|
||||
erase_label_area (ply_label_plugin_control_t *label)
|
||||
{
|
||||
ply_window_erase_area (label->window,
|
||||
label->area.x, label->area.y,
|
||||
label->area.width, label->area.height);
|
||||
}
|
||||
|
||||
void
|
||||
draw_control (ply_label_plugin_control_t *label)
|
||||
size_control (ply_label_plugin_control_t *label)
|
||||
{
|
||||
cairo_t *cairo_context;
|
||||
PangoLayout *pango_layout;
|
||||
PangoFontDescription *description;
|
||||
int text_width;
|
||||
int text_height;
|
||||
|
||||
if (label->is_hidden)
|
||||
return;
|
||||
|
||||
ply_frame_buffer_pause_updates (label->frame_buffer);
|
||||
erase_label_area (label);
|
||||
cairo_move_to (label->cairo_context,
|
||||
cairo_context = get_cairo_context_for_sizing (label);
|
||||
|
||||
pango_layout = pango_cairo_create_layout (cairo_context);
|
||||
|
||||
description = pango_font_description_from_string ("Sans 12");
|
||||
pango_layout_set_font_description (pango_layout, description);
|
||||
pango_font_description_free (description);
|
||||
|
||||
pango_layout_set_text (pango_layout, label->text, -1);
|
||||
pango_cairo_update_layout (cairo_context, pango_layout);
|
||||
pango_layout_get_size (pango_layout, &text_width, &text_height);
|
||||
label->area.width = (long) ((double) text_width / PANGO_SCALE) + 1;
|
||||
label->area.height = (long) ((double) text_height / PANGO_SCALE) + 1;
|
||||
|
||||
g_object_unref (pango_layout);
|
||||
cairo_destroy (cairo_context);
|
||||
}
|
||||
|
||||
void
|
||||
draw_control (ply_label_plugin_control_t *label,
|
||||
ply_pixel_buffer_t *pixel_buffer,
|
||||
long x,
|
||||
long y,
|
||||
unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
cairo_t *cairo_context;
|
||||
PangoLayout *pango_layout;
|
||||
PangoFontDescription *description;
|
||||
int text_width;
|
||||
int text_height;
|
||||
|
||||
if (label->is_hidden)
|
||||
return;
|
||||
|
||||
cairo_context = get_cairo_context_for_pixel_buffer (label, pixel_buffer);
|
||||
|
||||
pango_layout = pango_cairo_create_layout (cairo_context);
|
||||
|
||||
description = pango_font_description_from_string ("Sans 12");
|
||||
pango_layout_set_font_description (pango_layout, description);
|
||||
pango_font_description_free (description);
|
||||
|
||||
pango_layout_set_text (pango_layout, label->text, -1);
|
||||
pango_cairo_update_layout (cairo_context, pango_layout);
|
||||
pango_layout_get_size (pango_layout, &text_width, &text_height);
|
||||
label->area.width = (long) ((double) text_width / PANGO_SCALE) + 1;
|
||||
label->area.height = (long) ((double) text_height / PANGO_SCALE) + 1;
|
||||
|
||||
cairo_rectangle (cairo_context, x, y, width, height);
|
||||
cairo_clip (cairo_context);
|
||||
cairo_move_to (cairo_context,
|
||||
label->area.x + 1,
|
||||
label->area.y + 1);
|
||||
cairo_set_source_rgba (label->cairo_context, 0.0, 0.0, 0.0, 0.7);
|
||||
pango_cairo_show_layout (label->cairo_context,
|
||||
label->pango_layout);
|
||||
cairo_move_to (label->cairo_context,
|
||||
cairo_set_source_rgba (cairo_context, 0.0, 0.0, 0.0, 0.7);
|
||||
pango_cairo_show_layout (cairo_context,
|
||||
pango_layout);
|
||||
cairo_move_to (cairo_context,
|
||||
label->area.x,
|
||||
label->area.y);
|
||||
cairo_set_source_rgb (label->cairo_context, 1.0, 1.0, 1.0);
|
||||
pango_cairo_show_layout (label->cairo_context,
|
||||
label->pango_layout);
|
||||
cairo_surface_flush (label->cairo_surface);
|
||||
ply_frame_buffer_unpause_updates (label->frame_buffer);
|
||||
cairo_set_source_rgb (cairo_context, 1.0, 1.0, 1.0);
|
||||
pango_cairo_show_layout (cairo_context,
|
||||
pango_layout);
|
||||
|
||||
g_object_unref (pango_layout);
|
||||
cairo_destroy (cairo_context);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -151,56 +218,21 @@ set_text_for_control (ply_label_plugin_control_t *label,
|
|||
free (label->text);
|
||||
label->text = strdup (text);
|
||||
}
|
||||
|
||||
if (label->pango_layout != NULL)
|
||||
{
|
||||
pango_layout_set_text (label->pango_layout, text, -1);
|
||||
pango_cairo_update_layout (label->cairo_context, label->pango_layout);
|
||||
|
||||
label->area.width = get_width_of_control (label);
|
||||
label->area.height = get_height_of_control (label);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
show_control (ply_label_plugin_control_t *label,
|
||||
ply_window_t *window,
|
||||
ply_pixel_display_t *display,
|
||||
long x,
|
||||
long y)
|
||||
{
|
||||
PangoFontDescription *description;
|
||||
ply_frame_buffer_area_t size;
|
||||
unsigned char *data;
|
||||
|
||||
label->window = window;
|
||||
label->frame_buffer = ply_window_get_frame_buffer (window);
|
||||
data = (unsigned char *) ply_frame_buffer_get_bytes (label->frame_buffer);
|
||||
|
||||
label->display = display;
|
||||
label->area.x = x;
|
||||
label->area.y = y;
|
||||
|
||||
ply_frame_buffer_get_size (label->frame_buffer, &size);
|
||||
|
||||
label->cairo_surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
size.width,
|
||||
size.height,
|
||||
size.width * 4);
|
||||
|
||||
label->cairo_context = cairo_create (label->cairo_surface);
|
||||
label->pango_layout = pango_cairo_create_layout (label->cairo_context);
|
||||
|
||||
if (label->text != NULL)
|
||||
set_text_for_control (label, label->text);
|
||||
|
||||
description = pango_font_description_from_string ("Sans 12");
|
||||
pango_layout_set_font_description (label->pango_layout, description);
|
||||
pango_font_description_free (description);
|
||||
|
||||
label->is_hidden = false;
|
||||
|
||||
draw_control (label);
|
||||
size_control (label);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -208,22 +240,13 @@ show_control (ply_label_plugin_control_t *label,
|
|||
void
|
||||
hide_control (ply_label_plugin_control_t *label)
|
||||
{
|
||||
erase_label_area (label);
|
||||
|
||||
g_object_unref (label->pango_layout);
|
||||
label->pango_layout = NULL;
|
||||
|
||||
cairo_destroy (label->cairo_context);
|
||||
label->cairo_context = NULL;
|
||||
|
||||
cairo_surface_destroy (label->cairo_surface);
|
||||
label->cairo_surface = NULL;
|
||||
|
||||
label->frame_buffer = NULL;
|
||||
label->window = NULL;
|
||||
label->loop = NULL;
|
||||
|
||||
label->is_hidden = true;
|
||||
ply_pixel_display_draw_area (label->display,
|
||||
label->area.x, label->area.y,
|
||||
label->area.width, label->area.height);
|
||||
|
||||
label->display = NULL;
|
||||
label->loop = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
2
src/plugins/renderers/Makefile.am
Normal file
2
src/plugins/renderers/Makefile.am
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SUBDIRS = frame-buffer drm
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
27
src/plugins/renderers/drm/Makefile.am
Normal file
27
src/plugins/renderers/drm/Makefile.am
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
INCLUDES = -I$(top_srcdir) \
|
||||
-I$(srcdir)/../../../libply \
|
||||
-I$(srcdir)/../../../libplybootsplash \
|
||||
-I$(srcdir)/../../.. \
|
||||
-I$(srcdir)/../.. \
|
||||
-I$(srcdir)/.. \
|
||||
-I$(srcdir)
|
||||
|
||||
plugindir = $(libdir)/plymouth/renderers
|
||||
plugin_LTLIBRARIES = drm.la
|
||||
|
||||
drm_la_CFLAGS = $(PLYMOUTH_CFLAGS) $(DRM_CFLAGS)
|
||||
|
||||
drm_la_LDFLAGS = -module -avoid-version -export-dynamic
|
||||
drm_la_LIBADD = $(PLYMOUTH_LIBS) $(DRM_LIBS) \
|
||||
../../../libply/libply.la \
|
||||
../../../libplybootsplash/libplybootsplash.la
|
||||
drm_la_SOURCES = $(srcdir)/plugin.c \
|
||||
$(srcdir)/ply-renderer-driver.h \
|
||||
$(srcdir)/ply-renderer-i915-driver.h \
|
||||
$(srcdir)/ply-renderer-i915-driver.c \
|
||||
$(srcdir)/ply-renderer-radeon-driver.h \
|
||||
$(srcdir)/ply-renderer-radeon-driver.c \
|
||||
$(srcdir)/ply-renderer-nouveau-driver.h \
|
||||
$(srcdir)/ply-renderer-nouveau-driver.c
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
1075
src/plugins/renderers/drm/plugin.c
Normal file
1075
src/plugins/renderers/drm/plugin.c
Normal file
File diff suppressed because it is too large
Load diff
67
src/plugins/renderers/drm/ply-renderer-driver.h
Normal file
67
src/plugins/renderers/drm/ply-renderer-driver.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/* ply-renderer-driver.h
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_RENDERER_DRIVER_H
|
||||
#define PLY_RENDERER_DRIVER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ply-list.h"
|
||||
#include "ply-rectangle.h"
|
||||
#include "ply-utils.h"
|
||||
|
||||
typedef struct _ply_renderer_driver ply_renderer_driver_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_renderer_driver_t * (* create_driver) (int device_fd);
|
||||
|
||||
void (* destroy_driver) (ply_renderer_driver_t *driver);
|
||||
|
||||
uint32_t (* create_buffer) (ply_renderer_driver_t *driver,
|
||||
unsigned long width,
|
||||
unsigned long height,
|
||||
unsigned long *row_stride);
|
||||
bool (* fetch_buffer) (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id,
|
||||
unsigned long *width,
|
||||
unsigned long *height,
|
||||
unsigned long *row_stride);
|
||||
|
||||
bool (* map_buffer) (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id);
|
||||
|
||||
void (* unmap_buffer) (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id);
|
||||
|
||||
char * (* begin_flush) (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id);
|
||||
void (* end_flush) (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id);
|
||||
|
||||
void (* destroy_buffer) (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id);
|
||||
|
||||
} ply_renderer_driver_interface_t;
|
||||
|
||||
#endif /* PLY_RENDERER_DRIVER_H */
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
360
src/plugins/renderers/drm/ply-renderer-i915-driver.c
Normal file
360
src/plugins/renderers/drm/ply-renderer-i915-driver.c
Normal file
|
|
@ -0,0 +1,360 @@
|
|||
/* ply-renderer-i915-driver.c - interface to i915 drm driver
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "ply-renderer-i915-driver.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <values.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/i915_drm.h>
|
||||
#include <intel_bufmgr.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include "ply-hashtable.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-renderer-driver.h"
|
||||
|
||||
typedef struct _ply_renderer_buffer ply_renderer_buffer_t;
|
||||
|
||||
struct _ply_renderer_buffer
|
||||
{
|
||||
drm_intel_bo *object;
|
||||
uint32_t id;
|
||||
unsigned long width;
|
||||
unsigned long height;
|
||||
unsigned long row_stride;
|
||||
};
|
||||
|
||||
struct _ply_renderer_driver
|
||||
{
|
||||
int device_fd;
|
||||
drm_intel_bufmgr *manager;
|
||||
|
||||
ply_hashtable_t *buffers;
|
||||
};
|
||||
|
||||
static ply_renderer_driver_t *
|
||||
create_driver (int device_fd)
|
||||
{
|
||||
ply_renderer_driver_t *driver;
|
||||
int page_size;
|
||||
|
||||
driver = calloc (1, sizeof (ply_renderer_driver_t));
|
||||
driver->device_fd = device_fd;
|
||||
|
||||
page_size = (int) sysconf (_SC_PAGE_SIZE);
|
||||
|
||||
driver->manager = drm_intel_bufmgr_gem_init (driver->device_fd, page_size);
|
||||
if (driver->manager == NULL)
|
||||
{
|
||||
free (driver);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
driver->buffers = ply_hashtable_new (ply_hashtable_direct_hash,
|
||||
ply_hashtable_direct_compare);
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_driver (ply_renderer_driver_t *driver)
|
||||
{
|
||||
ply_hashtable_free (driver->buffers);
|
||||
|
||||
drm_intel_bufmgr_destroy (driver->manager);
|
||||
free (driver);
|
||||
}
|
||||
|
||||
static ply_renderer_buffer_t *
|
||||
ply_renderer_buffer_new (ply_renderer_driver_t *driver,
|
||||
drm_intel_bo *buffer_object,
|
||||
uint32_t id,
|
||||
unsigned long width,
|
||||
unsigned long height,
|
||||
unsigned long row_stride)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = calloc (1, sizeof (ply_renderer_buffer_t));
|
||||
buffer->object = buffer_object;
|
||||
buffer->id = id;
|
||||
buffer->width = width;
|
||||
buffer->height = height;
|
||||
buffer->row_stride = row_stride;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static drm_intel_bo *
|
||||
create_intel_bo_from_handle (ply_renderer_driver_t *driver,
|
||||
uint32_t handle)
|
||||
{
|
||||
struct drm_gem_flink flink_request;
|
||||
char *name;
|
||||
drm_intel_bo *buffer_object;
|
||||
|
||||
/* FIXME: This can't be the right way to do this.
|
||||
*
|
||||
* 1) It requires skirting around the API and using ioctls
|
||||
* 2) It requires taking a local handle, turning it into a
|
||||
* a global handle ("name"), just so we can use an api that
|
||||
* will open the global name and grab the local handle from it.
|
||||
*/
|
||||
|
||||
memset (&flink_request, 0, sizeof (struct drm_gem_flink));
|
||||
flink_request.handle = handle;
|
||||
|
||||
if (ioctl (driver->device_fd, DRM_IOCTL_GEM_FLINK, &flink_request) < 0)
|
||||
return NULL;
|
||||
|
||||
asprintf (&name, "buffer %u", handle);
|
||||
|
||||
buffer_object = drm_intel_bo_gem_create_from_name (driver->manager,
|
||||
name, flink_request.name);
|
||||
free (name);
|
||||
|
||||
return buffer_object;
|
||||
}
|
||||
|
||||
static ply_renderer_buffer_t *
|
||||
ply_renderer_buffer_new_from_id (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
drmModeFB *fb;
|
||||
drm_intel_bo *buffer_object;
|
||||
|
||||
fb = drmModeGetFB (driver->device_fd, buffer_id);
|
||||
|
||||
if (fb == NULL)
|
||||
return NULL;
|
||||
|
||||
buffer_object = create_intel_bo_from_handle (driver, fb->handle);
|
||||
|
||||
if (buffer_object == NULL)
|
||||
{
|
||||
drmModeFreeFB (fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = ply_renderer_buffer_new (driver, buffer_object, buffer_id,
|
||||
fb->width, fb->height, fb->pitch);
|
||||
drmModeFreeFB (fb);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static ply_renderer_buffer_t *
|
||||
get_buffer_from_id (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
static ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = ply_hashtable_lookup (driver->buffers,
|
||||
(void *) (uintptr_t) buffer_id);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static bool
|
||||
fetch_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id,
|
||||
unsigned long *width,
|
||||
unsigned long *height,
|
||||
unsigned long *row_stride)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
buffer = ply_renderer_buffer_new_from_id (driver, buffer_id);
|
||||
|
||||
if (buffer == NULL)
|
||||
return false;
|
||||
|
||||
ply_hashtable_insert (driver->buffers,
|
||||
(void *) (uintptr_t) buffer_id,
|
||||
buffer);
|
||||
}
|
||||
|
||||
if (width != NULL)
|
||||
*width = buffer->width;
|
||||
|
||||
if (height != NULL)
|
||||
*height = buffer->height;
|
||||
|
||||
if (row_stride != NULL)
|
||||
*row_stride = buffer->row_stride;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
create_buffer (ply_renderer_driver_t *driver,
|
||||
unsigned long width,
|
||||
unsigned long height,
|
||||
unsigned long *row_stride)
|
||||
{
|
||||
drm_intel_bo *buffer_object;
|
||||
ply_renderer_buffer_t *buffer;
|
||||
uint32_t buffer_id;
|
||||
|
||||
*row_stride = ply_round_to_multiple (width * 4, 256);
|
||||
|
||||
buffer_object = drm_intel_bo_alloc (driver->manager,
|
||||
"frame buffer",
|
||||
height * *row_stride, 0);
|
||||
|
||||
if (buffer_object == NULL)
|
||||
{
|
||||
ply_trace ("Could not allocate GEM object for frame buffer: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (drmModeAddFB (driver->device_fd, width, height,
|
||||
24, 32, *row_stride, buffer_object->handle,
|
||||
&buffer_id) != 0)
|
||||
{
|
||||
ply_trace ("Could not set up GEM object as frame buffer: %m");
|
||||
drm_intel_bo_unreference (buffer_object);
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer = ply_renderer_buffer_new (driver,
|
||||
buffer_object, buffer_id,
|
||||
width, height, *row_stride);
|
||||
ply_hashtable_insert (driver->buffers,
|
||||
(void *) (uintptr_t) buffer_id,
|
||||
buffer);
|
||||
|
||||
return buffer_id;
|
||||
}
|
||||
|
||||
static bool
|
||||
map_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
drm_intel_gem_bo_map_gtt (buffer->object);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
drm_intel_gem_bo_unmap_gtt (buffer->object);
|
||||
}
|
||||
|
||||
static char *
|
||||
begin_flush (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
return buffer->object->virtual;
|
||||
}
|
||||
|
||||
static void
|
||||
end_flush (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
drmModeRmFB (driver->device_fd, buffer->id);
|
||||
|
||||
drm_intel_bo_unreference (buffer->object);
|
||||
|
||||
ply_hashtable_remove (driver->buffers,
|
||||
(void *) (uintptr_t) buffer_id);
|
||||
free (buffer);
|
||||
}
|
||||
|
||||
ply_renderer_driver_interface_t *
|
||||
ply_renderer_i915_driver_get_interface (void)
|
||||
{
|
||||
static ply_renderer_driver_interface_t driver_interface =
|
||||
{
|
||||
.create_driver = create_driver,
|
||||
.destroy_driver = destroy_driver,
|
||||
.create_buffer = create_buffer,
|
||||
.fetch_buffer = fetch_buffer,
|
||||
.map_buffer = map_buffer,
|
||||
.unmap_buffer = unmap_buffer,
|
||||
.begin_flush = begin_flush,
|
||||
.end_flush = end_flush,
|
||||
.destroy_buffer = destroy_buffer,
|
||||
};
|
||||
|
||||
return &driver_interface;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
32
src/plugins/renderers/drm/ply-renderer-i915-driver.h
Normal file
32
src/plugins/renderers/drm/ply-renderer-i915-driver.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* ply-renderer-i915-driver.h
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_RENDERER_I915_DRIVER_H
|
||||
#define PLY_RENDERER_I915_DRIVER_H
|
||||
|
||||
#include "ply-renderer-driver.h"
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_renderer_driver_interface_t *ply_renderer_i915_driver_get_interface (void);
|
||||
#endif
|
||||
|
||||
#endif /* PLY_RENDERER_I915_DRIVER_H */
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
332
src/plugins/renderers/drm/ply-renderer-nouveau-driver.c
Normal file
332
src/plugins/renderers/drm/ply-renderer-nouveau-driver.c
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
/* ply-renderer-nouveau-driver.c - interface to nouveau drm driver
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "ply-renderer-nouveau-driver.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <values.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/nouveau_drm.h>
|
||||
#include <drm/nouveau_drmif.h>
|
||||
#include <nouveau/nouveau_bo.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include "ply-hashtable.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-renderer-driver.h"
|
||||
|
||||
typedef struct _ply_renderer_buffer ply_renderer_buffer_t;
|
||||
|
||||
struct _ply_renderer_buffer
|
||||
{
|
||||
struct nouveau_bo *object;
|
||||
uint32_t id;
|
||||
unsigned long width;
|
||||
unsigned long height;
|
||||
unsigned long row_stride;
|
||||
};
|
||||
|
||||
struct _ply_renderer_driver
|
||||
{
|
||||
int device_fd;
|
||||
struct nouveau_device *device;
|
||||
|
||||
ply_hashtable_t *buffers;
|
||||
};
|
||||
|
||||
static ply_renderer_driver_t *
|
||||
create_driver (int device_fd)
|
||||
{
|
||||
ply_renderer_driver_t *driver;
|
||||
|
||||
driver = calloc (1, sizeof (ply_renderer_driver_t));
|
||||
driver->device_fd = device_fd;
|
||||
|
||||
if (nouveau_device_open_existing (&driver->device, true,
|
||||
driver->device_fd, 0) < 0)
|
||||
{
|
||||
free (driver);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
driver->buffers = ply_hashtable_new (ply_hashtable_direct_hash,
|
||||
ply_hashtable_direct_compare);
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_driver (ply_renderer_driver_t *driver)
|
||||
{
|
||||
ply_hashtable_free (driver->buffers);
|
||||
|
||||
nouveau_device_close (&driver->device);
|
||||
free (driver);
|
||||
}
|
||||
|
||||
static ply_renderer_buffer_t *
|
||||
ply_renderer_buffer_new (ply_renderer_driver_t *driver,
|
||||
struct nouveau_bo *buffer_object,
|
||||
uint32_t id,
|
||||
unsigned long width,
|
||||
unsigned long height,
|
||||
unsigned long row_stride)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = calloc (1, sizeof (ply_renderer_buffer_t));
|
||||
buffer->object = buffer_object;
|
||||
buffer->id = id;
|
||||
buffer->width = width;
|
||||
buffer->height = height;
|
||||
buffer->row_stride = row_stride;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static ply_renderer_buffer_t *
|
||||
ply_renderer_buffer_new_from_id (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
drmModeFB *fb;
|
||||
struct nouveau_bo *buffer_object;
|
||||
|
||||
fb = drmModeGetFB (driver->device_fd, buffer_id);
|
||||
|
||||
if (fb == NULL)
|
||||
return NULL;
|
||||
|
||||
if (nouveau_bo_wrap (driver->device,
|
||||
fb->handle, &buffer_object) < 0)
|
||||
{
|
||||
drmModeFreeFB (fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = ply_renderer_buffer_new (driver, buffer_object, buffer_id,
|
||||
fb->width, fb->height, fb->pitch);
|
||||
drmModeFreeFB (fb);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static ply_renderer_buffer_t *
|
||||
get_buffer_from_id (ply_renderer_driver_t *driver,
|
||||
uint32_t id)
|
||||
{
|
||||
static ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = ply_hashtable_lookup (driver->buffers, (void *) (uintptr_t) id);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static bool
|
||||
fetch_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id,
|
||||
unsigned long *width,
|
||||
unsigned long *height,
|
||||
unsigned long *row_stride)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
buffer = ply_renderer_buffer_new_from_id (driver, buffer_id);
|
||||
|
||||
if (buffer == NULL)
|
||||
return false;
|
||||
|
||||
ply_hashtable_insert (driver->buffers,
|
||||
(void *) (uintptr_t) buffer_id,
|
||||
buffer);
|
||||
}
|
||||
|
||||
if (width != NULL)
|
||||
*width = buffer->width;
|
||||
|
||||
if (height != NULL)
|
||||
*height = buffer->height;
|
||||
|
||||
if (row_stride != NULL)
|
||||
*row_stride = buffer->row_stride;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
create_buffer (ply_renderer_driver_t *driver,
|
||||
unsigned long width,
|
||||
unsigned long height,
|
||||
unsigned long *row_stride)
|
||||
{
|
||||
struct nouveau_bo *buffer_object;
|
||||
ply_renderer_buffer_t *buffer;
|
||||
uint32_t buffer_id;
|
||||
|
||||
*row_stride = ply_round_to_multiple (width * 4, 256);
|
||||
|
||||
buffer_object = NULL;
|
||||
if (nouveau_bo_new (driver->device,
|
||||
NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 0,
|
||||
height * *row_stride, &buffer_object) < 0)
|
||||
{
|
||||
ply_trace ("Could not allocate GEM object for frame buffer: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The map here forces the buffer object to be instantiated
|
||||
* immediately (it's normally instantiated lazily when needed
|
||||
* by other nouveau_bo api)
|
||||
*/
|
||||
nouveau_bo_map (buffer_object, NOUVEAU_BO_WR);
|
||||
if (drmModeAddFB (driver->device_fd, width, height,
|
||||
24, 32, *row_stride, buffer_object->handle,
|
||||
&buffer_id) != 0)
|
||||
{
|
||||
nouveau_bo_unmap (buffer_object);
|
||||
ply_trace ("Could not set up GEM object as frame buffer: %m");
|
||||
nouveau_bo_ref (NULL, &buffer_object);
|
||||
return 0;
|
||||
}
|
||||
nouveau_bo_unmap (buffer_object);
|
||||
|
||||
buffer = ply_renderer_buffer_new (driver,
|
||||
buffer_object, buffer_id,
|
||||
width, height, *row_stride);
|
||||
ply_hashtable_insert (driver->buffers,
|
||||
(void *) (uintptr_t) buffer_id,
|
||||
buffer);
|
||||
|
||||
return buffer_id;
|
||||
}
|
||||
|
||||
static bool
|
||||
map_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
return nouveau_bo_map (buffer->object, NOUVEAU_BO_WR) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
nouveau_bo_unmap (buffer->object);
|
||||
}
|
||||
|
||||
static char *
|
||||
begin_flush (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
return buffer->object->map;
|
||||
}
|
||||
|
||||
static void
|
||||
end_flush (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
drmModeRmFB (driver->device_fd, buffer->id);
|
||||
|
||||
nouveau_bo_ref (NULL, &buffer->object);
|
||||
|
||||
ply_hashtable_remove (driver->buffers,
|
||||
(void *) (uintptr_t) buffer_id);
|
||||
free (buffer);
|
||||
}
|
||||
|
||||
ply_renderer_driver_interface_t *
|
||||
ply_renderer_nouveau_driver_get_interface (void)
|
||||
{
|
||||
static ply_renderer_driver_interface_t driver_interface =
|
||||
{
|
||||
.create_driver = create_driver,
|
||||
.destroy_driver = destroy_driver,
|
||||
.create_buffer = create_buffer,
|
||||
.fetch_buffer = fetch_buffer,
|
||||
.map_buffer = map_buffer,
|
||||
.unmap_buffer = unmap_buffer,
|
||||
.begin_flush = begin_flush,
|
||||
.end_flush = end_flush,
|
||||
.destroy_buffer = destroy_buffer,
|
||||
};
|
||||
|
||||
return &driver_interface;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
32
src/plugins/renderers/drm/ply-renderer-nouveau-driver.h
Normal file
32
src/plugins/renderers/drm/ply-renderer-nouveau-driver.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* ply-renderer-nouveau-driver.h
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_RENDERER_NOUVEAU_DRIVER_H
|
||||
#define PLY_RENDERER_NOUVEAU_DRIVER_H
|
||||
|
||||
#include "ply-renderer-driver.h"
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_renderer_driver_interface_t *ply_renderer_nouveau_driver_get_interface (void);
|
||||
#endif
|
||||
|
||||
#endif /* PLY_RENDERER_NOUVEAU_DRIVER_H */
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
354
src/plugins/renderers/drm/ply-renderer-radeon-driver.c
Normal file
354
src/plugins/renderers/drm/ply-renderer-radeon-driver.c
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
/* ply-renderer-radeon-driver.c - interface to radeon drm driver
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "ply-renderer-radeon-driver.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <values.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/radeon_drm.h>
|
||||
#include <drm/radeon_bo.h>
|
||||
#include <drm/radeon_bo_gem.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include "ply-hashtable.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-renderer-driver.h"
|
||||
|
||||
typedef struct _ply_renderer_buffer ply_renderer_buffer_t;
|
||||
|
||||
struct _ply_renderer_buffer
|
||||
{
|
||||
struct radeon_bo *object;
|
||||
uint32_t id;
|
||||
unsigned long width;
|
||||
unsigned long height;
|
||||
unsigned long row_stride;
|
||||
};
|
||||
|
||||
struct _ply_renderer_driver
|
||||
{
|
||||
int device_fd;
|
||||
struct radeon_bo_manager *manager;
|
||||
|
||||
ply_hashtable_t *buffers;
|
||||
};
|
||||
|
||||
static ply_renderer_driver_t *
|
||||
create_driver (int device_fd)
|
||||
{
|
||||
ply_renderer_driver_t *driver;
|
||||
|
||||
driver = calloc (1, sizeof (ply_renderer_driver_t));
|
||||
driver->device_fd = device_fd;
|
||||
|
||||
driver->manager = radeon_bo_manager_gem_ctor (driver->device_fd);
|
||||
if (driver->manager == NULL)
|
||||
{
|
||||
free (driver);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
driver->buffers = ply_hashtable_new (ply_hashtable_direct_hash,
|
||||
ply_hashtable_direct_compare);
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_driver (ply_renderer_driver_t *driver)
|
||||
{
|
||||
ply_hashtable_free (driver->buffers);
|
||||
|
||||
radeon_bo_manager_gem_dtor (driver->manager);
|
||||
free (driver);
|
||||
}
|
||||
|
||||
static ply_renderer_buffer_t *
|
||||
ply_renderer_buffer_new (ply_renderer_driver_t *driver,
|
||||
struct radeon_bo *buffer_object,
|
||||
uint32_t id,
|
||||
unsigned long width,
|
||||
unsigned long height,
|
||||
unsigned long row_stride)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = calloc (1, sizeof (ply_renderer_buffer_t));
|
||||
buffer->object = buffer_object;
|
||||
buffer->id = id;
|
||||
buffer->width = width;
|
||||
buffer->height = height;
|
||||
buffer->row_stride = row_stride;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static ply_renderer_buffer_t *
|
||||
get_buffer_from_id (ply_renderer_driver_t *driver,
|
||||
uint32_t id)
|
||||
{
|
||||
static ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = ply_hashtable_lookup (driver->buffers, (void *) (uintptr_t) id);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static struct radeon_bo *
|
||||
create_radeon_bo_from_handle (ply_renderer_driver_t *driver,
|
||||
uint32_t handle)
|
||||
{
|
||||
struct drm_gem_flink flink_request;
|
||||
struct radeon_bo *buffer_object;
|
||||
|
||||
/* FIXME: This can't be the right way to do this.
|
||||
*
|
||||
* 1) It requires skirting around the API and using ioctls
|
||||
* 2) It requires taking a local handle, turning it into a
|
||||
* a global handle ("name"), just so we can use an api that
|
||||
* will open the global name and grab the local handle from it.
|
||||
*/
|
||||
|
||||
memset (&flink_request, 0, sizeof (struct drm_gem_flink));
|
||||
flink_request.handle = handle;
|
||||
|
||||
if (ioctl (driver->device_fd, DRM_IOCTL_GEM_FLINK, &flink_request) < 0)
|
||||
return NULL;
|
||||
|
||||
buffer_object = radeon_bo_open (driver->manager, flink_request.name,
|
||||
0, 0, RADEON_GEM_DOMAIN_GTT, 0);
|
||||
|
||||
return buffer_object;
|
||||
}
|
||||
|
||||
static ply_renderer_buffer_t *
|
||||
ply_renderer_buffer_new_from_id (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
drmModeFB *fb;
|
||||
struct radeon_bo *buffer_object;
|
||||
|
||||
fb = drmModeGetFB (driver->device_fd, buffer_id);
|
||||
|
||||
if (fb == NULL)
|
||||
return NULL;
|
||||
|
||||
buffer_object = create_radeon_bo_from_handle (driver, fb->handle);
|
||||
|
||||
if (buffer_object == NULL)
|
||||
{
|
||||
drmModeFreeFB (fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = ply_renderer_buffer_new (driver, buffer_object, buffer_id,
|
||||
fb->width, fb->height, fb->pitch);
|
||||
drmModeFreeFB (fb);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
fetch_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id,
|
||||
unsigned long *width,
|
||||
unsigned long *height,
|
||||
unsigned long *row_stride)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
buffer = ply_renderer_buffer_new_from_id (driver, buffer_id);
|
||||
|
||||
if (buffer == NULL)
|
||||
return false;
|
||||
|
||||
ply_hashtable_insert (driver->buffers,
|
||||
(void *) (uintptr_t) buffer_id,
|
||||
buffer);
|
||||
}
|
||||
|
||||
if (width != NULL)
|
||||
*width = buffer->width;
|
||||
|
||||
if (height != NULL)
|
||||
*height = buffer->height;
|
||||
|
||||
if (row_stride != NULL)
|
||||
*row_stride = buffer->row_stride;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
create_buffer (ply_renderer_driver_t *driver,
|
||||
unsigned long width,
|
||||
unsigned long height,
|
||||
unsigned long *row_stride)
|
||||
{
|
||||
struct radeon_bo *buffer_object;
|
||||
ply_renderer_buffer_t *buffer;
|
||||
uint32_t buffer_id;
|
||||
|
||||
*row_stride = ply_round_to_multiple (width * 4, 256);
|
||||
|
||||
buffer_object = radeon_bo_open (driver->manager, 0,
|
||||
height * *row_stride,
|
||||
0, RADEON_GEM_DOMAIN_GTT, 0);
|
||||
|
||||
if (buffer_object == NULL)
|
||||
{
|
||||
ply_trace ("Could not allocate GEM object for frame buffer: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (drmModeAddFB (driver->device_fd, width, height,
|
||||
24, 32, *row_stride, buffer_object->handle,
|
||||
&buffer_id) != 0)
|
||||
{
|
||||
ply_trace ("Could not set up GEM object as frame buffer: %m");
|
||||
radeon_bo_unref (buffer_object);
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer = ply_renderer_buffer_new (driver,
|
||||
buffer_object, buffer_id,
|
||||
width, height, *row_stride);
|
||||
ply_hashtable_insert (driver->buffers,
|
||||
(void *) (uintptr_t) buffer_id,
|
||||
buffer);
|
||||
|
||||
return buffer_id;
|
||||
}
|
||||
|
||||
static bool
|
||||
map_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
return radeon_bo_map (buffer->object, true) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
radeon_bo_unmap (buffer->object);
|
||||
}
|
||||
|
||||
static char *
|
||||
begin_flush (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
return buffer->object->ptr;
|
||||
}
|
||||
|
||||
static void
|
||||
end_flush (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_buffer (ply_renderer_driver_t *driver,
|
||||
uint32_t buffer_id)
|
||||
{
|
||||
ply_renderer_buffer_t *buffer;
|
||||
|
||||
buffer = get_buffer_from_id (driver, buffer_id);
|
||||
|
||||
assert (buffer != NULL);
|
||||
|
||||
drmModeRmFB (driver->device_fd, buffer->id);
|
||||
|
||||
radeon_bo_unref (buffer->object);
|
||||
|
||||
ply_hashtable_remove (driver->buffers,
|
||||
(void *) (uintptr_t) buffer_id);
|
||||
free (buffer);
|
||||
}
|
||||
|
||||
ply_renderer_driver_interface_t *
|
||||
ply_renderer_radeon_driver_get_interface (void)
|
||||
{
|
||||
static ply_renderer_driver_interface_t driver_interface =
|
||||
{
|
||||
.create_driver = create_driver,
|
||||
.destroy_driver = destroy_driver,
|
||||
.create_buffer = create_buffer,
|
||||
.fetch_buffer = fetch_buffer,
|
||||
.map_buffer = map_buffer,
|
||||
.unmap_buffer = unmap_buffer,
|
||||
.begin_flush = begin_flush,
|
||||
.end_flush = end_flush,
|
||||
.destroy_buffer = destroy_buffer,
|
||||
};
|
||||
|
||||
return &driver_interface;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
32
src/plugins/renderers/drm/ply-renderer-radeon-driver.h
Normal file
32
src/plugins/renderers/drm/ply-renderer-radeon-driver.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* ply-renderer-radeon-driver.h
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written By: Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#ifndef PLY_RENDERER_RADEON_DRIVER_H
|
||||
#define PLY_RENDERER_RADEON_DRIVER_H
|
||||
|
||||
#include "ply-renderer-driver.h"
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_renderer_driver_interface_t *ply_renderer_radeon_driver_get_interface (void);
|
||||
#endif
|
||||
|
||||
#endif /* PLY_RENDERER_RADEON_DRIVER_H */
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
20
src/plugins/renderers/frame-buffer/Makefile.am
Normal file
20
src/plugins/renderers/frame-buffer/Makefile.am
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
INCLUDES = -I$(top_srcdir) \
|
||||
-I$(srcdir)/../../../libply \
|
||||
-I$(srcdir)/../../../libplybootsplash \
|
||||
-I$(srcdir)/../../.. \
|
||||
-I$(srcdir)/../.. \
|
||||
-I$(srcdir)/.. \
|
||||
-I$(srcdir)
|
||||
|
||||
plugindir = $(libdir)/plymouth/renderers
|
||||
plugin_LTLIBRARIES = frame-buffer.la
|
||||
|
||||
frame_buffer_la_CFLAGS = $(PLYMOUTH_CFLAGS)
|
||||
|
||||
frame_buffer_la_LDFLAGS = -module -avoid-version -export-dynamic
|
||||
frame_buffer_la_LIBADD = $(PLYMOUTH_LIBS) \
|
||||
../../../libply/libply.la \
|
||||
../../../libplybootsplash/libplybootsplash.la
|
||||
frame_buffer_la_SOURCES = $(srcdir)/plugin.c
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
667
src/plugins/renderers/frame-buffer/plugin.c
Normal file
667
src/plugins/renderers/frame-buffer/plugin.c
Normal file
|
|
@ -0,0 +1,667 @@
|
|||
/* plugin.c - frame-backend renderer plugin
|
||||
*
|
||||
* Copyright (C) 2006-2009 Red Hat, Inc.
|
||||
* 2008 Charlie Brej <cbrej@cs.man.ac.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Charlie Brej <cbrej@cs.man.ac.uk>
|
||||
* Kristian Høgsberg <krh@redhat.com>
|
||||
* Peter Jones <pjones@redhat.com>
|
||||
* Ray Strode <rstrode@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <values.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include "ply-buffer.h"
|
||||
#include "ply-event-loop.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-rectangle.h"
|
||||
#include "ply-region.h"
|
||||
#include "ply-terminal.h"
|
||||
|
||||
#include "ply-renderer.h"
|
||||
#include "ply-renderer-plugin.h"
|
||||
|
||||
#ifndef PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME
|
||||
#define PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME "/dev/fb"
|
||||
#endif
|
||||
|
||||
struct _ply_renderer_head
|
||||
{
|
||||
ply_pixel_buffer_t *pixel_buffer;
|
||||
ply_rectangle_t area;
|
||||
char *map_address;
|
||||
size_t size;
|
||||
|
||||
};
|
||||
|
||||
struct _ply_renderer_input_source
|
||||
{
|
||||
ply_fd_watch_t *terminal_input_watch;
|
||||
|
||||
ply_buffer_t *key_buffer;
|
||||
|
||||
ply_renderer_input_source_handler_t handler;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
struct _ply_renderer_backend
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
ply_console_t *console;
|
||||
ply_terminal_t *terminal;
|
||||
|
||||
char *device_name;
|
||||
int device_fd;
|
||||
|
||||
ply_renderer_input_source_t input_source;
|
||||
ply_renderer_head_t head;
|
||||
ply_list_t *heads;
|
||||
|
||||
uint32_t red_bit_position;
|
||||
uint32_t green_bit_position;
|
||||
uint32_t blue_bit_position;
|
||||
uint32_t alpha_bit_position;
|
||||
|
||||
uint32_t bits_for_red;
|
||||
uint32_t bits_for_green;
|
||||
uint32_t bits_for_blue;
|
||||
uint32_t bits_for_alpha;
|
||||
|
||||
int32_t dither_red;
|
||||
int32_t dither_green;
|
||||
int32_t dither_blue;
|
||||
|
||||
unsigned int bytes_per_pixel;
|
||||
unsigned int row_stride;
|
||||
|
||||
void (* flush_area) (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head,
|
||||
ply_rectangle_t *area_to_flush);
|
||||
};
|
||||
|
||||
ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void);
|
||||
static void ply_renderer_head_redraw (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head);
|
||||
|
||||
static inline uint_fast32_t
|
||||
argb32_pixel_value_to_device_pixel_value (ply_renderer_backend_t *backend,
|
||||
uint32_t pixel_value)
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
int orig_r, orig_g, orig_b, orig_a;
|
||||
uint8_t new_r, new_g, new_b;
|
||||
int i;
|
||||
|
||||
orig_a = pixel_value >> 24;
|
||||
a = orig_a >> (8 - backend->bits_for_alpha);
|
||||
|
||||
orig_r = ((pixel_value >> 16) & 0xff) - backend->dither_red;
|
||||
r = CLAMP (orig_r, 0, 255) >> (8 - backend->bits_for_red);
|
||||
|
||||
orig_g = ((pixel_value >> 8) & 0xff) - backend->dither_green;
|
||||
g = CLAMP (orig_g, 0, 255) >> (8 - backend->bits_for_green);
|
||||
|
||||
orig_b = (pixel_value & 0xff) - backend->dither_blue;
|
||||
b = CLAMP (orig_b, 0, 255) >> (8 - backend->bits_for_blue);
|
||||
|
||||
new_r = r << (8 - backend->bits_for_red);
|
||||
new_g = g << (8 - backend->bits_for_green);
|
||||
new_b = b << (8 - backend->bits_for_blue);
|
||||
|
||||
for (i = backend->bits_for_red; i < 8; i <<= 1)
|
||||
new_r |= new_r >> i;
|
||||
|
||||
for (i = backend->bits_for_green; i < 8; i <<= 1)
|
||||
new_g |= new_g >> i;
|
||||
|
||||
for (i = backend->bits_for_blue; i < 8; i <<= 1)
|
||||
new_b |= new_b >> i;
|
||||
|
||||
backend->dither_red = new_r - orig_r;
|
||||
backend->dither_green = new_g - orig_g;
|
||||
backend->dither_blue = new_b - orig_b;
|
||||
|
||||
return ((a << backend->alpha_bit_position)
|
||||
| (r << backend->red_bit_position)
|
||||
| (g << backend->green_bit_position)
|
||||
| (b << backend->blue_bit_position));
|
||||
}
|
||||
|
||||
static void
|
||||
flush_area_to_any_device (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head,
|
||||
ply_rectangle_t *area_to_flush)
|
||||
{
|
||||
unsigned long row, column;
|
||||
uint32_t *shadow_buffer;
|
||||
char *row_backend;
|
||||
size_t bytes_per_row;
|
||||
unsigned long x1, y1, x2, y2;
|
||||
|
||||
x1 = area_to_flush->x;
|
||||
y1 = area_to_flush->y;
|
||||
x2 = x1 + area_to_flush->width;
|
||||
y2 = y1 + area_to_flush->height;
|
||||
|
||||
bytes_per_row = area_to_flush->width * backend->bytes_per_pixel;
|
||||
row_backend = malloc (backend->row_stride);
|
||||
shadow_buffer = ply_pixel_buffer_get_argb32_data (backend->head.pixel_buffer);
|
||||
for (row = y1; row < y2; row++)
|
||||
{
|
||||
unsigned long offset;
|
||||
|
||||
for (column = x1; column < x2; column++)
|
||||
{
|
||||
uint32_t pixel_value;
|
||||
uint_fast32_t device_pixel_value;
|
||||
|
||||
pixel_value = shadow_buffer[row * head->area.width + column];
|
||||
|
||||
device_pixel_value = argb32_pixel_value_to_device_pixel_value (backend,
|
||||
pixel_value);
|
||||
|
||||
memcpy (row_backend + column * backend->bytes_per_pixel,
|
||||
&device_pixel_value, backend->bytes_per_pixel);
|
||||
}
|
||||
|
||||
offset = row * backend->row_stride + x1 * backend->bytes_per_pixel;
|
||||
memcpy (head->map_address + offset, row_backend + x1 * backend->bytes_per_pixel,
|
||||
area_to_flush->width * backend->bytes_per_pixel);
|
||||
}
|
||||
free (row_backend);
|
||||
}
|
||||
|
||||
static void
|
||||
flush_area_to_xrgb32_device (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head,
|
||||
ply_rectangle_t *area_to_flush)
|
||||
{
|
||||
unsigned long x1, y1, x2, y2, y;
|
||||
uint32_t *shadow_buffer;
|
||||
char *dst, *src;
|
||||
|
||||
x1 = area_to_flush->x;
|
||||
y1 = area_to_flush->y;
|
||||
x2 = x1 + area_to_flush->width;
|
||||
y2 = y1 + area_to_flush->height;
|
||||
|
||||
shadow_buffer = ply_pixel_buffer_get_argb32_data (backend->head.pixel_buffer);
|
||||
|
||||
dst = &head->map_address[y1 * backend->row_stride + x1 * backend->bytes_per_pixel];
|
||||
src = (char *) &shadow_buffer[y1 * head->area.width + x1];
|
||||
|
||||
if (area_to_flush->width == backend->row_stride)
|
||||
{
|
||||
memcpy (dst, src, area_to_flush->width * area_to_flush->height * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
for (y = y1; y < y2; y++)
|
||||
{
|
||||
memcpy (dst, src, area_to_flush->width * 4);
|
||||
dst += backend->row_stride;
|
||||
src += head->area.width * 4;
|
||||
}
|
||||
}
|
||||
|
||||
static ply_renderer_backend_t *
|
||||
create_backend (const char *device_name,
|
||||
ply_terminal_t *terminal,
|
||||
ply_console_t *console)
|
||||
{
|
||||
ply_renderer_backend_t *backend;
|
||||
|
||||
backend = calloc (1, sizeof (ply_renderer_backend_t));
|
||||
|
||||
if (device_name != NULL)
|
||||
backend->device_name = strdup (device_name);
|
||||
else if (getenv ("FRAMEBUFFER") != NULL)
|
||||
backend->device_name = strdup (getenv ("FRAMEBUFFER"));
|
||||
else
|
||||
backend->device_name =
|
||||
strdup (PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME);
|
||||
|
||||
backend->loop = ply_event_loop_get_default ();
|
||||
backend->heads = ply_list_new ();
|
||||
backend->input_source.key_buffer = ply_buffer_new ();
|
||||
backend->console = console;
|
||||
backend->terminal = terminal;
|
||||
|
||||
return backend;
|
||||
}
|
||||
|
||||
static void
|
||||
initialize_head (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head)
|
||||
{
|
||||
head->pixel_buffer = ply_pixel_buffer_new (head->area.width,
|
||||
head->area.height);
|
||||
ply_pixel_buffer_fill_with_color (backend->head.pixel_buffer, NULL,
|
||||
0.0, 0.0, 0.0, 1.0);
|
||||
ply_list_append_data (backend->heads, head);
|
||||
}
|
||||
|
||||
static void
|
||||
uninitialize_head (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head)
|
||||
{
|
||||
if (head->pixel_buffer != NULL)
|
||||
{
|
||||
ply_pixel_buffer_free (head->pixel_buffer);
|
||||
head->pixel_buffer = NULL;
|
||||
|
||||
ply_list_remove_data (backend->heads, head);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_backend (ply_renderer_backend_t *backend)
|
||||
{
|
||||
|
||||
free (backend->device_name);
|
||||
uninitialize_head (backend, &backend->head);
|
||||
|
||||
ply_list_free (backend->heads);
|
||||
|
||||
free (backend);
|
||||
}
|
||||
|
||||
static void
|
||||
on_active_vt_changed (ply_renderer_backend_t *backend)
|
||||
{
|
||||
if (ply_console_get_active_vt (backend->console) !=
|
||||
ply_terminal_get_vt_number (backend->terminal))
|
||||
return;
|
||||
|
||||
if (backend->head.map_address != MAP_FAILED)
|
||||
ply_renderer_head_redraw (backend, &backend->head);
|
||||
}
|
||||
|
||||
static bool
|
||||
open_device (ply_renderer_backend_t *backend)
|
||||
{
|
||||
backend->device_fd = open (backend->device_name, O_RDWR);
|
||||
|
||||
if (backend->device_fd < 0)
|
||||
{
|
||||
ply_trace ("could not open '%s': %m", backend->device_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
ply_console_watch_for_active_vt_change (backend->console,
|
||||
(ply_console_active_vt_changed_handler_t)
|
||||
on_active_vt_changed,
|
||||
backend);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
close_device (ply_renderer_backend_t *backend)
|
||||
{
|
||||
|
||||
ply_console_stop_watching_for_active_vt_change (backend->console,
|
||||
(ply_console_active_vt_changed_handler_t)
|
||||
on_active_vt_changed,
|
||||
backend);
|
||||
close (backend->device_fd);
|
||||
backend->device_fd = -1;
|
||||
|
||||
backend->bytes_per_pixel = 0;
|
||||
backend->head.area.x = 0;
|
||||
backend->head.area.y = 0;
|
||||
backend->head.area.width = 0;
|
||||
backend->head.area.height = 0;
|
||||
}
|
||||
|
||||
static const char const *get_visual_name (int visual)
|
||||
{
|
||||
static const char const *visuals[] =
|
||||
{
|
||||
[FB_VISUAL_MONO01] = "FB_VISUAL_MONO01",
|
||||
[FB_VISUAL_MONO10] = "FB_VISUAL_MONO10",
|
||||
[FB_VISUAL_TRUECOLOR] = "FB_VISUAL_TRUECOLOR",
|
||||
[FB_VISUAL_PSEUDOCOLOR] = "FB_VISUAL_PSEUDOCOLOR",
|
||||
[FB_VISUAL_DIRECTCOLOR] = "FB_VISUAL_DIRECTCOLOR",
|
||||
[FB_VISUAL_STATIC_PSEUDOCOLOR] = "FB_VISUAL_STATIC_PSEUDOCOLOR",
|
||||
NULL
|
||||
};
|
||||
static char unknown[] = "invalid visual: -4294967295";
|
||||
|
||||
if (visual < FB_VISUAL_MONO01 || visual > FB_VISUAL_STATIC_PSEUDOCOLOR)
|
||||
{
|
||||
sprintf (unknown, "invalid visual: %d", visual);
|
||||
return unknown;
|
||||
}
|
||||
|
||||
return visuals[visual];
|
||||
}
|
||||
|
||||
static bool
|
||||
query_device (ply_renderer_backend_t *backend)
|
||||
{
|
||||
struct fb_var_screeninfo variable_screen_info;
|
||||
struct fb_fix_screeninfo fixed_screen_info;
|
||||
|
||||
assert (backend != NULL);
|
||||
assert (backend->device_fd >= 0);
|
||||
|
||||
if (ioctl (backend->device_fd, FBIOGET_VSCREENINFO, &variable_screen_info) < 0)
|
||||
return false;
|
||||
|
||||
if (ioctl (backend->device_fd, FBIOGET_FSCREENINFO, &fixed_screen_info) < 0)
|
||||
return false;
|
||||
|
||||
/* Normally the pixel is divided into channels between the color components.
|
||||
* Each channel directly maps to a color channel on the hardware.
|
||||
*
|
||||
* There are some odd ball modes that use an indexed palette instead. In
|
||||
* those cases (pseudocolor, direct color, etc), the pixel value is just an
|
||||
* index into a lookup table of the real color values.
|
||||
*
|
||||
* We don't support that.
|
||||
*/
|
||||
if (fixed_screen_info.visual != FB_VISUAL_TRUECOLOR)
|
||||
{
|
||||
int rc = -1;
|
||||
int i;
|
||||
static const int depths[] = {32, 24, 16, 0};
|
||||
|
||||
ply_trace ("Visual was %s, trying to find usable mode.\n",
|
||||
get_visual_name (fixed_screen_info.visual));
|
||||
|
||||
for (i = 0; depths[i] != 0; i++)
|
||||
{
|
||||
variable_screen_info.bits_per_pixel = depths[i];
|
||||
variable_screen_info.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
|
||||
|
||||
rc = ioctl (backend->device_fd, FBIOPUT_VSCREENINFO, &variable_screen_info);
|
||||
if (rc >= 0)
|
||||
{
|
||||
if (ioctl (backend->device_fd, FBIOGET_FSCREENINFO, &fixed_screen_info) < 0)
|
||||
return false;
|
||||
|
||||
if (fixed_screen_info.visual == FB_VISUAL_TRUECOLOR)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl (backend->device_fd, FBIOGET_VSCREENINFO, &variable_screen_info) < 0)
|
||||
return false;
|
||||
|
||||
if (ioctl (backend->device_fd, FBIOGET_FSCREENINFO, &fixed_screen_info) < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fixed_screen_info.visual != FB_VISUAL_TRUECOLOR ||
|
||||
variable_screen_info.bits_per_pixel < 16)
|
||||
{
|
||||
ply_trace ("Visual is %s; not using graphics\n",
|
||||
get_visual_name (fixed_screen_info.visual));
|
||||
return false;
|
||||
}
|
||||
|
||||
backend->head.area.x = variable_screen_info.xoffset;
|
||||
backend->head.area.y = variable_screen_info.yoffset;
|
||||
backend->head.area.width = variable_screen_info.xres;
|
||||
backend->head.area.height = variable_screen_info.yres;
|
||||
|
||||
backend->red_bit_position = variable_screen_info.red.offset;
|
||||
backend->bits_for_red = variable_screen_info.red.length;
|
||||
|
||||
backend->green_bit_position = variable_screen_info.green.offset;
|
||||
backend->bits_for_green = variable_screen_info.green.length;
|
||||
|
||||
backend->blue_bit_position = variable_screen_info.blue.offset;
|
||||
backend->bits_for_blue = variable_screen_info.blue.length;
|
||||
|
||||
backend->alpha_bit_position = variable_screen_info.transp.offset;
|
||||
backend->bits_for_alpha = variable_screen_info.transp.length;
|
||||
|
||||
backend->bytes_per_pixel = variable_screen_info.bits_per_pixel >> 3;
|
||||
backend->row_stride = fixed_screen_info.line_length;
|
||||
backend->dither_red = 0;
|
||||
backend->dither_green = 0;
|
||||
backend->dither_blue = 0;
|
||||
|
||||
backend->head.size = backend->head.area.height * backend->row_stride;
|
||||
|
||||
if (backend->bytes_per_pixel == 4 &&
|
||||
backend->red_bit_position == 16 && backend->bits_for_red == 8 &&
|
||||
backend->green_bit_position == 8 && backend->bits_for_green == 8 &&
|
||||
backend->blue_bit_position == 0 && backend->bits_for_blue == 8)
|
||||
backend->flush_area = flush_area_to_xrgb32_device;
|
||||
else
|
||||
backend->flush_area = flush_area_to_any_device;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static bool
|
||||
map_to_device (ply_renderer_backend_t *backend)
|
||||
{
|
||||
ply_renderer_head_t *head;
|
||||
|
||||
assert (backend != NULL);
|
||||
assert (backend->device_fd >= 0);
|
||||
|
||||
head = &backend->head;
|
||||
assert (head->size > 0);
|
||||
|
||||
head->map_address = mmap (NULL, head->size, PROT_WRITE,
|
||||
MAP_SHARED, backend->device_fd, 0);
|
||||
|
||||
if (head->map_address == MAP_FAILED)
|
||||
return false;
|
||||
|
||||
initialize_head (backend, head);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_from_device (ply_renderer_backend_t *backend)
|
||||
{
|
||||
ply_renderer_head_t *head;
|
||||
|
||||
head = &backend->head;
|
||||
|
||||
uninitialize_head (backend, head);
|
||||
|
||||
if (head->map_address != MAP_FAILED)
|
||||
{
|
||||
munmap (head->map_address, head->size);
|
||||
head->map_address = MAP_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
flush_head (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head)
|
||||
{
|
||||
ply_region_t *updated_region;
|
||||
ply_list_t *areas_to_flush;
|
||||
ply_list_node_t *node;
|
||||
ply_pixel_buffer_t *pixel_buffer;
|
||||
|
||||
assert (backend != NULL);
|
||||
assert (&backend->head == head);
|
||||
|
||||
ply_console_set_mode (backend->console, PLY_CONSOLE_MODE_GRAPHICS);
|
||||
pixel_buffer = head->pixel_buffer;
|
||||
updated_region = ply_pixel_buffer_get_updated_areas (pixel_buffer);
|
||||
areas_to_flush = ply_region_get_rectangle_list (updated_region);
|
||||
|
||||
node = ply_list_get_first_node (areas_to_flush);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
ply_rectangle_t *area_to_flush;
|
||||
|
||||
area_to_flush = (ply_rectangle_t *) ply_list_node_get_data (node);
|
||||
|
||||
next_node = ply_list_get_next_node (areas_to_flush, node);
|
||||
|
||||
backend->flush_area (backend, head, area_to_flush);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
ply_region_clear (updated_region);
|
||||
}
|
||||
|
||||
static void
|
||||
ply_renderer_head_redraw (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head)
|
||||
{
|
||||
ply_region_t *region;
|
||||
|
||||
region = ply_pixel_buffer_get_updated_areas (head->pixel_buffer);
|
||||
|
||||
ply_region_add_rectangle (region, &head->area);
|
||||
|
||||
flush_head (backend, head);
|
||||
}
|
||||
|
||||
static ply_list_t *
|
||||
get_heads (ply_renderer_backend_t *backend)
|
||||
{
|
||||
return backend->heads;
|
||||
}
|
||||
|
||||
static ply_pixel_buffer_t *
|
||||
get_buffer_for_head (ply_renderer_backend_t *backend,
|
||||
ply_renderer_head_t *head)
|
||||
{
|
||||
|
||||
if (head != &backend->head)
|
||||
return NULL;
|
||||
|
||||
return backend->head.pixel_buffer;
|
||||
}
|
||||
|
||||
static bool
|
||||
has_input_source (ply_renderer_backend_t *backend,
|
||||
ply_renderer_input_source_t *input_source)
|
||||
{
|
||||
return input_source == &backend->input_source;
|
||||
}
|
||||
|
||||
static ply_renderer_input_source_t *
|
||||
get_input_source (ply_renderer_backend_t *backend)
|
||||
{
|
||||
return &backend->input_source;
|
||||
}
|
||||
|
||||
static void
|
||||
on_key_event (ply_renderer_input_source_t *input_source,
|
||||
int terminal_fd)
|
||||
{
|
||||
ply_buffer_append_from_fd (input_source->key_buffer,
|
||||
terminal_fd);
|
||||
|
||||
if (input_source->handler != NULL)
|
||||
input_source->handler (input_source->user_data, input_source->key_buffer, input_source);
|
||||
|
||||
}
|
||||
|
||||
static bool
|
||||
open_input_source (ply_renderer_backend_t *backend,
|
||||
ply_renderer_input_source_t *input_source)
|
||||
{
|
||||
int terminal_fd;
|
||||
|
||||
assert (backend != NULL);
|
||||
assert (has_input_source (backend, input_source));
|
||||
|
||||
terminal_fd = ply_terminal_get_fd (backend->terminal);
|
||||
|
||||
input_source->terminal_input_watch = ply_event_loop_watch_fd (backend->loop, terminal_fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
|
||||
(ply_event_handler_t) on_key_event,
|
||||
NULL, input_source);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
set_handler_for_input_source (ply_renderer_backend_t *backend,
|
||||
ply_renderer_input_source_t *input_source,
|
||||
ply_renderer_input_source_handler_t handler,
|
||||
void *user_data)
|
||||
{
|
||||
assert (backend != NULL);
|
||||
assert (has_input_source (backend, input_source));
|
||||
|
||||
input_source->handler = handler;
|
||||
input_source->user_data = user_data;
|
||||
}
|
||||
|
||||
static void
|
||||
close_input_source (ply_renderer_backend_t *backend,
|
||||
ply_renderer_input_source_t *input_source)
|
||||
{
|
||||
assert (backend != NULL);
|
||||
assert (has_input_source (backend, input_source));
|
||||
|
||||
ply_event_loop_stop_watching_fd (backend->loop, input_source->terminal_input_watch);
|
||||
input_source->terminal_input_watch = NULL;
|
||||
}
|
||||
|
||||
ply_renderer_plugin_interface_t *
|
||||
ply_renderer_backend_get_interface (void)
|
||||
{
|
||||
static ply_renderer_plugin_interface_t plugin_interface =
|
||||
{
|
||||
.create_backend = create_backend,
|
||||
.destroy_backend = destroy_backend,
|
||||
.open_device = open_device,
|
||||
.close_device = close_device,
|
||||
.query_device = query_device,
|
||||
.map_to_device = map_to_device,
|
||||
.unmap_from_device = unmap_from_device,
|
||||
.flush_head = flush_head,
|
||||
.get_heads = get_heads,
|
||||
.get_buffer_for_head = get_buffer_for_head,
|
||||
.get_input_source = get_input_source,
|
||||
.open_input_source = open_input_source,
|
||||
.set_handler_for_input_source = set_handler_for_input_source,
|
||||
.close_input_source = close_input_source
|
||||
};
|
||||
|
||||
return &plugin_interface;
|
||||
}
|
||||
/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
|
||||
|
|
@ -46,11 +46,10 @@
|
|||
#include "ply-key-file.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-image.h"
|
||||
#include "ply-text-display.h"
|
||||
#include "ply-trigger.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
|
|
@ -62,27 +61,66 @@ typedef enum {
|
|||
PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY
|
||||
} ply_boot_splash_display_type_t;
|
||||
|
||||
|
||||
typedef void (* ply_boot_splash_plugin_window_handler_t) (ply_window_t *window, ply_boot_splash_plugin_t *, void *user_data, void *other_user_data);
|
||||
|
||||
static void uninitialize_window (ply_window_t *window,
|
||||
ply_boot_splash_plugin_t *plugin);
|
||||
|
||||
static void for_each_window (ply_boot_splash_plugin_t *plugin,
|
||||
ply_boot_splash_plugin_window_handler_t handler,
|
||||
void *user_data,
|
||||
void *other_user_data);
|
||||
typedef struct
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
ply_text_display_t *display;
|
||||
} view_t;
|
||||
|
||||
ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void);
|
||||
struct _ply_boot_splash_plugin
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
ply_boot_splash_mode_t mode;
|
||||
ply_list_t *windows;
|
||||
ply_list_t *views;
|
||||
ply_boot_splash_display_type_t state;
|
||||
|
||||
};
|
||||
|
||||
static view_t *
|
||||
view_new (ply_boot_splash_plugin_t *plugin,
|
||||
ply_text_display_t *display)
|
||||
{
|
||||
view_t *view;
|
||||
|
||||
view = calloc (1, sizeof (view_t));
|
||||
view->plugin = plugin;
|
||||
view->display = display;
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
static void
|
||||
view_free (view_t *view)
|
||||
{
|
||||
free (view);
|
||||
}
|
||||
|
||||
static void
|
||||
free_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_free (view);
|
||||
ply_list_remove_node (plugin->views, node);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
ply_list_free (plugin->views);
|
||||
plugin->views = NULL;
|
||||
}
|
||||
|
||||
static ply_boot_splash_plugin_t *
|
||||
create_plugin (ply_key_file_t *key_file)
|
||||
{
|
||||
|
|
@ -91,7 +129,7 @@ create_plugin (ply_key_file_t *key_file)
|
|||
ply_trace ("creating plugin");
|
||||
|
||||
plugin = calloc (1, sizeof (ply_boot_splash_plugin_t));
|
||||
plugin->windows = ply_list_new ();
|
||||
plugin->views = ply_list_new ();
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
|
||||
return plugin;
|
||||
}
|
||||
|
|
@ -104,11 +142,7 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
if (plugin == NULL)
|
||||
return;
|
||||
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
uninitialize_window, NULL, NULL);
|
||||
|
||||
ply_list_free (plugin->windows);
|
||||
free_views (plugin);
|
||||
|
||||
free (plugin);
|
||||
}
|
||||
|
|
@ -122,103 +156,77 @@ detach_from_event_loop (ply_boot_splash_plugin_t *plugin)
|
|||
}
|
||||
|
||||
static void
|
||||
for_each_window (ply_boot_splash_plugin_t *plugin,
|
||||
ply_boot_splash_plugin_window_handler_t handler,
|
||||
void *user_data,
|
||||
void *other_user_data)
|
||||
view_write (view_t *view,
|
||||
const char *text,
|
||||
size_t number_of_bytes)
|
||||
{
|
||||
ply_terminal_t *terminal;
|
||||
|
||||
terminal = ply_text_display_get_terminal (view->display);
|
||||
ply_terminal_write (terminal, "%.*s", (int) number_of_bytes, text);
|
||||
}
|
||||
|
||||
static void
|
||||
write_on_views (ply_boot_splash_plugin_t *plugin,
|
||||
const char *text,
|
||||
size_t number_of_bytes)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->windows);
|
||||
if (number_of_bytes == 0)
|
||||
return;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
ply_window_t *window;
|
||||
view_t *view;
|
||||
|
||||
next_node = ply_list_get_next_node (plugin->windows, node);
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
window = ply_list_node_get_data (node);
|
||||
|
||||
handler (window, plugin, user_data, other_user_data);
|
||||
view_write (view, text, number_of_bytes);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
write_text_on_window (ply_window_t *window,
|
||||
ply_boot_splash_plugin_t *plugin,
|
||||
const char *text,
|
||||
void *user_data)
|
||||
add_text_display (ply_boot_splash_plugin_t *plugin,
|
||||
ply_text_display_t *display)
|
||||
{
|
||||
int fd;
|
||||
size_t size;
|
||||
view_t *view;
|
||||
|
||||
ply_window_set_mode (window, PLY_WINDOW_MODE_TEXT);
|
||||
view = view_new (plugin, display);
|
||||
|
||||
size = (size_t) user_data;
|
||||
|
||||
fd = ply_window_get_tty_fd (window);
|
||||
|
||||
write (fd, text, size);
|
||||
}
|
||||
|
||||
void
|
||||
on_keyboard_input (ply_boot_splash_plugin_t *plugin,
|
||||
const char *keyboard_input,
|
||||
size_t character_size)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_backspace (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_enter (ply_boot_splash_plugin_t *plugin,
|
||||
const char *line)
|
||||
{
|
||||
ply_list_append_data (plugin->views, view);
|
||||
}
|
||||
|
||||
static void
|
||||
add_window (ply_boot_splash_plugin_t *plugin,
|
||||
ply_window_t *window)
|
||||
remove_text_display (ply_boot_splash_plugin_t *plugin,
|
||||
ply_text_display_t *display)
|
||||
{
|
||||
ply_list_append_data (plugin->windows, window);
|
||||
}
|
||||
ply_list_node_t *node;
|
||||
|
||||
static void
|
||||
remove_window (ply_boot_splash_plugin_t *plugin,
|
||||
ply_window_t *window)
|
||||
{
|
||||
ply_list_remove_data (plugin->windows, window);
|
||||
}
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
view_t *view;
|
||||
ply_list_node_t *next_node;
|
||||
|
||||
static void
|
||||
initialize_window (ply_window_t *window,
|
||||
ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_window_set_mode (window, PLY_WINDOW_MODE_TEXT);
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_window_add_keyboard_input_handler (window,
|
||||
(ply_window_keyboard_input_handler_t)
|
||||
on_keyboard_input, plugin);
|
||||
ply_window_add_backspace_handler (window,
|
||||
(ply_window_backspace_handler_t)
|
||||
on_backspace, plugin);
|
||||
ply_window_add_enter_handler (window,
|
||||
(ply_window_enter_handler_t)
|
||||
on_enter, plugin);
|
||||
}
|
||||
if (view->display == display)
|
||||
{
|
||||
ply_list_remove_node (plugin->views, node);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
uninitialize_window (ply_window_t *window,
|
||||
ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_window_remove_keyboard_input_handler (window, (ply_window_keyboard_input_handler_t) on_keyboard_input);
|
||||
ply_window_remove_backspace_handler (window, (ply_window_backspace_handler_t) on_backspace);
|
||||
ply_window_remove_enter_handler (window, (ply_window_enter_handler_t) on_enter);
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -231,9 +239,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
|
||||
assert (plugin != NULL);
|
||||
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
initialize_window, NULL, NULL);
|
||||
plugin->loop = loop;
|
||||
plugin->mode = mode;
|
||||
|
||||
|
|
@ -243,10 +248,7 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
|
||||
size = ply_buffer_get_size (boot_buffer);
|
||||
|
||||
if (size > 0)
|
||||
write (STDOUT_FILENO,
|
||||
ply_buffer_get_bytes (boot_buffer),
|
||||
size);
|
||||
write_on_views (plugin, ply_buffer_get_bytes (boot_buffer), size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -265,13 +267,9 @@ on_boot_output (ply_boot_splash_plugin_t *plugin,
|
|||
const char *output,
|
||||
size_t size)
|
||||
{
|
||||
ply_trace ("writing '%s' to all windows (%d bytes)",
|
||||
ply_trace ("writing '%s' to all views (%d bytes)",
|
||||
output, (int) size);
|
||||
if (size > 0)
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) output, (void *) size);
|
||||
write_on_views (plugin, output, size);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -282,10 +280,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
|
||||
ply_trace ("hiding splash screen");
|
||||
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
uninitialize_window, NULL, NULL);
|
||||
|
||||
ply_event_loop_stop_watching_for_exit (plugin->loop,
|
||||
(ply_event_loop_exit_handler_t)
|
||||
detach_from_event_loop,
|
||||
|
|
@ -297,16 +291,11 @@ static void
|
|||
display_normal (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL)
|
||||
{
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) "\r\n", (void *) strlen ("\r\n"));
|
||||
}
|
||||
write_on_views (plugin, "\r\n", strlen ("\r\n"));
|
||||
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
display_password (ply_boot_splash_plugin_t *plugin,
|
||||
const char *prompt,
|
||||
|
|
@ -314,46 +303,26 @@ display_password (ply_boot_splash_plugin_t *plugin,
|
|||
{
|
||||
int i;
|
||||
if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY)
|
||||
{
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) "\r\n", (void *) strlen ("\r\n"));
|
||||
}
|
||||
write_on_views (plugin, "\r\n", strlen ("\r\n"));
|
||||
else
|
||||
{
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) CLEAR_LINE_SEQUENCE,
|
||||
(void *) strlen (CLEAR_LINE_SEQUENCE));
|
||||
}
|
||||
write_on_views (plugin,
|
||||
CLEAR_LINE_SEQUENCE,
|
||||
strlen (CLEAR_LINE_SEQUENCE));
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY;
|
||||
|
||||
if (prompt)
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) prompt,
|
||||
(void *) strlen (prompt));
|
||||
else
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) "Password",
|
||||
(void *) strlen ("Password"));
|
||||
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) ":",
|
||||
(void *) strlen (":"));
|
||||
for (i=0; i<bullets; i++)
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) "*",
|
||||
(void *) strlen ("*"));
|
||||
if (prompt)
|
||||
write_on_views (plugin,
|
||||
prompt,
|
||||
strlen (prompt));
|
||||
else
|
||||
write_on_views (plugin,
|
||||
"Password",
|
||||
strlen ("Password"));
|
||||
|
||||
write_on_views (plugin, ":", strlen (":"));
|
||||
|
||||
for (i = 0; i < bullets; i++)
|
||||
write_on_views (plugin, "*", strlen ("*"));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -362,37 +331,18 @@ display_question (ply_boot_splash_plugin_t *plugin,
|
|||
const char *entry_text)
|
||||
{
|
||||
if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY)
|
||||
{
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) "\r\n", (void *) strlen ("\r\n"));
|
||||
}
|
||||
write_on_views (plugin, "\r\n", strlen ("\r\n"));
|
||||
else
|
||||
{
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) CLEAR_LINE_SEQUENCE,
|
||||
(void *) strlen (CLEAR_LINE_SEQUENCE));
|
||||
}
|
||||
write_on_views (plugin,
|
||||
CLEAR_LINE_SEQUENCE,
|
||||
strlen (CLEAR_LINE_SEQUENCE));
|
||||
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY;
|
||||
if (prompt)
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) prompt,
|
||||
(void *) strlen (prompt));
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) ":",
|
||||
(void *) strlen (":"));
|
||||
for_each_window (plugin,
|
||||
(ply_boot_splash_plugin_window_handler_t)
|
||||
write_text_on_window,
|
||||
(void *) entry_text,
|
||||
(void *) strlen (entry_text));
|
||||
write_on_views (plugin, prompt, strlen (prompt));
|
||||
|
||||
write_on_views (plugin, ":", strlen (":"));
|
||||
write_on_views (plugin, entry_text, strlen (entry_text));
|
||||
}
|
||||
|
||||
ply_boot_splash_plugin_interface_t *
|
||||
|
|
@ -402,8 +352,8 @@ ply_boot_splash_plugin_get_interface (void)
|
|||
{
|
||||
.create_plugin = create_plugin,
|
||||
.destroy_plugin = destroy_plugin,
|
||||
.add_window = add_window,
|
||||
.remove_window = remove_window,
|
||||
.add_text_display = add_text_display,
|
||||
.remove_text_display = remove_text_display,
|
||||
.show_splash_screen = show_splash_screen,
|
||||
.update_status = update_status,
|
||||
.on_boot_output = on_boot_output,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -49,11 +49,10 @@
|
|||
#include "ply-label.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-image.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-trigger.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include "script.h"
|
||||
#include "script-parse.h"
|
||||
|
|
@ -70,32 +69,120 @@
|
|||
#define FRAMES_PER_SECOND 50
|
||||
#endif
|
||||
|
||||
struct _ply_boot_splash_plugin
|
||||
typedef struct
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
ply_boot_splash_mode_t mode;
|
||||
ply_frame_buffer_t *frame_buffer;
|
||||
ply_window_t *window;
|
||||
|
||||
char *script_filename;
|
||||
char *image_dir;
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
ply_pixel_display_t *display;
|
||||
|
||||
script_state_t *script_state;
|
||||
script_op_t *script_main_op;
|
||||
script_lib_sprite_data_t *script_sprite_lib;
|
||||
script_lib_image_data_t *script_image_lib;
|
||||
script_lib_plymouth_data_t *script_plymouth_lib;
|
||||
script_lib_math_data_t *script_math_lib;
|
||||
} view_t;
|
||||
|
||||
struct _ply_boot_splash_plugin
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
ply_boot_splash_mode_t mode;
|
||||
ply_list_t *views;
|
||||
|
||||
char *script_filename;
|
||||
char *image_dir;
|
||||
|
||||
script_op_t *script_main_op;
|
||||
|
||||
uint32_t is_animating : 1;
|
||||
};
|
||||
|
||||
static void add_handlers (ply_boot_splash_plugin_t *plugin);
|
||||
static void remove_handlers (ply_boot_splash_plugin_t *plugin);
|
||||
static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin);
|
||||
static void stop_animation (ply_boot_splash_plugin_t *plugin);
|
||||
ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void);
|
||||
|
||||
static view_t *
|
||||
view_new (ply_boot_splash_plugin_t *plugin,
|
||||
ply_pixel_display_t *display)
|
||||
{
|
||||
view_t *view;
|
||||
|
||||
view = calloc (1, sizeof (view_t));
|
||||
view->plugin = plugin;
|
||||
view->display = display;
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
static void
|
||||
view_free (view_t *view)
|
||||
{
|
||||
free (view);
|
||||
}
|
||||
|
||||
static void
|
||||
pause_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_pixel_display_pause_updates (view->display);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unpause_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_pixel_display_unpause_updates (view->display);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_free (view);
|
||||
ply_list_remove_node (plugin->views, node);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
ply_list_free (plugin->views);
|
||||
plugin->views = NULL;
|
||||
}
|
||||
|
||||
static ply_boot_splash_plugin_t *
|
||||
create_plugin (ply_key_file_t *key_file)
|
||||
{
|
||||
|
|
@ -105,6 +192,7 @@ create_plugin (ply_key_file_t *key_file)
|
|||
plugin->script_filename = ply_key_file_get_value (key_file,
|
||||
"script",
|
||||
"ScriptFile");
|
||||
plugin->views = ply_list_new ();
|
||||
return plugin;
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +201,6 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
{
|
||||
if (plugin == NULL)
|
||||
return;
|
||||
remove_handlers (plugin);
|
||||
|
||||
if (plugin->loop != NULL)
|
||||
{
|
||||
|
|
@ -124,27 +211,30 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
plugin);
|
||||
detach_from_event_loop (plugin);
|
||||
}
|
||||
|
||||
free_views (plugin);
|
||||
free (plugin->script_filename);
|
||||
free (plugin->image_dir);
|
||||
free (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
on_timeout (ply_boot_splash_plugin_t *plugin)
|
||||
on_timeout (view_t *view)
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
double sleep_time;
|
||||
|
||||
ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS);
|
||||
plugin = view->plugin;
|
||||
|
||||
script_lib_plymouth_on_refresh (plugin->script_state,
|
||||
plugin->script_plymouth_lib);
|
||||
script_lib_sprite_refresh (plugin->script_sprite_lib);
|
||||
script_lib_plymouth_on_refresh (view->script_state,
|
||||
view->script_plymouth_lib);
|
||||
script_lib_sprite_refresh (view->script_sprite_lib);
|
||||
|
||||
sleep_time = 1.0 / FRAMES_PER_SECOND;
|
||||
ply_event_loop_watch_for_timeout (plugin->loop,
|
||||
sleep_time,
|
||||
(ply_event_loop_timeout_handler_t)
|
||||
on_timeout, plugin);
|
||||
on_timeout, view);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -152,63 +242,128 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin,
|
|||
double duration,
|
||||
double percent_done)
|
||||
{
|
||||
script_lib_plymouth_on_boot_progress (plugin->script_state,
|
||||
plugin->script_plymouth_lib,
|
||||
duration,
|
||||
percent_done);
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
script_lib_plymouth_on_boot_progress (view->script_state,
|
||||
view->script_plymouth_lib,
|
||||
duration,
|
||||
percent_done);
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
view_start_animation (view_t *view)
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
|
||||
assert (view != NULL);
|
||||
|
||||
plugin = view->plugin;
|
||||
|
||||
view->script_state = script_state_new (view);
|
||||
view->script_image_lib = script_lib_image_setup (view->script_state,
|
||||
plugin->image_dir);
|
||||
view->script_sprite_lib = script_lib_sprite_setup (view->script_state,
|
||||
view->display);
|
||||
view->script_plymouth_lib = script_lib_plymouth_setup (view->script_state,
|
||||
plugin->mode);
|
||||
view->script_math_lib = script_lib_math_setup (view->script_state);
|
||||
|
||||
ply_trace ("executing script file");
|
||||
script_return_t ret = script_execute (view->script_state,
|
||||
plugin->script_main_op);
|
||||
script_obj_unref (ret.object);
|
||||
on_timeout (view);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
start_animation (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_frame_buffer_area_t area;
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->loop != NULL);
|
||||
|
||||
if (plugin->is_animating)
|
||||
return true;
|
||||
ply_frame_buffer_get_size (plugin->frame_buffer, &area);
|
||||
|
||||
ply_trace ("parsing script file");
|
||||
plugin->script_main_op = script_parse_file (plugin->script_filename);
|
||||
plugin->script_state = script_state_new (plugin);
|
||||
plugin->script_image_lib = script_lib_image_setup (plugin->script_state,
|
||||
plugin->image_dir);
|
||||
plugin->script_sprite_lib = script_lib_sprite_setup (plugin->script_state,
|
||||
plugin->window);
|
||||
plugin->script_plymouth_lib = script_lib_plymouth_setup (plugin->script_state,
|
||||
plugin->mode);
|
||||
plugin->script_math_lib = script_lib_math_setup (plugin->script_state);
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
ply_trace ("executing script file");
|
||||
script_return_t ret = script_execute (plugin->script_state,
|
||||
plugin->script_main_op);
|
||||
script_obj_unref (ret.object);
|
||||
on_timeout (plugin);
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_start_animation (view);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
plugin->is_animating = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
view_stop_animation (view_t *view)
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
|
||||
plugin = view->plugin;
|
||||
|
||||
if (plugin->loop != NULL)
|
||||
ply_event_loop_stop_watching_for_timeout (plugin->loop,
|
||||
(ply_event_loop_timeout_handler_t)
|
||||
on_timeout, view);
|
||||
|
||||
script_state_destroy (view->script_state);
|
||||
script_lib_sprite_destroy (view->script_sprite_lib);
|
||||
script_lib_image_destroy (view->script_image_lib);
|
||||
script_lib_plymouth_destroy (view->script_plymouth_lib);
|
||||
script_lib_math_destroy (view->script_math_lib);
|
||||
}
|
||||
|
||||
static void
|
||||
stop_animation (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->loop != NULL);
|
||||
|
||||
if (!plugin->is_animating)
|
||||
return;
|
||||
plugin->is_animating = false;
|
||||
if (plugin->loop != NULL)
|
||||
ply_event_loop_stop_watching_for_timeout (plugin->loop,
|
||||
(ply_event_loop_timeout_handler_t)
|
||||
on_timeout, plugin);
|
||||
script_state_destroy (plugin->script_state);
|
||||
script_lib_sprite_destroy (plugin->script_sprite_lib);
|
||||
script_lib_image_destroy (plugin->script_image_lib);
|
||||
script_lib_plymouth_destroy (plugin->script_plymouth_lib);
|
||||
script_lib_math_destroy (plugin->script_math_lib);
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_stop_animation (view);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
script_parse_op_free (plugin->script_main_op);
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +372,6 @@ on_interrupt (ply_boot_splash_plugin_t *plugin)
|
|||
{
|
||||
ply_event_loop_exit (plugin->loop, 1);
|
||||
stop_animation (plugin);
|
||||
ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -232,80 +386,105 @@ on_keyboard_input (ply_boot_splash_plugin_t *plugin,
|
|||
size_t character_size)
|
||||
{
|
||||
char keyboard_string[character_size + 1];
|
||||
ply_list_node_t *node;
|
||||
|
||||
memcpy (keyboard_string, keyboard_input, character_size);
|
||||
keyboard_string[character_size] = '\0';
|
||||
|
||||
script_lib_plymouth_on_keyboard_input (plugin->script_state,
|
||||
plugin->script_plymouth_lib,
|
||||
keyboard_string);
|
||||
/* FIXME: Not sure what to do here. We don't want to feed
|
||||
* the input once per monitor, I don't think, so we just call
|
||||
* it on the first available monitor.
|
||||
*
|
||||
* I'm not even sure it's useful for scripts to be able to access
|
||||
* this, but if it is we probably need to encode view awareness
|
||||
* into the script api somehow.
|
||||
*/
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
view_t *view;
|
||||
view = (view_t *) ply_list_node_get_data (node);
|
||||
|
||||
script_lib_plymouth_on_keyboard_input (view->script_state,
|
||||
view->script_plymouth_lib,
|
||||
keyboard_string);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_backspace (ply_boot_splash_plugin_t *plugin)
|
||||
{}
|
||||
|
||||
static void
|
||||
on_enter (ply_boot_splash_plugin_t *plugin,
|
||||
const char *text)
|
||||
{}
|
||||
|
||||
static void
|
||||
on_draw (ply_boot_splash_plugin_t *plugin,
|
||||
on_draw (view_t *view,
|
||||
ply_pixel_buffer_t *pixel_buffer,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{}
|
||||
|
||||
static void
|
||||
on_erase (ply_boot_splash_plugin_t *plugin,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{}
|
||||
|
||||
static void
|
||||
add_handlers (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_window_add_keyboard_input_handler (plugin->window,
|
||||
(ply_window_keyboard_input_handler_t)
|
||||
on_keyboard_input, plugin);
|
||||
ply_window_add_backspace_handler (plugin->window,
|
||||
(ply_window_backspace_handler_t)
|
||||
on_backspace, plugin);
|
||||
ply_window_add_enter_handler (plugin->window,
|
||||
(ply_window_enter_handler_t)
|
||||
on_enter, plugin);
|
||||
ply_window_set_draw_handler (plugin->window,
|
||||
(ply_window_draw_handler_t)
|
||||
on_draw, plugin);
|
||||
ply_window_set_erase_handler (plugin->window,
|
||||
(ply_window_erase_handler_t)
|
||||
on_erase, plugin);
|
||||
script_lib_sprite_draw_area (view->script_sprite_lib,
|
||||
pixel_buffer,
|
||||
x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_handlers (ply_boot_splash_plugin_t *plugin)
|
||||
set_keyboard (ply_boot_splash_plugin_t *plugin,
|
||||
ply_keyboard_t *keyboard)
|
||||
{
|
||||
ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input);
|
||||
ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace);
|
||||
ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter);
|
||||
|
||||
ply_keyboard_add_input_handler (keyboard,
|
||||
(ply_keyboard_input_handler_t)
|
||||
on_keyboard_input, plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
add_window (ply_boot_splash_plugin_t *plugin,
|
||||
ply_window_t *window)
|
||||
unset_keyboard (ply_boot_splash_plugin_t *plugin,
|
||||
ply_keyboard_t *keyboard)
|
||||
{
|
||||
plugin->window = window;
|
||||
ply_keyboard_remove_input_handler (keyboard,
|
||||
(ply_keyboard_input_handler_t)
|
||||
on_keyboard_input);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_window (ply_boot_splash_plugin_t *plugin,
|
||||
ply_window_t *window)
|
||||
add_pixel_display (ply_boot_splash_plugin_t *plugin,
|
||||
ply_pixel_display_t *display)
|
||||
{
|
||||
plugin->window = NULL;
|
||||
view_t *view;
|
||||
|
||||
view = view_new (plugin, display);
|
||||
|
||||
ply_pixel_display_set_draw_handler (view->display,
|
||||
(ply_pixel_display_draw_handler_t)
|
||||
on_draw, view);
|
||||
|
||||
ply_list_append_data (plugin->views, view);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_pixel_display (ply_boot_splash_plugin_t *plugin,
|
||||
ply_pixel_display_t *display)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
view_t *view;
|
||||
ply_list_node_t *next_node;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
if (view->display == display)
|
||||
{
|
||||
|
||||
ply_pixel_display_set_draw_handler (view->display, NULL, NULL);
|
||||
view_free (view);
|
||||
ply_list_remove_node (plugin->views, node);
|
||||
return;
|
||||
}
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -316,13 +495,9 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
{
|
||||
assert (plugin != NULL);
|
||||
|
||||
add_handlers (plugin);
|
||||
|
||||
plugin->loop = loop;
|
||||
plugin->mode = mode;
|
||||
|
||||
plugin->frame_buffer = ply_window_get_frame_buffer (plugin->window);
|
||||
|
||||
ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
|
||||
detach_from_event_loop,
|
||||
plugin);
|
||||
|
|
@ -332,12 +507,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
(ply_event_handler_t)
|
||||
on_interrupt, plugin);
|
||||
|
||||
ply_trace ("setting graphics mode");
|
||||
if (!ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS))
|
||||
return false;
|
||||
ply_window_clear_screen (plugin->window);
|
||||
ply_window_hide_text_cursor (plugin->window);
|
||||
|
||||
ply_trace ("starting boot animation");
|
||||
return start_animation (plugin);
|
||||
}
|
||||
|
|
@ -347,9 +516,23 @@ update_status (ply_boot_splash_plugin_t *plugin,
|
|||
const char *status)
|
||||
{
|
||||
assert (plugin != NULL);
|
||||
script_lib_plymouth_on_update_status (plugin->script_state,
|
||||
plugin->script_plymouth_lib,
|
||||
status);
|
||||
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
script_lib_plymouth_on_update_status (view->script_state,
|
||||
view->script_plymouth_lib,
|
||||
status);
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -358,8 +541,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
{
|
||||
assert (plugin != NULL);
|
||||
|
||||
remove_handlers (plugin);
|
||||
|
||||
if (plugin->loop != NULL)
|
||||
{
|
||||
stop_animation (plugin);
|
||||
|
|
@ -370,16 +551,27 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
plugin);
|
||||
detach_from_event_loop (plugin);
|
||||
}
|
||||
plugin->frame_buffer = NULL;
|
||||
|
||||
ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT);
|
||||
}
|
||||
|
||||
static void
|
||||
on_root_mounted (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
script_lib_plymouth_on_root_mounted (plugin->script_state,
|
||||
plugin->script_plymouth_lib);
|
||||
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
script_lib_plymouth_on_root_mounted (view->script_state,
|
||||
view->script_plymouth_lib);
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -392,8 +584,25 @@ become_idle (ply_boot_splash_plugin_t *plugin,
|
|||
static void
|
||||
display_normal (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
script_lib_plymouth_on_display_normal (plugin->script_state,
|
||||
plugin->script_plymouth_lib);
|
||||
ply_list_node_t *node;
|
||||
|
||||
pause_views (plugin);
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
script_lib_plymouth_on_display_normal (view->script_state,
|
||||
view->script_plymouth_lib);
|
||||
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -401,10 +610,27 @@ display_password (ply_boot_splash_plugin_t *plugin,
|
|||
const char *prompt,
|
||||
int bullets)
|
||||
{
|
||||
script_lib_plymouth_on_display_password (plugin->script_state,
|
||||
plugin->script_plymouth_lib,
|
||||
prompt,
|
||||
bullets);
|
||||
ply_list_node_t *node;
|
||||
|
||||
pause_views (plugin);
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
script_lib_plymouth_on_display_password (view->script_state,
|
||||
view->script_plymouth_lib,
|
||||
prompt,
|
||||
bullets);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
unpause_views (plugin);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -412,19 +638,51 @@ display_question (ply_boot_splash_plugin_t *plugin,
|
|||
const char *prompt,
|
||||
const char *entry_text)
|
||||
{
|
||||
script_lib_plymouth_on_display_question (plugin->script_state,
|
||||
plugin->script_plymouth_lib,
|
||||
prompt,
|
||||
entry_text);
|
||||
ply_list_node_t *node;
|
||||
|
||||
pause_views (plugin);
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
script_lib_plymouth_on_display_question (view->script_state,
|
||||
view->script_plymouth_lib,
|
||||
prompt,
|
||||
entry_text);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
display_message (ply_boot_splash_plugin_t *plugin,
|
||||
const char *message)
|
||||
{
|
||||
script_lib_plymouth_on_message (plugin->script_state,
|
||||
plugin->script_plymouth_lib,
|
||||
message);
|
||||
ply_list_node_t *node;
|
||||
|
||||
pause_views (plugin);
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
script_lib_plymouth_on_message (view->script_state,
|
||||
view->script_plymouth_lib,
|
||||
message);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
ply_boot_splash_plugin_interface_t *
|
||||
|
|
@ -434,8 +692,10 @@ ply_boot_splash_plugin_get_interface (void)
|
|||
{
|
||||
.create_plugin = create_plugin,
|
||||
.destroy_plugin = destroy_plugin,
|
||||
.add_window = add_window,
|
||||
.remove_window = remove_window,
|
||||
.set_keyboard = set_keyboard,
|
||||
.unset_keyboard = unset_keyboard,
|
||||
.add_pixel_display = add_pixel_display,
|
||||
.remove_pixel_display = remove_pixel_display,
|
||||
.show_splash_screen = show_splash_screen,
|
||||
.update_status = update_status,
|
||||
.on_boot_progress = on_boot_progress,
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@
|
|||
*/
|
||||
#include "ply-image.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-key-file.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "script.h"
|
||||
#include "script-parse.h"
|
||||
#include "script-execute.h"
|
||||
|
|
@ -141,22 +141,16 @@ static script_return_t sprite_window_get_width (script_state_t *state,
|
|||
void *user_data)
|
||||
{
|
||||
script_lib_sprite_data_t *data = user_data;
|
||||
ply_frame_buffer_t *frame_buffer = ply_window_get_frame_buffer (data->window);
|
||||
ply_frame_buffer_area_t area;
|
||||
|
||||
ply_frame_buffer_get_size (frame_buffer, &area);
|
||||
return script_return_obj (script_obj_new_number (area.width));
|
||||
return script_return_obj (script_obj_new_number (ply_pixel_display_get_width (data->display)));
|
||||
}
|
||||
|
||||
static script_return_t sprite_window_get_height (script_state_t *state,
|
||||
void *user_data)
|
||||
{
|
||||
script_lib_sprite_data_t *data = user_data;
|
||||
ply_frame_buffer_t *frame_buffer = ply_window_get_frame_buffer (data->window);
|
||||
ply_frame_buffer_area_t area;
|
||||
|
||||
ply_frame_buffer_get_size (frame_buffer, &area);
|
||||
return script_return_obj (script_obj_new_number (area.height));
|
||||
return script_return_obj (script_obj_new_number (ply_pixel_display_get_height (data->display)));
|
||||
}
|
||||
|
||||
static uint32_t extract_rgb_color (script_state_t *state)
|
||||
|
|
@ -188,29 +182,26 @@ static script_return_t sprite_window_set_background_bottom_color (script_state_t
|
|||
return script_return_obj_null ();
|
||||
}
|
||||
|
||||
static void
|
||||
draw_area (script_lib_sprite_data_t *data,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
void script_lib_sprite_draw_area (script_lib_sprite_data_t *data,
|
||||
ply_pixel_buffer_t *pixel_buffer,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
ply_frame_buffer_area_t clip_area;
|
||||
ply_rectangle_t clip_area;
|
||||
|
||||
clip_area.x = x;
|
||||
clip_area.y = y;
|
||||
clip_area.width = width;
|
||||
clip_area.height = height;
|
||||
ply_frame_buffer_t *frame_buffer = ply_window_get_frame_buffer (data->window);
|
||||
|
||||
ply_frame_buffer_pause_updates (frame_buffer);
|
||||
|
||||
if (data->background_color_start == data->background_color_end)
|
||||
ply_frame_buffer_fill_with_hex_color (frame_buffer,
|
||||
ply_pixel_buffer_fill_with_hex_color (pixel_buffer,
|
||||
&clip_area,
|
||||
data->background_color_start);
|
||||
else
|
||||
ply_frame_buffer_fill_with_gradient (frame_buffer,
|
||||
ply_pixel_buffer_fill_with_gradient (pixel_buffer,
|
||||
&clip_area,
|
||||
data->background_color_start,
|
||||
data->background_color_end);
|
||||
|
|
@ -220,7 +211,7 @@ draw_area (script_lib_sprite_data_t *data,
|
|||
node = ply_list_get_next_node (data->sprite_list, node))
|
||||
{
|
||||
sprite_t *sprite = ply_list_node_get_data (node);
|
||||
ply_frame_buffer_area_t sprite_area;
|
||||
ply_rectangle_t sprite_area;
|
||||
if (!sprite->image) continue;
|
||||
if (sprite->remove_me) continue;
|
||||
if (sprite->opacity < 0.011) continue;
|
||||
|
|
@ -234,24 +225,32 @@ draw_area (script_lib_sprite_data_t *data,
|
|||
|
||||
if ((sprite_area.x + (int) sprite_area.width) <= x) continue;
|
||||
if ((sprite_area.y + (int) sprite_area.height) <= y) continue;
|
||||
ply_frame_buffer_fill_with_argb32_data_at_opacity_with_clip (frame_buffer,
|
||||
ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip (pixel_buffer,
|
||||
&sprite_area,
|
||||
&clip_area,
|
||||
0, 0,
|
||||
ply_image_get_data (sprite->image),
|
||||
sprite->opacity);
|
||||
}
|
||||
ply_frame_buffer_unpause_updates (frame_buffer);
|
||||
}
|
||||
|
||||
script_lib_sprite_data_t *script_lib_sprite_setup (script_state_t *state,
|
||||
ply_window_t *window)
|
||||
void draw_area (script_lib_sprite_data_t *data,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
ply_pixel_display_draw_area (data->display, x, y, width, height);
|
||||
}
|
||||
|
||||
script_lib_sprite_data_t *script_lib_sprite_setup (script_state_t *state,
|
||||
ply_pixel_display_t *display)
|
||||
{
|
||||
script_lib_sprite_data_t *data = malloc (sizeof (script_lib_sprite_data_t));
|
||||
|
||||
data->class = script_obj_native_class_new (sprite_free, "sprite", data);
|
||||
data->sprite_list = ply_list_new ();
|
||||
data->window = window;
|
||||
data->display = display;
|
||||
|
||||
script_obj_t *sprite_hash = script_obj_hash_get_element (state->global, "Sprite");
|
||||
script_add_native_function (sprite_hash,
|
||||
|
|
@ -348,14 +347,9 @@ void script_lib_sprite_refresh (script_lib_sprite_data_t *data)
|
|||
|
||||
if (data->full_refresh)
|
||||
{
|
||||
ply_frame_buffer_area_t screen_area;
|
||||
ply_frame_buffer_t *frame_buffer = ply_window_get_frame_buffer (data->window);
|
||||
ply_frame_buffer_get_size (frame_buffer, &screen_area);
|
||||
draw_area (data,
|
||||
screen_area.x,
|
||||
screen_area.y,
|
||||
screen_area.width,
|
||||
screen_area.height);
|
||||
draw_area (data, 0, 0,
|
||||
ply_pixel_display_get_width (data->display),
|
||||
ply_pixel_display_get_height (data->display));
|
||||
data->full_refresh = false;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,10 +23,11 @@
|
|||
#define SCRIPT_LIB_SPRITE_H
|
||||
|
||||
#include "script.h"
|
||||
#include "ply-pixel-display.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_window_t *window;
|
||||
ply_pixel_display_t *display;
|
||||
ply_list_t *sprite_list;
|
||||
script_obj_native_class_t *class;
|
||||
script_op_t *script_main_op;
|
||||
|
|
@ -53,9 +54,15 @@ typedef struct
|
|||
script_obj_t *image_obj;
|
||||
} sprite_t;
|
||||
|
||||
script_lib_sprite_data_t *script_lib_sprite_setup (script_state_t *state,
|
||||
ply_window_t *window);
|
||||
script_lib_sprite_data_t *script_lib_sprite_setup (script_state_t *state,
|
||||
ply_pixel_display_t *display);
|
||||
void script_lib_sprite_refresh (script_lib_sprite_data_t *data);
|
||||
void script_lib_sprite_destroy (script_lib_sprite_data_t *data);
|
||||
void script_lib_sprite_draw_area (script_lib_sprite_data_t *data,
|
||||
ply_pixel_buffer_t *pixel_buffer,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
#endif /* SCRIPT_LIB_SPRITE_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -48,36 +48,270 @@
|
|||
#include "ply-key-file.h"
|
||||
#include "ply-list.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-image.h"
|
||||
#include "ply-text-display.h"
|
||||
#include "ply-text-progress-bar.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
#define CLEAR_LINE_SEQUENCE "\033[2K\r\n"
|
||||
#define BACKSPACE "\b\033[0K"
|
||||
|
||||
typedef enum {
|
||||
PLY_BOOT_SPLASH_DISPLAY_NORMAL,
|
||||
PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY,
|
||||
PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY
|
||||
} ply_boot_splash_display_type_t;
|
||||
|
||||
struct _ply_boot_splash_plugin
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
ply_boot_splash_mode_t mode;
|
||||
|
||||
ply_window_t *window;
|
||||
ply_list_t *views;
|
||||
|
||||
ply_text_progress_bar_t *progress_bar;
|
||||
ply_boot_splash_display_type_t state;
|
||||
|
||||
char *message;
|
||||
|
||||
uint32_t is_animating : 1;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
ply_text_display_t *display;
|
||||
ply_text_progress_bar_t *progress_bar;
|
||||
|
||||
} view_t;
|
||||
|
||||
static void hide_splash_screen (ply_boot_splash_plugin_t *plugin,
|
||||
ply_event_loop_t *loop);
|
||||
static void add_handlers (ply_boot_splash_plugin_t *plugin);
|
||||
static void remove_handlers (ply_boot_splash_plugin_t *plugin);
|
||||
|
||||
static view_t *
|
||||
view_new (ply_boot_splash_plugin_t *plugin,
|
||||
ply_text_display_t *display)
|
||||
{
|
||||
view_t *view;
|
||||
|
||||
view = calloc (1, sizeof (view_t));
|
||||
view->plugin = plugin;
|
||||
view->display = display;
|
||||
|
||||
view->progress_bar = ply_text_progress_bar_new ();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
static void
|
||||
view_free (view_t *view)
|
||||
{
|
||||
ply_text_progress_bar_free (view->progress_bar);
|
||||
|
||||
free (view);
|
||||
}
|
||||
|
||||
static void
|
||||
view_show_message (view_t *view)
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
int display_width, display_height;
|
||||
|
||||
plugin = view->plugin;
|
||||
|
||||
display_width = ply_text_display_get_number_of_columns (view->display);
|
||||
display_height = ply_text_display_get_number_of_rows (view->display);
|
||||
|
||||
ply_text_display_set_cursor_position (view->display, 0,
|
||||
display_height / 2);
|
||||
ply_text_display_clear_line (view->display);
|
||||
ply_text_display_set_cursor_position (view->display,
|
||||
(display_width -
|
||||
strlen (plugin->message)) / 2,
|
||||
display_height / 2);
|
||||
|
||||
ply_text_display_write (view->display, "%s", plugin->message);
|
||||
}
|
||||
|
||||
static void
|
||||
view_show_prompt (view_t *view,
|
||||
const char *prompt,
|
||||
const char *entered_text)
|
||||
{
|
||||
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
int display_width, display_height;
|
||||
int i;
|
||||
|
||||
plugin = view->plugin;
|
||||
|
||||
display_width = ply_text_display_get_number_of_columns (view->display);
|
||||
display_height = ply_text_display_get_number_of_rows (view->display);
|
||||
ply_text_display_set_background_color (view->display, PLY_TERMINAL_COLOR_DEFAULT);
|
||||
ply_text_display_clear_screen (view->display);
|
||||
|
||||
ply_text_display_set_cursor_position (view->display, 0, display_height / 2);
|
||||
|
||||
for (i=0; i < display_width; i++)
|
||||
ply_text_display_write (view->display, "%c", ' ');
|
||||
|
||||
ply_text_display_set_cursor_position (view->display,
|
||||
display_width / 2 - (strlen (prompt)),
|
||||
display_height / 2);
|
||||
|
||||
ply_text_display_write (view->display, "%s:%s", prompt, entered_text);
|
||||
|
||||
ply_text_display_show_cursor (view->display);
|
||||
}
|
||||
|
||||
static void
|
||||
view_start_animation (view_t *view)
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
ply_terminal_t *terminal;
|
||||
|
||||
assert (view != NULL);
|
||||
|
||||
plugin = view->plugin;
|
||||
|
||||
terminal = ply_text_display_get_terminal (view->display);
|
||||
|
||||
ply_terminal_set_color_hex_value (terminal,
|
||||
PLY_TERMINAL_COLOR_BLACK,
|
||||
0x000000);
|
||||
ply_terminal_set_color_hex_value (terminal,
|
||||
PLY_TERMINAL_COLOR_WHITE,
|
||||
0xffffff);
|
||||
ply_terminal_set_color_hex_value (terminal,
|
||||
PLY_TERMINAL_COLOR_BLUE,
|
||||
0x0073B3);
|
||||
ply_terminal_set_color_hex_value (terminal,
|
||||
PLY_TERMINAL_COLOR_BROWN,
|
||||
0x00457E);
|
||||
|
||||
ply_text_display_set_background_color (view->display,
|
||||
PLY_TERMINAL_COLOR_BLACK);
|
||||
ply_text_display_clear_screen (view->display);
|
||||
ply_text_display_hide_cursor (view->display);
|
||||
|
||||
if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN)
|
||||
{
|
||||
ply_text_progress_bar_hide (view->progress_bar);
|
||||
return;
|
||||
}
|
||||
|
||||
ply_text_progress_bar_show (view->progress_bar,
|
||||
view->display);
|
||||
}
|
||||
|
||||
static void
|
||||
view_redraw (view_t *view)
|
||||
{
|
||||
unsigned long screen_width, screen_height;
|
||||
|
||||
screen_width = ply_text_display_get_number_of_columns (view->display);
|
||||
screen_height = ply_text_display_get_number_of_rows (view->display);
|
||||
|
||||
ply_text_display_draw_area (view->display, 0, 0,
|
||||
screen_width, screen_height);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_redraw (view);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
view_hide (view_t *view)
|
||||
{
|
||||
if (view->display != NULL)
|
||||
{
|
||||
ply_terminal_t *terminal;
|
||||
|
||||
terminal = ply_text_display_get_terminal (view->display);
|
||||
|
||||
ply_text_display_set_background_color (view->display, PLY_TERMINAL_COLOR_DEFAULT);
|
||||
ply_text_display_clear_screen (view->display);
|
||||
ply_text_display_show_cursor (view->display);
|
||||
|
||||
ply_terminal_reset_colors (terminal);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hide_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_hide (view);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pause_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_text_display_pause_updates (view->display);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unpause_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_text_display_unpause_updates (view->display);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static ply_boot_splash_plugin_t *
|
||||
create_plugin (ply_key_file_t *key_file)
|
||||
|
|
@ -87,9 +321,10 @@ create_plugin (ply_key_file_t *key_file)
|
|||
ply_trace ("creating plugin");
|
||||
|
||||
plugin = calloc (1, sizeof (ply_boot_splash_plugin_t));
|
||||
plugin->progress_bar = ply_text_progress_bar_new ();
|
||||
plugin->message = NULL;
|
||||
|
||||
plugin->views = ply_list_new ();
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
|
|
@ -101,6 +336,31 @@ detach_from_event_loop (ply_boot_splash_plugin_t *plugin)
|
|||
ply_trace ("detaching from event loop");
|
||||
}
|
||||
|
||||
static void
|
||||
free_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_free (view);
|
||||
ply_list_remove_node (plugin->views, node);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
ply_list_free (plugin->views);
|
||||
plugin->views = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
|
|
@ -109,14 +369,12 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
if (plugin == NULL)
|
||||
return;
|
||||
|
||||
remove_handlers (plugin);
|
||||
|
||||
/* It doesn't ever make sense to keep this plugin on screen
|
||||
* after exit
|
||||
*/
|
||||
hide_splash_screen (plugin, plugin->loop);
|
||||
|
||||
ply_text_progress_bar_free (plugin->progress_bar);
|
||||
free_views (plugin);
|
||||
if (plugin->message != NULL)
|
||||
free (plugin->message);
|
||||
|
||||
|
|
@ -126,67 +384,52 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
static void
|
||||
show_message (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
int window_width, window_height;
|
||||
ply_list_node_t *node;
|
||||
|
||||
window_width = ply_window_get_number_of_text_columns (plugin->window);
|
||||
window_height = ply_window_get_number_of_text_rows (plugin->window);
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
ply_window_set_text_cursor_position (plugin->window,
|
||||
0, window_height / 2);
|
||||
ply_window_clear_text_line (plugin->window);
|
||||
ply_window_set_text_cursor_position (plugin->window,
|
||||
(window_width - strlen (plugin->message)) / 2,
|
||||
window_height / 2);
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
write (STDOUT_FILENO, plugin->message, strlen (plugin->message));
|
||||
view_show_message (view);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
start_animation (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->loop != NULL);
|
||||
|
||||
redraw_views (plugin);
|
||||
|
||||
if (plugin->message != NULL)
|
||||
show_message (plugin);
|
||||
|
||||
if (plugin->is_animating)
|
||||
return;
|
||||
|
||||
ply_window_set_color_hex_value (plugin->window,
|
||||
PLY_WINDOW_COLOR_BLACK,
|
||||
0x000000);
|
||||
ply_window_set_color_hex_value (plugin->window,
|
||||
PLY_WINDOW_COLOR_WHITE,
|
||||
0xffffff);
|
||||
ply_window_set_color_hex_value (plugin->window,
|
||||
PLY_WINDOW_COLOR_BLUE,
|
||||
0x0073B3);
|
||||
ply_window_set_color_hex_value (plugin->window,
|
||||
PLY_WINDOW_COLOR_BROWN,
|
||||
0x00457E);
|
||||
#if 0
|
||||
ply_window_set_color_hex_value (plugin->window,
|
||||
PLY_WINDOW_COLOR_BLUE,
|
||||
PLYMOUTH_BACKGROUND_START_COLOR);
|
||||
ply_window_set_color_hex_value (plugin->window,
|
||||
PLY_WINDOW_COLOR_GREEN,
|
||||
PLYMOUTH_BACKGROUND_COLOR);
|
||||
#endif
|
||||
|
||||
ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_BLACK);
|
||||
ply_window_clear_screen (plugin->window);
|
||||
ply_window_hide_text_cursor (plugin->window);
|
||||
|
||||
if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN)
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_text_progress_bar_hide (plugin->progress_bar);
|
||||
return;
|
||||
}
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
ply_text_progress_bar_show (plugin->progress_bar,
|
||||
plugin->window);
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_start_animation (view);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
plugin->is_animating = true;
|
||||
}
|
||||
|
|
@ -194,6 +437,8 @@ start_animation (ply_boot_splash_plugin_t *plugin)
|
|||
static void
|
||||
stop_animation (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->loop != NULL);
|
||||
|
||||
|
|
@ -202,64 +447,97 @@ stop_animation (ply_boot_splash_plugin_t *plugin)
|
|||
|
||||
plugin->is_animating = false;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
ply_text_progress_bar_hide (plugin->progress_bar);
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_text_progress_bar_hide (view->progress_bar);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
redraw_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->loop != NULL);
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_text_display_clear_screen (view->display);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_draw (ply_boot_splash_plugin_t *plugin,
|
||||
ply_terminal_t *terminal,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_BLUE);
|
||||
ply_window_clear_screen (plugin->window);
|
||||
clear_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
on_erase (ply_boot_splash_plugin_t *plugin,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
add_text_display (ply_boot_splash_plugin_t *plugin,
|
||||
ply_text_display_t *display)
|
||||
{
|
||||
ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_BLUE);
|
||||
ply_window_clear_screen (plugin->window);
|
||||
view_t *view;
|
||||
|
||||
view = view_new (plugin, display);
|
||||
|
||||
ply_text_display_set_draw_handler (view->display,
|
||||
(ply_text_display_draw_handler_t)
|
||||
on_draw, view);
|
||||
|
||||
ply_list_append_data (plugin->views, view);
|
||||
}
|
||||
|
||||
static void
|
||||
add_handlers (ply_boot_splash_plugin_t *plugin)
|
||||
remove_text_display (ply_boot_splash_plugin_t *plugin,
|
||||
ply_text_display_t *display)
|
||||
{
|
||||
ply_window_set_draw_handler (plugin->window,
|
||||
(ply_window_draw_handler_t)
|
||||
on_draw, plugin);
|
||||
ply_window_set_erase_handler (plugin->window,
|
||||
(ply_window_erase_handler_t)
|
||||
on_erase, plugin);
|
||||
}
|
||||
ply_list_node_t *node;
|
||||
|
||||
static void
|
||||
remove_handlers (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
view_t *view;
|
||||
ply_list_node_t *next_node;
|
||||
|
||||
ply_window_set_draw_handler (plugin->window, NULL, NULL);
|
||||
ply_window_set_erase_handler (plugin->window, NULL, NULL);
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
}
|
||||
if (view->display == display)
|
||||
{
|
||||
ply_text_display_set_draw_handler (view->display,
|
||||
NULL, NULL);
|
||||
view_free (view);
|
||||
ply_list_remove_node (plugin->views, node);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
add_window (ply_boot_splash_plugin_t *plugin,
|
||||
ply_window_t *window)
|
||||
{
|
||||
plugin->window = window;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_window (ply_boot_splash_plugin_t *plugin,
|
||||
ply_window_t *window)
|
||||
{
|
||||
plugin->window = NULL;
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -270,11 +548,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
{
|
||||
assert (plugin != NULL);
|
||||
|
||||
add_handlers (plugin);
|
||||
|
||||
ply_window_hide_text_cursor (plugin->window);
|
||||
ply_window_set_text_cursor_position (plugin->window, 0, 0);
|
||||
|
||||
plugin->loop = loop;
|
||||
plugin->mode = mode;
|
||||
ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
|
||||
|
|
@ -301,15 +574,30 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin,
|
|||
double duration,
|
||||
double percent_done)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
double total_duration;
|
||||
|
||||
total_duration = duration / percent_done;
|
||||
|
||||
/* Hi Will! */
|
||||
/* Fun made-up smoothing function to make the growth asymptotic:
|
||||
* fraction(time,estimate)=1-2^(-(time^1.45)/estimate) */
|
||||
percent_done = 1.0 - pow (2.0, -pow (duration, 1.45) / total_duration) * (1.0 - percent_done);
|
||||
|
||||
ply_text_progress_bar_set_percent_done (plugin->progress_bar, percent_done);
|
||||
ply_text_progress_bar_draw (plugin->progress_bar);
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_text_progress_bar_set_percent_done (view->progress_bar, percent_done);
|
||||
ply_text_progress_bar_draw (view->progress_bar);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -331,23 +619,21 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
detach_from_event_loop (plugin);
|
||||
}
|
||||
|
||||
if (plugin->window != NULL)
|
||||
{
|
||||
remove_handlers (plugin);
|
||||
|
||||
ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT);
|
||||
ply_window_clear_screen (plugin->window);
|
||||
ply_window_show_text_cursor (plugin->window);
|
||||
ply_window_reset_colors (plugin->window);
|
||||
}
|
||||
|
||||
hide_views (plugin);
|
||||
ply_show_new_kernel_messages (true);
|
||||
}
|
||||
|
||||
static void
|
||||
display_normal (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
start_animation(plugin);
|
||||
pause_views (plugin);
|
||||
if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL)
|
||||
{
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
|
||||
start_animation (plugin);
|
||||
redraw_views (plugin);
|
||||
}
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -361,40 +647,76 @@ display_message (ply_boot_splash_plugin_t *plugin,
|
|||
start_animation (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
show_password_prompt (ply_boot_splash_plugin_t *plugin,
|
||||
const char *prompt,
|
||||
int bullets)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
int i;
|
||||
char *entered_text;
|
||||
|
||||
entered_text = calloc (bullets + 1, sizeof (char));
|
||||
|
||||
for (i = 0; i < bullets; i++)
|
||||
entered_text[i] = '*';
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_show_prompt (view, prompt, entered_text);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
free (entered_text);
|
||||
}
|
||||
|
||||
static void
|
||||
show_prompt (ply_boot_splash_plugin_t *plugin,
|
||||
const char *prompt,
|
||||
const char *text)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_show_prompt (view, prompt, text);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_password (ply_boot_splash_plugin_t *plugin,
|
||||
const char *prompt,
|
||||
int bullets)
|
||||
{
|
||||
int window_width, window_height;
|
||||
int i;
|
||||
stop_animation (plugin);
|
||||
ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT);
|
||||
ply_window_clear_screen (plugin->window);
|
||||
pause_views (plugin);
|
||||
if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
|
||||
stop_animation (plugin);
|
||||
|
||||
window_width = ply_window_get_number_of_text_columns (plugin->window);
|
||||
window_height = ply_window_get_number_of_text_rows (plugin->window);
|
||||
|
||||
if (!prompt)
|
||||
prompt = "Password";
|
||||
|
||||
ply_window_set_text_cursor_position (plugin->window, 0, window_height / 2);
|
||||
|
||||
for (i=0; i < window_width; i++)
|
||||
{
|
||||
write (STDOUT_FILENO, " ", strlen (" "));
|
||||
}
|
||||
ply_window_set_text_cursor_position (plugin->window,
|
||||
window_width / 2 - (strlen (prompt)),
|
||||
window_height / 2);
|
||||
write (STDOUT_FILENO, prompt, strlen (prompt));
|
||||
write (STDOUT_FILENO, ":", strlen (":"));
|
||||
|
||||
for (i=0; i < bullets; i++)
|
||||
{
|
||||
write (STDOUT_FILENO, "*", strlen ("*"));
|
||||
}
|
||||
ply_window_show_text_cursor (plugin->window);
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY;
|
||||
|
||||
if (!prompt)
|
||||
prompt = "Password";
|
||||
|
||||
show_password_prompt (plugin, prompt, bullets);
|
||||
|
||||
redraw_views (plugin);
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -402,36 +724,21 @@ display_question (ply_boot_splash_plugin_t *plugin,
|
|||
const char *prompt,
|
||||
const char *entry_text)
|
||||
{
|
||||
int window_width, window_height;
|
||||
int i;
|
||||
stop_animation (plugin);
|
||||
ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT);
|
||||
ply_window_clear_screen (plugin->window);
|
||||
pause_views (plugin);
|
||||
if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
|
||||
stop_animation (plugin);
|
||||
|
||||
window_width = ply_window_get_number_of_text_columns (plugin->window);
|
||||
window_height = ply_window_get_number_of_text_rows (plugin->window);
|
||||
|
||||
if (!prompt)
|
||||
prompt = "";
|
||||
|
||||
ply_window_set_text_cursor_position (plugin->window,
|
||||
0, window_height / 2);
|
||||
|
||||
for (i=0; i < window_width; i++)
|
||||
{
|
||||
write (STDOUT_FILENO, " ", strlen (" "));
|
||||
}
|
||||
ply_window_set_text_cursor_position (plugin->window,
|
||||
window_width / 2 - (strlen (prompt)),
|
||||
window_height / 2);
|
||||
write (STDOUT_FILENO, prompt, strlen (prompt));
|
||||
write (STDOUT_FILENO, ":", strlen (":"));
|
||||
|
||||
write (STDOUT_FILENO, entry_text, strlen (entry_text));
|
||||
ply_window_show_text_cursor (plugin->window);
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY;
|
||||
|
||||
if (!prompt)
|
||||
prompt = "Password";
|
||||
|
||||
show_prompt (plugin, prompt, entry_text);
|
||||
|
||||
redraw_views (plugin);
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
|
||||
ply_boot_splash_plugin_interface_t *
|
||||
ply_boot_splash_plugin_get_interface (void)
|
||||
{
|
||||
|
|
@ -439,8 +746,8 @@ ply_boot_splash_plugin_get_interface (void)
|
|||
{
|
||||
.create_plugin = create_plugin,
|
||||
.destroy_plugin = destroy_plugin,
|
||||
.add_window = add_window,
|
||||
.remove_window = remove_window,
|
||||
.add_text_display = add_text_display,
|
||||
.remove_text_display = remove_text_display,
|
||||
.show_splash_screen = show_splash_screen,
|
||||
.update_status = update_status,
|
||||
.on_boot_progress = on_boot_progress,
|
||||
|
|
|
|||
|
|
@ -49,16 +49,14 @@
|
|||
#include "ply-list.h"
|
||||
#include "ply-progress-bar.h"
|
||||
#include "ply-logger.h"
|
||||
#include "ply-frame-buffer.h"
|
||||
#include "ply-image.h"
|
||||
#include "ply-trigger.h"
|
||||
#include "ply-pixel-buffer.h"
|
||||
#include "ply-pixel-display.h"
|
||||
#include "ply-utils.h"
|
||||
#include "ply-window.h"
|
||||
|
||||
#include "ply-throbber.h"
|
||||
|
||||
#include <linux/kd.h>
|
||||
|
||||
#ifndef FRAMES_PER_SECOND
|
||||
#define FRAMES_PER_SECOND 30
|
||||
#endif
|
||||
|
|
@ -73,21 +71,27 @@ typedef enum {
|
|||
PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY
|
||||
} ply_boot_splash_display_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
ply_pixel_display_t *display;
|
||||
ply_entry_t *entry;
|
||||
ply_throbber_t *throbber;
|
||||
ply_progress_bar_t *progress_bar;
|
||||
ply_label_t *label;
|
||||
ply_rectangle_t box_area, lock_area, logo_area, bar_area;
|
||||
} view_t;
|
||||
|
||||
struct _ply_boot_splash_plugin
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
ply_boot_splash_mode_t mode;
|
||||
ply_frame_buffer_t *frame_buffer;
|
||||
ply_frame_buffer_area_t box_area, lock_area, logo_area, bar_area;
|
||||
ply_image_t *logo_image;
|
||||
ply_image_t *lock_image;
|
||||
ply_image_t *box_image;
|
||||
ply_window_t *window;
|
||||
ply_list_t *views;
|
||||
|
||||
ply_entry_t *entry;
|
||||
ply_throbber_t *throbber;
|
||||
ply_label_t *label;
|
||||
ply_progress_bar_t *progress_bar;
|
||||
char *image_dir;
|
||||
ply_boot_splash_display_type_t state;
|
||||
|
||||
ply_trigger_t *idle_trigger;
|
||||
|
|
@ -97,11 +101,276 @@ struct _ply_boot_splash_plugin
|
|||
uint32_t is_animating : 1;
|
||||
};
|
||||
|
||||
static void add_handlers (ply_boot_splash_plugin_t *plugin);
|
||||
static void remove_handlers (ply_boot_splash_plugin_t *plugin);
|
||||
|
||||
static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin);
|
||||
|
||||
static view_t *
|
||||
view_new (ply_boot_splash_plugin_t *plugin,
|
||||
ply_pixel_display_t *display)
|
||||
{
|
||||
view_t *view;
|
||||
|
||||
view = calloc (1, sizeof (view_t));
|
||||
view->plugin = plugin;
|
||||
view->display = display;
|
||||
|
||||
view->entry = ply_entry_new (plugin->image_dir);
|
||||
view->throbber = ply_throbber_new (plugin->image_dir,
|
||||
"throbber-");
|
||||
view->progress_bar = ply_progress_bar_new ();
|
||||
view->label = ply_label_new ();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
static void
|
||||
view_free (view_t *view)
|
||||
{
|
||||
|
||||
ply_entry_free (view->entry);
|
||||
ply_throbber_free (view->throbber);
|
||||
ply_progress_bar_free (view->progress_bar);
|
||||
ply_label_free (view->label);
|
||||
|
||||
free (view);
|
||||
}
|
||||
|
||||
static void
|
||||
free_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_free (view);
|
||||
ply_list_remove_node (plugin->views, node);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
ply_list_free (plugin->views);
|
||||
plugin->views = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
view_load (view_t *view)
|
||||
{
|
||||
ply_trace ("loading entry");
|
||||
if (!ply_entry_load (view->entry))
|
||||
return false;
|
||||
|
||||
ply_trace ("loading throbber");
|
||||
if (!ply_throbber_load (view->throbber))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
load_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
bool view_loaded;
|
||||
|
||||
view_loaded = false;
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
if (view_load (view))
|
||||
view_loaded = true;
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
return view_loaded;
|
||||
}
|
||||
|
||||
static void
|
||||
view_redraw (view_t *view)
|
||||
{
|
||||
unsigned long screen_width, screen_height;
|
||||
|
||||
screen_width = ply_pixel_display_get_width (view->display);
|
||||
screen_height = ply_pixel_display_get_height (view->display);
|
||||
|
||||
ply_pixel_display_draw_area (view->display, 0, 0,
|
||||
screen_width, screen_height);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_redraw (view);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pause_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_pixel_display_pause_updates (view->display);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unpause_views (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_pixel_display_unpause_updates (view->display);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
view_start_animation (view_t *view)
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
|
||||
unsigned long screen_width, screen_height;
|
||||
long width, height;
|
||||
|
||||
assert (view != NULL);
|
||||
|
||||
plugin = view->plugin;
|
||||
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->loop != NULL);
|
||||
|
||||
screen_width = ply_pixel_display_get_width (view->display);
|
||||
screen_height = ply_pixel_display_get_height (view->display);
|
||||
|
||||
ply_pixel_display_draw_area (view->display, 0, 0,
|
||||
screen_width, screen_height);
|
||||
|
||||
if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN)
|
||||
return;
|
||||
|
||||
width = ply_throbber_get_width (view->throbber);
|
||||
height = ply_throbber_get_height (view->throbber);
|
||||
ply_throbber_start (view->throbber,
|
||||
plugin->loop,
|
||||
view->display,
|
||||
screen_width / 2.0 - width / 2.0,
|
||||
view->logo_area.y + view->logo_area.height + height / 2);
|
||||
ply_progress_bar_show (view->progress_bar,
|
||||
view->display,
|
||||
0, screen_height - ply_progress_bar_get_height (view->progress_bar));
|
||||
view_redraw (view);
|
||||
}
|
||||
|
||||
static void
|
||||
view_show_prompt (view_t *view,
|
||||
const char *prompt)
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
int x, y;
|
||||
int entry_width, entry_height;
|
||||
|
||||
assert (view != NULL);
|
||||
|
||||
plugin = view->plugin;
|
||||
|
||||
if (ply_entry_is_hidden (view->entry))
|
||||
{
|
||||
unsigned long screen_width, screen_height;
|
||||
|
||||
screen_width = ply_pixel_display_get_width (view->display);
|
||||
screen_height = ply_pixel_display_get_height (view->display);
|
||||
|
||||
view->box_area.width = ply_image_get_width (plugin->box_image);
|
||||
view->box_area.height = ply_image_get_height (plugin->box_image);
|
||||
view->box_area.x = screen_width / 2.0 - view->box_area.width / 2.0;
|
||||
view->box_area.y = screen_height / 2.0 - view->box_area.height / 2.0;
|
||||
|
||||
view->lock_area.width = ply_image_get_width (plugin->lock_image);
|
||||
view->lock_area.height = ply_image_get_height (plugin->lock_image);
|
||||
|
||||
entry_width = ply_entry_get_width (view->entry);
|
||||
entry_height = ply_entry_get_height (view->entry);
|
||||
|
||||
x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0 + view->lock_area.width;
|
||||
y = screen_height / 2.0 - entry_height / 2.0;
|
||||
|
||||
view->lock_area.x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0;
|
||||
view->lock_area.y = screen_height / 2.0 - view->lock_area.height / 2.0;
|
||||
|
||||
ply_entry_show (view->entry, plugin->loop, view->display, x, y);
|
||||
}
|
||||
|
||||
if (prompt != NULL)
|
||||
{
|
||||
int label_width, label_height;
|
||||
|
||||
ply_label_set_text (view->label, prompt);
|
||||
label_width = ply_label_get_width (view->label);
|
||||
label_height = ply_label_get_height (view->label);
|
||||
|
||||
x = view->box_area.x + view->lock_area.width / 2;
|
||||
y = view->box_area.y + view->box_area.height;
|
||||
|
||||
ply_label_show (view->label, view->display, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
view_hide_prompt (view_t *view)
|
||||
{
|
||||
assert (view != NULL);
|
||||
|
||||
ply_entry_hide (view->entry);
|
||||
ply_label_hide (view->label);
|
||||
}
|
||||
|
||||
static ply_boot_splash_plugin_t *
|
||||
create_plugin (ply_key_file_t *key_file)
|
||||
{
|
||||
|
|
@ -122,11 +391,8 @@ create_plugin (ply_key_file_t *key_file)
|
|||
plugin->box_image = ply_image_new (image_path);
|
||||
free (image_path);
|
||||
|
||||
plugin->entry = ply_entry_new (image_dir);
|
||||
plugin->throbber = ply_throbber_new (image_dir, "throbber-");
|
||||
plugin->label = ply_label_new ();
|
||||
plugin->progress_bar = ply_progress_bar_new ();
|
||||
free(image_dir);
|
||||
plugin->image_dir = image_dir;
|
||||
plugin->views = ply_list_new ();
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
|
@ -137,8 +403,6 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
if (plugin == NULL)
|
||||
return;
|
||||
|
||||
remove_handlers (plugin);
|
||||
|
||||
if (plugin->loop != NULL)
|
||||
{
|
||||
ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t)
|
||||
|
|
@ -150,83 +414,83 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
ply_image_free (plugin->logo_image);
|
||||
ply_image_free (plugin->box_image);
|
||||
ply_image_free (plugin->lock_image);
|
||||
ply_entry_free (plugin->entry);
|
||||
ply_throbber_free (plugin->throbber);
|
||||
ply_label_free (plugin->label);
|
||||
ply_progress_bar_free (plugin->progress_bar);
|
||||
|
||||
free_views (plugin);
|
||||
|
||||
free (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_background (ply_boot_splash_plugin_t *plugin,
|
||||
ply_frame_buffer_area_t *area)
|
||||
draw_background (view_t *view,
|
||||
ply_pixel_buffer_t *pixel_buffer,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
ply_frame_buffer_area_t screen_area;
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
ply_rectangle_t area;
|
||||
|
||||
if (area == NULL)
|
||||
{
|
||||
ply_frame_buffer_get_size (plugin->frame_buffer, &screen_area);
|
||||
area = &screen_area;
|
||||
}
|
||||
plugin = view->plugin;
|
||||
|
||||
ply_window_erase_area (plugin->window, area->x, area->y,
|
||||
area->width, area->height);
|
||||
area.x = x;
|
||||
area.y = y;
|
||||
area.width = width;
|
||||
area.height = height;
|
||||
|
||||
ply_pixel_buffer_fill_with_gradient (pixel_buffer, &area,
|
||||
PLYMOUTH_BACKGROUND_START_COLOR,
|
||||
PLYMOUTH_BACKGROUND_END_COLOR);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_logo (ply_boot_splash_plugin_t *plugin)
|
||||
draw_logo (view_t *view,
|
||||
ply_pixel_buffer_t *pixel_buffer)
|
||||
{
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
uint32_t *logo_data;
|
||||
unsigned long screen_width, screen_height;
|
||||
long width, height;
|
||||
|
||||
plugin = view->plugin;
|
||||
|
||||
screen_width = ply_pixel_display_get_width (view->display);
|
||||
screen_height = ply_pixel_display_get_height (view->display);
|
||||
|
||||
width = ply_image_get_width (plugin->logo_image);
|
||||
height = ply_image_get_height (plugin->logo_image);
|
||||
logo_data = ply_image_get_data (plugin->logo_image);
|
||||
ply_frame_buffer_get_size (plugin->frame_buffer, &plugin->logo_area);
|
||||
plugin->logo_area.x = (plugin->logo_area.width / 2) - (width / 2);
|
||||
plugin->logo_area.y = (plugin->logo_area.height / 2) - (height / 2);
|
||||
plugin->logo_area.width = width;
|
||||
plugin->logo_area.height = height;
|
||||
view->logo_area.x = (screen_width / 2) - (width / 2);
|
||||
view->logo_area.y = (screen_height / 2) - (height / 2);
|
||||
view->logo_area.width = width;
|
||||
view->logo_area.height = height;
|
||||
|
||||
ply_frame_buffer_pause_updates (plugin->frame_buffer);
|
||||
draw_background (plugin, &plugin->logo_area);
|
||||
ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
|
||||
&plugin->logo_area, 0, 0,
|
||||
ply_pixel_buffer_fill_with_argb32_data (pixel_buffer,
|
||||
&view->logo_area, 0, 0,
|
||||
logo_data);
|
||||
ply_frame_buffer_unpause_updates (plugin->frame_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
start_animation (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
|
||||
long width, height;
|
||||
ply_frame_buffer_area_t area;
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->loop != NULL);
|
||||
ply_list_node_t *node;
|
||||
|
||||
if (plugin->is_animating)
|
||||
return;
|
||||
|
||||
draw_background (plugin, NULL);
|
||||
draw_logo (plugin);
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN)
|
||||
return;
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_frame_buffer_get_size (plugin->frame_buffer, &area);
|
||||
view_start_animation (view);
|
||||
|
||||
width = ply_throbber_get_width (plugin->throbber);
|
||||
height = ply_throbber_get_height (plugin->throbber);
|
||||
ply_throbber_start (plugin->throbber,
|
||||
plugin->loop,
|
||||
plugin->window,
|
||||
area.width / 2.0 - width / 2.0,
|
||||
plugin->logo_area.y + plugin->logo_area.height + height / 2);
|
||||
ply_progress_bar_show (plugin->progress_bar,
|
||||
plugin->window,
|
||||
0, area.height - ply_progress_bar_get_height (plugin->progress_bar));
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
plugin->is_animating = true;
|
||||
}
|
||||
|
|
@ -235,6 +499,8 @@ static void
|
|||
stop_animation (ply_boot_splash_plugin_t *plugin,
|
||||
ply_trigger_t *trigger)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->loop != NULL);
|
||||
|
||||
|
|
@ -243,30 +509,25 @@ stop_animation (ply_boot_splash_plugin_t *plugin,
|
|||
|
||||
plugin->is_animating = false;
|
||||
|
||||
ply_progress_bar_hide (plugin->progress_bar);
|
||||
ply_throbber_stop (plugin->throbber, trigger);
|
||||
|
||||
#ifdef ENABLE_FADE_OUT
|
||||
int i;
|
||||
for (i = 0; i < 10; i++)
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_frame_buffer_fill_with_hex_color_at_opacity (plugin->frame_buffer, NULL,
|
||||
PLYMOUTH_BACKGROUND_COLOR,
|
||||
.1 + .1 * i);
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_progress_bar_hide (view->progress_bar);
|
||||
if (trigger != NULL)
|
||||
ply_trigger_ignore_next_pull (trigger);
|
||||
ply_throbber_stop (view->throbber, trigger);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
|
||||
ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer, NULL,
|
||||
PLYMOUTH_BACKGROUND_COLOR);
|
||||
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL,
|
||||
0.0, 0.0, 0.0, .05 + .05 * i);
|
||||
}
|
||||
|
||||
ply_frame_buffer_fill_with_color (plugin->frame_buffer, NULL,
|
||||
0.0, 0.0, 0.0, 1.0);
|
||||
#endif
|
||||
if (trigger != NULL)
|
||||
ply_trigger_pull (trigger, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -274,7 +535,6 @@ on_interrupt (ply_boot_splash_plugin_t *plugin)
|
|||
{
|
||||
ply_event_loop_exit (plugin->loop, 1);
|
||||
stop_animation (plugin, NULL);
|
||||
ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -283,119 +543,93 @@ detach_from_event_loop (ply_boot_splash_plugin_t *plugin)
|
|||
plugin->loop = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
on_keyboard_input (ply_boot_splash_plugin_t *plugin,
|
||||
const char *keyboard_input,
|
||||
size_t character_size)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_backspace (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_enter (ply_boot_splash_plugin_t *plugin,
|
||||
const char *text)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_draw (ply_boot_splash_plugin_t *plugin,
|
||||
static void
|
||||
on_draw (view_t *view,
|
||||
ply_pixel_buffer_t *pixel_buffer,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
ply_frame_buffer_area_t area;
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
ply_rectangle_t area;
|
||||
|
||||
area.x = x;
|
||||
area.y = y;
|
||||
area.width = width;
|
||||
area.height = height;
|
||||
|
||||
ply_frame_buffer_pause_updates (plugin->frame_buffer);
|
||||
draw_background (plugin, &area);
|
||||
plugin = view->plugin;
|
||||
|
||||
if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY ||
|
||||
draw_background (view, pixel_buffer, x, y, width, height);
|
||||
|
||||
if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY ||
|
||||
plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY )
|
||||
{
|
||||
ply_entry_draw (plugin->entry);
|
||||
ply_label_draw (plugin->label);
|
||||
uint32_t *box_data, *lock_data;
|
||||
|
||||
box_data = ply_image_get_data (plugin->box_image);
|
||||
ply_pixel_buffer_fill_with_argb32_data (pixel_buffer,
|
||||
&view->box_area, 0, 0,
|
||||
box_data);
|
||||
ply_entry_draw_area (view->entry, pixel_buffer, x, y, width, height);
|
||||
ply_label_draw_area (view->label, pixel_buffer, x, y, width, height);
|
||||
lock_data = ply_image_get_data (plugin->lock_image);
|
||||
ply_pixel_buffer_fill_with_argb32_data (pixel_buffer,
|
||||
&view->lock_area, 0, 0,
|
||||
lock_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_logo (plugin);
|
||||
ply_progress_bar_draw (plugin->progress_bar);
|
||||
draw_logo (view, pixel_buffer);
|
||||
ply_throbber_draw_area (view->throbber,
|
||||
pixel_buffer, x, y, width, height);
|
||||
ply_progress_bar_draw_area (view->progress_bar,
|
||||
pixel_buffer, x, y, width, height);
|
||||
}
|
||||
ply_frame_buffer_unpause_updates (plugin->frame_buffer);
|
||||
}
|
||||
|
||||
void
|
||||
on_erase (ply_boot_splash_plugin_t *plugin,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
ply_frame_buffer_area_t area;
|
||||
|
||||
area.x = x;
|
||||
area.y = y;
|
||||
area.width = width;
|
||||
area.height = height;
|
||||
|
||||
ply_frame_buffer_fill_with_gradient (plugin->frame_buffer, &area,
|
||||
PLYMOUTH_BACKGROUND_START_COLOR,
|
||||
PLYMOUTH_BACKGROUND_END_COLOR);
|
||||
}
|
||||
|
||||
static void
|
||||
add_handlers (ply_boot_splash_plugin_t *plugin)
|
||||
add_pixel_display (ply_boot_splash_plugin_t *plugin,
|
||||
ply_pixel_display_t *display)
|
||||
{
|
||||
ply_window_add_keyboard_input_handler (plugin->window,
|
||||
(ply_window_keyboard_input_handler_t)
|
||||
on_keyboard_input, plugin);
|
||||
ply_window_add_backspace_handler (plugin->window,
|
||||
(ply_window_backspace_handler_t)
|
||||
on_backspace, plugin);
|
||||
ply_window_add_enter_handler (plugin->window,
|
||||
(ply_window_enter_handler_t)
|
||||
on_enter, plugin);
|
||||
view_t *view;
|
||||
|
||||
ply_window_set_draw_handler (plugin->window,
|
||||
(ply_window_draw_handler_t)
|
||||
on_draw, plugin);
|
||||
view = view_new (plugin, display);
|
||||
|
||||
ply_window_set_erase_handler (plugin->window,
|
||||
(ply_window_erase_handler_t)
|
||||
on_erase, plugin);
|
||||
ply_pixel_display_set_draw_handler (view->display,
|
||||
(ply_pixel_display_draw_handler_t)
|
||||
on_draw, view);
|
||||
|
||||
ply_list_append_data (plugin->views, view);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_handlers (ply_boot_splash_plugin_t *plugin)
|
||||
remove_pixel_display (ply_boot_splash_plugin_t *plugin,
|
||||
ply_pixel_display_t *display)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input);
|
||||
ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace);
|
||||
ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter);
|
||||
ply_window_set_draw_handler (plugin->window, NULL, NULL);
|
||||
ply_window_set_erase_handler (plugin->window, NULL, NULL);
|
||||
}
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
view_t *view;
|
||||
ply_list_node_t *next_node;
|
||||
|
||||
static void
|
||||
add_window (ply_boot_splash_plugin_t *plugin,
|
||||
ply_window_t *window)
|
||||
{
|
||||
plugin->window = window;
|
||||
}
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
static void
|
||||
remove_window (ply_boot_splash_plugin_t *plugin,
|
||||
ply_window_t *window)
|
||||
{
|
||||
plugin->window = NULL;
|
||||
if (view->display == display)
|
||||
{
|
||||
|
||||
ply_pixel_display_set_draw_handler (view->display, NULL, NULL);
|
||||
view_free (view);
|
||||
ply_list_remove_node (plugin->views, node);
|
||||
return;
|
||||
}
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -407,8 +641,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
assert (plugin != NULL);
|
||||
assert (plugin->logo_image != NULL);
|
||||
|
||||
add_handlers (plugin);
|
||||
|
||||
plugin->loop = loop;
|
||||
plugin->mode = mode;
|
||||
|
||||
|
|
@ -424,19 +656,11 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
if (!ply_image_load (plugin->box_image))
|
||||
return false;
|
||||
|
||||
ply_trace ("loading entry");
|
||||
if (!ply_entry_load (plugin->entry))
|
||||
return false;
|
||||
|
||||
ply_trace ("loading throbber");
|
||||
if (!ply_throbber_load (plugin->throbber))
|
||||
return false;
|
||||
|
||||
ply_trace ("setting graphics mode");
|
||||
if (!ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS))
|
||||
return false;
|
||||
|
||||
plugin->frame_buffer = ply_window_get_frame_buffer (plugin->window);
|
||||
if (!load_views (plugin))
|
||||
{
|
||||
ply_trace ("couldn't load views");
|
||||
return false;
|
||||
}
|
||||
|
||||
ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
|
||||
detach_from_event_loop,
|
||||
|
|
@ -447,9 +671,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
(ply_event_handler_t)
|
||||
on_interrupt, plugin);
|
||||
|
||||
ply_window_clear_screen (plugin->window);
|
||||
ply_window_hide_text_cursor (plugin->window);
|
||||
|
||||
ply_trace ("starting boot animation");
|
||||
start_animation (plugin);
|
||||
|
||||
|
|
@ -470,6 +691,7 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin,
|
|||
double duration,
|
||||
double percent_done)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
double total_duration;
|
||||
|
||||
total_duration = duration / percent_done;
|
||||
|
|
@ -478,8 +700,21 @@ on_boot_progress (ply_boot_splash_plugin_t *plugin,
|
|||
* fraction(time,estimate)=1-2^(-(time^1.45)/estimate) */
|
||||
percent_done = 1.0 - pow (2.0, -pow (duration, 1.45) / total_duration) * (1.0 - percent_done);
|
||||
|
||||
ply_progress_bar_set_percent_done (plugin->progress_bar, percent_done);
|
||||
ply_progress_bar_draw (plugin->progress_bar);
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
ply_progress_bar_set_percent_done (view->progress_bar, percent_done);
|
||||
ply_progress_bar_draw (view->progress_bar);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -488,8 +723,6 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
{
|
||||
assert (plugin != NULL);
|
||||
|
||||
remove_handlers (plugin);
|
||||
|
||||
if (plugin->loop != NULL)
|
||||
{
|
||||
stop_animation (plugin, NULL);
|
||||
|
|
@ -500,76 +733,53 @@ hide_splash_screen (ply_boot_splash_plugin_t *plugin,
|
|||
detach_from_event_loop (plugin);
|
||||
}
|
||||
|
||||
plugin->frame_buffer = NULL;
|
||||
plugin->is_visible = false;
|
||||
|
||||
ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_TEXT);
|
||||
}
|
||||
|
||||
static void
|
||||
show_password_prompt (ply_boot_splash_plugin_t *plugin,
|
||||
const char *prompt)
|
||||
const char *text,
|
||||
int number_of_bullets)
|
||||
{
|
||||
ply_frame_buffer_area_t area;
|
||||
int x, y;
|
||||
int entry_width, entry_height;
|
||||
ply_list_node_t *node;
|
||||
|
||||
uint32_t *box_data, *lock_data;
|
||||
|
||||
assert (plugin != NULL);
|
||||
|
||||
if (ply_entry_is_hidden (plugin->entry))
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
draw_background (plugin, NULL);
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
ply_frame_buffer_get_size (plugin->frame_buffer, &area);
|
||||
plugin->box_area.width = ply_image_get_width (plugin->box_image);
|
||||
plugin->box_area.height = ply_image_get_height (plugin->box_image);
|
||||
plugin->box_area.x = area.width / 2.0 - plugin->box_area.width / 2.0;
|
||||
plugin->box_area.y = area.height / 2.0 - plugin->box_area.height / 2.0;
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
plugin->lock_area.width = ply_image_get_width (plugin->lock_image);
|
||||
plugin->lock_area.height = ply_image_get_height (plugin->lock_image);
|
||||
view_show_prompt (view, text);
|
||||
ply_entry_set_bullet_count (view->entry, number_of_bullets);
|
||||
|
||||
entry_width = ply_entry_get_width (plugin->entry);
|
||||
entry_height = ply_entry_get_height (plugin->entry);
|
||||
|
||||
x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0 + plugin->lock_area.width;
|
||||
y = area.height / 2.0 - entry_height / 2.0;
|
||||
|
||||
plugin->lock_area.x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0;
|
||||
plugin->lock_area.y = area.height / 2.0 - plugin->lock_area.height / 2.0;
|
||||
|
||||
box_data = ply_image_get_data (plugin->box_image);
|
||||
ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
|
||||
&plugin->box_area, 0, 0,
|
||||
box_data);
|
||||
|
||||
ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y);
|
||||
|
||||
lock_data = ply_image_get_data (plugin->lock_image);
|
||||
ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
|
||||
&plugin->lock_area, 0, 0,
|
||||
lock_data);
|
||||
node = next_node;
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
static void
|
||||
show_prompt (ply_boot_splash_plugin_t *plugin,
|
||||
const char *prompt,
|
||||
const char *entry_text)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_entry_draw (plugin->entry);
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_show_prompt (view, prompt);
|
||||
ply_entry_set_text (view->entry, entry_text);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
if (prompt != NULL)
|
||||
{
|
||||
int label_width, label_height;
|
||||
|
||||
ply_label_set_text (plugin->label, prompt);
|
||||
label_width = ply_label_get_width (plugin->label);
|
||||
label_height = ply_label_get_height (plugin->label);
|
||||
|
||||
x = plugin->box_area.x + plugin->lock_area.width / 2;
|
||||
y = plugin->box_area.y + plugin->box_area.height;
|
||||
|
||||
ply_label_show (plugin->label, plugin->window, x, y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -585,15 +795,38 @@ become_idle (ply_boot_splash_plugin_t *plugin,
|
|||
stop_animation (plugin, idle_trigger);
|
||||
}
|
||||
|
||||
static void
|
||||
hide_prompt (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
ply_list_node_t *node;
|
||||
|
||||
node = ply_list_get_first_node (plugin->views);
|
||||
while (node != NULL)
|
||||
{
|
||||
ply_list_node_t *next_node;
|
||||
view_t *view;
|
||||
|
||||
view = ply_list_node_get_data (node);
|
||||
next_node = ply_list_get_next_node (plugin->views, node);
|
||||
|
||||
view_hide_prompt (view);
|
||||
|
||||
node = next_node;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_normal (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
pause_views (plugin);
|
||||
if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL)
|
||||
{
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
|
||||
ply_entry_hide (plugin->entry);
|
||||
start_animation(plugin);
|
||||
hide_prompt (plugin);
|
||||
start_animation (plugin);
|
||||
redraw_views (plugin);
|
||||
}
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -601,13 +834,14 @@ display_password (ply_boot_splash_plugin_t *plugin,
|
|||
const char *prompt,
|
||||
int bullets)
|
||||
{
|
||||
pause_views (plugin);
|
||||
if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
|
||||
{
|
||||
stop_animation (plugin, NULL);
|
||||
}
|
||||
stop_animation (plugin, NULL);
|
||||
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY;
|
||||
show_password_prompt (plugin, prompt);
|
||||
ply_entry_set_bullet_count (plugin->entry, bullets);
|
||||
show_password_prompt (plugin, prompt, bullets);
|
||||
redraw_views (plugin);
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -615,14 +849,14 @@ display_question (ply_boot_splash_plugin_t *plugin,
|
|||
const char *prompt,
|
||||
const char *entry_text)
|
||||
{
|
||||
pause_views (plugin);
|
||||
if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
|
||||
{
|
||||
stop_animation (plugin, NULL);
|
||||
}
|
||||
stop_animation (plugin, NULL);
|
||||
|
||||
plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY;
|
||||
show_password_prompt (plugin, prompt);
|
||||
ply_entry_set_text (plugin->entry, entry_text);
|
||||
show_prompt (plugin, prompt, entry_text);
|
||||
redraw_views (plugin);
|
||||
unpause_views (plugin);
|
||||
}
|
||||
|
||||
ply_boot_splash_plugin_interface_t *
|
||||
|
|
@ -632,8 +866,8 @@ ply_boot_splash_plugin_get_interface (void)
|
|||
{
|
||||
.create_plugin = create_plugin,
|
||||
.destroy_plugin = destroy_plugin,
|
||||
.add_window = add_window,
|
||||
.remove_window = remove_window,
|
||||
.add_pixel_display = add_pixel_display,
|
||||
.remove_pixel_display = remove_pixel_display,
|
||||
.show_splash_screen = show_splash_screen,
|
||||
.update_status = update_status,
|
||||
.on_boot_progress = on_boot_progress,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -9,7 +9,6 @@ TESTS =
|
|||
if ENABLE_TESTS
|
||||
include $(srcdir)/ply-boot-server-test.am
|
||||
include $(srcdir)/ply-boot-splash-test.am
|
||||
include $(srcdir)/ply-window-test.am
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = $(TESTS)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,19 @@ ply_boot_splash_test_LDADD = $(PLYMOUTH_LIBS) ../libply/libply.la
|
|||
|
||||
ply_boot_splash_test_SOURCES = \
|
||||
$(srcdir)/../libplybootsplash/ply-boot-splash-plugin.h \
|
||||
$(srcdir)/../libplybootsplash/ply-window.h \
|
||||
$(srcdir)/../libplybootsplash/ply-window.c \
|
||||
$(srcdir)/../libplybootsplash/ply-console.h \
|
||||
$(srcdir)/../libplybootsplash/ply-console.c \
|
||||
$(srcdir)/../libplybootsplash/ply-keyboard.h \
|
||||
$(srcdir)/../libplybootsplash/ply-keyboard.c \
|
||||
$(srcdir)/../libplybootsplash/ply-pixel-buffer.h \
|
||||
$(srcdir)/../libplybootsplash/ply-pixel-buffer.c \
|
||||
$(srcdir)/../libplybootsplash/ply-pixel-display.h \
|
||||
$(srcdir)/../libplybootsplash/ply-pixel-display.c \
|
||||
$(srcdir)/../libplybootsplash/ply-renderer.h \
|
||||
$(srcdir)/../libplybootsplash/ply-renderer.c \
|
||||
$(srcdir)/../libplybootsplash/ply-terminal.h \
|
||||
$(srcdir)/../libplybootsplash/ply-terminal.c \
|
||||
$(srcdir)/../libplybootsplash/ply-text-display.h \
|
||||
$(srcdir)/../libplybootsplash/ply-text-display.c \
|
||||
$(srcdir)/../libplybootsplash/ply-boot-splash.h \
|
||||
$(srcdir)/../libplybootsplash/ply-boot-splash.c
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
TESTS += ply-window-test
|
||||
|
||||
ply_window_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_WINDOW_ENABLE_TEST
|
||||
ply_window_test_LDADD = $(PLYMOUTH_LIBS) ../libply/libply.la
|
||||
|
||||
ply_window_test_SOURCES = \
|
||||
$(srcdir)/../libplybootsplash/ply-window.h \
|
||||
$(srcdir)/../libplybootsplash/ply-window.c
|
||||
Loading…
Add table
Reference in a new issue