all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Patch to fix non-deterministic frame-positioning under X
@ 2006-06-13 19:25 Fran Litterio
  2006-06-15 22:28 ` Kim F. Storm
  0 siblings, 1 reply; 6+ messages in thread
From: Fran Litterio @ 2006-06-13 19:25 UTC (permalink / raw)
  Cc: Richard Stallman, Drew Adams

[-- Attachment #1: Type: text/plain, Size: 740 bytes --]

Now that the FSF has my signed copyright assignment, RMS asked me to
resend my patch with itemized changelog entries. The patch is
attached.

This patch fixes a bug where frame positioning under X would sometimes
(non-deterministically) misplace a frame when set-frame-position was
called.  To test this patch, start Emacs like this:

    emacs -q

and evaluate this Elisp:

(dolist (i '(1 2 3 4 5 6 7 8 9 a b c d e))
         (let ((frame (make-frame '((top . 50) (left . 50)))))
           (set-frame-position frame 200 200)
           (set-frame-position frame 300 300)))

You should be able to repeatedly evaluate the above form, and all
newly created frames should end up in exactly the same location (x/y =
300/300).
--
Fran Litterio

[-- Attachment #2: frame-position.patch --]
[-- Type: application/octet-stream, Size: 9440 bytes --]

Index: ChangeLog
===================================================================
RCS file: /cvsroot/emacs/emacs/src/ChangeLog,v
retrieving revision 1.5132
diff -u -r1.5132 ChangeLog
--- ChangeLog	12 Jun 2006 22:32:24 -0000	1.5132
+++ ChangeLog	13 Jun 2006 19:06:01 -0000
@@ -1,3 +1,12 @@
+2006-06-13  Francis Litterio  <flitterio@gmail.com>
+
+	* xterm.c (x_check_expected_move, handle_one_xevent)
+	(x_set_offset, x_check_fullscreen): Extensive changes to make
+	frame positioning deterministic under X.
+
+	* xterm.h (x_output): Added members left_before_move and
+	top_before_move.  Removed members expected_left and expected_top.
+	
 2006-06-13  Kim F. Storm  <storm@cua.dk>
 
 	* dispnew.c: Modify preemptive redisplay to be based on periodic
Index: xterm.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xterm.c,v
retrieving revision 1.917
diff -u -r1.917 xterm.c
--- xterm.c	29 May 2006 08:06:15 -0000	1.917
+++ xterm.c	13 Jun 2006 19:06:18 -0000
@@ -354,7 +354,8 @@
 					    Lisp_Object *, Lisp_Object *,
 					    unsigned long *));
 static void x_check_fullscreen P_ ((struct frame *));
-static void x_check_expected_move P_ ((struct frame *));
+static void x_check_expected_move P_ ((struct frame *, int, int));
+static void x_sync_with_move P_ ((struct frame *, int, int, int));
 static int handle_one_xevent P_ ((struct x_display_info *, XEvent *,
 				  int *, struct input_event *));
 static SIGTYPE x_connection_closed P_ ((Display *, char *));
@@ -6673,11 +6674,8 @@
               && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
 #endif
             {
-	      /* What we have now is the position of Emacs's own window.
-		 Convert that to the position of the window manager window.  */
 	      x_real_positions (f, &f->left_pos, &f->top_pos);
 
-	      x_check_expected_move (f);
 	      if (f->want_fullscreen & FULLSCREEN_WAIT)
 		f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
             }
@@ -8223,8 +8221,11 @@
 {
   int modified_top, modified_left;
 
-  if (change_gravity > 0)
+  if (change_gravity != 0)
     {
+      FRAME_X_OUTPUT (f)->left_before_move = f->left_pos;
+      FRAME_X_OUTPUT (f)->top_before_move = f->top_pos;
+
       f->top_pos = yoff;
       f->left_pos = xoff;
       f->size_hint_flags &= ~ (XNegative | YNegative);
@@ -8242,7 +8243,7 @@
   modified_left = f->left_pos;
   modified_top = f->top_pos;
 
-  if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
+  if (change_gravity != 0 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
     {
       /* Some WMs (twm, wmaker at least) has an offset that is smaller
          than the WM decorations.  So we use the calculated offset instead
@@ -8254,13 +8255,26 @@
   XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
                modified_left, modified_top);
 
-  if (FRAME_VISIBLE_P (f)
-      && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
-    {
-      FRAME_X_OUTPUT (f)->check_expected_move = 1;
-      FRAME_X_OUTPUT (f)->expected_top = f->top_pos;
-      FRAME_X_OUTPUT (f)->expected_left = f->left_pos;
-    }
+  x_sync_with_move (f, f->left_pos, f->top_pos,
+                    FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
+                    ? 1 : 0);
+
+  /* change_gravity is non-zero when this function is called from Lisp to
+     programmatically move a frame.  In that case, we call
+     x_check_expected_move to discover if we have a "Type A" or "Type B"
+     window manager, and, for a "Type A" window manager, adjust the position
+     of the frame.
+
+     We call x_check_expected_move if a programmatic move occurred, and
+     either the window manager type (A/B) is unknown or it is Type A but we
+     need to compute the top/left offset adjustment for this frame.  */
+
+  if (change_gravity != 0 &&
+      (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
+       || (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
+           && (FRAME_X_OUTPUT (f)->move_offset_left == 0
+               && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
+    x_check_expected_move (f, modified_left, modified_top);
 
   UNBLOCK_INPUT;
 }
@@ -8295,37 +8309,96 @@
     }
 }
 
-/* If frame parameters are set after the frame is mapped, we need to move
-   the window.
-   Some window managers moves the window to the right position, some
-   moves the outer window manager window to the specified position.
-   Here we check that we are in the right spot.  If not, make a second
-   move, assuming we are dealing with the second kind of window manager. */
+/* This function is called by x_set_offset to determine whether the window
+   manager interfered with the positioning of the frame.  Type A window
+   managers position the surrounding window manager decorations a small
+   amount above and left of the user-supplied position.  Type B window
+   managers position the surrounding window manager decorations at the
+   user-specified position.  If we detect a Type A window manager, we
+   compensate by moving the window right and down by the proper amount.  */
+
 static void
-x_check_expected_move (f)
+x_check_expected_move (f, expected_left, expected_top)
      struct frame *f;
+     int expected_left;
+     int expected_top;
 {
-  if (FRAME_X_OUTPUT (f)->check_expected_move)
-  {
-    int expect_top = FRAME_X_OUTPUT (f)->expected_top;
-    int expect_left = FRAME_X_OUTPUT (f)->expected_left;
+  int count = 0, current_left = 0, current_top = 0;
+
+  /* x_real_positions returns the left and top offsets of the outermost
+     window manager window around the frame.  */
 
-    if (expect_top != f->top_pos || expect_left != f->left_pos)
+  x_real_positions (f, &current_left, &current_top);
+
+  if (current_left != expected_left || current_top != expected_top)
       {
+      /* It's a "Type A" window manager. */
+
+      int adjusted_left;
+      int adjusted_top;
+
         FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
-        FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos;
-        FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos;
+      FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
+      FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
+
+      /* Now fix the mispositioned frame's location. */
+
+      adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
+      adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
+
+      XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+                   adjusted_left, adjusted_top);
 
-        f->left_pos = expect_left;
-        f->top_pos = expect_top;
-        x_set_offset (f, expect_left, expect_top, 0);
+      x_sync_with_move (f, expected_left, expected_top, 0);
       }
-    else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
+  else
+    /* It's a "Type B" window manager.  We don't have to adjust the
+       frame's position. */
+
       FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
+}
 
-    /* Just do this once */
-    FRAME_X_OUTPUT (f)->check_expected_move = 0;
+
+/* Wait for XGetGeometry to return up-to-date position information for a
+   recently-moved frame.  Call this immediately after calling XMoveWindow.
+   If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
+   frame has been moved to, so we use a fuzzy position comparison instead
+   of an exact comparison.  */
+
+static void
+x_sync_with_move (f, left, top, fuzzy)
+    struct frame *f;
+    int left, top, fuzzy;
+{
+  int count = 0;
+
+  while (count++ < 50)
+    {
+      int current_left = 0, current_top = 0;
+
+      /* In theory, this call to XSync only needs to happen once, but in
+         practice, it doesn't seem to work, hence the need for the surrounding
+         loop.  */
+
+      XSync (FRAME_X_DISPLAY (f), False);
+      x_real_positions (f, &current_left, &current_top);
+
+      if (fuzzy)
+        {
+          /* The left fuzz-factor is 10 pixels.  The top fuzz-factor is 40
+             pixels.  */
+
+          if (abs (current_left - left) <= 10 && abs (current_top - top) <= 40)
+            return;
   }
+      else if (current_left == left && current_top == top)
+        return;
+    }
+
+  /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
+     will then return up-to-date position info. */
+
+  wait_reading_process_output (0, 500000, 0, 0, Qnil, NULL, 0);
 }
 
 
Index: xterm.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xterm.h,v
retrieving revision 1.184
diff -u -r1.184 xterm.h
--- xterm.h	23 May 2006 07:12:49 -0000	1.184
+++ xterm.h	13 Jun 2006 19:06:20 -0000
@@ -637,18 +637,14 @@
      FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */
   int focus_state;
 
-  /* The latest move we made to FRAME_OUTER_WINDOW.  Saved so we can
-     compensate for type A WMs (see wm_type in dpyinfo above).  */
-  int expected_top;
-  int expected_left;
-
   /* The offset we need to add to compensate for type A WMs.  */
   int move_offset_top;
   int move_offset_left;
 
-  /* Nonzero if we have made a move and needs to check if the WM placed us
-     at the right position.  */
-  int check_expected_move;
+  /* The frame's left/top offsets before we call XMoveWindow.  See
+     x_check_expected_move.  */
+  int left_before_move;
+  int top_before_move;
 };
 
 #define No_Cursor (None)

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Patch to fix non-deterministic frame-positioning under X
  2006-06-13 19:25 Patch to fix non-deterministic frame-positioning under X Fran Litterio
@ 2006-06-15 22:28 ` Kim F. Storm
  2006-06-16  5:36   ` Jan Djärv
  0 siblings, 1 reply; 6+ messages in thread
From: Kim F. Storm @ 2006-06-15 22:28 UTC (permalink / raw)


"Fran Litterio" <flitterio@gmail.com> writes:

Has anyone looked at this patch yet?  Jan D.?

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Patch to fix non-deterministic frame-positioning under X
  2006-06-15 22:28 ` Kim F. Storm
