1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#import <AppKit/AppKit.h>
41#include "qmacnativewidget_mac.h"
42
43#include <QtCore/qdebug.h>
44#include <QtGui/qwindow.h>
45#include <QtGui/qguiapplication.h>
46#include <qpa/qplatformnativeinterface.h>
47
48/*!
49    \class QMacNativeWidget
50    \since 4.5
51    \brief The QMacNativeWidget class provides a widget for \macos that provides
52    a way to put Qt widgets into Cocoa hierarchies.
53
54    \ingroup advanced
55    \inmodule QtWidgets
56
57    On \macos, there is a difference between a window and view;
58    normally expressed as widgets in Qt.  Qt makes assumptions about its
59    parent-child hierarchy that make it complex to put an arbitrary Qt widget
60    into a hierarchy of "normal" views from Apple frameworks. QMacNativeWidget
61    bridges the gap between views and windows and makes it possible to put a
62    hierarchy of Qt widgets into a non-Qt window or view.
63
64    QMacNativeWidget pretends it is a window (i.e. isWindow() will return true),
65    but it cannot be shown on its own. It needs to be put into a window
66    when it is created or later through a native call.
67
68    Here is an example showing how to put a QPushButton into a NSWindow:
69
70    \snippet qmacnativewidget/main.mm 0
71
72    Note that QMacNativeWidget requires knowledge of Cocoa. All it
73    does is get the Qt hierarchy into a window not owned by Qt. It is then up
74    to the programmer to ensure it is placed correctly in the window and
75    responds correctly to events.
76*/
77
78QT_BEGIN_NAMESPACE
79
80namespace {
81// TODO use QtMacExtras copy of this function when available.
82inline QPlatformNativeInterface::NativeResourceForIntegrationFunction resolvePlatformFunction(const QByteArray &functionName)
83{
84    QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
85    QPlatformNativeInterface::NativeResourceForIntegrationFunction function =
86        nativeInterface->nativeResourceFunctionForIntegration(functionName);
87    if (Q_UNLIKELY(!function))
88         qWarning("Qt could not resolve function %s from "
89                  "QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration()",
90                  functionName.constData());
91    return function;
92}
93} //namespsace
94
95NSView *getEmbeddableView(QWindow *qtWindow)
96{
97    // Make sure the platform window is created
98    qtWindow->create();
99
100    // Inform the window that it's a subwindow of a non-Qt window. This must be
101    // done after create() because we need to have a QPlatformWindow instance.
102    // The corresponding NSWindow will not be shown and can be deleted later.
103    typedef void (*SetEmbeddedInForeignViewFunction)(QPlatformWindow *window, bool embedded);
104    reinterpret_cast<SetEmbeddedInForeignViewFunction>(resolvePlatformFunction("setEmbeddedInForeignView"))(qtWindow->handle(), true);
105
106    // Get the Qt content NSView for the QWindow from the Qt platform plugin
107    QPlatformNativeInterface *platformNativeInterface = QGuiApplication::platformNativeInterface();
108    NSView *qtView = (NSView *)platformNativeInterface->nativeResourceForWindow("nsview", qtWindow);
109    return qtView; // qtView is ready for use.
110}
111
112/*!
113    Create a QMacNativeWidget with \a parentView as its "superview" (i.e.,
114    parent). The \a parentView is  a NSView pointer.
115*/
116QMacNativeWidget::QMacNativeWidget(NSView *parentView)
117    : QWidget(0)
118{
119    Q_UNUSED(parentView);
120
121    //d_func()->topData()->embedded = true;
122    setPalette(QPalette(Qt::transparent));
123    setAttribute(Qt::WA_SetPalette, false);
124    setAttribute(Qt::WA_LayoutUsesWidgetRect);
125    setAttribute(Qt::WA_TranslucentBackground);
126    setAttribute(Qt::WA_NoSystemBackground, false);
127}
128
129/*!
130    Destroy the QMacNativeWidget.
131*/
132QMacNativeWidget::~QMacNativeWidget()
133{
134}
135
136/*!
137    \reimp
138*/
139QSize QMacNativeWidget::sizeHint() const
140{
141    // QMacNativeWidget really does not have any other choice
142    // than to fill its designated area.
143    if (windowHandle())
144        return windowHandle()->size();
145    return QWidget::sizeHint();
146}
147
148/*!
149    Returns the native view backing the QMacNativeWidget.
150
151*/
152NSView *QMacNativeWidget::nativeView() const
153{
154    winId();
155    return getEmbeddableView(windowHandle());
156}
157
158/*!
159    \reimp
160*/
161bool QMacNativeWidget::event(QEvent *ev)
162{
163    return QWidget::event(ev);
164}
165
166QT_END_NAMESPACE
167