From 02d6f3e38480442f5957aac3571f611c28349c81 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Tue, 14 Jun 2011 15:09:55 +0000 Subject: [PATCH] Add support for modal dialogs (issue #250). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@255 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- include/cef.h | 28 ++++++- include/cef_capi.h | 28 ++++++- libcef/browser_impl.cc | 59 ++++++++++---- libcef/browser_impl.h | 26 ++++++- libcef/browser_impl_win.cc | 29 +++++++ libcef/browser_webview_delegate_win.cc | 44 ++++++++++- libcef_dll/cpptoc/browser_cpptoc.cc | 11 +++ libcef_dll/cpptoc/life_span_handler_cpptoc.cc | 26 +++++++ libcef_dll/ctocpp/browser_ctocpp.cc | 8 ++ libcef_dll/ctocpp/browser_ctocpp.h | 1 + libcef_dll/ctocpp/life_span_handler_ctocpp.cc | 22 +++++- libcef_dll/ctocpp/life_span_handler_ctocpp.h | 2 + tests/cefclient/cefclient.cpp | 5 ++ tests/cefclient/cefclient.h | 1 + tests/cefclient/cefclient.rc | 3 + tests/cefclient/cefclient_win.cpp | 16 ++++ tests/cefclient/client_handler_win.cpp | 8 ++ tests/cefclient/res/modaldialog.html | 78 +++++++++++++++++++ tests/cefclient/res/modalmain.html | 57 ++++++++++++++ tests/cefclient/resource.h | 5 +- 20 files changed, 434 insertions(+), 23 deletions(-) create mode 100644 tests/cefclient/res/modaldialog.html create mode 100644 tests/cefclient/res/modalmain.html diff --git a/include/cef.h b/include/cef.h index 2640e98c4..fc4f52d99 100644 --- a/include/cef.h +++ b/include/cef.h @@ -612,6 +612,14 @@ public: /*--cef()--*/ virtual CefWindowHandle GetWindowHandle() =0; + /// + // Retrieve the window handle of the browser that opened this browser. Will + // return NULL for non-popup windows. This method can be used in combination + // with custom handling of modal windows. + /// + /*--cef()--*/ + virtual CefWindowHandle GetOpenerWindowHandle() =0; + /// // Returns true if the window is a popup window. /// @@ -972,10 +980,28 @@ public: virtual void OnAfterCreated(CefRefPtr browser) {} /// - // Called just before a window is closed. + // Called just before a window is closed. If this is a modal window and you + // handled the RunModal() event you can use this callback to restore + // the opener window to a usable state. /// /*--cef()--*/ virtual void OnBeforeClose(CefRefPtr browser) {} + + /// + // Called to enter the modal loop. Provide your own modal loop here. Return + // true if you ran your own modal loop and false to use the default. You can + // also use this event to know when a modal window is about to start. + /// + /*--cef()--*/ + virtual bool RunModal(CefRefPtr browser) { return false; } + + /// + // Called when a modal browser window has been destroyed. You must implement + // this if you are handling RunModal(). You can also use this event to know + // when a modal window is about to be closed. + /// + /*--cef()--*/ + virtual void QuitModal(CefRefPtr browser) { } }; diff --git a/include/cef_capi.h b/include/cef_capi.h index 99f2e58e5..69f0cee37 100644 --- a/include/cef_capi.h +++ b/include/cef_capi.h @@ -451,6 +451,14 @@ typedef struct _cef_browser_t cef_window_handle_t (CEF_CALLBACK *get_window_handle)( struct _cef_browser_t* self); + /// + // Retrieve the window handle of the browser that opened this browser. Will + // return NULL for non-popup windows. This function can be used in combination + // with custom handling of modal windows. + /// + cef_window_handle_t (CEF_CALLBACK *get_opener_window_handle)( + struct _cef_browser_t* self); + /// // Returns true (1) if the window is a popup window. /// @@ -815,11 +823,29 @@ typedef struct _cef_life_span_handler_t struct _cef_browser_t* browser); /// - // Called just before a window is closed. + // Called just before a window is closed. If this is a modal window and you + // handled the run_modal() event you can use this callback to restore the + // opener window to a usable state. /// void (CEF_CALLBACK *on_before_close)(struct _cef_life_span_handler_t* self, struct _cef_browser_t* browser); + /// + // Called to enter the modal loop. Provide your own modal loop here. Return + // true (1) if you ran your own modal loop and false (0) to use the default. + // You can also use this event to know when a modal window is about to start. + /// + int (CEF_CALLBACK *run_modal)(struct _cef_life_span_handler_t* self, + struct _cef_browser_t* browser); + + /// + // Called when a modal browser window has been destroyed. You must implement + // this if you are handling run_modal(). You can also use this event to know + // when a modal window is about to be closed. + /// + void (CEF_CALLBACK *quit_modal)(struct _cef_life_span_handler_t* self, + struct _cef_browser_t* browser); + } cef_life_span_handler_t; diff --git a/libcef/browser_impl.cc b/libcef/browser_impl.cc index 51887f2b9..e1b6fef9d 100644 --- a/libcef/browser_impl.cc +++ b/libcef/browser_impl.cc @@ -150,7 +150,7 @@ CefRefPtr CefBrowser::CreateBrowserSync( } CefRefPtr browser( - new CefBrowserImpl(windowInfo, settings, false, client)); + new CefBrowserImpl(windowInfo, settings, NULL, client)); static_cast(browser.get())->UIT_CreateBrowser(url); return browser; @@ -158,12 +158,17 @@ CefRefPtr CefBrowser::CreateBrowserSync( CefBrowserImpl::CefBrowserImpl(const CefWindowInfo& windowInfo, - const CefBrowserSettings& settings, bool popup, + const CefBrowserSettings& settings, + gfx::NativeView opener, CefRefPtr client) - : window_info_(windowInfo), settings_(settings), is_popup_(popup), + : window_info_(windowInfo), settings_(settings), opener_(opener), is_modal_(false), client_(client), webviewhost_(NULL), popuphost_(NULL), zoom_level_(0.0), can_go_back_(false), can_go_forward_(false), main_frame_(NULL), unique_id_(0) +#if defined(OS_WIN) + , opener_was_disabled_by_modal_loop_(false), + internal_modal_message_loop_is_active_(false) +#endif { delegate_.reset(new BrowserWebViewDelegate(this)); popup_delegate_.reset(new BrowserWebViewDelegate(this)); @@ -674,13 +679,28 @@ WebFrame* CefBrowserImpl::UIT_GetWebFrame(CefRefPtr frame) void CefBrowserImpl::UIT_DestroyBrowser() { - if(client_.get()) { - CefRefPtr handler = client_->GetLifeSpanHandler(); - if (handler.get()) { - // Notify the handler that the window is about to be closed. - handler->OnBeforeClose(this); +#if defined(OS_WIN) + if (is_modal_) { + // Exit our own internal modal message loop now. + if (internal_modal_message_loop_is_active_) { + MessageLoop* message_loop = MessageLoop::current(); + message_loop->QuitNow(); + } + + // If the client implemented its own modal loop then the above would not + // run, so this call is for the client to exit its loop. Otherwise, + // QuitModal can be used to let clients know that the modal loop is about + // to exit. + if (client_.get()) { + CefRefPtr handler = client_->GetLifeSpanHandler(); + if (handler.get()) { + // Notify the handler that it can exit its modal loop if it was in one. + handler->QuitModal(this); + } } } +#endif + UIT_GetWebViewDelegate()->RevokeDragDrop(); // If the current browser window is a dev tools client then disconnect from @@ -705,7 +725,7 @@ void CefBrowserImpl::UIT_DestroyBrowser() // Clean up anything associated with the WebViewHost widget. UIT_GetWebViewHost()->webwidget()->close(); webviewhost_.reset(); - + // Remove the reference added in UIT_CreateBrowser(). Release(); @@ -716,10 +736,20 @@ void CefBrowserImpl::UIT_DestroyBrowser() void CefBrowserImpl::UIT_CloseBrowser() { REQUIRE_UIT(); - if (!IsWindowRenderingDisabled()) - UIT_CloseView(UIT_GetMainWndHandle()); - else + if (IsWindowRenderingDisabled()) { + // There is no window here so we need to notify the client that this + // browser instance is about to go away. + if (client_.get()) { + CefRefPtr handler = client_->GetLifeSpanHandler(); + if (handler.get()) { + // Notify the handler that the window is about to be closed. + handler->OnBeforeClose(this); + } + } UIT_DestroyBrowser(); + } else { + UIT_CloseView(UIT_GetMainWndHandle()); + } } void CefBrowserImpl::UIT_LoadURL(CefRefPtr frame, @@ -1082,8 +1112,11 @@ CefRefPtr CefBrowserImpl::UIT_CreatePopupWindow( } } + // Modal windows need to know which window is being suspended (the opener) + // so that it can be disabled while the modal window is open. CefRefPtr browser( - new CefBrowserImpl(info, settings, true, client)); + new CefBrowserImpl(info, settings, UIT_GetMainWndHandle(), client)); + // Don't pass the URL to UIT_CreateBrowser for popup windows or the URL will // be loaded twice. browser->UIT_CreateBrowser(CefString()); diff --git a/libcef/browser_impl.h b/libcef/browser_impl.h index dfb246350..be12f06ec 100644 --- a/libcef/browser_impl.h +++ b/libcef/browser_impl.h @@ -50,7 +50,8 @@ public: }; CefBrowserImpl(const CefWindowInfo& windowInfo, - const CefBrowserSettings& settings, bool popup, + const CefBrowserSettings& settings, + gfx::NativeView opener, CefRefPtr client); virtual ~CefBrowserImpl() {} @@ -71,6 +72,8 @@ public: virtual void StopLoad() OVERRIDE; virtual void SetFocus(bool enable) OVERRIDE; virtual CefWindowHandle GetWindowHandle() OVERRIDE; + virtual CefWindowHandle GetOpenerWindowHandle() OVERRIDE + { return opener_window(); } virtual bool IsPopup() OVERRIDE { return is_popup(); } virtual CefRefPtr GetClient() OVERRIDE { return client_; } virtual CefRefPtr GetMainFrame() OVERRIDE @@ -309,7 +312,8 @@ public: // These variables are read-only. const CefBrowserSettings& settings() const { return settings_; } const FilePath& file_system_root() const { return file_system_root_.path(); } - bool is_popup() { return is_popup_; } + gfx::NativeView opener_window() { return opener_; } + bool is_popup() { return (opener_ != NULL); } // These variables may be read/written from multiple threads. void set_zoom_level(double zoomLevel); @@ -318,6 +322,17 @@ public: bool can_go_back(); bool can_go_forward(); +#if defined(OS_WIN) + void set_opener_was_disabled_by_modal_loop(bool disabled) + { + opener_was_disabled_by_modal_loop_ = disabled; + } + void set_internal_modal_message_loop_is_active(bool active) + { + internal_modal_message_loop_is_active_ = active; + } +#endif + void set_popup_rect(const gfx::Rect& rect) { popup_rect_ = rect; } static bool ImplementsThreadSafeReferenceCounting() { return true; } @@ -332,7 +347,8 @@ protected: protected: CefWindowInfo window_info_; CefBrowserSettings settings_; - bool is_popup_; + // Handle of the browser window that opened this window. + gfx::NativeView opener_; bool is_modal_; CefRefPtr client_; scoped_ptr webviewhost_; @@ -355,6 +371,10 @@ protected: #if defined(OS_WIN) // Context object used to manage printing. printing::PrintingContext print_context_; + + // Used to re-enable the opener when a modal window gets closed. + bool opener_was_disabled_by_modal_loop_; + bool internal_modal_message_loop_is_active_; #endif typedef std::map FrameMap; diff --git a/libcef/browser_impl_win.cc b/libcef/browser_impl_win.cc index b0ba4dae7..1f5d9e997 100644 --- a/libcef/browser_impl_win.cc +++ b/libcef/browser_impl_win.cc @@ -38,6 +38,35 @@ LRESULT CALLBACK CefBrowserImpl::WndProc(HWND hwnd, UINT message, static_cast(ui::GetWindowUserData(hwnd)); switch (message) { + case WM_CLOSE: + // It is the responsibility of the client to send this message to this + // window if it is created as a child window of a client's frame window. + // This is particularly important when this window is modal. + if(browser) { + // Here the window really is about to get closed. + if (browser->client_.get()) { + CefRefPtr handler = + browser->client_->GetLifeSpanHandler(); + if (handler.get()) { + // Notify the handler that the window is about to be closed. + handler->OnBeforeClose(browser); + } + } + + // We must re-enable the opener (owner of the modal window) + // before we close the popup to avoid focus/activation/z-order issues. + if (browser->opener_ && browser->opener_was_disabled_by_modal_loop_) { + HWND owner = ::GetAncestor(browser->opener_, GA_ROOT); + ::EnableWindow(owner, TRUE); + } + + // Don't do the default if this is a contained window as the destruction + // will occur when the parent frame window is destroyed. + if (::GetAncestor(hwnd, GA_ROOT) != hwnd) + return 0; + } + break; + case WM_DESTROY: if (browser) { // Clear the user data pointer. diff --git a/libcef/browser_webview_delegate_win.cc b/libcef/browser_webview_delegate_win.cc index 477efabd2..aed199752 100644 --- a/libcef/browser_webview_delegate_win.cc +++ b/libcef/browser_webview_delegate_win.cc @@ -178,8 +178,48 @@ void BrowserWebViewDelegate::runModal() { browser_->UIT_SetIsModal(true); - // TODO(CEF): Add a handler notification for modal windows so the client can - // make the window behave modally. + CefRefPtr client = browser_->GetClient(); + CefRefPtr handler; + + if( client.get()) + handler = client->GetLifeSpanHandler(); + + bool handled(false); + + if (handler.get()) { + // Let the client override the modal message loop. + handled = handler->RunModal(browser_); + } + + if (!handled) { + HWND child = ::GetAncestor(browser_->UIT_GetMainWndHandle(), GA_ROOT); + HWND owner = ::GetAncestor(browser_->opener_window(), GA_ROOT); + + if (child && owner) { + // Set the owner so that Windows keeps this window above the owner. + ::SetWindowLong(child, GWL_HWNDPARENT, (LONG)owner); + // Disable the owner if it is enabled so that you can't interact with it. + // while this child window is open. + if (::IsWindowEnabled(owner)) { + ::EnableWindow(owner, FALSE); + browser_->set_opener_was_disabled_by_modal_loop(true); + } + DWORD dwStyle = ::GetWindowLong(child, GWL_STYLE); + DWORD dwNewStyle = dwStyle | WS_POPUP; + if(dwStyle != dwNewStyle) + ::SetWindowLong(child, GWL_STYLE, dwNewStyle); + } + + // Tell the browser to exit this message loop when this window closes. + browser_->set_internal_modal_message_loop_is_active(true); + + // Start a new message loop here and return when this window closes. + MessageLoop* message_loop = MessageLoop::current(); + bool old_state = message_loop->NestableTasksAllowed(); + message_loop->SetNestableTasksAllowed(true); + message_loop->Run(); + message_loop->SetNestableTasksAllowed(old_state); + } } // WebPluginPageDelegate ------------------------------------------------------ diff --git a/libcef_dll/cpptoc/browser_cpptoc.cc b/libcef_dll/cpptoc/browser_cpptoc.cc index 33790d429..947d9e0ab 100644 --- a/libcef_dll/cpptoc/browser_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_cpptoc.cc @@ -160,6 +160,16 @@ cef_window_handle_t CEF_CALLBACK browser_get_window_handle( return CefBrowserCppToC::Get(self)->GetWindowHandle(); } +cef_window_handle_t CEF_CALLBACK browser_get_opener_window_handle( + struct _cef_browser_t* self) +{ + DCHECK(self); + if(!self) + return NULL; + + return CefBrowserCppToC::Get(self)->GetOpenerWindowHandle(); +} + int CEF_CALLBACK browser_is_popup(struct _cef_browser_t* self) { DCHECK(self); @@ -450,6 +460,7 @@ CefBrowserCppToC::CefBrowserCppToC(CefBrowser* cls) struct_.struct_.stop_load = browser_stop_load; struct_.struct_.set_focus = browser_set_focus; struct_.struct_.get_window_handle = browser_get_window_handle; + struct_.struct_.get_opener_window_handle = browser_get_opener_window_handle; struct_.struct_.is_popup = browser_is_popup; struct_.struct_.get_client = browser_get_client; struct_.struct_.get_main_frame = browser_get_main_frame; diff --git a/libcef_dll/cpptoc/life_span_handler_cpptoc.cc b/libcef_dll/cpptoc/life_span_handler_cpptoc.cc index dadd4f3d3..39200dfeb 100644 --- a/libcef_dll/cpptoc/life_span_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/life_span_handler_cpptoc.cc @@ -97,6 +97,30 @@ void CEF_CALLBACK life_span_handler_on_before_close( CefBrowserCToCpp::Wrap(browser)); } +int CEF_CALLBACK life_span_handler_run_modal( + struct _cef_life_span_handler_t* self, cef_browser_t* browser) +{ + DCHECK(self); + DCHECK(browser); + if (!self || !browser) + return 0; + + return CefLifeSpanHandlerCppToC::Get(self)->RunModal( + CefBrowserCToCpp::Wrap(browser)); +} + +void CEF_CALLBACK life_span_handler_quit_modal( + struct _cef_life_span_handler_t* self, cef_browser_t* browser) +{ + DCHECK(self); + DCHECK(browser); + if (!self || !browser) + return; + + CefLifeSpanHandlerCppToC::Get(self)->QuitModal( + CefBrowserCToCpp::Wrap(browser)); +} + // CONSTRUCTOR - Do not edit by hand. @@ -107,6 +131,8 @@ CefLifeSpanHandlerCppToC::CefLifeSpanHandlerCppToC(CefLifeSpanHandler* cls) struct_.struct_.on_before_popup = life_span_handler_on_before_popup; struct_.struct_.on_after_created = life_span_handler_on_after_created; struct_.struct_.on_before_close = life_span_handler_on_before_close; + struct_.struct_.run_modal = life_span_handler_run_modal; + struct_.struct_.quit_modal = life_span_handler_quit_modal; } #ifndef NDEBUG diff --git a/libcef_dll/ctocpp/browser_ctocpp.cc b/libcef_dll/ctocpp/browser_ctocpp.cc index eeb644228..b9ea97788 100644 --- a/libcef_dll/ctocpp/browser_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_ctocpp.cc @@ -120,6 +120,14 @@ CefWindowHandle CefBrowserCToCpp::GetWindowHandle() return struct_->get_window_handle(struct_); } +CefWindowHandle CefBrowserCToCpp::GetOpenerWindowHandle() +{ + if (CEF_MEMBER_MISSING(struct_, get_opener_window_handle)) + return 0; + + return struct_->get_opener_window_handle(struct_); +} + bool CefBrowserCToCpp::IsPopup() { if(CEF_MEMBER_MISSING(struct_, is_popup)) diff --git a/libcef_dll/ctocpp/browser_ctocpp.h b/libcef_dll/ctocpp/browser_ctocpp.h index 8482dcb2d..6fd04d842 100644 --- a/libcef_dll/ctocpp/browser_ctocpp.h +++ b/libcef_dll/ctocpp/browser_ctocpp.h @@ -41,6 +41,7 @@ public: virtual void StopLoad() OVERRIDE; virtual void SetFocus(bool enable) OVERRIDE; virtual CefWindowHandle GetWindowHandle() OVERRIDE; + virtual CefWindowHandle GetOpenerWindowHandle() OVERRIDE; virtual bool IsPopup() OVERRIDE; virtual CefRefPtr GetClient() OVERRIDE; virtual CefRefPtr GetMainFrame() OVERRIDE; diff --git a/libcef_dll/ctocpp/life_span_handler_ctocpp.cc b/libcef_dll/ctocpp/life_span_handler_ctocpp.cc index 36d4c61f7..399b35b69 100644 --- a/libcef_dll/ctocpp/life_span_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/life_span_handler_ctocpp.cc @@ -52,7 +52,7 @@ void CefLifeSpanHandlerCToCpp::OnAfterCreated(CefRefPtr browser) if (CEF_MEMBER_MISSING(struct_, on_after_created)) return; - return struct_->on_after_created(struct_, CefBrowserCppToC::Wrap(browser)); + struct_->on_after_created(struct_, CefBrowserCppToC::Wrap(browser)); } void CefLifeSpanHandlerCToCpp::OnBeforeClose(CefRefPtr browser) @@ -60,7 +60,25 @@ void CefLifeSpanHandlerCToCpp::OnBeforeClose(CefRefPtr browser) if (CEF_MEMBER_MISSING(struct_, on_before_close)) return; - return struct_->on_before_close(struct_, CefBrowserCppToC::Wrap(browser)); + struct_->on_before_close(struct_, CefBrowserCppToC::Wrap(browser)); +} + +bool CefLifeSpanHandlerCToCpp::RunModal(CefRefPtr browser) +{ + if (CEF_MEMBER_MISSING(struct_, run_modal)) + return false; + + int rv = struct_->run_modal(struct_, CefBrowserCppToC::Wrap(browser)); + + return (rv ? true : false); +} + +void CefLifeSpanHandlerCToCpp::QuitModal(CefRefPtr browser) +{ + if (CEF_MEMBER_MISSING(struct_, quit_modal)) + return; + + struct_->quit_modal(struct_, CefBrowserCppToC::Wrap(browser)); } diff --git a/libcef_dll/ctocpp/life_span_handler_ctocpp.h b/libcef_dll/ctocpp/life_span_handler_ctocpp.h index 65db16643..e1940c5fa 100644 --- a/libcef_dll/ctocpp/life_span_handler_ctocpp.h +++ b/libcef_dll/ctocpp/life_span_handler_ctocpp.h @@ -39,6 +39,8 @@ public: CefBrowserSettings& settings) OVERRIDE; virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE; virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE; + virtual bool RunModal(CefRefPtr browser) OVERRIDE; + virtual void QuitModal(CefRefPtr browser) OVERRIDE; }; #endif // BUILDING_CEF_SHARED diff --git a/tests/cefclient/cefclient.cpp b/tests/cefclient/cefclient.cpp index ac2924b06..800acfe1c 100644 --- a/tests/cefclient/cefclient.cpp +++ b/tests/cefclient/cefclient.cpp @@ -307,3 +307,8 @@ void RunDragDropTest(CefRefPtr browser) { browser->GetMainFrame()->LoadURL("http://html5demos.com/drag"); } + +void RunModalDialogTest(CefRefPtr browser) +{ + browser->GetMainFrame()->LoadURL("http://tests/modalmain"); +} diff --git a/tests/cefclient/cefclient.h b/tests/cefclient/cefclient.h index a8ac1a166..ceb76cf12 100644 --- a/tests/cefclient/cefclient.h +++ b/tests/cefclient/cefclient.h @@ -31,5 +31,6 @@ void RunXMLHTTPRequestTest(CefRefPtr browser); void RunWebURLRequestTest(CefRefPtr browser); void RunDOMAccessTest(CefRefPtr browser); void RunDragDropTest(CefRefPtr browser); +void RunModalDialogTest(CefRefPtr browser); #endif // _CEFCLIENT_H diff --git a/tests/cefclient/cefclient.rc b/tests/cefclient/cefclient.rc index a9202f51f..6696c8221 100644 --- a/tests/cefclient/cefclient.rc +++ b/tests/cefclient/cefclient.rc @@ -35,6 +35,8 @@ IDS_LOGOBALL BINARY "res\\logoball.png" IDS_LOCALSTORAGE BINARY "res\\localstorage.html" IDS_XMLHTTPREQUEST BINARY "res\\xmlhttprequest.html" IDS_DOMACCESS BINARY "res\\domaccess.html" +IDS_MODALMAIN BINARY "res\\modalmain.html" +IDS_MODALDIALOG BINARY "res\\modaldialog.html" ///////////////////////////////////////////////////////////////////////////// // @@ -92,6 +94,7 @@ BEGIN MENUITEM "Reset Zoom", ID_TESTS_ZOOM_RESET MENUITEM "Show Developer Tools", ID_TESTS_DEVTOOLS_SHOW MENUITEM "Close Developer Tools", ID_TESTS_DEVTOOLS_CLOSE + MENUITEM "Modal Dialog", ID_TESTS_MODALDIALOG END END diff --git a/tests/cefclient/cefclient_win.cpp b/tests/cefclient/cefclient_win.cpp index f612a2cb8..e5b0883fb 100644 --- a/tests/cefclient/cefclient_win.cpp +++ b/tests/cefclient/cefclient_win.cpp @@ -560,6 +560,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (browser.get()) browser->CloseDevTools(); return 0; + case ID_TESTS_MODALDIALOG: + if(browser.get()) + RunModalDialogTest(browser); + return 0; } } break; @@ -606,6 +610,18 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) return 0; } break; + + case WM_CLOSE: + // All clients must forward the WM_CLOSE call to all contained browser + // windows to give those windows a chance to cleanup before the window + // closes. Don't forward this message if you are cancelling the request. + if(g_handler.get()) + { + HWND hWnd = g_handler->GetBrowserHwnd(); + if (hWnd) + ::SendMessage(hWnd, WM_CLOSE, 0, 0); + } + break; case WM_DESTROY: // The frame window has exited diff --git a/tests/cefclient/client_handler_win.cpp b/tests/cefclient/client_handler_win.cpp index 0247e68d0..ea007e370 100644 --- a/tests/cefclient/client_handler_win.cpp +++ b/tests/cefclient/client_handler_win.cpp @@ -87,6 +87,14 @@ bool ClientHandler::OnBeforeResourceLoad(CefRefPtr browser, resourceStream = GetBinaryResourceReader(IDS_LOGOBALL); response->SetMimeType("image/png"); response->SetStatus(200); + } else if(url == "http://tests/modalmain") { + resourceStream = GetBinaryResourceReader(IDS_MODALMAIN); + response->SetMimeType("text/html"); + response->SetStatus(200); + } else if(url == "http://tests/modaldialog") { + resourceStream = GetBinaryResourceReader(IDS_MODALDIALOG); + response->SetMimeType("text/html"); + response->SetStatus(200); } return false; diff --git a/tests/cefclient/res/modaldialog.html b/tests/cefclient/res/modaldialog.html new file mode 100644 index 000000000..07e05cf36 --- /dev/null +++ b/tests/cefclient/res/modaldialog.html @@ -0,0 +1,78 @@ + + + + A Modal Dialog + + +Argument:
+
+Reply:
+

+ +

+

+ + + diff --git a/tests/cefclient/res/modalmain.html b/tests/cefclient/res/modalmain.html new file mode 100644 index 000000000..2e2a18602 --- /dev/null +++ b/tests/cefclient/res/modalmain.html @@ -0,0 +1,57 @@ + + + +Test Modal Dialog + + + +

Test Modal Dialog

+Click this to open a modal dialog. + +

Time (timers are suppresed while the modal dialog is open)

+
+ +

Result Log

+
+ + + + + diff --git a/tests/cefclient/resource.h b/tests/cefclient/resource.h index 0c0f41ae4..090b598d3 100644 --- a/tests/cefclient/resource.h +++ b/tests/cefclient/resource.h @@ -51,6 +51,7 @@ #define ID_TESTS_DOMACCESS 32791 #define ID_TESTS_DRAGDROP 32792 #define ID_TESTS_OSRAPP 32793 +#define ID_TESTS_MODALDIALOG 32794 #define IDC_STATIC -1 #define IDS_LOGO 1000 #define IDS_UIPLUGIN 1001 @@ -59,6 +60,8 @@ #define IDS_XMLHTTPREQUEST 1004 #define IDS_DOMACCESS 1005 #define IDS_OSRPLUGIN 1006 +#define IDS_MODALMAIN 1007 +#define IDS_MODALDIALOG 1008 // Avoid files associated with MacOS #define _X86_ @@ -69,7 +72,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 130 -#define _APS_NEXT_COMMAND_VALUE 32793 +#define _APS_NEXT_COMMAND_VALUE 32795 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 110 #endif