From 745ee04583787e52fc71239e2ef30d67880747a6 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Wed, 26 Sep 2018 16:44:46 +0200 Subject: [PATCH] Window manager test for tiled-console scenario --- .../gems/recipes/src/test-tiled_wm/content.mk | 18 ++ repos/gems/recipes/src/test-tiled_wm/hash | 1 + .../gems/recipes/src/test-tiled_wm/used_apis | 13 + repos/gems/run/tiled_wm.run | 248 ++++++++++++++++++ repos/gems/src/test/tiled_wm/app/app.cpp | 45 ++++ repos/gems/src/test/tiled_wm/app/app.h | 46 ++++ repos/gems/src/test/tiled_wm/app/app.pro | 6 + repos/gems/src/test/tiled_wm/app/app.qrc | 8 + repos/gems/src/test/tiled_wm/app/main.cpp | 55 ++++ repos/gems/src/test/tiled_wm/app/target.mk | 1 + repos/gems/src/test/tiled_wm/manager/main.cc | 211 +++++++++++++++ .../gems/src/test/tiled_wm/manager/target.mk | 3 + repos/gems/src/test/tiled_wm/overlay/main.cpp | 43 +++ .../src/test/tiled_wm/overlay/overlay.cpp | 37 +++ .../gems/src/test/tiled_wm/overlay/overlay.h | 46 ++++ .../src/test/tiled_wm/overlay/overlay.pro | 6 + .../src/test/tiled_wm/overlay/overlay.qrc | 8 + .../gems/src/test/tiled_wm/overlay/target.mk | 1 + repos/gems/src/test/tiled_wm/panel/main.cpp | 45 ++++ repos/gems/src/test/tiled_wm/panel/panel.cpp | 144 ++++++++++ repos/gems/src/test/tiled_wm/panel/panel.h | 109 ++++++++ repos/gems/src/test/tiled_wm/panel/panel.pro | 6 + repos/gems/src/test/tiled_wm/panel/panel.qrc | 9 + repos/gems/src/test/tiled_wm/panel/target.mk | 3 + repos/gems/src/test/tiled_wm/panel/wifi.png | Bin 0 -> 4502 bytes repos/gems/src/test/tiled_wm/style.qss | 22 ++ repos/gems/src/test/tiled_wm/target.inc | 25 ++ repos/gems/src/test/tiled_wm/util.h | 153 +++++++++++ 28 files changed, 1312 insertions(+) create mode 100644 repos/gems/recipes/src/test-tiled_wm/content.mk create mode 100644 repos/gems/recipes/src/test-tiled_wm/hash create mode 100644 repos/gems/recipes/src/test-tiled_wm/used_apis create mode 100644 repos/gems/run/tiled_wm.run create mode 100644 repos/gems/src/test/tiled_wm/app/app.cpp create mode 100644 repos/gems/src/test/tiled_wm/app/app.h create mode 100644 repos/gems/src/test/tiled_wm/app/app.pro create mode 100644 repos/gems/src/test/tiled_wm/app/app.qrc create mode 100644 repos/gems/src/test/tiled_wm/app/main.cpp create mode 100644 repos/gems/src/test/tiled_wm/app/target.mk create mode 100644 repos/gems/src/test/tiled_wm/manager/main.cc create mode 100644 repos/gems/src/test/tiled_wm/manager/target.mk create mode 100644 repos/gems/src/test/tiled_wm/overlay/main.cpp create mode 100644 repos/gems/src/test/tiled_wm/overlay/overlay.cpp create mode 100644 repos/gems/src/test/tiled_wm/overlay/overlay.h create mode 100644 repos/gems/src/test/tiled_wm/overlay/overlay.pro create mode 100644 repos/gems/src/test/tiled_wm/overlay/overlay.qrc create mode 100644 repos/gems/src/test/tiled_wm/overlay/target.mk create mode 100644 repos/gems/src/test/tiled_wm/panel/main.cpp create mode 100644 repos/gems/src/test/tiled_wm/panel/panel.cpp create mode 100644 repos/gems/src/test/tiled_wm/panel/panel.h create mode 100644 repos/gems/src/test/tiled_wm/panel/panel.pro create mode 100644 repos/gems/src/test/tiled_wm/panel/panel.qrc create mode 100644 repos/gems/src/test/tiled_wm/panel/target.mk create mode 100644 repos/gems/src/test/tiled_wm/panel/wifi.png create mode 100644 repos/gems/src/test/tiled_wm/style.qss create mode 100644 repos/gems/src/test/tiled_wm/target.inc create mode 100644 repos/gems/src/test/tiled_wm/util.h diff --git a/repos/gems/recipes/src/test-tiled_wm/content.mk b/repos/gems/recipes/src/test-tiled_wm/content.mk new file mode 100644 index 000000000..3bf4ad64d --- /dev/null +++ b/repos/gems/recipes/src/test-tiled_wm/content.mk @@ -0,0 +1,18 @@ +MIRROR_FROM_REP_DIR := src/test/tiled_wm + +content: $(MIRROR_FROM_REP_DIR) LICENSE + +$(MIRROR_FROM_REP_DIR): + $(mirror_from_rep_dir) + +MIRROR_FROM_LIBPORTS := src/app/qt5/tmpl/target_defaults.inc \ + src/app/qt5/tmpl/target_final.inc + +content: $(MIRROR_FROM_LIBPORTS) + +$(MIRROR_FROM_LIBPORTS): + mkdir -p $(dir $@) + cp -r $(GENODE_DIR)/repos/libports/$@ $(dir $@) + +LICENSE: + cp $(GENODE_DIR)/LICENSE $@ diff --git a/repos/gems/recipes/src/test-tiled_wm/hash b/repos/gems/recipes/src/test-tiled_wm/hash new file mode 100644 index 000000000..d3ce74600 --- /dev/null +++ b/repos/gems/recipes/src/test-tiled_wm/hash @@ -0,0 +1 @@ +2018-10-02 0741bbe9067957b8884dfc14708e0dbcce6f5285 diff --git a/repos/gems/recipes/src/test-tiled_wm/used_apis b/repos/gems/recipes/src/test-tiled_wm/used_apis new file mode 100644 index 000000000..a73c52e02 --- /dev/null +++ b/repos/gems/recipes/src/test-tiled_wm/used_apis @@ -0,0 +1,13 @@ +base +libc +os +qoost +qt5_core +qt5_gui +qt5_qjpeg +qt5_qpa_nitpicker +qt5_widgets +report_session +stdcxx +timer_session +vfs diff --git a/repos/gems/run/tiled_wm.run b/repos/gems/run/tiled_wm.run new file mode 100644 index 000000000..91cb43ebc --- /dev/null +++ b/repos/gems/run/tiled_wm.run @@ -0,0 +1,248 @@ +source ${genode_dir}/repos/libports/run/qt5_common.inc + +import_from_depot [depot_user]/src/qt5_component \ + [depot_user]/src/qt5_printsupport \ + [depot_user]/src/qt5_textedit \ + [depot_user]/src/qt5_widgets \ + [depot_user]/src/dynamic_rom \ + [depot_user]/src/test-tiled_wm + +if {[have_spec odroid_xu]} { + puts "Run script does not support this platform." + exit 0 +} + +# +# Generate config +# + +proc qt5_layouter_config { } { + return { } +} + +proc qt5_decorator_binary { } { return "themed_decorator" } + +proc qt5_decorator_config { } { + return { + + + + + + + + + + + + + } +} + +append config { + + } [qt5_parent_provides feature] { + + + + + } [qt5_start_nodes feature] { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2018-01-01 00:01 + + + + + + + + + + + + + + + + + + + + + + + + + + 2018-01-01 00:01 + + + + + + + + + + + + + + + + + + + + + + + 2018-01-01 00:01 + + + + + + + + + + + + + + + + + + + + + + + 2018-01-01 00:01 + + + + + + + + + + + + + + + + + + + + + + 2018-01-01 00:01 + + + + + + + + + + + + + + + +} + +install_config $config + +append build_components [qt5_build_components feature] + +# for debugging only +#append build_components { app/window_layouter app/themed_decorator } + +build $build_components + +append boot_modules [qt5_boot_modules feature] + +# for debugging only +#append boot_modules { window_layouter themed_decorator } + +build_boot_image $boot_modules + +append qemu_args " -usbdevice tablet " + +run_genode_until forever + +# vi: set ft=tcl : diff --git a/repos/gems/src/test/tiled_wm/app/app.cpp b/repos/gems/src/test/tiled_wm/app/app.cpp new file mode 100644 index 000000000..486d31a33 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/app/app.cpp @@ -0,0 +1,45 @@ +/* + * \brief Tiled-WM test: example application widget + * \author Christian Helmuth + * \date 2018-09-28 + */ + +/* + * 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. + */ + +/* Qt includes */ +#include +#include + +/* local includes */ +#include "app.h" + + +App::App(QString name) +{ + _name->setText("This is " + name + " an example application for the tiled-WM test."); + _entry->setPlaceholderText("Placeholder text"); + + _layout->addWidget(new Spacer(), 1); + _layout->addWidget(_name); + _layout->addWidget(new Spacer(), 1); + _layout->addWidget(_entry); + _layout->addWidget(new Spacer(), 1); + + for (int i = 0; i < 3; ++i) { + QLabel *l = new QLabel(QString("QLabel No." + QString::number(i))); + l->setToolTip(QString::number(i) + " is just a number."); + _layout->addWidget(l); + } + + _layout->addWidget(new Spacer(), 1); +} + + +App::~App() +{ +} diff --git a/repos/gems/src/test/tiled_wm/app/app.h b/repos/gems/src/test/tiled_wm/app/app.h new file mode 100644 index 000000000..328bd8a2a --- /dev/null +++ b/repos/gems/src/test/tiled_wm/app/app.h @@ -0,0 +1,46 @@ +/* + * \brief TIled-WM test: example application widget + * \author Christian Helmuth + * \date 2018-09-28 + */ + +/* + * 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. + */ + +#ifndef _TEST__TILED_WM__APP__APP_H_ +#define _TEST__TILED_WM__APP__APP_H_ + +/* Qt includes */ +#include +#include +#include +#include + +/* Qoost includes */ +#include +#include + +/* local includes */ +#include + + +class App : public Compound_widget +{ + Q_OBJECT + + private: + + QMember _name; + QMember _entry; + + public: + + App(QString name); + ~App(); +}; + +#endif /* _TEST__TILED_WM__APP__APP_H_ */ diff --git a/repos/gems/src/test/tiled_wm/app/app.pro b/repos/gems/src/test/tiled_wm/app/app.pro new file mode 100644 index 000000000..70756a500 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/app/app.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = test-tiled_wm-app +QT = core gui widgets +SOURCES += main.cpp app.cpp +HEADERS += app.h ../util.h +RESOURCES = app.qrc diff --git a/repos/gems/src/test/tiled_wm/app/app.qrc b/repos/gems/src/test/tiled_wm/app/app.qrc new file mode 100644 index 000000000..cb8c387b6 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/app/app.qrc @@ -0,0 +1,8 @@ + + + + ../style.qss + + + + diff --git a/repos/gems/src/test/tiled_wm/app/main.cpp b/repos/gems/src/test/tiled_wm/app/main.cpp new file mode 100644 index 000000000..275a3a810 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/app/main.cpp @@ -0,0 +1,55 @@ +/* + * \brief Tiled-WM test: example application + * \author Christian Helmuth + * \date 2018-09-26 + */ + +/* + * 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 + +/* local includes */ +#include +#include "app.h" + + +struct Main +{ + Libc::Env &env; + + Genode::Attached_rom_dataspace config { env, "config" }; + + QApplication &app { qt5_initialization(env) }; + + QMember widget { name_from_config() }; + + QString name_from_config() + { + Name name = config.xml().attribute_value("name", Name("no name")); + + return QString(name.string()); + } + + Main(Libc::Env &env) : env(env) + { + widget->show(); + } +}; + + +void Libc::Component::construct(Libc::Env &env) +{ + Libc::with_libc([&] { + + static Main main { env }; + + exit(main.app.exec()); + }); +} + diff --git a/repos/gems/src/test/tiled_wm/app/target.mk b/repos/gems/src/test/tiled_wm/app/target.mk new file mode 100644 index 000000000..48ac9307d --- /dev/null +++ b/repos/gems/src/test/tiled_wm/app/target.mk @@ -0,0 +1 @@ +include $(PRG_DIR)/../target.inc diff --git a/repos/gems/src/test/tiled_wm/manager/main.cc b/repos/gems/src/test/tiled_wm/manager/main.cc new file mode 100644 index 000000000..c9a14a1e0 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/manager/main.cc @@ -0,0 +1,211 @@ +/* + * \brief Tiled-WM test: GUI manager + * \author Christian Helmuth + * \date 2018-09-26 + * + * GUI manager implements the user-visible display state machine. + */ + +/* + * 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 + + +typedef Genode::String<32> Name; + + +namespace Test { struct Manager; } + +struct Test::Manager +{ + Genode::Env &env; + + Genode::Attached_rom_dataspace content_request_rom { env, "content_request" }; + Genode::Attached_rom_dataspace overlay_request_rom { env, "overlay_request" }; + + Genode::Signal_handler content_request_handler { + env.ep(), *this, &Manager::handle_content_request }; + Genode::Signal_handler overlay_request_handler { + env.ep(), *this, &Manager::handle_overlay_request }; + + Genode::Reporter apps_report { env, "apps" }; + Genode::Reporter overlay_report { env, "overlay" }; + + Genode::Reporter layout_rules_report { env, "rules", "layout_rules" }; + + struct App { + char const *label; + char const *name; + bool visible; + } apps[3] { + { "test-tiled_wm-app-1", "app1", true }, + { "test-tiled_wm-app-2", "app2", false }, + { "textedit", "textedit", false } + }; + + bool overlay_visible { false }; + + void report_apps(); + void report_overlay(); + void report_layout_rules(); + + void handle_content_request(); + void handle_overlay_request(); + + Manager(Genode::Env &env); +}; + + +void Test::Manager::handle_content_request() +{ + content_request_rom.update(); + + Name requested_app = + content_request_rom.xml().attribute_value("name", Name()); + + if (!requested_app.valid()) return; + + App *found = nullptr; + for (App &app : apps) { + if (requested_app != app.name) continue; + found = &app; + break; + } + if (!found || found->visible) return; + + for (App &app : apps) { + if (&app == found) { + app.visible = true; + } else { + app.visible = false; + } + } + + report_apps(); + report_layout_rules(); +} + + +void Test::Manager::handle_overlay_request() +{ + overlay_request_rom.update(); + + bool const request_visible = + overlay_request_rom.xml().attribute_value("visible", false); + + if (request_visible == overlay_visible) return; + + overlay_visible = request_visible; + + report_overlay(); + report_layout_rules(); +} + + +void Test::Manager::report_apps() +{ + Genode::Reporter::Xml_generator xml(apps_report, [&] () { + for (App &app : apps) { + xml.node("app", [&] () { + xml.attribute("name", app.name); + xml.attribute("visible", app.visible); + }); + } + }); +} + + +void Test::Manager::report_overlay() +{ + Genode::Reporter::Xml_generator xml(overlay_report, [&] () { + xml.attribute("visible", overlay_visible); + }); +} + + +void Test::Manager::report_layout_rules() +{ + Genode::Reporter::Xml_generator xml(layout_rules_report, [&] () { + xml.node("screen", [&] () { + xml.node("column", [&] () { + xml.attribute("name", "screen"); + xml.attribute("layer", "1"); + xml.node("row", [&] () { + xml.attribute("name", "content"); + xml.attribute("layer", "4"); + xml.node("column", [&] () { + xml.attribute("weight", "2"); + }); + xml.node("column", [&] () { + xml.attribute("name", "overlay"); + xml.attribute("layer", "3"); + xml.attribute("weight", "1"); + }); + }); + xml.node("row", [&] () { + xml.attribute("name", "panel"); + xml.attribute("layer", "2"); + xml.attribute("height", "24"); + }); + }); + }); + xml.node("assign", [&] () { + xml.attribute("label_prefix", "test-tiled_wm-panel"); + xml.attribute("target", "panel"); + }); + if (overlay_visible) { + xml.node("assign", [&] () { + xml.attribute("label_prefix", "test-tiled_wm-overlay"); + xml.attribute("target", "overlay"); + }); + } + + /* debug */ + if (false) { + xml.node("assign", [&] () { + xml.attribute("label_prefix", ""); + xml.attribute("target", "screen"); + xml.attribute("xpos", "any"); + xml.attribute("ypos", "any"); + }); + } + + for (App &app : apps) { + if (!app.visible) continue; + + xml.node("assign", [&] () { + xml.attribute("label_prefix", app.label); + xml.attribute("target", "content"); + }); + break; + } + }); +} + + +Test::Manager::Manager(Genode::Env &env) : env(env) +{ + apps_report.enabled(true); + overlay_report.enabled(true); + layout_rules_report.enabled(true); + + content_request_rom.sigh(content_request_handler); + overlay_request_rom.sigh(overlay_request_handler); + + report_apps(); + report_overlay(); + report_layout_rules(); +} + + +void Component::construct(Genode::Env &env) { static Test::Manager manager(env); } diff --git a/repos/gems/src/test/tiled_wm/manager/target.mk b/repos/gems/src/test/tiled_wm/manager/target.mk new file mode 100644 index 000000000..de4d67ed8 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/manager/target.mk @@ -0,0 +1,3 @@ +TARGET = test-tiled_wm-manager +SRC_CC = main.cc +LIBS = base diff --git a/repos/gems/src/test/tiled_wm/overlay/main.cpp b/repos/gems/src/test/tiled_wm/overlay/main.cpp new file mode 100644 index 000000000..4889626bc --- /dev/null +++ b/repos/gems/src/test/tiled_wm/overlay/main.cpp @@ -0,0 +1,43 @@ +/* + * \brief Tiled-WM test: example overlay + * \author Christian Helmuth + * \date 2018-09-28 + */ + +/* + * 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. + */ + +/* local includes */ +#include +#include "overlay.h" + + +struct Main +{ + Libc::Env &env; + + QApplication &app { qt5_initialization(env) }; + + QMember widget { }; + + Main(Libc::Env &env) : env(env) + { + widget->show(); + } +}; + + +void Libc::Component::construct(Libc::Env &env) +{ + Libc::with_libc([&] { + + static Main main { env }; + + exit(main.app.exec()); + }); +} + diff --git a/repos/gems/src/test/tiled_wm/overlay/overlay.cpp b/repos/gems/src/test/tiled_wm/overlay/overlay.cpp new file mode 100644 index 000000000..3acad9735 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/overlay/overlay.cpp @@ -0,0 +1,37 @@ +/* + * \brief Tiled-WM test: overlay widget + * \author Christian Helmuth + * \date 2018-09-28 + */ + +/* + * 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. + */ + +/* Qt includes */ +#include +#include + +/* local includes */ +#include "overlay.h" + + +Overlay::Overlay() +{ + _label->setText("WiFi overlay"); + _entry->setEchoMode(QLineEdit::Password); + + _layout->addWidget(new Spacer(), 1); + _layout->addWidget(_label); + _layout->addWidget(new Spacer(), 1); + _layout->addWidget(_entry); + _layout->addWidget(new Spacer(), 1); +} + + +Overlay::~Overlay() +{ +} diff --git a/repos/gems/src/test/tiled_wm/overlay/overlay.h b/repos/gems/src/test/tiled_wm/overlay/overlay.h new file mode 100644 index 000000000..ac880c498 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/overlay/overlay.h @@ -0,0 +1,46 @@ +/* + * \brief Tiled-WM test: overlay widget + * \author Christian Helmuth + * \date 2018-09-28 + */ + +/* + * 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. + */ + +#ifndef _TEST__TILED_WM__OVERLAY__OVERLAY_H_ +#define _TEST__TILED_WM__OVERLAY__OVERLAY_H_ + +/* Qt includes */ +#include +#include +#include +#include + +/* Qoost includes */ +#include +#include + +/* local includes */ +#include + + +class Overlay : public Compound_widget +{ + Q_OBJECT + + private: + + QMember _label; + QMember _entry; + + public: + + Overlay(); + ~Overlay(); +}; + +#endif /* _TEST__TILED_WM__OVERLAY__OVERLAY_H_ */ diff --git a/repos/gems/src/test/tiled_wm/overlay/overlay.pro b/repos/gems/src/test/tiled_wm/overlay/overlay.pro new file mode 100644 index 000000000..2635ce4a9 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/overlay/overlay.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = test-tiled_wm-overlay +QT = core gui widgets +SOURCES += main.cpp overlay.cpp +HEADERS += overlay.h ../util.h +RESOURCES = overlay.qrc diff --git a/repos/gems/src/test/tiled_wm/overlay/overlay.qrc b/repos/gems/src/test/tiled_wm/overlay/overlay.qrc new file mode 100644 index 000000000..cb8c387b6 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/overlay/overlay.qrc @@ -0,0 +1,8 @@ + + + + ../style.qss + + + + diff --git a/repos/gems/src/test/tiled_wm/overlay/target.mk b/repos/gems/src/test/tiled_wm/overlay/target.mk new file mode 100644 index 000000000..48ac9307d --- /dev/null +++ b/repos/gems/src/test/tiled_wm/overlay/target.mk @@ -0,0 +1 @@ +include $(PRG_DIR)/../target.inc diff --git a/repos/gems/src/test/tiled_wm/panel/main.cpp b/repos/gems/src/test/tiled_wm/panel/main.cpp new file mode 100644 index 000000000..75342881b --- /dev/null +++ b/repos/gems/src/test/tiled_wm/panel/main.cpp @@ -0,0 +1,45 @@ +/* + * \brief Tiled-WM test: panel + * \author Christian Helmuth + * \date 2018-09-26 + * + * Panel is a Qt5-based example panel at the bottom of the screen. + */ + +/* + * 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. + */ + +/* local includes */ +#include "panel.h" + + +struct Main +{ + Libc::Env &env; + + Genode_signal_dispatcher dispatcher { env }; + + QApplication &app { qt5_initialization(env) }; + + QMember widget { env, dispatcher.signal_receiver() }; + + Main(Libc::Env &env) : env(env) + { + widget->show(); + } +}; + + +void Libc::Component::construct(Libc::Env &env) +{ + Libc::with_libc([&] { + + static Main main { env }; + + exit(main.app.exec()); + }); +} diff --git a/repos/gems/src/test/tiled_wm/panel/panel.cpp b/repos/gems/src/test/tiled_wm/panel/panel.cpp new file mode 100644 index 000000000..c7a2f8a07 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/panel/panel.cpp @@ -0,0 +1,144 @@ +/* + * \brief Tiled-WM test: panel widget + * \author Christian Helmuth + * \date 2018-09-28 + */ + +/* + * 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. + */ + +/* Qt includes */ +#include +#include + +/* local includes */ +#include "panel.h" + + +void Panel_button::_clicked() { Q_EMIT clicked(text()); } +void Panel_button::_toggled(bool checked) { Q_EMIT toggled(checked, text()); } + + +Panel_button::Panel_button(QString label) +{ + if (!label.isNull()) { + setText(label); + } + + setCheckable(true); + setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + + _layout->addWidget(_icon, 0, Qt::AlignCenter); + + connect(this, SIGNAL(clicked()), SLOT(_clicked())); + connect(this, SIGNAL(toggled(bool)), SLOT(_toggled(bool))); +} + + +Panel_button::~Panel_button() { } + + +void App_bar::_app_button(QAbstractButton *b, bool checked) +{ + if (!checked) return; + + if (Panel_button *button = qobject_cast(b)) { + Name name { button->text().toUtf8().constData() }; + + Genode::Reporter::Xml_generator xml(_content_request, [&] () { + xml.attribute("name", name); + }); + } +} + + +void App_bar::_handle_apps() +{ + /* empty bar before adding current apps */ + while (QLayoutItem *item = _layout->takeAt(0)) { + if (Panel_button *button = qobject_cast(item->widget())) { + _button_group->removeButton(button); + button->deleteLater(); + } + delete item; + } + + _apps.update(); + + Panel_button *visible_app_button = nullptr; + + _apps.xml().for_each_sub_node("app", [&] (Genode::Xml_node node) { + QString const name { node.attribute_value("name", Name("no name")).string() }; + bool const visible { node.attribute_value("visible", false) }; + Panel_button *button { new Panel_button(name) }; + + if (visible) visible_app_button = button; + + _button_group->addButton(button); + _layout->addWidget(button); + }); + + if (visible_app_button) visible_app_button->setChecked(true); +} + + +App_bar::App_bar(Genode::Env &env, Genode::Signal_receiver &sig_rec) +: + _apps(env, "apps"), _content_request(env, "content_request"), + _apps_proxy(sig_rec) +{ + _content_request.enabled(true); + + _button_group->setExclusive(true); + + _handle_apps(); + + _apps.sigh(*_apps_proxy); + + connect(_apps_proxy, SIGNAL(signal()), SLOT(_handle_apps())); + connect(_button_group, SIGNAL(buttonToggled(QAbstractButton *, bool)), + SLOT(_app_button(QAbstractButton *, bool))); +} + + +App_bar::~App_bar() { } + + +void Panel::_wifi_toggled(bool checked) +{ + Genode::Reporter::Xml_generator xml(_overlay_request, [&] () { + xml.attribute("visible", checked); + }); +} + + +Panel::Panel(Genode::Env &env, Genode::Signal_receiver &sig_rec) +: + _overlay(env, "overlay"), _overlay_request(env, "overlay_request"), + _panel_button("Panel"), _app_bar(env, sig_rec) +{ + _layout->addWidget(_panel_button); + _layout->addWidget(new Spacer(), 1); + _layout->addWidget(_app_bar); + _layout->addWidget(new Spacer(), 1); + _layout->addWidget(_wifi_button); + + _panel_button->setCheckable(false); + _panel_button->setToolTip("This panel is just an example."); + + _wifi_button->setObjectName("wifi"); + _wifi_button->setToolTip("Open WiFi overlay"); + + _overlay_request.enabled(true); + + _wifi_toggled(_wifi_button->isChecked()); + + connect(_wifi_button, SIGNAL(toggled(bool)), SLOT(_wifi_toggled(bool))); +} + + +Panel::~Panel() { } diff --git a/repos/gems/src/test/tiled_wm/panel/panel.h b/repos/gems/src/test/tiled_wm/panel/panel.h new file mode 100644 index 000000000..afe3eb70a --- /dev/null +++ b/repos/gems/src/test/tiled_wm/panel/panel.h @@ -0,0 +1,109 @@ +/* + * \brief Tiled-WM test: panel widget + * \author Christian Helmuth + * \date 2018-09-27 + */ + +/* + * 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. + */ + +#ifndef _TEST__TILED_WM__PANEL__PANEL_H_ +#define _TEST__TILED_WM__PANEL__PANEL_H_ + +/* Qt includes */ +#include +#include +#include +#include + +/* Qoost includes */ +#include +#include + +/* Genode includes */ +#include +#include + +/* local includes */ +#include +#include /* build-dir copy of qoost/icon.h works around missing "vtable for Icon" */ + + +class Panel_button : public Compound_widget +{ + Q_OBJECT + + private: + + QMember _icon; + + private Q_SLOTS: + + void _clicked(); + void _toggled(bool); + + public: + + Panel_button(QString label = QString()); + ~Panel_button(); + + Q_SIGNALS: + + void clicked(QString label); + void toggled(bool checked, QString label); +}; + + +class App_bar : public Compound_widget +{ + Q_OBJECT + + private: + + Genode::Attached_rom_dataspace _apps; + Genode::Reporter _content_request; + + QMember _button_group; + QMember _apps_proxy; + + private Q_SLOTS: + + void _handle_apps(); + void _app_button(QAbstractButton *, bool); + + public: + + App_bar(Genode::Env &, Genode::Signal_receiver &); + ~App_bar(); +}; + + + +class Panel : public Compound_widget +{ + Q_OBJECT + + private: + + Genode::Attached_rom_dataspace _overlay; + Genode::Reporter _overlay_request; + + QMember _panel_button; + QMember _app_bar; + QMember _wifi_button; + + private Q_SLOTS: + + void _wifi_toggled(bool); + + public: + + Panel(Genode::Env &, Genode::Signal_receiver &); + ~Panel(); +}; + +#endif /* _TEST__TILED_WM__PANEL__PANEL_H_ */ diff --git a/repos/gems/src/test/tiled_wm/panel/panel.pro b/repos/gems/src/test/tiled_wm/panel/panel.pro new file mode 100644 index 000000000..3ec8f3f59 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/panel/panel.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = test-tiled_wm-panel +QT = core gui widgets +SOURCES += main.cpp panel.cpp +HEADERS += panel.h icon.h ../util.h +RESOURCES = panel.qrc diff --git a/repos/gems/src/test/tiled_wm/panel/panel.qrc b/repos/gems/src/test/tiled_wm/panel/panel.qrc new file mode 100644 index 000000000..9092a358d --- /dev/null +++ b/repos/gems/src/test/tiled_wm/panel/panel.qrc @@ -0,0 +1,9 @@ + + + + ../style.qss + wifi.png + + + + diff --git a/repos/gems/src/test/tiled_wm/panel/target.mk b/repos/gems/src/test/tiled_wm/panel/target.mk new file mode 100644 index 000000000..3b2def425 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/panel/target.mk @@ -0,0 +1,3 @@ +include $(PRG_DIR)/../target.inc + +panel.o main.o: icon.h diff --git a/repos/gems/src/test/tiled_wm/panel/wifi.png b/repos/gems/src/test/tiled_wm/panel/wifi.png new file mode 100644 index 0000000000000000000000000000000000000000..502591d38ec29cb8449b13cf07f3409a25cb3f58 GIT binary patch literal 4502 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 ATL1t6 literal 0 HcmV?d00001 diff --git a/repos/gems/src/test/tiled_wm/style.qss b/repos/gems/src/test/tiled_wm/style.qss new file mode 100644 index 000000000..067e94aab --- /dev/null +++ b/repos/gems/src/test/tiled_wm/style.qss @@ -0,0 +1,22 @@ +Panel, Overlay, App { min-width: 100px; min-height: 100px; } + +QFrame { padding: 5px; } +QLabel { color: white; } +/*QPushButton { border: none; outline: none; }*/ + +Panel { + background-color: rgb(51, 93, 128); +} + +Panel_button Icon { qproperty-iconSize: 18px; } +Panel_button#wifi Icon { qproperty-iconFile: url(:/wifi.png); } + +Overlay { + background-color: rgba(25, 69, 105, 100); +} + +App { + background-color: rgb(96, 130, 159); +} + +/* vi: set ft=css : */ diff --git a/repos/gems/src/test/tiled_wm/target.inc b/repos/gems/src/test/tiled_wm/target.inc new file mode 100644 index 000000000..723db9f45 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/target.inc @@ -0,0 +1,25 @@ +include $(call select_from_repositories,src/app/qt5/tmpl/target_defaults.inc) + +include $(call select_from_repositories,src/app/qt5/tmpl/target_final.inc) + +CC_CXX_WARN_STRICT = + +INC_DIR += $(PRG_DIR)/.. + +LIBS += qoost + +# +# We need Qt headers in a local directory for MOC to work correctly +# + +# icon.h from the qoost API package +ICON_H = $(call select_from_repositories,include/qoost/icon.h) + +# fall-back to the qoost port directory if that fails +ifeq ($(ICON_H),) +ICON_H = $(call select_from_ports,qoost)/include/qoost/icon.h +endif + +icon.h: $(ICON_H) + $(VERBOSE)cp $(ICON_H) . + diff --git a/repos/gems/src/test/tiled_wm/util.h b/repos/gems/src/test/tiled_wm/util.h new file mode 100644 index 000000000..6f0efee47 --- /dev/null +++ b/repos/gems/src/test/tiled_wm/util.h @@ -0,0 +1,153 @@ +/* + * \brief Tiled-WM test: utilities + * \author Christian Helmuth + * \date 2018-09-26 + */ + +/* + * 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. + */ + +#ifndef _TEST__TILED_WM__UTIL_H_ +#define _TEST__TILED_WM__UTIL_H_ + +/* Genode includes */ +#include +#include +#include +#include + +/* Qt includes */ +#include +#include +#include +#include +#include + +/* Qoost includes */ +#include + +/* Libc includes */ +#include + + +typedef Genode::String<32> Name; + + +/* + * Genode signal to queued Qt signal proxy + */ +class Genode_signal_proxy : public QObject, + public Genode::Signal_dispatcher +{ + Q_OBJECT + + public: + + Genode_signal_proxy(Genode::Signal_receiver &sig_rec) + : + Genode::Signal_dispatcher( + sig_rec, *this, &Genode_signal_proxy::handle_genode_signal) + { + connect(this, SIGNAL(internal_signal()), + this, SIGNAL(signal()), + Qt::QueuedConnection); + } + + /* called by signal dispatcher / emits internal signal in context of + * signal-dispatcher thread */ + void handle_genode_signal(unsigned = 0) { Q_EMIT internal_signal(); } + + Q_SIGNALS: + + /* internal_signal() is Qt::QueuedConnection to signal() */ + void internal_signal(); + + /* finally signal() is emitted in the context of the Qt main thread */ + void signal(); +}; + + +/* + * Genode signal dispatcher thread + */ +class Genode_signal_dispatcher : public Genode::Thread +{ + private: + + Genode::Signal_receiver _sig_rec; + + void entry() + { + /* dispatch signals */ + while (true) { + Genode::Signal sig = _sig_rec.wait_for_signal(); + Genode::Signal_dispatcher_base *dispatcher { + dynamic_cast(sig.context()) }; + + if (dispatcher) + dispatcher->dispatch(sig.num()); + } + } + + public: + + Genode_signal_dispatcher(Genode::Env &env) + : + Genode::Thread(env, "signal_dispatcher", 0x4000) + { + start(); + } + + Genode::Signal_receiver &signal_receiver() { return _sig_rec; } +}; + + +/* + * Qt initialization + */ + +extern void initialize_qt_core(Genode::Env &); +extern void initialize_qt_gui(Genode::Env &); + +static inline QApplication & qt5_initialization(Libc::Env &env) +{ + initialize_qt_core(env); + initialize_qt_gui(env); + + char const *argv[] = { "qt5_app", 0 }; + int argc = sizeof(argv)/sizeof(*argv); + + static QApplication app(argc, (char**)argv); + + QFile file(":style.qss"); + if (!file.open(QFile::ReadOnly)) { + qWarning() << "Warning:" << file.errorString() + << "opening file" << file.fileName(); + } else { + qApp->setStyleSheet(QLatin1String(file.readAll())); + } + + app.connect(&app, SIGNAL(lastWindowClosed()), SLOT(quit())); + + return app; +} + + +/* + * Widget utilities + */ + +struct Spacer : QFrame +{ + Q_OBJECT public: + + Spacer(QString const &style_id = "") { setObjectName(style_id); } + + ~Spacer() { } +}; + +#endif /* _TEST__TILED_WM__UTIL_H_ */