Add 2008 to copyright years.
[bpt/emacs.git] / src / frame.c
index d86d29d..958d603 100644 (file)
@@ -1,12 +1,12 @@
 /* Generic frame functions.
-   Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2003, 2004, 2005
-   Free Software Foundation.
+   Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003,
+                 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include <config.h>
 
@@ -71,7 +71,6 @@ Lisp_Object Qx, Qw32, Qmac, Qpc;
 Lisp_Object Qvisible;
 Lisp_Object Qdisplay_type;
 Lisp_Object Qbackground_mode;
-Lisp_Object Qinhibit_default_face_x_resources;
 
 Lisp_Object Qx_frame_parameter;
 Lisp_Object Qx_resource_name;
@@ -101,6 +100,7 @@ Lisp_Object Qouter_window_id;
 #endif
 Lisp_Object Qparent_id;
 Lisp_Object Qtitle, Qname;
+Lisp_Object Qexplicit_name;
 Lisp_Object Qunsplittable;
 Lisp_Object Qmenu_bar_lines, Qtool_bar_lines;
 Lisp_Object Qleft_fringe, Qright_fringe;
@@ -109,6 +109,7 @@ Lisp_Object Qtty_color_mode;
 
 Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
 
+Lisp_Object Qinhibit_face_set_after_frame_default;
 Lisp_Object Qface_set_after_frame_default;
 
 
@@ -118,6 +119,8 @@ Lisp_Object Vdefault_frame_scroll_bars;
 Lisp_Object Vmouse_position_function;
 Lisp_Object Vmouse_highlight;
 Lisp_Object Vdelete_frame_functions;
+
+int focus_follows_mouse;
 \f
 static void
 set_menu_bar_lines_1 (window, n)
@@ -399,7 +402,7 @@ make_frame_without_minibuffer (mini_window, kb, display)
 #ifdef MULTI_KBOARD
   if (!NILP (mini_window)
       && XFRAME (XWINDOW (mini_window)->frame)->kboard != kb)
-    error ("frame and minibuffer must be on the same display");
+    error ("Frame and minibuffer must be on the same display");
 #endif
 
   /* Make a frame containing just a root window.  */
@@ -579,7 +582,7 @@ Note that changing the size of one terminal frame automatically affects all.  */
     abort ();
 #else /* not MSDOS */
 
-#ifdef MAC_OS
+#ifdef MAC_OS8
   if (sf->output_method != output_mac)
     error ("Not running on a Macintosh screen; cannot make a new Macintosh frame");
 #else
@@ -729,7 +732,7 @@ do_switch_frame (frame, track, for_deletion)
   return frame;
 }
 
-DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
+DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 1, "e",
        doc: /* Select the frame FRAME.
 Subsequent editing commands apply to its selected window.
 The selection of FRAME lasts until the next time the user does
@@ -740,14 +743,14 @@ the command loop, because it still may have the window system's input
 focus.  On a text-only terminal, the next redisplay will display FRAME.
 
 This function returns FRAME, or nil if FRAME has been deleted.  */)
-  (frame, no_enter)
-    Lisp_Object frame, no_enter;
+  (frame)
+    Lisp_Object frame;
 {
   return do_switch_frame (frame, 1, 0);
 }
 
 
-DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
+DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "e",
        doc: /* Handle a switch-frame event EVENT.
 Switch-frame events are usually bound to this function.
 A switch-frame event tells Emacs that the window manager has requested
@@ -756,8 +759,8 @@ This function selects the selected window of the frame of EVENT.
 
 If EVENT is frame object, handle it as if it were a switch-frame event
 to that frame.  */)
