minor fix on CMakeLists for checking MSVC_VERSION
[freeglut] / src / x11 / fg_state_x11.c
index 9765319..60906b3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * freeglut_state_x11.c
+ * fg_state_x11.c
  *
  * X11-specific freeglut state query methods.
  *
  */
 
 #include <GL/freeglut.h>
-#include "../fg_internal.h"
+#include "fg_internal.h"
+#ifdef EGL_VERSION_1_0
+#include "egl/fg_state_egl.h"
+#else
+#include "x11/fg_state_x11_glx.h"
+#endif
 
 int fgPlatformGlutDeviceGet ( GLenum eWhat )
 {
@@ -49,7 +54,7 @@ int fgPlatformGlutDeviceGet ( GLenum eWhat )
          * but at least one X server has a bug where this causes a segfault.
          *
          * In XFree86/Xorg servers, a mouse wheel is seen as two buttons
-         * rather than an Axis; "freeglut_main.c" expects this when
+         * rather than an Axis; "fg_main.c" expects this when
          * checking for a wheel event.
          */
         {
@@ -74,24 +79,30 @@ int fgPlatformGlutGet ( GLenum eWhat )
     {
 
     /*
-     * Those calls are somewhat similiar, as they use XGetWindowAttributes()
+     * Those calls are somewhat similar, as they use XGetWindowAttributes()
      * function
      */
     case GLUT_WINDOW_X:
     case GLUT_WINDOW_Y:
-    case GLUT_WINDOW_BORDER_WIDTH:
-    case GLUT_WINDOW_HEADER_HEIGHT:
     {
         int x, y;
-        Window w;
+        Window p,w;
 
         if( fgStructure.CurrentWindow == NULL )
             return 0;
 
+        if (fgStructure.CurrentWindow->Parent)
+            /* For child window, we should return relative to upper-left
+             * of parent's client area.
+             */
+            p = fgStructure.CurrentWindow->Parent->Window.Handle;
+        else
+            p = fgDisplay.pDisplay.RootWindow;
+            
         XTranslateCoordinates(
             fgDisplay.pDisplay.Display,
             fgStructure.CurrentWindow->Window.Handle,
-            fgDisplay.pDisplay.RootWindow,
+            p,
             0, 0, &x, &y, &w);
 
         switch ( eWhat )
@@ -99,18 +110,71 @@ int fgPlatformGlutGet ( GLenum eWhat )
         case GLUT_WINDOW_X: return x;
         case GLUT_WINDOW_Y: return y;
         }
-
-        if ( w == 0 )
+    }
+    
+    case GLUT_WINDOW_BORDER_WIDTH:
+    case GLUT_WINDOW_HEADER_HEIGHT:
+    {
+        Atom actual_type, net_extents;
+        int actual_format;
+        unsigned long nitems, bytes_after;
+        unsigned char *data = NULL;
+        int result, top, left;
+        
+        if (fgStructure.CurrentWindow == NULL || fgStructure.CurrentWindow->Parent)
+            /* can't get widths/heights if no current window
+             * and child windows don't have borders */
             return 0;
-        XTranslateCoordinates(
-            fgDisplay.pDisplay.Display,
-            fgStructure.CurrentWindow->Window.Handle,
-            w, 0, 0, &x, &y, &w);
+        
+        /* try to get through _NET_FRAME_EXTENTS */
+        net_extents = XInternAtom(fgDisplay.pDisplay.Display, "_NET_FRAME_EXTENTS", False);
+        
+        result = XGetWindowProperty(
+            fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, net_extents,
+            0, 4, False, AnyPropertyType, 
+            &actual_type, &actual_format, 
+            &nitems, &bytes_after, &data);
+
+        if (result == Success && nitems == 4 && bytes_after == 0)
+            /* got the data we expected, here's to hoping that
+             * _NET_FRAME_EXTENTS is supported and the data
+             * contain sensible values */
+        {
+            long *extents = (long *)data;
+            left = (int) extents[0]; /* we take left as border width, consistent with old logic. bottom and right better be the same... */
+            top  = (int) extents[2];
+        }
+        else
+        {
+            /* try in the previous way as fall-back */
+            Window w;
+            int x,y;
+            
+            XTranslateCoordinates(
+                fgDisplay.pDisplay.Display,
+                fgStructure.CurrentWindow->Window.Handle,
+                fgDisplay.pDisplay.RootWindow,
+                0, 0, &x, &y, &w);
+            
+            if (w == 0)
+                /* logic below needs w */
+                return 0;
+            
+            XTranslateCoordinates(
+                fgDisplay.pDisplay.Display,
+                fgStructure.CurrentWindow->Window.Handle,
+                w, 0, 0, &x, &y, &w);  
+            
+            left = x;
+            top  = y;
+        }
+        if (result == Success)
+            XFree(data);
 
         switch ( eWhat )
         {
-        case GLUT_WINDOW_BORDER_WIDTH:  return x;
-        case GLUT_WINDOW_HEADER_HEIGHT: return y;
+        case GLUT_WINDOW_BORDER_WIDTH:  return left;
+        case GLUT_WINDOW_HEADER_HEIGHT: return top;
         }
     }
 
@@ -150,6 +214,7 @@ int fgPlatformGlutGet ( GLenum eWhat )
         else
         {
           XVisualInfo * visualInfo;
+                 int result;
 #ifdef EGL_VERSION_1_0
          EGLint vid = 0;
          XVisualInfo visualTemplate;
@@ -161,13 +226,15 @@ int fgPlatformGlutGet ( GLenum eWhat )
          visualTemplate.visualid = vid;
          visualInfo = XGetVisualInfo(fgDisplay.pDisplay.Display, VisualIDMask, &visualTemplate, &num_visuals);
 #else
+         {
           const GLXFBConfig fbconfig =
                 fgStructure.CurrentWindow->Window.pContext.FBConfig;
 
           visualInfo =
                 glXGetVisualFromFBConfig( fgDisplay.pDisplay.Display, fbconfig );
+         }
 #endif
-          const int result = visualInfo->visual->map_entries;
+          result = visualInfo->visual->map_entries;
 
           XFree(visualInfo);