Cocoa: Add QCocoaWindowPointer
This patch extends 5b54c352ed
by abstracting the watcher pattern. The class is specialized
for QCocoaWindow since it's aware of the QObject sentinel there.
We update the usage in QNSWindowHelper and extend it to the
forward window (this one is used for mouse coordinate conversion
when docking windows).
Change-Id: I628415527593daec835bbad1b6e83d13fe7b6703
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
This commit is contained in:
parent
e6c0373421
commit
6eb27afcdf
@ -38,6 +38,7 @@
|
||||
|
||||
#include <qpa/qplatformwindow.h>
|
||||
#include <QRect>
|
||||
#include <QPointer>
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
#include "qcocoaglcontext.h"
|
||||
@ -47,6 +48,32 @@
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QCocoaWindow)
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QCocoaWindowPointer
|
||||
{
|
||||
public:
|
||||
void assign(QCocoaWindow *w);
|
||||
void clear();
|
||||
|
||||
QCocoaWindow *data() const
|
||||
{ return watcher.isNull() ? Q_NULLPTR : window; }
|
||||
bool isNull() const
|
||||
{ return watcher.isNull(); }
|
||||
operator QCocoaWindow*() const
|
||||
{ return data(); }
|
||||
QCocoaWindow *operator->() const
|
||||
{ return data(); }
|
||||
QCocoaWindow &operator*() const
|
||||
{ return *data(); }
|
||||
|
||||
private:
|
||||
QPointer<QObject> watcher;
|
||||
QCocoaWindow *window;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@class QT_MANGLE_NAMESPACE(QNSWindowHelper);
|
||||
|
||||
@protocol QNSWindowProtocol
|
||||
@ -63,14 +90,13 @@ typedef NSWindow<QNSWindowProtocol> QCocoaNSWindow;
|
||||
@interface QT_MANGLE_NAMESPACE(QNSWindowHelper) : NSObject
|
||||
{
|
||||
QCocoaNSWindow *_window;
|
||||
QCocoaWindow *_platformWindow;
|
||||
QCocoaWindowPointer _platformWindow;
|
||||
BOOL _grabbingMouse;
|
||||
BOOL _releaseOnMouseUp;
|
||||
QPointer<QObject> _watcher;
|
||||
}
|
||||
|
||||
@property (nonatomic, readonly) QCocoaNSWindow *window;
|
||||
@property (nonatomic, readonly) QCocoaWindow *platformWindow;
|
||||
@property (nonatomic, readonly) QCocoaWindowPointer platformWindow;
|
||||
@property (nonatomic) BOOL grabbingMouse;
|
||||
@property (nonatomic) BOOL releaseOnMouseUp;
|
||||
|
||||
@ -254,7 +280,7 @@ public: // for QNSView
|
||||
NSView *m_contentView;
|
||||
QNSView *m_qtView;
|
||||
QCocoaNSWindow *m_nsWindow;
|
||||
QCocoaWindow *m_forwardWindow;
|
||||
QCocoaWindowPointer m_forwardWindow;
|
||||
|
||||
// TODO merge to one variable if possible
|
||||
bool m_contentViewIsEmbedded; // true if the m_contentView is actually embedded in a "foreign" NSView hiearchy
|
||||
@ -317,9 +343,8 @@ public: // for QNSView
|
||||
QHash<quintptr, BorderRange> m_contentBorderAreas; // identifer -> uppper/lower
|
||||
QHash<quintptr, bool> m_enabledContentBorderAreas; // identifer -> enabled state (true/false)
|
||||
|
||||
// This object is tracked by a 'watcher'
|
||||
// object in a window helper, preventing use of dangling
|
||||
// pointers.
|
||||
// This object is tracked by QCocoaWindowPointer,
|
||||
// preventing the use of dangling pointers.
|
||||
QObject sentinel;
|
||||
};
|
||||
|
||||
|
@ -85,7 +85,7 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_window = window;
|
||||
_platformWindow = platformWindow;
|
||||
_platformWindow.assign(platformWindow);
|
||||
|
||||
_window.delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:_platformWindow];
|
||||
|
||||
@ -94,7 +94,6 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
// make sure that m_nsWindow stays valid until the
|
||||
// QCocoaWindow is deleted by Qt.
|
||||
[_window setReleasedWhenClosed:NO];
|
||||
_watcher = &_platformWindow->sentinel;
|
||||
}
|
||||
|
||||
return self;
|
||||
@ -103,19 +102,19 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
- (void)handleWindowEvent:(NSEvent *)theEvent
|
||||
{
|
||||
QCocoaWindow *pw = self.platformWindow;
|
||||
if (_watcher && pw && pw->m_forwardWindow) {
|
||||
if (pw && pw->m_forwardWindow) {
|
||||
if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) {
|
||||
QNSView *forwardView = pw->m_qtView;
|
||||
if (theEvent.type == NSLeftMouseUp) {
|
||||
[forwardView mouseUp:theEvent];
|
||||
pw->m_forwardWindow = 0;
|
||||
pw->m_forwardWindow.clear();
|
||||
} else {
|
||||
[forwardView mouseDragged:theEvent];
|
||||
}
|
||||
}
|
||||
|
||||
if (!pw->m_isNSWindowChild && theEvent.type == NSLeftMouseDown) {
|
||||
pw->m_forwardWindow = 0;
|
||||
pw->m_forwardWindow.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,7 +141,7 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
if (!self.window.delegate)
|
||||
return; // Already detached, pending NSAppKitDefined event
|
||||
|
||||
if (_watcher && pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
|
||||
if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
|
||||
NSPoint loc = [theEvent locationInWindow];
|
||||
NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]];
|
||||
NSRect contentFrame = [[self.window contentView] frame];
|
||||
@ -157,8 +156,7 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
|
||||
- (void)detachFromPlatformWindow
|
||||
{
|
||||
_platformWindow = 0;
|
||||
_watcher.clear();
|
||||
self.platformWindow.clear();
|
||||
[self.window.delegate release];
|
||||
self.window.delegate = nil;
|
||||
}
|
||||
@ -179,7 +177,7 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
- (void)dealloc
|
||||
{
|
||||
_window = nil;
|
||||
_platformWindow = 0;
|
||||
self.platformWindow.clear();
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@ -331,6 +329,18 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
|
||||
@end
|
||||
|
||||
void QCocoaWindowPointer::assign(QCocoaWindow *w)
|
||||
{
|
||||
window = w;
|
||||
watcher = &w->sentinel;
|
||||
}
|
||||
|
||||
void QCocoaWindowPointer::clear()
|
||||
{
|
||||
window = Q_NULLPTR;
|
||||
watcher.clear();
|
||||
}
|
||||
|
||||
const int QCocoaWindow::NoAlertRequest = -1;
|
||||
|
||||
QCocoaWindow::QCocoaWindow(QWindow *tlw)
|
||||
@ -338,7 +348,6 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
|
||||
, m_contentView(nil)
|
||||
, m_qtView(nil)
|
||||
, m_nsWindow(0)
|
||||
, m_forwardWindow(0)
|
||||
, m_contentViewIsEmbedded(false)
|
||||
, m_contentViewIsToBeEmbedded(false)
|
||||
, m_parentCocoaWindow(0)
|
||||
@ -1320,7 +1329,7 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
|
||||
if (oldParentCocoaWindow) {
|
||||
if (!m_isNSWindowChild || oldParentCocoaWindow != m_parentCocoaWindow)
|
||||
oldParentCocoaWindow->removeChildWindow(this);
|
||||
m_forwardWindow = oldParentCocoaWindow;
|
||||
m_forwardWindow.assign(oldParentCocoaWindow);
|
||||
}
|
||||
|
||||
setNSWindow(m_nsWindow);
|
||||
|
@ -741,7 +741,7 @@ QT_WARNING_POP
|
||||
if (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)
|
||||
targetView = m_platformWindow->m_forwardWindow->m_qtView;
|
||||
else
|
||||
m_platformWindow->m_forwardWindow = 0;
|
||||
m_platformWindow->m_forwardWindow.clear();
|
||||
}
|
||||
|
||||
// Popups implicitly grap mouse events; forward to the active popup if there is one
|
||||
|
Loading…
Reference in New Issue
Block a user