From 62d9365b5199636a6dd6fc2814a7b31f38fdf240 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Fri, 6 Jun 2014 19:04:21 +0000 Subject: [PATCH] Fix delivery of focus/blur events (issue #1301). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1717 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- include/capi/cef_browser_capi.h | 12 +++- include/cef_browser.h | 12 +++- libcef/browser/browser_host_impl.cc | 36 ++++++---- libcef/browser/browser_host_impl.h | 11 ++- libcef/browser/browser_host_impl_linux.cc | 18 +++++ libcef/browser/browser_host_impl_mac.mm | 86 ++++++++++++++++++----- libcef/browser/browser_host_impl_win.cc | 26 +++++-- libcef/browser/window_x11.cc | 42 +++++++++-- libcef/browser/window_x11.h | 10 +++ libcef_dll/cpptoc/browser_host_cpptoc.cc | 18 ++++- libcef_dll/ctocpp/browser_host_ctocpp.cc | 15 +++- libcef_dll/ctocpp/browser_host_ctocpp.h | 3 +- patch/patches/views_widget_180.patch | 16 +++++ tests/cefclient/cefclient_gtk.cpp | 4 +- tests/cefclient/cefclient_mac.mm | 59 +++++++++++++++- tests/cefclient/cefclient_win.cpp | 7 +- tests/cefclient/client_handler.cpp | 6 ++ 17 files changed, 314 insertions(+), 67 deletions(-) diff --git a/include/capi/cef_browser_capi.h b/include/capi/cef_browser_capi.h index 35030f92c..649b6892b 100644 --- a/include/capi/cef_browser_capi.h +++ b/include/capi/cef_browser_capi.h @@ -235,10 +235,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 da5b738a6..2ab08ef1b 100644 --- a/include/cef_browser.h +++ b/include/cef_browser.h @@ -271,11 +271,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 26a98ba69..063905870 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -632,11 +632,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() { @@ -1499,15 +1517,7 @@ void CefBrowserHostImpl::OnSetFocus(cef_focus_source_t source) { } } - if (web_contents_.get()) - web_contents_->Focus(); - -#if defined(OS_WIN) - // 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 04eb1bc68..82b5c9941 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -127,7 +127,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; @@ -443,8 +444,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. @@ -454,6 +453,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_linux.cc b/libcef/browser/browser_host_impl_linux.cc index 677c97e13..87bd8fa02 100644 --- a/libcef/browser/browser_host_impl_linux.cc +++ b/libcef/browser/browser_host_impl_linux.cc @@ -100,6 +100,24 @@ void CefBrowserHostImpl::PlatformSizeTo(int width, int height) { } } +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_->Focus(); + } + + if (window_x11_) { + // Give native focus to the DesktopNativeWidgetAura for the root window. + // Needs to be done via the ::Window so that keyboard focus is assigned + // correctly. + window_x11_->Focus(); + } +} + CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() { return window_info_.window; } diff --git a/libcef/browser/browser_host_impl_mac.mm b/libcef/browser/browser_host_impl_mac.mm index 6d1731176..158066c6b 100644 --- a/libcef/browser/browser_host_impl_mac.mm +++ b/libcef/browser/browser_host_impl_mac.mm @@ -18,6 +18,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/common/file_chooser_params.h" #include "grit/ui_strings.h" @@ -34,7 +35,6 @@ @interface CefBrowserHostView : NSView { @private CefBrowserHostImpl* browser_; // weak - bool is_in_onsetfocus_; } @property (nonatomic, assign) CefBrowserHostImpl* browser; @@ -55,23 +55,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. @@ -88,6 +71,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() <= @@ -345,6 +370,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_->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 window_info_.view; } diff --git a/libcef/browser/browser_host_impl_win.cc b/libcef/browser/browser_host_impl_win.cc index eb565e49c..c3d2e6b1c 100644 --- a/libcef/browser/browser_host_impl_win.cc +++ b/libcef/browser/browser_host_impl_win.cc @@ -601,7 +601,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: @@ -611,11 +611,6 @@ LRESULT CALLBACK CefBrowserHostImpl::WndProc(HWND hwnd, UINT message, return DefWindowProc(hwnd, message, wParam, lParam); } -void CefBrowserHostImpl::PlatformSetViewFocus() { - if (window_widget_) - ::SetFocus(views::HWNDForWidget(window_widget_)); -} - ui::PlatformCursor CefBrowserHostImpl::GetPlatformCursor( blink::WebCursorInfo::Type type) { HMODULE module_handle = NULL; @@ -701,6 +696,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_->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 window_info_.window; } diff --git a/libcef/browser/window_x11.cc b/libcef/browser/window_x11.cc index 96b8bcc40..20ba5523e 100644 --- a/libcef/browser/window_x11.cc +++ b/libcef/browser/window_x11.cc @@ -10,6 +10,7 @@ #include #include +#include "ui/base/x/x11_util.h" #include "ui/events/platform/x11/x11_event_source.h" namespace { @@ -58,7 +59,9 @@ CefWindowX11::CefWindowX11(CefRefPtr browser, xwindow_(0), window_mapped_(false), bounds_(bounds), - atom_cache_(xdisplay_, kAtomsToCache) { + focus_pending_(false), + atom_cache_(xdisplay_, kAtomsToCache), + weak_ptr_factory_(this) { if (parent_xwindow_ == None) parent_xwindow_ = DefaultRootWindow(xdisplay_); @@ -166,6 +169,17 @@ void CefWindowX11::Hide() { } } +void CefWindowX11::Focus() { + if (xwindow_ == None || !window_mapped_) + return; + + ::Window child = FindChild(xdisplay_, xwindow_); + if (child && ui::IsWindowVisible(child)) { + // Give focus to the child DesktopWindowTreeHostX11. + XSetInputFocus(xdisplay_, child, RevertToParent, CurrentTime); + } +} + void CefWindowX11::SetBounds(const gfx::Rect& bounds) { if (xwindow_ == None) return; @@ -274,13 +288,31 @@ uint32_t CefWindowX11::DispatchEvent(const ui::PlatformEvent& event) { // "_NET_ACTIVE_WINDOW" message it will erroneously mark the WebView // (hosted in a DesktopWindowTreeHostX11) as unfocused. Use a delayed // task here to restore the WebView's focus state. - CEF_POST_DELAYED_TASK(CEF_UIT, - base::Bind(&CefBrowserHostImpl::OnSetFocus, browser_, - FOCUS_SOURCE_SYSTEM), - 100); + if (!focus_pending_) { + focus_pending_ = true; + CEF_POST_DELAYED_TASK(CEF_UIT, + base::Bind(&CefWindowX11::ContinueFocus, + weak_ptr_factory_.GetWeakPtr()), + 100); + } + break; + case FocusOut: + // Cancel the pending focus change if some other window has gained focus + // while waiting for the async task to run. Otherwise we can get stuck in + // a focus change loop. + if (focus_pending_) + focus_pending_ = false; break; } return ui::POST_DISPATCH_STOP_PROPAGATION; } +void CefWindowX11::ContinueFocus() { + if (!focus_pending_) + return; + browser_->SetFocus(true); + focus_pending_ = false; +} + + diff --git a/libcef/browser/window_x11.h b/libcef/browser/window_x11.h index 042ec8092..7475e93fe 100644 --- a/libcef/browser/window_x11.h +++ b/libcef/browser/window_x11.h @@ -11,6 +11,7 @@ #include "libcef/browser/browser_host_impl.h" +#include "base/memory/weak_ptr.h" #include "ui/events/platform/platform_event_dispatcher.h" #include "ui/gfx/rect.h" #include "ui/gfx/x/x11_atom_cache.h" @@ -29,6 +30,8 @@ class CefWindowX11 : public ui::PlatformEventDispatcher { void Show(); void Hide(); + void Focus(); + void SetBounds(const gfx::Rect& bounds); gfx::Rect GetBoundsInScreen(); @@ -41,6 +44,8 @@ class CefWindowX11 : public ui::PlatformEventDispatcher { gfx::Rect bounds() const { return bounds_; } private: + void ContinueFocus(); + CefRefPtr browser_; // The display and the native X window hosting the root window. @@ -54,8 +59,13 @@ class CefWindowX11 : public ui::PlatformEventDispatcher { // The bounds of |xwindow_|. gfx::Rect bounds_; + bool focus_pending_; + ui::X11AtomCache atom_cache_; + // Must always be the last member. + base::WeakPtrFactory weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(CefWindowX11); }; diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.cc b/libcef_dll/cpptoc/browser_host_cpptoc.cc index dfd8ebddd..d32a1eb54 100644 --- a/libcef_dll/cpptoc/browser_host_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_host_cpptoc.cc @@ -126,7 +126,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); @@ -135,7 +135,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( @@ -527,6 +540,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 7186d3e54..4292fd5e6 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_host_ctocpp.cc @@ -87,7 +87,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; @@ -95,7 +95,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 7f9e77820..5a50e1766 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 56a6be635..0e35333be 100644 --- a/patch/patches/views_widget_180.patch +++ b/patch/patches/views_widget_180.patch @@ -26,6 +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); +@@ -775,6 +777,7 @@ + + 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(); +@@ -782,6 +785,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: desktop_aura/desktop_window_tree_host_x11.cc =================================================================== --- desktop_aura/desktop_window_tree_host_x11.cc (revision 272007) diff --git a/tests/cefclient/cefclient_gtk.cpp b/tests/cefclient/cefclient_gtk.cpp index 20aeb3107..f30e014a9 100644 --- a/tests/cefclient/cefclient_gtk.cpp +++ b/tests/cefclient/cefclient_gtk.cpp @@ -94,9 +94,7 @@ gboolean WindowFocusIn(GtkWidget* widget, CefRefPtr browser = g_handler->GetBrowser(); if (browser) { // Give focus to the browser window. - ::Display* xdisplay = cef_get_xdisplay(); - ::Window xwindow = browser->GetHost()->GetWindowHandle(); - XSetInputFocus(xdisplay, xwindow, RevertToParent, CurrentTime); + browser->GetHost()->SetFocus(true); return TRUE; } } diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm index ae3b90f25..4f23e58cc 100644 --- a/tests/cefclient/cefclient_mac.mm +++ b/tests/cefclient/cefclient_mac.mm @@ -202,10 +202,63 @@ 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()) + 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()) + 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 4e11f54dd..405ad36c5 100644 --- a/tests/cefclient/cefclient_win.cpp +++ b/tests/cefclient/cefclient_win.cpp @@ -517,11 +517,8 @@ 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); + // 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 dcd21dc30..aa4b4deea 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -306,6 +306,12 @@ 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. Perform asynchronously because the + // parent window may attempt to keep focus after launching the popup. + CefPostTask(TID_UI, + NewCefRunnableMethod(browser->GetHost().get(), + &CefBrowserHost::SetFocus, true)); } m_BrowserCount++;