X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fx11%2Ffg_window_x11.c;h=2736a5925a6ffb5932b37f9554fcb5a072e9797a;hb=a0871c21cb859cea6f24802b6828352a211ab102;hp=6f927c2c454facefc057430fde7e62f6384a51f5;hpb=a7362e5d688d2d2873d6bab49b86302aa588f1bf;p=freeglut diff --git a/src/x11/fg_window_x11.c b/src/x11/fg_window_x11.c index 6f927c2..2736a59 100644 --- a/src/x11/fg_window_x11.c +++ b/src/x11/fg_window_x11.c @@ -1,5 +1,5 @@ /* - * freeglut_window_x11.c + * fg_window_x11.c * * Window management methods for X11 * @@ -28,12 +28,11 @@ #define FREEGLUT_BUILDING_LIB #include -#include /* LONG_MAX */ -#include /* usleep */ +#include /* LONG_MAX */ +#include /* usleep, gethostname, getpid */ +#include /* pid_t */ #include "../fg_internal.h" -extern void fghRedrawWindow(SFG_Window *window); - #ifdef EGL_VERSION_1_0 #include "egl/fg_window_egl.h" #define fghCreateNewContext fghCreateNewContextEGL @@ -41,18 +40,37 @@ extern void fghRedrawWindow(SFG_Window *window); #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; + SFG_Window *win = fgStructure.CurrentWindow; if(glutGet(GLUT_FULL_SCREEN)) { /* restore original window size */ - SFG_Window *win = fgStructure.CurrentWindow; - fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE; - fgStructure.CurrentWindow->State.Width = win->State.pWState.OldWidth; - fgStructure.CurrentWindow->State.Height = win->State.pWState.OldHeight; + fgStructure.CurrentWindow->State.WorkMask = GLUT_SIZE_WORK; + fgStructure.CurrentWindow->State.DesiredWidth = win->State.pWState.OldWidth; + fgStructure.CurrentWindow->State.DesiredHeight = win->State.pWState.OldHeight; } else { + fgStructure.CurrentWindow->State.pWState.OldWidth = win->State.Width; + fgStructure.CurrentWindow->State.pWState.OldHeight = win->State.Height; + /* resize the window to cover the entire screen */ XGetWindowAttributes(fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, @@ -135,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 ) ) @@ -164,6 +182,8 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, fgState.DisplayMode |= GLUT_DOUBLE ; fghChooseConfig(&WINDOW_CONFIG); fgState.DisplayMode &= ~GLUT_DOUBLE; + + if( WINDOW_CONFIG ) goto done_retry; } #endif @@ -172,8 +192,20 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, fgState.DisplayMode &= ~GLUT_MULTISAMPLE ; fghChooseConfig(&WINDOW_CONFIG); fgState.DisplayMode |= GLUT_MULTISAMPLE; + + if( WINDOW_CONFIG ) goto done_retry; + } + + if( fgState.DisplayMode & GLUT_SRGB ) + { + fgState.DisplayMode &= ~GLUT_SRGB ; + fghChooseConfig(&WINDOW_CONFIG); + fgState.DisplayMode |= GLUT_SRGB; + + if( WINDOW_CONFIG ) goto done_retry; } } +done_retry: FREEGLUT_INTERNAL_ERROR_EXIT( WINDOW_CONFIG != NULL, "FBConfig with necessary capabilities not found", "fgOpenWindow" ); @@ -245,14 +277,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 @@ -299,12 +331,6 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, } #endif - /* - * XXX Assume the new window is visible by default - * XXX Is this a safe assumption? - */ - window->State.Visible = GL_TRUE; - sizeHints.flags = 0; if ( positionUse ) sizeHints.flags |= USPosition; @@ -345,6 +371,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 @@ -361,11 +441,16 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, fgRegisterDevices( fgDisplay.pDisplay.Display, &(window->Window.Handle) ); #endif - XMapWindow( fgDisplay.pDisplay.Display, window->Window.Handle ); + if (!window->IsMenu) /* Don't show window after creation if its a menu */ + { + XMapWindow( fgDisplay.pDisplay.Display, window->Window.Handle ); + window->State.Visible = GL_TRUE; + } XFree(visualInfo); - if( !isSubWindow) + /* wait till window visible */ + if( !isSubWindow && !window->IsMenu) XPeekIfEvent( fgDisplay.pDisplay.Display, &eventReturnBuffer, &fghWindowIsVisible, (XPointer)(window->Window.Handle) ); #undef WINDOW_CONFIG } @@ -383,15 +468,6 @@ void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) /* - * A static helper function to execute display callback for a window - */ -void fgPlatformDisplayWindow ( SFG_Window *window ) -{ - fghRedrawWindow ( window ) ; -} - - -/* * Closes a window, destroying the frame and OpenGL context */ void fgPlatformCloseWindow( SFG_Window* window ) @@ -412,35 +488,35 @@ void fgPlatformCloseWindow( SFG_Window* window ) /* - * This function makes the current window visible + * This function makes the specified window visible */ -void fgPlatformGlutShowWindow( void ) +void fgPlatformShowWindow( SFG_Window *window ) { - XMapWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle ); + XMapWindow( fgDisplay.pDisplay.Display, window->Window.Handle ); XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ } /* - * This function hides the current window + * This function hides the specified window */ -void fgPlatformGlutHideWindow( void ) +void fgPlatformHideWindow( SFG_Window *window ) { - if( fgStructure.CurrentWindow->Parent == NULL ) + if( window->Parent == NULL ) XWithdrawWindow( fgDisplay.pDisplay.Display, - fgStructure.CurrentWindow->Window.Handle, + window->Window.Handle, fgDisplay.pDisplay.Screen ); else XUnmapWindow( fgDisplay.pDisplay.Display, - fgStructure.CurrentWindow->Window.Handle ); + window->Window.Handle ); XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ } /* - * Iconify the current window (top-level windows only) + * Iconify the specified window (top-level windows only) */ -void fgPlatformGlutIconifyWindow( void ) +void fgPlatformIconifyWindow( SFG_Window *window ) { - XIconifyWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, + XIconifyWindow( fgDisplay.pDisplay.Display, window->Window.Handle, fgDisplay.pDisplay.Screen ); XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ @@ -490,59 +566,35 @@ void fgPlatformGlutSetIconTitle( const char* title ) } /* - * Change the current window's position + * Change the specified window's position */ -void fgPlatformGlutPositionWindow( int x, int y ) +void fgPlatformPositionWindow( SFG_Window *window, int x, int y ) { - XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, + XMoveWindow( fgDisplay.pDisplay.Display, window->Window.Handle, x, y ); XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */ } /* - * Lowers the current window (by Z order change) - */ -void fgPlatformGlutPushWindow( void ) -{ - XLowerWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle ); -} - -/* - * Raises the current window (by Z order change) - */ -void fgPlatformGlutPopWindow( void ) -{ - XRaiseWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle ); -} - -/* - * Resize the current window so that it fits the whole screen + * Lowers the specified window (by Z order change) */ -void fgPlatformGlutFullScreen( SFG_Window *win ) +void fgPlatformPushWindow( SFG_Window *window ) { - if(!glutGet(GLUT_FULL_SCREEN)) { - if(fghToggleFullscreen() != -1) { - win->State.IsFullscreen = GL_TRUE; - } - } + XLowerWindow( fgDisplay.pDisplay.Display, window->Window.Handle ); } /* - * If we are fullscreen, resize the current window back to its original size + * Raises the specified window (by Z order change) */ -void fgPlatformGlutLeaveFullScreen( SFG_Window *win ) +void fgPlatformPopWindow( SFG_Window *window ) { - if(glutGet(GLUT_FULL_SCREEN)) { - if(fghToggleFullscreen() != -1) { - win->State.IsFullscreen = GL_FALSE; - } - } + XRaiseWindow( fgDisplay.pDisplay.Display, window->Window.Handle ); } /* * Toggle the window's full screen state. */ -void fgPlatformGlutFullScreenToggle( SFG_Window *win ) +void fgPlatformFullScreenToggle( SFG_Window *win ) { if(fghToggleFullscreen() != -1) { win->State.IsFullscreen = !win->State.IsFullscreen;