Skip to content

Commit

Permalink
Translucent Menus
Browse files Browse the repository at this point in the history
  Adds new MenuStyle option 'Translucent', which can set the
  Translucent percent of menus using the associated style.
  This option takes one additional value that is a number
  between 0 (fully translucent) to 100 (not translucent).
  Supplying no value (or an invalid value), or using
  '!Translucent' turns translucency off.
  • Loading branch information
somiaj committed Nov 11, 2022
1 parent 9a2e418 commit 31c22d6
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 22 deletions.
9 changes: 8 additions & 1 deletion doc/fvwm3_manpage_source.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2523,7 +2523,8 @@ SubmenusLeft, SelectOnRelease, ItemFormat, VerticalItemSpacing,
VerticalMargins, VerticalTitleSpacing, AutomaticHotkeys /
!AutomaticHotkeys, UniqueHotkeyActivatesImmediate /
!UniqueHotkeyActivatesImmediate, MouseWheel, ScrollOffPage /
!ScrollOffPage, TrianglesUseFore / !TrianglesUseFore.
!ScrollOffPage, TrianglesUseFore / !TrianglesUseFore,
Translucent / !Translucent.
+
In the above list some options are listed as option pairs or triples
with a '/' in between. These options exclude each other. All paired
Expand Down Expand Up @@ -2598,6 +2599,12 @@ style. No other parts of the colorset are used.
_TitleColorset_ works exactly like _MenuColorset_, but is used only
for menu titles.
+
_Translucent_ controls a pseudo transparent effect that uses a image
of the desktop under the menu as its background image. This option
takes one value that is a number between 0 (fully translucent)
and 100 (not translucent), which is the percent of the translucency.
Use _!Translucent_ (or no additional value) to turn the effect off.
+
_Hilight3DThick_, _Hilight3DThin_ and _Hilight3DOff_ determine if the
selected menu item is hilighted with a 3D relief. Thick reliefs are
two pixels wide, thin reliefs are one pixel wide.
Expand Down
3 changes: 3 additions & 0 deletions fvwm/menuroot.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ typedef struct MenuRootDynamic
int d_npixels;
} stored_pixels;
/* alloc pixels when dithering is used for gradients */
/* x,y XMapRaise */
int x;
int y;
} MenuRootDynamic;

/* access macros to dynamic menu members */
Expand Down
193 changes: 175 additions & 18 deletions fvwm/menus.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@
#define SCTX_GET_MR(ctx) ((ctx).type == SCTX_MENU_ROOT ? \
(ctx).menu_root.menu_root : NULL)

#define MR_IS_TRANSLUCENT(mr) (!MR_IS_TEAR_OFF_MENU(mr) && \
MST_IS_TRANSLUCENT(mr))
#define MR_IS_TRANSPARENT(mr) (MR_IS_TRANSLUCENT(mr) || \
CSET_IS_TRANSPARENT(MST_CSET_MENU((mr))))

/* ---------------------------- imports ------------------------------------ */

/* This external is safe. It's written only during startup. */
Expand Down Expand Up @@ -219,6 +224,8 @@ typedef struct mloop_static_info_t
} mloop_static_info_t;

/* ---------------------------- forward declarations ----------------------- */
static MenuRoot *seek_submenu_instance(
MenuRoot *parent_menu, MenuItem *parent_item);

/* ---------------------------- local variables ---------------------------- */

