* Patch to fix frame positioning bug on Windows with (make-frame '((left . -1))) @ 2005-01-11 20:30 Francis Litterio 2005-01-12 20:04 ` Jan D. 0 siblings, 1 reply; 5+ messages in thread From: Francis Litterio @ 2005-01-11 20:30 UTC (permalink / raw) Cc: emacs-devel Using Emacs built from CVS source code on Windows XP, the frame created using the following Emacs-Lisp code is positioned such that the rightmost 7 pixels of the frame are off the right edge of the screen: (make-frame '((width . 80) (height . 20) (top . 0) (left . -1))) Those 7 pixels encompass the border of the Windows frame and some of the right fringe. This may have been caused by revision 1.220 of w32term.c in which function x_calc_absolute_position() was changed: revision 1.220 date: 2004/12/11 21:12:45; author: jhd; state: Exp; lines: +0 -30 * w32term.c (x_calc_absolute_position): Remove calculation of difference between inner and outer window. Don't subtract difference for left and top calculations. The below patch solves the problem but it may not be optimal because it simply subtracts 7 from the computed value of f->left_pos. One risk I see in this solution is that the user can change the Active Window Border size to have any pixel width (right click on the desktop, choose Properties, choose Appeareance, click Advanced, choose Active Window Border from the Item listbox). This code (both with and without my patch) does not take the user-configurable size of the Active Window Border into account. I hope this helps. -- Francis Litterio franl <at> world . std . com --- w32term.c 03 Jan 2005 17:52:51 -0500 1.221 +++ w32term.c 11 Jan 2005 15:27:02 -0500 @@ -5381,7 +5381,8 @@ if (flags & XNegative) f->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width - FRAME_PIXEL_WIDTH (f) - + f->left_pos); + + f->left_pos + - 7); if (flags & YNegative) f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Patch to fix frame positioning bug on Windows with (make-frame '((left . -1))) 2005-01-11 20:30 Patch to fix frame positioning bug on Windows with (make-frame '((left . -1))) Francis Litterio @ 2005-01-12 20:04 ` Jan D. 2005-01-12 20:45 ` Francis Litterio 0 siblings, 1 reply; 5+ messages in thread From: Jan D. @ 2005-01-12 20:04 UTC (permalink / raw) Cc: help-emacs-windows, emacs-devel > Using Emacs built from CVS source code on Windows XP, the frame created > using the following Emacs-Lisp code is positioned such that the > rightmost 7 pixels of the frame are off the right edge of the screen: > > (make-frame '((width . 80) (height . 20) (top . 0) (left . -1))) > > Those 7 pixels encompass the border of the Windows frame and some of > the > right fringe. This may have been caused by revision 1.220 of w32term.c > in which function x_calc_absolute_position() was changed: > > revision 1.220 > date: 2004/12/11 21:12:45; author: jhd; state: Exp; lines: +0 -30 > * w32term.c (x_calc_absolute_position): Remove calculation of > difference between inner and outer window. Don't subtract difference > for left and top calculations. > > The below patch solves the problem but it may not be optimal because it > simply subtracts 7 from the computed value of f->left_pos. Can you verify if your change has any impact on this bug: http://lists.gnu.org/archive/html/emacs-pretest-bug/2004-11/ msg00519.html This was the reason a change was made. It may be impossible to get Emacs to work correctly on W32. Just adding 7 is no good, as you self pointed out, a more general solution must be found. Jan D. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Patch to fix frame positioning bug on Windows with (make-frame '((left . -1))) 2005-01-12 20:04 ` Jan D. @ 2005-01-12 20:45 ` Francis Litterio 2005-01-13 2:59 ` Francis Litterio 0 siblings, 1 reply; 5+ messages in thread From: Francis Litterio @ 2005-01-12 20:45 UTC (permalink / raw) Cc: help-emacs-windows Jan D. wrote: >> Using Emacs built from CVS source code on Windows XP, the frame created >> using the following Emacs-Lisp code is positioned such that the >> rightmost 7 pixels of the frame are off the right edge of the screen: >> >> (make-frame '((width . 80) (height . 20) (top . 0) (left . -1))) ... >> The below patch solves the problem but it may not be optimal because it >> simply subtracts 7 from the computed value of f->left_pos. > > Can you verify if your change has any impact on this bug: > > http://lists.gnu.org/archive/html/emacs-pretest-bug/2004-11/msg00519.html > > This was the reason a change was made. It may be impossible to get > Emacs to work correctly on W32. Just [subtracting] 7 is no good, as > you self pointed out, a more general solution must be found. My change breaks the fix for that bug, so I'm going to investigate further. In my testing, I noticed that (make-frame '((top . -1))) on Windows suffers an even worse positioning error -- about 30 pixels at the bottom of the frame fall off the bottom of the screen! I would think that when a frame is positioned so that it is completely visible, we have the following variables and relations: OUTER-LEFT: The number of pixels between the left screen edge and the left border drawn by Windows of the frame. This can be 0. LEFT-BORDER: The width of the left border drawn by Windows (in pixels). FRAME-CONTENT-WIDTH: The width of the frame content, including the fringes but not including the left and right borders drawn by Windows. RIGHT-BORDER: The width of the right border drawn by Windows (in pixels). OUTER-RIGHT: The number of pixels between the right screen edge and the right border drawn by Windows of the frame. This can be 0. DISPLAY-WIDTH: The width of the display (in pixels). and finally this relation should hold: DISPLAY-WIDTH = OUTER-LEFT + LEFT-BORDER + FRAME-CONTENT-WIDTH + RIGHT-BORDER + OUTER-RIGHT A similar relation can be constructed for the vertical screen dimension. Given this model, we should be able to make w32term.c position frames consistently, regardless of whether the 'top or 'left frame parameter was positive or negative (modulo the issue with the user being able to change the width of the border drawn by Windows -- but it should work with Windows' default border sizes). -- Francis Litterio franl <at> world . std . com ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Patch to fix frame positioning bug on Windows with (make-frame '((left . -1))) 2005-01-12 20:45 ` Francis Litterio @ 2005-01-13 2:59 ` Francis Litterio 2005-01-13 3:37 ` Francis Litterio 0 siblings, 1 reply; 5+ messages in thread From: Francis Litterio @ 2005-01-13 2:59 UTC (permalink / raw) Cc: help-emacs-windows Francis Litterio wrote: > Jan D. wrote: >> Can you verify if your change has any impact on this bug: >> >> http://lists.gnu.org/archive/html/emacs-pretest-bug/2004-11/msg00519.html >> >> This was the reason a change was made. It may be impossible to get >> Emacs to work correctly on W32. Just [subtracting] 7 is no good, as >> you self pointed out, a more general solution must be found. > > My change breaks the fix for that bug, so I'm going to investigate > further. OK, I think I've gotten to the bottom of the issue. The above bug report by Drew Adams contains an incorrect assumption in step #2 of the steps to reproduce: > 1. Position a new frame at the left border (the position isn't important, > but keep track of the position you use - using 0 makes it easier). Evaluate > (assq 'left (frame-parameters nil)), getting, for example, (left . 0). > > 2. Measure the frame width in pixels: (frame-pixel-width nil), getting, for > example, 600. 600 is not the width of the frame in pixels. It is the width of the frame's client area in pixels. The window manager (i.e., Windows) draws left and right borders on either side of the client area, but frame-pixel-width does not include those borders in the value it returns.. So the value computed in step #2 above should be: (+ (frame-pixel-width nil) 6 6) => 612 Assuming his window manager borders are 6 pixels wide. > 3. Measure the display width in pixels: (display-pixel-width nil), getting, > for example, 1280. > > 4. Calculate the distance of the frame's right edge from the display's right > edge, getting, for example, 1280 - 600 = 680. In step #4, the calculation of the frame's right edge from the display's right edit should be: 1280 - 612 = 668 Actually, since a 'left parameter of 0 means "flush against the left edge of the screen" but -1 means "flush against the right edge of the screen", that calculation should be: 1280 - 612 + 1 = 669 > 5. Change the frame's left parameter to the negation of the value in #4, for > example: (modify-frame-parameters nil '((left . -680))). According to the > doc, this positions the right edge of the frame 680 pixels from the right > edge of the display. > > However the frame has in fact shifted 12 pixels to the left. The reason for this movement is that setting the 'left parameter to -680 was wrong. It should have been set to -669. To demonstrate that the window borders must be taken into account when computing the negative 'left frame parameter, evaluate the below form in a frame that is completely visible (no parts of the frame are off-screen). Evaluating this form should not move the frame at all, assuming your window manager draws left and right borders that are 4 pixels each (change the two 4's if your borders are different): (let ((negative-left (- (+ 1 (- (display-pixel-width) (+ 4 4 (frame-pixel-width nil) (frame-parameter nil 'left))))))) (modify-frame-parameters nil `((left . ,negative-left)))) On Windows, Emacs does not have to take the window manager borders into account when positioning frames using positive 'left and 'top parameters. Positive 'left and 'top parameters are simply passed directly to Windows, which is why this form: (make-frame '((top . 0) (left . 0))) positions the frame with the Windows borders flush against the left and top of the screen. This is desirable behavior. The only time that Emacs needs to take the window manager borders into account is when it converts a negative 'left or 'top parameter to an equivalent positive value, which is done in x_calc_absolute_position(): void x_calc_absolute_position (f) struct frame *f; { int flags = f->size_hint_flags; /* Treat negative positions as relative to the leftmost 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); if (flags & YNegative) f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height - FRAME_PIXEL_HEIGHT (f) + f->top_pos); /* The left_pos and top_pos are now relative to the top and left screen edges, so the flags should correspond. */ f->size_hint_flags &= ~ (XNegative | YNegative); } and nowhere else (that I can find). Thus, to fix both the bug reported in: http://lists.gnu.org/archive/html/emacs-pretest-bug/2004-11/msg00519.html and my bug, the above function needs to compute f->left_pos like this: f->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width - FRAME_PIXEL_WIDTH (f) + f->left_pos - (FRAME_W32_VERTICAL_BORDER_WIDTH * 2) - 1); where FRAME_W32_VERTICAL_BORDER_WIDTH is a proposed macro that evaluates to the pixel width of one vertical border drawn by Windows. On my system, it would expand to 4. On other Windows system, it may be different. Worse, under XP, the user can change it interactively using the Appearance tab on the desktop properties dialog. Similarly, f->top_pos should be computed like this: f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height - FRAME_PIXEL_HEIGHT (f) + f->top_pos - (FRAME_W32_TOP_BORDER_WIDTH + FRAME_W32_BOTTOM_BORDER_WIDTH) - 1); This needs two new macros, because the top and bottom borders have different sizes. The question is: What is the correct implementation of these new macros? On my system (Windows XP, with ), these values work: #define FRAME_W32_VERTICAL_BORDER_WIDTH 4 #define FRAME_W32_TOP_BORDER_WIDTH 25 #define FRAME_W32_BOTTOM_BORDER_WIDTH 4 I have build Emacs with the above change (and the above macro values), and when I evaluate: (make-frame '((top . -1) (left . -1))) the new frame is perfectly positioned flush against the right and bottom edges of the display. I hope this helps. -- Francis Litterio franl <at> world . std . com ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Patch to fix frame positioning bug on Windows with (make-frame '((left . -1))) 2005-01-13 2:59 ` Francis Litterio @ 2005-01-13 3:37 ` Francis Litterio 0 siblings, 0 replies; 5+ messages in thread From: Francis Litterio @ 2005-01-13 3:37 UTC (permalink / raw) Cc: help-emacs-windows I wrote: > To demonstrate that the window borders must be taken into account when > computing the negative 'left frame parameter, evaluate the below form in > a frame that is completely visible (no parts of the frame are > off-screen). Evaluating this form should not move the frame at all, > assuming your window manager draws left and right borders that are 4 > pixels each (change the two 4's if your borders are different): > > (let ((negative-left (- (+ 1 (- (display-pixel-width) > (+ 4 4 > (frame-pixel-width nil) > (frame-parameter nil 'left))))))) > (modify-frame-parameters nil `((left . ,negative-left)))) Sorry. You will only see no frame movement when evaluating the above form if you have already patched x_calc_absolute_position() as described in the parent of this article. -- Francis Litterio franl <at> world . std . com ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2005-01-13 3:37 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-01-11 20:30 Patch to fix frame positioning bug on Windows with (make-frame '((left . -1))) Francis Litterio 2005-01-12 20:04 ` Jan D. 2005-01-12 20:45 ` Francis Litterio 2005-01-13 2:59 ` Francis Litterio 2005-01-13 3:37 ` Francis Litterio
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.