@ 2006-06-16  5:36   ` Jan Djärv
  2006-06-16  8:03     ` Kim F. Storm
  2006-06-16 15:06     ` Richard Stallman
  0 siblings, 2 replies; 6+ messages in thread
From: Jan Djärv @ 2006-06-16  5:36 UTC (permalink / raw)
  Cc: emacs-devel

Kim F. Storm skrev:
> "Fran Litterio" <flitterio@gmail.com> writes:
> 
> Has anyone looked at this patch yet?  Jan D.?
> 

Yes, I looked and ran it a while back.  We where waiting for papers, have 
these arrived?

	Jan D.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Patch to fix non-deterministic frame-positioning under X
  2006-06-16  5:36   ` Jan Djärv
@ 2006-06-16  8:03     ` Kim F. Storm
  2006-06-16 12:14       ` Jan Djärv
  2006-06-16 15:06     ` Richard Stallman
  1 sibling, 1 reply; 6+ messages in thread
From: Kim F. Storm @ 2006-06-16  8:03 UTC (permalink / raw)
  Cc: emacs-devel

Jan Djärv <jan.h.d@swipnet.se> writes:

> Kim F. Storm skrev:
>> "Fran Litterio" <flitterio@gmail.com> writes:
>>
>> Has anyone looked at this patch yet?  Jan D.?
>>
>
> Yes, I looked and ran it a while back.  We where waiting for papers,
> have these arrived?

Yes.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Patch to fix non-deterministic frame-positioning under X
  2006-06-16  8:03     ` Kim F. Storm
