emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Improved patch to fix frame positioning bug on Windows


From: Francis Litterio
Subject: Improved patch to fix frame positioning bug on Windows
Date: Thu, 13 Jan 2005 12:41:44 -0500
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/21.3.50 (windows-nt)

On Windows, evaluating (make-frame '((left . -1))) creates a frame that
is positioned several pixels off the right edge of the display.
Similarly, (make-frame '((top . -1))) creates a frame that is positioned
off the bottom edge of the display.

The below patch fixes this bug and does not regress the fix to Drew
Adams' bug reported at:

  http://lists.gnu.org/archive/html/emacs-pretest-bug/2004-11/msg00519.html

(modulo the mistaken assumption about frame width in step #2 of Drew's
bug report).

This patch changes function x_calc_absolute_position() in w32term.c so
that it properly accounts for the width and height of the Windows-drawn
borders around the frame when converting a negative 'left or 'top
parameter into its equivalent non-negative value.  This code works
correctly even if the user has configured the Windows-drawn borders to
have a different width or height from the default.

After applying this patch, you can test it by evaluating these forms and
seeing the described behavior:

  ;; Create a frame flush against the right edge of the display.
  (make-frame '((left . -1)))

  ;; Create a frame flush against the bottom edge of the display.
  (make-frame '((top . -1)))

  ;; Create a frame flush against the bottom/right edge of the display.
  (make-frame '((top . -1) (left . -1)))

  ;; Move the current frame flush against the right edge of the display.
  (modify-frame-parameters nil '((left . -1)))

  ;; Move the current frame flush against the bottom edge of the display.
  (modify-frame-parameters nil '((top . -1)))

  ;; Test that setting the current frame's 'left parameter to a negative
  ;; value that is equivalent to its current positive value does not
  ;; move the frame.  The value of border-width in this test _MUST_ be
  ;; set to the width of your left (or right) Windows border in pixels.
  ;; Values shown here are typical but may not be correct for your
  ;; system.
  (let* ((border-width 4)
         (negative-left (- (+ 1 (- (display-pixel-width)
                                 (+ (* 2 border-width)
                                    (frame-pixel-width nil)
                                    (frame-parameter nil 'left)))))))
    (modify-frame-parameters nil `((left . ,negative-left))))

  ;; Test that setting the current frame's 'top parameter to a negative
  ;; value that is equivalent to its current positive value does not
  ;; move the frame.  The value of border-height-top in this test _MUST_
  ;; be set to the height of your top Windows border in pixels.  The
  ;; value of border-height-bottom in this test _MUST_ be set to the
  ;; height of your bottom Windows border in pixels.  Values shown here
  ;; are typical but may not be correct for your system.
  (let* ((border-height-top 29)
         (border-height-bottom 4)
         (negative-top (- (+ 1 (- (display-pixel-height)
                                (+ border-height-top
                                   border-height-bottom
                                   (frame-pixel-height nil)
                                   (frame-parameter nil 'top)))))))
    (modify-frame-parameters nil `((top . ,negative-top))))

I hope this helps.
--
Francis Litterio
franl <at> world . std . com


--- src/ChangeLog       10 Jan 2005 08:29:50 -0500      1.4147
+++ src/ChangeLog       13 Jan 2005 12:39:35 -0500      
@@ -1,3 +1,10 @@
+2005-01-13  Francis Litterio  <address@hidden>
+
+       * w32term.c (x_calc_absolute_position): Changed function
+       x_calc_absolute_position() to account for the Windows-drawn
+       borders around a frame when converting a negative 'top or 'left
+       parameter into the equivalent positive value.
+
 2005-01-10  Kim F. Storm  <address@hidden>
 
        * dispextern.h (merge_faces): Rename from merge_into_realized_face.


--- src/w32term.c       03 Jan 2005 17:52:51 -0500      1.221
+++ src/w32term.c       13 Jan 2005 12:17:05 -0500      
@@ -1461,7 +1461,7 @@
     {
       real_x = max (real_x, s->gc->clip_rectangle.left);
       real_y = max (real_y, s->gc->clip_rectangle.top);
-      real_w = min (real_w, s->gc->clip_rectangle.right
+      real_w = min (real_w, s->gc->clip_rectangle.r ght
                     - s->gc->clip_rectangle.left);
       real_h = min (real_h, s->gc->clip_rectangle.bottom
                     - s->gc->clip_rectangle.top);
@@ -5376,17 +5376,58 @@
 {
   int flags = f->size_hint_flags;
 
-  /* Treat negative positions as relative to the leftmost bottommost
+  /* left_right_borders_width holds the sum of the widths of the frame's left
+     and right borders (in pixels) drawn by Windows. */
+
+  unsigned int left_right_borders_width = 8;   /* A sensible default value. */
+
+  /* top_bottom_borders_height holds the sum of the heights of the frame's top 
and
+     bottom borders (in pixels) drawn by Windows. */
+
+  unsigned int top_bottom_borders_height = 32;  /* A sensible default value. */
+
+  /* Now obtain the actual values of the above two variables.  If we fail to
+     obtain the actual values, we will use the defaults assigned above.  We 
compute
+     the border width (height) by subtracting the width (height) of the frame's
+     client area from the width (height) of the frame's entire window.
+  */
+
+  WINDOWPLACEMENT wp = { 0 };
+
+  BOOL status = GetWindowPlacement (FRAME_W32_WINDOW (f), &wp);
+
+  if (status != FALSE)
+  {
+      RECT client_rect = { 0 };
+
+      status = GetClientRect (FRAME_W32_WINDOW (f), &client_rect);
+
+      if (status != FALSE)
+      {
+         left_right_borders_width =
+             (wp.rcNormalPosition.right - wp.rcNormalPosition.left) -
+             (client_rect.right - client_rect.left);
+
+         top_bottom_borders_height =
+             (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) -
+             (client_rect.bottom - client_rect.top);
+      }
+  }
+
+  /* Treat negative positions as relative to the rightmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
     f->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
                   - FRAME_PIXEL_WIDTH (f)
-                  + f->left_pos);
+                  + f->left_pos
+                  - (left_right_borders_width - 1));
 
   if (flags & YNegative)
     f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
                  - FRAME_PIXEL_HEIGHT (f)
-                 + f->top_pos);
+                 + f->top_pos
+                  - (top_bottom_borders_height - 1));
+
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */





reply via email to

[Prev in Thread] Current Thread [Next in Thread]