Yet another attempt at fixing bugs #14602, 14630, 14669.
authorEli Zaretskii <eliz@gnu.org>
Thu, 20 Jun 2013 17:36:24 +0000 (20:36 +0300)
committerEli Zaretskii <eliz@gnu.org>
Thu, 20 Jun 2013 17:36:24 +0000 (20:36 +0300)
 src/w32fns.c (w32_wnd_proc): Don't compute the header line and mode
 line dimensions here, to avoid race conditions with the main
 thread.
 src/w32term.c (w32_draw_window_cursor): Compute the header line and
 mode line dimensions here.
 <w32_system_caret_window, w32_system_caret_hdr_height>:
 <w32_system_caret_mode_height>: New variables.
 src/w32term.h: Declare them.

src/ChangeLog
src/w32fns.c
src/w32term.c
src/w32term.h

index 82856eb..2aeccc2 100644 (file)
@@ -1,3 +1,16 @@
+2013-06-20  Eli Zaretskii  <eliz@gnu.org>
+
+       * w32fns.c (w32_wnd_proc): Don't compute the header line and mode
+       line dimensions here, to avoid race conditions with the main
+       thread.  (Bug#14062, bug#14630, bug#14669)
+
+       * w32term.c (w32_draw_window_cursor): Compute the header line and
+       mode line dimensions here.
+       <w32_system_caret_window, w32_system_caret_hdr_height>:
+       <w32_system_caret_mode_height>: New variables.
+
+       * w32term.h: Declare them.
+
 2013-06-20  Paul Eggert  <eggert@cs.ucla.edu>
 
        * alloc.c (die): Move "assertion failed" string here ...
index 970c44c..46fb02d 100644 (file)
@@ -3175,23 +3175,39 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
          HIMC context;
          struct window *w;
 
+         /* Implementation note: The code below does something that
+            one shouldn't do: it accesses the window object from a
+            separate thread, while the main (a.k.a. "Lisp") thread
+            runs and can legitimately delete and even GC it.  That is
+            why we are extra careful not to futz with a window that
+            is different from the one recorded when the system caret
+            coordinates were last modified.  That is also why we are
+            careful not to move the IME window if the window
+            described by W was deleted, as indicated by its buffer
+            field being reset to nil.  */
          f = x_window_to_frame (dpyinfo, hwnd);
          w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+         /* Punt if someone changed the frame's selected window
+            behind our back. */
+         if (w != w32_system_caret_window)
+           break;
 
          form.dwStyle = CFS_RECT;
          form.ptCurrentPos.x = w32_system_caret_x;
          form.ptCurrentPos.y = w32_system_caret_y;
 
          form.rcArea.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, 0);
-         form.rcArea.top = WINDOW_TOP_EDGE_Y (w);
-         if (BUFFERP (w->contents)
-             && FRAMEP (WINDOW_FRAME (w)))
-           form.rcArea.top += WINDOW_HEADER_LINE_HEIGHT (w);
+         form.rcArea.top = (WINDOW_TOP_EDGE_Y (w)
+                            + w32_system_caret_hdr_height);
          form.rcArea.right = (WINDOW_BOX_RIGHT_EDGE_X (w)
                               - WINDOW_RIGHT_MARGIN_WIDTH (w)
                               - WINDOW_RIGHT_FRINGE_WIDTH (w));
          form.rcArea.bottom = (WINDOW_BOTTOM_EDGE_Y (w)
-                               - WINDOW_MODE_LINE_HEIGHT (w));
+                               - w32_system_caret_mode_height);
+
+         /* Punt if the window was deleted behind our back.  */
+         if (!BUFFERP (w->contents))
+           break;
 
          context = get_ime_context_fn (hwnd);
 
index 617492e..d3174c6 100644 (file)
@@ -151,6 +151,9 @@ HWND w32_system_caret_hwnd;
 int w32_system_caret_height;
 int w32_system_caret_x;
 int w32_system_caret_y;
+struct window *w32_system_caret_window;
+int w32_system_caret_hdr_height;
+int w32_system_caret_mode_height;
 DWORD dwWindowsThreadId = 0;
 HANDLE hWindowsThread = NULL;
 DWORD dwMainThreadId = 0;
@@ -5328,6 +5331,9 @@ w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
          w32_system_caret_y
            = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
               + glyph_row->ascent - w->phys_cursor_ascent);
+         w32_system_caret_window = w;
+         w32_system_caret_hdr_height = WINDOW_HEADER_LINE_HEIGHT (w);
+         w32_system_caret_mode_height = WINDOW_MODE_LINE_HEIGHT (w);
 
          PostMessage (hwnd, WM_IME_STARTCOMPOSITION, 0, 0);
 
index be0b4a6..ace5875 100644 (file)
@@ -750,6 +750,9 @@ extern HWND w32_system_caret_hwnd;
 extern int w32_system_caret_height;
 extern int w32_system_caret_x;
 extern int w32_system_caret_y;
+extern struct window *w32_system_caret_window;
+extern int w32_system_caret_hdr_height;
+extern int w32_system_caret_mode_height;
 
 #ifdef _MSC_VER
 #ifndef EnumSystemLocales