Expand Down Expand Up @@ -380,11 +387,22 @@ static void animated_move_back(
Bool transparent_bg = False;

/* move it back */
if (CSET_IS_TRANSPARENT(ST_CSET_MENU(MR_STYLE(mr))))
if (MR_IS_TRANSPARENT(mr))
{
transparent_bg = True;
get_menu_repaint_transparent_parameters(
&mrtp, mr, fw);
if (MR_IS_TRANSLUCENT(mr) && MR_SUBMENU_ITEM(mr))
{
MenuRoot *smr;
smr = seek_submenu_instance(
mr, MR_SUBMENU_ITEM(mr));
if (smr)
{
/* just unmap it here, popdown later */
XUnmapWindow(dpy, MR_WINDOW(smr));
}
}
}
end.x = start.x - MR_XANIMATION(mr);
end.y = start.y;
Expand Down Expand Up @@ -1908,6 +1926,7 @@ static void make_menu_window(MenuRoot *mr, Bool is_tear_off)
/* Doh. Use the standard display instead. */
MR_CREATE_DPY(mr) = dpy;
}
MR_IS_TEAR_OFF_MENU(mr) = 1;
}
else
{
Expand Down Expand Up @@ -2450,7 +2469,45 @@ static void paint_menu(
}
MR_IS_PAINTED(mr) = 1;
/* paint the menu background */
if (ms && MR_IS_BACKGROUND_SET(mr) == False)
if (MR_IS_TRANSLUCENT(mr))
{
Pixmap trans = None;
FvwmRenderAttributes fra;
fra.mask = 0;
fra.mask = FRAM_HAVE_TINT;
fra.tint = Colorset[ST_CSET_MENU(ms)].bg;
fra.tint_percent = ST_TRANSLUCENT_PERCENT(ms);

if (MR_IS_BACKGROUND_SET(mr) == False)
{
trans = PGraphicsCreateTranslucent(
dpy, MR_WINDOW(mr), &fra,
BACK_GC(ST_MENU_INACTIVE_GCS(ms)),
mr->d->x, mr->d->y, MR_WIDTH(mr),
MR_HEIGHT(mr));
XMapRaised(dpy, MR_WINDOW(mr));
if (trans != None)
{
XSetWindowBackgroundPixmap(
dpy, MR_WINDOW(mr), trans);
MR_IS_BACKGROUND_SET(mr) = True;
if (pevent == NULL)
{
XClearWindow(dpy, MR_WINDOW(mr));
} else {
XClearArea(
dpy, MR_WINDOW(mr),
pevent->xexpose.x,
pevent->xexpose.y,
pevent->xexpose.width,
pevent->xexpose.height,
False);
}
XFreePixmap(dpy, trans);
}
}
}
else if (ms && MR_IS_BACKGROUND_SET(mr) == False)
{
SetWindowBackground(
dpy, MR_WINDOW(mr), MR_WIDTH(mr),
Expand Down Expand Up @@ -3078,8 +3135,7 @@ static int pop_menu_up(
MR_HAS_POPPED_UP_RIGHT(mr) = 0;
}
MR_XANIMATION(parent_menu) += end_x - prev_x;
if (CSET_IS_TRANSPARENT(ST_CSET_MENU(
MR_STYLE(parent_menu))))
if (MR_IS_TRANSPARENT(parent_menu))
{
transparent_bg = True;
get_menu_repaint_transparent_parameters(
Expand Down Expand Up @@ -3262,10 +3318,21 @@ static int pop_menu_up(
*/

XMoveWindow(dpy, MR_WINDOW(mr), x, y);
mr->d->x = x;
mr->d->y = y;
XSelectInput(dpy, MR_WINDOW(mr), event_mask);
XMapRaised(dpy, MR_WINDOW(mr));
if (popdown_window)
XUnmapWindow(dpy, popdown_window);
if (MR_IS_TRANSLUCENT(mr))
{
if (popdown_window)
XUnmapWindow(dpy, popdown_window);
paint_menu(mr, NULL, fw);
}
else
{
XMapRaised(dpy, MR_WINDOW(mr));
if (popdown_window)
XUnmapWindow(dpy, popdown_window);
}
XFlush(dpy);
MR_MAPPED_COPIES(mr)++;
MST_USAGE_COUNT(mr)++;
Expand Down Expand Up @@ -5833,16 +5900,106 @@ void update_transparent_menu_bg(
{
last = True;
}
if (!last && CSET_IS_TRANSPARENT_PR_TINT(ST_CSET_MENU(ms)))
if (!last &&
(CSET_IS_TRANSPARENT_PR_TINT(ST_CSET_MENU(ms)) ||
MR_IS_TRANSLUCENT(mr)))
{
/* too slow ... */
return;
}
SetWindowBackgroundWithOffset(
dpy, MR_WINDOW(mr), step_x - current_x, step_y - current_y,
MR_WIDTH(mr), MR_HEIGHT(mr),
&Colorset[ST_CSET_MENU(ms)], Pdepth,
FORE_GC(MST_MENU_INACTIVE_GCS(mr)), False);
if (MR_IS_TRANSLUCENT(mr))
{
Pixmap trans, tmp;
FvwmRenderAttributes fra;
fra.mask = 0;
fra.mask = FRAM_HAVE_TINT;
fra.tint = Colorset[ST_CSET_MENU(ms)].bg;
fra.tint_percent = ST_TRANSLUCENT_PERCENT(ms);
mr->d->x = step_x;
mr->d->y = step_y;

if (current_x == step_x)
{
/*
* Reuse the old pixmap for the part of the menu
* that has not moved. (This can be extended to get
* two new rectangles, one in each direction)
*
* It saves the unmapping of the window and makes
* Things less flickering.
*/
GC my_gc;
unsigned long valuemask = GCSubwindowMode;
XGCValues values;
int out_y = (step_y < 0) ? -step_y : 0;
int delta_y = step_y - current_y;
values.subwindow_mode = IncludeInferiors;
trans = XCreatePixmap(
dpy, MR_WINDOW(mr), MR_WIDTH(mr),
MR_HEIGHT(mr), Pdepth);
my_gc = fvwmlib_XCreateGC(dpy, MR_WINDOW(mr), 0, NULL);
XChangeGC(dpy, my_gc, valuemask, &values);
XClearWindow(dpy, MR_WINDOW(mr));

if (current_y < step_y)
{
XCopyArea(dpy, MR_WINDOW(mr), trans, my_gc, 0,
delta_y, MR_WIDTH(mr),
MR_HEIGHT(mr) - delta_y, 0, 0);
tmp = PGraphicsCreateTranslucent(
dpy, MR_WINDOW(mr), &fra,
BACK_GC(ST_MENU_INACTIVE_GCS(ms)),
current_x, current_y + MR_HEIGHT(mr),
MR_WIDTH(mr), delta_y);
XCopyArea(dpy, tmp, trans, my_gc, 0, 0,
MR_WIDTH(mr), delta_y,
0, MR_HEIGHT(mr) - delta_y);
} else {
XCopyArea(dpy, MR_WINDOW(mr), trans, my_gc,
0, 0, MR_WIDTH(mr),
MR_HEIGHT(mr) + delta_y,
0, -delta_y);
tmp = PGraphicsCreateTranslucent(
dpy, MR_WINDOW(mr), &fra,
BACK_GC(ST_MENU_INACTIVE_GCS(ms)),
current_x, step_y, MR_WIDTH(mr),
-delta_y);
XCopyArea(dpy, tmp, trans, my_gc, 0, 0,
MR_WIDTH(mr), -delta_y, 0, out_y);
}
XFreePixmap(dpy, tmp);
XFreeGC(dpy, my_gc);
} else {
XUnmapWindow(dpy, MR_WINDOW(mr));
trans = PGraphicsCreateTranslucent(
dpy, MR_WINDOW(mr), &fra,
BACK_GC(ST_MENU_INACTIVE_GCS(ms)),
step_x, step_y, MR_WIDTH(mr),
MR_HEIGHT(mr));
XMapRaised(dpy, MR_WINDOW(mr));
}
XSetWindowBackgroundPixmap(dpy, MR_WINDOW(mr), trans);
XFreePixmap(dpy, trans);
if (current_x == step_x)
{
/* Redraw the border */
RelieveRectangle(
dpy, MR_WINDOW(mr), 0, 0, MR_WIDTH(mr) - 1,
MR_HEIGHT(mr) - 1, (Pdepth < 2) ?
SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)) :
HILIGHT_GC(MST_MENU_INACTIVE_GCS(mr)),
SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)),
MST_BORDER_WIDTH(mr));
}
}
else
{
SetWindowBackgroundWithOffset(
dpy, MR_WINDOW(mr), step_x - current_x,
step_y - current_y, MR_WIDTH(mr), MR_HEIGHT(mr),
&Colorset[ST_CSET_MENU(ms)], Pdepth,
FORE_GC(MST_MENU_INACTIVE_GCS(mr)), False);
}
}


Expand Down Expand Up @@ -5883,10 +6040,7 @@ void repaint_transparent_menu(
}
if (!is_bg_set)
{
SetWindowBackground(
dpy, MR_WINDOW(mr), MR_WIDTH(mr), MR_HEIGHT(mr),
&Colorset[ST_CSET_MENU(ms)], Pdepth,
FORE_GC(MST_MENU_INACTIVE_GCS(mr)), False);
update_transparent_menu_bg(prtm, x, y, x, y, end_x, end_y);
}
/* redraw the background of non active item */
for (mi = MR_FIRST_ITEM(mr); mi != NULL; mi = MI_NEXT_ITEM(mi))
Expand Down Expand Up @@ -6522,7 +6676,10 @@ void UpdateMenuColorset(int cset)
&Colorset[ST_CSET_MENU(ms2)],
Pdepth,
FORE_GC(MST_MENU_INACTIVE_GCS(mr)),
True);
False);
XClearArea(
dpy, MR_WINDOW(mr), 0, 0,
MR_WIDTH(mr), MR_HEIGHT(mr), True);
}
else if (ST_CSET_ACTIVE(ms2) == cset ||
ST_CSET_GREYED(ms2) == cset)
Expand Down
14 changes: 14 additions & 0 deletions fvwm/menustyle.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ static int menustyle_get_styleopt_index(char *option)
"TitleFont",
"VerticalMargins",
"UniqueHotkeyActivatesImmediate",
"Translucent",
NULL
};

