gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r12341: Refactored input device supp


From: Rob Savoye
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r12341: Refactored input device support for the framebuffer GUI.
Date: Thu, 29 Jul 2010 12:45:30 -0600
User-agent: Bazaar (2.0.3)

------------------------------------------------------------
revno: 12341 [merge]
committer: Rob Savoye <address@hidden>
branch nick: trunk
timestamp: Thu 2010-07-29 12:45:30 -0600
message:
  Refactored input device support for the framebuffer GUI.
  Improved configure support for the framebuffer GUI.
added:
  gui/EventDevice.cpp
  gui/InputDevice.cpp
  gui/InputDevice.h
  gui/MouseDevice.cpp
  gui/TouchDevice.cpp
modified:
  configure.ac
  gui/Makefile.am
  gui/fb/fb.am
  gui/fb/fb.cpp
  gui/fb/fbsup.h
  gui/gui.h
  libcore/movie_root.cpp
=== modified file 'configure.ac'
--- a/configure.ac      2010-07-24 10:56:21 +0000
+++ b/configure.ac      2010-07-29 18:45:30 +0000
@@ -559,11 +559,62 @@
 
 dnl The class file is an optional file that if it is specified at configure 
time
 dnl with --with-classfile=, then only those classes are compiled and built 
into the
-dnl class library used for Gnash. THis is designed for small systems that 
execute the
+dnl class library used for Gnash. This is designed for small systems that 
execute the
 dnl same swf file over and over, and don't need the same level of 
functionality that
 dnl a browser plugin does.
 GNASH_PKG_CLASSFILE
 
+dnl Add an option for double buffering when rendering, currently only used by
+dnl the frmaebuffer GUI.
+dnl If defined, an internal software-buffer is used for rendering and is then
+dnl copied to the video RAM. This avoids flicker and is faster for complex 
+dnl graphics, as video RAM access is usually slower. (strongly suggested)
+AC_ARG_ENABLE(doublebuf,
+  AC_HELP_STRING([--enable-doublebuf], [Enable support for double buffering 
when rendering]),
+  [case "${enableval}" in
+    yes) doublebuf=yes ;;
+    no)  doublebuf=no ;;
+    *)   AC_MSG_ERROR([bad value ${enableval} for enable-doublebuf option]) ;;
+  esac], doublebuf=no
+)
+AM_CONDITIONAL(ENABLE_DBUF, [test x"$doublebuf" = xyes])
+if test x$doublebuf = xyes; then
+    AC_DEFINE(ENABLE_DOUBLE_BUFFERING, [1], [Enable double buffering])
+fi
+
+dnl This enables rendering to an offscreen buffer, instead of directly to 
window
+AC_ARG_ENABLE(offscreen,
+  AC_HELP_STRING([--enable-offscreen], [Enable support for rendering 
offscreen]),
+  [case "${enableval}" in
+    yes) offscreen=yes ;;
+    no)  offscreen=no ;;
+    *)   AC_MSG_ERROR([bad value ${enableval} for enable-offscreen option]) ;;
+  esac], offscreen=no
+)
+
+dnl We can use Xephyr or fbe to create a fake framebuffer instead of real
+dnl video memory. This lets us test on a desktop machine.
+AC_ARG_WITH(fakefb,
+AC_HELP_STRING([--with-fakefb],
+ [specify a file to be mapped instead of a real framebuffer]),
+ with_fakefb=${withval})
+
+fakefb=
+if test x"${with_fakefb}" = xyes; then
+  dnl This is the default file name fbe uses.
+  fakefb=/tmp/fbe_buffer
+else
+  if test x"${with_fakefb}" != x; then
+    fakefb=${with_fakefb}
+  fi
+fi
+FAKEFB=${fakefb}
+AC_SUBST(FAKEFB)
+
+if test x"${fakefb}" != x; then
+    AC_DEFINE(ENABLE_FAKE_FRAMEBUFFER, [1], [Enable using a file instead of a 
real framebuffer])
+fi
+
 has_gtk2=no                     dnl FIXME: has_* shouldn't be in configure but 
in a macro
 
 build_haiku=no
@@ -697,6 +748,80 @@
   fi
 fi
 
+dnl Multiple input devices are supported. These can all work in varying 
combinations,
+dnl so several may be listed. These are only required when using the 
Framebuffer,
+dnl as without the X11 desktop, Gnash has to handle all these internally. This 
can get
+dnl messy, as one might want to use a touchscreen with a normal mouse or 
keyboard
+dnl attached. 
+
+dnl By default, don't build any of these, as they are only for the Framebuffer
+dnl running without X11.
+if test x"${build_fb}" = xyes; then
+build_ps2mouse=yes
+build_ps2keyboard=no
+build_input_events=yes
+build_tslib=yes
+input_events="PS/2 Mouse, Input Devices, Touchscreen via Tslib"
+else
+build_ps2mouse=no
+build_ps2keyboard=no
+build_input_events=no
+build_tslib=no
+input_events=
+fi
+AC_ARG_ENABLE(input,
+  AC_HELP_STRING([--enable-input=], [Enable support for the specified input 
devices for the framebuffer GUI 
(default=ps2mouse|ps2keyboard|events|touchscreen)]),
+  [if test -n ${enableval}; then
+    enableval=`echo ${enableval} | tr '\054' ' ' `
+  fi
+  while test -n "${enableval}" ; do
+    val=`echo ${enableval} | cut -d ' ' -f 1`
+    case "${val}" in
+      ps2m*|PS2m*|m*|M*)        dnl a PS/2 style mouse
+        build_ps2mouse=yes
+        input_events="${input_events}, PS/2 Mouse"
+        ;;
+      ps2k*|PS2K*|k*|K*)        dnl a PS/2 style keyboard
+        build_ps2keyboard=yes
+        input_events="${input_events}, PS/2 Keyboard"
+        ;;
+      i*|I*|ev*|Ev*)    dnl use the new Input Event, which supports both
+        input_events="${input_events}, Input Event Device"
+        build_input_events=yes
+        ;;
+      t*|T*) dnl use a touchscreen with tslib, which works like a mouse
+        build_tslib=yes
+        input_events="${input_events}, Touchscreen"
+        ;;
+      *) AC_MSG_ERROR([invalid input device list! ${enableval} given (accept: 
ps2mouse|keyboard|events,touchscreen)])
+         ;;
+      esac
+    enableval=`echo ${enableval} | cut -d ' ' -f 2-6`
+    if test "x$val" = "x$enableval"; then
+      break;
+    fi
+  done],
+)
+
+if test x"${build_tslib}" = xyes; then
+  AC_DEFINE(USE_TSLIB, [1], [Use a tslib supported touchscreen])
+  GNASH_PKG_FIND(ts, [tslib.h], [Touchscreen library], ts_config)
+fi
+AM_CONDITIONAL(ENABLE_TSLIB, [test x"$build_tslib" = xyes])
+
+if test x"${build_ps2mouse}" = xyes; then
+  AC_DEFINE(USE_MOUSE_PS2, [1], [Add support for a directly using a PS/2 
Mouse])
+fi
+AM_CONDITIONAL(USE_PS2_MOUSE, [test x"${build_ps2mouse}" = xyes])
+
+if test x"${build_ps2keyboard}" = xyes; then
+  AC_DEFINE(USE_KEYBOARD_PS2, [1], [Add support for directly using a PS/2 
Keyboard])
+fi
+if test x"${build_input_events}" = xyes; then
+  AC_DEFINE(USE_INPUT_EVENTS, [1], [Add support for a directly using Linux 
Input Event Devices])
+fi
+AM_CONDITIONAL(USE_INPUT_EVENTS, [test x"${build_input_events}" = xyes])
+
 dnl By default, we want to to build all renderers
 build_ovg=no
 build_gles=no
@@ -2132,8 +2257,6 @@
 AM_CONDITIONAL(KPARTS3, [test x"${build_kparts3}" = xyes])
 AM_CONDITIONAL(KPARTS4, [test x"${build_kparts4}" = xyes])
 
-GNASH_PKG_FIND(ts, [tslib.h], [Touchscreen library], ts_config)
-
 if test x"${build_gles}" = xyes; then
   GNASH_PKG_FIND(EGL, [EGL/egl.h], [EGL library], eglGetDisplay)
   GNASH_PATH_GLES
@@ -3833,6 +3956,21 @@
   echo "        DocBook document processing disabled (default)"
 fi
 
+dnl The Framebuffer GUI has several other settings. As it doesn't have X11,
+dnl we have to handle input devices ourselves.
+if test x"${build_fb}" = xyes; then
+echo "        Using ${input_events} for Input"
+  if test x"${fakefb}" != x; then
+    echo "        Using shared memory as a fake framebuffer"
+  fi
+  if test x"${offscreen}" = xyes; then
+    echo "        Using offscreen rendering"
+  fi
+  if test x"${doublebuf}" = xyes; then
+    echo "        Using double buffering when rendering"
+  fi
+fi
+
 if test -s $cwarn; then
   echo ""
   cat $cwarn

