4d65c64
--- plib-1.8.4/src/pw/pw.h.fs	2004-04-07 01:45:19.000000000 +0200
4d65c64
+++ plib-1.8.4/src/pw/pw.h	2006-05-17 16:03:09.000000000 +0200
4d65c64
@@ -54,6 +54,11 @@
4d65c64
 void pwSetCursor     ( int c ) ;
4d65c64
 void pwCleanup       () ;
4d65c64
 void pwSetAutoRepeatKey ( bool enable ) ;
4d65c64
+void pwSetResizable ( bool enable ) ;
4d65c64
+void pwSetCursorEx ( int wm, int fs ) ;
4d65c64
+void pwSetFullscreen () ;
4d65c64
+void pwSetWindowed () ;
4d65c64
+void pwToggleFullscreen () ;
4d65c64
 
4d65c64
 #define PW_CURSOR_NONE    0
4d65c64
 #define PW_CURSOR_RIGHT   1
4d65c64
--- plib-1.8.4/src/pw/pwX11.cxx.fs	2004-04-07 01:45:19.000000000 +0200
4d65c64
+++ plib-1.8.4/src/pw/pwX11.cxx	2006-05-17 16:06:07.000000000 +0200
4d65c64
@@ -74,14 +74,31 @@
4d65c64
 
4d65c64
 #endif
4d65c64
 
4d65c64
-static bool initialised    = false ;
4d65c64
+/* For XF86VIDMODE Support */
4d65c64
+#ifdef XF86VIDMODE
4d65c64
+#include <X11/extensions/xf86vmode.h>   
4d65c64
+
4d65c64
+static struct xf86vidmode_data {
4d65c64
+  int vidmode_available;
4d65c64
+  XF86VidModeModeInfo orig_mode;
4d65c64
+  int orig_viewport_x;
4d65c64
+  int orig_viewport_y;
4d65c64
+} XF86VidModeData = { 1, { 0 }, 0, 0 };
4d65c64
+
4d65c64
+static void xf86_vidmode_init () ;
4d65c64
+#endif
4d65c64
+
4d65c64
 static bool insideCallback = false ;
4d65c64
+static bool resizable      = true;
4d65c64
+static bool mouse_grabbed  = false;
4d65c64
+static bool keyb_grabbed = false;
4d65c64
 static int modifiers   = 0 ;
4d65c64
 static int origin [2]  = {   0,   0 } ;
4d65c64
 static int size   [2]  = { 640, 480 } ;
4d65c64
 static int currScreen  = 0 ;
4d65c64
 static int currConnect = 0 ;
4d65c64
-static int currCursor  = PW_CURSOR_LEFT ;
4d65c64
+static int wmCursor    = PW_CURSOR_LEFT ;
4d65c64
+static int fsCursor    = PW_CURSOR_LEFT ;
4d65c64
 
4d65c64
 static pwResizeCB     *resizeCB = NULL ;
4d65c64
 static pwExitCB       *exitCB   = NULL ;
4d65c64
@@ -92,12 +110,17 @@
4d65c64
 static Display     *currDisplay = NULL ;
4d65c64
 static XVisualInfo *visualInfo  = NULL ;
4d65c64
 static Window       currHandle  ;
4d65c64
+static Window       wmWindow    ;
4d65c64
+static Window       fsWindow    = None ;
4d65c64
 static GLXContext   currContext ;
4d65c64
 static Window       rootWindow  ;
4d65c64
 static Atom         delWinAtom  ;
4d65c64
+static XTextProperty *titlePropertyPtr = NULL;
4d65c64
 
4d65c64
 static bool autoRepeat = false ;
4d65c64
 
4d65c64
+static void getEvents ();
4d65c64
+
4d65c64
 void pwSetAutoRepeatKey ( bool enable )
4d65c64
 {
4d65c64
   autoRepeat = enable ;
4d65c64
@@ -181,6 +204,41 @@
4d65c64
 }
4d65c64
 
4d65c64
 
