Reworking layer/surface management
[staging/HomeScreen.git] / WindowManager / src / windowmanager.cpp
index dcab2f4..ac34756 100644 (file)
 
 #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];
 
-WindowManager::WindowManager(QObject *parent) :
-    QObject(parent)
+    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("WindowManager");
-#ifdef __arm__
+    qDebug("-=[start]=-");
+    mp_layoutAreaToSurfaceIdAssignment = new QMap<int, unsigned int>;
+#ifdef HAVE_IVI_LAYERMANAGEMENT_API
     ilmErrorTypes err;
-    if (true)//!ilm_isInitialized()) ...crashes...
+
+    err = ilm_init();
+    qDebug("ilm_init = %d", err);
+    if(ILM_SUCCESS != err)
     {
-        err = ilm_init();
-        qDebug("ilm_init = %d", err);
+        qDebug("failed! Exiting!");
+        exit(-1);
     }
 
+    myThis = this;
 
-    t_ilm_uint screenID = 0;
-    t_ilm_uint width;
-    t_ilm_uint height;
+    ilm_getScreenResolution(m_screenId, &m_screenWidth, &m_screenHeight);
 
-    err = ilm_getScreenResolution(screenID, &width, &height);
-    qDebug("ilm_getScreenResolution = %d", err);
-    qDebug("pWidth %d, pHeight %d", width, height);
+    createNewLayer(WINDOWMANAGER_LAYER_POPUP);
+    createNewLayer(WINDOWMANAGER_LAYER_HOMESCREEN_OVERLAY);
+    createNewLayer(WINDOWMANAGER_LAYER_HOMESCREEN);
 
+    ilm_registerNotification(WindowManager::notificationFunc_static, this);
+#endif
 
-    t_ilm_layer layerId = 42; // does not matter
-    err = ilm_layerCreateWithDimension(&layerId, width, height);
-    qDebug("ilm_layerCreateWithDimension = %d", err);
-    qDebug("layerId = %d", layerId);
+    QDBusConnection dbus = QDBusConnection::sessionBus();
+    dbus.registerObject("/windowmanager", this);
+    dbus.registerService("org.agl.windowmanager");
 
-    err = ilm_layerSetVisibility(layerId, true);
-    qDebug("ilm_layerSetVisibility = %d", err);
+    // publish windowmanager interface
+    mp_windowManagerAdaptor = new WindowmanagerAdaptor((QObject*)this);
+}
 
-    ilm_commitChanges();
+WindowManager::~WindowManager()
+{
+    qDebug("-=[~WindowManager]=-");
+    delete mp_windowManagerAdaptor;
+#ifdef HAVE_IVI_LAYERMANAGEMENT_API
+    ilm_destroy();
+#endif
+    delete mp_layoutAreaToSurfaceIdAssignment;
+}
 
-    err = ilm_displaySetRenderOrder(screenID, &layerId, 1);
-    qDebug("ilm_displaySetRenderOrder = %d", err);
+#ifdef HAVE_IVI_LAYERMANAGEMENT_API
+int WindowManager::getLayerRenderOrder(t_ilm_layer id_array[])
+{
+    int i, j;
 
-    ilm_commitChanges();
+    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;
+    }
+}
 
-    err =  ilm_layerSetSourceRectangle(layerId, 0, 0, width, height);
-    qDebug("ilm_layerSetSourceRectangle = %d", err);
-    err =  ilm_layerSetDestinationRectangle(layerId, 0, 0, width, height);
-    qDebug("layerSetDestinationRectangle = %d", err);
+#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_float opacity = 1.0;
+t_ilm_layer WindowManager::getAppLayerID(pid_t pid)
+{
+    t_ilm_layer layer_id;
 
-    err =  ilm_layerSetOpacity(layerId, opacity);
-    qDebug("ilm_layerSetOpacity = %d", err);
+//    layer_id = pid + (WINDOWMANAGER_LAYER_APPLICATIONS << WINDOWMANAGER_LAYER_ID_SHIFT);
+    layer_id = pid + (WINDOWMANAGER_LAYER_APPLICATIONS * 100000); /* for debug */
 
+    return layer_id;
+}
 
