]> git.eshelyaron.com Git - emacs.git/commitdiff
Colored menu highlight in Lucid backend
authorManuel Giraud <manuel@ledu-giraud.fr>
Mon, 11 Jul 2022 09:14:08 +0000 (11:14 +0200)
committerPo Lu <luangruo@yahoo.com>
Sat, 16 Jul 2022 10:59:09 +0000 (18:59 +0800)
* lwlib/xlwmenuP.h:
* lwlib/xlwmenu.h:
* lwlib/xlwmenu.c: Introduce resources to handle colored highlighting
of menu entries.
* doc/emacs/xresources.texi (Lucid Resources): Documentation.

doc/emacs/xresources.texi
etc/NEWS
lwlib/xlwmenu.c
lwlib/xlwmenu.h
lwlib/xlwmenuP.h

index 2c2700bc15b9487f22a10a629f464863f81ffd28..8915d2025ba46728c1dee75ef507b73c74a6dd99 100644 (file)
@@ -449,6 +449,12 @@ Foreground color for a selected item.
 Foreground color.
 @item disabledForeground
 Foreground color for a disabled menu item.
+@item highlightForeground
+Foreground color for a menu item highlighted by the mouse or key
+navigation.
+@item highlightBackground
+Background color for a menu item highlighted by the mouse or key
+navigation.
 @ifnottex
 @item horizontalSpacing
 Horizontal spacing in pixels between items.  Default is 3.
index d99d0a008ef394b1b571bc6c3c46b861aa687a25..604e30ce251de78256147c6855a6026c48cf3dd9 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -549,6 +549,11 @@ and pop-up menus.
 This controls the style of the pre-edit and status areas of X input
 methods.
 
++++
+** New X resources: "highlightForeground" and "highlightBackground"
+Only in the Lucid build, this controls colors used for highlighted
+menu item widgets.
+
 +++
 ** On X11, Emacs now tries to synchronize window resize with the window manager.
 This leads to less flicker and empty areas of a frame being displayed
index 68f49e646dad889c33a404b3edc70988fa43e815..2450e718c2b53ec206810d187311df629bf226df 100644 (file)
@@ -121,6 +121,10 @@ xlwMenuResources[] =
    offset(menu.disabled_foreground), XtRString, (XtPointer)NULL},
   {XtNbuttonForeground, XtCButtonForeground, XtRPixel, sizeof(Pixel),
      offset(menu.button_foreground), XtRString, "XtDefaultForeground"},
