init implementation of MacOS window btn location

This commit is contained in:
Altair Wei 2021-10-07 19:29:45 +08:00
parent 50dafa0c5e
commit c8cfefb3ca
7 changed files with 138 additions and 14 deletions

View File

@ -126,7 +126,7 @@
</property> </property>
<property name="font"> <property name="font">
<font> <font>
<family>Segoe UI</family> <family>Arial</family>
<pointsize>9</pointsize> <pointsize>9</pointsize>
</font> </font>
</property> </property>
@ -283,6 +283,8 @@
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<resources> <resources>
<include location="../images.qrc"/> <include location="../images.qrc"/>
<include location="../images.qrc"/>
<include location="../images.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -107,6 +107,7 @@ void MainWindow::showEvent(QShowEvent *event)
titleBarWidget->maximizeButton->hide(); titleBarWidget->maximizeButton->hide();
titleBarWidget->closeButton->hide(); titleBarWidget->closeButton->hide();
Utilities::showMacWindowButton(windowHandle()); Utilities::showMacWindowButton(windowHandle());
Utilities::setStandardWindowButtonsOffset(win, QPoint(0, -5));
#endif // Q_OS_MAC #endif // Q_OS_MAC
inited = true; inited = true;
} }
@ -172,4 +173,4 @@ void MainWindow::paintEvent(QPaintEvent *event)
painter.restore(); painter.restore();
} }
} }
#endif // Q_OS_MAC #endif // Q_OS_MAC

View File

@ -37,6 +37,7 @@ void FLWindow::initFramelessWindow()
m_maximizeButton->hide(); m_maximizeButton->hide();
m_closeButton->hide(); m_closeButton->hide();
Utilities::showMacWindowButton(windowHandle()); Utilities::showMacWindowButton(windowHandle());
Utilities::setStandardWindowButtonsOffset(windowHandle(), QPoint(10, 10));
#endif #endif
} }
@ -64,6 +65,18 @@ bool FLWindow::nativeEvent(const QByteArray &eventType, void *message, long *res
} }
#endif // Q_OS_WIN #endif // Q_OS_WIN
#ifdef Q_OS_MAC
void FLWindow::resizeEvent(QResizeEvent *event)
{
auto win = windowHandle();
if (win) {
Utilities::setStandardWindowButtonsOffset(win, QPoint(10, 10));
}
QWidget::resizeEvent(event);
}
#endif // Q_OS_MAC
void FLWindow::setupUi() void FLWindow::setupUi()
{ {
resize(800, 600); resize(800, 600);

View File

@ -18,6 +18,10 @@ protected:
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
#endif // Q_OS_WIN #endif // Q_OS_WIN
#ifdef Q_OS_MAC
void resizeEvent(QResizeEvent *event) override;
#endif // Q_OS_MAC
private: private:
void initFramelessWindow(); void initFramelessWindow();
void setupUi(); void setupUi();
@ -28,4 +32,4 @@ private:
QPushButton *m_minimizeButton = nullptr; QPushButton *m_minimizeButton = nullptr;
QPushButton *m_maximizeButton = nullptr; QPushButton *m_maximizeButton = nullptr;
QPushButton *m_closeButton = nullptr; QPushButton *m_closeButton = nullptr;
}; };

View File

@ -496,7 +496,6 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
resizeWindow(re->size()); resizeWindow(re->size());
break; break;
} }
case QEvent::NonClientAreaMouseMove: case QEvent::NonClientAreaMouseMove:
case QEvent::MouseMove: case QEvent::MouseMove:
{ {

View File

@ -76,6 +76,11 @@ FRAMELESSHELPER_API bool unsetMacWindowFrameless(QWindow* w);
FRAMELESSHELPER_API bool startMacDrag(QWindow* w, const QPoint& pos); FRAMELESSHELPER_API bool startMacDrag(QWindow* w, const QPoint& pos);
FRAMELESSHELPER_API Qt::MouseButtons getMacMouseButtons(); FRAMELESSHELPER_API Qt::MouseButtons getMacMouseButtons();
FRAMELESSHELPER_API bool showMacWindowButton(QWindow *w); FRAMELESSHELPER_API bool showMacWindowButton(QWindow *w);
FRAMELESSHELPER_API bool isMacKeyWindow(QWindow *w);
FRAMELESSHELPER_API bool isMacMainWindow(QWindow *w);
FRAMELESSHELPER_API bool makeMacKeyWindow(QWindow *w);
FRAMELESSHELPER_API bool makeMacMainWindow(QWindow *w);
FRAMELESSHELPER_API bool setStandardWindowButtonsOffset(QWindow *w, const QPoint &offset);
#endif // Q_OS_MAC #endif // Q_OS_MAC
} }

View File