-    t_ilm_int length;
-    t_ilm_surface* pArray;
+void WindowManager::addSurface(t_ilm_surface surfaceId)
+{
+    struct ilmSurfaceProperties surfaceProperties;
+    pid_t pid;
 
-    err = ilm_getSurfaceIDs(&length, &pArray);
-    qDebug("ilm_getSurfaceIDs = %d", err);
-    qDebug("length %d pArray[0] %d", length, pArray[0]);
+    ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
+    pid = surfaceProperties.creatorPid;
 
-    if (length > 0)
-    {
-        t_ilm_surface surfaceId = pArray[0];
+    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);
 
-        err = ilm_layerAddSurface(layerId, surfaceId);
-        qDebug("ilm_layerAddSurface = %d", err);
+        /* 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;
+}
 
-        t_ilm_bool visibility;
-        err = ilm_surfaceGetVisibility(surfaceId, &visibility);
-        qDebug("ilm_surfaceGetVisibility = %d", err);
-        qDebug("visibility %d", visibility);
+void WindowManager::addSurfaceToLayer(int surfaceId, int layerId)
+{
+    qDebug("-=[addSurfaceToLayer]=-");
+    qDebug("  surfaceId %d", surfaceId);
+    qDebug("  layerId %d", layerId);
 
-        err = ilm_surfaceSetVisibility(surfaceId, true);
-        qDebug("ilm_surfaceSetVisibility = %d", err);
+    if (layerId == WINDOWMANAGER_LAYER_HOMESCREEN)
+    {
+      ilm_layerAddSurface(layerId, surfaceId);
+    }
+    else if (layerId == WINDOWMANAGER_LAYER_HOMESCREEN_OVERLAY)
+    {
+        struct ilmSurfaceProperties surfaceProperties;
+        ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
 
-        err = ilm_surfaceSetOpacity(surfaceId, opacity);
-        qDebug("ilm_surfaceSetOpacity = %d", err);
+        //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);
 
-        err = ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, 200, 200);
-        qDebug("ilm_surfaceSetSourceRectangle = %d", err);
-        err = ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, 200, 200);
-        qDebug("surfaceSetDestinationRectangle = %d", err);
+        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();
+}
 
-    struct ilmScreenProperties screenProperties;
-    struct ilmLayerProperties layerProperties;
-    struct ilmSurfaceProperties surfaceProperties;
+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);
 
-    err =  ilm_getPropertiesOfScreen(0, &screenProperties);
-    qDebug("ilm_getPropertiesOfScreen = %d", err);
-    err =  ilm_getPropertiesOfLayer(layerId, &layerProperties);
-    qDebug("ilm_getPropertiesOfLayer = %d", err);
-    err =  ilm_getPropertiesOfSurface(pArray[0], &surfaceProperties);
-    qDebug("ilm_getPropertiesOfSurface = %d", err);
-
-
-    qDebug("screen");
-    qDebug("t_ilm_uint %d", screenProperties.layerCount);          /*!< number of layers displayed on the screen */
-    //qDebug("t_ilm_layer* %d", screenProperties.layerIds[0]);          /*!< array of layer ids */
-    qDebug("t_ilm_uint %d", screenProperties.harwareLayerCount);   /*!< number of hardware layers */
-    qDebug("t_ilm_uint %d", screenProperties.screenWidth);         /*!< width value of screen in pixels */
-    qDebug("t_ilm_uint %d", screenProperties.screenHeight);        /*!< height value of screen in pixels */
-
-    qDebug("layer");
-    qDebug("t_ilm_float %f", layerProperties.opacity);         /*!< opacity value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.sourceX);          /*!< x source position value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.sourceY);          /*!< y source position value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.sourceWidth);      /*!< source width value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.sourceHeight);     /*!< source height value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.origSourceWidth);  /*!< original source width value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.origSourceHeight); /*!< original source height value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.destX);            /*!< x destination position value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.destY);            /*!< y desitination position value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.destWidth);        /*!< destination width value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.destHeight);       /*!< destination height value of the layer */
-    qDebug("ilmOrientation%d",  layerProperties.orientation);  /*!< orientation value of the layer */
-    qDebug("t_ilm_bool %d", layerProperties.visibility);       /*!< visibility value of the layer */
-    qDebug("t_ilm_uint %d", layerProperties.type);             /*!< type of layer */
-    qDebug("t_ilm_int  %d", layerProperties.creatorPid);       /*!< process id of application that created this layer */
-
-    qDebug("surface");
-    qDebug("t_ilm_float %f", surfaceProperties.opacity);                    /*!< opacity value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.sourceX);                     /*!< x source position value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.sourceY);                     /*!< y source position value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.sourceWidth);                 /*!< source width value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.sourceHeight);                /*!< source height value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.origSourceWidth);             /*!< original source width value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.origSourceHeight);            /*!< original source height value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.destX);                       /*!< x destination position value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.destY);                       /*!< y desitination position value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.destWidth);                   /*!< destination width value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.destHeight);                  /*!< destination height value of the surface */
-    qDebug("ilmOrientation %d", surfaceProperties.orientation);             /*!< orientation value of the surface */
-    qDebug("t_ilm_bool %d", surfaceProperties.visibility);                  /*!< visibility value of the surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.frameCounter);                /*!< already rendered frames of surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.drawCounter);                 /*!< content updates of surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.updateCounter);               /*!< content updates of surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.pixelformat);                 /*!< pixel format of surface */
-    qDebug("t_ilm_uint %d", surfaceProperties.nativeSurface);               /*!< native surface handle of surface */
-    qDebug("t_ilm_int  %d", surfaceProperties.creatorPid);                  /*!< process id of application that created this surface */
-    qDebug("ilmInputDevice %d", surfaceProperties.focus);                   /*!< bitmask of every type of device that this surface has focus in */
-
-    err =  ilm_registerNotification(WindowManager::notificationFunc_static, this);
-#endif
+    ilm_commitChanges();
 }
 
