Add framework to support input events + X11 implementation
authorFrédéric Blain <frederic.blain@valeo.com>
Fri, 19 Aug 2011 10:57:38 +0000 (12:57 +0200)
committerMichael Schuldt <michael.schuldt@bmw-carit.de>
Mon, 22 Aug 2011 06:44:53 +0000 (08:44 +0200)
CMakeLists.txt
LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/X11WindowSystem.h
LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/X11WindowSystem.cpp
LayerManagerService/include/GraphicalSurface.h
LayerManagerService/include/Scene.h
LayerManagerService/src/GraphicalSurface.cpp [new file with mode: 0644]
LayerManagerService/src/Scene.cpp

index 8bdbb0e..7ca4768 100644 (file)
@@ -59,6 +59,9 @@ option (WITH_TESTS
 option (WITH_XTHREADS
         "Build with usage of X11 Threading" ON)
 
+option (WITH_INPUT_EVENTS
+        "Activate input events handling" OFF)
+
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")
 
 option (WITH_FORCE_COPY 
@@ -67,6 +70,11 @@ option (WITH_FORCE_COPY
 if (WITH_XTHREADS)
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_XTHREADS" CACHE STRING "" FORCE)
 endif(WITH_XTHREADS)
+
+if (WITH_INPUT_EVENTS)
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_INPUT_EVENTS" CACHE STRING "" FORCE)
+endif(WITH_INPUT_EVENTS)
+
         
 if (WITH_FORCE_COPY)
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLX_GRAPHICSYSTEM_FORCE_COPY -DGLES_FORCE_COPY" CACHE STRING "" FORCE)
index ed1a8a2..3294c3b 100644 (file)
@@ -116,7 +116,10 @@ private:
     static int error(Display *dpy, XErrorEvent *ev);
        bool redrawEvent;
     static bool m_xerror;
-    
+#ifdef ENABLE_INPUT_EVENTS
+       void ManageXInputEvent(XEvent *pevent);
+#endif
+
     friend void * X11eventLoopCallback(void *);
 };
 
index 19ac088..07bee49 100644 (file)
@@ -451,7 +451,11 @@ bool X11WindowSystem::CreateCompositorWindow()
     XSetWindowAttributes attr;
     // draw a black background the full size of the resolution
     attr.override_redirect = True;
-    attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
+#ifdef ENABLE_INPUT_EVENTS
+       attr.event_mask =  ExposureMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask;
+#else
+       attr.event_mask = ExposureMask | StructureNotifyMask;
+#endif
     attr.background_pixel = 0;
     attr.border_pixel = 0;
     windowVis = getVisualFunc(x11Display);
@@ -770,10 +774,6 @@ void* X11WindowSystem::EventLoop()
                                LOG_DEBUG("X11WindowSystem", "Expose Event");
                                checkRedraw = true;
                                break;
-                       case ButtonPress:
-                               LOG_DEBUG("X11WindowSystem", "Button press Event");
-                               //running = False;
-                               break;
                        case MapNotify:
                                LOG_DEBUG("X11WindowSystem", "Map Event");
                                this->MapWindow(event.xmap.window);
@@ -791,7 +791,12 @@ void* X11WindowSystem::EventLoop()
                                //                       else
                                //                               renderer->DestroyWindow(event.xreparent.window);
                                break;
-
+#ifdef ENABLE_INPUT_EVENTS
+                       case ButtonPress:
+                       case ButtonRelease:
+                               ManageXInputEvent(&event);
+                               break;
+#endif
                        default:
                                if (event.type == this->damage_event + XDamageNotify)
                                {
@@ -846,6 +851,37 @@ void* X11WindowSystem::EventLoop()
        LOG_INFO("X11WindowSystem", "Renderer thread finished");
        return NULL;
 }
+
+
+#ifdef ENABLE_INPUT_EVENTS
+void X11WindowSystem::ManageXInputEvent(XEvent *pevent)
+{
+       Surface * surf;
+       unsigned int x, y;
+
+       switch (pevent->type)
+       {
+               case ButtonRelease:
+               case ButtonPress:
+                       x = ((XButtonEvent*)pevent)->x;
+                       y = ((XButtonEvent*)pevent)->y;
+
+                       surf = m_pScene->getSurfaceAt(&x, &y, 0.1);
+                       if (surf != NULL)
+                       {
+                               ((XButtonEvent*)pevent)->x = x;
+                               ((XButtonEvent*)pevent)->y = y;
+                               XSendEvent(x11Display, surf->nativeHandle, false, 0, pevent);
+                       }
+                       break;
+
+               default:
+                       break;
+       }
+}
+#endif
+
+
 #ifdef USE_XTHREADS
 static Display* displaySignal = NULL;
 #endif //USE_XTHREADS
index f9d8cd7..10c498d 100644 (file)
@@ -70,6 +70,34 @@ public:
 
                const Rectangle& getDestinationRegion() const;
                Vector2 getDimension();
+
+               /**
+                * @Description Indicate if a x,y position is inside the destination region.
+                *              Attention: Graphical Surface rotation is not yet supported.
+                * @param x_DestCoordonateSyst x position in the destination coordonate system
+                * @param y_DestCoordonateSyst y position in the destination coordonate system
+                * @return TRUE if the position is inside the destination region
+                */
+               bool isInside(unsigned int x_DestCoordonateSyst, unsigned int y_DestCoordonateSyst) const;
+
+               /**
+                * @Description Transform a x,y position from destination coordonate system to
+                *              source coordonate system. Attention, to get valid result the x,y
+                *              positions given in parameter must be located within the destination
+                *              region of the GraphicalSurface
+                *
+                * @param x in/out : IN    x position in the destination coordonate system
+                *                   OUT   x position in the source coordonate system
+                * @param y in/out : IN    y position in the destination coordonate system
+                *                   OUT   y position in the source coordonate system
+                * @param check If TRUE, a test will be done to make sure the x,y positions
+                *              given in parameter are located within the destination region.
+                *
+                * @return TRUE if the coordonates have been translated
+                *         FALSE if an error occured, exp: The position is not in the destination region
+                */
+               bool DestToSourceCoordonates(unsigned int *x, unsigned int *y, bool check) const;
+
 private:
     OrientationType m_orientation; // Rotation of the graphical content
     Rectangle m_sourceViewport;
index 0cd44e7..7024e94 100644 (file)
@@ -80,6 +80,7 @@ public:
     void removeSurfaceGroup(SurfaceGroup *surface);
     void removeLayerGroup(LayerGroup *layer);
     const SurfaceMap getAllSurfaces() const;
+    Surface* getSurfaceAt(unsigned int *x, unsigned int *y, double minOpacity);
 
 private:
     const LayerMap getAllLayers() const;
diff --git a/LayerManagerService/src/GraphicalSurface.cpp b/LayerManagerService/src/GraphicalSurface.cpp
new file mode 100644 (file)
index 0000000..4d7c810
--- /dev/null
@@ -0,0 +1,101 @@
+/***************************************************************************
+ *
+ * Copyright 2011 Valeo
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+#include "GraphicalSurface.h"
+
+
+bool GraphicalSurface::isInside(unsigned int x_DestCoordonateSyst, unsigned int y_DestCoordonateSyst) const
+{
+       bool ret;
+
+       switch (m_orientation)
+       {
+               case Zero:
+                       ret = (
+                                  ((x_DestCoordonateSyst >= m_destinationViewport.x) && (x_DestCoordonateSyst < m_destinationViewport.x + m_destinationViewport.width))
+                               &&
+                                  ((y_DestCoordonateSyst >= m_destinationViewport.y) && (y_DestCoordonateSyst < m_destinationViewport.y + m_destinationViewport.height))
+                             );
+                       break;
+
+               case Ninety:
+               case OneEighty:
+               case TwoSeventy:
+                       /* Not yet supported */
+                       ret = false;
+                       break;
+
+               default:
+                       ret = false;
+                       break;
+       }
+
+       return ret;
+}
+
+
+
+/**
+ * We are going to change of coordonate system.
+ * The input coordonates are in the Dest system, we have to change them to the Source system.
+ * For this, 4 operations have to be undone, in order :
+ *  - translation in source system
+ *  - scaling
+ *  - translation in destination system
+ *  - rotation (not yet implemented)
+ *
+ */
+bool GraphicalSurface::DestToSourceCoordonates(unsigned int *x, unsigned int *y, bool check) const
+{
+       bool    ret;
+       int     TVxD, TVyD;  /* Translation vector x,y in destination system */ 
+       int     TVxS, TVyS;  /* Translation vector x,y in source system */
+       float   SFx, SFy;    /* Scaling factor x,y  */
+
+       if (!check || isInside(*x, *y))
+       {
+               /* The translation vector in the Destination system */
+               TVxD = m_destinationViewport.x;
+               TVyD = m_destinationViewport.y;
+
+               /* The translation vector in the Source system */
+               TVxS = m_sourceViewport.x;
+               TVyS = m_sourceViewport.y;
+
+               /* Compute the scaling factors */
+               SFx = (float) m_sourceViewport.width  / (float) m_destinationViewport.width;
+               SFy = (float) m_sourceViewport.height / (float) m_destinationViewport.height;
+
+               /* Compute the rotation */
+               // To be done ...
+
+               /* Apply the transformations */
+               *x = ((*x - TVxD) * SFx) + TVxS;
+               *y = ((*y - TVyD) * SFy) + TVyS;
+
+               ret = true;
+       }
+       else
+       {
+               ret = false;
+       }
+
+       return ret;
+}
+
index 66b5282..1158b39 100644 (file)
@@ -379,3 +379,64 @@ void Scene::getLayerGroupIDs(uint* length, uint** array) const
     }
 }
 
