frameless_view.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright (c) 2014 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/ui/views/frameless_view.h"
  5. #include "shell/browser/native_window_views.h"
  6. #include "ui/base/hit_test.h"
  7. #include "ui/base/metadata/metadata_impl_macros.h"
  8. #include "ui/views/widget/widget.h"
  9. #include "ui/views/widget/widget_delegate.h"
  10. namespace electron {
  11. namespace {
  12. const int kResizeInsideBoundsSize = 5;
  13. const int kResizeAreaCornerSize = 16;
  14. } // namespace
  15. FramelessView::FramelessView() = default;
  16. FramelessView::~FramelessView() = default;
  17. void FramelessView::Init(NativeWindowViews* window, views::Widget* frame) {
  18. window_ = window;
  19. frame_ = frame;
  20. }
  21. int FramelessView::ResizingBorderHitTest(const gfx::Point& point) {
  22. return ResizingBorderHitTestImpl(point, gfx::Insets(kResizeInsideBoundsSize));
  23. }
  24. int FramelessView::ResizingBorderHitTestImpl(const gfx::Point& point,
  25. const gfx::Insets& resize_border) {
  26. // to be used for resize handles.
  27. bool can_ever_resize = frame_->widget_delegate()
  28. ? frame_->widget_delegate()->CanResize()
  29. : false;
  30. // https://github.com/electron/electron/issues/611
  31. // If window isn't resizable, we should always return HTNOWHERE, otherwise the
  32. // hover state of DOM will not be cleared probably.
  33. if (!can_ever_resize)
  34. return HTNOWHERE;
  35. // Don't allow overlapping resize handles when the window is maximized or
  36. // fullscreen, as it can't be resized in those states.
  37. bool allow_overlapping_handles =
  38. !frame_->IsMaximized() && !frame_->IsFullscreen();
  39. return GetHTComponentForFrame(
  40. point, allow_overlapping_handles ? resize_border : gfx::Insets(),
  41. kResizeAreaCornerSize, kResizeAreaCornerSize, can_ever_resize);
  42. }
  43. gfx::Rect FramelessView::GetBoundsForClientView() const {
  44. return bounds();
  45. }
  46. gfx::Rect FramelessView::GetWindowBoundsForClientBounds(
  47. const gfx::Rect& client_bounds) const {
  48. gfx::Rect window_bounds = client_bounds;
  49. // Enforce minimum size (1, 1) in case that client_bounds is passed with
  50. // empty size. This could occur when the frameless window is being
  51. // initialized.
  52. if (window_bounds.IsEmpty()) {
  53. window_bounds.set_width(1);
  54. window_bounds.set_height(1);
  55. }
  56. return window_bounds;
  57. }
  58. int FramelessView::NonClientHitTest(const gfx::Point& point) {
  59. if (frame_->IsFullscreen())
  60. return HTCLIENT;
  61. int contents_hit_test = window_->NonClientHitTest(point);
  62. if (contents_hit_test != HTNOWHERE)
  63. return contents_hit_test;
  64. // Support resizing frameless window by dragging the border.
  65. int frame_component = ResizingBorderHitTest(point);
  66. if (frame_component != HTNOWHERE)
  67. return frame_component;
  68. return HTCLIENT;
  69. }
  70. views::View* FramelessView::TargetForRect(views::View* root,
  71. const gfx::Rect& rect) {
  72. CHECK_EQ(root, this);
  73. if (NonClientHitTest(rect.origin()) != HTCLIENT)
  74. return this;
  75. return NonClientFrameView::TargetForRect(root, rect);
  76. }
  77. gfx::Size FramelessView::CalculatePreferredSize(
  78. const views::SizeBounds& available_size) const {
  79. return frame_->non_client_view()
  80. ->GetWindowBoundsForClientBounds(gfx::Rect(
  81. frame_->client_view()->CalculatePreferredSize(available_size)))
  82. .size();
  83. }
  84. gfx::Size FramelessView::GetMinimumSize() const {
  85. return window_->GetContentMinimumSize();
  86. }
  87. gfx::Size FramelessView::GetMaximumSize() const {
  88. gfx::Size size = window_->GetContentMaximumSize();
  89. // Electron public APIs returns (0, 0) when maximum size is not set, but it
  90. // would break internal window APIs like HWNDMessageHandler::SetAspectRatio.
  91. return size.IsEmpty() ? gfx::Size(INT_MAX, INT_MAX) : size;
  92. }
  93. BEGIN_METADATA(FramelessView)
  94. END_METADATA
  95. } // namespace electron