summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Vlad <marius.vlad@collabora.com>2022-11-01 13:29:43 +0200
committerMarius Vlad <marius.vlad@collabora.com>2023-01-20 11:14:12 +0200
commitbb4c83e294f109497f504c0dd8e23143c07883d6 (patch)
tree393a77c13dd4979e6f3480ae83c4792ece55207c
parentd4f3ddfbad7a64937f00f13ba964e18d33effbb0 (diff)
homescreen: Add support for defining an activation area
This is an example on how to use it, and it enables a new variable HOMESCREEN_EMBEDDED_PANELS to test it out. It gives out the same rectangle are we have in the homescreen demo, but the panels are this time embedded into the background surface, rather than being a separate surface. This introduces a new Qml file, background_with_panels which integrates both the top and the bottom panel into a single qml, which main.cpp loads. While at it, this corrects up the indentation we have in shell.cpp file and sets up the default output in homeScreenHandler constructor. Due to this way integrates and works, it should *not* be visual change between the two (the normal, two panel surfaces) and this version. It can used as a example how to integrate this better, when managing multiple surfaces is not easy to be done by the toolkit or runtime. Bug-AGL: SPEC-4594 Signed-off-by: Marius Vlad <marius.vlad@collabora.com> Change-Id: Ibe274b336b15e9713d0cdded5424cc8e92257d7f
-rw-r--r--homescreen/qml/background_with_panels.qml159
-rw-r--r--homescreen/qml/qml.qrc1
-rw-r--r--homescreen/src/homescreenhandler.cpp9
-rw-r--r--homescreen/src/homescreenhandler.h1
-rw-r--r--homescreen/src/main.cpp81
-rw-r--r--homescreen/src/shell.cpp8
-rw-r--r--homescreen/src/shell.h20
7 files changed, 252 insertions, 27 deletions
diff --git a/homescreen/qml/background_with_panels.qml b/homescreen/qml/background_with_panels.qml
new file mode 100644
index 0000000..f0cb958
--- /dev/null
+++ b/homescreen/qml/background_with_panels.qml
@@ -0,0 +1,159 @@
+import QtQuick 2.13
+import QtQuick.Window 2.13
+import QtQuick.Layouts 1.15
+
+Window {
+ id: background
+ width: Screen.width
+ height: Screen.height
+ flags: Qt.FramelessWindowHint
+ visible: true
+
+ Grid {
+ rows: 3
+ spacing: 0
+
+ Rectangle {
+ width: Screen.width
+ height: 216
+ color: "#33363a"
+
+ Timer {
+ id:notificationTimer
+ interval: 3000
+ running: false
+ repeat: true
+ onTriggered: notificationItem.visible = false
+ }
+
+ Item {
+ id: notificationItem
+ x: 0
+ y: 0
+ z: 1
+ width: 1280
+ height: 100
+ opacity: 0.8
+ visible: false
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ anchors.fill: parent
+ color: "gray"
+ Image {
+ id: notificationIcon
+ width: 70
+ height: 70
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ anchors.verticalCenter: parent.verticalCenter
+ source: ""
+ }
+
+ Text {
+ id: notificationtext
+ font.pixelSize: 25
+ anchors.left: notificationIcon.right
+ anchors.leftMargin: 5
+ anchors.verticalCenter: parent.verticalCenter
+ color: "white"
+ text: qsTr("")
+ }
+ }
+ }
+
+ Connections {
+ target: homescreenHandler
+ onShowNotification: {
+ notificationIcon.source = icon_path
+ notificationtext.text = text
+ notificationItem.visible = true
+ notificationTimer.restart()
+ }
+ }
+
+ Image {
+ anchors.fill: parent
+ source: './images/TopSection_NoText_NoIcons-01.svg'
+ //fillMode: Image.PreserveAspectCrop
+ fillMode: Image.Stretch
+
+ RowLayout {
+ anchors.fill: parent
+ spacing: 0
+ ShortcutArea {
+ id: shortcutArea
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.preferredWidth: 775
+ }
+ StatusArea {
+ id: statusArea
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.preferredWidth: 291
+ }
+ }
+ }
+
+ }
+
+ Rectangle {
+ width: Screen.width
+ height: Screen.height - (2 * 216)
+ Image {
+ anchors.fill: parent
+ source: './images/AGL_HMI_Blue_Background_NoCar-01.png'
+ }
+
+ }
+
+ Rectangle {
+ width: Screen.width
+ height: 216
+ color: "#33363a"
+
+ MediaArea {
+ }
+
+ Timer {
+ id:informationTimer
+ interval: 3000
+ running: false
+ repeat: true
+ onTriggered: {
+ bottomInformation.visible = false
+ }
+ }
+
+ Item {
+ id: bottomInformation
+ width: parent.width
+ height: 216
+ anchors.bottom: parent.bottom
+ visible: false
+ Text {
+ id: bottomText
+ anchors.centerIn: parent
+ font.pixelSize: 25
+ font.letterSpacing: 5
+ horizontalAlignment: Text.AlignHCenter
+ color: "white"
+ text: ""
+ z:1
+ }
+ }
+
+ Connections {
+ target: homescreenHandler
+ onShowInformation: {
+ bottomText.text = info
+ bottomInformation.visible = true
+ informationTimer.restart()
+ }
+ }
+
+ }
+ }
+}
diff --git a/homescreen/qml/qml.qrc b/homescreen/qml/qml.qrc
index 319e1da..3c0dbcd 100644
--- a/homescreen/qml/qml.qrc
+++ b/homescreen/qml/qml.qrc
@@ -10,6 +10,7 @@
<file>TopArea.qml</file>
<file>IconItem.qml</file>
<file>background.qml</file>
+ <file>background_with_panels.qml</file>
<file>toppanel.qml</file>
<file>bottompanel.qml</file>
<file>background_demo.qml</file>
diff --git a/homescreen/src/homescreenhandler.cpp b/homescreen/src/homescreenhandler.cpp
index 2858ef4..e61f0de 100644
--- a/homescreen/src/homescreenhandler.cpp
+++ b/homescreen/src/homescreenhandler.cpp
@@ -18,12 +18,17 @@
// a user session by systemd
#define LAUNCHER_APP_ID "launcher"
+static struct wl_output *
+getWlOutput(QPlatformNativeInterface *native, QScreen *screen);
+
HomescreenHandler::HomescreenHandler(Shell *_aglShell, ApplicationLauncher *launcher, QObject *parent) :
QObject(parent),
aglShell(_aglShell)
{
mp_launcher = launcher;
mp_applauncher_client = new AppLauncherClient();
+ QPlatformNativeInterface *native = qApp->platformNativeInterface();
+ m_output = getWlOutput(native, qApp->screens().first());
//
// The "started" event is received any time a start request is made to applaunchd,
@@ -88,15 +93,13 @@ void HomescreenHandler::addAppToStack(const QString& app_id)
void HomescreenHandler::activateApp(const QString& app_id)
{
struct agl_shell *agl_shell = aglShell->shell.get();
- QPlatformNativeInterface *native = qApp->platformNativeInterface();
- struct wl_output *output = getWlOutput(native, qApp->screens().first());
if (mp_launcher) {
mp_launcher->setCurrent(app_id);
}
HMI_DEBUG("HomeScreen", "Activating application %s", app_id.toStdString().c_str());
- agl_shell_activate_app(agl_shell, app_id.toStdString().c_str(), output);
+ agl_shell_activate_app(agl_shell, app_id.toStdString().c_str(), m_output);
}
void HomescreenHandler::deactivateApp(const QString& app_id)
diff --git a/homescreen/src/homescreenhandler.h b/homescreen/src/homescreenhandler.h
index a2baeb2..751457e 100644
--- a/homescreen/src/homescreenhandler.h
+++ b/homescreen/src/homescreenhandler.h
@@ -40,6 +40,7 @@ public slots:
private:
ApplicationLauncher *mp_launcher;
AppLauncherClient *mp_applauncher_client;
+ struct wl_output *m_output;
Shell *aglShell;
diff --git a/homescreen/src/main.cpp b/homescreen/src/main.cpp
index c910727..674ef5d 100644
--- a/homescreen/src/main.cpp
+++ b/homescreen/src/main.cpp
@@ -112,7 +112,7 @@ global_add(void *data, struct wl_registry *reg, uint32_t name,
if (ver >= 2) {
shell_data->shell =
static_cast<struct agl_shell *>(
- wl_registry_bind(reg, name, &agl_shell_interface, MIN(3, ver)));
+ wl_registry_bind(reg, name, &agl_shell_interface, MIN(4, ver)));
#ifdef AGL_SHELL_BOUND_OK_SINCE_VERSION
agl_shell_add_listener(shell_data->shell, &shell_listener, data);
#endif
@@ -213,15 +213,14 @@ static void
load_agl_shell_app(QPlatformNativeInterface *native,
QQmlApplicationEngine *engine,
struct agl_shell *agl_shell,
- const char *screen_name,
- bool is_demo)
+ const char *screen_name, bool is_demo, bool embedded_panels)
{
struct wl_surface *bg, *top, *bottom;
struct wl_output *output;
QObject *qobj_bg, *qobj_top, *qobj_bottom;
QScreen *screen = nullptr;
- if (is_demo) {
+ if (is_demo && !embedded_panels) {
QQmlComponent bg_comp(engine, QUrl("qrc:/background_demo.qml"));
qInfo() << bg_comp.errors();
@@ -234,7 +233,16 @@ load_agl_shell_app(QPlatformNativeInterface *native,
top = create_component(native, &top_comp, screen, &qobj_top);
bottom = create_component(native, &bot_comp, screen, &qobj_bottom);
bg = create_component(native, &bg_comp, screen, &qobj_bg);
- } else {
+
+ /* engine.rootObjects() works only if we had a load() */
+ StatusBarModel *statusBar = qobj_top->findChild<StatusBarModel *>("statusBar");
+ if (statusBar) {
+ qDebug() << "got statusBar objectname, doing init()";
+ statusBar->init(engine->rootContext());
+ }
+
+ qDebug() << "init debug mode";
+ } else if (!embedded_panels) {
QQmlComponent bg_comp(engine, QUrl("qrc:/background.qml"));
qInfo() << bg_comp.errors();
@@ -247,6 +255,24 @@ load_agl_shell_app(QPlatformNativeInterface *native,
top = create_component(native, &top_comp, screen, &qobj_top);
bottom = create_component(native, &bot_comp, screen, &qobj_bottom);
bg = create_component(native, &bg_comp, screen, &qobj_bg);
+
+ /* engine.rootObjects() works only if we had a load() */
+ StatusBarModel *statusBar = qobj_top->findChild<StatusBarModel *>("statusBar");
+ if (statusBar) {
+ qDebug() << "got statusBar objectname, doing init()";
+ statusBar->init(engine->rootContext());
+ }
+
+ qDebug() << "init normal mode";
+ } else {
+ // this incorporates the panels directly, but in doing so, it
+ // would also need to specify an activation area the same area
+ // in order to void overlapping any new activation window
+ QQmlComponent bg_comp(engine, QUrl("qrc:/background_with_panels.qml"));
+ qInfo() << bg_comp.errors();
+
+ bg = create_component(native, &bg_comp, screen, &qobj_bg);
+ qDebug() << "init embedded panels mode";
}
if (!screen_name)
@@ -263,22 +289,39 @@ load_agl_shell_app(QPlatformNativeInterface *native,
"first screen " << qApp->screens().first()->name();
output = getWlOutput(native, screen);
- /* engine.rootObjects() works only if we had a load() */
- StatusBarModel *statusBar = qobj_top->findChild<StatusBarModel *>("statusBar");
- if (statusBar) {
- qDebug() << "got statusBar objectname, doing init()";
- statusBar->init(engine->rootContext());
- }
-
- agl_shell_set_panel(agl_shell, top, output, AGL_SHELL_EDGE_TOP);
- agl_shell_set_panel(agl_shell, bottom, output, AGL_SHELL_EDGE_BOTTOM);
qDebug() << "Setting homescreen to screen " << screen->name();
-
agl_shell_set_background(agl_shell, bg, output);
+ if (embedded_panels) {
+ int32_t x, y;
+ int32_t width, height;
+ QSize size = screen->size();
+
+ x = 0;
+ y = 216;
+
+ width = size.width();
+ height = size.height() - (2 * y);
+
+ qDebug() << "Using custom rectangle " << width << "x" << height
+ << "+" << x << "x" << y << " for activation";
+ qDebug() << "Panels should be embedded the background surface";
+
+#ifdef AGL_SHELL_SET_ACTIVATE_REGION_SINCE_VERSION
+ agl_shell_set_activate_region(agl_shell, output,
+ x, y, width, height);
+#endif
+
+ } else {
+ agl_shell_set_panel(agl_shell, top, output, AGL_SHELL_EDGE_TOP);
+ agl_shell_set_panel(agl_shell, bottom, output, AGL_SHELL_EDGE_BOTTOM);
+ qDebug() << "Setting regular panels";
+ }
+
/* Delay the ready signal until after Qt has done all of its own setup
* in a.exec() */
QTimer::singleShot(500, [agl_shell](){
+ qDebug() << "sending ready to compositor";
agl_shell_ready(agl_shell);
});
}
@@ -291,6 +334,7 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
const char *screen_name;
bool is_demo_val = false;
+ bool is_embedded_panels = false;
int ret = 0;
struct shell_data shell_data = { nullptr, nullptr, true, false, 0 };
@@ -301,6 +345,10 @@ int main(int argc, char *argv[])
if (is_demo && strcmp(is_demo, "1") == 0)
is_demo_val = true;
+ const char *embedded_panels = getenv("HOMESCREEN_EMBEDDED_PANELS");
+ if (embedded_panels && strcmp(embedded_panels, "1") == 0)
+ is_embedded_panels = true;
+
QCoreApplication::setOrganizationDomain("LinuxFoundation");
QCoreApplication::setOrganizationName("AutomotiveGradeLinux");
QCoreApplication::setApplicationName("HomeScreen");
@@ -358,7 +406,8 @@ int main(int argc, char *argv[])
// Instead of loading main.qml we load one-by-one each of the QMLs,
// divided now between several surfaces: panels, background.
- load_agl_shell_app(native, &engine, shell_data.shell, screen_name, is_demo_val);
+ load_agl_shell_app(native, &engine, shell_data.shell,
+ screen_name, is_demo_val, is_embedded_panels);
return app.exec();
}
diff --git a/homescreen/src/shell.cpp b/homescreen/src/shell.cpp
index ffb4439..b7583c1 100644
--- a/homescreen/src/shell.cpp
+++ b/homescreen/src/shell.cpp
@@ -50,3 +50,11 @@ void Shell::activate_app(QWindow *win, const QString &app_id)
app_id.toStdString().c_str(),
output);
}
+
+void Shell::set_activate_region(struct wl_output *output, int32_t x, int32_t y,
+ int32_t width, int32_t height)
+{
+#ifdef AGL_SHELL_SET_ACTIVATE_REGION_SINCE_VERSION
+ agl_shell_set_activate_region(this->shell.get(), output, x, y, width, height);
+#endif
+}
diff --git a/homescreen/src/shell.h b/homescreen/src/shell.h
index a6e3f7e..51990d8 100644
--- a/homescreen/src/shell.h
+++ b/homescreen/src/shell.h
@@ -41,16 +41,20 @@
class Shell : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- std::shared_ptr<struct agl_shell> shell;
-
- Shell(std::shared_ptr<struct agl_shell> shell, QObject *parent = nullptr) :
- QObject(parent), shell(shell)
- {}
-public slots:
- void activate_app(QWindow *win, const QString &app_id);
+ std::shared_ptr<struct agl_shell> shell;
+
+ Shell(std::shared_ptr<struct agl_shell> shell, QObject *parent = nullptr) :
+ QObject(parent), shell(shell)
+ {}
+ public slots:
+ void activate_app(QWindow *win, const QString &app_id);
+ void set_activate_region(struct wl_output *output, int32_t x, int32_t y,
+ int32_t width, int32_t height);
+private:
+ struct wl_region *m_region = nullptr;
};
#endif // SHELLHANDLER_H