Windows: Use WS_EX_NOACTIVATE to control initial window activation (issue #1856)

This commit is contained in:
Marshall Greenblatt 2019-02-07 16:36:31 -05:00
parent 84a5749f9f
commit b8eaec0db2
10 changed files with 107 additions and 7 deletions

View File

@ -207,8 +207,27 @@ bool CefBrowserPlatformDelegateNativeWin::CreateHostWindow() {
gfx::Rect(0, 0, point.x(), point.y())); gfx::Rect(0, 0, point.x(), point.y()));
window_widget_ = delegate_view->GetWidget(); window_widget_ = delegate_view->GetWidget();
const HWND widget_hwnd = HWNDForWidget(window_widget_);
DCHECK(widget_hwnd);
const DWORD widget_ex_styles = GetWindowLongPtr(widget_hwnd, GWL_EXSTYLE);
if (window_info_.ex_style & WS_EX_NOACTIVATE) {
// Add the WS_EX_NOACTIVATE style on the DesktopWindowTreeHostWin HWND
// so that HWNDMessageHandler::Show() called via Widget::Show() does not
// activate the window.
SetWindowLongPtr(widget_hwnd, GWL_EXSTYLE,
widget_ex_styles | WS_EX_NOACTIVATE);
}
window_widget_->Show(); window_widget_->Show();
if (window_info_.ex_style & WS_EX_NOACTIVATE) {
// Remove the WS_EX_NOACTIVATE style so that future mouse clicks inside the
// browser correctly activate and focus the window.
SetWindowLongPtr(widget_hwnd, GWL_EXSTYLE, widget_ex_styles);
}
return true; return true;
} }

View File

@ -41,6 +41,9 @@ void BrowserWindowOsrWin::GetPopupConfig(CefWindowHandle temp_handle,
windowInfo.external_begin_frame_enabled = windowInfo.external_begin_frame_enabled =
osr_window_->settings().external_begin_frame_enabled; osr_window_->settings().external_begin_frame_enabled;
// Don't activate the hidden browser on creation.
windowInfo.ex_style |= WS_EX_NOACTIVATE;
client = client_handler_; client = client_handler_;
} }

View File

@ -26,6 +26,11 @@ void BrowserWindowStdWin::CreateBrowser(
RECT wnd_rect = {rect.x, rect.y, rect.x + rect.width, rect.y + rect.height}; RECT wnd_rect = {rect.x, rect.y, rect.x + rect.width, rect.y + rect.height};
window_info.SetAsChild(parent_handle, wnd_rect); window_info.SetAsChild(parent_handle, wnd_rect);
if (GetWindowLongPtr(parent_handle, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
// Don't activate the browser window on creation.
window_info.ex_style |= WS_EX_NOACTIVATE;
}
CefBrowserHost::CreateBrowser(window_info, client_handler_, CefBrowserHost::CreateBrowser(window_info, client_handler_,
client_handler_->startup_url(), settings, client_handler_->startup_url(), settings,
request_context); request_context);
@ -39,6 +44,10 @@ void BrowserWindowStdWin::GetPopupConfig(CefWindowHandle temp_handle,
// The window will be properly sized after the browser is created. // The window will be properly sized after the browser is created.
windowInfo.SetAsChild(temp_handle, RECT()); windowInfo.SetAsChild(temp_handle, RECT());
// Don't activate the hidden browser window on creation.
windowInfo.ex_style |= WS_EX_NOACTIVATE;
client = client_handler_; client = client_handler_;
} }
@ -53,8 +62,11 @@ void BrowserWindowStdWin::ShowPopup(ClientWindowHandle parent_handle,
if (hwnd) { if (hwnd) {
SetParent(hwnd, parent_handle); SetParent(hwnd, parent_handle);
SetWindowPos(hwnd, NULL, x, y, static_cast<int>(width), SetWindowPos(hwnd, NULL, x, y, static_cast<int>(width),
static_cast<int>(height), SWP_NOZORDER); static_cast<int>(height), SWP_NOZORDER | SWP_NOACTIVATE);
ShowWindow(hwnd, SW_SHOW);
const bool no_activate =
GetWindowLongPtr(parent_handle, GWL_EXSTYLE) & WS_EX_NOACTIVATE;
ShowWindow(hwnd, no_activate ? SW_SHOWNOACTIVATE : SW_SHOW);
} }
} }

