- moving to a new way of handling window changes (position, size, visibility)
[freeglut] / src / x11 / fg_main_x11.c
index cc57185..7af570f 100644 (file)
 #    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);
 
@@ -63,8 +74,7 @@ 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)...
@@ -644,29 +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;
-                    INVOKE_WCB( *window, Reshape, ( 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;
 
@@ -918,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;
             }
 
@@ -1071,3 +1077,72 @@ void fgPlatformMainLoopPreliminaryWork ( void )
 {
 }
 
+
+/* Step through the work list */
+void fgPlatformProcessWork(SFG_Window *window)
+{
+    unsigned int workMask = window->State.WorkMask;
+    /* Now clear it so that any callback generated by the actions below can set work again */
+    window->State.WorkMask = 0;
+
+    /* This is before the first display callback: call a few callbacks to inform user of window size, position, etc
+     * we know this is before the first display callback of a window as for all windows GLUT_INIT_WORK is set when
+     * they are opened, and work is done before displaying in the mainloop.
+     */
+    if (workMask & GLUT_INIT_WORK)
+    {
+        /* 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?
+         */
+
+        /* Call init context callback */
+        INVOKE_WCB( *window, InitContext, ());
+
+        /* Lastly, check if we have a display callback, error out if not
+         * This is the right place to do it, as the redisplay will be
+         * next right after we exit this function, so there is no more
+         * opportunity for the user to register a callback for this window.
+         */
+        if (!FETCH_WCB(*window, Display))
+            fgError ( "ERROR:  No display callback registered for window %d\n", window->ID );
+    }
+
+    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 );
+    }
+
+    if (workMask & GLUT_VISIBILITY_WORK)
+    {
+        /* 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;
+        }
+    }
+}
+