-     (event, no_enter)
-     Lisp_Object event, no_enter;
+     (event)
+     Lisp_Object event;
 {
   /* Preserve prefix arg that the command loop just cleared.  */
   current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
@@ -901,7 +904,7 @@ DEFUN ("frame-list", Fframe_list, Sframe_list,
    If MINIBUF is 0, include all visible and iconified frames.
    Otherwise, include all frames.  */
 
-Lisp_Object
+static Lisp_Object
 next_frame (frame, minibuf)
      Lisp_Object frame;
      Lisp_Object minibuf;
@@ -978,7 +981,7 @@ next_frame (frame, minibuf)
    If MINIBUF is 0, include all visible and iconified frames.
    Otherwise, include all frames.  */
 
-Lisp_Object
+static Lisp_Object
 prev_frame (frame, minibuf)
      Lisp_Object frame;
      Lisp_Object minibuf;
@@ -1260,6 +1263,10 @@ The functions are run with one arg, the frame to be deleted.  */)
   if (FRAME_X_P (f))
     x_clear_frame_selections (f);
 #endif
+#ifdef MAC_OS
+  if (FRAME_MAC_P (f))
+    x_clear_frame_selections (f);
+#endif
 
   /* Free glyphs.
      This function must be called before the window tree of the
@@ -1425,7 +1432,8 @@ The functions are run with one arg, the frame to be deleted.  */)
 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
        doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
 The position is given in character cells, where (0, 0) is the
-upper-left corner.
+upper-left corner of the frame, X is the horizontal offset, and Y is
+the vertical offset.
 If Emacs is running on a mouseless terminal or hasn't been programmed
 to read the mouse position, it returns the selected frame for FRAME
 and nil for X and Y.
@@ -1473,7 +1481,8 @@ DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
        Smouse_pixel_position, 0, 0, 0,
        doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
 The position is given in pixel units, where (0, 0) is the
-upper-left corner.
+upper-left corner of the frame, X is the horizontal offset, and Y is
+the vertical offset.
 If Emacs is running on a mouseless terminal or hasn't been programmed
 to read the mouse position, it returns the selected frame for FRAME
 and nil for X and Y.  */)
@@ -1506,6 +1515,10 @@ Coordinates are relative to the frame, not a window,
 so the coordinates of the top left character in the frame
 may be nonzero due to left-hand scroll bars or the menu bar.
 
+The position is given in character cells, where (0, 0) is the
+upper-left corner of the frame, X is the horizontal offset, and Y is
+the vertical offset.
+
 This function is a no-op for an X frame that is not visible.
 If you have just created a frame, you must wait for it to become visible
 before calling this function on it, like this.
@@ -1526,7 +1539,7 @@ before calling this function on it, like this.
 #if defined (MSDOS) && defined (HAVE_MOUSE)
   if (FRAME_MSDOS_P (XFRAME (frame)))
     {
-      Fselect_frame (frame, Qnil);
+      Fselect_frame (frame);
       mouse_moveto (XINT (x), XINT (y));
     }
 #endif
@@ -1538,6 +1551,9 @@ before calling this function on it, like this.
 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
        Sset_mouse_pixel_position, 3, 3, 0,
        doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
+The position is given in pixels, where (0, 0) is the upper-left corner
+of the frame, X is the horizontal offset, and Y is the vertical offset.
+
 Note, this is a no-op for an X frame that is not visible.
 If you have just created a frame, you must wait for it to become visible
 before calling this function on it, like this.
@@ -1558,7 +1574,7 @@ before calling this function on it, like this.
 #if defined (MSDOS) && defined (HAVE_MOUSE)
   if (FRAME_MSDOS_P (XFRAME (frame)))
     {
-      Fselect_frame (frame, Qnil);
+      Fselect_frame (frame);
       mouse_moveto (XINT (x), XINT (y));
     }
 #endif
@@ -1680,7 +1696,7 @@ If omitted, FRAME defaults to the currently selected frame.  */)
 #if 0 /* This isn't logically necessary, and it can do GC.  */
   /* Don't let the frame remain selected.  */
   if (EQ (frame, selected_frame))
-    Fhandle_switch_frame (next_frame (frame, Qt), Qnil);
+    Fhandle_switch_frame (next_frame (frame, Qt));
 #endif
 
   /* Don't allow minibuf_window to remain on a deleted frame.  */
@@ -1809,7 +1825,7 @@ Focus redirection is useful for temporarily redirecting keystrokes to
 a surrogate minibuffer frame when a frame doesn't have its own
 minibuffer window.
 
