OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.h" |
| 6 |
| 7 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 8 #import "chrome/browser/ui/cocoa/fullscreen_toolbar_controller.h" |
| 9 |
| 10 namespace { |
| 11 |
| 12 // The event kind value for a undocumented menubar show/hide Carbon event. |
| 13 const CGFloat kMenuBarRevealEventKind = 2004; |
| 14 |
| 15 OSStatus MenuBarRevealHandler(EventHandlerCallRef handler, |
| 16 EventRef event, |
| 17 void* context) { |
| 18 FullscreenMenubarTracker* self = |
| 19 static_cast<FullscreenMenubarTracker*>(context); |
| 20 |
| 21 // If Chrome has multiple fullscreen windows in their own space, the Handler |
| 22 // becomes flaky and might start receiving kMenuBarRevealEventKind events |
| 23 // from another space. Since the menubar in the another space is in either a |
| 24 // shown or hidden state, it will give us a reveal fraction of 0.0 or 1.0. |
| 25 // As such, we should ignore the kMenuBarRevealEventKind event if it gives |
| 26 // us a fraction of 0.0 or 1.0, and rely on kEventMenuBarShown and |
| 27 // kEventMenuBarHidden to set these values. |
| 28 if (GetEventKind(event) == kMenuBarRevealEventKind) { |
| 29 CGFloat revealFraction = 0; |
| 30 GetEventParameter(event, FOUR_CHAR_CODE('rvlf'), typeCGFloat, NULL, |
| 31 sizeof(CGFloat), NULL, &revealFraction); |
| 32 if (revealFraction > 0.0 && revealFraction < 1.0) |
| 33 [self setMenubarProgress:revealFraction]; |
| 34 } else if (GetEventKind(event) == kEventMenuBarShown) { |
| 35 [self setMenubarProgress:1.0]; |
| 36 } else { |
| 37 [self setMenubarProgress:0.0]; |
| 38 } |
| 39 |
| 40 return CallNextEventHandler(handler, event); |
| 41 } |
| 42 |
| 43 } // end namespace |
| 44 |
| 45 @interface FullscreenMenubarTracker () { |
| 46 // Our owner. |
| 47 FullscreenToolbarController* owner_; // weak |
| 48 |
| 49 // The window's controller. |
| 50 BrowserWindowController* browserController_; // weak |
| 51 |
| 52 // A Carbon event handler that tracks the revealed fraction of the menu bar. |
| 53 EventHandlerRef menuBarTrackingHandler_; |
| 54 } |
| 55 |
| 56 // Returns YES if the mouse is on the same screen as the window. |
| 57 - (BOOL)isMouseOnScreen; |
| 58 |
| 59 @end |
| 60 |
| 61 @implementation FullscreenMenubarTracker |
| 62 |
| 63 @synthesize state = state_; |
| 64 @synthesize menubarFraction = menubarFraction_; |
| 65 |
| 66 - (id)initWithFullscreenToolbarController:(FullscreenToolbarController*)owner { |
| 67 if ((self = [super init])) { |
| 68 owner_ = owner; |
| 69 browserController_ = [owner_ browserWindowController]; |
| 70 state_ = FullscreenMenubarState::HIDDEN; |
| 71 } |
| 72 |
| 73 // Install the Carbon event handler for the menubar show, hide and |
| 74 // undocumented reveal event. |
| 75 EventTypeSpec eventSpecs[3]; |
| 76 |
| 77 eventSpecs[0].eventClass = kEventClassMenu; |
| 78 eventSpecs[0].eventKind = kMenuBarRevealEventKind; |
| 79 |
| 80 eventSpecs[1].eventClass = kEventClassMenu; |
| 81 eventSpecs[1].eventKind = kEventMenuBarShown; |
| 82 |
| 83 eventSpecs[2].eventClass = kEventClassMenu; |
| 84 eventSpecs[2].eventKind = kEventMenuBarHidden; |
| 85 |
| 86 InstallApplicationEventHandler(NewEventHandlerUPP(&MenuBarRevealHandler), 3, |
| 87 eventSpecs, self, &menuBarTrackingHandler_); |
| 88 |
| 89 // Register for Active Space change notifications. |
| 90 [[[NSWorkspace sharedWorkspace] notificationCenter] |
| 91 addObserver:self |
| 92 selector:@selector(activeSpaceDidChange:) |
| 93 name:NSWorkspaceActiveSpaceDidChangeNotification |
| 94 object:nil]; |
| 95 |
| 96 return self; |
| 97 } |
| 98 |
| 99 - (void)dealloc { |
| 100 RemoveEventHandler(menuBarTrackingHandler_); |
| 101 [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self]; |
| 102 |
| 103 [super dealloc]; |
| 104 } |
| 105 |
| 106 - (CGFloat)menubarFraction { |
| 107 return menubarFraction_; |
| 108 } |
| 109 |
| 110 - (void)setMenubarProgress:(CGFloat)progress { |
| 111 if (![browserController_ isInAnyFullscreenMode] || |
| 112 [browserController_ isFullscreenTransitionInProgress]) { |
| 113 return; |
| 114 } |
| 115 |
| 116 // If the menubarFraction increases, check if we are in the right screen |
| 117 // so that the toolbar is not revealed on the wrong screen. |
| 118 if (![self isMouseOnScreen] && progress > menubarFraction_) |
| 119 return; |
| 120 |
| 121 // Ignore the menubarFraction changes if the Space is inactive. |
| 122 if (![[browserController_ window] isOnActiveSpace]) |
| 123 return; |
| 124 |
| 125 if (base::mac::IsCGFloatEqual(progress, 1.0)) |
| 126 state_ = FullscreenMenubarState::SHOWN; |
| 127 else if (base::mac::IsCGFloatEqual(progress, 0.0)) |
| 128 state_ = FullscreenMenubarState::HIDDEN; |
| 129 else if (progress < menubarFraction_) |
| 130 state_ = FullscreenMenubarState::HIDING; |
| 131 else if (progress > menubarFraction_) |
| 132 state_ = FullscreenMenubarState::SHOWING; |
| 133 |
| 134 menubarFraction_ = progress; |
| 135 |
| 136 [owner_ updateToolbar]; |
| 137 } |
| 138 |
| 139 - (BOOL)isMouseOnScreen { |
| 140 return NSMouseInRect([NSEvent mouseLocation], |
| 141 [[browserController_ window] screen].frame, false); |
| 142 } |
| 143 |
| 144 - (void)activeSpaceDidChange:(NSNotification*)notification { |
| 145 menubarFraction_ = 0.0; |
| 146 state_ = FullscreenMenubarState::HIDDEN; |
| 147 [owner_ updateToolbar]; |
| 148 } |
| 149 |
| 150 @end |
OLD | NEW |