Windows: Add per-monitor DPI support (issue #2313)
This commit is contained in:
parent
57fb011377
commit
57b9cf9ddd
|
@ -4,12 +4,6 @@
|
|||
|
||||
#include "include/base/cef_build.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
|
||||
#include <shellscalingapi.h>
|
||||
#endif
|
||||
|
||||
#include "include/internal/cef_logging_internal.h"
|
||||
#include "include/internal/cef_thread_internal.h"
|
||||
#include "include/internal/cef_trace_event_internal.h"
|
||||
|
@ -19,50 +13,8 @@
|
|||
#include "base/trace_event/trace_event.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "base/win/windows_version.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Implementation from chrome/app/chrome_exe_main_win.cc.
|
||||
|
||||
// Win8.1 supports monitor-specific DPI scaling.
|
||||
bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) {
|
||||
typedef HRESULT(WINAPI * SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS);
|
||||
SetProcessDpiAwarenessPtr set_process_dpi_awareness_func =
|
||||
reinterpret_cast<SetProcessDpiAwarenessPtr>(GetProcAddress(
|
||||
GetModuleHandleA("user32.dll"), "SetProcessDpiAwarenessInternal"));
|
||||
if (set_process_dpi_awareness_func) {
|
||||
HRESULT hr = set_process_dpi_awareness_func(value);
|
||||
if (SUCCEEDED(hr)) {
|
||||
VLOG(1) << "SetProcessDpiAwareness succeeded.";
|
||||
return true;
|
||||
} else if (hr == E_ACCESSDENIED) {
|
||||
LOG(ERROR) << "Access denied error from SetProcessDpiAwareness. "
|
||||
"Function called twice, or manifest was used.";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function works for Windows Vista through Win8. Win8.1 must use
|
||||
// SetProcessDpiAwareness[Wrapper].
|
||||
BOOL SetProcessDPIAwareWrapper() {
|
||||
typedef BOOL(WINAPI * SetProcessDPIAwarePtr)(VOID);
|
||||
SetProcessDPIAwarePtr set_process_dpi_aware_func =
|
||||
reinterpret_cast<SetProcessDPIAwarePtr>(
|
||||
GetProcAddress(GetModuleHandleA("user32.dll"), "SetProcessDPIAware"));
|
||||
return set_process_dpi_aware_func && set_process_dpi_aware_func();
|
||||
}
|
||||
|
||||
void EnableHighDPISupport() {
|
||||
if (!SetProcessDpiAwarenessWrapper(PROCESS_SYSTEM_DPI_AWARE)) {
|
||||
SetProcessDPIAwareWrapper();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // defined(OS_WIN)
|
||||
#include "base/win/win_util.h"
|
||||
#endif
|
||||
|
||||
// The contents of this file are a compilation unit that is not called by other
|
||||
// functions in the the library. Consiquently MSVS will exclude it during the
|
||||
|
@ -399,10 +351,6 @@ cef_get_current_platform_thread_handle() {
|
|||
|
||||
void CefEnableHighDPISupport() {
|
||||
#if defined(OS_WIN)
|
||||
// We don't want to set DPI awareness on pre-Win7 because we don't support
|
||||
// DirectWrite there. GDI fonts are kerned very badly, so better to leave
|
||||
// DPI-unaware and at effective 1.0. See also ShouldUseDirectWrite().
|
||||
if (base::win::GetVersion() >= base::win::VERSION_WIN7)
|
||||
EnableHighDPISupport();
|
||||
base::win::EnableHighDPISupport();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -5,16 +5,13 @@
|
|||
#include "tests/cefclient/browser/browser_window_osr_win.h"
|
||||
|
||||
#include "tests/shared/browser/main_message_loop.h"
|
||||
#include "tests/shared/browser/util_win.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
BrowserWindowOsrWin::BrowserWindowOsrWin(BrowserWindow::Delegate* delegate,
|
||||
const std::string& startup_url,
|
||||
const OsrRenderer::Settings& settings)
|
||||
: BrowserWindow(delegate),
|
||||
osr_hwnd_(NULL),
|
||||
device_scale_factor_(client::GetDeviceScaleFactor()) {
|
||||
: BrowserWindow(delegate), osr_hwnd_(NULL), device_scale_factor_(0) {
|
||||
osr_window_ = new OsrWindowWin(this, settings);
|
||||
client_handler_ = new ClientHandlerOsr(this, osr_window_.get(), startup_url);
|
||||
}
|
||||
|
@ -92,6 +89,7 @@ void BrowserWindowOsrWin::SetDeviceScaleFactor(float device_scale_factor) {
|
|||
|
||||
float BrowserWindowOsrWin::GetDeviceScaleFactor() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK_GT(device_scale_factor_, 0);
|
||||
return device_scale_factor_;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ OsrWindowWin::OsrWindowWin(Delegate* delegate,
|
|||
hwnd_(NULL),
|
||||
hdc_(NULL),
|
||||
hrc_(NULL),
|
||||
device_scale_factor_(client::GetDeviceScaleFactor()),
|
||||
device_scale_factor_(0),
|
||||
painting_popup_(false),
|
||||
render_task_pending_(false),
|
||||
hidden_(false),
|
||||
|
@ -872,6 +872,7 @@ bool OsrWindowWin::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
|||
|
||||
bool OsrWindowWin::GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK_GT(device_scale_factor_, 0);
|
||||
|
||||
rect.x = rect.y = 0;
|
||||
rect.width = DeviceToLogical(client_rect_.right - client_rect_.left,
|
||||
|
@ -887,6 +888,7 @@ bool OsrWindowWin::GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
|||
int& screenX,
|
||||
int& screenY) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK_GT(device_scale_factor_, 0);
|
||||
|
||||
if (!::IsWindow(hwnd_))
|
||||
return false;
|
||||
|
@ -903,6 +905,7 @@ bool OsrWindowWin::GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
|||
bool OsrWindowWin::GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
||||
CefScreenInfo& screen_info) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK_GT(device_scale_factor_, 0);
|
||||
|
||||
if (!::IsWindow(hwnd_))
|
||||
return false;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "tests/cefclient/browser/root_window_win.h"
|
||||
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/cef_app.h"
|
||||
|
@ -46,30 +48,55 @@ INT_PTR CALLBACK AboutWndProc(HWND hDlg,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
int GetButtonWidth() {
|
||||
static int button_width = BUTTON_WIDTH;
|
||||
static bool initialized = false;
|
||||
|
||||
if (!initialized) {
|
||||
button_width =
|
||||
LogicalToDevice(BUTTON_WIDTH, client::GetDeviceScaleFactor());
|
||||
initialized = true;
|
||||
// Returns true if the process is per monitor DPI aware.
|
||||
bool IsProcessPerMonitorDpiAware() {
|
||||
enum class PerMonitorDpiAware {
|
||||
UNKNOWN = 0,
|
||||
PER_MONITOR_DPI_UNAWARE,
|
||||
PER_MONITOR_DPI_AWARE,
|
||||
};
|
||||
static PerMonitorDpiAware per_monitor_dpi_aware = PerMonitorDpiAware::UNKNOWN;
|
||||
if (per_monitor_dpi_aware == PerMonitorDpiAware::UNKNOWN) {
|
||||
per_monitor_dpi_aware = PerMonitorDpiAware::PER_MONITOR_DPI_UNAWARE;
|
||||
HMODULE shcore_dll = ::LoadLibrary(L"shcore.dll");
|
||||
if (shcore_dll) {
|
||||
typedef HRESULT(WINAPI * GetProcessDpiAwarenessPtr)(
|
||||
HANDLE, PROCESS_DPI_AWARENESS*);
|
||||
GetProcessDpiAwarenessPtr func_ptr =
|
||||
reinterpret_cast<GetProcessDpiAwarenessPtr>(
|
||||
::GetProcAddress(shcore_dll, "GetProcessDpiAwareness"));
|
||||
if (func_ptr) {
|
||||
PROCESS_DPI_AWARENESS awareness;
|
||||
if (SUCCEEDED(func_ptr(nullptr, &awareness)) &&
|
||||
awareness == PROCESS_PER_MONITOR_DPI_AWARE)
|
||||
per_monitor_dpi_aware = PerMonitorDpiAware::PER_MONITOR_DPI_AWARE;
|
||||
}
|
||||
|
||||
return button_width;
|
||||
}
|
||||
}
|
||||
return per_monitor_dpi_aware == PerMonitorDpiAware::PER_MONITOR_DPI_AWARE;
|
||||
}
|
||||
|
||||
int GetURLBarHeight() {
|
||||
static int urlbar_height = URLBAR_HEIGHT;
|
||||
static bool initialized = false;
|
||||
// DPI value for 1x scale factor.
|
||||
#define DPI_1X 96
|
||||
|
||||
if (!initialized) {
|
||||
urlbar_height =
|
||||
LogicalToDevice(URLBAR_HEIGHT, client::GetDeviceScaleFactor());
|
||||
initialized = true;
|
||||
int GetWindowScaleFactor(HWND hwnd) {
|
||||
if (hwnd && IsProcessPerMonitorDpiAware()) {
|
||||
typedef UINT(WINAPI * GetDpiForWindowPtr)(HWND);
|
||||
static GetDpiForWindowPtr func_ptr = reinterpret_cast<GetDpiForWindowPtr>(
|
||||
GetProcAddress(GetModuleHandle(L"user32.dll"), "GetDpiForWindow"));
|
||||
if (func_ptr)
|
||||
return func_ptr(hwnd) / DPI_1X;
|
||||
}
|
||||
|
||||
return urlbar_height;
|
||||
return client::GetDeviceScaleFactor();
|
||||
}
|
||||
|
||||
int GetButtonWidth(HWND hwnd) {
|
||||
return LogicalToDevice(BUTTON_WIDTH, GetWindowScaleFactor(hwnd));
|
||||
}
|
||||
|
||||
int GetURLBarHeight(HWND hwnd) {
|
||||
return LogicalToDevice(URLBAR_HEIGHT, GetWindowScaleFactor(hwnd));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -84,6 +111,7 @@ RootWindowWin::RootWindowWin()
|
|||
hwnd_(NULL),
|
||||
draggable_region_(NULL),
|
||||
font_(NULL),
|
||||
font_height_(0),
|
||||
back_hwnd_(NULL),
|
||||
forward_hwnd_(NULL),
|
||||
reload_hwnd_(NULL),
|
||||
|
@ -97,7 +125,8 @@ RootWindowWin::RootWindowWin()
|
|||
find_next_(false),
|
||||
find_match_case_last_(false),
|
||||
window_destroyed_(false),
|
||||
browser_destroyed_(false) {
|
||||
browser_destroyed_(false),
|
||||
called_enable_non_client_dpi_scaling_(false) {
|
||||
find_buff_[0] = 0;
|
||||
|
||||
// Create a HRGN representing the draggable window area.
|
||||
|
@ -313,8 +342,6 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings,
|
|||
// Adjust the window size to account for window frame and controls.
|
||||
RECT window_rect = start_rect_;
|
||||
::AdjustWindowRectEx(&window_rect, dwStyle, with_controls_, 0);
|
||||
if (with_controls_)
|
||||
window_rect.bottom += GetURLBarHeight();
|
||||
|
||||
x = start_rect_.left;
|
||||
y = start_rect_.top;
|
||||
|
@ -322,110 +349,23 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings,
|
|||
height = window_rect.bottom - window_rect.top;
|
||||
}
|
||||
|
||||
browser_settings_ = settings;
|
||||
|
||||
// Create the main window initially hidden.
|
||||
hwnd_ = CreateWindow(window_class.c_str(), window_title.c_str(), dwStyle, x,
|
||||
y, width, height, NULL, NULL, hInstance, NULL);
|
||||
CreateWindow(window_class.c_str(), window_title.c_str(), dwStyle, x, y, width,
|
||||
height, NULL, NULL, hInstance, this);
|
||||
CHECK(hwnd_);
|
||||
|
||||
// Associate |this| with the main window.
|
||||
SetUserDataPtr(hwnd_, this);
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(hwnd_, &rect);
|
||||
|
||||
if (with_controls_) {
|
||||
// Create the child controls.
|
||||
int x_offset = 0;
|
||||
|
||||
const int button_width = GetButtonWidth();
|
||||
const int urlbar_height = GetURLBarHeight();
|
||||
const int font_height = LogicalToDevice(14, client::GetDeviceScaleFactor());
|
||||
|
||||
// Create a scaled font.
|
||||
font_ =
|
||||
::CreateFont(-font_height, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
|
||||
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
||||
DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial");
|
||||
|
||||
back_hwnd_ = CreateWindow(
|
||||
L"BUTTON", L"Back", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_DISABLED,
|
||||
x_offset, 0, button_width, urlbar_height, hwnd_,
|
||||
reinterpret_cast<HMENU>(IDC_NAV_BACK), hInstance, 0);
|
||||
CHECK(back_hwnd_);
|
||||
SendMessage(back_hwnd_, WM_SETFONT, reinterpret_cast<WPARAM>(font_), TRUE);
|
||||
x_offset += button_width;
|
||||
|
||||
forward_hwnd_ =
|
||||
CreateWindow(L"BUTTON", L"Forward",
|
||||
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_DISABLED,
|
||||
x_offset, 0, button_width, urlbar_height, hwnd_,
|
||||
reinterpret_cast<HMENU>(IDC_NAV_FORWARD), hInstance, 0);
|
||||
CHECK(forward_hwnd_);
|
||||
SendMessage(forward_hwnd_, WM_SETFONT, reinterpret_cast<WPARAM>(font_),
|
||||
TRUE);
|
||||
x_offset += button_width;
|
||||
|
||||
reload_hwnd_ =
|
||||
CreateWindow(L"BUTTON", L"Reload",
|
||||
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_DISABLED,
|
||||
x_offset, 0, button_width, urlbar_height, hwnd_,
|
||||
reinterpret_cast<HMENU>(IDC_NAV_RELOAD), hInstance, 0);
|
||||
CHECK(reload_hwnd_);
|
||||
SendMessage(reload_hwnd_, WM_SETFONT, reinterpret_cast<WPARAM>(font_),
|
||||
TRUE);
|
||||
x_offset += button_width;
|
||||
|
||||
stop_hwnd_ = CreateWindow(
|
||||
L"BUTTON", L"Stop", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_DISABLED,
|
||||
x_offset, 0, button_width, urlbar_height, hwnd_,
|
||||
reinterpret_cast<HMENU>(IDC_NAV_STOP), hInstance, 0);
|
||||
CHECK(stop_hwnd_);
|
||||
SendMessage(stop_hwnd_, WM_SETFONT, reinterpret_cast<WPARAM>(font_), TRUE);
|
||||
x_offset += button_width;
|
||||
|
||||
edit_hwnd_ = CreateWindow(L"EDIT", 0,
|
||||
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT |
|
||||
ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_DISABLED,
|
||||
x_offset, 0, rect.right - button_width * 4,
|
||||
urlbar_height, hwnd_, 0, hInstance, 0);
|
||||
SendMessage(edit_hwnd_, WM_SETFONT, reinterpret_cast<WPARAM>(font_), TRUE);
|
||||
CHECK(edit_hwnd_);
|
||||
|
||||
// Override the edit control's window procedure.
|
||||
edit_wndproc_old_ = SetWndProcPtr(edit_hwnd_, EditWndProc);
|
||||
|
||||
// Associate |this| with the edit window.
|
||||
SetUserDataPtr(edit_hwnd_, this);
|
||||
|
||||
rect.top += urlbar_height;
|
||||
|
||||
if (!with_osr_) {
|
||||
// Remove the menu items that are only used with OSR.
|
||||
HMENU hMenu = ::GetMenu(hwnd_);
|
||||
if (hMenu) {
|
||||
HMENU hTestMenu = ::GetSubMenu(hMenu, 2);
|
||||
if (hTestMenu) {
|
||||
::RemoveMenu(hTestMenu, ID_TESTS_OSR_FPS, MF_BYCOMMAND);
|
||||
::RemoveMenu(hTestMenu, ID_TESTS_OSR_DSF, MF_BYCOMMAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No controls so also remove the default menu.
|
||||
::SetMenu(hwnd_, NULL);
|
||||
}
|
||||
|
||||
if (!is_popup_) {
|
||||
// Create the browser window.
|
||||
CefRect cef_rect(rect.left, rect.top, rect.right - rect.left,
|
||||
rect.bottom - rect.top);
|
||||
browser_window_->CreateBrowser(hwnd_, cef_rect, settings,
|
||||
delegate_->GetRequestContext(this));
|
||||
} else {
|
||||
// With popups we already have a browser window. Parent the browser window
|
||||
// to the root window and show it in the correct location.
|
||||
browser_window_->ShowPopup(hwnd_, rect.left, rect.top,
|
||||
rect.right - rect.left, rect.bottom - rect.top);
|
||||
if (!called_enable_non_client_dpi_scaling_ && IsProcessPerMonitorDpiAware()) {
|
||||
// This call gets Windows to scale the non-client area when WM_DPICHANGED
|
||||
// is fired on Windows versions < 10.0.14393.0.
|
||||
// Derived signature; not available in headers.
|
||||
typedef LRESULT(WINAPI * EnableChildWindowDpiMessagePtr)(HWND, BOOL);
|
||||
static EnableChildWindowDpiMessagePtr func_ptr =
|
||||
reinterpret_cast<EnableChildWindowDpiMessagePtr>(GetProcAddress(
|
||||
GetModuleHandle(L"user32.dll"), "EnableChildWindowDpiMessage"));
|
||||
if (func_ptr)
|
||||
func_ptr(hwnd_, TRUE);
|
||||
}
|
||||
|
||||
if (!initially_hidden) {
|
||||
|
@ -535,12 +475,15 @@ LRESULT CALLBACK RootWindowWin::RootWndProc(HWND hWnd,
|
|||
LPARAM lParam) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
RootWindowWin* self = GetUserDataPtr<RootWindowWin*>(hWnd);
|
||||
RootWindowWin* self = NULL;
|
||||
if (message != WM_NCCREATE) {
|
||||
self = GetUserDataPtr<RootWindowWin*>(hWnd);
|
||||
if (!self)
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
DCHECK(hWnd == self->hwnd_);
|
||||
DCHECK_EQ(hWnd, self->hwnd_);
|
||||
}
|
||||
|
||||
if (message == self->find_message_id_) {
|
||||
if (self && message == self->find_message_id_) {
|
||||
// Message targeting the find dialog.
|
||||
LPFINDREPLACE lpfr = reinterpret_cast<LPFINDREPLACE>(lParam);
|
||||
CHECK(lpfr == &self->find_state_);
|
||||
|
@ -589,6 +532,10 @@ LRESULT CALLBACK RootWindowWin::RootWndProc(HWND hWnd,
|
|||
self->OnMove();
|
||||
return 0;
|
||||
|
||||
case WM_DPICHANGED:
|
||||
self->OnDpiChanged(wParam, lParam);
|
||||
break;
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
if (self->OnEraseBkgnd())
|
||||
break;
|
||||
|
@ -629,6 +576,21 @@ LRESULT CALLBACK RootWindowWin::RootWndProc(HWND hWnd,
|
|||
return hit;
|
||||
}
|
||||
|
||||
case WM_NCCREATE: {
|
||||
CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lParam);
|
||||
self = reinterpret_cast<RootWindowWin*>(cs->lpCreateParams);
|
||||
DCHECK(self);
|
||||
// Associate |self| with the main window.
|
||||
SetUserDataPtr(hWnd, self);
|
||||
self->hwnd_ = hWnd;
|
||||
|
||||
self->OnNCCreate(cs);
|
||||
} break;
|
||||
|
||||
case WM_CREATE:
|
||||
self->OnCreate(reinterpret_cast<CREATESTRUCT*>(lParam));
|
||||
break;
|
||||
|
||||
case WM_NCDESTROY:
|
||||
// Clear the reference to |self|.
|
||||
SetUserDataPtr(hWnd, NULL);
|
||||
|
@ -670,37 +632,70 @@ void RootWindowWin::OnSize(bool minimized) {
|
|||
RECT rect;
|
||||
GetClientRect(hwnd_, &rect);
|
||||
|
||||
if (with_controls_) {
|
||||
static int button_width = GetButtonWidth();
|
||||
static int urlbar_height = GetURLBarHeight();
|
||||
if (with_controls_ && edit_hwnd_) {
|
||||
const int button_width = GetButtonWidth(hwnd_);
|
||||
const int urlbar_height = GetURLBarHeight(hwnd_);
|
||||
const int font_height = LogicalToDevice(14, GetWindowScaleFactor(hwnd_));
|
||||
|
||||
if (font_height != font_height_) {
|
||||
if (font_) {
|
||||
DeleteObject(font_);
|
||||
}
|
||||
|
||||
// Create a scaled font.
|
||||
font_ =
|
||||
::CreateFont(-font_height, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
|
||||
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
||||
DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial");
|
||||
|
||||
SendMessage(back_hwnd_, WM_SETFONT, reinterpret_cast<WPARAM>(font_),
|
||||
TRUE);
|
||||
SendMessage(forward_hwnd_, WM_SETFONT, reinterpret_cast<WPARAM>(font_),
|
||||
TRUE);
|
||||
SendMessage(reload_hwnd_, WM_SETFONT, reinterpret_cast<WPARAM>(font_),
|
||||
TRUE);
|
||||
SendMessage(stop_hwnd_, WM_SETFONT, reinterpret_cast<WPARAM>(font_),
|
||||
TRUE);
|
||||
SendMessage(edit_hwnd_, WM_SETFONT, reinterpret_cast<WPARAM>(font_),
|
||||
TRUE);
|
||||
}
|
||||
|
||||
// Resize the window and address bar to match the new frame size.
|
||||
rect.top += urlbar_height;
|
||||
|
||||
int urloffset = rect.left + button_width * 4;
|
||||
int x_offset = rect.left;
|
||||
|
||||
// |browser_hwnd| may be NULL if the browser has not yet been created.
|
||||
HWND browser_hwnd = NULL;
|
||||
if (browser_window_)
|
||||
browser_hwnd = browser_window_->GetWindowHandle();
|
||||
|
||||
// Resize all controls.
|
||||
HDWP hdwp = BeginDeferWindowPos(browser_hwnd ? 6 : 5);
|
||||
hdwp = DeferWindowPos(hdwp, back_hwnd_, NULL, x_offset, 0, button_width,
|
||||
urlbar_height, SWP_NOZORDER);
|
||||
x_offset += button_width;
|
||||
hdwp = DeferWindowPos(hdwp, forward_hwnd_, NULL, x_offset, 0, button_width,
|
||||
urlbar_height, SWP_NOZORDER);
|
||||
x_offset += button_width;
|
||||
hdwp = DeferWindowPos(hdwp, reload_hwnd_, NULL, x_offset, 0, button_width,
|
||||
urlbar_height, SWP_NOZORDER);
|
||||
x_offset += button_width;
|
||||
hdwp = DeferWindowPos(hdwp, stop_hwnd_, NULL, x_offset, 0, button_width,
|
||||
urlbar_height, SWP_NOZORDER);
|
||||
x_offset += button_width;
|
||||
hdwp = DeferWindowPos(hdwp, edit_hwnd_, NULL, x_offset, 0,
|
||||
rect.right - x_offset, urlbar_height, SWP_NOZORDER);
|
||||
|
||||
if (browser_hwnd) {
|
||||
// Resize both the browser and the URL edit field.
|
||||
HDWP hdwp = BeginDeferWindowPos(2);
|
||||
hdwp =
|
||||
DeferWindowPos(hdwp, edit_hwnd_, NULL, urloffset, 0,
|
||||
rect.right - urloffset, urlbar_height, SWP_NOZORDER);
|
||||
hdwp = DeferWindowPos(hdwp, browser_hwnd, NULL, rect.left, rect.top,
|
||||
rect.right - rect.left, rect.bottom - rect.top,
|
||||
SWP_NOZORDER);
|
||||
}
|
||||
|
||||
BOOL result = EndDeferWindowPos(hdwp);
|
||||
ALLOW_UNUSED_LOCAL(result);
|
||||
DCHECK(result);
|
||||
} else {
|
||||
// Resize just the URL edit field.
|
||||
SetWindowPos(edit_hwnd_, NULL, urloffset, 0, rect.right - urloffset,
|
||||
urlbar_height, SWP_NOZORDER);
|
||||
}
|
||||
} else if (browser_window_) {
|
||||
// Size the browser window to the whole client area.
|
||||
browser_window_->SetBounds(0, 0, rect.right, rect.bottom);
|
||||
|
@ -715,6 +710,32 @@ void RootWindowWin::OnMove() {
|
|||
browser->GetHost()->NotifyMoveOrResizeStarted();
|
||||
}
|
||||
|
||||
void RootWindowWin::OnDpiChanged(WPARAM wParam, LPARAM lParam) {
|
||||
if (LOWORD(wParam) != HIWORD(wParam)) {
|
||||
NOTIMPLEMENTED() << "Received non-square scaling factors";
|
||||
return;
|
||||
}
|
||||
|
||||
if (browser_window_) {
|
||||
if (with_osr_) {
|
||||
browser_window_->SetDeviceScaleFactor(LOWORD(wParam) / DPI_1X);
|
||||
} else {
|
||||
// Forward the DPI change to the browser window handle.
|
||||
HWND browser_hwnd = browser_window_->GetWindowHandle();
|
||||
if (browser_hwnd) {
|
||||
RECT child_rect = {};
|
||||
SendMessage(browser_hwnd, WM_DPICHANGED, wParam,
|
||||
reinterpret_cast<LPARAM>(&child_rect));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Suggested size and position of the current window scaled for the new DPI.
|
||||
const RECT* rect = reinterpret_cast<RECT*>(lParam);
|
||||
SetBounds(rect->left, rect->top, rect->right - rect->left,
|
||||
rect->bottom - rect->top);
|
||||
}
|
||||
|
||||
bool RootWindowWin::OnEraseBkgnd() {
|
||||
// Erase the background when the browser does not exist.
|
||||
return (GetBrowser() == NULL);
|
||||
|
@ -821,6 +842,113 @@ void RootWindowWin::OnAbout() {
|
|||
AboutWndProc);
|
||||
}
|
||||
|
||||
void RootWindowWin::OnNCCreate(LPCREATESTRUCT lpCreateStruct) {
|
||||
if (IsProcessPerMonitorDpiAware()) {
|
||||
// This call gets Windows to scale the non-client area when WM_DPICHANGED
|
||||
// is fired on Windows versions >= 10.0.14393.0.
|
||||
typedef BOOL(WINAPI * EnableNonClientDpiScalingPtr)(HWND);
|
||||
static EnableNonClientDpiScalingPtr func_ptr =
|
||||
reinterpret_cast<EnableNonClientDpiScalingPtr>(GetProcAddress(
|
||||
GetModuleHandle(L"user32.dll"), "EnableNonClientDpiScaling"));
|
||||
called_enable_non_client_dpi_scaling_ = !!(func_ptr && func_ptr(hwnd_));
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowWin::OnCreate(LPCREATESTRUCT lpCreateStruct) {
|
||||
const HINSTANCE hInstance = lpCreateStruct->hInstance;
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(hwnd_, &rect);
|
||||
|
||||
if (with_controls_) {
|
||||
// Create the child controls.
|
||||
int x_offset = 0;
|
||||
|
||||
const int button_width = GetButtonWidth(hwnd_);
|
||||
const int urlbar_height = GetURLBarHeight(hwnd_);
|
||||
|
||||
back_hwnd_ = CreateWindow(
|
||||
L"BUTTON", L"Back", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_DISABLED,
|
||||
x_offset, 0, button_width, urlbar_height, hwnd_,
|
||||
reinterpret_cast<HMENU>(IDC_NAV_BACK), hInstance, 0);
|
||||
CHECK(back_hwnd_);
|
||||
x_offset += button_width;
|
||||
|
||||
forward_hwnd_ =
|
||||
CreateWindow(L"BUTTON", L"Forward",
|
||||
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_DISABLED,
|
||||
x_offset, 0, button_width, urlbar_height, hwnd_,
|
||||
reinterpret_cast<HMENU>(IDC_NAV_FORWARD), hInstance, 0);
|
||||
CHECK(forward_hwnd_);
|
||||
x_offset += button_width;
|
||||
|
||||
reload_hwnd_ =
|
||||
CreateWindow(L"BUTTON", L"Reload",
|
||||
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_DISABLED,
|
||||
x_offset, 0, button_width, urlbar_height, hwnd_,
|
||||
reinterpret_cast<HMENU>(IDC_NAV_RELOAD), hInstance, 0);
|
||||
CHECK(reload_hwnd_);
|
||||
x_offset += button_width;
|
||||
|
||||
stop_hwnd_ = CreateWindow(
|
||||
L"BUTTON", L"Stop", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_DISABLED,
|
||||
x_offset, 0, button_width, urlbar_height, hwnd_,
|
||||
reinterpret_cast<HMENU>(IDC_NAV_STOP), hInstance, 0);
|
||||
CHECK(stop_hwnd_);
|
||||
x_offset += button_width;
|
||||
|
||||
edit_hwnd_ = CreateWindow(L"EDIT", 0,
|
||||
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT |
|
||||
ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_DISABLED,
|
||||
x_offset, 0, rect.right - button_width * 4,
|
||||
urlbar_height, hwnd_, 0, hInstance, 0);
|
||||
CHECK(edit_hwnd_);
|
||||
|
||||
// Override the edit control's window procedure.
|
||||
edit_wndproc_old_ = SetWndProcPtr(edit_hwnd_, EditWndProc);
|
||||
|
||||
// Associate |this| with the edit window.
|
||||
SetUserDataPtr(edit_hwnd_, this);
|
||||
|
||||
rect.top += urlbar_height;
|
||||
|
||||
if (!with_osr_) {
|
||||
// Remove the menu items that are only used with OSR.
|
||||
HMENU hMenu = ::GetMenu(hwnd_);
|
||||
if (hMenu) {
|
||||
HMENU hTestMenu = ::GetSubMenu(hMenu, 2);
|
||||
if (hTestMenu) {
|
||||
::RemoveMenu(hTestMenu, ID_TESTS_OSR_FPS, MF_BYCOMMAND);
|
||||
::RemoveMenu(hTestMenu, ID_TESTS_OSR_DSF, MF_BYCOMMAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No controls so also remove the default menu.
|
||||
::SetMenu(hwnd_, NULL);
|
||||
}
|
||||
|
||||
const int device_scale_factor = GetWindowScaleFactor(hwnd_);
|
||||
|
||||
if (with_osr_) {
|
||||
browser_window_->SetDeviceScaleFactor(device_scale_factor);
|
||||
}
|
||||
|
||||
if (!is_popup_) {
|
||||
// Create the browser window.
|
||||
CefRect cef_rect(rect.left, rect.top, rect.right - rect.left,
|
||||
rect.bottom - rect.top);
|
||||
cef_rect = client::DeviceToLogical(cef_rect, device_scale_factor);
|
||||
browser_window_->CreateBrowser(hwnd_, cef_rect, browser_settings_,
|
||||
delegate_->GetRequestContext(this));
|
||||
} else {
|
||||
// With popups we already have a browser window. Parent the browser window
|
||||
// to the root window and show it in the correct location.
|
||||
browser_window_->ShowPopup(hwnd_, rect.left, rect.top,
|
||||
rect.right - rect.left, rect.bottom - rect.top);
|
||||
}
|
||||
}
|
||||
|
||||
bool RootWindowWin::OnClose() {
|
||||
if (browser_window_ && !browser_window_->IsClosing()) {
|
||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
||||
|
@ -915,9 +1043,9 @@ void RootWindowWin::OnAutoResize(const CefSize& new_size) {
|
|||
if (new_width < 200)
|
||||
new_width = 200;
|
||||
|
||||
RECT rect = {
|
||||
0, 0, LogicalToDevice(new_width, client::GetDeviceScaleFactor()),
|
||||
LogicalToDevice(new_size.height, client::GetDeviceScaleFactor())};
|
||||
const int device_scale_factor = GetWindowScaleFactor(hwnd_);
|
||||
RECT rect = {0, 0, LogicalToDevice(new_width, device_scale_factor),
|
||||
LogicalToDevice(new_size.height, device_scale_factor)};
|
||||
DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
|
||||
DWORD ex_style = GetWindowLong(hwnd_, GWL_EXSTYLE);
|
||||
bool has_menu = !(style & WS_CHILD) && (GetMenu(hwnd_) != NULL);
|
||||
|
|
|
@ -83,11 +83,14 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
|||
void OnActivate(bool active);
|
||||
void OnSize(bool minimized);
|
||||
void OnMove();
|
||||
void OnDpiChanged(WPARAM wParam, LPARAM lParam);
|
||||
bool OnEraseBkgnd();
|
||||
bool OnCommand(UINT id);
|
||||
void OnFind();
|
||||
void OnFindEvent();
|
||||
void OnAbout();
|
||||
void OnNCCreate(LPCREATESTRUCT lpCreateStruct);
|
||||
void OnCreate(LPCREATESTRUCT lpCreateStruct);
|
||||
bool OnClose();
|
||||
void OnDestroyed();
|
||||
|
||||
|
@ -114,6 +117,7 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
|||
bool is_popup_;
|
||||
RECT start_rect_;
|
||||
scoped_ptr<BrowserWindow> browser_window_;
|
||||
CefBrowserSettings browser_settings_;
|
||||
bool initialized_;
|
||||
|
||||
// Main window.
|
||||
|
@ -124,6 +128,7 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
|||
|
||||
// Font for buttons and text fields.
|
||||
HFONT font_;
|
||||
int font_height_;
|
||||
|
||||
// Buttons.
|
||||
HWND back_hwnd_;
|
||||
|
@ -150,6 +155,8 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
|||
bool window_destroyed_;
|
||||
bool browser_destroyed_;
|
||||
|
||||
bool called_enable_non_client_dpi_scaling_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RootWindowWin);
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,13 @@ int DeviceToLogical(int value, float device_scale_factor) {
|
|||
return static_cast<int>(std::floor(scaled_val));
|
||||
}
|
||||
|
||||
CefRect DeviceToLogical(const CefRect& value, float device_scale_factor) {
|
||||
return CefRect(DeviceToLogical(value.x, device_scale_factor),
|
||||
DeviceToLogical(value.y, device_scale_factor),
|
||||
DeviceToLogical(value.width, device_scale_factor),
|
||||
DeviceToLogical(value.height, device_scale_factor));
|
||||
}
|
||||
|
||||
void DeviceToLogical(CefMouseEvent& value, float device_scale_factor) {
|
||||
value.x = DeviceToLogical(value.x, device_scale_factor);
|
||||
value.y = DeviceToLogical(value.y, device_scale_factor);
|
||||
|
|
|
@ -16,6 +16,7 @@ CefRect LogicalToDevice(const CefRect& value, float device_scale_factor);
|
|||
|
||||
// Convert |value| from device coordinates to logical coordinates.
|
||||
int DeviceToLogical(int value, float device_scale_factor);
|
||||
CefRect DeviceToLogical(const CefRect& value, float device_scale_factor);
|
||||
void DeviceToLogical(CefMouseEvent& value, float device_scale_factor);
|
||||
|
||||
} // namespace client
|
||||
|
|
Loading…
Reference in New Issue