Interactive browsing through a PDF
This patch introduces the basic key handling required to browse through a multi-page PDF document ([page-up] or [enter] -> next page, [page-down] or [backspace] -> previous page).
This commit is contained in:
parent
ea8b113303
commit
3c09a06620
|
@ -14,6 +14,10 @@
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <framebuffer_session/connection.h>
|
#include <framebuffer_session/connection.h>
|
||||||
#include <base/sleep.h>
|
#include <base/sleep.h>
|
||||||
|
#include <input_session/connection.h>
|
||||||
|
#include <input/event.h>
|
||||||
|
#include <input/keycodes.h>
|
||||||
|
#include <timer_session/connection.h>
|
||||||
|
|
||||||
/* MuPDF includes */
|
/* MuPDF includes */
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -116,17 +120,18 @@ class Pdf_view
|
||||||
struct _Framebuffer : Framebuffer::Connection
|
struct _Framebuffer : Framebuffer::Connection
|
||||||
{
|
{
|
||||||
typedef uint16_t pixel_t;
|
typedef uint16_t pixel_t;
|
||||||
int width, height;
|
|
||||||
Framebuffer::Session::Mode mode;
|
Framebuffer::Mode mode;
|
||||||
pixel_t *base;
|
pixel_t *base;
|
||||||
|
|
||||||
_Framebuffer()
|
_Framebuffer()
|
||||||
|
:
|
||||||
|
mode(Framebuffer::Connection::mode()),
|
||||||
|
base(Genode::env()->rm_session()->attach(dataspace()))
|
||||||
{
|
{
|
||||||
info(&width, &height, &mode);
|
PDBG("Framebuffer is %dx%d\n", mode.width(), mode.height());
|
||||||
base = Genode::env()->rm_session()->attach(dataspace());
|
|
||||||
PDBG("Framebuffer is %dx%d\n", width, height);
|
|
||||||
|
|
||||||
if (mode != Framebuffer::Session::RGB565) {
|
if (mode.format() != Framebuffer::Mode::RGB565) {
|
||||||
PERR("Color modes other than RGB565 are not supported. Exiting.");
|
PERR("Color modes other than RGB565 are not supported. Exiting.");
|
||||||
throw Non_supported_framebuffer_mode();
|
throw Non_supported_framebuffer_mode();
|
||||||
}
|
}
|
||||||
|
@ -148,10 +153,10 @@ class Pdf_view
|
||||||
{
|
{
|
||||||
pdfapp_init(&_pdfapp);
|
pdfapp_init(&_pdfapp);
|
||||||
_pdfapp.userdata = this;
|
_pdfapp.userdata = this;
|
||||||
_pdfapp.scrw = _framebuffer.width;
|
_pdfapp.scrw = _framebuffer.mode.width();
|
||||||
_pdfapp.scrh = _framebuffer.height;
|
_pdfapp.scrh = _framebuffer.mode.height();
|
||||||
_pdfapp.resolution = 2*75; /* XXX read from config */
|
_pdfapp.resolution = 75; /* XXX read from config */
|
||||||
_pdfapp.pageno = 9; /* XXX read from config */
|
_pdfapp.pageno = 0; /* XXX read from config */
|
||||||
|
|
||||||
int fd = open(file_name, O_BINARY | O_RDONLY, 0666);
|
int fd = open(file_name, O_BINARY | O_RDONLY, 0666);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -168,18 +173,23 @@ class Pdf_view
|
||||||
}
|
}
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
|
|
||||||
|
void handle_key(int ascii)
|
||||||
|
{
|
||||||
|
pdfapp_onkey(&_pdfapp, ascii);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void Pdf_view::show()
|
void Pdf_view::show()
|
||||||
{
|
{
|
||||||
int const x_max = Genode::min(_framebuffer.width, _pdfapp.image->w);
|
int const x_max = Genode::min(_framebuffer.mode.width(), _pdfapp.image->w);
|
||||||
int const y_max = Genode::min(_framebuffer.height, _pdfapp.image->h);
|
int const y_max = Genode::min(_framebuffer.mode.height(), _pdfapp.image->h);
|
||||||
|
|
||||||
Genode::size_t src_line_bytes = _pdfapp.image->n * _pdfapp.image->w;
|
Genode::size_t src_line_bytes = _pdfapp.image->n * _pdfapp.image->w;
|
||||||
unsigned char *src_line = _pdfapp.image->samples;
|
unsigned char *src_line = _pdfapp.image->samples;
|
||||||
|
|
||||||
Genode::size_t dst_line_width = _framebuffer.width; /* in pixels */
|
Genode::size_t dst_line_width = _framebuffer.mode.width(); /* in pixels */
|
||||||
_Framebuffer::pixel_t *dst_line = _framebuffer.base;
|
_Framebuffer::pixel_t *dst_line = _framebuffer.base;
|
||||||
|
|
||||||
for (int y = 0; y < y_max; y++) {
|
for (int y = 0; y < y_max; y++) {
|
||||||
|
@ -188,7 +198,13 @@ void Pdf_view::show()
|
||||||
dst_line += dst_line_width;
|
dst_line += dst_line_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
_framebuffer.refresh(0, 0, _framebuffer.width, _framebuffer.height);
|
_framebuffer.refresh(0, 0, _framebuffer.mode.width(), _framebuffer.mode.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void _sigprocmask()
|
||||||
|
{
|
||||||
|
/* suppress debug message by default "not-implemented" implementation */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -270,12 +286,57 @@ void winresize(pdfapp_t *app, int w, int h)
|
||||||
** Main program **
|
** 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';
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int, char **)
|
int main(int, char **)
|
||||||
{
|
{
|
||||||
char const *file_name = "test.pdf"; /* XXX read from config */
|
char const *file_name = "test.pdf"; /* XXX read from config */
|
||||||
|
|
||||||
static Pdf_view pdf_view(file_name);
|
static Pdf_view pdf_view(file_name);
|
||||||
|
|
||||||
|
static Input::Connection input;
|
||||||
|
static Timer::Connection timer;
|
||||||
|
|
||||||
|
Input::Event *ev_buf = Genode::env()->rm_session()->attach(input.dataspace());
|
||||||
|
int key_cnt = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Input event loop
|
||||||
|
*/
|
||||||
|
for (;;) {
|
||||||
|
while (!input.is_pending()) timer.msleep(20);
|
||||||
|
|
||||||
|
for (int i = 0, num_ev = input.flush(); i < num_ev; i++) {
|
||||||
|
|
||||||
|
Input::Event const &ev = ev_buf[i];
|
||||||
|
|
||||||
|
if (ev.type() == Input::Event::PRESS) key_cnt++;
|
||||||
|
if (ev.type() == Input::Event::RELEASE) key_cnt--;
|
||||||
|
|
||||||
|
if (ev.type() == Input::Event::PRESS && key_cnt == 1) {
|
||||||
|
|
||||||
|
PDBG("key %d pressed", ev.keycode());
|
||||||
|
|
||||||
|
int const ascii = keycode_to_ascii(ev.keycode());
|
||||||
|
if (ascii)
|
||||||
|
pdf_view.handle_key(ascii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Genode::sleep_forever();
|
Genode::sleep_forever();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user