Expand Down Expand Up @@ -487,6 +488,7 @@ MenuStyle *menustyle_parse_style(F_CMD_ARGS)
ST_SCROLL_OFF_PAGE(tmpms) = 1;
ST_DO_HILIGHT_TITLE_BACK(tmpms) = 0;
ST_USING_DEFAULT_TITLEFONT(tmpms) = True;
ST_TRANSLUCENT_PERCENT(tmpms) = 100;
has_gc_changed = True;
option = "fvwm";
}
Expand Down Expand Up @@ -1072,6 +1074,18 @@ MenuStyle *menustyle_parse_style(F_CMD_ARGS)
ST_HOTKEY_ACTIVATES_IMMEDIATE(tmpms) = on;
break;

case 55: /* Translucent */
if (!on ||
GetIntegerArguments(args, NULL, val, 1) == 0 ||
*val < 0 || *val > 100)
{
/* 100 percent means not translucent */
ST_TRANSLUCENT_PERCENT(tmpms) = 100;
} else {
ST_TRANSLUCENT_PERCENT(tmpms) = *val;
}
break;

#if 0
case 99: /* PositionHints */
/* to be implemented */
Expand Down
7 changes: 7 additions & 0 deletions fvwm/menustyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@
#define MST_PTITLEFONT(m) ((m)->s->ms->look.pTitleFont)
#define ST_FONT_HEIGHT(s) ((s)->look.FontHeight)
#define MST_FONT_HEIGHT(m) ((m)->s->ms->look.FontHeight)
#define ST_TRANSLUCENT_PERCENT(s) ((s)->look.TranslucentPercent)
#define MST_TRANSLUCENT_PERCENT(m) ((m)->s->ms->look.TranslucentPercent)
#define ST_IS_TRANSLUCENT(s) ((s)->look.TranslucentPercent != 100)
#define MST_IS_TRANSLUCENT(m) ((m)->s->ms->look.TranslucentPercent != 100)