-A frame's focus redirection can be changed by select-frame.  If frame
+A frame's focus redirection can be changed by `select-frame'.  If frame
 FOO is selected, and then a different frame BAR is selected, any
 frames redirecting their focus to FOO are shifted to redirect their
 focus to BAR.  This allows focus redirection to work properly when the
@@ -1817,7 +1833,7 @@ user switches from one frame to another using `select-window'.
 
 This means that a frame whose focus is redirected to itself is treated
 differently from a frame whose focus is redirected to nil; the former
-is affected by select-frame, while the latter is not.
+is affected by `select-frame', while the latter is not.
 
 The redirection lasts until `redirect-frame-focus' is called to change it.  */)
      (frame, focus_frame)
@@ -1948,7 +1964,7 @@ frame_name_fnn_p (str, len)
 /* Set the name of the terminal frame.  Also used by MSDOS frames.
    Modeled after x_set_name which is used for WINDOW frames.  */
 
-void
+static void
 set_term_frame_name (f, name)
      struct frame *f;
      Lisp_Object name;
@@ -2255,15 +2271,6 @@ enabled such bindings for that variable with `make-variable-frame-local'.  */)
 {
   FRAME_PTR f;
   register Lisp_Object tail, prop, val;
-  int count = SPECPDL_INDEX ();
-
-  /* Bind this to t to inhibit initialization of the default face from
-     X resources in face-set-after-frame-default.  If we don't inhibit
-     this, modifying the `font' frame parameter, for example, while
-     there is a `default.attributeFont' X resource, won't work,
-     because `default's font is reset to the value of the X resource
-     and that resets the `font' frame parameter.  */
-  specbind (Qinhibit_default_face_x_resources, Qt);
 
   if (EQ (frame, Qnil))
     frame = selected_frame;
@@ -2309,10 +2316,16 @@ enabled such bindings for that variable with `make-variable-frame-local'.  */)
          prop = parms[i];
          val = values[i];
          store_frame_param (f, prop, val);
+
+         /* Changing the background color might change the background
+            mode, so that we have to load new defface specs.
+            Call frame-set-background-mode to do that.  */
+         if (EQ (prop, Qbackground_color))
+           call1 (Qframe_set_background_mode, frame);
        }
     }
 
-  return unbind_to (count, Qnil);
+  return Qnil;
 }
 \f
 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
@@ -2343,8 +2356,7 @@ DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
        0, 1, 0,
        doc: /* Width in pixels of characters in the font in frame FRAME.
 If FRAME is omitted, the selected frame is used.
-The width is the same for all characters, because
-currently Emacs supports only fixed-width fonts.
+On a graphical screen, the width is the standard width of the default font.
 For a terminal screen, the value is always 1.  */)
      (frame)
      Lisp_Object frame;
@@ -2579,7 +2591,7 @@ extern Lisp_Object Qbox;
 extern Lisp_Object Qtop;
 
 /* Calculate fullscreen size.  Return in *TOP_POS and *LEFT_POS the
-   wanted positions of the WM window (not emacs window).
+   wanted positions of the WM window (not Emacs window).
    Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
    window (FRAME_X_WINDOW).
  */
@@ -2711,12 +2723,20 @@ x_set_frame_parameters (f, alist)
           || EQ (prop, Qfullscreen))
        {
          register Lisp_Object param_index, old_value;
+         int count = SPECPDL_INDEX ();
 
          old_value = get_frame_param (f, prop);
          fullscreen_is_being_set |= EQ (prop, Qfullscreen);
 
          if (NILP (Fequal (val, old_value)))
            {
+             /* For :font attributes, the frame_parm_handler
+                x_set_font calls `face-set-after-frame-default'.
+                Unless we bind inhibit-face-set-after-frame-default
+                here, this would reset the :font attribute that we
+                just applied to the default value for new faces.  */
+             specbind (Qinhibit_face_set_after_frame_default, Qt);
+
              store_frame_param (f, prop, val);
 
              param_index = Fget (prop, Qx_frame_parameter);
@@ -2725,6 +2745,8 @@ x_set_frame_parameters (f, alist)
                      < sizeof (frame_parms)/sizeof (frame_parms[0]))
                  && rif->frame_parm_handlers[XINT (param_index)])
                (*(rif->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
+
+             unbind_to (count, Qnil);
            }
        }
     }
@@ -2985,6 +3007,7 @@ x_report_frame_params (f, alistptr)
     tem = Qnil;
   else
     XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
+  store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
   store_in_alist (alistptr, Qparent_id, tem);
 }
 
@@ -3005,6 +3028,9 @@ x_set_fullscreen (f, new_value, old_value)
     f->want_fullscreen = FULLSCREEN_WIDTH;
   else if (EQ (new_value, Qfullheight))
     f->want_fullscreen = FULLSCREEN_HEIGHT;
+
+  if (fullscreen_hook != NULL) 
+    fullscreen_hook (f);
 }
 
 
@@ -3021,8 +3047,7 @@ x_set_line_spacing (f, new_value, old_value)
   else if (NATNUMP (new_value))
     f->extra_line_spacing = XFASTINT (new_value);
   else
-    Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
-                           Fcons (new_value, Qnil)));
+    signal_error ("Invalid line-spacing", new_value);
   if (FRAME_VISIBLE_P (f))
     redraw_frame (f);
 }
@@ -3036,16 +3061,30 @@ x_set_screen_gamma (f, new_value, old_value)
      struct frame *f;
      Lisp_Object new_value, old_value;
 {
+  Lisp_Object bgcolor;
+
   if (NILP (new_value))
     f->gamma = 0;
   else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
     /* The value 0.4545 is the normal viewing gamma.  */
     f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
   else
-    Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
-                           Fcons (new_value, Qnil)));
+    signal_error ("Invalid screen-gamma", new_value);
+
+  /* Apply the new gamma value to the frame background.  */
+  bgcolor = Fassq (Qbackground_color, f->param_alist);
+  if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
+    {
+      Lisp_Object index = Fget (Qbackground_color, Qx_frame_parameter);
+      if (NATNUMP (index)
+         && (XFASTINT (index)
+             < sizeof (frame_parms)/sizeof (frame_parms[0]))
+         && rif->frame_parm_handlers[XFASTINT (index)])
+       (*(rif->frame_parm_handlers[XFASTINT (index)]))
+         (f, bgcolor, Qnil);
+    }
 
-  clear_face_cache (0);
+  Fclear_face_cache (Qnil);
 }
 
 
@@ -3086,6 +3125,11 @@ x_set_font (f, arg, oldval)
       else if (!NILP (Fequal (result, oldval)))
         return;
 
+      /* Recalculate toolbar height.  */
+      f->n_tool_bar_rows = 0;
+      /* Ensure we redraw it.  */
+      clear_current_matrices (f);
+
       store_frame_param (f, Qfont, result);
       recompute_basic_faces (f);
     }
@@ -3125,10 +3169,8 @@ x_set_border_width (f, arg, oldval)
   if (XINT (arg) == f->border_width)
     return;
 
-#ifndef MAC_OS
   if (FRAME_X_WINDOW (f) != 0)
-    error ("Cannot change the border width of a window");
-#endif /* MAC_TODO */
+    error ("Cannot change the border width of a frame");
 
   f->border_width = XINT (arg);
 }
@@ -3364,7 +3406,7 @@ extern char *x_get_string_resource P_ ((XrmDatabase, char *, char *));
 extern Display_Info *check_x_display_info P_ ((Lisp_Object));
 
 
-/* Get specified attribute from resource database RDB.  
+/* Get specified attribute from resource database RDB.
    See Fx_get_resource below for other parameters.  */
 
 static Lisp_Object
@@ -3501,7 +3543,7 @@ x_get_resource_string (attribute, class)
 
 Lisp_Object
 x_get_arg (dpyinfo, alist, param, attribute, class, type)
-     Display_Info *dpyinfo; 
+     Display_Info *dpyinfo;
      Lisp_Object alist, param;
      char *attribute;
      char *class;
@@ -3510,8 +3552,27 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
   register Lisp_Object tem;
 
   tem = Fassq (param, alist);
