5#include <QtGui/qtguiglobal.h>
7#include <AppKit/AppKit.h>
8#include <MetalKit/MetalKit.h>
9#include <UniformTypeIdentifiers/UTCoreTypes.h>
18#include <qpa/qplatformintegration.h>
20#include <qpa/qwindowsysteminterface.h>
21#include <QtGui/QTextFormat>
22#include <QtCore/QDebug>
23#include <QtCore/QPointer>
25#include <QtCore/private/qcore_mac_p.h>
26#include <QtGui/QAccessible>
27#include <QtGui/QImage>
28#include <private/qguiapplication_p.h>
29#include <private/qcoregraphics_p.h>
30#include <private/qwindow_p.h>
31#include <private/qpointingdevice_p.h>
32#include <private/qhighdpiscaling_p.h>
38#include <QtGui/private/qmacmimeregistry_p.h>
39#include <QtGui/private/qmetallayer_p.h>
41#include <QuartzCore/CATransaction.h>
43@interface QNSView (Drawing) <CALayerDelegate>
47@interface QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) : NSObject
48- (instancetype)initWithView:(QNSView *)theView;
49- (
void)mouseMoved:(NSEvent *)theEvent;
50- (
void)mouseEntered:(NSEvent *)theEvent;
51- (
void)mouseExited:(NSEvent *)theEvent;
52- (
void)cursorUpdate:(NSEvent *)theEvent;
55QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSViewMouseMoveHelper);
57@interface QNSView (Mouse)
59- (NSPoint)screenMousePoint:(NSEvent *)theEvent;
60- (
void)mouseMovedImpl:(NSEvent *)theEvent;
61- (
void)mouseEnteredImpl:(NSEvent *)theEvent;
62- (
void)mouseExitedImpl:(NSEvent *)theEvent;
65@interface QNSView (Touch)
68@interface QNSView (Tablet)
69- (
bool)handleTabletEvent:(NSEvent *)theEvent;
72@interface QNSView (Gestures)
75@interface QNSView (Dragging)
76-(
void)registerDragTypes;
79@interface QNSView (Keys)
82@interface QNSView (ComplexText) <NSTextInputClient>
83@property (readonly) QObject* focusObject;
86@interface QNSView (ServicesMenu) <NSServicesMenuRequestor>
89#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(150000
)
90@interface QNSView (ContentSelectionInfo) <NSViewContentSelectionInfo>
94@interface QT_MANGLE_NAMESPACE(QNSViewMenuHelper) : NSObject
95- (instancetype)initWithView:(QNSView *)theView;
97QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSViewMenuHelper);
101- (BOOL)isTransparentForUserInput;
102@property (assign) NSView* previousSuperview;
103@property (assign) NSWindow* previousWindow;
104@property (retain) QNSViewMenuHelper* menuHelper;
105@property (nonatomic, retain) NSColorSpace *colorSpace;
108@implementation QNSView {
109 QPointer<QCocoaWindow> m_platformWindow;
112 QNSViewMouseMoveHelper *m_mouseMoveHelper;
113 Qt::MouseButtons m_buttons;
114 Qt::MouseButtons m_acceptedMouseDowns;
115 Qt::MouseButtons m_frameStrutButtons;
116 Qt::KeyboardModifiers m_currentWheelModifiers;
117 bool m_dontOverrideCtrlLMB;
118 bool m_sendUpAsRightButton;
125 bool m_sendKeyEventWithoutText;
126 NSEvent *m_currentlyInterpretedKeyEvent;
127 QSet<quint32> m_acceptedKeyDowns;
130 QString m_composingText;
131 QPointer<QObject> m_composingFocusObject;
134@synthesize colorSpace = m_colorSpace;
136- (instancetype)initWithCocoaWindow:(QCocoaWindow *)platformWindow
138 if ((self = [super initWithFrame:NSZeroRect])) {
139 m_platformWindow = platformWindow;
148 self.focusRingType = NSFocusRingTypeNone;
150 self.previousSuperview = nil;
151 self.previousWindow = nil;
155 [self registerDragTypes];
157 m_updatingDrag =
false;
159 m_lastKeyDead =
false;
160 m_sendKeyEvent =
false;
161 m_currentlyInterpretedKeyEvent = nil;
163 self.menuHelper = [[[QNSViewMenuHelper alloc] initWithView:self] autorelease];
170 qCDebug(lcQpaWindow) <<
"Deallocating" << self;
172 self.menuHelper = nil;
174 [[NSNotificationCenter defaultCenter] removeObserver:self];
175 [m_mouseMoveHelper release];
182 NSMutableString *description = [NSMutableString stringWithString:[super description]];
184#ifndef QT_NO_DEBUG_STREAM
185 QString platformWindowDescription;
186 QDebug debug(&platformWindowDescription);
187 debug.nospace() <<
"; " << m_platformWindow <<
">";
189 NSRange lastCharacter = [description rangeOfComposedCharacterSequenceAtIndex:description.length - 1];
190 [description replaceCharactersInRange:lastCharacter withString:platformWindowDescription.toNSString()];
198- (
void)removeFromSuperview
200 qCDebug(lcQpaWindow) <<
"Removing" << self <<
"from" << self.superview;
201 QMacAutoReleasePool pool;
202 [super removeFromSuperview];
205- (
void)viewWillMoveToSuperview:(NSView *)newSuperview
207 Q_ASSERT(!self.previousSuperview);
208 self.previousSuperview = self.superview;
210 if (newSuperview == self.superview)
211 qCDebug(lcQpaWindow) <<
"Re-ordering" << self <<
"inside" << self.superview;
213 qCDebug(lcQpaWindow) <<
"Re-parenting" << self <<
"from" << self.superview <<
"to" << newSuperview;
216- (
void)viewDidMoveToSuperview
218 auto cleanup = qScopeGuard([&] { self.previousSuperview = nil; });
220 if (self.superview == self.previousSuperview) {
221 qCDebug(lcQpaWindow) <<
"Done re-ordering" << self <<
"new index:"
222 << [self.superview.subviews indexOfObject:self];
226 qCDebug(lcQpaWindow) <<
"Done re-parenting" << self <<
"into" << self.superview;
231 if (m_platformWindow && m_platformWindow->isEmbedded()) {
233 m_platformWindow->handleGeometryChange();
236 [self setNeedsDisplay:YES];
240- (
void)viewWillMoveToWindow:(NSWindow *)newWindow
242 Q_ASSERT(!self.previousWindow);
243 self.previousWindow = self.window;
247 if (newWindow == self.window)
250 qCDebug(lcQpaWindow) <<
"Moving" << self <<
"from" << self.window <<
"to" << newWindow;
256- (
void)viewDidMoveToWindow
258 auto cleanup = qScopeGuard([&] { self.previousWindow = nil; });
262 if (self.window == self.previousWindow)
265 qCDebug(lcQpaWindow) <<
"Done moving" << self <<
"to" << self.window;
268 if (m_platformWindow && m_platformWindow->isEmbedded())
269 m_platformWindow->recreateWindowIfNeeded();
279- (
void)didAddSubview:(NSView *)subview
281 self.clipsToBounds = YES;
284- (
void)willRemoveSubview:(NSView *)subview
286 self.clipsToBounds = self.subviews.count > 1;
293 if (!m_platformWindow)
296 QWindow *focusWindow = m_platformWindow->window();
300 if (qstrcmp(focusWindow->metaObject()->className(),
"QWidgetWindow") == 0) {
301 while (focusWindow->parent()) {
302 focusWindow = focusWindow->parent();
310
311
312
315 qCDebug(lcQpaWindow) <<
"Did hide" << self;
317 if (!m_platformWindow->isExposed())
320 m_platformWindow->handleExposeEvent(QRegion());
324
325
326
329 qCDebug(lcQpaWindow) <<
"Did unhide" << self;
331 [self setNeedsDisplay:YES];
334- (BOOL)isTransparentForUserInput
336 return m_platformWindow->window() &&
337 m_platformWindow->window()->flags() & Qt::WindowTransparentForInput;
340- (BOOL)becomeFirstResponder
342 if (!m_platformWindow)
344 if ([self isTransparentForUserInput])
347 if (!m_platformWindow->windowIsPopupType()
348 && (!self.window.canBecomeKeyWindow || self.window.keyWindow)) {
364 QWindowSystemInterface::handleFocusWindowChanged<QWindowSystemInterface::SynchronousDelivery>(
365 [self topLevelWindow], Qt::ActiveWindowFocusReason);
371- (BOOL)acceptsFirstResponder
373 if (!m_platformWindow)
375 if (m_platformWindow->shouldRefuseKeyWindowAndFirstResponder())
377 if ([self isTransparentForUserInput])
379 if ((m_platformWindow->window()->flags() & Qt::ToolTip) == Qt::ToolTip)
384- (
NSView *)hitTest:(NSPoint)aPoint
386 NSView *candidate = [super hitTest:aPoint];
387 if (candidate == self) {
388 if ([self isTransparentForUserInput])
394- (
void)convertFromScreen:(NSPoint)mouseLocation toWindowPoint:(QPointF *)qtWindowPoint andScreenPoint:(QPointF *)qtScreenPoint
414 NSWindow *window = [self window];
415 NSPoint nsWindowPoint;
416 NSRect windowRect = [window convertRectFromScreen:NSMakeRect(mouseLocation.x, mouseLocation.y, 1, 1)];
417 nsWindowPoint = windowRect.origin;
418 NSPoint nsViewPoint = [self convertPoint: nsWindowPoint fromView: nil];
419 *qtWindowPoint = QPointF(nsViewPoint.x, nsViewPoint.y);
420 *qtScreenPoint = QCocoaScreen::mapFromNative(mouseLocation);
434#if QT_CONFIG(accessibility)
435#include "qnsview_accessibility.mm"
440@implementation QNSView (QtExtras)
442- (QCocoaWindow*)platformWindow
444 return m_platformWindow.data();;
Q_FORWARD_DECLARE_OBJC_CLASS(NSView)
Q_FORWARD_DECLARE_OBJC_CLASS(NSString)