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)
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(CALayer);
|
||||
typedef long NSInteger;
|
||||
enum NSVisualEffectMaterial : NSInteger;
|
||||
enum NSVisualEffectBlendingMode : NSInteger;
|
||||
enum NSVisualEffectState: NSInteger;
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -63,6 +67,9 @@ struct Q_GUI_EXPORT QCocoaWindow
|
||||
virtual void setContentBorderEnabled(bool enable) = 0;
|
||||
virtual QPoint bottomLeftClippedByNSWindowOffset() const = 0;
|
||||
virtual CALayer *contentLayer() const = 0;
|
||||
virtual void manageVisualEffectArea(quintptr identifier, const QRect &rect,
|
||||
NSVisualEffectMaterial material, NSVisualEffectBlendingMode blendMode,
|
||||
NSVisualEffectState activationState) = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -19,11 +19,12 @@
|
||||
#include <MoltenVK/mvk_vulkan.h>
|
||||
#endif
|
||||
|
||||
#include <QHash>
|
||||
#include <QtCore/private/qflatmap_p.h>
|
||||
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(NSWindow);
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(NSView);
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(NSCursor);
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(NSVisualEffectView);
|
||||
|
||||
#if !defined(__OBJC__)
|
||||
using NSInteger = long;
|
||||
@ -227,6 +228,11 @@ public: // for QNSView
|
||||
|
||||
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;
|
||||
QCocoaNSWindow *m_nsWindow = nil;
|
||||
|
||||
|
@ -2224,6 +2224,47 @@ CALayer *QCocoaWindow::contentLayer() const
|
||||
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
|
||||
QDebug operator<<(QDebug debug, const QCocoaWindow *window)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user