mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 03:45:24 +00:00
Pdf_view: load arbitrary *.pdf files, input improvements
The component is no longer loads from '/test.pdf', the first PDF file found in the root directory of the file-system is loaded automatically. The behavior cannot be overridden by configuration. Feed MuPDF with characters from input events to MuPDF rather than translate raw key codes to ASCII. This enables almost all MuPDF key bindings without the need to maintain a lookup table. Mouse navigation has been enabled as well. To print the key-bindings to log, press '?'. Fix #2859
This commit is contained in:
parent
9d8bf1373e
commit
fb0a50c71c
@ -1,17 +1,15 @@
|
||||
set build_components {
|
||||
core init
|
||||
drivers/timer
|
||||
app/pdf_view
|
||||
drivers/framebuffer drivers/input
|
||||
}
|
||||
set build_components { app/pdf_view }
|
||||
|
||||
source ${genode_dir}/repos/base/run/platform_drv.inc
|
||||
append_platform_drv_build_components
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
import_from_depot \
|
||||
genodelabs/src/[base_src] \
|
||||
genodelabs/pkg/[drivers_interactive_pkg] \
|
||||
|
||||
set config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
@ -28,36 +26,22 @@ set config {
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<default caps="100"/>
|
||||
}
|
||||
|
||||
append_if [have_spec sdl] config {
|
||||
<start name="fb_sdl">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides>
|
||||
<service name="Input"/>
|
||||
<service name="Framebuffer"/>
|
||||
</provides>
|
||||
</start>}
|
||||
|
||||
append_platform_drv_config
|
||||
|
||||
append_if [have_spec framebuffer] config {
|
||||
<start name="fb_drv" caps="200">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides><service name="Framebuffer"/></provides>
|
||||
</start>}
|
||||
|
||||
append_if [have_spec ps2] config {
|
||||
<start name="ps2_drv">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Input"/></provides>
|
||||
</start> }
|
||||
|
||||
append config {
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="drivers" caps="1000">
|
||||
<resource name="RAM" quantum="32M" constrain_phys="yes"/>
|
||||
<binary name="init"/>
|
||||
<route>
|
||||
<service name="ROM" label="config"> <parent label="drivers.config"/> </service>
|
||||
<service name="Timer"> <child name="timer"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
<provides>
|
||||
<service name="Input"/> <service name="Framebuffer"/>
|
||||
</provides>
|
||||
</start>
|
||||
<start name="pdf_view" caps="256">
|
||||
<resource name="RAM" quantum="1G"/>
|
||||
<config>
|
||||
@ -86,7 +70,7 @@ if {![file exist bin/test.pdf]} {
|
||||
exit 1
|
||||
}
|
||||
|
||||
set boot_modules {
|
||||
append boot_modules {
|
||||
core init ld.lib.so timer
|
||||
libc.lib.so vfs.lib.so libm.lib.so
|
||||
openjpeg.lib.so freetype.lib.so libpng.lib.so zlib.lib.so jbig2dec.lib.so
|
||||
@ -95,12 +79,6 @@ set boot_modules {
|
||||
test.pdf
|
||||
}
|
||||
|
||||
lappend_if [have_spec linux] boot_modules fb_sdl
|
||||
lappend_if [have_spec framebuffer] boot_modules fb_drv
|
||||
lappend_if [have_spec ps2] boot_modules ps2_drv
|
||||
|
||||
append_platform_drv_boot_modules
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
append qemu_args " -m 768"
|
||||
|
@ -33,6 +33,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
/* libc includes */
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
@ -105,6 +106,16 @@ static void convert_line_rgba_to_rgb565(const unsigned char *rgba_src,
|
||||
}
|
||||
|
||||
|
||||
static int pdf_select(const struct dirent *d)
|
||||
{
|
||||
char const *name = d->d_name;
|
||||
int n = strlen(name);
|
||||
return (n > 4)
|
||||
? (!strncmp(&name[n-4], ".pdf", 4))
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
||||
/**************
|
||||
** PDF view **
|
||||
**************/
|
||||
@ -117,7 +128,6 @@ class Pdf_view
|
||||
* Exception types
|
||||
*/
|
||||
class Non_supported_framebuffer_mode { };
|
||||
class Invalid_input_file_name { };
|
||||
class Unexpected_document_color_depth { };
|
||||
|
||||
private:
|
||||
@ -140,7 +150,7 @@ class Pdf_view
|
||||
handle_resize();
|
||||
}
|
||||
|
||||
Genode::Constructible<Genode::Attached_dataspace> ds;
|
||||
Genode::Constructible<Genode::Attached_dataspace> ds { };
|
||||
|
||||
void handle_resize()
|
||||
{
|
||||
@ -185,7 +195,10 @@ class Pdf_view
|
||||
|
||||
Genode::Signal_handler<Pdf_view> _resize_handler;
|
||||
|
||||
pdfapp_t _pdfapp;
|
||||
pdfapp_t _pdfapp { };
|
||||
|
||||
int _motion_x = 0;
|
||||
int _motion_y = 0;
|
||||
|
||||
public:
|
||||
|
||||
@ -193,10 +206,9 @@ class Pdf_view
|
||||
* Constructor
|
||||
*
|
||||
* \throw Non_supported_framebuffer_mode
|
||||
* \throw Invalid_input_file_name
|
||||
* \throw Unexpected_document_color_depth
|
||||
*/
|
||||
Pdf_view(Genode::Env &env, char const *file_name)
|
||||
Pdf_view(Genode::Env &env)
|
||||
:
|
||||
_framebuffer_mode(0, 0, Framebuffer::Mode::RGB565),
|
||||
_framebuffer(env, _framebuffer_mode),
|
||||
@ -209,12 +221,23 @@ class Pdf_view
|
||||
_update_pdfapp_parameters();
|
||||
_pdfapp.pageno = 0; /* XXX read from config */
|
||||
|
||||
int fd = open(file_name, O_BINARY | O_RDONLY, 0666);
|
||||
if (fd < 0) {
|
||||
Genode::error("Could not open input file \"", file_name, "\", Exiting.");
|
||||
throw Invalid_input_file_name();
|
||||
{
|
||||
struct dirent **list = NULL;
|
||||
if (scandir("/", &list, pdf_select, alphasort) > 0) {
|
||||
|
||||
char const *file_name = list[0]->d_name;
|
||||
int fd = open(file_name, O_BINARY | O_RDONLY, 0666);
|
||||
if (fd < 0) {
|
||||
Genode::error("Could not open input file \"", file_name, "\", Exiting.");
|
||||
exit(fd);
|
||||
}
|
||||
pdfapp_open(&_pdfapp, (char *)file_name, fd, 0);
|
||||
|
||||
} else {
|
||||
Genode::error("failed to find a PDF to open");
|
||||
exit(~0);
|
||||
}
|
||||
}
|
||||
pdfapp_open(&_pdfapp, (char *)file_name, fd, 0);
|
||||
|
||||
if (_pdfapp.image->n != 4) {
|
||||
Genode::error("Unexpected color depth, expected 4, got ",
|
||||
@ -225,9 +248,40 @@ class Pdf_view
|
||||
|
||||
void show();
|
||||
|
||||
void handle_key(int ascii)
|
||||
void handle_input(Input::Event const &ev)
|
||||
{
|
||||
Libc::with_libc([&] () { pdfapp_onkey(&_pdfapp, ascii); });
|
||||
using namespace Input;
|
||||
|
||||
ev.handle_relative_motion([&] (int x, int y) {
|
||||
_motion_x += x;
|
||||
_motion_y += y;
|
||||
});
|
||||
|
||||
ev.handle_absolute_motion([&] (int x, int y) {
|
||||
_motion_x = x;
|
||||
_motion_y = y;
|
||||
});
|
||||
|
||||
if (ev.key_press(BTN_LEFT))
|
||||
pdfapp_onmouse(&_pdfapp, _motion_x, _motion_y, 1, 0, -1);
|
||||
|
||||
if (ev.key_release(BTN_LEFT))
|
||||
pdfapp_onmouse(&_pdfapp, _motion_x, _motion_y, 1, 0, 1);
|
||||
|
||||
ev.handle_press([&] (Keycode, Codepoint glyph) {
|
||||
if ((glyph.value & 0x7f) && !(glyph.value & 0x80)) {
|
||||
pdfapp_onkey(&_pdfapp, glyph.value);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* XXX: wheel pans the view, which doesn't seem to be implemented
|
||||
ev.handle_wheel([&] (int, int y) {
|
||||
pdfapp_onmouse(
|
||||
&_pdfapp, _motion_x, _motion_y,
|
||||
y > 0 ? 4 : 5, 0, 1);
|
||||
});
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
@ -287,17 +341,21 @@ void winrepaint(pdfapp_t *pdfapp)
|
||||
}
|
||||
|
||||
|
||||
void winrepaintsearch(pdfapp_t *)
|
||||
void winrepaintsearch(pdfapp_t *pdfapp)
|
||||
{
|
||||
Genode::warning(__func__, " not implemented");
|
||||
Pdf_view *pdf_view = (Pdf_view *)pdfapp->userdata;
|
||||
pdf_view->show();
|
||||
}
|
||||
|
||||
|
||||
void wincursor(pdfapp_t *, int curs)
|
||||
void wincursor(pdfapp_t *, int)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void windocopy(pdfapp_t*) { }
|
||||
|
||||
|
||||
void winerror(pdfapp_t *, fz_error error)
|
||||
{
|
||||
Genode::error("winerror: error=", error);
|
||||
@ -311,7 +369,10 @@ void winwarn(pdfapp_t *, char *msg)
|
||||
}
|
||||
|
||||
|
||||
void winhelp(pdfapp_t *) { }
|
||||
void winhelp(pdfapp_t *pdfapp)
|
||||
{
|
||||
Genode::log(Genode::Cstring(pdfapp_usage(pdfapp)));
|
||||
}
|
||||
|
||||
|
||||
char *winpassword(pdfapp_t *, char *)
|
||||
@ -321,9 +382,15 @@ char *winpassword(pdfapp_t *, char *)
|
||||
}
|
||||
|
||||
|
||||
void winclose(pdfapp_t *app)
|
||||
void winopenuri(pdfapp_t*, char *s)
|
||||
{
|
||||
Genode::warning(__func__, " not implemented");
|
||||
Genode::log(Genode::Cstring(s));
|
||||
}
|
||||
|
||||
|
||||
void winclose(pdfapp_t *)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
@ -333,12 +400,12 @@ void winreloadfile(pdfapp_t *)
|
||||
}
|
||||
|
||||
|
||||
void wintitle(pdfapp_t *app, char *s)
|
||||
void wintitle(pdfapp_t *, char *)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void winresize(pdfapp_t *app, int w, int h)
|
||||
void winresize(pdfapp_t *, int, int)
|
||||
{
|
||||
}
|
||||
|
||||
@ -347,41 +414,19 @@ void winresize(pdfapp_t *app, int w, int h)
|
||||
** Main program **
|
||||
******************/
|
||||
|
||||
static int keycode_to_ascii(int code)
|
||||
{
|
||||
switch (code) {
|
||||
case Input::KEY_LEFT: return 'h';
|
||||
case Input::KEY_RIGHT: return 'l';
|
||||
case Input::KEY_DOWN: return 'j';
|
||||
case Input::KEY_UP: return 'k';
|
||||
case Input::KEY_PAGEDOWN:
|
||||
case Input::KEY_ENTER: return ' ';
|
||||
case Input::KEY_PAGEUP:
|
||||
case Input::KEY_BACKSPACE: return 'b';
|
||||
case Input::KEY_9: return '-';
|
||||
case Input::KEY_0: return '+';
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct Main
|
||||
{
|
||||
Genode::Env &_env;
|
||||
|
||||
char const *_file_name { "test.pdf" }; /* XXX read from config */
|
||||
|
||||
Pdf_view _pdf_view { _env, _file_name };
|
||||
Pdf_view _pdf_view { _env };
|
||||
Input::Connection _input { _env };
|
||||
|
||||
void _handle_input()
|
||||
{
|
||||
_input.for_each_event([&] (Input::Event const &ev) {
|
||||
ev.handle_press([&] (Input::Keycode key, Genode::Codepoint) {
|
||||
int const ascii = keycode_to_ascii(key);
|
||||
if (ascii) { _pdf_view.handle_key(ascii); }
|
||||
});
|
||||
});
|
||||
Libc::with_libc([&] () {
|
||||
_input.for_each_event([&] (Input::Event const &ev) {
|
||||
_pdf_view.handle_input(ev); }); });
|
||||
}
|
||||
|
||||
Genode::Signal_handler<Main> _input_handler {
|
||||
|
@ -6,5 +6,3 @@ LIBS := base libc mupdf
|
||||
INC_DIR += $(MUPDF_DIR)/apps
|
||||
|
||||
vpath pdfapp.c $(MUPDF_DIR)/apps
|
||||
|
||||
CC_CXX_WARN_STRICT =
|
||||
|
Loading…
x
Reference in New Issue
Block a user