New issue
Advanced search Search tips

Issue 602692 link

Starred by 5 users

Issue metadata

Status: Archived
Owner: ----
Closed: Aug 22
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug



Sign in to add a comment

Windows: views: NonClientView::GetPreferredSize calculation is wrong on high-dpi displays

Project Member Reported by marshall@chromium.org, Apr 12 2016

Issue description

Version: Chromium revision 0bfd25d4 (#381305)
OS: Windows 10 64-bit, HiDPI display

What steps will reproduce the problem?
(1) Call Widget::Init() with empty initial bounds.

What is the expected output?

The Widget size is set to the NonClientView preferred size in DIPs due to the following code from Widget::SetInitialBounds():

native_widget_->CenterWindow(non_client_view_->GetPreferredSize());

For example, if the ClientView returns a preferred size of 400x400 DIPs and the insets for the NonClientView determined by GetWindowBoundsForClientBounds() in hwnd_util_aurawin.cc are [-8, -31, 8, 8] then the value passed to CenterWindow() should be 416x439 DIPs.

What do you see instead?

The NonClientView insets calculated by GetWindowBoundsForClientBounds() are in pixel coordinates instead of DIPs [1]. On HiDPI displays this results in incorrect insets of [-13, -58, 13, 13] which, combined with the ClientView preferred size of 400x400 DIPs, results in an incorrect size of 426x471 DIPs being passed to CenterWindow().

[1] https://code.google.com/p/chromium/codesearch#chromium/src/ui/views/win/hwnd_util_aurawin.cc&q=GetWindowBoundsForClientBounds&sq=package:chromium&type=cs&l=31

Please use labels and text to provide additional information.

Call stack:

>	libcef.dll!views::GetWindowBoundsForClientBounds(views::View * view, const gfx::Rect & client_bounds) Line 41	C++
 	libcef.dll!views::NativeFrameView::GetWindowBoundsForClientBounds(const gfx::Rect & client_bounds) Line 41	C++
 	libcef.dll!views::NonClientView::GetWindowBoundsForClientBounds(const gfx::Rect client_bounds) Line 89	C++
 	libcef.dll!views::NonClientView::GetPreferredSize() Line 145	C++
 	libcef.dll!views::Widget::SetInitialBounds(const gfx::Rect & bounds) Line 1440	C++
 	libcef.dll!views::Widget::Init(const views::Widget::InitParams & in_params) Line 370	C++

 
Changing NativeFrameView::GetWindowBoundsForClientBounds() from:

  return views::GetWindowBoundsForClientBounds(
      static_cast<View*>(const_cast<NativeFrameView*>(this)), client_bounds);

to:

  gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(client_bounds);
  pixel_bounds = views::GetWindowBoundsForClientBounds(
      static_cast<View*>(const_cast<NativeFrameView*>(this)), pixel_bounds);
  return gfx::win::ScreenToDIPRect(pixel_bounds);

fixes the problem for me on Windows.

I wonder, though, if perhaps we shouldn't be using the Screen/DIP methods from ui/gfx/win/dpi.h since they don't account for multiple monitors with different scale factors (presuming such a thing is possible on Windows?)
The Screen/DIP methods will account for multiple monitors in the future and such a thing is possible in Windows 8.1 and later.

 http://crbug.com/426656  covers the multiple DPI support work.
Status: Archived (was: Untriaged)
Archiving old bugs that haven't been modified in over two years. 

If you feel this issue should still be addressed, feel free to reopen it or to file a new issue. Thanks!

Sign in to add a comment