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 plugins 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 #ifndef QCOCOAWINDOW_H 41 #define QCOCOAWINDOW_H 42 43 #include <AppKit/AppKit.h> 44 45 #include <qpa/qplatformwindow.h> 46 #include <QRect> 47 #include <QPointer> 48 49 #ifndef QT_NO_OPENGL 50 #include "qcocoaglcontext.h" 51 #endif 52 #include "qnsview.h" 53 #include "qnswindow.h" 54 55 #if QT_CONFIG(vulkan) 56 #include <MoltenVK/mvk_vulkan.h> 57 #endif 58 59 QT_BEGIN_NAMESPACE 60 61 #ifndef QT_NO_DEBUG_STREAM 62 class QDebug; 63 #endif 64 65 // QCocoaWindow 66 // 67 // QCocoaWindow is an NSView (not an NSWindow!) in the sense 68 // that it relies on a NSView for all event handling and 69 // graphics output and does not require a NSWindow, except for 70 // for the window-related functions like setWindowTitle. 71 // 72 // As a consequence of this it is possible to embed the QCocoaWindow 73 // in an NSView hierarchy by getting a pointer to the "backing" 74 // NSView and not calling QCocoaWindow::show(): 75 // 76 // QWindow *qtWindow = new MyWindow(); 77 // qtWindow->create(); 78 // QPlatformNativeInterface *platformNativeInterface = QGuiApplication::platformNativeInterface(); 79 // NSView *qtView = (NSView *)platformNativeInterface->nativeResourceForWindow("nsview", qtWindow); 80 // [parentView addSubview:qtView]; 81 // 82 // See the qt_on_cocoa manual tests for a working example, located 83 // in tests/manual/cocoa at the time of writing. 84 85 #ifdef Q_MOC_RUN 86 #define Q_NOTIFICATION_HANDLER(notification) Q_INVOKABLE Q_COCOA_NOTIFICATION_##notification 87 #else 88 #define Q_NOTIFICATION_HANDLER(notification) 89 #define Q_NOTIFICATION_PREFIX QT_STRINGIFY2(Q_COCOA_NOTIFICATION_) 90 #endif 91 92 class QCocoaMenuBar; 93 94 class QCocoaWindow : public QObject, public QPlatformWindow 95 { 96 Q_OBJECT 97 public: 98 QCocoaWindow(QWindow *tlw, WId nativeHandle = 0); 99 ~QCocoaWindow(); 100 101 void initialize() override; 102 103 void setGeometry(const QRect &rect) override; 104 QRect geometry() const override; 105 void setCocoaGeometry(const QRect &rect); 106 107 void setVisible(bool visible) override; 108 void setWindowFlags(Qt::WindowFlags flags) override; 109 void setWindowState(Qt::WindowStates state) override; 110 void setWindowTitle(const QString &title) override; 111 void setWindowFilePath(const QString &filePath) override; 112 void setWindowIcon(const QIcon &icon) override; 113 void setAlertState(bool enabled) override; 114 bool isAlertState() const override; 115 void raise() override; 116 void lower() override; 117 bool isExposed() const override; 118 bool isEmbedded() const override; 119 bool isOpaque() const; 120 void propagateSizeHints() override; 121 void setOpacity(qreal level) override; 122 void setMask(const QRegion ®ion) override; 123 bool setKeyboardGrabEnabled(bool grab) override; 124 bool setMouseGrabEnabled(bool grab) override; 125 QMargins frameMargins() const override; 126 QSurfaceFormat format() const override; 127 128 bool isForeignWindow() const override; 129 130 void requestUpdate() override; 131 bool updatesWithDisplayLink() const; 132 void deliverUpdateRequest() override; 133 134 void requestActivateWindow() override; 135 136 WId winId() const override; 137 void setParent(const QPlatformWindow *window) override; 138 139 NSView *view() const; 140 NSWindow *nativeWindow() const; 141 142 void setEmbeddedInForeignView(); 143 144 Q_NOTIFICATION_HANDLER(NSViewFrameDidChangeNotification) void viewDidChangeFrame(); 145 Q_NOTIFICATION_HANDLER(NSViewGlobalFrameDidChangeNotification) void viewDidChangeGlobalFrame(); 146 147 Q_NOTIFICATION_HANDLER(NSWindowWillMoveNotification) void windowWillMove(); 148 Q_NOTIFICATION_HANDLER(NSWindowDidMoveNotification) void windowDidMove(); 149 Q_NOTIFICATION_HANDLER(NSWindowDidResizeNotification) void windowDidResize(); 150 Q_NOTIFICATION_HANDLER(NSWindowDidEndLiveResizeNotification) void windowDidEndLiveResize(); 151 Q_NOTIFICATION_HANDLER(NSWindowDidBecomeKeyNotification) void windowDidBecomeKey(); 152 Q_NOTIFICATION_HANDLER(NSWindowDidResignKeyNotification) void windowDidResignKey(); 153 Q_NOTIFICATION_HANDLER(NSWindowWillMiniaturizeNotification) void windowWillMiniaturize(); 154 Q_NOTIFICATION_HANDLER(NSWindowDidMiniaturizeNotification) void windowDidMiniaturize(); 155 Q_NOTIFICATION_HANDLER(NSWindowDidDeminiaturizeNotification) void windowDidDeminiaturize(); 156 Q_NOTIFICATION_HANDLER(NSWindowWillEnterFullScreenNotification) void windowWillEnterFullScreen(); 157 Q_NOTIFICATION_HANDLER(NSWindowDidEnterFullScreenNotification) void windowDidEnterFullScreen(); 158 Q_NOTIFICATION_HANDLER(NSWindowWillExitFullScreenNotification) void windowWillExitFullScreen(); 159 Q_NOTIFICATION_HANDLER(NSWindowDidExitFullScreenNotification) void windowDidExitFullScreen(); 160 Q_NOTIFICATION_HANDLER(NSWindowDidOrderOnScreenAndFinishAnimatingNotification) void windowDidOrderOnScreen(); 161 Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen(); 162 Q_NOTIFICATION_HANDLER(NSWindowDidChangeOcclusionStateNotification) void windowDidChangeOcclusionState(); 163 Q_NOTIFICATION_HANDLER(NSWindowDidChangeScreenNotification) void windowDidChangeScreen(); 164 Q_NOTIFICATION_HANDLER(NSWindowWillCloseNotification) void windowWillClose(); 165 166 bool windowShouldClose(); 167 bool windowIsPopupType(Qt::WindowType type = Qt::Widget) const; 168 169 NSInteger windowLevel(Qt::WindowFlags flags); 170 NSUInteger windowStyleMask(Qt::WindowFlags flags); 171 void setWindowZoomButton(Qt::WindowFlags flags); 172 173 bool setWindowModified(bool modified) override; 174 175 void setFrameStrutEventsEnabled(bool enabled) override; frameStrutEventsEnabled()176 bool frameStrutEventsEnabled() const override 177 { return m_frameStrutEventsEnabled; } 178 179 void setMenubar(QCocoaMenuBar *mb); 180 QCocoaMenuBar *menubar() const; 181 182 void setWindowCursor(NSCursor *cursor); 183 184 void registerTouch(bool enable); 185 void setContentBorderThickness(int topThickness, int bottomThickness); 186 void registerContentBorderArea(quintptr identifier, int upper, int lower); 187 void setContentBorderAreaEnabled(quintptr identifier, bool enable); 188 void setContentBorderEnabled(bool enable); 189 bool testContentBorderAreaPosition(int position) const; 190 void applyContentBorderThickness(NSWindow *window = nullptr); 191 void updateNSToolbar(); 192 193 qreal devicePixelRatio() const override; 194 QWindow *childWindowAt(QPoint windowPoint); 195 bool shouldRefuseKeyWindowAndFirstResponder(); 196 197 static QPoint bottomLeftClippedByNSWindowOffsetStatic(QWindow *window); 198 QPoint bottomLeftClippedByNSWindowOffset() const; 199 200 enum RecreationReason { 201 RecreationNotNeeded = 0, 202 ParentChanged = 0x1, 203 MissingWindow = 0x2, 204 WindowModalityChanged = 0x4, 205 ContentViewChanged = 0x10, 206 PanelChanged = 0x20, 207 }; 208 Q_DECLARE_FLAGS(RecreationReasons, RecreationReason) 209 Q_FLAG(RecreationReasons) 210 211 protected: 212 void recreateWindowIfNeeded(); 213 QCocoaNSWindow *createNSWindow(bool shouldBePanel); 214 215 Qt::WindowState windowState() const; 216 void applyWindowState(Qt::WindowStates newState); 217 void toggleMaximized(); 218 void toggleFullScreen(); 219 bool isTransitioningToFullScreen() const; 220 221 bool startSystemMove() override; 222 223 // private: 224 public: // for QNSView 225 friend class QCocoaBackingStore; 226 friend class QCocoaNativeInterface; 227 228 bool isContentView() const; 229 230 bool alwaysShowToolWindow() const; 231 void removeMonitor(); 232 233 enum HandleFlags { 234 NoHandleFlags = 0, 235 HandleUnconditionally = 1 236 }; 237 238 void handleGeometryChange(); 239 void handleWindowStateChanged(HandleFlags flags = NoHandleFlags); 240 void handleExposeEvent(const QRegion ®ion); 241 242 NSView *m_view; 243 QCocoaNSWindow *m_nsWindow; 244 245 Qt::WindowStates m_lastReportedWindowState; 246 Qt::WindowModality m_windowModality; 247 QPointer<QWindow> m_enterLeaveTargetWindow; 248 bool m_windowUnderMouse; 249 250 bool m_initialized; 251 bool m_inSetVisible; 252 bool m_inSetGeometry; 253 bool m_inSetStyleMask; 254 QCocoaMenuBar *m_menubar; 255 256 bool m_needsInvalidateShadow; 257 258 bool m_frameStrutEventsEnabled; 259 QRect m_exposedRect; 260 int m_registerTouchCount; 261 bool m_resizableTransientParent; 262 263 static const int NoAlertRequest; 264 NSInteger m_alertRequest; 265 id monitor; 266 267 bool m_drawContentBorderGradient; 268 int m_topContentBorderThickness; 269 int m_bottomContentBorderThickness; 270 271 struct BorderRange { BorderRangeBorderRange272 BorderRange(quintptr i, int u, int l) : identifier(i), upper(u), lower(l) { } 273 quintptr identifier; 274 int upper; 275 int lower; 276 bool operator<(BorderRange const& right) const { 277 return upper < right.upper; 278 } 279 }; 280 QHash<quintptr, BorderRange> m_contentBorderAreas; // identifer -> uppper/lower 281 QHash<quintptr, bool> m_enabledContentBorderAreas; // identifer -> enabled state (true/false) 282 283 #if QT_CONFIG(vulkan) 284 VkSurfaceKHR m_vulkanSurface = nullptr; 285 #endif 286 }; 287 288 #ifndef QT_NO_DEBUG_STREAM 289 QDebug operator<<(QDebug debug, const QCocoaWindow *window); 290 #endif 291 292 QT_END_NAMESPACE 293 294 #endif // QCOCOAWINDOW_H 295 296