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