diff --git a/run/pike_loader.run b/run/pike_loader.run new file mode 100644 index 0000000..e3b6d68 --- /dev/null +++ b/run/pike_loader.run @@ -0,0 +1,163 @@ +# +# Build +# +if {![have_spec linux]} { + puts "Runs on Linux only" + exit 0 +} + +set build_components { + core init + app/cli_monitor + app/pike_loader + app/pointer + drivers/framebuffer + drivers/timer + server/dynamic_rom + server/loader + server/nit_fb + server/nitpicker + server/terminal + test/nitpicker +} + +build $build_components + +create_boot_directory + +# +# Generate config +# + +append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +# +# Boot modules +# + +# generic modules +set boot_modules { + core ld.lib.so init + cli_monitor + fb_sdl + loader + nit_fb + nitpicker + pike_loader + pointer + terminal + testnit + timer +} + + +build_boot_image $boot_modules + +run_genode_until forever diff --git a/src/app/pike_loader/main.cc b/src/app/pike_loader/main.cc new file mode 100644 index 0000000..c295a73 --- /dev/null +++ b/src/app/pike_loader/main.cc @@ -0,0 +1,270 @@ +/* + * \brief Rio inspired launcher + * \author Emery Hemingway + * \date 2017-04-13 + */ + +/* + * Copyright (C) 2017 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 + +namespace Morse { + + typedef Nitpicker::Session::View_handle View_handle; + typedef Nitpicker::Session::Command Command; + typedef Genode::String<80> String; + struct Main; + +}; + + +struct Morse::Main +{ + Genode::Env &env; + + Genode::Attached_rom_dataspace config_rom { env, "config" }; + + Nitpicker::Connection nitpicker { env, "input" }; + + Input::Session_client &input = *nitpicker.input(); + + Genode::Reconstructible loader { + env, env.ram().avail() - 4096 }; + + + /******************************** + ** State held between signals ** + ********************************/ + + enum Phase { IDLE, ENTER, DRAG, EXIT }; + + Phase phase = IDLE; + + int entry_key = Input::KEY_UNKNOWN; + int entry_count; + int entry_x; + int entry_y; + int exit_x; + int exit_y; + + + /*************** + ** Rendering ** + ***************/ + + Nitpicker::Session::View_handle view_handle = nitpicker.create_view(); + + Nitpicker::Point nit_point() + { + return Nitpicker::Point( + entry_x < exit_x ? entry_x : exit_x, + entry_y < exit_y ? entry_y : exit_y); + } + + + Nitpicker::Area nit_area() + { + return Nitpicker::Area( + entry_x < exit_x ? exit_x - entry_x : entry_x - exit_x, + entry_y < exit_y ? exit_y - entry_y : entry_y - exit_y); + } + + Nitpicker::Rect nit_rect() + { + return Nitpicker::Rect(nit_point(), nit_area()); + } + + void render_drag() + { + nitpicker.enqueue(view_handle, nit_rect()); + nitpicker.execute(); + } + + String loader_binary(Genode::Xml_node const &start_node) + { + using Genode::Xml_node; + String name; + + try { + Xml_node binary = start_node.sub_node("binary"); + binary.attribute("name").value(&name); + } catch (Xml_node::Nonexistent_sub_node) { + start_node.attribute("name").value(&name); + } + return name; + } + + String loader_label(Genode::Xml_node const &start_node) + { + String name; + start_node.attribute("name").value(&name); + return name; + } + + void render_loader() + { + using namespace Nitpicker; + using namespace Genode; + + /* Reduce the view area to zero unit the loader is ready */ + nitpicker.enqueue( + view_handle, Nitpicker::Rect(nit_point(), Nitpicker::Area())); + nitpicker.execute(); + + /* If the selected view is too tiny, back out */ + Nitpicker::Area area = nit_area(); + if (area.w() < 16 && area.h() < 16) + return; + + Xml_node start_node = config_rom.xml().sub_node("start"); + + /* We are only patron of single load, so transfer the slack RAM */ + loader.construct(env, env.ram().avail() - 4096); + + try { + Xml_node config_xml = start_node.sub_node("config"); + Attached_dataspace ds( + env.rm(), loader->alloc_rom_module("config", config_xml.size())); + + strncpy(ds.local_addr(), config_xml.addr(), + config_xml.size()+1); + loader->commit_rom_module("config"); + } catch (Xml_node::Nonexistent_sub_node) { } + + + loader->view_ready_sigh(view_ready_handler); + loader->parent_view(nitpicker.view_capability(view_handle)); + + loader->start(loader_binary(start_node).string(), + loader_label(start_node).string()); + } + + + /********************* + ** Signal handling ** + *********************/ + + void handle_input() + { + using namespace Input; + + input.for_each_event([&] (Event const &ev) { + switch (ev.type()) { + case Event::MOTION: + switch (phase) { + case ENTER: + phase = DRAG; + nitpicker.enqueue(view_handle); + entry_x = exit_x = ev.ax(); + entry_y = exit_y = ev.ay(); + break; + case DRAG: + exit_x = ev.ax(); + exit_y = ev.ay(); + break; + default: break; + } + break; + + case Event::PRESS: + switch (phase) { + case IDLE: + phase = ENTER; + loader.destruct(); + entry_key = ev.code(); + entry_count = 1; + entry_x = entry_y = exit_x = exit_y = 0; + break; + default: break; + } + break; + + case Event::RELEASE: + switch (phase) { + case IDLE: + break; + default: + if (entry_key == ev.code()) { + phase = EXIT; + nitpicker.enqueue(view_handle); + } + } + break; + default: break; + } + }); + + switch (phase) { + case DRAG: + render_drag(); + break; + + case EXIT: + phase = IDLE; + render_loader(); + break; + + default: + break; + } + } + + Genode::Signal_handler
input_handler { + env.ep(), *this, &Main::handle_input }; + + void handle_view_ready() + { + Loader::Area const la = loader->view_size(); + Nitpicker::Area const na = nit_area(); + { + using namespace Loader; + + Area area( + Genode::min(la.w(), na.w()), + Genode::min(la.h(), na.h())); + + Rect const rect(Point(), area); + + { + using namespace Nitpicker; + + Point const np = nit_point(); + + Point const offset_point( + rect.w() < na.w() ? np.x() + (na.w() - rect.w()) / 2 : np.x(), + rect.h() < na.h() ? np.y() + (na.h() - rect.h()) / 2 : np.y()); + Rect const offset_rect(offset_point, area); + nitpicker.enqueue( + view_handle, offset_rect); + nitpicker.execute(); + } + + loader->view_geometry(rect, Point()); + } + } + + Genode::Signal_handler
view_ready_handler { + env.ep(), *this, &Main::handle_view_ready }; + + Main(Genode::Env &env) : env(env) + { + input.sigh(input_handler); + } +}; + + +void Component::construct(Genode::Env &env) +{ + static Morse::Main main(env); +} diff --git a/src/app/pike_loader/target.mk b/src/app/pike_loader/target.mk new file mode 100644 index 0000000..c72b535 --- /dev/null +++ b/src/app/pike_loader/target.mk @@ -0,0 +1,3 @@ +TARGET = pike_loader +SRC_CC = main.cc +LIBS = base