#include "canvas/scroll_group.h"
#include "canvas/utils.h"
+#ifdef __APPLE__
+#include <gdk/gdk.h>
+#include "gtkmm2ext/nsglview.h"
+#endif
+
using namespace std;
using namespace ArdourCanvas;
, 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 |
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)
{
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.
}
+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)
{
#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.
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<Cairo::Context> draw_context;
Cairo::RefPtr<Cairo::Context> 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;
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
}
#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;
}
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.
*/
}
/** @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 ());