diff options
author | Jorge Arellano Cid <jcid@dillo.org> | 2012-11-14 09:56:01 -0300 |
---|---|---|
committer | Jorge Arellano Cid <jcid@dillo.org> | 2012-11-14 09:56:01 -0300 |
commit | f1a5856eeda2ee4c17dd7b1d4dfa0d8f4330ad3e (patch) | |
tree | c2e47588894418653eeb58b8050cf9e868ff34f9 /src/tipwin.cc | |
parent | b56864d7c883b204f55bf31eb09fc30a68ab4f10 (diff) |
Avoid scroll flickering with a custom tooltip class (TipWin) & a custom button
Removed the workaround [1] that added a full UI and viewport
redraw to conceal the lingering tooltips bug [2]. It produced
annoying scroll flickering when the mouse was in the UI but
outside the viewport (e.g. over the panel).
This is more a FLTK bug than anything; the FLTK team's plan is
to fix it in FLTK3, and also extend the tooltips API.
As FLTK3 may take long to be released, and porting dillo to it
is non-trivial (if both events ever come to happen), this custom
solution looks quite reasonable for the present times.
The patch introduces a new CustButton class that uses TipWin,
and thus the tooltip handling is no longer handled by FLTK. This
patch switches the UI buttons to the new CustButton.
1] http://lists.auriga.wearlab.de/pipermail/dillo-dev/2011-July/008515.html
2] http://lists.auriga.wearlab.de/pipermail/dillo-dev/2011-July/008494.html
Diffstat (limited to 'src/tipwin.cc')
-rw-r--r-- | src/tipwin.cc | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/tipwin.cc b/src/tipwin.cc new file mode 100644 index 00000000..cec3dbaa --- /dev/null +++ b/src/tipwin.cc @@ -0,0 +1,181 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <FL/fl_draw.H> +#include <FL/Fl.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Menu_Window.H> +#include <FL/Fl_Tooltip.H> +#include <FL/Fl_Button.H> + +#include "tipwin.hh" + +/* + * Forward declarations + */ +static void show_timeout(void*); +static void recent_timeout(void*); + +/* + * Custom tooltip window + */ +TipWin::TipWin() : Fl_Menu_Window(1, 1) // will autosize +{ + bgcolor = fl_color_cube(FL_NUM_RED - 1, FL_NUM_GREEN - 1, FL_NUM_BLUE - 2); + recent = 0; + strcpy(tip, ""); + cur_widget = NULL; + set_override(); // no border + end(); +} + +void TipWin::draw() +{ + draw_box(FL_BORDER_BOX, 0, 0, w(), h(), bgcolor); + fl_color(FL_BLACK); + fl_font(labelfont(), labelsize()); + fl_draw(tip, 3, 3, w() - 6, h() - 6, + //Fl_Align(FL_ALIGN_LEFT | FL_ALIGN_WRAP)); + Fl_Align(FL_ALIGN_LEFT)); +} + +void TipWin::value(const char *s) { + // Recalc size of window + snprintf(tip, sizeof(tip) - 1, "%s", s); + fl_font(labelfont(), labelsize()); + int W = w(), H = h(); + W = 0; + fl_measure(tip, W, H, 0); + W += 8; H += 8; + size(W, H); + redraw(); +} + +void TipWin::do_show(void *wid) { + cur_widget = wid; // Keep track of requesting widget + Fl::add_timeout(recent ? 0.2f : 0.8f, show_timeout); +} + +void TipWin::do_hide() { + Fl::remove_timeout(show_timeout); + if (shown()) { + hide(); + recent = 1; + Fl::add_timeout(0.8f, recent_timeout); + } +} + +void TipWin::recent_tooltip(int val) { + recent = val; +} + +//-------------------------------------------------------------------------- + +TipWin *my_tipwin(void) +{ + static TipWin *tw = NULL; + + if (!tw) { + Fl_Group *save = Fl_Group::current(); // save current widget.. + tw = new TipWin(); // ..because this trashes it + tw->hide(); // start hidden + Fl_Group::current(save); // ..then back to previous. + } + return tw; +} + +static void show_timeout(void*) { + // if offscreen, move tip ABOVE mouse instead + int scr_x, scr_y, scr_w, scr_h; + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); + int ty = Fl::event_y_root() + 20; + if (ty + my_tipwin()->h() > scr_h) + ty = Fl::event_y_root() - 20 - my_tipwin()->h(); + if (ty < 0) ty = 0; + + my_tipwin()->position(Fl::event_x_root(), ty); + my_tipwin()->show(); + my_tipwin()->recent_tooltip(0); +} + +static void recent_timeout(void*) { + my_tipwin()->recent_tooltip(0); +} + + +//--------------------------------------------------------------------------- + +/* + * A Button sharing a custom tooltip window + */ +TipWinButton::TipWinButton(int x, int y, int w, int h, const char *l) : + Fl_Button(x, y, w, h, l) +{ + tipwin = my_tipwin(); + mytooltip = strdup("empty"); +} + +TipWinButton::~TipWinButton(void) +{ + tipwin->cancel(this); // cancel tooltip if shown + free(mytooltip); +} + +int TipWinButton::handle(int e) +{ + switch (e) { + case FL_ENTER: + tipwin->value(mytooltip); + tipwin->do_show(this); + break; + case FL_PUSH: // push mouse + case FL_RELEASE: // release mouse + case FL_HIDE: // widget goes away + case FL_LEAVE: // leave focus + tipwin->do_hide(); + break; + } + return (Fl_Button::handle(e)); +} + +void TipWinButton::set_tooltip(const char *s) +{ + free(mytooltip); + mytooltip = strdup(s); +} + + +//--------------------------------------------------------------------------- + +/* + * A Light Button sharing a custom tooltip window + */ +CustButton::CustButton(int x, int y, int w, int h, const char *l) : + TipWinButton(x,y,w,h,l) +{ + norm_color = color(); + light_color = 17; // {17,26,51} +} + +int CustButton::handle(int e) +{ + if (active()) { + if (e == FL_ENTER) { + color(light_color); + redraw(); + } else if (e == FL_LEAVE || e == FL_RELEASE || e == FL_HIDE) { + color(norm_color); + redraw(); + } + } else if (e == FL_DEACTIVATE && color() != norm_color) { + color(norm_color); + redraw(); + } + return TipWinButton::handle(e); +} + +void CustButton::hl_color(Fl_Color col) +{ + light_color = col; +} + |