New layer management in WindowManager. Three layers are created. One for the HomeScre...
[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         // homescreen app always fullscreen in the back
151         t_ilm_uint screenID = 0;
152         t_ilm_uint width;
153         t_ilm_uint height;
154
155         ilm_getScreenResolution(screenID, &width, &height);
156
157         ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, width, height);
158         ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
159         ilm_surfaceSetOpacity(surfaceId, 1.0);
160         ilm_surfaceSetVisibility(surfaceId, ILM_TRUE);
161
162         ilm_layerAddSurface(layerId, surfaceId);
163     }
164
165     if (layerId == WINDOWMANAGER_LAYER_APPLICATIONS)
166     {
167         struct ilmSurfaceProperties surfaceProperties;
168         ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
169
170         ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
171         ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
172         ilm_surfaceSetOpacity(surfaceId, 0.0);
173         ilm_surfaceSetVisibility(surfaceId, ILM_FALSE);
174
175         ilm_layerAddSurface(layerId, surfaceId);
176     }
177
178     if (layerId == WINDOWMANAGER_LAYER_POPUP)
179     {
180         struct ilmSurfaceProperties surfaceProperties;
181         ilm_getPropertiesOfSurface(surfaceId, &surfaceProperties);
182
183         ilm_surfaceSetDestinationRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
184         ilm_surfaceSetSourceRectangle(surfaceId, 0, 0, surfaceProperties.origSourceWidth, surfaceProperties.origSourceHeight);
185         ilm_surfaceSetOpacity(surfaceId, 0.0);
186         ilm_surfaceSetVisibility(surfaceId, ILM_FALSE);
187
188         ilm_layerAddSurface(layerId, surfaceId);
189     }
190
191     ilm_commitChanges();
192 }
193
194 #endif
195
196 void WindowManager::updateScreen()
197 {
198     qDebug("-=[updateScreen]=-");
199
200     if (-1 != m_currentLayout)
201     {
202 #ifdef __arm__
203
204         t_ilm_layer renderOrder[WINDOWMANAGER_LAYER_NUM];
205         renderOrder[0] = WINDOWMANAGER_LAYER_HOMESCREEN;
206         renderOrder[1] = WINDOWMANAGER_LAYER_APPLICATIONS;
207         renderOrder[2] = WINDOWMANAGER_LAYER_POPUP;
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_displaySetRenderOrder(0, renderOrder, WINDOWMANAGER_LAYER_NUM);
253
254         ilm_commitChanges();
255 #endif
256     }
257 }
258
259 #ifdef __arm__
260 void WindowManager::notificationFunc_non_static(ilmObjectType object,
261                                     t_ilm_uint id,
262                                     t_ilm_bool created)
263 {
264     qDebug("-=[notificationFunc_non_static]=-");
265     qDebug("Notification from weston!");
266     if (ILM_SURFACE == object)
267     {
268         struct ilmSurfaceProperties surfaceProperties;
269
270         if (created)
271         {
272             qDebug("Surface created, ID: %d", id);
273             ilm_getPropertiesOfSurface(id, &surfaceProperties);
274             qDebug("  origSourceWidth : %d", surfaceProperties.origSourceWidth);
275             qDebug("  origSourceHeight: %d", surfaceProperties.origSourceHeight);
276
277             if (m_homeScreenPid == surfaceProperties.creatorPid)
278             {
279                 if (m_homeScreenSurfaceId != id)
280                 {
281                     qDebug("HomeScreen app detected");
282                     m_homeScreenSurfaceId = id;
283                     addSurfaceToLayer(id, WINDOWMANAGER_LAYER_HOMESCREEN);
284                     updateScreen();
285                 }
286             }
287             else
288             {
289                 addSurfaceToLayer(id, WINDOWMANAGER_LAYER_APPLICATIONS);
290
291                 m_surfaces.append(id);
292             }
293             ilm_surfaceAddNotification(id, surfaceCallbackFunction_static);
294
295             ilm_commitChanges();
296         }
297         else
298         {
299             qDebug("Surface destroyed, ID: %d", id);
300             m_surfaces.removeAt(m_surfaces.indexOf(id));
301             ilm_surfaceRemoveNotification(id);
302
303             ilm_commitChanges();
304         }
305     }
306     if (ILM_LAYER == object)
307     {
308         //qDebug("Layer.. we don't care...");
309     }
310 }
311
312 void WindowManager::notificationFunc_static(ilmObjectType object,
313                                             t_ilm_uint id,
314                                             t_ilm_bool created,
315                                             void* user_data)
316 {
317     static_cast<WindowManager*>(WindowManager::myThis)->notificationFunc_non_static(object, id, created);
318 }
319
320 void WindowManager::surfaceCallbackFunction_non_static(t_ilm_surface surface,
321                                     struct ilmSurfaceProperties* surfaceProperties,
322                                     t_ilm_notification_mask mask)
323 {
324     qDebug("-=[surfaceCallbackFunction_non_static]=-");
325     qDebug("surfaceCallbackFunction_non_static changes for surface %d", surface);
326     if (ILM_NOTIFICATION_VISIBILITY & mask)
327     {
328         qDebug("ILM_NOTIFICATION_VISIBILITY");
329     }
330
331     if (ILM_NOTIFICATION_OPACITY & mask)
332     {
333         qDebug("ILM_NOTIFICATION_OPACITY");
334     }
335
336     if (ILM_NOTIFICATION_ORIENTATION & mask)
337     {
338         qDebug("ILM_NOTIFICATION_ORIENTATION");
339     }
340
341     if (ILM_NOTIFICATION_SOURCE_RECT & mask)
342     {
343         qDebug("ILM_NOTIFICATION_SOURCE_RECT");
344     }
345
346     if (ILM_NOTIFICATION_DEST_RECT & mask)
347     {
348         qDebug("ILM_NOTIFICATION_DEST_RECT");
349     }
350 }
351
352 void WindowManager::surfaceCallbackFunction_static(t_ilm_surface surface,
353                                     struct ilmSurfaceProperties* surfaceProperties,
354                                     t_ilm_notification_mask mask)
355
356 {
357     static_cast<WindowManager*>(WindowManager::myThis)->surfaceCallbackFunction_non_static(surface, surfaceProperties, mask);
358 }
359 #endif
360
361
362 int WindowManager::homeScreenPid() const
363 {
364     return m_homeScreenPid;
365 }
366
367 void WindowManager::setHomeScreenPid(int value)
368 {
369     m_homeScreenPid = value;
370 #ifdef __arm__
371     // maybe the HomeSceen app has already provided its surface.
372     // if so, shift it to the correct layer
373     // find the current used layout
374     QList<int>::iterator ci = m_surfaces.begin();
375
376     struct ilmSurfaceProperties surfaceProperties;
377     bool found = false;
378     while ((!found) && (ci != m_surfaces.constEnd()))
379     {
380         ilm_getPropertiesOfSurface(*ci, &surfaceProperties);
381         if (m_homeScreenPid == surfaceProperties.creatorPid)
382         {
383             qDebug("HomeScreen app detected");
384             m_homeScreenSurfaceId = *ci;
385             addSurfaceToLayer(*ci, WINDOWMANAGER_LAYER_HOMESCREEN);
386             m_surfaces.erase(ci);
387             found = true;
388             updateScreen();
389         }
390
391         ++ci;
392     }
393 #endif
394
395     updateScreen();
396     dumpScene();
397 }
398
399 int WindowManager::layoutId() const
400 {
401     return m_currentLayout;
402 }
403
404 QString WindowManager::layoutName() const
405 {
406     QList<Layout>::const_iterator i = m_layouts.begin();
407
408     QString result = "not found";
409     while (i != m_layouts.constEnd())
410     {
411         if (i->id == m_currentLayout)
412         {
413             result = i->name;
414         }
415
416         ++i;
417     }
418
419     return result;
420 }
421
422
423 int WindowManager::addLayout(int layoutId, const QString &layoutName, const QList<LayoutArea> &surfaceAreas)
424 {
425     qDebug("-=[addLayout]=-");
426     m_layouts.append(Layout(layoutId, layoutName, surfaceAreas));
427
428     qDebug("addLayout %d %s, size %d",
429            layoutId,
430            layoutName.toStdString().c_str(),
431            surfaceAreas.size());
432
433     dumpScene();
434
435     return WINDOWMANAGER_NO_ERROR;
436 }
437
438 QList<Layout> WindowManager::getAllLayouts()
439 {
440     qDebug("-=[getAllLayouts]=-");
441
442     return m_layouts;
443 }
444
445 QList<int> WindowManager::getAvailableLayouts(int numberOfAppSurfaces)
446 {
447     qDebug("-=[getAvailableLayouts]=-");
448     QList<Layout>::const_iterator i = m_layouts.begin();
449
450     QList<int> result;
451     while (i != m_layouts.constEnd())
452     {
453         if (i->layoutAreas.size() == numberOfAppSurfaces)
454         {
455             result.append(i->id);
456         }
457
458         ++i;
459     }
460
461     return result;
462 }
463
464 QList<int> WindowManager::getAvailableSurfaces()
465 {
466     qDebug("-=[getAvailableSurfaces]=-");
467
468     return m_surfaces;
469 }
470
471 QString WindowManager::getLayoutName(int layoutId)
472 {
473     qDebug("-=[getLayoutName]=-");
474     QList<Layout>::const_iterator i = m_layouts.begin();
475
476     QString result = "not found";
477     while (i != m_layouts.constEnd())
478     {
479         if (i->id == layoutId)
480         {
481             result = i->name;
482         }
483
484         ++i;
485     }
486
487     return result;
488 }
489
490
491 int WindowManager::setLayoutById(int layoutId)
492 {
493     qDebug("-=[setLayoutById]=-");
494     int result = WINDOWMANAGER_NO_ERROR;
495     m_currentLayout = layoutId;
496
497     mp_layoutAreaToSurfaceIdAssignment->clear();
498
499     dumpScene();
500
501     return result;
502 }
503
504 int WindowManager::setLayoutByName(const QString &layoutName)
505 {
506     qDebug("-=[setLayoutByName]=-");
507     int result = WINDOWMANAGER_NO_ERROR;
508
509     QList<Layout>::const_iterator i = m_layouts.begin();
510
511     while (i != m_layouts.constEnd())
512     {
513         if (i->name == layoutName)
514         {
515             m_currentLayout = i->id;
516
517             mp_layoutAreaToSurfaceIdAssignment->clear();
518
519             dumpScene();
520         }
521
522         ++i;
523     }
524
525     return result;
526 }
527
528 int WindowManager::setSurfaceToLayoutArea(int surfaceId, int layoutAreaId)
529 {
530     qDebug("-=[setSurfaceToLayoutArea]=-");
531     int result = WINDOWMANAGER_NO_ERROR;
532
533     qDebug("surfaceId %d", surfaceId);
534     qDebug("layoutAreaId %d", layoutAreaId);
535     mp_layoutAreaToSurfaceIdAssignment->insert(layoutAreaId, surfaceId);
536
537     updateScreen();
538
539     dumpScene();
540
541     return result;
542 }