-  if (EQ (tem, Qnil))
+
+  if (!NILP (tem))
+    {
+      /* If we find this parm in ALIST, clear it out
+        so that it won't be "left over" at the end.  */
+#ifndef WINDOWSNT /* w32fns.c has not yet been changed to cope with this.  */
+      Lisp_Object tail;
+      XSETCAR (tem, Qnil);
+      /* In case the parameter appears more than once in the alist,
+        clear it out.  */
+      for (tail = alist; CONSP (tail); tail = XCDR (tail))
+       if (CONSP (XCAR (tail))
+           && EQ (XCAR (XCAR (tail)), param))
+         XSETCAR (XCAR (tail), Qnil);
+#endif
+    }
+  else
     tem = Fassq (param, Vdefault_frame_alist);
+
+  /* If it wasn't specified in ALIST or the Lisp-level defaults,
+     look in the X resources.  */
   if (EQ (tem, Qnil))
     {
       if (attribute)
@@ -3595,7 +3656,7 @@ x_frame_get_and_record_arg (f, alist, param, attribute, class, type)
 
   value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
                     attribute, class, type);
-  if (! NILP (value))
+  if (! NILP (value) && ! EQ (value, Qunbound))
     store_frame_param (f, param, value);
 
   return value;
@@ -3861,7 +3922,7 @@ x_figure_window_size (f, parms, toolbar_p)
       int width, height;
 
       /* It takes both for some WM:s to place it where we want */
-      window_prompting = USPosition | PPosition;
+      window_prompting |= USPosition | PPosition;
       x_fullscreen_adjust (f, &width, &height, &top, &left);
       FRAME_COLS (f) = width;
       FRAME_LINES (f) = height;
@@ -3908,6 +3969,8 @@ syms_of_frame ()
   staticpro (&Qframep);
   Qframe_live_p = intern ("frame-live-p");
   staticpro (&Qframe_live_p);
+  Qexplicit_name = intern ("explicit-name");
+  staticpro (&Qexplicit_name);
   Qheight = intern ("height");
   staticpro (&Qheight);
   Qicon = intern ("icon");
@@ -3966,6 +4029,10 @@ syms_of_frame ()
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
 
+  Qinhibit_face_set_after_frame_default
+    = intern ("inhibit-face-set-after-frame-default");
+  staticpro (&Qinhibit_face_set_after_frame_default);
+
   Qfullwidth = intern ("fullwidth");
   staticpro (&Qfullwidth);
   Qfullheight = intern ("fullheight");
@@ -4046,15 +4113,11 @@ Setting this variable does not affect existing frames, only new ones.  */);
   Vdefault_frame_scroll_bars = Qnil;
 #endif
 
-  Qinhibit_default_face_x_resources
-    = intern ("inhibit-default-face-x-resources");
-  staticpro (&Qinhibit_default_face_x_resources);
-
   DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
               doc: /* The initial frame-object, which represents Emacs's stdout.  */);
 
   DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
-              doc: /* Non-nil if all of emacs is iconified and frame updates are not needed.  */);
+              doc: /* Non-nil if all of Emacs is iconified and frame updates are not needed.  */);
   Vemacs_iconified = Qnil;
 
   DEFVAR_LISP ("mouse-position-function", &Vmouse_position_function,
@@ -4094,6 +4157,21 @@ displayed.
 
 This variable is local to the current terminal and cannot be buffer-local.  */);
 
+  DEFVAR_BOOL ("focus-follows-mouse", &focus_follows_mouse,
+              doc: /* Non-nil if window system changes focus when you move the mouse.
+You should set this variable to tell Emacs how your window manager
+handles focus, since there is no way in general for Emacs to find out
+automatically.  */);
+#ifdef HAVE_WINDOW_SYSTEM
+#if defined(HAVE_NTGUI) || defined(MAC_OS)
+  focus_follows_mouse = 0;
+#else
+  focus_follows_mouse = 1;
+#endif
+#else
+  focus_follows_mouse = 0;
+#endif
+        
   staticpro (&Vframe_list);
 
   defsubr (&Sactive_minibuffer_window);