=== added file 'gui/EventDevice.cpp'
--- a/gui/EventDevice.cpp       1970-01-01 00:00:00 +0000
+++ b/gui/EventDevice.cpp       2010-07-29 16:02:59 +0000
@@ -0,0 +1,497 @@
+// 
+//   Copyright (C) 2010 Free Software Foundation, 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 3 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include "log.h"
+#include "InputDevice.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/input.h>
+#include <linux/kd.h>
+
+namespace gnash {
+
+static const char *INPUT_DEVICE = "/dev/input/event0";
+
+EventDevice::EventDevice()
+{
+    // GNASH_REPORT_FUNCTION;
+}
+
+EventDevice::EventDevice(Gui *gui)
+{
+    // GNASH_REPORT_FUNCTION;
+
+    _gui = gui;
+}
+
+bool
+EventDevice::init()
+{
+    GNASH_REPORT_FUNCTION;
+
+    return init(INPUT_DEVICE, DEFAULT_BUFFER_SIZE);
+}
+
+bool
+EventDevice::init(const std::string &filespec, size_t /* size */)
+{
+    GNASH_REPORT_FUNCTION;
+    
+    _filespec = filespec;
+    
+    // Try to open mouse device, be error tolerant (FD is kept open all the 
time)
+    _fd = open(filespec.c_str(), O_RDONLY);
+  
+    if (_fd < 0) {
+        log_debug(_("Could not open %s: %s"), filespec.c_str(), 
strerror(errno));    
+        return false;
+    }
+  
+    if (fcntl(_fd, F_SETFL, fcntl(_fd, F_GETFL) | O_NONBLOCK) < 0) {
+        log_error(_("Could not set non-blocking mode for pointing device: %s"),
+                  strerror(errno));
+        close(_fd);
+        _fd = -1;
+        return false; 
+    }
+
+    // Get the version number of the input event subsystem
+    int version;
+    if (ioctl(_fd, EVIOCGVERSION, &version)) {
+        perror("evdev ioctl");
+    }
+    log_debug("evdev driver version is %d.%d.%d",
+              version >> 16, (version >> 8) & 0xff,
+              version & 0xff);
+    
+    if(ioctl(_fd, EVIOCGID, &_device_info)) {
+        perror("evdev ioctl");
+    }
+    
+    char name[256]= "Unknown";
+    if(ioctl(_fd, EVIOCGNAME(sizeof(name)), name) < 0) {
+        perror("evdev ioctl");
+    }
+    log_debug("The device on %s says its name is %s", filespec, name);
+    
+    log_debug("vendor %04hx product %04hx version %04hx",
+              _device_info.vendor, _device_info.product,
+              _device_info.version);
+    switch (_device_info.bustype) {
+      case BUS_PCI:
+          log_unimpl("is a PCI bus type");
+          break;
+      case BUS_ISAPNP:
+          log_unimpl("is a PNP bus type");
+          break;          
+      case BUS_USB:
+          // FIXME: this probably needs a better way of checking what
+          // device things truly are.          
+          log_debug("is on a Universal Serial Bus");
+          // ID 0eef:0001 D-WAV Scientific Co., Ltd eGalax TouchScreen
+          if ((_device_info.product == 0x0001) && (_device_info.vendor == 
0x0eef)) {
+              _type = InputDevice::TOUCHMOUSE;
+              // ID 046d:c001 Logitech, Inc. N48/M-BB48 [FirstMouse Plus]
+          } else if ((_device_info.product == 0xc001) && (_device_info.vendor 
== 0x046d)) {
+              _type = InputDevice::MOUSE;
+              // ID 0001:0001 AT Translated Set 2 keyboard
+          } else if ((_device_info.product == 0x0001) && (_device_info.vendor 
== 0x0001)) {
+              _type = InputDevice::MOUSE;
+              // ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
+          } else if ((_device_info.product == 0x2303) && (_device_info.vendor 
== 0x067b)) {
+              _type = InputDevice::SERIALUSB ;
+                  // ID 0471:0815 Philips (or NXP) eHome Infrared Receiver
+          } else if ((_device_info.product == 0x0815) && (_device_info.vendor 
== 0x0471)) {
+              _type = InputDevice::INFRARED;
+          }
+          break;
+      case BUS_HIL:
+          log_unimpl("is a HIL bus type");
+          break;
+      case BUS_BLUETOOTH:
+          log_unimpl("is Bluetooth bus type ");
+          break;
+      case BUS_VIRTUAL:
+          log_unimpl("is a Virtual bus type ");
+          break;
+      case BUS_ISA:
+          log_unimpl("is an ISA bus type");
+          break;
+      case BUS_I8042:
+          // This is for keyboards and mice
+          log_debug("is an I8042 bus type");
+          if (strstr(name, "keyboard") != 0) {
+              _type = InputDevice::KEYBOARD;
+          } else {
+              if (strstr(name, "Mouse") != 0) {
+                  _type = InputDevice::MOUSE;
+              }
+          }
+          break;
+      case BUS_XTKBD:
+          log_unimpl("is an XTKBD bus type");
+          break;
+      case BUS_RS232:
+          log_unimpl("is a serial port bus type");
+          break;
+      case BUS_GAMEPORT:
+          log_unimpl("is a gameport bus type");
+          break;
+      case BUS_PARPORT:
+          log_unimpl("is a parallel port bus type");
+          break;
+      case BUS_AMIGA:
+          log_unimpl("is an Amiga bus type");
+          break;
+      case BUS_ADB:
+          log_unimpl("is an AOB bus type");
+          break;
+      case BUS_I2C:
+          log_unimpl("is an i2C bus type ");
+          break;
+      case BUS_HOST:
+          log_debug("is Host bus type");
+          _type = InputDevice::POWERBUTTON;
+          break;
+      case BUS_GSC:
+          log_unimpl("is a GSC bus type");
+          break;
+      case BUS_ATARI:
+          log_unimpl("is an Atari bus type");
+          break;
+      default:
+          log_error("Unknown bus type %d!", _device_info.bustype);
+    }
+    
+    log_debug("Event enabled for %s on fd #%d", _filespec, _fd);
+    
+    return true;
+}
+
+bool
+EventDevice::check()
+{
+    GNASH_REPORT_FUNCTION;
+    
+    bool activity = false;
+  
+    if (_fd < 0) {
+        return false;           // no device
+    }
+
+    // Try to read something from the device
+    boost::shared_array<boost::uint8_t> buf = readData(sizeof( struct 
input_event));
+    // time,type,code,value
+    if (!buf) {
+        return false;
+    }
+    
+    struct input_event *ev = reinterpret_cast<struct input_event *>(buf.get());
+    // log_debug("Type is: %hd, Code is: %hd, Val us: %d", ev->type, ev->code,
+    //           ev->value);
+    switch (ev->type) {
+      case EV_SYN:
+          log_unimpl("Sync event from Input Event Device");
+          break;
+        // Keyboard event
+      case EV_KEY:
+      {
+          // code == scan code of the key (KEY_xxxx defines in input.h)        
 
+          // value == 0  key has been released
+          // value == 1  key has been pressed
+          // value == 2  repeated key reporting (while holding the key)
+          if (ev->code == KEY_LEFTSHIFT) {
+              keyb_lshift = ev->value;
+          } else if (ev->code == KEY_RIGHTSHIFT) {
+              keyb_rshift = ev->value;
+          } else if (ev->code == KEY_LEFTCTRL) {
+              keyb_lctrl = ev->value;
+          } else if (ev->code == KEY_RIGHTCTRL) {
+              keyb_rctrl = ev->value;
+          } else if (ev->code == KEY_LEFTALT) {
+              keyb_lalt = ev->value;
+          } else if (ev->code == KEY_RIGHTALT) {
+              keyb_ralt = ev->value;
+          } else {
+              gnash::key::code  c = scancode_to_gnash_key(ev->code,
+                                            keyb_lshift || keyb_rshift);
+                  // build modifier
+              int modifier = gnash::key::GNASH_MOD_NONE;
+              
+              if (keyb_lshift || keyb_rshift) {
+                  modifier = modifier | gnash::key::GNASH_MOD_SHIFT;
+              }
+              
+              if (keyb_lctrl || keyb_rctrl) {
+                  modifier = modifier | gnash::key::GNASH_MOD_CONTROL;
+              }
+              
+              if (keyb_lalt || keyb_ralt) {
+                  modifier = modifier | gnash::key::GNASH_MOD_ALT;
+              }
+              
+              // send event
+              if (c != gnash::key::INVALID) {
+                  _gui->notify_key_event(c, modifier, ev->value);
+                  activity = true;
+              }
+          } // if normal key
+          break;
+      } // case EV_KEY
+      // Mouse
+      case EV_REL:
+          log_unimpl("Relative move event from Input Event Device");
+          // Touchscreen or joystick
+          break;
+      case EV_ABS:
+          log_unimpl("Absolute move event from Input Event Device");
+          break;
+      case EV_MSC:
+          log_unimpl("Misc event from Input Event Device");
+          break;
+      case EV_LED:
+          log_unimpl("LED event from Input Event Device");
+          break;
+      case EV_SND:
+          log_unimpl("Sound event from Input Event Device");
+          break;
+      case EV_REP:
+          log_unimpl("Key autorepeat event from Input Event Device");
+          break;
+      case EV_FF:
+          log_unimpl("Force Feedback event from Input Event Device");
+          break;
+      case EV_FF_STATUS:  
+          log_unimpl("Force Feedback status event from Input Event Device");
+          break;
+      case EV_PWR:
+          log_unimpl("Power event from Input Event Device");
+          break;
+    }
+
+    return activity;
+}
+
+gnash::key::code
+EventDevice::scancode_to_gnash_key(int code, bool shift)
+{ 
+    // NOTE: Scancodes are mostly keyboard oriented (ie. Q, W, E, R, T, ...)
+    // while Gnash codes are mostly ASCII-oriented (A, B, C, D, ...) so no
+    // direct conversion is possible.
+    
+    // TODO: This is a very *incomplete* list and I also dislike this method
+    // very much because it depends on the keyboard layout (ie. pressing "Z"
+    // on a german keyboard will print "Y" instead). So we need some 
+    // alternative...
+    
+    switch (code) {
+      case KEY_1      : return !shift ? gnash::key::_1 : gnash::key::EXCLAM;
+      case KEY_2      : return !shift ? gnash::key::_2 : 
gnash::key::DOUBLE_QUOTE; 
+      case KEY_3      : return !shift ? gnash::key::_3 : gnash::key::HASH; 
+      case KEY_4      : return !shift ? gnash::key::_4 : gnash::key::DOLLAR; 
+      case KEY_5      : return !shift ? gnash::key::_5 : gnash::key::PERCENT; 
+      case KEY_6      : return !shift ? gnash::key::_6 : 
gnash::key::AMPERSAND; 
+      case KEY_7      : return !shift ? gnash::key::_7 : 
gnash::key::SINGLE_QUOTE; 
+      case KEY_8      : return !shift ? gnash::key::_8 : 
gnash::key::PAREN_LEFT; 
+      case KEY_9      : return !shift ? gnash::key::_9 : 
gnash::key::PAREN_RIGHT; 
+      case KEY_0      : return !shift ? gnash::key::_0 : gnash::key::ASTERISK;
+                            
+      case KEY_A      : return shift ? gnash::key::A : gnash::key::a;
+      case KEY_B      : return shift ? gnash::key::B : gnash::key::b;
+      case KEY_C      : return shift ? gnash::key::C : gnash::key::c;
+      case KEY_D      : return shift ? gnash::key::D : gnash::key::d;
+      case KEY_E      : return shift ? gnash::key::E : gnash::key::e;
+      case KEY_F      : return shift ? gnash::key::F : gnash::key::f;
+      case KEY_G      : return shift ? gnash::key::G : gnash::key::g;
+      case KEY_H      : return shift ? gnash::key::H : gnash::key::h;
+      case KEY_I      : return shift ? gnash::key::I : gnash::key::i;
+      case KEY_J      : return shift ? gnash::key::J : gnash::key::j;
+      case KEY_K      : return shift ? gnash::key::K : gnash::key::k;
+      case KEY_L      : return shift ? gnash::key::L : gnash::key::l;
+      case KEY_M      : return shift ? gnash::key::M : gnash::key::m;
+      case KEY_N      : return shift ? gnash::key::N : gnash::key::n;
+      case KEY_O      : return shift ? gnash::key::O : gnash::key::o;
+      case KEY_P      : return shift ? gnash::key::P : gnash::key::p;
+      case KEY_Q      : return shift ? gnash::key::Q : gnash::key::q;
+      case KEY_R      : return shift ? gnash::key::R : gnash::key::r;
+      case KEY_S      : return shift ? gnash::key::S : gnash::key::s;
+      case KEY_T      : return shift ? gnash::key::T : gnash::key::t;
+      case KEY_U      : return shift ? gnash::key::U : gnash::key::u;
+      case KEY_V      : return shift ? gnash::key::V : gnash::key::v;
+      case KEY_W      : return shift ? gnash::key::W : gnash::key::w;
+      case KEY_X      : return shift ? gnash::key::X : gnash::key::x;
+      case KEY_Y      : return shift ? gnash::key::Y : gnash::key::y;
+      case KEY_Z      : return shift ? gnash::key::Z : gnash::key::z;
+
+      case KEY_F1     : return gnash::key::F1; 
+      case KEY_F2     : return gnash::key::F2; 
+      case KEY_F3     : return gnash::key::F3; 
+      case KEY_F4     : return gnash::key::F4; 
+      case KEY_F5     : return gnash::key::F5; 
+      case KEY_F6     : return gnash::key::F6; 
+      case KEY_F7     : return gnash::key::F7; 
+      case KEY_F8     : return gnash::key::F8; 
+      case KEY_F9     : return gnash::key::F9;
+      case KEY_F10    : return gnash::key::F10;
+      case KEY_F11    : return gnash::key::F11;
+      case KEY_F12    : return gnash::key::F12;
+    
+      case KEY_KP0    : return gnash::key::KP_0; 
+      case KEY_KP1    : return gnash::key::KP_1; 
+      case KEY_KP2    : return gnash::key::KP_2; 
+      case KEY_KP3    : return gnash::key::KP_3; 
+      case KEY_KP4    : return gnash::key::KP_4; 
+      case KEY_KP5    : return gnash::key::KP_5; 
+      case KEY_KP6    : return gnash::key::KP_6; 
+      case KEY_KP7    : return gnash::key::KP_7; 
+      case KEY_KP8    : return gnash::key::KP_8; 
+      case KEY_KP9    : return gnash::key::KP_9;
+
+      case KEY_KPMINUS       : return gnash::key::KP_SUBTRACT;
+      case KEY_KPPLUS        : return gnash::key::KP_ADD;
+      case KEY_KPDOT         : return gnash::key::KP_DECIMAL;
+      case KEY_KPASTERISK    : return gnash::key::KP_MULTIPLY;
+      case KEY_KPENTER       : return gnash::key::KP_ENTER;
+    
+      case KEY_ESC           : return gnash::key::ESCAPE;
+      case KEY_MINUS         : return gnash::key::MINUS;
+      case KEY_EQUAL         : return gnash::key::EQUALS;
+      case KEY_BACKSPACE     : return gnash::key::BACKSPACE;
+      case KEY_TAB           : return gnash::key::TAB;
+      case KEY_LEFTBRACE     : return gnash::key::LEFT_BRACE;
+      case KEY_RIGHTBRACE    : return gnash::key::RIGHT_BRACE;
+      case KEY_ENTER         : return gnash::key::ENTER;
+      case KEY_LEFTCTRL      : return gnash::key::CONTROL;
+      case KEY_SEMICOLON     : return gnash::key::SEMICOLON;
+          //case KEY_APOSTROPHE    : return gnash::key::APOSTROPHE;  
+          //case KEY_GRAVE         : return gnash::key::GRAVE;
+      case KEY_LEFTSHIFT     : return gnash::key::SHIFT;
+      case KEY_BACKSLASH     : return gnash::key::BACKSLASH;
+      case KEY_COMMA         : return gnash::key::COMMA;
+      case KEY_SLASH         : return gnash::key::SLASH;
+      case KEY_RIGHTSHIFT    : return gnash::key::SHIFT;
+      case KEY_LEFTALT       : return gnash::key::ALT;
+      case KEY_SPACE         : return gnash::key::SPACE;
+      case KEY_CAPSLOCK      : return gnash::key::CAPSLOCK;
+      case KEY_NUMLOCK       : return gnash::key::NUM_LOCK;
+          //case KEY_SCROLLLOCK    : return gnash::key::SCROLLLOCK;
+    
+      case KEY_UP            : return gnash::key::UP;
+      case KEY_DOWN          : return gnash::key::DOWN;
+      case KEY_LEFT          : return gnash::key::LEFT;
+      case KEY_RIGHT         : return gnash::key::RIGHT;
+      case KEY_PAGEUP        : return gnash::key::PGUP;
+      case KEY_PAGEDOWN      : return gnash::key::PGDN;
+      case KEY_INSERT        : return gnash::key::INSERT;
+      case KEY_DELETE        : return gnash::key::DELETEKEY;
+      case KEY_HOME          : return gnash::key::HOME;
+      case KEY_END           : return gnash::key::END;
+    
+    }
+  
+    return gnash::key::INVALID;  
+}
+
+// This looks in the input event devices
+std::vector<boost::shared_ptr<InputDevice> > 
+EventDevice::scanForDevices(Gui *gui)
+{
+    // GNASH_REPORT_FUNCTION;
+
+    struct stat st;
+
+    int total = 0;
+    std::vector<boost::shared_ptr<InputDevice> > devices;
+    
+    // The default path for input event devices.
+    char *filespec = strdup("/dev/input/eventX");
+    int len = strlen(filespec) - 1;
+
+    // Walk through all the input event devices for the ones that
+    // match the type we want. There can be multiple devices of the same
+    // type, so we return the ID of the event devices.
+    filespec[len] = '0';
+    int fd = 0;
+    while (fd >= 0) {
+        // First see if the file exists
+        if (stat(filespec, &st) == 0) {
+            // Then see if we can open it
+            if ((fd = open(filespec, O_RDWR)) < 0) {
+                log_error("You don't have the proper permissions to open %s",
+                          filespec);
+                // Try the next input event device file
+                total++;
+                filespec[len] = '0' + total;
+                fd = 0;
+                continue;
+            }
+        } else {
+            // No more device files to try, so we're done scanning
+            break;
+        }
+
+        char name[256] = "Unknown";
+        if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) {
+            perror("evdev ioctl");
+        }
+        log_debug("The device on %s says its name is %s", filespec, name);
+
+        struct input_id device_info;
+        if(ioctl(fd, EVIOCGID, &device_info)) {
+            perror("evdev ioctl");
+        }
+        log_debug("vendor %04hx product %04hx version %04hx",
+                  device_info.vendor, device_info.product,
+                  device_info.version);
+        close(fd);
+        boost::shared_ptr<InputDevice> dev;
+        dev = boost::shared_ptr<InputDevice>(new EventDevice(gui));
+        // For now we only want keyboards, as the mouse interface
+        // default of /dev/input/mice supports hotpluging devices,
+        // unlike the regular event.
+        if (dev->init(filespec, DEFAULT_BUFFER_SIZE)) {
+            if ((dev->getType() == InputDevice::KEYBOARD)) {
+                devices.push_back(dev);
+            }
+        }
+
+//        dev->dump();
+        
+        // setup the next device filespec to try
+        total++;
+        filespec[len] = '0' + total;
+    }
+    
+    free (filespec);
+    
+    return devices;
+}
+
+// end of namespace
+}
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== added file 'gui/InputDevice.cpp'
--- a/gui/InputDevice.cpp       1970-01-01 00:00:00 +0000
+++ b/gui/InputDevice.cpp       2010-07-29 18:45:30 +0000
@@ -0,0 +1,195 @@
+// 
+//   Copyright (C) 2010 Free Software Foundation, 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 3 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include "gui.h"
+#include "log.h"
+#include "InputDevice.h"
+
+namespace gnash {
+
+InputDevice::InputDevice()
+    : _type(InputDevice::UNKNOWN),
+      _fd(-1),
+      _x(0),
+      _y(0),
+      _button(0),
+      _position(0),
+      _gui(0)
+{
+    // GNASH_REPORT_FUNCTION;
+}
+
+InputDevice::InputDevice(Gui *gui)
+    : _type(InputDevice::UNKNOWN),
+      _fd(-1),
+      _x(0),
+      _y(0),
+      _button(0),
+      _position(0),
+      _gui(gui)
+{
+    // GNASH_REPORT_FUNCTION;
+}
+
+InputDevice::~InputDevice()
+{
+    // GNASH_REPORT_FUNCTION;
+}
+
+bool
+InputDevice::init()
+{
+    // GNASH_REPORT_FUNCTION;
+    
+    return true;
+}
+
+bool
+InputDevice::init(InputDevice::devicetype_e type)
+{
+    GNASH_REPORT_FUNCTION;
+    return init(type, std::string(), DEFAULT_BUFFER_SIZE);
+}
+
+bool
+InputDevice::init(InputDevice::devicetype_e type, size_t size)
+{
+    GNASH_REPORT_FUNCTION;
+
+    return init(type, std::string(), size);
+}
+
+bool
+InputDevice::init(InputDevice::devicetype_e type, const std::string &filespec,
+                  size_t size)
+{
+    GNASH_REPORT_FUNCTION;
+
+    _type = type;
+    _filespec = filespec;
+    
+    return init(filespec, size);
+}
+
+// Read data into the Device input buffer.
+boost::shared_array<boost::uint8_t>
+InputDevice::readData(size_t size)
+{
+    GNASH_REPORT_FUNCTION;
+
+    boost::shared_array<boost::uint8_t> inbuf;
+
+    if (_fd < 0) {
+        return inbuf;   // no mouse available
+    }
+
+    fd_set fdset;
+    FD_ZERO(&fdset);
+    FD_SET(_fd, &fdset);
+    struct timeval tval;
+    tval.tv_sec  = 0;
+    tval.tv_usec = 1;
+    errno = 0;
+    int ret = ::select(_fd+1, &fdset, NULL, NULL, &tval);
+    if (ret == 0) {
+//            log_debug ("The pipe for fd #%d timed out waiting to read", fd);
+        return inbuf;
+    } else if (ret == 1) {
+        log_debug ("The device for fd #%d is ready", _fd);
+    } else {
+        log_error("The device has this error: %s", strerror(errno));
+        return inbuf;
+    }
+    
+    inbuf.reset(new boost::uint8_t[size]);
+    ret = ::read(_fd, inbuf.get(), size);
+    if (ret > 0) {
+        log_debug("Read %d bytes, %s", ret, hexify(inbuf.get(), ret, false));
+    } else {
+        inbuf.reset();
+    }
+
+    return inbuf;
+}   
+
+void
+InputDevice::dump()
+{
+    // Debug strings to make output more readable
+    const char *debug[] = {
+        "UNKNOWN",
+        "Keyboard",
+        "Mouse",
+        "Touchscreen",
+        "Touchscreen Mouse",
+        "Power Button",
+        "Sleep Button",
+        "Serial-USB Adapter",
+        "Infrared Receiver"
+    };    
+
+    std::cerr << "Device type is: " << debug[_type] << std::endl;
+    std::cerr << "\tfilespec is: " << _filespec
+              << ", fd #" << _fd << std::endl;
+    std::cerr << "\tX is: " << _x << ", Y is: " << _y << std::endl;
+}
+
+// Scan for all the possible input devices. This aggregates all
+// the devices from each type into a single big vector.
+std::vector<boost::shared_ptr<InputDevice> >
+InputDevice::scanForDevices(Gui *gui)
+{
+    // GNASH_REPORT_FUNCTION;
+
+    std::vector<boost::shared_ptr<InputDevice> > devices;
+    
+    std::vector<boost::shared_ptr<InputDevice> > id;
+    std::vector<boost::shared_ptr<InputDevice> >::iterator it;
+#ifdef USE_INPUT_EVENTS
+    id = EventDevice::scanForDevices(gui);
+    for (it=id.begin(); it!=id.end(); ++it) {
+        devices.push_back(*it);
+    }
+#endif
+#if defined(USE_MOUSE_PS2) || defined(USE_MOUSE_ETT)
+    id = MouseDevice::scanForDevices(gui);
+    for (it=id.begin(); it!=id.end(); ++it) {
+        devices.push_back(*it);
+    }
+#endif
+#ifdef USE_TSLIB
+    id = TouchDevice::scanForDevices(gui);
+    for (it=id.begin(); it!=id.end(); ++it) {
+        devices.push_back(*it);
+    }
+#endif
+
+    return devices;
+}
+
+// end of gnash namespace
+}
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== added file 'gui/InputDevice.h'
--- a/gui/InputDevice.h 1970-01-01 00:00:00 +0000
+++ b/gui/InputDevice.h 2010-07-29 16:02:59 +0000
@@ -0,0 +1,163 @@
+// 
+//   Copyright (C) 2010 Free Software Foundation, 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 3 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef GNASH_INPUTDEVICE_H
+#define GNASH_INPUTDEVICE_H
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <boost/scoped_array.hpp>
+#include <boost/shared_array.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/cstdint.hpp>
+
+#include "gui.h"
+
+#include <linux/input.h>
+
+namespace gnash {
+
+// Define if you want to support multiple input devices of the same type.
+// The default is to support the devices we prefer for moluse, keyboard,
+// and touchscreen.
+// #define MULTIPLE_DEVICES 1
+
+// Forward declarations
+class Gui;
+
+// If we have a mouse, but the size isn't specified, then this is the
+// default size.
+static const int DEFAULT_BUFFER_SIZE = 256;
+
+// This is an InputDevice class to cover the various touchscreens, Mice, or
+// keyboards supported.
+class InputDevice
+{
+public:
+    typedef enum {
+        UNKNOWN,
+        KEYBOARD,
+        MOUSE,
+        TOUCHSCREEN,
+        TOUCHMOUSE,
+        POWERBUTTON,
+        SLEEPBUTTON,
+        SERIALUSB,
+        INFRARED
+    } devicetype_e;
+    InputDevice();
+    InputDevice(Gui *gui);
+    virtual ~InputDevice();
+    
+    virtual bool init();
+    bool init(devicetype_e type);
+    bool init(devicetype_e type, size_t size);
+    bool init(devicetype_e type, const std::string &filespec);
+    bool init(devicetype_e type, const std::string &filespec, size_t size);
+    virtual bool init(const std::string &filespec, size_t size) = 0;
+    virtual bool check() = 0;
+
+    static std::vector<boost::shared_ptr<InputDevice> > scanForDevices(Gui 
*gui);
+
+    InputDevice::devicetype_e getType() { return _type; };
+
+    // Read data into the Device input buffer.
+    boost::shared_array<boost::uint8_t> readData(size_t size);
+
+    void dump();
+    
+protected:
+    devicetype_e        _type;
+    std::string         _filespec;
+    int                 _fd;
+    int                 _x;
+    int                 _y;
+    // Touchscreens don't have buttons
+    int                 _button;
+    size_t              _position;
+    boost::scoped_array<boost::uint8_t> _buffer;
+    // We don't control the memory associated with the Gui, we just use
+    // it to propogate the events from this device.
+    Gui                 *_gui;
+};
+
+class MouseDevice : public InputDevice
+{
+public:    
+    MouseDevice();
+    MouseDevice(Gui *gui);
+    virtual bool init();
+    virtual bool init(const std::string &filespec, size_t size);
+    virtual bool check();
+
+    static std::vector<boost::shared_ptr<InputDevice> > scanForDevices(Gui 
*gui);
+    
+    /// Sends a command to the mouse and waits for the response
+    bool command(unsigned char cmd, unsigned char *buf, int count);
+};
+
+class TouchDevice : public InputDevice
+{
+public:
+    TouchDevice();
+    TouchDevice(Gui *gui);
+    virtual ~TouchDevice();
+    virtual bool init();
+    virtual bool init(const std::string &filespec, size_t size);
+    virtual bool check();
+
+    void apply_ts_calibration(float* cx, float* cy, int rawx, int rawy);
+    
+    static std::vector<boost::shared_ptr<InputDevice> > scanForDevices(Gui 
*gui);
+private:
+    // Although the value is only set when using a touchscreen, it takes up 
little
+    // memory to initialize a pointer to avoid lots of messy ifdefs.
+    struct tsdev *_tsDev;
+};
+
+class EventDevice : public InputDevice
+{
+public:    
+    EventDevice();
+    EventDevice(Gui *gui);
+    virtual bool init();
+    virtual bool init(const std::string &filespec, size_t size);
+    virtual bool check();
+
+    gnash::key::code scancode_to_gnash_key(int code, bool shift);
+
+    // This looks for all the input event devices.
+    static std::vector<boost::shared_ptr<InputDevice> > scanForDevices(Gui 
*gui);
+    
+private:
+    // Keyboard SHIFT/CTRL/ALT states (left + right)
+     bool keyb_lshift, keyb_rshift, keyb_lctrl, keyb_rctrl, keyb_lalt, 
keyb_ralt;
+    struct input_id _device_info;
+};
+
+} // end of gnash namespace
+
+// end of GNASH_INPUTDEVICE_H
+#endif
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== modified file 'gui/Makefile.am'
--- a/gui/Makefile.am   2010-07-15 03:07:54 +0000
+++ b/gui/Makefile.am   2010-07-29 18:45:30 +0000
@@ -197,10 +197,29 @@
        cp $< $@
        chmod +x $@
 
