macOS: Move QNSView drawing related functionality to its own file

Change-Id: Iaeaa5c57368445a1fd67d110823c919aa7173a7a
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
Tor Arne Vestbø 2018-03-19 15:58:31 +01:00
parent bbdc1b5ccb
commit 9b604a151a
3 changed files with 172 additions and 117 deletions

View File

@ -58,13 +58,15 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (instancetype)initWithCocoaWindow:(QCocoaWindow *)platformWindow;
- (void)convertFromScreen:(NSPoint)mouseLocation toWindowPoint:(QPointF *)qtWindowPoint andScreenPoint:(QPointF *)qtScreenPoint;
@end
@interface QT_MANGLE_NAMESPACE(QNSView) (DrawingAPI)
- (void)requestUpdate;
#ifndef QT_NO_OPENGL
- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
#endif
- (void)convertFromScreen:(NSPoint)mouseLocation toWindowPoint:(QPointF *)qtWindowPoint andScreenPoint:(QPointF *)qtScreenPoint;
- (void)requestUpdate;
@end
@interface QT_MANGLE_NAMESPACE(QNSView) (MouseAPI)

View File

@ -74,6 +74,9 @@
- (BOOL)isTransparentForUserInput;
@end
@interface QT_MANGLE_NAMESPACE(QNSView) (Drawing)
@end
@interface QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) : NSObject
- (instancetype)initWithView:(QNSView *)theView;
- (void)mouseMoved:(NSEvent *)theEvent;
@ -231,18 +234,6 @@
return description;
}
#ifndef QT_NO_OPENGL
- (void)setQCocoaGLContext:(QCocoaGLContext *)context
{
m_glContext = context;
[m_glContext->nsOpenGLContext() setView:self];
if (![m_glContext->nsOpenGLContext() view]) {
//was unable to set view
m_shouldSetGLContextinDrawRect = true;
}
}
#endif
- (void)viewDidMoveToSuperview
{
if (!m_platformWindow)
@ -296,107 +287,6 @@
[super removeFromSuperview];
}
- (BOOL)isOpaque
{
if (!m_platformWindow)
return true;
return m_platformWindow->isOpaque();
}
- (void)requestUpdate
{
if (self.needsDisplay) {
// If the view already has needsDisplay set it means that there may be code waiting for
// a real expose event, so we can't issue setNeedsDisplay now as a way to trigger an
// update request. We will re-trigger requestUpdate from drawRect.
return;
}
[self setNeedsDisplay:YES];
m_updateRequested = true;
}
- (void)setNeedsDisplayInRect:(NSRect)rect
{
[super setNeedsDisplayInRect:rect];
m_updateRequested = false;
}
- (void)drawRect:(NSRect)dirtyRect
{
Q_UNUSED(dirtyRect);
if (!m_platformWindow)
return;
QRegion exposedRegion;
const NSRect *dirtyRects;
NSInteger numDirtyRects;
[self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
for (int i = 0; i < numDirtyRects; ++i)
exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
[self updateRegion:exposedRegion];
}
- (void)updateRegion:(QRegion)dirtyRegion
{
#ifndef QT_NO_OPENGL
if (m_glContext && m_shouldSetGLContextinDrawRect) {
[m_glContext->nsOpenGLContext() setView:self];
m_shouldSetGLContextinDrawRect = false;
}
#endif
QWindowPrivate *windowPrivate = qt_window_private(m_platformWindow->window());
if (m_updateRequested) {
Q_ASSERT(windowPrivate->updateRequestPending);
qCDebug(lcQpaWindow) << "Delivering update request to" << m_platformWindow->window();
windowPrivate->deliverUpdateRequest();
m_updateRequested = false;
} else {
m_platformWindow->handleExposeEvent(dirtyRegion);
}
if (windowPrivate->updateRequestPending) {
// A call to QWindow::requestUpdate was issued during event delivery above,
// but AppKit will reset the needsDisplay state of the view after completing
// the current display cycle, so we need to defer the request to redisplay.
// FIXME: Perhaps this should be a trigger to enable CADisplayLink?
qCDebug(lcQpaDrawing) << "[QNSView drawRect:] issuing deferred setNeedsDisplay due to pending update request";
dispatch_async(dispatch_get_main_queue (), ^{ [self requestUpdate]; });
}
}
- (BOOL)wantsUpdateLayer
{
return YES;
}
- (void)updateLayer
{
if (!m_platformWindow)
return;
qCDebug(lcQpaDrawing) << "[QNSView updateLayer]" << m_platformWindow->window();
// FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
[self updateRegion:QRectF::fromCGRect(self.bounds).toRect()];
}
- (void)viewDidChangeBackingProperties
{
if (self.layer)
self.layer.contentsScale = self.window.backingScaleFactor;
}
- (BOOL)isFlipped
{
return YES;
}
- (BOOL)isTransparentForUserInput
{
return m_platformWindow->window() &&
@ -470,6 +360,7 @@
@end
#include "qnsview_drawing.mm"
#include "qnsview_mouse.mm"
#include "qnsview_touch.mm"
#include "qnsview_gestures.mm"

View File

@ -0,0 +1,162 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
// This file is included from qnsview.mm, and only used to organize the code
@implementation QT_MANGLE_NAMESPACE(QNSView) (DrawingAPI)
- (void)requestUpdate
{
if (self.needsDisplay) {
// If the view already has needsDisplay set it means that there may be code waiting for
// a real expose event, so we can't issue setNeedsDisplay now as a way to trigger an
// update request. We will re-trigger requestUpdate from drawRect.
return;
}
[self setNeedsDisplay:YES];
m_updateRequested = true;
}
#ifndef QT_NO_OPENGL
- (void)setQCocoaGLContext:(QCocoaGLContext *)context
{
m_glContext = context;
[m_glContext->nsOpenGLContext() setView:self];
if (![m_glContext->nsOpenGLContext() view]) {
//was unable to set view
m_shouldSetGLContextinDrawRect = true;
}
}
#endif
@end
@implementation QT_MANGLE_NAMESPACE(QNSView) (Drawing)
- (BOOL)isOpaque
{
if (!m_platformWindow)
return true;
return m_platformWindow->isOpaque();
}
- (BOOL)isFlipped
{
return YES;
}
- (void)setNeedsDisplayInRect:(NSRect)rect
{
qDebug() << "setNeedsDisplayInRect" << QRectF::fromCGRect(rect);
[super setNeedsDisplayInRect:rect];
m_updateRequested = false;
}
- (void)drawRect:(NSRect)dirtyRect
{
Q_UNUSED(dirtyRect);
if (!m_platformWindow)
return;
QRegion exposedRegion;
const NSRect *dirtyRects;
NSInteger numDirtyRects;
[self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
for (int i = 0; i < numDirtyRects; ++i)
exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
[self updateRegion:exposedRegion];
}
- (void)updateRegion:(QRegion)dirtyRegion
{
#ifndef QT_NO_OPENGL
if (m_glContext && m_shouldSetGLContextinDrawRect) {
[m_glContext->nsOpenGLContext() setView:self];
m_shouldSetGLContextinDrawRect = false;
}
#endif
QWindowPrivate *windowPrivate = qt_window_private(m_platformWindow->window());
if (m_updateRequested) {
Q_ASSERT(windowPrivate->updateRequestPending);
qCDebug(lcQpaWindow) << "Delivering update request to" << m_platformWindow->window();
windowPrivate->deliverUpdateRequest();
m_updateRequested = false;
} else {
m_platformWindow->handleExposeEvent(dirtyRegion);
}
if (windowPrivate->updateRequestPending) {
// A call to QWindow::requestUpdate was issued during event delivery above,
// but AppKit will reset the needsDisplay state of the view after completing
// the current display cycle, so we need to defer the request to redisplay.
// FIXME: Perhaps this should be a trigger to enable CADisplayLink?
qCDebug(lcQpaDrawing) << "[QNSView drawRect:] issuing deferred setNeedsDisplay due to pending update request";
dispatch_async(dispatch_get_main_queue (), ^{ [self requestUpdate]; });
}
}
- (BOOL)wantsUpdateLayer
{
return YES;
}
- (void)updateLayer
{
if (!m_platformWindow)
return;
qCDebug(lcQpaDrawing) << "[QNSView updateLayer]" << m_platformWindow->window();
// FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
[self updateRegion:QRectF::fromCGRect(self.bounds).toRect()];
}
- (void)viewDidChangeBackingProperties
{
if (self.layer)
self.layer.contentsScale = self.window.backingScaleFactor;
}
@end