aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Djärv2006-06-16 12:12:27 +0000
committerJan Djärv2006-06-16 12:12:27 +0000
commitd692a3d5c580f15bc5968a034286922c1a1bf423 (patch)
tree69a256c12c72ecc834a97d2522026b47c5e25884 /src
parentdb600ab1dbf2f0c84e6b82bef80dec3f68326637 (diff)
downloademacs-d692a3d5c580f15bc5968a034286922c1a1bf423.tar.gz
emacs-d692a3d5c580f15bc5968a034286922c1a1bf423.zip
2006-06-16 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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog9
-rw-r--r--src/xterm.c139
-rw-r--r--src/xterm.h12
3 files changed, 119 insertions, 41 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 0f16f42b857..536edd3e287 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,12 @@
12006-06-16 Francis Litterio <flitterio@gmail.com>
2
3 * xterm.c (x_check_expected_move, handle_one_xevent)
4 (x_set_offset, x_check_fullscreen): Extensive changes to make
5 frame positioning deterministic under X.
6
7 * xterm.h (x_output): Added members left_before_move and
8 top_before_move. Removed members expected_left and expected_top.
9
12006-06-16 Kim F. Storm <storm@cua.dk> 102006-06-16 Kim F. Storm <storm@cua.dk>
2 11
3 * dispextern.h (struct it): Add union to iterator stack to save 12 * dispextern.h (struct it): Add union to iterator stack to save
diff --git a/src/xterm.c b/src/xterm.c
index 343ca30caa9..dfa5f4f4413 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -354,7 +354,8 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
354 Lisp_Object *, Lisp_Object *, 354 Lisp_Object *, Lisp_Object *,
355 unsigned long *)); 355 unsigned long *));
356static void x_check_fullscreen P_ ((struct frame *)); 356static void x_check_fullscreen P_ ((struct frame *));
357static void x_check_expected_move P_ ((struct frame *)); 357static void x_check_expected_move P_ ((struct frame *, int, int));
358static void x_sync_with_move P_ ((struct frame *, int, int, int));
358static int handle_one_xevent P_ ((struct x_display_info *, XEvent *, 359static int handle_one_xevent P_ ((struct x_display_info *, XEvent *,
359 int *, struct input_event *)); 360 int *, struct input_event *));
360static SIGTYPE x_connection_closed P_ ((Display *, char *)); 361static SIGTYPE x_connection_closed P_ ((Display *, char *));
@@ -6673,11 +6674,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
6673 && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f))) 6674 && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
6674#endif 6675#endif
6675 { 6676 {
6676 /* What we have now is the position of Emacs's own window.
6677 Convert that to the position of the window manager window. */
6678 x_real_positions (f, &f->left_pos, &f->top_pos); 6677 x_real_positions (f, &f->left_pos, &f->top_pos);
6679 6678
6680 x_check_expected_move (f);
6681 if (f->want_fullscreen & FULLSCREEN_WAIT) 6679 if (f->want_fullscreen & FULLSCREEN_WAIT)
6682 f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH); 6680 f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
6683 } 6681 }
@@ -8223,8 +8221,11 @@ x_set_offset (f, xoff, yoff, change_gravity)
8223{ 8221{
8224 int modified_top, modified_left; 8222 int modified_top, modified_left;
8225 8223
8226 if (change_gravity > 0) 8224 if (change_gravity != 0)
8227 { 8225 {
8226 FRAME_X_OUTPUT (f)->left_before_move = f->left_pos;
8227 FRAME_X_OUTPUT (f)->top_before_move = f->top_pos;
8228
8228 f->top_pos = yoff; 8229 f->top_pos = yoff;
8229 f->left_pos = xoff; 8230 f->left_pos = xoff;
8230 f->size_hint_flags &= ~ (XNegative | YNegative); 8231 f->size_hint_flags &= ~ (XNegative | YNegative);
@@ -8242,7 +8243,7 @@ x_set_offset (f, xoff, yoff, change_gravity)
8242 modified_left = f->left_pos; 8243 modified_left = f->left_pos;
8243 modified_top = f->top_pos; 8244 modified_top = f->top_pos;
8244 8245
8245 if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A) 8246 if (change_gravity != 0 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
8246 { 8247 {
8247 /* Some WMs (twm, wmaker at least) has an offset that is smaller 8248 /* Some WMs (twm, wmaker at least) has an offset that is smaller
8248 than the WM decorations. So we use the calculated offset instead 8249 than the WM decorations. So we use the calculated offset instead
@@ -8254,13 +8255,26 @@ x_set_offset (f, xoff, yoff, change_gravity)
8254 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 8255 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8255 modified_left, modified_top); 8256 modified_left, modified_top);
8256 8257
8257 if (FRAME_VISIBLE_P (f) 8258 x_sync_with_move (f, f->left_pos, f->top_pos,
8258 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN) 8259 FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
8259 { 8260 ? 1 : 0);
8260 FRAME_X_OUTPUT (f)->check_expected_move = 1; 8261
8261 FRAME_X_OUTPUT (f)->expected_top = f->top_pos; 8262 /* change_gravity is non-zero when this function is called from Lisp to
8262 FRAME_X_OUTPUT (f)->expected_left = f->left_pos; 8263 programmatically move a frame. In that case, we call
8263 } 8264 x_check_expected_move to discover if we have a "Type A" or "Type B"
8265 window manager, and, for a "Type A" window manager, adjust the position
8266 of the frame.
8267
8268 We call x_check_expected_move if a programmatic move occurred, and
8269 either the window manager type (A/B) is unknown or it is Type A but we
8270 need to compute the top/left offset adjustment for this frame. */
8271
8272 if (change_gravity != 0 &&
8273 (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
8274 || (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
8275 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
8276 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
8277 x_check_expected_move (f, modified_left, modified_top);
8264 8278
8265 UNBLOCK_INPUT; 8279 UNBLOCK_INPUT;
8266} 8280}
@@ -8295,37 +8309,96 @@ x_check_fullscreen (f)
8295 } 8309 }
8296} 8310}
8297 8311
8298/* If frame parameters are set after the frame is mapped, we need to move 8312/* This function is called by x_set_offset to determine whether the window
8299 the window. 8313 manager interfered with the positioning of the frame. Type A window
8300 Some window managers moves the window to the right position, some 8314 managers position the surrounding window manager decorations a small
8301 moves the outer window manager window to the specified position. 8315 amount above and left of the user-supplied position. Type B window
8302 Here we check that we are in the right spot. If not, make a second 8316 managers position the surrounding window manager decorations at the
8303 move, assuming we are dealing with the second kind of window manager. */ 8317 user-specified position. If we detect a Type A window manager, we
8318 compensate by moving the window right and down by the proper amount. */
8319
8304static void 8320static void
8305x_check_expected_move (f) 8321x_check_expected_move (f, expected_left, expected_top)
8306 struct frame *f; 8322 struct frame *f;
8323 int expected_left;
8324 int expected_top;
8307{ 8325{
8308 if (FRAME_X_OUTPUT (f)->check_expected_move) 8326 int count = 0, current_left = 0, current_top = 0;
8309 { 8327
8310 int expect_top = FRAME_X_OUTPUT (f)->expected_top; 8328 /* x_real_positions returns the left and top offsets of the outermost
8311 int expect_left = FRAME_X_OUTPUT (f)->expected_left; 8329 window manager window around the frame. */
8312 8330
8313 if (expect_top != f->top_pos || expect_left != f->left_pos) 8331 x_real_positions (f, &current_left, &current_top);
8332
8333 if (current_left != expected_left || current_top != expected_top)
8314 { 8334 {
8335 /* It's a "Type A" window manager. */
8336
8337 int adjusted_left;
8338 int adjusted_top;
8339
8315 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A; 8340 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
8316 FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos; 8341 FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
8317 FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos; 8342 FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
8343
8344 /* Now fix the mispositioned frame's location. */
8318 8345
8319 f->left_pos = expect_left; 8346 adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
8320 f->top_pos = expect_top; 8347 adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
8321 x_set_offset (f, expect_left, expect_top, 0); 8348
8349 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8350 adjusted_left, adjusted_top);
8351
8352 x_sync_with_move (f, expected_left, expected_top, 0);
8322 } 8353 }
8323 else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN) 8354 else
8355 /* It's a "Type B" window manager. We don't have to adjust the
8356 frame's position. */
8357
8324 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B; 8358 FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
8359}
8360
8361
8362/* Wait for XGetGeometry to return up-to-date position information for a
8363 recently-moved frame. Call this immediately after calling XMoveWindow.
8364 If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
8365 frame has been moved to, so we use a fuzzy position comparison instead
8366 of an exact comparison. */
8367
8368static void
8369x_sync_with_move (f, left, top, fuzzy)
8370 struct frame *f;
8371 int left, top, fuzzy;
8372{
8373 int count = 0;
8374
8375 while (count++ < 50)
8376 {
8377 int current_left = 0, current_top = 0;
8378
8379 /* In theory, this call to XSync only needs to happen once, but in
8380 practice, it doesn't seem to work, hence the need for the surrounding
8381 loop. */
8382
8383 XSync (FRAME_X_DISPLAY (f), False);
8384 x_real_positions (f, &current_left, &current_top);
8385
8386 if (fuzzy)
8387 {
8388 /* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
8389 pixels. */
8325 8390
8326 /* Just do this once */ 8391 if (abs (current_left - left) <= 10 && abs (current_top - top) <= 40)
8327 FRAME_X_OUTPUT (f)->check_expected_move = 0; 8392 return;
8328 } 8393 }
8394 else if (current_left == left && current_top == top)
8395 return;
8396 }
8397
8398 /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
8399 will then return up-to-date position info. */
8400
8401 wait_reading_process_output (0, 500000, 0, 0, Qnil, NULL, 0);
8329} 8402}
8330 8403
8331 8404
diff --git a/src/xterm.h b/src/xterm.h
index 797c8b30e0f..10a9aaa2961 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -637,18 +637,14 @@ struct x_output
637 FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */ 637 FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */
638 int focus_state; 638 int focus_state;
639 639
640 /* The latest move we made to FRAME_OUTER_WINDOW. Saved so we can
641 compensate for type A WMs (see wm_type in dpyinfo above). */
642 int expected_top;
643 int expected_left;
644
645 /* The offset we need to add to compensate for type A WMs. */ 640 /* The offset we need to add to compensate for type A WMs. */
646 int move_offset_top; 641 int move_offset_top;
647 int move_offset_left; 642 int move_offset_left;
648 643
649 /* Nonzero if we have made a move and needs to check if the WM placed us 644 /* The frame's left/top offsets before we call XMoveWindow. See
650 at the right position. */ 645 x_check_expected_move. */
651 int check_expected_move; 646 int left_before_move;
647 int top_before_move;
652}; 648};
653 649
654#define No_Cursor (None) 650#define No_Cursor (None)