X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fcanvas%2Fcanvas.cc;h=7f9c8fab597337ca08f71b7bbeb45cae266ee673;hb=8671e109fcc5089226da1e539bc8b7327b2cb5bf;hp=975dcf84efd9d89a73b4f08849e759a2ce767eb0;hpb=ef56948d4acaa55f76ca6bde3eba3faec168ffdb;p=ardour.git diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc index 975dcf84ef..7f9c8fab59 100644 --- a/libs/canvas/canvas.cc +++ b/libs/canvas/canvas.cc @@ -18,6 +18,10 @@ */ +#if !defined USE_CAIRO_IMAGE_SURFACE && !defined NDEBUG +#define OPTIONAL_CAIRO_IMAGE_SURFACE +#endif + /** @file canvas/canvas.cc * @brief Implementation of the main canvas classes. */ @@ -32,6 +36,7 @@ #include "pbd/stacktrace.h" #include "canvas/canvas.h" +#include "canvas/colors.h" #include "canvas/debug.h" #include "canvas/line.h" #include "canvas/scroll_group.h" @@ -229,12 +234,7 @@ Canvas::item_changed (Item* item, boost::optional pre_change_bounding_box) Duple Canvas::window_to_canvas (Duple const & d) const { - /* Find the scroll group that covers d (a window coordinate). Scroll groups are only allowed - * as children of the root group, so we just scan its first level - * children and see what we can find. - */ - - std::list const& root_children (_root.items()); + ScrollGroup* best_group = 0; ScrollGroup* sg = 0; /* if the coordinates are negative, clamp to zero and find the item @@ -250,14 +250,33 @@ Canvas::window_to_canvas (Duple const & d) const in_window.y = 0; } - for (std::list::const_iterator i = root_children.begin(); i != root_children.end(); ++i) { - if (((sg = dynamic_cast(*i)) != 0) && sg->covers_window (in_window)) { - break; + for (list::const_iterator s = scrollers.begin(); s != scrollers.end(); ++s) { + + if ((*s)->covers_window (in_window)) { + sg = *s; + + /* XXX January 22nd 2015: leaving this in place for now + * but I think it fixes a bug that really should be + * fixed in a different way (and will be) by my next + * commit. But it may still be relevant. + */ + + /* If scroll groups overlap, choose the one with the highest sensitivity, + that is, choose an HV scroll group over an H or V + only group. + */ + if (!best_group || sg->sensitivity() > best_group->sensitivity()) { + best_group = sg; + if (sg->sensitivity() == (ScrollGroup::ScrollsVertically | ScrollGroup::ScrollsHorizontally)) { + /* Can't do any better than this. */ + break; + } + } } } - if (sg) { - return d.translate (sg->scroll_offset()); + if (best_group) { + return d.translate (best_group->scroll_offset()); } return d; @@ -280,7 +299,6 @@ Canvas::canvas_to_window (Duple const & d, bool rounded) const break; } } - if (sg) { wd = d.translate (-sg->scroll_offset()); @@ -368,12 +386,14 @@ GtkCanvas::GtkCanvas () , _new_current_item (0) , _grabbed_item (0) , _focused_item (0) + , _single_exposure (1) , current_tooltip_item (0) , tooltip_window (0) { /* these are the events we want to know about */ add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | - Gdk::SCROLL_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); + Gdk::SCROLL_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | + Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK); } void @@ -514,8 +534,8 @@ GtkCanvas::deliver_enter_leave (Duple const & point, int state) leave_event.type = GDK_LEAVE_NOTIFY; Item* i; - GdkNotifyType enter_detail; - GdkNotifyType leave_detail; + GdkNotifyType enter_detail = GDK_NOTIFY_UNKNOWN; + GdkNotifyType leave_detail = GDK_NOTIFY_UNKNOWN; vector items_to_leave_virtual; vector items_to_enter_virtual; @@ -738,12 +758,18 @@ void GtkCanvas::on_size_allocate (Gtk::Allocation& a) { EventBox::on_size_allocate (a); -#ifdef USE_CAIRO_IMAGE_SURFACE +#ifdef OPTIONAL_CAIRO_IMAGE_SURFACE + if (getenv("ARDOUR_IMAGE_SURFACE")) { +#endif +#if defined USE_CAIRO_IMAGE_SURFACE || defined OPTIONAL_CAIRO_IMAGE_SURFACE /* allocate an image surface as large as the canvas itself */ canvas_image.clear (); canvas_image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, a.get_width(), a.get_height()); #endif +#ifdef OPTIONAL_CAIRO_IMAGE_SURFACE + } +#endif } /** Handler for GDK expose events. @@ -753,7 +779,19 @@ GtkCanvas::on_size_allocate (Gtk::Allocation& a) bool GtkCanvas::on_expose_event (GdkEventExpose* ev) { -#ifdef USE_CAIRO_IMAGE_SURFACE +#ifdef OPTIONAL_CAIRO_IMAGE_SURFACE + Cairo::RefPtr draw_context; + Cairo::RefPtr window_context; + if (getenv("ARDOUR_IMAGE_SURFACE")) { + if (!canvas_image) { + canvas_image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, get_width(), get_height()); + } + draw_context = Cairo::Context::create (canvas_image); + window_context = get_window()->create_cairo_context (); + } else { + draw_context = get_window()->create_cairo_context (); + } +#elif defined USE_CAIRO_IMAGE_SURFACE if (!canvas_image) { canvas_image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, get_width(), get_height()); } @@ -765,20 +803,32 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev) /* draw background color */ - draw_context->save (); draw_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height); - draw_context->clip (); - draw_context->set_operator (Cairo::OPERATOR_SOURCE); + draw_context->clip_preserve (); set_source_rgba (draw_context, _bg_color); - draw_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height); draw_context->fill (); - draw_context->restore (); /* render canvas */ - - render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), draw_context); + if ( _single_exposure ) { + + render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), draw_context); -#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_GTK_CANVAS + } else { + GdkRectangle* rects; + gint nrects; + + gdk_region_get_rectangles (ev->region, &rects, &nrects); + for (gint n = 0; n < nrects; ++n) { + draw_context->set_identity_matrix(); //reset the cairo matrix, just in case someone left it transformed after drawing ( cough ) + render (Rect (rects[n].x, rects[n].y, rects[n].x + rects[n].width, rects[n].y + rects[n].height), draw_context); + } + g_free (rects); + } + +#ifdef OPTIONAL_CAIRO_IMAGE_SURFACE + if (getenv("ARDOUR_IMAGE_SURFACE")) { +#endif +#if defined USE_CAIRO_IMAGE_SURFACE || defined OPTIONAL_CAIRO_IMAGE_SURFACE /* now blit our private surface back to the GDK one */ window_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height); @@ -787,6 +837,9 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev) window_context->set_operator (Cairo::OPERATOR_SOURCE); window_context->paint (); #endif +#ifdef OPTIONAL_CAIRO_IMAGE_SURFACE + } +#endif return true; } @@ -817,6 +870,28 @@ GtkCanvas::on_scroll_event (GdkEventScroll* ev) return deliver_event (reinterpret_cast(©)); } +/** Handler for GDK key press events. + * @param ev Event. + * @return true if the event was handled. + */ +bool +GtkCanvas::on_key_press_event (GdkEventKey* ev) +{ + DEBUG_TRACE (PBD::DEBUG::CanvasEvents, "canvas key press\n"); + return deliver_event (reinterpret_cast(ev)); +} + +/** Handler for GDK key release events. + * @param ev Event. + * @return true if the event was handled. + */ +bool +GtkCanvas::on_key_release_event (GdkEventKey* ev) +{ + DEBUG_TRACE (PBD::DEBUG::CanvasEvents, "canvas key release\n"); + return deliver_event (reinterpret_cast(ev)); +} + /** Handler for GDK button press events. * @param ev Event. * @return true if the event was handled. @@ -1109,7 +1184,7 @@ GtkCanvas::show_tooltip () tooltip_label = manage (new Gtk::Label); tooltip_label->show (); tooltip_window->add (*tooltip_label); - tooltip_window->set_border_width (6); + tooltip_window->set_border_width (1); tooltip_window->set_name ("tooltip"); } @@ -1142,7 +1217,8 @@ GtkCanvas::show_tooltip () * to get it away from the pointer. */ - tooltip_window_origin.x += 20; + tooltip_window_origin.x += 30; + tooltip_window_origin.y += 45; /* move the tooltip window into position */ @@ -1164,6 +1240,11 @@ GtkCanvas::hide_tooltip () if (tooltip_window) { tooltip_window->hide (); + + // Delete the tooltip window so it'll get re-created + // (i.e. properly re-sized) on the next usage. + delete tooltip_window; + tooltip_window = NULL; } }