Subject: bug#64440: closed (Re: bug#64440: 30.0.50; [PATCH] Highlight on non toolkit menu bar items)

From: [email-masked] (GNU bug Tracking System)
Date: Sat, 28 Oct 2023 05:28:02 +0000

Your bug report

#64440: 30.0.50; [PATCH] Highlight on non toolkit menu bar items

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
64440: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=64440
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#64440: 30.0.50; [PATCH] Highlight on non toolkit menu bar items
From: Po Lu <[email-masked]>
To: Eli Zaretskii <[email-masked]>
Cc: [email-masked], [email-masked], [email-masked]
Date: Sat, 28 Oct 2023 13:26:52 +0800
List-Id: <debbugs-submit.debbugs.gnu.org>

Now done, and thanks.

Subject: 30.0.50; [PATCH] Highlight on non toolkit menu bar items
From: Manuel Giraud <[email-masked]>
To: [email-masked]
Date: Mon, 03 Jul 2023 17:59:31 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

Hi,

Here is a set of patches to have highlighting on the menu bar items (for
the non toolkit build only).

The first patch is a bit "intrusive" because it adds a menu_bar_p
selector to 'window_from_coordinates'.  Maybe it is not needed and I
could drop this selector and make 'window_from_coordinates' return
f->menu_bar_window when the mouse is on it.

The second patch is the real meat and is modeled after other
"note_*_highlight" functions.  It seems to work as expected but now I
think I need to define another face (I'm using MENU_FACE_ID now so it is
not really visual) or maybe we should be able to propertize the menu bar
entries.  WDYT?

>From ceb818090de83fe216af3e9b6bcc198eba9188e3 Mon Sep 17 00:00:00 2001
From: Manuel Giraud <[email-masked]>
Date: Sat, 1 Jul 2023 21:19:06 +0200
Subject: [PATCH 1/2] Possibility to get enter event from menu_bar window

---
 src/haikuterm.c |  8 ++++----
 src/keyboard.c  |  2 +-
 src/msdos.c     |  2 +-
 src/pgtkterm.c  |  4 ++--
 src/w32inevt.c  |  2 +-
 src/w32term.c   |  8 ++++----
 src/window.c    | 20 ++++++++++++++++++--
 src/window.h    |  2 +-
 src/xdisp.c     |  4 ++--
 src/xterm.c     | 17 +++++++++--------
 10 files changed, 43 insertions(+), 26 deletions(-)

