From ee3f0e0680c7a328987fbe8c6879477e738009c8 Mon Sep 17 00:00:00 2001 From: fayjf Date: Wed, 18 Nov 2009 01:52:13 +0000 Subject: [PATCH] Putting in the "glutFullScreen" support for Gnome and other X window managers per e-mail with patch file from John Tsiombikas dated 2:14 AM, 11/16/09 git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@849 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/freeglut_internal.h | 2 + freeglut/freeglut/src/freeglut_state.c | 18 +-- freeglut/freeglut/src/freeglut_structure.c | 1 + freeglut/freeglut/src/freeglut_window.c | 173 +++++++++++++-------- 4 files changed, 111 insertions(+), 83 deletions(-) diff --git a/freeglut/freeglut/src/freeglut_internal.h b/freeglut/freeglut/src/freeglut_internal.h index 5b2784a..7c71873 100644 --- a/freeglut/freeglut/src/freeglut_internal.h +++ b/freeglut/freeglut/src/freeglut_internal.h @@ -436,6 +436,8 @@ struct tagSFG_WindowState GLboolean KeyRepeating; /* Currently in repeat mode */ GLboolean NeedToResize; /* Do we need to resize the window? */ + + GLboolean IsFullscreen; /* is the window fullscreen? */ }; diff --git a/freeglut/freeglut/src/freeglut_state.c b/freeglut/freeglut/src/freeglut_state.c index a763d27..589f8ff 100644 --- a/freeglut/freeglut/src/freeglut_state.c +++ b/freeglut/freeglut/src/freeglut_state.c @@ -68,23 +68,9 @@ static int fghGetConfig( int attribute ) static int fghCheckFullScreen(void) { #if TARGET_HOST_POSIX_X11 - - int result; - - result = 0; - if (fgDisplay.StateFullScreen != None) - { - result = fgHintPresent(fgStructure.CurrentWindow->Window.Handle, - fgDisplay.State, - fgDisplay.StateFullScreen); - } - - return result; - + return fgStructure.CurrentWindow->State.IsFullscreen; #else - - return 0; - + return 0; #endif } diff --git a/freeglut/freeglut/src/freeglut_structure.c b/freeglut/freeglut/src/freeglut_structure.c index c1b9145..e092429 100644 --- a/freeglut/freeglut/src/freeglut_structure.c +++ b/freeglut/freeglut/src/freeglut_structure.c @@ -97,6 +97,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, window->State.IgnoreKeyRepeat = GL_FALSE; window->State.KeyRepeating = GL_FALSE; + window->State.IsFullscreen = GL_FALSE; /* * Open the window now. The fgOpenWindow() function is system diff --git a/freeglut/freeglut/src/freeglut_window.c b/freeglut/freeglut/src/freeglut_window.c index 1327b1e..e19eaff 100644 --- a/freeglut/freeglut/src/freeglut_window.c +++ b/freeglut/freeglut/src/freeglut_window.c @@ -1559,41 +1559,111 @@ void FGAPIENTRY glutPopWindow( void ) #endif } -/* - * Resize the current window so that it fits the whole screen - */ -void FGAPIENTRY glutFullScreen( void ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" ); - FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" ); +#if TARGET_HOST_POSIX_X11 +static int ewmh_fullscr_toggle(void); +static int resize_fullscr_toogle(void); - if (glutGet(GLUT_FULL_SCREEN)) - { - /* Leave full screen state before resizing. */ - glutFullScreenToggle(); +static int toggle_fullscreen(void) +{ + /* first try the EWMH (_NET_WM_STATE) method ... */ + if(ewmh_fullscr_toggle() != -1) { + return 0; } - { -#if TARGET_HOST_POSIX_X11 + /* fall back to resizing the window */ + if(resize_fullscr_toogle() != -1) { + return 0; + } + return -1; +} - Status status; /* Returned by XGetWindowAttributes(), not checked. */ - XWindowAttributes attributes; +#define _NET_WM_STATE_TOGGLE 2 +static int ewmh_fullscr_toggle(void) +{ + XEvent xev; + long evmask = SubstructureRedirectMask | SubstructureNotifyMask; - status = XGetWindowAttributes(fgDisplay.Display, - fgStructure.CurrentWindow->Window.Handle, - &attributes); + if(!fgDisplay.State || !fgDisplay.StateFullScreen) { + return -1; + } + + xev.type = ClientMessage; + xev.xclient.window = fgStructure.CurrentWindow->Window.Handle; + xev.xclient.message_type = fgDisplay.State; + xev.xclient.format = 32; + xev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE; + xev.xclient.data.l[1] = fgDisplay.StateFullScreen; + xev.xclient.data.l[2] = 0; /* no second property to toggle */ + xev.xclient.data.l[3] = 1; /* source indication: application */ + xev.xclient.data.l[4] = 0; /* unused */ + + if(!XSendEvent(fgDisplay.Display, fgDisplay.RootWindow, 0, evmask, &xev)) { + return -1; + } + return 0; +} + +static int resize_fullscr_toogle(void) +{ + XWindowAttributes attributes; + + 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.OldWidth; + fgStructure.CurrentWindow->State.Height = win->State.OldHeight; + + } else { + /* resize the window to cover the entire screen */ + XGetWindowAttributes(fgDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + &attributes); + /* * The "x" and "y" members of "attributes" are the window's coordinates * relative to its parent, i.e. to the decoration window. */ XMoveResizeWindow(fgDisplay.Display, - fgStructure.CurrentWindow->Window.Handle, - -attributes.x, - -attributes.y, - fgDisplay.ScreenWidth, - fgDisplay.ScreenHeight); + fgStructure.CurrentWindow->Window.Handle, + -attributes.x, + -attributes.y, + fgDisplay.ScreenWidth, + fgDisplay.ScreenHeight); + } + return 0; +} +#endif /* TARGET_HOST_POSIX_X11 */ + + +/* + * Resize the current window so that it fits the whole screen + */ +void FGAPIENTRY glutFullScreen( void ) +{ + SFG_Window *win; + + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" ); + FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" ); + + win = fgStructure.CurrentWindow; + +#if TARGET_HOST_POSIX_X11 + if(!glutGet(GLUT_FULL_SCREEN)) { + if(toggle_fullscreen() != -1) { + win->State.IsFullscreen = GL_TRUE; + } + } #elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: what about WinCE */ + + if (glutGet(GLUT_FULL_SCREEN)) + { + /* Leave full screen state before resizing. */ + glutFullScreenToggle(); + } + + { RECT rect; /* For fullscreen mode, force the top-left corner to 0,0 @@ -1625,8 +1695,10 @@ void FGAPIENTRY glutFullScreen( void ) SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER ); -#endif + + win->State.IsFullscreen = GL_TRUE; } +#endif } /* @@ -1634,54 +1706,21 @@ void FGAPIENTRY glutFullScreen( void ) */ void FGAPIENTRY glutFullScreenToggle( void ) { + SFG_Window *win; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" ); FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" ); - { + win = fgStructure.CurrentWindow; + #if TARGET_HOST_POSIX_X11 - - if (fgDisplay.StateFullScreen != None) - { - XEvent xevent; - long event_mask; - int status; - - xevent.type = ClientMessage; - xevent.xclient.type = ClientMessage; - xevent.xclient.serial = 0; - xevent.xclient.send_event = True; - xevent.xclient.display = fgDisplay.Display; - xevent.xclient.window = fgStructure.CurrentWindow->Window.Handle; - xevent.xclient.message_type = fgDisplay.State; - xevent.xclient.format = 32; - xevent.xclient.data.l[0] = 2; /* _NET_WM_STATE_TOGGLE */ - xevent.xclient.data.l[1] = fgDisplay.StateFullScreen; - xevent.xclient.data.l[2] = 0; - xevent.xclient.data.l[3] = 0; - xevent.xclient.data.l[4] = 0; - - /*** Don't really understand how event masks work... ***/ - event_mask = SubstructureRedirectMask | SubstructureNotifyMask; - - status = XSendEvent(fgDisplay.Display, - fgDisplay.RootWindow, - False, - event_mask, - &xevent); - FREEGLUT_INTERNAL_ERROR_EXIT(status != 0, - "XSendEvent failed", - "glutFullScreenToggle"); - } - else -#endif - { - /* - * If the window manager is not Net WM compliant, fall back to legacy - * behaviour. - */ - glutFullScreen(); - } + if(toggle_fullscreen() != -1) { + win->State.IsFullscreen = !win->State.IsFullscreen; } +#elif TARGET_HOST_MS_WINDOWS + glutFullScreen(); + win->State.IsFullscreen = !win->State.IsFullscreen; +#endif } /*