Fix delivery of focus/blur events (issue #1301).

git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/1916@1718 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2014-06-06 19:06:03 +00:00
parent 58c80976a7
commit cd628ae71b
14 changed files with 266 additions and 89 deletions

View File

@ -236,10 +236,16 @@ typedef struct _cef_browser_host_t {
int force_close);
///
// Set focus for the browser window. If |enable| is true (1) focus will be set
// to the window. Otherwise, focus will be removed.
// Set whether the browser is focused.
///
void (CEF_CALLBACK *set_focus)(struct _cef_browser_host_t* self, int enable);
void (CEF_CALLBACK *set_focus)(struct _cef_browser_host_t* self, int focus);
///
// Set whether the window containing the browser is visible
// (minimized/unminimized, app hidden/unhidden, etc). Only used on Mac OS X.
///
void (CEF_CALLBACK *set_window_visibility)(struct _cef_browser_host_t* self,
int visible);
///
// Retrieve the window handle for this browser.

View File

@ -274,11 +274,17 @@ class CefBrowserHost : public virtual CefBase {
virtual void CloseBrowser(bool force_close) =0;
///
// Set focus for the browser window. If |enable| is true focus will be set to
// the window. Otherwise, focus will be removed.
// Set whether the browser is focused.
///
/*--cef()--*/
virtual void SetFocus(bool enable) =0;
virtual void SetFocus(bool focus) =0;
///
// Set whether the window containing the browser is visible
// (minimized/unminimized, app hidden/unhidden, etc). Only used on Mac OS X.
///
/*--cef()--*/
virtual void SetWindowVisibility(bool visible) =0;
///
// Retrieve the window handle for this browser.

View File

@ -682,11 +682,29 @@ void CefBrowserHostImpl::CloseBrowser(bool force_close) {
}
}
void CefBrowserHostImpl::SetFocus(bool enable) {
if (!enable)
return;
void CefBrowserHostImpl::SetFocus(bool focus) {
if (focus) {
OnSetFocus(FOCUS_SOURCE_SYSTEM);
} else {
if (CEF_CURRENTLY_ON_UIT()) {
PlatformSetFocus(false);
} else {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::PlatformSetFocus, this, false));
}
}
}
OnSetFocus(FOCUS_SOURCE_SYSTEM);
void CefBrowserHostImpl::SetWindowVisibility(bool visible) {
#if defined(OS_MACOSX)
if (CEF_CURRENTLY_ON_UIT()) {
PlatformSetWindowVisibility(visible);
} else {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::PlatformSetWindowVisibility,
this, visible));
}
#endif
}
CefWindowHandle CefBrowserHostImpl::GetWindowHandle() {
@ -1687,17 +1705,7 @@ void CefBrowserHostImpl::OnSetFocus(cef_focus_source_t source) {
}
}
if (web_contents_.get())
web_contents_->GetView()->Focus();
#if defined(OS_WIN)
if (!IsWindowRenderingDisabled()) {
// When windowed rendering is used in combination with Aura on Windows we
// need to explicitly set focus to the native window handle. Otherwise,
// the window doesn't get keyboard focus.
PlatformSetViewFocus();
}
#endif // defined(OS_WIN)
PlatformSetFocus(true);
} else {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::OnSetFocus, this, source));

View File

@ -126,7 +126,8 @@ class CefBrowserHostImpl : public CefBrowserHost,
// CefBrowserHost methods.
virtual CefRefPtr<CefBrowser> GetBrowser() OVERRIDE;
virtual void CloseBrowser(bool force_close) OVERRIDE;
virtual void SetFocus(bool enable) OVERRIDE;
virtual void SetFocus(bool focus) OVERRIDE;
virtual void SetWindowVisibility(bool visible) OVERRIDE;
virtual CefWindowHandle GetWindowHandle() OVERRIDE;
virtual CefWindowHandle GetOpenerWindowHandle() OVERRIDE;
virtual CefRefPtr<CefClient> GetClient() OVERRIDE;
@ -465,8 +466,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
static LPCTSTR GetWndClass();
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam);
void PlatformSetViewFocus();
#endif
// Create the window.
@ -476,6 +475,12 @@ class CefBrowserHostImpl : public CefBrowserHost,
void PlatformCloseWindow();
// Resize the window to the given dimensions.
void PlatformSizeTo(int width, int height);
// Set or remove focus from the window.
void PlatformSetFocus(bool focus);
#if defined(OS_MACOSX)
// Set or remove window visibility.
void PlatformSetWindowVisibility(bool visible);
#endif
// Return the handle for this window.
CefWindowHandle PlatformGetWindowHandle();
// Open the specified text in the default text editor.

