| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | // Copyright (c) 2018 GitHub, Inc.
 | 
					
						
							|  |  |  | // Use of this source code is governed by the MIT license that can be
 | 
					
						
							|  |  |  | // found in the LICENSE file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/browser/ui/views/root_view.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-16 18:12:00 -04:00
										 |  |  | #include <memory>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-07 17:18:35 -04:00
										 |  |  | #include "components/input/native_web_keyboard_event.h"
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/browser/native_window.h"
 | 
					
						
							|  |  |  | #include "shell/browser/ui/views/menu_bar.h"
 | 
					
						
							| 
									
										
										
										
											2024-04-08 10:30:23 -07:00
										 |  |  | #include "ui/views/layout/box_layout.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 14:23:04 -07:00
										 |  |  | namespace electron { | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-07 17:18:35 -04:00
										 |  |  | bool IsAltKey(const input::NativeWebKeyboardEvent& event) { | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |   return event.windows_key_code == ui::VKEY_MENU; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-07 17:18:35 -04:00
										 |  |  | bool IsAltModifier(const input::NativeWebKeyboardEvent& event) { | 
					
						
							| 
									
										
										
										
											2025-05-14 10:00:00 -05:00
										 |  |  |   using Mods = input::NativeWebKeyboardEvent::Modifiers; | 
					
						
							|  |  |  |   return (event.GetModifiers() & Mods::kKeyModifiers) == Mods::kAltKey; | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-29 19:08:47 +01:00
										 |  |  | RootView::RootView(NativeWindow* window) | 
					
						
							| 
									
										
										
										
											2024-05-15 13:45:47 -05:00
										 |  |  |     : window_{raw_ref<NativeWindow>::from_ptr(window)}, | 
					
						
							|  |  |  |       main_view_{raw_ref<views::View>::from_ptr( | 
					
						
							|  |  |  |           AddChildView(std::make_unique<views::View>()))} { | 
					
						
							| 
									
										
										
										
											2025-04-22 15:53:29 -04:00
										 |  |  |   set_owned_by_client(OwnedByClientPassKey{}); | 
					
						
							| 
									
										
										
										
											2024-04-08 10:30:23 -07:00
										 |  |  |   views::BoxLayout* layout = | 
					
						
							|  |  |  |       SetLayoutManager(std::make_unique<views::BoxLayout>( | 
					
						
							|  |  |  |           views::BoxLayout::Orientation::kVertical)); | 
					
						
							|  |  |  |   main_view_->SetUseDefaultFillLayout(true); | 
					
						
							| 
									
										
										
										
											2024-05-15 13:45:47 -05:00
										 |  |  |   layout->SetFlexForView(&main_view_.get(), 1); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-16 18:12:00 -04:00
										 |  |  | RootView::~RootView() = default; | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 12:19:40 -08:00
										 |  |  | void RootView::SetMenu(ElectronMenuModel* menu_model) { | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |   if (menu_model == nullptr) { | 
					
						
							|  |  |  |     // Remove accelerators
 | 
					
						
							| 
									
										
										
										
											2018-11-09 13:54:16 -08:00
										 |  |  |     UnregisterAcceleratorsWithFocusManager(); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |     // and menu bar.
 | 
					
						
							|  |  |  |     SetMenuBarVisibility(false); | 
					
						
							|  |  |  |     menu_bar_.reset(); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 13:54:16 -08:00
										 |  |  |   RegisterAcceleratorsWithFocusManager(menu_model); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Do not show menu bar in frameless window.
 | 
					
						
							|  |  |  |   if (!window_->has_frame()) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!menu_bar_) { | 
					
						
							| 
									
										
										
										
											2024-05-15 13:45:47 -05:00
										 |  |  |     menu_bar_ = std::make_unique<MenuBar>(&window_.get(), this); | 
					
						
							| 
									
										
										
										
											2025-04-22 15:53:29 -04:00
										 |  |  |     menu_bar_->set_owned_by_client(OwnedByClientPassKey{}); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |     if (!menu_bar_autohide_) | 
					
						
							|  |  |  |       SetMenuBarVisibility(true); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   menu_bar_->SetMenu(menu_model); | 
					
						
							| 
									
										
										
										
											2024-02-14 12:33:32 -05:00
										 |  |  |   InvalidateLayout(); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool RootView::HasMenu() const { | 
					
						
							|  |  |  |   return !!menu_bar_; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int RootView::GetMenuBarHeight() const { | 
					
						
							| 
									
										
										
										
											2024-04-08 10:30:23 -07:00
										 |  |  |   return menu_bar_ ? menu_bar_->GetPreferredSize().height() : 0; | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RootView::SetAutoHideMenuBar(bool auto_hide) { | 
					
						
							|  |  |  |   menu_bar_autohide_ = auto_hide; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RootView::SetMenuBarVisibility(bool visible) { | 
					
						
							| 
									
										
										
										
											2018-05-08 15:24:53 +09:00
										 |  |  |   if (!window_->content_view() || !menu_bar_ || menu_bar_visible_ == visible) | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   menu_bar_visible_ = visible; | 
					
						
							|  |  |  |   if (visible) { | 
					
						
							| 
									
										
										
										
											2024-04-08 10:30:23 -07:00
										 |  |  |     AddChildViewAt(menu_bar_.get(), 0); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |   } else { | 
					
						
							|  |  |  |     RemoveChildView(menu_bar_.get()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-14 12:33:32 -05:00
										 |  |  |   InvalidateLayout(); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-07 17:18:35 -04:00
										 |  |  | void RootView::HandleKeyEvent(const input::NativeWebKeyboardEvent& event) { | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |   if (!menu_bar_) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Show accelerator when "Alt" is pressed.
 | 
					
						
							|  |  |  |   if (menu_bar_visible_ && IsAltKey(event)) | 
					
						
							| 
									
										
										
										
											2020-05-26 13:06:26 -07:00
										 |  |  |     menu_bar_->SetAcceleratorVisibility( | 
					
						
							|  |  |  |         event.GetType() == blink::WebInputEvent::Type::kRawKeyDown); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Show the submenu when "Alt+Key" is pressed.
 | 
					
						
							| 
									
										
										
										
											2020-05-26 13:06:26 -07:00
										 |  |  |   if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown && | 
					
						
							| 
									
										
										
										
											2021-06-01 10:48:52 +09:00
										 |  |  |       event.windows_key_code >= ui::VKEY_A && | 
					
						
							|  |  |  |       event.windows_key_code <= ui::VKEY_Z && IsAltModifier(event) && | 
					
						
							|  |  |  |       menu_bar_->HasAccelerator(event.windows_key_code)) { | 
					
						
							|  |  |  |     if (!menu_bar_visible_) { | 
					
						
							|  |  |  |       SetMenuBarVisibility(true); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 10:48:52 +09:00
										 |  |  |       View* focused_view = GetFocusManager()->GetFocusedView(); | 
					
						
							| 
									
										
										
										
											2024-05-15 13:45:47 -05:00
										 |  |  |       last_focused_view_tracker_.SetView(focused_view); | 
					
						
							| 
									
										
										
										
											2021-06-01 10:48:52 +09:00
										 |  |  |       menu_bar_->RequestFocus(); | 
					
						
							| 
									
										
										
										
											2018-10-29 19:08:47 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-01 10:48:52 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |     menu_bar_->ActivateAccelerator(event.windows_key_code); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2018-10-29 19:08:47 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Toggle the menu bar only when a single Alt is released.
 | 
					
						
							| 
									
										
										
										
											2020-05-26 13:06:26 -07:00
										 |  |  |   if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown && | 
					
						
							|  |  |  |       IsAltKey(event)) { | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |     // When a single Alt is pressed:
 | 
					
						
							|  |  |  |     menu_bar_alt_pressed_ = true; | 
					
						
							| 
									
										
										
										
											2020-05-26 13:06:26 -07:00
										 |  |  |   } else if (event.GetType() == blink::WebInputEvent::Type::kKeyUp && | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |              IsAltKey(event) && menu_bar_alt_pressed_) { | 
					
						
							|  |  |  |     // When a single Alt is released right after a Alt is pressed:
 | 
					
						
							|  |  |  |     menu_bar_alt_pressed_ = false; | 
					
						
							| 
									
										
										
										
											2018-10-29 19:08:47 +01:00
										 |  |  |     if (menu_bar_autohide_) | 
					
						
							|  |  |  |       SetMenuBarVisibility(!menu_bar_visible_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     View* focused_view = GetFocusManager()->GetFocusedView(); | 
					
						
							| 
									
										
										
										
											2024-05-15 13:45:47 -05:00
										 |  |  |     last_focused_view_tracker_.SetView(focused_view); | 
					
						
							| 
									
										
										
										
											2019-04-15 20:54:27 +03:00
										 |  |  |     if (menu_bar_visible_) { | 
					
						
							|  |  |  |       menu_bar_->RequestFocus(); | 
					
						
							|  |  |  |       // Show accelerators when menu bar is focused
 | 
					
						
							|  |  |  |       menu_bar_->SetAcceleratorVisibility(true); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |   } else { | 
					
						
							|  |  |  |     // When any other keys except single Alt have been pressed/released:
 | 
					
						
							|  |  |  |     menu_bar_alt_pressed_ = false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-29 19:08:47 +01:00
										 |  |  | void RootView::RestoreFocus() { | 
					
						
							| 
									
										
										
										
											2024-05-15 13:45:47 -05:00
										 |  |  |   View* last_focused_view = last_focused_view_tracker_.view(); | 
					
						
							| 
									
										
										
										
											2018-10-29 19:08:47 +01:00
										 |  |  |   if (last_focused_view) { | 
					
						
							|  |  |  |     GetFocusManager()->SetFocusedViewWithReason( | 
					
						
							| 
									
										
										
										
											2019-08-23 21:14:23 -04:00
										 |  |  |         last_focused_view, | 
					
						
							|  |  |  |         views::FocusManager::FocusChangeReason::kFocusRestore); | 
					
						
							| 
									
										
										
										
											2018-10-29 19:08:47 +01:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (menu_bar_autohide_) | 
					
						
							|  |  |  |     SetMenuBarVisibility(false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | void RootView::ResetAltState() { | 
					
						
							|  |  |  |   menu_bar_alt_pressed_ = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | gfx::Size RootView::GetMinimumSize() const { | 
					
						
							|  |  |  |   return window_->GetMinimumSize(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | gfx::Size RootView::GetMaximumSize() const { | 
					
						
							|  |  |  |   return window_->GetMaximumSize(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool RootView::AcceleratorPressed(const ui::Accelerator& accelerator) { | 
					
						
							|  |  |  |   return accelerator_util::TriggerAcceleratorTableCommand(&accelerator_table_, | 
					
						
							|  |  |  |                                                           accelerator); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 12:19:40 -08:00
										 |  |  | void RootView::RegisterAcceleratorsWithFocusManager( | 
					
						
							|  |  |  |     ElectronMenuModel* menu_model) { | 
					
						
							| 
									
										
										
										
											2018-11-09 13:54:16 -08:00
										 |  |  |   if (!menu_model) | 
					
						
							|  |  |  |     return; | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |   // Clear previous accelerators.
 | 
					
						
							| 
									
										
										
										
											2018-11-09 13:54:16 -08:00
										 |  |  |   UnregisterAcceleratorsWithFocusManager(); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 13:54:16 -08:00
										 |  |  |   views::FocusManager* focus_manager = GetFocusManager(); | 
					
						
							| 
									
										
										
										
											2018-05-01 13:28:22 +09:00
										 |  |  |   // Register accelerators with focus manager.
 | 
					
						
							|  |  |  |   accelerator_util::GenerateAcceleratorTable(&accelerator_table_, menu_model); | 
					
						
							|  |  |  |   for (const auto& iter : accelerator_table_) { | 
					
						
							|  |  |  |     focus_manager->RegisterAccelerator( | 
					
						
							|  |  |  |         iter.first, ui::AcceleratorManager::kNormalPriority, this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 13:54:16 -08:00
										 |  |  | void RootView::UnregisterAcceleratorsWithFocusManager() { | 
					
						
							|  |  |  |   views::FocusManager* focus_manager = GetFocusManager(); | 
					
						
							|  |  |  |   accelerator_table_.clear(); | 
					
						
							|  |  |  |   focus_manager->UnregisterAccelerators(this); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 14:23:04 -07:00
										 |  |  | }  // namespace electron
 |