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);

Reply via email to