New functions that return window edges with absolute coords (bug#5721).
[bpt/emacs.git] / src / window.c
index 2c178a6..deca842 100644 (file)
@@ -1,7 +1,7 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
    Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
-                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -54,7 +54,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
 Lisp_Object Qdisplay_buffer;
-Lisp_Object Qscroll_up, Qscroll_down;
+Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
 Lisp_Object Qwindow_size_fixed;
 
 extern Lisp_Object Qleft_margin, Qright_margin;
@@ -652,6 +652,48 @@ of just the text area, use `window-inside-pixel-edges'.  */)
                Qnil))));
 }
 
+static void
+calc_absolute_offset(struct window *w, int *add_x, int *add_y)
+{
+  struct frame *f = XFRAME (w->frame);
+  *add_y = f->top_pos;
+#ifdef FRAME_MENUBAR_HEIGHT
+  *add_y += FRAME_MENUBAR_HEIGHT (f);
+#endif
+#ifdef FRAME_TOOLBAR_HEIGHT
+  *add_y += FRAME_TOOLBAR_HEIGHT (f);
+#endif
+#ifdef FRAME_NS_TITLEBAR_HEIGHT
+  *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
+#endif
+  *add_x = f->left_pos;
+}
+
+DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
+       Swindow_absolute_pixel_edges, 0, 1, 0,
+       doc: /* Return a list of the edge pixel coordinates of WINDOW.
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
+the top left corner of the display.
+
+RIGHT is one more than the rightmost x position occupied by WINDOW.
+BOTTOM is one more than the bottommost y position occupied by WINDOW.
+The pixel edges include the space used by WINDOW's scroll bar, display
+margins, fringes, header line, and/or mode line.  For the pixel edges
+of just the text area, use `window-inside-pixel-edges'.  */)
+     (window)
+     Lisp_Object window;
+{
+  register struct window *w = decode_any_window (window);
+  int add_x, add_y;
+  calc_absolute_offset(w, &add_x, &add_y);
+
+  return Fcons (make_number (WINDOW_LEFT_EDGE_X (w) + add_x),
+         Fcons (make_number (WINDOW_TOP_EDGE_Y (w) + add_y),
+        Fcons (make_number (WINDOW_RIGHT_EDGE_X (w) + add_x),
+        Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w) + add_y),
+               Qnil))));
+}
+
 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
        doc: /* Return a list of the edge coordinates of WINDOW.
 The list has the form (LEFT TOP RIGHT BOTTOM).
@@ -705,6 +747,36 @@ display margins, fringes, header line, and/or mode line.  */)
                             - WINDOW_MODE_LINE_HEIGHT (w)));
 }
 
+DEFUN ("window-inside-absolute-pixel-edges",
+       Fwindow_inside_absolute_pixel_edges,
+       Swindow_inside_absolute_pixel_edges, 0, 1, 0,
+       doc: /* Return a list of the edge pixel coordinates of WINDOW.
+The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
+the top left corner of the display.
+
+RIGHT is one more than the rightmost x position of WINDOW's text area.
+BOTTOM is one more than the bottommost y position of WINDOW's text area.
+The inside edges do not include the space used by WINDOW's scroll bar,
+display margins, fringes, header line, and/or mode line.  */)
+     (window)
+     Lisp_Object window;
+{
+  register struct window *w = decode_any_window (window);
+  int add_x, add_y;
+  calc_absolute_offset(w, &add_x, &add_y);
+
+  return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
+                            + WINDOW_LEFT_MARGIN_WIDTH (w)
+                            + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
+               make_number (WINDOW_TOP_EDGE_Y (w)
+                            + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
+               make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
+                            - WINDOW_RIGHT_MARGIN_WIDTH (w)
+                            - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
+               make_number (WINDOW_BOTTOM_EDGE_Y (w)
+                            - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
+}
+
 /* Test if the character at column *X, row *Y is within window W.
    If it is not, return ON_NOTHING;
    if it is in the window's text area,
@@ -3611,6 +3683,7 @@ selected window before each command.  */)
     {
       ++window_select_count;
       XSETFASTINT (w->use_time, window_select_count);
+      record_buffer (w->buffer);
     }
 
   if (EQ (window, selected_window))
@@ -3646,8 +3719,6 @@ selected window before each command.  */)
 
   selected_window = window;
 
-  if (NILP (norecord))
-    record_buffer (w->buffer);
   Fset_buffer (w->buffer);
 
   XBUFFER (w->buffer)->last_selected_window = window;
@@ -4648,12 +4719,15 @@ grow_mini_window (w, delta)
   struct window *root;
 
   xassert (MINI_WINDOW_P (w));
-  xassert (delta >= 0);
+  /* Commenting out the following assertion goes against the stated interface
+     of the function, but it currently does not seem to do anything useful.
+     See discussion of this issue in the thread for bug#4534.
+     xassert (delta >= 0); */
 
   /* Compute how much we can enlarge the mini-window without deleting
      other windows.  */
   root = XWINDOW (FRAME_ROOT_WINDOW (f));
