fix: Wayland resizing border (#46155)
* fix: Wayland resizing border Closes https://github.com/electron/electron/issues/44543 Refs CL:5180720 Fixes an issue where the resizing border didn't work as expected on Wayland windows. * fix: border insets when fullscreen
This commit is contained in:
		
					parent
					
						
							
								b8150f33db
							
						
					
				
			
			
				commit
				
					
						47cf4e7bfd
					
				
			
		
					 4 changed files with 50 additions and 36 deletions
				
			
		|  | @ -47,22 +47,28 @@ void ElectronDesktopWindowTreeHostLinux::OnWidgetInitDone() { | |||
|   UpdateFrameHints(); | ||||
| } | ||||
| 
 | ||||
| bool ElectronDesktopWindowTreeHostLinux::IsShowingFrame() const { | ||||
|   return !native_window_view_->IsFullscreen() && | ||||
|          !native_window_view_->IsMaximized() && | ||||
|          !native_window_view_->IsMinimized(); | ||||
| } | ||||
| 
 | ||||
| gfx::Insets ElectronDesktopWindowTreeHostLinux::CalculateInsetsInDIP( | ||||
|     ui::PlatformWindowState window_state) const { | ||||
|   // If we are not showing frame, the insets should be zero.
 | ||||
|   if (native_window_view_->IsFullscreen()) { | ||||
|     return {}; | ||||
|   if (!IsShowingFrame()) { | ||||
|     return gfx::Insets(); | ||||
|   } | ||||
| 
 | ||||
|   if (!native_window_view_->has_frame() || | ||||
|       !native_window_view_->has_client_frame()) { | ||||
|     return {}; | ||||
|     return gfx::Insets(); | ||||
|   } | ||||
| 
 | ||||
|   auto* view = static_cast<ClientFrameViewLinux*>( | ||||
|       native_window_view_->widget()->non_client_view()->frame_view()); | ||||
| 
 | ||||
|   gfx::Insets insets = view->GetBorderDecorationInsets(); | ||||
|   gfx::Insets insets = view->RestoredMirroredFrameBorderInsets(); | ||||
|   if (base::i18n::IsRTL()) | ||||
|     insets.set_left_right(insets.right(), insets.left()); | ||||
|   return insets; | ||||
|  | @ -99,9 +105,14 @@ void ElectronDesktopWindowTreeHostLinux::OnWindowTiledStateChanged( | |||
|   // of view.
 | ||||
|   if (native_window_view_->has_frame() && | ||||
|       native_window_view_->has_client_frame()) { | ||||
|     static_cast<ClientFrameViewLinux*>( | ||||
|         native_window_view_->widget()->non_client_view()->frame_view()) | ||||
|         ->set_tiled_edges(new_tiled_edges); | ||||
|     ClientFrameViewLinux* frame = static_cast<ClientFrameViewLinux*>( | ||||
|         native_window_view_->widget()->non_client_view()->frame_view()); | ||||
| 
 | ||||
|     bool maximized = new_tiled_edges.top && new_tiled_edges.left && | ||||
|                      new_tiled_edges.bottom && new_tiled_edges.right; | ||||
|     bool tiled = new_tiled_edges.top || new_tiled_edges.left || | ||||
|                  new_tiled_edges.bottom || new_tiled_edges.right; | ||||
|     frame->set_tiled(tiled && !maximized); | ||||
|   } | ||||
|   UpdateFrameHints(); | ||||
| } | ||||
|  | @ -181,7 +192,7 @@ void ElectronDesktopWindowTreeHostLinux::UpdateFrameHints() { | |||
|     if (ui::OzonePlatform::GetInstance()->IsWindowCompositingSupported()) { | ||||
|       // Set the opaque region.
 | ||||
|       std::vector<gfx::Rect> opaque_region; | ||||
|       if (!native_window_view_->IsFullscreen()) { | ||||
|       if (!IsShowingFrame()) { | ||||
|         // The opaque region is a list of rectangles that contain only fully
 | ||||
|         // opaque pixels of the window.  We need to convert the clipping
 | ||||
|         // rounded-rect into this format.
 | ||||
|  |  | |||
|  | @ -65,6 +65,8 @@ class ElectronDesktopWindowTreeHostLinux | |||
|  private: | ||||
|   void UpdateWindowState(ui::PlatformWindowState new_state); | ||||
| 
 | ||||
|   bool IsShowingFrame() const; | ||||
| 
 | ||||
|   raw_ptr<NativeWindowViews> native_window_view_;  // weak ref
 | ||||
| 
 | ||||
|   base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver> | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ namespace electron { | |||
| namespace { | ||||
| 
 | ||||
| // These values should be the same as Chromium uses.
 | ||||
| constexpr int kResizeOutsideBorderSize = 10; | ||||
| constexpr int kResizeBorder = 10; | ||||
| constexpr int kResizeInsideBoundsSize = 5; | ||||
| 
 | ||||
| ui::NavButtonProvider::ButtonState ButtonStateToNavButtonProviderState( | ||||
|  | @ -142,25 +142,28 @@ void ClientFrameViewLinux::Init(NativeWindowViews* window, | |||
|   UpdateThemeValues(); | ||||
| } | ||||
| 
 | ||||
| gfx::Insets ClientFrameViewLinux::GetBorderDecorationInsets() const { | ||||
|   const auto insets = GetFrameProvider()->GetFrameThicknessDip(); | ||||
| gfx::Insets ClientFrameViewLinux::RestoredMirroredFrameBorderInsets() const { | ||||
|   auto border = RestoredFrameBorderInsets(); | ||||
|   return base::i18n::IsRTL() ? gfx::Insets::TLBR(border.top(), border.right(), | ||||
|                                                  border.bottom(), border.left()) | ||||
|                              : border; | ||||
| } | ||||
| 
 | ||||
|   // We shouldn't draw frame decorations for the tiled edges.
 | ||||
|   // See https://wayland.app/protocols/xdg-shell#xdg_toplevel:enum:state
 | ||||
|   const auto& edges = tiled_edges(); | ||||
|   return gfx::Insets::TLBR( | ||||
|       edges.top ? 0 : insets.top(), edges.left ? 0 : insets.left(), | ||||
|       edges.bottom ? 0 : insets.bottom(), edges.right ? 0 : insets.right()); | ||||
| gfx::Insets ClientFrameViewLinux::RestoredFrameBorderInsets() const { | ||||
|   gfx::Insets insets = GetFrameProvider()->GetFrameThicknessDip(); | ||||
|   insets.SetToMax(GetInputInsets()); | ||||
|   return insets; | ||||
| } | ||||
| 
 | ||||
| gfx::Insets ClientFrameViewLinux::GetInputInsets() const { | ||||
|   return gfx::Insets{ | ||||
|       host_supports_client_frame_shadow_ ? -kResizeOutsideBorderSize : 0}; | ||||
|   bool showing_shadow = host_supports_client_frame_shadow_ && | ||||
|                         !frame_->IsMaximized() && !frame_->IsFullscreen(); | ||||
|   return gfx::Insets(showing_shadow ? kResizeBorder : 0); | ||||
| } | ||||
| 
 | ||||
| gfx::Rect ClientFrameViewLinux::GetWindowContentBounds() const { | ||||
|   gfx::Rect content_bounds = bounds(); | ||||
|   content_bounds.Inset(GetBorderDecorationInsets()); | ||||
|   content_bounds.Inset(RestoredMirroredFrameBorderInsets()); | ||||
|   return content_bounds; | ||||
| } | ||||
| 
 | ||||
|  | @ -194,15 +197,15 @@ void ClientFrameViewLinux::OnWindowButtonOrderingChange() { | |||
| } | ||||
| 
 | ||||
| int ClientFrameViewLinux::ResizingBorderHitTest(const gfx::Point& point) { | ||||
|   return ResizingBorderHitTestImpl( | ||||
|       point, | ||||
|       GetBorderDecorationInsets() + gfx::Insets(kResizeInsideBoundsSize)); | ||||
|   return ResizingBorderHitTestImpl(point, | ||||
|                                    RestoredMirroredFrameBorderInsets() + | ||||
|                                        gfx::Insets(kResizeInsideBoundsSize)); | ||||
| } | ||||
| 
 | ||||
| gfx::Rect ClientFrameViewLinux::GetBoundsForClientView() const { | ||||
|   gfx::Rect client_bounds = bounds(); | ||||
|   if (!frame_->IsFullscreen()) { | ||||
|     client_bounds.Inset(GetBorderDecorationInsets()); | ||||
|     client_bounds.Inset(RestoredMirroredFrameBorderInsets()); | ||||
|     client_bounds.Inset( | ||||
|         gfx::Insets::TLBR(GetTitlebarBounds().height(), 0, 0, 0)); | ||||
|   } | ||||
|  | @ -239,10 +242,8 @@ int ClientFrameViewLinux::NonClientHitTest(const gfx::Point& point) { | |||
| } | ||||
| 
 | ||||
| ui::WindowFrameProvider* ClientFrameViewLinux::GetFrameProvider() const { | ||||
|   const bool tiled = tiled_edges().top || tiled_edges().left || | ||||
|                      tiled_edges().bottom || tiled_edges().right; | ||||
|   return ui::LinuxUiTheme::GetForProfile(nullptr)->GetWindowFrameProvider( | ||||
|       !host_supports_client_frame_shadow_, tiled, frame_->IsMaximized()); | ||||
|       !host_supports_client_frame_shadow_, tiled(), frame_->IsMaximized()); | ||||
| } | ||||
| 
 | ||||
| void ClientFrameViewLinux::GetWindowMask(const gfx::Size& size, | ||||
|  | @ -465,7 +466,7 @@ gfx::Rect ClientFrameViewLinux::GetTitlebarBounds() const { | |||
|       std::max(font_height, theme_values_.titlebar_min_height) + | ||||
|       GetTitlebarContentInsets().height(); | ||||
| 
 | ||||
|   gfx::Insets decoration_insets = GetBorderDecorationInsets(); | ||||
|   gfx::Insets decoration_insets = RestoredMirroredFrameBorderInsets(); | ||||
| 
 | ||||
|   // We add the inset height here, so the .Inset() that follows won't reduce it
 | ||||
|   // to be too small.
 | ||||
|  | @ -486,7 +487,7 @@ gfx::Rect ClientFrameViewLinux::GetTitlebarContentBounds() const { | |||
| } | ||||
| 
 | ||||
| gfx::Size ClientFrameViewLinux::SizeWithDecorations(gfx::Size size) const { | ||||
|   gfx::Insets decoration_insets = GetBorderDecorationInsets(); | ||||
|   gfx::Insets decoration_insets = RestoredMirroredFrameBorderInsets(); | ||||
| 
 | ||||
|   size.Enlarge(0, GetTitlebarBounds().height()); | ||||
|   size.Enlarge(decoration_insets.width(), decoration_insets.height()); | ||||
|  |  | |||
|  | @ -43,16 +43,16 @@ class ClientFrameViewLinux : public FramelessView, | |||
|   void Init(NativeWindowViews* window, views::Widget* frame) override; | ||||
| 
 | ||||
|   // These are here for ElectronDesktopWindowTreeHostLinux to use.
 | ||||
|   gfx::Insets GetBorderDecorationInsets() const; | ||||
|   gfx::Insets RestoredMirroredFrameBorderInsets() const; | ||||
|   gfx::Insets RestoredFrameBorderInsets() const; | ||||
|   gfx::Insets GetInputInsets() const; | ||||
|   gfx::Rect GetWindowContentBounds() const; | ||||
|   SkRRect GetRoundedWindowContentBounds() const; | ||||
|   int GetTranslucentTopAreaHeight() const; | ||||
|   // Returns which edges of the frame are tiled.
 | ||||
|   const ui::WindowTiledEdges& tiled_edges() const { return tiled_edges_; } | ||||
|   void set_tiled_edges(ui::WindowTiledEdges tiled_edges) { | ||||
|     tiled_edges_ = tiled_edges; | ||||
|   } | ||||
| 
 | ||||
|   // Returns whether the frame is in a tiled state.
 | ||||
|   bool tiled() const { return tiled_; } | ||||
|   void set_tiled(bool tiled) { tiled_ = tiled; } | ||||
| 
 | ||||
|  protected: | ||||
|   // ui::NativeThemeObserver:
 | ||||
|  | @ -149,7 +149,7 @@ class ClientFrameViewLinux : public FramelessView, | |||
| 
 | ||||
|   base::CallbackListSubscription paint_as_active_changed_subscription_; | ||||
| 
 | ||||
|   ui::WindowTiledEdges tiled_edges_; | ||||
|   bool tiled_ = false; | ||||
| }; | ||||
| 
 | ||||
| }  // namespace electron
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Shelley Vohr
				Shelley Vohr