diff --git a/ChangeLog b/ChangeLog index 9c76485e7c..e5870a0984 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2006-04-11 Anders Carlsson + + * gdk/quartz/GdkQuartzView.c: + (-[GdkQuartzView drawRect:]): + * gdk/quartz/gdkdrawable-quartz.c: + (gdk_quartz_ref_cairo_surface): + (_gdk_quartz_drawable_get_context): + (_gdk_quartz_drawable_release_context): + * gdk/quartz/gdkwindow-quartz.c: + (gdk_window_impl_quartz_finalize): + (gdk_window_impl_quartz_class_init): + (gdk_window_impl_quartz_begin_paint_region): + (gdk_window_impl_quartz_end_paint): + (gdk_window_impl_quartz_invalidate_maybe_recurse): + (gdk_window_impl_quartz_process_updates): + (gdk_window_impl_quartz_paintable_init): + (_gdk_window_impl_quartz_get_type): + * gdk/quartz/gdkwindow-quartz.h: + Have GdkWindowImplQuartz implement GdkPaintable. + 2006-04-10 Michael Natterer * gtk/gtktextbufferrichtext.c (gtk_text_buffer_deserialize): diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 9c76485e7c..e5870a0984 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,23 @@ +2006-04-11 Anders Carlsson + + * gdk/quartz/GdkQuartzView.c: + (-[GdkQuartzView drawRect:]): + * gdk/quartz/gdkdrawable-quartz.c: + (gdk_quartz_ref_cairo_surface): + (_gdk_quartz_drawable_get_context): + (_gdk_quartz_drawable_release_context): + * gdk/quartz/gdkwindow-quartz.c: + (gdk_window_impl_quartz_finalize): + (gdk_window_impl_quartz_class_init): + (gdk_window_impl_quartz_begin_paint_region): + (gdk_window_impl_quartz_end_paint): + (gdk_window_impl_quartz_invalidate_maybe_recurse): + (gdk_window_impl_quartz_process_updates): + (gdk_window_impl_quartz_paintable_init): + (_gdk_window_impl_quartz_get_type): + * gdk/quartz/gdkwindow-quartz.h: + Have GdkWindowImplQuartz implement GdkPaintable. + 2006-04-10 Michael Natterer * gtk/gtktextbufferrichtext.c (gtk_text_buffer_deserialize): diff --git a/gdk/quartz/GdkQuartzView.c b/gdk/quartz/GdkQuartzView.c index 979e0e354e..e4089aceb2 100644 --- a/gdk/quartz/GdkQuartzView.c +++ b/gdk/quartz/GdkQuartzView.c @@ -50,32 +50,36 @@ { NSRect bounds = [self bounds]; GdkRectangle gdk_rect; + GdkWindowObject *private = GDK_WINDOW_OBJECT (gdk_window); + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); GDK_QUARTZ_ALLOC_POOL; - /* Draw background */ - if (GDK_WINDOW_OBJECT (gdk_window)->bg_pixmap == NULL) - { - CGContextRef context; - - context = [[NSGraphicsContext currentContext] graphicsPort]; - CGContextSaveGState (context); - - _gdk_quartz_set_context_fill_color_from_pixel (context, gdk_drawable_get_colormap (gdk_window), - GDK_WINDOW_OBJECT (gdk_window)->bg_color.pixel); - - CGContextFillRect (context, CGRectMake (bounds.origin.x, bounds.origin.y, - bounds.size.width, bounds.size.height)); - CGContextRestoreGState (context); - } - - gdk_rect.x = bounds.origin.x; - gdk_rect.y = bounds.origin.y; - gdk_rect.width = bounds.size.width; - gdk_rect.height = bounds.size.height; + gdk_rect.x = rect.origin.x; + gdk_rect.y = rect.origin.y; + gdk_rect.width = rect.size.width; + gdk_rect.height = rect.size.height; - gdk_window_invalidate_rect (gdk_window, &gdk_rect, FALSE); - gdk_window_process_updates (gdk_window, FALSE); + if (private->event_mask & GDK_EXPOSURE_MASK) + { + GdkEvent event; + + event.expose.type = GDK_EXPOSE; + event.expose.window = g_object_ref (gdk_window); + event.expose.send_event = FALSE; + event.expose.count = 0; + event.expose.region = gdk_region_rectangle (&gdk_rect); + event.expose.area = gdk_rect; + + impl->in_paint_rect_count ++; + + (*_gdk_event_func) (&event, _gdk_event_data); + + impl->in_paint_rect_count --; + + g_object_unref (gdk_window); + gdk_region_destroy (event.expose.region); + } GDK_QUARTZ_RELEASE_POOL; } diff --git a/gdk/quartz/gdkdrawable-quartz.c b/gdk/quartz/gdkdrawable-quartz.c index 4f2b136e29..6e5cdd8525 100644 --- a/gdk/quartz/gdkdrawable-quartz.c +++ b/gdk/quartz/gdkdrawable-quartz.c @@ -61,7 +61,7 @@ gdk_quartz_ref_cairo_surface (GdkDrawable *drawable) gdk_drawable_get_size (drawable, &width, &height); - surface = cairo_quartz_surface_create (context, TRUE, width, height); + surface = cairo_quartz_surface_create (context, width, height, TRUE); info = g_new (SurfaceInfo, 1); info->drawable = drawable; @@ -586,6 +586,37 @@ _gdk_quartz_drawable_get_context (GdkDrawable *drawable, gboolean antialias) CGContextSaveGState (context); CGContextSetAllowsAntialiasing (context, antialias); + /* We'll emulate the clipping caused by double buffering here */ + if (impl->begin_paint_count != 0) + { + CGRect rect; + CGRect *cg_rects; + GdkRectangle *rects; + gint n_rects, i; + + gdk_region_get_rectangles (impl->paint_clip_region, + &rects, &n_rects); + + if (n_rects == 1) + cg_rects = ▭ + else + cg_rects = g_new (CGRect, n_rects); + + for (i = 0; i < n_rects; i++) + { + cg_rects[i].origin.x = rects[i].x; + cg_rects[i].origin.y = rects[i].y; + cg_rects[i].size.width = rects[i].width; + cg_rects[i].size.height = rects[i].height; + } + + CGContextClipToRects (context, cg_rects, n_rects); + + g_free (rects); + if (cg_rects != &rect) + g_free (cg_rects); + } + return context; } else if (GDK_IS_PIXMAP_IMPL_QUARTZ (drawable)) @@ -623,7 +654,9 @@ _gdk_quartz_drawable_release_context (GdkDrawable *drawable, CGContextRef contex CGContextRestoreGState (context); CGContextSetAllowsAntialiasing (context, TRUE); - [[NSGraphicsContext currentContext] flushGraphics]; + if (impl->in_paint_rect_count == 0) + CGContextFlush (context); + [impl->view unlockFocus]; [impl->pool release]; } diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index 1f39743f97..92c915c9d3 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -105,6 +105,9 @@ gdk_window_impl_quartz_finalize (GObject *object) if (impl->nscursor) [impl->nscursor release]; + if (impl->paint_clip_region) + gdk_region_destroy (impl->paint_clip_region); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -112,9 +115,12 @@ static void gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass) { GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); + object_class->finalize = gdk_window_impl_quartz_finalize; + drawable_class->get_size = gdk_window_impl_quartz_get_size; /* Visible and clip regions are the same */ @@ -130,6 +136,89 @@ gdk_window_impl_quartz_init (GdkWindowImplQuartz *impl) impl->height = 1; } +static void +gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable, + GdkRegion *region) +{ + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable); + CGContextRef context = _gdk_quartz_drawable_get_context (GDK_DRAWABLE (impl), FALSE); + int i, n_rects; + GdkRectangle *rects; + + if (impl->begin_paint_count == 0) + impl->paint_clip_region = gdk_region_copy (region); + else + gdk_region_union (impl->paint_clip_region, region); + + impl->begin_paint_count ++; + + gdk_region_get_rectangles (region, &rects, &n_rects); + for (i = 0; i < n_rects; i++) + { + _gdk_quartz_set_context_fill_color_from_pixel (context, gdk_drawable_get_colormap (GDK_DRAWABLE_IMPL_QUARTZ (impl)->wrapper), + GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_QUARTZ (impl)->wrapper)->bg_color.pixel); + + CGContextFillRect (context, CGRectMake (rects[i].x, rects[i].y, rects[i].width, rects[i].height)); + + } + g_free (rects); + + _gdk_quartz_drawable_release_context (GDK_DRAWABLE (impl), context); +} + +static void +gdk_window_impl_quartz_end_paint (GdkPaintable *paintable) +{ + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable); + + impl->begin_paint_count --; +} + +static void +gdk_window_impl_quartz_invalidate_maybe_recurse (GdkPaintable *paintable, + GdkRegion *region, + gboolean (*child_func) (GdkWindow *, gpointer), + gpointer user_data) +{ + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable); + int i, n_rects; + GdkRectangle *rects; + + gdk_region_get_rectangles (region, &rects, &n_rects); + + for (i = 0; i < n_rects; i++) + { + [impl->view setNeedsDisplayInRect:NSMakeRect (rects[i].x, rects[i].y, + rects[i].width, rects[i].height)]; + } + + g_free (rects); + + /* FIXME: Check if we need to traverse the children */ +} + +static void +gdk_window_impl_quartz_process_updates (GdkPaintable *paintable, + gboolean update_children) +{ + GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable); + + [impl->view display]; + + /* FIXME: Check if display actually updates the children too */ +} + +static void +gdk_window_impl_quartz_paintable_init (GdkPaintableIface *iface) +{ + iface->begin_paint_region = gdk_window_impl_quartz_begin_paint_region; + iface->end_paint = gdk_window_impl_quartz_end_paint; + + iface->invalidate_maybe_recurse = gdk_window_impl_quartz_invalidate_maybe_recurse; + iface->process_updates = gdk_window_impl_quartz_process_updates; +} + + GType _gdk_window_impl_quartz_get_type (void) { @@ -150,9 +239,19 @@ _gdk_window_impl_quartz_get_type (void) (GInstanceInitFunc) gdk_window_impl_quartz_init, }; + static const GInterfaceInfo paintable_info = + { + (GInterfaceInitFunc) gdk_window_impl_quartz_paintable_init, + NULL, + NULL + }; + object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_QUARTZ, "GdkWindowImplQuartz", &object_info, 0); + g_type_add_interface_static (object_type, + GDK_TYPE_PAINTABLE, + &paintable_info); } return object_type; diff --git a/gdk/quartz/gdkwindow-quartz.h b/gdk/quartz/gdkwindow-quartz.h index 0fe45d1f21..1bbc3cd35c 100644 --- a/gdk/quartz/gdkwindow-quartz.h +++ b/gdk/quartz/gdkwindow-quartz.h @@ -58,6 +58,10 @@ struct _GdkWindowImplQuartz NSAutoreleasePool *pool; NSCursor *nscursor; + + GdkRegion *paint_clip_region; + gint begin_paint_count; + gint in_paint_rect_count; }; struct _GdkWindowImplQuartzClass