View File

@ -319,6 +319,11 @@ void CefBrowserHostImpl::PlatformSizeTo(int width, int height) {
}
}
void CefBrowserHostImpl::PlatformSetFocus(bool focus) {
if (focus && web_contents_)
web_contents_->GetView()->Focus();
}
CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() {
return IsWindowRenderingDisabled() ?
window_info_.parent_widget :

View File

@ -20,6 +20,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/file_chooser_params.h"
@ -37,7 +38,6 @@
@interface CefBrowserHostView : NSView {
@private
CefBrowserHostImpl* browser_; // weak
bool is_in_onsetfocus_;
}
@property (nonatomic, assign) CefBrowserHostImpl* browser;
@ -58,23 +58,6 @@
[super dealloc];
}
- (BOOL)acceptsFirstResponder {
return browser_ && browser_->GetWebContents();
}
- (BOOL)becomeFirstResponder {
if (browser_ && browser_->GetWebContents()) {
// Avoid re-entering OnSetFocus.
if (!is_in_onsetfocus_) {
is_in_onsetfocus_ = true;
browser_->OnSetFocus(FOCUS_SOURCE_SYSTEM);
is_in_onsetfocus_ = false;
}
}
return YES;
}
@end
// Receives notifications from the browser window. Will delete itself when done.
@ -91,6 +74,48 @@
@synthesize browser = browser_;
// Called when we are activated (when we gain focus).
- (void)windowDidBecomeKey:(NSNotification*)notification {
if (browser_)
browser_->SetFocus(true);
}
// Called when we are deactivated (when we lose focus).
- (void)windowDidResignKey:(NSNotification*)notification {
if (browser_)
browser_->SetFocus(false);
}
// Called when we have been minimized.
- (void)windowDidMiniaturize:(NSNotification *)notification {
if (browser_)
browser_->SetWindowVisibility(false);
}
// Called when we have been unminimized.
- (void)windowDidDeminiaturize:(NSNotification *)notification {
if (browser_)
browser_->SetWindowVisibility(true);
}
// Called when the application has been hidden.
- (void)applicationDidHide:(NSNotification *)notification {
// If the window is miniaturized then nothing has really changed.
if (![[notification object] isMiniaturized]) {
if (browser_)
browser_->SetWindowVisibility(false);
}
}
// Called when the application has been unhidden.
- (void)applicationDidUnhide:(NSNotification *)notification {
// If the window is miniaturized then nothing has really changed.
if (![[notification object] isMiniaturized]) {
if (browser_)
browser_->SetWindowVisibility(true);
}
}
- (BOOL)windowShouldClose:(id)window {
// Protect against multiple requests to close while the close is pending.
if (browser_ && browser_->destruction_state() <=
@ -401,6 +426,31 @@ void CefBrowserHostImpl::PlatformSizeTo(int width, int height) {
// Not needed; subviews are bound.
}
void CefBrowserHostImpl::PlatformSetFocus(bool focus) {
if (web_contents_) {
if (content::RenderWidgetHostView* view =
web_contents_->GetRenderWidgetHostView()) {
view->SetActive(focus);
if (focus) {
// Give keyboard focus to the native view.
NSView* view = web_contents_->GetView()->GetContentNativeView();
DCHECK([view canBecomeKeyView]);
[[view window] makeFirstResponder:view];
}
}
}
}
void CefBrowserHostImpl::PlatformSetWindowVisibility(bool visible) {
if (web_contents_) {
if (content::RenderWidgetHostView* view =
web_contents_->GetRenderWidgetHostView()) {
view->SetWindowVisibility(visible);
}
}
}
CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() {
return IsWindowRenderingDisabled() ?
window_info_.parent_view :

View File

@ -39,9 +39,9 @@
#include "ui/views/background.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/win/hwnd_util.h"
#pragma comment(lib, "dwmapi.lib")
@ -64,21 +64,6 @@ void SetAeroGlass(HWND hWnd) {
DwmExtendFrameIntoClientArea(hWnd, &mgMarInset);
}
HWND GetHWND(views::Widget* widget) {
gfx::NativeWindow window = widget->GetNativeWindow();
DCHECK(window);
if (!window)
return NULL;
views::DesktopWindowTreeHostWin* host =
static_cast<views::DesktopWindowTreeHostWin*>(window->GetHost());
DCHECK(host);
if (!host)
return NULL;
HWND hwnd = host->GetHWND();
DCHECK(hwnd);
return hwnd;
}
void WriteTempFileAndView(scoped_refptr<base::RefCountedString> str) {
CEF_REQUIRE_FILET();
@ -573,7 +558,6 @@ class CefWindowDelegateView : public views::WidgetDelegateView {
explicit CefWindowDelegateView(SkColor background_color)
: background_color_(background_color),
web_view_(NULL) {
}
// Create the Widget and associated root window.
@ -709,7 +693,7 @@ LRESULT CALLBACK CefBrowserHostImpl::WndProc(HWND hwnd, UINT message,
case WM_SETFOCUS:
if (browser)
browser->OnSetFocus(FOCUS_SOURCE_SYSTEM);
browser->SetFocus(true);
return 0;
case WM_ERASEBKGND:
@ -726,11 +710,6 @@ LRESULT CALLBACK CefBrowserHostImpl::WndProc(HWND hwnd, UINT message,
return DefWindowProc(hwnd, message, wParam, lParam);
}
void CefBrowserHostImpl::PlatformSetViewFocus() {
if (window_widget_)
::SetFocus(GetHWND(window_widget_));
}
ui::PlatformCursor CefBrowserHostImpl::GetPlatformCursor(
blink::WebCursorInfo::Type type) {
HMODULE module_handle = NULL;
@ -822,6 +801,25 @@ void CefBrowserHostImpl::PlatformSizeTo(int width, int height) {
rect.bottom, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
}
void CefBrowserHostImpl::PlatformSetFocus(bool focus) {
if (!focus)
return;
if (web_contents_) {
// Give logical focus to the RenderWidgetHostViewAura in the views
// hierarchy. This does not change the native keyboard focus.
web_contents_->GetView()->Focus();
}
if (window_widget_) {
// Give native focus to the DesktopNativeWidgetAura for the root window.
// Needs to be done via the HWND so that keyboard focus is assigned
// correctly. DesktopNativeWidgetAura will update focus state on the
// aura::Window when WM_SETFOCUS and WM_KILLFOCUS are received.
::SetFocus(HWNDForWidget(window_widget_));
}
}
CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() {
return IsWindowRenderingDisabled() ?
window_info_.parent_window :

View File

@ -127,7 +127,7 @@ void CEF_CALLBACK browser_host_close_browser(struct _cef_browser_host_t* self,
}
void CEF_CALLBACK browser_host_set_focus(struct _cef_browser_host_t* self,
int enable) {
int focus) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
@ -136,7 +136,20 @@ void CEF_CALLBACK browser_host_set_focus(struct _cef_browser_host_t* self,
// Execute
CefBrowserHostCppToC::Get(self)->SetFocus(
enable?true:false);
focus?true:false);
}
void CEF_CALLBACK browser_host_set_window_visibility(
struct _cef_browser_host_t* self, int visible) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefBrowserHostCppToC::Get(self)->SetWindowVisibility(
visible?true:false);
}
cef_window_handle_t CEF_CALLBACK browser_host_get_window_handle(
@ -758,6 +771,7 @@ CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls)
struct_.struct_.get_browser = browser_host_get_browser;
struct_.struct_.close_browser = browser_host_close_browser;
struct_.struct_.set_focus = browser_host_set_focus;
struct_.struct_.set_window_visibility = browser_host_set_window_visibility;
struct_.struct_.get_window_handle = browser_host_get_window_handle;
struct_.struct_.get_opener_window_handle =
browser_host_get_opener_window_handle;

View File

@ -88,7 +88,7 @@ void CefBrowserHostCToCpp::CloseBrowser(bool force_close) {
force_close);
}
void CefBrowserHostCToCpp::SetFocus(bool enable) {
void CefBrowserHostCToCpp::SetFocus(bool focus) {
if (CEF_MEMBER_MISSING(struct_, set_focus))
return;
@ -96,7 +96,18 @@ void CefBrowserHostCToCpp::SetFocus(bool enable) {
// Execute
struct_->set_focus(struct_,
enable);
focus);
}
void CefBrowserHostCToCpp::SetWindowVisibility(bool visible) {
if (CEF_MEMBER_MISSING(struct_, set_window_visibility))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
struct_->set_window_visibility(struct_,
visible);
}
CefWindowHandle CefBrowserHostCToCpp::GetWindowHandle() {

View File

@ -39,7 +39,8 @@ class CefBrowserHostCToCpp
// CefBrowserHost methods
virtual CefRefPtr<CefBrowser> GetBrowser() OVERRIDE;
virtual void CloseBrowser(bool force_close) OVERRIDE;
virtual void SetFocus(bool enable) OVERRIDE;
virtual void SetFocus(bool focus) OVERRIDE;
virtual void SetWindowVisibility(bool visible) OVERRIDE;
virtual CefWindowHandle GetWindowHandle() OVERRIDE;
virtual CefWindowHandle GetOpenerWindowHandle() OVERRIDE;
virtual CefRefPtr<CefClient> GetClient() OVERRIDE;

View File

@ -26,18 +26,22 @@ Index: desktop_aura/desktop_window_tree_host_win.cc
parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget();
message_handler_->set_remove_standard_frame(params.remove_standard_frame);
Index: desktop_aura/desktop_window_tree_host_win.h
===================================================================
--- desktop_aura/desktop_window_tree_host_win.h (revision 266998)
+++ desktop_aura/desktop_window_tree_host_win.h (working copy)
@@ -214,6 +214,7 @@
LPARAM l_param) OVERRIDE;
virtual bool HandleScrollEvent(const ui::ScrollEvent& event) OVERRIDE;
@@ -828,6 +830,7 @@
+ public:
Widget* GetWidget();
const Widget* GetWidget() const;
HWND GetHWND() const;
void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) {
// TODO(beng): inform the native_widget_delegate_.
+ GetWidget()->GetNativeWindow()->Focus();
InputMethod* input_method = GetInputMethod();
if (input_method)
input_method->OnFocus();
@@ -835,6 +838,7 @@
void DesktopWindowTreeHostWin::HandleNativeBlur(HWND focused_window) {
// TODO(beng): inform the native_widget_delegate_.
+ GetWidget()->GetNativeWindow()->Blur();
InputMethod* input_method = GetInputMethod();
if (input_method)
input_method->OnBlur();
Index: widget.cc
===================================================================
--- widget.cc (revision 266998)

View File

@ -212,10 +212,71 @@ const int kWindowHeight = 600;
[self alert:@"File Download" withMessage:str];
}
// Called when we are activated (when we gain focus).
- (void)windowDidBecomeKey:(NSNotification*)notification {
if (g_handler.get() && g_handler->GetBrowserId()) {
// Give focus to the browser window.
g_handler->GetBrowser()->GetHost()->SetFocus(true);
if (g_handler.get()) {
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (browser.get()) {
if (AppIsOffScreenRenderingEnabled())
browser->GetHost()->SendFocusEvent(true);
else
browser->GetHost()->SetFocus(true);
}
}
}
// Called when we are deactivated (when we lose focus).
- (void)windowDidResignKey:(NSNotification*)notification {
if (g_handler.get()) {
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (browser.get()) {
if (AppIsOffScreenRenderingEnabled())
browser->GetHost()->SendFocusEvent(false);
else
browser->GetHost()->SetFocus(false);
}
}
}
// Called when we have been minimized.
- (void)windowDidMiniaturize:(NSNotification *)notification {
if (g_handler.get()) {
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (browser.get())
browser->GetHost()->SetWindowVisibility(false);
}
}
// Called when we have been unminimized.
- (void)windowDidDeminiaturize:(NSNotification *)notification {
if (g_handler.get()) {
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (browser.get())
browser->GetHost()->SetWindowVisibility(true);
}
}
// Called when the application has been hidden.
- (void)applicationDidHide:(NSNotification *)notification {
// If the window is miniaturized then nothing has really changed.
if (![[notification object] isMiniaturized]) {
if (g_handler.get()) {
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (browser.get())
browser->GetHost()->SetWindowVisibility(false);
}
}
}
// Called when the application has been unhidden.
- (void)applicationDidUnhide:(NSNotification *)notification {
// If the window is miniaturized then nothing has really changed.
if (![[notification object] isMiniaturized]) {
if (g_handler.get()) {
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
if (browser.get())
browser->GetHost()->SetWindowVisibility(true);
}
}
}

View File

@ -539,11 +539,16 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
case WM_SETFOCUS:
if (g_handler.get() && g_handler->GetBrowser()) {
// Pass focus to the browser window
CefWindowHandle hwnd =
g_handler->GetBrowser()->GetHost()->GetWindowHandle();
if (hwnd)
PostMessage(hwnd, WM_SETFOCUS, wParam, NULL);
if (AppIsOffScreenRenderingEnabled()) {
// Give focus to the OSR window.
CefRefPtr<OSRWindow> osr_window =
static_cast<OSRWindow*>(g_handler->GetOSRHandler().get());
if (osr_window)
::SetFocus(osr_window->hwnd());
} else {
// Give focus to the browser.
g_handler->GetBrowser()->GetHost()->SetFocus(true);
}
}
return 0;

View File

@ -322,6 +322,9 @@ void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
} else if (browser->IsPopup()) {
// Add to the list of popup browsers.
m_PopupBrowsers.push_back(browser);
// Give focus to the popup browser.
browser->GetHost()->SetFocus(true);
}
m_BrowserCount++;