Subject: bug#73838: 31.0.50; Problems in note_mouse_highlight if -nw

From: Gerd Möllmann <[email-masked]>
Date: Wed, 16 Oct 2024 16:19:53 +0200

Gerd Möllmann <[email-masked]> writes:

> This is with master fdac10b216f7b47e2eea129d2a96807a0c2055f3 on
> macOS, built with ASAN.
>
>   $ /Users/gerd/emacs/savannah/master/configure --cache-file /var/folders/1d/k_6t25f94sl83szqbf8gpkrh0000gn/T//config.cache.master --without-tree-sitter --with-native-compilation=no CC=clang 'LDFLAGS=-fsanitize=address -fno-omit-frame-pointer' 'CFLAGS=-Wgnu-imaginary-constant -Wunused-result -g -fno-omit-frame-pointer -g -O0 -fsanitize=address -fno-omit-frame-pointer'
>
> Recipe:
>
> - emacs -nw -q
> - M-x xterm-mouse-mode RET
> - M-x make TAB
> - Move the move over the completion candidates
>
> => ASAN abort in note_mouse_highlight, xdisp.c:36108
>
> The line number may vary. Looking at that in the debugger, I see
>
> 	default:
> 	  /* This should not happen.  */
> 	  if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
> 	    cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
>
> nsterm.h defines FRAME_OUTPUT_DATA(f) as
>
>   #define FRAME_OUTPUT_DATA(f) ((f)->output_data.ns)
>
> and since we are not in a GUI frame, this is no good. Analogous defines
> are in xterm.h etc., so the problem is not limited to macOS.
>
> (I built with ASAN because I observe weird things with mouse stuff in
> conjunction with tty child frames, and wanted to check what's up with
> that in master.)

I'd like to propose a change like in the attached patch (from my tty
child frames branch). It fixes the case I mentioned above.

diff --git a/src/nsterm.h b/src/nsterm.h
index 256a233558e..0343064fe5b 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -1020,10 +1020,18 @@ #define KEY_NS_SHOW_PREFS              ((1<<28)|(0<<16)|14)
   int unused;
 };
 
+INLINE struct ns_output *
+frame_output_data (struct frame *f)
+{
+  eassert (FRAME_NS_P (f));
+  return f->output_data.ns;
+}
+
+/* xdisp.c checks for this macro being #defined.  */
+#define FRAME_OUTPUT_DATA(f) frame_output_data (f)
 
 /* This gives the ns_display_info structure for the display F is on.  */
 #define FRAME_DISPLAY_INFO(f) ((f)->output_data.ns->display_info)
-#define FRAME_OUTPUT_DATA(f) ((f)->output_data.ns)
 #define FRAME_NS_WINDOW(f) ((f)->output_data.ns->window_desc)
 #define FRAME_NATIVE_WINDOW(f) FRAME_NS_WINDOW (f)
 
diff --git a/src/xdisp.c b/src/xdisp.c
index 25184e8d186..8321702b760 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -36106,7 +36106,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
 #ifdef HAVE_WINDOW_SYSTEM
   /* If the cursor is on the internal border of FRAME and FRAME's
      internal border is draggable, provide some visual feedback.  */
-  if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
+  if (FRAME_WINDOW_P (f)
+      && FRAME_INTERNAL_BORDER_WIDTH (f) > 0
       && !NILP (get_frame_param (f, Qdrag_internal_border)))
     {
       enum internal_border_part part = frame_internal_border_part (f, x, y);
@@ -36170,7 +36171,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
      buffer.  */
   if (EQ (window, f->menu_bar_window))
     {
-      cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
+      if (FRAME_WINDOW_P (f))
+	cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
       goto set_cursor;
     }
 #endif
@@ -36181,10 +36183,13 @@ note_mouse_highlight (struct frame *f, int x, int y)
   if (EQ (window, f->tab_bar_window))
     {
       note_tab_bar_highlight (f, x, y);
-      if (tab_bar__dragging_in_progress)
-	  cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
-      else
-	cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
+      if (FRAME_WINDOW_P (f))
+	{
+	  if (tab_bar__dragging_in_progress)
+	    cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
+	  else
+	    cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
+	}
       goto set_cursor;
     }
   else
@@ -36203,7 +36208,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
   if (EQ (window, f->tool_bar_window))
     {
       note_tool_bar_highlight (f, x, y);
-      cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
+      if (FRAME_WINDOW_P (f))
+	cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
       goto set_cursor;
     }
 #endif
@@ -36217,7 +36223,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
 #ifdef HAVE_WINDOW_SYSTEM
       if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
 	{
-	  cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
+	  if (FRAME_WINDOW_P (f))
+	    cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
 	  /* Show non-text cursor (Bug#16647).  */
 	  goto set_cursor;
 	}
@@ -36229,13 +36236,15 @@ note_mouse_highlight (struct frame *f, int x, int y)
 #ifdef HAVE_WINDOW_SYSTEM
   if (part == ON_VERTICAL_BORDER)
     {
-      cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
+      if (FRAME_WINDOW_P (f))
+	cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
       help_echo_string = build_string ("drag-mouse-1: resize");
       goto set_cursor;
     }
   else if (part == ON_RIGHT_DIVIDER)
     {
-      cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
+      if (FRAME_WINDOW_P (f))
+	cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
       help_echo_string = build_string ("drag-mouse-1: resize");
       goto set_cursor;
     }
@@ -36244,7 +36253,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
 	|| minibuf_level
 	|| NILP (Vresize_mini_windows))
       {
-	cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
+	if (FRAME_WINDOW_P (f))
+	  cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
 	help_echo_string = build_string ("drag-mouse-1: resize");
 	goto set_cursor;
       }
@@ -36252,13 +36262,17 @@ note_mouse_highlight (struct frame *f, int x, int y)
       cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
   else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
     {
-      cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
+      if (FRAME_WINDOW_P (f))
+	cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
       note_fringe_highlight (f, window, x, y, part);
     }
   else if (part == ON_VERTICAL_SCROLL_BAR
 	   || part == ON_HORIZONTAL_SCROLL_BAR)
-    cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
-  else
+    {
+      if (FRAME_WINDOW_P (f))
+	cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
+    }
+  else if (FRAME_WINDOW_P (f))
     cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
 #endif