1010#include " qwkglobal_p.h"
1111#include " systemwindow_p.h"
1212
13+ // https://forgetsou.github.io/2020/11/06/macos%E5%BC%80%E5%8F%91-%E5%85%B3%E9%97%AD-%E6%9C%80%E5%B0%8F%E5%8C%96-%E5%85%A8%E5%B1%8F%E5%B1%85%E4%B8%AD%E5%A4%84%E7%90%86(%E4%BB%BFMac%20QQ)/
14+ // https://nyrra33.com/2019/03/26/changing-titlebars-height/
15+
1316namespace QWK {
1417
1518 struct NSWindowProxy ;
2427
2528struct QWK_NSWindowDelegate {
2629public:
30+ enum NSEventType {
31+ WillEnterFullScreen,
32+ DidEnterFullScreen,
33+ WillExitFullScreen,
34+ DidExitFullScreen,
35+ DidResize,
36+ };
37+
2738 virtual ~QWK_NSWindowDelegate () = default ;
28- virtual void windowWillEnterFullScreen (){};
29- virtual void windowDidEnterFullScreen (){};
30- virtual void windowWillExitFullScreen (){};
31- virtual void windowDidExitFullScreen (){};
32- virtual void windowDidResize (){};
39+ virtual void windowEvent (NSEventType eventType) = 0;
3340};
3441
3542//
@@ -77,35 +84,40 @@ - (void)dealloc {
7784- (void )windowWillEnterFullScreen : (NSNotification *)notification {
7885 auto nswindow = reinterpret_cast <NSWindow *>(notification.object );
7986 if (auto proxy = QWK::g_proxyIndexes->value (nswindow)) {
80- reinterpret_cast <QWK_NSWindowDelegate *>(proxy)->windowWillEnterFullScreen ();
87+ reinterpret_cast <QWK_NSWindowDelegate *>(proxy)->windowEvent (
88+ QWK_NSWindowDelegate::WillEnterFullScreen);
8189 }
8290}
8391
8492- (void )windowDidEnterFullScreen : (NSNotification *)notification {
8593 auto nswindow = reinterpret_cast <NSWindow *>(notification.object );
8694 if (auto proxy = QWK::g_proxyIndexes->value (nswindow)) {
87- reinterpret_cast <QWK_NSWindowDelegate *>(proxy)->windowDidEnterFullScreen ();
95+ reinterpret_cast <QWK_NSWindowDelegate *>(proxy)->windowEvent (
96+ QWK_NSWindowDelegate::DidEnterFullScreen);
8897 }
8998}
9099
91100- (void )windowWillExitFullScreen : (NSNotification *)notification {
92101 auto nswindow = reinterpret_cast <NSWindow *>(notification.object );
93102 if (auto proxy = QWK::g_proxyIndexes->value (nswindow)) {
94- reinterpret_cast <QWK_NSWindowDelegate *>(proxy)->windowWillExitFullScreen ();
103+ reinterpret_cast <QWK_NSWindowDelegate *>(proxy)->windowEvent (
104+ QWK_NSWindowDelegate::WillExitFullScreen);
95105 }
96106}
97107
98108- (void )windowDidExitFullScreen : (NSNotification *)notification {
99109 auto nswindow = reinterpret_cast <NSWindow *>(notification.object );
100110 if (auto proxy = QWK::g_proxyIndexes->value (nswindow)) {
101- reinterpret_cast <QWK_NSWindowDelegate *>(proxy)->windowDidExitFullScreen ();
111+ reinterpret_cast <QWK_NSWindowDelegate *>(proxy)->windowEvent (
112+ QWK_NSWindowDelegate::DidExitFullScreen);
102113 }
103114}
104115
105116- (void )windowDidResize : (NSNotification *)notification {
106117 auto nswindow = reinterpret_cast <NSWindow *>(notification.object );
107118 if (auto proxy = QWK::g_proxyIndexes->value (nswindow)) {
108- reinterpret_cast <QWK_NSWindowDelegate *>(proxy)->windowDidResize ();
119+ reinterpret_cast <QWK_NSWindowDelegate *>(proxy)->windowEvent (
120+ QWK_NSWindowDelegate::DidResize);
109121 }
110122}
111123
@@ -134,38 +146,43 @@ - (void)windowDidResize:(NSNotification *)notification {
134146 }
135147
136148 // Delegate
137- void windowWillEnterFullScreen () override {
138- }
139-
140- void windowDidEnterFullScreen () override {
141- }
142-
143- void windowWillExitFullScreen () override {
144- if (systemButtonRect.isEmpty () || !systemButtonVisible)
145- return ;
149+ void windowEvent (NSEventType eventType) override {
150+ switch (eventType) {
151+ case WillExitFullScreen: {
152+ if (!screenRectCallback || !systemButtonVisible)
153+ return ;
154+
155+ // The system buttons will stuck at their default positions when the
156+ // exit-fullscreen animation is running, we need to hide them until the
157+ // animation finishes
158+ for (const auto &button : systemButtons ()) {
159+ button.hidden = true ;
160+ }
161+ break ;
162+ }
146163
147- // The system buttons will stuck at their default positions when the exit-fullscreen
148- // animation is running, we need to hide them until the animation finishes
149- for (const auto &button : systemButtons ()) {
150- button.hidden = true ;
151- }
152- }
164+ case DidExitFullScreen: {
165+ if (!screenRectCallback || !systemButtonVisible)
166+ return ;
153167
154- void windowDidExitFullScreen () override {
155- if (systemButtonRect.isEmpty () || !systemButtonVisible)
156- return ;
168+ for (const auto &button : systemButtons ()) {
169+ button.hidden = false ;
170+ }
171+ updateSystemButtonRect ();
172+ break ;
173+ }
157174
158- for (const auto &button : systemButtons ()) {
159- button.hidden = false ;
160- }
161- updateSystemButtonRect ();
162- }
175+ case DidResize: {
176+ if (!screenRectCallback || !systemButtonVisible) {
177+ return ;
178+ }
179+ updateSystemButtonRect ();
180+ break ;
181+ }
163182
164- void windowDidResize () override {
165- if (systemButtonRect.isEmpty () || !systemButtonVisible) {
166- return ;
183+ default :
184+ break ;
167185 }
168- updateSystemButtonRect ();
169186 }
170187
171188 // System buttons visibility
@@ -175,35 +192,42 @@ void setSystemButtonVisible(bool visible) {
175192 button.hidden = !visible;
176193 }
177194
178- if (systemButtonRect. isEmpty () || !visible) {
195+ if (!screenRectCallback || !visible) {
179196 return ;
180197 }
181198 updateSystemButtonRect ();
182199 }
183200
184201 // System buttons area
185- void setSystemButtonRect (const QRect &rect ) {
186- systemButtonRect = rect ;
202+ void setScreenRectCallback (const ScreenRectCallback &callback ) {
203+ screenRectCallback = callback ;
187204
188- if (rect. isEmpty () || !systemButtonVisible) {
205+ if (!callback || !systemButtonVisible) {
189206 return ;
190207 }
191208 updateSystemButtonRect ();
192209 }
193210
194211 void updateSystemButtonRect () {
195- // https://forgetsou.github.io/2020/11/06/macos%E5%BC%80%E5%8F%91-%E5%85%B3%E9%97%AD-%E6%9C%80%E5%B0%8F%E5%8C%96-%E5%85%A8%E5%B1%8F%E5%B1%85%E4%B8%AD%E5%A4%84%E7%90%86(%E4%BB%BFMac%20QQ)/
196-
197212 const auto &buttons = systemButtons ();
198213 const auto &leftButton = buttons[0 ];
199214 const auto &midButton = buttons[1 ];
200215 const auto &rightButton = buttons[2 ];
201216
217+ auto titlebar = rightButton.superview ;
218+ int titlebarHeight = titlebar.frame .size .height ;
219+
202220 auto spacing = midButton.frame .origin .x - leftButton.frame .origin .x ;
203221 auto width = midButton.frame .size .width ;
204222 auto height = midButton.frame .size .height ;
205223
206- QPoint center = systemButtonRect.center ();
224+ auto viewSize =
225+ nswindow.contentView ? nswindow.contentView .frame .size : nswindow.frame .size ;
226+ QPoint center = screenRectCallback (QSize (viewSize.width , titlebarHeight)).center ();
227+
228+ // The origin of the NSWindow coordinate system is in the lower left corner, we
229+ // do the necessary transformations
230+ center.ry () = titlebarHeight - center.y ();
207231
208232 // Mid button
209233 NSPoint centerOrigin = {
@@ -234,6 +258,11 @@ void updateSystemButtonRect() {
234258 return {closeBtn, minimizeBtn, zoomBtn};
235259 }
236260
261+ inline int titleBarHeight () const {
262+ NSButton *closeBtn = [nswindow standardWindowButton: NSWindowCloseButton];
263+ return closeBtn.superview .frame .size .height ;
264+ }
265+
237266 // Blur effect
238267 bool setBlurEffect (BlurMode mode) {
239268 static Class visualEffectViewClass = NSClassFromString (@" NSVisualEffectView" );
@@ -293,7 +322,7 @@ void setSystemTitleBarVisible(const bool visible) {
293322 nswindow.titlebarAppearsTransparent = (visible ? NO : YES );
294323 nswindow.titleVisibility = (visible ? NSWindowTitleVisible : NSWindowTitleHidden);
295324 nswindow.hasShadow = YES ;
296- nswindow.showsToolbarButton = NO ;
325+ // nswindow.showsToolbarButton = NO;
297326 nswindow.movableByWindowBackground = NO ;
298327 nswindow.movable = NO ; // This line causes the window in the wrong position when
299328 // become fullscreen.
@@ -437,7 +466,7 @@ static void sendEvent(id obj, SEL sel, NSEvent *event) {
437466 NSWindow *nswindow = nil ;
438467
439468 bool systemButtonVisible = true ;
440- QRect systemButtonRect ;
469+ ScreenRectCallback screenRectCallback ;
441470
442471 static inline QWK_NSWindowObserver *windowObserver = nil ;
443472
@@ -638,7 +667,7 @@ static inline void releaseWindowProxy(const WId windowId) {
638667 void CocoaWindowContext::virtual_hook (int id , void *data) {
639668 switch (id ) {
640669 case SystemButtonAreaChangedHook: {
641- ensureWindowProxy (windowId)->setSystemButtonRect (m_systemButtonArea );
670+ ensureWindowProxy (windowId)->setScreenRectCallback (m_systemButtonAreaCallback );
642671 return ;
643672 }
644673
@@ -648,6 +677,15 @@ static inline void releaseWindowProxy(const WId windowId) {
648677 AbstractWindowContext::virtual_hook (id , data);
649678 }
650679
680+ QVariant CocoaWindowContext::windowAttribute (const QString &key) const {
681+ if (key == QStringLiteral (" title-bar-height" )) {
682+ if (!m_windowHandle)
683+ return 0 ;
684+ return ensureWindowProxy (windowId)->titleBarHeight ();
685+ }
686+ return AbstractWindowContext::windowAttribute (key);
687+ }
688+
651689 void CocoaWindowContext::winIdChanged () {
652690 // If the original window id is valid, remove all resources related
653691 if (windowId) {
0 commit comments