MacOSX doesn't define HOST_NAME_MAX in unistd.h, which made freeglut fail to
[freeglut] / src / x11 / fg_window_x11.c
index d2a3bbd..90f1966 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * freeglut_window_x11.c
+ * fg_window_x11.c
  *
  * Window management methods for X11
  *
@@ -28,8 +28,9 @@
 
 #define FREEGLUT_BUILDING_LIB
 #include <GL/freeglut.h>
-#include <limits.h>  /* LONG_MAX */
-#include <unistd.h>  /* usleep */
+#include <limits.h>     /* LONG_MAX */
+#include <unistd.h>     /* usleep, gethostname, getpid */
+#include <sys/types.h>  /* pid_t */
 #include "../fg_internal.h"
 
 #ifdef EGL_VERSION_1_0
 #include "x11/fg_window_x11_glx.h"
 #endif
 
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX  255
+#endif
+
+/* Motif window hints, only define needed ones */
+typedef struct
+{
+    unsigned long flags;
+    unsigned long functions;
+    unsigned long decorations;
+    long input_mode;
+    unsigned long status;
+} MotifWmHints;
+#define MWM_HINTS_DECORATIONS         (1L << 1)
+#define MWM_DECOR_BORDER              (1L << 1)
+
 static int fghResizeFullscrToggle(void)
 {
     XWindowAttributes attributes;
@@ -136,7 +153,7 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
     XEvent eventReturnBuffer; /* return buffer required for a call */
     unsigned long mask;
     unsigned int current_DisplayMode = fgState.DisplayMode ;
-    XConfigureEvent fakeEvent = {0};
+    XEvent fakeEvent = {0};
 
     /* Save the display mode if we are creating a menu window */
     if( window->IsMenu && ( ! fgStructure.MenuContext ) )
@@ -246,14 +263,14 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
     /* Fake configure event to force viewport setup
      * even with no window manager.
      */
-    fakeEvent.type = ConfigureNotify;
-    fakeEvent.display = fgDisplay.pDisplay.Display;
-    fakeEvent.window = window->Window.Handle;
-    fakeEvent.x = x;
-    fakeEvent.y = y;
-    fakeEvent.width = w;
-    fakeEvent.height = h;
-    XPutBackEvent(fgDisplay.pDisplay.Display, (XEvent*)&fakeEvent);
+    fakeEvent.xconfigure.type = ConfigureNotify;
+    fakeEvent.xconfigure.display = fgDisplay.pDisplay.Display;
+    fakeEvent.xconfigure.window = window->Window.Handle;
+    fakeEvent.xconfigure.x = x;
+    fakeEvent.xconfigure.y = y;
+    fakeEvent.xconfigure.width = w;
+    fakeEvent.xconfigure.height = h;
+    XPutBackEvent(fgDisplay.pDisplay.Display, &fakeEvent);
 
     /*
      * The GLX context creation, possibly trying the direct context rendering
@@ -340,6 +357,60 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
     XSetWMProtocols( fgDisplay.pDisplay.Display, window->Window.Handle,
                      &fgDisplay.pDisplay.DeleteWindow, 1 );
 
+    if (!isSubWindow && !window->IsMenu &&
+        ((fgState.DisplayMode & GLUT_BORDERLESS) || (fgState.DisplayMode & GLUT_CAPTIONLESS)))
+    {
+        /* _MOTIF_WM_HINTS is replaced by _NET_WM_WINDOW_TYPE, but that property does not allow precise
+         * control over the visual style of the window, which is what we are trying to achieve here.
+         * Stick with Motif and hope for the best... */
+        MotifWmHints hints = {0};
+        hints.flags = MWM_HINTS_DECORATIONS;
+        hints.decorations = (fgState.DisplayMode & GLUT_CAPTIONLESS) ? MWM_DECOR_BORDER:0;
+
+        XChangeProperty(fgDisplay.pDisplay.Display, window->Window.Handle,
+                        XInternAtom( fgDisplay.pDisplay.Display, "_MOTIF_WM_HINTS", False ),
+                        XInternAtom( fgDisplay.pDisplay.Display, "_MOTIF_WM_HINTS", False ), 32,
+                        PropModeReplace,
+                        (unsigned char*) &hints,
+                        sizeof(MotifWmHints) / sizeof(long));
+    }
+
+
+    if (fgDisplay.pDisplay.NetWMSupported
+        && fgDisplay.pDisplay.NetWMPid != None
+        && fgDisplay.pDisplay.ClientMachine != None)
+    {
+      char hostname[HOST_NAME_MAX];
+      pid_t pid = getpid();
+
+      if (pid > 0 && gethostname(hostname, sizeof(hostname)) > -1)
+      {
+        hostname[sizeof(hostname) - 1] = '\0';
+
+        XChangeProperty(
+            fgDisplay.pDisplay.Display,
+            window->Window.Handle,
+            fgDisplay.pDisplay.NetWMPid,
+            XA_CARDINAL,
+            32,
+            PropModeReplace,
+            (unsigned char *) &pid,
+            1
+        );
+
+        XChangeProperty(
+            fgDisplay.pDisplay.Display,
+            window->Window.Handle,
+            fgDisplay.pDisplay.ClientMachine,
+            XA_STRING,
+            8,
+            PropModeReplace,
+            (unsigned char *) hostname,
+            strlen(hostname)
+        );
+      }
+    }
+
 #ifdef EGL_VERSION_1_0
     fghPlatformOpenWindowEGL(window);
 #else