4d65c64
+static void pwRealSetResizable ( bool enable, int width, int height )
4d65c64
+{
4d65c64
+  XSizeHints         sizeHints ;
4d65c64
+  XWMHints             wmHints ;
4d65c64
+
4d65c64
+  resizable = enable;
4d65c64
+
4d65c64
+  if (resizable)
4d65c64
+    sizeHints.flags     = USSize;
4d65c64
+  else
4d65c64
+    sizeHints.flags     = PSize | PMinSize | PMaxSize;;
4d65c64
+
4d65c64
+  if ( origin[0] >= 0 && origin[1] >= 0 )
4d65c64
+    sizeHints.flags |= USPosition ;
4d65c64
+
4d65c64
+  sizeHints.x           = origin[0] ;
4d65c64
+  sizeHints.y           = origin[1] ;
4d65c64
+  sizeHints.width       = width ;
4d65c64
+  sizeHints.height      = height ;
4d65c64
+  sizeHints.min_width   = width ;
4d65c64
+  sizeHints.min_height  = height ;
4d65c64
+  sizeHints.base_width  = width ;
4d65c64
+  sizeHints.base_height = height ;
4d65c64
+  sizeHints.max_width   = width ;
4d65c64
+  sizeHints.max_height  = height ;
4d65c64
+
4d65c64
+  wmHints.flags         = StateHint;
4d65c64
+  wmHints.initial_state = NormalState ;
4d65c64
+
4d65c64
+  XSetWMProperties ( currDisplay, wmWindow,
4d65c64
+	                  titlePropertyPtr, titlePropertyPtr, 0, 0,
4d65c64
+                          &sizeHints, &wmHints, NULL ) ;
4d65c64
+}
4d65c64
+
4d65c64
+
4d65c64
 void pwInit ( int multisample, int num_samples )
4d65c64
 {
4d65c64
   pwInit ( 0, 0, -1, -1, multisample, "NoName", FALSE, num_samples ) ;
4d65c64
@@ -191,7 +249,7 @@
4d65c64
                       pwMousePosFunc *mp, pwResizeCB *rcb,
4d65c64
                       pwExitCB *ecb )
4d65c64
 {
4d65c64
-  if ( ! initialised )
4d65c64
+  if ( ! currDisplay )
4d65c64
   {
4d65c64
     fprintf ( stderr, "PW: You must not call pwSetCallbacks before pwInit.\n");
4d65c64
     exit ( 1 ) ;
4d65c64
@@ -228,6 +286,7 @@
4d65c64
   {
4d65c64
     fprintf ( stderr, "PW: GLX extension not available on display '%s'?!?",
4d65c64
                                              XDisplayName ( displayName ) ) ;
4d65c64
+    XCloseDisplay ( currDisplay ) ;
4d65c64
     exit ( 1 ) ;
4d65c64
   }
4d65c64
 
4d65c64
@@ -235,6 +294,11 @@
4d65c64
   rootWindow   = RootWindow       ( currDisplay, currScreen ) ;
4d65c64
   currConnect  = ConnectionNumber ( currDisplay ) ;
4d65c64
   delWinAtom   = XInternAtom      ( currDisplay, "WM_DELETE_WINDOW", 0 ) ;
4d65c64
+  fsWindow     = None;
4d65c64
+  
4d65c64
+#ifdef XF86VIDMODE
4d65c64
+  xf86_vidmode_init () ;
4d65c64
+#endif
4d65c64
 
4d65c64
   if ( w == -1 ) w = DisplayWidth  ( currDisplay, currScreen ) ;
4d65c64
   if ( h == -1 ) h = DisplayHeight ( currDisplay, currScreen ) ;
4d65c64
@@ -244,10 +308,8 @@
4d65c64
   size   [ 0 ] = w ;
4d65c64
   size   [ 1 ] = h ;
4d65c64
 
4d65c64
+  static XTextProperty titleProperty ;
4d65c64
   XSetWindowAttributes attribs ;
4d65c64
-  XTextProperty   textProperty ;
4d65c64
-  XSizeHints         sizeHints ;
4d65c64
-  XWMHints             wmHints ;
4d65c64
   unsigned int            mask ;
4d65c64
   PixelFormat               pf ;
4d65c64
 
4d65c64
@@ -280,6 +342,7 @@
4d65c64
     if ( visualInfo == NULL )
4d65c64
     {
4d65c64
       fprintf ( stderr, "PW: Unable to open a suitable graphics window,\n" ) ;
4d65c64
+      XCloseDisplay ( currDisplay ) ;
4d65c64
       exit ( 1 ) ;
4d65c64
     }
4d65c64
   }
4d65c64
@@ -300,7 +363,12 @@
4d65c64
 
4d65c64
   mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
4d65c64
 
4d65c64
-  currHandle = XCreateWindow ( currDisplay, rootWindow,
4d65c64
+  wmWindow = XCreateWindow ( currDisplay, rootWindow,
4d65c64
+                           x, y, w, h, 0, visualInfo->depth,
4d65c64
+                           InputOutput, visualInfo->visual,
4d65c64
+                           mask, &attribs ) ;
4d65c64
+
4d65c64
+  currHandle = XCreateWindow ( currDisplay, wmWindow,
4d65c64
                            x, y, w, h, 0, visualInfo->depth,
4d65c64
                            InputOutput, visualInfo->visual,
4d65c64
                            mask, &attribs ) ;
4d65c64
@@ -315,19 +383,6 @@
4d65c64
     fprintf ( stderr,"PW: That may be bad for performance." ) ;
4d65c64
   }
4d65c64
 
4d65c64
-  sizeHints.flags = 0 ;
4d65c64
-
4d65c64
-  if ( x >= 0 && y >= 0 )
4d65c64
-    sizeHints.flags |= USPosition ;
4d65c64
-
4d65c64
-  sizeHints.flags |= USSize ;
4d65c64
-
4d65c64
-  sizeHints.x      = x ; sizeHints.y      = y ;
4d65c64
-  sizeHints.width  = w ; sizeHints.height = h ;
4d65c64
-
4d65c64
-  wmHints.flags = StateHint;
4d65c64
-  wmHints.initial_state = NormalState ;
4d65c64
-
4d65c64
   PropMotifWmHints hints  ;
4d65c64
   Atom prop_t ;
4d65c64
   Atom prop   ;
4d65c64
@@ -338,17 +393,17 @@
4d65c64
   prop_t = prop = XInternAtom ( currDisplay, "_MOTIF_WM_HINTS", True ) ;
4d65c64
 
4d65c64
   if ( prop != 0 )
4d65c64
-    XChangeProperty ( currDisplay, currHandle, prop, prop_t, 32,
4d65c64
+    XChangeProperty ( currDisplay, wmWindow, prop, prop_t, 32,
4d65c64
                       PropModeReplace, (unsigned char *) &hints,
4d65c64
                       PROP_MOTIF_WM_HINTS_ELEMENTS) ;
4d65c64
 
4d65c64
-  XStringListToTextProperty ( (char **) &title, 1, &textProperty ) ;
4d65c64
+  if (XStringListToTextProperty ( (char **) &title, 1, &titleProperty ) )
4d65c64
+    titlePropertyPtr = &titleProperty;
4d65c64
 
4d65c64
-  XSetWMProperties ( currDisplay, currHandle,
4d65c64
-	                  &textProperty, &textProperty, 0, 0,
4d65c64
-                          &sizeHints, &wmHints, NULL ) ;
4d65c64
-  XSetWMProtocols  ( currDisplay, currHandle, &delWinAtom  , 1 );
4d65c64
+  pwRealSetResizable   ( true, w, h );
4d65c64
+  XSetWMProtocols  ( currDisplay, wmWindow, &delWinAtom  , 1 );
4d65c64
   XMapWindow       ( currDisplay, currHandle ) ;
4d65c64
+  XMapWindow       ( currDisplay, wmWindow ) ;
4d65c64
   glXMakeCurrent   ( currDisplay, currHandle, currContext ) ;
4d65c64
 
4d65c64
   pwSetCursor ( PW_CURSOR_LEFT ) ;
4d65c64
@@ -357,13 +412,14 @@
4d65c64
   glHint ( GL_MULTISAMPLE_FILTER_HINT_NV, multisample ) ;
4d65c64
 #endif
4d65c64
 
4d65c64
+  atexit( pwCleanup ) ;
4d65c64
+
4d65c64
   kbCB     = NULL ;
4d65c64
   msCB     = NULL ;
4d65c64
   mpCB     = NULL ;
4d65c64
   resizeCB = NULL ;
4d65c64
   exitCB   = defaultExitFunc ;
4d65c64
 
4d65c64
-  initialised = true ;
4d65c64
   insideCallback = false ;
4d65c64
 
4d65c64
   glClear ( GL_COLOR_BUFFER_BIT ) ;
4d65c64
@@ -373,6 +429,14 @@
4d65c64
 }
4d65c64
 
4d65c64
 
4d65c64
+void pwSetResizable ( bool enable )
4d65c64
+{
4d65c64
+  /* Make sure we get any last resize events before doing this */
4d65c64
+  getEvents();
4d65c64
+  pwRealSetResizable ( enable, size[0], size[1] ) ;
4d65c64
+}
4d65c64
+
4d65c64
+
4d65c64
 void pwGetSize ( int *w, int *h )
4d65c64
 {
4d65c64
   if ( w ) *w = size[0] ;
4d65c64
@@ -380,17 +444,19 @@
4d65c64
 }
4d65c64
 
4d65c64
 
4d65c64
-void pwSetCursor ( int c )
4d65c64
+void pwRealSetCursor ( int c )
4d65c64
 {
4d65c64
+  int newCursor;
4d65c64
+
4d65c64
   switch ( c )
4d65c64
   {
4d65c64
-    case PW_CURSOR_RIGHT  : currCursor = XC_right_ptr      ; break ;
4d65c64
-    case PW_CURSOR_LEFT   : currCursor = XC_left_ptr       ; break ;
4d65c64
-    case PW_CURSOR_QUERY  : currCursor = XC_question_arrow ; break ;
4d65c64
-    case PW_CURSOR_AIM    : currCursor = XC_target         ; break ;
4d65c64
-    case PW_CURSOR_CIRCLE : currCursor = XC_circle         ; break ;
4d65c64
-    case PW_CURSOR_WAIT   : currCursor = XC_watch          ; break ;
4d65c64
-    case PW_CURSOR_CROSS  : currCursor = XC_crosshair      ; break ;
4d65c64
+    case PW_CURSOR_RIGHT  : newCursor = XC_right_ptr      ; break ;
4d65c64
+    case PW_CURSOR_LEFT   : newCursor = XC_left_ptr       ; break ;
4d65c64
+    case PW_CURSOR_QUERY  : newCursor = XC_question_arrow ; break ;
4d65c64
+    case PW_CURSOR_AIM    : newCursor = XC_target         ; break ;
4d65c64
+    case PW_CURSOR_CIRCLE : newCursor = XC_circle         ; break ;
4d65c64
+    case PW_CURSOR_WAIT   : newCursor = XC_watch          ; break ;
4d65c64
+    case PW_CURSOR_CROSS  : newCursor = XC_crosshair      ; break ;
4d65c64
 
4d65c64
     case PW_CURSOR_NONE  :
4d65c64
     default:
4d65c64
@@ -406,36 +472,231 @@
4d65c64
                         XCreatePixmapCursor ( currDisplay,
4d65c64
                             pix, pix, &bcol, &bcol, 0, 0 ) ) ;
4d65c64
         XFreePixmap   ( currDisplay, pix ) ;
4d65c64
-
4d65c64
-        currCursor = 0 ;
4d65c64
       }
4d65c64
       return ;
4d65c64
   }
4d65c64
  
4d65c64
   XDefineCursor( currDisplay, currHandle,
4d65c64
-                 XCreateFontCursor ( currDisplay, currCursor ) ) ;
4d65c64
+                 XCreateFontCursor ( currDisplay, newCursor ) ) ;
4d65c64
 }
4d65c64
 
4d65c64
 
4d65c64
-void pwSetSize ( int w, int h )
4d65c64
+void pwSetCursor ( int c )
4d65c64
+{
4d65c64
+  pwRealSetCursor (c);
4d65c64
+  wmCursor = c;
4d65c64
+  fsCursor = c;
4d65c64
+}
4d65c64
+
4d65c64
+
4d65c64
+void pwSetCursorEx ( int wm, int fs )
4d65c64
 {
4d65c64
+  if (fsWindow == None)
4d65c64
+    pwRealSetCursor (wm);
4d65c64
+  else
4d65c64
+    pwRealSetCursor (fs);
4d65c64
+  wmCursor = wm;
4d65c64
+  fsCursor = fs;
4d65c64
+}
4d65c64
+
4d65c64
+
4d65c64
+#ifdef XF86VIDMODE      
4d65c64
+static void
4d65c64
+xf86_vidmode_init ( void )
4d65c64
+{
4d65c64
+  int i,j;
4d65c64
+  XF86VidModeModeLine *l = (XF86VidModeModeLine *)((char *)
4d65c64
+    &XF86VidModeData.orig_mode + sizeof XF86VidModeData.orig_mode.dotclock);
4d65c64
+  
4d65c64
+  if (!XF86VidModeQueryVersion(currDisplay, &i, &j))
4d65c64
+    XF86VidModeData.vidmode_available = 0;
4d65c64
+  else if (!XF86VidModeQueryExtension(currDisplay, &i, &j))
4d65c64
+    XF86VidModeData.vidmode_available = 0;
4d65c64
+  else if (!XF86VidModeGetModeLine(currDisplay, currScreen,
4d65c64
+            (int *)&XF86VidModeData.orig_mode.dotclock, l))
4d65c64
+    XF86VidModeData.vidmode_available = 0;
4d65c64
+  else if (!XF86VidModeGetViewPort(currDisplay, currScreen,
4d65c64
+            &XF86VidModeData.orig_viewport_x,
4d65c64
+            &XF86VidModeData.orig_viewport_y))
4d65c64
+    XF86VidModeData.vidmode_available = 0;
4d65c64
+  
4d65c64
+  if (!XF86VidModeData.vidmode_available)
4d65c64
+    fprintf(stderr, "Warning: XF86VidMode not available\n");
4d65c64
+}
4d65c64
+
4d65c64
+
4d65c64
+/* qsort comparison function for sorting the modes */
4d65c64
+static int cmpmodes(const void *va, const void *vb)
4d65c64
+{
4d65c64
+    const XF86VidModeModeInfo *a = *(const XF86VidModeModeInfo **)va;
4d65c64
+    const XF86VidModeModeInfo *b = *(const XF86VidModeModeInfo **)vb;
4d65c64
+    if ( a->hdisplay == b->hdisplay )
4d65c64
+        return b->vdisplay - a->vdisplay;  
4d65c64
+    else
4d65c64
+        return b->hdisplay - a->hdisplay;
4d65c64
+}
4d65c64
+
4d65c64
+
4d65c64
+static void pwXf86VmSetFullScreenResolution (int desired_width,
4d65c64
+  int desired_height, int &result_width, int &result_height)
4d65c64
+{
4d65c64
+  int i;
4d65c64
+  XF86VidModeModeLine mode ; /* = { .hdisplay = 0, .privsize = 0 } ; */
4d65c64
+  XF86VidModeModeInfo **modes;
4d65c64
+  int mode_count;
4d65c64
+  
4d65c64
+  /* C++ can't do struct initialization by struct member name? */
4d65c64
+  mode.hdisplay = 0;
4d65c64
+  mode.privsize = 0;
4d65c64
+
4d65c64
+  if ( ! XF86VidModeData.vidmode_available )
4d65c64
+    return;
4d65c64
+  
4d65c64
+  /* Try to switch video mode. This must be done after the pointer is
4d65c64
+     grabbed, because otherwise it can be outside the window negating the
4d65c64
+     XF86VidModeSetViewPort. */
4d65c64
+  if (XF86VidModeGetModeLine(currDisplay, currScreen, &i, &mode))
4d65c64
+  {
4d65c64
+    result_width  = mode.hdisplay;
4d65c64
+    result_height = mode.vdisplay;
4d65c64
+  }
4d65c64
+    
4d65c64
+  /* Get list of modelines.  */
4d65c64
+  if (!XF86VidModeGetAllModeLines(currDisplay, currScreen, &mode_count, &modes))
4d65c64
+          mode_count = 0;
4d65c64
+     
4d65c64
+  /* Search for an exact matching video mode.  */
4d65c64
+  for (i = 0; i < mode_count; i++) {
4d65c64
+     if ((modes[i]->hdisplay == desired_width) && 
4d65c64
+         (modes[i]->vdisplay == desired_height))
4d65c64
+       break;
4d65c64
+  }
4d65c64
+
4d65c64
+  /* Search for a non exact match (smallest bigger res). */
4d65c64
+  if (i == mode_count) {
4d65c64
+    int best_width = 0, best_height = 0;
4d65c64
+    qsort(modes, mode_count, sizeof(void *), cmpmodes);
4d65c64
+    for (i = mode_count-1; i > 0; i--) {
4d65c64
+       if ( ! best_width ) {
4d65c64
+          if ( (modes[i]->hdisplay >= desired_width) &&
4d65c64
+               (modes[i]->vdisplay >= desired_height) ) {
4d65c64
+             best_width = modes[i]->hdisplay;
4d65c64
+             best_height = modes[i]->vdisplay;
4d65c64
+          }
4d65c64
+       } else {
4d65c64
+          if ( (modes[i]->hdisplay != best_width) ||
4d65c64
+               (modes[i]->vdisplay != best_height) ) {
4d65c64
+             i++;
4d65c64
+             break;
4d65c64
+          }
4d65c64
+       }
4d65c64
+    }
4d65c64
+  }
4d65c64
+      
4d65c64
+  /* Switch video mode.  */
4d65c64
+  if ((i >= 0) &&
4d65c64
+      ((modes[i]->hdisplay != mode.hdisplay) ||
4d65c64
+       (modes[i]->vdisplay != mode.vdisplay)) &&
4d65c64
+      XF86VidModeSwitchToMode(currDisplay, currScreen, modes[i]))
4d65c64
+  {
4d65c64
+    result_width  = modes[i]->hdisplay;
4d65c64
+    result_height = modes[i]->vdisplay;
4d65c64
+  }
4d65c64
+  
4d65c64
+  /* Lock mode switching.  */
4d65c64
+  XF86VidModeLockModeSwitch(currDisplay, currScreen, True);
4d65c64
+         
4d65c64
+  /* Set viewport. */
4d65c64
+  XF86VidModeSetViewPort(currDisplay, currScreen, 0, 0);
4d65c64
+
4d65c64
+  /* clean up */
4d65c64
+  if (mode.privsize)
4d65c64
+    XFree(mode.c_private);
4d65c64
+
4d65c64
+  if (mode_count)
4d65c64
+  {
4d65c64
+    for (i = 0; i < mode_count; i++)
4d65c64
+      if (modes[i]->privsize)
4d65c64
+        XFree(modes[i]->c_private);
4d65c64
+    XFree(modes);
4d65c64
+  }
4d65c64
+}
4d65c64
+
4d65c64
+
4d65c64
+static void pwXf86VmRestoreOriginalResolution ( )
4d65c64
+{
4d65c64
+  int i;
4d65c64
+  XF86VidModeModeLine mode;
4d65c64
+
4d65c64
+  if ( ! XF86VidModeData.vidmode_available )
4d65c64
+    return;
4d65c64
+  
4d65c64
+  /* Unlock mode switching.  */
4d65c64
+  XF86VidModeLockModeSwitch(currDisplay, currScreen, False);
4d65c64
+
4d65c64
+  if (!XF86VidModeGetModeLine(currDisplay, currScreen, &i, &mode) ||
4d65c64
+      (mode.hdisplay != XF86VidModeData.orig_mode.hdisplay) ||
4d65c64
+      (mode.vdisplay != XF86VidModeData.orig_mode.vdisplay))
4d65c64
+  {
4d65c64
+    if (!XF86VidModeSwitchToMode(currDisplay, currScreen,
4d65c64
+          &XF86VidModeData.orig_mode))
4d65c64
+      fprintf(stderr, "XF86VidMode couldnot restore original resolution\n");
4d65c64
+  }
4d65c64
+  if (XF86VidModeData.orig_viewport_x || XF86VidModeData.orig_viewport_y)
4d65c64
+  {
4d65c64
+    if (!XF86VidModeSetViewPort(currDisplay, currScreen,
4d65c64
+          XF86VidModeData.orig_viewport_x,
4d65c64
+          XF86VidModeData.orig_viewport_y))
4d65c64
+      fprintf(stderr, "XF86VidMode couldnot restore original viewport\n");
4d65c64
+  }
4d65c64
+}
4d65c64
+#endif
4d65c64
+
4d65c64
+
4d65c64
+void 
4d65c64
+pwSetSize ( int w, int h )
4d65c64
+{
4d65c64
+  bool notResizable = !resizable;
4d65c64
+  
4d65c64
+  if (notResizable)
4d65c64
+    pwRealSetResizable ( true, w, h );
4d65c64
+
4d65c64
   XResizeWindow ( currDisplay, currHandle, w, h ) ;
4d65c64
-  XFlush        ( currDisplay ) ;
4d65c64
+  XResizeWindow ( currDisplay, wmWindow, w, h ) ;
4d65c64
+
4d65c64
+  if (notResizable)
4d65c64
+    pwRealSetResizable ( false, w, h );
4d65c64
+
4d65c64
+#ifdef XF86VIDMODE      
4d65c64
+  if (fsWindow != None)
4d65c64
+  {
4d65c64
+    int screen_w = 0, screen_h ;
4d65c64
+    pwXf86VmSetFullScreenResolution ( w, h, screen_w, screen_h ) ;
4d65c64
+    /* check pwXf86VmSetFullScreenResolution didn't fail completly. */
4d65c64
+    if (screen_w)
4d65c64
+    {
4d65c64
+      /* Center the window */
4d65c64
+      XMoveWindow ( currDisplay, currHandle, ( screen_w - w ) / 2,
4d65c64
+                   ( screen_h - h ) / 2 ) ;
4d65c64
+    }
4d65c64
+  }
4d65c64
+#endif
4d65c64
+
4d65c64
+  XFlush ( currDisplay );
4d65c64
 }