View File

@ -249,7 +249,8 @@ ClientHandler::ClientHandler(Delegate* delegate,
browser_count_(0), browser_count_(0),
console_log_file_(MainContext::Get()->GetConsoleLogPath()), console_log_file_(MainContext::Get()->GetConsoleLogPath()),
first_console_message_(true), first_console_message_(true),
focus_on_editable_field_(false) { focus_on_editable_field_(false),
initial_navigation_(true) {
DCHECK(!console_log_file_.empty()); DCHECK(!console_log_file_.empty());
#if defined(OS_LINUX) #if defined(OS_LINUX)
@ -497,6 +498,22 @@ void ClientHandler::OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) {
NotifyTakeFocus(next); NotifyTakeFocus(next);
} }
bool ClientHandler::OnSetFocus(CefRefPtr<CefBrowser> browser,
FocusSource source) {
CEF_REQUIRE_UI_THREAD();
if (initial_navigation_) {
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
if (command_line->HasSwitch(switches::kNoActivate)) {
// Don't give focus to the browser on creation.
return true;
}
}
return false;
}
bool ClientHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser, bool ClientHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event, const CefKeyEvent& event,
CefEventHandle os_event, CefEventHandle os_event,
@ -606,6 +623,10 @@ void ClientHandler::OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool canGoForward) { bool canGoForward) {
CEF_REQUIRE_UI_THREAD(); CEF_REQUIRE_UI_THREAD();
if (!isLoading && initial_navigation_) {
initial_navigation_ = false;
}
NotifyLoadingState(isLoading, canGoBack, canGoForward); NotifyLoadingState(isLoading, canGoBack, canGoForward);
} }

View File

@ -169,6 +169,7 @@ class ClientHandler : public CefClient,
// CefFocusHandler methods // CefFocusHandler methods
void OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) OVERRIDE; void OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) OVERRIDE;
bool OnSetFocus(CefRefPtr<CefBrowser> browser, FocusSource source) OVERRIDE;
// CefKeyboardHandler methods // CefKeyboardHandler methods
bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser, bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
@ -370,6 +371,9 @@ class ClientHandler : public CefClient,
// True if an editable field currently has focus. // True if an editable field currently has focus.
bool focus_on_editable_field_; bool focus_on_editable_field_;
// True for the initial navigation after browser creation.
bool initial_navigation_;
// Set of Handlers registered with the message router. // Set of Handlers registered with the message router.
MessageHandlerSet message_handler_set_; MessageHandlerSet message_handler_set_;

View File

