File: fullscreen_toolbar_mouse_tracker.mm

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (120 lines) | stat: -rw-r--r-- 3,689 bytes parent folder | download | duplicates (6)
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
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h"

#include <memory>

#import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.h"
#include "chrome/browser/ui/cocoa/scoped_menu_bar_lock.h"
#import "ui/base/cocoa/tracking_area.h"

namespace {

// Additional height threshold added at the toolbar's bottom. This is to mimic
// threshold the mouse position needs to be at before the menubar automatically
// hides.
const CGFloat kTrackingAreaAdditionalThreshold = 50;

}  // namespace

@implementation FullscreenToolbarMouseTracker {
  // The frame for the tracking area. The value is the toolbar's frame with
  // additional height added at the bottom.
  NSRect _trackingAreaFrame;

  // The tracking area associated with the toolbar. This tracking area is used
  // to keep the toolbar active if the menubar had animated out but the mouse
  // is still on the toolbar.
  CrTrackingArea* __strong _trackingArea;

  // Keeps the menu bar from hiding until the mouse exits the tracking area.
  std::unique_ptr<ScopedMenuBarLock> _menuBarLock;

  // The content view for the window.
  // TODO(lgrey): Instead of retaining this, we should refrain from trying to
  // remove the tracking area when the content view has already dealloced.
  // Unfortunately, until we have a repro for https://crbug.com/1064911, we
  // can't verify more targeted fixes (for example, only removing the tracking
  // area if |_controller| has a window).
  NSView* __strong _contentView;

  FullscreenToolbarController* _controller;  // weak
}

- (instancetype)initWithFullscreenToolbarController:
    (FullscreenToolbarController*)controller {
  if ((self = [super init])) {
    _controller = controller;
  }

  return self;
}

- (void)dealloc {
  [self removeTrackingArea];
}

- (void)updateTrackingArea {
  // Remove the tracking area if the toolbar and menu bar aren't both visible.
  if ([_controller toolbarFraction] == 0 || ![NSMenu menuBarVisible]) {
    [self removeTrackingArea];
    _menuBarLock.reset();
    return;
  }

  if (_trackingArea) {
    // If |trackingArea_|'s rect matches |trackingAreaFrame_|, quit early.
    if (NSEqualRects(_trackingAreaFrame, [_trackingArea rect])) {
      return;
    }

    [self removeTrackingArea];
  }

  _contentView = [[_controller window] contentView];

  _trackingArea = [[CrTrackingArea alloc]
      initWithRect:_trackingAreaFrame
           options:NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow
             owner:self
          userInfo:nil];

  [_contentView addTrackingArea:_trackingArea];
}

- (void)updateToolbarFrame:(NSRect)frame {
  NSRect contentBounds = [[[_controller window] contentView] bounds];
  _trackingAreaFrame = frame;
  _trackingAreaFrame.origin.y -= kTrackingAreaAdditionalThreshold;
  _trackingAreaFrame.size.height =
      NSMaxY(contentBounds) - _trackingAreaFrame.origin.y;

  [self updateTrackingArea];
}

- (void)removeTrackingArea {
  if (!_trackingArea) {
    return;
  }

  // TODO(https://crbug.com/1063417, https://crbug.com/1064911): This DCHECK
  // is hit when closing a fullscreen window using the traffic lights. This is
  // because removeTrackingArea should be removed in response to the window
  // closing, but isn't.
  // DCHECK(_contentView);
  [_contentView removeTrackingArea:_trackingArea];
  _trackingArea = nil;
  _contentView = nil;
}

- (void)mouseEntered:(NSEvent*)event {
  _menuBarLock = std::make_unique<ScopedMenuBarLock>();
}

- (void)mouseExited:(NSEvent*)event {
  _menuBarLock = nil;
}

@end