macOS: Add native interface API to manage visual effect view
NSVisualEffectView is the only supported way to add effects to views, such as showing a blurred representation of the content under the window, or within the window. Now that we render the content of our QNSView into a sublayer of the view's root layer, we can add NSVisualEffectViews as child views without obscuring the view's own content, by making sure that the NSVisualEffectView layer has a lower Z order in the layer tree of our view's root layer. This works because adding a layer-backed or -hosted view as a subview will also add its layer as a sublayer of the view's layer, making the effect layer and our content layer sibling layers. Change-Id: Iab822e8462f54025559b3e3f26c7df668c885d75 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
parent
db7e2d6fd0
commit
6f67925799
@ -30,6 +30,10 @@ struct wl_surface;
|
|||||||
|
|
||||||
#if defined(Q_OS_MACOS)
|
#if defined(Q_OS_MACOS)
|
||||||
Q_FORWARD_DECLARE_OBJC_CLASS(CALayer);
|
Q_FORWARD_DECLARE_OBJC_CLASS(CALayer);
|
||||||
|
typedef long NSInteger;
|
||||||
|
enum NSVisualEffectMaterial : NSInteger;
|
||||||
|
enum NSVisualEffectBlendingMode : NSInteger;
|
||||||
|
enum NSVisualEffectState: NSInteger;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -63,6 +67,9 @@ struct Q_GUI_EXPORT QCocoaWindow
|
|||||||
virtual void setContentBorderEnabled(bool enable) = 0;
|
virtual void setContentBorderEnabled(bool enable) = 0;
|
||||||
virtual QPoint bottomLeftClippedByNSWindowOffset() const = 0;
|
virtual QPoint bottomLeftClippedByNSWindowOffset() const = 0;
|
||||||
virtual CALayer *contentLayer() const = 0;
|
virtual CALayer *contentLayer() const = 0;
|
||||||
|
virtual void manageVisualEffectArea(quintptr identifier, const QRect &rect,
|
||||||
|
NSVisualEffectMaterial material, NSVisualEffectBlendingMode blendMode,
|
||||||
|
NSVisualEffectState activationState) = 0;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -19,11 +19,12 @@
|
|||||||
#include <MoltenVK/mvk_vulkan.h>
|
#include <MoltenVK/mvk_vulkan.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QHash>
|
#include <QtCore/private/qflatmap_p.h>
|
||||||
|
|
||||||
Q_FORWARD_DECLARE_OBJC_CLASS(NSWindow);
|
Q_FORWARD_DECLARE_OBJC_CLASS(NSWindow);
|
||||||
Q_FORWARD_DECLARE_OBJC_CLASS(NSView);
|
Q_FORWARD_DECLARE_OBJC_CLASS(NSView);
|
||||||
Q_FORWARD_DECLARE_OBJC_CLASS(NSCursor);
|
Q_FORWARD_DECLARE_OBJC_CLASS(NSCursor);
|
||||||
|
Q_FORWARD_DECLARE_OBJC_CLASS(NSVisualEffectView);
|
||||||
|
|
||||||
#if !defined(__OBJC__)
|
#if !defined(__OBJC__)
|
||||||
using NSInteger = long;
|
using NSInteger = long;
|
||||||
@ -227,6 +228,11 @@ public: // for QNSView
|
|||||||
|
|
||||||
CALayer *contentLayer() const override;
|
CALayer *contentLayer() const override;
|
||||||
|
|
||||||
|
void manageVisualEffectArea(quintptr identifier, const QRect &rect,
|
||||||
|
NSVisualEffectMaterial material, NSVisualEffectBlendingMode blendMode,
|
||||||
|
NSVisualEffectState activationState) override;
|
||||||
|
QFlatMap<quintptr, NSVisualEffectView*> m_effectViews;
|
||||||
|
|
||||||
NSView *m_view = nil;
|
NSView *m_view = nil;
|
||||||
QCocoaNSWindow *m_nsWindow = nil;
|
QCocoaNSWindow *m_nsWindow = nil;
|
||||||
|
|
||||||
|
@ -2224,6 +2224,47 @@ CALayer *QCocoaWindow::contentLayer() const
|
|||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QCocoaWindow::manageVisualEffectArea(quintptr identifier, const QRect &rect,
|
||||||
|
NSVisualEffectMaterial material, NSVisualEffectBlendingMode blendMode,
|
||||||
|
NSVisualEffectState activationState)
|
||||||
|
{
|
||||||
|
if (!qt_objc_cast<QContainerLayer*>(m_view.layer)) {
|
||||||
|
qCWarning(lcQpaWindow) << "Can not manage visual effect areas"
|
||||||
|
<< "in views without a container layer";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(lcQpaWindow) << "Updating visual effect area" << identifier
|
||||||
|
<< "to" << rect << "with material" << material << "blend mode"
|
||||||
|
<< blendMode << "and activation state" << activationState;
|
||||||
|
|
||||||
|
NSVisualEffectView *effectView = nullptr;
|
||||||
|
if (m_effectViews.contains(identifier)) {
|
||||||
|
effectView = m_effectViews.value(identifier);
|
||||||
|
if (rect.isEmpty()) {
|
||||||
|
[effectView removeFromSuperview];
|
||||||
|
m_effectViews.remove(identifier);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (!rect.isEmpty()) {
|
||||||
|
effectView = [NSVisualEffectView new];
|
||||||
|
// Ensure that the visual effect layer is stacked well
|
||||||
|
// below our content layer (which defaults to a z of 0).
|
||||||
|
effectView.wantsLayer = YES;
|
||||||
|
effectView.layer.zPosition = -FLT_MAX;
|
||||||
|
[m_view addSubview:effectView];
|
||||||
|
m_effectViews.insert(identifier, effectView);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!effectView)
|
||||||
|
return;
|
||||||
|
|
||||||
|
effectView.frame = rect.toCGRect();
|
||||||
|
effectView.material = material;
|
||||||
|
effectView.blendingMode = blendMode;
|
||||||
|
effectView.state = activationState;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG_STREAM
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
QDebug operator<<(QDebug debug, const QCocoaWindow *window)
|
QDebug operator<<(QDebug debug, const QCocoaWindow *window)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user