(Vafter_change_functions, Vbefore_change_functions): Declared.
[bpt/emacs.git] / src / frame.c
index e7bdc95..60f50a8 100644 (file)
@@ -331,30 +331,10 @@ make_terminal_frame ()
   return f;
 }
 \f
-DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
-  "Select the frame FRAME.\n\
-Subsequent editing commands apply to its selected window.\n\
-The selection of FRAME lasts until the next time the user does\n\
-something to select a different frame, or until the next time this\n\
-function is called.")
-  (frame, no_enter)
-    Lisp_Object frame, no_enter;
-{
-  return Fhandle_switch_frame (frame, no_enter);
-}
-
-
-DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
-  "Handle a switch-frame event EVENT.\n\
-Switch-frame events are usually bound to this function.\n\
-A switch-frame event tells Emacs that the window manager has requested\n\
-that the user's events be directed to the frame mentioned in the event.\n\
-This function selects the selected window of the frame of EVENT.\n\
-\n\
-If EVENT is frame object, handle it as if it were a switch-frame event\n\
-to that frame.")
-  (frame, no_enter)
+static Lisp_Object
+do_switch_frame (frame, no_enter, track)
      Lisp_Object frame, no_enter;
+     int track;
 {
   /* If FRAME is a switch-frame event, extract the frame we should
      switch to.  */
@@ -363,11 +343,19 @@ to that frame.")
       && CONSP (XCONS (frame)->cdr))
     frame = XCONS (XCONS (frame)->cdr)->car;
 
-  CHECK_LIVE_FRAME (frame, 0);
+  /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
+     a switch-frame event to arrive after a frame is no longer live,
+     especially when deleting the initial frame during startup.  */
+  CHECK_FRAME (frame, 0);
+  if (! FRAME_LIVE_P (XFRAME (frame)))
+    return Qnil;
 
   if (selected_frame == XFRAME (frame))
     return frame;
 
+  /* This is too greedy; it causes inappropriate focus redirection
+     that's hard to get rid of.  */
+#if 0
   /* If a frame's focus has been redirected toward the currently
      selected frame, we should change the redirection to point to the
      newly selected frame.  This means that if the focus is redirected
@@ -375,23 +363,41 @@ to that frame.")
      can use `other-window' to switch between all the frames using
      that minibuffer frame, and the focus redirection will follow us
      around.  */
-  {
-    Lisp_Object tail;
+  if (track)
+    {
+      Lisp_Object tail;
 
-    for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
-      {
-       Lisp_Object focus;
+      for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+       {
+         Lisp_Object focus;
 
-       if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
-         abort ();
+         if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
+           abort ();
 
-       focus = FRAME_FOCUS_FRAME (XFRAME (XCONS (tail)->car));
+         focus = FRAME_FOCUS_FRAME (XFRAME (XCONS (tail)->car));
 
-       if (XTYPE (focus) == Lisp_Frame
-           && XFRAME (focus) == selected_frame)
-         Fredirect_frame_focus (XCONS (tail)->car, frame);
-      }
-  }
+         if (XTYPE (focus) == Lisp_Frame
+             && XFRAME (focus) == selected_frame)
+           Fredirect_frame_focus (XCONS (tail)->car, frame);
+       }
+    }
+#else /* ! 0 */
+  /* Instead, apply it only to the frame we're pointing to.  */
+#ifdef HAVE_X_WINDOWS
+  if (track)
+    {
+      Lisp_Object focus, xfocus;
+
+      xfocus = x_get_focus_frame ();
+      if (FRAMEP (xfocus))
+       {
+         focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
+         if (FRAMEP (focus) && XFRAME (focus) == selected_frame)
+           Fredirect_frame_focus (xfocus, frame);
+       }
+    }
+#endif /* HAVE_X_WINDOWS */
+#endif /* ! 0 */
 
   selected_frame = XFRAME (frame);
   if (! FRAME_MINIBUF_ONLY_P (selected_frame))
@@ -411,6 +417,35 @@ to that frame.")
   return frame;
 }
 
+DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
+  "Select the frame FRAME.\n\
+Subsequent editing commands apply to its selected window.\n\
+The selection of FRAME lasts until the next time the user does\n\
+something to select a different frame, or until the next time this\n\
+function is called.")
+  (frame, no_enter)
+    Lisp_Object frame, no_enter;
+{
+  return do_switch_frame (frame, no_enter, 1);
+}
+
+
+DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
+  "Handle a switch-frame event EVENT.\n\
+Switch-frame events are usually bound to this function.\n\
+A switch-frame event tells Emacs that the window manager has requested\n\
+that the user's events be directed to the frame mentioned in the event.\n\
+This function selects the selected window of the frame of EVENT.\n\
+\n\
+If EVENT is frame object, handle it as if it were a switch-frame event\n\
+to that frame.")
+  (frame, no_enter)
+     Lisp_Object frame, no_enter;
+{
+  return do_switch_frame (frame, no_enter, 0);
+}
+
+
 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
   "Return the frame that is now selected.")
   ()
@@ -429,6 +464,33 @@ DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
   return XWINDOW (window)->frame;
 }
 
+DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
+  "Returns the topmost, leftmost window of FRAME.\n\
+If omitted, FRAME defaults to the currently selected frame.")
+  (frame)
+     Lisp_Object frame;
+{
+  Lisp_Object w;
+
+  if (NILP (frame))
+    w = selected_frame->root_window;
+  else
+    {
+      CHECK_LIVE_FRAME (frame, 0);
+      w = XFRAME (frame)->root_window;
+    }
+  while (NILP (XWINDOW (w)->buffer))
+    {
+      if (! NILP (XWINDOW (w)->hchild))
+       w = XWINDOW (w)->hchild;
+      else if (! NILP (XWINDOW (w)->vchild))
+       w = XWINDOW (w)->vchild;
+      else
+       abort ();
+    }
+  return w;
+}
+
 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
        "Returns the root-window of FRAME.\n\
 If omitted, FRAME defaults to the currently selected frame.")
@@ -492,8 +554,9 @@ next_frame (frame, minibuf)
   while (1)
     for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
       {
-       Lisp_Object f = XCONS (tail)->car;
+       Lisp_Object f;
 
+       f = XCONS (tail)->car;
        if (passed)
          {
            /* Decide whether this frame is eligible to be returned.  */
@@ -551,8 +614,9 @@ prev_frame (frame, minibuf)
   prev = Qnil;
   for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
     {
-      Lisp_Object f = XCONS (tail)->car;
+      Lisp_Object f;
 
+      f = XCONS (tail)->car;
       if (XTYPE (f) != Lisp_Frame)
        abort ();
 
@@ -657,8 +721,9 @@ other_visible_frames (f)
           CONSP (frames);
           frames = XCONS (frames)->cdr)
        {
-         Lisp_Object this = XCONS (frames)->car;
+         Lisp_Object this;
 
+         this = XCONS (frames)->car;
          /* Verify that the frame's window still exists
             and we can still talk to it.  And note any recent change
             in visibility.  */
@@ -794,14 +859,16 @@ but if the second optional argument FORCE is non-nil, you may do so.")
       Lisp_Object frames;
 
       /* The last frame we saw with a minibuffer, minibuffer-only or not.  */
-      Lisp_Object frame_with_minibuf = Qnil;
+      Lisp_Object frame_with_minibuf;
 
+      frame_with_minibuf = Qnil;
       for (frames = Vframe_list;
           CONSP (frames);
           frames = XCONS (frames)->cdr)
        {
-         Lisp_Object this = XCONS (frames)->car;
+         Lisp_Object this;
 
+         this = XCONS (frames)->car;
          if (XTYPE (this) != Lisp_Frame)
            abort ();
          f = XFRAME (this);
@@ -1616,6 +1683,8 @@ keys_of_frame ()
 /* If we're not using multi-frame stuff, we still need to provide some
    support functions.  */
 
+Lisp_Object Vterminal_frame;
+
 /* Unless this function is defined, providing set-frame-height and
    set-frame-width doesn't help compatibility any, since they both
    want this as their first argument.  */
@@ -1807,6 +1876,10 @@ and nil for X and Y.")
 
 syms_of_frame ()
 {
+  DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
+    "The initial frame-object, which represents Emacs's stdout.");
+  XFASTINT (Vterminal_frame) = 0;
+
   defsubr (&Sselected_frame);
   defsubr (&Sframep);
   defsubr (&Sframe_char_height);
@@ -1830,7 +1903,3 @@ keys_of_frame ()
 }
 
 #endif /* not MULTI_FRAME */
-
-
-
-