-Make the SampleNav app yellow.
[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 // three layers will be defined. The HomeScreen will be placed
27 // full screen in the background.
28 // On top all applications in one layer.
29 // On top of that, the popup layer.
30 #define WINDOWMANAGER_LAYER_POPUP 100
31 #define WINDOWMANAGER_LAYER_APPLICATIONS 101
32 #define WINDOWMANAGER_LAYER_HOMESCREEN 102
33
34 #define WINDOWMANAGER_LAYER_NUM 3
35
36 // the HomeScreen app has to have the surface id 1000
37 #define WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID 1000
38
39
40 void* WindowManager::myThis = 0;
41
42 WindowManager::WindowManager(QObject *parent) :
43     QObject(parent),
44     m_layouts(),
45     m_surfaces(),
46     mp_layoutAreaToSurfaceIdAssignment(0),
47     m_currentLayout(-1)
48 {
49     qDebug("-=[WindowManager]=-");
50     // publish windowmanager interface
51     mp_windowManagerAdaptor = new WindowmanagerAdaptor((QObject*)this);
52
53     QDBusConnection dbus = QDBusConnection::sessionBus();
54     dbus.registerObject("/windowmanager", this);
55     dbus.registerService("org.agl.windowmanager");
56 }
57
58 void WindowManager::start()
59 {
60     qDebug("-=[start]=-");
61     mp_layoutAreaToSurfaceIdAssignment = new QMap<int, unsigned int>;
62 #ifdef __arm__
63     ilmErrorTypes err;
64
65     err = ilm_init();
66     qDebug("ilm_init = %d", err);
67
68     myThis = this;
69     err =  ilm_registerNotification(WindowManager::notificationFunc_static, this);
70
71     createNewLayer(WINDOWMANAGER_LAYER_POPUP);
72     createNewLayer(WINDOWMANAGER_LAYER_APPLICATIONS);
73     createNewLayer(WINDOWMANAGER_LAYER_HOMESCREEN);
74 #endif
75 }
76
77 WindowManager::~WindowManager()
78 {
79     qDebug("-=[~WindowManager]=-");
80     delete mp_windowManagerAdaptor;
81 #ifdef __arm__
82     ilm_destroy();
83 #endif
84     delete mp_layoutAreaToSurfaceIdAssignment;
85 }
86
87 void WindowManager::dumpScene()
88 {
89     qDebug("\n");
90     qDebug("current layout   : %d", m_currentLayout);
91     qDebug("available layouts: %d", m_layouts.size());
92     QList<Layout>::const_iterator i = m_layouts.begin();
93
94     while (i != m_layouts.constEnd())
95     {
96         qDebug("--[id: %d]--[%s]--", i->id, i->name.toStdString().c_str());
97         qDebug("  %d surface areas", i->layoutAreas.size());
98         for (int j = 0; j < i->layoutAreas.size(); ++j)
99         {
100             qDebug("  -area %d", j);
101             qDebug("    -x     : %d", i->layoutAreas.at(j).x);
102             qDebug("    -y     : %d", i->layoutAreas.at(j).y);
103             qDebug("    -width : %d", i->layoutAreas.at(j).width);
104             qDebug("    -height: %d", i->layoutAreas.at(j).height);
105         }
106
107         ++i;
108     }
109 }
110
111 #ifdef __arm__
112
113 void WindowManager::createNewLayer(int layerId)
114 {
115     qDebug("-=[createNewLayer]=-");
116     qDebug("layerId %d", layerId);
117
118     t_ilm_uint screenID = 0;
119     t_ilm_uint width;
120     t_ilm_uint height;
121
122     ilm_getScreenResolution(screenID, &width, &height);
123
124     t_ilm_layer newLayerId = layerId;
125     ilm_layerCreateWithDimension(&newLayerId, width, height);
126     ilm_layerSetOpacity(newLayerId, 1.0);
127     ilm_layerSetVisibility(newLayerId, ILM_TRUE);
128     ilm_layerSetSourceRectangle(newLayerId,
129                                     0,
130                                     0,
131                                     width,
132                                     height);
133     ilm_layerSetDestinationRectangle(newLayerId,
134                                     0,
135                                     0,
136                                     width,
137                                     height);
138
139     ilm_commitChanges();
140 }
141
142 void WindowManager::addSurfaceToLayer(int surfaceId, int layerId)
143 {
144     qDebug("-=[addSurfaceToLayer]=-");
145     qDebug("surfaceId %d", surfaceId);
146     qDebug("layerId %d", layerId);
147
148     if (layerId == WINDOWMANAGER_LAYER_HOMESCREEN)
149     {
150         struct ilmSurfaceProperties surfaceProperties;
151         ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
152
153         qDebug("sourceX %d", surfaceProperties.sourceX);
154         qDebug("sourceY %d", surfaceProperties.sourceY);
155         qDebug("sourceWidth %d", surfaceProperties.sourceWidth);
156         qDebug("sourceHeight %d", surfaceProperties.sourceHeight);
157
158         // homescreen app always fullscreen in the back
159         t_ilm_uint screenID = 0;
160         t_ilm_uint width;
161         t_ilm_uint height;
162
163         ilm_getScreenResolution(screenID, &width, &height);
164
165         ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, width, height);
166         ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, width, height);
167         ilm_surfaceSetOpacity(surfaceId, 1.0);
168         ilm_surfaceSetVisibility(surfaceId, ILM_TRUE);
169
170         ilm_layerAddSurface(layerId, surfaceId);
171     }
172
173     if (layerId == WINDOWMANAGER_LAYER_APPLICATIONS)
174     {
175         struct ilmSurfaceProperties surfaceProperties;
176         ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
177
178         ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
179         ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
180         ilm_surfaceSetOpacity(surfaceId, 0.0);
181         ilm_surfaceSetVisibility(surfaceId, ILM_FALSE);
182
183         ilm_layerAddSurface(layerId, surfaceId);
184     }
185
186     if (layerId == WINDOWMANAGER_LAYER_POPUP)
187     {
188         struct ilmSurfaceProperties surfaceProperties;
189         ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
190
191         ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
192         ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
193         ilm_surfaceSetOpacity(surfaceId, 0.0);
194         ilm_surfaceSetVisibility(surfaceId, ILM_FALSE);
195
196         ilm_layerAddSurface(layerId, surfaceId);
197     }
198
199     ilm_commitChanges();
200 }
201
202 #endif
203
204 void WindowManager::updateScreen()
205 {
206     qDebug("-=[updateScreen]=-");
207
208 #ifdef __arm__
209     if (-1 != m_currentLayout)
210     {
211
212         // hide all surfaces
213         for (int i = 0; i < m_surfaces.size(); ++i)
214         {
215             ilm_surfaceSetVisibility(m_surfaces.at(i), ILM_FALSE);
216             ilm_surfaceSetOpacity(m_surfaces.at(i), 0.0);
217         }
218
219         // find the current used layout
220         QList<Layout>::const_iterator ci = m_layouts.begin();
221
222         Layout currentLayout;
223         while (ci != m_layouts.constEnd())
224         {
225             if (ci->id == m_currentLayout)
226             {
227                 currentLayout = *ci;
228             }
229
230             ++ci;
231         }
232
233         qDebug("show %d apps", mp_layoutAreaToSurfaceIdAssignment->size());
234         for (int j = 0; j < mp_layoutAreaToSurfaceIdAssignment->size(); ++j)
235         {
236             int surfaceToShow = mp_layoutAreaToSurfaceIdAssignment->find(j).value();
237             qDebug("  surface no. %d: %d", j, surfaceToShow);
238
239             ilm_surfaceSetVisibility(surfaceToShow, ILM_TRUE);
240             ilm_surfaceSetOpacity(surfaceToShow, 1.0);
241
242             qDebug("  layout area %d", j);
243             qDebug("    x: %d", currentLayout.layoutAreas[j].x);
244             qDebug("    y: %d", currentLayout.layoutAreas[j].y);
245             qDebug("    w: %d", currentLayout.layoutAreas[j].width);
246             qDebug("    h: %d", currentLayout.layoutAreas[j].height);
247
248             ilm_surfaceSetDestinationRectangle(surfaceToShow,
249                                              currentLayout.layoutAreas[j].x,
250                                              currentLayout.layoutAreas[j].y,
251                                              currentLayout.layoutAreas[j].width,
252                                              currentLayout.layoutAreas[j].height);
253         }
254
255         ilm_commitChanges();
256     }
257
258     t_ilm_layer renderOrder[WINDOWMANAGER_LAYER_NUM];
259     renderOrder[0] = WINDOWMANAGER_LAYER_HOMESCREEN;
260     renderOrder[1] = WINDOWMANAGER_LAYER_APPLICATIONS;
261     renderOrder[2] = WINDOWMANAGER_LAYER_POPUP;
262
263     ilm_displaySetRenderOrder(0, renderOrder, WINDOWMANAGER_LAYER_NUM);
264
265     ilm_commitChanges();
266
267 #endif
268 }
269
270 #ifdef __arm__
271 void WindowManager::notificationFunc_non_static(ilmObjectType object,
272                                     t_ilm_uint id,
273                                     t_ilm_bool created)
274 {
275     qDebug("-=[notificationFunc_non_static]=-");
276     qDebug("Notification from weston!");
277     if (ILM_SURFACE == object)
278     {
279         struct ilmSurfaceProperties surfaceProperties;
280
281         if (created)
282         {
283             qDebug("Surface created, ID: %d", id);
284             ilm_getPropertiesOfSurface(id, &surfaceProperties);
285             qDebug("  origSourceWidth : %d", surfaceProperties.origSourceWidth);
286             qDebug("  origSourceHeight: %d", surfaceProperties.origSourceHeight);
287
288             if (WINDOWMANAGER_HOMESCREEN_MAIN_SURFACE_ID == id)
289             {
290                 qDebug("HomeScreen app detected");
291                 addSurfaceToLayer(id, WINDOWMANAGER_LAYER_HOMESCREEN);
292                 updateScreen();
293             }
294             else
295             {
296                 addSurfaceToLayer(id, WINDOWMANAGER_LAYER_APPLICATIONS);
297
298                 m_surfaces.append(id);
299             }
300             ilm_surfaceAddNotification(id, surfaceCallbackFunction_static);
301
302             ilm_commitChanges();
303         }
304         else
305         {
306             qDebug("Surface destroyed, ID: %d", id);
307             m_surfaces.removeAt(m_surfaces.indexOf(id));
308             ilm_surfaceRemoveNotification(id);
309
310             ilm_commitChanges();
311         }
312     }
313     if (ILM_LAYER == object)
314     {
315         //qDebug("Layer.. we don't care...");
316     }
317 }
318
319 void WindowManager::notificationFunc_static(ilmObjectType object,
320                                             t_ilm_uint id,
321                                             t_ilm_bool created,
322                                             void* user_data)
323 {
324     static_cast<WindowManager*>(WindowManager::myThis)->notificationFunc_non_static(object, id, created);
325 }
326
327 void WindowManager::surfaceCallbackFunction_non_static(t_ilm_surface surface,
328                                     struct ilmSurfaceProperties* surfaceProperties,
329                                     t_ilm_notification_mask mask)
330 {
331     qDebug("-=[surfaceCallbackFunction_non_static]=-");
332     qDebug("surfaceCallbackFunction_non_static changes for surface %d", surface);
333     if (ILM_NOTIFICATION_VISIBILITY & mask)
334     {
335         qDebug("ILM_NOTIFICATION_VISIBILITY");
336     }
337     if (ILM_NOTIFICATION_OPACITY & mask)
338     {
339         qDebug("ILM_NOTIFICATION_OPACITY");
340     }
341     if (ILM_NOTIFICATION_ORIENTATION & mask)
342     {
343         qDebug("ILM_NOTIFICATION_ORIENTATION");
344     }
345     if (ILM_NOTIFICATION_SOURCE_RECT & mask)
346     {
347         qDebug("ILM_NOTIFICATION_SOURCE_RECT");
348     }
349     if (ILM_NOTIFICATION_DEST_RECT & mask)
350     {
351         qDebug("ILM_NOTIFICATION_DEST_RECT");
352     }
353     if (ILM_NOTIFICATION_CONTENT_AVAILABLE & mask)
354     {
355         qDebug("ILM_NOTIFICATION_CONTENT_AVAILABLE");
356     }
357     if (ILM_NOTIFICATION_CONTENT_REMOVED & mask)
358     {
359         qDebug("ILM_NOTIFICATION_CONTENT_REMOVED");
360     }
361     if (ILM_NOTIFICATION_CONFIGURED & mask)
362     {
363         qDebug("ILM_NOTIFICATION_CONFIGURED");
364         updateScreen();
365     }
366 }
367
368 void WindowManager::surfaceCallbackFunction_static(t_ilm_surface surface,
369                                     struct ilmSurfaceProperties* surfaceProperties,
370                                     t_ilm_notification_mask mask)
371
372 {
373     static_cast<WindowManager*>(WindowManager::myThis)->surfaceCallbackFunction_non_static(surface, surfaceProperties, mask);
374 }
375 #endif
376
377 int WindowManager::layoutId() const
378 {
379     return m_currentLayout;
380 }
381
382 QString WindowManager::layoutName() const
383 {
384     QList<Layout>::const_iterator i = m_layouts.begin();
385
386     QString result = "not found";
387     while (i != m_layouts.constEnd())
388     {
389         if (i->id == m_currentLayout)
390         {
391             result = i->name;
392         }
393
394         ++i;
395     }
396
397     return result;
398 }
399
400
401 int WindowManager::addLayout(int layoutId, const QString &layoutName, const QList<LayoutArea> &surfaceAreas)
402 {
403     qDebug("-=[addLayout]=-");
404     m_layouts.append(Layout(layoutId, layoutName, surfaceAreas));
405
406     qDebug("addLayout %d %s, size %d",
407            layoutId,
408            layoutName.toStdString().c_str(),
409            surfaceAreas.size());
410
411     dumpScene();
412
413     return WINDOWMANAGER_NO_ERROR;
414 }
415
416 int WindowManager::deleteLayoutById(int layoutId)
417 {
418     qDebug("-=[deleteLayoutById]=-");
419     qDebug("layoutId: %d", layoutId);
420     int result = WINDOWMANAGER_NO_ERROR;
421
422     if (m_currentLayout == layoutId)
423     {
424         result = WINDOWMANAGER_ERROR_ID_IN_USE;
425     }
426     else
427     {
428         QList<Layout>::iterator i = m_layouts.begin();
429         result = WINDOWMANAGER_ERROR_ID_IN_USE;
430         while (i != m_layouts.constEnd())
431         {
432             if (i->id == layoutId)
433             {
434                 m_layouts.erase(i);
435                 result = WINDOWMANAGER_NO_ERROR;
436                 break;
437             }
438
439             ++i;
440         }
441     }
442
443     return result;
444 }
445
446
447 QList<Layout> WindowManager::getAllLayouts()
448 {
449     qDebug("-=[getAllLayouts]=-");
450
451     return m_layouts;
452 }
453
454 QList<int> WindowManager::getAllSurfacesOfProcess(int pid)
455 {
456     QList<int> result;
457 #ifdef __arm__
458     struct ilmSurfaceProperties surfaceProperties;
459
460     for (int i = 0; i < m_surfaces.size(); ++i)
461     {
462         ilm_getPropertiesOfSurface(m_surfaces.at(i), &surfaceProperties);
463         if (pid == surfaceProperties.creatorPid)
464         {
465             result.append(m_surfaces.at(i));
466         }
467     }
468 #endif
469     return result;
470 }
471
472 QList<int> WindowManager::getAvailableLayouts(int numberOfAppSurfaces)
473 {
474     qDebug("-=[getAvailableLayouts]=-");
475     QList<Layout>::const_iterator i = m_layouts.begin();
476
477     QList<int> result;
478     while (i != m_layouts.constEnd())
479     {
480         if (i->layoutAreas.size() == numberOfAppSurfaces)
481         {
482             result.append(i->id);
483         }
484
485         ++i;
486     }
487
488     return result;
489 }
490
491 QList<int> WindowManager::getAvailableSurfaces()
492 {
493     qDebug("-=[getAvailableSurfaces]=-");
494
495     return m_surfaces;
496 }
497
498 QString WindowManager::getLayoutName(int layoutId)
499 {
500     qDebug("-=[getLayoutName]=-");
501     QList<Layout>::const_iterator i = m_layouts.begin();
502
503     QString result = "not found";
504     while (i != m_layouts.constEnd())
505     {
506         if (i->id == layoutId)
507         {
508             result = i->name;
509         }
510
511         ++i;
512     }
513
514     return result;
515 }
516
517 void WindowManager::hideLayer(int layer)
518 {
519     qDebug("-=[hideLayer]=-");
520     qDebug("layer %d", layer);
521
522 #ifdef __arm__
523     if (0 == layer)
524     {
525         ilm_layerSetVisibility(WINDOWMANAGER_LAYER_POPUP, ILM_FALSE);
526     }
527     if (1 == layer)
528     {
529         ilm_layerSetVisibility(WINDOWMANAGER_LAYER_APPLICATIONS, ILM_FALSE);
530     }
531     if (2 == layer)
532     {
533         ilm_layerSetVisibility(WINDOWMANAGER_LAYER_HOMESCREEN, ILM_FALSE);
534     }
535     ilm_commitChanges();
536 #endif
537 }
538
539 int WindowManager::setLayoutById(int layoutId)
540 {
541     qDebug("-=[setLayoutById]=-");
542     int result = WINDOWMANAGER_NO_ERROR;
543     m_currentLayout = layoutId;
544
545     mp_layoutAreaToSurfaceIdAssignment->clear();
546
547     dumpScene();
548
549     return result;
550 }
551
552 int WindowManager::setLayoutByName(const QString &layoutName)
553 {
554     qDebug("-=[setLayoutByName]=-");
555     int result = WINDOWMANAGER_NO_ERROR;
556
557     QList<Layout>::const_iterator i = m_layouts.begin();
558
559     while (i != m_layouts.constEnd())
560     {
561         if (i->name == layoutName)
562         {
563             m_currentLayout = i->id;
564
565             mp_layoutAreaToSurfaceIdAssignment->clear();
566
567             dumpScene();
568         }
569
570         ++i;
571     }
572
573     return result;
574 }
575
576 int WindowManager::setSurfaceToLayoutArea(int surfaceId, int layoutAreaId)
577 {
578     qDebug("-=[setSurfaceToLayoutArea]=-");
579     int result = WINDOWMANAGER_NO_ERROR;
580
581     qDebug("surfaceId %d", surfaceId);
582     qDebug("layoutAreaId %d", layoutAreaId);
583     mp_layoutAreaToSurfaceIdAssignment->insert(layoutAreaId, surfaceId);
584
585     updateScreen();
586
587     dumpScene();
588
589     return result;
590 }
591
592 void WindowManager::showLayer(int layer)
593 {
594     qDebug("-=[showLayer]=-");
595     qDebug("layer %d", layer);
596
597 #ifdef __arm__
598     if (0 == layer)
599     {
600         ilm_layerSetVisibility(WINDOWMANAGER_LAYER_POPUP, ILM_TRUE);
601     }
602     if (1 == layer)
603     {
604         ilm_layerSetVisibility(WINDOWMANAGER_LAYER_APPLICATIONS, ILM_TRUE);
605     }
606     if (2 == layer)
607     {
608         ilm_layerSetVisibility(WINDOWMANAGER_LAYER_HOMESCREEN, ILM_TRUE);
609     }
610     ilm_commitChanges();
611 #endif
612 }