mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 23:37:33 +09:00
Issue #1667 - Part 2: Add MacOS 11.0 Big Sur widget compatibility
This involves refactoring the vibrancy and OpenGL/Pixel rendering changes contained in the following Mozilla meta bugs: 1496823 and 1491445 Also add Big Sur to the features tests and update popup menu look and feel based on Mozilla bug 1656301.
This commit is contained in:
parent
0fb2ab04a6
commit
de885df033
10 changed files with 286 additions and 609 deletions
|
|
@ -146,7 +146,10 @@ bool gUserCancelledDrag = false;
|
|||
|
||||
uint32_t nsChildView::sLastInputEventCount = 0;
|
||||
|
||||
static uint32_t gNumberOfWidgetsNeedingEventThread = 0;
|
||||
// The view that will do our drawing or host our NSOpenGLContext or Core Animation layer.
|
||||
@interface PixelHostingView : NSView {
|
||||
}
|
||||
@end
|
||||
|
||||
@interface ChildView(Private)
|
||||
|
||||
|
|
@ -163,14 +166,9 @@ static uint32_t gNumberOfWidgetsNeedingEventThread = 0;
|
|||
|
||||
- (BOOL)isRectObscuredBySubview:(NSRect)inRect;
|
||||
|
||||
- (void)processPendingRedraws;
|
||||
|
||||
- (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext;
|
||||
- (LayoutDeviceIntRegion)nativeDirtyRegionWithBoundingRect:(NSRect)aRect;
|
||||
- (BOOL)isUsingMainThreadOpenGL;
|
||||
- (BOOL)isUsingOpenGL;
|
||||
- (void)drawUsingOpenGL;
|
||||
- (void)drawUsingOpenGLCallback;
|
||||
|
||||
- (BOOL)hasRoundedBottomCorners;
|
||||
- (CGFloat)cornerRadius;
|
||||
|
|
@ -195,7 +193,6 @@ static uint32_t gNumberOfWidgetsNeedingEventThread = 0;
|
|||
|
||||
- (LayoutDeviceIntPoint)convertWindowCoordinates:(NSPoint)aPoint;
|
||||
- (LayoutDeviceIntPoint)convertWindowCoordinatesRoundDown:(NSPoint)aPoint;
|
||||
- (IAPZCTreeManager*)apzctm;
|
||||
|
||||
- (BOOL)inactiveWindowAcceptsMouseEvent:(NSEvent*)aEvent;
|
||||
- (void)updateWindowDraggableState;
|
||||
|
|
@ -204,26 +201,10 @@ static uint32_t gNumberOfWidgetsNeedingEventThread = 0;
|
|||
|
||||
@end
|
||||
|
||||
@interface EventThreadRunner : NSObject
|
||||
{
|
||||
NSThread* mThread;
|
||||
}
|
||||
- (id)init;
|
||||
|
||||
+ (void)start;
|
||||
+ (void)stop;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSView(NSThemeFrameCornerRadius)
|
||||
- (float)roundedCornerRadius;
|
||||
@end
|
||||
|
||||
@interface NSView(DraggableRegion)
|
||||
- (CGSRegionObj)_regionForOpaqueDescendants:(NSRect)aRect forMove:(BOOL)aForMove;
|
||||
- (CGSRegionObj)_regionForOpaqueDescendants:(NSRect)aRect forMove:(BOOL)aForMove forUnderTitlebar:(BOOL)aForUnderTitlebar;
|
||||
@end
|
||||
|
||||
@interface NSWindow(NSWindowShouldZoomOnDoubleClick)
|
||||
+ (BOOL)_shouldZoomOnDoubleClick; // present on 10.7 and above
|
||||
@end
|
||||
|
|
@ -380,13 +361,6 @@ nsChildView::~nsChildView()
|
|||
|
||||
DestroyCompositor();
|
||||
|
||||
if (mAPZC && gfxPrefs::AsyncPanZoomSeparateEventThread()) {
|
||||
gNumberOfWidgetsNeedingEventThread--;
|
||||
if (gNumberOfWidgetsNeedingEventThread == 0) {
|
||||
[EventThreadRunner stop];
|
||||
}
|
||||
}
|
||||
|
||||
// An nsChildView object that was in use can be destroyed without Destroy()
|
||||
// ever being called on it. So we also need to do a quick, safe cleanup
|
||||
// here (it's too late to just call Destroy(), which can cause crashes).
|
||||
|
|
@ -455,7 +429,8 @@ nsChildView::Create(nsIWidget* aParent,
|
|||
// that NS_NATIVE_WIDGET is the NSView.
|
||||
CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(mParentView);
|
||||
NSRect r = nsCocoaUtils::DevPixelsToCocoaPoints(mBounds, scaleFactor);
|
||||
mView = [(NSView<mozView>*)CreateCocoaView(r) retain];
|
||||
mView = [[[[ChildView alloc] initWithFrame:r geckoChild:this] autorelease] retain];
|
||||
|
||||
if (!mView) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
@ -488,17 +463,6 @@ nsChildView::Create(nsIWidget* aParent,
|
|||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
// Creates the appropriate child view. Override to create something other than
|
||||
// our |ChildView| object. Autoreleases, so caller must retain.
|
||||
NSView*
|
||||
nsChildView::CreateCocoaView(NSRect inFrame)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
return [[[ChildView alloc] initWithFrame:inFrame geckoChild:this] autorelease];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
void nsChildView::TearDownView()
|
||||
{
|
||||
|
|
@ -982,8 +946,9 @@ NS_IMETHODIMP nsChildView::Resize(double aWidth, double aHeight, bool aRepaint)
|
|||
[mView setFrame:DevPixelsToCocoaPoints(mBounds)];
|
||||
});
|
||||
|
||||
if (mVisible && aRepaint)
|
||||
[mView setNeedsDisplay:YES];
|
||||
if (mVisible && aRepaint) {
|
||||
[[mView pixelHostingView] setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
NotifyRollupGeometryChange();
|
||||
ReportSizeEvent();
|
||||
|
|
@ -1021,8 +986,9 @@ NS_IMETHODIMP nsChildView::Resize(double aX, double aY,
|
|||
[mView setFrame:DevPixelsToCocoaPoints(mBounds)];
|
||||
});
|
||||
|
||||
if (mVisible && aRepaint)
|
||||
[mView setNeedsDisplay:YES];
|
||||
if (mVisible && aRepaint) {
|
||||
[[mView pixelHostingView] setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
NotifyRollupGeometryChange();
|
||||
if (isMoving) {
|
||||
|
|
@ -1341,14 +1307,7 @@ NS_IMETHODIMP nsChildView::Invalidate(const LayoutDeviceIntRect& aRect)
|
|||
NS_ASSERTION(GetLayerManager()->GetBackendType() != LayersBackend::LAYERS_CLIENT,
|
||||
"Shouldn't need to invalidate with accelerated OMTC layers!");
|
||||
|
||||
if ([NSView focusView]) {
|
||||
// if a view is focussed (i.e. being drawn), then postpone the invalidate so that we
|
||||
// don't lose it.
|
||||
[mView setNeedsPendingDisplayInRect:DevPixelsToCocoaPoints(aRect)];
|
||||
}
|
||||
else {
|
||||
[mView setNeedsDisplayInRect:DevPixelsToCocoaPoints(aRect)];
|
||||
}
|
||||
[[mView pixelHostingView] setNeedsDisplayInRect:DevPixelsToCocoaPoints(aRect)];
|
||||
|
||||
return NS_OK;
|
||||
|
||||
|
|
@ -1920,13 +1879,6 @@ void
|
|||
nsChildView::ConfigureAPZCTreeManager()
|
||||
{
|
||||
nsBaseWidget::ConfigureAPZCTreeManager();
|
||||
|
||||
if (gfxPrefs::AsyncPanZoomSeparateEventThread()) {
|
||||
if (gNumberOfWidgetsNeedingEventThread == 0) {
|
||||
[EventThreadRunner start];
|
||||
}
|
||||
gNumberOfWidgetsNeedingEventThread++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2557,14 +2509,6 @@ nsChildView::UpdateVibrancy(const nsTArray<ThemeGeometry>& aThemeGeometries)
|
|||
vm.UpdateVibrantRegion(VibrancyType::DARK, vibrantDarkRegion);
|
||||
}
|
||||
|
||||
void
|
||||
nsChildView::ClearVibrantAreas()
|
||||
{
|
||||
if (VibrancyManager::SystemSupportsVibrancy()) {
|
||||
EnsureVibrancyManager().ClearVibrantAreas();
|
||||
}
|
||||
}
|
||||
|
||||
static VibrancyType
|
||||
ThemeGeometryTypeToVibrancyType(nsITheme::ThemeGeometryType aThemeGeometryType)
|
||||
{
|
||||
|
|
@ -2617,7 +2561,7 @@ nsChildView::EnsureVibrancyManager()
|
|||
{
|
||||
MOZ_ASSERT(mView, "Only call this once we have a view!");
|
||||
if (!mVibrancyManager) {
|
||||
mVibrancyManager = MakeUnique<VibrancyManager>(*this, mView);
|
||||
mVibrancyManager = MakeUnique<VibrancyManager>(*this, [mView vibrancyViewsContainer]);
|
||||
}
|
||||
return *mVibrancyManager;
|
||||
}
|
||||
|
|
@ -2787,9 +2731,10 @@ nsChildView::UpdateWindowDraggingRegion(const LayoutDeviceIntRegion& aRegion)
|
|||
|
||||
// Suppress calls to setNeedsDisplay during NSView geometry changes.
|
||||
ManipulateViewWithoutNeedingDisplay(mView, ^() {
|
||||
changed = mNonDraggableRegion.UpdateRegion(nonDraggable, *this, mView, ^() {
|
||||
return [[NonDraggableView alloc] initWithFrame:NSZeroRect];
|
||||
});
|
||||
changed = mNonDraggableRegion.UpdateRegion(
|
||||
nonDraggable, *this, [mView nonDraggableViewsContainer], ^() {
|
||||
return [[NonDraggableView alloc] initWithFrame:NSZeroRect];
|
||||
});
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
|
|
@ -3160,6 +3105,31 @@ private:
|
|||
|
||||
#pragma mark -
|
||||
|
||||
// ViewRegionContainerView is a view class for certain subviews of ChildView
|
||||
// which contain the NSViews created for ViewRegions (see ViewRegion.h).
|
||||
// It doesn't do anything interesting, it only acts as a container so that it's
|
||||
// easier for ChildView to control the z order of its children.
|
||||
@interface ViewRegionContainerView : NSView {
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation ViewRegionContainerView
|
||||
|
||||
- (NSView*)hitTest:(NSPoint)aPoint {
|
||||
return nil; // Be transparent to mouse events.
|
||||
}
|
||||
|
||||
- (BOOL)isFlipped {
|
||||
return [[self superview] isFlipped];
|
||||
}
|
||||
|
||||
- (BOOL)mouseDownCanMoveWindow {
|
||||
return [[self superview] mouseDownCanMoveWindow];
|
||||
}
|
||||
|
||||
@end
|
||||
;
|
||||
|
||||
@implementation ChildView
|
||||
|
||||
// globalDragPboard is non-null during native drag sessions that did not originate
|
||||
|
|
@ -3215,7 +3185,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
|
||||
if ((self = [super initWithFrame:inFrame])) {
|
||||
mGeckoChild = inChild;
|
||||
mPendingDisplay = NO;
|
||||
mBlockedLastMouseDown = NO;
|
||||
mExpectingWheelStop = NO;
|
||||
|
||||
|
|
@ -3236,6 +3205,20 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
mCancelSwipeAnimation = nil;
|
||||
#endif
|
||||
|
||||
mNonDraggableViewsContainer = [[ViewRegionContainerView alloc] initWithFrame:[self bounds]];
|
||||
mVibrancyViewsContainer = [[ViewRegionContainerView alloc] initWithFrame:[self bounds]];
|
||||
|
||||
[mNonDraggableViewsContainer setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[mVibrancyViewsContainer setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
|
||||
[self addSubview:mNonDraggableViewsContainer];
|
||||
[self addSubview:mVibrancyViewsContainer];
|
||||
|
||||
mPixelHostingView = [[PixelHostingView alloc] initWithFrame:[self bounds]];
|
||||
[mPixelHostingView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
|
||||
[self addSubview:mPixelHostingView];
|
||||
|
||||
mTopLeftCornerMask = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -3250,10 +3233,9 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
selector:@selector(systemMetricsChanged)
|
||||
name:NSSystemColorsDidChangeNotification
|
||||
object:nil];
|
||||
// TODO: replace the string with the constant once we build with the 10.7 SDK
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(scrollbarSystemMetricChanged)
|
||||
name:@"NSPreferredScrollerStyleDidChangeNotification"
|
||||
name:NSPreferredScrollerStyleDidChangeNotification
|
||||
object:nil];
|
||||
[[NSDistributedNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(systemMetricsChanged)
|
||||
|
|
@ -3263,7 +3245,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(_surfaceNeedsUpdate:)
|
||||
name:NSViewGlobalFrameDidChangeNotification
|
||||
object:self];
|
||||
object:mPixelHostingView];
|
||||
|
||||
return self;
|
||||
|
||||
|
|
@ -3348,12 +3330,23 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (NSView*)vibrancyViewsContainer {
|
||||
return mVibrancyViewsContainer;
|
||||
}
|
||||
|
||||
- (NSView*)nonDraggableViewsContainer {
|
||||
return mNonDraggableViewsContainer;
|
||||
}
|
||||
|
||||
- (NSView*)pixelHostingView {
|
||||
return mPixelHostingView;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
[mGLContext release];
|
||||
[mPendingDirtyRects release];
|
||||
[mLastMouseDownEvent release];
|
||||
[mLastKeyDownEvent release];
|
||||
[mClickThroughMouseDownEvent release];
|
||||
|
|
@ -3362,6 +3355,12 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
|
||||
[mVibrancyViewsContainer removeFromSuperview];
|
||||
[mVibrancyViewsContainer release];
|
||||
[mNonDraggableViewsContainer removeFromSuperview];
|
||||
[mNonDraggableViewsContainer release];
|
||||
[mPixelHostingView removeFromSuperview];
|
||||
[mPixelHostingView release];
|
||||
|
||||
[super dealloc];
|
||||
|
||||
|
|
@ -3408,82 +3407,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
}
|
||||
}
|
||||
|
||||
- (void)setNeedsPendingDisplay
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
mPendingFullDisplay = YES;
|
||||
if (!mPendingDisplay) {
|
||||
[self performSelector:@selector(processPendingRedraws) withObject:nil afterDelay:0];
|
||||
mPendingDisplay = YES;
|
||||
}
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)setNeedsPendingDisplayInRect:(NSRect)invalidRect
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
if (!mPendingDirtyRects)
|
||||
mPendingDirtyRects = [[NSMutableArray alloc] initWithCapacity:1];
|
||||
[mPendingDirtyRects addObject:[NSValue valueWithRect:invalidRect]];
|
||||
if (!mPendingDisplay) {
|
||||
[self performSelector:@selector(processPendingRedraws) withObject:nil afterDelay:0];
|
||||
mPendingDisplay = YES;
|
||||
}
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
// Clears the queue of any pending invalides
|
||||
- (void)processPendingRedraws
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
if (mPendingFullDisplay) {
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
else if (mPendingDirtyRects) {
|
||||
unsigned int count = [mPendingDirtyRects count];
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
[self setNeedsDisplayInRect:[[mPendingDirtyRects objectAtIndex:i] rectValue]];
|
||||
}
|
||||
}
|
||||
mPendingFullDisplay = NO;
|
||||
mPendingDisplay = NO;
|
||||
[mPendingDirtyRects release];
|
||||
mPendingDirtyRects = nil;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)setNeedsDisplayInRect:(NSRect)aRect
|
||||
{
|
||||
if (![self isUsingOpenGL]) {
|
||||
[super setNeedsDisplayInRect:aRect];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([[self window] isVisible] && [self isUsingMainThreadOpenGL]) {
|
||||
// Draw without calling drawRect. This prevent us from
|
||||
// needing to access the normal window buffer surface unnecessarily, so we
|
||||
// waste less time synchronizing the two surfaces. (These synchronizations
|
||||
// show up in a profiler as CGSDeviceLock / _CGSLockWindow /
|
||||
// _CGSSynchronizeWindowBackingStore.) It also means that Cocoa doesn't
|
||||
// have any potentially expensive invalid rect management for us.
|
||||
if (!mWaitingForPaint) {
|
||||
mWaitingForPaint = YES;
|
||||
// Use NSRunLoopCommonModes instead of the default NSDefaultRunLoopMode
|
||||
// so that the timer also fires while a native menu is open.
|
||||
[self performSelector:@selector(drawUsingOpenGLCallback)
|
||||
withObject:nil
|
||||
afterDelay:0
|
||||
inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString*)description
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
|
@ -3537,25 +3460,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (void)scrollRect:(NSRect)aRect by:(NSSize)offset
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
// Update any pending dirty rects to reflect the new scroll position
|
||||
if (mPendingDirtyRects) {
|
||||
unsigned int count = [mPendingDirtyRects count];
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
NSRect oldRect = [[mPendingDirtyRects objectAtIndex:i] rectValue];
|
||||
NSRect newRect = NSOffsetRect(oldRect, offset.width, offset.height);
|
||||
[mPendingDirtyRects replaceObjectAtIndex:i
|
||||
withObject:[NSValue valueWithRect:newRect]];
|
||||
}
|
||||
}
|
||||
[super scrollRect:aRect by:offset];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (BOOL)mouseDownCanMoveWindow
|
||||
{
|
||||
// Return YES so that parts of this view can be draggable. The non-draggable
|
||||
|
|
@ -3567,7 +3471,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
|
||||
-(void)updateGLContext
|
||||
{
|
||||
[mGLContext setView:self];
|
||||
[mGLContext setView:mPixelHostingView];
|
||||
[mGLContext update];
|
||||
}
|
||||
|
||||
|
|
@ -3580,11 +3484,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
}
|
||||
}
|
||||
|
||||
- (BOOL)wantsBestResolutionOpenGLSurface
|
||||
{
|
||||
return nsCocoaUtils::HiDPIEnabled() ? YES : NO;
|
||||
}
|
||||
|
||||
- (void)viewDidChangeBackingProperties
|
||||
{
|
||||
[super viewDidChangeBackingProperties];
|
||||
|
|
@ -3646,7 +3545,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
LayoutDeviceIntRect boundingRect = mGeckoChild->CocoaPointsToDevPixels(aRect);
|
||||
const NSRect *rects;
|
||||
NSInteger count;
|
||||
[self getRectsBeingDrawn:&rects count:&count];
|
||||
[mPixelHostingView getRectsBeingDrawn:&rects count:&count];
|
||||
|
||||
if (count > MAX_RECTS_IN_REGION) {
|
||||
return boundingRect;
|
||||
|
|
@ -3662,53 +3561,28 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
|
||||
// The display system has told us that a portion of our view is dirty. Tell
|
||||
// gecko to paint it
|
||||
- (void)drawRect:(NSRect)aRect
|
||||
// This method is called from mPixelHostingView's drawRect handler.
|
||||
- (void)doDrawRect:(NSRect)aRect
|
||||
{
|
||||
CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
||||
[self drawRect:aRect inContext:cgContext];
|
||||
|
||||
// If we're a transparent window and our contents have changed, we need
|
||||
// to make sure the shadow is updated to the new contents.
|
||||
if ([[self window] isKindOfClass:[BaseWindow class]]) {
|
||||
[(BaseWindow*)[self window] deferredInvalidateShadow];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)aRect inContext:(CGContextRef)aContext
|
||||
{
|
||||
if (!mGeckoChild || !mGeckoChild->IsVisible())
|
||||
return;
|
||||
|
||||
#ifdef DEBUG_UPDATE
|
||||
LayoutDeviceIntRect geckoBounds = mGeckoChild->GetBounds();
|
||||
|
||||
fprintf (stderr, "---- Update[%p][%p] [%f %f %f %f] cgc: %p\n gecko bounds: [%d %d %d %d]\n",
|
||||
self, mGeckoChild,
|
||||
aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height, aContext,
|
||||
geckoBounds.x, geckoBounds.y, geckoBounds.width, geckoBounds.height);
|
||||
|
||||
CGAffineTransform xform = CGContextGetCTM(aContext);
|
||||
fprintf (stderr, " xform in: [%f %f %f %f %f %f]\n", xform.a, xform.b, xform.c, xform.d, xform.tx, xform.ty);
|
||||
#endif
|
||||
|
||||
if ([self isUsingOpenGL]) {
|
||||
// For Gecko-initiated repaints in OpenGL mode, drawUsingOpenGL is
|
||||
// directly called from a delayed perform callback - without going through
|
||||
// drawRect.
|
||||
// Paints that come through here are triggered by something that Cocoa
|
||||
// controls, for example by window resizing or window focus changes.
|
||||
|
||||
// Since this view is usually declared as opaque, the window's pixel
|
||||
// buffer may now contain garbage which we need to prevent from reaching
|
||||
// the screen. The only place where garbage can show is in the window
|
||||
// corners and the vibrant regions of the window - the rest of the window
|
||||
// is covered by opaque content in our OpenGL surface.
|
||||
// So we need to clear the pixel buffer contents in these areas.
|
||||
mGeckoChild->ClearVibrantAreas();
|
||||
[self clearCorners];
|
||||
|
||||
// Do GL composition and return.
|
||||
[self drawUsingOpenGL];
|
||||
// Force a sync OMTC composite into the OpenGL context and return.
|
||||
LayoutDeviceIntRect geckoBounds = mGeckoChild->GetBounds();
|
||||
LayoutDeviceIntRegion region(geckoBounds);
|
||||
|
||||
mGeckoChild->PaintWindow(region);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3720,54 +3594,31 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
// multiple dev pixels. But Gecko expects its supplied context to be scaled
|
||||
// to device pixels, so we need to reverse the scaling.
|
||||
double scale = mGeckoChild->BackingScaleFactor();
|
||||
CGContextSaveGState(aContext);
|
||||
CGContextScaleCTM(aContext, 1.0 / scale, 1.0 / scale);
|
||||
CGContextSaveGState(cgContext);
|
||||
CGContextScaleCTM(cgContext, 1.0 / scale, 1.0 / scale);
|
||||
|
||||
NSSize viewSize = [self bounds].size;
|
||||
gfx::IntSize backingSize = gfx::IntSize::Truncate(viewSize.width * scale, viewSize.height * scale);
|
||||
LayoutDeviceIntRegion region = [self nativeDirtyRegionWithBoundingRect:aRect];
|
||||
|
||||
bool painted = mGeckoChild->PaintWindowInContext(aContext, region, backingSize);
|
||||
bool painted = mGeckoChild->PaintWindowInContext(cgContext, region, backingSize);
|
||||
|
||||
// Undo the scale transform so that from now on the context is in
|
||||
// CocoaPoints again.
|
||||
CGContextRestoreGState(aContext);
|
||||
CGContextRestoreGState(cgContext);
|
||||
|
||||
if (!painted && [self isOpaque]) {
|
||||
if (!painted && [mPixelHostingView isOpaque]) {
|
||||
// Gecko refused to draw, but we've claimed to be opaque, so we have to
|
||||
// draw something--fill with white.
|
||||
CGContextSetRGBFillColor(aContext, 1, 1, 1, 1);
|
||||
CGContextFillRect(aContext, NSRectToCGRect(aRect));
|
||||
CGContextSetRGBFillColor(cgContext, 1, 1, 1, 1);
|
||||
CGContextFillRect(cgContext, NSRectToCGRect(aRect));
|
||||
}
|
||||
|
||||
if ([self isCoveringTitlebar]) {
|
||||
[self drawTitleString];
|
||||
[self drawTitlebarHighlight];
|
||||
[self maskTopCornersInContext:aContext];
|
||||
[self maskTopCornersInContext:cgContext];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_UPDATE
|
||||
fprintf (stderr, "---- update done ----\n");
|
||||
|
||||
#if 0
|
||||
CGContextSetRGBStrokeColor (aContext,
|
||||
((((unsigned long)self) & 0xff)) / 255.0,
|
||||
((((unsigned long)self) & 0xff00) >> 8) / 255.0,
|
||||
((((unsigned long)self) & 0xff0000) >> 16) / 255.0,
|
||||
0.5);
|
||||
#endif
|
||||
CGContextSetRGBStrokeColor(aContext, 1, 0, 0, 0.8);
|
||||
CGContextSetLineWidth(aContext, 4.0);
|
||||
CGContextStrokeRect(aContext, NSRectToCGRect(aRect));
|
||||
#endif
|
||||
}
|
||||
|
||||
- (BOOL)isUsingMainThreadOpenGL
|
||||
{
|
||||
if (!mGeckoChild || ![self window])
|
||||
return NO;
|
||||
|
||||
return mGeckoChild->GetLayerManager(nullptr)->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL;
|
||||
}
|
||||
|
||||
- (BOOL)isUsingOpenGL
|
||||
|
|
@ -3775,33 +3626,9 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||
if (!mGeckoChild || ![self window])
|
||||
return NO;
|
||||
|
||||
return mGLContext || mUsingOMTCompositor || [self isUsingMainThreadOpenGL];
|
||||
return mGLContext || mUsingOMTCompositor;
|
||||
}
|
||||
|
||||
- (void)drawUsingOpenGL
|
||||
{
|
||||
PROFILER_LABEL("ChildView", "drawUsingOpenGL",
|
||||
js::ProfileEntry::Category::GRAPHICS);
|
||||
|
||||
if (![self isUsingOpenGL] || !mGeckoChild->IsVisible())
|
||||
return;
|
||||
|
||||
mWaitingForPaint = NO;
|
||||
|
||||
LayoutDeviceIntRect geckoBounds = mGeckoChild->GetBounds();
|
||||
LayoutDeviceIntRegion region(geckoBounds);
|
||||
|
||||
mGeckoChild->PaintWindow(region);
|
||||
}
|
||||
|
||||
// Called asynchronously after setNeedsDisplay in order to avoid entering the
|
||||
// normal drawing machinery.
|
||||
- (void)drawUsingOpenGLCallback
|
||||
{
|
||||
if (mWaitingForPaint) {
|
||||
[self drawUsingOpenGL];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)hasRoundedBottomCorners
|
||||
{
|
||||
|
|
@ -4803,12 +4630,6 @@ GetIntegerDeltaForEvent(NSEvent* aEvent)
|
|||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
if (gfxPrefs::AsyncPanZoomSeparateEventThread() && [self apzctm]) {
|
||||
// Disable main-thread scrolling completely when using APZ with the
|
||||
// separate event thread. This is bug 1013412.
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoRetainCocoaObject kungFuDeathGrip(self);
|
||||
|
||||
ChildViewMouseTracker::MouseScrolled(theEvent);
|
||||
|
|
@ -4928,105 +4749,6 @@ GetIntegerDeltaForEvent(NSEvent* aEvent)
|
|||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)handleAsyncScrollEvent:(CGEventRef)cgEvent ofType:(CGEventType)type
|
||||
{
|
||||
IAPZCTreeManager* apzctm = [self apzctm];
|
||||
if (!apzctm) {
|
||||
return;
|
||||
}
|
||||
|
||||
CGPoint loc = CGEventGetLocation(cgEvent);
|
||||
loc.y = nsCocoaUtils::FlippedScreenY(loc.y);
|
||||
NSPoint locationInWindow =
|
||||
nsCocoaUtils::ConvertPointFromScreen([self window], NSPointFromCGPoint(loc));
|
||||
ScreenIntPoint location = ViewAs<ScreenPixel>(
|
||||
[self convertWindowCoordinates:locationInWindow],
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
|
||||
|
||||
static NSTimeInterval sStartTime = [NSDate timeIntervalSinceReferenceDate];
|
||||
static TimeStamp sStartTimeStamp = TimeStamp::Now();
|
||||
|
||||
if (type == kCGEventScrollWheel) {
|
||||
NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
|
||||
NSEventPhase phase = nsCocoaUtils::EventPhase(event);
|
||||
NSEventPhase momentumPhase = nsCocoaUtils::EventMomentumPhase(event);
|
||||
CGFloat pixelDeltaX = 0, pixelDeltaY = 0;
|
||||
nsCocoaUtils::GetScrollingDeltas(event, &pixelDeltaX, &pixelDeltaY);
|
||||
uint32_t eventTime = ([event timestamp] - sStartTime) * 1000;
|
||||
TimeStamp eventTimeStamp = sStartTimeStamp +
|
||||
TimeDuration::FromSeconds([event timestamp] - sStartTime);
|
||||
NSPoint locationInWindowMoved = NSMakePoint(
|
||||
locationInWindow.x + pixelDeltaX,
|
||||
locationInWindow.y - pixelDeltaY);
|
||||
ScreenIntPoint locationMoved = ViewAs<ScreenPixel>(
|
||||
[self convertWindowCoordinates:locationInWindowMoved],
|
||||
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
|
||||
ScreenPoint delta = ScreenPoint(locationMoved - location);
|
||||
ScrollableLayerGuid guid;
|
||||
|
||||
// MayBegin and Cancelled are dispatched when the fingers start or stop
|
||||
// touching the touchpad before any scrolling has occurred. These events
|
||||
// can be used to control scrollbar visibility or interrupt scroll
|
||||
// animations. They are only dispatched on 10.8 or later, and only by
|
||||
// relatively modern devices.
|
||||
if (phase == NSEventPhaseMayBegin) {
|
||||
PanGestureInput panInput(PanGestureInput::PANGESTURE_MAYSTART, eventTime,
|
||||
eventTimeStamp, location, ScreenPoint(0, 0), 0);
|
||||
apzctm->ReceiveInputEvent(panInput, &guid, nullptr);
|
||||
return;
|
||||
}
|
||||
if (phase == NSEventPhaseCancelled) {
|
||||
PanGestureInput panInput(PanGestureInput::PANGESTURE_CANCELLED, eventTime,
|
||||
eventTimeStamp, location, ScreenPoint(0, 0), 0);
|
||||
apzctm->ReceiveInputEvent(panInput, &guid, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Legacy scroll events are dispatched by devices that do not have a
|
||||
// concept of a scroll gesture, for example by USB mice with
|
||||
// traditional mouse wheels.
|
||||
// For these kinds of scrolls, we want to surround every single scroll
|
||||
// event with a PANGESTURE_START and a PANGESTURE_END event. The APZC
|
||||
// needs to know that the real scroll gesture can end abruptly after any
|
||||
// one of these events.
|
||||
bool isLegacyScroll = (phase == NSEventPhaseNone &&
|
||||
momentumPhase == NSEventPhaseNone && delta != ScreenPoint(0, 0));
|
||||
|
||||
if (phase == NSEventPhaseBegan || isLegacyScroll) {
|
||||
PanGestureInput panInput(PanGestureInput::PANGESTURE_START, eventTime,
|
||||
eventTimeStamp, location, ScreenPoint(0, 0), 0);
|
||||
apzctm->ReceiveInputEvent(panInput, &guid, nullptr);
|
||||
}
|
||||
if (momentumPhase == NSEventPhaseNone && delta != ScreenPoint(0, 0)) {
|
||||
PanGestureInput panInput(PanGestureInput::PANGESTURE_PAN, eventTime,
|
||||
eventTimeStamp, location, delta, 0);
|
||||
apzctm->ReceiveInputEvent(panInput, &guid, nullptr);
|
||||
}
|
||||
if (phase == NSEventPhaseEnded || isLegacyScroll) {
|
||||
PanGestureInput panInput(PanGestureInput::PANGESTURE_END, eventTime,
|
||||
eventTimeStamp, location, ScreenPoint(0, 0), 0);
|
||||
apzctm->ReceiveInputEvent(panInput, &guid, nullptr);
|
||||
}
|
||||
|
||||
// Any device that can dispatch momentum events supports all three momentum phases.
|
||||
if (momentumPhase == NSEventPhaseBegan) {
|
||||
PanGestureInput panInput(PanGestureInput::PANGESTURE_MOMENTUMSTART, eventTime,
|
||||
eventTimeStamp, location, ScreenPoint(0, 0), 0);
|
||||
apzctm->ReceiveInputEvent(panInput, &guid, nullptr);
|
||||
}
|
||||
if (momentumPhase == NSEventPhaseChanged && delta != ScreenPoint(0, 0)) {
|
||||
PanGestureInput panInput(PanGestureInput::PANGESTURE_MOMENTUMPAN, eventTime,
|
||||
eventTimeStamp, location, delta, 0);
|
||||
apzctm->ReceiveInputEvent(panInput, &guid, nullptr);
|
||||
}
|
||||
if (momentumPhase == NSEventPhaseEnded) {
|
||||
PanGestureInput panInput(PanGestureInput::PANGESTURE_MOMENTUMEND, eventTime,
|
||||
eventTimeStamp, location, ScreenPoint(0, 0), 0);
|
||||
apzctm->ReceiveInputEvent(panInput, &guid, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(NSMenu*)menuForEvent:(NSEvent*)theEvent
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
|
@ -5571,11 +5293,6 @@ GetIntegerDeltaForEvent(NSEvent* aEvent)
|
|||
return mGeckoChild->CocoaPointsToDevPixelsRoundDown(localPoint);
|
||||
}
|
||||
|
||||
- (IAPZCTreeManager*)apzctm
|
||||
{
|
||||
return mGeckoChild ? mGeckoChild->APZCTM() : nullptr;
|
||||
}
|
||||
|
||||
// This is a utility function used by NSView drag event methods
|
||||
// to send events. It contains all of the logic needed for Gecko
|
||||
// dragging to work. Returns the appropriate cocoa drag operation code.
|
||||
|
|
@ -6209,6 +5926,26 @@ nsChildView::GetSelectionAsPlaintext(nsAString& aResult)
|
|||
|
||||
@end
|
||||
|
||||
@implementation PixelHostingView
|
||||
|
||||
- (BOOL)isFlipped {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSView*)hitTest:(NSPoint)aPoint {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)aRect {
|
||||
[(ChildView*)[self superview] doDrawRect:aRect];
|
||||
}
|
||||
|
||||
- (BOOL)wantsBestResolutionOpenGLSurface {
|
||||
return nsCocoaUtils::HiDPIEnabled() ? YES : NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
void
|
||||
|
|
@ -6377,106 +6114,6 @@ ChildViewMouseTracker::WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent,
|
|||
|
||||
#pragma mark -
|
||||
|
||||
@interface EventThreadRunner(Private)
|
||||
- (void)runEventThread;
|
||||
- (void)shutdownAndReleaseCalledOnEventThread;
|
||||
- (void)shutdownAndReleaseCalledOnAnyThread;
|
||||
- (void)handleEvent:(CGEventRef)cgEvent type:(CGEventType)type;
|
||||
@end
|
||||
|
||||
static EventThreadRunner* sEventThreadRunner = nil;
|
||||
|
||||
@implementation EventThreadRunner
|
||||
|
||||
+ (void)start
|
||||
{
|
||||
sEventThreadRunner = [[EventThreadRunner alloc] init];
|
||||
}
|
||||
|
||||
+ (void)stop
|
||||
{
|
||||
if (sEventThreadRunner) {
|
||||
[sEventThreadRunner shutdownAndReleaseCalledOnAnyThread];
|
||||
sEventThreadRunner = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
mThread = nil;
|
||||
[NSThread detachNewThreadSelector:@selector(runEventThread)
|
||||
toTarget:self
|
||||
withObject:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static CGEventRef
|
||||
HandleEvent(CGEventTapProxy aProxy, CGEventType aType,
|
||||
CGEventRef aEvent, void* aClosure)
|
||||
{
|
||||
[(EventThreadRunner*)aClosure handleEvent:aEvent type:aType];
|
||||
return aEvent;
|
||||
}
|
||||
|
||||
- (void)runEventThread
|
||||
{
|
||||
char aLocal;
|
||||
profiler_register_thread("APZC Event Thread", &aLocal);
|
||||
PR_SetCurrentThreadName("APZC Event Thread");
|
||||
|
||||
mThread = [NSThread currentThread];
|
||||
ProcessSerialNumber currentProcess;
|
||||
GetCurrentProcess(¤tProcess);
|
||||
CFMachPortRef eventPort =
|
||||
CGEventTapCreateForPSN(¤tProcess,
|
||||
kCGHeadInsertEventTap,
|
||||
kCGEventTapOptionListenOnly,
|
||||
CGEventMaskBit(kCGEventScrollWheel),
|
||||
HandleEvent,
|
||||
self);
|
||||
CFRunLoopSourceRef eventPortSource =
|
||||
CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, eventPort, 0);
|
||||
CFRunLoopAddSource(CFRunLoopGetCurrent(), eventPortSource, kCFRunLoopCommonModes);
|
||||
CFRunLoopRun();
|
||||
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), eventPortSource, kCFRunLoopCommonModes);
|
||||
CFRelease(eventPortSource);
|
||||
CFRelease(eventPort);
|
||||
[self release];
|
||||
}
|
||||
|
||||
- (void)shutdownAndReleaseCalledOnEventThread
|
||||
{
|
||||
CFRunLoopStop(CFRunLoopGetCurrent());
|
||||
}
|
||||
|
||||
- (void)shutdownAndReleaseCalledOnAnyThread
|
||||
{
|
||||
[self performSelector:@selector(shutdownAndReleaseCalledOnEventThread) onThread:mThread withObject:nil waitUntilDone:NO];
|
||||
}
|
||||
|
||||
static const CGEventField kCGWindowNumberField = (const CGEventField) 51;
|
||||
|
||||
// Called on scroll thread
|
||||
- (void)handleEvent:(CGEventRef)cgEvent type:(CGEventType)type
|
||||
{
|
||||
if (type != kCGEventScrollWheel) {
|
||||
return;
|
||||
}
|
||||
|
||||
int windowNumber = CGEventGetIntegerValueField(cgEvent, kCGWindowNumberField);
|
||||
NSWindow* window = [NSApp windowWithWindowNumber:windowNumber];
|
||||
if (!window || ![window isKindOfClass:[BaseWindow class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
ChildView* childView = [(BaseWindow*)window mainChildView];
|
||||
[childView handleAsyncScrollEvent:cgEvent ofType:type];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface NSView (MethodSwizzling)
|
||||
- (BOOL)nsChildView_NSView_mouseDownCanMoveWindow;
|
||||
@end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue