Commit 4e5eb9ab authored by Zakhar Voit's avatar Zakhar Voit Committed by Commit Bot

[ozone/wayland] Fix force-device-scale-factor command line flag

Fixes browser crash when the --force-device-scale-factor flag is used on
4K monitors and the user is trying to open a popup window.

Cause of the crash: ui_scale()/buffer_scale division here
https://source.chromium.org/chromium/chromium/src/+/master:ui/ozone/platform/wayland/host/wayland_popup.cc;l=159;drc=1e3319e24d05bef56bcf40b2cacf256e285e1342
resulted in 0 because both methods return integer.

This CL also simplifies scaling logic in WaylandPopup and
WaylandAuxiliaryWindow. These classes used to convert pixel bounds to
DIP before changing them to the coordinates relative to the parent (by
applying mixed ui_scale/buffer_scale arithmetic). It's not necessary
and doesn't work sometimes when ui_scale != buffer_scale.

This CL was tested with --force-device-scale-factor flag as well as on
single monitor setups with different scaling.

Fixes for multi-monitor setups will be added in a separate CL, because
at the moment scaling is not always correctly propagated to each
window on them.

Bug: 1052685
Change-Id: I6259e62c640e6f9cd6aeee45f27377dfa34d1ee6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2318230Reviewed-by: default avatarMaksim Sisov (GMT+3) <msisov@igalia.com>
Commit-Queue: Zakhar Voit <zvoit@igalia.com>
Cr-Commit-Position: refs/heads/master@{#796345}
parent 61b4ce98
......@@ -172,4 +172,16 @@ ui::WaylandWindow* RootWindowFromWlSurface(wl_surface* surface) {
return wayland_surface->root_window();
}
gfx::Rect TranslateWindowBoundsToParentDIP(ui::WaylandWindow* window,
ui::WaylandWindow* parent_window) {
DCHECK(window);
DCHECK(parent_window);
DCHECK_EQ(window->buffer_scale(), parent_window->buffer_scale());
DCHECK_EQ(window->ui_scale(), parent_window->ui_scale());
return gfx::ScaleToRoundedRect(
wl::TranslateBoundsToParentCoordinates(window->GetBounds(),
parent_window->GetBounds()),
1.0 / window->buffer_scale());
}
} // namespace wl
......@@ -66,6 +66,13 @@ bool IsMenuType(ui::PlatformWindowType type);
// Returns the root WaylandWindow for the given wl_surface.
ui::WaylandWindow* RootWindowFromWlSurface(wl_surface* surface);
// Returns bounds of the given window, adjusted to its subsurface. We need to
// adjust bounds because WaylandWindow::GetBounds() returns absolute bounds in
// pixels, but wl_subsurface works with bounds relative to the parent surface
// and in DIP.
gfx::Rect TranslateWindowBoundsToParentDIP(ui::WaylandWindow* window,
ui::WaylandWindow* parent_window);
} // namespace wl
#endif // UI_OZONE_PLATFORM_WAYLAND_COMMON_WAYLAND_UTIL_H_
......@@ -12,21 +12,6 @@
namespace ui {
namespace {
gfx::Rect AdjustSubsurfaceBounds(const gfx::Rect& bounds_px,
const gfx::Rect& parent_bounds_px,
float ui_scale,
int32_t buffer_scale) {
const auto parent_bounds_dip =
gfx::ScaleToRoundedRect(parent_bounds_px, 1.0 / ui_scale);
auto new_bounds_dip =
wl::TranslateBoundsToParentCoordinates(bounds_px, parent_bounds_dip);
return gfx::ScaleToRoundedRect(new_bounds_dip, ui_scale / buffer_scale);
}
} // namespace
WaylandAuxiliaryWindow::WaylandAuxiliaryWindow(PlatformWindowDelegate* delegate,
WaylandConnection* connection)
: WaylandWindow(delegate, connection) {}
......@@ -63,11 +48,10 @@ void WaylandAuxiliaryWindow::SetBounds(const gfx::Rect& bounds) {
if (old_bounds == bounds || !parent_window())
return;
// Translate location from screen to surface coordinates.
auto bounds_px = AdjustSubsurfaceBounds(
GetBounds(), parent_window()->GetBounds(), ui_scale(), buffer_scale());
wl_subsurface_set_position(subsurface_.get(), bounds_px.x() / buffer_scale(),
bounds_px.y() / buffer_scale());
auto subsurface_bounds_dip =
wl::TranslateWindowBoundsToParentDIP(this, parent_window());
wl_subsurface_set_position(subsurface_.get(), subsurface_bounds_dip.x(),
subsurface_bounds_dip.y());
root_surface()->Commit();
connection()->ScheduleFlush();
}
......@@ -99,16 +83,13 @@ void WaylandAuxiliaryWindow::CreateSubsurface() {
subsurface_ = root_surface()->CreateSubsurface(parent->root_surface());
// Chromium positions tooltip windows in screen coordinates, but Wayland
// requires them to be in local surface coordinates a.k.a relative to parent
// window.
auto bounds_px = AdjustSubsurfaceBounds(GetBounds(), parent->GetBounds(),
ui_scale(), buffer_scale());
auto subsurface_bounds_dip =
wl::TranslateWindowBoundsToParentDIP(this, parent);
DCHECK(subsurface_);
// Convert position to DIP.
wl_subsurface_set_position(subsurface_.get(), bounds_px.x() / buffer_scale(),
bounds_px.y() / buffer_scale());
wl_subsurface_set_position(subsurface_.get(), subsurface_bounds_dip.x(),
subsurface_bounds_dip.y());
wl_subsurface_set_desync(subsurface_.get());
parent->root_surface()->Commit();
connection()->ScheduleFlush();
......
......@@ -24,10 +24,12 @@ bool WaylandPopup::CreateShellPopup() {
DCHECK(parent_window() && !shell_popup_);
auto bounds_px = AdjustPopupWindowPosition();
auto subsurface_bounds_dip =
wl::TranslateWindowBoundsToParentDIP(this, parent_window());
ShellObjectFactory factory;
shell_popup_ = factory.CreateShellPopupWrapper(connection(), this, bounds_px);
shell_popup_ = factory.CreateShellPopupWrapper(connection(), this,
subsurface_bounds_dip);
if (!shell_popup_) {
LOG(ERROR) << "Failed to create Wayland shell popup";
return false;
......@@ -143,20 +145,4 @@ bool WaylandPopup::OnInitialize(PlatformWindowInitProperties properties) {
return true;
}
gfx::Rect WaylandPopup::AdjustPopupWindowPosition() {
auto* top_level_parent = GetRootParentWindow();
DCHECK(top_level_parent);
DCHECK(buffer_scale() == top_level_parent->buffer_scale());
DCHECK(ui_scale() == top_level_parent->ui_scale());
// Chromium positions windows in screen coordinates, but Wayland requires them
// to be in local surface coordinates a.k.a relative to parent window.
const gfx::Rect parent_bounds_dip =
gfx::ScaleToRoundedRect(parent_window()->GetBounds(), 1.0 / ui_scale());
gfx::Rect new_bounds_dip = wl::TranslateBoundsToParentCoordinates(
gfx::ScaleToRoundedRect(GetBounds(), 1.0 / ui_scale()),
parent_bounds_dip);
return gfx::ScaleToRoundedRect(new_bounds_dip, ui_scale() / buffer_scale());
}
} // namespace ui
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment