renamed all references to freeglut_xxx files (their old names) to fg_xxx
[freeglut] / src / x11 / fg_main_x11.c
index e72db37..6d2d8a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * freeglut_main_x11.c
+ * fg_main_x11.c
  *
  * The X11-specific windows message processing methods.
  *
@@ -40,6 +40,7 @@
 #    define VFPRINTF(s,f,a)
 #endif
 
+
 /*
  * Try to get the maximum value allowed for ints, falling back to the minimum
  * guaranteed by ISO C99 if there is no suitable header.
 #    define MIN(a,b) (((a)<(b)) ? (a) : (b))
 #endif
 
+extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify);
+extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify);
+extern void fgPlatformFullScreenToggle( SFG_Window *win );
+extern void fgPlatformPositionWindow( SFG_Window *window, int x, int y );
+extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height );
+extern void fgPlatformPushWindow( SFG_Window *window );
+extern void fgPlatformPopWindow( SFG_Window *window );
+extern void fgPlatformHideWindow( SFG_Window *window );
+extern void fgPlatformIconifyWindow( SFG_Window *window );
+extern void fgPlatformShowWindow( SFG_Window *window );
+
+/* used in the event handling code to match and discard stale mouse motion events */
+static Bool match_motion(Display *dpy, XEvent *xev, XPointer arg);
+
 /*
  * TODO BEFORE THE STABLE RELEASE:
  *
  * There are some issues concerning window redrawing under X11, and maybe
- * some events are not handled. The Win32 version lacks some more features,
- * but seems acceptable for not demanding purposes.
+ * some events are not handled.
  *
  * Need to investigate why the X11 version breaks out with an error when
  * closing a window (using the window manager, not glutDestroyWindow)...
  */
  
  
-/*
- * Handle a window configuration change. When no reshape
- * callback is hooked, the viewport size is updated to
- * match the new window size.
- */
-void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
-{
-    XResizeWindow( fgDisplay.pDisplay.Display, window->Window.Handle,
-                   width, height );
-    XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
-}
-
-
-/*
- * A static helper function to execute display callback for a window
- */
-void fgPlatformDisplayWindow ( SFG_Window *window )
-{
-        fghRedrawWindow ( window ) ;
-}
-
 
 fg_time_t fgPlatformSystemTime ( void )
 {
@@ -295,7 +288,7 @@ static const char* fghColormapStateToString( int state )
     }
 }
 
-static void fghPrintEvent( XEvent *event )
+__fg_unused static void fghPrintEvent( XEvent *event )
 {
     switch( event->type ) {
 
@@ -625,10 +618,11 @@ void fgPlatformProcessSingleEvent ( void )
         switch( event.type )
         {
         case ClientMessage:
-            if(fgIsSpaceballXEvent(&event)) {
-                fgSpaceballHandleXEvent(&event);
-                break;
-            }
+            if (fgStructure.CurrentWindow)
+                if(fgIsSpaceballXEvent(&event)) {
+                    fgSpaceballHandleXEvent(&event);
+                    break;
+                }
             /* Destroy the window when the WM_DELETE_WINDOW message arrives */
             if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.pDisplay.DeleteWindow )
             {
@@ -660,35 +654,25 @@ void fgPlatformProcessSingleEvent ( void )
         case CreateNotify:
         case ConfigureNotify:
             {
-                int width, height;
+                int width, height, x, y;
                 if( event.type == CreateNotify ) {
                     GETWINDOW( xcreatewindow );
                     width = event.xcreatewindow.width;
                     height = event.xcreatewindow.height;
+                    x = event.xcreatewindow.x;
+                    y = event.xcreatewindow.y;
                 } else {
                     GETWINDOW( xconfigure );
                     width = event.xconfigure.width;
                     height = event.xconfigure.height;
+                    x = event.xconfigure.x;
+                    y = event.xconfigure.y;
                 }
 
-                if( ( width != window->State.pWState.OldWidth ) ||
-                    ( height != window->State.pWState.OldHeight ) )
-                {
-                    SFG_Window *current_window = fgStructure.CurrentWindow;
-
-                    window->State.pWState.OldWidth = width;
-                    window->State.pWState.OldHeight = height;
-                    if( FETCH_WCB( *window, Reshape ) )
-                        INVOKE_WCB( *window, Reshape, ( width, height ) );
-                    else
-                    {
-                        fgSetWindow( window );
-                        glViewport( 0, 0, width, height );
-                    }
-                    glutPostRedisplay( );
-                    if( window->IsMenu )
-                        fgSetWindow( current_window );
-                }
+                /* Update state and call callback, if there was a change */
+                fghOnPositionNotify(window, x, y, GL_FALSE);
+                /* Update state and call callback, if there was a change */
+                fghOnReshapeNotify(window, width, height, GL_FALSE);
             }
             break;
 
@@ -714,7 +698,7 @@ void fgPlatformProcessSingleEvent ( void )
             if( event.xexpose.count == 0 )
             {
                 GETWINDOW( xexpose );
-                window->State.Redisplay = GL_TRUE;
+                window->State.WorkMask |= GLUT_DISPLAY_WORK;
             }
             break;
 
@@ -788,6 +772,13 @@ void fgPlatformProcessSingleEvent ( void )
 
         case MotionNotify:
         {
+            /* if GLUT_SKIP_STALE_MOTION_EVENTS is true, then discard all but
+             * the last motion event from the queue
+             */
+            if(fgState.SkipStaleMotion) {
+                while(XCheckIfEvent(fgDisplay.pDisplay.Display, &event, match_motion, 0));
+            }
+
             GETWINDOW( xmotion );
             GETMOUSE( xmotion );
 
@@ -855,7 +846,7 @@ void fgPlatformProcessSingleEvent ( void )
              * private call should be generated.
              */
             if( fgCheckActiveMenu( window, button, pressed,
-                                   event.xbutton.x_root, event.xbutton.y_root ) )
+                                   event.xbutton.x, event.xbutton.y ) )
                 break;
 
             /*
@@ -933,20 +924,20 @@ void fgPlatformProcessSingleEvent ( void )
                     if ( event.xkey.keycode<256 )            /* XQueryKeymap is limited to 256 keycodes    */
                     {
                         if ( keys[event.xkey.keycode>>3] & (1<<(event.xkey.keycode%8)) )
-                            window->State.KeyRepeating = GL_TRUE;
+                            window->State.pWState.KeyRepeating = GL_TRUE;
                         else
-                            window->State.KeyRepeating = GL_FALSE;
+                            window->State.pWState.KeyRepeating = GL_FALSE;
                     }
                 }
             }
             else