+/**
+ * @Description:
+ * Return the first Surface located below a specific coordinate, and for which
+ * the opacity is above a certain level. Also translate the input coordonates
+ * which are display wide into surface wide coordonates.
+ *
+ * This function is mainly used to dispatch mouse events to the underlying
+ * window. For this, we need to know to what is the layer / surface under the
+ * (x,y) mouse pointer.
+ *
+ *
+ *
+ * @param x in/out : IN    x position in the scene
+ *                   OUT   x position in the surface coordonate system
+ * @param y in/out : IN    y position in the scene
+ *                   OUT   y position in the surface coordonate system
+ * @param minOpacity Minimal opacity that a surface should have to be elected
+ */
+Surface* Scene::getSurfaceAt(unsigned int *x, unsigned int *y, double minOpacity)
+{
+       Surface* surf;
+       LayerListIterator currentLayer;
+       SurfaceListIterator currentSurf;
+       unsigned int x_SurfCoordonate, y_SurfCoordonate;
+
+       surf = NULL;
+
+       /* Need to browse for all layers */
+       for (currentLayer = m_currentRenderOrder.begin();
+            currentLayer != m_currentRenderOrder.end() && surf == NULL;
+            currentLayer++)
+       {
+               if ( ((*currentLayer)->visibility) && ((*currentLayer)->getOpacity() >= minOpacity) )
+               {
+                       if ((*currentLayer)->isInside(*x, *y))
+                       {
+                               x_SurfCoordonate = *x;
+                               y_SurfCoordonate = *y;
+                               (*currentLayer)->DestToSourceCoordonates(&x_SurfCoordonate, &y_SurfCoordonate, false);
+                               /* Need to browse for all surfaces */
+                               for (currentSurf = (*currentLayer)->getAllSurfaces().begin();
+                                    currentSurf != (*currentLayer)->getAllSurfaces().end() && surf == NULL;
+                                    currentSurf++)
+                               {
+                                       if ( ((*currentSurf)->visibility) && ((*currentSurf)->getOpacity() >= minOpacity) )
+                                       {
+                                               if ((*currentSurf)->isInside(x_SurfCoordonate, y_SurfCoordonate))
+                                               {
+                                                       surf = *currentSurf;
+                                                       (*currentSurf)->DestToSourceCoordonates(&x_SurfCoordonate, &y_SurfCoordonate, false);
+                                                       *x = x_SurfCoordonate;
+                                                       *y = y_SurfCoordonate;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return surf;
+}
+