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