| | |
| | | #include "cocoawindowcontext_p.h" |
| | | |
| | | #include <objc/runtime.h> |
| | | #include <AppKit/AppKit.h> |
| | | |
| | | #include <QtGui/QGuiApplication> |
| | | |
| | | namespace QWK { |
| | | |
| | | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
| | |
| | | } g_hook{}; |
| | | #endif |
| | | |
| | | class NSWindowProxy |
| | | { |
| | | Q_DISABLE_COPY_MOVE(NSWindowProxy) |
| | | |
| | | class NSWindowProxy : public QObject { |
| | | Q_OBJECT |
| | | public: |
| | | NSWindowProxy(NSWindow *macWindow) |
| | | { |
| | | NSWindowProxy(NSWindow *macWindow) { |
| | | if (instances.contains(macWindow)) { |
| | | return; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | ~NSWindowProxy() override |
| | | { |
| | | ~NSWindowProxy() override { |
| | | instances.remove(nswindow); |
| | | if (instances.count() <= 0) { |
| | | restoreImplementations(); |
| | |
| | | } |
| | | |
| | | public Q_SLOTS: |
| | | void replaceImplementations() |
| | | { |
| | | void replaceImplementations() { |
| | | Method method = class_getInstanceMethod(windowClass, @selector(setStyleMask:)); |
| | | Q_ASSERT(method); |
| | | oldSetStyleMask = reinterpret_cast<setStyleMaskPtr>(method_setImplementation(method, reinterpret_cast<IMP>(setStyleMask))); |
| | | oldSetStyleMask = reinterpret_cast<setStyleMaskPtr>( |
| | | method_setImplementation(method, reinterpret_cast<IMP>(setStyleMask))); |
| | | Q_ASSERT(oldSetStyleMask); |
| | | |
| | | method = class_getInstanceMethod(windowClass, @selector(setTitlebarAppearsTransparent:)); |
| | | method = |
| | | class_getInstanceMethod(windowClass, @selector(setTitlebarAppearsTransparent:)); |
| | | Q_ASSERT(method); |
| | | oldSetTitlebarAppearsTransparent = reinterpret_cast<setTitlebarAppearsTransparentPtr>(method_setImplementation(method, reinterpret_cast<IMP>(setTitlebarAppearsTransparent))); |
| | | oldSetTitlebarAppearsTransparent = |
| | | reinterpret_cast<setTitlebarAppearsTransparentPtr>(method_setImplementation( |
| | | method, reinterpret_cast<IMP>(setTitlebarAppearsTransparent))); |
| | | Q_ASSERT(oldSetTitlebarAppearsTransparent); |
| | | |
| | | #if 0 |
| | |
| | | |
| | | method = class_getInstanceMethod(windowClass, @selector(sendEvent:)); |
| | | Q_ASSERT(method); |
| | | oldSendEvent = reinterpret_cast<sendEventPtr>(method_setImplementation(method, reinterpret_cast<IMP>(sendEvent))); |
| | | oldSendEvent = reinterpret_cast<sendEventPtr>( |
| | | method_setImplementation(method, reinterpret_cast<IMP>(sendEvent))); |
| | | Q_ASSERT(oldSendEvent); |
| | | } |
| | | |
| | | void restoreImplementations() |
| | | { |
| | | void restoreImplementations() { |
| | | Method method = class_getInstanceMethod(windowClass, @selector(setStyleMask:)); |
| | | Q_ASSERT(method); |
| | | method_setImplementation(method, reinterpret_cast<IMP>(oldSetStyleMask)); |
| | | oldSetStyleMask = nil; |
| | | |
| | | method = class_getInstanceMethod(windowClass, @selector(setTitlebarAppearsTransparent:)); |
| | | method = |
| | | class_getInstanceMethod(windowClass, @selector(setTitlebarAppearsTransparent:)); |
| | | Q_ASSERT(method); |
| | | method_setImplementation(method, reinterpret_cast<IMP>(oldSetTitlebarAppearsTransparent)); |
| | | method_setImplementation(method, |
| | | reinterpret_cast<IMP>(oldSetTitlebarAppearsTransparent)); |
| | | oldSetTitlebarAppearsTransparent = nil; |
| | | |
| | | #if 0 |
| | |
| | | oldSendEvent = nil; |
| | | } |
| | | |
| | | void setSystemTitleBarVisible(const bool visible) |
| | | { |
| | | void setSystemTitleBarVisible(const bool visible) { |
| | | NSView *nsview = [nswindow contentView]; |
| | | if (!nsview) { |
| | | return; |
| | |
| | | nswindow.showsToolbarButton = NO; |
| | | nswindow.movableByWindowBackground = NO; |
| | | nswindow.movable = NO; |
| | | // For some unknown reason, we don't need the following hack in Qt versions below or equal to 6.2.4. |
| | | // For some unknown reason, we don't need the following hack in Qt versions below or |
| | | // equal to 6.2.4. |
| | | #if (QT_VERSION > QT_VERSION_CHECK(6, 2, 4)) |
| | | [nswindow standardWindowButton:NSWindowCloseButton].hidden = (visible ? NO : YES); |
| | | [nswindow standardWindowButton:NSWindowMiniaturizeButton].hidden = (visible ? NO : YES); |
| | |
| | | } |
| | | |
| | | private: |
| | | static BOOL canBecomeKeyWindow(id obj, SEL sel) |
| | | { |
| | | static BOOL canBecomeKeyWindow(id obj, SEL sel) { |
| | | if (instances.contains(reinterpret_cast<NSWindow *>(obj))) { |
| | | return YES; |
| | | } |
| | |
| | | return YES; |
| | | } |
| | | |
| | | static BOOL canBecomeMainWindow(id obj, SEL sel) |
| | | { |
| | | static BOOL canBecomeMainWindow(id obj, SEL sel) { |
| | | if (instances.contains(reinterpret_cast<NSWindow *>(obj))) { |
| | | return YES; |
| | | } |
| | |
| | | return YES; |
| | | } |
| | | |
| | | static void setStyleMask(id obj, SEL sel, NSWindowStyleMask styleMask) |
| | | { |
| | | static void setStyleMask(id obj, SEL sel, NSWindowStyleMask styleMask) { |
| | | if (instances.contains(reinterpret_cast<NSWindow *>(obj))) { |
| | | styleMask |= NSWindowStyleMaskFullSizeContentView; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | static void setTitlebarAppearsTransparent(id obj, SEL sel, BOOL transparent) |
| | | { |
| | | static void setTitlebarAppearsTransparent(id obj, SEL sel, BOOL transparent) { |
| | | if (instances.contains(reinterpret_cast<NSWindow *>(obj))) { |
| | | transparent = YES; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | static void sendEvent(id obj, SEL sel, NSEvent *event) |
| | | { |
| | | static void sendEvent(id obj, SEL sel, NSEvent *event) { |
| | | if (oldSendEvent) { |
| | | oldSendEvent(obj, sel, event); |
| | | } |
| | |
| | | using ProxyList = QHash<WId, NSWindowProxy *>; |
| | | Q_GLOBAL_STATIC(ProxyList, g_proxyList); |
| | | |
| | | static inline NSWindow *mac_getNSWindow(const WId windowId) |
| | | { |
| | | static inline NSWindow *mac_getNSWindow(const WId windowId) { |
| | | const auto nsview = reinterpret_cast<NSView *>(windowId); |
| | | if (!nsview) { |
| | | return nil; |
| | |
| | | return [nsview window]; |
| | | } |
| | | |
| | | static inline void cleanupProxy() |
| | | { |
| | | static inline void cleanupProxy() { |
| | | if (g_proxyList()->isEmpty()) { |
| | | return; |
| | | } |
| | |
| | | g_proxyList()->clear(); |
| | | } |
| | | |
| | | static inline NSWindowProxy *ensureWindowProxy(const WId windowId) |
| | | { |
| | | static inline NSWindowProxy *ensureWindowProxy(const WId windowId) { |
| | | auto it = g_proxyList()->find(windowId); |
| | | if (it == g_proxyList()->end()) { |
| | | NSWindow *nswindow = mac_getNSWindow(windowId); |
| | |
| | | } |
| | | |
| | | } |
| | | |
| | | #include "cocoawindowcontext.moc" |