X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fcanvas%2Fcanvas.cc;h=be0f25d7a24f1afed057e85dbc10ba947e4a35fd;hb=c4c7598adbc9e5eca5fe04a23bb7e88fc0989f34;hp=baced0761c2cd5c4e94ea87e9b42d618e162e450;hpb=2a53154892a25d7d93208df18eee27e7ef9b0aaf;p=ardour.git diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc index baced0761c..be0f25d7a2 100644 --- a/libs/canvas/canvas.cc +++ b/libs/canvas/canvas.cc @@ -32,9 +32,11 @@ #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" +#include "canvas/utils.h" using namespace std; using namespace ArdourCanvas; @@ -44,6 +46,7 @@ uint32_t Canvas::tooltip_timeout_msecs = 750; /** Construct a new Canvas */ Canvas::Canvas () : _root (this) + , _bg_color (rgba_to_color (0, 1.0, 0.0, 1.0)) { set_epoch (); } @@ -113,7 +116,7 @@ Canvas::render (Rect const & area, Cairo::RefPtr const & context _root.render (*draw, context); -#ifdef CANVAS_DEBUG +#if defined CANVAS_DEBUG && !PLATFORM_WINDOWS if (getenv ("CANVAS_HARLEQUIN_DEBUGGING")) { // This transparently colors the rect being rendered, after it has been drawn. double r = (random() % 65536) /65536.0; @@ -340,6 +343,18 @@ Canvas::set_tooltip_timeout (uint32_t msecs) tooltip_timeout_msecs = msecs; } +void +Canvas::set_background_color (Color c) +{ + _bg_color = c; + + boost::optional r = _root.bounding_box(); + + if (r) { + request_redraw (_root.item_to_window (r.get())); + } +} + void GtkCanvas::re_enter () { @@ -359,7 +374,8 @@ GtkCanvas::GtkCanvas () { /* 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 @@ -720,6 +736,18 @@ GtkCanvas::item_going_away (Item* item, boost::optional bounding_box) } +void +GtkCanvas::on_size_allocate (Gtk::Allocation& a) +{ + EventBox::on_size_allocate (a); +#ifdef USE_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 +} + /** Handler for GDK expose events. * @param ev Event. * @return true if the event was handled. @@ -727,21 +755,38 @@ GtkCanvas::item_going_away (Item* item, boost::optional bounding_box) bool GtkCanvas::on_expose_event (GdkEventExpose* ev) { - Cairo::RefPtr cairo_context = get_window()->create_cairo_context (); - render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), cairo_context); - return true; -} - -/** @return Our Cairo context, or 0 if we don't have one */ -Cairo::RefPtr -GtkCanvas::context () -{ - Glib::RefPtr w = get_window (); - if (!w) { - return Cairo::RefPtr (); +#ifdef USE_CAIRO_IMAGE_SURFACE + if (!canvas_image) { + canvas_image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, get_width(), get_height()); } + Cairo::RefPtr draw_context = Cairo::Context::create (canvas_image); + Cairo::RefPtr window_context = get_window()->create_cairo_context (); +#else + Cairo::RefPtr draw_context = get_window()->create_cairo_context (); +#endif - return w->create_cairo_context (); + /* draw background color */ + + draw_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height); + draw_context->clip_preserve (); + set_source_rgba (draw_context, _bg_color); + draw_context->fill (); + + /* render canvas */ + + 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 + /* 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); + window_context->clip (); + window_context->set_source (canvas_image, 0, 0); + window_context->set_operator (Cairo::OPERATOR_SOURCE); + window_context->paint (); +#endif + + return true; } /** Handler for GDK scroll events. @@ -770,6 +815,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. @@ -900,6 +967,11 @@ GtkCanvas::on_leave_notify_event (GdkEventCrossing* ev) stop_tooltip_timeout (); hide_tooltip (); break; + default: + /* we don't care about any other kind + of leave event (notably GDK_NOTIFY_INFERIOR) + */ + break; } _new_current_item = 0; deliver_enter_leave (Duple (ev->x, ev->y), ev->state);