HomeScreen is now visible independent of the Layout set.
[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 void* WindowManager::myThis = 0;
37
38 WindowManager::WindowManager(QObject *parent) :
39     QObject(parent),
40     m_layouts(),
41     m_surfaces(),
42     mp_layoutAreaToSurfaceIdAssignment(0),
43     m_currentLayout(-1),
44     m_homeScreenPid(-1)
45 {
46     qDebug("-=[WindowManager]=-");
47     // publish windowmanager interface
48     mp_windowManagerAdaptor = new WindowmanagerAdaptor((QObject*)this);
49
50     QDBusConnection dbus = QDBusConnection::sessionBus();
51     dbus.registerObject("/windowmanager", this);
52     dbus.registerService("org.agl.windowmanager");
53 }
54
55 void WindowManager::start()
56 {
57     qDebug("-=[start]=-");
58     mp_layoutAreaToSurfaceIdAssignment = new QMap<int, unsigned int>;
59 #ifdef __arm__
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
68     createNewLayer(WINDOWMANAGER_LAYER_POPUP);
69     createNewLayer(WINDOWMANAGER_LAYER_APPLICATIONS);
70     createNewLayer(WINDOWMANAGER_LAYER_HOMESCREEN);
71 #endif
72 }
73
74 WindowManager::~WindowManager()
75 {
76     qDebug("-=[~WindowManager]=-");
77     delete mp_windowManagerAdaptor;
78 #ifdef __arm__
79     ilm_destroy();
80 #endif
81     delete mp_layoutAreaToSurfaceIdAssignment;
82 }
83
84 void WindowManager::dumpScene()
85 {
86     qDebug("\n");
87     qDebug("current layout   : %d", m_currentLayout);
88     qDebug("available layouts: %d", m_layouts.size());
89     QList<Layout>::const_iterator i = m_layouts.begin();
90
91     while (i != m_layouts.constEnd())
92     {
93         qDebug("--[id: %d]--[%s]--", i->id, i->name.toStdString().c_str());
94         qDebug("  %d surface areas", i->layoutAreas.size());
95         for (int j = 0; j < i->layoutAreas.size(); ++j)
96         {
97             qDebug("  -area %d", j);
98             qDebug("    -x     : %d", i->layoutAreas.at(j).x);
99             qDebug("    -y     : %d", i->layoutAreas.at(j).y);
100             qDebug("    -width : %d", i->layoutAreas.at(j).width);
101             qDebug("    -height: %d", i->layoutAreas.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
115     t_ilm_uint screenID = 0;
116     t_ilm_uint width;
117     t_ilm_uint height;
118
119     ilm_getScreenResolution(screenID, &width, &height);
120
121     t_ilm_layer newLayerId = layerId;
122     ilm_layerCreateWithDimension(&newLayerId, width, height);
123     ilm_layerSetOpacity(newLayerId, 1.0);
124     ilm_layerSetVisibility(newLayerId, ILM_TRUE);
125     ilm_layerSetSourceRectangle(newLayerId,
126                                     0,
127                                     0,
128                                     width,
129                                     height);
130     ilm_layerSetDestinationRectangle(newLayerId,
131                                     0,
132                                     0,
133                                     width,
134                                     height);
135
136     ilm_commitChanges();
137 }
138
139 void WindowManager::addSurfaceToLayer(int surfaceId, int layerId)
140 {
141     qDebug("-=[addSurfaceToLayer]=-");
142     qDebug("surfaceId %d", surfaceId);
143     qDebug("layerId %d", layerId);
144
145     if (layerId == WINDOWMANAGER_LAYER_HOMESCREEN)
146     {
147         struct ilmSurfaceProperties surfaceProperties;
148         ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
149
150         qDebug("sourceX %d", surfaceProperties.sourceX);
151         qDebug("sourceY %d", surfaceProperties.sourceY);
152         qDebug("sourceWidth %d", surfaceProperties.sourceWidth);
153         qDebug("sourceHeight %d", surfaceProperties.sourceHeight);
154
155         // homescreen app always fullscreen in the back
156         t_ilm_uint screenID = 0;
157         t_ilm_uint width;
158         t_ilm_uint height;
159
160         ilm_getScreenResolution(screenID, &width, &height);
161
162         ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, width, height);
163         ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
164         ilm_surfaceSetOpacity(surfaceId, 1.0);
165         ilm_surfaceSetVisibility(surfaceId, ILM_TRUE);
166
167         ilm_layerAddSurface(layerId, surfaceId);
168     }
169
170     if (layerId == WINDOWMANAGER_LAYER_APPLICATIONS)
171     {
172         struct ilmSurfaceProperties surfaceProperties;
173         ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
174
175         ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
176         ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
177         ilm_surfaceSetOpacity(surfaceId, 0.0);
178         ilm_surfaceSetVisibility(surfaceId, ILM_FALSE);
179
180         ilm_layerAddSurface(layerId, surfaceId);
181     }
182
183     if (layerId == WINDOWMANAGER_LAYER_POPUP)
184     {
185         struct ilmSurfaceProperties surfaceProperties;
186         ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
187
188         ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
189         ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
190         ilm_surfaceSetOpacity(surfaceId, 0.0);
191         ilm_surfaceSetVisibility(surfaceId, ILM_FALSE);
192
193         ilm_layerAddSurface(layerId, surfaceId);
194     }
195
196     ilm_commitChanges();
197 }
198
199 #endif
200
201 void WindowManager::updateScreen()
202 {
203     qDebug("-=[updateScreen]=-");
204
205 #ifdef __arm__
206     if (-1 != m_currentLayout)
207     {
208
209         // hide all surfaces
210         for (int i = 0; i < m_surfaces.size(); ++i)
211         {
212             ilm_surfaceSetVisibility(m_surfaces.at(i), ILM_FALSE);
213             ilm_surfaceSetOpacity(m_surfaces.at(i), 0.0);
214         }
215
216         // find the current used layout
217         QList<Layout>::const_iterator ci = m_layouts.begin();
218
219         Layout currentLayout;
220         while (ci != m_layouts.constEnd())
221         {
222             if (ci->id == m_currentLayout)
223             {
224                 currentLayout = *ci;
225             }
226
227             ++ci;
228         }
229
230         qDebug("show %d apps", mp_layoutAreaToSurfaceIdAssignment->size());
231         for (int j = 0; j < mp_layoutAreaToSurfaceIdAssignment->size(); ++j)
232         {
233             int surfaceToShow = mp_layoutAreaToSurfaceIdAssignment->find(j).value();
234             qDebug("  surface no. %d: %d", j, surfaceToShow);
235
236             ilm_surfaceSetVisibility(surfaceToShow, ILM_TRUE);
237             ilm_surfaceSetOpacity(surfaceToShow, 1.0);
238
239             qDebug("  layout area %d", j);
240             qDebug("    x: %d", currentLayout.layoutAreas[j].x);
241             qDebug("    y: %d", currentLayout.layoutAreas[j].y);
242             qDebug("    w: %d", currentLayout.layoutAreas[j].width);
243             qDebug("    h: %d", currentLayout.layoutAreas[j].height);
244
245             ilm_surfaceSetDestinationRectangle(surfaceToShow,
246                                              currentLayout.layoutAreas[j].x,
247                                              currentLayout.layoutAreas[j].y,
248                                              currentLayout.layoutAreas[j].width,
249                                              currentLayout.layoutAreas[j].height);
250         }
251
252         ilm_commitChanges();
253     }
254
255     t_ilm_layer renderOrder[WINDOWMANAGER_LAYER_NUM];
256     renderOrder[0] = WINDOWMANAGER_LAYER_HOMESCREEN;
257     renderOrder[1] = WINDOWMANAGER_LAYER_APPLICATIONS;
258     renderOrder[2] = WINDOWMANAGER_LAYER_POPUP;
259
260     ilm_displaySetRenderOrder(0, renderOrder, WINDOWMANAGER_LAYER_NUM);
261
262     ilm_commitChanges();
263
264 #endif
265 }
266
267 #ifdef __arm__
268 void WindowManager::notificationFunc_non_static(ilmObjectType object,
269                                     t_ilm_uint id,
270                                     t_ilm_bool created)
271 {
272     qDebug("-=[notificationFunc_non_static]=-");
273     qDebug("Notification from weston!");
274     if (ILM_SURFACE == object)
275     {
276         struct ilmSurfaceProperties surfaceProperties;
277
278         if (created)
279         {
280             qDebug("Surface created, ID: %d", id);
281             ilm_getPropertiesOfSurface(id, &surfaceProperties);
282             qDebug("  origSourceWidth : %d", surfaceProperties.origSourceWidth);
283             qDebug("  origSourceHeight: %d", surfaceProperties.origSourceHeight);
284
285             if (m_homeScreenPid == surfaceProperties.creatorPid)
286             {
287                 if (m_homeScreenSurfaceId != id)
288                 {
289                     qDebug("HomeScreen app detected");
290                     m_homeScreenSurfaceId = id;
291                     addSurfaceToLayer(id, WINDOWMANAGER_LAYER_HOMESCREEN);
292                     updateScreen();
293                 }
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
339     if (ILM_NOTIFICATION_OPACITY & mask)
340     {
341         qDebug("ILM_NOTIFICATION_OPACITY");
342     }
343
344     if (ILM_NOTIFICATION_ORIENTATION & mask)
345     {
346         qDebug("ILM_NOTIFICATION_ORIENTATION");
347     }
348
349     if (ILM_NOTIFICATION_SOURCE_RECT & mask)
350     {
351         qDebug("ILM_NOTIFICATION_SOURCE_RECT");
352     }
353
354     if (ILM_NOTIFICATION_DEST_RECT & mask)
355     {
356         qDebug("ILM_NOTIFICATION_DEST_RECT");
357     }
358 }
359
360 void WindowManager::surfaceCallbackFunction_static(t_ilm_surface surface,
361                                     struct ilmSurfaceProperties* surfaceProperties,
362                                     t_ilm_notification_mask mask)
363
364 {
365     static_cast<WindowManager*>(WindowManager::myThis)->surfaceCallbackFunction_non_static(surface, surfaceProperties, mask);
366 }
367 #endif
368
369
370 int WindowManager::homeScreenPid() const
371 {
372     return m_homeScreenPid;
373 }
374
375 void WindowManager::setHomeScreenPid(int value)
376 {
377     m_homeScreenPid = value;
378 #ifdef __arm__
379     // maybe the HomeSceen app has already provided its surface.
380     // if so, shift it to the correct layer
381     // find the current used layout
382     QList<int>::iterator ci = m_surfaces.begin();
383
384     struct ilmSurfaceProperties surfaceProperties;
385     bool found = false;
386     while ((!found) && (ci != m_surfaces.constEnd()))
387     {
388         ilm_getPropertiesOfSurface(*ci, &surfaceProperties);
389         if (m_homeScreenPid == surfaceProperties.creatorPid)
390         {
391             qDebug("HomeScreen app detected");
392             m_homeScreenSurfaceId = *ci;
393             addSurfaceToLayer(*ci, WINDOWMANAGER_LAYER_HOMESCREEN);
394             m_surfaces.erase(ci);
395             found = true;
396             updateScreen();
397         }
398
399         ++ci;
400     }
401 #endif
402
403     updateScreen();
404     dumpScene();
405 }
406
407 int WindowManager::layoutId() const
408 {
409     return m_currentLayout;
410 }
411
412 QString WindowManager::layoutName() const
413 {
414     QList<Layout>::const_iterator i = m_layouts.begin();
415
416     QString result = "not found";
417     while (i != m_layouts.constEnd())
418     {
419         if (i->id == m_currentLayout)
420         {
421             result = i->name;
422         }
423
424         ++i;
425     }
426
427     return result;
428 }
429
430
431 int WindowManager::addLayout(int layoutId, const QString &layoutName, const QList<LayoutArea> &surfaceAreas)
432 {
433     qDebug("-=[addLayout]=-");
434     m_layouts.append(Layout(layoutId, layoutName, surfaceAreas));
435
436     qDebug("addLayout %d %s, size %d",
437            layoutId,
438            layoutName.toStdString().c_str(),
439            surfaceAreas.size());
440
441     dumpScene();
442
443     return WINDOWMANAGER_NO_ERROR;
444 }
445
446 QList<Layout> WindowManager::getAllLayouts()
447 {
448     qDebug("-=[getAllLayouts]=-");
449
450     return m_layouts;
451 }
452
453 QList<int> WindowManager::getAvailableLayouts(int numberOfAppSurfaces)
454 {
455     qDebug("-=[getAvailableLayouts]=-");
456     QList<Layout>::const_iterator i = m_layouts.begin();
457
458     QList<int> result;
459     while (i != m_layouts.constEnd())
460     {
461         if (i->layoutAreas.size() == numberOfAppSurfaces)
462         {
463             result.append(i->id);
464         }
465
466         ++i;
467     }
468
469     return result;
470 }
471
472 QList<int> WindowManager::getAvailableSurfaces()
473 {
474     qDebug("-=[getAvailableSurfaces]=-");
475
476     return m_surfaces;
477 }
478
479 QString WindowManager::getLayoutName(int layoutId)
480 {
481     qDebug("-=[getLayoutName]=-");
482     QList<Layout>::const_iterator i = m_layouts.begin();
483
484     QString result = "not found";
485     while (i != m_layouts.constEnd())
486     {
487         if (i->id == layoutId)
488         {
489             result = i->name;
490         }
491
492         ++i;
493     }
494
495     return result;
496 }
497
498
499 int WindowManager::setLayoutById(int layoutId)
500 {
501     qDebug("-=[setLayoutById]=-");
502     int result = WINDOWMANAGER_NO_ERROR;
503     m_currentLayout = layoutId;
504
505     mp_layoutAreaToSurfaceIdAssignment->clear();
506
507     dumpScene();
508
509     return result;
510 }
511
512 int WindowManager::setLayoutByName(const QString &layoutName)
513 {
514     qDebug("-=[setLayoutByName]=-");
515     int result = WINDOWMANAGER_NO_ERROR;
516
517     QList<Layout>::const_iterator i = m_layouts.begin();
518
519     while (i != m_layouts.constEnd())
520     {
521         if (i->name == layoutName)
522         {
523             m_currentLayout = i->id;
524
525             mp_layoutAreaToSurfaceIdAssignment->clear();
526
527             dumpScene();
528         }
529
530         ++i;
531     }
532
533     return result;
534 }
535
536 int WindowManager::setSurfaceToLayoutArea(int surfaceId, int layoutAreaId)
537 {
538     qDebug("-=[setSurfaceToLayoutArea]=-");
539     int result = WINDOWMANAGER_NO_ERROR;
540
541     qDebug("surfaceId %d", surfaceId);
542     qDebug("layoutAreaId %d", layoutAreaId);
543     mp_layoutAreaToSurfaceIdAssignment->insert(layoutAreaId, surfaceId);
544
545     updateScreen();
546
547     dumpScene();
548
549     return result;
550 }