X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fcanvas%2Fcanvas.cc;h=fb06b06b975eb49eca34793a18cfee07c125742f;hb=eb5161b6012a73eae0a288d71727edcfd161d16a;hp=97e001abba750f846543e5862808ee2a54b0f160;hpb=86ac64d5288baf2ad5d020b2b872598b7ee84d62;p=ardour.git diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc index 97e001abba..fb06b06b97 100644 --- a/libs/canvas/canvas.cc +++ b/libs/canvas/canvas.cc @@ -44,6 +44,11 @@ #include "canvas/scroll_group.h" #include "canvas/utils.h" +#ifdef __APPLE__ +#include +#include "gtkmm2ext/nsglview.h" +#endif + using namespace std; using namespace ArdourCanvas; @@ -390,6 +395,7 @@ GtkCanvas::GtkCanvas () , current_tooltip_item (0) , tooltip_window (0) , _in_dtor (false) + , _nsglview (0) { /* these are the events we want to know about */ add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | @@ -397,6 +403,16 @@ GtkCanvas::GtkCanvas () Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK); } +void +GtkCanvas::use_nsglview () +{ + assert (!_nsglview); + assert (!is_realized()); +#ifdef ARDOUR_CANVAS_NSVIEW_TAG // patched gdkquartz.h + _nsglview = Gtkmm2ext::nsglview_create (this); +#endif +} + void GtkCanvas::pick_current_item (int state) { @@ -713,6 +729,15 @@ GtkCanvas::deliver_event (GdkEvent* event) return false; } +void +GtkCanvas::item_shown_or_hidden (Item* item) +{ + if (item == current_tooltip_item) { + stop_tooltip_timeout (); + } + Canvas::item_shown_or_hidden (item); +} + /** Called when an item is being destroyed. * @param item Item being destroyed. * @param bounding_box Last known bounding box of the item. @@ -755,6 +780,17 @@ GtkCanvas::item_going_away (Item* item, Rect bounding_box) } +void +GtkCanvas::on_realize () +{ + Gtk::EventBox::on_realize(); +#ifdef __APPLE__ + if (_nsglview) { + Gtkmm2ext::nsglview_overlay (_nsglview, get_window()->gobj()); + } +#endif +} + void GtkCanvas::on_size_allocate (Gtk::Allocation& a) { @@ -771,6 +807,18 @@ GtkCanvas::on_size_allocate (Gtk::Allocation& a) #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE } #endif + +#ifdef __APPLE__ + if (_nsglview) { + gint xx, yy; + gtk_widget_translate_coordinates( + GTK_WIDGET(gobj()), + GTK_WIDGET(get_toplevel()->gobj()), + 0, 0, &xx, &yy); + Gtkmm2ext::nsglview_resize (_nsglview, xx, yy, a.get_width(), a.get_height()); + } +#endif + } /** Handler for GDK expose events. @@ -783,6 +831,16 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev) if (_in_dtor) { return true; } +#ifdef __APPLE__ + if (_nsglview) { + Gtkmm2ext::nsglview_queue_draw (_nsglview, ev->area.x, ev->area.y, ev->area.width, ev->area.height); + return true; + } +#endif + +#ifdef CANVAS_PROFILE + const int64_t start = g_get_monotonic_time (); +#endif #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE Cairo::RefPtr draw_context; @@ -806,17 +864,34 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev) Cairo::RefPtr draw_context = get_window()->create_cairo_context (); #endif - /* draw background color */ + draw_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height); + draw_context->clip(); + +#ifdef __APPLE__ + /* group calls cairo_quartz_surface_create() which + * effectively uses a CGBitmapContext + image-surface + * + * This avoids expensive argb32_image_mark_image() during drawing. + * Although the final paint() operation still takes the slow path + * through image_mark_image instead of ColorMaskCopyARGB888_sse :( + * + * profiling indicates a speed up of factor 2. (~ 5-10ms render time, + * instead of 10-20ms, which is still slow compared to XCB and win32 surfaces (~0.2 ms) + * + * Fixing this for good likely involves changes to GdkQuartzWindow, GdkQuartzView + */ + draw_context->push_group (); +#endif + /* 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 */ 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); + Canvas::render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), draw_context); } else { GdkRectangle* rects; @@ -825,11 +900,16 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev) 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); + Canvas::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 __APPLE__ + draw_context->pop_group_to_source (); + draw_context->paint (); +#endif + #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE if (getenv("ARDOUR_IMAGE_SURFACE")) { #endif @@ -846,6 +926,12 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev) } #endif +#ifdef CANVAS_PROFILE + const int64_t end = g_get_monotonic_time (); + const int64_t elapsed = end - start; + printf ("GtkCanvas::on_expose_event %f ms\n", elapsed / 1000.f); +#endif + return true; } @@ -1038,6 +1124,36 @@ GtkCanvas::on_leave_notify_event (GdkEventCrossing* ev) return true; } +void +GtkCanvas::on_map () +{ + Gtk::EventBox::on_map(); +#ifdef __APPLE__ + if (_nsglview) { + Gtkmm2ext::nsglview_set_visible (_nsglview, true); + Gtk::Allocation a = get_allocation(); + gint xx, yy; + gtk_widget_translate_coordinates( + GTK_WIDGET(gobj()), + GTK_WIDGET(get_toplevel()->gobj()), + 0, 0, &xx, &yy); + Gtkmm2ext::nsglview_resize (_nsglview, xx, yy, a.get_width(), a.get_height()); + } +#endif +} + +void +GtkCanvas::on_unmap () +{ + stop_tooltip_timeout (); + Gtk::EventBox::on_unmap(); +#ifdef __APPLE__ + if (_nsglview) { + Gtkmm2ext::nsglview_set_visible (_nsglview, false); + } +#endif +} + /** Called to request a redraw of our canvas. * @param area Area to redraw, in window coordinates. */ @@ -1122,7 +1238,7 @@ GtkCanvas::unfocus (Item* item) } /** @return The visible area of the canvas, in window coordinates */ -Rect +ArdourCanvas::Rect GtkCanvas::visible_area () const { return Rect (0, 0, get_allocation().get_width (), get_allocation().get_height ());