|
@@ -23,10 +23,6 @@ namespace QWK {
|
|
|
|
|
|
|
|
using ProxyList = QHash<WId, NSWindowProxy *>;
|
|
using ProxyList = QHash<WId, NSWindowProxy *>;
|
|
|
Q_GLOBAL_STATIC(ProxyList, g_proxyList);
|
|
Q_GLOBAL_STATIC(ProxyList, g_proxyList);
|
|
|
-
|
|
|
|
|
- using ProxyList2 = QHash<NSWindow *, NSWindowProxy *>;
|
|
|
|
|
- Q_GLOBAL_STATIC(ProxyList2, g_proxyIndexes);
|
|
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
struct QWK_NSWindowDelegate {
|
|
struct QWK_NSWindowDelegate {
|
|
@@ -87,7 +83,8 @@ public:
|
|
|
|
|
|
|
|
- (void)windowWillEnterFullScreen:(NSNotification *)notification {
|
|
- (void)windowWillEnterFullScreen:(NSNotification *)notification {
|
|
|
auto nswindow = reinterpret_cast<NSWindow *>(notification.object);
|
|
auto nswindow = reinterpret_cast<NSWindow *>(notification.object);
|
|
|
- if (auto proxy = QWK::g_proxyIndexes->value(nswindow)) {
|
|
|
|
|
|
|
+ auto nsview = [nswindow contentView];
|
|
|
|
|
+ if (auto proxy = QWK::g_proxyList->value(reinterpret_cast<WId>(nsview))) {
|
|
|
reinterpret_cast<QWK_NSWindowDelegate *>(proxy)->windowEvent(
|
|
reinterpret_cast<QWK_NSWindowDelegate *>(proxy)->windowEvent(
|
|
|
QWK_NSWindowDelegate::WillEnterFullScreen);
|
|
QWK_NSWindowDelegate::WillEnterFullScreen);
|
|
|
}
|
|
}
|
|
@@ -95,7 +92,8 @@ public:
|
|
|
|
|
|
|
|
- (void)windowDidEnterFullScreen:(NSNotification *)notification {
|
|
- (void)windowDidEnterFullScreen:(NSNotification *)notification {
|
|
|
auto nswindow = reinterpret_cast<NSWindow *>(notification.object);
|
|
auto nswindow = reinterpret_cast<NSWindow *>(notification.object);
|
|
|
- if (auto proxy = QWK::g_proxyIndexes->value(nswindow)) {
|
|
|
|
|
|
|
+ auto nsview = [nswindow contentView];
|
|
|
|
|
+ if (auto proxy = QWK::g_proxyList->value(reinterpret_cast<WId>(nsview))) {
|
|
|
reinterpret_cast<QWK_NSWindowDelegate *>(proxy)->windowEvent(
|
|
reinterpret_cast<QWK_NSWindowDelegate *>(proxy)->windowEvent(
|
|
|
QWK_NSWindowDelegate::DidEnterFullScreen);
|
|
QWK_NSWindowDelegate::DidEnterFullScreen);
|
|
|
}
|
|
}
|
|
@@ -103,7 +101,8 @@ public:
|
|
|
|
|
|
|
|
- (void)windowWillExitFullScreen:(NSNotification *)notification {
|
|
- (void)windowWillExitFullScreen:(NSNotification *)notification {
|
|
|
auto nswindow = reinterpret_cast<NSWindow *>(notification.object);
|
|
auto nswindow = reinterpret_cast<NSWindow *>(notification.object);
|
|
|
- if (auto proxy = QWK::g_proxyIndexes->value(nswindow)) {
|
|
|
|
|
|
|
+ auto nsview = [nswindow contentView];
|
|
|
|
|
+ if (auto proxy = QWK::g_proxyList->value(reinterpret_cast<WId>(nsview))) {
|
|
|
reinterpret_cast<QWK_NSWindowDelegate *>(proxy)->windowEvent(
|
|
reinterpret_cast<QWK_NSWindowDelegate *>(proxy)->windowEvent(
|
|
|
QWK_NSWindowDelegate::WillExitFullScreen);
|
|
QWK_NSWindowDelegate::WillExitFullScreen);
|
|
|
}
|
|
}
|
|
@@ -111,7 +110,8 @@ public:
|
|
|
|
|
|
|
|
- (void)windowDidExitFullScreen:(NSNotification *)notification {
|
|
- (void)windowDidExitFullScreen:(NSNotification *)notification {
|
|
|
auto nswindow = reinterpret_cast<NSWindow *>(notification.object);
|
|
auto nswindow = reinterpret_cast<NSWindow *>(notification.object);
|
|
|
- if (auto proxy = QWK::g_proxyIndexes->value(nswindow)) {
|
|
|
|
|
|
|
+ auto nsview = [nswindow contentView];
|
|
|
|
|
+ if (auto proxy = QWK::g_proxyList->value(reinterpret_cast<WId>(nsview))) {
|
|
|
reinterpret_cast<QWK_NSWindowDelegate *>(proxy)->windowEvent(
|
|
reinterpret_cast<QWK_NSWindowDelegate *>(proxy)->windowEvent(
|
|
|
QWK_NSWindowDelegate::DidExitFullScreen);
|
|
QWK_NSWindowDelegate::DidExitFullScreen);
|
|
|
}
|
|
}
|
|
@@ -119,7 +119,8 @@ public:
|
|
|
|
|
|
|
|
- (void)windowDidResize:(NSNotification *)notification {
|
|
- (void)windowDidResize:(NSNotification *)notification {
|
|
|
auto nswindow = reinterpret_cast<NSWindow *>(notification.object);
|
|
auto nswindow = reinterpret_cast<NSWindow *>(notification.object);
|
|
|
- if (auto proxy = QWK::g_proxyIndexes->value(nswindow)) {
|
|
|
|
|
|
|
+ auto nsview = [nswindow contentView];
|
|
|
|
|
+ if (auto proxy = QWK::g_proxyList->value(reinterpret_cast<WId>(nsview))) {
|
|
|
reinterpret_cast<QWK_NSWindowDelegate *>(proxy)->windowEvent(
|
|
reinterpret_cast<QWK_NSWindowDelegate *>(proxy)->windowEvent(
|
|
|
QWK_NSWindowDelegate::DidResize);
|
|
QWK_NSWindowDelegate::DidResize);
|
|
|
}
|
|
}
|
|
@@ -127,6 +128,10 @@ public:
|
|
|
|
|
|
|
|
@end
|
|
@end
|
|
|
|
|
|
|
|
|
|
+@interface QWK_NSViewObserver : NSObject
|
|
|
|
|
+- (instancetype)initWithProxy:(QWK::NSWindowProxy*)proxy;
|
|
|
|
|
+@end
|
|
|
|
|
+
|
|
|
//
|
|
//
|
|
|
// Objective C++ End
|
|
// Objective C++ End
|
|
|
//
|
|
//
|
|
@@ -140,13 +145,19 @@ namespace QWK {
|
|
|
None,
|
|
None,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- NSWindowProxy(NSWindow *macWindow) {
|
|
|
|
|
- nswindow = macWindow;
|
|
|
|
|
- g_proxyIndexes->insert(nswindow, this);
|
|
|
|
|
|
|
+ NSWindowProxy(NSView *macView) {
|
|
|
|
|
+ nsview = macView;
|
|
|
|
|
+
|
|
|
|
|
+ observer = [[QWK_NSViewObserver alloc] initWithProxy:this];
|
|
|
|
|
+ [nsview addObserver:observer
|
|
|
|
|
+ forKeyPath:@"window"
|
|
|
|
|
+ options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
|
|
|
|
|
+ context:nil];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
~NSWindowProxy() override {
|
|
~NSWindowProxy() override {
|
|
|
- g_proxyIndexes->remove(nswindow);
|
|
|
|
|
|
|
+ [nsview removeObserver:observer forKeyPath:@"window"];
|
|
|
|
|
+ [observer release];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Delegate
|
|
// Delegate
|
|
@@ -213,6 +224,9 @@ namespace QWK {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void updateSystemButtonRect() {
|
|
void updateSystemButtonRect() {
|
|
|
|
|
+ if (!screenRectCallback || !systemButtonVisible) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
const auto &buttons = systemButtons();
|
|
const auto &buttons = systemButtons();
|
|
|
const auto &leftButton = buttons[0];
|
|
const auto &leftButton = buttons[0];
|
|
|
const auto &midButton = buttons[1];
|
|
const auto &midButton = buttons[1];
|
|
@@ -225,8 +239,7 @@ namespace QWK {
|
|
|
auto width = midButton.frame.size.width;
|
|
auto width = midButton.frame.size.width;
|
|
|
auto height = midButton.frame.size.height;
|
|
auto height = midButton.frame.size.height;
|
|
|
|
|
|
|
|
- auto viewSize =
|
|
|
|
|
- nswindow.contentView ? nswindow.contentView.frame.size : nswindow.frame.size;
|
|
|
|
|
|
|
+ auto viewSize = nsview.frame.size;
|
|
|
QPoint center = screenRectCallback(QSize(viewSize.width, titlebarHeight)).center();
|
|
QPoint center = screenRectCallback(QSize(viewSize.width, titlebarHeight)).center();
|
|
|
|
|
|
|
|
// The origin of the NSWindow coordinate system is in the lower left corner, we
|
|
// The origin of the NSWindow coordinate system is in the lower left corner, we
|
|
@@ -256,6 +269,10 @@ namespace QWK {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline std::array<NSButton *, 3> systemButtons() {
|
|
inline std::array<NSButton *, 3> systemButtons() {
|
|
|
|
|
+ auto nswindow = [nsview window];
|
|
|
|
|
+ if (!nswindow) {
|
|
|
|
|
+ return {nullptr, nullptr, nullptr};
|
|
|
|
|
+ }
|
|
|
NSButton *closeBtn = [nswindow standardWindowButton:NSWindowCloseButton];
|
|
NSButton *closeBtn = [nswindow standardWindowButton:NSWindowCloseButton];
|
|
|
NSButton *minimizeBtn = [nswindow standardWindowButton:NSWindowMiniaturizeButton];
|
|
NSButton *minimizeBtn = [nswindow standardWindowButton:NSWindowMiniaturizeButton];
|
|
|
NSButton *zoomBtn = [nswindow standardWindowButton:NSWindowZoomButton];
|
|
NSButton *zoomBtn = [nswindow standardWindowButton:NSWindowZoomButton];
|
|
@@ -263,6 +280,10 @@ namespace QWK {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline int titleBarHeight() const {
|
|
inline int titleBarHeight() const {
|
|
|
|
|
+ auto nswindow = [nsview window];
|
|
|
|
|
+ if (!nswindow) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
NSButton *closeBtn = [nswindow standardWindowButton:NSWindowCloseButton];
|
|
NSButton *closeBtn = [nswindow standardWindowButton:NSWindowCloseButton];
|
|
|
return closeBtn.superview.frame.size.height;
|
|
return closeBtn.superview.frame.size.height;
|
|
|
}
|
|
}
|
|
@@ -274,8 +295,7 @@ namespace QWK {
|
|
|
return false;
|
|
return false;
|
|
|
|
|
|
|
|
NSVisualEffectView *effectView = nil;
|
|
NSVisualEffectView *effectView = nil;
|
|
|
- NSView *const view = [nswindow contentView];
|
|
|
|
|
- for (NSView *subview in [[view superview] subviews]) {
|
|
|
|
|
|
|
+ for (NSView *subview in [[nsview superview] subviews]) {
|
|
|
if ([subview isKindOfClass:visualEffectViewClass]) {
|
|
if ([subview isKindOfClass:visualEffectViewClass]) {
|
|
|
effectView = reinterpret_cast<NSVisualEffectView *>(subview);
|
|
effectView = reinterpret_cast<NSVisualEffectView *>(subview);
|
|
|
}
|
|
}
|
|
@@ -311,8 +331,8 @@ namespace QWK {
|
|
|
|
|
|
|
|
// System title bar
|
|
// System title bar
|
|
|
void setSystemTitleBarVisible(const bool visible) {
|
|
void setSystemTitleBarVisible(const bool visible) {
|
|
|
- NSView *nsview = [nswindow contentView];
|
|
|
|
|
- if (!nsview) {
|
|
|
|
|
|
|
+ auto nswindow = [nsview window];
|
|
|
|
|
+ if (!nswindow) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -396,7 +416,9 @@ namespace QWK {
|
|
|
|
|
|
|
|
protected:
|
|
protected:
|
|
|
static BOOL canBecomeKeyWindow(id obj, SEL sel) {
|
|
static BOOL canBecomeKeyWindow(id obj, SEL sel) {
|
|
|
- if (g_proxyIndexes->contains(reinterpret_cast<NSWindow *>(obj))) {
|
|
|
|
|
|
|
+ auto nswindow = reinterpret_cast<NSWindow *>(obj);
|
|
|
|
|
+ auto nsview = [nswindow contentView];
|
|
|
|
|
+ if (g_proxyList->contains(reinterpret_cast<WId>(nsview))) {
|
|
|
return YES;
|
|
return YES;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -408,7 +430,9 @@ namespace QWK {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static BOOL canBecomeMainWindow(id obj, SEL sel) {
|
|
static BOOL canBecomeMainWindow(id obj, SEL sel) {
|
|
|
- if (g_proxyIndexes->contains(reinterpret_cast<NSWindow *>(obj))) {
|
|
|
|
|
|
|
+ auto nswindow = reinterpret_cast<NSWindow *>(obj);
|
|
|
|
|
+ auto nsview = [nswindow contentView];
|
|
|
|
|
+ if (g_proxyList->contains(reinterpret_cast<WId>(nsview))) {
|
|
|
return YES;
|
|
return YES;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -420,7 +444,9 @@ namespace QWK {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void setStyleMask(id obj, SEL sel, NSWindowStyleMask styleMask) {
|
|
static void setStyleMask(id obj, SEL sel, NSWindowStyleMask styleMask) {
|
|
|
- if (g_proxyIndexes->contains(reinterpret_cast<NSWindow *>(obj))) {
|
|
|
|
|
|
|
+ auto nswindow = reinterpret_cast<NSWindow *>(obj);
|
|
|
|
|
+ auto nsview = [nswindow contentView];
|
|
|
|
|
+ if (g_proxyList->contains(reinterpret_cast<WId>(nsview))) {
|
|
|
styleMask |= NSWindowStyleMaskFullSizeContentView;
|
|
styleMask |= NSWindowStyleMaskFullSizeContentView;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -430,7 +456,9 @@ namespace QWK {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void setTitlebarAppearsTransparent(id obj, SEL sel, BOOL transparent) {
|
|
static void setTitlebarAppearsTransparent(id obj, SEL sel, BOOL transparent) {
|
|
|
- if (g_proxyIndexes->contains(reinterpret_cast<NSWindow *>(obj))) {
|
|
|
|
|
|
|
+ auto nswindow = reinterpret_cast<NSWindow *>(obj);
|
|
|
|
|
+ auto nsview = [nswindow contentView];
|
|
|
|
|
+ if (g_proxyList->contains(reinterpret_cast<WId>(nsview))) {
|
|
|
transparent = YES;
|
|
transparent = YES;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -463,7 +491,8 @@ namespace QWK {
|
|
|
private:
|
|
private:
|
|
|
Q_DISABLE_COPY(NSWindowProxy)
|
|
Q_DISABLE_COPY(NSWindowProxy)
|
|
|
|
|
|
|
|
- NSWindow *nswindow = nil;
|
|
|
|
|
|
|
+ NSView *nsview = nil;
|
|
|
|
|
+ QWK_NSViewObserver* observer = nil;
|
|
|
|
|
|
|
|
bool systemButtonVisible = true;
|
|
bool systemButtonVisible = true;
|
|
|
ScreenRectCallback screenRectCallback;
|
|
ScreenRectCallback screenRectCallback;
|
|
@@ -500,8 +529,8 @@ namespace QWK {
|
|
|
|
|
|
|
|
auto it = g_proxyList->find(windowId);
|
|
auto it = g_proxyList->find(windowId);
|
|
|
if (it == g_proxyList->end()) {
|
|
if (it == g_proxyList->end()) {
|
|
|
- NSWindow *nswindow = mac_getNSWindow(windowId);
|
|
|
|
|
- const auto proxy = new NSWindowProxy(nswindow);
|
|
|
|
|
|
|
+ NSView *nsview = reinterpret_cast<NSView *>(windowId);
|
|
|
|
|
+ const auto proxy = new NSWindowProxy(nsview);
|
|
|
it = g_proxyList->insert(windowId, proxy);
|
|
it = g_proxyList->insert(windowId, proxy);
|
|
|
}
|
|
}
|
|
|
return it.value();
|
|
return it.value();
|
|
@@ -701,7 +730,12 @@ namespace QWK {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Allocate new resources
|
|
// Allocate new resources
|
|
|
- ensureWindowProxy(winId)->setSystemTitleBarVisible(false);
|
|
|
|
|
|
|
+ const auto proxy = ensureWindowProxy(winId);
|
|
|
|
|
+ if (proxy) {
|
|
|
|
|
+ proxy->setSystemButtonVisible(!windowAttribute(QStringLiteral("no-system-buttons")).toBool());
|
|
|
|
|
+ proxy->setScreenRectCallback(m_systemButtonAreaCallback);
|
|
|
|
|
+ proxy->setSystemTitleBarVisible(false);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool CocoaWindowContext::windowAttributeChanged(const QString &key, const QVariant &attribute,
|
|
bool CocoaWindowContext::windowAttributeChanged(const QString &key, const QVariant &attribute,
|
|
@@ -711,7 +745,11 @@ namespace QWK {
|
|
|
Q_ASSERT(m_windowId);
|
|
Q_ASSERT(m_windowId);
|
|
|
|
|
|
|
|
if (key == QStringLiteral("no-system-buttons")) {
|
|
if (key == QStringLiteral("no-system-buttons")) {
|
|
|
|
|
+#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
|
|
if (attribute.type() != QVariant::Bool)
|
|
if (attribute.type() != QVariant::Bool)
|
|
|
|
|
+#else
|
|
|
|
|
+ if (attribute.typeId() != QMetaType::Type::Bool)
|
|
|
|
|
+#endif
|
|
|
return false;
|
|
return false;
|
|
|
ensureWindowProxy(m_windowId)->setSystemButtonVisible(!attribute.toBool());
|
|
ensureWindowProxy(m_windowId)->setSystemButtonVisible(!attribute.toBool());
|
|
|
return true;
|
|
return true;
|
|
@@ -719,14 +757,22 @@ namespace QWK {
|
|
|
|
|
|
|
|
if (key == QStringLiteral("blur-effect")) {
|
|
if (key == QStringLiteral("blur-effect")) {
|
|
|
auto mode = NSWindowProxy::BlurMode::None;
|
|
auto mode = NSWindowProxy::BlurMode::None;
|
|
|
|
|
+#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
|
|
if (attribute.type() == QVariant::Bool) {
|
|
if (attribute.type() == QVariant::Bool) {
|
|
|
|
|
+#else
|
|
|
|
|
+ if (attribute.typeId() == QMetaType::Type::Bool) {
|
|
|
|
|
+#endif
|
|
|
if (attribute.toBool()) {
|
|
if (attribute.toBool()) {
|
|
|
NSString *osxMode =
|
|
NSString *osxMode =
|
|
|
[[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
|
|
[[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
|
|
|
mode = [osxMode isEqualToString:@"Dark"] ? NSWindowProxy::BlurMode::Dark
|
|
mode = [osxMode isEqualToString:@"Dark"] ? NSWindowProxy::BlurMode::Dark
|
|
|
: NSWindowProxy::BlurMode::Light;
|
|
: NSWindowProxy::BlurMode::Light;
|
|
|
}
|
|
}
|
|
|
|
|
+#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
|
|
} else if (attribute.type() == QVariant::String) {
|
|
} else if (attribute.type() == QVariant::String) {
|
|
|
|
|
+#else
|
|
|
|
|
+ } else if (attribute.typeId() == QMetaType::Type::QString) {
|
|
|
|
|
+#endif
|
|
|
auto value = attribute.toString();
|
|
auto value = attribute.toString();
|
|
|
if (value == QStringLiteral("dark")) {
|
|
if (value == QStringLiteral("dark")) {
|
|
|
mode = NSWindowProxy::BlurMode::Dark;
|
|
mode = NSWindowProxy::BlurMode::Dark;
|
|
@@ -746,3 +792,33 @@ namespace QWK {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+@implementation QWK_NSViewObserver {
|
|
|
|
|
+ QWK::NSWindowProxy* _proxy; // Weak reference
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+- (instancetype)initWithProxy:(QWK::NSWindowProxy*)proxy {
|
|
|
|
|
+ if (self = [super init]) {
|
|
|
|
|
+ _proxy = proxy;
|
|
|
|
|
+ }
|
|
|
|
|
+ return self;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Using QEvent::Show to call setSystemTitleBarVisible/updateSystemButtonRect could also work,
|
|
|
|
|
+// but observing the window property change via KVO provides more immediate notification when
|
|
|
|
|
+// the NSWindow becomes available, making this approach more natural and reliable.
|
|
|
|
|
+- (void)observeValueForKeyPath:(NSString*)keyPath
|
|
|
|
|
+ ofObject:(id)object
|
|
|
|
|
+ change:(NSDictionary*)change
|
|
|
|
|
+ context:(void*)context {
|
|
|
|
|
+ if ([keyPath isEqualToString:@"window"]) {
|
|
|
|
|
+ NSWindow* newWindow = change[NSKeyValueChangeNewKey];
|
|
|
|
|
+ // NSWindow* oldWindow = change[NSKeyValueChangeOldKey];
|
|
|
|
|
+ if (newWindow) {
|
|
|
|
|
+ _proxy->setSystemTitleBarVisible(false);
|
|
|
|
|
+ _proxy->updateSystemButtonRect();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@end
|