[gtk/gtk-3-24] [quartz] Handle scale changes using NSView::shouldInheritContentsScale.



commit 8d4c4cdca49ab97a86dac19bc5f1a313c5a16870
Author: John Ralls <jralls ceridwen us>
Date:   Tue May 31 14:43:29 2022 -0700

    [quartz] Handle scale changes using NSView::shouldInheritContentsScale.
    
    Includes creating the CVPixelBuffer to supply the layer contents when
    creating the cairo_image_surface, which reduces the number of them created
    at the wrong scale.

 gdk/quartz/GdkQuartzView.c    | 56 ++++++++++++++++++++++++-------------------
 gdk/quartz/GdkQuartzView.h    |  3 ++-
 gdk/quartz/gdkwindow-quartz.c |  2 +-
 3 files changed, 35 insertions(+), 26 deletions(-)
---
diff --git a/gdk/quartz/GdkQuartzView.c b/gdk/quartz/GdkQuartzView.c
index f7ac47dcc0..3a3bcdee0d 100644
--- a/gdk/quartz/GdkQuartzView.c
+++ b/gdk/quartz/GdkQuartzView.c
@@ -36,7 +36,6 @@
 {
   if ((self = [super initWithFrame: frameRect]))
     {
-      CVReturn rv;
       pb_props = @{
         (id)kCVPixelBufferIOSurfaceCoreAnimationCompatibilityKey: @1,
         (id)kCVPixelBufferBytesPerRowAlignmentKey: @64,
@@ -46,10 +45,6 @@
 
       markedRange = NSMakeRange (NSNotFound, 0);
       selectedRange = NSMakeRange (0, 0);
-      rv = CVPixelBufferCreate (NULL, frameRect.size.width,
-                                frameRect.size.height,
-                                kCVPixelFormatType_32ARGB,
-                                cfpb_props, &pixels);
     }
 
   [self setValue: @(YES) forKey: @"postsFrameChangedNotifications"];
@@ -384,8 +379,8 @@ copy_rectangle_argb32 (cairo_surface_t *dest, cairo_surface_t *source,
     {
       g_warning ("Failed to map destination image surface, %d %d %d %d on %d %d: %s\n",
                  rect->x, rect->y, rect->width, rect->height,
-                 cairo_image_surface_get_width (source),
-                 cairo_image_surface_get_height (source),
+                 cairo_image_surface_get_width (dest),
+                 cairo_image_surface_get_height (dest),
                  cairo_status_to_string (status));
        goto CLEANUP;
     }
@@ -414,15 +409,8 @@ copy_rectangle_argb32 (cairo_surface_t *dest, cairo_surface_t *source,
   if (GDK_WINDOW_DESTROYED (gdk_window))
     return;
 
-  ++impl->in_paint_rect_count;
-  CVPixelBufferLockBaseAddress (pixels, 0);
-  cvpb_surface =
-    cairo_image_surface_create_for_data (CVPixelBufferGetBaseAddress (pixels),
-                                         CAIRO_FORMAT_ARGB32,
-                                         (int)CVPixelBufferGetWidth (pixels),
-                                         (int)CVPixelBufferGetHeight (pixels),
-                                         (int)CVPixelBufferGetBytesPerRow (pixels));
 
+  ++impl->in_paint_rect_count;
   cairo_rect_from_nsrect (&extents, &backing_bounds);
   if (impl->needs_display_region)
     {
@@ -441,10 +429,18 @@ copy_rectangle_argb32 (cairo_surface_t *dest, cairo_surface_t *source,
       _gdk_window_process_updates_recurse (gdk_window, region);
       cairo_region_destroy (region);
     }
-  
+
   if (!impl || !impl->cairo_surface)
     return;
 
+  CVPixelBufferLockBaseAddress (pixels, 0);
+  cvpb_surface =
+    cairo_image_surface_create_for_data (CVPixelBufferGetBaseAddress (pixels),
+                                         CAIRO_FORMAT_ARGB32,
+                                         (int)CVPixelBufferGetWidth (pixels),
+                                         (int)CVPixelBufferGetHeight (pixels),
+                                         (int)CVPixelBufferGetBytesPerRow (pixels));
+
   copy_rectangle_argb32 (cvpb_surface, impl->cairo_surface, &extents);
 
   cairo_surface_destroy (cvpb_surface);
@@ -508,22 +504,34 @@ copy_rectangle_argb32 (cairo_surface_t *dest, cairo_surface_t *source,
     }
 }
 
--(void)setFrame: (NSRect)frame
+-(void)createBackingStoreWithWidth: (CGFloat) width andHeight: (CGFloat) height
 {
   CVReturn rv;
-  NSRect rect = self.layer ? self.layer.bounds : frame;
-  NSRect backing_rect = [self convertRectToBacking: rect];
 
-  if (GDK_WINDOW_DESTROYED (gdk_window))
-    return;
+  g_return_if_fail (width && height);
 
   CVPixelBufferRelease (pixels);
-  rv = CVPixelBufferCreate (NULL, backing_rect.size.width,
-                            backing_rect.size.height,
+  rv = CVPixelBufferCreate (NULL, width, height,
                             kCVPixelFormatType_32BGRA,
                             cfpb_props, &pixels);
 
-  //Force a new cairo_surface for drawing
+}
+
+-(BOOL)layer:(CALayer*) layer shouldInheritContentsScale: (CGFloat)scale fromWindow: (NSWindow *) window
+{
+  if (layer == self.layer && window == self.window)
+    {
+      _gdk_quartz_unref_cairo_surface (gdk_window);
+      [self setNeedsDisplay: YES];
+    }
+  return YES;
+}
+
+-(void)setFrame: (NSRect)frame
+{
+  if (GDK_WINDOW_DESTROYED (gdk_window))
+    return;
+
   _gdk_quartz_unref_cairo_surface (gdk_window);
   [super setFrame: frame];
 
diff --git a/gdk/quartz/GdkQuartzView.h b/gdk/quartz/GdkQuartzView.h
index 0c1558a7ec..e1530bdd71 100644
--- a/gdk/quartz/GdkQuartzView.h
+++ b/gdk/quartz/GdkQuartzView.h
@@ -34,7 +34,7 @@
 #define GIC_FILTER_PASSTHRU    0
 #define GIC_FILTER_FILTERED    1
 
-@interface GdkQuartzView : NSView <NSTextInputClient>
+@interface GdkQuartzView : NSView <NSTextInputClient, NSViewLayerContentScaleDelegate>
 {
   GdkWindow *gdk_window;
   NSTrackingRectTag trackingRect;
@@ -50,5 +50,6 @@
 - (GdkWindow *)gdkWindow;
 - (NSTrackingRectTag)trackingRect;
 - (void)setNeedsInvalidateShadow: (BOOL)invalidate;
+- (void)createBackingStoreWithWidth: (CGFloat) width andHeight: (CGFloat) height;
 
 @end
diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c
index a9bc6c6504..1800ca83ea 100644
--- a/gdk/quartz/gdkwindow-quartz.c
+++ b/gdk/quartz/gdkwindow-quartz.c
@@ -309,11 +309,11 @@ gdk_quartz_create_cairo_surface (GdkWindowImplQuartz *impl,
   GdkQuartzCairoSurfaceData *surface_data;
   cairo_surface_t *surface;
 
-
   surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
   surface_data->window_impl = impl;
   surface_data->cg_context = NULL;
 
+  [impl->view createBackingStoreWithWidth: width andHeight: height];
   surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
   cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
                                surface_data,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]