diff --git a/include/capi/views/cef_window_delegate_capi.h b/include/capi/views/cef_window_delegate_capi.h index c26f0969f..d6d0c6382 100644 --- a/include/capi/views/cef_window_delegate_capi.h +++ b/include/capi/views/cef_window_delegate_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=a0cec778fbaf0b1f5c9b3ef75dc7bbeeba777a44$ +// $hash=734a13cd5ad9b0af1b29e1e91b406dd5e6740dc4$ // #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_WINDOW_DELEGATE_CAPI_H_ @@ -87,6 +87,16 @@ typedef struct _cef_window_delegate_t { int* is_menu, int* can_activate_menu); + /// + // Return the initial bounds for |window| in screen coordinates. If this + // function returns an NULL CefRect then get_preferred_size() will be called + // to retrieve the size, and the window will be placed on the default screen + // with origin (0,0). + /// + cef_rect_t(CEF_CALLBACK* get_initial_bounds)( + struct _cef_window_delegate_t* self, + struct _cef_window_t* window); + /// // Return true (1) if |window| should be created without a frame or title bar. // The window will be resizable if can_resize() returns true (1). Use diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h index 343e1c60c..621a47843 100644 --- a/include/cef_api_hash.h +++ b/include/cef_api_hash.h @@ -42,13 +42,13 @@ // way that may cause binary incompatibility with other builds. The universal // hash value will change if any platform is affected whereas the platform hash // values will change only if that particular platform is affected. -#define CEF_API_HASH_UNIVERSAL "09dba98bcfcdf8a84e6e1bddf9cfbfd02cdb9c41" +#define CEF_API_HASH_UNIVERSAL "09d3d4f08869644fe3baa7a751de537f3446525b" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "52cba70fb6dd7cfa07a64033875f2b9951ab194b" +#define CEF_API_HASH_PLATFORM "3022db6736af26cc38158d38e22f74a51312a5c9" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "40ddb93c4e9b9d0f81b62a61a595307c6ed204e5" +#define CEF_API_HASH_PLATFORM "13e2e2451c2320f0d16b35ba53b3295409888dd8" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "e48b0f06a363df82624951e4b85fb638bf0987c0" +#define CEF_API_HASH_PLATFORM "d781b815150795b0bce95d72ce967b508c9a04d5" #endif #ifdef __cplusplus diff --git a/include/views/cef_window_delegate.h b/include/views/cef_window_delegate.h index a1457824a..74e45b080 100644 --- a/include/views/cef_window_delegate.h +++ b/include/views/cef_window_delegate.h @@ -78,6 +78,17 @@ class CefWindowDelegate : public CefPanelDelegate { return nullptr; } + /// + // Return the initial bounds for |window| in screen coordinates. If this + // method returns an empty CefRect then GetPreferredSize() will be called to + // retrieve the size, and the window will be placed on the default screen with + // origin (0,0). + /// + /*--cef()--*/ + virtual CefRect GetInitialBounds(CefRefPtr window) { + return CefRect(); + } + /// // Return true if |window| should be created without a frame or title bar. The // window will be resizable if CanResize() returns true. Use diff --git a/libcef/browser/views/window_view.cc b/libcef/browser/views/window_view.cc index de8cc3a57..f12bc425c 100644 --- a/libcef/browser/views/window_view.cc +++ b/libcef/browser/views/window_view.cc @@ -250,13 +250,15 @@ void CefWindowView::CreateWidget() { views::Widget::InitParams params; params.delegate = this; params.type = views::Widget::InitParams::TYPE_WINDOW; - params.bounds = gfx::Rect(CalculatePreferredSize()); bool can_activate = true; if (cef_delegate()) { CefRefPtr cef_window = GetCefWindow(); is_frameless_ = cef_delegate()->IsFrameless(cef_window); + auto bounds = cef_delegate()->GetInitialBounds(cef_window); + params.bounds = gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height); + bool is_menu = false; bool can_activate_menu = true; CefRefPtr parent_window = cef_delegate()->GetParentWindow( @@ -279,6 +281,11 @@ void CefWindowView::CreateWidget() { } } + if (params.bounds.IsEmpty()) { + // The window will be placed on the default screen with origin (0,0). + params.bounds = gfx::Rect(CalculatePreferredSize()); + } + #if defined(OS_WIN) if (is_frameless_) { // Don't show the native window caption. Setting this value on Linux will diff --git a/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc b/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc index 59b706dab..a9a8e542e 100644 --- a/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc +++ b/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=52b31a63bbe83937a9f5dc557accfc1e84af6d84$ +// $hash=fc5a46d1a73e61c08ec1266ac1c481dc65aedf6b$ // #include "libcef_dll/cpptoc/views/window_delegate_cpptoc.h" @@ -108,6 +108,29 @@ window_delegate_get_parent_window(struct _cef_window_delegate_t* self, return CefWindowCToCpp::Unwrap(_retval); } +cef_rect_t CEF_CALLBACK +window_delegate_get_initial_bounds(struct _cef_window_delegate_t* self, + cef_window_t* window) { + shutdown_checker::AssertNotShutdown(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return CefRect(); + // Verify param: window; type: refptr_diff + DCHECK(window); + if (!window) + return CefRect(); + + // Execute + cef_rect_t _retval = CefWindowDelegateCppToC::Get(self)->GetInitialBounds( + CefWindowCToCpp::Wrap(window)); + + // Return type: simple + return _retval; +} + int CEF_CALLBACK window_delegate_is_frameless(struct _cef_window_delegate_t* self, cef_window_t* window) { @@ -475,6 +498,7 @@ CefWindowDelegateCppToC::CefWindowDelegateCppToC() { GetStruct()->on_window_created = window_delegate_on_window_created; GetStruct()->on_window_destroyed = window_delegate_on_window_destroyed; GetStruct()->get_parent_window = window_delegate_get_parent_window; + GetStruct()->get_initial_bounds = window_delegate_get_initial_bounds; GetStruct()->is_frameless = window_delegate_is_frameless; GetStruct()->can_resize = window_delegate_can_resize; GetStruct()->can_maximize = window_delegate_can_maximize; diff --git a/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc b/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc index 833ced7a9..a393a9e5c 100644 --- a/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc +++ b/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=42f9fdcc49577f6d052e4f357138efe4443a72d9$ +// $hash=c2193e3a76df58538caf73c332d4148d00e235d4$ // #include "libcef_dll/ctocpp/views/window_delegate_ctocpp.h" @@ -104,6 +104,29 @@ CefRefPtr CefWindowDelegateCToCpp::GetParentWindow( return CefWindowCppToC::Unwrap(_retval); } +NO_SANITIZE("cfi-icall") +CefRect CefWindowDelegateCToCpp::GetInitialBounds(CefRefPtr window) { + shutdown_checker::AssertNotShutdown(); + + cef_window_delegate_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_initial_bounds)) + return CefRect(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: window; type: refptr_diff + DCHECK(window.get()); + if (!window.get()) + return CefRect(); + + // Execute + cef_rect_t _retval = + _struct->get_initial_bounds(_struct, CefWindowCppToC::Wrap(window)); + + // Return type: simple + return _retval; +} + NO_SANITIZE("cfi-icall") bool CefWindowDelegateCToCpp::IsFrameless(CefRefPtr window) { shutdown_checker::AssertNotShutdown(); diff --git a/libcef_dll/ctocpp/views/window_delegate_ctocpp.h b/libcef_dll/ctocpp/views/window_delegate_ctocpp.h index 6ed7b3915..082683cff 100644 --- a/libcef_dll/ctocpp/views/window_delegate_ctocpp.h +++ b/libcef_dll/ctocpp/views/window_delegate_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=e1c4def5dc9c50b90a1a57bb7769f18763827b25$ +// $hash=2e94fea293b3a9e82cdb57d9e3cb630c13ce0ede$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_WINDOW_DELEGATE_CTOCPP_H_ @@ -42,6 +42,7 @@ class CefWindowDelegateCToCpp CefRefPtr GetParentWindow(CefRefPtr window, bool* is_menu, bool* can_activate_menu) override; + CefRect GetInitialBounds(CefRefPtr window) override; bool IsFrameless(CefRefPtr window) override; bool CanResize(CefRefPtr window) override; bool CanMaximize(CefRefPtr window) override; diff --git a/tests/ceftests/views/test_window_delegate.cc b/tests/ceftests/views/test_window_delegate.cc index 95c4ede9f..299ea8680 100644 --- a/tests/ceftests/views/test_window_delegate.cc +++ b/tests/ceftests/views/test_window_delegate.cc @@ -70,9 +70,24 @@ void TestWindowDelegate::OnWindowCreated(CefRefPtr window) { EXPECT_TRUE(window->GetDisplay().get()); - // Size will come from GetPreferredSize() on initial Window creation. - EXPECT_TRUE(got_get_preferred_size_); + // Size will come from GetGetInitialBounds() or GetPreferredSize() on + // initial Window creation. + EXPECT_TRUE(got_get_initial_bounds_); + if (config_.window_origin.IsEmpty()) + EXPECT_TRUE(got_get_preferred_size_); + else + EXPECT_FALSE(got_get_preferred_size_); + CefRect client_bounds = window->GetBounds(); + if (!config_.window_origin.IsEmpty()) { + EXPECT_EQ(config_.window_origin.x, client_bounds.x); + EXPECT_EQ(config_.window_origin.y, client_bounds.y); + } else { + // Default origin is (0,0). + EXPECT_EQ(0, client_bounds.x); + EXPECT_EQ(0, client_bounds.y); + } + if (config_.frameless) { EXPECT_EQ(config_.window_size, client_bounds.width); EXPECT_EQ(config_.window_size, client_bounds.height); @@ -124,6 +139,17 @@ bool TestWindowDelegate::IsFrameless(CefRefPtr window) { return config_.frameless; } +CefRect TestWindowDelegate::GetInitialBounds(CefRefPtr window) { + got_get_initial_bounds_ = true; + if (!config_.window_origin.IsEmpty()) { + return CefRect(config_.window_origin.x, config_.window_origin.y, + window_size_.width, window_size_.height); + } + + // Call GetPreferredSize(). + return CefRect(); +} + CefSize TestWindowDelegate::GetPreferredSize(CefRefPtr view) { got_get_preferred_size_ = true; return window_size_; diff --git a/tests/ceftests/views/test_window_delegate.h b/tests/ceftests/views/test_window_delegate.h index 2f0519ba2..1c7b0f90e 100644 --- a/tests/ceftests/views/test_window_delegate.h +++ b/tests/ceftests/views/test_window_delegate.h @@ -28,6 +28,7 @@ class TestWindowDelegate : public CefWindowDelegate { bool frameless = false; bool close_window = true; int window_size = kWSize; + CefPoint window_origin = {}; }; // Creates a Window with a new TestWindowDelegate instance and executes @@ -42,6 +43,7 @@ class TestWindowDelegate : public CefWindowDelegate { void OnWindowCreated(CefRefPtr window) override; void OnWindowDestroyed(CefRefPtr window) override; bool IsFrameless(CefRefPtr window) override; + CefRect GetInitialBounds(CefRefPtr window) override; CefSize GetPreferredSize(CefRefPtr view) override; bool OnAccelerator(CefRefPtr window, int command_id) override; bool OnKeyEvent(CefRefPtr window, @@ -62,6 +64,7 @@ class TestWindowDelegate : public CefWindowDelegate { CefRefPtr window_; + bool got_get_initial_bounds_ = false; bool got_get_preferred_size_ = false; // Must be the last member. diff --git a/tests/ceftests/views/window_unittest.cc b/tests/ceftests/views/window_unittest.cc index a2be32135..420d9d56f 100644 --- a/tests/ceftests/views/window_unittest.cc +++ b/tests/ceftests/views/window_unittest.cc @@ -47,12 +47,23 @@ void WindowCreateFramelessImpl(CefRefPtr event) { TestWindowDelegate::RunTest(event, config); } -void RunWindowShowHide(CefRefPtr window) { +void RunWindowShow(CefRefPtr window) { EXPECT_FALSE(window->IsVisible()); EXPECT_FALSE(window->IsDrawn()); window->Show(); EXPECT_TRUE(window->IsVisible()); EXPECT_TRUE(window->IsDrawn()); +} + +void WindowCreateWithOriginImpl(CefRefPtr event) { + TestWindowDelegate::Config config; + config.window_origin = {100, 200}; + config.on_window_created = base::Bind(RunWindowShow); + TestWindowDelegate::RunTest(event, config); +} + +void RunWindowShowHide(CefRefPtr window) { + RunWindowShow(window); window->Hide(); EXPECT_FALSE(window->IsVisible()); EXPECT_FALSE(window->IsDrawn()); @@ -481,6 +492,7 @@ void WindowAcceleratorImpl(CefRefPtr event) { // we presume that Chromium is testing). WINDOW_TEST_ASYNC(WindowCreate) WINDOW_TEST_ASYNC(WindowCreateFrameless) +WINDOW_TEST_ASYNC(WindowCreateWithOrigin) WINDOW_TEST_ASYNC(WindowShowHide) WINDOW_TEST_ASYNC(WindowShowHideFrameless) WINDOW_TEST_ASYNC(WindowLayoutAndCoords)