@ -30,6 +30,7 @@
#include <QtGui/qguiapplication.h> #include <QtGui/qguiapplication.h>
#include <QtCore/qlist.h> #include <QtCore/qlist.h>
#include <QtCore/qdebug.h>
FRAMELESSHELPER_BEGIN_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE
@ -191,6 +192,19 @@ static void __sendEvent(id obj, SEL sel, NSEvent* event)
QGuiApplication::processEvents(); QGuiApplication::processEvents();
} }
typedef BOOL (*isFlippedType)(id, SEL);
static isFlippedType gOrigIsFlipped = nullptr;
static BOOL __isFlipped(id obj, SEL sel)
{
if (!gFlsWindows.contains(reinterpret_cast<NSWindow *>(obj)))
return true;
if (gOrigIsFlipped != nullptr)
return gOrigIsFlipped(obj, sel);
return false;
}
/*! /*!
Replace origin method \a origSEL of class \a cls with new one \a newIMP , Replace origin method \a origSEL of class \a cls with new one \a newIMP ,
then return old method as function pointer. then return old method as function pointer.
@ -227,6 +241,8 @@ static void overrideNSWindowMethods(NSWindow* window)
cls, @selector(canBecomeMainWindow), (IMP) __canBecomeMainWindow); cls, @selector(canBecomeMainWindow), (IMP) __canBecomeMainWindow);
gOrigSendEvent = (sendEventType) replaceMethod( gOrigSendEvent = (sendEventType) replaceMethod(
cls, @selector(sendEvent:), (IMP) __sendEvent); cls, @selector(sendEvent:), (IMP) __sendEvent);
gOrigIsFlipped = (isFlippedType) replaceMethod(
cls, @selector (isFlipped), (IMP) __isFlipped);
gNSWindowOverrode = true; gNSWindowOverrode = true;
} }
@ -255,6 +271,9 @@ static void restoreNSWindowMethods(NSWindow* window)
restoreMethod(cls, @selector(sendEvent:), (IMP) gOrigSendEvent); restoreMethod(cls, @selector(sendEvent:), (IMP) gOrigSendEvent);
gOrigSendEvent = nullptr; gOrigSendEvent = nullptr;
restoreMethod(cls, @selector(isFlipped), (IMP) gOrigIsFlipped);
gOrigIsFlipped = nullptr;
gNSWindowOverrode = false; gNSWindowOverrode = false;
} }
@ -265,9 +284,17 @@ static QHash<QWindow*, NSWindow*> gQWindowToNSWindow;
static NSWindow* getNSWindow(QWindow* w) static NSWindow* getNSWindow(QWindow* w)
{ {
NSView* view = reinterpret_cast<NSView *>(w->winId()); NSView* view = reinterpret_cast<NSView *>(w->winId());
if (view == nullptr) if (view == nullptr) {
qWarning() << "Unable to get NSView.";
return nullptr; return nullptr;
return [view window]; }
NSWindow* nswindow = [view window];
if (nswindow == nullptr) {
qWarning() << "Unable to get NSWindow.";
return nullptr;
}
return nswindow;
} }
bool setMacWindowHook(QWindow* w) bool setMacWindowHook(QWindow* w)
@ -350,10 +377,7 @@ bool unsetMacWindowFrameless(QWindow* w)
bool showMacWindowButton(QWindow *w) bool showMacWindowButton(QWindow *w)
{ {
NSView* view = reinterpret_cast<NSView *>(w->winId()); NSWindow* nswindow = getNSWindow(w);
if (view == nullptr)
return false;
NSWindow* nswindow = [view window];
if (nswindow == nullptr) if (nswindow == nullptr)
return false; return false;
@ -367,10 +391,7 @@ bool showMacWindowButton(QWindow *w)
bool startMacDrag(QWindow* w, const QPoint& pos) bool startMacDrag(QWindow* w, const QPoint& pos)
{ {
NSView* view = reinterpret_cast<NSView *>(w->winId()); NSWindow* nswindow = getNSWindow(w);
if (view == nullptr)
return false;
NSWindow* nswindow = [view window];
if (nswindow == nullptr) if (nswindow == nullptr)
return false; return false;
@ -387,6 +408,85 @@ Qt::MouseButtons getMacMouseButtons()
return static_cast<Qt::MouseButtons>((uint)(NSEvent.pressedMouseButtons & Qt::MouseButtonMask)); return static_cast<Qt::MouseButtons>((uint)(NSEvent.pressedMouseButtons & Qt::MouseButtonMask));
} }
bool isMacKeyWindow(QWindow *w)
{
NSWindow* nswindow = getNSWindow(w);
if (nswindow == nullptr) {
qWarning() << "Unable to get NSView.";
return false;
}
return [nswindow isKeyWindow];
}
bool isMacMainWindow(QWindow *w)
{
NSWindow* nswindow = getNSWindow(w);
if (nswindow == nullptr)
return false;
return [nswindow isMainWindow];
}
bool makeMacKeyWindow(QWindow *w)
{
NSWindow* nswindow = getNSWindow(w);
if (nswindow == nullptr)
return false;
[nswindow makeKeyWindow];
return true;
}
bool makeMacMainWindow(QWindow *w)
{
NSWindow* nswindow = getNSWindow(w);
if (nswindow == nullptr)
return false;
[nswindow makeMainWindow];
return true;
}
static void setButtonLocation(NSButton * btn, const QPoint &offset, NSView *contentview)
{
if (btn.superview != contentview) {
[btn.superview willRemoveSubview:btn];
[btn removeFromSuperview];
[btn viewWillMoveToSuperview:contentview];
[contentview addSubview:btn];
[btn viewDidMoveToSuperview];
}
auto frame = btn.frame;
btn.frame = NSMakeRect(
frame.origin.x + offset.x(),
frame.origin.y + offset.y(),
frame.size.width, frame.size.height);
}
/*! The origin of AppKit coordinate system is bottom-left. */
bool setStandardWindowButtonsOffset(QWindow *w, const QPoint &offset)
{
NSWindow* nswindow = getNSWindow(w);
if (nswindow == nullptr)
return false;
NSView* contentview = nswindow.contentView;
if (contentview == nullptr)
return false;
auto close = [nswindow standardWindowButton:NSWindowCloseButton];
auto min = [nswindow standardWindowButton:NSWindowMiniaturizeButton];
auto zoom = [nswindow standardWindowButton:NSWindowZoomButton];
setButtonLocation(close, offset, contentview);
setButtonLocation(min, offset, contentview);
setButtonLocation(zoom, offset, contentview);
return true;
}
} // namespace Utilities } // namespace Utilities
FRAMELESSHELPER_END_NAMESPACE FRAMELESSHELPER_END_NAMESPACE