diff --git a/src/haikuterm.c b/src/haikuterm.c
index ed28a806ff2..0af9aa746a9 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -3472,7 +3472,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
 		if (!NILP (Vmouse_autoselect_window))
 		  {
 		    static Lisp_Object last_mouse_window;
-		    Lisp_Object window = window_from_coordinates (f, b->x, b->y, 0, 0, 0);
+		    Lisp_Object window = window_from_coordinates (f, b->x, b->y, 0, 0, 0, 0);
 
 		    if (WINDOWP (window)
 			&& !EQ (window, last_mouse_window)
@@ -3555,7 +3555,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
 		int x = b->x;
 		int y = b->y;
 
-		window = window_from_coordinates (f, x, y, 0, true, true);
+		window = window_from_coordinates (f, x, y, 0, true, true, true);
 		tab_bar_p = EQ (window, f->tab_bar_window);
 
 		if (tab_bar_p)
@@ -3573,7 +3573,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
 		int x = b->x;
 		int y = b->y;
 
-		window = window_from_coordinates (f, x, y, 0, true, true);
+		window = window_from_coordinates (f, x, y, 0, true, true, true);
 		tool_bar_p = (EQ (window, f->tool_bar_window)
 			      && (type != BUTTON_UP
 				  || f->last_tool_bar_item != -1));
@@ -3834,7 +3834,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
 
 	    BView_get_mouse (FRAME_HAIKU_VIEW (f), &x, &y);
 
-	    wheel_window = window_from_coordinates (f, x, y, 0, false, false);
+	    wheel_window = window_from_coordinates (f, x, y, 0, false, false, false);
 
 	    if (NILP (wheel_window))
 	      {
diff --git a/src/keyboard.c b/src/keyboard.c
index b61b1766856..4cc0c70b11e 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -5414,7 +5414,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
   int xret = 0, yret = 0;
   /* The window or frame under frame pixel coordinates (x,y)  */
   Lisp_Object window_or_frame = f
-    ? window_from_coordinates (f, mx, my, &part, true, true)
+    ? window_from_coordinates (f, mx, my, &part, true, true, true)
     : Qnil;
 #ifdef HAVE_WINDOW_SYSTEM
   bool tool_bar_p = false;
diff --git a/src/msdos.c b/src/msdos.c
index 75a39045cee..6e779ffb2e2 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -2655,7 +2655,7 @@ dos_rawgetc (void)
 	      static Lisp_Object last_mouse_window;
 
 	      mouse_window = window_from_coordinates
-		(SELECTED_FRAME (), mouse_last_x, mouse_last_y, 0, 0, 0);
+		(SELECTED_FRAME (), mouse_last_x, mouse_last_y, 0, 0, 0, 0);
 	      /* A window will be selected only when it is not
 		 selected now, and the last mouse movement event was
 		 not in it.  A minibuffer window will be selected iff
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index dc2d6477bb5..788d4a7bdfb 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -5891,7 +5891,7 @@ motion_notify_event (GtkWidget *widget, GdkEvent *event,
 	{
 	  static Lisp_Object last_mouse_window;
 	  Lisp_Object window = window_from_coordinates
-	    (f, event->motion.x, event->motion.y, 0, false, false);
+	    (f, event->motion.x, event->motion.y, 0, false, false, false);
 
 	  /* A window will be autoselected only when it is not
 	     selected now and the last mouse movement event was
@@ -6044,7 +6044,7 @@ button_event (GtkWidget *widget, GdkEvent *event,
 	  int x = event->button.x;
 	  int y = event->button.y;
 
-	  window = window_from_coordinates (f, x, y, 0, true, true);
+	  window = window_from_coordinates (f, x, y, 0, true, true, true);
 	  tab_bar_p = EQ (window, f->tab_bar_window);
 
 	  if (tab_bar_p)
diff --git a/src/w32inevt.c b/src/w32inevt.c
index 29717954cfd..630a9f4e5fb 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -496,7 +496,7 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
 	    if (!NILP (Vmouse_autoselect_window))
 	      {
 		Lisp_Object mouse_window = window_from_coordinates (f, mx, my,
-								    0, 0, 0);
+								    0, 0, 0, 0);
 		/* A window will be selected only when it is not
 		   selected now, and the last mouse movement event was
 		   not in it.  A minibuffer window will be selected iff
diff --git a/src/w32term.c b/src/w32term.c
index 57dc6b465e4..9c5a298a645 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -3376,7 +3376,7 @@ w32_construct_mouse_wheel (struct input_event *result, W32Msg *msg,
       if (w32_wheel_scroll_lines == UINT_MAX)
 	{
 	  Lisp_Object window = window_from_coordinates (f, p.x, p.y, NULL,
-							false, false);
+							false, false, false);
 	  if (!WINDOWP (window))
 	    {
 	      result->kind = NO_EVENT;
@@ -5335,7 +5335,7 @@ w32_read_socket (struct terminal *terminal,
 		{
 		  static Lisp_Object last_mouse_window;
 		  Lisp_Object window = window_from_coordinates
-		    (f, LOWORD (msg.msg.lParam), HIWORD (msg.msg.lParam), 0, 0, 0);
+		    (f, LOWORD (msg.msg.lParam), HIWORD (msg.msg.lParam), 0, 0, 0, 0);
 
 		  /* Window will be selected only when it is not
 		     selected now and last mouse movement event was
@@ -5407,7 +5407,7 @@ w32_read_socket (struct terminal *terminal,
 		    int x = XFIXNAT (inev.x);
 		    int y = XFIXNAT (inev.y);
 
-                    window = window_from_coordinates (f, x, y, 0, 1, 1);
+                    window = window_from_coordinates (f, x, y, 0, 1, 1, 1);
 
                     if (EQ (window, f->tab_bar_window))
                       {
@@ -5435,7 +5435,7 @@ w32_read_socket (struct terminal *terminal,
 		    int x = XFIXNAT (inev.x);
 		    int y = XFIXNAT (inev.y);
 
-                    window = window_from_coordinates (f, x, y, 0, 1, 1);
+                    window = window_from_coordinates (f, x, y, 0, 1, 1, 1);
 
                     if (EQ (window, f->tool_bar_window)
 			/* Make sure the tool bar was previously
diff --git a/src/window.c b/src/window.c
index 2a0c62f5d53..af7dcfdd423 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1680,7 +1680,8 @@ check_window_containing (struct window *w, void *user_data)
 
 Lisp_Object
 window_from_coordinates (struct frame *f, int x, int y,
-			 enum window_part *part, bool tab_bar_p, bool tool_bar_p)
+			 enum window_part *part, bool menu_bar_p,
+			 bool tab_bar_p, bool tool_bar_p)
 {
   Lisp_Object window;
   struct check_window_data cw;
@@ -1693,6 +1694,21 @@ window_from_coordinates (struct frame *f, int x, int y,
   cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
   foreach_window (f, check_window_containing, &cw);
 
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_MENU_BAR)
+  /* If not found above, see if it's in the menu bar window, if a menu
+     bar exists.  */
+  if (NILP (window)
+      && menu_bar_p
+      && WINDOWP (f->menu_bar_window)
+      && WINDOW_TOTAL_LINES (XWINDOW (f->menu_bar_window)) > 0
+      && (coordinates_in_window (XWINDOW (f->menu_bar_window), x, y)
+	  != ON_NOTHING))
+    {
+      *part = ON_TEXT;
+      window = f->menu_bar_window;
+    }
+#endif
+
 #if defined (HAVE_WINDOW_SYSTEM)
   /* If not found above, see if it's in the tab bar window, if a tab
      bar exists.  */
@@ -1746,7 +1762,7 @@ DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
 				   + FRAME_INTERNAL_BORDER_WIDTH (f)),
 				  (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
 				   + FRAME_INTERNAL_BORDER_WIDTH (f)),
-				  0, false, false);
+				  0, false, false, false);
 }
 
 ptrdiff_t
