aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/utils/touchbar/touchbar_appdelegate_mac.mm
blob: 1284760b8c3e04d700ba34cb51dc8c785e4f7452 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0

#include "touchbar_appdelegate_mac_p.h"
#include "touchbar_mac_p.h"

#include <stack>

#import <AppKit/NSTouchBar.h>
#import <AppKit/NSWindow.h>

Q_GLOBAL_STATIC(Utils::Internal::ApplicationDelegate, staticApplicationDelegate);

namespace Utils {
namespace Internal {

ApplicationDelegate *ApplicationDelegate::instance()
{
    return staticApplicationDelegate;
}

ApplicationDelegate::ApplicationDelegate()
{
    applicationDelegate = [[ApplicationDelegateImpl alloc] init];
    [applicationDelegate installAsDelegateForApplication:[NSApplication sharedApplication]];
}

ApplicationDelegate::~ApplicationDelegate()
{
    [applicationDelegate release];
}

void ApplicationDelegate::setApplicationTouchBar(TouchBarPrivate *touchBar)
{
    [applicationDelegate setApplicationTouchBar: touchBar];
}

void ApplicationDelegate::pushTouchBar(TouchBarPrivate *touchBar)
{
    [applicationDelegate pushTouchBar: touchBar];
}

void ApplicationDelegate::popTouchBar()
{
    [applicationDelegate popTouchBar];
}

} // Internal
} // Utils

using namespace Utils::Internal;

@implementation ApplicationDelegateImpl {
    std::stack<TouchBarPrivate *> touchBarStack;
}
@synthesize qtDelegate;

- (id)init
{
    self = [super init];
    return self;
}

- (void)setApplicationTouchBar:(TouchBarPrivate *)bar
{
    while (!touchBarStack.empty())
        [self popTouchBar];
    [self pushTouchBar:bar];
}

- (void)pushTouchBar:(TouchBarPrivate *)bar
{
    if (!touchBarStack.empty())
        touchBarStack.top()->m_invalidate = [](){}; // do nothing
    touchBarStack.push(bar);
    if (bar)
        bar->m_invalidate = []() { staticApplicationDelegate->applicationDelegate.touchBar = nil; };
    self.touchBar = nil; // force re-build
}

- (void)popTouchBar
{
    if (!touchBarStack.empty()) {
        touchBarStack.top()->m_invalidate = [](){}; // do nothing
        touchBarStack.pop();
        if (!touchBarStack.empty()) {
            touchBarStack.top()->m_invalidate = [](){
                staticApplicationDelegate->applicationDelegate.touchBar = nil;
            };
        }
        self.touchBar = nil; // force re-build
    }
}

- (NSTouchBar *)makeTouchBar
{
    if (!touchBarStack.empty())
        return [touchBarStack.top()->m_delegate makeTouchBar];
    return nil;
}

- (void)installAsDelegateForApplication:(NSApplication *)application
{
    self.qtDelegate = application.delegate;
    application.delegate = self;
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    // We want to forward to the Qt delegate. Respond to selectors it
    // responds to in addition to selectors this instance resonds to.
    return [self.qtDelegate respondsToSelector:aSelector] || [super respondsToSelector:aSelector];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    if ([super respondsToSelector:aSelector])
        return [super methodSignatureForSelector:aSelector];
    return [self.qtDelegate methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    // Forward to the existing delegate. This function is only called for selectors
    // this instance does not responds to, which means that the Qt delegate
    // must respond to it (due to the respondsToSelector implementation above).
    [anInvocation invokeWithTarget:self.qtDelegate];
}

// Work around QTBUG-61707
- (void)applicationWillFinishLaunching:(NSNotification*)notify
{
    Q_UNUSED(notify)
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
    NSWindow.allowsAutomaticWindowTabbing = NO;
}
@end