@ 2006-06-16 12:14       ` Jan Djärv
  0 siblings, 0 replies; 6+ messages in thread
From: Jan Djärv @ 2006-06-16 12:14 UTC (permalink / raw)
  Cc: emacs-devel



Kim F. Storm skrev:
> Jan Djärv <jan.h.d@swipnet.se> writes:
> 
>> Kim F. Storm skrev:
>>> "Fran Litterio" <flitterio@gmail.com> writes:
>>>
>>> Has anyone looked at this patch yet?  Jan D.?
>>>
>> Yes, I looked and ran it a while back.  We where waiting for papers,
>> have these arrived?
> 
> Yes.

I have checked it in now.  I must have missed some mails.

	Jan D.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Patch to fix non-deterministic frame-positioning under X
  2006-06-16  5:36   ` Jan Djärv
  2006-06-16  8:03     ` Kim F. Storm
@ 2006-06-16 15:06     ` Richard Stallman
  1 sibling, 0 replies; 6+ messages in thread
From: Richard Stallman @ 2006-06-16 15:06 UTC (permalink / raw)
  Cc: emacs-devel, storm

The papers arrived; would someone please install the patch?

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2006-06-16 15:06 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-13 19:25 Patch to fix non-deterministic frame-positioning under X Fran Litterio
2006-06-15 22:28 ` Kim F. Storm
2006-06-16  5:36   ` Jan Djärv
2006-06-16  8:03     ` Kim F. Storm
2006-06-16 12:14       ` Jan Djärv
2006-06-16 15:06     ` Richard Stallman

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.