+
+/** Try to fit a string into a given horizontal space by ellipsizing it.
+ * @param cr Cairo context in which the text will be plotted.
+ * @param name Text.
+ * @param avail Available horizontal space.
+ * @return (Text, possibly ellipsized) and (horizontal size of text)
+ */
+
+std::pair<std::string, double>
+Gtkmm2ext::fit_to_pixels (cairo_t* cr, std::string name, double avail)
+{
+ /* XXX hopefully there exists a more efficient way of doing this */
+
+ bool abbreviated = false;
+ uint32_t width = 0;
+
+ while (1) {
+ cairo_text_extents_t ext;
+ cairo_text_extents (cr, name.c_str(), &ext);
+
+ if (ext.width < avail || name.length() <= 4) {
+ width = ext.width;
+ break;
+ }
+
+ if (abbreviated) {
+ name = name.substr (0, name.length() - 4) + "...";
+ } else {
+ name = name.substr (0, name.length() - 3) + "...";
+ abbreviated = true;
+ }
+ }
+
+ return std::make_pair (name, width);
+}
+
+Gtk::Label *
+Gtkmm2ext::left_aligned_label (string const & t)
+{
+ Gtk::Label* l = new Gtk::Label (t);
+ l->set_alignment (0, 0.5);
+ return l;
+}
+
+static bool
+make_null_tooltip (int, int, bool, const Glib::RefPtr<Gtk::Tooltip>& t)
+{
+ t->set_tip_area (Gdk::Rectangle (0, 0, 0, 0));
+ return true;
+}
+
+/** Hackily arrange for the provided widget to have no tooltip,
+ * and also to stop any other widget from providing one while
+ * the mouse is over w.
+ */
+void
+Gtkmm2ext::set_no_tooltip_whatsoever (Gtk::Widget& w)
+{
+ w.property_has_tooltip() = true;
+ w.signal_query_tooltip().connect (sigc::ptr_fun (make_null_tooltip));
+}
+
+void
+Gtkmm2ext::enable_tooltips ()
+{
+ gtk_rc_parse_string ("gtk-enable-tooltips = 1");
+}
+
+void
+Gtkmm2ext::disable_tooltips ()
+{
+ gtk_rc_parse_string ("gtk-enable-tooltips = 0");
+}
+
+bool
+Gtkmm2ext::event_inside_widget_window (Gtk::Widget& widget, GdkEvent* ev)
+{
+ gdouble evx, evy;
+
+ if (!gdk_event_get_root_coords (ev, &evx, &evy)) {
+ return false;
+ }
+
+ gint wx;
+ gint wy;
+ gint width, height, depth;
+ gint x, y;
+
+ Glib::RefPtr<Gdk::Window> widget_window = widget.get_window();
+
+ widget_window->get_geometry (x, y, width, height, depth);
+ widget_window->get_root_origin (wx, wy);
+
+ if ((evx >= wx && evx < wx + width) &&
+ (evy >= wy && evy < wy + height)) {
+ return true;
+ }
+
+ return false;
+}
+
+const char*
+Gtkmm2ext::event_type_string (int event_type)
+{
+ switch (event_type) {
+ case GDK_NOTHING:
+ return "nothing";
+ case GDK_DELETE:
+ return "delete";
+ case GDK_DESTROY:
+ return "destroy";
+ case GDK_EXPOSE:
+ return "expose";
+ case GDK_MOTION_NOTIFY:
+ return "motion_notify";
+ case GDK_BUTTON_PRESS:
+ return "button_press";
+ case GDK_2BUTTON_PRESS:
+ return "2button_press";
+ case GDK_3BUTTON_PRESS:
+ return "3button_press";
+ case GDK_BUTTON_RELEASE:
+ return "button_release";
+ case GDK_KEY_PRESS:
+ return "key_press";
+ case GDK_KEY_RELEASE:
+ return "key_release";
+ case GDK_ENTER_NOTIFY:
+ return "enter_notify";
+ case GDK_LEAVE_NOTIFY:
+ return "leave_notify";
+ case GDK_FOCUS_CHANGE:
+ return "focus_change";
+ case GDK_CONFIGURE:
+ return "configure";
+ case GDK_MAP:
+ return "map";
+ case GDK_UNMAP:
+ return "unmap";
+ case GDK_PROPERTY_NOTIFY:
+ return "property_notify";
+ case GDK_SELECTION_CLEAR:
+ return "selection_clear";
+ case GDK_SELECTION_REQUEST:
+ return "selection_request";
+ case GDK_SELECTION_NOTIFY:
+ return "selection_notify";
+ case GDK_PROXIMITY_IN:
+ return "proximity_in";
+ case GDK_PROXIMITY_OUT:
+ return "proximity_out";
+ case GDK_DRAG_ENTER:
+ return "drag_enter";
+ case GDK_DRAG_LEAVE:
+ return "drag_leave";
+ case GDK_DRAG_MOTION:
+ return "drag_motion";
+ case GDK_DRAG_STATUS:
+ return "drag_status";
+ case GDK_DROP_START:
+ return "drop_start";
+ case GDK_DROP_FINISHED:
+ return "drop_finished";
+ case GDK_CLIENT_EVENT:
+ return "client_event";
+ case GDK_VISIBILITY_NOTIFY:
+ return "visibility_notify";
+ case GDK_NO_EXPOSE:
+ return "no_expose";
+ case GDK_SCROLL:
+ return "scroll";
+ case GDK_WINDOW_STATE:
+ return "window_state";
+ case GDK_SETTING:
+ return "setting";
+ case GDK_OWNER_CHANGE:
+ return "owner_change";
+ case GDK_GRAB_BROKEN:
+ return "grab_broken";
+ case GDK_DAMAGE:
+ return "damage";
+ }
+
+ return "unknown";
+}