Index: fvwm/events.c =================================================================== --- fvwm/events.c (revision 12) +++ fvwm/events.c (revision 13) @@ -163,6 +163,7 @@ int last_event_type = 0; Window PressedW = None; +Window HoverW = None; /* ---------------------------- local functions ---------------------------- */ @@ -1713,6 +1714,23 @@ return; } +static void redraw_hover(FvwmWindow* fw, Window w) +{ + if (fw) + { + int i; + 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); + HoverW = None; + } +} + /* ---------------------------- event handlers ----------------------------- */ void HandleButtonPress(const evh_args_t *ea) @@ -1919,6 +1937,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); + if ( ewp->window == Scr.Root && ewp->detail == NotifyInferior && ewp->mode == NotifyNormal) @@ -2593,6 +2613,7 @@ FvwmWindow * const fw = ea->exc->w.fw; DBUG("HandleLeaveNotify", "Routine Entered"); + redraw_hover(fw, te->xcrossing.window); 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; Index: fvwm/fvwm.h =================================================================== --- fvwm/fvwm.h (revision 12) +++ fvwm/fvwm.h (revision 13) @@ -706,6 +706,7 @@ unsigned buttons_lit : NUMBER_OF_TITLE_BUTTONS; unsigned buttons_inverted : NUMBER_OF_TITLE_BUTTONS; unsigned buttons_toggled : NUMBER_OF_TITLE_BUTTONS; + unsigned buttons_hover : NUMBER_OF_TITLE_BUTTONS; unsigned parts_drawn : 12; unsigned parts_lit : 12; unsigned parts_inverted : 12; Index: fvwm/screen.h =================================================================== --- fvwm/screen.h (revision 12) +++ fvwm/screen.h (revision 13) @@ -202,12 +202,16 @@ BS_All = -1, BS_ActiveUp, BS_ActiveDown, + BS_ActiveHover, BS_InactiveUp, BS_InactiveDown, + BS_InactiveHover, BS_ToggledActiveUp, BS_ToggledActiveDown, + BS_ToggledActiveHover, BS_ToggledInactiveUp, BS_ToggledInactiveDown, + BS_ToggledInactiveHover, BS_MaxButtonState, BS_MaxButtonStateMask = BS_MaxButtonState - 1, BS_Active, @@ -220,10 +224,13 @@ BS_AllInactive, BS_AllUp, BS_AllDown, + BS_AllHover, BS_AllActiveUp, BS_AllActiveDown, + BS_AllActiveHover, BS_AllInactiveUp, BS_AllInactiveDown, + BS_AllInactiveHover, BS_MaxButtonStateName } ButtonState; @@ -510,6 +517,7 @@ unsigned use_active_down_buttons : 1; unsigned use_inactive_buttons : 1; unsigned use_inactive_down_buttons : 1; + unsigned use_hover_buttons : 1; } gs; /* global style structure */ struct { Index: fvwm/builtins.c =================================================================== --- fvwm/builtins.c (revision 12) +++ fvwm/builtins.c (revision 13) @@ -93,12 +93,16 @@ { "ActiveUp", "ActiveDown", + "ActiveHover", "InactiveUp", "InactiveDown", + "InactiveHover", "ToggledActiveUp", "ToggledActiveDown", + "ToggledActiveHover", "ToggledInactiveUp", "ToggledInactiveDown", + "ToggledInactiveHover", "Active", "Inactive", "ToggledActive", @@ -109,10 +113,13 @@ "AllInactive", "AllUp", "AllDown", + "AllHover", "AllActiveUp", "AllActiveDown", + "AllActiveHover", "AllInactiveUp", "AllInactiveDown", + "AllInactiveHover", NULL }; Index: fvwm/borders.c =================================================================== --- fvwm/borders.c (revision 12) +++ fvwm/borders.c (revision 13) @@ -65,6 +65,7 @@ /* ---------------------------- imports ------------------------------------ */ extern Window PressedW; +extern Window HoverW; /* ---------------------------- included code files ------------------------ */ @@ -185,6 +186,7 @@ unsigned clear_bmask : NUMBER_OF_TITLE_BUTTONS; unsigned draw_bmask : NUMBER_OF_TITLE_BUTTONS; unsigned max_bmask : NUMBER_OF_TITLE_BUTTONS; + unsigned hover_bmask : NUMBER_OF_TITLE_BUTTONS; ButtonState bstate[NUMBER_OF_TITLE_BUTTONS]; unsigned is_title_pressed : 1; unsigned is_title_lit : 1; @@ -290,8 +292,12 @@ /* rules to get button state */ static ButtonState border_flags_to_button_state( - int is_pressed, int is_lit, int is_toggled) + int is_pressed, int is_lit, int is_toggled, int is_hover) { + if (is_lit && is_hover && Scr.gs.use_hover_buttons) + { + return BS_ActiveHover; + } if (!is_lit && Scr.gs.use_inactive_buttons) { if (is_pressed && Scr.gs.use_inactive_down_buttons) @@ -589,7 +595,7 @@ /* check if state changed */ old_state = border_flags_to_button_state( (fw->decor_state.parts_inverted & PART_TITLE), - (fw->decor_state.parts_lit & PART_TITLE), 0); + (fw->decor_state.parts_lit & PART_TITLE), 0, 0); if (old_state != td->tbstate.tstate) { draw_parts |= PART_TITLE; @@ -613,7 +619,8 @@ old_state = border_flags_to_button_state( (fw->decor_state.buttons_inverted & mask), (fw->decor_state.buttons_lit & mask), - (fw->decor_state.buttons_toggled & mask)); + (fw->decor_state.buttons_toggled & mask), + (fw->decor_state.buttons_hover & mask)); if (old_state != td->tbstate.bstate[i]) { draw_parts |= PART_BUTTONS; @@ -3993,6 +4000,7 @@ fw->decor_state.buttons_inverted = td->tbstate.pressed_bmask; fw->decor_state.buttons_lit = td->tbstate.lit_bmask; fw->decor_state.buttons_toggled = td->tbstate.toggled_bmask; + fw->decor_state.buttons_hover = td->tbstate.hover_bmask; return; } @@ -4259,13 +4267,18 @@ { tbstate->toggled_bmask |= mask; } + if (FW_W_BUTTON(fw, i) == HoverW) + { + tbstate->hover_bmask |= mask; + } tbstate->bstate[i] = border_flags_to_button_state( tbstate->pressed_bmask & mask, tbstate->lit_bmask & mask, - tbstate->toggled_bmask & mask); + tbstate->toggled_bmask & mask, + tbstate->hover_bmask & mask); } tbstate->tstate = border_flags_to_button_state( - tbstate->is_title_pressed, tbstate->is_title_lit, 0); + tbstate->is_title_pressed, tbstate->is_title_lit, 0, 0); } static window_parts border_get_titlebar_descr( @@ -4527,6 +4540,7 @@ fw->decor_state.buttons_lit = 0; fw->decor_state.buttons_inverted = 0; fw->decor_state.buttons_toggled = 0; + fw->decor_state.buttons_hover = 0; return; } memset(&td, 0, sizeof(td)); @@ -4578,6 +4592,7 @@ fw->decor_state.buttons_toggled = (fw->decor_state.buttons_toggled & ~td.tbstate.max_bmask) | td.tbstate.toggled_bmask; + fw->decor_state.buttons_hover &= td.tbstate.hover_bmask; } return; @@ -4668,11 +4683,12 @@ ButtonState bs; int is_pressed; int is_toggled; + int is_hover; int i; /* title */ is_pressed = (FW_W_TITLE(fw) == PressedW); - bs = border_flags_to_button_state(is_pressed, has_focus, 0); + bs = border_flags_to_button_state(is_pressed, has_focus, 0, 0); if (DFS_USE_BORDER_STYLE(TB_STATE(GetDecor(fw, titlebar))[bs].style)) { return 1; @@ -4685,8 +4701,9 @@ } is_pressed = (FW_W_BUTTON(fw, i) == PressedW); is_toggled = (is_button_toggled(fw, i) == True); + is_hover = (FW_W_BUTTON(fw, i) == HoverW); bs = border_flags_to_button_state( - is_pressed, (has_focus == True), is_toggled); + is_pressed, (has_focus == True), is_toggled, is_hover); if (DFS_USE_BORDER_STYLE( TB_STATE(GetDecor(fw, buttons[i]))[bs].style)) { @@ -5147,6 +5164,7 @@ DEFAULT_USE_INACTIVE_BUTTONS; Scr.gs.use_inactive_down_buttons = DEFAULT_USE_INACTIVE_DOWN_BUTTONS; + Scr.gs.use_hover_buttons = 0; return; } first = False; @@ -5168,6 +5186,12 @@ action, &action, DEFAULT_USE_INACTIVE_DOWN_BUTTONS, True); } + else if (StrEquals("hover", token)) + { + Scr.gs.use_hover_buttons = ParseToggleArgument( + action, &action, + 0, True); + } else { Scr.gs.use_active_down_buttons = @@ -5176,6 +5200,7 @@ DEFAULT_USE_INACTIVE_BUTTONS; Scr.gs.use_inactive_down_buttons = DEFAULT_USE_INACTIVE_DOWN_BUTTONS; + Scr.gs.use_hover_buttons = 0; fvwm_msg(ERR, "cmd_button_state", "Unknown button state %s", token); return;