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