#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
#include <Aspect_Convert.hxx>
+#include <Aspect_ScrollDelta.hxx>
#include <Aspect_WindowDefinitionError.hxx>
+#include <Aspect_WindowInputListener.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
//#include <X11/XF86keysym.h>
-#if defined(HAVE_EGL) || defined(HAVE_GLES2)
- #include <EGL/egl.h>
- #ifndef EGL_OPENGL_ES3_BIT
- #define EGL_OPENGL_ES3_BIT 0x00000040
- #endif
-#else
- #include <GL/glx.h>
-
-namespace
-{
-
- //! Search for RGBA double-buffered visual with stencil buffer.
- static int TheDoubleBuffVisual[] =
- {
- GLX_RGBA,
- GLX_DEPTH_SIZE, 16,
- GLX_STENCIL_SIZE, 1,
- GLX_DOUBLEBUFFER,
- None
- };
-
- //! Search for RGBA double-buffered visual with stencil buffer.
- static int TheDoubleBuffFBConfig[] =
- {
- GLX_X_RENDERABLE, True,
- GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
- GLX_RENDER_TYPE, GLX_RGBA_BIT,
- GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
- GLX_DEPTH_SIZE, 16,
- GLX_STENCIL_SIZE, 1,
- GLX_DOUBLEBUFFER, True,
- None
- };
-
-}
-
-#endif
-
IMPLEMENT_STANDARD_RTTIEXT(Xw_Window, Aspect_Window)
// =======================================================================
const Standard_Integer thePxLeft,
const Standard_Integer thePxTop,
const Standard_Integer thePxWidth,
- const Standard_Integer thePxHeight,
- const Aspect_FBConfig theFBConfig)
+ const Standard_Integer thePxHeight)
: Aspect_Window(),
myDisplay (theXDisplay),
myXWindow (0),
- myFBConfig (theFBConfig),
+ myFBConfig (NULL),
myXLeft (thePxLeft),
myYTop (thePxTop),
myXRight (thePxLeft + thePxWidth),
else if (theXDisplay.IsNull())
{
throw Aspect_WindowDefinitionError("Xw_Window, X Display connection is undefined");
- return;
}
+ myFBConfig = theXDisplay->GetDefaultFBConfig();
+ XVisualInfo* aVisInfo = theXDisplay->GetDefaultVisualInfo();
+
Display* aDisp = myDisplay->GetDisplay();
int aScreen = DefaultScreen(aDisp);
Window aParent = RootWindow (aDisp, aScreen);
- XVisualInfo* aVisInfo = NULL;
-
-#if defined(HAVE_EGL) || defined(HAVE_GLES2)
- EGLDisplay anEglDisplay = eglGetDisplay (aDisp);
- EGLint aVerMajor = 0; EGLint aVerMinor = 0;
- XVisualInfo aVisInfoTmp; memset (&aVisInfoTmp, 0, sizeof(aVisInfoTmp));
- if (anEglDisplay != EGL_NO_DISPLAY
- && eglInitialize (anEglDisplay, &aVerMajor, &aVerMinor) == EGL_TRUE)
- {
- EGLint aConfigAttribs[] =
- {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 0,
- EGL_DEPTH_SIZE, 24,
- EGL_STENCIL_SIZE, 8,
- #if defined(HAVE_GLES2)
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- #else
- EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
- #endif
- EGL_NONE
- };
-
- EGLint aNbConfigs = 0;
- void* anEglConfig = NULL;
- for (Standard_Integer aGlesVer = 3; aGlesVer >= 2; --aGlesVer)
- {
- #if defined(GL_ES_VERSION_2_0)
- aConfigAttribs[6 * 2 + 1] = aGlesVer == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
- #else
- if (aGlesVer == 2)
- {
- break;
- }
- #endif
-
- if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) == EGL_TRUE
- && anEglConfig != NULL)
- {
- break;
- }
- eglGetError();
-
- aConfigAttribs[4 * 2 + 1] = 16; // try config with smaller depth buffer
- if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) == EGL_TRUE
- && anEglConfig != NULL)
- {
- break;
- }
- eglGetError();
- }
-
- if (anEglConfig != NULL
- && eglGetConfigAttrib (anEglDisplay, anEglConfig, EGL_NATIVE_VISUAL_ID, (EGLint* )&aVisInfoTmp.visualid) == EGL_TRUE)
- {
- int aNbVisuals = 0;
- aVisInfoTmp.screen = DefaultScreen (aDisp);
- aVisInfo = XGetVisualInfo (aDisp, VisualIDMask | VisualScreenMask, &aVisInfoTmp, &aNbVisuals);
- }
- }
- if (aVisInfo == NULL)
- {
- Message::SendWarning ("Warning: cannot choose Visual using EGL while creating Xw_Window");
- }
-#else
- int aDummy = 0;
- if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy))
- {
- throw Aspect_WindowDefinitionError("Xw_Window, GLX extension is unavailable");
- return;
- }
- if (myFBConfig == NULL)
- {
- // FBConfigs were added in GLX version 1.3
- int aGlxMajor = 0;
- int aGlxMinor = 0;
- const bool hasFBCfg = glXQueryVersion (aDisp, &aGlxMajor, &aGlxMinor)
- && ((aGlxMajor == 1 && aGlxMinor >= 3) || (aGlxMajor > 1));
- if (hasFBCfg)
- {
- int aFBCount = 0;
- GLXFBConfig* aFBCfgList = NULL;
- if (hasFBCfg)
- {
- aFBCfgList = glXChooseFBConfig (aDisp, aScreen, TheDoubleBuffFBConfig, &aFBCount);
- }
- if(aFBCfgList != NULL
- && aFBCount >= 1)
- {
- myFBConfig = aFBCfgList[0];
- aVisInfo = glXGetVisualFromFBConfig (aDisp, myFBConfig);
- }
- XFree (aFBCfgList);
- }
- }
- if (aVisInfo == NULL)
- {
- aVisInfo = glXChooseVisual (aDisp, aScreen, TheDoubleBuffVisual);
- }
- if (aVisInfo == NULL)
- {
- throw Aspect_WindowDefinitionError("Xw_Window, couldn't find compatible Visual (RGBA, double-buffered)");
- return;
- }
-#endif
unsigned long aMask = 0;
XSetWindowAttributes aWinAttr;
InputOutput,
aVisInfo != NULL ? aVisInfo->visual : CopyFromParent,
CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttr);
- if (aVisInfo != NULL)
- {
- XFree (aVisInfo);
- aVisInfo = NULL;
- }
if (myXWindow == 0)
{
throw Aspect_WindowDefinitionError("Xw_Window, Unable to create window");
- return;
}
// if parent - desktop
if (theXWin == 0)
{
throw Aspect_WindowDefinitionError("Xw_Window, given invalid X window");
- return;
}
else if (theXDisplay.IsNull())
{
throw Aspect_WindowDefinitionError("Xw_Window, X Display connection is undefined");
- return;
- }
-#if !defined(HAVE_EGL) && !defined(HAVE_GLES2)
- int aDummy = 0;
- if (!glXQueryExtension (myDisplay->GetDisplay(), &aDummy, &aDummy))
- {
- myXWindow = 0;
- throw Aspect_WindowDefinitionError("Xw_Window, GLX extension is unavailable");
- return;
}
-#endif
Display* aDisp = myDisplay->GetDisplay();
if (aVisInfo == NULL)
{
throw Aspect_WindowDefinitionError("Xw_Window, Visual is unavailable");
- return;
}
XFree (aVisInfo);
// =======================================================================
Aspect_TypeOfResize Xw_Window::DoResize()
{
- if (myXWindow == 0)
+ if (IsVirtual() || myXWindow == 0)
{
return Aspect_TOR_UNKNOWN;
}
// =======================================================================
Standard_Real Xw_Window::Ratio() const
{
- if (myXWindow == 0)
+ if (IsVirtual() || myXWindow == 0)
{
- return 1.0;
+ return Standard_Real(myXRight - myXLeft) / Standard_Real(myYBottom - myYTop);
}
XFlush (myDisplay->GetDisplay());
// function : Position
// purpose :
// =======================================================================
-void Xw_Window::Position (Standard_Integer& X1, Standard_Integer& Y1,
- Standard_Integer& X2, Standard_Integer& Y2) const
+void Xw_Window::Position (Standard_Integer& theX1, Standard_Integer& theY1,
+ Standard_Integer& theX2, Standard_Integer& theY2) const
{
- if (myXWindow == 0)
+ if (IsVirtual() || myXWindow == 0)
{
+ theX1 = myXLeft;
+ theX2 = myXRight;
+ theY1 = myYTop;
+ theY2 = myYBottom;
return;
}
XTranslateCoordinates (myDisplay->GetDisplay(), anAttributes.root, myXWindow,
0, 0, &anAttributes.x, &anAttributes.y, &aChild);
- X1 = -anAttributes.x;
- X2 = X1 + anAttributes.width;
- Y1 = -anAttributes.y;
- Y2 = Y1 + anAttributes.height;
+ theX1 = -anAttributes.x;
+ theX2 = theX1 + anAttributes.width;
+ theY1 = -anAttributes.y;
+ theY2 = theY1 + anAttributes.height;
}
// =======================================================================
void Xw_Window::Size (Standard_Integer& theWidth,
Standard_Integer& theHeight) const
{
- if (myXWindow == 0)
+ if (IsVirtual() || myXWindow == 0)
{
+ theWidth = myXRight - myXLeft;
+ theHeight = myYBottom - myYTop;
return;
}
return Aspect_VKey_UNKNOWN;
}
+// =======================================================================
+// function : ProcessMessage
+// purpose :
+// =======================================================================
+bool Xw_Window::ProcessMessage (Aspect_WindowInputListener& theListener,
+ XEvent& theMsg)
+{
+ Display* aDisplay = myDisplay->GetDisplay();
+
+ // Handle event for the chosen display connection
+ switch (theMsg.type)
+ {
+ case ClientMessage:
+ {
+ if ((Atom)theMsg.xclient.data.l[0] == myDisplay->GetAtom (Aspect_XA_DELETE_WINDOW)
+ && theMsg.xclient.window == myXWindow)
+ {
+ theListener.ProcessClose();
+ return true;
+ }
+ return false;
+ }
+ case FocusIn:
+ case FocusOut:
+ {
+ if (theMsg.xfocus.window == myXWindow)
+ {
+ theListener.ProcessFocus (theMsg.type == FocusIn);
+ }
+ return true;
+ }
+ case Expose:
+ {
+ if (theMsg.xexpose.window == myXWindow)
+ {
+ theListener.ProcessExpose();
+ }
+
+ // remove all the ExposureMask and process them at once
+ for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
+ {
+ if (!XCheckWindowEvent (aDisplay, myXWindow, ExposureMask, &theMsg))
+ {
+ break;
+ }
+ }
+
+ return true;
+ }
+ case ConfigureNotify:
+ {
+ // remove all the StructureNotifyMask and process them at once
+ for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
+ {
+ if (!XCheckWindowEvent (aDisplay, myXWindow, StructureNotifyMask, &theMsg))
+ {
+ break;
+ }
+ }
+
+ if (theMsg.xconfigure.window == myXWindow)
+ {
+ theListener.ProcessConfigure (true);
+ }
+ return true;
+ }
+ case KeyPress:
+ case KeyRelease:
+ {
+ XKeyEvent* aKeyEvent = (XKeyEvent* )&theMsg;
+ const KeySym aKeySym = XLookupKeysym (aKeyEvent, 0);
+ const Aspect_VKey aVKey = Xw_Window::VirtualKeyFromNative (aKeySym);
+ if (aVKey != Aspect_VKey_UNKNOWN)
+ {
+ const double aTimeStamp = theListener.EventTime();
+ if (theMsg.type == KeyPress)
+ {
+ theListener.KeyDown (aVKey, aTimeStamp);
+ }
+ else
+ {
+ theListener.KeyUp (aVKey, aTimeStamp);
+ }
+ theListener.ProcessInput();
+ }
+ return true;
+ }
+ case ButtonPress:
+ case ButtonRelease:
+ {
+ const Graphic3d_Vec2i aPos (theMsg.xbutton.x, theMsg.xbutton.y);
+ Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
+ Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
+ if (theMsg.xbutton.button == Button1) { aButton = Aspect_VKeyMouse_LeftButton; }
+ if (theMsg.xbutton.button == Button2) { aButton = Aspect_VKeyMouse_MiddleButton; }
+ if (theMsg.xbutton.button == Button3) { aButton = Aspect_VKeyMouse_RightButton; }
+
+ if ((theMsg.xbutton.state & ControlMask) != 0) { aFlags |= Aspect_VKeyFlags_CTRL; }
+ if ((theMsg.xbutton.state & ShiftMask) != 0) { aFlags |= Aspect_VKeyFlags_SHIFT; }
+ if (theListener.Keys().IsKeyDown (Aspect_VKey_Alt))
+ {
+ aFlags |= Aspect_VKeyFlags_ALT;
+ }
+
+ if (theMsg.xbutton.button == Button4
+ || theMsg.xbutton.button == Button5)
+ {
+ if (theMsg.type != ButtonPress)
+ {
+ return true;
+ }
+
+ const double aDeltaF = (theMsg.xbutton.button == Button4 ? 1.0 : -1.0);
+ theListener.UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
+ }
+ else if (theMsg.type == ButtonPress)
+ {
+ theListener.PressMouseButton (aPos, aButton, aFlags, false);
+ }
+ else
+ {
+ theListener.ReleaseMouseButton (aPos, aButton, aFlags, false);
+ }
+ theListener.ProcessInput();
+ return true;
+ }
+ case MotionNotify:
+ {
+ if (theMsg.xmotion.window != myXWindow)
+ {
+ return false;
+ }
+
+ // remove all the ButtonMotionMask and process them at once
+ for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
+ {
+ if (!XCheckWindowEvent (aDisplay, myXWindow, ButtonMotionMask | PointerMotionMask, &theMsg))
+ {
+ break;
+ }
+ }
+
+ Graphic3d_Vec2i aPos (theMsg.xmotion.x, theMsg.xmotion.y);
+ Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
+ Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
+ if ((theMsg.xmotion.state & Button1Mask) != 0) { aButtons |= Aspect_VKeyMouse_LeftButton; }
+ if ((theMsg.xmotion.state & Button2Mask) != 0) { aButtons |= Aspect_VKeyMouse_MiddleButton; }
+ if ((theMsg.xmotion.state & Button3Mask) != 0) { aButtons |= Aspect_VKeyMouse_RightButton; }
+
+ if ((theMsg.xmotion.state & ControlMask) != 0) { aFlags |= Aspect_VKeyFlags_CTRL; }
+ if ((theMsg.xmotion.state & ShiftMask) != 0) { aFlags |= Aspect_VKeyFlags_SHIFT; }
+ if (theListener.Keys().IsKeyDown (Aspect_VKey_Alt))
+ {
+ aFlags |= Aspect_VKeyFlags_ALT;
+ }
+
+ theListener.UpdateMousePosition (aPos, aButtons, aFlags, false);
+ theListener.ProcessInput();
+ return true;
+ }
+ }
+ return false;
+}
+
#endif // Win32 or Mac OS X