diff --git a/include/capi/cef_browser_capi.h b/include/capi/cef_browser_capi.h index 611b4dadb..5873c5fc4 100644 --- a/include/capi/cef_browser_capi.h +++ b/include/capi/cef_browser_capi.h @@ -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. diff --git a/include/cef_browser.h b/include/cef_browser.h index 6214c4e4e..e197c000d 100644 --- a/include/cef_browser.h +++ b/include/cef_browser.h @@ -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. diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 30c1e4e55..81bd6c7ff 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -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)); diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index 8b95ff395..8bd5c3e18 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -126,7 +126,8 @@ class CefBrowserHostImpl : public CefBrowserHost, // CefBrowserHost methods. virtual CefRefPtr 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 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. diff --git a/libcef/browser/browser_host_impl_gtk.cc b/libcef/browser/browser_host_impl_gtk.cc index 257f53637..1615b5c12 100644 --- a/libcef/browser/browser_host_impl_gtk.cc +++ b/libcef/browser/browser_host_impl_gtk.cc @@ -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 : diff --git a/libcef/browser/browser_host_impl_mac.mm b/libcef/browser/browser_host_impl_mac.mm index 4b1271450..8a7f1802c 100644 --- a/libcef/browser/browser_host_impl_mac.mm +++ b/libcef/browser/browser_host_impl_mac.mm @@ -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 : diff --git a/libcef/browser/browser_host_impl_win.cc b/libcef/browser/browser_host_impl_win.cc index 86b77f4b5..852798cbb 100644 --- a/libcef/browser/browser_host_impl_win.cc +++ b/libcef/browser/browser_host_impl_win.cc @@ -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(window->GetHost()); - DCHECK(host); - if (!host) - return NULL; - HWND hwnd = host->GetHWND(); - DCHECK(hwnd); - return hwnd; -} - void WriteTempFileAndView(scoped_refptr 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 : diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.cc b/libcef_dll/cpptoc/browser_host_cpptoc.cc index 9c40da0e7..bd035e159 100644 --- a/libcef_dll/cpptoc/browser_host_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_host_cpptoc.cc @@ -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; diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.cc b/libcef_dll/ctocpp/browser_host_ctocpp.cc index 23fc986bd..fc07e15eb 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_host_ctocpp.cc @@ -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() { diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.h b/libcef_dll/ctocpp/browser_host_ctocpp.h index d0909fed8..b10cad81a 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.h +++ b/libcef_dll/ctocpp/browser_host_ctocpp.h @@ -39,7 +39,8 @@ class CefBrowserHostCToCpp // CefBrowserHost methods virtual CefRefPtr 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 GetClient() OVERRIDE; diff --git a/patch/patches/views_widget_180.patch b/patch/patches/views_widget_180.patch index 8d64b8ed0..dd5d3fd9a 100644 --- a/patch/patches/views_widget_180.patch +++ b/patch/patches/views_widget_180.patch @@ -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) diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm index 1602951da..8eed2f416 100644 --- a/tests/cefclient/cefclient_mac.mm +++ b/tests/cefclient/cefclient_mac.mm @@ -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 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 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 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 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 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 browser = g_handler->GetBrowser(); + if (browser.get()) + browser->GetHost()->SetWindowVisibility(true); + } } } diff --git a/tests/cefclient/cefclient_win.cpp b/tests/cefclient/cefclient_win.cpp index 5320244e2..09eefedc1 100644 --- a/tests/cefclient/cefclient_win.cpp +++ b/tests/cefclient/cefclient_win.cpp @@ -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 osr_window = + static_cast(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; diff --git a/tests/cefclient/client_handler.cpp b/tests/cefclient/client_handler.cpp index 7deef5081..55a7e9a5c 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -322,6 +322,9 @@ void ClientHandler::OnAfterCreated(CefRefPtr 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++;