17
17
//
18
18
19
19
import Cocoa
20
+ import Combine
20
21
21
22
final class MainView : NSView {
23
+ let tabBarContainerView = NSView ( )
24
+ let navigationBarContainerView = NSView ( )
25
+ let webContainerView = NSView ( )
26
+ let findInPageContainerView = NSView ( ) . hidden ( )
27
+ let bookmarksBarContainerView = NSView ( )
28
+ let fireContainerView = NSView ( )
29
+ let divider = ColorView ( frame: . zero, backgroundColor: . separatorColor)
30
+
31
+ private( set) var navigationBarTopConstraint : NSLayoutConstraint !
32
+ private( set) var addressBarHeightConstraint : NSLayoutConstraint !
33
+ private( set) var bookmarksBarHeightConstraint : NSLayoutConstraint !
34
+
35
+ @Published var isMouseAboveWebView : Bool = false
36
+
37
+ override init ( frame frameRect: NSRect ) {
38
+ super. init ( frame: frameRect)
39
+
40
+ for subview in [
41
+ tabBarContainerView,
42
+ divider,
43
+ bookmarksBarContainerView,
44
+ navigationBarContainerView,
45
+ webContainerView,
46
+ findInPageContainerView,
47
+ fireContainerView,
48
+ ] {
49
+ subview. translatesAutoresizingMaskIntoConstraints = false
50
+ addSubview ( subview)
51
+ }
52
+
53
+ addConstraints ( )
54
+ }
55
+
56
+ required init ? ( coder: NSCoder ) {
57
+ fatalError ( " init(coder:) has not been implemented " )
58
+ }
59
+
60
+ private func addConstraints( ) {
61
+ bookmarksBarHeightConstraint = bookmarksBarContainerView. heightAnchor. constraint ( equalToConstant: 34 )
62
+
63
+ navigationBarTopConstraint = navigationBarContainerView. topAnchor. constraint ( equalTo: topAnchor, constant: 38 )
64
+ addressBarHeightConstraint = navigationBarContainerView. heightAnchor. constraint ( equalToConstant: 42 )
65
+
66
+ NSLayoutConstraint . activate ( [
67
+ tabBarContainerView. topAnchor. constraint ( equalTo: topAnchor) ,
68
+ tabBarContainerView. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
69
+ tabBarContainerView. trailingAnchor. constraint ( equalTo: trailingAnchor) ,
70
+ tabBarContainerView. heightAnchor. constraint ( equalToConstant: 38 ) ,
71
+
72
+ divider. topAnchor. constraint ( equalTo: navigationBarContainerView. bottomAnchor) ,
73
+ divider. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
74
+ divider. trailingAnchor. constraint ( equalTo: trailingAnchor) ,
75
+ divider. heightAnchor. constraint ( equalToConstant: 1 ) ,
76
+
77
+ bookmarksBarContainerView. topAnchor. constraint ( equalTo: divider. bottomAnchor) ,
78
+ bookmarksBarContainerView. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
79
+ bookmarksBarContainerView. trailingAnchor. constraint ( equalTo: trailingAnchor) ,
80
+ bookmarksBarHeightConstraint,
81
+
82
+ navigationBarTopConstraint,
83
+ navigationBarContainerView. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
84
+ navigationBarContainerView. trailingAnchor. constraint ( equalTo: trailingAnchor) ,
85
+ addressBarHeightConstraint,
86
+
87
+ webContainerView. topAnchor. constraint ( equalTo: bookmarksBarContainerView. bottomAnchor) ,
88
+ webContainerView. bottomAnchor. constraint ( equalTo: bottomAnchor) ,
89
+ webContainerView. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
90
+ webContainerView. trailingAnchor. constraint ( equalTo: trailingAnchor) ,
91
+ webContainerView. widthAnchor. constraint ( greaterThanOrEqualToConstant: 512 ) ,
92
+ webContainerView. heightAnchor. constraint ( greaterThanOrEqualToConstant: 178 ) ,
93
+
94
+ findInPageContainerView. topAnchor. constraint ( equalTo: bookmarksBarContainerView. bottomAnchor, constant: - 4 ) ,
95
+ findInPageContainerView. topAnchor. constraint ( equalTo: navigationBarContainerView. bottomAnchor, constant: - 4 ) . priority ( 900 ) ,
96
+ findInPageContainerView. centerXAnchor. constraint ( equalTo: navigationBarContainerView. centerXAnchor) ,
97
+ findInPageContainerView. widthAnchor. constraint ( equalToConstant: 400 ) ,
98
+ findInPageContainerView. heightAnchor. constraint ( equalToConstant: 40 ) ,
99
+
100
+ fireContainerView. topAnchor. constraint ( equalTo: topAnchor) ,
101
+ fireContainerView. bottomAnchor. constraint ( equalTo: bottomAnchor) ,
102
+ fireContainerView. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
103
+ fireContainerView. trailingAnchor. constraint ( equalTo: trailingAnchor) ,
104
+ ] )
105
+ }
106
+
22
107
private typealias CFWebServicesCopyProviderInfoType = @convention ( c) ( CFString , UnsafeRawPointer ? ) -> NSDictionary ?
23
108
24
109
// PDF Plugin context menu
@@ -47,7 +132,7 @@ final class MainView: NSView {
47
132
}
48
133
}
49
134
50
- // MARK: NSDraggingDestination
135
+ // MARK: - NSDraggingDestination
51
136
52
137
override func draggingEntered( _ draggingInfo: NSDraggingInfo ) -> NSDragOperation {
53
138
return ( nextResponder as? NSDraggingDestination ) ? . draggingEntered ? ( draggingInfo) ?? . none
@@ -61,4 +146,50 @@ final class MainView: NSView {
61
146
return ( nextResponder as? NSDraggingDestination ) ? . performDragOperation ? ( draggingInfo) ?? false
62
147
}
63
148
149
+ // MARK: - Mouse Tracking
150
+
151
+ func setMouseAboveWebViewTrackingAreaEnabled( _ isEnabled: Bool ) {
152
+ if isEnabled {
153
+ let trackingArea = makeMouseAboveViewTrackingArea ( )
154
+ addTrackingArea ( trackingArea)
155
+ mouseAboveWebViewTrackingArea = trackingArea
156
+ } else if let mouseAboveWebViewTrackingArea {
157
+ removeTrackingArea ( mouseAboveWebViewTrackingArea)
158
+ self . mouseAboveWebViewTrackingArea = nil
159
+ isMouseAboveWebView = false
160
+ }
161
+ }
162
+
163
+ override func updateTrackingAreas( ) {
164
+ if let mouseAboveWebViewTrackingArea {
165
+ removeTrackingArea ( mouseAboveWebViewTrackingArea)
166
+ isMouseAboveWebView = false
167
+ let trackingArea = makeMouseAboveViewTrackingArea ( )
168
+ self . mouseAboveWebViewTrackingArea = trackingArea
169
+ addTrackingArea ( trackingArea)
170
+ }
171
+ super. updateTrackingAreas ( )
172
+ }
173
+
174
+ override func mouseEntered( with event: NSEvent ) {
175
+ if let mouseAboveWebViewTrackingArea, event. trackingArea == mouseAboveWebViewTrackingArea {
176
+ isMouseAboveWebView = true
177
+ }
178
+ }
179
+
180
+ override func mouseExited( with event: NSEvent ) {
181
+ if let mouseAboveWebViewTrackingArea, event. trackingArea == mouseAboveWebViewTrackingArea {
182
+ isMouseAboveWebView = false
183
+ }
184
+ }
185
+
186
+ private func makeMouseAboveViewTrackingArea( ) -> NSTrackingArea {
187
+ var bounds = bounds
188
+ bounds. size. height -= webContainerView. bounds. maxY
189
+ bounds. origin. y += webContainerView. bounds. maxY
190
+ return NSTrackingArea ( rect: bounds, options: [ . activeAlways, . mouseEnteredAndExited] , owner: self , userInfo: nil )
191
+ }
192
+
193
+ private var mouseAboveWebViewTrackingArea : NSTrackingArea ?
194
+
64
195
}
0 commit comments