Good morning/evening, It seems that most modern GUIs try to highlight a widget under the mouse pointer. This visual feedback is especially useful for closely-spaced widgets like fvwm buttons in window titlebar, so I'm attaching a patch which implements this functionality.
A few notes: 1. I used Jesús Guerrero's hover patch as a starting point (But rather than allowing user to specify "hover" styles in the configuration, my patch simply highlights the existing button pixmap without any configuration requirements) 2. I know very little about xlib programming ;-( so I would not be too surprised if the patch turns out to fundamentally stupid (it does work for me) 3. There seem to be some kind of build issue (missing Xrender library) triggered by the patch when compiling fvwm modules: I had to do make LIBS=-lXrender to get fvwm to compile. 4. There is a already a bug report in fvwm bug-tracker requesting this kind of functionality http://www.fvwm.org/cgi-bin/fvwm-bug/enhancements?id=321 What do you think? Ilya diff -r -u fvwm-2.5.27/fvwm/borders.c fvwm-2.5.27-wrk/fvwm/borders.c --- fvwm-2.5.27/fvwm/borders.c 2009-02-08 02:32:40.000000000 -0800 +++ fvwm-2.5.27-wrk/fvwm/borders.c 2009-03-16 11:50:18.000000000 -0700 @@ -67,7 +67,7 @@ /* ---------------------------- imports ------------------------------------ */ extern Window PressedW; - +extern Window HoverW; /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ @@ -3395,6 +3395,21 @@ p = border_create_decor_pixmap(td->cd, &(td->layout.button_g[button])); /* set the background tile */ border_set_button_pixmap(fw, td, button, &p, FW_W_BUTTON(fw, button)); + + if (HoverW == FW_W_BUTTON( fw, button)) + { + rectangle* decor_g = &(td->layout.button_g[button]); + Pixmap hoverPixmap = None; + /* printf("redrawing hover button %d\n", button);*/ + fflush(stdout); + hoverPixmap = CreateLighterPixmap( dpy, p, decor_g->width, + decor_g->height, Pdepth, 50); + if (hoverPixmap) { + XFreePixmap(dpy, p); + p = hoverPixmap; + } + } + /* apply the pixmap and destroy it */ border_set_part_background(FW_W_BUTTON(fw, button), p); XFreePixmap(dpy, p); diff -r -u fvwm-2.5.27/fvwm/events.c fvwm-2.5.27-wrk/fvwm/events.c --- fvwm-2.5.27/fvwm/events.c 2009-02-08 02:59:03.000000000 -0800 +++ fvwm-2.5.27-wrk/fvwm/events.c 2009-03-15 18:18:58.000000000 -0700 @@ -163,6 +163,7 @@ int last_event_type = 0; Window PressedW = None; +Window HoverW = None; /* ---------------------------- local functions ---------------------------- */ @@ -1713,6 +1714,29 @@ return; } +/* enter is 1 when entering, 0 when leaving*/ +static void redraw_hover(FvwmWindow* fw, Window w, int enter) +{ + if (fw) + { + int i; + if ( ! enter) { + HoverW = None; + border_redraw_decorations(fw); + return; + } + + for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) + { + if (w == FW_W_BUTTON(fw, i)) + { + HoverW = FW_W_BUTTON(fw, i); + } + } + border_redraw_decorations(fw); + } +} + /* ---------------------------- event handlers ----------------------------- */ void HandleButtonPress(const evh_args_t *ea) @@ -1919,6 +1943,8 @@ ewp = &te->xcrossing; ENTER_DBG((stderr, "++++++++ en (%d): fw 0x%08x w 0x%08x sw 0x%08xmode 0x%x detail 0x%x '%s'\n", ++ecount, (int)fw, (int)ewp->window, (int)ewp->subwindow, ewp->mode, ewp->detail, fw?fw->visible_name:"(none)")); + redraw_hover(fw, ewp->window, 1); + if ( ewp->window == Scr.Root && ewp->detail == NotifyInferior && ewp->mode == NotifyNormal) @@ -2594,6 +2620,8 @@ DBUG("HandleLeaveNotify", "Routine Entered"); + redraw_hover(fw, te->xcrossing.window, 0); + ENTER_DBG((stderr, "-------- ln (%d): fw 0x%08x w 0x%08x sw 0x%08x mode 0x%x detail 0x%x '%s'\n", ++ecount, (int)fw, (int)te->xcrossing.window, (int)te->xcrossing.subwindow, te->xcrossing.mode, te->xcrossing.detail, fw?fw->visible_name:"(none)")); lwp = &te->xcrossing; if ( diff -r -u fvwm-2.5.27/libs/Graphics.c fvwm-2.5.27-wrk/libs/Graphics.c --- fvwm-2.5.27/libs/Graphics.c 2007-01-27 03:33:16.000000000 -0800 +++ fvwm-2.5.27-wrk/libs/Graphics.c 2009-03-16 11:43:00.000000000 -0700 @@ -33,6 +33,7 @@ #include "libs/gravity.h" #include "libs/FImage.h" #include "libs/Graphics.h" +#include "libs/ColorUtils.h" /* ---------------------------- local definitions -------------------------- */ @@ -178,6 +179,80 @@ return; } +Pixmap CreateLighterPixmap( + Display *dpy, Pixmap src, int src_width, int src_height, int depth, + int percent) +{ + + int i, j; + FImage *src_fim = NULL; + FImage *fim = NULL; + Pixmap pixmap = None; /* result*/ + int error = False; + GC my_gc = None; + + pixmap = XCreatePixmap(dpy, src, src_width, src_height, depth); + + if (pixmap == None) + { + return None; + } + my_gc = fvwmlib_XCreateGC(dpy, pixmap, 0, 0); + + if (!(src_fim = FGetFImage( + dpy, src, Pvisual, depth, 0, 0, src_width, src_height, + AllPlanes, ZPixmap))) + { + error = True; + goto bail; + } + + if (!(fim = FCreateFImage( + dpy, Pvisual, depth, ZPixmap, src_width, src_height))) + { + error = True; + goto bail; + } + + for ( i=0; i< src_width; i++) + { + + for ( j=0; j< src_height; j++) + { + long pixel = XGetPixel( src_fim->im, i,j); + + pixel = GetTintedPixel( pixel, PictureWhitePixel(), + percent); + + XPutPixel( fim->im, i, j, pixel); + } + + } + FPutFImage(dpy, pixmap, my_gc, fim, 0, 0, 0, 0, src_width, src_height); + +bail: + + if (my_gc) + { + XFreeGC(dpy, my_gc); + } + if (error && pixmap) + { + XFreePixmap( dpy, pixmap); + pixmap = None; + } + if (fim) + { + FDestroyFImage(dpy, fim); + } + if (src_fim) + { + FDestroyFImage(dpy, src_fim); + } + + return pixmap; +} + /* Creates a pixmap that is a horizontally stretched version of the input * pixmap */ diff -r -u fvwm-2.5.27/libs/Graphics.h fvwm-2.5.27-wrk/libs/Graphics.h --- fvwm-2.5.27/libs/Graphics.h 2007-01-27 03:28:55.000000000 -0800 +++ fvwm-2.5.27-wrk/libs/Graphics.h 2009-03-15 20:37:44.000000000 -0700 @@ -38,6 +38,10 @@ Display *dpy, Pixmap src, int src_width, int src_height, int depth, GC gc, int rotation); +Pixmap CreateLighterPixmap( + Display *dpy, Pixmap src, int src_width, int src_height, int depth, + int percent); /* donot need graphics context?*/ + GC fvwmlib_XCreateGC( Display *display, Drawable drawable, unsigned long valuemask, XGCValues *values);