[gtk/wip/chergert/quartz4u] macos: avoid recreating views for opaque regions
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/quartz4u] macos: avoid recreating views for opaque regions
- Date: Thu, 4 Jun 2020 00:46:07 +0000 (UTC)
commit 886c9dc496a13f8b55b94055f2d7cb93198f59e4
Author: Christian Hergert <chergert redhat com>
Date: Wed Jun 3 17:44:09 2020 -0700
macos: avoid recreating views for opaque regions
gdk/macos/GdkMacosCairoView.c | 49 +++++++++++++++++++++++++++++++++++++++++--
gdk/macos/GdkMacosCairoView.h | 1 +
2 files changed, 48 insertions(+), 2 deletions(-)
---
diff --git a/gdk/macos/GdkMacosCairoView.c b/gdk/macos/GdkMacosCairoView.c
index 06f1db44a8..e6a31178b4 100644
--- a/gdk/macos/GdkMacosCairoView.c
+++ b/gdk/macos/GdkMacosCairoView.c
@@ -33,6 +33,14 @@
@implementation GdkMacosCairoView
+-(void)dealloc
+{
+ g_clear_pointer (&self->opaque, g_ptr_array_unref);
+ self->transparent = NULL;
+
+ [super dealloc];
+}
+
-(BOOL)isOpaque
{
if ([self window])
@@ -57,6 +65,9 @@
{
[[self->transparent subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
+
+ if (self->opaque->len)
+ g_ptr_array_remove_range (self->opaque, 0, self->opaque->len);
}
-(void)setOpaqueRegion:(cairo_region_t *)region
@@ -64,13 +75,38 @@
NSRect abs_bounds;
guint n_rects;
- [self removeOpaqueChildren];
-
if (region == NULL)
return;
abs_bounds = [self convertRect:[self bounds] toView:nil];
n_rects = cairo_region_num_rectangles (region);
+
+ /* The common case (at least for opaque windows and CSD) is that we will
+ * have either one or two opaque rectangles. If we detect that the same
+ * number of them are available as the previous, we can just resize the
+ * previous ones to avoid adding/removing views at a fast rate while
+ * resizing.
+ */
+ if (n_rects == self->opaque->len)
+ {
+ for (guint i = 0; i < n_rects; i++)
+ {
+ GdkMacosCairoSubview *child;
+ cairo_rectangle_int_t rect;
+
+ child = g_ptr_array_index (self->opaque, i);
+ cairo_region_get_rectangle (region, i, &rect);
+
+ [child setFrame:NSMakeRect (rect.x - abs_bounds.origin.x,
+ rect.y - abs_bounds.origin.y,
+ rect.width,
+ rect.height)];
+ }
+
+ return;
+ }
+
+ [self removeOpaqueChildren];
for (guint i = 0; i < n_rects; i++)
{
GdkMacosCairoSubview *child;
@@ -87,6 +123,7 @@
[child setOpaque:YES];
[child setWantsLayer:YES];
[self->transparent addSubview:child];
+ g_ptr_array_add (self->opaque, child);
}
}
@@ -94,6 +131,13 @@
{
if ((self = [super initWithFrame:frame]))
{
+ /* An array to track all the opaque children placed into
+ * the child self->transparent. This allows us to reuse them
+ * when we receive a new opaque area instead of discarding
+ * them on each draw.
+ */
+ self->opaque = g_ptr_array_new ();
+
/* Setup our primary subview which will render all content that is not
* within an opaque region (such as shadows for CSD windows). For opaque
* windows, this will all be obscurred by other views, so it doesn't
@@ -101,6 +145,7 @@
*/
self->transparent = [[GdkMacosCairoSubview alloc] initWithFrame:frame];
[self addSubview:self->transparent];
+
}
return self;
diff --git a/gdk/macos/GdkMacosCairoView.h b/gdk/macos/GdkMacosCairoView.h
index 913c24e399..1c28d83b39 100644
--- a/gdk/macos/GdkMacosCairoView.h
+++ b/gdk/macos/GdkMacosCairoView.h
@@ -28,6 +28,7 @@
@interface GdkMacosCairoView : GdkMacosBaseView
{
NSView *transparent;
+ GPtrArray *opaque;
}
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]