+  {XtNhighlightForeground, XtCHighlightForeground, XtRPixel, sizeof(Pixel),
+   offset(menu.highlight_foreground), XtRString, "XtDefaultForeground"},
+  {XtNhighlightBackground, XtCHighlightBackground, XtRPixel, sizeof(Pixel),
+   offset(menu.highlight_background), XtRImmediate, (XtPointer)-1},
   {XtNmargin, XtCMargin, XtRDimension,  sizeof(Dimension),
      offset(menu.margin), XtRImmediate, (XtPointer)1},
   {XtNhorizontalSpacing, XtCMargin, XtRDimension,  sizeof(Dimension),
@@ -570,8 +574,7 @@ draw_arrow (XlwMenuWidget mw,
             int down_p)
 {
   Display *dpy = XtDisplay (mw);
-  GC top_gc = mw->menu.shadow_top_gc;
-  GC bottom_gc = mw->menu.shadow_bottom_gc;
+  GC top_gc, bottom_gc;
   int thickness = mw->menu.shadow_thickness;
   int height = width;
   XPoint pt[10];
@@ -584,10 +587,13 @@ draw_arrow (XlwMenuWidget mw,
 
   if (down_p)
     {
-      GC temp;
-      temp = top_gc;
-      top_gc = bottom_gc;
-      bottom_gc = temp;
+      top_gc = mw->menu.highlight_shadow_bottom_gc;
+      bottom_gc = mw->menu.highlight_shadow_top_gc;
+    }
+  else
+    {
+      top_gc = mw->menu.shadow_top_gc;
+      bottom_gc = mw->menu.shadow_bottom_gc;
     }
 
   pt[0].x = x;
@@ -621,24 +627,34 @@ draw_arrow (XlwMenuWidget mw,
   XFillPolygon (dpy, window, bottom_gc, pt, 4, Convex, CoordModeOrigin);
 }
 
-
-
+/* Generic draw shadow rectangle function.  It is used to draw shadows
+   on menus, menu items and also toggle buttons.  When ERASE_P is
+   true, it clears shadows.  DOWN_P is true when a menu item is pushed
+   or a button toggled.  TOP_GC and BOTTOM_GC are the graphic contexts
+   used to draw the top and bottom shadow respectively.  */
 static void
-draw_shadow_rectangle (XlwMenuWidget mw,
-                       Window window,
-                       int x,
-                       int y,
-                       int width,
-                       int height,
-                       int erase_p,
-                       int down_p)
+draw_shadow_rectangle (XlwMenuWidget mw, Window window, int x, int y,
+                      int width, int height, int erase_p, int down_p,
+                      GC top_gc, GC bottom_gc)
 {
   Display *dpy = XtDisplay (mw);
-  GC top_gc = !erase_p ? mw->menu.shadow_top_gc : mw->menu.background_gc;
-  GC bottom_gc = !erase_p ? mw->menu.shadow_bottom_gc : mw->menu.background_gc;
   int thickness = !x && !y ? mw->menu.border_thickness : mw->menu.shadow_thickness;
   XPoint points [4];
 
+  /* Choose correct GC with a standard default if NULL.  */
+  if (erase_p)
+    {
+      top_gc = mw->menu.background_gc;
+      bottom_gc = mw->menu.background_gc;
+    }
+  else
+    {
+      if (top_gc == NULL)
+       top_gc = mw->menu.shadow_top_gc;
+      if (bottom_gc == NULL)
+       bottom_gc = mw->menu.shadow_bottom_gc;
+    }
+
   if (!erase_p && width == height && width == toggle_button_width (mw))
     {
       points [0].x = x;
@@ -662,6 +678,7 @@ draw_shadow_rectangle (XlwMenuWidget mw,
       bottom_gc = temp;
     }
 
+  /* Do draw (or erase) shadows */
   points [0].x = x;
   points [0].y = y;
   points [1].x = x + width;
@@ -702,21 +719,28 @@ draw_shadow_rectangle (XlwMenuWidget mw,
 
 
 static void
-draw_shadow_rhombus (XlwMenuWidget mw,
-                     Window window,
-                     int x,
-                     int y,
-                     int width,
-                     int height,
-                     int erase_p,
-                     int down_p)
+draw_shadow_rhombus (XlwMenuWidget mw, Window window, int x, int y,
+                     int width, int height, int erase_p, int down_p,
+                    GC top_gc, GC bottom_gc)
 {
   Display *dpy = XtDisplay (mw);
-  GC top_gc = !erase_p ? mw->menu.shadow_top_gc : mw->menu.background_gc;
-  GC bottom_gc = !erase_p ? mw->menu.shadow_bottom_gc : mw->menu.background_gc;
   int thickness = mw->menu.shadow_thickness;
   XPoint points [4];
 
+  /* Choose correct GC with a standard default if NULL */
+  if (erase_p)
+    {
+      top_gc = mw->menu.background_gc;
+      bottom_gc = mw->menu.background_gc;
+    }
+  else
+    {
+      if (top_gc == NULL)
+       top_gc = mw->menu.shadow_top_gc;
+      if (bottom_gc == NULL)
+       top_gc = mw->menu.shadow_bottom_gc;
+    }
+
   if (!erase_p && width == height && width == radio_button_width (mw))
     {
       points [0].x = x;
@@ -784,15 +808,29 @@ draw_shadow_rhombus (XlwMenuWidget mw,
    toggle button is selected.  */
 
 static void
-draw_toggle (XlwMenuWidget mw, Window window, int x, int y, int selected_p)
+draw_toggle (XlwMenuWidget mw, Window window, int x, int y, int selected_p,
+            int highlighted_p)
 {
   int width, height;
+  GC top_gc, bottom_gc;
+
+  if (highlighted_p)
+    {
+      top_gc = mw->menu.highlight_shadow_top_gc;
+      bottom_gc = mw->menu.highlight_shadow_bottom_gc;
+    }
+  else
+    {
+      top_gc = mw->menu.shadow_top_gc;
+      bottom_gc = mw->menu.shadow_bottom_gc;
+    }
 
   width = toggle_button_width (mw);
   height = width;
   x += mw->menu.horizontal_spacing;
   y += (MENU_FONT_ASCENT (mw) - height) / 2;
-  draw_shadow_rectangle (mw, window, x, y, width, height, False, selected_p);
+  draw_shadow_rectangle (mw, window, x, y, width, height, False,
+                        selected_p, top_gc, bottom_gc);
 }
 
 
@@ -801,15 +839,29 @@ draw_toggle (XlwMenuWidget mw, Window window, int x, int y, int selected_p)
    toggle button is selected.  */
 
 static void
-draw_radio (XlwMenuWidget mw, Window window, int x, int y, int selected_p)
+draw_radio (XlwMenuWidget mw, Window window, int x, int y, int selected_p,
+           int highlighted_p)
 {
   int width, height;
+  GC top_gc, bottom_gc;
+
+  if (highlighted_p)
+    {
+      top_gc = mw->menu.highlight_shadow_top_gc;
+      bottom_gc = mw->menu.highlight_shadow_bottom_gc;
+    }
+  else
+    {
+      top_gc = mw->menu.shadow_top_gc;
+      bottom_gc = mw->menu.shadow_bottom_gc;
+    }
 
   width = radio_button_width (mw);
   height = width;
   x += mw->menu.horizontal_spacing;
   y += (MENU_FONT_ASCENT (mw) - height) / 2;
-  draw_shadow_rhombus (mw, window, x, y, width, height, False, selected_p);
+  draw_shadow_rhombus (mw, window, x, y, width, height, False, selected_p,
+                      top_gc, bottom_gc);
 }
 
 
@@ -968,6 +1020,31 @@ separator_height (enum menu_separator separator)
     }
 }
 
+/* Draw the highlighted background and shadows.  */
+
+static void
+draw_highlight (XlwMenuWidget mw, Window window, int x, int y, int width,
+               int height)
+{
+  Display *dpy = XtDisplay (mw);
+  XPoint points [4];
+
+  points [0].x = x;
+  points [0].y = y;
+  points [1].x = x + width;
+  points [1].y = y;
+  points [2].x = x + width;
+  points [2].y = y + height;
+  points [3].x = x;
+  points [3].y = y + height;
+  XFillPolygon (dpy, window,
+               mw->menu.highlight_background_gc,
+               points, 4, Convex, CoordModeOrigin);
+
+  draw_shadow_rectangle(mw, window, x, y, width, height, False, False,
+                       mw->menu.highlight_shadow_top_gc,
+                       mw->menu.highlight_shadow_bottom_gc);
+}
 
 /* Display the menu item and increment where.x and where.y to show how large
    the menu item was.  */
@@ -983,7 +1060,6 @@ display_menu_item (XlwMenuWidget mw,
 {
   GC deco_gc;
   GC text_gc;
-  int font_height = MENU_FONT_HEIGHT (mw);
   int font_ascent = MENU_FONT_ASCENT (mw);
   int shadow = mw->menu.shadow_thickness;
   int margin = mw->menu.margin;
@@ -1032,12 +1108,21 @@ display_menu_item (XlwMenuWidget mw,
 
       /* pick the foreground and background GC. */
       if (val->enabled)
-       text_gc = mw->menu.foreground_gc;
+       if (highlighted_p)
+         text_gc = mw->menu.highlight_foreground_gc;
+       else
+         text_gc = mw->menu.foreground_gc;
       else
        text_gc = mw->menu.disabled_gc;
       deco_gc = mw->menu.foreground_gc;
 #if defined USE_CAIRO || defined HAVE_XFT
-      xftfg = val->enabled ? &mw->menu.xft_fg : &mw->menu.xft_disabled_fg;
+      if (val->enabled)
+       if (highlighted_p)
+         xftfg = &mw->menu.xft_highlight_fg;
+       else
+         xftfg = &mw->menu.xft_fg;
+      else
+       xftfg = &mw->menu.xft_disabled_fg;
 #endif
 
       if (separator_p)
@@ -1048,8 +1133,11 @@ display_menu_item (XlwMenuWidget mw,
        {
          int x_offset = x + h_spacing + shadow;
          char* display_string = resource_widget_value (mw, val);
-         draw_shadow_rectangle (mw, ws->pixmap, x, y, width, height, True,
-                                False);
+         /* Clears shadows and maybe highlight */
+         draw_shadow_rectangle (mw, ws->pixmap, x, y, width, height,
+                                True, False, NULL, NULL);
+         if (highlighted_p)
+           draw_highlight (mw, ws->pixmap, x, y, width, height);
 
          /* Deal with centering a menu title. */
          if (!horizontal_p && !val->contents && !val->call_data)
@@ -1095,10 +1183,10 @@ display_menu_item (XlwMenuWidget mw,
            {
              if (val->button_type == BUTTON_TYPE_TOGGLE)
                draw_toggle (mw, ws->pixmap, x, y + v_spacing + shadow,
-                            val->selected);
+                            val->selected, highlighted_p);
              else if (val->button_type == BUTTON_TYPE_RADIO)
                draw_radio (mw, ws->pixmap, x, y + v_spacing + shadow,
-                           val->selected);
+                           val->selected, highlighted_p);
 
              if (val->contents)
                {
@@ -1145,25 +1233,18 @@ display_menu_item (XlwMenuWidget mw,
            }
          else
            {
-             XDrawRectangle (XtDisplay (mw), ws->pixmap,
-                             mw->menu.background_gc,
-                             x + shadow, y + shadow,
-                             label_width + h_spacing - 1,
-                             font_height + 2 * v_spacing - 1);
-             draw_shadow_rectangle (mw, ws->pixmap, x, y, width, height,
-                                    True, False);
+             /* If not highlighted, clears shadows for horizontal
+                menu item */
+             if (!highlighted_p)
+               draw_shadow_rectangle (mw, ws->pixmap, x, y, width, height,
+                                      True, False, NULL, NULL);
            }
 #ifdef USE_CAIRO
          if (ws->xft_draw)
            cairo_surface_flush (cairo_get_target (ws->xft_draw));
 #endif
-
-         if (highlighted_p)
-           draw_shadow_rectangle (mw, ws->pixmap, x, y, width, height, False,
-                                  False);
        }
     }
-
   where->x += width;
   where->y += height;
 }
@@ -1257,7 +1338,7 @@ display_menu (XlwMenuWidget mw,
   if (!just_compute_p)
     {
       draw_shadow_rectangle (mw, ws->pixmap, 0, 0, ws->width, ws->height,
-                             False, False);
+                             False, False, NULL, NULL);
       XCopyArea (XtDisplay (mw), ws->pixmap, ws->window,
                  mw->menu.foreground_gc, 0, 0, ws->width, ws->height, 0, 0);
     }
@@ -1714,6 +1795,18 @@ make_drawing_gcs (XlwMenuWidget mw)
   xgcv.foreground = mw->core.background_pixel;
   xgcv.background = mw->menu.foreground;
   mw->menu.background_gc = XtGetGC ((Widget)mw, mask, &xgcv);
+
+  xgcv.foreground = mw->menu.highlight_foreground;
+  xgcv.background = ((mw->menu.highlight_background == -1)
+                    ? mw->core.background_pixel
+                    : mw->menu.highlight_background);
+  mw->menu.highlight_foreground_gc = XtGetGC ((Widget)mw, mask, &xgcv);
+
+  xgcv.foreground = ((mw->menu.highlight_background == -1)
+                    ? mw->core.background_pixel
+                    : mw->menu.highlight_background);
+  xgcv.background = mw->menu.foreground;
+  mw->menu.highlight_background_gc = XtGetGC ((Widget)mw, mask, &xgcv);
 }
 
 static void
@@ -1724,12 +1817,16 @@ release_drawing_gcs (XlwMenuWidget mw)
   XtReleaseGC ((Widget) mw, mw->menu.disabled_gc);
   XtReleaseGC ((Widget) mw, mw->menu.inactive_button_gc);
   XtReleaseGC ((Widget) mw, mw->menu.background_gc);
+  XtReleaseGC ((Widget) mw, mw->menu.highlight_foreground_gc);
+  XtReleaseGC ((Widget) mw, mw->menu.highlight_background_gc);
   /* let's get some segvs if we try to use these... */
   mw->menu.foreground_gc = (GC) -1;
   mw->menu.button_gc = (GC) -1;
   mw->menu.disabled_gc = (GC) -1;
   mw->menu.inactive_button_gc = (GC) -1;
   mw->menu.background_gc = (GC) -1;
+  mw->menu.highlight_foreground_gc = (GC) -1;
+  mw->menu.highlight_background_gc = (GC) -1;
 }
 
 #ifndef emacs
@@ -1738,29 +1835,29 @@ release_drawing_gcs (XlwMenuWidget mw)
 #endif
 
 static void
-make_shadow_gcs (XlwMenuWidget mw)
+compute_shadow_colors (XlwMenuWidget mw, Pixel *top_color, Pixel *bottom_color,
+                      Boolean *free_top_p, Boolean *free_bottom_p,
+                      Pixmap *top_pixmap, Pixmap *bottom_pixmap,
+                      Pixel fore_color, Pixel back_color)
 {
-  XGCValues xgcv;
-  unsigned long pm = 0;
   Display *dpy = XtDisplay ((Widget) mw);
   Screen *screen = XtScreen ((Widget) mw);
   Colormap cmap = mw->core.colormap;
   XColor topc, botc;
   int top_frobbed = 0, bottom_frobbed = 0;
 
-  mw->menu.free_top_shadow_color_p = 0;
-  mw->menu.free_bottom_shadow_color_p = 0;
+  *free_top_p = False;
+  *free_bottom_p = False;
 
-  if (mw->menu.top_shadow_color == -1)
-    mw->menu.top_shadow_color = mw->core.background_pixel;
+  if (*top_color == -1)
+    *top_color = back_color;
 
-  if (mw->menu.bottom_shadow_color == -1)
-    mw->menu.bottom_shadow_color = mw->menu.foreground;
+  if (*bottom_color == -1)
+    *bottom_color = fore_color;
 
-  if (mw->menu.top_shadow_color == mw->core.background_pixel ||
-      mw->menu.top_shadow_color == mw->menu.foreground)
+  if (*top_color == back_color || *top_color == fore_color)
     {
-      topc.pixel = mw->core.background_pixel;
+      topc.pixel = back_color;
 #ifdef emacs
       if (x_alloc_lighter_color_for_widget ((Widget) mw, dpy, cmap,
                                            &topc.pixel,
@@ -1774,15 +1871,14 @@ make_shadow_gcs (XlwMenuWidget mw)
       if (XAllocColor (dpy, cmap, &topc))
 #endif
        {
-         mw->menu.top_shadow_color = topc.pixel;
-         mw->menu.free_top_shadow_color_p = 1;
+         *top_color = topc.pixel;
+         *free_top_p = True;
          top_frobbed = 1;
        }
     }
-  if (mw->menu.bottom_shadow_color == mw->menu.foreground ||
-      mw->menu.bottom_shadow_color == mw->core.background_pixel)
+  if (*bottom_color == fore_color || *bottom_color == back_color)
     {
-      botc.pixel = mw->core.background_pixel;
+      botc.pixel = back_color;
 #ifdef emacs
       if (x_alloc_lighter_color_for_widget ((Widget) mw, dpy, cmap,
                                            &botc.pixel,
@@ -1795,8 +1891,8 @@ make_shadow_gcs (XlwMenuWidget mw)
       if (XAllocColor (dpy, cmap, &botc))
 #endif
        {
-         mw->menu.bottom_shadow_color = botc.pixel;
-         mw->menu.free_bottom_shadow_color_p = 1;
+         *bottom_color = botc.pixel;
+         *free_bottom_p = True;
          bottom_frobbed = 1;
        }
     }
@@ -1805,63 +1901,94 @@ make_shadow_gcs (XlwMenuWidget mw)
     {
       if (topc.pixel == botc.pixel)
        {
-         if (botc.pixel == mw->menu.foreground)
+         if (botc.pixel == fore_color)
            {
-             if (mw->menu.free_top_shadow_color_p)
+             if (*free_top_p)
                {
-                 x_free_dpy_colors (dpy, screen, cmap,
-                                    &mw->menu.top_shadow_color, 1);
-                 mw->menu.free_top_shadow_color_p = 0;
+                 x_free_dpy_colors (dpy, screen, cmap, top_color, 1);
+                 *free_top_p = False;
                }
-             mw->menu.top_shadow_color = mw->core.background_pixel;
+             *top_color = back_color;
            }
          else
            {
-             if (mw->menu.free_bottom_shadow_color_p)
+             if (*free_bottom_p)
                {
-                 x_free_dpy_colors (dpy, screen, cmap,
-                                    &mw->menu.bottom_shadow_color, 1);
-                 mw->menu.free_bottom_shadow_color_p = 0;
+                 x_free_dpy_colors (dpy, screen, cmap, bottom_color, 1);
+                 *free_bottom_p = False;
                }
-             mw->menu.bottom_shadow_color = mw->menu.foreground;
+             *bottom_color = fore_color;
            }
        }
     }
 
-  if (!mw->menu.top_shadow_pixmap
-      && mw->menu.top_shadow_color == mw->core.background_pixel)
+  if (!*top_pixmap && *top_color == back_color)
     {
-      mw->menu.top_shadow_pixmap = mw->menu.gray_pixmap;
-      if (mw->menu.free_top_shadow_color_p)
+      *top_pixmap = mw->menu.gray_pixmap;
+      if (*free_top_p)
        {
-         x_free_dpy_colors (dpy, screen, cmap, &mw->menu.top_shadow_color, 1);
-         mw->menu.free_top_shadow_color_p = 0;
+         x_free_dpy_colors (dpy, screen, cmap, top_color, 1);
+         *free_top_p = False;
        }
-      mw->menu.top_shadow_color = mw->menu.foreground;
+      *top_color = fore_color;
     }
-  if (!mw->menu.bottom_shadow_pixmap
-      && mw->menu.bottom_shadow_color == mw->core.background_pixel)
+  if (!*bottom_pixmap && *bottom_color == back_color)
     {
-      mw->menu.bottom_shadow_pixmap = mw->menu.gray_pixmap;
-      if (mw->menu.free_bottom_shadow_color_p)
+      *bottom_pixmap = mw->menu.gray_pixmap;
+      if (*free_bottom_p)
        {
-         x_free_dpy_colors (dpy, screen, cmap,
-                            &mw->menu.bottom_shadow_color, 1);
-         mw->menu.free_bottom_shadow_color_p = 0;
+         x_free_dpy_colors (dpy, screen, cmap, bottom_color, 1);
+         *free_bottom_p = False;
        }
-      mw->menu.bottom_shadow_color = mw->menu.foreground;
+      *bottom_color = fore_color;
     }
+}
+
+static void
+make_shadow_gcs (XlwMenuWidget mw)
+{
+  XGCValues xgcv;
+  unsigned long pm = 0;
+
+  /* Normal shadows */
+  compute_shadow_colors (mw, &(mw->menu.top_shadow_color),
+                        &(mw->menu.bottom_shadow_color),
+                        &(mw->menu.free_top_shadow_color_p),
+                        &(mw->menu.free_bottom_shadow_color_p),
+                        &(mw->menu.top_shadow_pixmap),
+                        &(mw->menu.bottom_shadow_pixmap),
+                        mw->menu.foreground, mw->core.background_pixel);
+
+  /* Highlight shadows */
+  compute_shadow_colors (mw, &(mw->menu.top_highlight_shadow_color),
+                        &(mw->menu.bottom_highlight_shadow_color),
+                        &(mw->menu.free_top_highlight_shadow_color_p),
+                        &(mw->menu.free_bottom_highlight_shadow_color_p),
+                        &(mw->menu.top_highlight_shadow_pixmap),
+                        &(mw->menu.bottom_highlight_shadow_pixmap),
+                        mw->menu.highlight_foreground,
+                        mw->menu.highlight_background);
 
   xgcv.fill_style = FillStippled;
   xgcv.foreground = mw->menu.top_shadow_color;
   xgcv.stipple = mw->menu.top_shadow_pixmap;
-  pm = (xgcv.stipple ? GCStipple|GCFillStyle : 0);
-  mw->menu.shadow_top_gc = XtGetGC ((Widget)mw, GCForeground | pm, &xgcv);
+  pm = (xgcv.stipple ? GCStipple | GCFillStyle : 0);
+  mw->menu.shadow_top_gc = XtGetGC ((Widget) mw, GCForeground | pm, &xgcv);
 
   xgcv.foreground = mw->menu.bottom_shadow_color;
   xgcv.stipple = mw->menu.bottom_shadow_pixmap;
-  pm = (xgcv.stipple ? GCStipple|GCFillStyle : 0);
-  mw->menu.shadow_bottom_gc = XtGetGC ((Widget)mw, GCForeground | pm, &xgcv);
+  pm = (xgcv.stipple ? GCStipple | GCFillStyle : 0);
+  mw->menu.shadow_bottom_gc = XtGetGC ((Widget) mw, GCForeground | pm, &xgcv);
+
+  xgcv.foreground = mw->menu.top_highlight_shadow_color;
+  xgcv.stipple = mw->menu.top_highlight_shadow_pixmap;
+  pm = (xgcv.stipple ? GCStipple | GCFillStyle : 0);
+  mw->menu.highlight_shadow_top_gc = XtGetGC ((Widget) mw, GCForeground | pm, &xgcv);
+
+  xgcv.foreground = mw->menu.bottom_highlight_shadow_color;
+  xgcv.stipple = mw->menu.bottom_highlight_shadow_pixmap;
+  pm = (xgcv.stipple ? GCStipple | GCFillStyle : 0);
+  mw->menu.highlight_shadow_bottom_gc = XtGetGC ((Widget) mw, GCForeground | pm, &xgcv);
 }
 
 
@@ -1871,18 +1998,24 @@ release_shadow_gcs (XlwMenuWidget mw)
   Display *dpy = XtDisplay ((Widget) mw);
   Screen *screen = XtScreen ((Widget) mw);
   Colormap cmap = mw->core.colormap;
-  Pixel px[2];
+  Pixel px[4];
   int i = 0;
 
   if (mw->menu.free_top_shadow_color_p)
     px[i++] = mw->menu.top_shadow_color;
   if (mw->menu.free_bottom_shadow_color_p)
     px[i++] = mw->menu.bottom_shadow_color;
+  if (mw->menu.free_top_highlight_shadow_color_p)
+    px[i++] = mw->menu.top_highlight_shadow_color;
+  if (mw->menu.free_bottom_highlight_shadow_color_p)
+    px[i++] = mw->menu.bottom_highlight_shadow_color;
   if (i > 0)
     x_free_dpy_colors (dpy, screen, cmap, px, i);
 
   XtReleaseGC ((Widget) mw, mw->menu.shadow_top_gc);
   XtReleaseGC ((Widget) mw, mw->menu.shadow_bottom_gc);
+  XtReleaseGC ((Widget) mw, mw->menu.highlight_shadow_top_gc);
+  XtReleaseGC ((Widget) mw, mw->menu.highlight_shadow_bottom_gc);
 }
 
 #if defined USE_CAIRO || defined HAVE_XFT
@@ -1964,6 +2097,11 @@ XlwMenuInitialize (Widget request, Widget w, ArgList args, Cardinal *num_args)
     mw->menu.font_extents = XExtentsOfFontSet (mw->menu.fontSet);
 #endif
 
+  mw->menu.top_highlight_shadow_color = -1;
+  mw->menu.bottom_highlight_shadow_color = -1;
+  mw->menu.top_highlight_shadow_pixmap = None;
+  mw->menu.bottom_highlight_shadow_pixmap = None;
+
   make_drawing_gcs (mw);
   make_shadow_gcs (mw);
 
@@ -2038,12 +2176,14 @@ XlwMenuRealize (Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
 #if defined USE_CAIRO || defined HAVE_XFT
   if (mw->menu.xft_font)
     {
-      XColor colors[3];
+      XColor colors[4];
       colors[0].pixel = mw->menu.xft_fg.pixel = mw->menu.foreground;
       colors[1].pixel = mw->menu.xft_bg.pixel = mw->core.background_pixel;
       colors[2].pixel = mw->menu.xft_disabled_fg.pixel
         = mw->menu.disabled_foreground;
-      XQueryColors (XtDisplay (mw), mw->core.colormap, colors, 3);
+      colors[3].pixel = mw->menu.xft_highlight_fg.pixel
+       = mw->menu.highlight_foreground;
+      XQueryColors (XtDisplay (mw), mw->core.colormap, colors, 4);
       mw->menu.xft_fg.color.alpha = 0xFFFF;
       mw->menu.xft_fg.color.red = colors[0].red;
       mw->menu.xft_fg.color.green = colors[0].green;
@@ -2056,6 +2196,10 @@ XlwMenuRealize (Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
       mw->menu.xft_disabled_fg.color.red = colors[2].red;
       mw->menu.xft_disabled_fg.color.green = colors[2].green;
       mw->menu.xft_disabled_fg.color.blue = colors[2].blue;
+      mw->menu.xft_highlight_fg.color.alpha = 0xFFFF;
+      mw->menu.xft_highlight_fg.color.red = colors[3].red;
+      mw->menu.xft_highlight_fg.color.green = colors[3].green;
+      mw->menu.xft_highlight_fg.color.blue = colors[3].blue;
     }
 #endif
 }
index 7f4bf35939ae73c582da86207f59560035a4f191..4e36bde3fb97e9d469a8ae59056b9c5573864d5b 100644 (file)
@@ -58,6 +58,10 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #define XtCAllowResize "AllowResize"
 #define XtNborderThickness "borderThickness"
 #define XtCBorderThickness "BorderThickness"
+#define XtNhighlightForeground "highlightForeground"
+#define XtCHighlightForeground "HighlightForeground"
+#define XtNhighlightBackground "highlightBackground"
+#define XtCHighlightBackground "HighlightBackground"
 
 /* Motif-compatible resource names */
 #define XmNshadowThickness     "shadowThickness"
index 455ecdbce01f034fcc9ebe19e09c4a22927ec04d..c314eb3e9107ed4836667a58be7b600d433afbb5 100644 (file)
@@ -63,13 +63,15 @@ typedef struct _XlwMenu_part
 #if defined USE_CAIRO || defined HAVE_XFT
   int           default_face;
   XftFont*      xft_font;
-  XftColor      xft_fg, xft_bg, xft_disabled_fg;
+  XftColor      xft_fg, xft_bg, xft_disabled_fg, xft_highlight_fg;
 #endif
   String       fontName;
   XFontStruct* font;
   Pixel                foreground;
   Pixel                disabled_foreground;
   Pixel                button_foreground;
+  Pixel                highlight_foreground;
+  Pixel                highlight_background;
   Dimension    margin;
   Dimension    horizontal_spacing;
   Dimension    vertical_spacing;
@@ -80,6 +82,10 @@ typedef struct _XlwMenu_part
   Pixel        bottom_shadow_color;
   Pixmap       top_shadow_pixmap;
   Pixmap       bottom_shadow_pixmap;
+  Pixel        top_highlight_shadow_color;
+  Pixel        bottom_highlight_shadow_color;
+  Pixmap       top_highlight_shadow_pixmap;
+  Pixmap       bottom_highlight_shadow_pixmap;
   Cursor       cursor_shape;
   XtCallbackList       open;
   XtCallbackList       select, highlight;
@@ -88,8 +94,10 @@ typedef struct _XlwMenu_part
   int          horizontal;
 
   /* True means top_shadow_color and/or bottom_shadow_color must be freed.  */
-  bool_bf free_top_shadow_color_p : 1;
-  bool_bf free_bottom_shadow_color_p : 1;
+  Boolean free_top_shadow_color_p;
+  Boolean free_bottom_shadow_color_p;
+  Boolean free_top_highlight_shadow_color_p;
+  Boolean free_bottom_highlight_shadow_color_p;
 
   /* State of the XlwMenu */
   int                   top_depth;
@@ -112,9 +120,13 @@ typedef struct _XlwMenu_part
   GC                   button_gc;
   GC                   background_gc;
   GC                   disabled_gc;
+  GC                   highlight_foreground_gc;
+  GC                   highlight_background_gc;
   GC                   inactive_button_gc;
   GC                   shadow_top_gc;
   GC                   shadow_bottom_gc;
+  GC                   highlight_shadow_top_gc;
+  GC                   highlight_shadow_bottom_gc;
   Cursor               cursor;
   Boolean              popped_up;
   Pixmap               gray_pixmap;