summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJorge Arellano Cid <jcid@dillo.org>2012-11-14 09:56:01 -0300
committerJorge Arellano Cid <jcid@dillo.org>2012-11-14 09:56:01 -0300
commitf1a5856eeda2ee4c17dd7b1d4dfa0d8f4330ad3e (patch)
treec2e47588894418653eeb58b8050cf9e868ff34f9
parentb56864d7c883b204f55bf31eb09fc30a68ab4f10 (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
-rw-r--r--src/Makefile.am2
-rw-r--r--src/tipwin.cc181
-rw-r--r--src/tipwin.hh58
-rw-r--r--src/ui.cc65
-rw-r--r--src/ui.hh36
-rw-r--r--src/uicmd.cc6
6 files changed, 276 insertions, 72 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index ceba3e01..c4c7949a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,6 +25,8 @@ dillo_SOURCES = \
dillo.cc \
paths.cc \
paths.hh \
+ tipwin.cc \
+ tipwin.hh \
ui.cc \
ui.hh \
uicmd.cc \
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;
+}
+
diff --git a/src/tipwin.hh b/src/tipwin.hh
new file mode 100644
index 00000000..77ffa60e
--- /dev/null
+++ b/src/tipwin.hh
@@ -0,0 +1,58 @@
+#ifndef __TIPWIN_HH__
+#define __TIPWIN_HH__
+
+#include <FL/Fl_Menu_Window.H>
+#include <FL/Fl_Button.H>
+
+
+/*
+ * Custom tooltip window
+ */
+class TipWin : public Fl_Menu_Window {
+ char tip[256];
+ int bgcolor, recent;
+ void *cur_widget;
+public:
+ TipWin();
+ void draw();
+ void value(const char *s);
+ void do_show(void *wid);
+ void do_hide();
+ void recent_tooltip(int val);
+
+ void cancel(void *wid) {
+ if (wid == cur_widget) { cur_widget = NULL; do_hide(); }
+ }
+};
+
+extern TipWin *my_tipwin(void);
+
+
+/*
+ * A Button sharing a custom tooltip window
+ */
+class TipWinButton : public Fl_Button {
+ char *mytooltip;
+ TipWin *tipwin;
+ public:
+ TipWinButton(int x, int y, int w, int h, const char *l = 0);
+ ~TipWinButton();
+ virtual int handle(int e);
+
+ void set_tooltip(const char *s);
+};
+
+/*
+ * A button that highlights on mouse over
+ */
+class CustButton : public TipWinButton {
+ Fl_Color norm_color, light_color;
+public:
+ CustButton(int x, int y, int w, int h, const char *l=0);
+ virtual int handle(int e);
+ void hl_color(Fl_Color col);
+};
+
+
+#endif // __TIPWIN_HH__
+
diff --git a/src/ui.cc b/src/ui.cc
index 5755cf98..6d53251b 100644
--- a/src/ui.cc
+++ b/src/ui.cc
@@ -19,6 +19,7 @@
#include "msg.h"
#include "timeout.hh"
#include "utf8.hh"
+#include "tipwin.hh"
#include <FL/Fl.H>
#include <FL/Fl_Pixmap.H>
@@ -158,10 +159,10 @@ int CustInput::handle(int e)
/*
* Used to handle "paste" within the toolbar's Clear button.
*/
-class CustPasteButton : public CustLightButton {
+class CustPasteButton : public CustButton {
public:
CustPasteButton(int x, int y, int w, int h, const char *l=0) :
- CustLightButton(x,y,w,h,l) {};
+ CustButton(x,y,w,h,l) {};
int handle(int e);
};
@@ -175,7 +176,7 @@ int CustPasteButton::handle(int e)
return 1;
}
}
- return CustLightButton::handle(e);
+ return CustButton::handle(e);
}
//----------------------------------------------------------------------------
@@ -379,13 +380,13 @@ static void bugmeter_cb(Fl_Widget *wid, void *data)
/*
* Make a generic navigation button
*/
-Fl_Button *UI::make_button(const char *label, Fl_Image *img, Fl_Image *deimg,
- int b_n, int start)
+CustButton *UI::make_button(const char *label, Fl_Image *img, Fl_Image *deimg,
+ int b_n, int start)
{
if (start)
p_xpos = 0;
- Fl_Button *b = new CustLightButton(p_xpos, 0, bw, bh, (lbl) ? label : NULL);
+ CustButton *b = new CustButton(p_xpos, 0, bw, bh, (lbl) ? label : NULL);
if (img)
b->image(img);
if (deimg)
@@ -413,14 +414,14 @@ void UI::make_toolbar(int tw, int th)
Bookmarks = make_button("Book", icons->ImgBook, NULL, UI_BOOK);
Tools = make_button("Tools", icons->ImgTools, NULL, UI_TOOLS);
- Back->tooltip("Previous page");
- Forw->tooltip("Next page");
- Home->tooltip("Go to the Home page");
- Reload->tooltip("Reload");
- Save->tooltip("Save this page");
- Stop->tooltip("Stop loading");
- Bookmarks->tooltip("View bookmarks");
- Tools->tooltip("Settings");
+ Back->set_tooltip("Previous page");
+ Forw->set_tooltip("Next page");
+ Home->set_tooltip("Go to the Home page");
+ Reload->set_tooltip("Reload");
+ Save->set_tooltip("Save this page");
+ Stop->set_tooltip("Stop loading");
+ Bookmarks->set_tooltip("View bookmarks");
+ Tools->set_tooltip("Settings");
}
/*
@@ -428,14 +429,14 @@ void UI::make_toolbar(int tw, int th)
*/
void UI::make_location(int ww)
{
- Fl_Button *b;
+ CustButton *b;
- Clear = b = new CustPasteButton(p_xpos,0,16,lh,0);
+ b = Clear = (CustButton*) new CustPasteButton(p_xpos,0,16,lh,0);
b->image(icons->ImgClear);
b->callback(clear_cb, this);
b->clear_visible_focus();
b->box(FL_THIN_UP_BOX);
- b->tooltip("Clear the URL box.\nMiddle-click to paste a URL.");
+ b->set_tooltip("Clear the URL box.\nMiddle-click to paste a URL.");
p_xpos += b->w();
Fl_Input *i = Location = new CustInput(p_xpos,0,ww-p_xpos-32,lh,0);
@@ -445,20 +446,20 @@ void UI::make_location(int ww)
i->tooltip("Location");
p_xpos += i->w();
- Search = b = new CustLightButton(p_xpos,0,16,lh,0);
+ Search = b = new CustButton(p_xpos,0,16,lh,0);
b->image(icons->ImgSearch);
b->callback(search_cb, this);
b->clear_visible_focus();
b->box(FL_THIN_UP_BOX);
- b->tooltip("Search the Web");
+ b->set_tooltip("Search the Web");
p_xpos += b->w();
- Help = b = new CustLightButton(p_xpos,0,16,lh,0);
+ Help = b = new CustButton(p_xpos,0,16,lh,0);
b->image(icons->ImgHelp);
b->callback(help_cb, this);
b->clear_visible_focus();
b->box(FL_THIN_UP_BOX);
- b->tooltip("Help");
+ b->set_tooltip("Help");
p_xpos += b->w();
}
@@ -489,10 +490,10 @@ void UI::make_progress_bars(int wide, int thin_up)
*/
Fl_Widget *UI::make_filemenu_button()
{
- Fl_Button *btn;
+ CustButton *btn;
int w = 0, h = 0, padding;
- FileButton = btn = new Fl_Button(p_xpos,0,bw,bh,"W");
+ FileButton = btn = new CustButton(p_xpos,0,bw,bh,"W");
btn->labeltype(FL_FREE_LABELTYPE);
btn->measure_label(w, h);
padding = w;
@@ -504,7 +505,7 @@ Fl_Widget *UI::make_filemenu_button()
_MSG("UI::make_filemenu_button w=%d h=%d padding=%d\n", w, h, padding);
btn->box(FL_THIN_UP_BOX);
btn->callback(filemenu_cb, this);
- btn->tooltip("File menu");
+ btn->set_tooltip("File menu");
btn->clear_visible_focus();
if (!prefs.show_filemenu)
btn->hide();
@@ -610,11 +611,11 @@ void UI::make_status_bar(int ww, int wh)
StatusOutput->color(FL_GRAY_RAMP + 18);
// Bug Meter
- BugMeter = new CustLightButton(ww-bm_w,wh-sh,bm_w,sh);
+ BugMeter = new CustButton(ww-bm_w,wh-sh,bm_w,sh);
BugMeter->image(icons->ImgMeterOK);
BugMeter->box(FL_THIN_DOWN_BOX);
BugMeter->align(FL_ALIGN_INSIDE | FL_ALIGN_TEXT_NEXT_TO_IMAGE);
- BugMeter->tooltip("Show HTML bugs\n(right-click for menu)");
+ BugMeter->set_tooltip("Show HTML bugs\n(right-click for menu)");
BugMeter->callback(bugmeter_cb, this);
BugMeter->clear_visible_focus();
@@ -632,7 +633,6 @@ UI::UI(int x, int y, int ui_w, int ui_h, const char* label, const UI *cur_ui) :
LocBar = NavBar = StatusBar = NULL;
Tabs = NULL;
- TabTooltip = NULL;
TopGroup = this;
TopGroup->box(FL_NO_BOX);
clear_flag(SHORTCUT_LABEL);
@@ -691,7 +691,6 @@ UI::UI(int x, int y, int ui_w, int ui_h, const char* label, const UI *cur_ui) :
UI::~UI()
{
_MSG("UI::~UI()\n");
- dFree(TabTooltip);
}
/*
@@ -703,16 +702,6 @@ int UI::handle(int event)
int ret = 0;
if (event == FL_KEYBOARD) {
- /* WORKAROUND: remove the Panel's fltk-tooltip.
- * Although the expose event is delivered, it has an offset. This
- * extra call avoids the lingering tooltip. */
- if (!Fl::event_inside(Main) &&
- (Fl::event_inside((Fl_Widget*)tabs()) ||
- Fl::event_inside(NavBar) ||
- (LocBar && Fl::event_inside(LocBar)) ||
- (StatusBar && Fl::event_inside(StatusBar))))
- window()->damage(FL_DAMAGE_EXPOSE,0,0,1,1);
-
return 0; // Receive as shortcut
} else if (event == FL_SHORTCUT) {
KeysCommand_t cmd = Keys::getKeyCmd();
diff --git a/src/ui.hh b/src/ui.hh
index ddc350a5..ac47b13c 100644
--- a/src/ui.hh
+++ b/src/ui.hh
@@ -11,6 +11,7 @@
#include <FL/Fl_Image.H>
#include <FL/Fl_Tabs.H>
+#include "tipwin.hh"
#include "findbar.hh"
typedef enum {
@@ -115,43 +116,16 @@ public:
}
};
-/*
- * A button that highlights on mouse over
- */
-class CustLightButton : public Fl_Button {
- Fl_Color norm_color, light_color;
-public:
- CustLightButton(int x, int y, int w, int h, const char *l=0) :
- Fl_Button(x,y,w,h,l) { norm_color = color(); light_color = 51; };
- virtual int handle(int e)
- {
- if (active()) {
- if (e == FL_ENTER) {
- color(light_color); // {17,26,51}
- 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 Fl_Button::handle(e);
- }
- void hl_color(Fl_Color col) { light_color = col; };
-};
//
// UI class definition -------------------------------------------------------
//
class UI : public CustGroupVertical {
CustTabs *Tabs;
- char *TabTooltip;
CustGroupVertical *TopGroup;
- Fl_Button *Back, *Forw, *Home, *Reload, *Save, *Stop, *Bookmarks, *Tools,
- *Clear, *Search, *Help, *BugMeter, *FileButton;
+ CustButton *Back, *Forw, *Home, *Reload, *Save, *Stop, *Bookmarks,
+ *Tools, *Clear, *Search, *Help, *BugMeter, *FileButton;
CustGroupHorizontal *LocBar, *NavBar, *StatusBar;
Fl_Input *Location;
CustProgressBox *PProg, *IProg;
@@ -166,8 +140,8 @@ class UI : public CustGroupVertical {
bool PanelTemporary;
UIPanelmode Panelmode;
- Fl_Button *make_button(const char *label, Fl_Image *img,
- Fl_Image*deimg, int b_n, int start = 0);
+ CustButton *make_button(const char *label, Fl_Image *img, Fl_Image*deimg,
+ int b_n, int start = 0);
void make_toolbar(int tw, int th);
void make_location(int ww);
void make_progress_bars(int wide, int thin_up);
diff --git a/src/uicmd.cc b/src/uicmd.cc
index 40279a60..27ad7d49 100644
--- a/src/uicmd.cc
+++ b/src/uicmd.cc
@@ -107,7 +107,7 @@ class CustTabs : public Fl_Group {
Fl_Scroll *Scroll;
Fl_Pack *Pack;
Fl_Group *Control;
- CustLightButton *CloseBtn;
+ CustButton *CloseBtn;
int tabcolor_inactive, tabcolor_active;
void update_pack_offset(void);
@@ -151,12 +151,12 @@ public:
/* control buttons go inside a group */
Control = new Fl_Group(ww-ctl_w,0,ctl_w,ctab_h);
- CloseBtn = new CustLightButton(ww-ctl_w+2,0,btn_w,ctab_h, "X");
+ CloseBtn = new CustButton(ww-ctl_w+2,0,btn_w,ctab_h, "X");
CloseBtn->box(FL_THIN_UP_BOX);
CloseBtn->labelcolor(0x00641000);
CloseBtn->hl_color(FL_WHITE);
CloseBtn->clear_visible_focus();
- CloseBtn->tooltip(prefs.right_click_closes_tab ?
+ CloseBtn->set_tooltip(prefs.right_click_closes_tab ?
"Close current tab.\nor Right-click tab label to close." :
"Close current tab.\nor Middle-click tab label to close.");
CloseBtn->callback(close_tab_btn_cb, this);