diff --git a/src/window.h b/src/window.h
index 2f793ebe438..4f4a0a79216 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1092,7 +1092,7 @@ #define WINDOW_TEXT_TO_FRAME_PIXEL_X(W, X)	\
 
 extern Lisp_Object make_window (void);
 extern Lisp_Object window_from_coordinates (struct frame *, int, int,
-                                            enum window_part *, bool, bool);
+                                            enum window_part *, bool, bool, bool);
 extern void resize_frame_windows (struct frame *, int, bool);
 extern void restore_window_configuration (Lisp_Object);
 extern void delete_all_child_windows (Lisp_Object);
diff --git a/src/xdisp.c b/src/xdisp.c
index 85ece901111..4c02a217cef 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2739,7 +2739,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
       goto virtual_glyph;
     }
   else if (!f->glyphs_initialized_p
-	   || (window = window_from_coordinates (f, gx, gy, &part, false, false),
+	   || (window = window_from_coordinates (f, gx, gy, &part, false, false, false),
 	       NILP (window)))
     {
       width = FRAME_SMALLEST_CHAR_WIDTH (f);
@@ -35124,7 +35124,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
     return;
 
   /* Which window is that in?  */
-  window = window_from_coordinates (f, x, y, &part, true, true);
+  window = window_from_coordinates (f, x, y, &part, true, true, true);
 
   /* If displaying active text in another window, clear that.  */
   if (! EQ (window, hlinfo->mouse_face_window)
diff --git a/src/xterm.c b/src/xterm.c
index f84eaeb8cbd..e58e6276aae 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -20925,7 +20925,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		  }
 
 		Lisp_Object window = window_from_coordinates
-		  (f, xmotion.x, xmotion.y, 0, false, false);
+		  (f, xmotion.x, xmotion.y, 0, false, false, false);
 
 		/* A window will be autoselected only when it is not
 		   selected now and the last mouse movement event was
@@ -21656,7 +21656,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                 int x = event->xbutton.x;
                 int y = event->xbutton.y;
 
-                window = window_from_coordinates (f, x, y, 0, true, true);
+                window = window_from_coordinates (f, x, y, 0, true, true, true);
                 tab_bar_p = EQ (window, f->tab_bar_window);
 
                 if (tab_bar_p)
@@ -21677,7 +21677,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                 int x = event->xbutton.x;
                 int y = event->xbutton.y;
 
-                window = window_from_coordinates (f, x, y, 0, true, true);
+                window = window_from_coordinates (f, x, y, 0, true, true, true);
                 tool_bar_p = (EQ (window, f->tool_bar_window)
 			      && (event->xbutton.type != ButtonRelease
 				  || f->last_tool_bar_item != -1));
@@ -22398,7 +22398,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 			    continue;
 
 			  window = window_from_coordinates (f, real_x, real_y, NULL,
-							    false, false);
+							    false, false, false);
 
 			  if (WINDOWP (window))
 			    scroll_height = XWINDOW (window)->pixel_height;
@@ -22841,7 +22841,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 			  || !NILP (focus_follows_mouse)))
 		    {
 		      static Lisp_Object last_mouse_window;
-		      Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false);
+		      Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false,
+								    false);
 
 		      /* A window will be autoselected only when it is not
 			 selected now and the last mouse movement event was
@@ -23419,7 +23420,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		      int x = bv.x;
 		      int y = bv.y;
 
-		      window = window_from_coordinates (f, x, y, 0, true, true);
+		      window = window_from_coordinates (f, x, y, 0, true, true, true);
 		      tab_bar_p = EQ (window, f->tab_bar_window);
 
 		      if (tab_bar_p)
@@ -23440,7 +23441,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		      int x = bv.x;
 		      int y = bv.y;
 
-		      window = window_from_coordinates (f, x, y, 0, true, true);
+		      window = window_from_coordinates (f, x, y, 0, true, true, true);
 		      /* Ignore button release events if the mouse
 			 wasn't previously pressed on the tool bar.
 			 We do this because otherwise selecting some
@@ -24300,7 +24301,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		  int x = xev->event_x;
 		  int y = xev->event_y;
 
-		  window = window_from_coordinates (f, x, y, 0, true, true);
+		  window = window_from_coordinates (f, x, y, 0, true, true, true);
 		  /* Ignore button release events if the mouse
 		     wasn't previously pressed on the tool bar.
 		     We do this because otherwise selecting some
-- 
2.40.0

>From d5ddf8e04d06730917f94cb7d2fcb026c4437788 Mon Sep 17 00:00:00 2001
From: Manuel Giraud <[email-masked]>
Date: Mon, 3 Jul 2023 17:35:06 +0200
Subject: [PATCH 2/2] Highlight on non toolkit menu bar items

* src/xdisp.c (get_menu_bar_item, note_menu_bar_highlight): New
functions to highlight item in the menu-bar.
(note_mouse_highlight): Use it.
---
 src/xdisp.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 126 insertions(+)

diff --git a/src/xdisp.c b/src/xdisp.c
index 4c02a217cef..25b33e3a8c4 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -13859,6 +13859,122 @@ update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
   return hooks_run;
 }
 
+/* Get information about the menu-bar item at position X/Y on frame F.
+   Return menu-bar's item char position in H_START/H_END and pixel
+   position in X_START/X_END.  Value is
+
+   -1	if X/Y is not on a menu-bar item
+   0	if X/Y is on the same item that was highlighted before.
+   1	otherwise.  */
+
+static int
+get_menu_bar_item (struct frame *f, int x, int y, int *h_start, int *h_end,
+		   int *x_start, int *x_end, int *vpos)
+{
+  Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+  struct window *w = XWINDOW (f->menu_bar_window);
+  struct glyph_row *row;
+  int dummy;
+  Lisp_Object items;
+  int i;
+
+  /* Find glyph's hpos and vpos under X/Y.  */
+  if (x_y_to_hpos_vpos (w, x, y, h_start, vpos, NULL, NULL, &dummy) == NULL)
+    return -1;
+
+  /* Compute h_start and h_end for this menu bar item.  */
+  items = FRAME_MENU_BAR_ITEMS (f);
+  for (i = 0; i < ASIZE (items); i += 4)
+    {
+      Lisp_Object pos, string;
+      string = AREF (items, i + 1);
+      pos = AREF (items, i + 3);
+      if (NILP (string))
+	return -1;
+      if (*h_start >= XFIXNUM (pos)
+	  && *h_start < XFIXNUM (pos) + SCHARS (string))
+	{
+	  *h_start = XFIXNUM (pos);
+	  *h_end = *h_start + SCHARS (string);
+	  break;
+	}
+    }
+
+  /* Convert to pixels bounds.  */
+  row = MATRIX_ROW (w->current_matrix, *vpos);
+  *x_start = 0;
+  for (i = 0; i < *h_start; ++i)
+    *x_start += row->glyphs[TEXT_AREA][i].pixel_width;
+
+  *x_end = *x_start;
+  for (i = *h_start; i < *h_end; ++i)
+    *x_end += row->glyphs[TEXT_AREA][i].pixel_width;
+
+  /* Is mouse on the highlighted item?  */
+  if (EQ (f->menu_bar_window, hlinfo->mouse_face_window)
+      && *vpos >= hlinfo->mouse_face_beg_row
+      && *vpos <= hlinfo->mouse_face_end_row
+      && (*vpos > hlinfo->mouse_face_beg_row
+	  || *h_start >= hlinfo->mouse_face_beg_col)
+      && (*vpos < hlinfo->mouse_face_end_row
+	  || *h_end < hlinfo->mouse_face_end_col
+	  || hlinfo->mouse_face_past_end))
+    return 0;
+
+  return 1;
+}
+
+/* Possibly highlight a menu-bar item on frame F when mouse moves to
+   menu-bar window-relative coordinates X/Y.  Called from
+   note_mouse_highlight.  */
+
+static void
+note_menu_bar_highlight (struct frame *f, int x, int y)
+{
+  Lisp_Object window = f->menu_bar_window;
+  Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+  int h_start, h_end, vpos, x_start, x_end;
+  int rc;
+
+  /* Function note_mouse_highlight is called with negative X/Y
+     values when mouse moves outside of the frame.  */
+  if (x <= 0 || y <= 0)
+    {
+      clear_mouse_face (hlinfo);
+      return;
+    }
+
+  h_start = h_end = 0;
+  rc = get_menu_bar_item (f, x, y, &h_start, &h_end, &x_start, &x_end, &vpos);
+  if (rc < 0)
+    {
+      /* Not on menu-bar item.  */
+      clear_mouse_face (hlinfo);
+      return;
+    }
+  else if (rc == 0)
+    /* On same menu-bar item as before.  */
+    return;
+
+  if (!NILP (Vmouse_highlight))
+    {
+      /* Record this as the current active region.  */
+      hlinfo->mouse_face_beg_col = h_start;
+      hlinfo->mouse_face_beg_row = vpos;
+      hlinfo->mouse_face_beg_x = x_start;
+      hlinfo->mouse_face_past_end = false;
+
+      hlinfo->mouse_face_end_col = h_end;
+      hlinfo->mouse_face_end_row = vpos;
+      hlinfo->mouse_face_end_x = x_end;
+      hlinfo->mouse_face_window = window;
+      hlinfo->mouse_face_face_id = MENU_FACE_ID;
+
+      /* Display it as active.  */
+      show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
+    }
+}
+
 
 
 /***********************************************************************
@@ -35223,6 +35339,16 @@ note_mouse_highlight (struct frame *f, int x, int y)
   w = XWINDOW (window);
   frame_to_window_pixel_xy (w, &x, &y);
 
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_MENU_BAR)
+  /* Handle menu-bar window differently since it doesn't display a
+     buffer.  */
+  if (EQ (window, f->menu_bar_window))
+    {
+      note_menu_bar_highlight (f, x, y);
+      return;
+    }
+#endif
+
 #if defined (HAVE_WINDOW_SYSTEM)
   /* Handle tab-bar window differently since it doesn't display a
      buffer.  */
-- 
2.40.0

In GNU Emacs 30.0.50 (build 1, x86_64-unknown-openbsd7.3, cairo version
 1.17.8) of 2023-07-03 built on computer
Repository revision: ceb818090de83fe216af3e9b6bcc198eba9188e3
Repository branch: mgi/menu
Windowing system distributor 'The X.Org Foundation', version 11.0.12101006
System Description: OpenBSD computer 7.3 GENERIC.MP#1125 amd64

Configured using:
 'configure --prefix=/home/manuel/emacs --bindir=/home/manuel/bin
 --with-x-toolkit=no --with-toolkit-scroll-bars=no --without-sound
 --without-compress-install CPPFLAGS=-I/usr/local/include
 LDFLAGS=-L/usr/local/lib'

Configured features:
CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG JSON
LCMS2 LIBOTF LIBXML2 MODULES NOTIFY KQUEUE OLDXMENU PDUMPER PNG RSVG
SQLITE3 THREADS TIFF TREE_SITTER WEBP X11 XDBE XIM XINPUT2 XPM ZLIB

Important settings:
  value of $LC_ALL: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Dired by name

Minor modes in effect:
  global-git-commit-mode: t
  magit-auto-revert-mode: t
  gnus-dired-mode: t
  display-time-mode: t
  display-battery-mode: t
  server-mode: t
  shell-dirtrack-mode: t
  override-global-mode: t
  repeat-mode: t
  desktop-save-mode: t
  global-eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  buffer-read-only: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
/home/manuel/.el/nov hides /home/manuel/.emacs.d/elpa/nov-20230421.1548/nov
/home/manuel/.emacs.d/elpa/ef-themes-1.1.1/theme-loaddefs hides /home/manuel/emacs/share/emacs/30.0.50/lisp/theme-loaddefs

Features:
(shadow sort mail-extr emacsbug whitespace magit-patch misearch
multi-isearch pulse magit-extras face-remap magit-submodule
magit-obsolete magit-blame magit-stash magit-reflog magit-bisect
magit-push magit-pull magit-fetch magit-clone magit-remote magit-commit
magit-sequence magit-notes magit-worktree magit-tag magit-merge
magit-branch magit-reset magit-files magit-refs magit-status magit
magit-repos magit-apply magit-wip magit-log which-func magit-diff
smerge-mode diff git-commit log-edit add-log magit-core magit-autorevert
magit-margin magit-transient magit-process with-editor magit-mode
transient magit-git magit-section magit-utils dash org-agenda
emacs-news-mode org-indent css-mode sgml-mode facemenu imenu vc-cvs
vc-rcs log-view pcvs-util make-mode pascal vc-hg conf-mode org-element
org-persist org-id org-refile avl-tree oc-basic ol-eww eww url-queue
mm-url ol-rmail ol-mhe ol-irc ol-info ol-gnus nnselect ol-docview
doc-view jka-compr image-mode exif ol-bibtex bibtex ol-bbdb ol-w3m
ol-doi org-link-doi org ob ob-tangle ob-ref ob-lob ob-table ob-exp
org-macro org-src ob-comint org-pcomplete org-list org-footnote
org-faces org-entities ob-emacs-lisp ob-core ob-eval org-cycle org-table
ol org-fold org-fold-core org-keys oc org-loaddefs org-version
org-compat org-macs view sh-script smie treesit executable gnus-dired
paredit mule-util vc-git diff-mode vc-svn vc vc-dispatcher bug-reference
time battery cus-load exwm-randr xcb-randr exwm-config ido exwm
exwm-input xcb-keysyms xcb-xkb exwm-manage exwm-floating xcb-cursor
xcb-render exwm-layout exwm-workspace exwm-core xcb-ewmh xcb-icccm xcb
xcb-xproto xcb-types xcb-debug server modus-operandi-theme modus-themes
zone speed-type url-http url-auth url-gw nsm compat ytdious mingus
libmpdee reporter edebug debug backtrace detached-init detached
autorevert filenotify transmission color calc-bin calc-ext calc
calc-loaddefs rect calc-macs supercite regi ebdb-message ebdb-gnus
gnus-msg gnus-art mm-uu mml2015 mm-view mml-smime smime gnutls dig
gnus-sum shr pixel-fill kinsoku url-file svg dom gnus-group gnus-undo
gnus-start gnus-dbus gnus-cloud nnimap nnmail mail-source utf7 nnoo
gnus-spec gnus-int gnus-range message sendmail yank-media puny rfc822
mml mml-sec epa epg rfc6068 epg-config mm-decode mm-bodies mm-encode
mail-parse rfc2231 rfc2047 rfc2045 ietf-drums gmm-utils mailheader
gnus-win gnus nnheader gnus-util mail-utils range mm-util mail-prsvr
wid-edit ebdb-mua ebdb-com crm ebdb-format ebdb mailabbrev eieio-opt
speedbar ezimage dframe find-func eieio-base pcase timezone icalendar
visual-basic-mode cl web-mode derived disp-table erlang-start
smart-tabs-mode skeleton cc-mode cc-fonts cc-guess cc-menus cc-cmds
cc-styles cc-align cc-engine cc-vars cc-defs slime-asdf grep slime-tramp
tramp rx tramp-loaddefs trampver tramp-integration files-x tramp-compat
xdg shell pcomplete parse-time iso8601 time-date format-spec slime-fancy
slime-indentation slime-cl-indent cl-indent slime-trace-dialog
slime-fontifying-fu slime-package-fu slime-references
slime-compiler-notes-tree advice slime-scratch slime-presentations
bridge slime-macrostep macrostep slime-mdot-fu slime-enclosing-context
slime-fuzzy slime-fancy-trace slime-fancy-inspector slime-c-p-c
slime-editing-commands slime-autodoc slime-repl slime-parse slime
apropos compile text-property-search etags fileloop generator xref
project arc-mode archive-mode noutline outline icons pp comint ansi-osc
ansi-color ring hyperspec thingatpt slime-autoloads edmacro kmacro
use-package-bind-key bind-key appt diary-lib diary-loaddefs cal-menu
calendar cal-loaddefs dired-x dired-aux dired dired-loaddefs
notifications dbus xml cl-extra help-mode use-package-core repeat
easy-mmode desktop frameset debbugs-autoloads detached-autoloads
ebdb-autoloads ef-themes-autoloads exwm-autoloads hyperbole-autoloads
magit-autoloads git-commit-autoloads finder-inf magit-section-autoloads
dash-autoloads nov-autoloads esxml-autoloads kv-autoloads osm-autoloads
paredit-autoloads rust-mode-autoloads speed-type-autoloads
transmission-autoloads visual-fill-column-autoloads
with-editor-autoloads info compat-autoloads ytdious-autoloads package
browse-url url url-proxy url-privacy url-expand url-methods url-history
url-cookie generate-lisp-file url-domsuf url-util mailcap url-handlers
url-parse auth-source cl-seq eieio eieio-core cl-macs password-cache
json subr-x map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs
cl-lib rmc iso-transl tooltip cconv eldoc paren electric uniquify
ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win
term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode lisp-mode prog-mode register
page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer nadvice seq simple cl-generic indonesian philippine
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads dbusbind kqueue lcms2 dynamic-setting system-font-setting
font-render-setting cairo xinput2 x multi-tty make-network-process
emacs)

Memory information:
((conses 16 1679605 226472) (symbols 48 60222 5)
 (strings 32 194847 17038) (string-bytes 1 6134459)
 (vectors 16 117354) (vector-slots 8 2341200 178993)
 (floats 8 591 3029) (intervals 56 239858 3338) (buffers 984 165))

-- 
Manuel Giraud