/* * Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH * Copyright (c) 2017, 2018 TOYOTA MOTOR CORPORATION * * 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<QGuiApplication>#include<QCommandLineParser>#include<QtCore/QUrlQuery>#include<QtGui/QGuiApplication>#include<QtQml/QQmlApplicationEngine>#include<QtQml/QQmlContext>#include<QtQml/QQmlComponent>#include<QtQml/qqml.h>#include<QQuickWindow>#include<QTimer>#include<weather.h>#include<bluetooth.h>#include"applicationlauncher.h"#include"statusbarmodel.h"#include"mastervolume.h"#include"homescreenhandler.h"#include"hmi-debug.h"#include<qpa/qplatformnativeinterface.h>#include<wayland-client.h>#include"wayland-agl-shell-client-protocol.h"#include"wayland-agl-shell-desktop-client-protocol.h"#include"shell.h"structshell_data{structagl_shell*shell;structagl_shell_desktop*shell_desktop;};staticvoidagl_shell_desktop_application(void*data,structagl_shell_desktop*agl_shell_desktop,constchar*app_id){HomescreenHandler*homescreenHandler=static_cast<HomescreenHandler*>(data);if(homescreenHandler)homescreenHandler->addAppToStack(app_id);}staticvoidagl_shell_desktop_state_app(void*data,structagl_shell_desktop*agl_shell_desktop,constchar*app_id,constchar*app_data,uint32_tstate,uint32_trole){HomescreenHandler*homescreenHandler=static_cast<HomescreenHandler*>(data);if(homescreenHandler&&state==AGL_SHELL_DESKTOP_APP_STATE_DESTROYED)homescreenHandler->appTerminated(app_id);}staticconststructagl_shell_desktop_listenershell_desktop_listener={agl_shell_desktop_application,agl_shell_desktop_state_app};staticvoidglobal_add(void*data,structwl_registry*reg,uint32_tname,constchar*interface,uint32_t){structshell_data*shell_data=static_cast<structshell_data*>(data);if(!shell_data)return;if(strcmp(interface,agl_shell_interface.name)==0){shell_data->shell=static_cast<structagl_shell*>(wl_registry_bind(reg,name,&agl_shell_interface,1));}if(strcmp(interface,agl_shell_desktop_interface.name)==0){shell_data->shell_desktop=static_cast<structagl_shell_desktop*>(wl_registry_bind(reg,name,&agl_shell_desktop_interface,1));}}staticvoidglobal_remove(void*data,structwl_registry*reg,uint32_tid){/* Don't care */(void)data;(void)reg;(void)id;}staticconststructwl_registry_listenerregistry_listener={global_add,global_remove,};staticstructwl_surface*getWlSurface(QPlatformNativeInterface*native,QWindow*window){void*surf=native->nativeResourceForWindow("surface",window);returnstatic_cast<struct::wl_surface*>(surf);}staticstructwl_output*getWlOutput(QPlatformNativeInterface*native,QScreen*screen){void*output=native->nativeResourceForScreen("output",screen);returnstatic_cast<struct::wl_output*>(output);}staticvoidregister_agl_shell(QPlatformNativeInterface*native,structshell_data*shell_data){structwl_display*wl;structwl_registry*registry;wl=static_cast<structwl_display*>(native->nativeResourceForIntegration("display"));registry=wl_display_get_registry(wl);wl_registry_add_listener(registry,®istry_listener,shell_data);/* Roundtrip to get all globals advertised by the compositor */wl_display_roundtrip(wl);wl_registry_destroy(registry);}staticstructwl_surface*create_component(QPlatformNativeInterface*native,QQmlComponent*comp,QScreen*screen,QObject**qobj){QObject*obj=comp->create();obj->setParent(screen);QWindow*win=qobject_cast<QWindow*>(obj);*qobj=obj;returngetWlSurface(native,win);}staticQScreen*find_screen(constchar*screen_name){QList<QScreen*>screens=qApp->screens();QScreen*found=nullptr;QStringqstr_name=QString::fromUtf8(screen_name,-1);for(QScreen*xscreen:screens){if(qstr_name==xscreen->name()){found=xscreen;break;}}returnfound;}staticvoidload_agl_shell_app(QPlatformNativeInterface*native,QQmlApplicationEngine*engine,structagl_shell*agl_shell,constchar*screen_name,boolis_demo){structwl_surface*bg,*top,*bottom;structwl_output*output;QObject*qobj_bg,*qobj_top,*qobj_bottom;QScreen*screen=nullptr;if(is_demo){QQmlComponentbg_comp(engine,QUrl("qrc:/background_demo.qml"));qInfo()<<bg_comp.errors();QQmlComponenttop_comp(engine,QUrl("qrc:/toppanel_demo.qml"));qInfo()<<top_comp.errors();QQmlComponentbot_comp(engine,QUrl("qrc:/bottompanel_demo.qml"));qInfo()<<bot_comp.errors();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{QQmlComponentbg_comp(engine,QUrl("qrc:/background.qml"));qInfo()<<bg_comp.errors();QQmlComponenttop_comp(engine,QUrl("qrc:/toppanel.qml"));qInfo()<<top_comp.errors();QQmlComponentbot_comp(engine,QUrl("qrc:/bottompanel.qml"));qInfo()<<bot_comp.errors();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);}if(!screen_name)screen=qApp->primaryScreen();elsescreen=find_screen(screen_name);qDebug()<<"found primary screen "<<qApp->primaryScreen()->name()<<"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);/* Delay the ready signal until after Qt has done all of its own setup * in a.exec() */QTimer::singleShot(500,[agl_shell](){agl_shell_ready(agl_shell);});}intmain(intargc,char*argv[]){setenv("QT_QPA_PLATFORM","wayland",1);QGuiApplicationa(argc,argv);constchar*screen_name;boolis_demo_val=false;structshell_datashell_data={nullptr,nullptr};QPlatformNativeInterface*native=qApp->platformNativeInterface();screen_name=getenv("HOMESCREEN_START_SCREEN");constchar*is_demo=getenv("HOMESCREEN_DEMO_CI");if(is_demo&&strcmp(is_demo,"1")==0)is_demo_val=true;QCoreApplication::setOrganizationDomain("LinuxFoundation");QCoreApplication::setOrganizationName("AutomotiveGradeLinux");QCoreApplication::setApplicationName("HomeScreen");QCoreApplication::setApplicationVersion("0.7.0");/* we need to have an app_id */a.setDesktopFileName("homescreen");register_agl_shell(native,&shell_data);if(!shell_data.shell){fprintf(stderr,"agl_shell extension is not advertised. ""Are you sure that agl-compositor is running?\n");exit(EXIT_FAILURE);}if(!shell_data.shell_desktop){fprintf(stderr,"agl_shell_desktop extension is not advertised. ""Are you sure that agl-compositor is running?\n");exit(EXIT_FAILURE);}std::shared_ptr<structagl_shell>agl_shell{shell_data.shell,agl_shell_destroy};Shell*aglShell=newShell(agl_shell,&a);// import C++ class to QMLqmlRegisterType<StatusBarModel>("HomeScreen",1,0,"StatusBarModel");qmlRegisterType<MasterVolume>("MasterVolume",1,0,"MasterVolume");ApplicationLauncher*launcher=newApplicationLauncher();launcher->setCurrent(QStringLiteral("launcher"));HomescreenHandler*homescreenHandler=newHomescreenHandler(aglShell,launcher);homescreenHandler->init();agl_shell_desktop_add_listener(shell_data.shell_desktop,&shell_desktop_listener,homescreenHandler);QQmlApplicationEngineengine;QQmlContext*context=engine.rootContext();context->setContextProperty("homescreenHandler",homescreenHandler);context->setContextProperty("launcher",launcher);context->setContextProperty("weather",newWeather());context->setContextProperty("bluetooth",newBluetooth(false,context));// we add it here even if we don't use itcontext->setContextProperty("shell",aglShell);/* 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);returna.exec();}