diff options
| author | Jan Djärv | 2006-06-16 12:12:27 +0000 |
|---|---|---|
| committer | Jan Djärv | 2006-06-16 12:12:27 +0000 |
| commit | d692a3d5c580f15bc5968a034286922c1a1bf423 (patch) | |
| tree | 69a256c12c72ecc834a97d2522026b47c5e25884 /src | |
| parent | db600ab1dbf2f0c84e6b82bef80dec3f68326637 (diff) | |
| download | emacs-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/ChangeLog | 9 | ||||
| -rw-r--r-- | src/xterm.c | 139 | ||||
| -rw-r--r-- | src/xterm.h | 12 |
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 @@ | |||
| 1 | 2006-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 | |||
| 1 | 2006-06-16 Kim F. Storm <storm@cua.dk> | 10 | 2006-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 *)); |
| 356 | static void x_check_fullscreen P_ ((struct frame *)); | 356 | static void x_check_fullscreen P_ ((struct frame *)); |
| 357 | static void x_check_expected_move P_ ((struct frame *)); | 357 | static void x_check_expected_move P_ ((struct frame *, int, int)); |
| 358 | static void x_sync_with_move P_ ((struct frame *, int, int, int)); | ||
| 358 | static int handle_one_xevent P_ ((struct x_display_info *, XEvent *, | 359 | static int handle_one_xevent P_ ((struct x_display_info *, XEvent *, |
| 359 | int *, struct input_event *)); | 360 | int *, struct input_event *)); |
| 360 | static SIGTYPE x_connection_closed P_ ((Display *, char *)); | 361 | static 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 | |||
| 8304 | static void | 8320 | static void |
| 8305 | x_check_expected_move (f) | 8321 | x_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, ¤t_left, ¤t_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 | |||
| 8368 | static void | ||
| 8369 | x_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, ¤t_left, ¤t_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) |