X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fgtkmm2ext%2Fcairo_widget.cc;h=8349a685fa4dc50340278298d7bb7c9a7a3197a3;hb=ca98c7a0511a2282e3f3fcfd7c17d5c508be47bd;hp=2ffb2b47f3ad4665ea03117ecc157c406357eba8;hpb=198c4d1d8899296da19daff08de2395d13494fc1;p=ardour.git diff --git a/libs/gtkmm2ext/cairo_widget.cc b/libs/gtkmm2ext/cairo_widget.cc index 2ffb2b47f3..8349a685fa 100644 --- a/libs/gtkmm2ext/cairo_widget.cc +++ b/libs/gtkmm2ext/cairo_widget.cc @@ -23,22 +23,21 @@ #include "gtkmm2ext/cairo_widget.h" #include "gtkmm2ext/gui_thread.h" -#include "i18n.h" +#include "pbd/i18n.h" static const char* has_cairo_widget_background_info = "has_cairo_widget_background_info"; bool CairoWidget::_flat_buttons = false; bool CairoWidget::_widget_prelight = true; -static void noop() { } -sigc::slot CairoWidget::focus_handler (sigc::ptr_fun (noop)); +sigc::slot CairoWidget::focus_handler; void CairoWidget::set_source_rgb_a( cairo_t* cr, Gdk::Color col, float a) //ToDo: this one and the Canvas version should be in a shared file (?) { float r = col.get_red_p (); float g = col.get_green_p (); float b = col.get_blue_p (); - + cairo_set_source_rgba(cr, r, g, b, a); } @@ -61,10 +60,103 @@ CairoWidget::~CairoWidget () bool CairoWidget::on_button_press_event (GdkEventButton*) { - focus_handler(); + focus_handler (this); return false; } + +#ifdef USE_TRACKS_CODE_FEATURES + +/* This is Tracks version of this method. + + The use of get_visible_window() in this method is an abuse of the GDK/GTK + semantics. It can and may break on different GDK backends, and uses a + side-effect/unintended behaviour in GDK/GTK to try to accomplish something + which should be done differently. I (Paul) have confirmed this with the GTK + development team. + + For this reason, this code is not acceptable for ordinary merging into the Ardour libraries. + + Ardour Developers: you are not obligated to maintain the internals of this + implementation in the face of build-time environment changes (e.g. -D + defines etc). +*/ + +bool +CairoWidget::on_expose_event (GdkEventExpose *ev) +{ + cairo_rectangle_t expose_area; + expose_area.width = ev->area.width; + expose_area.height = ev->area.height; + +#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_CAIRO_WIDGET + Cairo::RefPtr cr; + if (get_visible_window ()) { + expose_area.x = 0; + expose_area.y = 0; + if (!_image_surface) { + _image_surface = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, get_width(), get_height()); + } + cr = Cairo::Context::create (_image_surface); + } else { + expose_area.x = ev->area.x; + expose_area.y = ev->area.y; + cr = get_window()->create_cairo_context (); + } +#else + expose_area.x = ev->area.x; + expose_area.y = ev->area.y; + Cairo::RefPtr cr = get_window()->create_cairo_context (); +#endif + + cr->rectangle (expose_area.x, expose_area.y, expose_area.width, expose_area.height); + cr->clip (); + + /* paint expose area the color of the parent window bg + */ + + if (get_visible_window ()) { + Gdk::Color bg (get_parent_bg()); + cr->rectangle (expose_area.x, expose_area.y, expose_area.width, expose_area.height); + cr->set_source_rgb (bg.get_red_p(), bg.get_green_p(), bg.get_blue_p()); + cr->fill (); + } + + render (cr->cobj(), &expose_area); + +#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_CAIRO_WIDGET + if(get_visible_window ()) { + _image_surface->flush(); + /* now blit our private surface back to the GDK one */ + + Cairo::RefPtr cairo_context = get_window()->create_cairo_context (); + + cairo_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height); + cairo_context->clip (); + cairo_context->set_source (_image_surface, ev->area.x, ev->area.y); + cairo_context->set_operator (Cairo::OPERATOR_OVER); + cairo_context->paint (); + } +#endif + + Gtk::Widget* child = get_child (); + + if (child) { + propagate_expose (*child, ev); + } + + return true; +} + +#else + +/* Ardour mainline: not using Tracks code features. + + Tracks Developers: please do not modify this version of + ::on_expose_event(). The version used by Tracks is before the preceding + #else and contains hacks required for the Tracks GUI to work. +*/ + bool CairoWidget::on_expose_event (GdkEventExpose *ev) { @@ -90,15 +182,21 @@ CairoWidget::on_expose_event (GdkEventExpose *ev) #endif cr->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height); - cr->clip_preserve (); - /* paint expose area the color of the parent window bg - */ - - Gdk::Color bg (get_parent_bg()); - - cr->set_source_rgb (bg.get_red_p(), bg.get_green_p(), bg.get_blue_p()); - cr->fill (); + if (_need_bg) { + cr->clip_preserve (); + + /* paint expose area the color of the parent window bg + */ + + Gdk::Color bg (get_parent_bg()); + + cr->set_source_rgb (bg.get_red_p(), bg.get_green_p(), bg.get_blue_p()); + cr->fill (); + } else { + std::cerr << get_name() << " skipped bg fill\n"; + cr->clip (); + } cairo_rectangle_t expose_area; expose_area.x = ev->area.x; @@ -130,15 +228,21 @@ CairoWidget::on_expose_event (GdkEventExpose *ev) return true; } +#endif + /** Marks the widget as dirty, so that render () will be called on * the next GTK expose event. */ void -CairoWidget::set_dirty () +CairoWidget::set_dirty (cairo_rectangle_t *area) { ENSURE_GUI_THREAD (*this, &CairoWidget::set_dirty); - queue_draw (); + if (!area) { + queue_draw (); + } else { + queue_draw_area (area->x, area->y, area->width, area->height); + } } /** Handle a size allocation. @@ -289,7 +393,7 @@ CairoWidget::set_widget_prelight (bool yn) } void -CairoWidget::set_focus_handler (sigc::slot s) +CairoWidget::set_focus_handler (sigc::slot s) { focus_handler = s; }