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
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)
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 *);
};
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);
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);
// 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)
{
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
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;
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;
--- /dev/null
+/***************************************************************************
+ *
+ * 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;
+}
+
}
}
+/**
+ * @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;
+}
+