Browse Source

A tooltip is no longer hidden if the mouse cursor is moving towards it

merge-requests/382/head
eidheim 8 years ago
parent
commit
3d166a8988
  1. 15
      src/source.cc
  2. 62
      src/tooltips.cc
  3. 15
      src/tooltips.h
  4. 2
      tests/stubs/tooltips.cc

15
src/source.cc

@ -515,6 +515,13 @@ void Source::View::configure() {
} }
void Source::View::setup_tooltip_and_dialog_events() { void Source::View::setup_tooltip_and_dialog_events() {
type_tooltips.on_motion=[this] {
delayed_tooltips_connection.disconnect();
};
diagnostic_tooltips.on_motion=[this] {
delayed_tooltips_connection.disconnect();
};
get_buffer()->signal_changed().connect([this] { get_buffer()->signal_changed().connect([this] {
hide_tooltips(); hide_tooltips();
}); });
@ -526,6 +533,8 @@ void Source::View::setup_tooltip_and_dialog_events() {
gdouble x=event->x; gdouble x=event->x;
gdouble y=event->y; gdouble y=event->y;
delayed_tooltips_connection=Glib::signal_timeout().connect([this, x, y]() { delayed_tooltips_connection=Glib::signal_timeout().connect([this, x, y]() {
type_tooltips.hide();
diagnostic_tooltips.hide();
Tooltips::init(); Tooltips::init();
Gdk::Rectangle rectangle(x, y, 1, 1); Gdk::Rectangle rectangle(x, y, 1, 1);
if(parsed) { if(parsed) {
@ -535,8 +544,10 @@ void Source::View::setup_tooltip_and_dialog_events() {
return false; return false;
}, 100); }, 100);
} }
type_tooltips.hide(); auto last_mouse_pos = std::make_pair(on_motion_last_x, on_motion_last_y);
diagnostic_tooltips.hide(); auto mouse_pos = std::make_pair(event->x, event->y);
type_tooltips.hide(last_mouse_pos, mouse_pos);
diagnostic_tooltips.hide(last_mouse_pos, mouse_pos);
} }
on_motion_last_x=event->x; on_motion_last_x=event->x;
on_motion_last_y=event->y; on_motion_last_y=event->y;

62
src/tooltips.cc

@ -35,7 +35,7 @@ void Tooltip::update() {
} }
} }
void Tooltip::show(bool disregard_drawn) { void Tooltip::show(bool disregard_drawn, const std::function<void()> &on_motion) {
Tooltips::shown_tooltips.emplace(this); Tooltips::shown_tooltips.emplace(this);
if(!window) { if(!window) {
@ -55,6 +55,12 @@ void Tooltip::show(bool disregard_drawn) {
window->set_skip_taskbar_hint(true); window->set_skip_taskbar_hint(true);
window->set_default_size(0, 0); window->set_default_size(0, 0);
window->signal_motion_notify_event().connect([on_motion](GdkEventMotion *event) {
if(on_motion)
on_motion();
return false;
});
window->get_style_context()->add_class("juci_tooltip_window"); window->get_style_context()->add_class("juci_tooltip_window");
auto visual = window->get_screen()->get_rgba_visual(); auto visual = window->get_screen()->get_rgba_visual();
if(visual) if(visual)
@ -91,13 +97,13 @@ void Tooltip::show(bool disregard_drawn) {
int root_x, root_y; int root_x, root_y;
dialog->get_position(root_x, root_y); dialog->get_position(root_x, root_y);
root_x-=3; // -1xpadding root_x-=3; // -1xpadding
position.first=root_x; rectangle.set_x(root_x);
position.second=root_y-size.second; rectangle.set_y(root_y-size.second);
if(position.second<0) if(rectangle.get_y()<0)
position.second=0; rectangle.set_y(0);
} }
} }
window->move(position.first, position.second); window->move(rectangle.get_x(), rectangle.get_y());
}); });
} }
@ -115,7 +121,6 @@ void Tooltip::show(bool disregard_drawn) {
if(root_y<size.second) if(root_y<size.second)
root_x+=visible_rect.get_width()*0.1; root_x+=visible_rect.get_width()*0.1;
} }
Gdk::Rectangle rectangle;
rectangle.set_x(root_x); rectangle.set_x(root_x);
rectangle.set_y(std::max(0, root_y-size.second)); rectangle.set_y(std::max(0, root_y-size.second));
rectangle.set_width(size.first); rectangle.set_width(size.first);
@ -136,16 +141,39 @@ void Tooltip::show(bool disregard_drawn) {
Tooltips::drawn_tooltips_rectangle=rectangle; Tooltips::drawn_tooltips_rectangle=rectangle;
} }
position={rectangle.get_x(), rectangle.get_y()};
if(window->get_realized()) if(window->get_realized())
window->move(position.first, position.second); window->move(rectangle.get_x(), rectangle.get_y());
window->show_all(); window->show_all();
shown=true;
} }
void Tooltip::hide() { void Tooltip::hide(const std::pair<int, int> &last_mouse_pos, const std::pair<int, int> &mouse_pos) {
// Keep tooltip if mouse is moving towards it
// Calculated using dot product between the mouse_pos vector and the corners of the tooltip window
if(text_view && window && shown && last_mouse_pos.first!=-1 && last_mouse_pos.second!=-1 && mouse_pos.first!=-1 && mouse_pos.second!=-1) {
static int root_x, root_y;
text_view->get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(last_mouse_pos.first, last_mouse_pos.second, root_x, root_y);
int diff_x=mouse_pos.first-last_mouse_pos.first;
int diff_y=mouse_pos.second-last_mouse_pos.second;
class Corner {
public:
Corner(int x, int y): x(x-root_x), y(y-root_y) {}
int x, y;
};
std::vector<Corner> corners;
corners.emplace_back(rectangle.get_x(), rectangle.get_y());
corners.emplace_back(rectangle.get_x()+rectangle.get_width(), rectangle.get_y());
corners.emplace_back(rectangle.get_x(), rectangle.get_y()+rectangle.get_height());
corners.emplace_back(rectangle.get_x()+rectangle.get_width(), rectangle.get_y()+rectangle.get_height());
for(auto &corner: corners) {
if(diff_x*corner.x + diff_y*corner.y >= 0)
return;
}
}
Tooltips::shown_tooltips.erase(this); Tooltips::shown_tooltips.erase(this);
if(window) if(window)
window->hide(); window->hide();
shown=false;
} }
void Tooltip::wrap_lines() { void Tooltip::wrap_lines() {
@ -196,10 +224,8 @@ void Tooltip::wrap_lines() {
void Tooltips::show(const Gdk::Rectangle& rectangle, bool disregard_drawn) { void Tooltips::show(const Gdk::Rectangle& rectangle, bool disregard_drawn) {
for(auto &tooltip : tooltip_list) { for(auto &tooltip : tooltip_list) {
tooltip.update(); tooltip.update();
if(rectangle.intersects(tooltip.activation_rectangle)) { if(rectangle.intersects(tooltip.activation_rectangle))
tooltip.show(disregard_drawn); tooltip.show(disregard_drawn, on_motion);
shown=true;
}
else else
tooltip.hide(); tooltip.hide();
} }
@ -208,13 +234,11 @@ void Tooltips::show(const Gdk::Rectangle& rectangle, bool disregard_drawn) {
void Tooltips::show(bool disregard_drawn) { void Tooltips::show(bool disregard_drawn) {
for(auto &tooltip : tooltip_list) { for(auto &tooltip : tooltip_list) {
tooltip.update(); tooltip.update();
tooltip.show(disregard_drawn); tooltip.show(disregard_drawn, on_motion);
shown=true;
} }
} }
void Tooltips::hide() { void Tooltips::hide(const std::pair<int, int> &last_mouse_pos, const std::pair<int, int> &mouse_pos) {
for(auto &tooltip : tooltip_list) for(auto &tooltip : tooltip_list)
tooltip.hide(); tooltip.hide(last_mouse_pos, mouse_pos);
shown=false;
} }

15
src/tooltips.h

@ -12,8 +12,8 @@ public:
~Tooltip(); ~Tooltip();
void update(); void update();
void show(bool disregard_drawn=false); void show(bool disregard_drawn=false, const std::function<void()> &on_motion=nullptr);
void hide(); void hide(const std::pair<int, int> &last_mouse_pos = {-1, -1}, const std::pair<int, int> &mouse_pos = {-1, -1});
Gdk::Rectangle activation_rectangle; Gdk::Rectangle activation_rectangle;
Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark; Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark;
@ -27,17 +27,20 @@ private:
std::function<Glib::RefPtr<Gtk::TextBuffer>()> create_tooltip_buffer; std::function<Glib::RefPtr<Gtk::TextBuffer>()> create_tooltip_buffer;
Gtk::TextView *text_view; Gtk::TextView *text_view;
std::pair<int, int> size; std::pair<int, int> size;
std::pair<int, int> position; Gdk::Rectangle rectangle;
bool shown=false;
}; };
class Tooltips { class Tooltips {
public: public:
static std::set<Tooltip*> shown_tooltips; static std::set<Tooltip*> shown_tooltips;
static Gdk::Rectangle drawn_tooltips_rectangle;
static void init() {drawn_tooltips_rectangle=Gdk::Rectangle();} static void init() {drawn_tooltips_rectangle=Gdk::Rectangle();}
void show(const Gdk::Rectangle& rectangle, bool disregard_drawn=false); void show(const Gdk::Rectangle& rectangle, bool disregard_drawn=false);
void show(bool disregard_drawn=false); void show(bool disregard_drawn=false);
bool shown=false; void hide(const std::pair<int, int> &last_mouse_pos = {-1, -1}, const std::pair<int, int> &mouse_pos = {-1, -1});
void hide();
void clear() {tooltip_list.clear();}; void clear() {tooltip_list.clear();};
template<typename... Ts> template<typename... Ts>
@ -45,7 +48,7 @@ public:
tooltip_list.emplace_back(std::forward<Ts>(params)...); tooltip_list.emplace_back(std::forward<Ts>(params)...);
} }
static Gdk::Rectangle drawn_tooltips_rectangle; std::function<void()> on_motion;
private: private:
std::list<Tooltip> tooltip_list; std::list<Tooltip> tooltip_list;

2
tests/stubs/tooltips.cc

@ -13,4 +13,4 @@ void Tooltips::show(Gdk::Rectangle const&, bool) {}
void Tooltips::show(bool) {} void Tooltips::show(bool) {}
void Tooltips::hide() {} void Tooltips::hide(const std::pair<int, int> &, const std::pair<int, int> &) {}

Loading…
Cancel
Save