+# These are used to handle input events from a keyboard, mouse, or
+# touchscreen. These are only used by the Framebuffer GUI, as without
+# X11, it has no event handling. We do it this way so the optionally
+# built source files still get included in the source tarball.
+DEVICES = \
+       InputDevice.cpp InputDevice.h \
+       TouchDevice.cpp \
+       MouseDevice.cpp \
+       EventDevice.cpp
+EXTRA_DIST += $(DEVICES)
+
+if USE_INPUT_EVENTS
+INPUTDEVS = $(DEVICES)
+else
+INPUTDEVS = 
+endif
+
 GUI_SRCS = gnash.cpp \
        gui.cpp gui.h \
        Player.cpp Player.h \
-       NullGui.cpp NullGui.h
+       NullGui.cpp NullGui.h \
+       $(INPUTDEVS) \
+       $(NULL)
 
 if BUILD_AQUA_GUI
 BUILT_SOURCES += bundle

=== added file 'gui/MouseDevice.cpp'
--- a/gui/MouseDevice.cpp       1970-01-01 00:00:00 +0000
+++ b/gui/MouseDevice.cpp       2010-07-29 16:02:59 +0000
@@ -0,0 +1,355 @@
+// 
+//   Copyright (C) 2010 Free Software Foundation, 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 3 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "GnashSleep.h"
+#include "log.h"
+#include "InputDevice.h"
+
+namespace gnash {
+
+static const char *MOUSE_DEVICE = "/dev/input/mice";
+
+MouseDevice::MouseDevice()
+{
+    GNASH_REPORT_FUNCTION;
+}
+
+MouseDevice::MouseDevice(Gui *gui)
+{
+    // GNASH_REPORT_FUNCTION;
+
+    _gui = gui;
+}
+
+std::vector<boost::shared_ptr<InputDevice> >
+MouseDevice::scanForDevices(Gui *gui)
+{
+    // GNASH_REPORT_FUNCTION;
+
+    struct stat st;
+
+    std::vector<boost::shared_ptr<InputDevice> > devices;
+
+    // Look for these files for mouse input
+    struct mouse_types {
+        InputDevice::devicetype_e type;
+        const char *filespec;
+    };
+
+    // Debug strings to make output more readable
+    const char *debug[] = {
+        "UNKNOWN",
+        "Keyboard",
+        "Mouse",
+        "Touchscreen",
+        "Touchscreen Mouse",
+        "Power Button",
+        "Sleep Button",
+        "Serial-USB Adapter",
+        "Infrared Receiver"
+    };    
+
+    struct mouse_types mice[] = {
+        InputDevice::MOUSE, "/dev/input/mice",      // PS/2 Mouse
+#ifdef MULTIPLE_DEVICES
+        InputDevice::MOUSE, "/dev/input/mouse0",
+        InputDevice::MOUSE, "/dev/input/mouse1",
+        InputDevice::MOUSE, "/dev/usb/tkpanel0",    // eTurboTouch touchscreen
+#endif
+        InputDevice::UNKNOWN, 0
+    };
+
+    int i = 0;
+    while (mice[i].type != InputDevice::UNKNOWN) {
+        int fd = 0;
+        if (stat(mice[i].filespec, &st) == 0) {
+            // Then see if we can open it
+            if ((fd = open(mice[i].filespec, O_RDWR)) < 0) {
+                log_error("You don't have the proper permissions to open %s",
+                          mice[i].filespec);
+                i++;
+                continue;
+            }
+            close(fd);
+            log_debug("Found a %s device for mouse input using %s",
+                      debug[mice[i].type], mice[i].filespec);
+            
+            boost::shared_ptr<InputDevice> dev;
+#if defined(USE_MOUSE_PS2) || defined(USE_MOUSE_ETT)
+            dev = boost::shared_ptr<InputDevice>(new MouseDevice(gui));
+            if (dev->init(mice[i].filespec, DEFAULT_BUFFER_SIZE)) {
+                devices.push_back(dev);
+            }
+//            dev->dump();
+#endif
+        }     // stat()
+        i++;
+    }         // while()
+    
+    return devices;
+}
+
+bool
+MouseDevice::init()
+{
+    GNASH_REPORT_FUNCTION;
+
+    return init(MOUSE_DEVICE, DEFAULT_BUFFER_SIZE);
+}
+
+bool
+MouseDevice::init(const std::string &filespec, size_t size)
+{
+    GNASH_REPORT_FUNCTION;
+
+    _type = MOUSE;
+    _filespec = filespec;
+    _buffer.reset(new boost::uint8_t[size]);
+
+    // see http://www.computer-engineering.org/ps2mouse/ 
+    
+    // Try to open mouse device, be error tolerant (FD is kept open all the 
time)
+    _fd = open(filespec.c_str(), O_RDWR);
+    
+    if (_fd < 0) {
+        log_debug("Could not open %s: %s", filespec, strerror(errno));
+        return false;
+    }
+    
+    if (fcntl(_fd, F_SETFL, fcntl(_fd, F_GETFL) | O_NONBLOCK) < 0) {
+        log_error("Could not set non-blocking mode for mouse device: %s", 
strerror(errno));
+        close(_fd);
+        _fd = -1;
+        return false; 
+    }
+    
+    // Clear input buffer
+    unsigned char buf[10], byte;
+    while (read(_fd, buf, sizeof buf) > 0 ) { }
+
+    // A touchscreen works similar to a Mouse, but not exactly...
+    if (_type == InputDevice::MOUSE) {
+        // Reset mouse
+        if ((!command(0xFF, buf, 3)) || (buf[0] != 0xFA)) {
+            log_debug(_("Mouse reset failed"));
+            close(_fd);
+            _fd = -1;
+            return false; 
+        }
+        
+        // Get Device ID (not crucial, debug only)
+        if ((!command(0xF2, buf, 2)) || (buf[0] != 0xFA)) {
+            log_debug(_("WARNING: Could not detect mouse device ID"));
+        } else {
+            unsigned char devid = buf[1];
+            if (devid != 0)
+                log_debug(_("WARNING: Non-standard mouse device ID %d"), 
devid);
+        }
+        
+        // Enable mouse data reporting
+        if ((!command(0xF4, &byte, 1)) || (byte != 0xFA)) {
+            log_debug(_("Could not activate Data Reporting mode for mouse"));
+            close(_fd);
+            _fd = -1;
+            return false; 
+        }  
+        
+        log_debug("Mouse enabled for %s on fd #%d", _filespec, _fd);
+    }
+      
+    return true;
+}
+
+// From http://www.computer-engineering.org/ps2mouse
+//
+// PS/2 Mouse mouse data is always in a 3 byte packet that looks like this:
+//
+//            Bit 7       Bit 6         Bit 5        Bit 4      Bit 3     Bit 
2    Bit 1   Bit 0
+// Byte 1 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | 
Middle | Right | Left
+// Byte 2                               X movement
+// Byte 3                               Y movement
+//
+// The movement values are 9-bit 2's complement integers, where the
+// most significant bit appears as a "sign" bit in byte 1 of the
+// movement data packet. Their value represents the mouse's offset
+// relative to its position when the previous packet was sent, in
+// units determined by the current resolution. The range of values
+// that can be expressed is -255 to +255. If this range is exceeded,
+// the appropriate overflow bit is set.
+//
+// Note that reporting is disabled by default. The mouse will not
+// actually issue any movement data packets until it receives the
+// "Enable Data Reporting" (0xF4) command. 
+//
+// Stream mode is the default operating mode, and is otherwise set
+// using the "Set Stream Mode" (0xEA) command.
+//
+// In remote mode the mouse reads its inputs and updates its
+// counters/flags at the current sample rate, but it does not
+// automatically issue data packets when movement has
+// occured. Instead, the host polls the mouse using the "Read Data"
+// (0xEB) command. Upon receiving this command the mouse will issue a
+// single movement data packet and reset its movement counters. 
+
+// The mouse enters remote mode upon receiving the "Set Remote Mode"
+// (0xF0) command.
+bool
+MouseDevice::check()
+{
+    GNASH_REPORT_FUNCTION;
+
+    if (_fd < 0) {
+        return false;   // no mouse available
+    }
+    
+    int i;
+    int xmove, ymove, btn, btn_changed;
+    boost::shared_array<boost::uint8_t> buf;
+    if (_type == InputDevice::TOUCHMOUSE) {
+        // The eTurboTouch has a 4 byte packet
+        buf = readData(4);
+    } else {
+        // PS/2 Mouse packets are always 3 bytes
+        buf = readData(3);
+    }
+    
+    if (!buf) {
+        return false;
+    }
+    
+    // resync
+    if (!buf[0] & 8) { // bit 3 us always set in the first byte
+        log_error("No sync in first byte!");
+        return false;
+    }
+
+    // A Touchscreen works similar to a Mouse, but not exactly.
+    // At least for the eTurboTouch, it has a different layout
+    // in the packet for the location as it has an additional byte
+    btn   = buf[0] & 1;
+    if (_type == InputDevice::TOUCHMOUSE) {
+        xmove = (buf[1] << 7) | (buf[2]);
+        ymove = (buf[3] << 7) | (buf[4]);
+        /*
+          printf("touchscreen: %02x %02x %02x %02x %02x | status %d, pos: 
%d/%d\n",
+          mouse_buf[0], mouse_buf[1], mouse_buf[2], mouse_buf[3], 
mouse_buf[4],   
+          new_btn, new_x, new_y);
+        */    
+        
+        xmove = static_cast<int>(((static_cast<double>(xmove)- 355) / (1702 - 
355)
+                                  * 1536 + 256));
+        ymove = static_cast<int>(((static_cast<double>(ymove) - 482) / (1771 - 
482)
+                                  * 1536 + 256));
+        
+        xmove = xmove * _gui->getStage()->getStageWidth() / 2048;
+        ymove = (2048-ymove) * _gui->getStage()->getStageHeight() / 2048;
+    } else {                    // end of InputDevice::MOUSE
+        xmove = buf[1];
+        ymove = buf[2];
+    
+        if (buf[0] & 0x10) {
+            xmove = -(256-xmove);
+        }
+        if (buf[0] & 0x20) {
+            ymove = -(256-ymove);
+        }
+        
+        ymove *= -1; // vertical movement is upside-down
+        
+        log_debug(_("x/y %d/%d button %d"), xmove, ymove, btn);
+        
+        // movement    
+        _x += xmove;
+        _y += ymove;
+        
+        if (_x < 0) {
+            _x = 0;
+        }
+        if (_y < 0) {
+            _y = 0;
+        }
+        if (_x > _gui->getStage()->getStageWidth()) {
+            _x = _gui->getStage()->getStageWidth();
+        }
+        if (_y > _gui->getStage()->getStageHeight()) {
+            _y = _gui->getStage()->getStageHeight();
+        }
+    } // end of InputDevice::MOUSE
+    
+    log_debug(_("read mouse @ %d / %d, btn %d"), _x, _y, _button);
+    _gui->notifyMouseMove(_x, _y);
+    
+    // button
+    if (btn != _button) {
+        _button = btn;
+        log_debug("clicked: %d", btn); 
+        _gui->notifyMouseClick(btn); 
+        log_debug(_("mouse click! %d"), btn);
+    }
+    
+    return true;
+}
+
+bool
+MouseDevice::command(unsigned char cmd, unsigned char *buf, int count)
+{
+    GNASH_REPORT_FUNCTION;
+
+    int n;
+    
+    // flush input buffer
+    char trash[16];
+    do {
+        n = read(_fd, trash, sizeof trash);
+        if (n > 0) 
+            log_debug(_("mouse_command: discarded %d bytes from input 
buffer"), n);
+    } while (n > 0);
+    
+    // send command
+    write(_fd, &cmd, 1);
+
+    // read response (if any)
+    while (count > 0) {
+        gnashSleep(250*1000); // 250 ms inter-char timeout (simple method)
+        // TODO: use select() instead
+        
+        n = read(_fd, buf, count);
+        if (n <= 0) return false;
+        count -= n;
+        buf += n;
+    }
+    
+    return true;
+    
+} // command()
+
+// end of namespace
+}
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== added file 'gui/TouchDevice.cpp'
--- a/gui/TouchDevice.cpp       1970-01-01 00:00:00 +0000
+++ b/gui/TouchDevice.cpp       2010-07-29 16:23:03 +0000
@@ -0,0 +1,327 @@
+// 
+//   Copyright (C) 2010 Free Software Foundation, 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 3 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef HAVE_TSLIB_H
+# include <tslib.h>
+#endif
+#if defined(ENABLE_TSLIB) && !defined(HAVE_TSLIB_H)
+# warning "No tslib.h! Disabling touchscreen support"
+# undef ENABLE_TSLIB
+#endif
+
+#include "log.h"
+#include "InputDevice.h"
+
+#ifdef USE_TSLIB
+// Either use environment variable or hardcoded value
+// Hint: /dev/ts can be a symlink to the real ts device.
+// TSLIB_DEVICE environment variable should point to the
+// touchscreen device the library is using.
+static const char *TSLIB_DEVICE_ENV = "TSLIB_TSDEVICE";
+static const char *TSLIB_DEVICE_NAME = "/dev/ts";
+#endif
+
+namespace gnash {
+
+//static const char *MOUSE_DEVICE = "/dev/usb/tkpanel0";
+
+TouchDevice::TouchDevice()
+{
+    GNASH_REPORT_FUNCTION;
+}
+
+TouchDevice::TouchDevice(Gui *gui)
+{
+    GNASH_REPORT_FUNCTION;
+
+    _gui = gui;
+}
+
+TouchDevice::~TouchDevice()
+{
+    if (_tsDev) {
+        ts_close(_tsDev);
+    }
+}    
+
+bool
+TouchDevice::init()
+{
+    return init(TSLIB_DEVICE_NAME, DEFAULT_BUFFER_SIZE);
+}
+
+bool
+TouchDevice::init(const std::string &filespec, size_t /* size */)
+{
+    GNASH_REPORT_FUNCTION;
+
+    _type = TouchDevice::TOUCHSCREEN;
+    _filespec = filespec;
+    
+    char *devname = getenv(TSLIB_DEVICE_ENV);
+    if (!devname) {
+        devname = const_cast<char *>(TSLIB_DEVICE_NAME);
+    } else {
+        if (!filespec.empty()) {
+            devname = const_cast<char *>(_filespec.c_str());
+        } else {
+            log_error("No filespec specified for the touchscreen device.");
+        }
+    }
+    
+    _tsDev = ts_open(devname, 1);  //Open tslib non-blocking
+    if (_tsDev == 0) {
+        log_debug("Could not open touchscreen %s: %s", devname, 
strerror(errno));
+        return false;
+    }
+    
+    ts_config(_tsDev); 
+    if (ts_fd(_tsDev) < 0) {
+        log_debug("Could not get touchscreen fd %s: %s", devname, 
strerror(errno));
+        return false;
+    }
+    
+    log_debug("Using TSLIB on %s", devname);
+    return true;
+}
+
+bool
+TouchDevice::check()
+{
+    GNASH_REPORT_FUNCTION;
+
+    // Read events from the touchscreen and transport them into Gnash
+    // Tslib should be setup so the output is pretty clean.
+    struct ts_sample event;
+    // unsigned long    flags;
+    // unsigned long    buttons;
+    
+    if (_tsDev == 0) {
+        return false;           // No tslib device initialized, exit!
+    }
+    
+    int n = ts_read(_tsDev, &event, 1);     // read one event
+
+    // Did we read an event?
+    if (n == 1) {
+        if (event.pressure > 0) {
+            // the screen is touched
+            if (event.x > static_cast<int>(_gui->getStage()->getStageWidth())) 
{
+                event.x = static_cast<int>(_gui->getStage()->getStageWidth());
+            }
+            if (event.y > 
static_cast<int>(_gui->getStage()->getStageHeight())) {
+                event.y = static_cast<int>(_gui->getStage()->getStageHeight());
+            }
+            // FIXME: the API for these mouse events has changed, so this 
needs to be
+            // updated.
+            _gui->notifyMouseMove(int(event.x / _gui->getXScale()),
+                                  int(event.y / _gui->getYScale()));
+            _gui->notifyMouseClick(true);  //fire mouse click event into Gnash
+            
+            log_debug("Touched x: %d y: %d width: %d height: %d",
+                      event.x , event.y, _gui->getStage()->getStageWidth(),
+                      _gui->getStage()->getStageHeight());
+        } else {
+            _gui->notifyMouseClick(false);  //button released
+            log_debug("lifted x: %d y: %d", event.x, event.y); //debug
+        }
+    }
+
+    return true;
+}
+
+void
+TouchDevice::apply_ts_calibration(float* cx, float* cy, int rawx, int rawy)
+{
+    // This method use 3 points calibration
+    // it is described in http://www.embedded.com/story/OEG20020529S0046
+    
+    float k,a,b,c,d,e,f;
+    
+    float ref0x = _gui->getStage()->getStageWidth() / 5 * 1;
+    float ref0y = _gui->getStage()->getStageHeight() / 5 * 1;
+    float ref1x = _gui->getStage()->getStageWidth() / 5 * 4;
+
+    float ref1y = _gui->getStage()->getStageHeight() / 5 * 1;
+    float ref2x = _gui->getStage()->getStageWidth() / 5 * 4;
+    float ref2y = _gui->getStage()->getStageHeight() / 5 * 4;
+  
+    static float cal0x = 2048/5*1;   // very approximative default values
+    static float cal0y = 2048/5*4;
+    static float cal1x = 2048/5*1;
+    static float cal1y = 2048/5*1;
+    static float cal2x = 2048/5*4;
+    static float cal2y = 2048/5*1;
+  
+    static bool initialized=false; // woohooo.. better don't look at this 
code...
+    if (!initialized) {
+        initialized = true;
+    
+        char* settings = std::getenv("TSCALIB");
+    
+        if (settings) {
+    
+            // expected format: 
+            // 491,1635,451,537,1581,646
+            // (cal0x,cal0y,cal1x,cal1y,cal2x,cal2y; all integers)
+            char buffer[1024];      
+            char* p1;
+            char* p2;
+            bool ok = false;
+      
+            snprintf(buffer, sizeof buffer, "%s", settings);
+            p1 = buffer;
+      
+            do {
+                p2 = strchr(p1, ',');
+                if (!p2) continue; // stop here
+                *p2 = 0;
+                cal0x = atoi(p1);        
+                p1=p2+1;
+                
+                // cal0y        
+                p2 = strchr(p1, ',');
+                if (!p2) continue; // stop here
+                *p2 = 0;
+                cal0y = atoi(p1);        
+                p1=p2+1;
+                
+                // cal1x        
+                p2 = strchr(p1, ',');
+                if (!p2) continue; // stop here
+                *p2 = 0;
+                cal1x = atoi(p1);        
+                p1=p2+1;
+        
+                // cal1y        
+                p2 = strchr(p1, ',');
+                if (!p2) continue; // stop here
+                *p2 = 0;
+                cal1y = atoi(p1);        
+                p1=p2+1;
+        
+                // cal2x        
+                p2 = strchr(p1, ',');
+                if (!p2) continue; // stop here
+                *p2 = 0;
+                cal2x = atoi(p1);        
+                p1=p2+1;
+        
+                // cal2y        
+                cal2y = atoi(p1);
+        
+                ok = true;        
+        
+            } while (0);
+      
+            if (!ok)
+                log_debug(_("WARNING: Error parsing calibration data!"));
+      
+            log_debug(_("Using touchscreen calibration data: %.0f / %.0f / 
%.0f / %.0f / %.0f / %.0f"),
+                      cal0x, cal0y, cal1x, cal1y, cal2x, cal2y);
+        } else {
+            log_debug(_("WARNING: No touchscreen calibration settings found. "
+                        "The mouse pointer most probably won't work precisely. 
Set "
+                        "TSCALIB environment variable with correct values for 
better results"));
+        }
+    
+    } //!initialized
+
+      // calcul of K, A, B, C, D, E and F
+    k = (cal0x - cal2x) * (cal1y - cal2y) - (cal1x - cal2x) * (cal0y - cal2y);
+    a = ((ref0x - ref2x) * (cal1y - cal2y) - (ref1x - ref2x) * (cal0y - 
cal2y)) / k;
+    b = ((ref1x - ref2x) * (cal0x - cal2x) - (ref0x - ref2x) * (cal1x - 
cal2x)) / k;
+    c = (cal0y * (cal2x * ref1x - cal1x * ref2x) + cal1y * (cal0x * ref2x - 
cal2x * ref0x) + cal2y * (cal1x * ref0x - cal0x * ref1x)) / k;
+    d = ((ref0y - ref2y) * (cal1y - cal2y) - (ref1y - ref2y) * (cal0y - 
cal2y)) / k;
+    e = ((ref1y - ref2y) * (cal0x - cal2x) - (ref0y - ref2y) * (cal1x - 
cal2x)) / k;
+    f = (cal0y * (cal2x * ref1y - cal1x * ref2y) + cal1y * (cal0x * ref2y - 
cal2x * ref0y) + cal2y * (cal1x * ref0y - cal0x * ref1y)) / k;
+    
+    // real duty:
+    *cx = a * rawx + b * rawy + c;
+    *cy = d * rawx + e * rawy + f;
+}
+
+std::vector<boost::shared_ptr<InputDevice> >
+TouchDevice::scanForDevices(Gui *gui)
+{
+    // GNASH_REPORT_FUNCTION;
+
+    struct stat st;
+
+    std::vector<boost::shared_ptr<InputDevice> > devices;
+
+    // Debug strings to make output more readable
+    const char *debug[] = {
+        "TSlib"
+    };
+    
+    // Look for these files for mouse input
+    struct ts_types {
+        InputDevice::devicetype_e type;
+        const char *filespec;
+    };
+
+    struct ts_types touch[] = {
+        InputDevice::TOUCHSCREEN, "/dev/ts",
+        InputDevice::UNKNOWN, 0
+    };
+
+    int i = 0;
+    while (touch[i].type != InputDevice::UNKNOWN) {
+        int fd = 0;
+        if (stat(touch[i].filespec, &st) == 0) {
+            // Then see if we can open it
+            if ((fd = open(touch[i].filespec, O_RDWR)) < 0) {
+                log_error("You don't have the proper permissions to open %s",
+                          touch[i].filespec);
+                i++;
+                continue;
+            } // open()
+            log_debug("Found a %s device for mouse input using %s",
+                      debug[touch[i].type], touch[i].filespec);
+            boost::shared_ptr<InputDevice> dev;
+            dev = boost::shared_ptr<InputDevice>(new TouchDevice(gui));
+            if (dev->init(touch[i].filespec, DEFAULT_BUFFER_SIZE)) {
+                devices.push_back(dev);
+            }
+            dev->dump();
+            
+            devices.push_back(dev);
+        }     // stat()
+        close(fd);
+        i++;
+    }         // while()
+    
+    return devices;
+}
+
+// end of namespace
+}
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== modified file 'gui/fb/fb.am'
--- a/gui/fb/fb.am      2010-07-15 03:07:54 +0000
+++ b/gui/fb/fb.am      2010-07-26 21:27:28 +0000
@@ -21,7 +21,7 @@
 if BUILD_FB_GUI
 bin_PROGRAMS += fb-gnash
 fb_gnash_SOURCES = $(GUI_SRCS) fb/gui_fb.cpp fb/fb.cpp fb/fbsup.h
-fb_gnash_CPPFLAGS = -DGUI_FB -DGUI_CONFIG=\"FB\" \
+fb_gnash_CPPFLAGS = -DGUI_FB -DGUI_CONFIG=\"FB\" -DFAKEFB=\"$(FAKEFB)\" \
        $(AM_CPPFLAGS) 
 fb_gnash_LDFLAGS = $(LIBLTDL) -export-dynamic $(AM_LDFLAGS)
 #fb_gnash_DEPENDENCIES = .configline

=== modified file 'gui/fb/fb.cpp'
--- a/gui/fb/fb.cpp     2010-07-15 03:07:54 +0000
+++ b/gui/fb/fb.cpp     2010-07-29 16:02:59 +0000
@@ -24,15 +24,10 @@
 /// Linux Input Subsystem (/dev/input/event*). Both standard mice and 
 /// touchscreen devices are supported.
 ///
-/// Make sure the USE_INPUT_EVENTS macro is defined in fbsup.h so that
-/// the events system is enabled for the FB GUI (this may be configurable
-/// at runtime sometime).
-///
 /// Since there can be multiple input devices in /dev/input/ you have to
 /// specify which device to use using the 
 ///  POINTING_DEVICE environment variable for the mouse and
 ///  KEYBOARD_DEVICE environment variable for the keyboard
-   
 
 /// \page fb_calibration FB GUI Touchscreen Calibration
 ///
@@ -65,6 +60,19 @@
 /// commas (X,Y,X,Y), like this: 
 ///   TSCALIB=491,1635,1581,639 gnash yourmovie.swf    
 
+///
+/// 10-4-2008  N. Coesel
+/// Added support for tslib. Tslib is a library which allows to create
+/// a stack / cascade of filters to filter and scale touch-screen output.
+/// The source doesn't come with much documentation, but writing your
+/// own filter based on an existing filter is really easy. Tslib can 
+/// deal with old style H3600 style touchscreens and the newer event 
+/// interface. See http://tslib.berlios.de/ to get the source. 
+///
+/// The check_tslib() routine assumes filtering for movement and presses
+/// is properly setup. Scaling is supposed to be performed by tslib or
+/// the underlying touchscreen driver.
+
 #ifdef HAVE_CONFIG_H
 #include "gnashconfig.h"
 #endif
@@ -83,6 +91,14 @@
 #include <csignal>
 #include <cstdlib> // getenv
 
+#ifdef HAVE_TSLIB_H
+# include <tslib.h>
+#endif
+#if defined(ENABLE_TSLIB) && !defined(HAVE_TSLIB_H)
+# warning "No tslib.h! Disabling touchscreen support"
+# undef ENABLE_TSLIB
+#endif
+
 #include "gnash.h"
 #include "gui.h"
 #include "fbsup.h"
@@ -130,1344 +146,753 @@
 #ifdef DEBUG_SHOW_FPS
 double fps_timer=0;
 int fps_counter=0;
-void profile() {
-  int fd;
-  double uptime, idletime;
-  char buffer[20];
-  int readcount;
-
-  fd = open("/proc/uptime", O_RDONLY);
-  if (fd<0) return;
-  readcount = read(fd, buffer, sizeof(buffer)-1);
-  buffer[readcount]=0;
-  sscanf(buffer, "%lf %lf", &uptime, &idletime);
-  close(fd);
-  
-  fps_counter++;
-
-  if (fps_counter<2) {
-    fps_timer = uptime;
-    return;    
-  }
-  
-  printf("FPS: %.3f (%.2f)\n", fps_counter/(uptime-fps_timer), 
uptime-fps_timer);
-  
+void
+profile()
+{
+    int fd;
+    double uptime, idletime;
+    char buffer[20];
+    int readcount;
+    
+    fd = open("/proc/uptime", O_RDONLY);
+    if (fd<0) return;
+    readcount = read(fd, buffer, sizeof(buffer)-1);
+    buffer[readcount]=0;
+    sscanf(buffer, "%lf %lf", &uptime, &idletime);
+    close(fd);
+    
+    fps_counter++;
+    
+    if (fps_counter<2) {
+        fps_timer = uptime;
+        return;    
+    }
+    
+    printf("FPS: %.3f (%.2f)\n", fps_counter/(uptime-fps_timer), 
uptime-fps_timer);
+    
 }
 #endif
-//---------------
 
-int terminate_request=false;  // global scope to avoid GUI access
+int terminate_request = false;  // global scope to avoid GUI access
 
 /// Called on CTRL-C and alike
-void terminate_signal(int /*signo*/) {
-  terminate_request=true;
+void
+terminate_signal(int /*signo*/) {
+    terminate_request = true;
 }
 
-
-//---------------
-
 FBGui::FBGui(unsigned long xid, float scale, bool loop, RunResources& r)
-  : Gui(xid, scale, loop, r)
+    : Gui(xid, scale, loop, r),
+      fd(-1),
+      original_vt(-1),
+      original_kd(-1),
+      own_vt(-1),
+      fbmem(0),
+      buffer(0),                // the real value is set by 
ENABLE_DOUBLE_BUFFERING
+      m_stage_width(0),
+      m_stage_height(0),
+      m_rowsize(0)
 {
-  fd      = -1;
-  fbmem   = NULL;
-  #ifdef DOUBLE_BUFFER
-  buffer  = NULL;
-  #endif
-
-  input_fd=-1;
-  
-  signal(SIGINT, terminate_signal);
-  signal(SIGTERM, terminate_signal);
+    // initializing to zero helps with debugging and prevents weird bugs
+//    memset(mouse_buf, 0, 256);
+    memset(&var_screeninfo, 0, sizeof(fb_var_screeninfo));
+    memset(&fix_screeninfo, 0, sizeof(fb_fix_screeninfo));
+    
+    signal(SIGINT, terminate_signal);
+    signal(SIGTERM, terminate_signal);
 }
 
 FBGui::~FBGui()
-{
-  
-  if (fd>0) {
-    enable_terminal();
-    log_debug(_("Closing framebuffer device"));
-    close(fd);
-  }
-  
-  close(input_fd);
-
-  #ifdef DOUBLE_BUFFER
-  if (buffer) {
-    log_debug(_("Free'ing offscreen buffer"));
-    free(buffer);
-  }
-  #endif
-}
-
-
-bool FBGui::set_grayscale_lut8()
-{
-  #define TO_16BIT(x) (x | (x<<8))
-
-  struct fb_cmap cmap;
-  int i;
-
-  log_debug(_("LUT8: Setting up colormap"));
-
-  cmap.start=0;
-  cmap.len=256;
-  cmap.red = (__u16*)malloc(CMAP_SIZE);
-  cmap.green = (__u16*)malloc(CMAP_SIZE);
-  cmap.blue = (__u16*)malloc(CMAP_SIZE);
-  cmap.transp = NULL;
-
-  for (i=0; i<256; i++) {
-
-    int r = i;
-    int g = i;
-    int b = i;
-
-    cmap.red[i] = TO_16BIT(r);
-    cmap.green[i] = TO_16BIT(g);
-    cmap.blue[i] = TO_16BIT(b);
-
-  }
-
-  if (ioctl(fd, FBIOPUTCMAP, &cmap)) {
-    log_error(_("LUT8: Error setting colormap: %s"), strerror(errno));
-    return false;
-  }
-
-  return true;
-
-  #undef TO_16BIT
-}
-
-
-bool FBGui::init(int /*argc*/, char *** /*argv*/)
-{
-
-  // Initialize mouse (don't abort if no mouse found)
-  if (!init_mouse()) {
-    // just report to the user, keep on going...
-    log_debug(_("You won't have any pointing input device, sorry."));
-  }
-  
-  // Initialize keyboard (still not critical)
-  if (!init_keyboard()) {   
-    log_debug(_("You won't have any keyboard input device, sorry."));
-  }
-
-  // Open the framebuffer device
-  fd = open("/dev/fb0", O_RDWR);
-  if (fd<0) {
-    fatal_error("Could not open framebuffer device: %s", strerror(errno));
-    return false;
-  }
-  
-  // Load framebuffer properties
-  ioctl(fd, FBIOGET_VSCREENINFO, &var_screeninfo);
-  ioctl(fd, FBIOGET_FSCREENINFO, &fix_screeninfo);
-  log_debug(_("Framebuffer device uses %d bytes of memory."),
-    fix_screeninfo.smem_len);
-  log_debug(_("Video mode: %dx%d with %d bits per pixel."),
-    var_screeninfo.xres, var_screeninfo.yres, var_screeninfo.bits_per_pixel);
-
-  // map framebuffer into memory
-  fbmem = (unsigned char *)
-    mmap(0, fix_screeninfo.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-
-#ifdef DOUBLE_BUFFER
-  // allocate offscreen buffer
-  buffer = (unsigned char*)malloc(fix_screeninfo.smem_len);
-  memset(buffer, 0, fix_screeninfo.smem_len);
+{  
+    if (fd > 0) {
+        enable_terminal();
+        log_debug(_("Closing framebuffer device"));
+        close(fd);
+    }
+
+#ifdef ENABLE_DOUBLE_BUFFERING
+    if (buffer) {
+        log_debug(_("Free'ing offscreen buffer"));
+        free(buffer);
+    }
+#endif
+}
+
+bool
+FBGui::set_grayscale_lut8()
+{
+#define TO_16BIT(x) (x | (x<<8))
+
+    struct fb_cmap cmap;
+    int i;
+
+    log_debug(_("LUT8: Setting up colormap"));
+
+    cmap.start=0;
+    cmap.len=256;
+    cmap.red = (__u16*)malloc(CMAP_SIZE);
+    cmap.green = (__u16*)malloc(CMAP_SIZE);
+    cmap.blue = (__u16*)malloc(CMAP_SIZE);
+    cmap.transp = NULL;
+
+    for (i=0; i<256; i++) {
+        int r = i;
+        int g = i;
+        int b = i;
+
+        cmap.red[i] = TO_16BIT(r);
+        cmap.green[i] = TO_16BIT(g);
+        cmap.blue[i] = TO_16BIT(b);
+    }
+
+#ifdef ENABLE_FAKE_FRAMEBUFFER
+    if (fakefb_ioctl(fd, FBIOPUTCMAP, &cmap))
+#else
+    if (ioctl(fd, FBIOPUTCMAP, &cmap))
+#endif
+    {
+        log_error(_("LUT8: Error setting colormap: %s"), strerror(errno));
+        return false;
+    }
+
+    return true;
+
+#undef TO_16BIT
+}
+
+bool
+FBGui::init(int /*argc*/, char *** /*argv*/)
+{
+    GNASH_REPORT_FUNCTION;
+
+    // Initialize all the input devices
+
+    // Look for Mice that use the PS/2 mouse protocol
+    _inputs = InputDevice::scanForDevices(this);
+    if (_inputs.empty()) {
+        log_error("Found no accessible input event devices");
+    }
+    
+    // Open the framebuffer device
+#ifdef ENABLE_FAKE_FRAMEBUFFER
+    fd = open(FAKEFB, O_RDWR);
+#else
+    fd = open("/dev/fb0", O_RDWR);
+#endif
+    if (fd < 0) {
+        fatal_error("Could not open framebuffer device: %s", strerror(errno));
+        return false;
+    }
+  
+    // Load framebuffer properties
+#ifdef ENABLE_FAKE_FRAMEBUFFER
+    fakefb_ioctl(fd, FBIOGET_VSCREENINFO, &var_screeninfo);
+    fakefb_ioctl(fd, FBIOGET_FSCREENINFO, &fix_screeninfo);
+#else
+    ioctl(fd, FBIOGET_VSCREENINFO, &var_screeninfo);
+    ioctl(fd, FBIOGET_FSCREENINFO, &fix_screeninfo);
+#endif
+    log_debug(_("Framebuffer device uses %d bytes of memory."),
+              fix_screeninfo.smem_len);
+    log_debug(_("Video mode: %dx%d with %d bits per pixel."),
+              var_screeninfo.xres, var_screeninfo.yres, 
var_screeninfo.bits_per_pixel);
+
+    // map framebuffer into memory
+    fbmem = (unsigned char *)
+        mmap(0, fix_screeninfo.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 
0);
+
+#ifdef ENABLE_DOUBLE_BUFFERING
+    // allocate offscreen buffer
+    buffer = (unsigned char*)malloc(fix_screeninfo.smem_len);
+    memset(buffer, 0, fix_screeninfo.smem_len);
 #endif  
 
 #ifdef PIXELFORMAT_LUT8
-  // Set grayscale for 8 bit modes
-  if (var_screeninfo.bits_per_pixel==8) {
-    if (!set_grayscale_lut8())
-      return false;
-  }
+    // Set grayscale for 8 bit modes
+    if (var_screeninfo.bits_per_pixel==8) {
+        if (!set_grayscale_lut8())
+            return false;
+    }
 #endif
 
-  // Ok, now initialize AGG
-  return initialize_renderer();
+    // Ok, now initialize AGG
+    return initialize_renderer();
 }
 
-bool FBGui::initialize_renderer() {
-  const int width    = var_screeninfo.xres;
-  const int height   = var_screeninfo.yres;
-  const int bpp = var_screeninfo.bits_per_pixel;
-  const int size = fix_screeninfo.smem_len; 
-
-  // TODO: should recalculate!  
-  unsigned char* mem;
-  Renderer_agg_base* agg_handler;
-  
-  m_stage_width = width;
-  m_stage_height = height;
-  
-  _validbounds.setTo(0, 0, width - 1, height - 1);
-    
-  
-#ifdef DOUBLE_BUFFER
-  log_debug(_("Double buffering enabled"));
-  mem = buffer;
+bool
+FBGui::initialize_renderer()
+{
+    GNASH_REPORT_FUNCTION;
+
+    const int width    = var_screeninfo.xres;
+    const int height   = var_screeninfo.yres;
+    const int bpp = var_screeninfo.bits_per_pixel;
+    const int size = fix_screeninfo.smem_len; 
+
+    // TODO: should recalculate!  
+    unsigned char* mem;
+    Renderer_agg_base* agg_handler;
+  
+    m_stage_width = width;
+    m_stage_height = height;
+  
+    _validbounds.setTo(0, 0, width - 1, height - 1);    
+  
+#ifdef ENABLE_DOUBLE_BUFFERING
+    log_debug(_("Double buffering enabled"));
+    mem = buffer;
 #else
-  log_debug(_("Double buffering disabled"));
-  mem = fbmem;
-#endif
-  
-  
-  agg_handler = NULL;
-  
-  // choose apropriate pixel format
-  
-  log_debug(_("red channel: %d / %d"), var_screeninfo.red.offset, 
-    var_screeninfo.red.length);
-  log_debug(_("green channel: %d / %d"), var_screeninfo.green.offset, 
-    var_screeninfo.green.length);
-  log_debug(_("blue channel: %d / %d"), var_screeninfo.blue.offset, 
-    var_screeninfo.blue.length);
-  log_debug(_("Total bits per pixel: %d"), var_screeninfo.bits_per_pixel);
-  
-  const char* pixelformat = agg_detect_pixel_format(
-    var_screeninfo.red.offset, var_screeninfo.red.length,
-    var_screeninfo.green.offset, var_screeninfo.green.length,
-    var_screeninfo.blue.offset, var_screeninfo.blue.length,
-    bpp
-  );
-
-  if (pixelformat) {    
-    agg_handler = create_Renderer_agg(pixelformat);      
-  } else {
-    fatal_error("The pixel format of your framebuffer could not be detected.");
-    return false;
-  }
-
-  assert(agg_handler);
-
-  _renderer.reset(agg_handler);
-
-  _runResources.setRenderer(_renderer);
-  
-  m_rowsize = var_screeninfo.xres_virtual*((bpp+7)/8);
-  
-  agg_handler->init_buffer(mem, size, width, height, m_rowsize);
-  
-  disable_terminal();
-
-  return true;
-}
-
-bool FBGui::run()
-{
-  struct timeval tv;
-
-  double start_timer;
-  
-  if (!gettimeofday(&tv, NULL))
-    start_timer = static_cast<double>(tv.tv_sec) +
-    static_cast<double>(tv.tv_usec) / 1000000.0;
-  else
-    start_timer = 0.0;
-    
-  
-  // let the GUI recompute the x/y scale factors to best fit the whole screen
-  resize_view(_validbounds.width(), _validbounds.height());
-
-  while (!terminate_request) {
-  
-    // wait the "heartbeat" inteval
-    gnashSleep(_interval * 1000);    
-    // TODO: Do we need to check the real time slept or is it OK when we woke
-    // up early because of some Linux signal sent to our process (and thus
-    // "advance" faster than the "heartbeat" interval)? - Udo
-  
-    // check input devices
-    check_mouse();
-    check_keyboard();
-  
-    // advance movie  
-    Gui::advance_movie(this);
-    
-  }
-  
-  return true;
-}
-
-void FBGui::renderBuffer()
-{
-  if ( _drawbounds.size() == 0 ) return; // nothing to do..
-
-#ifdef DOUBLE_BUFFER
-
-  // Size of a pixel in bytes
-  // NOTE: +7 to support 15 bpp
-  const unsigned int pixel_size = (var_screeninfo.bits_per_pixel+7)/8;
-
-    
-  for (unsigned int bno=0; bno < _drawbounds.size(); bno++) {
-  
-    geometry::Range2d<int>& bounds = _drawbounds[bno];
-    
-    assert ( ! bounds.isWorld() );  
-    
-    // Size, in bytes, of a row that has to be copied
-    const unsigned int row_size = (bounds.width()+1) * pixel_size;
-      
-    // copy each row
-    const int minx = bounds.getMinX();
-    const int maxy = bounds.getMaxY();
-    
-    for (int y=bounds.getMinY(); y<=maxy; ++y) {
-    
-      const unsigned int pixel_index = y * m_rowsize + minx*pixel_size;
-      
-      memcpy(&fbmem[pixel_index], &buffer[pixel_index], row_size);
-      
-    }
-  }  
+    log_debug(_("Double buffering disabled"));
+    mem = fbmem;
+#endif
+  
+    agg_handler = NULL;
+  
+    // choose apropriate pixel format
+  
+    log_debug(_("red channel: %d / %d"), var_screeninfo.red.offset, 
+              var_screeninfo.red.length);
+    log_debug(_("green channel: %d / %d"), var_screeninfo.green.offset, 
+              var_screeninfo.green.length);
+    log_debug(_("blue channel: %d / %d"), var_screeninfo.blue.offset, 
+              var_screeninfo.blue.length);
+    log_debug(_("Total bits per pixel: %d"), var_screeninfo.bits_per_pixel);
+  
+    const char* pixelformat = agg_detect_pixel_format(
+        var_screeninfo.red.offset, var_screeninfo.red.length,
+        var_screeninfo.green.offset, var_screeninfo.green.length,
+        var_screeninfo.blue.offset, var_screeninfo.blue.length,
+        bpp
+        );
+
+    if (pixelformat) {    
+        agg_handler = create_Renderer_agg(pixelformat);      
+    } else {
+        fatal_error("The pixel format of your framebuffer could not be 
detected.");
+        return false;
+    }
+
+    assert(agg_handler);
+
+    _renderer.reset(agg_handler);
+
+    _runResources.setRenderer(_renderer);
+  
+    m_rowsize = var_screeninfo.xres_virtual*((bpp+7)/8);
+  
+    agg_handler->init_buffer(mem, size, width, height, m_rowsize);
+  
+    disable_terminal();
+
+    return true;
+}
+
+bool
+FBGui::run()
+{
+    GNASH_REPORT_FUNCTION;
+
+    struct timeval tv;
+
+    double start_timer;
+  
+#ifdef USE_TSLIB
+    int ts_loop_count;
+#endif
+    
+    if (!gettimeofday(&tv, NULL)) {
+        start_timer = static_cast<double>(tv.tv_sec) +
+            static_cast<double>(tv.tv_usec) / 1000000.0;
+    } else {
+        start_timer = 0.0;
+    }  
+  
+    // let the GUI recompute the x/y scale factors to best fit the whole screen
+    resize_view(_validbounds.width(), _validbounds.height());
+
+    // This loops endlessly at the frame rate
+    while (!terminate_request) {  
+        // wait the "heartbeat" inteval
+        gnashSleep(_interval * 1000);    
+        // TODO: Do we need to check the real time slept or is it OK when we 
woke
+        // up early because of some Linux signal sent to our process (and thus
+        // "advance" faster than the "heartbeat" interval)? - Udo
+
+#ifdef USE_TSLIB
+        ts_loop_count++; //increase loopcount
+#endif        
+        
+        // check input devices
+        checkForData();
+        
+        // advance movie  
+        Gui::advance_movie(this);
+    }
+  
+    return true;
+}
+
+void
+FBGui::renderBuffer()
+{
+    GNASH_REPORT_FUNCTION;
+
+    if ( _drawbounds.size() == 0 ) return; // nothing to do..
+
+#ifdef ENABLE_DOUBLE_BUFFERING
+    // Size of a pixel in bytes
+    // NOTE: +7 to support 15 bpp
+    const unsigned int pixel_size = (var_screeninfo.bits_per_pixel+7)/8;
+    
+    for (unsigned int bno=0; bno < _drawbounds.size(); bno++) {  
+        geometry::Range2d<int>& bounds = _drawbounds[bno];
+        assert ( ! bounds.isWorld() );  
+    
+        // Size, in bytes, of a row that has to be copied
+        const unsigned int row_size = (bounds.width()+1) * pixel_size;
+      
+        // copy each row
+        const int minx = bounds.getMinX();
+        const int maxy = bounds.getMaxY();
+    
+        for (int y=bounds.getMinY(); y<=maxy; ++y) {
+            const unsigned int pixel_index = y * m_rowsize + minx*pixel_size;  
    
+            memcpy(&fbmem[pixel_index], &buffer[pixel_index], row_size);
+        }
+    }  
        
 #endif
   
 #ifdef DEBUG_SHOW_FPS
-  profile();
+    profile();
 #endif
 }
 
-bool FBGui::createWindow(const char* /*title*/, int /*width*/, int /*height*/,
+bool
+FBGui::createWindow(const char* /*title*/, int /*width*/, int /*height*/,
                      int /*xPosition*/, int /*yPosition*/)
 {
-  // Framebuffer has no windows... :-)
-
-  return true;
-}
-
-bool FBGui::createMenu()
-{
-  // no menu support! 
-  return true;
-}
-
-bool FBGui::setupEvents()
-{
-  // events currently not supported!
-  return true;
-}
-
-void FBGui::setInterval(unsigned int interval)
-{
-  _interval = interval;
-}
-
-void FBGui::setTimeout(unsigned int /*timeout*/)
-{
-
-}
-
-void FBGui::setFullscreen()
-{
-  // FB GUI always runs fullscreen; ignore...
-}
-
-void FBGui::unsetFullscreen()
-{
-  // FB GUI always runs fullscreen; ignore...
-}
-
-void FBGui::showMenu(bool /*show*/)
-{
-  log_unimpl(_("This GUI does not yet support menus"));
-}
-
-bool FBGui::showMouse(bool /*show*/)
-{
-  log_unimpl(_("This GUI does not yet support a mouse pointer"));
-  // Should return true if the pointer was visible before call,
-  // otherwise false;
-  return true;
-}
-
-
-int FBGui::valid_x(int x) {
-  if (x<0) x=0;
-  if (x>=m_stage_width) x=m_stage_width-1;
-  return x;
-}
-
-int FBGui::valid_y(int y) {
-  if (y<0) y=0;
-  if (y>=m_stage_height) y=m_stage_height-1;
-  return y;
-}
-
-void FBGui::setInvalidatedRegions(const InvalidatedRanges& ranges)
-{
-  _renderer->set_invalidated_regions(ranges);
-
-  _drawbounds.clear();
-    
-  for (unsigned int rno=0; rno<ranges.size(); rno++) {
-  
-    geometry::Range2d<int> bounds = Intersection(
-      _renderer->world_to_pixel(ranges.getRange(rno)),
-      _validbounds);
-      
-    // it may happen that a particular range is out of the screen, which 
-    // will lead to bounds==null. 
-    if (bounds.isNull()) continue; 
-    
-    _drawbounds.push_back(bounds);
-      
-  }
-  
-}
-
-char* FBGui::find_accessible_tty(int no) {
-
-  char* fn;
-  
-  fn = find_accessible_tty("/dev/vc/%d", no);   if (fn) return fn;
-  fn = find_accessible_tty("/dev/tty%d", no);   if (fn) return fn;
-  fn = find_accessible_tty("/dev/tty%02x", no); if (fn) return fn;
-  fn = find_accessible_tty("/dev/tty%x", no);   if (fn) return fn;
-  fn = find_accessible_tty("/dev/tty%02d", no); if (fn) return fn;
-  
-  if (no==0) {
-    fn = find_accessible_tty("/dev/tty", no);  // just "/dev/tty" 
-    if (fn) return fn;
-  }
-    
-  return NULL;
-
-}
-
-char* FBGui::find_accessible_tty(const char* format, int no) {
-
-  static char fname[1024];
-  
-  snprintf(fname, sizeof fname, format, no);
-    
-  if (access(fname, R_OK|W_OK) != -1) {
-    return fname;
-  }
-
-  return NULL; 
-}
-
-bool FBGui::disable_terminal() 
-{
-  original_kd = -1;
-  
-  struct vt_stat vts;
-  
-  // Find the TTY device name
-  
-  char* tty = find_accessible_tty(0);
-  
-  int fd;
-  
-  if (!tty) {
-    log_debug(_("WARNING: Could not detect controlling TTY"));
-    return false;
-  }
-  
-  
-  // Detect the currently active virtual terminal (so we can switch back to
-  // it later)
-  
-  fd = open(tty, O_RDWR);
-  if (fd<0) {
-    log_debug(_("WARNING: Could not open %s"), tty);
-    return false;
-  }
-  
-  if (ioctl(fd, VT_GETSTATE, &vts) == -1) {
-    log_debug(_("WARNING: Could not get current VT state"));
-    close(fd);
-    return false;
-  }
-    
-  original_vt = vts.v_active;
-  log_debug(_("Original TTY NO = %d"), original_vt);   
+    // Framebuffer has no windows... :-)
+    
+    return true;
+}
+
+bool
+FBGui::createMenu()
+{
+    // no menu support! 
+    return true;
+}
+
+bool
+FBGui::setupEvents()
+{
+    // events currently not supported!
+    return true;
+}
+
+void
+FBGui::setInterval(unsigned int interval)
+{
+    _interval = interval;
+}
+
+void
+FBGui::setTimeout(unsigned int /*timeout*/)
+{
+
+}
+
+void
+FBGui::setFullscreen()
+{
+    // FB GUI always runs fullscreen; ignore...
+}
+
+void
+FBGui::unsetFullscreen()
+{
+  // FB GUI always runs fullscreen; ignore...
+}
+
+void
+FBGui::showMenu(bool /*show*/)
+{
+    log_unimpl(_("This GUI does not yet support menus"));
+}
+
+bool
+FBGui::showMouse(bool /*show*/)
+{
+    log_unimpl(_("This GUI does not yet support a mouse pointer"));
+    // Should return true if the pointer was visible before call,
+    // otherwise false;
+    return true;
+}
+
+int
+FBGui::valid_x(int x) {
+    if (x < 0) x = 0;
+    if (x >= m_stage_width) x = m_stage_width - 1;
+    return x;
+}
+
+int
+FBGui::valid_y(int y)
+{
+    if (y < 0) y = 0;
+    if (y >= m_stage_height) y = m_stage_height - 1;
+    return y;
+}
+
+void
+FBGui::setInvalidatedRegions(const InvalidatedRanges& ranges)
+{
+    _renderer->set_invalidated_regions(ranges);
+    
+    _drawbounds.clear();
+    
+    for (unsigned int rno=0; rno<ranges.size(); rno++) {
+        geometry::Range2d<int> bounds = Intersection(
+            _renderer->world_to_pixel(ranges.getRange(rno)),
+            _validbounds);
+        
+        // it may happen that a particular range is out of the screen, which 
+        // will lead to bounds==null. 
+        if (bounds.isNull()) continue; 
+        
+        _drawbounds.push_back(bounds);   
+    }
+}
+
+char *
+FBGui::find_accessible_tty(int no)
+{
+    char* fn;
+    
+    fn = find_accessible_tty("/dev/vc/%d", no);   if (fn) return fn;
+    fn = find_accessible_tty("/dev/tty%d", no);   if (fn) return fn;
+    fn = find_accessible_tty("/dev/tty%02x", no); if (fn) return fn;
+    fn = find_accessible_tty("/dev/tty%x", no);   if (fn) return fn;
+    fn = find_accessible_tty("/dev/tty%02d", no); if (fn) return fn;
+  
+    if (no==0) {
+        fn = find_accessible_tty("/dev/tty", no);  // just "/dev/tty" 
+        if (fn) return fn;
+    }
+    
+    return NULL;
+}
+
+char *
+FBGui::find_accessible_tty(const char* format, int no)
+{
+    static char fname[1024];
+    
+    snprintf(fname, sizeof fname, format, no);
+    
+    if (access(fname, R_OK|W_OK) != -1) {
+        return fname;
+    }
+    
+    return NULL; 
+}
+
+bool
+FBGui::disable_terminal() 
+{
+    original_kd = -1;
+    
+    struct vt_stat vts;
+    
+    // Find the TTY device name
+    
+    char* tty = find_accessible_tty(0);
+    
+    int fd;
+  
+    if (!tty) {
+        log_debug(_("WARNING: Could not detect controlling TTY"));
+        return false;
+    }
+    
+    
+    // Detect the currently active virtual terminal (so we can switch back to
+    // it later)
+    
+    fd = open(tty, O_RDWR);
+    if (fd < 0) {
+        log_debug(_("WARNING: Could not open %s"), tty);
+        return false;
+    }
+    
+    if (ioctl(fd, VT_GETSTATE, &vts) == -1) {
+        log_debug(_("WARNING: Could not get current VT state"));
+        close(fd);
+        return false;
+    }
+    
+    original_vt = vts.v_active;
+    log_debug(_("Original TTY NO = %d"), original_vt);   
   
 #ifdef REQUEST_NEW_VT
+    // Request a new VT number
+    if (ioctl(fd, VT_OPENQRY, &own_vt) == -1) {
+        log_debug(_("WARNING: Could not request a new VT"));
+        close(fd);
+        return false;
+    }
+  
+    log_debug(_("Own TTY NO = %d"), own_vt);
 
-  // Request a new VT number
-  if (ioctl(fd, VT_OPENQRY, &own_vt) == -1) {
-    log_debug(_("WARNING: Could not request a new VT"));
-    close(fd);
-    return false;
-  }
-  
-  log_debug(_("Own TTY NO = %d"), own_vt);
-  
-  close(fd);
-  
-  // Activate our new VT
-  tty = find_accessible_tty(own_vt);
-  if (!tty) {
-    log_debug(_("WARNING: Could not find device for VT number %d"), own_vt);
-    return false;
-  }
-  
-  fd = open(tty, O_RDWR);
-  if (fd<0) {
-    log_debug(_("WARNING: Could not open %s"), tty);
-    return false;
-  }
-  
-  if (ioctl(fd, VT_ACTIVATE, own_vt) == -1) {
-    log_debug(_("WARNING: Could not activate VT number %d"), own_vt);
-    close(fd);
-    return false;
-  }
-  
-  if (ioctl(fd, VT_WAITACTIVE, own_vt) == -1) {
-    log_debug(_("WARNING: Error waiting for VT %d becoming active"), own_vt);
-    //close(tty);
-    //return false;   don't abort
-  }
+    if (fd > 0) {
+        close(fd);
+    }
+  
+    // Activate our new VT
+    tty = find_accessible_tty(own_vt);
+    if (!tty) {
+        log_debug(_("WARNING: Could not find device for VT number %d"), 
own_vt);
+        return false;
+    }
+  
+    fd = open(tty, O_RDWR);
+    if (fd < 0) {
+        log_debug(_("WARNING: Could not open %s"), tty);
+        return false;
+    }
+  
+    if (ioctl(fd, VT_ACTIVATE, own_vt) == -1) {
+        log_debug(_("WARNING: Could not activate VT number %d"), own_vt);
+        close(fd);
+        return false;
+    }
+  
+    if (ioctl(fd, VT_WAITACTIVE, own_vt) == -1) {
+        log_debug(_("WARNING: Error waiting for VT %d becoming active"), 
own_vt);
+        //close(tty);
+        //return false;   don't abort
+    }
 
 #else
 
-  own_vt = original_vt;   // keep on using the original VT
-  
-  close(fd);
-  
-  // Activate our new VT
-  tty = find_accessible_tty(own_vt);
-  if (!tty) {
-    log_debug(_("WARNING: Could not find device for VT number %d"), own_vt);
-    return false;
-  }
-  
-  fd = open(tty, O_RDWR);
-  if (fd<0) {
-    log_debug(_("WARNING: Could not open %s"), tty);
-    return false;
-  }
-  
-  /*
-  // Become session leader and attach to terminal
-  setsid();
-  if (ioctl(fd, TIOCSCTTY, 0) == -1) {
+    own_vt = original_vt;   // keep on using the original VT
+  
+    if (fd > 0) {
+        close(fd);
+    }
+  
+    // Activate our new VT
+    tty = find_accessible_tty(own_vt);
+    if (!tty) {
+        log_debug(_("WARNING: Could not find device for VT number %d"), 
own_vt);
+        return false;
+    }
+  
+    fd = open(tty, O_RDWR);
+    if (fd < 0) {
+        log_debug(_("WARNING: Could not open %s"), tty);
+        return false;
+    }
+  
+    /*
+    // Become session leader and attach to terminal
+    setsid();
+    if (ioctl(fd, TIOCSCTTY, 0) == -1) {
     log_debug(_("WARNING: Could not attach controlling terminal (%s)"), tty);
-  }
-  */
-  
-
+    }
+    */
 #endif  
   
-  // Disable keyboard cursor
-  
-  if (ioctl(fd, KDGETMODE, &original_kd) == -1) {
-    log_debug(_("WARNING: Could not query current keyboard mode on VT"));
-  }
-
-  if (ioctl(fd, KDSETMODE, KD_GRAPHICS) == -1) {
-    log_debug(_("WARNING: Could not switch to graphics mode on new VT"));
-  }
-   
-  close(fd);
-  
-  log_debug(_("VT %d ready"), own_vt);
-  
-  
-  // NOTE: We could also implement virtual console switching by using 
-  // VT_GETMODE / VT_SETMODE ioctl calls and handling their signals, but
-  // probably nobody will ever want to switch consoles, so I don't bother... 
-  
-  return true;
-}
-
-bool FBGui::enable_terminal() 
-{
-
-  log_debug(_("Restoring terminal..."));
-
-  char* tty = find_accessible_tty(own_vt);
-  if (!tty) {
-    log_debug(_("WARNING: Could not find device for VT number %d"), own_vt);
-    return false;
-  }
-
-  int fd = open(tty, O_RDWR);
-  if (fd<0) {
-    log_debug(_("WARNING: Could not open %s"), tty);
-    return false;
-  }
-
-  if (ioctl(fd, VT_ACTIVATE, original_vt)) {
-    log_debug(_("WARNING: Could not activate VT number %d"), original_vt);
-    close(fd);
-    return false;
-  }
-
-  if (ioctl(fd, VT_WAITACTIVE, original_vt)) {
-    log_debug(_("WARNING: Error waiting for VT %d becoming active"), 
original_vt);
-    //close(tty);
-    //return false;   don't abort
-  }
-
-  
-  
-  // Restore keyboard
-  
-  if (ioctl(fd, KDSETMODE, original_kd)) {
-    log_debug(_("WARNING: Could not restore keyboard mode"));
-  }  
-  
-  close(fd);
-  
-  return true;
-}
-
-void FBGui::read_mouse_data()
-{
-  if (input_fd<0) return;   // no mouse available
-  
-  int count;  
-  
-  unsigned char *ptr;
-  
-  ptr = mouse_buf + mouse_buf_size;
-  
-  count = read(input_fd, mouse_buf + mouse_buf_size, 
-    sizeof(mouse_buf) - mouse_buf_size);
-    
-  if (count<=0) return;
-  
-  /*
-  printf("read data: ");
-  int i;
-  for (i=0; i<count; i++) 
-    printf("%02x ", ptr[i]);
-  printf("\n");
-  */
-  
-  mouse_buf_size += count;
-  
-}
-
-#ifdef USE_MOUSE_PS2    
-bool FBGui::mouse_command(unsigned char cmd, unsigned char *buf, int count) {
-  int n;
-  
-  // flush input buffer
-  char trash[16];
-  do {
-    n = read(input_fd, trash, sizeof trash);
-    if (n>0) 
-      log_debug(_("mouse_command: discarded %d bytes from input buffer"), n);
-  } while (n>0);
-  
-  // send command
-  write(input_fd, &cmd, 1);
-  
-  // read response (if any)
-  while (count>0) {
-    gnashSleep(250*1000); // 250 ms inter-char timeout (simple method)
-    // TODO: use select() instead
-    
-    n = read(input_fd, buf, count);
-    if (n<=0) return false;
-    count-=n;
-    buf+=n;
-  }
-  
-  return true;
-  
-} //command()
-#endif
-
-#ifdef USE_MOUSE_PS2    
-bool FBGui::init_mouse() 
-{
-
-  // see http://www.computer-engineering.org/ps2mouse/
-  
-
-  // Try to open mouse device, be error tolerant (FD is kept open all the time)
-  input_fd = open(MOUSE_DEVICE, O_RDWR);
-  
-  if (input_fd<0) {
-    log_debug(_("Could not open " MOUSE_DEVICE ": %s"), strerror(errno));    
-    return false;
-  }
-  
-  unsigned char buf[10], byte;
-
-  if (fcntl(input_fd, F_SETFL, fcntl(input_fd, F_GETFL) | O_NONBLOCK)<0) {
-    log_error("Could not set non-blocking mode for mouse device: %s", 
strerror(errno));
-    close(input_fd);
-    input_fd=-1;
-    return false; 
-  }
-  
-  // Clear input buffer
-  while ( read(input_fd, buf, sizeof buf) > 0 ) { }
-  
-  // Reset mouse
-  if ((!mouse_command(0xFF, buf, 3)) || (buf[0]!=0xFA)) {
-    log_debug(_("Mouse reset failed"));
-    close(input_fd);
-    input_fd=-1;
-    return false; 
-  }
-  
-  // Get Device ID (not crucial, debug only)
-  if ((!mouse_command(0xF2, buf, 2)) || (buf[0]!=0xFA)) {
-    log_debug(_("WARNING: Could not detect mouse device ID"));
-  } else {
-    unsigned char devid = buf[1];
-    if (devid!=0)
-      log_debug(_("WARNING: Non-standard mouse device ID %d"), devid);
-  }
-  
-  // Enable mouse data reporting
-  if ((!mouse_command(0xF4, &byte, 1)) || (byte!=0xFA)) {
-    log_debug(_("Could not activate Data Reporting mode for mouse"));
-    close(input_fd);
-    input_fd=-1;
-    return false; 
-  }
-  
-  
-  log_debug(_("Mouse enabled."));
-      
-  mouse_x = 0;
-  mouse_y = 0;
-  mouse_btn = 0;
-  
-  return true;
-}
-#endif
-
-#ifdef USE_MOUSE_PS2    
-bool FBGui::check_mouse() 
-{
-  if (input_fd<0) return false;   // no mouse available
-  
-  int i;
-  int xmove, ymove, btn, btn_changed;
-  
-  read_mouse_data();
-  
-  // resync
-  int pos = -1;
-  for (i=0; i<mouse_buf_size; i++)
-  if (mouse_buf[i] & 8) { // bit 3 must be high for the first byte
-    pos = i;
-    break;    
-  }
-  if (pos<0) return false; // no sync or no data
-  
-  if (pos>0) {
-    // remove garbage:
-    memmove(mouse_buf, mouse_buf + pos, mouse_buf_size - pos);
-    mouse_buf_size -= pos;
-  }
-  
-  
-  if (mouse_buf_size >= 3) {
-  
-    xmove = mouse_buf[1];
-    ymove = mouse_buf[2];
-    btn = mouse_buf[0] & 1;
-    
-    if (mouse_buf[0] & 0x10) xmove = -(256-xmove);
-    if (mouse_buf[0] & 0x20) ymove = -(256-ymove);
-    
-    ymove *= -1; // vertical movement is upside-down
-    
-    log_debug(_("x/y %d/%d btn %d"), xmove, ymove, btn);
-
-    // movement    
-    mouse_x += xmove;
-    mouse_y += ymove;
-    
-    if (mouse_x<0) mouse_x=0;
-    if (mouse_y<0) mouse_y=0;
-    if (mouse_x>m_stage_width) mouse_x=m_stage_width;
-    if (mouse_y>m_stage_height) mouse_y=m_stage_height;
-    
-    //log_debug(_("mouse @ %d / %d, btn %d"), mouse_x, mouse_y, mouse_btn);
-    
-    notifyMouseMove(mouse_x, mouse_y);
-    
-    // button
-    if (btn != mouse_btn) {
-      mouse_btn = btn;
-printf("clicked: %d\n", btn);      
-      notifyMouseClick(btn);  // mark=??
-      //log_debug(_("mouse click! %d"), btn);
-    }    
-
-    // remove from buffer
-    pos=3;
-    memmove(mouse_buf, mouse_buf + pos, mouse_buf_size - pos);
-    mouse_buf_size -= pos;  
-    
-    return true;
-  
-  }
-  
-}
-#endif
-
-#ifdef USE_MOUSE_ETT    
-bool FBGui::init_mouse()
-{
-  // Try to open mouse device, be error tolerant (FD is kept open all the time)
-  input_fd = open(MOUSE_DEVICE, O_RDWR);
-  
-  if (input_fd<0) {
-    log_debug(_("Could not open " MOUSE_DEVICE ": %s"), strerror(errno));    
-    return false;
-  }
-  
-  unsigned char buf[10];
-
-  if (fcntl(input_fd, F_SETFL, fcntl(input_fd, F_GETFL) | O_NONBLOCK)<0) {
-    log_error("Could not set non-blocking mode for touchpad device: %s", 
strerror(errno));
-    close(input_fd);
-    input_fd=-1;
-    return false; 
-  }
-  
-  // Clear input buffer
-  while ( read(input_fd, buf, sizeof buf) > 0 ) { }
-  
-  mouse_buf_size=0;
-  
-  log_debug(_("Touchpad enabled."));
-  return true;
-} 
-#endif
-
-#ifdef USE_MOUSE_ETT    
-bool FBGui::check_mouse() 
-{
-  bool activity = false;
-  
-  if (input_fd<0) return false;   // no mouse available
-  
-  read_mouse_data();
-  
-  // resync
-  int pos = -1;
-  int i;
-  for (i=0; i<mouse_buf_size; i++)
-  if (mouse_buf[i] & 0x80) { 
-    pos = i;
-    break;    
-  }
-  if (pos<0) return false; // no sync or no data
-  
-  if (pos>0) {
-    //printf("touchscreen: removing %d bytes garbage!\n", pos);  
-    memmove(mouse_buf, mouse_buf + pos, mouse_buf_size - pos);
-    mouse_buf_size -= pos;
-  }
-    
-  // packet complete?
-  while (mouse_buf_size > 4) {
-    /*
-    eTurboTouch version??
-    mouse_btn = ((mouse_buf[0] >> 4) & 1);
-    mouse_x = (mouse_buf[1] << 4) | (mouse_buf[2] >> 3);
-    mouse_y = (mouse_buf[3] << 4) | (mouse_buf[4] >> 3);
-    */
-
-    int new_btn = (mouse_buf[0] & 1);
-    int new_x = (mouse_buf[1] << 7) | (mouse_buf[2]);
-    int new_y = (mouse_buf[3] << 7) | (mouse_buf[4]);
-    
-    /*
-    printf("touchscreen: %02x %02x %02x %02x %02x | status %d, pos: %d/%d\n",
-      mouse_buf[0], mouse_buf[1], mouse_buf[2], mouse_buf[3], mouse_buf[4],   
-      new_btn, new_x, new_y);
-    */
-    
-    
-    new_x = static_cast<int>(((static_cast<double>(new_x )- 355) / (1702 - 355)
-    * 1536 + 256));
-    new_y = static_cast<int>(((static_cast<double>(new_y) - 482) / (1771 - 482)
-    * 1536 + 256));
-    
-    
-    new_x = new_x * m_stage_width / 2048;
-    new_y = (2048-new_y) * m_stage_height / 2048;
-    
-    if ((new_x!=mouse_x) || (new_y!=mouse_y)) {
-      mouse_x = new_x;
-      mouse_y = new_y;
-      notifyMouseMove(mouse_x, mouse_y);
-      activity = true;
-    }
-    
-    if (new_btn != mouse_btn) {
-      mouse_btn = new_btn;      
-printf("clicked: %d\n", mouse_btn);      
-      notifyMouseClick(mouse_btn);  // mask=?
-      activity = true;
-    }
-    
-    // remove from buffer
-    pos=5;
-    memmove(mouse_buf, mouse_buf + pos, mouse_buf_size - pos);
-    mouse_buf_size -= pos;    
-  }
-  
-  return activity;
-  
-}
-#endif
-
-#ifdef USE_INPUT_EVENTS   
-bool FBGui::init_mouse()
-{
-  std::string dev;
-
-  char* devname = std::getenv("POINTING_DEVICE");
-  if (devname) dev = devname;
-  else dev = "/dev/input/event0";
-
-  // Try to open mouse device, be error tolerant (FD is kept open all the time)
-  input_fd = open(dev.c_str(), O_RDONLY);
-  
-  if (input_fd<0) {
-    log_debug(_("Could not open %s: %s"), dev.c_str(), strerror(errno));    
-    return false;
-  }
-  
-  log_debug(_("Pointing device %s open"), dev.c_str());
-  
-  if (fcntl(input_fd, F_SETFL, fcntl(input_fd, F_GETFL) | O_NONBLOCK)<0) {
-    log_error(_("Could not set non-blocking mode for pointing device: %s"), 
strerror(errno));
-    close(input_fd);
-    input_fd=-1;
-    return false; 
-  }
-  
-  return true;
-
-} //init_mouse
-
-void FBGui::apply_ts_calibration(float* cx, float* cy, int rawx, int rawy) {
-
-  /*
-  <UdoG>:
-  This is a *very* simple method to translate raw touchscreen coordinates to
-  the screen coordinates. We simply to linear interpolation between two points.
-  Note this won't work well when the touchscreen is not perfectly aligned to
-  the screen (ie. slightly rotated). Standard touchscreen calibration uses
-  5 calibration points (or even 25). If someone can give me the formula, tell
-  me! I'm too lazy right now to do the math myself... ;)  
-  
-  And sorry for the quick-and-dirty implementation! I'm in a hurry...
-  */
-
-  float ref1x = m_stage_width  / 5 * 1;
-  float ref1y = m_stage_height / 5 * 1;
-  float ref2x = m_stage_width  / 5 * 4;
-  float ref2y = m_stage_height / 5 * 4;
-  
-  static float cal1x = 2048/5*1;   // very approximative default values
-  static float cal1y = 2048/5*4;
-  static float cal2x = 2048/5*4;
-  static float cal2y = 2048/5*1;
-  
-  static bool initialized=false; // woohooo.. better don't look at this code...
-  if (!initialized) {
-    initialized=true;
-    
-    char* settings = std::getenv("TSCALIB");
-    
-    if (settings) {
-    
-      // expected format: 
-      // 491,1635,1581,646      (cal1x,cal1y,cal2x,cal2y; all integers)
-
-      char buffer[1024];      
-      char* p1;
-      char* p2;
-      bool ok = false;
-      
-      snprintf(buffer, sizeof buffer, "%s", settings);
-      p1 = buffer;
-      
-      do {
-        // cal1x        
-        p2 = strchr(p1, ',');
-        if (!p2) continue; // stop here
-        *p2 = 0;
-        cal1x = atoi(p1);        
-        p1=p2+1;
-        
-        // cal1y        
-        p2 = strchr(p1, ',');
-        if (!p2) continue; // stop here
-        *p2 = 0;
-        cal1y = atoi(p1);        
-        p1=p2+1;
-        
-        // cal2x        
-        p2 = strchr(p1, ',');
-        if (!p2) continue; // stop here
-        *p2 = 0;
-        cal2x = atoi(p1);        
-        p1=p2+1;
-        
-        // cal2y        
-        cal2y = atoi(p1);
-        
-        ok = true;        
-        
-      } while (0);
-      
-      if (!ok)
-        log_debug(_("WARNING: Error parsing calibration data!"));
-      
-      log_debug(_("Using touchscreen calibration data: %.0f / %.0f / %.0f / 
%.0f"),
-        cal1x, cal1y, cal2x, cal2y);
-    
-    } else {
-      log_debug(_("WARNING: No touchscreen calibration settings found. "
-        "The mouse pointer most probably won't work precisely. Set "
-        "TSCALIB environment variable with correct values for better 
results"));
-    }
-    
-  } //!initialized
-
-
-  // real duty: 
-  *cx = (rawx-cal1x) / (cal2x-cal1x) * (ref2x-ref1x) + ref1x;
-  *cy = (rawy-cal1y) / (cal2y-cal1y) * (ref2y-ref1y) + ref1y;
-}
-
-bool FBGui::check_mouse()
-{
-  bool activity = false;
-  
-  if (input_fd < 0) return false;
-
-  struct input_event ev;  // time,type,code,value
-  
-  static int new_mouse_x = 0; // all uncalibrated!
-  static int new_mouse_y = 0;
-  static int new_mouse_btn = 0;
-  
-  int notify_x=0;     // coordinate to be sent via notifyMouseMove()
-  int notify_y=0;
-  bool move_pending = false;  // true: notifyMouseMove() should be called
-  
-  // this is necessary for our quick'n'dirty touchscreen calibration: 
-  static int coordinatedebug = std::getenv("DUMP_RAW")!=NULL;
-  
-  // The while loop is limited because the kernel tends to send us hundreds
-  // of events while the touchscreen is touched. We don't loose any 
-  // information if we stop reading because the kernel will stop
-  // sending redundant information.
-  int loops=0;  
-  
-  // Assuming we will never read less than one full struct...  
-  
-  while ((loops++ < 100) && (read(input_fd, &ev, sizeof ev) == (sizeof ev))) {
-
-    if (ev.type == EV_SYN) {    // synchronize (apply information)
-      if ((new_mouse_x != mouse_x) || (new_mouse_y != mouse_y)) {
-      
-        mouse_x = new_mouse_x;
-        mouse_y = new_mouse_y;
-        
-        float cx, cy;
-        
-        if (std::getenv("TSCALIB"))  // ONLY convert when requested
-          apply_ts_calibration(&cx, &cy, mouse_x, mouse_y);
-        else
-          { cx=mouse_x; cy=mouse_y; }
-              
-        // Don't call notifyMouseMove() here because this would lead to
-        // lots of calls, especially for touchscreens. Instead we save the
-        // coordinate and call notifyMouseMove() only once.
-        notify_x = cx;
-        notify_y = cy;
-        move_pending = true;        
-      }
-      
-      if (new_mouse_btn != mouse_btn) {
-      
-        if (move_pending) {
-          notifyMouseMove(notify_x, notify_y);
-          activity = true;
-          move_pending = false;
-        }
-      
-        mouse_btn = new_mouse_btn;
-        notifyMouseClick(mouse_btn);  // mark=??
-        activity = true;
-      }
-
-      if (coordinatedebug)
-        printf("DEBUG: % 5d / % 5d / % 5d\n", mouse_x, mouse_y, mouse_btn);
-      
-    }
-  
-    if (ev.type == EV_KEY) {    // button down/up
-    
-      // don't care which button, we support only one...
-      new_mouse_btn = ev.value;      
-      
-    }
-      
-    if (ev.type == EV_ABS) {    // absolute coordinate
-      if (ev.code == ABS_X) new_mouse_x = ev.value;
-      if (ev.code == ABS_Y) new_mouse_y = ev.value;
-      if (ev.code == ABS_PRESSURE) new_mouse_btn = ev.value >= 128;
-    }
-    
-    if (ev.type == EV_REL) {    // relative movement
-      if (ev.code == REL_X) new_mouse_x += ev.value;
-      if (ev.code == REL_Y) new_mouse_y += ev.value;
-      
-      if (new_mouse_x < 0) new_mouse_x=0;
-      if (new_mouse_y < 0) new_mouse_y=0;
-      
-      if (new_mouse_x > m_stage_width ) new_mouse_x = m_stage_width;
-      if (new_mouse_y > m_stage_height) new_mouse_y = m_stage_height;
-    }      
-  
-  } 
-  
-  if (move_pending) {
-    notifyMouseMove(notify_x, notify_y);
-    activity = true;
-  }
-  
-  return activity;
- 
-} //check_mouse
-#endif
-
-
-bool FBGui::init_keyboard() 
-{
-  std::string dev;
-
-  char* devname = std::getenv("KEYBOARD_DEVICE");
-  if (devname) dev = devname;
-  else dev = "/dev/input/event0";
-
-  // Try to open keyboard device, be error tolerant (FD is kept open all the 
time)
-  keyb_fd = open(dev.c_str(), O_RDONLY);
-  
-  if (keyb_fd<0) {
-    log_debug(_("Could not open %s: %s"), dev.c_str(), strerror(errno));    
-    return false;
-  }
-  
-  log_debug(_("Keyboard device %s open"), dev.c_str());
-  
-  if (fcntl(keyb_fd, F_SETFL, fcntl(keyb_fd, F_GETFL) | O_NONBLOCK)<0) {
-    log_error(_("Could not set non-blocking mode for keyboard device: %s"), 
strerror(errno));
-    close(keyb_fd);
-    keyb_fd=-1;
-    return false; 
-  }
-  
-  return true;
-}
-
-gnash::key::code FBGui::scancode_to_gnash_key(int code, bool shift) {
- 
-  // NOTE: Scancodes are mostly keyboard oriented (ie. Q, W, E, R, T, ...)
-  // while Gnash codes are mostly ASCII-oriented (A, B, C, D, ...) so no
-  // direct conversion is possible.
-  
-  // TODO: This is a very *incomplete* list and I also dislike this method
-  // very much because it depends on the keyboard layout (ie. pressing "Z"
-  // on a german keyboard will print "Y" instead). So we need some 
-  // alternative...
-  
-  switch (code) {
-  
-    case KEY_1      : return !shift ? gnash::key::_1 : gnash::key::EXCLAM;
-    case KEY_2      : return !shift ? gnash::key::_2 : 
gnash::key::DOUBLE_QUOTE; 
-    case KEY_3      : return !shift ? gnash::key::_3 : gnash::key::HASH; 
-    case KEY_4      : return !shift ? gnash::key::_4 : gnash::key::DOLLAR; 
-    case KEY_5      : return !shift ? gnash::key::_5 : gnash::key::PERCENT; 
-    case KEY_6      : return !shift ? gnash::key::_6 : gnash::key::AMPERSAND; 
-    case KEY_7      : return !shift ? gnash::key::_7 : 
gnash::key::SINGLE_QUOTE; 
-    case KEY_8      : return !shift ? gnash::key::_8 : gnash::key::PAREN_LEFT; 
-    case KEY_9      : return !shift ? gnash::key::_9 : 
gnash::key::PAREN_RIGHT; 
-    case KEY_0      : return !shift ? gnash::key::_0 : gnash::key::ASTERISK;
-                            
-    case KEY_A      : return shift ? gnash::key::A : gnash::key::a;
-    case KEY_B      : return shift ? gnash::key::B : gnash::key::b;
-    case KEY_C      : return shift ? gnash::key::C : gnash::key::c;
-    case KEY_D      : return shift ? gnash::key::D : gnash::key::d;
-    case KEY_E      : return shift ? gnash::key::E : gnash::key::e;
-    case KEY_F      : return shift ? gnash::key::F : gnash::key::f;
-    case KEY_G      : return shift ? gnash::key::G : gnash::key::g;
-    case KEY_H      : return shift ? gnash::key::H : gnash::key::h;
-    case KEY_I      : return shift ? gnash::key::I : gnash::key::i;
-    case KEY_J      : return shift ? gnash::key::J : gnash::key::j;
-    case KEY_K      : return shift ? gnash::key::K : gnash::key::k;
-    case KEY_L      : return shift ? gnash::key::L : gnash::key::l;
-    case KEY_M      : return shift ? gnash::key::M : gnash::key::m;
-    case KEY_N      : return shift ? gnash::key::N : gnash::key::n;
-    case KEY_O      : return shift ? gnash::key::O : gnash::key::o;
-    case KEY_P      : return shift ? gnash::key::P : gnash::key::p;
-    case KEY_Q      : return shift ? gnash::key::Q : gnash::key::q;
-    case KEY_R      : return shift ? gnash::key::R : gnash::key::r;
-    case KEY_S      : return shift ? gnash::key::S : gnash::key::s;
-    case KEY_T      : return shift ? gnash::key::T : gnash::key::t;
-    case KEY_U      : return shift ? gnash::key::U : gnash::key::u;
-    case KEY_V      : return shift ? gnash::key::V : gnash::key::v;
-    case KEY_W      : return shift ? gnash::key::W : gnash::key::w;
-    case KEY_X      : return shift ? gnash::key::X : gnash::key::x;
-    case KEY_Y      : return shift ? gnash::key::Y : gnash::key::y;
-    case KEY_Z      : return shift ? gnash::key::Z : gnash::key::z;
-
-    case KEY_F1     : return gnash::key::F1; 
-    case KEY_F2     : return gnash::key::F2; 
-    case KEY_F3     : return gnash::key::F3; 
-    case KEY_F4     : return gnash::key::F4; 
-    case KEY_F5     : return gnash::key::F5; 
-    case KEY_F6     : return gnash::key::F6; 
-    case KEY_F7     : return gnash::key::F7; 
-    case KEY_F8     : return gnash::key::F8; 
-    case KEY_F9     : return gnash::key::F9;
-    case KEY_F10    : return gnash::key::F10;
-    case KEY_F11    : return gnash::key::F11;
-    case KEY_F12    : return gnash::key::F12;
-    
-    case KEY_KP0    : return gnash::key::KP_0; 
-    case KEY_KP1    : return gnash::key::KP_1; 
-    case KEY_KP2    : return gnash::key::KP_2; 
-    case KEY_KP3    : return gnash::key::KP_3; 
-    case KEY_KP4    : return gnash::key::KP_4; 
-    case KEY_KP5    : return gnash::key::KP_5; 
-    case KEY_KP6    : return gnash::key::KP_6; 
-    case KEY_KP7    : return gnash::key::KP_7; 
-    case KEY_KP8    : return gnash::key::KP_8; 
-    case KEY_KP9    : return gnash::key::KP_9;
-
-    case KEY_KPMINUS       : return gnash::key::KP_SUBTRACT;
-    case KEY_KPPLUS        : return gnash::key::KP_ADD;
-    case KEY_KPDOT         : return gnash::key::KP_DECIMAL;
-    case KEY_KPASTERISK    : return gnash::key::KP_MULTIPLY;
-    case KEY_KPENTER       : return gnash::key::KP_ENTER;
-    
-    case KEY_ESC           : return gnash::key::ESCAPE;
-    case KEY_MINUS         : return gnash::key::MINUS;
-    case KEY_EQUAL         : return gnash::key::EQUALS;
-    case KEY_BACKSPACE     : return gnash::key::BACKSPACE;
-    case KEY_TAB           : return gnash::key::TAB;
-    case KEY_LEFTBRACE     : return gnash::key::LEFT_BRACE;
-    case KEY_RIGHTBRACE    : return gnash::key::RIGHT_BRACE;
-    case KEY_ENTER         : return gnash::key::ENTER;
-    case KEY_LEFTCTRL      : return gnash::key::CONTROL;
-    case KEY_SEMICOLON     : return gnash::key::SEMICOLON;
-    //case KEY_APOSTROPHE    : return gnash::key::APOSTROPHE;  
-    //case KEY_GRAVE         : return gnash::key::GRAVE;
-    case KEY_LEFTSHIFT     : return gnash::key::SHIFT;
-    case KEY_BACKSLASH     : return gnash::key::BACKSLASH;
-    case KEY_COMMA         : return gnash::key::COMMA;
-    case KEY_SLASH         : return gnash::key::SLASH;
-    case KEY_RIGHTSHIFT    : return gnash::key::SHIFT;
-    case KEY_LEFTALT       : return gnash::key::ALT;
-    case KEY_SPACE         : return gnash::key::SPACE;
-    case KEY_CAPSLOCK      : return gnash::key::CAPSLOCK;
-    case KEY_NUMLOCK       : return gnash::key::NUM_LOCK;
-    //case KEY_SCROLLLOCK    : return gnash::key::SCROLLLOCK;
-    
-    case KEY_UP            : return gnash::key::UP;
-    case KEY_DOWN          : return gnash::key::DOWN;
-    case KEY_LEFT          : return gnash::key::LEFT;
-    case KEY_RIGHT         : return gnash::key::RIGHT;
-    case KEY_PAGEUP        : return gnash::key::PGUP;
-    case KEY_PAGEDOWN      : return gnash::key::PGDN;
-    case KEY_INSERT        : return gnash::key::INSERT;
-    case KEY_DELETE        : return gnash::key::DELETEKEY;
-    case KEY_HOME          : return gnash::key::HOME;
-    case KEY_END           : return gnash::key::END;
-    
-  }
-  
-  return gnash::key::INVALID;  
-}
-
-bool FBGui::check_keyboard()
-{
-  bool activity = false;
-  
-  if (keyb_fd < 0) return false;
-
-  struct input_event ev;  // time,type,code,value
-
-  
-  while (read(keyb_fd, &ev, sizeof ev) == (sizeof ev)) {
-  
-    if (ev.type == EV_KEY) {
-    
-      // code == scan code of the key (KEY_xxxx defines in input.h)
-      
-      // value == 0  key has been released
-      // value == 1  key has been pressed
-      // value == 2  repeated key reporting (while holding the key) 
-
-      if (ev.code==KEY_LEFTSHIFT) 
-        keyb_lshift = ev.value;
-      else
-      if (ev.code==KEY_RIGHTSHIFT) 
-        keyb_rshift = ev.value;
-      else
-      if (ev.code==KEY_LEFTCTRL) 
-        keyb_lctrl = ev.value;
-      else
-      if (ev.code==KEY_RIGHTCTRL) 
-        keyb_rctrl = ev.value;
-      else
-      if (ev.code==KEY_LEFTALT) 
-        keyb_lalt = ev.value;
-      else
-      if (ev.code==KEY_RIGHTALT) 
-        keyb_ralt = ev.value;
-      else {
-      
-        gnash::key::code  c = scancode_to_gnash_key(ev.code, 
-          keyb_lshift || keyb_rshift);
-      
-        // build modifier
-      
-        int modifier = gnash::key::GNASH_MOD_NONE;
-        
-        if (keyb_lshift || keyb_rshift)
-          modifier = modifier | gnash::key::GNASH_MOD_SHIFT;
-
-        if (keyb_lctrl || keyb_rctrl)
-          modifier = modifier | gnash::key::GNASH_MOD_CONTROL;
-
-        if (keyb_lalt || keyb_ralt)
-          modifier = modifier | gnash::key::GNASH_MOD_ALT;
-          
-          
-        // send event
-        if (c != gnash::key::INVALID) {
-          Gui::notify_key_event(c, modifier, ev.value);
-          activity=true;
-        }
-              
-      } //if normal key
-
-    } //if EV_KEY      
-  
-  } //while
-  
-  return activity;
-
+    // Disable keyboard cursor
+  
+    if (ioctl(fd, KDGETMODE, &original_kd) == -1) {
+        log_debug(_("WARNING: Could not query current keyboard mode on VT"));
+    }
+
+    if (ioctl(fd, KDSETMODE, KD_GRAPHICS) == -1) {
+        log_debug(_("WARNING: Could not switch to graphics mode on new VT"));
+    }
+
+    if (fd > 0) {
+        close(fd);
+    }
+  
+    log_debug(_("VT %d ready"), own_vt);  
+  
+    // NOTE: We could also implement virtual console switching by using 
+    // VT_GETMODE / VT_SETMODE ioctl calls and handling their signals, but
+    // probably nobody will ever want to switch consoles, so I don't bother... 
+  
+    return true;
+}
+
+bool
+FBGui::enable_terminal() 
+{
+    log_debug(_("Restoring terminal..."));
+
+    char* tty = find_accessible_tty(own_vt);
+    if (!tty) {
+        log_debug(_("WARNING: Could not find device for VT number %d"), 
own_vt);
+        return false;
+    }
+
+    int fd = open(tty, O_RDWR);
+    if (fd < 0) {
+        log_debug(_("WARNING: Could not open %s"), tty);
+        return false;
+    }
+
+    if (ioctl(fd, VT_ACTIVATE, original_vt)) {
+        log_debug(_("WARNING: Could not activate VT number %d"), original_vt);
+        close(fd);
+        return false;
+    }
+
+    if (ioctl(fd, VT_WAITACTIVE, original_vt)) {
+        log_debug(_("WARNING: Error waiting for VT %d becoming active"), 
original_vt);
+        //close(tty);
+        //return false;   don't abort
+    }  
+  
+    // Restore keyboard
+  
+    if (ioctl(fd, KDSETMODE, original_kd)) {
+        log_debug(_("WARNING: Could not restore keyboard mode"));
+    }  
+
+    if (fd > 0) {
+        close(fd);
+    }
+  
+    return true;
+}
+
+bool
+FBGui::checkForData()
+{
+    GNASH_REPORT_FUNCTION;
+
+    std::vector<boost::shared_ptr<InputDevice> >::iterator it;
+
+    for (it=_inputs.begin(); it!=_inputs.end(); ++it) {
+        (*it)->check();
+    }
 }
 
 // end of namespace gnash
 }
+
+#ifdef ENABLE_FAKE_FRAMEBUFFER
+// Simulate the ioctls used to get information from the framebuffer
+// driver. Since this is an emulator, we have to set these fields
+// to a reasonable default.
+int
+fakefb_ioctl(int /* fd */, int request, void *data)
+{
+    // GNASH_REPORT_FUNCTION;
+    
+    switch (request) {
+      case FBIOGET_VSCREENINFO:
+      {
+          struct fb_var_screeninfo *ptr =
+              reinterpret_cast<struct fb_var_screeninfo *>(data);
+          // If we are using a simulated framebuffer, the default for
+          // fbe us 640x480, 8bits. So use that as a sensible
+          // default. Note that the fake framebuffer is only used for
+          // debugging and development.
+          ptr->xres          = 640; // visible resolution
+          ptr->xres_virtual  = 640; // virtual resolution
+          ptr->yres          = 480; // visible resolution
+          ptr->yres_virtual  = 480; // virtual resolution
+          ptr->width         = 640; // width of picture in mm
+          ptr->height        = 480; // height of picture in mm
+
+          // Android and fbe use a 16bit 5/6/5 framebuffer
+          ptr->bits_per_pixel = 16;
+          ptr->red.length    = 5;
+          ptr->red.offset    = 11;
+          ptr->green.length  = 6;
+          ptr->green.offset  = 5;
+          ptr->blue.length   = 5;
+          ptr->blue.offset   = 0;
+          ptr->transp.offset = 0;
+          ptr->transp.length = 0;
+          // 8bit framebuffer
+          // ptr->bits_per_pixel = 8;
+          // ptr->red.length    = 8;
+          // ptr->red.offset    = 0;
+          // ptr->green.length  = 8;
+          // ptr->green.offset  = 0;
+          // ptr->blue.length   = 8;
+          // ptr->blue.offset   = 0;
+          // ptr->transp.offset = 0;
+          // ptr->transp.length = 0;
+          ptr->grayscale     = 1; // != 0 Graylevels instead of color
+          
+          break;
+      }
+      case FBIOGET_FSCREENINFO:
+      {
+          struct fb_fix_screeninfo *ptr =
+              reinterpret_cast<struct fb_fix_screeninfo *>(data);
+          ptr->smem_len = 307200; // Length of frame buffer mem
+          ptr->type = FB_TYPE_PACKED_PIXELS; // see FB_TYPE_*
+          ptr->visual = FB_VISUAL_PSEUDOCOLOR; // see FB_VISUAL_*
+          ptr->xpanstep = 0;      // zero if no hardware panning
+          ptr->ypanstep = 0;      // zero if no hardware panning
+          ptr->ywrapstep = 0;     // zero if no hardware panning
+          ptr->accel = FB_ACCEL_NONE; // Indicate to driver which specific
+                                  // chip/card we have
+          break;
+      }
+      case FBIOPUTCMAP:
+      {
+          // Fbe uses this name for the fake framebuffer, so in this
+          // case assume we're using fbe, so write to the known fbe
+          // cmap file.
+          std::string str = FAKEFB;
+          if (str == "/tmp/fbe_buffer") {
+              int fd = open("/tmp/fbe_cmap", O_WRONLY);
+              if (fd) {
+                  write(fd, data, sizeof(struct fb_cmap));
+                  close(fd);
+              } else {
+                  gnash::log_error("Couldn't write to the fake cmap!");
+                  return -1;
+              }
+          } else {
+              gnash::log_error("Couldn't write to the fake cmap, unknown 
type!");
+              return -1;
+          }
+          // If we send a SIGUSR1 signal to fbe, it'll reload the
+          // color map.
+          int fd = open("/tmp/fbe.pid", O_RDONLY);
+          char buf[10];
+          if (fd) {
+              if (read(fd, buf, 10) == 0) {
+                  close(fd);
+                  return -1;
+              } else {
+                  pid_t pid = strtol(buf, 0, NULL);
+                  kill(pid, SIGUSR1);
+                  gnash::log_debug("Signaled fbe to reload it's colormap.");
+              }
+              close(fd);
+          }
+          break;
+      }
+      default:
+          gnash::log_unimpl("fakefb_ioctl(%d)", request);
+          break;
+    }
+
+    return 0;
+}
+#endif  // ENABLE_FAKE_FRAMEBUFFER
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== modified file 'gui/fb/fbsup.h'
--- a/gui/fb/fbsup.h    2010-07-15 03:07:54 +0000
+++ b/gui/fb/fbsup.h    2010-07-28 18:56:29 +0000
@@ -23,53 +23,33 @@
 #include "gnashconfig.h"
 #endif
 
+#include <boost/scoped_array.hpp>
 #include <vector>
+#include <linux/fb.h>
 
 #include "gui.h"
-#include <linux/fb.h>
+#include "InputDevice.h"
 
 #define PIXELFORMAT_LUT8
 #define CMAP_SIZE (256*2)
 
-// If defined, an internal software-buffer is used for rendering and is then
-// copied to the video RAM. This avoids flicker and is faster for complex 
-// graphics, as video RAM access is usually slower. 
-// (strongly suggested)
-#define DOUBLE_BUFFER
-
-
-// TODO: Make this configurable via ./configure!
-
-
-// Define this to read from /dev/input/mice (any PS/2 compatbile mouse or
-// emulated by the Kernel) 
-//#define USE_MOUSE_PS2
-
-// Define this to read from /dev/input/event0 (new generic input subsystem)
-#define USE_INPUT_EVENTS
-
-// Define this to support eTurboTouch / eGalax touchscreens. When reading from
-// a serial device, it must be initialized (stty) externally. 
-//#define USE_MOUSE_ETT
-
 #ifdef USE_MOUSE_PS2
-#define MOUSE_DEVICE "/dev/input/mice"
+# define MOUSE_DEVICE "/dev/input/mice"
 #endif
 
-#ifdef USE_MOUSE_ETT
+// FIXME: this should really be TSLIB_DEVICE_NAME, but I don't have the
+// ETT SDK, so for now, leave it the way it was.
+#ifdef USE_ETT_TSLIB
 #define MOUSE_DEVICE "/dev/usb/tkpanel0"
 #endif
 
-
 // Define this to request a new virtual terminal at startup. This doesn't 
always
 // work and probably is not necessary anyway
 //#define REQUEST_NEW_VT
 
-
 namespace gnash
 {
 
-
 /// A Framebuffer-based GUI for Gnash.
 /// ----------------------------------
 ///
@@ -92,7 +72,7 @@
 /// touchscreens but will make it difficult for standard mice. This will be 
 /// fixed in near time.
 //
-/// Supported graphics modes:
+// Supported graphics modes:
 ///
 ///   Resolution: any
 ///
@@ -110,85 +90,48 @@
 ///   to /dev/input/mice
 class FBGui : public Gui
 {
-       private:
-               int fd;
-               int original_vt;       // virtual terminal that was active at 
startup
-               int original_kd;       // keyboard mode at startup
-               int own_vt;            // virtual terminal we are running in   
-               unsigned char *fbmem;  // framebuffer memory
-#ifdef DOUBLE_BUFFER
-               unsigned char *buffer; // offscreen buffer
-#endif         
-
+private:
+    int fd;
+    int original_vt;       // virtual terminal that was active at startup
+    int original_kd;       // keyboard mode at startup
+    int own_vt;            // virtual terminal we are running in   
+    unsigned char *fbmem;  // framebuffer memory
+    unsigned char *buffer; // offscreen buffer
+    
     std::vector< geometry::Range2d<int> > _drawbounds;
-
+    
     int m_stage_width;
     int m_stage_height;
     unsigned m_rowsize;
-
-       int input_fd; /// file descriptor for /dev/input/mice
-       int keyb_fd; /// file descriptor for /dev/input/event* (keyboard)
-       int mouse_x, mouse_y, mouse_btn;
-       unsigned char mouse_buf[256];
-       int mouse_buf_size;
-       
-       // Keyboard SHIFT/CTRL/ALT states (left + right)
-       bool keyb_lshift, keyb_rshift, keyb_lctrl, keyb_rctrl, keyb_lalt, 
keyb_ralt;
+    
+    std::vector<boost::shared_ptr<InputDevice> > _inputs;
 
     struct fb_var_screeninfo var_screeninfo;
-       struct fb_fix_screeninfo fix_screeninfo;
-
-       /// For 8 bit (palette / LUT) modes, sets a grayscale palette.
-       //
-       /// This GUI currently does not support palette modes. 
-       ///
-       bool set_grayscale_lut8();
-       
-       bool initialize_renderer();
-       
-       /// Tries to find a accessible tty
-       char* find_accessible_tty(int no);
-       char* find_accessible_tty(const char* format, int no);
-       
-       /// switches from text mode to graphics mode (disables the text 
terminal)
-       bool disable_terminal();
-       
-       /// reverts disable_terminal() changes
-       bool enable_terminal();
-
-#ifdef USE_MOUSE_PS2   
-       /// Sends a command to the mouse and waits for the response
-       bool mouse_command(unsigned char cmd, unsigned char *buf, int count);
-#endif
-
-    /// Fills the mouse data input buffer with fresh data
-    void read_mouse_data();    
-       
-       /// Initializes mouse routines
-       bool init_mouse();
-       
-       /// Checks for and processes any mouse activity. Returns true on 
activity.
-       bool check_mouse();
-       
-       /// Initializes keyboard routines 
-       bool init_keyboard();
-               
-       /// Translates a scancode from the Linux Input Subsystem to a Gnash key 
code 
-    gnash::key::code scancode_to_gnash_key(int code, bool shift);
-       
-       /// Checks for and processes any keyboard activity. Returns true on 
activity.
-       bool check_keyboard();
-       
-#ifdef USE_INPUT_EVENTS        
-    /// Applies builtin touchscreen calibration
-       void apply_ts_calibration(float* cx, float* cy, int rawx, int rawy);
-#endif
-       
-       int valid_x(int x);
-       int valid_y(int y);
-               
-       public:
-               FBGui(unsigned long xid, float scale, bool loop, RunResources& 
r);
+    struct fb_fix_screeninfo fix_screeninfo;
+    
+    /// For 8 bit (palette / LUT) modes, sets a grayscale palette.
+    //
+    /// This GUI currently does not support palette modes. 
+    ///
+    bool set_grayscale_lut8();
+    
+    bool initialize_renderer();
+    
+    /// Tries to find a accessible tty
+    char* find_accessible_tty(int no);
+    char* find_accessible_tty(const char* format, int no);
+    
+    /// switches from text mode to graphics mode (disables the text terminal)
+    bool disable_terminal();
+    
+    /// reverts disable_terminal() changes
+    bool enable_terminal();
+    
+    int valid_x(int x);
+    int valid_y(int y);
+    
+public:
+    FBGui(unsigned long xid, float scale, bool loop, RunResources& r);
     virtual ~FBGui();
     virtual bool init(int argc, char ***argv);
     virtual bool createWindow(const char *title, int width, int height,
@@ -208,10 +151,23 @@
     
     virtual void setInvalidatedRegions(const InvalidatedRanges& ranges);
     virtual bool want_multiple_regions() { return true; }
+
+    bool checkForData();    
 };
 
 // end of namespace gnash
 }
 
+#ifdef ENABLE_FAKE_FRAMEBUFFER
+/// Simulate the ioctls used to get information from the framebuffer driver.
+///
+/// Since this is an emulator, we have to set these fields to a reasonable 
default.
+int fakefb_ioctl(int fd, int request, void *data);
 #endif
 
+#endif  // end of GNASH_FBSUP_H
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== modified file 'gui/gui.h'
--- a/gui/gui.h 2010-07-10 09:22:49 +0000
+++ b/gui/gui.h 2010-07-27 22:45:27 +0000
@@ -30,6 +30,7 @@
 #include "VirtualClock.h"
 #include "SystemClock.h"
 #include "gnash.h" // for Quality
+#include "movie_root.h"
 
 #ifdef USE_SWFTREE
 #include "tree.hh" // for tree
@@ -470,6 +471,9 @@
     /// Set the stage to advance/display
     void setStage(movie_root* stage);
 
+    /// The root movie, or "Stage"
+    movie_root *getStage() { return _stage; };
+    
     /// Handle error message from the core
     //
     /// @param msg        The error message recieved
@@ -488,6 +492,12 @@
     ///
     virtual bool yesno(const std::string& question);
 
+    /// Width of a window pixel, in stage pseudopixel units.
+    float getXScale() { return _xscale; };
+
+    /// Height of a window pixel, in stage pseudopixel units.
+    float getYScale() { return _yscale; };
+
 protected:
 
     /// Default constructor. Initialises members to safe defaults.

=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp    2010-07-26 09:39:53 +0000
+++ b/libcore/movie_root.cpp    2010-07-28 18:55:32 +0000
@@ -979,11 +979,9 @@
     Renderer* renderer = _runResources.renderer();
     if (!renderer) return;
 
-    renderer->begin_display(
-        m_background_color,
-        _stageWidth, _stageHeight,
-        frame_size.get_x_min(), frame_size.get_x_max(),
-        frame_size.get_y_min(), frame_size.get_y_max());
+    renderer->begin_display(m_background_color, _stageWidth, _stageHeight,
+                            frame_size.get_x_min(), frame_size.get_x_max(),
+                            frame_size.get_y_min(), frame_size.get_y_max());
 
 
     for (Levels::iterator i=_movies.begin(), e=_movies.end(); i!=e; ++i)
@@ -1175,7 +1173,11 @@
     }
 
     // If scaling is allowed, always return the original movie size.
-    return static_cast<size_t>(_rootMovie->widthPixels());
+    if (_rootMovie) {
+        return static_cast<size_t>(_rootMovie->widthPixels());
+    } else {
+        return 0;
+    }
 }
 
 /// Get actionscript height of stage, in pixels. The height
@@ -1188,7 +1190,11 @@
     }
 
     // If scaling is allowed, always return the original movie size.
-    return static_cast<size_t>(_rootMovie->heightPixels());
+    if (_rootMovie) {
+        return static_cast<size_t>(_rootMovie->heightPixels());
+    } else {
+        return 0;
+    }
 }
 
 /// Takes a short int bitfield: the four bits correspond


reply via email to

[Prev in Thread] Current Thread [Next in Thread]