-WindowManager::~WindowManager()
+void WindowManager::configureAppSurface(pid_t pid, t_ilm_surface surface, t_ilm_int width, t_ilm_int height)
 {
-#ifdef __arm__
-    ilmErrorTypes err;
-    if (ilm_isInitialized())
+    /* 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)
     {
-        err = ilm_destroy();
-        qDebug("ilm_destroy = %d", err);
+        // 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 __arm__
+#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("-=[notificationFunc_non_static]=-");
+    qDebug("Notification from weston!");
     if (ILM_SURFACE == object)
     {
         struct ilmSurfaceProperties surfaceProperties;
 
         if (created)
         {
-            qDebug("Surface created, ID: %d", id);
-
-            ilm_layerAddSurface(42 /*always use layer 42 for now*/, id);
-            ilm_surfaceSetOpacity(id, 1.0);
-            ilm_surfaceSetVisibility(id, true);
-            ilm_getPropertiesOfSurface(id, &surfaceProperties);
-            ilm_surfaceSetSourceRectangle(id, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
-
-            ilm_commitChanges();
+            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);
         }
 
-        t_ilm_uint screenID = 0;
-        t_ilm_uint width;
-        t_ilm_uint height;
-        ilm_getScreenResolution(screenID, &width, &height);
+        ++i;
+    }
 
-        t_ilm_int length;
-        t_ilm_surface* pArray;
+    return result;
+}
 
-        ilm_getSurfaceIDs(&length, &pArray);
-        qDebug("length %d", length);
+#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();
 
-        for (int i = 0; i < length; ++i)
+    QString result = "not found";
+    while (i != m_layouts.constEnd())
+    {
+        if (i->id == layoutId)
         {
-            //ilm_getPropertiesOfSurface(pArray[i], &surfaceProperties);
-            qDebug("place surface %d at x: %f, y: %f, width: %f, height: %f",
-                   pArray[i],
-                   i * (width / (1.0 * length)),
-                   0,
-                   width / (1.0 * length),
-                   height);
-            ilm_surfaceSetDestinationRectangle(pArray[(int)i],
-                    i * (width / (1.0 * length)),
-                    0,
-                    width / (1.0 * length),
-                    height);
+            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();
     }
-    if (ILM_LAYER == object)
+#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())
     {
-        qDebug("Layer.. we don't care...");
+        if (i->name == layoutName)
+        {
+            m_currentLayout = i->id;
+
+            mp_layoutAreaToSurfaceIdAssignment->clear();
+
+            dumpScene();
+        }
+
+        ++i;
     }
+
+    return result;
 }
 
-void WindowManager::notificationFunc_static(ilmObjectType object,
-                                            t_ilm_uint id,
-                                            t_ilm_bool created,
-                                            void* user_data)
+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("notificationFunc_static");
-    static_cast<WindowManager*>(user_data)->notificationFunc_non_static(object, id, created);
+    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
+}