-                window->State.KeyRepeating = GL_FALSE;
+                window->State.pWState.KeyRepeating = GL_FALSE;
 
             /* Cease processing this event if it is auto repeated */
 
-            if (window->State.KeyRepeating)
+            if (window->State.pWState.KeyRepeating)
             {
-                if (event.type == KeyPress) window->State.KeyRepeating = GL_FALSE;
+                if (event.type == KeyPress) window->State.pWState.KeyRepeating = GL_FALSE;
                 break;
             }
 
@@ -1077,7 +1068,64 @@ void fgPlatformProcessSingleEvent ( void )
 }
 
 
+static Bool match_motion(Display *dpy, XEvent *xev, XPointer arg)
+{
+    return xev->type == MotionNotify;
+}
+
 void fgPlatformMainLoopPreliminaryWork ( void )
 {
 }
 
+
+/* deal with work list items */
+void fgPlatformInitWork(SFG_Window* window)
+{
+    /* Notify windowStatus/visibility, position and size get notified on window creation with message handlers above 
+     * XXX CHECK: do the messages happen too early like on windows, so client code cannot have registered
+     * a callback yet and the message is thus never received by client?
+     * -> this is a no-op
+     */
+     return;
+}
+
+void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask)
+{
+    if (workMask & GLUT_FULL_SCREEN_WORK)
+        fgPlatformFullScreenToggle( window );
+    if (workMask & GLUT_POSITION_WORK)
+        fgPlatformPositionWindow( window, window->State.DesiredXpos, window->State.DesiredYpos );
+    if (workMask & GLUT_SIZE_WORK)
+        fgPlatformReshapeWindow ( window, window->State.DesiredWidth, window->State.DesiredHeight );
+    if (workMask & GLUT_ZORDER_WORK)
+    {
+        if (window->State.DesiredZOrder < 0)
+            fgPlatformPushWindow( window );
+        else
+            fgPlatformPopWindow( window );
+    }
+}
+
+void fgPlatformVisibilityWork(SFG_Window* window)
+{
+    /* Visibility status of window gets updated in the window message handlers above 
+     * XXX: is this really the case? check
+     */
+    SFG_Window *win = window;
+    switch (window->State.DesiredVisibility)
+    {
+    case DesireHiddenState:
+        fgPlatformHideWindow( window );
+        break;
+    case DesireIconicState:
+        /* Call on top-level window */
+        while (win->Parent)
+            win = win->Parent;
+        fgPlatformIconifyWindow( win );
+        break;
+    case DesireNormalState:
+        fgPlatformShowWindow( window );
+        break;
+    }
+}
+