Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 90 additions & 12 deletions src/core/contexts/cocoawindowcontext.mm
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,15 @@ @interface QWK_NSViewObserver : NSObject
- (instancetype)initWithProxy:(QWK::NSWindowProxy*)proxy;
@end

// AppKit re-shows the traffic-light buttons after panels close, so we use this to detect that and
// re-hide them.
@interface QWK_NSButtonObserver : NSObject
- (instancetype)initWithProxy:(QWK::NSWindowProxy *)proxy;

- (void)attach:(NSArray<NSButton *> *)buttons;
- (void)detach;
@end

//
// Objective C++ End
//
Expand All @@ -153,9 +162,13 @@ - (instancetype)initWithProxy:(QWK::NSWindowProxy*)proxy;
forKeyPath:@"window"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:nil];

buttonObserver = [[QWK_NSButtonObserver alloc] initWithProxy:this];
}

~NSWindowProxy() override {
[buttonObserver release];

[nsview removeObserver:observer forKeyPath:@"window"];
[observer release];
}
Expand All @@ -172,19 +185,16 @@ void windowEvent(NSEventType eventType) override {
// The system buttons will stuck at their default positions when the
// exit-fullscreen animation is running, we need to hide them until the
// animation finishes
for (const auto &button : systemButtons()) {
button.hidden = true;
}
setButtonsVisible(false);
break;
}

case DidExitFullScreen: {
if (!screenRectCallback || !systemButtonVisible)
return;

for (const auto &button : systemButtons()) {
button.hidden = false;
}
setButtonsVisible(systemButtonVisible);

updateSystemButtonRect();
break;
}
Expand All @@ -211,9 +221,7 @@ void windowEvent(NSEventType eventType) override {
// System buttons visibility
void setSystemButtonVisible(bool visible) {
systemButtonVisible = visible;
for (const auto &button : systemButtons()) {
button.hidden = !visible;
}
setButtonsVisible(visible);

if (!screenRectCallback || !visible) {
return;
Expand Down Expand Up @@ -287,6 +295,20 @@ void updateSystemButtonRect() {
return {closeBtn, minimizeBtn, zoomBtn};
}

void setButtonsVisible(bool visible) {
checkButton = false;

for (NSButton * button : systemButtons()) {
button.hidden = !visible;
}

checkButton = true;
}

bool hasButtonVisible() const { return systemButtonVisible; }

bool hasCheckButton() const { return checkButton; }

inline int titleBarHeight() const {
auto nswindow = [nsview window];
if (!nswindow) {
Expand Down Expand Up @@ -358,9 +380,18 @@ void setSystemTitleBarVisible(const bool visible) {
nswindow.movableByWindowBackground = NO;
nswindow.movable = NO; // This line causes the window in the wrong position when
// become fullscreen.
[nswindow standardWindowButton:NSWindowCloseButton].hidden = NO;
[nswindow standardWindowButton:NSWindowMiniaturizeButton].hidden = NO;
[nswindow standardWindowButton:NSWindowZoomButton].hidden = NO;

NSWindowProxy *self_ = this;
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray<NSButton *> *array = [NSMutableArray arrayWithCapacity:3];
for (NSButton *button : self_->systemButtons()) {
button.hidden = !self_->systemButtonVisible;
[array addObject:button];
}

// Attach observer to get notified when AppKit reshows buttons.
[self_->buttonObserver attach:array];
});
}

static void replaceImplementations() {
Expand Down Expand Up @@ -501,8 +532,10 @@ static void sendEvent(id obj, SEL sel, NSEvent *event) {

NSView *nsview = nil;
QWK_NSViewObserver* observer = nil;
QWK_NSButtonObserver* buttonObserver = nil;

bool systemButtonVisible = true;
bool checkButton = true;
ScreenRectCallback screenRectCallback;

static inline QWK_NSWindowObserver *windowObserver = nil;
Expand Down Expand Up @@ -829,3 +862,48 @@ - (void)observeValueForKeyPath:(NSString*)keyPath
}

@end

@implementation QWK_NSButtonObserver {
QWK::NSWindowProxy *_proxy;
NSMutableArray<NSButton *> *_buttons;
}

- (instancetype)initWithProxy:(QWK::NSWindowProxy *)proxy {
if (self = [super init]) {
_proxy = proxy;
_buttons = [[NSMutableArray alloc] init];
}
return self;
}

- (void)dealloc {
[self detach];
[_buttons release];
[super dealloc];
}

- (void)detach {
for (NSButton *button in _buttons) {
[button removeObserver:self forKeyPath:@"hidden"];
}
[_buttons removeAllObjects];
}

- (void)attach:(NSArray<NSButton *> *)buttons {
[self detach];
for (NSButton *button in buttons) {
[button addObserver:self forKeyPath:@"hidden" options:0 context:nil];
[_buttons addObject:button];
}
}

- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (!_proxy || !_proxy->hasCheckButton()) return;

_proxy->setButtonsVisible(_proxy->hasButtonVisible());
}

@end