4d65c64
 
4d65c64
 
4d65c64
 void pwSetOrigin ( int x, int y )
4d65c64
 {
4d65c64
-  XMoveWindow ( currDisplay, currHandle, x, y ) ;
4d65c64
+  XMoveWindow ( currDisplay, wmWindow, x, y ) ;
4d65c64
   XFlush      ( currDisplay ) ;
4d65c64
 }
4d65c64
 
4d65c64
 
4d65c64
 void pwSetSizeOrigin ( int x, int y, int w, int h )
4d65c64
 {
4d65c64
-  XMoveWindow   ( currDisplay, currHandle, x, y ) ;
4d65c64
-  XResizeWindow ( currDisplay, currHandle, w, h ) ;
4d65c64
-  XFlush        ( currDisplay ) ;
4d65c64
+  XMoveWindow   ( currDisplay, wmWindow, x, y ) ;
4d65c64
+  pwSetSize     ( w, h );
4d65c64
 }
4d65c64
 
4d65c64
 
4d65c64
@@ -474,7 +735,11 @@
4d65c64
     switch ( event.type )
4d65c64
     {
4d65c64
       case ClientMessage   : (*exitCB)() ; break ;
4d65c64
-      case DestroyNotify   : (*exitCB)() ; break ;
4d65c64
+
4d65c64
+      case DestroyNotify   : 
4d65c64
+        if ( event.xdestroywindow.window == wmWindow )
4d65c64
+          (*exitCB)() ;
4d65c64
+        break ;
4d65c64
 
4d65c64
       case ConfigureNotify :
4d65c64
         if ( currHandle == event.xconfigure.window &&
4d65c64
@@ -605,7 +870,7 @@
4d65c64
 
4d65c64
 void pwSwapBuffers ()
4d65c64
 {
4d65c64
-  if ( ! initialised )
4d65c64
+  if ( ! currDisplay )
4d65c64
   {
4d65c64
     fprintf ( stderr, "PLIB/PW: FATAL - Application called pwSwapBuffers"
4d65c64
                       " before pwInit.\n" ) ;
4d65c64
@@ -635,15 +900,133 @@
4d65c64
 #endif
4d65c64
 
4d65c64
 
4d65c64
+void pwSetFullscreen ()
4d65c64
+{
4d65c64
+  XEvent event;
4d65c64
+  XSetWindowAttributes setattr;
4d65c64
+  /* local width and height vars used for fullscreen window size and for
4d65c64
+     storing the video_mode size which is then used to center the window */
4d65c64
+  int fs_width  = DisplayWidth(currDisplay, currScreen);
4d65c64
+  int fs_height = DisplayHeight(currDisplay, currScreen);
4d65c64
+
4d65c64
+  /* Grab the keyboard */
4d65c64
+  if (XGrabKeyboard(currDisplay, rootWindow, False, GrabModeAsync,
4d65c64
+        GrabModeAsync, CurrentTime) != GrabSuccess)
4d65c64
+  {
4d65c64
+    fprintf(stderr, "Error can not grab keyboard, not going fullscreen\n");
4d65c64
+    return;
4d65c64
+  }
4d65c64
+  keyb_grabbed = true;
4d65c64
+  
4d65c64
+  /* Create the fullscreen window */
4d65c64
+  setattr.override_redirect = True;
4d65c64
+  setattr.background_pixel = XBlackPixel(currDisplay, currScreen);
4d65c64
+  setattr.border_pixel = XBlackPixel(currDisplay, currScreen);
4d65c64
+  setattr.event_mask = StructureNotifyMask;
4d65c64
+  setattr.colormap = XCreateColormap ( currDisplay, rootWindow,
4d65c64
+                                       visualInfo->visual, AllocNone ) ;
4d65c64
+  fsWindow = XCreateWindow(currDisplay, rootWindow,
4d65c64
+                               0, 0, fs_width, fs_height, 0,
4d65c64
+                               visualInfo->depth, InputOutput,
4d65c64
+                               visualInfo->visual, CWOverrideRedirect |
4d65c64
+                               CWBackPixel | CWColormap | CWBorderPixel |
4d65c64
+                               CWEventMask, &setattr);
4d65c64
+
4d65c64
+  /* Map the fullscreen window */
4d65c64
+  XMapRaised(currDisplay, fsWindow);
4d65c64
+  /* wait until we are mapped. (shamelessly borrowed from SDL) */
4d65c64
+  do {
4d65c64
+    XMaskEvent(currDisplay, StructureNotifyMask, &event); 
4d65c64
+  } while ( (event.type != MapNotify) || 
4d65c64
+            (event.xmap.event != fsWindow) );
4d65c64
+  /* Make sure we got to the top of the window stack */
4d65c64
+  XRaiseWindow(currDisplay, fsWindow);
4d65c64
+  
4d65c64
+  /* Reparent the real window */
4d65c64
+  XReparentWindow(currDisplay, currHandle, fsWindow, 0, 0);
4d65c64
+
4d65c64
+  /* Grab the mouse.  */
4d65c64
+  if (XGrabPointer(currDisplay, currHandle, False,
4d65c64
+        PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
4d65c64
+        GrabModeAsync, GrabModeAsync, currHandle, None,
4d65c64
+        CurrentTime) == GrabSuccess)
4d65c64
+    mouse_grabbed = true;
4d65c64
+  else
4d65c64
+    fprintf(stderr, "Warning can not grab mouse\n");
4d65c64
+
4d65c64
+  /* Make sure we get any last resize events before using size[] */
4d65c64
+  getEvents();
4d65c64
+
4d65c64
+#ifdef XF86VIDMODE
4d65c64
+  /* Switch resolution */
4d65c64
+  pwXf86VmSetFullScreenResolution (size[0], size[1], fs_width, fs_height);
4d65c64
+#endif
4d65c64
+  
4d65c64
+  /* Center the window (if nescesarry) */
4d65c64
+  if ((fs_width != size[0]) || (fs_height != size[1]))
4d65c64
+    XMoveWindow(currDisplay, currHandle, (fs_width - size[0]) / 2,
4d65c64
+                 (fs_height - size[1]) / 2);
4d65c64
+                 
4d65c64
+  /* And last set the cursor */
4d65c64
+  pwRealSetCursor (fsCursor);
4d65c64
+}
4d65c64
+
4d65c64
+
4d65c64
+void pwSetWindowed ()
4d65c64
+{
4d65c64
+  if (mouse_grabbed) {
4d65c64
+    XUngrabPointer(currDisplay, CurrentTime);
4d65c64
+    mouse_grabbed = false;
4d65c64
+  }
4d65c64
+  if (keyb_grabbed) {
4d65c64
+    XUngrabKeyboard(currDisplay, CurrentTime);
4d65c64
+    keyb_grabbed = false;
4d65c64
+  }
4d65c64
+
4d65c64
+#ifdef XF86VIDMODE
4d65c64
+  /* Switch resolution */
4d65c64
+  pwXf86VmRestoreOriginalResolution ( ) ;
4d65c64
+#endif
4d65c64
+
4d65c64
+  /* Reparent the real window! */
4d65c64
+  XReparentWindow(currDisplay, currHandle, wmWindow, 0, 0);
4d65c64
+  XUnmapWindow(currDisplay, fsWindow);
4d65c64
+  XDestroyWindow(currDisplay, fsWindow);
4d65c64
+  fsWindow = None;
4d65c64
+
4d65c64
+  /* And last set the cursor */
4d65c64
+  pwRealSetCursor (wmCursor);
4d65c64
+}
4d65c64
+
4d65c64
+
4d65c64
+void pwToggleFullscreen ()
4d65c64
+{
4d65c64
+  if (fsWindow == None)
4d65c64
+    pwSetFullscreen () ;
4d65c64
+  else
4d65c64
+    pwSetWindowed () ;
4d65c64
+}
4d65c64
+
4d65c64
+
4d65c64
 void pwCleanup ()
4d65c64
 {
4d65c64
-  if ( ! initialised )
4d65c64
-    fprintf ( stderr, "PLIB/PW: WARNING - Application called pwCleanup"
4d65c64
-                      " before pwInit.\n" ) ;
4d65c64
+  if ( ! currDisplay )
4d65c64
+    return;
4d65c64
+
4d65c64
+  if ( titlePropertyPtr )
4d65c64
+  {
4d65c64
+    XFree ( titlePropertyPtr->value ) ;
4d65c64
+    titlePropertyPtr = NULL;
4d65c64
+  }
4d65c64
+
4d65c64
+  if ( fsWindow != None )
4d65c64
+    pwSetWindowed ( ) ;
4d65c64
 
4d65c64
   glXDestroyContext ( currDisplay, currContext ) ;
4d65c64
   XDestroyWindow    ( currDisplay, currHandle  ) ;
4d65c64
-  XFlush            ( currDisplay ) ;
4d65c64
+  XDestroyWindow    ( currDisplay, wmWindow    ) ;
4d65c64
+  XCloseDisplay     ( currDisplay ) ;
4d65c64
+  currDisplay = NULL;
4d65c64
 }
4d65c64
 
4d65c64