@ -76,6 +76,11 @@ void OsrWindowWin::CreateBrowser(HWND parent_hwnd,
CefWindowInfo window_info; CefWindowInfo window_info;
window_info.SetAsWindowless(hwnd_); window_info.SetAsWindowless(hwnd_);
if (GetWindowLongPtr(parent_hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
// Don't activate the browser window on creation.
window_info.ex_style |= WS_EX_NOACTIVATE;
}
window_info.shared_texture_enabled = settings_.shared_texture_enabled; window_info.shared_texture_enabled = settings_.shared_texture_enabled;
window_info.external_begin_frame_enabled = window_info.external_begin_frame_enabled =
settings_.external_begin_frame_enabled; settings_.external_begin_frame_enabled;
@ -220,10 +225,16 @@ void OsrWindowWin::Create(HWND parent_hwnd, const RECT& rect) {
RegisterOsrClass(hInst, background_brush); RegisterOsrClass(hInst, background_brush);
DWORD ex_style = 0;
if (GetWindowLongPtr(parent_hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
// Don't activate the browser window on creation.
ex_style |= WS_EX_NOACTIVATE;
}
// Create the native window with a border so it's easier to visually identify // Create the native window with a border so it's easier to visually identify
// OSR windows. // OSR windows.
hwnd_ = ::CreateWindow( hwnd_ = ::CreateWindowEx(
kWndClass, 0, ex_style, kWndClass, 0,
WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
parent_hwnd, 0, hInst, 0); parent_hwnd, 0, hInst, 0);

View File

@ -150,6 +150,7 @@ class RootWindow
ShowNormal, ShowNormal,
ShowMinimized, ShowMinimized,
ShowMaximized, ShowMaximized,
ShowNoActivate,
}; };
// Show the window. // Show the window.

View File

@ -226,6 +226,9 @@ void RootWindowWin::Show(ShowMode mode) {
case ShowMaximized: case ShowMaximized:
nCmdShow = SW_SHOWMAXIMIZED; nCmdShow = SW_SHOWMAXIMIZED;
break; break;
case ShowNoActivate:
nCmdShow = SW_SHOWNOACTIVATE;
break;
default: default:
break; break;
} }
@ -334,8 +337,16 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings,
find_message_id_ = RegisterWindowMessage(FINDMSGSTRING); find_message_id_ = RegisterWindowMessage(FINDMSGSTRING);
CHECK(find_message_id_); CHECK(find_message_id_);
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
const bool no_activate = command_line->HasSwitch(switches::kNoActivate);
const DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN; const DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
const DWORD dwExStyle = always_on_top_ ? WS_EX_TOPMOST : 0; DWORD dwExStyle = always_on_top_ ? WS_EX_TOPMOST : 0;
if (no_activate) {
// Don't activate the browser window on creation.
dwExStyle |= WS_EX_NOACTIVATE;
}
int x, y, width, height; int x, y, width, height;
if (::IsRectEmpty(&start_rect_)) { if (::IsRectEmpty(&start_rect_)) {
@ -373,7 +384,7 @@ void RootWindowWin::CreateRootWindow(const CefBrowserSettings& settings,
if (!initially_hidden) { if (!initially_hidden) {
// Show this window. // Show this window.
Show(ShowNormal); Show(no_activate ? ShowNoActivate : ShowNormal);
} }
} }
@ -1069,6 +1080,22 @@ void RootWindowWin::OnSetLoadingState(bool isLoading,
EnableWindow(stop_hwnd_, isLoading); EnableWindow(stop_hwnd_, isLoading);
EnableWindow(edit_hwnd_, TRUE); EnableWindow(edit_hwnd_, TRUE);
} }
if (!isLoading && GetWindowLongPtr(hwnd_, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
// Done with the initial navigation. Remove the WS_EX_NOACTIVATE style so
// that future mouse clicks inside the browser correctly activate and focus
// the window. For the top-level window removing this style causes Windows
// to display the task bar button.
SetWindowLongPtr(hwnd_, GWL_EXSTYLE,
GetWindowLongPtr(hwnd_, GWL_EXSTYLE) & ~WS_EX_NOACTIVATE);
if (browser_window_) {
HWND browser_hwnd = browser_window_->GetWindowHandle();
SetWindowLongPtr(
browser_hwnd, GWL_EXSTYLE,
GetWindowLongPtr(browser_hwnd, GWL_EXSTYLE) & ~WS_EX_NOACTIVATE);
}
}
} }
namespace { namespace {

View File

@ -43,6 +43,7 @@ const char kWidevineCdmPath[] = "widevine-cdm-path";
const char kSslClientCertificate[] = "ssl-client-certificate"; const char kSslClientCertificate[] = "ssl-client-certificate";
const char kCRLSetsPath[] = "crl-sets-path"; const char kCRLSetsPath[] = "crl-sets-path";
const char kLoadExtension[] = "load-extension"; const char kLoadExtension[] = "load-extension";
const char kNoActivate[] = "no-activate";
} // namespace switches } // namespace switches
} // namespace client } // namespace client

View File

@ -37,6 +37,7 @@ extern const char kWidevineCdmPath[];
extern const char kSslClientCertificate[]; extern const char kSslClientCertificate[];
extern const char kCRLSetsPath[]; extern const char kCRLSetsPath[];
extern const char kLoadExtension[]; extern const char kLoadExtension[];
extern const char kNoActivate[];
} // namespace switches } // namespace switches
} // namespace client } // namespace client