/* feel */
#define ST_IS_ANIMATED(s) ((s)->feel.flags.is_animated)
#define MST_IS_ANIMATED(m) ((m)->s->ms->feel.flags.is_animated)
Expand Down Expand Up @@ -268,6 +274,7 @@ typedef struct MenuLook
FlocaleFont *pStdFont;
FlocaleFont *pTitleFont;
int FontHeight;
int TranslucentPercent;
} MenuLook;

typedef struct MenuStyle
Expand Down
4 changes: 1 addition & 3 deletions libs/PictureGraphics.c
Original file line number Diff line number Diff line change
Expand Up @@ -1361,7 +1361,7 @@ void PGraphicsTintRectangle(
}
}

#if 0 /* humm... maybe useful one day with menus */
/* Used for translucent menus */
Pixmap PGraphicsCreateTranslucent(
Display *dpy, Window win, FvwmRenderAttributes *fra, GC gc,
int x, int y, int width, int height)
Expand Down Expand Up @@ -1470,8 +1470,6 @@ Pixmap PGraphicsCreateTranslucent(
}
return r;
}
#endif


/* never tested and used ! */
Pixmap PGraphicsCreateDitherPixmap(
Expand Down
4 changes: 4 additions & 0 deletions libs/PictureGraphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ void PGraphicsTintRectangle(
Drawable dest, Bool dest_is_a_window, GC gc, GC mono_gc, GC alpha_gc,
int dest_x, int dest_y, int dest_w, int dest_h);

Pixmap PGraphicsCreateTranslucent(
Display *dpy, Window win, FvwmRenderAttributes *fra, GC gc,
int x, int y, int width, int height);

/* never used ! */
Pixmap PGraphicsCreateDitherPixmap(
Display *dpy, Window win, Drawable src, Pixmap mask, int depth, GC gc,
Expand Down

0 comments on commit 31c22d6

Please sign in to comment.