From xemacs-m  Thu Feb 27 14:40:09 1997
Received: from GS213.SP.CS.CMU.EDU (GS213.SP.CS.CMU.EDU [128.2.209.183])
	by xemacs.org (8.8.5/8.8.5) with SMTP id OAA08695
	for <xemacs-beta@xemacs.org>; Thu, 27 Feb 1997 14:40:08 -0600 (CST)
Received: by GS213.SP.CS.CMU.EDU (AIX 3.2/UCB 5.64/4.03)
          id AA37950; Thu, 27 Feb 1997 15:40:05 -0500
Date: Thu, 27 Feb 1997 15:40:05 -0500
Message-Id: <9702272040.AA37950@GS213.SP.CS.CMU.EDU>
From: Darrell Kindred <dkindred@cmu.edu>
To: xemacs-beta@xemacs.org
Subject: 19.15b95: delayed redisplay bug [w/ PATCH]
Organization: Carnegie Mellon University School of Computer Science

In 19.15b95, I've noticed the following bug.  (I'm not sure
whether it's been reported before.)

   Run xemacs -q.  In *scratch*, type (sleep-for 10) and press C-j.
   Quickly move to another fvwm page so the xemacs frame is no
   longer visible.  After 10 seconds have elapsed, switch
   back to the original fvwm page *without* focusing on the
   xemacs frame.  Note that the "nil" result of the evaluation
   hasn't appeared.  When you focus on the xemacs frame, it 
   will appear.

The problem is this: In b95, event-Xt.c was modified to
clear the frame-visible flag when fvwm sends a
VisibilityNotify event indicating the window is hidden.
Redisplay is inhibited while the frame is invisible.  When
the frame becomes visible again another VisibilityNotify
event arrives, and the visible flag is turned on, but no
redisplay is triggered.  The patch below treats these
VisibilityNotify events basically like the MapNotify events
you get on (de)iconification, which seems to me like the
right thing.

Let me know if you have any questions or think this is the
wrong approach.

- Darrell

--- src/event-Xt.c.orig	Sat Feb 22 17:08:36 1997
+++ src/event-Xt.c	Thu Feb 27 15:39:35 1997
@@ -992,6 +992,37 @@
   handle_focus_event_1 (f, event->type == FocusIn);
 }
 
+/* both MapNotify and VisibilityNotify can cause this */
+static void
+change_frame_visibility (struct frame *f, int is_visible)
+{
+  Lisp_Object frame = Qnil;
+
+  XSETFRAME (frame, f);
+
+  if (!FRAME_VISIBLE_P (f) && is_visible)
+    {
+      FRAME_VISIBLE_P (f) = 1;
+      /* This improves the double flicker when uniconifying a frame
+	 some.  A lot of it is not showing a buffer which has changed
+	 while the frame was iconified.  To fix it further requires
+	 the good 'ol double redisplay structure. */
+      MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
+      va_run_hook_with_args (Qmap_frame_hook, 1, frame);
+#ifdef EPOCH
+      dispatch_epoch_event (f, event, Qx_map);
+#endif
+    }
+  else if (FRAME_VISIBLE_P (f) && !is_visible) 
+    {
+      FRAME_VISIBLE_P (f) = 0;
+      va_run_hook_with_args (Qunmap_frame_hook, 1, frame);
+#ifdef EPOCH
+      dispatch_epoch_event (f, event, Qx_unmap);
+#endif
+    }
+}
+
 static void
 handle_map_event (struct frame *f, XEvent *event)
 {
@@ -1048,34 +1079,14 @@
 	 rather than consulting some internal (and likely
 	 inaccurate) state flag.  Therefore, ignoring the MapNotify
 	 is correct. */
-      if (!f->visible && NILP (Fframe_iconified_p (frame)))
-#endif
-      if (!f->visible)
-	{
-	  f->visible = 1;
-	  /* This improves the double flicker when uniconifying a frame
-	     some.  A lot of it is not showing a buffer which has changed
-	     while the frame was iconified.  To fix it further requires
-	     the good 'ol double redisplay structure. */
-	  MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
-	  va_run_hook_with_args (Qmap_frame_hook, 1, frame);
-#ifdef EPOCH
-	  dispatch_epoch_event (f, event, Qx_map);
+      if (!FRAME_VISIBLE_P (f) && NILP (Fframe_iconified_p (frame)))
 #endif
-	}
+      change_frame_visibility (f, 1);
     }
   else
     {
       FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
-      if (f->visible)
-	{
-	  f->visible = 0;
-	  va_run_hook_with_args (Qunmap_frame_hook, 1, frame);
-#ifdef EPOCH
-	  dispatch_epoch_event (f, event, Qx_unmap);
-#endif
-	}
-
+      change_frame_visibility (f, 0);
       /* Calling Fframe_iconified_p is the only way we have to
          correctly update FRAME_ICONIFIED_P */
       Fframe_iconified_p (frame);
@@ -1223,12 +1234,17 @@
     case VisibilityNotify: /* window visiblity has changed */
       if (event->xvisibility.window == XtWindow (FRAME_X_SHELL_WIDGET (f)))
 	{
-	  /* Note that the fvwm pager only sends VisibilityNotify when
-	     changing pages. Is this all we need to do ? JV */
-	  FRAME_VISIBLE_P (f) =
-	    ( event->xvisibility.state != VisibilityFullyObscured);
 	  FRAME_X_TOTALLY_VISIBLE_P (f) =
 	    (event->xvisibility.state == VisibilityUnobscured);
+	  /* Note that the fvwm pager only sends VisibilityNotify when
+	     changing pages. Is this all we need to do ? JV */
+	  /* Nope.  We must at least trigger a redisplay here.  
+             Since this case seems similar to MapNotify, I've 
+             factored out some code to change_frame_visibility(). 
+	     This triggers the necessary redisplay and runs
+	     (un)map-frame-hook.  - dkindred@cs.cmu.edu */
+	  change_frame_visibility (f, (event->xvisibility.state
+				       != VisibilityFullyObscured));
 	}
       break;
       

