X11WindowSystem: Fixing parameter assignment
[profile/ivi/layer-management.git] / LayerManagerPlugins / Renderers / Graphic / src / WindowSystems / X11WindowSystem.cpp
1 /***************************************************************************
2 *
3 * Copyright 2010,2011 BMW Car IT GmbH
4 *
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *        http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ****************************************************************************/
19
20 #include "WindowSystems/X11WindowSystem.h"
21 #include "config.h"
22 #include "Log.h"
23 #include "Layer.h"
24 #include "Rectangle.h"
25 #include <time.h>
26 #include <sys/time.h>
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include <X11/Xatom.h>
30 #include <X11/extensions/Xcomposite.h>
31 #include <X11/extensions/Xdamage.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <iomanip>
37
38 int     X11WindowSystem::composite_opcode;
39 int     X11WindowSystem::damage_opcode;
40 const char X11WindowSystem::CompositorWindowTitle[] = "LayerManager";
41 bool    X11WindowSystem::m_xerror = false;
42
43 X11WindowSystem::X11WindowSystem(const char* displayname,
44                                 int width,
45                                 int height,
46                                 Scene* pScene,
47                                 InputManager* pInputManager,
48                                 GetVisualInfoFunction func)
49 : BaseWindowSystem(pScene, pInputManager)
50 , takeScreenshot(ScreenShotNone)
51 , screenShotFile()
52 , screenShotSurfaceID(0)
53 , screenShotLayerID()
54 , displayname(displayname)
55 , getVisualFunc(func)
56 , debugMode(false)
57 , resolutionWidth(width)
58 , resolutionHeight(height)
59 , composite_event(0)
60 , composite_error(0)
61 , composite_major(0)
62 , composite_minor(0)
63 , damage_event(0)
64 , damage_error(0)
65 , damage_major(0)
66 , damage_minor(0)
67 , m_running(false)
68 /*, m_initialized(false)*/
69 , m_success(false)
70 , m_systemState(IDLE_STATE)
71 , m_displayEnvironment(NULL)
72 , x11Display(0)
73 , renderThread(0)
74 , windowWidth(width)
75 , windowHeight(height)
76 , CompositorWindow(0)
77 , windowVis(0)
78 , m_fpsinterval(10.0f)
79 , run_lock()
80 , graphicSystem(0)
81 {
82     LOG_DEBUG("X11WindowSystem", "creating X11WindowSystem");
83
84     // init and take mutex, so windowsystem only does init phase until mutex is released again
85     pthread_mutex_init(&run_lock, NULL);
86     pthread_cond_init(&run_condition, NULL);
87     pthread_cond_init(&init_condition, NULL);
88     pthread_mutex_init(&init_lock, NULL);
89 }
90
91 X11WindowSystem::~X11WindowSystem()
92 {
93     if (windowVis)
94     {
95         delete windowVis;
96     }
97 }
98
99 XVisualInfo* X11WindowSystem::getDefaultVisual(Display *dpy)
100 {
101     XVisualInfo* windowVis = new XVisualInfo();
102     if (windowVis)
103     {
104         windowVis->depth = DefaultDepth(dpy, DefaultScreen(dpy));
105         if (!XMatchVisualInfo(dpy, 0, windowVis->depth, TrueColor, windowVis))
106         {
107             LOG_ERROR("X11WindowSystem", "Error: Required visual not found\n");
108             delete windowVis;
109             return NULL;
110         }
111     }
112     else
113     {
114         LOG_ERROR("X11WindowSystem", "Error: Unable to acquire visual\n");
115     }
116     return windowVis;
117 }
118
119 bool X11WindowSystem::OpenDisplayConnection()
120 {
121     m_displayEnvironment = getenv("DISPLAY");
122
123     if (m_displayEnvironment == NULL)
124     {
125         m_displayEnvironment = ":0.0";
126         setenv("DISPLAY", m_displayEnvironment, 1);
127     }
128
129     x11Display = XOpenDisplay(m_displayEnvironment);
130     if (!x11Display)
131     {
132         LOG_ERROR("X11WindowSystem", "Couldn't open default display!");
133         return false;
134     }
135     LOG_DEBUG("X11WindowSystem", "Display connection: " << x11Display);
136     return true;
137 }
138
139 bool X11WindowSystem::checkForCompositeExtension()
140 {
141     if (x11Display == NULL || !XQueryExtension(x11Display, COMPOSITE_NAME, &composite_opcode, &composite_event, &composite_error))
142     {
143         LOG_ERROR("X11WindowSystem", "No composite extension");
144         return false;
145     }
146     XCompositeQueryVersion(x11Display, &composite_major, &composite_minor);
147     LOG_DEBUG("X11WindowSystem", "Found composite extension: composite opcode: " << composite_opcode);
148     LOG_DEBUG("X11WindowSystem", "composite_major: " << composite_major);
149     LOG_DEBUG("X11WindowSystem", "composite_minor: " << composite_minor);
150     return true;
151 }
152
153 bool X11WindowSystem::checkForDamageExtension()
154 {
155     if (x11Display == NULL || !XQueryExtension(x11Display, DAMAGE_NAME, &damage_opcode,
156                 &damage_event, &damage_error))
157     {
158         LOG_ERROR("X11WindowSystem", "No damage extension");
159         return false;
160     }
161     XDamageQueryVersion(x11Display, &damage_major, &damage_minor);
162     x11DamageRegion = XFixesCreateRegion(x11Display, 0, 0);
163     LOG_DEBUG("X11WindowSystem", "Found damage extension: damage opcode: " << damage_opcode);
164     LOG_DEBUG("X11WindowSystem", "damage_major: " << damage_major);
165     LOG_DEBUG("X11WindowSystem", "damage_minor: " << damage_minor);
166     return true;
167 }
168
169 void X11WindowSystem::printDebug()
170 {
171     // print stuff about layerlist
172     std::stringstream debugmessage;
173     debugmessage << "Layer:  ID |   X  |   Y  |   W  |   H  | Al. \n";
174
175     LayerList list = m_pScene->getCurrentRenderOrder(0);
176
177     // loop the layers
178     LayerListConstIterator iter = list.begin();
179     LayerListConstIterator iterEnd = list.end();
180
181     for (; iter != iterEnd; ++iter)
182     {
183         Rectangle dest = (*iter)->getDestinationRegion();
184         debugmessage << "            " << std::setw(4) << (*iter)->getID() << " " << std::setw(3) << dest.x << " " << std::setw(3) << dest.y << " " << std::setw(3) << dest.width << " " << std::setw(3) << dest.height << " " << std::setw(3) << (*iter)->opacity << "\n";
185
186         debugmessage << "    Surface:  ID |Al.|  SVP: X |  Y |  W |  H     DVP:  X |  Y |  W |  H \n";
187
188         // loop the surfaces of within each layer
189         SurfaceList surfaceList = (*iter)->getAllSurfaces();
190         SurfaceListIterator surfaceIter = surfaceList.begin();
191         SurfaceListIterator surfaceIterEnd = surfaceList.end();
192
193         for (; surfaceIter != surfaceIterEnd; ++surfaceIter)
194         {
195             Rectangle src = (*surfaceIter)->getSourceRegion();
196             Rectangle dest = (*surfaceIter)->getDestinationRegion();
197             debugmessage << "                        " << std::setw(4) << (*surfaceIter)->getID() << " " << std::setprecision(3) << (*surfaceIter)->opacity << " " << std::setw(3) << src.x << " " << std::setw(3) << src.y << " " << std::setw(3) << src.width << " " << std::setw(3) << src.height << " " << std::setw(3) << dest.x << " " << std::setw(3) << dest.y << " " << std::setw(3) << dest.width << " " << std::setw(3) << dest.height << "\n";
198         }
199     }
200     LOG_DEBUG("X11WindowSystem", debugmessage.str());
201 }
202
203 Window * getListOfAllTopLevelWindows(Display *disp, unsigned int *len)
204 {
205     LOG_DEBUG("X11WindowSystem", "Getting list of all windows");
206     Window *children;
207     Window root_return;
208     Window parent_return;
209     Window root = XDefaultRootWindow(disp);
210     XQueryTree(disp, root, &root_return, &parent_return, &children, len);
211     return children;
212 }
213
214 bool X11WindowSystem::isWindowValid(Window w)
215 {
216     // skip our own two windows
217     return (w != None && w != CompositorWindow);
218 }
219
220 Surface* X11WindowSystem::getSurfaceForWindow(Window w)
221 {
222     // go though all surfaces
223     const std::map<unsigned int, Surface*> surfaces = m_pScene->getAllSurfaces();
224     for (std::map<unsigned int, Surface*>::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); ++currentS)
225     {
226         Surface* currentSurface = (*currentS).second;
227         if (!currentSurface)
228         {
229             continue;
230         }
231         if (currentSurface->getNativeContent() == static_cast<int>(w))
232         {
233             return currentSurface;
234         }
235     }
236     LOG_DEBUG("X11WindowSystem", "could not find surface for window " << w);
237     return NULL;
238 }
239
240 void X11WindowSystem::checkForNewSurfaceNativeContent()
241 {
242     m_pScene->lockScene();
243     LayerList layers = m_pScene->getCurrentRenderOrder(0);
244     for (LayerListConstIterator current = layers.begin(); current != layers.end(); current++)
245     {
246         SurfaceList surfaces = (*current)->getAllSurfaces();
247         for (SurfaceListConstIterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++)
248         {
249             if ((*currentS)->hasNativeContent())
250             {
251                 allocatePlatformSurface(*currentS);
252             }
253             else // While we are at it, also cleanup any stale native content
254             {
255                 deallocatePlatformSurface(*currentS);
256             }
257         }
258     }
259     m_pScene->unlockScene();
260 }
261
262 void X11WindowSystem::configureSurfaceWindow(Window window)
263 {
264     if (isWindowValid(window))
265     {
266         LOG_INFO("X11WindowSystem", "Configure surface window " << window);
267
268         XWindowAttributes att;
269         XGetWindowAttributes(x11Display, window, &att);
270         int winWidth = att.width;
271         int winHeight = att.height;
272
273         Surface* surface = getSurfaceForWindow(window);
274         if (!surface)
275         {
276             LOG_WARNING("X11WindowSystem", "Could not find surface for window " << window);
277             return;
278         }
279         LOG_INFO("X11WindowSystem", "Configure surface dimension " << surface->getID());
280
281         if (surface->OriginalSourceHeight != winHeight || surface->OriginalSourceWidth != winWidth)
282         {
283             LOG_INFO("X11WindowSystem","Surface dimension differs from creation dimension");
284             unsigned int layerid = surface->getContainingLayerId();
285             surface->OriginalSourceHeight = winHeight;
286             surface->OriginalSourceWidth = winWidth;
287
288             Rectangle newDestination = surface->getDestinationRegion();
289             newDestination.width = surface->OriginalSourceWidth;
290             newDestination.height = surface->OriginalSourceHeight;
291             surface->setDestinationRegion(newDestination);
292             Rectangle newSource = surface->getSourceRegion();
293             newSource.width = surface->OriginalSourceWidth;
294             newSource.height = surface->OriginalSourceHeight;
295             surface->setSourceRegion(newSource);
296
297             if ( layerid != Surface::INVALID_ID ) 
298             {
299                 surface->calculateTargetDestination(m_pScene->getLayer(layerid)->getSourceRegion()
300                                                     ,m_pScene->getLayer(layerid)->getDestinationRegion());
301             }
302             surface->damaged = false; // Waiting for damage event to get updated content
303             surface->m_surfaceResized = true;
304             LOG_INFO("X11WindowSystem", "Dimension  : " << surface->OriginalSourceWidth << ", " << surface->OriginalSourceHeight);
305             LOG_INFO("X11WindowSystem", "SourceDim  : " << surface->getSourceRegion().width << ", " << surface->getSourceRegion().height);
306             LOG_INFO("X11WindowSystem", "DestDim    : " << surface->getDestinationRegion().width << ", " << surface->getDestinationRegion().height);
307         }
308                 
309         if (!surface->platform)
310         {
311             LOG_WARNING("X11WindowSystem", "Platform surface not available for window " << window);
312             return;
313         }
314
315         UnMapWindow(window);
316         MapWindow(window);        
317         LOG_INFO("X11WindowSystem", "Done configure surface " << surface->getID() << " for window " << window);
318     }
319 }
320
321 void X11WindowSystem::MapWindow(Window window)
322 {
323     LOG_DEBUG("X11WindowSystem", "Map window begin");
324     if (isWindowValid(window))
325     {
326         XWindowAttributes att;
327         XGetWindowAttributes(x11Display, window, &att);
328 /*      LOG_DEBUG("X11WindowSystem", "XCompositeRedirectWindow()");
329         XCompositeRedirectWindow(x11Display, window, CompositeRedirectManual);
330         XSync(x11Display, 0);*/
331         if (att.map_state == IsViewable && att.override_redirect == 0)
332         {
333             LOG_DEBUG("X11WindowSystem", "Mapping surface to window " << window);
334             Surface* surface = getSurfaceForWindow(window);
335             if (!surface)
336             {
337                 LOG_WARNING("X11WindowSystem", "Could not map surface to window " << window);
338                 return;
339             }
340             if (!surface->platform)
341             {
342                 LOG_WARNING("X11WindowSystem", "Platform surface not available for window " << window);
343                 return;
344             }
345
346             XPlatformSurface* x11surf = (XPlatformSurface*)surface->platform;
347             if (x11surf->isMapped)
348             {
349                 LOG_WARNING("X11WindowSystem", "Platform surface already mapped");
350                 return;
351             }
352             x11surf->isMapped = true;
353
354             LOG_DEBUG("X11WindowSystem", "getting pixmap for window");
355             LOG_DEBUG("X11WindowSystem", "window width: " << att.width);
356             LOG_DEBUG("X11WindowSystem", "window height: " << att.height);
357             LOG_DEBUG("X11WindowSystem", "map state: " << att.map_state);
358             LOG_DEBUG("X11WindowSystem", "window x: " << att.x);
359             LOG_DEBUG("X11WindowSystem", "window backing: " << att.backing_pixel);
360             LOG_DEBUG("X11WindowSystem", "window save under: " << att.save_under);
361             LOG_DEBUG("X11WindowSystem", "window orride: " << att.override_redirect);
362             LOG_DEBUG("X11WindowSystem", "parent/root: " << att.root);
363             LOG_DEBUG("X11WindowSystem", "root window: " << DefaultRootWindow(x11Display));
364
365             int winWidth = att.width;
366             int winHeight = att.height;
367
368             surface->OriginalSourceHeight = winHeight;
369             surface->OriginalSourceWidth = winWidth;
370             surface->renderPropertyChanged = true;
371
372             graphicSystem->getTextureBinder()->createClientBuffer(surface);
373             x11surf->enableRendering();
374             XSync(x11Display, 0);
375
376             LOG_DEBUG("X11WindowSystem", "Mapping Surface " << surface->getID() << " to window " << window);
377             LOG_DEBUG("X11WindowSystem", "Mapping successfull");
378         }
379     }
380     LOG_DEBUG("X11WindowSystem", "Map window end");
381 }
382
383 void X11WindowSystem::UnMapWindow(Window window)
384 {
385     LOG_DEBUG("X11WindowSystem", "Unmap begin");
386     if (isWindowValid(window))
387     {
388         LOG_DEBUG("X11WindowSystem", "Unmapping surface from window " << window);
389         Surface* surface = getSurfaceForWindow(window);
390         if (!surface)
391         {
392             LOG_WARNING("X11WindowSystem", "Could not unmap window " << window);
393             return;
394         }
395         if (!surface->platform)
396         {
397             LOG_WARNING("X11WindowSystem", "Platform surface not available for window " << window);
398             return;
399         }
400         XPlatformSurface* x11surf = (XPlatformSurface*)surface->platform;
401         x11surf->disableRendering();
402         LOG_DEBUG("X11WindowSystem", "Unmapping surface " << surface->getID());
403         if (!x11surf->isMapped)
404         {
405             LOG_WARNING("X11WindowSystem", "Platform surface already unmapped");
406             return;
407         }
408         x11surf->isMapped = false;
409
410         LOG_DEBUG("X11WindowSystem", "Destroying ClientBuffer");
411         graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
412         XSync(x11Display, 0);
413
414         LOG_DEBUG("X11WindowSystem", "Removing X Pixmap");
415         if (x11surf->pixmap)
416         {
417             int result = XFreePixmap(x11Display, x11surf->pixmap);
418             LOG_DEBUG("X11WindowSystem", "XFreePixmap() returned " << result);
419         }
420
421         surface->renderPropertyChanged = true;
422     }
423     LOG_DEBUG("X11WindowSystem", "Unmap finished");
424 }
425
426 void X11WindowSystem::NewWindow(Surface* surface, Window window)
427 {
428     if (isWindowValid(window))
429     {
430         LOG_INFO("X11WindowSystem", "Creating Surface for new window " << window);
431         // get the windows attributes
432         XWindowAttributes att;
433         int status = XGetWindowAttributes(x11Display, window, &att);
434         LOG_DEBUG("X11WindowSystem", "Got window attrbutes");
435         char* name;
436         status = XFetchName(x11Display, window, &name);
437         LOG_DEBUG("X11WindowSystem", "Got window name");
438         if (status >= Success && name)
439         {
440             LOG_DEBUG("X11WindowSystem", "Found window: " << window << " " << name);
441             char GuiTitle[]  = "Layermanager Remote GUI\0";
442             if (strcmp(name, GuiTitle) == 0)
443             {
444                 LOG_DEBUG("X11WindowSystem", "Found gui window: repositioning it");
445                 XCompositeUnredirectWindow(x11Display, window, CompositeRedirectManual);
446                 XMoveWindow(x11Display, window, 50, 500);
447                 XMapRaised(x11Display, window);
448             }
449         }
450         else
451         {
452             LOG_DEBUG("X11WindowSystem", "Error fetching window name");
453         }
454
455         if (att.c_class == InputOutput)
456         {
457             LOG_DEBUG("X11WindowSystem", "Creating New Damage for window - " << window);
458             XDamageCreate(x11Display, window, XDamageReportNonEmpty);
459         }
460
461         XFree(name);
462         XLowerWindow(x11Display, window);
463
464         surface->setNativeContent(window);
465         XPlatformSurface * platformSurface = (XPlatformSurface*)graphicSystem->getTextureBinder()->createPlatformSurface(surface);
466         platformSurface->isMapped = false;
467
468         LOG_DEBUG("X11WindowSystem", "Created native Surface for X11 Window id " << window);
469
470         surface->platform = platformSurface;
471
472         int winWidth = att.width;
473         int winHeight = att.height;
474
475         surface->OriginalSourceHeight = winHeight;
476         surface->OriginalSourceWidth = winWidth;
477
478         LOG_DEBUG("X11WindowSystem", "Original width " << surface->OriginalSourceWidth);
479         LOG_DEBUG("X11WindowSystem", "Original heigth " << surface->OriginalSourceHeight);
480     }
481     else
482     {
483         LOG_DEBUG("X11WindowSystem", "skipping window");
484     }
485     LOG_INFO("X11WindowSystem", "created the new surface");
486 }
487
488 void X11WindowSystem::DestroyWindow(Window window)
489 {
490     if (isWindowValid(window))
491     {
492         LOG_DEBUG("X11WindowSystem", "Destroying Surface for window " << window);
493         Surface* surface = getSurfaceForWindow(window);
494         if (!surface)
495         {
496             LOG_WARNING("X11WindowSystem", "Could not find surface for window " << window);
497             return;
498         }
499         graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
500         LOG_DEBUG("X11WindowSystem", "Unmapping window " << window);
501         UnMapWindow(window);
502         LOG_DEBUG("X11WindowSystem", "Remove Native Content from Surface " << surface->getID());
503         surface->removeNativeContent();
504         /* To force a recomposition of all surface which are behind of that surface inside the Layer RenderOrder */
505         surface->renderPropertyChanged = true;
506         /* Remove synchronized flag, no damage will occur anymore */
507         surface->setSynchronized(false);
508         surface->m_resizesync = false;
509         delete surface->platform;
510         surface->platform = NULL;
511     }
512 }
513
514 bool X11WindowSystem::CreatePixmapsForAllWindows()
515 {
516     bool result = true;
517     LOG_DEBUG("X11WindowSystem", "redirecting all windows");
518     Window root = RootWindow(x11Display, DefaultScreen(x11Display));
519     XCompositeRedirectSubwindows(x11Display, root, CompositeRedirectManual);
520     XSync(x11Display, 0);
521     return result;
522 }
523
524 bool X11WindowSystem::CreateCompositorWindow()
525 {
526     LOG_DEBUG("X11WindowSystem", "Get root window");
527     bool result = true;
528     CompositorWindow = None;
529     Window root = RootWindow(x11Display, DefaultScreen(x11Display));
530
531     LOG_DEBUG("X11WindowSystem", "Creating Compositor Window");
532
533     XSetWindowAttributes attr;
534     // draw a black background the full size of the resolution
535     attr.override_redirect = True;
536     attr.event_mask = ExposureMask
537                         | StructureNotifyMask
538                         | ButtonPressMask
539                         | ButtonReleaseMask
540                         | Button1MotionMask
541                         | KeyPressMask
542                         | KeyReleaseMask;
543     attr.background_pixel = 0;
544     attr.border_pixel = 0;
545     windowVis = getVisualFunc(x11Display);
546     if (!windowVis)
547     {
548         return false;
549     }
550     attr.colormap = XCreateColormap(x11Display, root, windowVis->visual, AllocNone);
551     attr.override_redirect = True;
552
553     Window compManager = XGetSelectionOwner(x11Display, XInternAtom(x11Display, "_NET_WM_CM_S0", 0));
554     if (None != compManager)
555     {
556         LOG_ERROR("X11WindowSystem", "Could not create compositor window, annother compisite manager is already running");
557         return false;
558     }
559
560     CompositorWindow = XCreateWindow(x11Display, root, 0, 0, windowWidth, windowHeight,
561             0, windowVis->depth, InputOutput,
562             windowVis->visual, CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &attr);
563
564     if (None == CompositorWindow)
565     {
566         LOG_ERROR("X11WindowSystem", "Could not create window");
567         return false;
568     }
569
570     LOG_DEBUG("X11WindowSystem", "Created the Compositor Window");
571     XSelectInput(x11Display, root,
572             SubstructureNotifyMask|
573             ExposureMask|
574             StructureNotifyMask|
575             PropertyChangeMask);
576
577     LOG_DEBUG("X11WindowSystem", "Created the window");
578     XSizeHints sizehints;
579     sizehints.width = windowWidth;
580     sizehints.height = windowHeight;
581     sizehints.flags = USSize;
582     XSetNormalHints(x11Display, CompositorWindow, &sizehints);
583     XSetStandardProperties(x11Display, CompositorWindow, CompositorWindowTitle, CompositorWindowTitle,
584             None, (char **)NULL, 0, &sizehints);
585     XMapRaised(x11Display, CompositorWindow);
586     XFlush(x11Display);
587     return result;
588 }
589
590 static float timeSinceLastCalc = 0.0;
591 static float FPS = 0.0;
592 static struct timeval tv;
593 static struct timeval tv0;
594 static int Frame = 0;
595
596
597 void X11WindowSystem::calculateSurfaceFps(Surface *currentSurface, float time)
598 {
599     char floatStringBuffer[256];
600     float surfaceUpdateFps = ((float)(currentSurface->updateCounter)) / time;
601     float surfaceDrawFps = ((float)(currentSurface->drawCounter)) / time;
602     sprintf(floatStringBuffer, "0x%08x update fps: %3.2f", currentSurface->getID(), surfaceUpdateFps);
603     currentSurface->updateCounter = 0;
604     LOG_INFO("X11WindowSystem", "Surface " << floatStringBuffer);
605     sprintf(floatStringBuffer, "0x%08x draw fps: %3.2f", currentSurface->getID(), surfaceDrawFps);
606     currentSurface->drawCounter = 0;
607     LOG_INFO("X11WindowSystem", "Surface " << floatStringBuffer);
608 }
609
610 void X11WindowSystem::calculateFps()
611 {
612     // we have rendered a frame
613     Frame ++;
614     std::list<Layer*> layers = m_pScene->getCurrentRenderOrder(0);
615     // every 3 seconds, calculate & print fps
616     gettimeofday(&tv, NULL);
617     timeSinceLastCalc = (float)(tv.tv_sec-tv0.tv_sec) + 0.000001*((float)(tv.tv_usec-tv0.tv_usec));
618
619     if (timeSinceLastCalc > m_fpsinterval)
620     {
621         FPS = ((float)(Frame)) / timeSinceLastCalc;
622         char floatStringBuffer[256];
623         sprintf(floatStringBuffer, "Overall fps: %f", FPS);
624         for (std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); ++current)
625         {
626             SurfaceList surfaceList = (*current)->getAllSurfaces();
627             SurfaceListIterator surfaceIter = surfaceList.begin();
628             SurfaceListIterator surfaceIterEnd = surfaceList.end();
629             for (; surfaceIter != surfaceIterEnd; ++surfaceIter)
630             {
631                 calculateSurfaceFps((*surfaceIter), timeSinceLastCalc);
632             }
633         }
634         LOG_INFO("X11WindowSystem", floatStringBuffer);
635         tv0 = tv;
636         Frame = 0;
637     }
638 }
639
640 bool X11WindowSystem::RedrawAllLayers(bool clear, bool swap)
641 {
642     bool result = false;
643     LayerList layers = m_pScene->getCurrentRenderOrder(0);
644     LayerList swLayers;
645
646     // Refresh HW Layers, find SW Layers
647     for (LayerListConstIterator current = layers.begin(); current != layers.end(); ++current)
648     {
649         if ((*current)->getLayerType() == Hardware)
650         {
651             // Redraw HW layers independently of other layers
652             if (m_forceComposition || graphicSystem->needsRedraw(*current))
653             {
654                 renderHWLayer(*current);
655             }
656         }
657         else
658         {
659             swLayers.push_back(*current);
660         }
661     }
662
663     if (m_forceComposition || graphicSystem->needsRedraw(swLayers))
664     {
665         graphicSystem->renderSWLayers(swLayers, clear);
666         result = true;
667
668         if (swap)
669         {
670             graphicSystem->swapBuffers();
671         }
672
673         if (debugMode)
674         {
675             printDebug();
676         }
677
678         calculateFps();
679     }
680     return result;
681 }
682
683 void X11WindowSystem::renderHWLayer(Layer *layer)
684 {
685     (void)layer;
686 }
687
688 void X11WindowSystem::Redraw()
689 {
690     // draw all the layers
691     /*LOG_INFO("X11WindowSystem","Locking List");*/
692     bool clear = false;
693     m_pScene->lockScene();
694
695     clear = RedrawAllLayers(true, true);  // Clear and Swap
696     if (clear)
697     {
698         ClearDamage();
699     };
700
701     m_pScene->unlockScene();
702
703     m_forceComposition = false;
704 }
705
706 void X11WindowSystem::Screenshot()
707 {
708     /*LOG_INFO("X11WindowSystem","Locking List");*/
709     m_pScene->lockScene();
710     if (takeScreenshot == ScreenshotOfDisplay)
711     {
712         LOG_DEBUG("X11WindowSystem", "Taking screenshot");
713         RedrawAllLayers(true, false);  // Do clear, Don't swap
714     }
715     else if (takeScreenshot == ScreenshotOfLayer)
716     {
717         LOG_DEBUG("X11WindowSystem", "Taking screenshot of layer");
718         Layer* layer = m_pScene->getLayer(screenShotLayerID);
719
720         if (layer != NULL)
721         {
722             graphicSystem->renderSWLayer(layer, true); // Do clear
723         }
724     }
725     else if (takeScreenshot == ScreenshotOfSurface)
726     {
727         LOG_DEBUG("X11WindowSystem", "Taking screenshot of surface");
728         Layer* layer = m_pScene->getLayer(screenShotLayerID);
729         Surface* surface = m_pScene->getSurface(screenShotSurfaceID);
730
731         graphicSystem->clearBackground();
732         if (layer != NULL && surface != NULL)
733         {
734             graphicSystem->beginLayer(layer);
735             graphicSystem->renderSurface(surface);
736             graphicSystem->endLayer();
737         }
738     }
739
740     graphicSystem->saveScreenShotOfFramebuffer(screenShotFile);
741     takeScreenshot = ScreenShotNone;
742     LOG_DEBUG("X11WindowSystem", "Done taking screenshot");
743     m_pScene->unlockScene();
744     /*LOG_INFO("X11WindowSystem","UnLocking List");*/
745 }
746
747 int
748 X11WindowSystem::error(Display *dpy, XErrorEvent *ev)
749 {
750     const char* name = NULL;
751     static char buffer[256];
752
753     if (ev->request_code == composite_opcode && ev->minor_code == X_CompositeRedirectSubwindows)
754     {
755         LOG_ERROR("X11WindowSystem", "Maybe another composite manager is already running");
756     }
757
758     if (!name)
759     {
760         buffer[0] = '\0';
761         XGetErrorText(dpy, ev->error_code, buffer, sizeof(buffer));
762         name = buffer;
763     }
764     name = (strlen(name) > 0) ? name : "unknown";
765     LOG_ERROR("X11WindowSystem", "X Error: " << (int)ev->error_code << " " << name << " request : " << (int)ev->request_code << " minor: " <<  (int)ev->minor_code << " serial: " << (int)ev->serial);
766     m_xerror = true;
767     return 0;
768 }
769
770 bool X11WindowSystem::initXServer()
771 {
772     LOG_DEBUG("X11WindowSystem", "Initialising XServer connection");
773     bool result = true;
774
775     //setDisplayMode();
776     if (!CreateCompositorWindow())
777     {
778         LOG_ERROR("X11WindowSystem", "Compositor Window creation failed ");
779         return false;
780     }
781
782     LOG_DEBUG("X11WindowSystem", "Compositor Window ID: " << CompositorWindow);
783
784     if (CreatePixmapsForAllWindows())
785     {
786             //unredirect our window
787 #ifdef FULLSCREEN
788         XCompositeUnredirectWindow(x11Display, background, CompositeRedirectManual);
789 #endif
790         XCompositeUnredirectWindow(x11Display, CompositorWindow, CompositeRedirectManual);
791         LOG_DEBUG("X11WindowSystem", "Initialised XServer connection complete");
792     }
793     else
794     {
795         LOG_ERROR("X11WindowSystem", "Initialised XServer connection failed");
796         result = false;
797     }
798
799     return result;
800 }
801
802 /**
803  * Thread in charge of the CompositorWindow eventloop
804  * Friend function of class X11WindowSystem
805  */
806 void * X11eventLoopCallback(void *ptr)
807 {
808     X11WindowSystem *windowsys = static_cast<X11WindowSystem*>((X11WindowSystem*) ptr);
809     return windowsys->EventLoop();
810 }
811
812 void* X11WindowSystem::EventLoop()
813 {
814     // INITALIZATION
815     LOG_INFO("X11WindowSystem", "XServer initialisation");
816     pthread_mutex_lock(&this->init_lock);
817     pthread_mutex_lock(&this->run_lock);
818     bool status = true;
819     bool checkRedraw = false;
820
821     XSetErrorHandler(error);
822     // init own stuff
823     LOG_DEBUG("X11WindowSystem", "open display connection");
824     status &= this->OpenDisplayConnection();
825     if (status == false) goto init_complete;
826     LOG_DEBUG("X11WindowSystem", "check for composite extension");
827     status &= this->checkForCompositeExtension();
828     if (status == false) goto init_complete;
829     LOG_DEBUG("X11WindowSystem", "check for damage extension");
830     status &= this->checkForDamageExtension();
831     if (status == false) goto init_complete;
832     LOG_DEBUG("X11WindowSystem", "init xserver");
833     status &= this->initXServer();
834     if (status == false) goto init_complete;
835     LOG_INFO("X11WindowSystem", "XServer initialisation completed");
836     LOG_DEBUG("X11WindowSystem", "Graphicsystem initialisation");
837     status &= this->graphicSystem->init(this->x11Display, this->CompositorWindow);
838     LOG_DEBUG("X11WindowSystem", "Graphicsystem initialisation complete");
839 init_complete:
840     this->m_success = status;
841     pthread_cond_signal(&this->init_condition);
842     pthread_mutex_unlock(&this->init_lock);
843     // Done with init, wait for lock to actually run (ie start/stop method called)
844     LOG_DEBUG("X11WindowSystem", "Waiting for startup");
845     pthread_cond_wait(&this->run_condition, &this->run_lock);
846     pthread_mutex_unlock(&this->run_lock);
847     LOG_DEBUG("X11WindowSystem", "Starting Event loop");
848     Layer* defaultLayer = 0;
849
850     // run the main event loop while rendering
851     gettimeofday(&tv0, NULL);
852     if (this->debugMode)
853     {
854         defaultLayer = this->m_pScene->createLayer(0, 0);
855         defaultLayer->setOpacity(1.0);
856         defaultLayer->setDestinationRegion(Rectangle(0, 0, this->resolutionWidth, this->resolutionHeight));
857         defaultLayer->setSourceRegion(Rectangle(0, 0, this->resolutionWidth, this->resolutionHeight));
858         this->m_pScene->getCurrentRenderOrder(0).push_back(defaultLayer);
859     }
860     LOG_INFO("X11WindowSystem", "Enter render loop");
861
862     // clear screen to avoid garbage on startup
863     this->graphicSystem->clearBackground();
864     this->graphicSystem->swapBuffers();
865     XFlush(this->x11Display);
866
867     while (this->m_running)
868     {
869         XEvent event;
870         // blocking wait for event
871         XNextEvent(this->x11Display, &event);
872         this->m_pScene->lockScene();
873         switch (event.type)
874         {
875         case CreateNotify:
876             {
877                 if (this->debugMode)
878                 {
879                     LOG_DEBUG("X11WindowSystem", "CreateNotify Event");
880                     Surface* s = this->m_pScene->createSurface(0, 0);
881                     s->setOpacity(1.0);
882                     this->NewWindow(s, event.xcreatewindow.window);
883                     defaultLayer->addSurface(s);
884                 }
885                 break;
886             }
887         case ConfigureNotify:
888             {
889                 LOG_DEBUG("X11WindowSystem", "Configure notify Event");
890                 this->configureSurfaceWindow( event.xconfigure.window);
891                 Surface* surfaceWindow = this->getSurfaceForWindow( event.xconfigure.window);
892                 if (surfaceWindow!=NULL)
893                 {
894                     checkRedraw = !surfaceWindow->m_surfaceResized;
895                 }
896             }
897             break;
898
899         case DestroyNotify:
900             LOG_DEBUG("X11WindowSystem", "Destroy  Event");
901             this->DestroyWindow(event.xdestroywindow.window);
902             checkRedraw = true;
903             break;
904         case Expose:
905             if (event.xexpose.window == this->CompositorWindow)
906             {
907                 checkRedraw = true;
908                 LOG_DEBUG("X11WindowSystem", "Expose Event triggered by internal Redraw");
909             }
910             else
911             {
912                 LOG_DEBUG("X11WindowSystem", "Expose Event triggered by external Application");
913             }
914             break;
915         case MapNotify:
916             LOG_DEBUG("X11WindowSystem", "Map Event");
917             this->MapWindow(event.xmap.window);
918             checkRedraw = true;
919             break;
920         case UnmapNotify:
921             LOG_DEBUG("X11WindowSystem", "Unmap Event");
922             this->UnMapWindow(event.xunmap.window);
923             checkRedraw = true;
924             break;
925         case ReparentNotify:
926             LOG_DEBUG("X11WindowSystem", "Reparent Event");
927             //           if (event.xreparent.parent == root)
928             //               renderer->NewWindow(event.xreparent.window);
929             //           else
930             //               renderer->DestroyWindow(event.xreparent.window);
931             break;
932
933         // Keyboard
934         case KeyPress:
935             ManageXInputEvent(INPUT_DEVICE_KEYBOARD, INPUT_STATE_PRESSED, &event);
936             break;
937         case KeyRelease:
938             ManageXInputEvent(INPUT_DEVICE_KEYBOARD, INPUT_STATE_RELEASED, &event);
939             break;
940
941         // Pointer
942         case ButtonPress:
943             ManageXInputEvent(INPUT_DEVICE_POINTER, INPUT_STATE_PRESSED, &event);
944             break;
945         case ButtonRelease:
946             ManageXInputEvent(INPUT_DEVICE_POINTER, INPUT_STATE_RELEASED, &event);
947             break;
948         case MotionNotify:
949             ManageXInputEvent(INPUT_DEVICE_POINTER, INPUT_STATE_MOTION, &event);
950             break;
951
952         // Touch
953         // TODO. See @ref<X11WindowSystem-MultiTouch> at the end of this file
954
955         default:
956             if (event.type == this->damage_event + XDamageNotify)
957             {
958                 XDamageSubtract(this->x11Display, ((XDamageNotifyEvent*)(&event))->damage, None, x11DamageRegion);
959                 Surface* currentSurface = this->getSurfaceForWindow(((XDamageNotifyEvent*)(&event))->drawable);
960                 if (currentSurface == NULL)
961                 {
962                     LOG_WARNING("X11WindowSystem", "Surface empty during damage notification");
963                     break;
964                 }
965                 else
966                 {
967                     if (currentSurface->platform != NULL)
968                     {
969                         XRectangle* rectangles;
970                         XRectangle geometry;
971                         XRectangle area;
972                         XRectangle bounds;
973                         int numberRects;
974                         /* Enable Rendering for Surface, after damage Notification was send successfully */
975                         /* This will ensure, that the content is not dirty */
976                         ((XPlatformSurface *)(currentSurface->platform))->enableRendering();
977                         geometry = ((XDamageNotifyEvent*)(&event))->geometry;
978                         area = ((XDamageNotifyEvent*)(&event))->area;
979
980                         LOG_DEBUG("X11WindowSystem","Damaged Geometry : [ " << geometry.x << ", " << geometry.y <<
981                                                                 ", " << geometry.width << ", " << geometry.height << " ]");
982                         LOG_DEBUG("X11WindowSystem","Damaged Area     : [ " << area.x << ", " << area.y <<
983                                                                 ", " << area.width << ", " << area.height << " ]");
984
985                         rectangles = XFixesFetchRegionAndBounds (this->x11Display, x11DamageRegion, &numberRects, &bounds);
986
987                         LOG_DEBUG("X11WindowSystem","Damaged Bounds   : [ " << bounds.x << ", " << bounds.y <<
988                                 ", " << bounds.width << ", " << bounds.height << " ]\n");
989                         // e->geometry is the geometry of the damaged window
990                         // e->area     is the bounding rect for the damaged area
991                         if ( currentSurface->OriginalSourceWidth != geometry.width || currentSurface->OriginalSourceHeight != geometry.height )
992                         {
993                             LOG_DEBUG("X11WindowSystem","Damaged Geometry differs from size : [ " << geometry.x << ", " << geometry.y <<
994                                                                 ", " << geometry.width << ", " << geometry.height << " ]");
995                             currentSurface->m_surfaceResized = true;
996                         }
997                         XFree(rectangles);
998                     }
999                     /* Ignore Damage Events after Resize, the content can be invalid */
1000                     if (!currentSurface->m_surfaceResized)
1001                     {
1002                         currentSurface->damaged = true;
1003                         currentSurface->updateCounter++;
1004                         currentSurface->m_resizesync = false;
1005                         checkRedraw = true;
1006                     } else {
1007                         LOG_DEBUG("X11WindowSystem", "Skipping Damage Event which was triggered after ConfigureNotify");
1008                         currentSurface->m_resizesync = true;
1009                         currentSurface->m_surfaceResized = false;
1010                     }
1011                 }
1012             }
1013             break;
1014         }
1015         this->m_pScene->unlockScene();
1016
1017         if (this->m_systemState == REDRAW_STATE)
1018         {
1019             LOG_DEBUG("X11WindowSystem", "Enter Redraw State");
1020             this->m_systemState = IDLE_STATE;
1021
1022             // check if we are supposed to take screenshot
1023             if (this->takeScreenshot != ScreenShotNone)
1024             {
1025                 this->Screenshot();
1026             }
1027             else
1028             {
1029                 this->checkForNewSurfaceNativeContent();
1030                 checkRedraw = true;
1031             }
1032         }
1033         else if (this->m_systemState == WAKEUP_STATE)
1034         {
1035             LOG_DEBUG("X11WindowSystem", "Enter Wake Up State");
1036             checkRedraw = false;
1037             graphicSystem->releaseGraphicContext();
1038             this->m_systemState = IDLE_STATE;
1039             while (this->m_systemState != WAKEUP_STATE);
1040             graphicSystem->activateGraphicContext();
1041             this->m_systemState = IDLE_STATE;
1042         }
1043
1044         if (checkRedraw)
1045         {
1046             this->Redraw();
1047             checkRedraw = false;
1048         }
1049     }
1050     this->cleanup();
1051     LOG_DEBUG("X11WindowSystem", "Renderer thread finished");
1052     return NULL;
1053 }
1054
1055
1056 void X11WindowSystem::ManageXInputEvent(InputDevice type, InputEventState state, XEvent *pevent)
1057 {
1058     Surface * surf;
1059
1060     switch (type)
1061     {
1062     case INPUT_DEVICE_KEYBOARD:
1063         {
1064             surf = m_pInputManager->reportKeyboardEvent(state, ((XKeyEvent *) pevent)->keycode);
1065             if (surf != NULL)
1066             {
1067                 pevent->xany.window = surf->getNativeContent();
1068                 XSendEvent(x11Display, pevent->xany.window, false, 0, pevent);
1069             }
1070         }
1071         break;
1072
1073     case INPUT_DEVICE_POINTER:
1074         {
1075             Point p = {state, ((XButtonEvent*)pevent)->x, ((XButtonEvent*)pevent)->y};
1076             surf = m_pInputManager->reportPointerEvent(p);
1077             if (surf != NULL)
1078             {
1079                 ((XButtonEvent*)pevent)->x = p.x;
1080                 ((XButtonEvent*)pevent)->y = p.y;
1081                 pevent->xany.window = surf->getNativeContent();
1082                 XSendEvent(x11Display, pevent->xany.window, false, 0, pevent);
1083             }
1084         }
1085         break;
1086
1087     case INPUT_DEVICE_TOUCH:
1088         /* TODO */
1089         break;
1090
1091     default:
1092     case INPUT_DEVICE_ALL:
1093         break;
1094     }
1095 }
1096
1097
1098 static Display* displaySignal = NULL;
1099
1100 void X11WindowSystem::wakeUpRendererThread()
1101 {
1102     // send dummy expose event, to wake up blocking x11 event loop (XNextEvent)
1103     LOG_DEBUG("X11WindowSystem", "Sending dummy event to wake up renderer thread");
1104     if (NULL == displaySignal)
1105     {
1106         displaySignal = XOpenDisplay(m_displayEnvironment);
1107     }
1108     XExposeEvent ev = { Expose, 0, 1, displaySignal, CompositorWindow, 0, 0, 100, 100, 0 };
1109     XLockDisplay(displaySignal);
1110     XSendEvent(displaySignal, CompositorWindow, False, ExposureMask, (XEvent *) &ev);
1111     XUnlockDisplay(displaySignal);
1112     XFlush(displaySignal);
1113     LOG_DEBUG("X11WindowSystem", "Event successfully sent to renderer");
1114 }
1115
1116 void X11WindowSystem::signalRedrawEvent()
1117 {
1118     // set flag that redraw is needed
1119     this->m_systemState = REDRAW_STATE;
1120     this->wakeUpRendererThread();
1121 }
1122
1123 void X11WindowSystem::cleanup()
1124 {
1125     LOG_DEBUG("X11WindowSystem", "Cleanup");
1126     if (None != CompositorWindow)
1127     {
1128         Window root = RootWindow(x11Display, DefaultScreen(x11Display));
1129         XCompositeUnredirectSubwindows(x11Display, root, CompositeRedirectManual);
1130         XFixesDestroyRegion(x11Display, x11DamageRegion);
1131         XDestroyWindow(x11Display, CompositorWindow);
1132     }
1133
1134     if (windowVis)
1135     {
1136         delete windowVis;
1137     }
1138
1139     if (NULL != displaySignal)
1140     {
1141         XCloseDisplay(displaySignal);
1142     }
1143
1144     XCloseDisplay(x11Display);
1145     pthread_mutex_lock(&this->run_lock);
1146     m_running = false;
1147     pthread_mutex_unlock(&this->run_lock);
1148 }
1149
1150 bool X11WindowSystem::init(BaseGraphicSystem<Display*, Window>* base)
1151 {
1152     XInitThreads();
1153     X11WindowSystem *renderer = this;
1154     graphicSystem = base;
1155     LOG_INFO("X11WindowSystem", "Initialization");
1156     pthread_mutex_lock(&init_lock);
1157     int status = pthread_create(&renderThread, NULL, X11eventLoopCallback, (void*) renderer);
1158     if (0 != status)
1159     {
1160         pthread_mutex_unlock(&init_lock);
1161         return false;
1162     }
1163     mThreadId = renderThread;
1164
1165     pthread_cond_wait(&init_condition, &init_lock);
1166     pthread_mutex_unlock(&init_lock);
1167     LOG_INFO("X11WindowSystem", "Initialization complete success :" << m_success);
1168     return m_success;
1169 }
1170
1171 bool X11WindowSystem::start()
1172 {
1173     bool result = true;
1174     pthread_mutex_lock(&this->run_lock);
1175     LOG_DEBUG("X11WindowSystem", "Startup");
1176     // let thread actually run
1177     if (m_xerror == false)
1178     {
1179         this->m_running = true;
1180         pthread_cond_signal(&this->run_condition);
1181         pthread_mutex_unlock(&this->run_lock);
1182     }
1183     else
1184     {
1185         this->m_running = false;
1186         pthread_cond_signal(&this->run_condition);
1187         pthread_mutex_unlock(&this->run_lock);
1188         result = false;
1189     }
1190     return result;
1191 }
1192
1193 void X11WindowSystem::stop()
1194 {
1195     LOG_INFO("X11WindowSystem", "Stopping..");
1196     pthread_mutex_lock(&this->run_lock);
1197     this->m_running = false;
1198     // needed if start was never called, we wake up thread, so it can immediatly finish
1199     this->signalRedrawEvent();
1200     pthread_cond_signal(&this->run_condition);
1201     pthread_mutex_unlock(&this->run_lock);
1202     pthread_join(renderThread, NULL);
1203 }
1204
1205 void X11WindowSystem::allocatePlatformSurface(Surface* surface)
1206 {
1207     LOG_DEBUG("X11WindowSystem", "allocatePlatformSurface begin");
1208     XPlatformSurface* nativeSurface = (XPlatformSurface*)surface->platform;
1209     if (!nativeSurface)
1210     {
1211         LOG_DEBUG("X11WindowSystem", "creating native surface for new window");
1212         // this surface does not have a native platform surface attached yet!
1213         NewWindow(surface, surface->getNativeContent());
1214         MapWindow(surface->getNativeContent());
1215     }
1216     LOG_DEBUG("X11WindowSystem", "allocatePlatformSurface end");
1217 }
1218
1219 void X11WindowSystem::deallocatePlatformSurface(Surface* surface)
1220 {
1221     LOG_DEBUG("X11WindowSystem", "deallocatePlatformSurface begin");
1222     XPlatformSurface* nativeSurface = (XPlatformSurface*)surface->platform;
1223     if (nativeSurface)
1224     {
1225         LOG_DEBUG("X11WindowSystem", "destroyingnative surface");
1226         graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
1227
1228         if (nativeSurface->pixmap)
1229         {
1230             XFreePixmap(x11Display, nativeSurface->pixmap);
1231         }
1232
1233         surface->renderPropertyChanged = true;
1234         delete surface->platform;
1235         surface->platform = NULL;
1236     }
1237     LOG_DEBUG("X11WindowSystem", "deallocatePlatformSurface end");
1238 }
1239
1240 void X11WindowSystem::doScreenShot(std::string fileName)
1241 {
1242     takeScreenshot = ScreenshotOfDisplay;
1243     screenShotFile = fileName;
1244 }
1245
1246 void X11WindowSystem::doScreenShotOfLayer(std::string fileName, const uint id)
1247 {
1248     takeScreenshot = ScreenshotOfLayer;
1249     screenShotFile = fileName;
1250     screenShotLayerID = id;
1251 }
1252
1253 void X11WindowSystem::doScreenShotOfSurface(std::string fileName, const uint id, const uint layer_id)
1254 {
1255     takeScreenshot = ScreenshotOfSurface;
1256     screenShotFile = fileName;
1257     screenShotSurfaceID = id;
1258     screenShotLayerID = layer_id;
1259 }
1260
1261
1262
1263 /**
1264  * @subsection <X11WindowSystem-MultiTouch> (Multi Touch)
1265  *
1266  *   X11 multi touch is not yet supported by Layer Manager.
1267  *
1268  *   TODO to add support:
1269  *     - Move all event management to xi2
1270  *     - For multi touch, make sure XInput protocol is > 2.2
1271  *         -> Via cmake ==> ?
1272  *         -> At runtime ==> http://who-t.blogspot.fr/2011/12/multitouch-in-x-getting-events.html
1273  *     - Register for XIDirectTouch. (No plan (yet?) to support XIDependentTouch)
1274  *     - Call m_pInputManager->reportTouchEvent() from ManageXInputEvent() to translate screen wide touch coordinates
1275  *      into surface wide coordinates
1276  *     - Forward the event to the native handle of the surface returned by m_pInputManager->reportTouchEvent()
1277  *
1278  *   Further reading:
1279  *     + XInput 2.x protocol : ftp://www.x.org/pub/xorg/current/doc/inputproto/XI2proto.txt
1280  *     + LWN article : http://lwn.net/Articles/475886/
1281  *
1282  */
1283