WindowManager now handles application surfaces by its pids.
[staging/HomeScreen.git] / WindowManager / src / windowmanager.cpp
1 /*
2  * Copyright (C) 2016 Mentor Graphics Development (Deutschland) GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "windowmanager.hpp"
18 #include <wayland-client.h>
19 #include <QFile>
20
21 //////////////////////////////////////////
22 // THIS IS STILL UNDER HEAVY DEVELOPMENT!
23 // DO NOT JUDGE THE SOURCE CODE :)
24 //////////////////////////////////////////
25
26 void* WindowManager::myThis = 0;
27
28 WindowManager::WindowManager(QObject *parent) :
29     QObject(parent),
30     m_layouts(),
31     m_layoutNames(),
32     m_currentLayout(-1),
33     m_homeScreenPid(-1),
34 #ifdef __arm__
35     mp_surfaces(0),
36     mp_processLayers(0),
37 #endif
38     mp_layoutAreaToPidAssignment(0)
39 {
40     qDebug("-=[WindowManager]=-");
41     qDebug("WindowManager");
42     // publish windowmanager interface
43     mp_windowManagerAdaptor = new WindowmanagerAdaptor((QObject*)this);
44
45     QDBusConnection dbus = QDBusConnection::sessionBus();
46     dbus.registerObject("/windowmanager", this);
47     dbus.registerService("org.agl.windowmanager");
48 }
49
50 void WindowManager::start()
51 {
52     qDebug("-=[start]=-");
53     mp_layoutAreaToPidAssignment = new QMap<int, unsigned int>;
54 #ifdef __arm__
55     mp_processLayers = new QList<int>;
56     mp_surfaces = new QMap<t_ilm_uint, SurfaceInfo>;
57
58     ilmErrorTypes err;
59
60     err = ilm_init();
61     qDebug("ilm_init = %d", err);
62
63     myThis = this;
64     err =  ilm_registerNotification(WindowManager::notificationFunc_static, this);
65 #endif
66 }
67
68 WindowManager::~WindowManager()
69 {
70     qDebug("-=[~WindowManager]=-");
71     delete mp_windowManagerAdaptor;
72 #ifdef __arm__
73     delete mp_surfaces;
74     delete mp_processLayers;
75
76     ilm_destroy();
77 #endif
78     delete mp_layoutAreaToPidAssignment;
79 }
80
81 void WindowManager::dumpScene()
82 {
83     qDebug("\n");
84     qDebug("current layout   : %d", m_currentLayout);
85     qDebug("available layouts: %d", m_layouts.size());
86     QMap<int, QList<SimpleRect> >::iterator i = m_layouts.begin();
87
88     QList<int> result;
89     while (i != m_layouts.constEnd())
90     {
91         qDebug("--[id: %d]--[%s]--", i.key(), m_layoutNames.find(i.key()).value().toStdString().c_str());
92         qDebug("  %d surface areas", i.value().size());
93         for (int j = 0; j < i.value().size(); ++j)
94         {
95             qDebug("  -area %d", j);
96             qDebug("    -x     : %d", i.value().at(j).x);
97             qDebug("    -y     : %d", i.value().at(j).y);
98             qDebug("    -width : %d", i.value().at(j).width);
99             qDebug("    -height: %d", i.value().at(j).height);
100         }
101
102         ++i;
103     }
104 }
105
106 #ifdef __arm__
107
108 void WindowManager::createNewLayer(int layerId)
109 {
110     qDebug("-=[createNewLayer]=-");
111     qDebug("layerId %d", layerId);
112     ilmErrorTypes err;
113
114     t_ilm_uint screenID = 0;
115     t_ilm_uint width;
116     t_ilm_uint height;
117
118     err = ilm_getScreenResolution(screenID, &width, &height);
119
120     t_ilm_layer newLayerId = layerId;
121     err = ilm_layerCreateWithDimension(&newLayerId, width, height);
122
123     t_ilm_float opacity = 0.0;
124     err =  ilm_layerSetOpacity(newLayerId, opacity);
125
126     ilm_layerSetVisibility(newLayerId, ILM_FALSE);
127
128     ilm_commitChanges();
129 }
130
131 void WindowManager::addSurfaceToLayer(int surfaceId, int layerId)
132 {
133     qDebug("-=[addSurfaceToLayer]=-");
134     qDebug("surfaceId %d", surfaceId);
135     qDebug("layerId %d", layerId);
136     t_ilm_int length;
137     t_ilm_layer* pArray;
138
139     ilm_getLayerIDs(&length, &pArray);
140     bool layerFound(false);
141     for (int i = 0; i < length; ++i)
142     {
143         if (layerId == pArray[i])
144         {
145             layerFound = true;
146         }
147     }
148
149     if (!layerFound)
150     {
151         createNewLayer(layerId);
152     }
153
154     struct ilmSurfaceProperties surfaceProperties;
155     ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
156     //qDebug("  origSourceWidth : %d", surfaceProperties.origSourceWidth);
157     //qDebug("  origSourceHeight: %d", surfaceProperties.origSourceHeight);
158
159     ilm_layerSetSourceRectangle(layerId,
160                                      0,
161                                      0,
162                                      surfaceProperties.origSourceWidth,
163                                      surfaceProperties.origSourceHeight);
164     ilm_commitChanges();
165
166     ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
167     ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
168     ilm_surfaceSetOpacity(surfaceId, 1.0);
169     ilm_surfaceSetVisibility(surfaceId, true);
170
171     ilm_layerAddSurface(layerId, surfaceId);
172
173     ilm_commitChanges();
174 }
175
176 void WindowManager::updateScreen()
177 {
178     qDebug("-=[updateScreen]=-");
179     int numberOfLayersToShow = 0;
180
181     QMap<int, QList<SimpleRect> >::iterator i = m_layouts.find(m_currentLayout);
182     if (m_layouts.end() != i)
183     {
184         numberOfLayersToShow += i.value().size();
185         qDebug("the current layout provides %d render areas", i.value().size());
186     }
187     else
188     {
189         qDebug("the current layout provides no render areas!");
190     }
191
192
193     t_ilm_layer renderOrder[numberOfLayersToShow];
194     int renderOrderCounter = 0;
195
196     qDebug("show home screen app");
197     if (-1 != m_homeScreenPid)
198     {
199         renderOrder[renderOrderCounter] = m_homeScreenPid;
200         ++renderOrderCounter;
201
202         ilm_layerSetVisibility(m_homeScreenPid, ILM_TRUE);
203         t_ilm_float opacity = 1.0;
204         ilm_layerSetOpacity(m_homeScreenPid, opacity);
205
206         // homescreen app always fullscreen in the back
207         t_ilm_uint screenID = 0;
208         t_ilm_uint width;
209         t_ilm_uint height;
210
211         ilm_getScreenResolution(screenID, &width, &height);
212
213         ilm_layerSetDestinationRectangle(m_homeScreenPid,
214                                          0,
215                                          0,
216                                          width,
217                                          height);
218     }
219
220
221     qDebug("show %d apps", numberOfLayersToShow);
222     for (int j = 0; j < numberOfLayersToShow; ++j)
223     {
224         int layerToShow = mp_layoutAreaToPidAssignment->find(j).value();
225         if (layerToShow != m_homeScreenPid)
226         {
227             qDebug("  app no. %d: %d", j, layerToShow);
228             renderOrder[renderOrderCounter] = layerToShow;
229             ++renderOrderCounter;
230
231             ilm_layerSetVisibility(layerToShow, ILM_TRUE);
232             t_ilm_float opacity = 1.0;
233             ilm_layerSetOpacity(layerToShow, opacity);
234
235             qDebug("  layout area %d", j);
236             qDebug("    x: %d", m_layouts.find(m_currentLayout).value()[j].x);
237             qDebug("    x: %d", m_layouts.find(m_currentLayout).value()[j].y);
238             qDebug("    w: %d", m_layouts.find(m_currentLayout).value()[j].width);
239             qDebug("    h: %d", m_layouts.find(m_currentLayout).value()[j].height);
240
241             ilm_layerSetDestinationRectangle(layerToShow,
242                                              m_layouts.find(m_currentLayout).value()[j].x,
243                                              m_layouts.find(m_currentLayout).value()[j].y,
244                                              m_layouts.find(m_currentLayout).value()[j].width,
245                                              m_layouts.find(m_currentLayout).value()[j].height);
246         }
247     }
248
249     qDebug("renderOrder");
250     for (int j = 0; j < renderOrderCounter; ++j)
251     {
252         qDebug("  %d: %d", j, renderOrder[j]);
253     }
254
255     ilm_displaySetRenderOrder(0, renderOrder, renderOrderCounter);
256
257     ilm_commitChanges();
258 }
259
260 void WindowManager::notificationFunc_non_static(ilmObjectType object,
261                                     t_ilm_uint id,
262                                     t_ilm_bool created)
263 {
264     qDebug("-=[notificationFunc_non_static]=-");
265     qDebug("Notification from weston!");
266     if (ILM_SURFACE == object)
267     {
268         struct ilmSurfaceProperties surfaceProperties;
269
270         if (created)
271         {
272             qDebug("Surface created, ID: %d", id);
273             //qDebug("Surface created, ID: 0x%s", QString(QByteArray::number(id,16)).toStdString().c_str());
274             ilm_getPropertiesOfSurface(id, &surfaceProperties);
275             qDebug("  origSourceWidth : %d", surfaceProperties.origSourceWidth);
276             qDebug("  origSourceHeight: %d", surfaceProperties.origSourceHeight);
277             SurfaceInfo surfaceInfo;
278             surfaceInfo.pid = surfaceProperties.creatorPid;
279             QString procInfoFileName = QString("/proc/") + QString::number(surfaceInfo.pid) + QString("/comm");
280             QFile procInfo(procInfoFileName);
281             if (procInfo.open(QIODevice::ReadOnly))
282             {
283                 QTextStream in(&procInfo);
284                 surfaceInfo.processName = in.readLine();
285                 qDebug("  creator pid %d %s", surfaceInfo.pid, surfaceInfo.processName.toStdString().c_str());
286                 addSurfaceToLayer(id, surfaceProperties.creatorPid);
287
288                 mp_surfaces->insert(id, surfaceInfo);
289                 ilm_surfaceAddNotification(id, surfaceCallbackFunction_static);
290
291                 ilm_commitChanges();
292
293                 if (0 == QString::compare("weston-fullscre", surfaceInfo.processName))
294                 {
295                     qDebug("HomeScreen app detected");
296                     m_homeScreenPid = surfaceInfo.pid;
297                     updateScreen();
298                 }
299             }
300             else
301             {
302                 qDebug("no creator pid found. Ignoring surface!");
303             }
304         }
305         else
306         {
307             qDebug("Surface destroyed, ID: %d", id);
308             mp_surfaces->erase(mp_surfaces->find(id));
309             ilm_surfaceRemoveNotification(id);
310
311             ilm_commitChanges();
312         }
313     }
314     if (ILM_LAYER == object)
315     {
316         //qDebug("Layer.. we don't care...");
317     }
318 }
319
320 void WindowManager::notificationFunc_static(ilmObjectType object,
321                                             t_ilm_uint id,
322                                             t_ilm_bool created,
323                                             void* user_data)
324 {
325     static_cast<WindowManager*>(WindowManager::myThis)->notificationFunc_non_static(object, id, created);
326 }
327
328
329
330
331 void WindowManager::surfaceCallbackFunction_non_static(t_ilm_surface surface,
332                                     struct ilmSurfaceProperties* surfaceProperties,
333                                     t_ilm_notification_mask mask)
334 {
335     qDebug("-=[surfaceCallbackFunction_non_static]=-");
336     qDebug("surfaceCallbackFunction_non_static changes for surface %d", surface);
337     if (ILM_NOTIFICATION_VISIBILITY & mask)
338     {
339         qDebug("ILM_NOTIFICATION_VISIBILITY");
340     }
341
342     if (ILM_NOTIFICATION_OPACITY & mask)
343     {
344         qDebug("ILM_NOTIFICATION_OPACITY");
345     }
346
347     if (ILM_NOTIFICATION_ORIENTATION & mask)
348     {
349         qDebug("ILM_NOTIFICATION_ORIENTATION");
350     }
351
352     if (ILM_NOTIFICATION_SOURCE_RECT & mask)
353     {
354         qDebug("ILM_NOTIFICATION_SOURCE_RECT");
355     }
356
357     if (ILM_NOTIFICATION_DEST_RECT & mask)
358     {
359         qDebug("ILM_NOTIFICATION_DEST_RECT");
360     }
361 }
362
363 void WindowManager::surfaceCallbackFunction_static(t_ilm_surface surface,
364                                     struct ilmSurfaceProperties* surfaceProperties,
365                                     t_ilm_notification_mask mask)
366
367 {
368     static_cast<WindowManager*>(WindowManager::myThis)->surfaceCallbackFunction_non_static(surface, surfaceProperties, mask);
369 }
370 #endif
371
372 int WindowManager::addLayout(int layoutId, const QString &layoutName, const QList<SimpleRect> &surfaceAreas)
373 {
374     qDebug("-=[addLayout]=-");
375     m_layouts.insert(layoutId, surfaceAreas);
376     m_layoutNames.insert(layoutId, layoutName);
377     qDebug("addLayout %d %s, size %d", layoutId, layoutName.toStdString().c_str(), surfaceAreas.size());
378
379     dumpScene();
380
381     return true;
382 }
383
384 QList<int> WindowManager::getAvailableLayouts(int numberOfAppSurfaces)
385 {
386     qDebug("-=[getAvailableLayouts]=-");
387     QMap<int, QList<SimpleRect> >::iterator i = m_layouts.begin();
388
389     QList<int> result;
390     while (i != m_layouts.constEnd())
391     {
392         if (i.value().size() == numberOfAppSurfaces)
393         {
394             result.append(i.key());
395         }
396
397         ++i;
398     }
399
400     return result;
401 }
402
403 // maybe not needed anymore
404 QList<SimplePoint> WindowManager::getAvailableSurfaces()
405 {
406     qDebug("-=[getAvailableSurfaces]=-");
407     QList<SimplePoint> points;
408     SimplePoint point;
409     point.x = 1;
410     point.y = 2;
411     points.append(point);
412     point.x = 11;
413     point.y = 22;
414     points.append(point);
415     point.x = 111;
416     point.y = 222;
417     points.append(point);
418
419     return points;
420 }
421
422 int WindowManager::getLayout()
423 {
424     qDebug("-=[getLayout]=-");
425     return m_currentLayout;
426 }
427
428 QString WindowManager::getLayoutName(int layoutId)
429 {
430     qDebug("-=[getLayoutName]=-");
431     return m_layoutNames.find(layoutId).value();
432 }
433
434 void WindowManager::setLayoutById(int layoutId)
435 {
436     qDebug("-=[setLayoutById]=-");
437     m_currentLayout = layoutId;
438
439     mp_layoutAreaToPidAssignment->clear();
440
441     dumpScene();
442 }
443
444 void WindowManager::setLayoutByName(const QString &layoutName)
445 {
446     qDebug("-=[setLayoutByName]=-");
447     QMap<int, QString>::iterator i = m_layoutNames.begin();
448     while (i != m_layoutNames.constEnd())
449     {
450         if (i.value() == layoutName)
451         {
452             m_currentLayout = i.key();
453         }
454         ++i;
455     }
456
457     mp_layoutAreaToPidAssignment->clear();
458
459     dumpScene();
460 }
461
462 void WindowManager::setPidToLayoutArea(int pid, int layoutAreaId)
463 {
464     qDebug("-=[setPidToLayoutArea]=-");
465     qDebug("pid %d", pid);
466     qDebug("layoutAreaId %d", layoutAreaId);
467     mp_layoutAreaToPidAssignment->insert(layoutAreaId, pid);
468
469 #ifdef __arm__
470     updateScreen();
471 #endif
472
473     dumpScene();
474 }