| 
									
										
										
										
											2021-08-11 11:07:36 -07:00
										 |  |  | // Copyright 2020 The Chromium Authors. All rights reserved.
 | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style license that can be
 | 
					
						
							|  |  |  | // found in the LICENSE file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-24 14:09:21 -08:00
										 |  |  | // Modified from
 | 
					
						
							|  |  |  | // chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-11 11:07:36 -07:00
										 |  |  | #include "shell/browser/ui/views/win_caption_button_container.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <memory>
 | 
					
						
							|  |  |  | #include <utility>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "shell/browser/ui/views/win_caption_button.h"
 | 
					
						
							|  |  |  | #include "shell/browser/ui/views/win_frame_view.h"
 | 
					
						
							|  |  |  | #include "ui/base/l10n/l10n_util.h"
 | 
					
						
							|  |  |  | #include "ui/strings/grit/ui_strings.h"
 | 
					
						
							|  |  |  | #include "ui/views/layout/flex_layout.h"
 | 
					
						
							|  |  |  | #include "ui/views/view_class_properties.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace electron { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::unique_ptr<WinCaptionButton> CreateCaptionButton( | 
					
						
							|  |  |  |     views::Button::PressedCallback callback, | 
					
						
							|  |  |  |     WinFrameView* frame_view, | 
					
						
							|  |  |  |     ViewID button_type, | 
					
						
							|  |  |  |     int accessible_name_resource_id) { | 
					
						
							|  |  |  |   return std::make_unique<WinCaptionButton>( | 
					
						
							|  |  |  |       std::move(callback), frame_view, button_type, | 
					
						
							|  |  |  |       l10n_util::GetStringUTF16(accessible_name_resource_id)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool HitTestCaptionButton(WinCaptionButton* button, const gfx::Point& point) { | 
					
						
							|  |  |  |   return button && button->GetVisible() && button->bounds().Contains(point); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // anonymous namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | WinCaptionButtonContainer::WinCaptionButtonContainer(WinFrameView* frame_view) | 
					
						
							|  |  |  |     : frame_view_(frame_view), | 
					
						
							|  |  |  |       minimize_button_(AddChildView(CreateCaptionButton( | 
					
						
							|  |  |  |           base::BindRepeating(&views::Widget::Minimize, | 
					
						
							|  |  |  |                               base::Unretained(frame_view_->frame())), | 
					
						
							|  |  |  |           frame_view_, | 
					
						
							|  |  |  |           VIEW_ID_MINIMIZE_BUTTON, | 
					
						
							|  |  |  |           IDS_APP_ACCNAME_MINIMIZE))), | 
					
						
							|  |  |  |       maximize_button_(AddChildView(CreateCaptionButton( | 
					
						
							|  |  |  |           base::BindRepeating(&views::Widget::Maximize, | 
					
						
							|  |  |  |                               base::Unretained(frame_view_->frame())), | 
					
						
							|  |  |  |           frame_view_, | 
					
						
							|  |  |  |           VIEW_ID_MAXIMIZE_BUTTON, | 
					
						
							|  |  |  |           IDS_APP_ACCNAME_MAXIMIZE))), | 
					
						
							|  |  |  |       restore_button_(AddChildView(CreateCaptionButton( | 
					
						
							|  |  |  |           base::BindRepeating(&views::Widget::Restore, | 
					
						
							|  |  |  |                               base::Unretained(frame_view_->frame())), | 
					
						
							|  |  |  |           frame_view_, | 
					
						
							|  |  |  |           VIEW_ID_RESTORE_BUTTON, | 
					
						
							|  |  |  |           IDS_APP_ACCNAME_RESTORE))), | 
					
						
							|  |  |  |       close_button_(AddChildView(CreateCaptionButton( | 
					
						
							|  |  |  |           base::BindRepeating(&views::Widget::CloseWithReason, | 
					
						
							|  |  |  |                               base::Unretained(frame_view_->frame()), | 
					
						
							|  |  |  |                               views::Widget::ClosedReason::kCloseButtonClicked), | 
					
						
							|  |  |  |           frame_view_, | 
					
						
							|  |  |  |           VIEW_ID_CLOSE_BUTTON, | 
					
						
							|  |  |  |           IDS_APP_ACCNAME_CLOSE))) { | 
					
						
							|  |  |  |   // Layout is horizontal, with buttons placed at the trailing end of the view.
 | 
					
						
							|  |  |  |   // This allows the container to expand to become a faux titlebar/drag handle.
 | 
					
						
							|  |  |  |   auto* const layout = SetLayoutManager(std::make_unique<views::FlexLayout>()); | 
					
						
							|  |  |  |   layout->SetOrientation(views::LayoutOrientation::kHorizontal) | 
					
						
							|  |  |  |       .SetMainAxisAlignment(views::LayoutAlignment::kEnd) | 
					
						
							|  |  |  |       .SetCrossAxisAlignment(views::LayoutAlignment::kStart) | 
					
						
							|  |  |  |       .SetDefault( | 
					
						
							|  |  |  |           views::kFlexBehaviorKey, | 
					
						
							|  |  |  |           views::FlexSpecification(views::LayoutOrientation::kHorizontal, | 
					
						
							|  |  |  |                                    views::MinimumFlexSizeRule::kPreferred, | 
					
						
							|  |  |  |                                    views::MaximumFlexSizeRule::kPreferred, | 
					
						
							|  |  |  |                                    /* adjust_width_for_height */ false, | 
					
						
							|  |  |  |                                    views::MinimumFlexSizeRule::kScaleToZero)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | WinCaptionButtonContainer::~WinCaptionButtonContainer() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int WinCaptionButtonContainer::NonClientHitTest(const gfx::Point& point) const { | 
					
						
							|  |  |  |   DCHECK(HitTestPoint(point)) | 
					
						
							|  |  |  |       << "should only be called with a point inside this view's bounds"; | 
					
						
							|  |  |  |   if (HitTestCaptionButton(minimize_button_, point)) { | 
					
						
							|  |  |  |     return HTMINBUTTON; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (HitTestCaptionButton(maximize_button_, point)) { | 
					
						
							|  |  |  |     return HTMAXBUTTON; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (HitTestCaptionButton(restore_button_, point)) { | 
					
						
							|  |  |  |     return HTMAXBUTTON; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (HitTestCaptionButton(close_button_, point)) { | 
					
						
							|  |  |  |     return HTCLOSE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return HTCAPTION; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-24 14:09:21 -08:00
										 |  |  | gfx::Size WinCaptionButtonContainer::GetButtonSize() const { | 
					
						
							|  |  |  |   // Close button size is set the same as all the buttons
 | 
					
						
							|  |  |  |   return close_button_->GetSize(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WinCaptionButtonContainer::SetButtonSize(gfx::Size size) { | 
					
						
							|  |  |  |   minimize_button_->SetSize(size); | 
					
						
							|  |  |  |   maximize_button_->SetSize(size); | 
					
						
							|  |  |  |   restore_button_->SetSize(size); | 
					
						
							|  |  |  |   close_button_->SetSize(size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-11 11:07:36 -07:00
										 |  |  | void WinCaptionButtonContainer::ResetWindowControls() { | 
					
						
							|  |  |  |   minimize_button_->SetState(views::Button::STATE_NORMAL); | 
					
						
							|  |  |  |   maximize_button_->SetState(views::Button::STATE_NORMAL); | 
					
						
							|  |  |  |   restore_button_->SetState(views::Button::STATE_NORMAL); | 
					
						
							|  |  |  |   close_button_->SetState(views::Button::STATE_NORMAL); | 
					
						
							|  |  |  |   InvalidateLayout(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WinCaptionButtonContainer::AddedToWidget() { | 
					
						
							|  |  |  |   views::Widget* const widget = GetWidget(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DCHECK(!widget_observation_.IsObserving()); | 
					
						
							|  |  |  |   widget_observation_.Observe(widget); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   UpdateButtons(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (frame_view_->window()->IsWindowControlsOverlayEnabled()) { | 
					
						
							|  |  |  |     SetPaintToLayer(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WinCaptionButtonContainer::RemovedFromWidget() { | 
					
						
							|  |  |  |   DCHECK(widget_observation_.IsObserving()); | 
					
						
							|  |  |  |   widget_observation_.Reset(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WinCaptionButtonContainer::OnWidgetBoundsChanged( | 
					
						
							|  |  |  |     views::Widget* widget, | 
					
						
							|  |  |  |     const gfx::Rect& new_bounds) { | 
					
						
							|  |  |  |   UpdateButtons(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void WinCaptionButtonContainer::UpdateButtons() { | 
					
						
							|  |  |  |   const bool is_maximized = frame_view_->frame()->IsMaximized(); | 
					
						
							|  |  |  |   restore_button_->SetVisible(is_maximized); | 
					
						
							|  |  |  |   maximize_button_->SetVisible(!is_maximized); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-23 19:08:32 +02:00
										 |  |  |   const bool minimizable = frame_view_->window()->IsMinimizable(); | 
					
						
							|  |  |  |   minimize_button_->SetEnabled(minimizable); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-11 11:07:36 -07:00
										 |  |  |   // In touch mode, windows cannot be taken out of fullscreen or tiled mode, so
 | 
					
						
							|  |  |  |   // the maximize/restore button should be disabled.
 | 
					
						
							|  |  |  |   const bool is_touch = ui::TouchUiController::Get()->touch_ui(); | 
					
						
							|  |  |  |   restore_button_->SetEnabled(!is_touch); | 
					
						
							| 
									
										
										
										
											2022-06-23 19:08:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // The maximize button should only be enabled if the window is
 | 
					
						
							|  |  |  |   // maximizable *and* touch mode is disabled.
 | 
					
						
							|  |  |  |   const bool maximizable = frame_view_->window()->IsMaximizable(); | 
					
						
							|  |  |  |   maximize_button_->SetEnabled(!is_touch && maximizable); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const bool closable = frame_view_->window()->IsClosable(); | 
					
						
							|  |  |  |   close_button_->SetEnabled(closable); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // If all three of closable, maximizable, and minimizable are disabled,
 | 
					
						
							|  |  |  |   // Windows natively only shows the disabled closable button. Copy that
 | 
					
						
							|  |  |  |   // behavior here.
 | 
					
						
							|  |  |  |   if (!maximizable && !closable && !minimizable) { | 
					
						
							|  |  |  |     minimize_button_->SetVisible(false); | 
					
						
							|  |  |  |     maximize_button_->SetVisible(false); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-11 11:07:36 -07:00
										 |  |  |   InvalidateLayout(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | }  // namespace electron
 |