forked from AuroraMiddleware/gtk
Merge branch 'wip/chergert/macos-fixes' into 'main'
various macOS fixes See merge request GNOME/gtk!4424
This commit is contained in:
commit
59eb9aeb73
@ -23,7 +23,6 @@
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <cairo-quartz.h>
|
||||
|
||||
|
||||
#import "GdkMacosCairoSubview.h"
|
||||
#import "GdkMacosCairoView.h"
|
||||
|
||||
@ -33,7 +32,9 @@
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
g_clear_pointer (&self->clip, cairo_region_destroy);
|
||||
g_clear_pointer (&self->clip, g_array_unref);
|
||||
g_clear_pointer (&self->damage, g_array_unref);
|
||||
g_clear_pointer (&self->image, CGImageRelease);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@ -55,132 +56,67 @@
|
||||
-(void)drawRect:(NSRect)rect
|
||||
{
|
||||
CGContextRef cgContext;
|
||||
GdkSurface *gdk_surface;
|
||||
cairo_surface_t *dest;
|
||||
const NSRect *rects = NULL;
|
||||
NSView *root_view;
|
||||
NSInteger n_rects = 0;
|
||||
NSRect abs_bounds;
|
||||
cairo_t *cr;
|
||||
CGRect image_rect;
|
||||
CGRect abs_bounds;
|
||||
CGSize scale;
|
||||
int scale_factor;
|
||||
int abs_height;
|
||||
|
||||
if (self->cairoSurface == NULL)
|
||||
if (self->image == NULL)
|
||||
return;
|
||||
|
||||
/* Acquire everything we need to do translations, drawing, etc */
|
||||
gdk_surface = [self gdkSurface];
|
||||
scale_factor = gdk_surface_get_scale_factor (gdk_surface);
|
||||
root_view = [[self window] contentView];
|
||||
cgContext = [[NSGraphicsContext currentContext] CGContext];
|
||||
root_view = [[self window] contentView];
|
||||
abs_bounds = [self convertRect:[self bounds] toView:root_view];
|
||||
abs_height = CGImageGetHeight (self->image);
|
||||
|
||||
CGContextSaveGState (cgContext);
|
||||
|
||||
/* Translate scaling to remove HiDPI scaling from CGContext as
|
||||
* cairo will be doing that for us already.
|
||||
/* Clip while our context is still using matching coordinates
|
||||
* to the self->clip region. This is usually just on the views
|
||||
* for the shadow areas.
|
||||
*/
|
||||
CGContextAddRect (cgContext, [self bounds]);
|
||||
if (self->clip != NULL)
|
||||
{
|
||||
for (guint i = 0; i < self->clip->len; i++)
|
||||
CGContextAddRect (cgContext, g_array_index (self->clip, CGRect, i));
|
||||
}
|
||||
if (self->damage != NULL)
|
||||
{
|
||||
for (guint i = 0; i < self->damage->len; i++)
|
||||
CGContextAddRect (cgContext, g_array_index (self->damage, CGRect, i));
|
||||
}
|
||||
CGContextClip (cgContext);
|
||||
|
||||
/* Scale/Translate so that the CGImageRef draws in proper format/placement */
|
||||
scale = CGSizeMake (1.0, 1.0);
|
||||
scale = CGContextConvertSizeToDeviceSpace (cgContext, scale);
|
||||
CGContextScaleCTM (cgContext, 1.0 / scale.width, 1.0 / scale.height);
|
||||
CGContextTranslateCTM (cgContext, -abs_bounds.origin.x, -abs_bounds.origin.y);
|
||||
image_rect = CGRectMake (-abs_bounds.origin.x,
|
||||
-abs_bounds.origin.y,
|
||||
CGImageGetWidth (self->image),
|
||||
CGImageGetHeight (self->image));
|
||||
CGContextDrawImage (cgContext, image_rect, self->image);
|
||||
|
||||
/* Create the cairo surface to draw to the CGContext and translate
|
||||
* coordinates so we can pretend we are in the same coordinate system
|
||||
* as the GDK surface.
|
||||
*/
|
||||
dest = cairo_quartz_surface_create_for_cg_context (cgContext,
|
||||
gdk_surface->width * scale_factor,
|
||||
gdk_surface->height * scale_factor);
|
||||
cairo_surface_set_device_scale (dest, scale_factor, scale_factor);
|
||||
|
||||
/* Create cairo context and translate things into the origin of
|
||||
* the topmost contentView so that we just draw at 0,0 with a
|
||||
* clip region to paint the surface.
|
||||
*/
|
||||
cr = cairo_create (dest);
|
||||
cairo_translate (cr, -abs_bounds.origin.x, -abs_bounds.origin.y);
|
||||
|
||||
/* Apply the clip if provided one */
|
||||
if (self->clip != NULL)
|
||||
{
|
||||
cairo_rectangle_int_t area;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (self->clip);
|
||||
for (guint i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_region_get_rectangle (self->clip, i, &area);
|
||||
cairo_rectangle (cr, area.x, area.y, area.width, area.height);
|
||||
}
|
||||
|
||||
cairo_clip (cr);
|
||||
}
|
||||
|
||||
/* Clip the cairo context based on the rectangles to be drawn
|
||||
* within the bounding box :rect.
|
||||
*/
|
||||
[self getRectsBeingDrawn:&rects count:&n_rects];
|
||||
for (NSInteger i = 0; i < n_rects; i++)
|
||||
{
|
||||
NSRect area = [self convertRect:rects[i] toView:root_view];
|
||||
cairo_rectangle (cr,
|
||||
area.origin.x, area.origin.y,
|
||||
area.size.width, area.size.height);
|
||||
}
|
||||
cairo_clip (cr);
|
||||
|
||||
/* Now paint the surface (without blending) as we do not need
|
||||
* any compositing here. The transparent regions (like shadows)
|
||||
* are already on non-opaque layers.
|
||||
*/
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_surface (cr, self->cairoSurface, 0, 0);
|
||||
cairo_paint (cr);
|
||||
|
||||
/* Cleanup state, flush the surface to the backing layer, and
|
||||
* restore GState for future use.
|
||||
*/
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_flush (dest);
|
||||
cairo_surface_destroy (dest);
|
||||
CGContextRestoreGState (cgContext);
|
||||
}
|
||||
|
||||
-(void)setCairoSurface:(cairo_surface_t *)surface
|
||||
withDamage:(cairo_region_t *)region
|
||||
-(void)setImage:(CGImageRef)theImage
|
||||
withDamage:(cairo_region_t *)region
|
||||
{
|
||||
if (surface != self->cairoSurface)
|
||||
if (theImage != image)
|
||||
{
|
||||
g_clear_pointer (&self->cairoSurface, cairo_surface_destroy);
|
||||
if (surface != NULL)
|
||||
self->cairoSurface = cairo_surface_reference (surface);
|
||||
g_clear_pointer (&image, CGImageRelease);
|
||||
if (theImage)
|
||||
image = CGImageRetain (theImage);
|
||||
}
|
||||
|
||||
if (region != NULL)
|
||||
{
|
||||
NSView *root_view = [[self window] contentView];
|
||||
NSRect abs_bounds = [self convertRect:[self bounds] toView:root_view];
|
||||
guint n_rects = cairo_region_num_rectangles (region);
|
||||
|
||||
for (guint i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
NSRect nsrect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
nsrect = NSMakeRect (rect.x, rect.y, rect.width, rect.height);
|
||||
|
||||
if (NSIntersectsRect (abs_bounds, nsrect))
|
||||
{
|
||||
nsrect.origin.x -= abs_bounds.origin.x;
|
||||
nsrect.origin.y -= abs_bounds.origin.y;
|
||||
[self setNeedsDisplayInRect:nsrect];
|
||||
}
|
||||
}
|
||||
}
|
||||
[self convertRegion:region toArray:&self->damage andDisplay:YES];
|
||||
|
||||
for (id view in [self subviews])
|
||||
[(GdkMacosCairoSubview *)view setCairoSurface:surface
|
||||
withDamage:region];
|
||||
[(GdkMacosCairoSubview *)view setImage:theImage withDamage:region];
|
||||
}
|
||||
|
||||
-(void)setOpaque:(BOOL)opaque
|
||||
@ -188,14 +124,44 @@
|
||||
self->_isOpaque = opaque;
|
||||
}
|
||||
|
||||
-(void)setClip:(cairo_region_t*)region
|
||||
-(void)convertRegion:(const cairo_region_t *)region
|
||||
toArray:(GArray **)array
|
||||
andDisplay:(BOOL)display
|
||||
{
|
||||
if (region != self->clip)
|
||||
NSView *root_view;
|
||||
CGRect abs_bounds;
|
||||
guint n_rects;
|
||||
|
||||
if (*array == NULL)
|
||||
*array = g_array_new (FALSE, FALSE, sizeof (CGRect));
|
||||
else
|
||||
g_array_set_size (*array, 0);
|
||||
|
||||
root_view = [[self window] contentView];
|
||||
abs_bounds = [self convertRect:[self bounds] toView:root_view];
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
|
||||
for (guint i = 0; i < n_rects; i++)
|
||||
{
|
||||
g_clear_pointer (&self->clip, cairo_region_destroy);
|
||||
if (region != NULL)
|
||||
self->clip = cairo_region_reference (region);
|
||||
cairo_rectangle_int_t rect;
|
||||
CGRect nsrect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
nsrect = CGRectIntersection (abs_bounds, CGRectMake (rect.x, rect.y, rect.width, rect.height));
|
||||
|
||||
if (!CGRectIsNull (nsrect))
|
||||
g_array_append_val (*array, nsrect);
|
||||
|
||||
if (display)
|
||||
[self setNeedsDisplayInRect:CGRectMake (rect.x - abs_bounds.origin.x,
|
||||
rect.y - abs_bounds.origin.y,
|
||||
rect.width, rect.height)];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)setClip:(cairo_region_t*)region
|
||||
{
|
||||
[self convertRegion:region toArray:&self->clip andDisplay:NO];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -19,19 +19,21 @@
|
||||
*/
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
|
||||
#define GDK_IS_MACOS_CAIRO_SUBVIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosCairoSubview class]])
|
||||
|
||||
@interface GdkMacosCairoSubview : NSView
|
||||
{
|
||||
BOOL _isOpaque;
|
||||
cairo_surface_t *cairoSurface;
|
||||
cairo_region_t *clip;
|
||||
BOOL _isOpaque;
|
||||
GArray *clip;
|
||||
GArray *damage;
|
||||
CGImageRef image;
|
||||
}
|
||||
|
||||
-(void)setOpaque:(BOOL)opaque;
|
||||
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
|
||||
withDamage:(cairo_region_t *)region;
|
||||
-(void)setImage:(CGImageRef)theImage withDamage:(cairo_region_t *)region;
|
||||
-(void)setClip:(cairo_region_t*)region;
|
||||
|
||||
@end
|
||||
|
@ -28,6 +28,7 @@
|
||||
#import "GdkMacosCairoView.h"
|
||||
#import "GdkMacosCairoSubview.h"
|
||||
|
||||
#include "gdkmacosmonitor-private.h"
|
||||
#include "gdkmacossurface-private.h"
|
||||
|
||||
@implementation GdkMacosCairoView
|
||||
@ -58,12 +59,92 @@
|
||||
[child setNeedsDisplay:needsDisplay];
|
||||
}
|
||||
|
||||
static void
|
||||
release_surface_provider (void *info,
|
||||
const void *data,
|
||||
size_t size)
|
||||
{
|
||||
cairo_surface_destroy (info);
|
||||
}
|
||||
|
||||
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
|
||||
withDamage:(cairo_region_t *)cairoRegion
|
||||
{
|
||||
CGImageRef image = NULL;
|
||||
|
||||
if (cairoSurface != NULL)
|
||||
{
|
||||
const CGColorRenderingIntent intent = kCGRenderingIntentDefault;
|
||||
CGDataProviderRef provider;
|
||||
CGColorSpaceRef rgb;
|
||||
cairo_format_t format;
|
||||
CGBitmapInfo bitmap = kCGBitmapByteOrder32Host;
|
||||
GdkMonitor *monitor;
|
||||
guint8 *framebuffer;
|
||||
size_t width;
|
||||
size_t height;
|
||||
int rowstride;
|
||||
int bpp;
|
||||
int bpc;
|
||||
|
||||
cairo_surface_flush (cairoSurface);
|
||||
|
||||
format = cairo_image_surface_get_format (cairoSurface);
|
||||
framebuffer = cairo_image_surface_get_data (cairoSurface);
|
||||
rowstride = cairo_image_surface_get_stride (cairoSurface);
|
||||
width = cairo_image_surface_get_width (cairoSurface);
|
||||
height = cairo_image_surface_get_height (cairoSurface);
|
||||
monitor = _gdk_macos_surface_get_best_monitor ([self gdkSurface]);
|
||||
rgb = _gdk_macos_monitor_copy_colorspace (GDK_MACOS_MONITOR (monitor));
|
||||
|
||||
/* If we have an WCG colorspace, just take the slow path or we risk
|
||||
* really screwing things up.
|
||||
*/
|
||||
if (CGColorSpaceIsWideGamutRGB (rgb))
|
||||
{
|
||||
CGColorSpaceRelease (rgb);
|
||||
rgb = CGColorSpaceCreateDeviceRGB ();
|
||||
}
|
||||
|
||||
/* Assert that our image surface was created correctly with
|
||||
* 16-byte aligned pointers and strides. This is needed to
|
||||
* ensure that we're working with fast paths in CoreGraphics.
|
||||
*/
|
||||
g_assert (format == CAIRO_FORMAT_ARGB32 || format == CAIRO_FORMAT_RGB24);
|
||||
g_assert (framebuffer != NULL);
|
||||
g_assert (((intptr_t)framebuffer & (intptr_t)~0xF) == (intptr_t)framebuffer);
|
||||
g_assert ((rowstride & ~0xF) == rowstride);
|
||||
|
||||
if (format == CAIRO_FORMAT_ARGB32)
|
||||
{
|
||||
bitmap |= kCGImageAlphaPremultipliedFirst;
|
||||
bpp = 32;
|
||||
bpc = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap |= kCGImageAlphaNoneSkipFirst;
|
||||
bpp = 32;
|
||||
bpc = 8;
|
||||
}
|
||||
|
||||
provider = CGDataProviderCreateWithData (cairo_surface_reference (cairoSurface),
|
||||
framebuffer,
|
||||
rowstride * height,
|
||||
release_surface_provider);
|
||||
|
||||
image = CGImageCreate (width, height, bpc, bpp, rowstride, rgb, bitmap, provider, NULL, FALSE, intent);
|
||||
|
||||
CGDataProviderRelease (provider);
|
||||
CGColorSpaceRelease (rgb);
|
||||
}
|
||||
|
||||
for (id view in [self subviews])
|
||||
[(GdkMacosCairoSubview *)view setCairoSurface:cairoSurface
|
||||
withDamage:cairoRegion];
|
||||
[(GdkMacosCairoSubview *)view setImage:image
|
||||
withDamage:cairoRegion];
|
||||
|
||||
if (image != NULL)
|
||||
CGImageRelease (image);
|
||||
}
|
||||
|
||||
-(void)removeOpaqueChildren
|
||||
@ -162,7 +243,6 @@
|
||||
*/
|
||||
self->transparent = [[GdkMacosCairoSubview alloc] initWithFrame:frame];
|
||||
[self addSubview:self->transparent];
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -214,7 +214,14 @@ typedef NSString *CALayerContentsGravity;
|
||||
* as we are leaving maximized state.
|
||||
*/
|
||||
if ((style_mask & NSWindowStyleMaskTitled) == 0 && [self isOpaque])
|
||||
[self setOpaque:NO];
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE ([self gdkSurface]);
|
||||
|
||||
[self setOpaque:NO];
|
||||
|
||||
/* Force updating of various styling, regions, etc */
|
||||
_gdk_surface_update_size (surface);
|
||||
}
|
||||
}
|
||||
|
||||
-(void)windowDidMove:(NSNotification *)aNotification
|
||||
|
@ -34,6 +34,7 @@ struct _GdkMacosCairoContext
|
||||
GdkCairoContext parent_instance;
|
||||
|
||||
cairo_surface_t *window_surface;
|
||||
cairo_t *cr;
|
||||
};
|
||||
|
||||
struct _GdkMacosCairoContextClass
|
||||
@ -46,30 +47,66 @@ G_DEFINE_TYPE (GdkMacosCairoContext, _gdk_macos_cairo_context, GDK_TYPE_CAIRO_CO
|
||||
static cairo_surface_t *
|
||||
create_cairo_surface_for_surface (GdkSurface *surface)
|
||||
{
|
||||
static const cairo_user_data_key_t buffer_key;
|
||||
cairo_surface_t *cairo_surface;
|
||||
guint8 *data;
|
||||
cairo_format_t format;
|
||||
size_t size;
|
||||
size_t rowstride;
|
||||
size_t width;
|
||||
size_t height;
|
||||
int scale;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
g_assert (GDK_IS_MACOS_SURFACE (surface));
|
||||
|
||||
/* We use a cairo image surface here instead of a quartz surface because
|
||||
* we get strange artifacts with the quartz surface such as empty
|
||||
* cross-fades when hovering buttons. For performance, we want to be using
|
||||
* GL rendering so there isn't much point here as correctness is better.
|
||||
*
|
||||
* Additionally, so we can take avantage of faster paths in Core
|
||||
* Graphics, we want our data pointer to be 16-byte aligned and our rows
|
||||
* to be 16-byte aligned or we risk errors below us. Normally, cairo
|
||||
* image surface does not guarantee the later, which means we could end
|
||||
* up doing some costly copies along the way to compositing.
|
||||
*/
|
||||
|
||||
if ([GDK_MACOS_SURFACE (surface)->window isOpaque])
|
||||
format = CAIRO_FORMAT_RGB24;
|
||||
else
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
|
||||
scale = gdk_surface_get_scale_factor (surface);
|
||||
width = scale * gdk_surface_get_width (surface);
|
||||
height = scale * gdk_surface_get_height (surface);
|
||||
|
||||
/* We use a cairo image surface here instead of a quartz surface because we
|
||||
* get strange artifacts with the quartz surface such as empty cross-fades
|
||||
* when hovering buttons. For performance, we want to be using GL rendering
|
||||
* so there isn't much point here as correctness is better.
|
||||
*/
|
||||
cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
|
||||
|
||||
if (cairo_surface != NULL)
|
||||
cairo_surface_set_device_scale (cairo_surface, scale, scale);
|
||||
rowstride = (cairo_format_stride_for_width (format, width) + 0xF) & ~0xF;
|
||||
size = rowstride * height;
|
||||
data = g_malloc0 (size);
|
||||
cairo_surface = cairo_image_surface_create_for_data (data, format, width, height, rowstride);
|
||||
cairo_surface_set_user_data (cairo_surface, &buffer_key, data, g_free);
|
||||
cairo_surface_set_device_scale (cairo_surface, scale, scale);
|
||||
|
||||
return cairo_surface;
|
||||
}
|
||||
|
||||
static cairo_t *
|
||||
do_cairo_create (GdkMacosCairoContext *self)
|
||||
{
|
||||
GdkSurface *surface;
|
||||
cairo_t *cr;
|
||||
|
||||
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
|
||||
|
||||
surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
|
||||
cr = cairo_create (self->window_surface);
|
||||
|
||||
/* Draw upside down as quartz prefers */
|
||||
cairo_translate (cr, 0, surface->height);
|
||||
cairo_scale (cr, 1.0, -1.0);
|
||||
|
||||
return cr;
|
||||
}
|
||||
|
||||
static cairo_t *
|
||||
_gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
|
||||
{
|
||||
@ -77,7 +114,10 @@ _gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
|
||||
|
||||
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
|
||||
|
||||
return cairo_create (self->window_surface);
|
||||
if (self->cr != NULL)
|
||||
return cairo_reference (self->cr);
|
||||
|
||||
return do_cairo_create (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -95,20 +135,18 @@ _gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
|
||||
|
||||
if (self->window_surface == NULL)
|
||||
self->window_surface = create_cairo_surface_for_surface (surface);
|
||||
|
||||
self->cr = do_cairo_create (self);
|
||||
|
||||
if (![nswindow isOpaque])
|
||||
{
|
||||
self->window_surface = create_cairo_surface_for_surface (surface);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (![nswindow isOpaque])
|
||||
{
|
||||
cairo_t *cr = cairo_create (self->window_surface);
|
||||
gdk_cairo_region (cr, region);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, 0);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_fill (cr);
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
cairo_save (self->cr);
|
||||
gdk_cairo_region (self->cr, region);
|
||||
cairo_set_source_rgba (self->cr, 0, 0, 0, 0);
|
||||
cairo_set_operator (self->cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_fill (self->cr);
|
||||
cairo_restore (self->cr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,6 +164,8 @@ _gdk_macos_cairo_context_end_frame (GdkDrawContext *draw_context,
|
||||
surface = gdk_draw_context_get_surface (draw_context);
|
||||
nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface));
|
||||
|
||||
g_clear_pointer (&self->cr, cairo_destroy);
|
||||
|
||||
if (GDK_IS_MACOS_CAIRO_VIEW (nsview))
|
||||
[(GdkMacosCairoView *)nsview setCairoSurface:self->window_surface
|
||||
withDamage:painted];
|
||||
@ -141,12 +181,25 @@ _gdk_macos_cairo_context_surface_resized (GdkDrawContext *draw_context)
|
||||
g_clear_pointer (&self->window_surface, cairo_surface_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_cairo_context_dispose (GObject *object)
|
||||
{
|
||||
GdkMacosCairoContext *self = (GdkMacosCairoContext *)object;
|
||||
|
||||
g_clear_pointer (&self->window_surface, cairo_surface_destroy);
|
||||
|
||||
G_OBJECT_CLASS (_gdk_macos_cairo_context_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_cairo_context_class_init (GdkMacosCairoContextClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GdkCairoContextClass *cairo_context_class = GDK_CAIRO_CONTEXT_CLASS (klass);
|
||||
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
|
||||
|
||||
object_class->dispose = _gdk_macos_cairo_context_dispose;
|
||||
|
||||
draw_context_class->begin_frame = _gdk_macos_cairo_context_begin_frame;
|
||||
draw_context_class->end_frame = _gdk_macos_cairo_context_end_frame;
|
||||
draw_context_class->surface_resized = _gdk_macos_cairo_context_surface_resized;
|
||||
|
@ -301,10 +301,14 @@ gdk_macos_display_frame_cb (gpointer data)
|
||||
|
||||
iter = iter->next;
|
||||
|
||||
_gdk_macos_surface_publish_timings (surface,
|
||||
source->presentation_time,
|
||||
source->refresh_interval);
|
||||
|
||||
_gdk_macos_display_remove_frame_callback (self, surface);
|
||||
_gdk_macos_surface_thaw (surface,
|
||||
source->presentation_time,
|
||||
source->refresh_interval);
|
||||
|
||||
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)))
|
||||
gdk_surface_thaw_updates (GDK_SURFACE (surface));
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
@ -987,7 +991,11 @@ _gdk_macos_display_add_frame_callback (GdkMacosDisplay *self,
|
||||
|
||||
if (!queue_contains (&self->awaiting_frames, &surface->frame))
|
||||
{
|
||||
g_queue_push_tail_link (&self->awaiting_frames, &surface->frame);
|
||||
/* Processing frames is always head to tail, so push to the
|
||||
* head so that we don't possibly re-enter this right after
|
||||
* adding to the queue.
|
||||
*/
|
||||
g_queue_push_head_link (&self->awaiting_frames, &surface->frame);
|
||||
|
||||
if (self->awaiting_frames.length == 1)
|
||||
gdk_display_link_source_unpause ((GdkDisplayLinkSource *)self->frame_source);
|
||||
|
@ -29,10 +29,11 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GdkMacosMonitor *_gdk_macos_monitor_new (GdkMacosDisplay *display,
|
||||
CGDirectDisplayID screen_id);
|
||||
CGDirectDisplayID _gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self);
|
||||
gboolean _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self);
|
||||
GdkMacosMonitor *_gdk_macos_monitor_new (GdkMacosDisplay *display,
|
||||
CGDirectDisplayID screen_id);
|
||||
CGDirectDisplayID _gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self);
|
||||
gboolean _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self);
|
||||
CGColorSpaceRef _gdk_macos_monitor_copy_colorspace (GdkMacosMonitor *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -298,3 +298,11 @@ _gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self)
|
||||
|
||||
return self->screen_id;
|
||||
}
|
||||
|
||||
CGColorSpaceRef
|
||||
_gdk_macos_monitor_copy_colorspace (GdkMacosMonitor *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MACOS_MONITOR (self), NULL);
|
||||
|
||||
return CGDisplayCopyColorSpace (self->screen_id);
|
||||
}
|
||||
|
@ -204,6 +204,10 @@ static void
|
||||
_gdk_macos_popup_surface_finalize (GObject *object)
|
||||
{
|
||||
GdkMacosPopupSurface *self = (GdkMacosPopupSurface *)object;
|
||||
GdkSurface *parent = GDK_SURFACE (self)->parent;
|
||||
|
||||
if (parent != NULL)
|
||||
parent->children = g_list_remove (parent->children, self);
|
||||
|
||||
g_clear_object (&GDK_SURFACE (self)->parent);
|
||||
g_clear_pointer (&self->layout, gdk_popup_layout_unref);
|
||||
|
@ -104,7 +104,7 @@ void _gdk_macos_surface_resize (GdkMacosSurface
|
||||
void _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface *self);
|
||||
void _gdk_macos_surface_update_position (GdkMacosSurface *self);
|
||||
void _gdk_macos_surface_show (GdkMacosSurface *self);
|
||||
void _gdk_macos_surface_thaw (GdkMacosSurface *self,
|
||||
void _gdk_macos_surface_publish_timings (GdkMacosSurface *self,
|
||||
gint64 predicted_presentation_time,
|
||||
gint64 refresh_interval);
|
||||
CGContextRef _gdk_macos_surface_acquire_context (GdkMacosSurface *self,
|
||||
|
@ -125,6 +125,8 @@ gdk_macos_surface_hide (GdkSurface *surface)
|
||||
|
||||
g_assert (GDK_IS_MACOS_SURFACE (self));
|
||||
|
||||
_gdk_macos_display_remove_frame_callback (GDK_MACOS_DISPLAY (surface->display), self);
|
||||
|
||||
was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
|
||||
|
||||
seat = gdk_display_get_default_seat (surface->display);
|
||||
@ -190,15 +192,20 @@ gdk_macos_surface_end_frame (GdkMacosSurface *self)
|
||||
|
||||
g_assert (GDK_IS_MACOS_SURFACE (self));
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (self))
|
||||
return;
|
||||
|
||||
display = gdk_surface_get_display (GDK_SURFACE (self));
|
||||
frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
|
||||
|
||||
if ((timings = gdk_frame_clock_get_current_timings (frame_clock)))
|
||||
self->pending_frame_counter = timings->frame_counter;
|
||||
|
||||
_gdk_macos_display_add_frame_callback (GDK_MACOS_DISPLAY (display), self);
|
||||
|
||||
gdk_surface_freeze_updates (GDK_SURFACE (self));
|
||||
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
|
||||
{
|
||||
_gdk_macos_display_add_frame_callback (GDK_MACOS_DISPLAY (display), self);
|
||||
gdk_surface_freeze_updates (GDK_SURFACE (self));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -210,10 +217,11 @@ gdk_macos_surface_before_paint (GdkMacosSurface *self,
|
||||
g_assert (GDK_IS_MACOS_SURFACE (self));
|
||||
g_assert (GDK_IS_FRAME_CLOCK (frame_clock));
|
||||
|
||||
if (surface->update_freeze_count > 0)
|
||||
if (GDK_SURFACE_DESTROYED (self))
|
||||
return;
|
||||
|
||||
gdk_macos_surface_begin_frame (self);
|
||||
if (surface->update_freeze_count == 0)
|
||||
gdk_macos_surface_begin_frame (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -225,10 +233,11 @@ gdk_macos_surface_after_paint (GdkMacosSurface *self,
|
||||
g_assert (GDK_IS_MACOS_SURFACE (self));
|
||||
g_assert (GDK_IS_FRAME_CLOCK (frame_clock));
|
||||
|
||||
if (surface->update_freeze_count > 0)
|
||||
if (GDK_SURFACE_DESTROYED (self))
|
||||
return;
|
||||
|
||||
gdk_macos_surface_end_frame (self);
|
||||
if (surface->update_freeze_count == 0)
|
||||
gdk_macos_surface_end_frame (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -715,18 +724,17 @@ _gdk_macos_surface_update_position (GdkMacosSurface *self)
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_surface_thaw (GdkMacosSurface *self,
|
||||
gint64 presentation_time,
|
||||
gint64 refresh_interval)
|
||||
_gdk_macos_surface_publish_timings (GdkMacosSurface *self,
|
||||
gint64 presentation_time,
|
||||
gint64 refresh_interval)
|
||||
{
|
||||
GdkFrameTimings *timings;
|
||||
GdkFrameClock *frame_clock;
|
||||
|
||||
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
|
||||
|
||||
gdk_surface_thaw_updates (GDK_SURFACE (self));
|
||||
|
||||
frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
|
||||
if (!(frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self))))
|
||||
return;
|
||||
|
||||
if (self->pending_frame_counter)
|
||||
{
|
||||
@ -986,6 +994,9 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
|
||||
|
||||
g_object_unref (monitor);
|
||||
}
|
||||
|
||||
_gdk_surface_update_size (GDK_SURFACE (self));
|
||||
gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
|
||||
}
|
||||
|
||||
GdkMonitor *
|
||||
|
Loading…
Reference in New Issue
Block a user