diff --git a/recipes/pkg/show_input/README b/recipes/pkg/show_input/README
new file mode 100644
index 0000000..a177202
--- /dev/null
+++ b/recipes/pkg/show_input/README
@@ -0,0 +1,2 @@
+
+ Utility to instrument key presses
diff --git a/recipes/pkg/show_input/archives b/recipes/pkg/show_input/archives
new file mode 100644
index 0000000..cae92d9
--- /dev/null
+++ b/recipes/pkg/show_input/archives
@@ -0,0 +1,3 @@
+_/src/libc
+_/src/vfs
+_/src/show_input
diff --git a/recipes/pkg/show_input/hash b/recipes/pkg/show_input/hash
new file mode 100644
index 0000000..39cdd0d
--- /dev/null
+++ b/recipes/pkg/show_input/hash
@@ -0,0 +1 @@
+-
diff --git a/recipes/pkg/show_input/runtime b/recipes/pkg/show_input/runtime
new file mode 100644
index 0000000..74ef05d
--- /dev/null
+++ b/recipes/pkg/show_input/runtime
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/recipes/src/show_input/content.mk b/recipes/src/show_input/content.mk
new file mode 100644
index 0000000..29ed504
--- /dev/null
+++ b/recipes/src/show_input/content.mk
@@ -0,0 +1,2 @@
+SRC_DIR := src/app/show_input
+include $(GENODE_DIR)/repos/base/recipes/src/content.inc
diff --git a/recipes/src/show_input/hash b/recipes/src/show_input/hash
new file mode 100644
index 0000000..39cdd0d
--- /dev/null
+++ b/recipes/src/show_input/hash
@@ -0,0 +1 @@
+-
diff --git a/recipes/src/show_input/used_apis b/recipes/src/show_input/used_apis
new file mode 100644
index 0000000..64c73aa
--- /dev/null
+++ b/recipes/src/show_input/used_apis
@@ -0,0 +1,9 @@
+base
+framebuffer_session
+gems
+input_session
+libc
+nitpicker_gfx
+nitpicker_session
+os
+vfs
diff --git a/src/app/show_input/main.cc b/src/app/show_input/main.cc
new file mode 100644
index 0000000..62f17db
--- /dev/null
+++ b/src/app/show_input/main.cc
@@ -0,0 +1,150 @@
+/*
+ * \brief Tool for checking input events
+ * \author Emery Hemingway
+ * \date 2018-10-09
+ */
+
+/*
+ * Copyright (C) 2018 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* gems includes */
+#include
+#include
+
+
+namespace Show_input {
+ using namespace Genode;
+ typedef Surface_base::Point Point;
+ typedef Surface_base::Area Area;
+ typedef Surface_base::Rect Rect;
+
+ struct Main;
+};
+
+
+struct Show_input::Main
+{
+ Genode::Env &_env;
+
+ Heap _heap { _env.ram(), _env.rm() };
+
+ Attached_rom_dataspace _config { _env, "config" };
+
+ Root_directory _root { _env, _heap, _config.xml().sub_node("vfs") };
+
+ Vfs_font _font { _heap, _root, "fonts/text/regular" };
+
+ Nitpicker::Connection _nitpicker { _env };
+
+ Input::Session_client &_input = *_nitpicker.input();
+ Framebuffer::Session &_fb = *_nitpicker.framebuffer();
+
+ Dataspace_capability _fb_ds_cap()
+ {
+ _nitpicker.buffer(_nitpicker.mode(), false);
+ return _fb.dataspace();
+ }
+
+ Attached_dataspace _fb_ds { _env.rm(), _fb_ds_cap() };
+
+ Nitpicker::Session::View_handle _view = _nitpicker.create_view();
+
+ typedef Pixel_rgb565 PT;
+
+ Surface_base::Area _size { (unsigned)_fb.mode().width(),
+ (unsigned)_font.height() };
+
+ Surface _surface { _fb_ds.local_addr(), _size };
+
+ void _refresh() { _fb.refresh(0, 0, _size.w(), _size.h()); }
+
+ Signal_handler _input_sigh {
+ _env.ep(), *this, &Main::_handle_input };
+
+ void _handle_input()
+ {
+ using namespace Input;
+ bool refresh = false;
+
+ _input.for_each_event([&] (Input::Event const &ev) {
+ ev.handle_press([&] (Keycode key, Codepoint codepoint) {
+ String<128> info(
+ key_name(key), " ",
+ codepoint, " "
+ "(", codepoint.value, ")");
+
+ Box_painter::paint(
+ _surface,
+ Rect(Point(), _size),
+ Color(0, 0, 0));
+
+
+ Text_painter::paint(
+ _surface,
+ Text_painter::Position(0, 0),
+ _font,
+ Color(255, 255, 255),
+ info.string());
+ refresh = true;
+
+ auto w = _font.string_width(info.string()).decimal();
+ auto h = _font.height();
+
+ _nitpicker.enqueue(
+ _view, Rect(Point(0, 0), Area(w*2, h*2)));
+ });
+ });
+
+ if (refresh) {
+ _nitpicker.execute();
+ _refresh();
+ }
+ }
+
+ Main(Env &env) : _env(env)
+ {
+ _input.sigh(_input_sigh);
+
+ _nitpicker.enqueue(
+ _view, Rect(Point(0, 0), _size));
+
+ _nitpicker.enqueue(
+ _view, Nitpicker::Session::View_handle());
+ _nitpicker.execute();
+
+ _surface.clip(Rect(Point(0, 0), _size));
+ }
+};
+
+
+void Component::construct(Genode::Env &env)
+{
+ env.exec_static_constructors();
+ static Show_input::Main inst(env);
+}
+
+/*
+ * Resolve symbol required by libc. It is unused as we implement
+ * 'Component::construct' directly instead of initializing the libc.
+ */
+
+#include
+
+void Libc::Component::construct(Libc::Env &) { }
+
diff --git a/src/app/show_input/target.mk b/src/app/show_input/target.mk
new file mode 100644
index 0000000..7d8e950
--- /dev/null
+++ b/src/app/show_input/target.mk
@@ -0,0 +1,3 @@
+TARGET = show_input
+SRC_CC = main.cc
+LIBS = base vfs