-  if (delta)
+  if (delta > 0)
     {
       int min_height = window_min_size (root, 0, 0, 0, 0);
       if (XFASTINT (root->total_lines) - delta < min_height)
@@ -4939,12 +5013,13 @@ window_scroll_pixel_based (window, n, whole, noerror)
   if (!NILP (Vscroll_preserve_screen_position))
     {
       /* We preserve the goal pixel coordinate across consecutive
-        calls to scroll-up or scroll-down.  This avoids the
+        calls to scroll-up, scroll-down and other commands that
+        have the `scroll-command' property.  This avoids the
         possibility of point becoming "stuck" on a tall line when
         scrolling by one line.  */
       if (window_scroll_pixel_based_preserve_y < 0
-         || (!EQ (current_kboard->Vlast_command, Qscroll_up)
-             && !EQ (current_kboard->Vlast_command, Qscroll_down)))
+         || !SYMBOLP (current_kboard->Vlast_command)
+         || NILP (Fget (current_kboard->Vlast_command, Qscroll_command)))
        {
          start_display (&it, w, start);
          move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
@@ -5204,8 +5279,8 @@ window_scroll_line_based (window, n, whole, noerror)
   if (!NILP (Vscroll_preserve_screen_position))
     {
       if (window_scroll_preserve_vpos <= 0
-         || (!EQ (current_kboard->Vlast_command, Qscroll_up)
-             && !EQ (current_kboard->Vlast_command, Qscroll_down)))
+         || !SYMBOLP (current_kboard->Vlast_command)
+         || NILP (Fget (current_kboard->Vlast_command, Qscroll_command)))
        {
          struct position posit
            = *compute_motion (startpos, 0, 0, 0,
@@ -7167,33 +7242,39 @@ init_window ()
 void
 syms_of_window ()
 {
-  Qscroll_up = intern ("scroll-up");
+  Qscroll_up = intern_c_string ("scroll-up");
   staticpro (&Qscroll_up);
 
-  Qscroll_down = intern ("scroll-down");
+  Qscroll_down = intern_c_string ("scroll-down");
   staticpro (&Qscroll_down);
 
-  Qwindow_size_fixed = intern ("window-size-fixed");
+  Qscroll_command = intern_c_string ("scroll-command");
+  staticpro (&Qscroll_command);
+
+  Fput (Qscroll_up, Qscroll_command, Qt);
+  Fput (Qscroll_down, Qscroll_command, Qt);
+
+  Qwindow_size_fixed = intern_c_string ("window-size-fixed");
   staticpro (&Qwindow_size_fixed);
   Fset (Qwindow_size_fixed, Qnil);
 
   staticpro (&Qwindow_configuration_change_hook);
   Qwindow_configuration_change_hook
-    = intern ("window-configuration-change-hook");
+    = intern_c_string ("window-configuration-change-hook");
 
-  Qwindowp = intern ("windowp");
+  Qwindowp = intern_c_string ("windowp");
   staticpro (&Qwindowp);
 
-  Qwindow_configuration_p = intern ("window-configuration-p");
+  Qwindow_configuration_p = intern_c_string ("window-configuration-p");
   staticpro (&Qwindow_configuration_p);
 
-  Qwindow_live_p = intern ("window-live-p");
+  Qwindow_live_p = intern_c_string ("window-live-p");
   staticpro (&Qwindow_live_p);
 
-  Qdisplay_buffer = intern ("display-buffer");
+  Qdisplay_buffer = intern_c_string ("display-buffer");
   staticpro (&Qdisplay_buffer);
 
-  Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
+  Qtemp_buffer_show_hook = intern_c_string ("temp-buffer-show-hook");
   staticpro (&Qtemp_buffer_show_hook);
 
   staticpro (&Vwindow_list);
@@ -7262,7 +7343,9 @@ at the scroll margin or window boundary respectively.
 A value of t means point keeps its screen position if the scroll
 command moved it vertically out of the window, e.g. when scrolling
 by full screens.
-Any other value means point always keeps its screen position.  */);
+Any other value means point always keeps its screen position.
+Scroll commands should have the `scroll-command' property
+on their symbols to be controlled by this variable.  */);
   Vscroll_preserve_screen_position = Qnil;
 
   DEFVAR_LISP ("window-point-insertion-type", &Vwindow_point_insertion_type,
@@ -7279,7 +7362,7 @@ with the relevant frame selected.  */);
 
   DEFVAR_LISP ("recenter-redisplay", &Vrecenter_redisplay,
               doc: /* If non-nil, then the `recenter' command with a nil argument
-the entire frame to be redrawn; the special value `tty' causes the
+will redraw the entire frame; the special value `tty' causes the
 frame to be redrawn only if it is a tty frame.  */);
   Vrecenter_redisplay = Qtty;
 
@@ -7301,8 +7384,10 @@ frame to be redrawn only if it is a tty frame.  */);
   defsubr (&Sset_window_redisplay_end_trigger);
   defsubr (&Swindow_edges);
   defsubr (&Swindow_pixel_edges);
+  defsubr (&Swindow_absolute_pixel_edges);
   defsubr (&Swindow_inside_edges);
   defsubr (&Swindow_inside_pixel_edges);
+  defsubr (&Swindow_inside_absolute_pixel_edges);
   defsubr (&Scoordinates_in_window_p);
   defsubr (&Swindow_at);
   defsubr (&Swindow_point);
@@ -7374,12 +7459,9 @@ keys_of_window ()
   initial_define_key (control_x_map, '<', "scroll-left");
   initial_define_key (control_x_map, '>', "scroll-right");
 
-  initial_define_key (global_map, Ctl ('V'), "scroll-up");
+  initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
   initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
-  initial_define_key (meta_map, 'v', "scroll-down");
-
-  initial_define_key (global_map, Ctl('L'), "recenter");
-  initial_define_key (meta_map, 'r', "move-to-window-line");
+  initial_define_key (meta_map, 'v', "scroll-down-command");
 }
 
 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f