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