From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Francis Litterio Newsgroups: gmane.emacs.devel,gmane.emacs.windows Subject: Re: Patch to fix frame positioning bug on Windows with (make-frame '((left . -1))) Date: Wed, 12 Jan 2005 21:59:18 -0500 Message-ID: References: <3ABA18C9-64D5-11D9-83C1-000D93505B76@swipnet.se> NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1105586904 3128 80.91.229.6 (13 Jan 2005 03:28:24 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Thu, 13 Jan 2005 03:28:24 +0000 (UTC) Cc: help-emacs-windows@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Jan 13 04:28:16 2005 Return-path: Original-Received: from lists.gnu.org ([199.232.76.165]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1Coveh-0007ys-00 for ; Thu, 13 Jan 2005 04:28:16 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1CovqK-0004vb-Sg for ged-emacs-devel@m.gmane.org; Wed, 12 Jan 2005 22:40:16 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Covpo-0004iY-JN for emacs-devel@gnu.org; Wed, 12 Jan 2005 22:39:44 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Covkl-0003qH-2U for emacs-devel@gnu.org; Wed, 12 Jan 2005 22:34:35 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Covkc-0003hu-5F for emacs-devel@gnu.org; Wed, 12 Jan 2005 22:34:22 -0500 Original-Received: from [80.91.229.2] (helo=main.gmane.org) by monty-python.gnu.org with esmtp (Exim 4.34) id 1CovCJ-0002N7-So for emacs-devel@gnu.org; Wed, 12 Jan 2005 21:58:56 -0500 Original-Received: from list by main.gmane.org with local (Exim 3.35 #1 (Debian)) id 1CovCI-0005nn-00 for ; Thu, 13 Jan 2005 03:58:54 +0100 Original-Received: from ppp0a036.std.com ([69.38.146.36]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Thu, 13 Jan 2005 03:58:54 +0100 Original-Received: from franl by ppp0a036.std.com with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Thu, 13 Jan 2005 03:58:54 +0100 X-Injected-Via-Gmane: http://gmane.org/ Original-To: emacs-devel@gnu.org Original-Lines: 164 Original-X-Complaints-To: usenet@sea.gmane.org X-Gmane-NNTP-Posting-Host: ppp0a036.std.com X-Draft-From: ("nntp+news.gmane.org:gmane.emacs.devel" 32172) Gcc: nnfolder:sent-usenet X-Random-Quote: Isn't it strange that I who have written only unpopular books should be such a popular fellow? -- Albert Einstein (1879 - 1955) User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/21.3.50 (windows-nt) Cancel-Lock: sha1:NZ+flzN0Jb5rukPzWMi7FpUZmqY= X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:32183 gmane.emacs.windows:2511 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:32183 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 world . std . com