diff options
-rw-r--r-- | README.md | 39 | ||||
-rw-r--r-- | config.tests/ivi_layermanagement_api/ivi_layermanagement_api.cpp | 7 | ||||
-rw-r--r-- | config.tests/ivi_layermanagement_api/ivi_layermanagement_api.pro | 5 | ||||
-rw-r--r-- | interfaces/LICENSE | 54 | ||||
-rw-r--r-- | interfaces/README.md | 11 | ||||
-rw-r--r-- | interfaces/include/windowmanager.hpp | 82 | ||||
-rw-r--r-- | interfaces/interfaces.pri | 18 | ||||
-rw-r--r-- | interfaces/interfaces.pro | 57 | ||||
-rw-r--r-- | interfaces/src/windowmanager.cpp | 116 | ||||
-rw-r--r-- | interfaces/windowmanager.xml | 208 | ||||
-rw-r--r-- | ivi_layermanagement_api.pri | 20 | ||||
-rw-r--r-- | test/commandlinetests.txt | 122 | ||||
-rw-r--r-- | windowmanager.pro | 23 | ||||
-rw-r--r-- | windowmanager/.gitignore | 125 | ||||
-rw-r--r-- | windowmanager/LICENSE | 54 | ||||
-rw-r--r-- | windowmanager/README.md | 11 | ||||
-rw-r--r-- | windowmanager/conf/WindowManager.service | 14 | ||||
-rw-r--r-- | windowmanager/src/main.cpp | 78 | ||||
-rw-r--r-- | windowmanager/src/windowmanager.cpp | 829 | ||||
-rw-r--r-- | windowmanager/src/windowmanager.hpp | 126 | ||||
-rw-r--r-- | windowmanager/windowmanager.pro | 33 |
21 files changed, 2032 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..64b1edf --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +This project contains: + +WindowManager: AGL WindowManager reference implementation + +AGL repo for source code: +https://gerrit.automotivelinux.org/gerrit/gitweb?p=staging%2FHomeScreen.git + +AGL repo for bitbake recipe: +https://gerrit.automotivelinux.org/gerrit/gitweb?p=AGL/meta-agl-demo.git;a=blob;f=recipes-demo-hmi/homescreen/homescreen_git.bb + + + + +Quickstart: + +Instructions for building WindowManager app +------------------------------------------ + +The WindowManager app is part of the +packagegroup-agl-demo-platform +packagegroup. + +This also includes the following apps: +- HomeScreen +- HomeScreenAppFrameworkBinderAGL +- InputEventManager +- SampleAppTimeDate +- SampleHomeScreenInterfaceApp + +And the library +- libhomescreen + + +To build all the above, follow the instrucions on the AGL +documentation website: +http://docs.automotivelinux.org/docs/getting_started/en/dev/reference/source-code.html#features-supported-by-aglsetup + +Please activate the "agl-demo" feature when running the aglsetup script: +http://docs.automotivelinux.org/docs/getting_started/en/dev/reference/source-code.html#features-supported-by-aglsetup diff --git a/config.tests/ivi_layermanagement_api/ivi_layermanagement_api.cpp b/config.tests/ivi_layermanagement_api/ivi_layermanagement_api.cpp new file mode 100644 index 0000000..579abdd --- /dev/null +++ b/config.tests/ivi_layermanagement_api/ivi_layermanagement_api.cpp @@ -0,0 +1,7 @@ +#include <ilm/ilm_control.h> + +int main(int argc,char **argv) +{ + return 0; +} + diff --git a/config.tests/ivi_layermanagement_api/ivi_layermanagement_api.pro b/config.tests/ivi_layermanagement_api/ivi_layermanagement_api.pro new file mode 100644 index 0000000..d230384 --- /dev/null +++ b/config.tests/ivi_layermanagement_api/ivi_layermanagement_api.pro @@ -0,0 +1,5 @@ +SOURCES = ivi_layermanagement_api.cpp + +CONFIG -= qt dylib + +LIBS += -lilmControl -lilmCommon diff --git a/interfaces/LICENSE b/interfaces/LICENSE new file mode 100644 index 0000000..31c692a --- /dev/null +++ b/interfaces/LICENSE @@ -0,0 +1,54 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + You must give any other recipients of the Work or Derivative Works a copy of this License; and + You must cause any modified files to carry prominent notices stating that You changed the files; and + You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/interfaces/README.md b/interfaces/README.md new file mode 100644 index 0000000..15dfaa9 --- /dev/null +++ b/interfaces/README.md @@ -0,0 +1,11 @@ +AGL Home Screen reference implementation +This lib provides the needed D-Bus interfaces + +Build with QtCreator 3.0.1 + +AGL repo for source code: +https://gerrit.automotivelinux.org/gerrit/#/admin/projects/staging/HomeScreen + +AGL repo for bitbake recipe: +https://gerrit.automotivelinux.org/gerrit/#/admin/projects/AGL/meta-agl-demo/recipes-demo-hmi/HomeScreen/HomeScreen_?.bb + diff --git a/interfaces/include/windowmanager.hpp b/interfaces/include/windowmanager.hpp new file mode 100644 index 0000000..dd268dd --- /dev/null +++ b/interfaces/include/windowmanager.hpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINDOWMANAGER_H +#define WINDOWMANAGER_H + +#include <QtDBus> + +#define WINDOWMANAGER_NO_ERROR 0 +#define WINDOWMANAGER_ERROR_ID_ALREADY_DEFINED 1 +#define WINDOWMANAGER_ERROR_NAME_ALREADY_DEFINED 2 +#define WINDOWMANAGER_ERROR_ID_NOT_FOUND 3 +#define WINDOWMANAGER_ERROR_NAME_NOT_FOUND 4 +#define WINDOWMANAGER_ERROR_ID_IN_USE 5 + +class SimplePoint +{ +public: + SimplePoint(); + virtual ~SimplePoint(); + + int x; + int y; + + friend QDBusArgument &operator <<(QDBusArgument &argument, const SimplePoint &mSimplePoint); + friend const QDBusArgument &operator >>(const QDBusArgument &argument, SimplePoint &mSimplePoint); +}; + + +class LayoutArea +{ +public: + LayoutArea(); + virtual ~LayoutArea(); + + int x; + int y; + int width; + int height; + + friend QDBusArgument &operator <<(QDBusArgument &argument, const LayoutArea &mLayoutArea); + friend const QDBusArgument &operator >>(const QDBusArgument &argument, LayoutArea &mLayoutArea); +}; + +class Layout +{ +public: + Layout(); + Layout(int layoutId, const QString &layoutName, const QList<LayoutArea> &surfaceAreas); + virtual ~Layout(); + + int id; + QString name; + QList<LayoutArea> layoutAreas; + + friend QDBusArgument &operator <<(QDBusArgument &argument, const Layout &mLayout); + friend const QDBusArgument &operator >>(const QDBusArgument &argument, Layout &mLayout); +}; + +Q_DECLARE_METATYPE(SimplePoint) +Q_DECLARE_METATYPE(QList<SimplePoint>) + +Q_DECLARE_METATYPE(LayoutArea) +Q_DECLARE_METATYPE(QList<LayoutArea>) + +Q_DECLARE_METATYPE(Layout) +Q_DECLARE_METATYPE(QList<Layout>) + +#endif // WINDOWMANAGER_H diff --git a/interfaces/interfaces.pri b/interfaces/interfaces.pri new file mode 100644 index 0000000..07b9e6a --- /dev/null +++ b/interfaces/interfaces.pri @@ -0,0 +1,18 @@ +# Copyright (C) 2016 The Qt Company Ltd. +# Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +INCLUDEPATH += $$PWD $$OUT_PWD/../interfaces/ + +LIBS += -L$$OUT_PWD/../interfaces/ -linterfaces diff --git a/interfaces/interfaces.pro b/interfaces/interfaces.pro new file mode 100644 index 0000000..60c2f6e --- /dev/null +++ b/interfaces/interfaces.pro @@ -0,0 +1,57 @@ +# Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +TEMPLATE = lib +TARGET = interfaces +QT = dbus +CONFIG += staticlib + +HEADERS += \ + include/windowmanager.hpp + +SOURCES += \ + src/windowmanager.cpp + +XMLSOURCES = \ + windowmanager.xml + +gen_adaptor_cpp.input = XMLSOURCES +gen_adaptor_cpp.commands = \ + qdbusxml2cpp -i include/${QMAKE_FILE_IN_BASE}.hpp -m -a ${QMAKE_FILE_IN_BASE}_adaptor ${QMAKE_FILE_IN}; \ + moc $$OUT_PWD/${QMAKE_FILE_IN_BASE}_adaptor.h -o $$OUT_PWD/${QMAKE_FILE_IN_BASE}_adaptor.moc +gen_adaptor_cpp.output = ${QMAKE_FILE_IN_BASE}_adaptor.cpp +gen_adaptor_cpp.variable_out = SOURCES +gen_adaptor_cpp.clean = ${QMAKE_FILE_IN_BASE}_adaptor.cpp + +gen_proxy_cpp.input = XMLSOURCES +gen_proxy_cpp.commands = \ + qdbusxml2cpp -i include/${QMAKE_FILE_IN_BASE}.hpp -m -p ${QMAKE_FILE_IN_BASE}_proxy ${QMAKE_FILE_IN}; \ + moc $$OUT_PWD/${QMAKE_FILE_IN_BASE}_proxy.h -o $$OUT_PWD/${QMAKE_FILE_IN_BASE}_proxy.moc +gen_proxy_cpp.output = ${QMAKE_FILE_IN_BASE}_proxy.cpp +gen_proxy_cpp.variable_out = SOURCES +gen_proxy_cpp.clean = ${QMAKE_FILE_IN_BASE}_proxy.cpp + +gen_adaptor_h.input = XMLSOURCES +gen_adaptor_h.commands = @echo Fake making the header for ${QMAKE_FILE_IN} +gen_adaptor_h.depends = ${QMAKE_FILE_IN_BASE}_adaptor.cpp +gen_adaptor_h.output = ${QMAKE_FILE_IN_BASE}_adaptor.h +gen_adaptor_h.clean = ${QMAKE_FILE_IN_BASE}_adaptor.h + +gen_proxy_h.input = XMLSOURCES +gen_proxy_h.commands = @echo Fake making the header for ${QMAKE_FILE_IN} +gen_proxy_h.depends = ${QMAKE_FILE_IN_BASE}_proxy.cpp +gen_proxy_h.output = ${QMAKE_FILE_IN_BASE}_proxy.h +gen_proxy_h.clean = ${QMAKE_FILE_IN_BASE}_proxy.h + +QMAKE_EXTRA_COMPILERS += gen_adaptor_cpp gen_proxy_cpp gen_adaptor_h gen_proxy_h diff --git a/interfaces/src/windowmanager.cpp b/interfaces/src/windowmanager.cpp new file mode 100644 index 0000000..0811a57 --- /dev/null +++ b/interfaces/src/windowmanager.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "include/windowmanager.hpp" + +SimplePoint::SimplePoint() +{ +} + +SimplePoint::~SimplePoint() +{ +} + + +LayoutArea::LayoutArea() +{ +} + +LayoutArea::~LayoutArea() +{ +} + + +Layout::Layout(): + id(-1), + name("N/A"), + layoutAreas() +{ +} + +Layout::Layout(int layoutId, const QString &layoutName, const QList<LayoutArea> &surfaceAreas): + id(layoutId), + name(layoutName), + layoutAreas(surfaceAreas) +{ +} + +Layout::~Layout() +{ +} + +QDBusArgument &operator <<(QDBusArgument &argument, const SimplePoint &mSimplePoint) +{ + argument.beginStructure(); + argument << mSimplePoint.x; + argument << mSimplePoint.y; + argument.endStructure(); + + return argument; +} + +const QDBusArgument &operator >>(const QDBusArgument &argument, SimplePoint &mSimplePoint) +{ + argument.beginStructure(); + argument >> mSimplePoint.x; + argument >> mSimplePoint.y; + argument.endStructure(); + return argument; +} + +QDBusArgument &operator <<(QDBusArgument &argument, const LayoutArea &mLayoutArea) +{ + argument.beginStructure(); + argument << mLayoutArea.x; + argument << mLayoutArea.y; + argument << mLayoutArea.width; + argument << mLayoutArea.height; + argument.endStructure(); + + return argument; +} + +const QDBusArgument &operator >>(const QDBusArgument &argument, LayoutArea &mLayoutArea) +{ + argument.beginStructure(); + argument >> mLayoutArea.x; + argument >> mLayoutArea.y; + argument >> mLayoutArea.width; + argument >> mLayoutArea.height; + argument.endStructure(); + return argument; +} + +QDBusArgument &operator <<(QDBusArgument &argument, const Layout &mLayout) +{ + argument.beginStructure(); + argument << mLayout.id; + argument << mLayout.name; + argument << mLayout.layoutAreas; + argument.endStructure(); + + return argument; +} + +const QDBusArgument &operator >>(const QDBusArgument &argument, Layout &mLayout) +{ + argument.beginStructure(); + argument >> mLayout.id; + argument >> mLayout.name; + argument >> mLayout.layoutAreas; + argument.endStructure(); + return argument; +} diff --git a/interfaces/windowmanager.xml b/interfaces/windowmanager.xml new file mode 100644 index 0000000..e3c6df3 --- /dev/null +++ b/interfaces/windowmanager.xml @@ -0,0 +1,208 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<!-- Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. --> +<node> + <!-- + org.agl.windowmanager: + @short_description: A Layout-based interface for the WindowManager. + + A Layout defines a list of surfaces areas. + --> + <interface name="org.agl.windowmanager"> + <!-- + addLayout: + @layoutId: A unique ID that represents this layout. If the ID is already in use WINDOWMANAGER_ERROR_ID_ALREADY_DEFINED will be returned. + @layoutName: A user readable string for the layout. If the string is already in use WINDOWMANAGER_ERROR_NAME_ALREADY_DEFINED will be returned. + @surfaceAreas: A list of surface areas. + @error: WINDOWMANAGER_NO_ERROR or the first error that occurred. + + Add a layout definition to the WindowManayer layout database. + The layout database is temoprary and not stored persistently. It has to be recreated by the client after + a WindowManager restart. + --> + <method name="addLayout"> + <arg name="layoutId" type="i" direction="in"/> + <arg name="layoutName" type="s" direction="in"/> + <arg name="surfaceAreas" type="a(iiii)" direction="in"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QList<LayoutArea>"/> + <arg name="error" type="i" direction="out"/> + </method> + + <!-- + deleteLayoutById: + @layoutId: The ID of the layout to delete. + @error: WINDOWMANAGER_NO_ERROR or the first error that occurred. + + Deletes the layout with the given ID. This cannot be the current active layout! + --> + <method name="deleteLayoutById"> + <arg name="layoutId" type="i" direction="in"/> + <arg name="error" type="i" direction="out"/> + </method> + + <!-- + setLayoutById: + @layoutId: The ID of the layout to activate. + @error: WINDOWMANAGER_NO_ERROR or the first error that occurred. + + Switch to the layout with the given ID. + --> + <method name="setLayoutById"> + <arg name="layoutId" type="i" direction="in"/> + <arg name="error" type="i" direction="out"/> + </method> + <!-- + setLayoutByName: + @layoutName: The name of the layout to activate. + @error: WINDOWMANAGER_NO_ERROR or the first error that occurred. + + Switch to the layout with the given name. + --> + <method name="setLayoutByName"> + <arg name="layoutName" type="s" direction="in"/> + <arg name="error" type="i" direction="out"/> + </method> + + <!-- + getLayoutName: + @layoutId: The ID of the requested layout name. + @layoutName: The name of the layout with the given ID. + + Request the name of the layout with the given ID. This does not set or activate a layout. + It is just returning the name of the given layout. + --> + <method name="getLayoutName"> + <arg name="layoutId" type="i" direction="in"/> + <arg name="layoutName" type="s" direction="out"/> + </method> + + <!-- + layout: + The current active layout with all its information. + --> + <property> + <arg name="layout" type="(isa(iiii))" access="read"/> + <annotation name="org.qtproject.QtDBus.QtTypeName" value="Layout"/> + </property> + <!-- + layoutId: + The current active layout id. This property is redundant, since its info is already available + in the property layout. But this property is more lightweight. + --> + <property name="layoutId" type="i" access="read"/> + <!-- + layoutName: + The name of the current active layout. This property is redundant, since its info is already available + in the property layout. But this property is more lightweight. + --> + <property name="layoutName" type="s" access="read"/> + + <!-- + getAllLayouts: + @layouts: A list of all layouts. + + Returns a list of all layouts that were added to the WindowManager. + --> + <method name="getAllLayouts"> + <arg name="layoutIds" type="a(isa(iiii))" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList<Layout>"/> + </method> + + <!-- + getAvailableLayouts: + @numberOfAppSurfaces: The ID of the requested layout name. + @layoutIds: A list of layouts that offer the exact requested ammount of surface render areas. + + Returns a list of layouts that offer the exact requested ammount of surface render areas. + If the list is empty, no layout fits the exact ammount. + --> + + <method name="getAvailableLayouts"> + <arg name="numberOfAppSurfaces" type="i" direction="in"/> + <arg name="layoutIds" type="ai" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList<int>"/> + </method> + + <!-- + setSurfaceToLayoutArea: + @surfaceId: The ID of the surface that shall be positioned. + @layoutAreaId: The ID of the layout area where the surface shall be rendered. + @error: WINDOWMANAGER_NO_ERROR or the first error that occurred. + + The surface will be scaled to the size of the layout area. + The surface will be made visible with this call. + --> + <method name="setSurfaceToLayoutArea"> + <arg name="surfaceId" type="i" direction="in"/> + <arg name="layoutAreaId" type="i" direction="in"/> + <arg name="error" type="i" direction="out"/> + </method> + + <!-- + getAvailableSurfaces: + @surfaceIds: A list of all known surfaceIds except for the surfaces created by the Home Screen app. + + If no surfaces are available, the returned list is empty. + --> + <method name="getAvailableSurfaces"> + <arg name="surfaceIds" type="a(i)" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList<int>"/> + </method> + + <!-- + surfaceVisibilityChanged: + @surfaceId: The surface that changed. + @visible: True, if the surface is visible. + + This is emitted when the visible property of the surfaces changes. + --> + <signal name="surfaceVisibilityChanged"> + <arg name="surfaceId" type="i"/> + <arg name="visible" type="b"/> + </signal> + + <!-- + showLayer: + @layer: The ID of the layer to show. POPUP=0, HOMESCREEN_OVERLAY=1, APPS=2, HOMESCREEN=3 + @pid: The PID of the app to show. (used only when layer is APPS=2) + + Show complete layers. + By default, all layers are shown. + --> + <method name="showLayer"> + <arg name="layer" type="i" direction="in"/> + <arg name="pid" type="i" direction="in"/> + </method> + <!-- + showAppLayer: + @pid: The PID of the app to show. + + Show layer for application . + --> + <method name="showAppLayer"> + <arg name="pid" type="i" direction="in"/> + </method> + <!-- + hideLayer: + @layer: The ID of the layer to hide. POPUP=0, HOMESCREEN_OVERLAY=1, APPS=2, HOMESCREEN=3 + + Hide complete layers. + By default, all layers are shown. + --> + <method name="hideLayer"> + <arg name="layer" type="i" direction="in"/> + </method> + </interface> +</node> + diff --git a/ivi_layermanagement_api.pri b/ivi_layermanagement_api.pri new file mode 100644 index 0000000..ad4513c --- /dev/null +++ b/ivi_layermanagement_api.pri @@ -0,0 +1,20 @@ +# Copyright (C) 2016 The Qt Company Ltd. +# Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +config_ivi_layermanagement_api { + DEFINES += HAVE_IVI_LAYERMANAGEMENT_API +} else { + message(HAVE_IVI_LAYERMANAGEMENT_API not available) +} diff --git a/test/commandlinetests.txt b/test/commandlinetests.txt new file mode 100644 index 0000000..4571802 --- /dev/null +++ b/test/commandlinetests.txt @@ -0,0 +1,122 @@ +Command line tests + +Precondition for all test is, that the D-Bus session is launched: +$export `dbus-launch` + +--------------------------------------------------------------------------------------------------------------------- +Interface: +org.agl.windowmanager + + +dbus-send --session --type=method_call --print-reply --dest=org.agl.windowmanager /windowmanager org.freedesktop.DBus.Properties.GetAll string:"org.agl.windowmanager" + +dbus-send --session --type=method_call --print-reply --dest=org.agl.windowmanager /windowmanager org.freedesktop.DBus.Properties.Get string:"org.agl.windowmanager" string:"homeScreenPid" + +dbus-send --session --type=method_call --print-reply --dest=org.agl.windowmanager /windowmanager org.freedesktop.DBus.Properties.Set string:"org.agl.windowmanager" string:"homeScreenPid" variant:int32:1 + + +Method: + <method name="addLayout"> + <arg name="layoutId" type="i" direction="in"/> + <arg name="layoutName" type="s" direction="in"/> + <arg name="surfaceAreas" type="a(iiii)" direction="in"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QList<SimpleRect>"/> + <arg name="error" type="i" direction="out"/> + </method> + +Preconditions: +- WindowManager app is running + +Test: +it is not possible to send isa(iiii) via the dbus-send tool. + +Method: + <method name="getAvailableLayouts"> + <arg name="numberOfAppSurfaces" type="i" direction="in"/> + <arg name="layoutIds" type="ai" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList<int>"/> + </method> + +Preconditions: +- HomeScreen app is running +- WindowManager app is running + +Test: +$dbus-send --session --type=method_call --print-reply --dest=org.agl.windowmanager /windowmanager org.agl.windowmanager.getAvailableLayouts int32:1 + + + +Method: + <method name="setLayoutById"> + <arg name="layoutId" type="i" direction="in"/> + </method> +Preconditions: +- HomeScreen app is running +- WindowManager app is running + +Test: +$dbus-send --session --type=method_call --print-reply --dest=org.agl.windowmanager /windowmanager org.agl.windowmanager.setLayoutById int32:1 + +Method: + <method name="setLayoutByName"> + <arg name="layoutName" type="s" direction="in"/> + </method> + +Preconditions: +- HomeScreen app is running +- WindowManager app is running + +Test: +$dbus-send --session --type=method_call --print-reply --dest=org.agl.windowmanager /windowmanager org.agl.windowmanager.setLayoutByName string:"name" + +Method: + <method name="getLayout"> + <arg name="layoutId" type="i" direction="out"/> + </method> + +Preconditions: +- HomeScreen app is running +- WindowManager app is running + +Test: +$dbus-send --session --type=method_call --print-reply --dest=org.agl.windowmanager /windowmanager org.agl.windowmanager.getLayout + +Method: + <method name="setPidToLayoutArea"> + <arg name="pid" type="i" direction="in"/> + <arg name="layoutAreaId" type="i" direction="in"/> + </method> + +Preconditions: +- HomeScreen app is running +- WindowManager app is running + +Test: +$dbus-send --session --type=method_call --print-reply --dest=org.agl.windowmanager /windowmanager org.agl.windowmanager.setPidToLayoutArea int32:1123 int32:1 + +Method: + <method name="getAvailableSurfaces"> + <arg name="surfacesAndPids" type="a(ii)" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList<SimplePoint>"/> + </method> + +Preconditions: +- HomeScreen app is running +- WindowManager app is running + +Test: +$dbus-send --session --type=method_call --print-reply --dest=org.agl.windowmanager /windowmanager org.agl.windowmanager.getAvailableSurfaces + +Method: + <method name="getLayoutName"> + <arg name="layoutId" type="i" direction="in"/> + <arg name="layoutName" type="s" direction="out"/> + </method> + +Preconditions: +- HomeScreen app is running +- WindowManager app is running + +Test: +$dbus-send --session --type=method_call --print-reply --dest=org.agl.windowmanager /windowmanager org.agl.windowmanager.getLayoutName int32:1 + diff --git a/windowmanager.pro b/windowmanager.pro new file mode 100644 index 0000000..42153ba --- /dev/null +++ b/windowmanager.pro @@ -0,0 +1,23 @@ +# Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +TEMPLATE = subdirs + +load(configure) +qtCompileTest(ivi_layermanagement_api) + +SUBDIRS = interfaces \ + windowmanager + +windowmanager.depends = interfaces diff --git a/windowmanager/.gitignore b/windowmanager/.gitignore new file mode 100644 index 0000000..051f2d5 --- /dev/null +++ b/windowmanager/.gitignore @@ -0,0 +1,125 @@ +# manually added: +.DS_Store + +# Created by https://www.gitignore.io/api/linux,qt,c,c++ + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + + +### Qt ### +# C++ objects and libs + +*.slo +*.lo +*.o +*.a +*.la +*.lai +*.so +*.dll +*.dylib + +# Qt-es + +/.qmake.cache +/.qmake.stash +*.pro.user +*.pro.user.* +*.qbs.user +*.qbs.user.* +*.moc +moc_*.cpp +qrc_*.cpp +ui_*.h +Makefile* +*build-* + +# QtCreator + +*.autosave + +# QtCtreator Qml +*.qmlproject.user +*.qmlproject.user.* + +# QtCtreator CMake +CMakeLists.txt.user + + + +### C ### +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ + + +### C++ ### +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + + diff --git a/windowmanager/LICENSE b/windowmanager/LICENSE new file mode 100644 index 0000000..31c692a --- /dev/null +++ b/windowmanager/LICENSE @@ -0,0 +1,54 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + You must give any other recipients of the Work or Derivative Works a copy of this License; and + You must cause any modified files to carry prominent notices stating that You changed the files; and + You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/windowmanager/README.md b/windowmanager/README.md new file mode 100644 index 0000000..a31c8e6 --- /dev/null +++ b/windowmanager/README.md @@ -0,0 +1,11 @@ +AGL WindowManager Sample App + + +Build with QtCreator 3.0.1 + +AGL repo for source code: +https://gerrit.automotivelinux.org/gerrit/#/admin/projects/staging/HomeScreen + +AGL repo for bitbake recipe: +https://gerrit.automotivelinux.org/gerrit/#/admin/projects/AGL/meta-agl-demo/recipes-demo-hmi/HomeScreen/HomeScreen_?.bb + diff --git a/windowmanager/conf/WindowManager.service b/windowmanager/conf/WindowManager.service new file mode 100644 index 0000000..7cb00fb --- /dev/null +++ b/windowmanager/conf/WindowManager.service @@ -0,0 +1,14 @@ +[Unit] +Description=AGL Window Manager +Requires=dbus.service + +[Service] +User=root +Type=dbus +BusName=org.agl.windowmanager +ExecStart=/usr/AGL/homescreen/WindowManager +Restart=on-failure +RestartSec=1 + +[Install] +WantedBy=default.target diff --git a/windowmanager/src/main.cpp b/windowmanager/src/main.cpp new file mode 100644 index 0000000..5526c92 --- /dev/null +++ b/windowmanager/src/main.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <QCoreApplication> +#include <QCommandLineParser> +#include "windowmanager.hpp" + + +void noOutput(QtMsgType, const QMessageLogContext &, const QString &) +{ +} + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + QCoreApplication::setOrganizationDomain("LinuxFoundation"); + QCoreApplication::setOrganizationName("AutomotiveGradeLinux"); + QCoreApplication::setApplicationName("WindowManager"); + QCoreApplication::setApplicationVersion("0.7.0"); + + QCommandLineParser parser; + parser.setApplicationDescription("AGL WindowManager - see wwww... for more details"); + parser.addHelpOption(); + parser.addVersionOption(); + QCommandLineOption quietOption(QStringList() << "q" << "quiet", + QCoreApplication::translate("main", "Be quiet. No outputs.")); + parser.addOption(quietOption); + QCommandLineOption displayOption(QStringList() << "d" << "display-id", + QCoreApplication::translate("main", "The display with this <id> to manage. Default=0"), + QCoreApplication::translate("main", "id")); + parser.addOption(displayOption); + parser.process(a); + + if (parser.isSet(quietOption)) + { + qInstallMessageHandler(noOutput); + } + + int displayId = 0; + if (parser.isSet(displayOption)) + { + displayId = parser.value(displayOption).toInt(); + } + qDebug() << "Using display" << displayId; + + qDBusRegisterMetaType<SimplePoint>(); + qDBusRegisterMetaType<QList<SimplePoint> >(); + qDBusRegisterMetaType<LayoutArea>(); + qDBusRegisterMetaType<QList<LayoutArea> >(); + qDBusRegisterMetaType<Layout>(); + qDBusRegisterMetaType<QList<Layout> >(); + + WindowManager *windowManager = new WindowManager(displayId); + windowManager->start(); + +#ifdef __arm__ + qDebug("Running on ARM architecture"); +#endif +#ifdef __i386__ + qDebug("Running on x86 architecture"); +#endif + + return a.exec(); +} diff --git a/windowmanager/src/windowmanager.cpp b/windowmanager/src/windowmanager.cpp new file mode 100644 index 0000000..e7802ca --- /dev/null +++ b/windowmanager/src/windowmanager.cpp @@ -0,0 +1,829 @@ +/* + * Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "windowmanager.hpp" + + +////////////////////////////////////////// +// THIS IS STILL UNDER HEAVY DEVELOPMENT! +// DO NOT JUDGE THE SOURCE CODE :) +////////////////////////////////////////// + +// three layers will be defined. The HomeScreen will be placed +// full screen in the background. +// On top all applications in one layer. +// On top of that, the popup layer. +#define WINDOWMANAGER_LAYER_POPUP 100 +#define WINDOWMANAGER_LAYER_HOMESCREEN_OVERLAY 101 +#define WINDOWMANAGER_LAYER_APPLICATIONS 102 +#define WINDOWMANAGER_LAYER_HOMESCREEN 103 + +#define WINDOWMANAGER_LAYER_NUM 4 + +#define WINDOWMANAGER_SURFACE_ID_SHIFT 22 + +// the HomeScreen app has to have the surface id 4194304 +#define WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID (1 << WINDOWMANAGER_SURFACE_ID_SHIFT) + +// Quick hack for scaling layer to fit non-FHD(1920x1080) screen +// * source rect of layer should be 1920x1080 +// * destination rect of layer should fit physical display resolution +// * source rect of surface shoud be based on 1920x1080 +// * destination rect of surface should be based on 1920x1080 +#define WINDOWMANAGER_HOMESCREEN_WIDTH 1080 +#define WINDOWMANAGER_HOMESCREEN_HEIGHT 1920 + +void* WindowManager::myThis = 0; + +WindowManager::WindowManager(int displayId, QObject *parent) : + QObject(parent), + m_layouts(), + mp_layoutAreaToSurfaceIdAssignment(0), + m_currentLayout(-1), + m_screenId(displayId), + m_screenWidth(0), + m_screenHeight(0) +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + , + m_appSurfaces(), + m_appLayers(), + m_pending_to_show(-1) +#endif +{ +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + m_showLayers = new t_ilm_layer[WINDOWMANAGER_LAYER_NUM]; + + m_showLayers[0] = 0; /* POPUP is not shown by default */ + m_showLayers[1] = 0; /* HOMESCREEN_OVERLAY is not shown by default */ + m_showLayers[2] = 0; /* APPLICATIONS is not shown by default */ + m_showLayers[3] = WINDOWMANAGER_LAYER_HOMESCREEN; /* HOMESCREEN is shwon by default */ + +#endif + qDebug("-=[WindowManager]=-"); +} + +void WindowManager::start() +{ + qDebug("-=[start]=-"); + mp_layoutAreaToSurfaceIdAssignment = new QMap<int, unsigned int>; +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + ilmErrorTypes err; + + err = ilm_init(); + qDebug("ilm_init = %d", err); + if(ILM_SUCCESS != err) + { + qDebug("failed! Exiting!"); + exit(-1); + } + + myThis = this; + + ilm_getScreenResolution(m_screenId, &m_screenWidth, &m_screenHeight); + + createNewLayer(WINDOWMANAGER_LAYER_POPUP); + createNewLayer(WINDOWMANAGER_LAYER_HOMESCREEN_OVERLAY); + createNewLayer(WINDOWMANAGER_LAYER_HOMESCREEN); + + ilm_registerNotification(WindowManager::notificationFunc_static, this); +#endif + + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerObject("/windowmanager", this); + dbus.registerService("org.agl.windowmanager"); + + // publish windowmanager interface + mp_windowManagerAdaptor = new WindowmanagerAdaptor((QObject*)this); +} + +WindowManager::~WindowManager() +{ + qDebug("-=[~WindowManager]=-"); + delete mp_windowManagerAdaptor; +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + ilm_destroy(); +#endif + delete mp_layoutAreaToSurfaceIdAssignment; +} + +#ifdef HAVE_IVI_LAYERMANAGEMENT_API +int WindowManager::getLayerRenderOrder(t_ilm_layer id_array[]) +{ + int i, j; + + for (i = WINDOWMANAGER_LAYER_NUM - 1, j = 0; i >= 0; i--) { + if (m_showLayers[i] != 0) { + id_array[j++] = m_showLayers[i]; + } + } + + return j; +} +#endif + +void WindowManager::dumpScene() +{ + qDebug("\n"); + qDebug("current layout : %d", m_currentLayout); + qDebug("available layouts: %d", m_layouts.size()); + QList<Layout>::const_iterator i = m_layouts.begin(); + + while (i != m_layouts.constEnd()) + { + qDebug("--[id: %d]--[%s]--", i->id, i->name.toStdString().c_str()); + qDebug(" %d surface areas", i->layoutAreas.size()); + for (int j = 0; j < i->layoutAreas.size(); ++j) + { + qDebug(" -area %d", j); + qDebug(" -x : %d", i->layoutAreas.at(j).x); + qDebug(" -y : %d", i->layoutAreas.at(j).y); + qDebug(" -width : %d", i->layoutAreas.at(j).width); + qDebug(" -height: %d", i->layoutAreas.at(j).height); + } + + ++i; + } +} + +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + +void WindowManager::createNewLayer(int layerId) +{ + qDebug("-=[createNewLayer]=-"); + qDebug(" layerId %d", layerId); + + t_ilm_layer newLayerId = layerId; + ilm_layerCreateWithDimension(&newLayerId, + WINDOWMANAGER_HOMESCREEN_WIDTH, + WINDOWMANAGER_HOMESCREEN_HEIGHT); + ilm_commitChanges(); + ilm_layerSetSourceRectangle(newLayerId, + 0, + 0, + WINDOWMANAGER_HOMESCREEN_WIDTH, + WINDOWMANAGER_HOMESCREEN_HEIGHT); + ilm_layerSetDestinationRectangle(newLayerId, + 0, + 0, + m_screenWidth, + m_screenHeight); + ilm_commitChanges(); + ilm_layerSetOpacity(newLayerId, 1.0); + ilm_layerSetVisibility(newLayerId, ILM_TRUE); + ilm_commitChanges(); +} + +t_ilm_layer WindowManager::getAppLayerID(pid_t pid) +{ + t_ilm_layer layer_id; + +// layer_id = pid + (WINDOWMANAGER_LAYER_APPLICATIONS << WINDOWMANAGER_LAYER_ID_SHIFT); + layer_id = pid + (WINDOWMANAGER_LAYER_APPLICATIONS * 100000); /* for debug */ + + return layer_id; +} + +void WindowManager::addSurface(t_ilm_surface surfaceId) +{ + struct ilmSurfaceProperties surfaceProperties; + pid_t pid; + + ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties); + pid = surfaceProperties.creatorPid; + + QMap<pid_t, t_ilm_surface>::const_iterator i = m_appSurfaces.find(pid); + if (i != m_appSurfaces.end() && i.value() == 0) { + /* Only the 1st surface is handled by Window Manager */ + qDebug("This surface (%d) is 1st one for app (%d)", surfaceId, pid); + /* update surface id */ + m_appSurfaces.insert(pid, surfaceId); + + /* this surface should be handled by WindowManager */ + ilm_surfaceAddNotification(surfaceId, surfaceCallbackFunction_static); + ilm_commitChanges(); + } +} + +t_ilm_layer WindowManager::addSurfaceToAppLayer(pid_t pid, int surfaceId) +{ + struct ilmSurfaceProperties surfaceProperties; + t_ilm_layer layer_id; + int found = 0; + + qDebug("-=[addSurfaceToAppLayer]=-"); + qDebug(" surfaceId %d", surfaceId); + + if (pid < 0) + return 0; + + QMap<pid_t, t_ilm_layer>::const_iterator i = m_appLayers.find(pid); + if (i == m_appLayers.end()) { + qDebug("No layer found, create new for app(pid=%d)", pid); + + /* not found, create new one */ + layer_id = getAppLayerID(pid); + + createNewLayer(layer_id); + m_appLayers.insert(pid, layer_id); + } else { + layer_id = i.value(); + } + + return layer_id; +} + +void WindowManager::addSurfaceToLayer(int surfaceId, int layerId) +{ + qDebug("-=[addSurfaceToLayer]=-"); + qDebug(" surfaceId %d", surfaceId); + qDebug(" layerId %d", layerId); + + if (layerId == WINDOWMANAGER_LAYER_HOMESCREEN) + { + ilm_layerAddSurface(layerId, surfaceId); + } + else if (layerId == WINDOWMANAGER_LAYER_HOMESCREEN_OVERLAY) + { + struct ilmSurfaceProperties surfaceProperties; + ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties); + + //ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight); + //ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight); + //ilm_surfaceSetOpacity(surfaceId, 0.5); + //ilm_surfaceSetVisibility(surfaceId, ILM_TRUE); + + ilm_layerAddSurface(layerId, surfaceId); + } + else if (layerId == WINDOWMANAGER_LAYER_POPUP) + { + struct ilmSurfaceProperties surfaceProperties; + ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties); + + //ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight); + //ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight); + //ilm_surfaceSetOpacity(surfaceId, 0.0); + //ilm_surfaceSetVisibility(surfaceId, ILM_FALSE); + + ilm_layerAddSurface(layerId, surfaceId); + } else { + return; + } + + ilm_commitChanges(); +} + +void WindowManager::configureHomeScreenMainSurface(t_ilm_surface surface, t_ilm_int width, t_ilm_int height) +{ + // homescreen app always fullscreen in the back + ilm_surfaceSetDestinationRectangle(surface, 0, 0, + WINDOWMANAGER_HOMESCREEN_WIDTH, + WINDOWMANAGER_HOMESCREEN_HEIGHT); + ilm_surfaceSetSourceRectangle(surface, 0, 0, width, height); + ilm_surfaceSetOpacity(surface, 1.0); + ilm_surfaceSetVisibility(surface, ILM_TRUE); + + ilm_commitChanges(); +} + +void WindowManager::configureAppSurface(pid_t pid, t_ilm_surface surface, t_ilm_int width, t_ilm_int height) +{ + /* Dirty hack! cut & paste from HomeScreen/src/layouthandler.cpp */ + const int SCREEN_WIDTH = 1080; + const int SCREEN_HEIGHT = 1920; + + const int TOPAREA_HEIGHT = 218; + const int TOPAREA_WIDTH = SCREEN_WIDTH; + const int TOPAREA_X = 0; + const int TOPAREA_Y = 0; + const int MEDIAAREA_HEIGHT = 215; + const int MEDIAAREA_WIDTH = SCREEN_WIDTH; + const int MEDIAAREA_X = 0; + const int MEDIAAREA_Y = SCREEN_HEIGHT - MEDIAAREA_HEIGHT; + + ilm_surfaceSetDestinationRectangle(surface, + 0, + TOPAREA_HEIGHT, + SCREEN_WIDTH, + SCREEN_HEIGHT - TOPAREA_HEIGHT - MEDIAAREA_HEIGHT); + ilm_surfaceSetSourceRectangle(surface, 0, 0, width, height); + ilm_surfaceSetOpacity(surface, 1.0); + ilm_surfaceSetVisibility(surface, ILM_TRUE); /* Hack to avoid blank screen when switch apps */ + + ilm_commitChanges(); +} +#endif + +void WindowManager::updateScreen() +{ + qDebug("-=[updateScreen]=-"); + +#if 0 +//#ifdef HAVE_IVI_LAYERMANAGEMENT_API + if (-1 != m_currentLayout) + { + // hide all surfaces + for (int i = 0; i < m_appSurfaces.size(); ++i) + { + ilm_layerRemoveSurface(WINDOWMANAGER_LAYER_APPLICATIONS, m_appSurfaces.at(i)); + //ilm_surfaceSetVisibility(m_appSurfaces.at(i), ILM_FALSE); + //ilm_surfaceSetOpacity(m_appSurfaces.at(i), 0.0); + ilm_commitChanges(); + } + + // find the current used layout + QList<Layout>::const_iterator ci = m_layouts.begin(); + + Layout currentLayout; + while (ci != m_layouts.constEnd()) + { + if (ci->id == m_currentLayout) + { + currentLayout = *ci; + } + + ++ci; + } + + qDebug("show %d apps", mp_layoutAreaToSurfaceIdAssignment->size()); + for (int j = 0; j < mp_layoutAreaToSurfaceIdAssignment->size(); ++j) + { + int surfaceToShow = mp_layoutAreaToSurfaceIdAssignment->find(j).value(); + qDebug(" surface no. %d: %d", j, surfaceToShow); + + addSurfaceToLayer(surfaceToShow, WINDOWMANAGER_LAYER_APPLICATIONS); + + ilm_surfaceSetVisibility(surfaceToShow, ILM_TRUE); + ilm_surfaceSetOpacity(surfaceToShow, 1.0); + + qDebug(" layout area %d", j); + qDebug(" x: %d", currentLayout.layoutAreas[j].x); + qDebug(" y: %d", currentLayout.layoutAreas[j].y); + qDebug(" w: %d", currentLayout.layoutAreas[j].width); + qDebug(" h: %d", currentLayout.layoutAreas[j].height); + + ilm_surfaceSetDestinationRectangle(surfaceToShow, + currentLayout.layoutAreas[j].x, + currentLayout.layoutAreas[j].y, + currentLayout.layoutAreas[j].width, + currentLayout.layoutAreas[j].height); + ilm_commitChanges(); + } + } + + // layer surface render order + t_ilm_int length; + t_ilm_surface* pArray; + ilm_getSurfaceIDsOnLayer(WINDOWMANAGER_LAYER_HOMESCREEN, &length, &pArray); + ilm_layerSetRenderOrder(WINDOWMANAGER_LAYER_HOMESCREEN, pArray, length); + ilm_commitChanges(); + ilm_getSurfaceIDsOnLayer(WINDOWMANAGER_LAYER_APPLICATIONS, &length, &pArray); + ilm_layerSetRenderOrder(WINDOWMANAGER_LAYER_APPLICATIONS, pArray, length); + ilm_commitChanges(); + ilm_getSurfaceIDsOnLayer(WINDOWMANAGER_LAYER_HOMESCREEN_OVERLAY, &length, &pArray); + ilm_layerSetRenderOrder(WINDOWMANAGER_LAYER_HOMESCREEN_OVERLAY, pArray, length); + ilm_commitChanges(); + ilm_getSurfaceIDsOnLayer(WINDOWMANAGER_LAYER_POPUP, &length, &pArray); + ilm_layerSetRenderOrder(WINDOWMANAGER_LAYER_POPUP, pArray, length); + ilm_commitChanges(); +#endif +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + if (m_pending_to_show != -1) { + qDebug("show pending app (%d)", m_pending_to_show); + showAppLayer(m_pending_to_show); + } else { + // display layer render order + t_ilm_layer renderOrder[WINDOWMANAGER_LAYER_NUM]; + int num_layers = getLayerRenderOrder(renderOrder); + + qDebug("Screen render order %d, %d layers", m_screenId, num_layers); + ilm_displaySetRenderOrder(m_screenId, renderOrder, num_layers); + ilm_commitChanges(); + } +#endif +} + +#ifdef HAVE_IVI_LAYERMANAGEMENT_API +void WindowManager::notificationFunc_non_static(ilmObjectType object, + t_ilm_uint id, + t_ilm_bool created) +{ + qDebug("-=[notificationFunc_non_static]=-"); + qDebug("Notification from weston!"); + if (ILM_SURFACE == object) + { + struct ilmSurfaceProperties surfaceProperties; + + if (created) + { + if (WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID == id) + { + ilm_surfaceAddNotification(id, surfaceCallbackFunction_static); + ilm_commitChanges(); + } + else + { + addSurface(id); + } + } + else + { + qDebug("Surface destroyed, ID: %d", id); +#if 0 + m_appSurfaces.removeAt(m_appSurfaces.indexOf(id)); + ilm_surfaceRemoveNotification(id); + + ilm_commitChanges(); +#endif + } + } + if (ILM_LAYER == object) + { + //qDebug("Layer.. we don't care..."); + } +} + +void WindowManager::notificationFunc_static(ilmObjectType object, + t_ilm_uint id, + t_ilm_bool created, + void* user_data) +{ + static_cast<WindowManager*>(WindowManager::myThis)->notificationFunc_non_static(object, id, created); +} + +void WindowManager::surfaceCallbackFunction_non_static(t_ilm_surface surface, + struct ilmSurfaceProperties* surfaceProperties, + t_ilm_notification_mask mask) +{ + qDebug("-=[surfaceCallbackFunction_non_static]=-"); + qDebug("surfaceCallbackFunction_non_static changes for surface %d", surface); + if (ILM_NOTIFICATION_VISIBILITY & mask) + { + qDebug("ILM_NOTIFICATION_VISIBILITY"); + surfaceVisibilityChanged(surface, surfaceProperties->visibility); + updateScreen(); + } + if (ILM_NOTIFICATION_OPACITY & mask) + { + qDebug("ILM_NOTIFICATION_OPACITY"); + } + if (ILM_NOTIFICATION_ORIENTATION & mask) + { + qDebug("ILM_NOTIFICATION_ORIENTATION"); + } + if (ILM_NOTIFICATION_SOURCE_RECT & mask) + { + qDebug("ILM_NOTIFICATION_SOURCE_RECT"); + } + if (ILM_NOTIFICATION_DEST_RECT & mask) + { + qDebug("ILM_NOTIFICATION_DEST_RECT"); + } + if (ILM_NOTIFICATION_CONTENT_AVAILABLE & mask) + { + qDebug("ILM_NOTIFICATION_CONTENT_AVAILABLE"); + } + if (ILM_NOTIFICATION_CONTENT_REMOVED & mask) + { + qDebug("ILM_NOTIFICATION_CONTENT_REMOVED"); + + /* application being down */ + m_appLayers.remove(surfaceProperties->creatorPid); + } + if (ILM_NOTIFICATION_CONFIGURED & mask) + { + qDebug("ILM_NOTIFICATION_CONFIGURED"); + qDebug(" surfaceProperties %d", surface); + qDebug(" surfaceProperties.origSourceWidth: %d", surfaceProperties->origSourceWidth); + qDebug(" surfaceProperties.origSourceHeight: %d", surfaceProperties->origSourceHeight); + + if (surface == WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID) { + addSurfaceToLayer(surface, WINDOWMANAGER_LAYER_HOMESCREEN); + configureHomeScreenMainSurface(surface, surfaceProperties->origSourceWidth, surfaceProperties->origSourceHeight); + } else { + ilmErrorTypes result; + pid_t pid = surfaceProperties->creatorPid; + t_ilm_layer layer = addSurfaceToAppLayer(pid, surface); + + if (layer != 0) { + configureAppSurface(pid, surface, + surfaceProperties->origSourceWidth, + surfaceProperties->origSourceHeight); + + result = ilm_layerAddSurface(layer, surface); + if (result != ILM_SUCCESS) { + qDebug("ilm_layerAddSurface(%d,%d) failed.", layer, surface); + } + ilm_commitChanges(); + } + } + updateScreen(); + } +} + +void WindowManager::surfaceCallbackFunction_static(t_ilm_surface surface, + struct ilmSurfaceProperties* surfaceProperties, + t_ilm_notification_mask mask) + +{ + static_cast<WindowManager*>(WindowManager::myThis)->surfaceCallbackFunction_non_static(surface, surfaceProperties, mask); +} +#endif + +int WindowManager::layoutId() const +{ + return m_currentLayout; +} + +QString WindowManager::layoutName() const +{ + QList<Layout>::const_iterator i = m_layouts.begin(); + + QString result = "not found"; + while (i != m_layouts.constEnd()) + { + if (i->id == m_currentLayout) + { + result = i->name; + } + + ++i; + } + + return result; +} + + +int WindowManager::addLayout(int layoutId, const QString &layoutName, const QList<LayoutArea> &surfaceAreas) +{ + qDebug("-=[addLayout]=-"); + m_layouts.append(Layout(layoutId, layoutName, surfaceAreas)); + + qDebug("addLayout %d %s, size %d", + layoutId, + layoutName.toStdString().c_str(), + surfaceAreas.size()); + + dumpScene(); + + return WINDOWMANAGER_NO_ERROR; +} + +int WindowManager::deleteLayoutById(int layoutId) +{ + qDebug("-=[deleteLayoutById]=-"); + qDebug("layoutId: %d", layoutId); + int result = WINDOWMANAGER_NO_ERROR; + + if (m_currentLayout == layoutId) + { + result = WINDOWMANAGER_ERROR_ID_IN_USE; + } + else + { + QList<Layout>::iterator i = m_layouts.begin(); + result = WINDOWMANAGER_ERROR_ID_IN_USE; + while (i != m_layouts.constEnd()) + { + if (i->id == layoutId) + { + m_layouts.erase(i); + result = WINDOWMANAGER_NO_ERROR; + break; + } + + ++i; + } + } + + return result; +} + + +QList<Layout> WindowManager::getAllLayouts() +{ + qDebug("-=[getAllLayouts]=-"); + + return m_layouts; +} + +#if 0 +QList<int> WindowManager::getAllSurfacesOfProcess(int pid) +{ + QList<int> result; +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + struct ilmSurfaceProperties surfaceProperties; + + for (int i = 0; i < m_appSurfaces.size(); ++i) + { + ilm_getPropertiesOfSurface(m_appSurfaces.at(i), &surfaceProperties); + if (pid == surfaceProperties.creatorPid) + { + result.append(m_appSurfaces.at(i)); + } + } +#endif + return result; +} +#endif + +QList<int> WindowManager::getAvailableLayouts(int numberOfAppSurfaces) +{ + qDebug("-=[getAvailableLayouts]=-"); + QList<Layout>::const_iterator i = m_layouts.begin(); + + QList<int> result; + while (i != m_layouts.constEnd()) + { + if (i->layoutAreas.size() == numberOfAppSurfaces) + { + result.append(i->id); + } + + ++i; + } + + return result; +} + +#if 0 +QList<int> WindowManager::getAvailableSurfaces() +{ + qDebug("-=[getAvailableSurfaces]=-"); + + return m_appSurfaces; +} +#endif + +QString WindowManager::getLayoutName(int layoutId) +{ + qDebug("-=[getLayoutName]=-"); + QList<Layout>::const_iterator i = m_layouts.begin(); + + QString result = "not found"; + while (i != m_layouts.constEnd()) + { + if (i->id == layoutId) + { + result = i->name; + } + + ++i; + } + + return result; +} + +void WindowManager::hideLayer(int layer) +{ + qDebug("-=[hideLayer]=-"); + qDebug("layer %d", layer); + +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + // POPUP=0, HOMESCREEN_OVERLAY=1, APPS=2, HOMESCREEN=3 + if (layer >= 0 && layer < WINDOWMANAGER_LAYER_NUM) { + /* hide target layer */ + m_showLayers[layer] = 0; + if (layer == 2) { + /* clear pending flag */ + m_pending_to_show = -1; + } + + t_ilm_layer renderOrder[WINDOWMANAGER_LAYER_NUM]; + int num_layers = getLayerRenderOrder(renderOrder); + ilm_displaySetRenderOrder(m_screenId, renderOrder, num_layers); + ilm_commitChanges(); + } +#endif +} + +int WindowManager::setLayoutById(int layoutId) +{ + qDebug("-=[setLayoutById]=-"); + int result = WINDOWMANAGER_NO_ERROR; + m_currentLayout = layoutId; + + mp_layoutAreaToSurfaceIdAssignment->clear(); + + dumpScene(); + + return result; +} + +int WindowManager::setLayoutByName(const QString &layoutName) +{ + qDebug("-=[setLayoutByName]=-"); + int result = WINDOWMANAGER_NO_ERROR; + + QList<Layout>::const_iterator i = m_layouts.begin(); + + while (i != m_layouts.constEnd()) + { + if (i->name == layoutName) + { + m_currentLayout = i->id; + + mp_layoutAreaToSurfaceIdAssignment->clear(); + + dumpScene(); + } + + ++i; + } + + return result; +} + +int WindowManager::setSurfaceToLayoutArea(int surfaceId, int layoutAreaId) +{ + qDebug("-=[setSurfaceToLayoutArea]=-"); + int result = WINDOWMANAGER_NO_ERROR; + + qDebug("surfaceId %d", surfaceId); + qDebug("layoutAreaId %d", layoutAreaId); + mp_layoutAreaToSurfaceIdAssignment->insert(layoutAreaId, surfaceId); + + updateScreen(); + + dumpScene(); + + return result; +} + +void WindowManager::showLayer(int layer) +{ + qDebug("-=[showLayer]=-"); + qDebug("layer %d", layer); + +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + // POPUP=0, HOMESCREEN_OVERLAY=1, APPS=2, HOMESCREEN=3 + if (layer >= 0 && layer < WINDOWMANAGER_LAYER_NUM) { + static const int layer_id_array[] = { + WINDOWMANAGER_LAYER_POPUP, + WINDOWMANAGER_LAYER_HOMESCREEN_OVERLAY, + WINDOWMANAGER_LAYER_APPLICATIONS, + WINDOWMANAGER_LAYER_HOMESCREEN, + }; + + m_showLayers[layer] = layer_id_array[layer]; + + t_ilm_layer renderOrder[WINDOWMANAGER_LAYER_NUM]; + int num_layers = getLayerRenderOrder(renderOrder); + ilm_displaySetRenderOrder(m_screenId, renderOrder, num_layers); + ilm_commitChanges(); + } +#endif +} + +void WindowManager::showAppLayer(int pid) +{ + qDebug("-=[showAppLayer]=-"); + qDebug("pid %d", pid); + + if (pid == -1) { + /* nothing to show */ + return; + } +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + /* clear pending flag */ + m_pending_to_show = -1; + + /* search layer id for application to show */ + QMap<pid_t, t_ilm_layer>::const_iterator i = m_appLayers.find(pid); + QMap<pid_t, t_ilm_surface>::const_iterator j = m_appSurfaces.find(pid); + + if (i != m_appLayers.end()) { + m_showLayers[2] = i.value(); + qDebug("Found layer(%d) to show for app(pid=%d)", m_showLayers[2], pid); + } else { + /* check if this app is registered */ + if (j == m_appSurfaces.end()) { + qDebug("New app %d", pid); + m_appSurfaces.insert(pid, 0); /* register pid only so far */ + } + + /* Probably app layer hasn't been made yet */ + m_pending_to_show = pid; + /* hide current app once, back to default screen */ + m_showLayers[2] = 0; + qDebug("No layer to show for app(pid=%d)", pid); + } + t_ilm_layer renderOrder[WINDOWMANAGER_LAYER_NUM]; + + int num_layers = getLayerRenderOrder(renderOrder); + ilm_displaySetRenderOrder(m_screenId, renderOrder, num_layers); + ilm_commitChanges(); +#endif +} diff --git a/windowmanager/src/windowmanager.hpp b/windowmanager/src/windowmanager.hpp new file mode 100644 index 0000000..89f255e --- /dev/null +++ b/windowmanager/src/windowmanager.hpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINDOWMANAGER_HPP +#define WINDOWMANAGER_HPP + +#include <QObject> +#include <QList> +#include <QMap> + +#include "windowmanager_adaptor.h" + +#ifdef HAVE_IVI_LAYERMANAGEMENT_API +#include <ilm/ilm_control.h> +#endif +class WindowManager : public QObject +{ + Q_OBJECT + +public: + explicit WindowManager(int displayId, QObject *parent = 0); + ~WindowManager(); + + void start(); +private: + WindowmanagerAdaptor *mp_windowManagerAdaptor; + QList<Layout> m_layouts; + QMap<int, unsigned int> *mp_layoutAreaToSurfaceIdAssignment; + + int m_currentLayout; + + int m_screenId; + unsigned int m_screenWidth; + unsigned int m_screenHeight; + + void dumpScene(); + +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + t_ilm_layer* m_showLayers; + QMap<pid_t, t_ilm_surface> m_appSurfaces; + QMap<pid_t, t_ilm_layer> m_appLayers; + int getLayerRenderOrder(t_ilm_layer* id_array); + + void createNewLayer(const int layerId); + + t_ilm_layer getAppLayerID(const pid_t pid); + + pid_t m_pending_to_show; + + void addSurface(const t_ilm_surface surfaceId); + t_ilm_layer addSurfaceToAppLayer(pid_t pid, const int surfaceId); + void addSurfaceToLayer(const int surfaceId, const int layerId); + + void configureHomeScreenMainSurface(const t_ilm_surface surface, const t_ilm_int width, const t_ilm_int height); + void configureAppSurface(const pid_t pid, const t_ilm_surface surface, const t_ilm_int width, const t_ilm_int height); +#endif + void updateScreen(); + + +public: + static void* myThis; + +#ifdef HAVE_IVI_LAYERMANAGEMENT_API + // for general notifications + void notificationFunc_non_static(ilmObjectType object, + t_ilm_uint id, + t_ilm_bool created); + static void notificationFunc_static(ilmObjectType object, + t_ilm_uint id, + t_ilm_bool created, + void* user_data); + + + // for surface notifications + void surfaceCallbackFunction_non_static(t_ilm_surface surface, + struct ilmSurfaceProperties* surfaceProperties, + t_ilm_notification_mask mask); + static void surfaceCallbackFunction_static(t_ilm_surface surface, + struct ilmSurfaceProperties* surfaceProperties, + t_ilm_notification_mask mask); + +#endif +public slots: + + +// from windowmanager_adaptor.h +public: // PROPERTIES + Q_PROPERTY(int layoutId READ layoutId) + int layoutId() const; + + Q_PROPERTY(QString layoutName READ layoutName) + QString layoutName() const; + +public Q_SLOTS: // METHODS + int addLayout(int layoutId, const QString &layoutName, const QList<LayoutArea> &surfaceAreas); + int deleteLayoutById(int layoutId); + QList<Layout> getAllLayouts(); + // QList<int> getAllSurfacesOfProcess(int pid); + QList<int> getAvailableLayouts(int numberOfAppSurfaces); + // QList<int> getAvailableSurfaces(); + QString getLayoutName(int layoutId); + void hideLayer(int layer); + int setLayoutById(int layoutId); + int setLayoutByName(const QString &layoutName); + int setSurfaceToLayoutArea(int surfaceId, int layoutAreaId); + void showLayer(int layer); + void showAppLayer(int pid); + +Q_SIGNALS: // SIGNALS + void surfaceVisibilityChanged(int surfaceId, bool visible); +}; + +#endif // WINDOWMANAGER_HPP diff --git a/windowmanager/windowmanager.pro b/windowmanager/windowmanager.pro new file mode 100644 index 0000000..bcf1f90 --- /dev/null +++ b/windowmanager/windowmanager.pro @@ -0,0 +1,33 @@ +# Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +TEMPLATE = app +TARGET = WindowManager +QT = core dbus + +include(../interfaces/interfaces.pri) +include(../ivi_layermanagement_api.pri) + +SOURCES += src/main.cpp \ + src/windowmanager.cpp + +HEADERS += \ + src/windowmanager.hpp + +config_ivi_layermanagement_api { + LIBS += -lilmControl -lilmCommon +} + +OTHER_FILES += \ + README.md |