From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Manuel Giraud Newsgroups: gmane.emacs.bugs Subject: bug#56538: 29.0.50; [PATCH] Colored highlight in Lucid backend Date: Thu, 14 Jul 2022 11:42:06 +0200 Message-ID: <87cze8t4i9.fsf@elite.giraud> References: <87wnch16as.fsf@elite.giraud> <87k08gtsz0.fsf@yahoo.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="31615"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (berkeley-unix) Cc: 56538@debbugs.gnu.org To: Po Lu Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Thu Jul 14 11:50:59 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oBvUn-0007pn-H4 for geb-bug-gnu-emacs@m.gmane-mx.org; Thu, 14 Jul 2022 11:50:57 +0200 Original-Received: from localhost ([::1]:60578 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oBvUl-0004Fv-Sg for geb-bug-gnu-emacs@m.gmane-mx.org; Thu, 14 Jul 2022 05:50:55 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:51768) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oBvN8-0006Bw-5y for bug-gnu-emacs@gnu.org; Thu, 14 Jul 2022 05:43:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:54989) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oBvN7-0006Kq-Tm for bug-gnu-emacs@gnu.org; Thu, 14 Jul 2022 05:43:01 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1oBvN7-0002b6-Q3 for bug-gnu-emacs@gnu.org; Thu, 14 Jul 2022 05:43:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Manuel Giraud Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 14 Jul 2022 09:43:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 56538 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 56538-submit@debbugs.gnu.org id=B56538.16577917399930 (code B ref 56538); Thu, 14 Jul 2022 09:43:01 +0000 Original-Received: (at 56538) by debbugs.gnu.org; 14 Jul 2022 09:42:19 +0000 Original-Received: from localhost ([127.0.0.1]:48886 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oBvMQ-0002a3-1n for submit@debbugs.gnu.org; Thu, 14 Jul 2022 05:42:19 -0400 Original-Received: from ledu-giraud.fr ([51.159.28.247]:10964) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oBvMN-0002Zu-D7 for 56538@debbugs.gnu.org; Thu, 14 Jul 2022 05:42:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=rsa; bh=jlscrrsdYP0gS3eP HeI+/83vE5jDf3ICWlmfPHyKAoQ=; h=date:references:in-reply-to:subject: cc:to:from; d=ledu-giraud.fr; b=RvvYasV5xJ68/EV0iXZniU710SNjpDaj63zSTl YH2aN9/v3MHJeOyfN3UgKegzcbBUiMdHpHJHjE0gaeLGoaN7E2oVPwpd6bvUXNXkZqcImn NITuxf0+VTEBvwAvidfi9dakREeaodEM9ZxSTO9K71ZVs0mwxm9lNI9yeBQr1aO1FzFSnN frvNOLQ1nvJ2cl2iKSbjsMRJfhdGOug+BDFDOrnKUJmQd6yuZdh8n5nXxOOsrqDbDoqZoN WGC1qayPkk9YjB15mdrXPA3SRP4OcCFSFuiw6+XM7UgD/X3T8omt2YJ0v+lU2FVoyNlsDP BYiUf3QSNaADMOmniZ6uSkfA== Original-Received: from elite.giraud ( [10.1.1.1]) by ledu-giraud.fr (OpenSMTPD) with ESMTPSA id 1865ba40 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 14 Jul 2022 11:42:12 +0200 (CEST) In-Reply-To: <87k08gtsz0.fsf@yahoo.com> (Po Lu's message of "Thu, 14 Jul 2022 08:53:39 +0800") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:236974 Archived-At: --=-=-= Content-Type: text/plain Po Lu writes: Hi Po and thanks for your comments, [...] >> + /* XXX the following permutation is on purpose */ > > This comment seems redundant. I have attached a new version of my patch taking your remarks into account but I did not remove this comment. I think it could be useful to understand that "top_gc = something_bottom_gc" is not a typo here. I have also done the following testing with Xft/cairo/PseudoColor combinations: |-------------+-----------------+-----------------+-----------------+---------------------| | | Xft + cairo | Xft only | cairo only | None | |-------------+-----------------+-----------------+-----------------+---------------------| | X Truecolor | ok | ok | ok | ok but with a | | | | | | default tiny face | |-------------+-----------------+-----------------+-----------------+---------------------| | Xephyr | ok but color | ok but color | ok but color | ok, colors ok, but | | Pseudocolor | not quite right | not quite right | not quite right | with a default tiny | | | around each | around menu | around each | face [fn:2] | | | glyph [fn:1] | labels [fn:2] | glyph [fn:1] | | |-------------+-----------------+-----------------+-----------------+---------------------| * Footnotes [fn:1] Aside from the Lucid widget, the emacs buffer is completly blank. [fn:2] This time the emacs buffer is here. tool-bar icons are ugly. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Colored-menu-highlight-in-Lucid-backend.patch >From e0fb799bc55367c08b2511fda78f98570bda6fdc Mon Sep 17 00:00:00 2001 From: Manuel Giraud Date: Mon, 11 Jul 2022 11:14:08 +0200 Subject: [PATCH] Colored menu highlight in Lucid backend * 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 | 4 + etc/NEWS | 5 + lwlib/xlwmenu.c | 342 ++++++++++++++++++++++++++++---------- lwlib/xlwmenu.h | 4 + lwlib/xlwmenuP.h | 18 +- 5 files changed, 281 insertions(+), 92 deletions(-) diff --git a/doc/emacs/xresources.texi b/doc/emacs/xresources.texi index 2c2700bc15..f8be06b5e7 100644 --- a/doc/emacs/xresources.texi +++ b/doc/emacs/xresources.texi @@ -449,6 +449,10 @@ Lucid Resources Foreground color. @item disabledForeground Foreground color for a disabled menu item. +@item highlightForeground +Foreground color for a highlighted menu item. +@item highlightBackground +Background color for a highlighted menu item. @ifnottex @item horizontalSpacing Horizontal spacing in pixels between items. Default is 3. diff --git a/etc/NEWS b/etc/NEWS index bf36316890..e1c708ca9d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -544,6 +544,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 widget. + +++ ** 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 diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c index 68f49e646d..a15803cfc3 100644 --- a/lwlib/xlwmenu.c +++ b/lwlib/xlwmenu.c @@ -121,6 +121,10 @@ #define DEFAULT_FONTNAME "XtDefaultFont" 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,14 @@ draw_arrow (XlwMenuWidget mw, if (down_p) { - GC temp; - temp = top_gc; - top_gc = bottom_gc; - bottom_gc = temp; + /* XXX the following permutation is on purpose */ + 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,8 +628,11 @@ draw_arrow (XlwMenuWidget mw, XFillPolygon (dpy, window, bottom_gc, pt, 4, Convex, CoordModeOrigin); } - - +/* Generic draw shadow rectangle function. It is used to draw 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, @@ -631,14 +641,28 @@ draw_shadow_rectangle (XlwMenuWidget mw, int width, int height, int erase_p, - int down_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; @@ -654,6 +678,7 @@ draw_shadow_rectangle (XlwMenuWidget mw, points, 4, Convex, CoordModeOrigin); } + if (!erase_p && down_p) { GC temp; @@ -662,6 +687,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; @@ -709,14 +735,28 @@ draw_shadow_rhombus (XlwMenuWidget mw, int width, int height, int erase_p, - int down_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 +824,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 +855,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 +1036,33 @@ separator_height (enum menu_separator separator) } } +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 +1078,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 +1126,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 +1151,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 +1201,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 +1251,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 +1356,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 +1813,18 @@ #define BRIGHTNESS(color) (((color) & 0xff) + (((color) >> 8) & 0xff) + (((color 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 +1835,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 +1853,34 @@ #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ #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 +1894,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 +1914,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 +1924,97 @@ 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); } @@ -1964,6 +2117,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 +2196,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 +2216,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 } diff --git a/lwlib/xlwmenu.h b/lwlib/xlwmenu.h index 7f4bf35939..4e36bde3fb 100644 --- a/lwlib/xlwmenu.h +++ b/lwlib/xlwmenu.h @@ -58,6 +58,10 @@ #define XtNallowResize "allowResize" #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" diff --git a/lwlib/xlwmenuP.h b/lwlib/xlwmenuP.h index 455ecdbce0..c314eb3e91 100644 --- a/lwlib/xlwmenuP.h +++ b/lwlib/xlwmenuP.h @@ -63,13 +63,15 @@ #define _XlwMenuP_h #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 @@ #define _XlwMenuP_h 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 @@ #define _XlwMenuP_h 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 @@ #define _XlwMenuP_h 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; -- 2.36.1 --=-=-= Content-Type: text/plain -- Manuel Giraud --=-=-=--