From 807a8f439b0e49e43ed042c15b451b82352daa72 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fr=C3=A9d=C3=A9ric=20Blain?= Date: Fri, 19 Aug 2011 12:57:38 +0200 Subject: [PATCH] Add framework to support input events + X11 implementation --- CMakeLists.txt | 8 ++ .../include/WindowSystems/X11WindowSystem.h | 5 +- .../Graphic/src/WindowSystems/X11WindowSystem.cpp | 48 ++++++++-- LayerManagerService/include/GraphicalSurface.h | 28 ++++++ LayerManagerService/include/Scene.h | 1 + LayerManagerService/src/GraphicalSurface.cpp | 101 +++++++++++++++++++++ LayerManagerService/src/Scene.cpp | 61 +++++++++++++ 7 files changed, 245 insertions(+), 7 deletions(-) create mode 100644 LayerManagerService/src/GraphicalSurface.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bdbb0e..7ca4768 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/X11WindowSystem.h b/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/X11WindowSystem.h index ed1a8a2..3294c3b 100644 --- a/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/X11WindowSystem.h +++ b/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/X11WindowSystem.h @@ -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 *); }; diff --git a/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/X11WindowSystem.cpp b/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/X11WindowSystem.cpp index 19ac088..07bee49 100644 --- a/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/X11WindowSystem.cpp +++ b/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/X11WindowSystem.cpp @@ -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 diff --git a/LayerManagerService/include/GraphicalSurface.h b/LayerManagerService/include/GraphicalSurface.h index f9d8cd7..10c498d 100644 --- a/LayerManagerService/include/GraphicalSurface.h +++ b/LayerManagerService/include/GraphicalSurface.h @@ -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; diff --git a/LayerManagerService/include/Scene.h b/LayerManagerService/include/Scene.h index 0cd44e7..7024e94 100644 --- a/LayerManagerService/include/Scene.h +++ b/LayerManagerService/include/Scene.h @@ -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 index 0000000..4d7c810 --- /dev/null +++ b/LayerManagerService/src/GraphicalSurface.cpp @@ -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; +} + diff --git a/LayerManagerService/src/Scene.cpp b/LayerManagerService/src/Scene.cpp index 66b5282..1158b39 100644 --- a/LayerManagerService/src/Scene.cpp +++ b/LayerManagerService/src/Scene.cpp @@ -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; +} + -- 2.7.4