mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Support JavaScript window.moveTo/By() and resizeTo/By() (fixes #698)
Adds new CefDisplayHandler::OnContentsBoundsChange and CefDisplayHandler::GetRootWindowScreenRect callbacks. cefclient: Implement the above callbacks and call CefBrowserHost::NotifyScreenInfoChanged when the root window bounds change. cefclient: osr: Use real screen bounds by default. Pass `--fake-screen-bounds` for the old default behavior. Load https://tests/window in cefclient for additional implementation details and usage examples.
This commit is contained in:
@ -410,6 +410,8 @@
|
|||||||
'tests/cefclient/browser/temp_window_mac.mm',
|
'tests/cefclient/browser/temp_window_mac.mm',
|
||||||
'tests/cefclient/browser/text_input_client_osr_mac.h',
|
'tests/cefclient/browser/text_input_client_osr_mac.h',
|
||||||
'tests/cefclient/browser/text_input_client_osr_mac.mm',
|
'tests/cefclient/browser/text_input_client_osr_mac.mm',
|
||||||
|
'tests/cefclient/browser/util_mac.h',
|
||||||
|
'tests/cefclient/browser/util_mac.mm',
|
||||||
'tests/cefclient/browser/views_window_mac.mm',
|
'tests/cefclient/browser/views_window_mac.mm',
|
||||||
'tests/cefclient/browser/window_test_runner_mac.h',
|
'tests/cefclient/browser/window_test_runner_mac.h',
|
||||||
'tests/cefclient/browser/window_test_runner_mac.mm',
|
'tests/cefclient/browser/window_test_runner_mac.mm',
|
||||||
|
@ -707,12 +707,24 @@ class CefBrowserHost : public virtual CefBaseRefCounted {
|
|||||||
virtual void WasHidden(bool hidden) = 0;
|
virtual void WasHidden(bool hidden) = 0;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Send a notification to the browser that the screen info has changed. The
|
/// Notify the browser that screen information has changed. Updated
|
||||||
/// browser will then call CefRenderHandler::GetScreenInfo to update the
|
/// information will be sent to the renderer process to configure screen size
|
||||||
/// screen information with the new values. This simulates moving the webview
|
/// and position values used by CSS and JavaScript (window.deviceScaleFactor,
|
||||||
/// window from one display to another, or changing the properties of the
|
/// window.screenX/Y, window.outerWidth/Height, etc.). For background see
|
||||||
/// current display. This method is only used when window rendering is
|
/// https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage.md#markdown-header-coordinate-systems
|
||||||
/// disabled.
|
///
|
||||||
|
/// This method is used with (a) windowless rendering and (b) windowed
|
||||||
|
/// rendering with external (client-provided) root window.
|
||||||
|
///
|
||||||
|
/// With windowless rendering the browser will call
|
||||||
|
/// CefRenderHandler::GetScreenInfo, CefRenderHandler::GetRootScreenRect and
|
||||||
|
/// CefRenderHandler::GetViewRect. This simulates moving or resizing the root
|
||||||
|
/// window in the current display, moving the root window from one display to
|
||||||
|
/// another, or changing the properties of the current display.
|
||||||
|
///
|
||||||
|
/// With windowed rendering the browser will call
|
||||||
|
/// CefDisplayHandler::GetRootWindowScreenRect and use the associated
|
||||||
|
/// display properties.
|
||||||
///
|
///
|
||||||
/*--cef()--*/
|
/*--cef()--*/
|
||||||
virtual void NotifyScreenInfoChanged() = 0;
|
virtual void NotifyScreenInfoChanged() = 0;
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#define CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_
|
#define CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "include/cef_api_hash.h"
|
||||||
#include "include/cef_base.h"
|
#include "include/cef_base.h"
|
||||||
#include "include/cef_browser.h"
|
#include "include/cef_browser.h"
|
||||||
#include "include/cef_frame.h"
|
#include "include/cef_frame.h"
|
||||||
@ -123,7 +124,7 @@ class CefDisplayHandler : public virtual CefBaseRefCounted {
|
|||||||
///
|
///
|
||||||
/// Called when auto-resize is enabled via
|
/// Called when auto-resize is enabled via
|
||||||
/// CefBrowserHost::SetAutoResizeEnabled and the contents have auto-resized.
|
/// CefBrowserHost::SetAutoResizeEnabled and the contents have auto-resized.
|
||||||
/// |new_size| will be the desired size in view coordinates. Return true if
|
/// |new_size| will be the desired size in DIP coordinates. Return true if
|
||||||
/// the resize was handled or false for default handling.
|
/// the resize was handled or false for default handling.
|
||||||
///
|
///
|
||||||
/*--cef()--*/
|
/*--cef()--*/
|
||||||
@ -162,6 +163,46 @@ class CefDisplayHandler : public virtual CefBaseRefCounted {
|
|||||||
virtual void OnMediaAccessChange(CefRefPtr<CefBrowser> browser,
|
virtual void OnMediaAccessChange(CefRefPtr<CefBrowser> browser,
|
||||||
bool has_video_access,
|
bool has_video_access,
|
||||||
bool has_audio_access) {}
|
bool has_audio_access) {}
|
||||||
|
|
||||||
|
#if CEF_API_ADDED(CEF_NEXT)
|
||||||
|
///
|
||||||
|
/// Called when JavaScript is requesting new bounds via window.moveTo/By() or
|
||||||
|
/// window.resizeTo/By(). |new_bounds| are in DIP screen coordinates.
|
||||||
|
///
|
||||||
|
/// With Views-hosted browsers |new_bounds| are the desired bounds for
|
||||||
|
/// the containing CefWindow and may be passed directly to
|
||||||
|
/// CefWindow::SetBounds. With external (client-provided) parent on macOS and
|
||||||
|
/// Windows |new_bounds| are the desired frame bounds for the containing root
|
||||||
|
/// window. With other non-Views browsers |new_bounds| are the desired bounds
|
||||||
|
/// for the browser content only unless the client implements either
|
||||||
|
/// CefDisplayHandler::GetRootWindowScreenRect for windowed browsers or
|
||||||
|
/// CefRenderHandler::GetWindowScreenRect for windowless browsers. Clients may
|
||||||
|
/// expand browser content bounds to window bounds using OS-specific or
|
||||||
|
/// CefDisplay methods.
|
||||||
|
///
|
||||||
|
/// Return true if this method was handled or false for default handling.
|
||||||
|
/// Default move/resize behavior is only provided with Views-hosted Chrome
|
||||||
|
/// style browsers.
|
||||||
|
///
|
||||||
|
/*--cef(added=next)--*/
|
||||||
|
virtual bool OnContentsBoundsChange(CefRefPtr<CefBrowser> browser,
|
||||||
|
const CefRect& new_bounds) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Called to retrieve the external (client-provided) root window rectangle in
|
||||||
|
/// screen DIP coordinates. Only called for windowed browsers on Windows and
|
||||||
|
/// Linux. Return true if the rectangle was provided. Return false to use the
|
||||||
|
/// root window bounds on Windows or the browser content bounds on Linux. For
|
||||||
|
/// additional usage details see CefBrowserHost::NotifyScreenInfoChanged.
|
||||||
|
///
|
||||||
|
/*--cef(added=next)--*/
|
||||||
|
virtual bool GetRootWindowScreenRect(CefRefPtr<CefBrowser> browser,
|
||||||
|
CefRect& rect) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_
|
#endif // CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_
|
||||||
|
@ -50,6 +50,9 @@
|
|||||||
/// indicated. Methods must be called on the browser process UI thread unless
|
/// indicated. Methods must be called on the browser process UI thread unless
|
||||||
/// otherwise indicated.
|
/// otherwise indicated.
|
||||||
///
|
///
|
||||||
|
/// For details on coordinate systems and usage see
|
||||||
|
/// https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage#markdown-header-coordinate-systems
|
||||||
|
///
|
||||||
/*--cef(source=library)--*/
|
/*--cef(source=library)--*/
|
||||||
class CefDisplay : public CefBaseRefCounted {
|
class CefDisplay : public CefBaseRefCounted {
|
||||||
public:
|
public:
|
||||||
@ -129,7 +132,9 @@ class CefDisplay : public CefBaseRefCounted {
|
|||||||
/// Returns this Display's device pixel scale factor. This specifies how much
|
/// Returns this Display's device pixel scale factor. This specifies how much
|
||||||
/// the UI should be scaled when the actual output has more pixels than
|
/// the UI should be scaled when the actual output has more pixels than
|
||||||
/// standard displays (which is around 100~120dpi). The potential return
|
/// standard displays (which is around 100~120dpi). The potential return
|
||||||
/// values differ by platform.
|
/// values differ by platform. Windowed browsers with 1.0 zoom will have a
|
||||||
|
/// JavaScript `window.devicePixelRatio` value matching the associated
|
||||||
|
/// Display's GetDeviceScaleFactor() value.
|
||||||
///
|
///
|
||||||
/*--cef()--*/
|
/*--cef()--*/
|
||||||
virtual float GetDeviceScaleFactor() = 0;
|
virtual float GetDeviceScaleFactor() = 0;
|
||||||
|
@ -416,24 +416,6 @@ void AlloyBrowserHostImpl::WasHidden(bool hidden) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlloyBrowserHostImpl::NotifyScreenInfoChanged() {
|
|
||||||
if (!IsWindowless()) {
|
|
||||||
DCHECK(false) << "Window rendering is not disabled";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
||||||
CEF_POST_TASK(
|
|
||||||
CEF_UIT,
|
|
||||||
base::BindOnce(&AlloyBrowserHostImpl::NotifyScreenInfoChanged, this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platform_delegate_) {
|
|
||||||
platform_delegate_->NotifyScreenInfoChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlloyBrowserHostImpl::Invalidate(PaintElementType type) {
|
void AlloyBrowserHostImpl::Invalidate(PaintElementType type) {
|
||||||
if (!IsWindowless()) {
|
if (!IsWindowless()) {
|
||||||
DCHECK(false) << "Window rendering is not disabled";
|
DCHECK(false) << "Window rendering is not disabled";
|
||||||
@ -998,6 +980,11 @@ void AlloyBrowserHostImpl::CloseContents(content::WebContents* source) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AlloyBrowserHostImpl::SetContentsBounds(content::WebContents* source,
|
||||||
|
const gfx::Rect& bounds) {
|
||||||
|
contents_delegate_.SetContentsBoundsEx(source, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
void AlloyBrowserHostImpl::UpdateTargetURL(content::WebContents* source,
|
void AlloyBrowserHostImpl::UpdateTargetURL(content::WebContents* source,
|
||||||
const GURL& url) {
|
const GURL& url) {
|
||||||
contents_delegate_.UpdateTargetURL(source, url);
|
contents_delegate_.UpdateTargetURL(source, url);
|
||||||
|
@ -90,7 +90,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
|
|||||||
bool IsWindowRenderingDisabled() override;
|
bool IsWindowRenderingDisabled() override;
|
||||||
void WasResized() override;
|
void WasResized() override;
|
||||||
void WasHidden(bool hidden) override;
|
void WasHidden(bool hidden) override;
|
||||||
void NotifyScreenInfoChanged() override;
|
|
||||||
void Invalidate(PaintElementType type) override;
|
void Invalidate(PaintElementType type) override;
|
||||||
void SendExternalBeginFrame() override;
|
void SendExternalBeginFrame() override;
|
||||||
void SendTouchEvent(const CefTouchEvent& event) override;
|
void SendTouchEvent(const CefTouchEvent& event) override;
|
||||||
@ -193,6 +192,8 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
|
|||||||
void LoadingStateChanged(content::WebContents* source,
|
void LoadingStateChanged(content::WebContents* source,
|
||||||
bool should_show_loading_ui) override;
|
bool should_show_loading_ui) override;
|
||||||
void CloseContents(content::WebContents* source) override;
|
void CloseContents(content::WebContents* source) override;
|
||||||
|
void SetContentsBounds(content::WebContents* source,
|
||||||
|
const gfx::Rect& bounds) override;
|
||||||
void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
|
void UpdateTargetURL(content::WebContents* source, const GURL& url) override;
|
||||||
bool DidAddMessageToConsole(content::WebContents* source,
|
bool DidAddMessageToConsole(content::WebContents* source,
|
||||||
blink::mojom::ConsoleMessageLevel log_level,
|
blink::mojom::ConsoleMessageLevel log_level,
|
||||||
|
@ -142,6 +142,18 @@ content::WebContents* CefBrowserContentsDelegate::OpenURLFromTabEx(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CefBrowserContentsDelegate::SetContentsBoundsEx(
|
||||||
|
content::WebContents* source,
|
||||||
|
const gfx::Rect& bounds) {
|
||||||
|
if (auto c = client()) {
|
||||||
|
if (auto handler = c->GetDisplayHandler()) {
|
||||||
|
return handler->OnContentsBoundsChange(
|
||||||
|
browser(), {bounds.x(), bounds.y(), bounds.width(), bounds.height()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void CefBrowserContentsDelegate::LoadingStateChanged(
|
void CefBrowserContentsDelegate::LoadingStateChanged(
|
||||||
content::WebContents* source,
|
content::WebContents* source,
|
||||||
bool should_show_loading_ui) {
|
bool should_show_loading_ui) {
|
||||||
|
@ -87,6 +87,10 @@ class CefBrowserContentsDelegate : public content::WebContentsDelegate,
|
|||||||
base::OnceCallback<void(content::NavigationHandle&)>&
|
base::OnceCallback<void(content::NavigationHandle&)>&
|
||||||
navigation_handle_callback);
|
navigation_handle_callback);
|
||||||
|
|
||||||
|
// Same as SetContentsBounds but returning false if unhandled.
|
||||||
|
bool SetContentsBoundsEx(content::WebContents* source,
|
||||||
|
const gfx::Rect& bounds);
|
||||||
|
|
||||||
// WebContentsDelegate methods:
|
// WebContentsDelegate methods:
|
||||||
void LoadingStateChanged(content::WebContents* source,
|
void LoadingStateChanged(content::WebContents* source,
|
||||||
bool should_show_loading_ui) override;
|
bool should_show_loading_ui) override;
|
||||||
|
@ -817,9 +817,30 @@ void CefBrowserHostBase::NotifyMoveOrResizeStarted() {
|
|||||||
if (platform_delegate_) {
|
if (platform_delegate_) {
|
||||||
platform_delegate_->NotifyMoveOrResizeStarted();
|
platform_delegate_->NotifyMoveOrResizeStarted();
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
LOG(WARNING)
|
||||||
|
<< "Incorrect usage of CefBrowserHost::NotifyMoveOrResizeStarted";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefBrowserHostBase::NotifyScreenInfoChanged() {
|
||||||
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||||
|
CEF_POST_TASK(
|
||||||
|
CEF_UIT,
|
||||||
|
base::BindOnce(&CefBrowserHostBase::NotifyScreenInfoChanged, this));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform_delegate_) {
|
||||||
|
if (IsWindowless() || platform_delegate_->HasExternalParent()) {
|
||||||
|
platform_delegate_->NotifyScreenInfoChanged();
|
||||||
|
} else {
|
||||||
|
LOG(WARNING)
|
||||||
|
<< "Incorrect usage of CefBrowserHost::NotifyScreenInfoChanged";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CefBrowserHostBase::IsFullscreen() {
|
bool CefBrowserHostBase::IsFullscreen() {
|
||||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||||
DCHECK(false) << "called on invalid thread";
|
DCHECK(false) << "called on invalid thread";
|
||||||
|
@ -265,6 +265,7 @@ class CefBrowserHostBase : public CefBrowserHost,
|
|||||||
void SetAudioMuted(bool mute) override;
|
void SetAudioMuted(bool mute) override;
|
||||||
bool IsAudioMuted() override;
|
bool IsAudioMuted() override;
|
||||||
void NotifyMoveOrResizeStarted() override;
|
void NotifyMoveOrResizeStarted() override;
|
||||||
|
void NotifyScreenInfoChanged() override;
|
||||||
bool IsFullscreen() override;
|
bool IsFullscreen() override;
|
||||||
void ExitFullscreen(bool will_cause_resize) override;
|
void ExitFullscreen(bool will_cause_resize) override;
|
||||||
bool IsRenderProcessUnresponsive() override;
|
bool IsRenderProcessUnresponsive() override;
|
||||||
|
@ -244,8 +244,7 @@ void CefBrowserPlatformDelegate::PopupBrowserCreated(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefBrowserView> new_browser_view =
|
auto new_browser_view = new_browser->GetBrowserView();
|
||||||
CefBrowserView::GetForBrowser(new_browser);
|
|
||||||
CHECK(new_browser_view);
|
CHECK(new_browser_view);
|
||||||
|
|
||||||
bool popup_handled = false;
|
bool popup_handled = false;
|
||||||
@ -389,9 +388,7 @@ bool CefBrowserPlatformDelegate::IsHidden() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserPlatformDelegate::NotifyScreenInfoChanged() {
|
void CefBrowserPlatformDelegate::NotifyScreenInfoChanged() {}
|
||||||
DCHECK(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserPlatformDelegate::Invalidate(cef_paint_element_type_t type) {
|
void CefBrowserPlatformDelegate::Invalidate(cef_paint_element_type_t type) {
|
||||||
DCHECK(false);
|
DCHECK(false);
|
||||||
|
@ -306,7 +306,7 @@ class CefBrowserPlatformDelegate {
|
|||||||
virtual bool IsHidden() const;
|
virtual bool IsHidden() const;
|
||||||
|
|
||||||
// Notify the browser that screen information has changed. Only used with
|
// Notify the browser that screen information has changed. Only used with
|
||||||
// windowless rendering.
|
// windowless rendering and external (client-provided) root window.
|
||||||
virtual void NotifyScreenInfoChanged();
|
virtual void NotifyScreenInfoChanged();
|
||||||
|
|
||||||
// Invalidate the view. Only used with windowless rendering.
|
// Invalidate the view. Only used with windowless rendering.
|
||||||
|
@ -173,6 +173,12 @@ class BrowserDelegate : public content::WebContentsDelegate {
|
|||||||
navigation_handle_callback) {
|
navigation_handle_callback) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same as SetContentsBounds but returning false if unhandled.
|
||||||
|
virtual bool SetContentsBoundsEx(content::WebContents* source,
|
||||||
|
const gfx::Rect& bounds) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cef
|
} // namespace cef
|
||||||
|
@ -573,6 +573,14 @@ bool ChromeBrowserDelegate::OpenURLFromTabEx(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChromeBrowserDelegate::SetContentsBoundsEx(content::WebContents* source,
|
||||||
|
const gfx::Rect& bounds) {
|
||||||
|
if (auto delegate = GetDelegateForWebContents(source)) {
|
||||||
|
return delegate->SetContentsBoundsEx(source, bounds);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ChromeBrowserDelegate::LoadingStateChanged(content::WebContents* source,
|
void ChromeBrowserDelegate::LoadingStateChanged(content::WebContents* source,
|
||||||
bool should_show_loading_ui) {
|
bool should_show_loading_ui) {
|
||||||
if (auto delegate = GetDelegateForWebContents(source)) {
|
if (auto delegate = GetDelegateForWebContents(source)) {
|
||||||
|
@ -94,6 +94,8 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate {
|
|||||||
const content::OpenURLParams& params,
|
const content::OpenURLParams& params,
|
||||||
base::OnceCallback<void(content::NavigationHandle&)>&
|
base::OnceCallback<void(content::NavigationHandle&)>&
|
||||||
navigation_handle_callback) override;
|
navigation_handle_callback) override;
|
||||||
|
bool SetContentsBoundsEx(content::WebContents* source,
|
||||||
|
const gfx::Rect& bounds) override;
|
||||||
|
|
||||||
// WebContentsDelegate methods:
|
// WebContentsDelegate methods:
|
||||||
void WebContentsCreated(content::WebContents* source_contents,
|
void WebContentsCreated(content::WebContents* source_contents,
|
||||||
|
@ -250,10 +250,6 @@ void ChromeBrowserHostImpl::WasHidden(bool hidden) {
|
|||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChromeBrowserHostImpl::NotifyScreenInfoChanged() {
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChromeBrowserHostImpl::Invalidate(PaintElementType type) {
|
void ChromeBrowserHostImpl::Invalidate(PaintElementType type) {
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,6 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
|
|||||||
bool IsWindowRenderingDisabled() override { return false; }
|
bool IsWindowRenderingDisabled() override { return false; }
|
||||||
void WasResized() override;
|
void WasResized() override;
|
||||||
void WasHidden(bool hidden) override;
|
void WasHidden(bool hidden) override;
|
||||||
void NotifyScreenInfoChanged() override;
|
|
||||||
void Invalidate(PaintElementType type) override;
|
void Invalidate(PaintElementType type) override;
|
||||||
void SendExternalBeginFrame() override;
|
void SendExternalBeginFrame() override;
|
||||||
void SendTouchEvent(const CefTouchEvent& event) override;
|
void SendTouchEvent(const CefTouchEvent& event) override;
|
||||||
|
@ -14,6 +14,10 @@
|
|||||||
#include "ui/views/win/hwnd_util.h"
|
#include "ui/views/win/hwnd_util.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_AURA)
|
||||||
|
#include "cef/libcef/browser/native/browser_platform_delegate_native_aura.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
gfx::AcceleratedWidget GetParentWidget(const CefWindowInfo& window_info) {
|
gfx::AcceleratedWidget GetParentWidget(const CefWindowInfo& window_info) {
|
||||||
@ -61,6 +65,9 @@ class ChildWindowDelegate : public CefWindowDelegate {
|
|||||||
void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
|
void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
|
||||||
browser_view_ = nullptr;
|
browser_view_ = nullptr;
|
||||||
window_ = nullptr;
|
window_ = nullptr;
|
||||||
|
#if BUILDFLAG(IS_WIN)
|
||||||
|
native_delegate_ = nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRect GetInitialBounds(CefRefPtr<CefWindow> window) override {
|
CefRect GetInitialBounds(CefRefPtr<CefWindow> window) override {
|
||||||
@ -71,22 +78,38 @@ class ChildWindowDelegate : public CefWindowDelegate {
|
|||||||
return initial_bounds;
|
return initial_bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(USE_AURA)
|
||||||
|
void OnWindowBoundsChanged(CefRefPtr<CefWindow> window,
|
||||||
|
const CefRect& new_bounds) override {
|
||||||
|
if (native_delegate_) {
|
||||||
|
// Send new bounds to the renderer process and trigger the resize event.
|
||||||
|
native_delegate_->NotifyScreenInfoChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
void ShowWindow() {
|
void ShowWindow() {
|
||||||
|
#if defined(USE_AURA)
|
||||||
|
auto browser = CefBrowserHostBase::FromBrowser(browser_view_->GetBrowser());
|
||||||
|
auto platform_delegate = browser->platform_delegate();
|
||||||
|
DCHECK(platform_delegate->IsViewsHosted());
|
||||||
|
auto chrome_delegate =
|
||||||
|
static_cast<CefBrowserPlatformDelegateChromeViews*>(platform_delegate);
|
||||||
|
native_delegate_ = static_cast<CefBrowserPlatformDelegateNativeAura*>(
|
||||||
|
chrome_delegate->native_delegate());
|
||||||
|
native_delegate_->InstallRootWindowBoundsCallback();
|
||||||
|
|
||||||
#if BUILDFLAG(IS_WIN)
|
#if BUILDFLAG(IS_WIN)
|
||||||
auto widget = static_cast<CefWindowImpl*>(window_.get())->widget();
|
auto widget = static_cast<CefWindowImpl*>(window_.get())->widget();
|
||||||
DCHECK(widget);
|
DCHECK(widget);
|
||||||
const HWND widget_hwnd = HWNDForWidget(widget);
|
const HWND widget_hwnd = HWNDForWidget(widget);
|
||||||
DCHECK(widget_hwnd);
|
DCHECK(widget_hwnd);
|
||||||
|
|
||||||
// The native delegate needs state to perform some actions.
|
// The Windows delegate needs state to perform some actions.
|
||||||
auto browser = CefBrowserHostBase::FromBrowser(browser_view_->GetBrowser());
|
auto* delegate_win =
|
||||||
auto platform_delegate = browser->platform_delegate();
|
static_cast<CefBrowserPlatformDelegateNativeWin*>(native_delegate_);
|
||||||
DCHECK(platform_delegate->IsViewsHosted());
|
delegate_win->set_widget(widget, widget_hwnd);
|
||||||
auto chrome_delegate =
|
|
||||||
static_cast<CefBrowserPlatformDelegateChromeViews*>(platform_delegate);
|
|
||||||
auto native_delegate = static_cast<CefBrowserPlatformDelegateNativeWin*>(
|
|
||||||
chrome_delegate->native_delegate());
|
|
||||||
native_delegate->set_widget(widget, widget_hwnd);
|
|
||||||
|
|
||||||
if (window_info_.ex_style & WS_EX_NOACTIVATE) {
|
if (window_info_.ex_style & WS_EX_NOACTIVATE) {
|
||||||
const DWORD widget_ex_styles = GetWindowLongPtr(widget_hwnd, GWL_EXSTYLE);
|
const DWORD widget_ex_styles = GetWindowLongPtr(widget_hwnd, GWL_EXSTYLE);
|
||||||
@ -105,6 +128,7 @@ class ChildWindowDelegate : public CefWindowDelegate {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif // BUILDFLAG(IS_WIN)
|
#endif // BUILDFLAG(IS_WIN)
|
||||||
|
#endif // defined(USE_AURA)
|
||||||
|
|
||||||
window_->Show();
|
window_->Show();
|
||||||
|
|
||||||
@ -112,7 +136,6 @@ class ChildWindowDelegate : public CefWindowDelegate {
|
|||||||
browser_view_->RequestFocus();
|
browser_view_->RequestFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
ChildWindowDelegate(CefRefPtr<CefBrowserView> browser_view,
|
ChildWindowDelegate(CefRefPtr<CefBrowserView> browser_view,
|
||||||
const CefWindowInfo& window_info)
|
const CefWindowInfo& window_info)
|
||||||
: browser_view_(browser_view), window_info_(window_info) {}
|
: browser_view_(browser_view), window_info_(window_info) {}
|
||||||
@ -122,6 +145,11 @@ class ChildWindowDelegate : public CefWindowDelegate {
|
|||||||
|
|
||||||
CefRefPtr<CefWindow> window_;
|
CefRefPtr<CefWindow> window_;
|
||||||
|
|
||||||
|
#if defined(USE_AURA)
|
||||||
|
base::raw_ptr<CefBrowserPlatformDelegateNativeAura> native_delegate_ =
|
||||||
|
nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(ChildWindowDelegate);
|
IMPLEMENT_REFCOUNTING(ChildWindowDelegate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "cef/libcef/browser/native/browser_platform_delegate_native.h"
|
#include "cef/libcef/browser/native/browser_platform_delegate_native.h"
|
||||||
|
|
||||||
#include "cef/libcef/browser/alloy/alloy_browser_host_impl.h"
|
#include "cef/libcef/browser/alloy/alloy_browser_host_impl.h"
|
||||||
|
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||||
#include "content/public/browser/render_view_host.h"
|
#include "content/public/browser/render_view_host.h"
|
||||||
#include "content/public/browser/render_widget_host.h"
|
#include "content/public/browser/render_widget_host.h"
|
||||||
#include "third_party/blink/public/common/input/web_mouse_event.h"
|
#include "third_party/blink/public/common/input/web_mouse_event.h"
|
||||||
@ -24,3 +25,25 @@ void CefBrowserPlatformDelegateNative::WasResized() {
|
|||||||
host->GetWidget()->SynchronizeVisualProperties();
|
host->GetWidget()->SynchronizeVisualProperties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNative::NotifyScreenInfoChanged() {
|
||||||
|
content::RenderWidgetHostImpl* render_widget_host = nullptr;
|
||||||
|
if (web_contents_) {
|
||||||
|
if (auto* rvh = web_contents_->GetRenderViewHost()) {
|
||||||
|
render_widget_host =
|
||||||
|
content::RenderWidgetHostImpl::From(rvh->GetWidget());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!render_widget_host) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send updated screen bounds information to the renderer process.
|
||||||
|
if (render_widget_host->delegate()) {
|
||||||
|
render_widget_host->delegate()->SendScreenRects();
|
||||||
|
} else {
|
||||||
|
render_widget_host->SendScreenRects();
|
||||||
|
}
|
||||||
|
|
||||||
|
render_widget_host->NotifyScreenInfoChanged();
|
||||||
|
}
|
||||||
|
@ -32,6 +32,7 @@ class CefBrowserPlatformDelegateNative
|
|||||||
// CefBrowserPlatformDelegate methods:
|
// CefBrowserPlatformDelegate methods:
|
||||||
SkColor GetBackgroundColor() const override;
|
SkColor GetBackgroundColor() const override;
|
||||||
void WasResized() override;
|
void WasResized() override;
|
||||||
|
void NotifyScreenInfoChanged() override;
|
||||||
|
|
||||||
// Translate CEF events to Chromium/Blink Web events.
|
// Translate CEF events to Chromium/Blink Web events.
|
||||||
virtual input::NativeWebKeyboardEvent TranslateWebKeyEvent(
|
virtual input::NativeWebKeyboardEvent TranslateWebKeyEvent(
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "cef/libcef/browser/native/browser_platform_delegate_native_aura.h"
|
#include "cef/libcef/browser/native/browser_platform_delegate_native_aura.h"
|
||||||
|
|
||||||
|
#include "cef/libcef/browser/browser_host_base.h"
|
||||||
#include "cef/libcef/browser/native/menu_runner_views_aura.h"
|
#include "cef/libcef/browser/native/menu_runner_views_aura.h"
|
||||||
#include "cef/libcef/browser/views/view_util.h"
|
#include "cef/libcef/browser/views/view_util.h"
|
||||||
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
|
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
|
||||||
@ -19,6 +20,42 @@ CefBrowserPlatformDelegateNativeAura::CefBrowserPlatformDelegateNativeAura(
|
|||||||
SkColor background_color)
|
SkColor background_color)
|
||||||
: CefBrowserPlatformDelegateNative(window_info, background_color) {}
|
: CefBrowserPlatformDelegateNative(window_info, background_color) {}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeAura::InstallRootWindowBoundsCallback() {
|
||||||
|
auto* host_view = GetHostView();
|
||||||
|
CHECK(host_view);
|
||||||
|
|
||||||
|
host_view->SetRootWindowBoundsCallback(base::BindRepeating(
|
||||||
|
[](base::WeakPtr<CefBrowserPlatformDelegateNativeAura> self) {
|
||||||
|
return self->RootWindowBoundsCallback();
|
||||||
|
},
|
||||||
|
weak_ptr_factory_.GetWeakPtr()));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<gfx::Rect>
|
||||||
|
CefBrowserPlatformDelegateNativeAura::RootWindowBoundsCallback() {
|
||||||
|
if (browser_) {
|
||||||
|
if (auto client = browser_->client()) {
|
||||||
|
if (auto handler = client->GetDisplayHandler()) {
|
||||||
|
CefRect rect;
|
||||||
|
if (handler->GetRootWindowScreenRect(browser_.get(), rect) &&
|
||||||
|
!rect.IsEmpty()) {
|
||||||
|
return gfx::Rect(rect.x, rect.y, rect.width, rect.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the default platform implementation, if any.
|
||||||
|
return GetRootWindowBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeAura::RenderViewReady() {
|
||||||
|
CefBrowserPlatformDelegateNative::RenderViewReady();
|
||||||
|
|
||||||
|
// The RWHV should now exist for Alloy style browsers.
|
||||||
|
InstallRootWindowBoundsCallback();
|
||||||
|
}
|
||||||
|
|
||||||
void CefBrowserPlatformDelegateNativeAura::SendKeyEvent(
|
void CefBrowserPlatformDelegateNativeAura::SendKeyEvent(
|
||||||
const CefKeyEvent& event) {
|
const CefKeyEvent& event) {
|
||||||
auto view = GetHostView();
|
auto view = GetHostView();
|
||||||
|
@ -5,19 +5,19 @@
|
|||||||
#ifndef CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_AURA_H_
|
#ifndef CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_AURA_H_
|
||||||
#define CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_AURA_H_
|
#define CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_AURA_H_
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "base/memory/raw_ptr.h"
|
#include "base/memory/raw_ptr.h"
|
||||||
#include "base/memory/weak_ptr.h"
|
#include "base/memory/weak_ptr.h"
|
||||||
#include "cef/libcef/browser/native/browser_platform_delegate_native.h"
|
#include "cef/libcef/browser/native/browser_platform_delegate_native.h"
|
||||||
#include "ui/events/event.h"
|
#include "ui/events/event.h"
|
||||||
|
#include "ui/gfx/geometry/rect.h"
|
||||||
|
#include "ui/gfx/geometry/vector2d.h"
|
||||||
|
|
||||||
namespace content {
|
namespace content {
|
||||||
class RenderWidgetHostViewAura;
|
class RenderWidgetHostViewAura;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace gfx {
|
|
||||||
class Vector2d;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Windowed browser implementation for Aura platforms.
|
// Windowed browser implementation for Aura platforms.
|
||||||
class CefBrowserPlatformDelegateNativeAura
|
class CefBrowserPlatformDelegateNativeAura
|
||||||
: public CefBrowserPlatformDelegateNative {
|
: public CefBrowserPlatformDelegateNative {
|
||||||
@ -25,7 +25,10 @@ class CefBrowserPlatformDelegateNativeAura
|
|||||||
CefBrowserPlatformDelegateNativeAura(const CefWindowInfo& window_info,
|
CefBrowserPlatformDelegateNativeAura(const CefWindowInfo& window_info,
|
||||||
SkColor background_color);
|
SkColor background_color);
|
||||||
|
|
||||||
|
void InstallRootWindowBoundsCallback();
|
||||||
|
|
||||||
// CefBrowserPlatformDelegate methods:
|
// CefBrowserPlatformDelegate methods:
|
||||||
|
void RenderViewReady() override;
|
||||||
void SendKeyEvent(const CefKeyEvent& event) override;
|
void SendKeyEvent(const CefKeyEvent& event) override;
|
||||||
void SendMouseClickEvent(const CefMouseEvent& event,
|
void SendMouseClickEvent(const CefMouseEvent& event,
|
||||||
CefBrowserHost::MouseButtonType type,
|
CefBrowserHost::MouseButtonType type,
|
||||||
@ -71,9 +74,16 @@ class CefBrowserPlatformDelegateNativeAura
|
|||||||
int deltaY) const;
|
int deltaY) const;
|
||||||
virtual gfx::Vector2d GetUiWheelEventOffset(int deltaX, int deltaY) const;
|
virtual gfx::Vector2d GetUiWheelEventOffset(int deltaX, int deltaY) const;
|
||||||
|
|
||||||
|
// Returns the root window bounds in screen DIP coordinates.
|
||||||
|
virtual std::optional<gfx::Rect> GetRootWindowBounds() {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
base::OnceClosure GetWidgetDeleteCallback();
|
base::OnceClosure GetWidgetDeleteCallback();
|
||||||
|
|
||||||
|
std::optional<gfx::Rect> RootWindowBoundsCallback();
|
||||||
|
|
||||||
static base::TimeTicks GetEventTimeStamp();
|
static base::TimeTicks GetEventTimeStamp();
|
||||||
static int TranslateUiEventModifiers(uint32_t cef_modifiers);
|
static int TranslateUiEventModifiers(uint32_t cef_modifiers);
|
||||||
static int TranslateUiChangedButtonFlags(uint32_t cef_modifiers);
|
static int TranslateUiChangedButtonFlags(uint32_t cef_modifiers);
|
||||||
|
@ -427,6 +427,27 @@ CefEventHandle CefBrowserPlatformDelegateNativeWin::GetEventHandle(
|
|||||||
const_cast<CHROME_MSG*>(&event.os_event->native_event()));
|
const_cast<CHROME_MSG*>(&event.os_event->native_event()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<gfx::Rect>
|
||||||
|
CefBrowserPlatformDelegateNativeWin::GetRootWindowBounds() {
|
||||||
|
if (window_widget_) {
|
||||||
|
if (HWND hwnd = GetHostWindowHandle()) {
|
||||||
|
if (HWND root_hwnd = ::GetAncestor(hwnd, GA_ROOT)) {
|
||||||
|
RECT root_rect = {};
|
||||||
|
if (::GetWindowRect(root_hwnd, &root_rect)) {
|
||||||
|
auto* top_level =
|
||||||
|
window_widget_->GetNativeWindow()->GetToplevelWindow();
|
||||||
|
gfx::Rect bounds(root_rect);
|
||||||
|
bounds = display::Screen::GetScreen()->ScreenToDIPRectInWindow(
|
||||||
|
top_level, bounds);
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
ui::KeyEvent CefBrowserPlatformDelegateNativeWin::TranslateUiKeyEvent(
|
ui::KeyEvent CefBrowserPlatformDelegateNativeWin::TranslateUiKeyEvent(
|
||||||
const CefKeyEvent& key_event) const {
|
const CefKeyEvent& key_event) const {
|
||||||
int flags = TranslateUiEventModifiers(key_event.modifiers);
|
int flags = TranslateUiEventModifiers(key_event.modifiers);
|
||||||
@ -596,8 +617,8 @@ LRESULT CALLBACK CefBrowserPlatformDelegateNativeWin::WndProc(HWND hwnd,
|
|||||||
|
|
||||||
case WM_MOVING:
|
case WM_MOVING:
|
||||||
case WM_MOVE:
|
case WM_MOVE:
|
||||||
if (browser) {
|
if (platform_delegate) {
|
||||||
browser->NotifyMoveOrResizeStarted();
|
platform_delegate->NotifyMoveOrResizeStarted();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ class CefBrowserPlatformDelegateNativeWin
|
|||||||
bool HandleKeyboardEvent(const input::NativeWebKeyboardEvent& event) override;
|
bool HandleKeyboardEvent(const input::NativeWebKeyboardEvent& event) override;
|
||||||
CefEventHandle GetEventHandle(
|
CefEventHandle GetEventHandle(
|
||||||
const input::NativeWebKeyboardEvent& event) const override;
|
const input::NativeWebKeyboardEvent& event) const override;
|
||||||
|
std::optional<gfx::Rect> GetRootWindowBounds() override;
|
||||||
|
|
||||||
// CefBrowserPlatformDelegateNativeAura methods:
|
// CefBrowserPlatformDelegateNativeAura methods:
|
||||||
ui::KeyEvent TranslateUiKeyEvent(const CefKeyEvent& key_event) const override;
|
ui::KeyEvent TranslateUiKeyEvent(const CefKeyEvent& key_event) const override;
|
||||||
|
@ -393,7 +393,10 @@ patches = [
|
|||||||
#
|
#
|
||||||
# Windows: Fix crash during window creation.
|
# Windows: Fix crash during window creation.
|
||||||
# https://bugs.chromium.org/p/chromium/issues/detail?id=761389
|
# https://bugs.chromium.org/p/chromium/issues/detail?id=761389
|
||||||
'name': 'rwh_background_color_1984',
|
#
|
||||||
|
# Add RWHVAura::SetRootWindowBoundsCallback.
|
||||||
|
# https://github.com/chromiumembedded/cef/issues/3920
|
||||||
|
'name': 'renderer_host_aura',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
# Expose RFH via NavigationHandle for retrieval in DidFinishNavigation on
|
# Expose RFH via NavigationHandle for retrieval in DidFinishNavigation on
|
||||||
|
@ -136,7 +136,7 @@ index 51c55cb054ae7..df9aa9bc45a67 100644
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc
|
diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc
|
||||||
index d45f8f1713c87..7d69f3d8bd4cc 100644
|
index d45f8f1713c87..de476f1ed4081 100644
|
||||||
--- chrome/browser/ui/browser.cc
|
--- chrome/browser/ui/browser.cc
|
||||||
+++ chrome/browser/ui/browser.cc
|
+++ chrome/browser/ui/browser.cc
|
||||||
@@ -272,6 +272,25 @@
|
@@ -272,6 +272,25 @@
|
||||||
@ -285,7 +285,21 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Browser::CloseContents(WebContents* source) {
|
void Browser::CloseContents(WebContents* source) {
|
||||||
@@ -2177,6 +2246,8 @@ void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) {
|
@@ -2157,6 +2226,13 @@ void Browser::CloseContents(WebContents* source) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) {
|
||||||
|
+#if BUILDFLAG(ENABLE_CEF)
|
||||||
|
+ if (cef_browser_delegate_ &&
|
||||||
|
+ cef_browser_delegate_->SetContentsBoundsEx(source, bounds)) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
if (is_type_normal()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@@ -2177,6 +2253,8 @@ void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browser::UpdateTargetURL(WebContents* source, const GURL& url) {
|
void Browser::UpdateTargetURL(WebContents* source, const GURL& url) {
|
||||||
@ -294,7 +308,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
std::vector<StatusBubble*> status_bubbles = GetStatusBubbles();
|
std::vector<StatusBubble*> status_bubbles = GetStatusBubbles();
|
||||||
for (StatusBubble* status_bubble : status_bubbles) {
|
for (StatusBubble* status_bubble : status_bubbles) {
|
||||||
StatusBubbleViews* status_bubble_views =
|
StatusBubbleViews* status_bubble_views =
|
||||||
@@ -2190,6 +2261,17 @@ void Browser::UpdateTargetURL(WebContents* source, const GURL& url) {
|
@@ -2190,6 +2268,17 @@ void Browser::UpdateTargetURL(WebContents* source, const GURL& url) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +326,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
void Browser::ContentsMouseEvent(WebContents* source, const ui::Event& event) {
|
void Browser::ContentsMouseEvent(WebContents* source, const ui::Event& event) {
|
||||||
const ui::EventType type = event.type();
|
const ui::EventType type = event.type();
|
||||||
const bool exited = type == ui::EventType::kMouseExited;
|
const bool exited = type == ui::EventType::kMouseExited;
|
||||||
@@ -2223,9 +2305,23 @@ void Browser::ContentsZoomChange(bool zoom_in) {
|
@@ -2223,9 +2312,23 @@ void Browser::ContentsZoomChange(bool zoom_in) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Browser::TakeFocus(content::WebContents* source, bool reverse) {
|
bool Browser::TakeFocus(content::WebContents* source, bool reverse) {
|
||||||
@ -336,7 +350,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
void Browser::BeforeUnloadFired(WebContents* web_contents,
|
void Browser::BeforeUnloadFired(WebContents* web_contents,
|
||||||
bool proceed,
|
bool proceed,
|
||||||
bool* proceed_to_fire_unload) {
|
bool* proceed_to_fire_unload) {
|
||||||
@@ -2338,12 +2434,24 @@ void Browser::WebContentsCreated(WebContents* source_contents,
|
@@ -2338,12 +2441,24 @@ void Browser::WebContentsCreated(WebContents* source_contents,
|
||||||
// to track `new_contents` after it is added to its TabModel this override can
|
// to track `new_contents` after it is added to its TabModel this override can
|
||||||
// be removed.
|
// be removed.
|
||||||
CreateSessionServiceTabHelper(new_contents);
|
CreateSessionServiceTabHelper(new_contents);
|
||||||
@ -361,7 +375,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
// Don't show the page hung dialog when a HTML popup hangs because
|
// Don't show the page hung dialog when a HTML popup hangs because
|
||||||
// the dialog will take the focus and immediately close the popup.
|
// the dialog will take the focus and immediately close the popup.
|
||||||
RenderWidgetHostView* view = render_widget_host->GetView();
|
RenderWidgetHostView* view = render_widget_host->GetView();
|
||||||
@@ -2356,6 +2464,13 @@ void Browser::RendererUnresponsive(
|
@@ -2356,6 +2471,13 @@ void Browser::RendererUnresponsive(
|
||||||
void Browser::RendererResponsive(
|
void Browser::RendererResponsive(
|
||||||
WebContents* source,
|
WebContents* source,
|
||||||
content::RenderWidgetHost* render_widget_host) {
|
content::RenderWidgetHost* render_widget_host) {
|
||||||
@ -375,7 +389,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
RenderWidgetHostView* view = render_widget_host->GetView();
|
RenderWidgetHostView* view = render_widget_host->GetView();
|
||||||
if (view && !render_widget_host->GetView()->IsHTMLFormPopup()) {
|
if (view && !render_widget_host->GetView()->IsHTMLFormPopup()) {
|
||||||
TabDialogs::FromWebContents(source)->HideHungRendererDialog(
|
TabDialogs::FromWebContents(source)->HideHungRendererDialog(
|
||||||
@@ -2365,6 +2480,15 @@ void Browser::RendererResponsive(
|
@@ -2365,6 +2487,15 @@ void Browser::RendererResponsive(
|
||||||
|
|
||||||
content::JavaScriptDialogManager* Browser::GetJavaScriptDialogManager(
|
content::JavaScriptDialogManager* Browser::GetJavaScriptDialogManager(
|
||||||
WebContents* source) {
|
WebContents* source) {
|
||||||
@ -391,7 +405,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
return javascript_dialogs::TabModalDialogManager::FromWebContents(source);
|
return javascript_dialogs::TabModalDialogManager::FromWebContents(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2400,6 +2524,11 @@ void Browser::DraggableRegionsChanged(
|
@@ -2400,6 +2531,11 @@ void Browser::DraggableRegionsChanged(
|
||||||
if (app_controller_) {
|
if (app_controller_) {
|
||||||
app_controller_->DraggableRegionsChanged(regions, contents);
|
app_controller_->DraggableRegionsChanged(regions, contents);
|
||||||
}
|
}
|
||||||
@ -403,7 +417,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<blink::mojom::RelatedApplicationPtr>
|
std::vector<blink::mojom::RelatedApplicationPtr>
|
||||||
@@ -2514,11 +2643,15 @@ void Browser::EnterFullscreenModeForTab(
|
@@ -2514,11 +2650,15 @@ void Browser::EnterFullscreenModeForTab(
|
||||||
const blink::mojom::FullscreenOptions& options) {
|
const blink::mojom::FullscreenOptions& options) {
|
||||||
exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab(
|
exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab(
|
||||||
requesting_frame, options.display_id);
|
requesting_frame, options.display_id);
|
||||||
@ -419,7 +433,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) {
|
bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) {
|
||||||
@@ -2728,6 +2861,16 @@ void Browser::RequestMediaAccessPermission(
|
@@ -2728,6 +2868,16 @@ void Browser::RequestMediaAccessPermission(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
const content::MediaStreamRequest& request,
|
const content::MediaStreamRequest& request,
|
||||||
content::MediaResponseCallback callback) {
|
content::MediaResponseCallback callback) {
|
||||||
@ -436,7 +450,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
const extensions::Extension* extension =
|
const extensions::Extension* extension =
|
||||||
GetExtensionForOrigin(profile_, request.security_origin);
|
GetExtensionForOrigin(profile_, request.security_origin);
|
||||||
MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
|
MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
|
||||||
@@ -3313,9 +3456,11 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) {
|
@@ -3313,9 +3463,11 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) {
|
||||||
// Browser, Getters for UI (private):
|
// Browser, Getters for UI (private):
|
||||||
|
|
||||||
std::vector<StatusBubble*> Browser::GetStatusBubbles() {
|
std::vector<StatusBubble*> Browser::GetStatusBubbles() {
|
||||||
@ -449,7 +463,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We hide the status bar for web apps windows as this matches native
|
// We hide the status bar for web apps windows as this matches native
|
||||||
@@ -3323,6 +3468,12 @@ std::vector<StatusBubble*> Browser::GetStatusBubbles() {
|
@@ -3323,6 +3475,12 @@ std::vector<StatusBubble*> Browser::GetStatusBubbles() {
|
||||||
// mode, as the minimal browser UI includes the status bar.
|
// mode, as the minimal browser UI includes the status bar.
|
||||||
if (web_app::AppBrowserController::IsWebApp(this) &&
|
if (web_app::AppBrowserController::IsWebApp(this) &&
|
||||||
!app_controller()->HasMinimalUiButtons()) {
|
!app_controller()->HasMinimalUiButtons()) {
|
||||||
@ -462,7 +476,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3476,6 +3627,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) {
|
@@ -3476,6 +3634,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) {
|
||||||
BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this);
|
BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this);
|
||||||
web_contents_collection_.StopObserving(web_contents);
|
web_contents_collection_.StopObserving(web_contents);
|
||||||
}
|
}
|
||||||
@ -471,7 +485,7 @@ index d45f8f1713c87..7d69f3d8bd4cc 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Browser::TabDetachedAtImpl(content::WebContents* contents,
|
void Browser::TabDetachedAtImpl(content::WebContents* contents,
|
||||||
@@ -3637,6 +3790,14 @@ bool Browser::PictureInPictureBrowserSupportsWindowFeature(
|
@@ -3637,6 +3797,14 @@ bool Browser::PictureInPictureBrowserSupportsWindowFeature(
|
||||||
|
|
||||||
bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
|
bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
|
||||||
bool check_can_support) const {
|
bool check_can_support) const {
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
diff --git content/browser/renderer_host/render_widget_host_view_aura.cc content/browser/renderer_host/render_widget_host_view_aura.cc
|
diff --git content/browser/renderer_host/render_widget_host_view_aura.cc content/browser/renderer_host/render_widget_host_view_aura.cc
|
||||||
index 5867fc3e77326..54ac130dea600 100644
|
index 5867fc3e77326..23656289851bc 100644
|
||||||
--- content/browser/renderer_host/render_widget_host_view_aura.cc
|
--- content/browser/renderer_host/render_widget_host_view_aura.cc
|
||||||
+++ content/browser/renderer_host/render_widget_host_view_aura.cc
|
+++ content/browser/renderer_host/render_widget_host_view_aura.cc
|
||||||
@@ -6,6 +6,7 @@
|
@@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
+#include <tuple>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
+#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "base/auto_reset.h"
|
||||||
@@ -52,6 +53,7 @@
|
@@ -52,6 +53,7 @@
|
||||||
#include "content/public/browser/content_browser_client.h"
|
#include "content/public/browser/content_browser_client.h"
|
||||||
#include "content/public/browser/device_service.h"
|
#include "content/public/browser/device_service.h"
|
||||||
@ -28,7 +28,20 @@ index 5867fc3e77326..54ac130dea600 100644
|
|||||||
SkColor color = *GetBackgroundColor();
|
SkColor color = *GetBackgroundColor();
|
||||||
window_->layer()->SetColor(color);
|
window_->layer()->SetColor(color);
|
||||||
}
|
}
|
||||||
@@ -2664,6 +2669,16 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
|
@@ -1102,6 +1107,12 @@ void RenderWidgetHostViewAura::TransformPointToRootSurface(gfx::PointF* point) {
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
|
||||||
|
+ if (!root_window_bounds_callback_.is_null()) {
|
||||||
|
+ if (auto bounds = root_window_bounds_callback_.Run()) {
|
||||||
|
+ return *bounds;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
aura::Window* top_level = window_->GetToplevelWindow();
|
||||||
|
gfx::Rect bounds(top_level->GetBoundsInScreen());
|
||||||
|
|
||||||
|
@@ -2664,6 +2675,16 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
|
||||||
window_->layer()->SetColor(GetBackgroundColor() ? *GetBackgroundColor()
|
window_->layer()->SetColor(GetBackgroundColor() ? *GetBackgroundColor()
|
||||||
: SK_ColorWHITE);
|
: SK_ColorWHITE);
|
||||||
UpdateFrameSinkIdRegistration();
|
UpdateFrameSinkIdRegistration();
|
||||||
@ -45,3 +58,29 @@ index 5867fc3e77326..54ac130dea600 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RenderWidgetHostViewAura::UpdateFrameSinkIdRegistration() {
|
void RenderWidgetHostViewAura::UpdateFrameSinkIdRegistration() {
|
||||||
|
diff --git content/browser/renderer_host/render_widget_host_view_aura.h content/browser/renderer_host/render_widget_host_view_aura.h
|
||||||
|
index 6f96b83c36ee0..52cc4b37f0bbe 100644
|
||||||
|
--- content/browser/renderer_host/render_widget_host_view_aura.h
|
||||||
|
+++ content/browser/renderer_host/render_widget_host_view_aura.h
|
||||||
|
@@ -451,6 +451,12 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
|
||||||
|
}
|
||||||
|
#endif // BUILDFLAG(IS_WIN)
|
||||||
|
|
||||||
|
+ using RootWindowBoundsCallback =
|
||||||
|
+ base::RepeatingCallback<std::optional<gfx::Rect>()>;
|
||||||
|
+ void SetRootWindowBoundsCallback(const RootWindowBoundsCallback& callback) {
|
||||||
|
+ root_window_bounds_callback_ = callback;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
protected:
|
||||||
|
~RenderWidgetHostViewAura() override;
|
||||||
|
|
||||||
|
@@ -874,6 +880,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
|
||||||
|
|
||||||
|
std::optional<display::ScopedDisplayObserver> display_observer_;
|
||||||
|
|
||||||
|
+ RootWindowBoundsCallback root_window_bounds_callback_;
|
||||||
|
+
|
||||||
|
base::WeakPtrFactory<RenderWidgetHostViewAura> weak_ptr_factory_{this};
|
||||||
|
};
|
||||||
|
|
@ -83,6 +83,16 @@ void BrowserWindow::OnAutoResize(const CefSize& new_size) {
|
|||||||
delegate_->OnAutoResize(new_size);
|
delegate_->OnAutoResize(new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BrowserWindow::OnContentsBounds(const CefRect& new_bounds) {
|
||||||
|
REQUIRE_MAIN_THREAD();
|
||||||
|
delegate_->OnContentsBounds(new_bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BrowserWindow::GetRootWindowScreenRect(CefRect& rect) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
return delegate_->GetRootWindowScreenRect(rect);
|
||||||
|
}
|
||||||
|
|
||||||
void BrowserWindow::OnSetLoadingState(bool isLoading,
|
void BrowserWindow::OnSetLoadingState(bool isLoading,
|
||||||
bool canGoBack,
|
bool canGoBack,
|
||||||
bool canGoForward) {
|
bool canGoForward) {
|
||||||
|
@ -20,7 +20,8 @@ namespace client {
|
|||||||
class BrowserWindow : public ClientHandler::Delegate {
|
class BrowserWindow : public ClientHandler::Delegate {
|
||||||
public:
|
public:
|
||||||
// This interface is implemented by the owner of the BrowserWindow. The
|
// This interface is implemented by the owner of the BrowserWindow. The
|
||||||
// methods of this class will be called on the main thread.
|
// methods of this class will be called on the main thread unless otherwise
|
||||||
|
// indicated.
|
||||||
class Delegate {
|
class Delegate {
|
||||||
public:
|
public:
|
||||||
// Returns true if the window should use Alloy style. Safe to call on any
|
// Returns true if the window should use Alloy style. Safe to call on any
|
||||||
@ -48,6 +49,9 @@ class BrowserWindow : public ClientHandler::Delegate {
|
|||||||
// Auto-resize contents.
|
// Auto-resize contents.
|
||||||
virtual void OnAutoResize(const CefSize& new_size) = 0;
|
virtual void OnAutoResize(const CefSize& new_size) = 0;
|
||||||
|
|
||||||
|
// Set contents bounds.
|
||||||
|
virtual void OnContentsBounds(const CefRect& new_bounds) = 0;
|
||||||
|
|
||||||
// Set the loading state.
|
// Set the loading state.
|
||||||
virtual void OnSetLoadingState(bool isLoading,
|
virtual void OnSetLoadingState(bool isLoading,
|
||||||
bool canGoBack,
|
bool canGoBack,
|
||||||
@ -57,6 +61,9 @@ class BrowserWindow : public ClientHandler::Delegate {
|
|||||||
virtual void OnSetDraggableRegions(
|
virtual void OnSetDraggableRegions(
|
||||||
const std::vector<CefDraggableRegion>& regions) = 0;
|
const std::vector<CefDraggableRegion>& regions) = 0;
|
||||||
|
|
||||||
|
// Called on the UI thread to retrieve root window bounds.
|
||||||
|
virtual bool GetRootWindowScreenRect(CefRect& rect) { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~Delegate() = default;
|
virtual ~Delegate() = default;
|
||||||
};
|
};
|
||||||
@ -132,13 +139,15 @@ class BrowserWindow : public ClientHandler::Delegate {
|
|||||||
void OnSetTitle(const std::string& title) override;
|
void OnSetTitle(const std::string& title) override;
|
||||||
void OnSetFullscreen(bool fullscreen) override;
|
void OnSetFullscreen(bool fullscreen) override;
|
||||||
void OnAutoResize(const CefSize& new_size) override;
|
void OnAutoResize(const CefSize& new_size) override;
|
||||||
|
void OnContentsBounds(const CefRect& new_bounds) override;
|
||||||
|
bool GetRootWindowScreenRect(CefRect& rect) override;
|
||||||
void OnSetLoadingState(bool isLoading,
|
void OnSetLoadingState(bool isLoading,
|
||||||
bool canGoBack,
|
bool canGoBack,
|
||||||
bool canGoForward) override;
|
bool canGoForward) override;
|
||||||
void OnSetDraggableRegions(
|
void OnSetDraggableRegions(
|
||||||
const std::vector<CefDraggableRegion>& regions) override;
|
const std::vector<CefDraggableRegion>& regions) override;
|
||||||
|
|
||||||
Delegate* delegate_;
|
Delegate* const delegate_;
|
||||||
CefRefPtr<CefBrowser> browser_;
|
CefRefPtr<CefBrowser> browser_;
|
||||||
CefRefPtr<ClientHandler> client_handler_;
|
CefRefPtr<ClientHandler> client_handler_;
|
||||||
bool is_closing_ = false;
|
bool is_closing_ = false;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "include/base/cef_logging.h"
|
#include "include/base/cef_logging.h"
|
||||||
#include "include/base/cef_macros.h"
|
#include "include/base/cef_macros.h"
|
||||||
|
#include "include/views/cef_display.h"
|
||||||
#include "include/wrapper/cef_closure_task.h"
|
#include "include/wrapper/cef_closure_task.h"
|
||||||
#include "tests/cefclient/browser/util_gtk.h"
|
#include "tests/cefclient/browser/util_gtk.h"
|
||||||
#include "tests/shared/browser/geometry_util.h"
|
#include "tests/shared/browser/geometry_util.h"
|
||||||
@ -1092,7 +1093,7 @@ void BrowserWindowOsrGtk::SetDeviceScaleFactor(float device_scale_factor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply some sanity checks.
|
// Apply some sanity checks.
|
||||||
if (device_scale_factor < 1.0f || device_scale_factor > 4.0f) {
|
if (device_scale_factor < 0.5f || device_scale_factor > 4.0f) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1142,15 +1143,36 @@ void BrowserWindowOsrGtk::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
|||||||
bool BrowserWindowOsrGtk::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
bool BrowserWindowOsrGtk::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
||||||
CefRect& rect) {
|
CefRect& rect) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
return false;
|
|
||||||
|
if (!renderer_.settings().real_screen_bounds) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!glarea_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float device_scale_factor;
|
||||||
|
{
|
||||||
|
base::AutoLock lock_scope(lock_);
|
||||||
|
device_scale_factor = device_scale_factor_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
|
|
||||||
|
GtkWidget* toplevel = gtk_widget_get_toplevel(glarea_);
|
||||||
|
|
||||||
|
// Convert to DIP coordinates.
|
||||||
|
rect = DeviceToLogical(
|
||||||
|
GetWindowBounds(GTK_WINDOW(toplevel), /*include_frame=*/true),
|
||||||
|
device_scale_factor);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserWindowOsrGtk::GetViewRect(CefRefPtr<CefBrowser> browser,
|
void BrowserWindowOsrGtk::GetViewRect(CefRefPtr<CefBrowser> browser,
|
||||||
CefRect& rect) {
|
CefRect& rect) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
rect.x = rect.y = 0;
|
|
||||||
|
|
||||||
if (!glarea_) {
|
if (!glarea_) {
|
||||||
// Never return an empty rectangle.
|
// Never return an empty rectangle.
|
||||||
rect.width = rect.height = 1;
|
rect.width = rect.height = 1;
|
||||||
@ -1163,18 +1185,24 @@ void BrowserWindowOsrGtk::GetViewRect(CefRefPtr<CefBrowser> browser,
|
|||||||
device_scale_factor = device_scale_factor_;
|
device_scale_factor = device_scale_factor_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The simulated screen and view rectangle are the same. This is necessary
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
// for popup menus to be located and sized inside the view.
|
|
||||||
GtkAllocation allocation;
|
GtkAllocation allocation = {};
|
||||||
gtk_widget_get_allocation(glarea_, &allocation);
|
gtk_widget_get_allocation(glarea_, &allocation);
|
||||||
rect.width = DeviceToLogical(allocation.width, device_scale_factor);
|
|
||||||
|
// Convert to DIP coordinates.
|
||||||
|
rect = DeviceToLogical(
|
||||||
|
{allocation.x, allocation.y, allocation.width, allocation.height},
|
||||||
|
device_scale_factor);
|
||||||
if (rect.width == 0) {
|
if (rect.width == 0) {
|
||||||
rect.width = 1;
|
rect.width = 1;
|
||||||
}
|
}
|
||||||
rect.height = DeviceToLogical(allocation.height, device_scale_factor);
|
|
||||||
if (rect.height == 0) {
|
if (rect.height == 0) {
|
||||||
rect.height = 1;
|
rect.height = 1;
|
||||||
}
|
}
|
||||||
|
if (!renderer_.settings().real_screen_bounds) {
|
||||||
|
rect.x = rect.y = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BrowserWindowOsrGtk::GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
bool BrowserWindowOsrGtk::GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
||||||
@ -1204,9 +1232,6 @@ bool BrowserWindowOsrGtk::GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
|||||||
CefScreenInfo& screen_info) {
|
CefScreenInfo& screen_info) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
CefRect view_rect;
|
|
||||||
GetViewRect(browser, view_rect);
|
|
||||||
|
|
||||||
float device_scale_factor;
|
float device_scale_factor;
|
||||||
{
|
{
|
||||||
base::AutoLock lock_scope(lock_);
|
base::AutoLock lock_scope(lock_);
|
||||||
@ -1215,10 +1240,23 @@ bool BrowserWindowOsrGtk::GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
|||||||
|
|
||||||
screen_info.device_scale_factor = device_scale_factor;
|
screen_info.device_scale_factor = device_scale_factor;
|
||||||
|
|
||||||
// The screen info rectangles are used by the renderer to create and position
|
if (renderer_.settings().real_screen_bounds) {
|
||||||
// popups. Keep popups inside the view rectangle.
|
CefRect root_rect;
|
||||||
screen_info.rect = view_rect;
|
GetRootScreenRect(browser, root_rect);
|
||||||
screen_info.available_rect = view_rect;
|
|
||||||
|
auto display = CefDisplay::GetDisplayMatchingBounds(
|
||||||
|
root_rect, /*input_pixel_coords=*/false);
|
||||||
|
screen_info.rect = display->GetBounds();
|
||||||
|
screen_info.available_rect = display->GetWorkArea();
|
||||||
|
} else {
|
||||||
|
CefRect view_rect;
|
||||||
|
GetViewRect(browser, view_rect);
|
||||||
|
|
||||||
|
// Keep HTML select popups inside the view rectangle.
|
||||||
|
screen_info.rect = view_rect;
|
||||||
|
screen_info.available_rect = view_rect;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,14 +9,18 @@
|
|||||||
#include <OpenGL/gl.h>
|
#include <OpenGL/gl.h>
|
||||||
#import <objc/runtime.h>
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "include/base/cef_logging.h"
|
#include "include/base/cef_logging.h"
|
||||||
#include "include/cef_parser.h"
|
#include "include/cef_parser.h"
|
||||||
|
#include "include/views/cef_display.h"
|
||||||
#include "include/wrapper/cef_closure_task.h"
|
#include "include/wrapper/cef_closure_task.h"
|
||||||
#include "tests/cefclient/browser/bytes_write_handler.h"
|
#include "tests/cefclient/browser/bytes_write_handler.h"
|
||||||
#include "tests/cefclient/browser/main_context.h"
|
#include "tests/cefclient/browser/main_context.h"
|
||||||
#include "tests/cefclient/browser/osr_accessibility_helper.h"
|
#include "tests/cefclient/browser/osr_accessibility_helper.h"
|
||||||
#include "tests/cefclient/browser/osr_accessibility_node.h"
|
#include "tests/cefclient/browser/osr_accessibility_node.h"
|
||||||
#include "tests/cefclient/browser/text_input_client_osr_mac.h"
|
#include "tests/cefclient/browser/text_input_client_osr_mac.h"
|
||||||
|
#include "tests/cefclient/browser/util_mac.h"
|
||||||
#include "tests/shared/browser/geometry_util.h"
|
#include "tests/shared/browser/geometry_util.h"
|
||||||
#include "tests/shared/browser/main_message_loop.h"
|
#include "tests/shared/browser/main_message_loop.h"
|
||||||
|
|
||||||
@ -784,7 +788,7 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
|
|||||||
- (void)windowDidChangeBackingProperties:(NSNotification*)notification {
|
- (void)windowDidChangeBackingProperties:(NSNotification*)notification {
|
||||||
// This delegate method is only called on 10.7 and later, so don't worry about
|
// This delegate method is only called on 10.7 and later, so don't worry about
|
||||||
// other backing changes calling it on 10.6 or earlier
|
// other backing changes calling it on 10.6 or earlier
|
||||||
[self resetDeviceScaleFactor];
|
[self resetDeviceScaleFactor:std::nullopt];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)drawRect:(NSRect)dirtyRect {
|
- (void)drawRect:(NSRect)dirtyRect {
|
||||||
@ -1210,11 +1214,13 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
|
|||||||
return viewPoint;
|
return viewPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)resetDeviceScaleFactor {
|
- (void)resetDeviceScaleFactor:(std::optional<float>)requested_scale_factor {
|
||||||
float device_scale_factor = 1.0f;
|
float device_scale_factor = requested_scale_factor.value_or(1.0f);
|
||||||
NSWindow* window = [self window];
|
if (!requested_scale_factor.has_value()) {
|
||||||
if (window) {
|
NSWindow* window = [self window];
|
||||||
device_scale_factor = [window backingScaleFactor];
|
if (window) {
|
||||||
|
device_scale_factor = [window backingScaleFactor];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
[self setDeviceScaleFactor:device_scale_factor];
|
[self setDeviceScaleFactor:device_scale_factor];
|
||||||
}
|
}
|
||||||
@ -1225,7 +1231,7 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply some sanity checks.
|
// Apply some sanity checks.
|
||||||
if (device_scale_factor < 1.0f || device_scale_factor > 4.0f) {
|
if (device_scale_factor < 0.5f || device_scale_factor > 4.0f) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1417,6 +1423,7 @@ class BrowserWindowOsrMacImpl {
|
|||||||
// The below members will only be accessed on the main thread which should be
|
// The below members will only be accessed on the main thread which should be
|
||||||
// the same as the CEF UI thread.
|
// the same as the CEF UI thread.
|
||||||
OsrRenderer renderer_;
|
OsrRenderer renderer_;
|
||||||
|
std::optional<float> initial_scale_factor_;
|
||||||
BrowserOpenGLView* native_browser_view_;
|
BrowserOpenGLView* native_browser_view_;
|
||||||
bool hidden_;
|
bool hidden_;
|
||||||
bool painting_popup_;
|
bool painting_popup_;
|
||||||
@ -1542,7 +1549,7 @@ void BrowserWindowOsrMacImpl::SetBounds(int x,
|
|||||||
size_t width,
|
size_t width,
|
||||||
size_t height) {
|
size_t height) {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
// Nothing to do here. GTK will take care of positioning in the container.
|
// Nothing to do here. Cocoa will take care of positioning in the container.
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserWindowOsrMacImpl::SetFocus(bool focus) {
|
void BrowserWindowOsrMacImpl::SetFocus(bool focus) {
|
||||||
@ -1556,6 +1563,8 @@ void BrowserWindowOsrMacImpl::SetDeviceScaleFactor(float device_scale_factor) {
|
|||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
if (native_browser_view_) {
|
if (native_browser_view_) {
|
||||||
[native_browser_view_ setDeviceScaleFactor:device_scale_factor];
|
[native_browser_view_ setDeviceScaleFactor:device_scale_factor];
|
||||||
|
} else {
|
||||||
|
initial_scale_factor_ = device_scale_factor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1564,7 +1573,7 @@ float BrowserWindowOsrMacImpl::GetDeviceScaleFactor() const {
|
|||||||
if (native_browser_view_) {
|
if (native_browser_view_) {
|
||||||
return [native_browser_view_ getDeviceScaleFactor];
|
return [native_browser_view_ getDeviceScaleFactor];
|
||||||
}
|
}
|
||||||
return 1.0f;
|
return initial_scale_factor_.value_or(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientWindowHandle BrowserWindowOsrMacImpl::GetWindowHandle() const {
|
ClientWindowHandle BrowserWindowOsrMacImpl::GetWindowHandle() const {
|
||||||
@ -1590,7 +1599,25 @@ void BrowserWindowOsrMacImpl::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
|||||||
bool BrowserWindowOsrMacImpl::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
bool BrowserWindowOsrMacImpl::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
||||||
CefRect& rect) {
|
CefRect& rect) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
return false;
|
if (!renderer_.settings().real_screen_bounds) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!native_browser_view_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto screen_rect =
|
||||||
|
GetWindowBoundsInScreen([native_browser_view_ window])) {
|
||||||
|
rect = *screen_rect;
|
||||||
|
}
|
||||||
|
if (rect.width == 0) {
|
||||||
|
rect.width = 1;
|
||||||
|
}
|
||||||
|
if (rect.height == 0) {
|
||||||
|
rect.height = 1;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserWindowOsrMacImpl::GetViewRect(CefRefPtr<CefBrowser> browser,
|
void BrowserWindowOsrMacImpl::GetViewRect(CefRefPtr<CefBrowser> browser,
|
||||||
@ -1598,6 +1625,7 @@ void BrowserWindowOsrMacImpl::GetViewRect(CefRefPtr<CefBrowser> browser,
|
|||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
|
// Keep (0,0) origin for proper layout on macOS.
|
||||||
rect.x = rect.y = 0;
|
rect.x = rect.y = 0;
|
||||||
|
|
||||||
if (!native_browser_view_) {
|
if (!native_browser_view_) {
|
||||||
@ -1614,12 +1642,12 @@ void BrowserWindowOsrMacImpl::GetViewRect(CefRefPtr<CefBrowser> browser,
|
|||||||
// Convert to device coordinates.
|
// Convert to device coordinates.
|
||||||
bounds = [native_browser_view_ convertRectToBackingInternal:bounds];
|
bounds = [native_browser_view_ convertRectToBackingInternal:bounds];
|
||||||
|
|
||||||
// Convert to browser view coordinates.
|
// Convert to DIP coordinates.
|
||||||
rect.width = DeviceToLogical(bounds.size.width, device_scale_factor);
|
rect.width = DeviceToLogical(bounds.size.width, device_scale_factor);
|
||||||
|
rect.height = DeviceToLogical(bounds.size.height, device_scale_factor);
|
||||||
if (rect.width == 0) {
|
if (rect.width == 0) {
|
||||||
rect.width = 1;
|
rect.width = 1;
|
||||||
}
|
}
|
||||||
rect.height = DeviceToLogical(bounds.size.height, device_scale_factor);
|
|
||||||
if (rect.height == 0) {
|
if (rect.height == 0) {
|
||||||
rect.height = 1;
|
rect.height = 1;
|
||||||
}
|
}
|
||||||
@ -1639,7 +1667,7 @@ bool BrowserWindowOsrMacImpl::GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
|||||||
|
|
||||||
const float device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
|
const float device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
|
||||||
|
|
||||||
// (viewX, viewX) is in browser view coordinates.
|
// (viewX, viewX) is in browser DIP coordinates.
|
||||||
// Convert to device coordinates.
|
// Convert to device coordinates.
|
||||||
NSPoint view_pt = NSMakePoint(LogicalToDevice(viewX, device_scale_factor),
|
NSPoint view_pt = NSMakePoint(LogicalToDevice(viewX, device_scale_factor),
|
||||||
LogicalToDevice(viewY, device_scale_factor));
|
LogicalToDevice(viewY, device_scale_factor));
|
||||||
@ -1670,16 +1698,24 @@ bool BrowserWindowOsrMacImpl::GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRect view_rect;
|
|
||||||
GetViewRect(browser, view_rect);
|
|
||||||
|
|
||||||
screen_info.device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
|
screen_info.device_scale_factor = [native_browser_view_ getDeviceScaleFactor];
|
||||||
|
|
||||||
// The screen info rectangles are used by the renderer to create and position
|
if (renderer_.settings().real_screen_bounds) {
|
||||||
// popups. Keep popups inside the view rectangle.
|
CefRect root_rect;
|
||||||
screen_info.rect = view_rect;
|
GetRootScreenRect(browser, root_rect);
|
||||||
screen_info.available_rect = view_rect;
|
|
||||||
|
|
||||||
|
auto display = CefDisplay::GetDisplayMatchingBounds(
|
||||||
|
root_rect, /*input_pixel_coords=*/false);
|
||||||
|
screen_info.rect = display->GetBounds();
|
||||||
|
screen_info.available_rect = display->GetWorkArea();
|
||||||
|
} else {
|
||||||
|
CefRect view_rect;
|
||||||
|
GetViewRect(browser, view_rect);
|
||||||
|
|
||||||
|
// Keep HTML select popups inside the view rectangle.
|
||||||
|
screen_info.rect = view_rect;
|
||||||
|
screen_info.available_rect = view_rect;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1892,7 +1928,7 @@ void BrowserWindowOsrMacImpl::Create(ClientWindowHandle parent_handle,
|
|||||||
addSubview:native_browser_view_];
|
addSubview:native_browser_view_];
|
||||||
|
|
||||||
// Determine the default scale factor.
|
// Determine the default scale factor.
|
||||||
[native_browser_view_ resetDeviceScaleFactor];
|
[native_browser_view_ resetDeviceScaleFactor:initial_scale_factor_];
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
addObserver:native_browser_view_
|
addObserver:native_browser_view_
|
||||||
|
@ -103,7 +103,7 @@ void BrowserWindowOsrWin::SetDeviceScaleFactor(float device_scale_factor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply some sanity checks.
|
// Apply some sanity checks.
|
||||||
if (device_scale_factor < 1.0f || device_scale_factor > 4.0f) {
|
if (device_scale_factor < 0.5f || device_scale_factor > 4.0f) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,12 +571,7 @@ ClientHandler::ClientHandler(Delegate* delegate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ClientHandler::DetachDelegate() {
|
void ClientHandler::DetachDelegate() {
|
||||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
REQUIRE_MAIN_THREAD();
|
||||||
// Execute this method on the main thread.
|
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(&ClientHandler::DetachDelegate, this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DCHECK(delegate_);
|
DCHECK(delegate_);
|
||||||
delegate_ = nullptr;
|
delegate_ = nullptr;
|
||||||
}
|
}
|
||||||
@ -869,6 +864,24 @@ bool ClientHandler::OnCursorChange(CefRefPtr<CefBrowser> browser,
|
|||||||
return mouse_cursor_change_disabled_;
|
return mouse_cursor_change_disabled_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CEF_API_ADDED(CEF_NEXT)
|
||||||
|
bool ClientHandler::OnContentsBoundsChange(CefRefPtr<CefBrowser> browser,
|
||||||
|
const CefRect& new_bounds) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
NotifyContentsBounds(new_bounds);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientHandler::GetRootWindowScreenRect(CefRefPtr<CefBrowser> browser,
|
||||||
|
CefRect& rect) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
if (delegate_) {
|
||||||
|
return delegate_->GetRootWindowScreenRect(rect);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool ClientHandler::CanDownload(CefRefPtr<CefBrowser> browser,
|
bool ClientHandler::CanDownload(CefRefPtr<CefBrowser> browser,
|
||||||
const CefString& url,
|
const CefString& url,
|
||||||
const CefString& request_method) {
|
const CefString& request_method) {
|
||||||
@ -1465,6 +1478,19 @@ void ClientHandler::NotifyAutoResize(const CefSize& new_size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientHandler::NotifyContentsBounds(const CefRect& new_bounds) {
|
||||||
|
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||||
|
// Execute this method on the main thread.
|
||||||
|
MAIN_POST_CLOSURE(
|
||||||
|
base::BindOnce(&ClientHandler::NotifyContentsBounds, this, new_bounds));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delegate_) {
|
||||||
|
delegate_->OnContentsBounds(new_bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClientHandler::NotifyLoadingState(bool isLoading,
|
void ClientHandler::NotifyLoadingState(bool isLoading,
|
||||||
bool canGoBack,
|
bool canGoBack,
|
||||||
bool canGoForward) {
|
bool canGoForward) {
|
||||||
|
@ -71,6 +71,9 @@ class ClientHandler : public BaseClientHandler,
|
|||||||
// Auto-resize contents.
|
// Auto-resize contents.
|
||||||
virtual void OnAutoResize(const CefSize& new_size) = 0;
|
virtual void OnAutoResize(const CefSize& new_size) = 0;
|
||||||
|
|
||||||
|
// Set contents bounds.
|
||||||
|
virtual void OnContentsBounds(const CefRect& new_bounds) = 0;
|
||||||
|
|
||||||
// Set the loading state.
|
// Set the loading state.
|
||||||
virtual void OnSetLoadingState(bool isLoading,
|
virtual void OnSetLoadingState(bool isLoading,
|
||||||
bool canGoBack,
|
bool canGoBack,
|
||||||
@ -89,6 +92,9 @@ class ClientHandler : public BaseClientHandler,
|
|||||||
// Called on the UI thread before a context menu is displayed.
|
// Called on the UI thread before a context menu is displayed.
|
||||||
virtual void OnBeforeContextMenu(CefRefPtr<CefMenuModel> model) {}
|
virtual void OnBeforeContextMenu(CefRefPtr<CefMenuModel> model) {}
|
||||||
|
|
||||||
|
// Called on the UI thread to retrieve root window bounds.
|
||||||
|
virtual bool GetRootWindowScreenRect(CefRect& rect) { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~Delegate() = default;
|
virtual ~Delegate() = default;
|
||||||
};
|
};
|
||||||
@ -101,7 +107,8 @@ class ClientHandler : public BaseClientHandler,
|
|||||||
const std::string& startup_url);
|
const std::string& startup_url);
|
||||||
|
|
||||||
// This object may outlive the Delegate object so it's necessary for the
|
// This object may outlive the Delegate object so it's necessary for the
|
||||||
// Delegate to detach itself before destruction.
|
// Delegate to detach itself before destruction. Called on the main thread
|
||||||
|
// after the browser has closed.
|
||||||
void DetachDelegate();
|
void DetachDelegate();
|
||||||
|
|
||||||
// CefClient methods
|
// CefClient methods
|
||||||
@ -176,6 +183,12 @@ class ClientHandler : public BaseClientHandler,
|
|||||||
CefCursorHandle cursor,
|
CefCursorHandle cursor,
|
||||||
cef_cursor_type_t type,
|
cef_cursor_type_t type,
|
||||||
const CefCursorInfo& custom_cursor_info) override;
|
const CefCursorInfo& custom_cursor_info) override;
|
||||||
|
#if CEF_API_ADDED(CEF_NEXT)
|
||||||
|
bool OnContentsBoundsChange(CefRefPtr<CefBrowser> browser,
|
||||||
|
const CefRect& new_bounds) override;
|
||||||
|
bool GetRootWindowScreenRect(CefRefPtr<CefBrowser> browser,
|
||||||
|
CefRect& rect) override;
|
||||||
|
#endif
|
||||||
|
|
||||||
// CefDownloadHandler methods
|
// CefDownloadHandler methods
|
||||||
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
||||||
@ -345,6 +358,7 @@ class ClientHandler : public BaseClientHandler,
|
|||||||
void NotifyFavicon(CefRefPtr<CefImage> image);
|
void NotifyFavicon(CefRefPtr<CefImage> image);
|
||||||
void NotifyFullscreen(bool fullscreen);
|
void NotifyFullscreen(bool fullscreen);
|
||||||
void NotifyAutoResize(const CefSize& new_size);
|
void NotifyAutoResize(const CefSize& new_size);
|
||||||
|
void NotifyContentsBounds(const CefRect& new_bounds);
|
||||||
void NotifyLoadingState(bool isLoading, bool canGoBack, bool canGoForward);
|
void NotifyLoadingState(bool isLoading, bool canGoBack, bool canGoForward);
|
||||||
void NotifyDraggableRegions(const std::vector<CefDraggableRegion>& regions);
|
void NotifyDraggableRegions(const std::vector<CefDraggableRegion>& regions);
|
||||||
void NotifyTakeFocus(bool next);
|
void NotifyTakeFocus(bool next);
|
||||||
@ -396,11 +410,7 @@ class ClientHandler : public BaseClientHandler,
|
|||||||
CefRefPtr<ClientPrintHandlerGtk> print_handler_;
|
CefRefPtr<ClientPrintHandlerGtk> print_handler_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// MAIN THREAD MEMBERS
|
// Safe to access from any thread during browser lifetime.
|
||||||
// The following members will only be accessed on the main thread. This will
|
|
||||||
// be the same as the CEF UI thread except when using multi-threaded message
|
|
||||||
// loop mode on Windows.
|
|
||||||
|
|
||||||
Delegate* delegate_;
|
Delegate* delegate_;
|
||||||
|
|
||||||
// UI THREAD MEMBERS
|
// UI THREAD MEMBERS
|
||||||
|
@ -239,6 +239,8 @@ void MainContextImpl::PopulateBrowserSettings(CefBrowserSettings* settings) {
|
|||||||
void MainContextImpl::PopulateOsrSettings(OsrRendererSettings* settings) {
|
void MainContextImpl::PopulateOsrSettings(OsrRendererSettings* settings) {
|
||||||
settings->show_update_rect =
|
settings->show_update_rect =
|
||||||
command_line_->HasSwitch(switches::kShowUpdateRect);
|
command_line_->HasSwitch(switches::kShowUpdateRect);
|
||||||
|
settings->real_screen_bounds =
|
||||||
|
!command_line_->HasSwitch(switches::kFakeScreenBounds);
|
||||||
|
|
||||||
settings->shared_texture_enabled = shared_texture_enabled_;
|
settings->shared_texture_enabled = shared_texture_enabled_;
|
||||||
settings->external_begin_frame_enabled = external_begin_frame_enabled_;
|
settings->external_begin_frame_enabled = external_begin_frame_enabled_;
|
||||||
|
@ -16,6 +16,14 @@ struct OsrRendererSettings {
|
|||||||
// If true draw a border around update rectangles.
|
// If true draw a border around update rectangles.
|
||||||
bool show_update_rect = false;
|
bool show_update_rect = false;
|
||||||
|
|
||||||
|
// If true return real screen bounds from GetRootScreenRect/GetScreenInfo.
|
||||||
|
// - Allows window.outerWidth/Height and window.screenX/Y to return correct
|
||||||
|
// values.
|
||||||
|
// - Allows JavaScript window.moveTo/By() and window.resizeTo/By() to provide
|
||||||
|
// bounds that include the window frame.
|
||||||
|
// - Causes HTML select popups to be cropped (limitation of cefclient impl).
|
||||||
|
bool real_screen_bounds = true;
|
||||||
|
|
||||||
// Background color. Enables transparency if the alpha component is 0.
|
// Background color. Enables transparency if the alpha component is 0.
|
||||||
cef_color_t background_color = 0;
|
cef_color_t background_color = 0;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "include/base/cef_build.h"
|
#include "include/base/cef_build.h"
|
||||||
|
#include "include/views/cef_display.h"
|
||||||
#include "tests/cefclient/browser/main_context.h"
|
#include "tests/cefclient/browser/main_context.h"
|
||||||
#include "tests/cefclient/browser/osr_accessibility_helper.h"
|
#include "tests/cefclient/browser/osr_accessibility_helper.h"
|
||||||
#include "tests/cefclient/browser/osr_accessibility_node.h"
|
#include "tests/cefclient/browser/osr_accessibility_node.h"
|
||||||
@ -30,20 +31,6 @@ namespace {
|
|||||||
|
|
||||||
const wchar_t kWndClass[] = L"Client_OsrWindow";
|
const wchar_t kWndClass[] = L"Client_OsrWindow";
|
||||||
|
|
||||||
// Helper funtion to check if it is Windows8 or greater.
|
|
||||||
// https://msdn.microsoft.com/en-us/library/ms724833(v=vs.85).aspx
|
|
||||||
inline BOOL IsWindows_8_Or_Newer() {
|
|
||||||
OSVERSIONINFOEX osvi = {0};
|
|
||||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
||||||
osvi.dwMajorVersion = 6;
|
|
||||||
osvi.dwMinorVersion = 2;
|
|
||||||
DWORDLONG dwlConditionMask = 0;
|
|
||||||
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
|
||||||
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
|
|
||||||
return ::VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
|
|
||||||
dwlConditionMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to detect mouse messages coming from emulation of touch
|
// Helper function to detect mouse messages coming from emulation of touch
|
||||||
// events. These should be ignored.
|
// events. These should be ignored.
|
||||||
bool IsMouseEventFromTouch(UINT message) {
|
bool IsMouseEventFromTouch(UINT message) {
|
||||||
@ -92,7 +79,7 @@ OsrWindowWin::OsrWindowWin(Delegate* delegate,
|
|||||||
last_mouse_pos_(),
|
last_mouse_pos_(),
|
||||||
current_mouse_pos_() {
|
current_mouse_pos_() {
|
||||||
DCHECK(delegate_);
|
DCHECK(delegate_);
|
||||||
client_rect_ = {0};
|
client_rect_ = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
OsrWindowWin::~OsrWindowWin() {
|
OsrWindowWin::~OsrWindowWin() {
|
||||||
@ -870,17 +857,6 @@ bool OsrWindowWin::OnTouchEvent(UINT message, WPARAM wParam, LPARAM lParam) {
|
|||||||
point.x = TOUCH_COORD_TO_PIXEL(input[i].x);
|
point.x = TOUCH_COORD_TO_PIXEL(input[i].x);
|
||||||
point.y = TOUCH_COORD_TO_PIXEL(input[i].y);
|
point.y = TOUCH_COORD_TO_PIXEL(input[i].y);
|
||||||
|
|
||||||
if (!IsWindows_8_Or_Newer()) {
|
|
||||||
// Windows 7 sends touch events for touches in the non-client area,
|
|
||||||
// whereas Windows 8 does not. In order to unify the behaviour, always
|
|
||||||
// ignore touch events in the non-client area.
|
|
||||||
LPARAM l_param_ht = MAKELPARAM(point.x, point.y);
|
|
||||||
LRESULT hittest = SendMessage(hwnd_, WM_NCHITTEST, 0, l_param_ht);
|
|
||||||
if (hittest != HTCLIENT) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ScreenToClient(hwnd_, &point);
|
ScreenToClient(hwnd_, &point);
|
||||||
touch_event.x = DeviceToLogical(point.x, device_scale_factor_);
|
touch_event.x = DeviceToLogical(point.x, device_scale_factor_);
|
||||||
touch_event.y = DeviceToLogical(point.y, device_scale_factor_);
|
touch_event.y = DeviceToLogical(point.y, device_scale_factor_);
|
||||||
@ -969,24 +945,52 @@ void OsrWindowWin::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
|||||||
bool OsrWindowWin::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
bool OsrWindowWin::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
||||||
CefRect& rect) {
|
CefRect& rect) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
return false;
|
DCHECK_GT(device_scale_factor_, 0);
|
||||||
|
|
||||||
|
if (!settings_.real_screen_bounds) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND root_hwnd = ::GetAncestor(hwnd_, GA_ROOT);
|
||||||
|
DCHECK(root_hwnd);
|
||||||
|
RECT root_rect = {};
|
||||||
|
::GetWindowRect(root_hwnd, &root_rect);
|
||||||
|
|
||||||
|
// Convert to DIP coordinates.
|
||||||
|
rect = DeviceToLogical(
|
||||||
|
{root_rect.left, root_rect.top, root_rect.right - root_rect.left,
|
||||||
|
root_rect.bottom - root_rect.top},
|
||||||
|
device_scale_factor_);
|
||||||
|
if (rect.width == 0) {
|
||||||
|
rect.width = 1;
|
||||||
|
}
|
||||||
|
if (rect.height == 0) {
|
||||||
|
rect.height = 1;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OsrWindowWin::GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) {
|
void OsrWindowWin::GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
DCHECK_GT(device_scale_factor_, 0);
|
DCHECK_GT(device_scale_factor_, 0);
|
||||||
|
|
||||||
rect.x = rect.y = 0;
|
RECT window_rect = {};
|
||||||
rect.width = DeviceToLogical(client_rect_.right - client_rect_.left,
|
::GetWindowRect(hwnd_, &window_rect);
|
||||||
device_scale_factor_);
|
|
||||||
|
// Convert to DIP coordinates.
|
||||||
|
rect = DeviceToLogical(
|
||||||
|
{window_rect.left, window_rect.top, window_rect.right - window_rect.left,
|
||||||
|
window_rect.bottom - window_rect.top},
|
||||||
|
device_scale_factor_);
|
||||||
if (rect.width == 0) {
|
if (rect.width == 0) {
|
||||||
rect.width = 1;
|
rect.width = 1;
|
||||||
}
|
}
|
||||||
rect.height = DeviceToLogical(client_rect_.bottom - client_rect_.top,
|
|
||||||
device_scale_factor_);
|
|
||||||
if (rect.height == 0) {
|
if (rect.height == 0) {
|
||||||
rect.height = 1;
|
rect.height = 1;
|
||||||
}
|
}
|
||||||
|
if (!settings_.real_screen_bounds) {
|
||||||
|
rect.x = rect.y = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OsrWindowWin::GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
bool OsrWindowWin::GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
||||||
@ -1019,15 +1023,24 @@ bool OsrWindowWin::GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRect view_rect;
|
|
||||||
GetViewRect(browser, view_rect);
|
|
||||||
|
|
||||||
screen_info.device_scale_factor = device_scale_factor_;
|
screen_info.device_scale_factor = device_scale_factor_;
|
||||||
|
|
||||||
// The screen info rectangles are used by the renderer to create and position
|
if (settings_.real_screen_bounds) {
|
||||||
// popups. Keep popups inside the view rectangle.
|
CefRect root_rect;
|
||||||
screen_info.rect = view_rect;
|
GetRootScreenRect(browser, root_rect);
|
||||||
screen_info.available_rect = view_rect;
|
|
||||||
|
auto display = CefDisplay::GetDisplayMatchingBounds(
|
||||||
|
root_rect, /*input_pixel_coords=*/false);
|
||||||
|
screen_info.rect = display->GetBounds();
|
||||||
|
screen_info.available_rect = display->GetWorkArea();
|
||||||
|
} else {
|
||||||
|
CefRect view_rect;
|
||||||
|
GetViewRect(browser, view_rect);
|
||||||
|
|
||||||
|
// Keep HTML select popups inside the view rectangle.
|
||||||
|
screen_info.rect = view_rect;
|
||||||
|
screen_info.available_rect = view_rect;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -185,8 +186,23 @@ class RootWindow
|
|||||||
// Hide the window.
|
// Hide the window.
|
||||||
virtual void Hide() = 0;
|
virtual void Hide() = 0;
|
||||||
|
|
||||||
// Set the window bounds in screen coordinates.
|
// Set bounds in DIP screen coordinates. If |content_bounds| is true then the
|
||||||
virtual void SetBounds(int x, int y, size_t width, size_t height) = 0;
|
// specified bounds are for the browser's content area and will be expanded to
|
||||||
|
// appropriate containing window bounds. Otherwise, the specified bounds are
|
||||||
|
// for the containing window directly. Bounds will be constrained to the
|
||||||
|
// containing display work area. Specific behavioral expectations depend on
|
||||||
|
// platform and run mode. See the https://tests/window example for details.
|
||||||
|
virtual void SetBounds(int x,
|
||||||
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds) = 0;
|
||||||
|
void SetBounds(const CefRect& bounds, bool content_bounds) {
|
||||||
|
SetBounds(bounds.x, bounds.y, bounds.width, bounds.height, content_bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if this RootWindow should default to sizing by content bounds.
|
||||||
|
virtual bool DefaultToContentBounds() const = 0;
|
||||||
|
|
||||||
// Close the window. If |force| is true onunload handlers will not be
|
// Close the window. If |force| is true onunload handlers will not be
|
||||||
// executed.
|
// executed.
|
||||||
@ -198,7 +214,7 @@ class RootWindow
|
|||||||
|
|
||||||
// Returns the device scale factor. Only used in combination with off-screen
|
// Returns the device scale factor. Only used in combination with off-screen
|
||||||
// rendering.
|
// rendering.
|
||||||
virtual float GetDeviceScaleFactor() const = 0;
|
virtual std::optional<float> GetDeviceScaleFactor() const = 0;
|
||||||
|
|
||||||
// Returns the browser that this window contains, if any.
|
// Returns the browser that this window contains, if any.
|
||||||
virtual CefRefPtr<CefBrowser> GetBrowser() const = 0;
|
virtual CefRefPtr<CefBrowser> GetBrowser() const = 0;
|
||||||
|
@ -14,11 +14,14 @@
|
|||||||
#include "include/cef_app.h"
|
#include "include/cef_app.h"
|
||||||
#include "tests/cefclient/browser/browser_window_osr_gtk.h"
|
#include "tests/cefclient/browser/browser_window_osr_gtk.h"
|
||||||
#include "tests/cefclient/browser/browser_window_std_gtk.h"
|
#include "tests/cefclient/browser/browser_window_std_gtk.h"
|
||||||
|
#include "tests/cefclient/browser/client_prefs.h"
|
||||||
#include "tests/cefclient/browser/main_context.h"
|
#include "tests/cefclient/browser/main_context.h"
|
||||||
#include "tests/cefclient/browser/resource.h"
|
#include "tests/cefclient/browser/resource.h"
|
||||||
|
#include "tests/cefclient/browser/root_window_manager.h"
|
||||||
#include "tests/cefclient/browser/temp_window.h"
|
#include "tests/cefclient/browser/temp_window.h"
|
||||||
#include "tests/cefclient/browser/util_gtk.h"
|
#include "tests/cefclient/browser/util_gtk.h"
|
||||||
#include "tests/cefclient/browser/window_test_runner_gtk.h"
|
#include "tests/cefclient/browser/window_test_runner_gtk.h"
|
||||||
|
#include "tests/shared/browser/geometry_util.h"
|
||||||
#include "tests/shared/browser/main_message_loop.h"
|
#include "tests/shared/browser/main_message_loop.h"
|
||||||
#include "tests/shared/common/client_switches.h"
|
#include "tests/shared/common/client_switches.h"
|
||||||
|
|
||||||
@ -59,23 +62,139 @@ void UseDefaultX11VisualForGtk(GtkWidget* widget) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsWindowMaximized(GtkWindow* window) {
|
// Keep the bounds inside the closest display work area.
|
||||||
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
|
CefRect ClampBoundsToDisplay(const CefRect& pixel_bounds) {
|
||||||
gint state = gdk_window_get_state(gdk_window);
|
auto display = CefDisplay::GetDisplayMatchingBounds(
|
||||||
return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false;
|
pixel_bounds, /*input_pixel_coords=*/true);
|
||||||
|
CefRect work_area =
|
||||||
|
LogicalToDevice(display->GetWorkArea(), display->GetDeviceScaleFactor());
|
||||||
|
|
||||||
|
CefRect bounds = pixel_bounds;
|
||||||
|
ConstrainWindowBounds(work_area, bounds);
|
||||||
|
|
||||||
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinimizeWindow(GtkWindow* window) {
|
float GetScaleFactor(const CefRect& bounds,
|
||||||
// Unmaximize the window before minimizing so restore behaves correctly.
|
const std::optional<float>& device_scale_factor,
|
||||||
if (IsWindowMaximized(window)) {
|
bool pixel_bounds) {
|
||||||
gtk_window_unmaximize(window);
|
if (device_scale_factor.has_value()) {
|
||||||
|
return *device_scale_factor;
|
||||||
|
}
|
||||||
|
auto display = CefDisplay::GetDisplayMatchingBounds(
|
||||||
|
bounds, /*input_pixel_coords=*/pixel_bounds);
|
||||||
|
return display->GetDeviceScaleFactor();
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRect GetScreenPixelBounds(const CefRect& dip_bounds,
|
||||||
|
const std::optional<float>& device_scale_factor) {
|
||||||
|
const auto scale_factor =
|
||||||
|
GetScaleFactor(dip_bounds, device_scale_factor, /*pixel_bounds=*/false);
|
||||||
|
return LogicalToDevice(dip_bounds, scale_factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRect GetScreenDIPBounds(const CefRect& pixel_bounds,
|
||||||
|
const std::optional<float>& device_scale_factor) {
|
||||||
|
const auto scale_factor =
|
||||||
|
GetScaleFactor(pixel_bounds, device_scale_factor, /*pixel_bounds=*/true);
|
||||||
|
return DeviceToLogical(pixel_bounds, scale_factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Existing window measurements in root window (pixel) coordinates.
|
||||||
|
struct BoundsInfo {
|
||||||
|
CefRect frame;
|
||||||
|
CefRect window;
|
||||||
|
CefRect browser;
|
||||||
|
};
|
||||||
|
|
||||||
|
// |content_bounds| is the browser content area bounds in DIP screen
|
||||||
|
// coordinates. Convert to root window (pixel) coordinates and then expand to
|
||||||
|
// frame bounds. Keep the resulting bounds inside the closest display work area.
|
||||||
|
// |device_scale_factor| will be specified with off-screen rendering.
|
||||||
|
CefRect GetFrameBoundsInDisplay(
|
||||||
|
const CefRect& content_bounds,
|
||||||
|
const BoundsInfo& bounds_info,
|
||||||
|
const std::optional<float>& device_scale_factor) {
|
||||||
|
CefRect pixel_bounds =
|
||||||
|
GetScreenPixelBounds(content_bounds, device_scale_factor);
|
||||||
|
|
||||||
|
// Expand the new bounds based on relative offsets for the current bounds.
|
||||||
|
// - Position includes the frame.
|
||||||
|
pixel_bounds.x -=
|
||||||
|
bounds_info.window.x + bounds_info.browser.x - bounds_info.frame.x;
|
||||||
|
pixel_bounds.y -=
|
||||||
|
bounds_info.window.y + bounds_info.browser.y - bounds_info.frame.y;
|
||||||
|
// - Size does not include the frame.
|
||||||
|
pixel_bounds.width += bounds_info.window.width - bounds_info.browser.width;
|
||||||
|
pixel_bounds.height += bounds_info.window.height - bounds_info.browser.height;
|
||||||
|
|
||||||
|
return ClampBoundsToDisplay(pixel_bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute calls on the required threads.
|
||||||
|
void GetPixelBoundsAndContinue(const CefRect& dip_bounds,
|
||||||
|
const std::optional<BoundsInfo>& bounds_info,
|
||||||
|
const std::optional<float>& device_scale_factor,
|
||||||
|
base::OnceCallback<void(const CefRect&)> next) {
|
||||||
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
|
CefPostTask(TID_UI, base::BindOnce(&GetPixelBoundsAndContinue, dip_bounds,
|
||||||
|
bounds_info, device_scale_factor,
|
||||||
|
std::move(next)));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_window_iconify(window);
|
CefRect pixel_bounds;
|
||||||
|
if (bounds_info.has_value()) {
|
||||||
|
pixel_bounds =
|
||||||
|
GetFrameBoundsInDisplay(dip_bounds, *bounds_info, device_scale_factor);
|
||||||
|
} else {
|
||||||
|
pixel_bounds = ClampBoundsToDisplay(
|
||||||
|
GetScreenPixelBounds(dip_bounds, device_scale_factor));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CURRENTLY_ON_MAIN_THREAD()) {
|
||||||
|
std::move(next).Run(pixel_bounds);
|
||||||
|
} else {
|
||||||
|
MAIN_POST_CLOSURE(base::BindOnce(std::move(next), pixel_bounds));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaximizeWindow(GtkWindow* window) {
|
void SaveWindowRestoreContinue(
|
||||||
gtk_window_maximize(window);
|
cef_show_state_t show_state,
|
||||||
|
const CefRect& pixel_bounds,
|
||||||
|
const std::optional<float>& device_scale_factor) {
|
||||||
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
|
CefPostTask(TID_UI, base::BindOnce(&SaveWindowRestoreContinue, show_state,
|
||||||
|
pixel_bounds, device_scale_factor));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRect dip_bounds;
|
||||||
|
if (show_state == CEF_SHOW_STATE_NORMAL) {
|
||||||
|
dip_bounds = GetScreenDIPBounds(pixel_bounds, device_scale_factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
prefs::SaveWindowRestorePreferences(show_state, dip_bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveWindowRestore(GtkWidget* widget,
|
||||||
|
const std::optional<float>& device_scale_factor) {
|
||||||
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
|
GtkWindow* window = GTK_WINDOW(widget);
|
||||||
|
|
||||||
|
cef_show_state_t show_state = CEF_SHOW_STATE_NORMAL;
|
||||||
|
CefRect pixel_bounds;
|
||||||
|
|
||||||
|
if (!gtk_widget_get_visible(widget)) {
|
||||||
|
show_state = CEF_SHOW_STATE_MINIMIZED;
|
||||||
|
} else if (IsWindowMaximized(window)) {
|
||||||
|
show_state = CEF_SHOW_STATE_MAXIMIZED;
|
||||||
|
} else {
|
||||||
|
pixel_bounds = GetWindowBounds(window, /*include_frame=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveWindowRestoreContinue(show_state, pixel_bounds, device_scale_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -117,10 +236,54 @@ void RootWindowGtk::Init(RootWindow::Delegate* delegate,
|
|||||||
with_controls_ = config->with_controls;
|
with_controls_ = config->with_controls;
|
||||||
always_on_top_ = config->always_on_top;
|
always_on_top_ = config->always_on_top;
|
||||||
with_osr_ = config->with_osr;
|
with_osr_ = config->with_osr;
|
||||||
start_rect_ = config->bounds;
|
|
||||||
|
|
||||||
CreateBrowserWindow(config->url);
|
CreateBrowserWindow(config->url);
|
||||||
|
|
||||||
|
if (CefCurrentlyOn(TID_UI)) {
|
||||||
|
ContinueInitOnUIThread(std::move(config), settings);
|
||||||
|
} else {
|
||||||
|
CefPostTask(TID_UI, base::BindOnce(&RootWindowGtk::ContinueInitOnUIThread,
|
||||||
|
this, std::move(config), settings));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootWindowGtk::ContinueInitOnUIThread(
|
||||||
|
std::unique_ptr<RootWindowConfig> config,
|
||||||
|
const CefBrowserSettings& settings) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
|
if (!config->bounds.IsEmpty()) {
|
||||||
|
// Initial state was specified via the config object.
|
||||||
|
start_rect_ = config->bounds;
|
||||||
|
initial_show_state_ = config->show_state;
|
||||||
|
} else {
|
||||||
|
// Initial state may be specified via the command-line or global
|
||||||
|
// preferences.
|
||||||
|
std::optional<CefRect> bounds;
|
||||||
|
if (prefs::LoadWindowRestorePreferences(initial_show_state_, bounds) &&
|
||||||
|
bounds) {
|
||||||
|
start_rect_ = GetScreenPixelBounds(*bounds, std::nullopt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (with_osr_) {
|
||||||
|
initial_scale_factor_ =
|
||||||
|
GetScaleFactor(start_rect_, std::nullopt, /*pixel_bounds=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CURRENTLY_ON_MAIN_THREAD()) {
|
||||||
|
ContinueInitOnMainThread(std::move(config), settings);
|
||||||
|
} else {
|
||||||
|
MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::ContinueInitOnMainThread,
|
||||||
|
this, std::move(config), settings));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootWindowGtk::ContinueInitOnMainThread(
|
||||||
|
std::unique_ptr<RootWindowConfig> config,
|
||||||
|
const CefBrowserSettings& settings) {
|
||||||
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
|
|
||||||
// Always post asynchronously to avoid reentrancy of the GDK lock.
|
// Always post asynchronously to avoid reentrancy of the GDK lock.
|
||||||
@ -135,6 +298,8 @@ void RootWindowGtk::InitAsPopup(RootWindow::Delegate* delegate,
|
|||||||
CefWindowInfo& windowInfo,
|
CefWindowInfo& windowInfo,
|
||||||
CefRefPtr<CefClient>& client,
|
CefRefPtr<CefClient>& client,
|
||||||
CefBrowserSettings& settings) {
|
CefBrowserSettings& settings) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
|
||||||
DCHECK(delegate);
|
DCHECK(delegate);
|
||||||
DCHECK(!initialized_);
|
DCHECK(!initialized_);
|
||||||
|
|
||||||
@ -143,6 +308,7 @@ void RootWindowGtk::InitAsPopup(RootWindow::Delegate* delegate,
|
|||||||
with_osr_ = with_osr;
|
with_osr_ = with_osr;
|
||||||
is_popup_ = true;
|
is_popup_ = true;
|
||||||
|
|
||||||
|
// NOTE: This will be the size for the whole window including frame.
|
||||||
if (popupFeatures.xSet) {
|
if (popupFeatures.xSet) {
|
||||||
start_rect_.x = popupFeatures.x;
|
start_rect_.x = popupFeatures.x;
|
||||||
}
|
}
|
||||||
@ -155,6 +321,13 @@ void RootWindowGtk::InitAsPopup(RootWindow::Delegate* delegate,
|
|||||||
if (popupFeatures.heightSet) {
|
if (popupFeatures.heightSet) {
|
||||||
start_rect_.height = popupFeatures.height;
|
start_rect_.height = popupFeatures.height;
|
||||||
}
|
}
|
||||||
|
start_rect_ =
|
||||||
|
ClampBoundsToDisplay(GetScreenPixelBounds(start_rect_, std::nullopt));
|
||||||
|
|
||||||
|
if (with_osr_) {
|
||||||
|
initial_scale_factor_ =
|
||||||
|
GetScaleFactor(start_rect_, std::nullopt, /*pixel_bounds=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
CreateBrowserWindow(std::string());
|
CreateBrowserWindow(std::string());
|
||||||
|
|
||||||
@ -203,26 +376,74 @@ void RootWindowGtk::Hide() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::SetBounds(int x, int y, size_t width, size_t height) {
|
void RootWindowGtk::SetBounds(int x,
|
||||||
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds) {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
if (!window_) {
|
if (!window_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CefRect dip_bounds{x, y, static_cast<int>(width), static_cast<int>(height)};
|
||||||
|
|
||||||
|
GetWindowBoundsAndContinue(
|
||||||
|
dip_bounds, content_bounds,
|
||||||
|
base::BindOnce(
|
||||||
|
[](GtkWidget* window, const CefRect& pixel_bounds) {
|
||||||
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
|
GdkWindow* gdk_window = gtk_widget_get_window(window);
|
||||||
|
gdk_window_move_resize(gdk_window, pixel_bounds.x, pixel_bounds.y,
|
||||||
|
pixel_bounds.width, pixel_bounds.height);
|
||||||
|
},
|
||||||
|
base::Unretained(window_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RootWindowGtk::DefaultToContentBounds() const {
|
||||||
|
if (!WithWindowlessRendering()) {
|
||||||
|
// Root GtkWindow bounds are provided via GetRootWindowScreenRect.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (osr_settings_.real_screen_bounds) {
|
||||||
|
// Root GtkWindow bounds are provided via GetRootScreenRect.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// The root GtkWindow will not be queried by default.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootWindowGtk::GetWindowBoundsAndContinue(
|
||||||
|
const CefRect& dip_bounds,
|
||||||
|
bool content_bounds,
|
||||||
|
base::OnceCallback<void(const CefRect& /*pixel_bounds*/)> next) {
|
||||||
|
REQUIRE_MAIN_THREAD();
|
||||||
|
DCHECK(window_);
|
||||||
|
|
||||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
|
|
||||||
GtkWindow* window = GTK_WINDOW(window_);
|
GtkWindow* window = GTK_WINDOW(window_);
|
||||||
GdkWindow* gdk_window = gtk_widget_get_window(window_);
|
|
||||||
|
|
||||||
// Make sure the window isn't minimized or maximized.
|
// Make sure the window isn't minimized or maximized. It must also be
|
||||||
if (IsWindowMaximized(window)) {
|
// presented before we can retrieve bounds information.
|
||||||
gtk_window_unmaximize(window);
|
RestoreWindow(window);
|
||||||
} else {
|
|
||||||
gtk_window_present(window);
|
std::optional<BoundsInfo> bounds_info;
|
||||||
|
|
||||||
|
if (content_bounds) {
|
||||||
|
// Existing measurements in root window (pixel) coordinates.
|
||||||
|
GdkWindow* gdk_window = gtk_widget_get_window(window_);
|
||||||
|
GdkRectangle frame_rect = {};
|
||||||
|
gdk_window_get_frame_extents(gdk_window, &frame_rect);
|
||||||
|
bounds_info = {
|
||||||
|
{frame_rect.x, frame_rect.y, frame_rect.width, frame_rect.height},
|
||||||
|
GetWindowBounds(window, /*include_frame=*/false),
|
||||||
|
browser_bounds_};
|
||||||
}
|
}
|
||||||
|
|
||||||
gdk_window_move_resize(gdk_window, x, y, width, height);
|
GetPixelBoundsAndContinue(dip_bounds, bounds_info, GetDeviceScaleFactor(),
|
||||||
|
std::move(next));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::Close(bool force) {
|
void RootWindowGtk::Close(bool force) {
|
||||||
@ -246,15 +467,14 @@ void RootWindowGtk::SetDeviceScaleFactor(float device_scale_factor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float RootWindowGtk::GetDeviceScaleFactor() const {
|
std::optional<float> RootWindowGtk::GetDeviceScaleFactor() const {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
if (browser_window_ && with_osr_) {
|
if (browser_window_ && with_osr_) {
|
||||||
return browser_window_->GetDeviceScaleFactor();
|
return browser_window_->GetDeviceScaleFactor();
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTREACHED();
|
return std::nullopt;
|
||||||
return 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefBrowser> RootWindowGtk::GetBrowser() const {
|
CefRefPtr<CefBrowser> RootWindowGtk::GetBrowser() const {
|
||||||
@ -273,15 +493,15 @@ ClientWindowHandle RootWindowGtk::GetWindowHandle() const {
|
|||||||
|
|
||||||
bool RootWindowGtk::WithWindowlessRendering() const {
|
bool RootWindowGtk::WithWindowlessRendering() const {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
DCHECK(initialized_);
|
||||||
return with_osr_;
|
return with_osr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::CreateBrowserWindow(const std::string& startup_url) {
|
void RootWindowGtk::CreateBrowserWindow(const std::string& startup_url) {
|
||||||
if (with_osr_) {
|
if (with_osr_) {
|
||||||
OsrRendererSettings settings = {};
|
MainContext::Get()->PopulateOsrSettings(&osr_settings_);
|
||||||
MainContext::Get()->PopulateOsrSettings(&settings);
|
browser_window_.reset(new BrowserWindowOsrGtk(this, with_controls_,
|
||||||
browser_window_.reset(
|
startup_url, osr_settings_));
|
||||||
new BrowserWindowOsrGtk(this, with_controls_, startup_url, settings));
|
|
||||||
} else {
|
} else {
|
||||||
browser_window_.reset(
|
browser_window_.reset(
|
||||||
new BrowserWindowStdGtk(this, with_controls_, startup_url));
|
new BrowserWindowStdGtk(this, with_controls_, startup_url));
|
||||||
@ -329,7 +549,7 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings,
|
|||||||
G_CALLBACK(&RootWindowGtk::WindowDelete), this);
|
G_CALLBACK(&RootWindowGtk::WindowDelete), this);
|
||||||
|
|
||||||
const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
|
const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
|
||||||
GdkRGBA rgba = {0};
|
GdkRGBA rgba = {};
|
||||||
rgba.red = CefColorGetR(background_color) * 65535 / 255;
|
rgba.red = CefColorGetR(background_color) * 65535 / 255;
|
||||||
rgba.green = CefColorGetG(background_color) * 65535 / 255;
|
rgba.green = CefColorGetG(background_color) * 65535 / 255;
|
||||||
rgba.blue = CefColorGetB(background_color) * 65535 / 255;
|
rgba.blue = CefColorGetB(background_color) * 65535 / 255;
|
||||||
@ -432,6 +652,20 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings,
|
|||||||
->set_xdisplay(xdisplay);
|
->set_xdisplay(xdisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (with_osr_) {
|
||||||
|
std::optional<float> parent_scale_factor;
|
||||||
|
if (is_popup_) {
|
||||||
|
if (auto parent_window =
|
||||||
|
MainContext::Get()->GetRootWindowManager()->GetWindowForBrowser(
|
||||||
|
opener_browser_id())) {
|
||||||
|
parent_scale_factor = parent_window->GetDeviceScaleFactor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
browser_window_->SetDeviceScaleFactor(
|
||||||
|
parent_scale_factor.value_or(initial_scale_factor_));
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_popup_) {
|
if (!is_popup_) {
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
browser_window_->CreateBrowser(parent, browser_bounds_, settings, nullptr,
|
browser_window_->CreateBrowser(parent, browser_bounds_, settings, nullptr,
|
||||||
@ -525,19 +759,18 @@ void RootWindowGtk::OnAutoResize(const CefSize& new_size) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
CefRect dip_bounds{0, 0, new_size.width, new_size.height};
|
||||||
|
|
||||||
GtkWindow* window = GTK_WINDOW(window_);
|
GetWindowBoundsAndContinue(
|
||||||
GdkWindow* gdk_window = gtk_widget_get_window(window_);
|
dip_bounds, /*content_bounds=*/true,
|
||||||
|
base::BindOnce(
|
||||||
// Make sure the window isn't minimized or maximized.
|
[](GtkWidget* window, const CefRect& pixel_bounds) {
|
||||||
if (IsWindowMaximized(window)) {
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
gtk_window_unmaximize(window);
|
GdkWindow* gdk_window = gtk_widget_get_window(window);
|
||||||
} else {
|
gdk_window_resize(gdk_window, pixel_bounds.width,
|
||||||
gtk_window_present(window);
|
pixel_bounds.height);
|
||||||
}
|
},
|
||||||
|
base::Unretained(window_)));
|
||||||
gdk_window_resize(gdk_window, new_size.width, new_size.height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::OnSetLoadingState(bool isLoading,
|
void RootWindowGtk::OnSetLoadingState(bool isLoading,
|
||||||
@ -561,29 +794,46 @@ void RootWindowGtk::OnSetDraggableRegions(
|
|||||||
// TODO(cef): Implement support for draggable regions on this platform.
|
// TODO(cef): Implement support for draggable regions on this platform.
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::NotifyMoveOrResizeStarted() {
|
bool RootWindowGtk::GetRootWindowScreenRect(CefRect& rect) {
|
||||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
CEF_REQUIRE_UI_THREAD();
|
||||||
MAIN_POST_CLOSURE(
|
|
||||||
base::BindOnce(&RootWindowGtk::NotifyMoveOrResizeStarted, this));
|
if (!window_) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
|
GtkWindow* window = GTK_WINDOW(window_);
|
||||||
|
CefRect pixel_bounds = GetWindowBounds(window, /*include_frame=*/true);
|
||||||
|
rect = GetScreenDIPBounds(pixel_bounds, std::nullopt);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootWindowGtk::NotifyMoveOrResizeStarted() {
|
||||||
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
// Called when size, position or stack order changes.
|
// Called when size, position or stack order changes.
|
||||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
if (auto browser = GetBrowser()) {
|
||||||
if (browser.get()) {
|
|
||||||
// Notify the browser of move/resize events so that:
|
// Notify the browser of move/resize events so that:
|
||||||
// - Popup windows are displayed in the correct location and dismissed
|
// - Popup windows are displayed in the correct location and dismissed
|
||||||
// when the window moves.
|
// when the window moves.
|
||||||
// - Drag&drop areas are updated accordingly.
|
// - Drag&drop areas are updated accordingly.
|
||||||
browser->GetHost()->NotifyMoveOrResizeStarted();
|
browser->GetHost()->NotifyMoveOrResizeStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaybeNotifyScreenInfoChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootWindowGtk::MaybeNotifyScreenInfoChanged() {
|
||||||
|
if (!DefaultToContentBounds()) {
|
||||||
|
// Send the new root window bounds to the renderer.
|
||||||
|
if (auto browser = GetBrowser()) {
|
||||||
|
browser->GetHost()->NotifyScreenInfoChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::NotifySetFocus() {
|
void RootWindowGtk::NotifySetFocus() {
|
||||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
REQUIRE_MAIN_THREAD();
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::NotifySetFocus, this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!browser_window_.get()) {
|
if (!browser_window_.get()) {
|
||||||
return;
|
return;
|
||||||
@ -594,11 +844,7 @@ void RootWindowGtk::NotifySetFocus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::NotifyVisibilityChange(bool show) {
|
void RootWindowGtk::NotifyVisibilityChange(bool show) {
|
||||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
REQUIRE_MAIN_THREAD();
|
||||||
MAIN_POST_CLOSURE(
|
|
||||||
base::BindOnce(&RootWindowGtk::NotifyVisibilityChange, this, show));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!browser_window_.get()) {
|
if (!browser_window_.get()) {
|
||||||
return;
|
return;
|
||||||
@ -646,10 +892,7 @@ void RootWindowGtk::NotifyContentBounds(int x, int y, int width, int height) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::NotifyLoadURL(const std::string& url) {
|
void RootWindowGtk::NotifyLoadURL(const std::string& url) {
|
||||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
REQUIRE_MAIN_THREAD();
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::NotifyLoadURL, this, url));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
CefRefPtr<CefBrowser> browser = GetBrowser();
|
||||||
if (browser.get()) {
|
if (browser.get()) {
|
||||||
@ -658,11 +901,7 @@ void RootWindowGtk::NotifyLoadURL(const std::string& url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::NotifyButtonClicked(int id) {
|
void RootWindowGtk::NotifyButtonClicked(int id) {
|
||||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
REQUIRE_MAIN_THREAD();
|
||||||
MAIN_POST_CLOSURE(
|
|
||||||
base::BindOnce(&RootWindowGtk::NotifyButtonClicked, this, id));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
CefRefPtr<CefBrowser> browser = GetBrowser();
|
||||||
if (!browser.get()) {
|
if (!browser.get()) {
|
||||||
@ -688,10 +927,7 @@ void RootWindowGtk::NotifyButtonClicked(int id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::NotifyMenuItem(int id) {
|
void RootWindowGtk::NotifyMenuItem(int id) {
|
||||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
REQUIRE_MAIN_THREAD();
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::NotifyMenuItem, this, id));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the test.
|
// Run the test.
|
||||||
if (delegate_) {
|
if (delegate_) {
|
||||||
@ -700,19 +936,13 @@ void RootWindowGtk::NotifyMenuItem(int id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::NotifyForceClose() {
|
void RootWindowGtk::NotifyForceClose() {
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
REQUIRE_MAIN_THREAD();
|
||||||
CefPostTask(TID_UI, base::BindOnce(&RootWindowGtk::NotifyForceClose, this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
force_close_ = true;
|
force_close_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowGtk::NotifyCloseBrowser() {
|
void RootWindowGtk::NotifyCloseBrowser() {
|
||||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
REQUIRE_MAIN_THREAD();
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(&RootWindowGtk::NotifyCloseBrowser, this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
CefRefPtr<CefBrowser> browser = GetBrowser();
|
||||||
if (browser) {
|
if (browser) {
|
||||||
@ -798,15 +1028,18 @@ gboolean RootWindowGtk::WindowDelete(GtkWidget* widget,
|
|||||||
RootWindowGtk* self) {
|
RootWindowGtk* self) {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
|
SaveWindowRestore(widget, self->GetDeviceScaleFactor());
|
||||||
|
|
||||||
// Called to query whether the root window should be closed.
|
// Called to query whether the root window should be closed.
|
||||||
if (self->force_close_) {
|
if (self->force_close_) {
|
||||||
return FALSE; // Allow the close.
|
return FALSE; // Allow the close.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self->is_closing_) {
|
if (!self->is_closing_) {
|
||||||
// Notify the browser window that we would like to close it. This
|
// Notify the browser window that we would like to close it. With Alloy
|
||||||
// will result in a call to ClientHandler::DoClose() if the
|
// style this will result in a call to ClientHandler::DoClose() if the
|
||||||
// JavaScript 'onbeforeunload' event handler allows it.
|
// JavaScript 'onbeforeunload' event handler allows it. With Chrome style
|
||||||
|
// this will close the window indirectly via browser destruction.
|
||||||
self->NotifyCloseBrowser();
|
self->NotifyCloseBrowser();
|
||||||
|
|
||||||
// Cancel the close.
|
// Cancel the close.
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "tests/cefclient/browser/browser_window.h"
|
#include "tests/cefclient/browser/browser_window.h"
|
||||||
|
#include "tests/cefclient/browser/osr_renderer_settings.h"
|
||||||
#include "tests/cefclient/browser/root_window.h"
|
#include "tests/cefclient/browser/root_window.h"
|
||||||
|
|
||||||
namespace client {
|
namespace client {
|
||||||
@ -38,15 +39,25 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
CefBrowserSettings& settings) override;
|
CefBrowserSettings& settings) override;
|
||||||
void Show(ShowMode mode) override;
|
void Show(ShowMode mode) override;
|
||||||
void Hide() override;
|
void Hide() override;
|
||||||
void SetBounds(int x, int y, size_t width, size_t height) override;
|
void SetBounds(int x,
|
||||||
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds) override;
|
||||||
|
bool DefaultToContentBounds() const override;
|
||||||
void Close(bool force) override;
|
void Close(bool force) override;
|
||||||
void SetDeviceScaleFactor(float device_scale_factor) override;
|
void SetDeviceScaleFactor(float device_scale_factor) override;
|
||||||
float GetDeviceScaleFactor() const override;
|
std::optional<float> GetDeviceScaleFactor() const override;
|
||||||
CefRefPtr<CefBrowser> GetBrowser() const override;
|
CefRefPtr<CefBrowser> GetBrowser() const override;
|
||||||
ClientWindowHandle GetWindowHandle() const override;
|
ClientWindowHandle GetWindowHandle() const override;
|
||||||
bool WithWindowlessRendering() const override;
|
bool WithWindowlessRendering() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ContinueInitOnUIThread(std::unique_ptr<RootWindowConfig> config,
|
||||||
|
const CefBrowserSettings& settings);
|
||||||
|
void ContinueInitOnMainThread(std::unique_ptr<RootWindowConfig> config,
|
||||||
|
const CefBrowserSettings& settings);
|
||||||
|
|
||||||
void CreateBrowserWindow(const std::string& startup_url);
|
void CreateBrowserWindow(const std::string& startup_url);
|
||||||
void CreateRootWindow(const CefBrowserSettings& settings,
|
void CreateRootWindow(const CefBrowserSettings& settings,
|
||||||
bool initially_hidden);
|
bool initially_hidden);
|
||||||
@ -60,11 +71,21 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
void OnSetTitle(const std::string& title) override;
|
void OnSetTitle(const std::string& title) override;
|
||||||
void OnSetFullscreen(bool fullscreen) override;
|
void OnSetFullscreen(bool fullscreen) override;
|
||||||
void OnAutoResize(const CefSize& new_size) override;
|
void OnAutoResize(const CefSize& new_size) override;
|
||||||
|
void OnContentsBounds(const CefRect& new_bounds) override {
|
||||||
|
RootWindow::SetBounds(new_bounds,
|
||||||
|
/*content_bounds=*/DefaultToContentBounds());
|
||||||
|
}
|
||||||
void OnSetLoadingState(bool isLoading,
|
void OnSetLoadingState(bool isLoading,
|
||||||
bool canGoBack,
|
bool canGoBack,
|
||||||
bool canGoForward) override;
|
bool canGoForward) override;
|
||||||
void OnSetDraggableRegions(
|
void OnSetDraggableRegions(
|
||||||
const std::vector<CefDraggableRegion>& regions) override;
|
const std::vector<CefDraggableRegion>& regions) override;
|
||||||
|
bool GetRootWindowScreenRect(CefRect& rect) override;
|
||||||
|
|
||||||
|
void GetWindowBoundsAndContinue(
|
||||||
|
const CefRect& dip_bounds,
|
||||||
|
bool content_bounds,
|
||||||
|
base::OnceCallback<void(const CefRect& /*pixel_bounds*/)> next);
|
||||||
|
|
||||||
void NotifyMoveOrResizeStarted();
|
void NotifyMoveOrResizeStarted();
|
||||||
void NotifySetFocus();
|
void NotifySetFocus();
|
||||||
@ -78,6 +99,8 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
void NotifyCloseBrowser();
|
void NotifyCloseBrowser();
|
||||||
void NotifyDestroyedIfDone(bool window_destroyed, bool browser_destroyed);
|
void NotifyDestroyedIfDone(bool window_destroyed, bool browser_destroyed);
|
||||||
|
|
||||||
|
void MaybeNotifyScreenInfoChanged();
|
||||||
|
|
||||||
GtkWidget* CreateMenuBar();
|
GtkWidget* CreateMenuBar();
|
||||||
GtkWidget* CreateMenu(GtkWidget* menu_bar, const char* text);
|
GtkWidget* CreateMenu(GtkWidget* menu_bar, const char* text);
|
||||||
GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text, int id);
|
GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text, int id);
|
||||||
@ -128,8 +151,11 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
bool with_controls_;
|
bool with_controls_;
|
||||||
bool always_on_top_;
|
bool always_on_top_;
|
||||||
bool with_osr_;
|
bool with_osr_;
|
||||||
|
OsrRendererSettings osr_settings_;
|
||||||
bool is_popup_;
|
bool is_popup_;
|
||||||
CefRect start_rect_;
|
CefRect start_rect_;
|
||||||
|
cef_show_state_t initial_show_state_ = CEF_SHOW_STATE_NORMAL;
|
||||||
|
float initial_scale_factor_ = 1.0;
|
||||||
std::unique_ptr<BrowserWindow> browser_window_;
|
std::unique_ptr<BrowserWindow> browser_window_;
|
||||||
|
|
||||||
// Main window.
|
// Main window.
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
|
struct OsrRendererSettings;
|
||||||
class RootWindowMacImpl;
|
class RootWindowMacImpl;
|
||||||
|
|
||||||
// OS X implementation of a top-level native window in the browser process.
|
// OS X implementation of a top-level native window in the browser process.
|
||||||
@ -27,6 +28,7 @@ class RootWindowMac : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
|
|
||||||
BrowserWindow* browser_window() const;
|
BrowserWindow* browser_window() const;
|
||||||
RootWindow::Delegate* delegate() const;
|
RootWindow::Delegate* delegate() const;
|
||||||
|
const OsrRendererSettings* osr_settings() const;
|
||||||
|
|
||||||
// RootWindow methods.
|
// RootWindow methods.
|
||||||
void Init(RootWindow::Delegate* delegate,
|
void Init(RootWindow::Delegate* delegate,
|
||||||
@ -41,10 +43,15 @@ class RootWindowMac : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
CefBrowserSettings& settings) override;
|
CefBrowserSettings& settings) override;
|
||||||
void Show(ShowMode mode) override;
|
void Show(ShowMode mode) override;
|
||||||
void Hide() override;
|
void Hide() override;
|
||||||
void SetBounds(int x, int y, size_t width, size_t height) override;
|
void SetBounds(int x,
|
||||||
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds) override;
|
||||||
|
bool DefaultToContentBounds() const override;
|
||||||
void Close(bool force) override;
|
void Close(bool force) override;
|
||||||
void SetDeviceScaleFactor(float device_scale_factor) override;
|
void SetDeviceScaleFactor(float device_scale_factor) override;
|
||||||
float GetDeviceScaleFactor() const override;
|
std::optional<float> GetDeviceScaleFactor() const override;
|
||||||
CefRefPtr<CefBrowser> GetBrowser() const override;
|
CefRefPtr<CefBrowser> GetBrowser() const override;
|
||||||
ClientWindowHandle GetWindowHandle() const override;
|
ClientWindowHandle GetWindowHandle() const override;
|
||||||
bool WithWindowlessRendering() const override;
|
bool WithWindowlessRendering() const override;
|
||||||
@ -57,6 +64,10 @@ class RootWindowMac : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
void OnSetTitle(const std::string& title) override;
|
void OnSetTitle(const std::string& title) override;
|
||||||
void OnSetFullscreen(bool fullscreen) override;
|
void OnSetFullscreen(bool fullscreen) override;
|
||||||
void OnAutoResize(const CefSize& new_size) override;
|
void OnAutoResize(const CefSize& new_size) override;
|
||||||
|
void OnContentsBounds(const CefRect& new_bounds) override {
|
||||||
|
RootWindow::SetBounds(new_bounds,
|
||||||
|
/*content_bounds=*/DefaultToContentBounds());
|
||||||
|
}
|
||||||
void OnSetLoadingState(bool isLoading,
|
void OnSetLoadingState(bool isLoading,
|
||||||
bool canGoBack,
|
bool canGoBack,
|
||||||
bool canGoForward) override;
|
bool canGoForward) override;
|
||||||
|
@ -14,7 +14,10 @@
|
|||||||
#include "tests/cefclient/browser/browser_window_std_mac.h"
|
#include "tests/cefclient/browser/browser_window_std_mac.h"
|
||||||
#include "tests/cefclient/browser/client_prefs.h"
|
#include "tests/cefclient/browser/client_prefs.h"
|
||||||
#include "tests/cefclient/browser/main_context.h"
|
#include "tests/cefclient/browser/main_context.h"
|
||||||
|
#include "tests/cefclient/browser/osr_renderer_settings.h"
|
||||||
|
#include "tests/cefclient/browser/root_window_manager.h"
|
||||||
#include "tests/cefclient/browser/temp_window.h"
|
#include "tests/cefclient/browser/temp_window.h"
|
||||||
|
#include "tests/cefclient/browser/util_mac.h"
|
||||||
#include "tests/cefclient/browser/window_test_runner_mac.h"
|
#include "tests/cefclient/browser/window_test_runner_mac.h"
|
||||||
#include "tests/shared/browser/main_message_loop.h"
|
#include "tests/shared/browser/main_message_loop.h"
|
||||||
#include "tests/shared/common/client_switches.h"
|
#include "tests/shared/common/client_switches.h"
|
||||||
@ -65,40 +68,6 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
|||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current DIP screen bounds for a visible window in the
|
|
||||||
// restored position, or nullopt if the window is currently minimized or
|
|
||||||
// fullscreen.
|
|
||||||
std::optional<CefRect> GetWindowBoundsInScreen(NSWindow* window) {
|
|
||||||
if ([window isMiniaturized] or [window isZoomed]) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto screen = [window screen];
|
|
||||||
if (screen == nil) {
|
|
||||||
screen = [NSScreen mainScreen];
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto bounds = [window frame];
|
|
||||||
const auto screen_bounds = [screen frame];
|
|
||||||
|
|
||||||
if (NSEqualRects(bounds, screen_bounds)) {
|
|
||||||
// Don't include windows that are transitioning to fullscreen.
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRect dip_bounds{static_cast<int>(bounds.origin.x),
|
|
||||||
static_cast<int>(bounds.origin.y),
|
|
||||||
static_cast<int>(bounds.size.width),
|
|
||||||
static_cast<int>(bounds.size.height)};
|
|
||||||
|
|
||||||
// Convert from macOS coordinates (bottom-left origin) to DIP coordinates
|
|
||||||
// (top-left origin).
|
|
||||||
dip_bounds.y = static_cast<int>(screen_bounds.size.height) -
|
|
||||||
dip_bounds.height - dip_bounds.y;
|
|
||||||
|
|
||||||
return dip_bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep the frame bounds inside the display work area.
|
// Keep the frame bounds inside the display work area.
|
||||||
NSRect ClampNSBoundsToWorkArea(const NSRect& frame_bounds,
|
NSRect ClampNSBoundsToWorkArea(const NSRect& frame_bounds,
|
||||||
const CefRect& display_bounds,
|
const CefRect& display_bounds,
|
||||||
@ -142,6 +111,7 @@ NSRect ClampNSBoundsToWorkArea(const NSRect& frame_bounds,
|
|||||||
void GetNSBoundsInDisplay(const CefRect& dip_bounds,
|
void GetNSBoundsInDisplay(const CefRect& dip_bounds,
|
||||||
bool input_content_bounds,
|
bool input_content_bounds,
|
||||||
NSWindowStyleMask style_mask,
|
NSWindowStyleMask style_mask,
|
||||||
|
bool add_controls,
|
||||||
NSRect& frame_rect,
|
NSRect& frame_rect,
|
||||||
NSRect& content_rect) {
|
NSRect& content_rect) {
|
||||||
// Identify the closest display.
|
// Identify the closest display.
|
||||||
@ -158,18 +128,24 @@ void GetNSBoundsInDisplay(const CefRect& dip_bounds,
|
|||||||
requested_rect.origin.y = display_bounds.height - requested_rect.size.height -
|
requested_rect.origin.y = display_bounds.height - requested_rect.size.height -
|
||||||
requested_rect.origin.y;
|
requested_rect.origin.y;
|
||||||
|
|
||||||
|
bool changed_content_bounds = false;
|
||||||
|
|
||||||
// Calculate the equivalent frame and content bounds.
|
// Calculate the equivalent frame and content bounds.
|
||||||
if (input_content_bounds) {
|
if (input_content_bounds) {
|
||||||
// Compute frame rect from content rect. Keep the requested origin.
|
// Compute frame rect from content rect. Keep the requested origin.
|
||||||
content_rect = requested_rect;
|
content_rect = requested_rect;
|
||||||
frame_rect = [NSWindow frameRectForContentRect:content_rect
|
frame_rect = [NSWindow frameRectForContentRect:content_rect
|
||||||
styleMask:style_mask];
|
styleMask:style_mask];
|
||||||
|
if (add_controls) {
|
||||||
|
frame_rect.size.height += URLBAR_HEIGHT;
|
||||||
|
}
|
||||||
frame_rect.origin = requested_rect.origin;
|
frame_rect.origin = requested_rect.origin;
|
||||||
} else {
|
} else {
|
||||||
// Compute content rect from frame rect.
|
// Compute content rect from frame rect.
|
||||||
frame_rect = requested_rect;
|
frame_rect = requested_rect;
|
||||||
content_rect = [NSWindow contentRectForFrameRect:frame_rect
|
content_rect = [NSWindow contentRectForFrameRect:frame_rect
|
||||||
styleMask:style_mask];
|
styleMask:style_mask];
|
||||||
|
changed_content_bounds = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the frame inside the display work area.
|
// Keep the frame inside the display work area.
|
||||||
@ -179,6 +155,12 @@ void GetNSBoundsInDisplay(const CefRect& dip_bounds,
|
|||||||
frame_rect = new_frame_rect;
|
frame_rect = new_frame_rect;
|
||||||
content_rect = [NSWindow contentRectForFrameRect:frame_rect
|
content_rect = [NSWindow contentRectForFrameRect:frame_rect
|
||||||
styleMask:style_mask];
|
styleMask:style_mask];
|
||||||
|
changed_content_bounds = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed_content_bounds && add_controls) {
|
||||||
|
content_rect.origin.y -= URLBAR_HEIGHT;
|
||||||
|
content_rect.size.height -= URLBAR_HEIGHT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,10 +193,15 @@ class RootWindowMacImpl
|
|||||||
CefBrowserSettings& settings);
|
CefBrowserSettings& settings);
|
||||||
void Show(RootWindow::ShowMode mode);
|
void Show(RootWindow::ShowMode mode);
|
||||||
void Hide();
|
void Hide();
|
||||||
void SetBounds(int x, int y, size_t width, size_t height);
|
void SetBounds(int x,
|
||||||
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds);
|
||||||
|
bool DefaultToContentBounds() const;
|
||||||
void Close(bool force);
|
void Close(bool force);
|
||||||
void SetDeviceScaleFactor(float device_scale_factor);
|
void SetDeviceScaleFactor(float device_scale_factor);
|
||||||
float GetDeviceScaleFactor() const;
|
std::optional<float> GetDeviceScaleFactor() const;
|
||||||
CefRefPtr<CefBrowser> GetBrowser() const;
|
CefRefPtr<CefBrowser> GetBrowser() const;
|
||||||
ClientWindowHandle GetWindowHandle() const;
|
ClientWindowHandle GetWindowHandle() const;
|
||||||
bool WithWindowlessRendering() const;
|
bool WithWindowlessRendering() const;
|
||||||
@ -236,6 +223,7 @@ class RootWindowMacImpl
|
|||||||
RootWindowMac& root_window_;
|
RootWindowMac& root_window_;
|
||||||
bool with_controls_ = false;
|
bool with_controls_ = false;
|
||||||
bool with_osr_ = false;
|
bool with_osr_ = false;
|
||||||
|
OsrRendererSettings osr_settings_;
|
||||||
bool is_popup_ = false;
|
bool is_popup_ = false;
|
||||||
CefRect initial_bounds_;
|
CefRect initial_bounds_;
|
||||||
cef_show_state_t initial_show_state_ = CEF_SHOW_STATE_NORMAL;
|
cef_show_state_t initial_show_state_ = CEF_SHOW_STATE_NORMAL;
|
||||||
@ -390,7 +378,11 @@ void RootWindowMacImpl::Hide() {
|
|||||||
[window_ orderOut:nil];
|
[window_ orderOut:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowMacImpl::SetBounds(int x, int y, size_t width, size_t height) {
|
void RootWindowMacImpl::SetBounds(int x,
|
||||||
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds) {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
if (!window_) {
|
if (!window_) {
|
||||||
@ -399,15 +391,29 @@ void RootWindowMacImpl::SetBounds(int x, int y, size_t width, size_t height) {
|
|||||||
|
|
||||||
const CefRect dip_bounds(x, y, static_cast<int>(width),
|
const CefRect dip_bounds(x, y, static_cast<int>(width),
|
||||||
static_cast<int>(height));
|
static_cast<int>(height));
|
||||||
|
const bool add_controls = WithWindowlessRendering() || with_controls_;
|
||||||
|
|
||||||
// Calculate the equivalent frame and content area bounds.
|
// Calculate the equivalent frame and content area bounds.
|
||||||
NSRect frame_rect, content_rect;
|
NSRect frame_rect, content_rect;
|
||||||
GetNSBoundsInDisplay(dip_bounds, /*input_content_bounds=*/true,
|
GetNSBoundsInDisplay(dip_bounds, content_bounds, [window_ styleMask],
|
||||||
[window_ styleMask], frame_rect, content_rect);
|
add_controls, frame_rect, content_rect);
|
||||||
|
|
||||||
[window_ setFrame:frame_rect display:YES];
|
[window_ setFrame:frame_rect display:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RootWindowMacImpl::DefaultToContentBounds() const {
|
||||||
|
if (!WithWindowlessRendering()) {
|
||||||
|
// The root NSWindow will be queried by default.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (osr_settings_.real_screen_bounds) {
|
||||||
|
// Root NSWindow bounds are provided via GetRootWindowRect.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// The root NSWindow will not be queried by default.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void RootWindowMacImpl::Close(bool force) {
|
void RootWindowMacImpl::Close(bool force) {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
@ -426,15 +432,14 @@ void RootWindowMacImpl::SetDeviceScaleFactor(float device_scale_factor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float RootWindowMacImpl::GetDeviceScaleFactor() const {
|
std::optional<float> RootWindowMacImpl::GetDeviceScaleFactor() const {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
if (browser_window_ && with_osr_) {
|
if (browser_window_ && with_osr_) {
|
||||||
return browser_window_->GetDeviceScaleFactor();
|
return browser_window_->GetDeviceScaleFactor();
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTREACHED();
|
return std::nullopt;
|
||||||
return 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefBrowser> RootWindowMacImpl::GetBrowser() const {
|
CefRefPtr<CefBrowser> RootWindowMacImpl::GetBrowser() const {
|
||||||
@ -453,6 +458,7 @@ ClientWindowHandle RootWindowMacImpl::GetWindowHandle() const {
|
|||||||
|
|
||||||
bool RootWindowMacImpl::WithWindowlessRendering() const {
|
bool RootWindowMacImpl::WithWindowlessRendering() const {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
DCHECK(root_window_.initialized_);
|
||||||
return with_osr_;
|
return with_osr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,10 +470,9 @@ void RootWindowMacImpl::OnNativeWindowClosed() {
|
|||||||
|
|
||||||
void RootWindowMacImpl::CreateBrowserWindow(const std::string& startup_url) {
|
void RootWindowMacImpl::CreateBrowserWindow(const std::string& startup_url) {
|
||||||
if (with_osr_) {
|
if (with_osr_) {
|
||||||
OsrRendererSettings settings = {};
|
MainContext::Get()->PopulateOsrSettings(&osr_settings_);
|
||||||
MainContext::Get()->PopulateOsrSettings(&settings);
|
|
||||||
browser_window_.reset(new BrowserWindowOsrMac(&root_window_, with_controls_,
|
browser_window_.reset(new BrowserWindowOsrMac(&root_window_, with_controls_,
|
||||||
startup_url, settings));
|
startup_url, osr_settings_));
|
||||||
} else {
|
} else {
|
||||||
browser_window_.reset(
|
browser_window_.reset(
|
||||||
new BrowserWindowStdMac(&root_window_, with_controls_, startup_url));
|
new BrowserWindowStdMac(&root_window_, with_controls_, startup_url));
|
||||||
@ -501,10 +506,12 @@ void RootWindowMacImpl::CreateRootWindow(const CefBrowserSettings& settings,
|
|||||||
(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
|
(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
|
||||||
NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable);
|
NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable);
|
||||||
|
|
||||||
// Calculate the equivalent frame and content area bounds.
|
// Calculate the equivalent frame and content area bounds. Controls, if any,
|
||||||
|
// are already included in the desired size.
|
||||||
NSRect frame_rect, content_rect;
|
NSRect frame_rect, content_rect;
|
||||||
GetNSBoundsInDisplay(dip_bounds, /*input_content_bounds=*/is_popup_,
|
GetNSBoundsInDisplay(dip_bounds, /*input_content_bounds=*/is_popup_,
|
||||||
style_mask, frame_rect, content_rect);
|
style_mask, /*add_controls=*/false, frame_rect,
|
||||||
|
content_rect);
|
||||||
|
|
||||||
// Create the main window.
|
// Create the main window.
|
||||||
window_ = [[NSWindow alloc] initWithContentRect:content_rect
|
window_ = [[NSWindow alloc] initWithContentRect:content_rect
|
||||||
@ -606,6 +613,25 @@ void RootWindowMacImpl::CreateRootWindow(const CefBrowserSettings& settings,
|
|||||||
// if the point is on a secondary display.
|
// if the point is on a secondary display.
|
||||||
[window_ setFrameOrigin:frame_rect.origin];
|
[window_ setFrameOrigin:frame_rect.origin];
|
||||||
|
|
||||||
|
if (with_osr_) {
|
||||||
|
std::optional<float> parent_scale_factor;
|
||||||
|
if (is_popup_) {
|
||||||
|
if (auto parent_window =
|
||||||
|
MainContext::Get()->GetRootWindowManager()->GetWindowForBrowser(
|
||||||
|
root_window_.opener_browser_id())) {
|
||||||
|
parent_scale_factor = parent_window->GetDeviceScaleFactor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent_scale_factor) {
|
||||||
|
browser_window_->SetDeviceScaleFactor(*parent_scale_factor);
|
||||||
|
} else {
|
||||||
|
auto display = CefDisplay::GetDisplayMatchingBounds(
|
||||||
|
dip_bounds, /*input_pixel_coords=*/false);
|
||||||
|
browser_window_->SetDeviceScaleFactor(display->GetDeviceScaleFactor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_popup_) {
|
if (!is_popup_) {
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
browser_window_->CreateBrowser(
|
browser_window_->CreateBrowser(
|
||||||
@ -709,14 +735,20 @@ void RootWindowMacImpl::OnAutoResize(const CefSize& new_size) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Desired content rectangle.
|
CefRect dip_bounds(0, 0, static_cast<int>(new_size.width),
|
||||||
NSRect content_rect;
|
static_cast<int>(new_size.height));
|
||||||
content_rect.size.width = static_cast<int>(new_size.width);
|
|
||||||
content_rect.size.height =
|
if (auto screen_bounds = GetWindowBoundsInScreen(window_)) {
|
||||||
static_cast<int>(new_size.height) + (with_controls_ ? URLBAR_HEIGHT : 0);
|
dip_bounds.x = (*screen_bounds).x;
|
||||||
|
dip_bounds.y = (*screen_bounds).y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the equivalent frame and content area bounds.
|
||||||
|
NSRect frame_rect, content_rect;
|
||||||
|
GetNSBoundsInDisplay(dip_bounds, /*input_content_bounds=*/true,
|
||||||
|
[window_ styleMask], with_controls_, frame_rect,
|
||||||
|
content_rect);
|
||||||
|
|
||||||
// Convert to a frame rectangle.
|
|
||||||
NSRect frame_rect = [window_ frameRectForContentRect:content_rect];
|
|
||||||
// Don't change the origin.
|
// Don't change the origin.
|
||||||
frame_rect.origin = window_.frame.origin;
|
frame_rect.origin = window_.frame.origin;
|
||||||
|
|
||||||
@ -775,6 +807,10 @@ RootWindow::Delegate* RootWindowMac::delegate() const {
|
|||||||
return delegate_;
|
return delegate_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const OsrRendererSettings* RootWindowMac::osr_settings() const {
|
||||||
|
return &impl_->osr_settings_;
|
||||||
|
}
|
||||||
|
|
||||||
void RootWindowMac::Init(RootWindow::Delegate* delegate,
|
void RootWindowMac::Init(RootWindow::Delegate* delegate,
|
||||||
std::unique_ptr<RootWindowConfig> config,
|
std::unique_ptr<RootWindowConfig> config,
|
||||||
const CefBrowserSettings& settings) {
|
const CefBrowserSettings& settings) {
|
||||||
@ -804,8 +840,16 @@ void RootWindowMac::Hide() {
|
|||||||
impl_->Hide();
|
impl_->Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowMac::SetBounds(int x, int y, size_t width, size_t height) {
|
void RootWindowMac::SetBounds(int x,
|
||||||
impl_->SetBounds(x, y, width, height);
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds) {
|
||||||
|
impl_->SetBounds(x, y, width, height, content_bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RootWindowMac::DefaultToContentBounds() const {
|
||||||
|
return impl_->DefaultToContentBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowMac::Close(bool force) {
|
void RootWindowMac::Close(bool force) {
|
||||||
@ -816,7 +860,7 @@ void RootWindowMac::SetDeviceScaleFactor(float device_scale_factor) {
|
|||||||
impl_->SetDeviceScaleFactor(device_scale_factor);
|
impl_->SetDeviceScaleFactor(device_scale_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
float RootWindowMac::GetDeviceScaleFactor() const {
|
std::optional<float> RootWindowMac::GetDeviceScaleFactor() const {
|
||||||
return impl_->GetDeviceScaleFactor();
|
return impl_->GetDeviceScaleFactor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1005,6 +1049,16 @@ void RootWindowMac::OnNativeWindowClosed() {
|
|||||||
if (dip_bounds) {
|
if (dip_bounds) {
|
||||||
last_visible_bounds_ = dip_bounds;
|
last_visible_bounds_ = dip_bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (root_window_->WithWindowlessRendering() &&
|
||||||
|
root_window_->osr_settings()->real_screen_bounds) {
|
||||||
|
// Send the new root window bounds to the renderer.
|
||||||
|
if (auto* browser_window = root_window_->browser_window()) {
|
||||||
|
if (auto browser = browser_window->GetBrowser()) {
|
||||||
|
browser->GetHost()->NotifyScreenInfoChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the application has been hidden.
|
// Called when the application has been hidden.
|
||||||
|
@ -137,11 +137,18 @@ void RootWindowViews::Hide() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowViews::SetBounds(int x, int y, size_t width, size_t height) {
|
void RootWindowViews::SetBounds(int x,
|
||||||
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds) {
|
||||||
|
// We always expect Window bounds with Views-hosted browsers.
|
||||||
|
DCHECK(!content_bounds);
|
||||||
|
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
// Execute this method on the UI thread.
|
// Execute this method on the UI thread.
|
||||||
CefPostTask(TID_UI, base::BindOnce(&RootWindowViews::SetBounds, this, x, y,
|
CefPostTask(TID_UI, base::BindOnce(&RootWindowViews::SetBounds, this, x, y,
|
||||||
width, height));
|
width, height, content_bounds));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +158,11 @@ void RootWindowViews::SetBounds(int x, int y, size_t width, size_t height) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RootWindowViews::DefaultToContentBounds() const {
|
||||||
|
// Views-hosted browsers always receive CefWindow bounds.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void RootWindowViews::Close(bool force) {
|
void RootWindowViews::Close(bool force) {
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
// Execute this method on the UI thread.
|
// Execute this method on the UI thread.
|
||||||
@ -169,11 +181,11 @@ void RootWindowViews::SetDeviceScaleFactor(float device_scale_factor) {
|
|||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
float RootWindowViews::GetDeviceScaleFactor() const {
|
std::optional<float> RootWindowViews::GetDeviceScaleFactor() const {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
// Windowless rendering is not supported.
|
// Windowless rendering is not supported.
|
||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
return 0.0;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefBrowser> RootWindowViews::GetBrowser() const {
|
CefRefPtr<CefBrowser> RootWindowViews::GetBrowser() const {
|
||||||
|
@ -44,10 +44,15 @@ class RootWindowViews : public RootWindow,
|
|||||||
CefBrowserSettings& settings) override;
|
CefBrowserSettings& settings) override;
|
||||||
void Show(ShowMode mode) override;
|
void Show(ShowMode mode) override;
|
||||||
void Hide() override;
|
void Hide() override;
|
||||||
void SetBounds(int x, int y, size_t width, size_t height) override;
|
void SetBounds(int x,
|
||||||
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds) override;
|
||||||
|
bool DefaultToContentBounds() const override;
|
||||||
void Close(bool force) override;
|
void Close(bool force) override;
|
||||||
void SetDeviceScaleFactor(float device_scale_factor) override;
|
void SetDeviceScaleFactor(float device_scale_factor) override;
|
||||||
float GetDeviceScaleFactor() const override;
|
std::optional<float> GetDeviceScaleFactor() const override;
|
||||||
CefRefPtr<CefBrowser> GetBrowser() const override;
|
CefRefPtr<CefBrowser> GetBrowser() const override;
|
||||||
ClientWindowHandle GetWindowHandle() const override;
|
ClientWindowHandle GetWindowHandle() const override;
|
||||||
bool WithWindowlessRendering() const override { return false; }
|
bool WithWindowlessRendering() const override { return false; }
|
||||||
@ -80,6 +85,10 @@ class RootWindowViews : public RootWindow,
|
|||||||
void OnSetFavicon(CefRefPtr<CefImage> image) override;
|
void OnSetFavicon(CefRefPtr<CefImage> image) override;
|
||||||
void OnSetFullscreen(bool fullscreen) override;
|
void OnSetFullscreen(bool fullscreen) override;
|
||||||
void OnAutoResize(const CefSize& new_size) override;
|
void OnAutoResize(const CefSize& new_size) override;
|
||||||
|
void OnContentsBounds(const CefRect& new_bounds) override {
|
||||||
|
RootWindow::SetBounds(new_bounds,
|
||||||
|
/*content_bounds=*/DefaultToContentBounds());
|
||||||
|
}
|
||||||
void OnSetLoadingState(bool isLoading,
|
void OnSetLoadingState(bool isLoading,
|
||||||
bool canGoBack,
|
bool canGoBack,
|
||||||
bool canGoForward) override;
|
bool canGoForward) override;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "tests/cefclient/browser/client_prefs.h"
|
#include "tests/cefclient/browser/client_prefs.h"
|
||||||
#include "tests/cefclient/browser/main_context.h"
|
#include "tests/cefclient/browser/main_context.h"
|
||||||
#include "tests/cefclient/browser/resource.h"
|
#include "tests/cefclient/browser/resource.h"
|
||||||
|
#include "tests/cefclient/browser/root_window_manager.h"
|
||||||
#include "tests/cefclient/browser/temp_window.h"
|
#include "tests/cefclient/browser/temp_window.h"
|
||||||
#include "tests/cefclient/browser/window_test_runner_win.h"
|
#include "tests/cefclient/browser/window_test_runner_win.h"
|
||||||
#include "tests/shared/browser/geometry_util.h"
|
#include "tests/shared/browser/geometry_util.h"
|
||||||
@ -85,6 +86,8 @@ bool IsProcessPerMonitorDpiAware() {
|
|||||||
// DPI value for 1x scale factor.
|
// DPI value for 1x scale factor.
|
||||||
#define DPI_1X 96.0f
|
#define DPI_1X 96.0f
|
||||||
|
|
||||||
|
// WARNING: Only use this value for scaling native controls. DIP coordinates
|
||||||
|
// originating from the browser should be converted using GetScreenPixelBounds.
|
||||||
float GetWindowScaleFactor(HWND hwnd) {
|
float GetWindowScaleFactor(HWND hwnd) {
|
||||||
if (hwnd && IsProcessPerMonitorDpiAware()) {
|
if (hwnd && IsProcessPerMonitorDpiAware()) {
|
||||||
typedef UINT(WINAPI * GetDpiForWindowPtr)(HWND);
|
typedef UINT(WINAPI * GetDpiForWindowPtr)(HWND);
|
||||||
@ -106,6 +109,104 @@ int GetURLBarHeight(HWND hwnd) {
|
|||||||
return LogicalToDevice(URLBAR_HEIGHT, GetWindowScaleFactor(hwnd));
|
return LogicalToDevice(URLBAR_HEIGHT, GetWindowScaleFactor(hwnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GetScaleFactor(const CefRect& bounds,
|
||||||
|
const std::optional<float>& device_scale_factor,
|
||||||
|
bool pixel_bounds) {
|
||||||
|
if (device_scale_factor.has_value()) {
|
||||||
|
return *device_scale_factor;
|
||||||
|
}
|
||||||
|
auto display = CefDisplay::GetDisplayMatchingBounds(
|
||||||
|
bounds, /*input_pixel_coords=*/pixel_bounds);
|
||||||
|
return display->GetDeviceScaleFactor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep the bounds inside the closest display work area.
|
||||||
|
CefRect ClampBoundsToDisplay(const CefRect& pixel_bounds) {
|
||||||
|
auto display = CefDisplay::GetDisplayMatchingBounds(
|
||||||
|
pixel_bounds, /*input_pixel_coords=*/true);
|
||||||
|
CefRect work_area =
|
||||||
|
CefDisplay::ConvertScreenRectToPixels(display->GetWorkArea());
|
||||||
|
|
||||||
|
CefRect bounds = pixel_bounds;
|
||||||
|
ConstrainWindowBounds(work_area, bounds);
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert DIP screen coordinates originating from the browser to device screen
|
||||||
|
// (pixel) coordinates. |device_scale_factor| will be specified with off-screen
|
||||||
|
// rendering.
|
||||||
|
CefRect GetScreenPixelBounds(const CefRect& dip_bounds,
|
||||||
|
const std::optional<float>& device_scale_factor) {
|
||||||
|
if (device_scale_factor.has_value()) {
|
||||||
|
return LogicalToDevice(dip_bounds, *device_scale_factor);
|
||||||
|
}
|
||||||
|
return CefDisplay::ConvertScreenRectToPixels(dip_bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// |content_bounds| is the browser content area bounds in DIP screen
|
||||||
|
// coordinates. Convert to device screen (pixel) coordinates and then expand to
|
||||||
|
// frame bounds. Keep the resulting bounds inside the closest display work area.
|
||||||
|
// |device_scale_factor| will be specified with off-screen rendering.
|
||||||
|
CefRect GetFrameBoundsInDisplay(
|
||||||
|
HWND hwnd,
|
||||||
|
const CefRect& content_bounds,
|
||||||
|
bool with_controls,
|
||||||
|
const std::optional<float>& device_scale_factor) {
|
||||||
|
CefRect pixel_bounds =
|
||||||
|
GetScreenPixelBounds(content_bounds, device_scale_factor);
|
||||||
|
if (with_controls) {
|
||||||
|
// Expand the bounds to include native controls.
|
||||||
|
const int urlbar_height = GetURLBarHeight(hwnd);
|
||||||
|
pixel_bounds.y -= urlbar_height;
|
||||||
|
pixel_bounds.height += urlbar_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
RECT rect = {pixel_bounds.x, pixel_bounds.y,
|
||||||
|
pixel_bounds.x + pixel_bounds.width,
|
||||||
|
pixel_bounds.y + pixel_bounds.height};
|
||||||
|
DWORD style = GetWindowLong(hwnd, GWL_STYLE);
|
||||||
|
DWORD ex_style = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||||
|
bool has_menu = !(style & WS_CHILD) && (GetMenu(hwnd) != nullptr);
|
||||||
|
|
||||||
|
// Calculate the frame size based on the current style.
|
||||||
|
AdjustWindowRectEx(&rect, style, has_menu, ex_style);
|
||||||
|
|
||||||
|
return ClampBoundsToDisplay(
|
||||||
|
{rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute calls on the required threads.
|
||||||
|
void GetPixelBoundsAndContinue(HWND hwnd,
|
||||||
|
const CefRect& dip_bounds,
|
||||||
|
bool content_bounds,
|
||||||
|
bool with_controls,
|
||||||
|
const std::optional<float>& device_scale_factor,
|
||||||
|
base::OnceCallback<void(const CefRect&)> next) {
|
||||||
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
|
CefPostTask(TID_UI,
|
||||||
|
base::BindOnce(&GetPixelBoundsAndContinue, hwnd, dip_bounds,
|
||||||
|
content_bounds, with_controls,
|
||||||
|
device_scale_factor, std::move(next)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRect pixel_bounds;
|
||||||
|
if (content_bounds) {
|
||||||
|
pixel_bounds = GetFrameBoundsInDisplay(hwnd, dip_bounds, with_controls,
|
||||||
|
device_scale_factor);
|
||||||
|
} else {
|
||||||
|
pixel_bounds = ClampBoundsToDisplay(
|
||||||
|
GetScreenPixelBounds(dip_bounds, device_scale_factor));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CURRENTLY_ON_MAIN_THREAD()) {
|
||||||
|
std::move(next).Run(pixel_bounds);
|
||||||
|
} else {
|
||||||
|
MAIN_POST_CLOSURE(base::BindOnce(std::move(next), pixel_bounds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
RootWindowWin::RootWindowWin(bool use_alloy_style)
|
RootWindowWin::RootWindowWin(bool use_alloy_style)
|
||||||
@ -165,8 +266,17 @@ void RootWindowWin::ContinueInitOnUIThread(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(&RootWindowWin::ContinueInitOnMainThread,
|
if (with_osr_) {
|
||||||
this, std::move(config), settings));
|
initial_scale_factor_ =
|
||||||
|
GetScaleFactor(initial_bounds_, std::nullopt, /*pixel_bounds=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CURRENTLY_ON_MAIN_THREAD()) {
|
||||||
|
ContinueInitOnMainThread(std::move(config), settings);
|
||||||
|
} else {
|
||||||
|
MAIN_POST_CLOSURE(base::BindOnce(&RootWindowWin::ContinueInitOnMainThread,
|
||||||
|
this, std::move(config), settings));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowWin::ContinueInitOnMainThread(
|
void RootWindowWin::ContinueInitOnMainThread(
|
||||||
@ -196,6 +306,7 @@ void RootWindowWin::InitAsPopup(RootWindow::Delegate* delegate,
|
|||||||
with_osr_ = with_osr;
|
with_osr_ = with_osr;
|
||||||
is_popup_ = true;
|
is_popup_ = true;
|
||||||
|
|
||||||
|
// NOTE: This will be the size for the whole window including frame.
|
||||||
if (popupFeatures.xSet) {
|
if (popupFeatures.xSet) {
|
||||||
initial_bounds_.x = popupFeatures.x;
|
initial_bounds_.x = popupFeatures.x;
|
||||||
}
|
}
|
||||||
@ -208,6 +319,13 @@ void RootWindowWin::InitAsPopup(RootWindow::Delegate* delegate,
|
|||||||
if (popupFeatures.heightSet) {
|
if (popupFeatures.heightSet) {
|
||||||
initial_bounds_.height = popupFeatures.height;
|
initial_bounds_.height = popupFeatures.height;
|
||||||
}
|
}
|
||||||
|
initial_bounds_ = ClampBoundsToDisplay(
|
||||||
|
CefDisplay::ConvertScreenRectToPixels(initial_bounds_));
|
||||||
|
|
||||||
|
if (with_osr_) {
|
||||||
|
initial_scale_factor_ =
|
||||||
|
GetScaleFactor(initial_bounds_, std::nullopt, /*pixel_bounds=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
CreateBrowserWindow(std::string());
|
CreateBrowserWindow(std::string());
|
||||||
|
|
||||||
@ -256,13 +374,51 @@ void RootWindowWin::Hide() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowWin::SetBounds(int x, int y, size_t width, size_t height) {
|
void RootWindowWin::SetBounds(int x,
|
||||||
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds) {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
if (hwnd_) {
|
if (!hwnd_) {
|
||||||
SetWindowPos(hwnd_, nullptr, x, y, static_cast<int>(width),
|
return;
|
||||||
static_cast<int>(height), SWP_NOZORDER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CefRect dip_bounds = {x, y, static_cast<int>(width),
|
||||||
|
static_cast<int>(height)};
|
||||||
|
GetWindowBoundsAndContinue(
|
||||||
|
dip_bounds, content_bounds,
|
||||||
|
base::BindOnce(
|
||||||
|
[](HWND hwnd, const CefRect& pixel_bounds) {
|
||||||
|
SetWindowPos(hwnd, nullptr, pixel_bounds.x, pixel_bounds.y,
|
||||||
|
pixel_bounds.width, pixel_bounds.height, SWP_NOZORDER);
|
||||||
|
},
|
||||||
|
hwnd_));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RootWindowWin::DefaultToContentBounds() const {
|
||||||
|
if (!WithWindowlessRendering()) {
|
||||||
|
// The root HWND will be queried by default.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (osr_settings_.real_screen_bounds) {
|
||||||
|
// Root HWND bounds are provided via GetRootWindowRect.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// The root HWND will not be queried by default.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootWindowWin::GetWindowBoundsAndContinue(
|
||||||
|
const CefRect& dip_bounds,
|
||||||
|
bool content_bounds,
|
||||||
|
base::OnceCallback<void(const CefRect&)> next) {
|
||||||
|
REQUIRE_MAIN_THREAD();
|
||||||
|
DCHECK(hwnd_);
|
||||||
|
|
||||||
|
GetPixelBoundsAndContinue(hwnd_, dip_bounds, content_bounds, with_controls_,
|
||||||
|
GetDeviceScaleFactor(), std::move(next));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowWin::Close(bool force) {
|
void RootWindowWin::Close(bool force) {
|
||||||
@ -285,15 +441,14 @@ void RootWindowWin::SetDeviceScaleFactor(float device_scale_factor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float RootWindowWin::GetDeviceScaleFactor() const {
|
std::optional<float> RootWindowWin::GetDeviceScaleFactor() const {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
if (browser_window_ && with_osr_) {
|
if (browser_window_ && with_osr_) {
|
||||||
return browser_window_->GetDeviceScaleFactor();
|
return browser_window_->GetDeviceScaleFactor();
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTREACHED();
|
return std::nullopt;
|
||||||
return 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefBrowser> RootWindowWin::GetBrowser() const {
|
CefRefPtr<CefBrowser> RootWindowWin::GetBrowser() const {
|
||||||
@ -312,15 +467,15 @@ ClientWindowHandle RootWindowWin::GetWindowHandle() const {
|
|||||||
|
|
||||||
bool RootWindowWin::WithWindowlessRendering() const {
|
bool RootWindowWin::WithWindowlessRendering() const {
|
||||||
REQUIRE_MAIN_THREAD();
|
REQUIRE_MAIN_THREAD();
|
||||||
|
DCHECK(initialized_);
|
||||||
return with_osr_;
|
return with_osr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowWin::CreateBrowserWindow(const std::string& startup_url) {
|
void RootWindowWin::CreateBrowserWindow(const std::string& startup_url) {
|
||||||
if (with_osr_) {
|
if (with_osr_) {
|
||||||
OsrRendererSettings settings = {};
|
MainContext::Get()->PopulateOsrSettings(&osr_settings_);
|
||||||
MainContext::Get()->PopulateOsrSettings(&settings);
|
|
||||||
browser_window_ = std::make_unique<BrowserWindowOsrWin>(
|
browser_window_ = std::make_unique<BrowserWindowOsrWin>(
|
||||||
this, with_controls_, startup_url, settings);
|
this, with_controls_, startup_url, osr_settings_);
|
||||||
} else {
|
} else {
|
||||||
browser_window_ = std::make_unique<BrowserWindowStdWin>(
|
browser_window_ = std::make_unique<BrowserWindowStdWin>(
|
||||||
this, with_controls_, startup_url);
|
this, with_controls_, startup_url);
|
||||||
@ -771,15 +926,27 @@ void RootWindowWin::OnSize(bool minimized) {
|
|||||||
// Size the browser window to the whole client area.
|
// Size the browser window to the whole client area.
|
||||||
browser_window_->SetBounds(0, 0, rect.right, rect.bottom);
|
browser_window_->SetBounds(0, 0, rect.right, rect.bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaybeNotifyScreenInfoChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowWin::OnMove() {
|
void RootWindowWin::OnMove() {
|
||||||
// Notify the browser of move events so that popup windows are displayed
|
// Notify the browser of move events so that popup windows are displayed
|
||||||
// in the correct location and dismissed when the window moves.
|
// in the correct location and dismissed when the window moves.
|
||||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
if (auto browser = GetBrowser()) {
|
||||||
if (browser) {
|
|
||||||
browser->GetHost()->NotifyMoveOrResizeStarted();
|
browser->GetHost()->NotifyMoveOrResizeStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaybeNotifyScreenInfoChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootWindowWin::MaybeNotifyScreenInfoChanged() {
|
||||||
|
if (!DefaultToContentBounds()) {
|
||||||
|
// Send the new root window bounds to the renderer.
|
||||||
|
if (auto browser = GetBrowser()) {
|
||||||
|
browser->GetHost()->NotifyScreenInfoChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowWin::OnDpiChanged(WPARAM wParam, LPARAM lParam) {
|
void RootWindowWin::OnDpiChanged(WPARAM wParam, LPARAM lParam) {
|
||||||
@ -788,6 +955,10 @@ void RootWindowWin::OnDpiChanged(WPARAM wParam, LPARAM lParam) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!hwnd_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (browser_window_ && with_osr_) {
|
if (browser_window_ && with_osr_) {
|
||||||
// Scale factor for the new display.
|
// Scale factor for the new display.
|
||||||
const float display_scale_factor =
|
const float display_scale_factor =
|
||||||
@ -797,8 +968,8 @@ void RootWindowWin::OnDpiChanged(WPARAM wParam, LPARAM lParam) {
|
|||||||
|
|
||||||
// Suggested size and position of the current window scaled for the new DPI.
|
// Suggested size and position of the current window scaled for the new DPI.
|
||||||
const RECT* rect = reinterpret_cast<RECT*>(lParam);
|
const RECT* rect = reinterpret_cast<RECT*>(lParam);
|
||||||
SetBounds(rect->left, rect->top, rect->right - rect->left,
|
SetWindowPos(hwnd_, nullptr, rect->left, rect->top, rect->right - rect->left,
|
||||||
rect->bottom - rect->top);
|
rect->bottom - rect->top, SWP_NOZORDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RootWindowWin::OnEraseBkgnd() {
|
bool RootWindowWin::OnEraseBkgnd() {
|
||||||
@ -999,42 +1170,37 @@ void RootWindowWin::OnCreate(LPCREATESTRUCT lpCreateStruct) {
|
|||||||
::SetMenu(hwnd_, nullptr);
|
::SetMenu(hwnd_, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float device_scale_factor = GetWindowScaleFactor(hwnd_);
|
|
||||||
|
|
||||||
if (with_osr_) {
|
if (with_osr_) {
|
||||||
browser_window_->SetDeviceScaleFactor(device_scale_factor);
|
std::optional<float> parent_scale_factor;
|
||||||
|
if (is_popup_) {
|
||||||
|
if (auto parent_window =
|
||||||
|
MainContext::Get()->GetRootWindowManager()->GetWindowForBrowser(
|
||||||
|
opener_browser_id())) {
|
||||||
|
parent_scale_factor = parent_window->GetDeviceScaleFactor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
browser_window_->SetDeviceScaleFactor(
|
||||||
|
parent_scale_factor.value_or(initial_scale_factor_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CefRect bounds(rect.left, rect.top, rect.right - rect.left,
|
||||||
|
rect.bottom - rect.top);
|
||||||
if (!is_popup_) {
|
if (!is_popup_) {
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
CefRect cef_rect(rect.left, rect.top, rect.right - rect.left,
|
browser_window_->CreateBrowser(hwnd_, bounds, browser_settings_, nullptr,
|
||||||
rect.bottom - rect.top);
|
|
||||||
browser_window_->CreateBrowser(hwnd_, cef_rect, browser_settings_, nullptr,
|
|
||||||
delegate_->GetRequestContext());
|
delegate_->GetRequestContext());
|
||||||
} else {
|
} else {
|
||||||
// With popups we already have a browser window. Parent the browser window
|
// With popups we already have a browser window. Parent the browser window
|
||||||
// to the root window and show it in the correct location.
|
// to the root window and show it in the correct location.
|
||||||
browser_window_->ShowPopup(hwnd_, rect.left, rect.top,
|
browser_window_->ShowPopup(hwnd_, bounds.x, bounds.y, bounds.width,
|
||||||
rect.right - rect.left, rect.bottom - rect.top);
|
bounds.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
window_created_ = true;
|
window_created_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RootWindowWin::OnClose() {
|
bool RootWindowWin::OnClose() {
|
||||||
if (browser_window_ && !browser_window_->IsClosing()) {
|
|
||||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
|
||||||
if (browser) {
|
|
||||||
// Notify the browser window that we would like to close it. This
|
|
||||||
// will result in a call to ClientHandler::DoClose() if the
|
|
||||||
// JavaScript 'onbeforeunload' event handler allows it.
|
|
||||||
browser->GetHost()->CloseBrowser(false);
|
|
||||||
|
|
||||||
// Cancel the close.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve current window placement information.
|
// Retrieve current window placement information.
|
||||||
WINDOWPLACEMENT placement;
|
WINDOWPLACEMENT placement;
|
||||||
::GetWindowPlacement(hwnd_, &placement);
|
::GetWindowPlacement(hwnd_, &placement);
|
||||||
@ -1047,6 +1213,20 @@ bool RootWindowWin::OnClose() {
|
|||||||
base::BindOnce(&RootWindowWin::SaveWindowRestoreOnUIThread, placement));
|
base::BindOnce(&RootWindowWin::SaveWindowRestoreOnUIThread, placement));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (browser_window_ && !browser_window_->IsClosing()) {
|
||||||
|
CefRefPtr<CefBrowser> browser = GetBrowser();
|
||||||
|
if (browser) {
|
||||||
|
// Notify the browser window that we would like to close it. With Alloy
|
||||||
|
// style this will result in a call to ClientHandler::DoClose() if the
|
||||||
|
// JavaScript 'onbeforeunload' event handler allows it. With Chrome style
|
||||||
|
// this will close the window indirectly via browser destruction.
|
||||||
|
browser->GetHost()->CloseBrowser(false);
|
||||||
|
|
||||||
|
// Cancel the close.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Allow the close.
|
// Allow the close.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1124,29 +1304,18 @@ void RootWindowWin::OnAutoResize(const CefSize& new_size) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int new_width = new_size.width;
|
CefRect dip_bounds = {0, 0, new_size.width, new_size.height};
|
||||||
|
|
||||||
// Make the window wide enough to drag by the top menu bar.
|
GetWindowBoundsAndContinue(
|
||||||
if (new_width < 200) {
|
dip_bounds, /*content_bounds=*/true,
|
||||||
new_width = 200;
|
base::BindOnce(
|
||||||
}
|
[](HWND hwnd, const CefRect& pixel_bounds) {
|
||||||
|
// Size the window and show if it's not currently visible.
|
||||||
const float device_scale_factor = GetWindowScaleFactor(hwnd_);
|
SetWindowPos(
|
||||||
RECT rect = {0, 0, LogicalToDevice(new_width, device_scale_factor),
|
hwnd, nullptr, 0, 0, pixel_bounds.width, pixel_bounds.height,
|
||||||
LogicalToDevice(new_size.height, device_scale_factor)};
|
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
|
||||||
DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
|
},
|
||||||
DWORD ex_style = GetWindowLong(hwnd_, GWL_EXSTYLE);
|
hwnd_));
|
||||||
bool has_menu = !(style & WS_CHILD) && (GetMenu(hwnd_) != nullptr);
|
|
||||||
|
|
||||||
// The size value is for the client area. Calculate the whole window size
|
|
||||||
// based on the current style.
|
|
||||||
AdjustWindowRectEx(&rect, style, has_menu, ex_style);
|
|
||||||
|
|
||||||
// Size the window. The left/top values may be negative.
|
|
||||||
// Also show the window if it's not currently visible.
|
|
||||||
SetWindowPos(hwnd_, nullptr, 0, 0, rect.right - rect.left,
|
|
||||||
rect.bottom - rect.top,
|
|
||||||
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowWin::OnSetLoadingState(bool isLoading,
|
void RootWindowWin::OnSetLoadingState(bool isLoading,
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "tests/cefclient/browser/browser_window.h"
|
#include "tests/cefclient/browser/browser_window.h"
|
||||||
|
#include "tests/cefclient/browser/osr_renderer_settings.h"
|
||||||
#include "tests/cefclient/browser/root_window.h"
|
#include "tests/cefclient/browser/root_window.h"
|
||||||
|
|
||||||
namespace client {
|
namespace client {
|
||||||
@ -40,10 +41,15 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
CefBrowserSettings& settings) override;
|
CefBrowserSettings& settings) override;
|
||||||
void Show(ShowMode mode) override;
|
void Show(ShowMode mode) override;
|
||||||
void Hide() override;
|
void Hide() override;
|
||||||
void SetBounds(int x, int y, size_t width, size_t height) override;
|
void SetBounds(int x,
|
||||||
|
int y,
|
||||||
|
size_t width,
|
||||||
|
size_t height,
|
||||||
|
bool content_bounds) override;
|
||||||
|
bool DefaultToContentBounds() const override;
|
||||||
void Close(bool force) override;
|
void Close(bool force) override;
|
||||||
void SetDeviceScaleFactor(float device_scale_factor) override;
|
void SetDeviceScaleFactor(float device_scale_factor) override;
|
||||||
float GetDeviceScaleFactor() const override;
|
std::optional<float> GetDeviceScaleFactor() const override;
|
||||||
CefRefPtr<CefBrowser> GetBrowser() const override;
|
CefRefPtr<CefBrowser> GetBrowser() const override;
|
||||||
ClientWindowHandle GetWindowHandle() const override;
|
ClientWindowHandle GetWindowHandle() const override;
|
||||||
bool WithWindowlessRendering() const override;
|
bool WithWindowlessRendering() const override;
|
||||||
@ -58,6 +64,11 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
void CreateRootWindow(const CefBrowserSettings& settings,
|
void CreateRootWindow(const CefBrowserSettings& settings,
|
||||||
bool initially_hidden);
|
bool initially_hidden);
|
||||||
|
|
||||||
|
void GetWindowBoundsAndContinue(
|
||||||
|
const CefRect& dip_bounds,
|
||||||
|
bool content_bounds,
|
||||||
|
base::OnceCallback<void(const CefRect& /*pixel_bounds*/)> next);
|
||||||
|
|
||||||
// Register the root window class.
|
// Register the root window class.
|
||||||
static void RegisterRootClass(HINSTANCE hInstance,
|
static void RegisterRootClass(HINSTANCE hInstance,
|
||||||
const std::wstring& window_class,
|
const std::wstring& window_class,
|
||||||
@ -106,6 +117,10 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
void OnSetTitle(const std::string& title) override;
|
void OnSetTitle(const std::string& title) override;
|
||||||
void OnSetFullscreen(bool fullscreen) override;
|
void OnSetFullscreen(bool fullscreen) override;
|
||||||
void OnAutoResize(const CefSize& new_size) override;
|
void OnAutoResize(const CefSize& new_size) override;
|
||||||
|
void OnContentsBounds(const CefRect& new_bounds) override {
|
||||||
|
RootWindow::SetBounds(new_bounds,
|
||||||
|
/*content_bounds=*/DefaultToContentBounds());
|
||||||
|
}
|
||||||
void OnSetLoadingState(bool isLoading,
|
void OnSetLoadingState(bool isLoading,
|
||||||
bool canGoBack,
|
bool canGoBack,
|
||||||
bool canGoForward) override;
|
bool canGoForward) override;
|
||||||
@ -114,6 +129,8 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
|
|
||||||
void NotifyDestroyedIfDone();
|
void NotifyDestroyedIfDone();
|
||||||
|
|
||||||
|
void MaybeNotifyScreenInfoChanged();
|
||||||
|
|
||||||
static void SaveWindowRestoreOnUIThread(const WINDOWPLACEMENT& placement);
|
static void SaveWindowRestoreOnUIThread(const WINDOWPLACEMENT& placement);
|
||||||
|
|
||||||
// After initialization all members are only accessed on the main thread.
|
// After initialization all members are only accessed on the main thread.
|
||||||
@ -121,9 +138,11 @@ class RootWindowWin : public RootWindow, public BrowserWindow::Delegate {
|
|||||||
bool with_controls_ = false;
|
bool with_controls_ = false;
|
||||||
bool always_on_top_ = false;
|
bool always_on_top_ = false;
|
||||||
bool with_osr_ = false;
|
bool with_osr_ = false;
|
||||||
|
OsrRendererSettings osr_settings_;
|
||||||
bool is_popup_ = false;
|
bool is_popup_ = false;
|
||||||
CefRect initial_bounds_;
|
CefRect initial_bounds_;
|
||||||
cef_show_state_t initial_show_state_ = CEF_SHOW_STATE_NORMAL;
|
cef_show_state_t initial_show_state_ = CEF_SHOW_STATE_NORMAL;
|
||||||
|
float initial_scale_factor_ = 1.0;
|
||||||
std::unique_ptr<BrowserWindow> browser_window_;
|
std::unique_ptr<BrowserWindow> browser_window_;
|
||||||
CefBrowserSettings browser_settings_;
|
CefBrowserSettings browser_settings_;
|
||||||
|
|
||||||
|
@ -146,7 +146,9 @@ void RunNewWindowTest(CefRefPtr<CefBrowser> browser) {
|
|||||||
|
|
||||||
void RunPopupWindowTest(CefRefPtr<CefBrowser> browser) {
|
void RunPopupWindowTest(CefRefPtr<CefBrowser> browser) {
|
||||||
browser->GetMainFrame()->ExecuteJavaScript(
|
browser->GetMainFrame()->ExecuteJavaScript(
|
||||||
"window.open('https://www.google.com');", "about:blank", 0);
|
"window.open('https://www.google.com', 'google', "
|
||||||
|
"'left=100,top=100,width=600,height=400');",
|
||||||
|
"about:blank", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunDialogWindowTest(CefRefPtr<CefBrowser> browser) {
|
void RunDialogWindowTest(CefRefPtr<CefBrowser> browser) {
|
||||||
@ -269,8 +271,8 @@ void PromptDSF(CefRefPtr<CefBrowser> browser) {
|
|||||||
|
|
||||||
// Format the default value string.
|
// Format the default value string.
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << RootWindow::GetForBrowser(browser->GetIdentifier())
|
ss << *RootWindow::GetForBrowser(browser->GetIdentifier())
|
||||||
->GetDeviceScaleFactor();
|
->GetDeviceScaleFactor();
|
||||||
|
|
||||||
Prompt(browser, kPromptDSF, "Enter Device Scale Factor", ss.str());
|
Prompt(browser, kPromptDSF, "Enter Device Scale Factor", ss.str());
|
||||||
}
|
}
|
||||||
|
@ -30,4 +30,54 @@ ScopedGdkThreadsEnter::~ScopedGdkThreadsEnter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CefRect GetWindowBounds(GtkWindow* window, bool include_frame) {
|
||||||
|
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
|
||||||
|
|
||||||
|
gint x = 0;
|
||||||
|
gint y = 0;
|
||||||
|
gdk_window_get_origin(gdk_window, &x, &y);
|
||||||
|
|
||||||
|
gint width = 0;
|
||||||
|
gint height = 0;
|
||||||
|
gdk_window_get_geometry(gdk_window, nullptr, nullptr, &width, &height);
|
||||||
|
|
||||||
|
if (include_frame) {
|
||||||
|
GdkRectangle frame_rect = {};
|
||||||
|
gdk_window_get_frame_extents(gdk_window, &frame_rect);
|
||||||
|
|
||||||
|
// This calculation assumes that all added frame height is at the top of the
|
||||||
|
// window, which may be incorrect for some window managers.
|
||||||
|
y -= frame_rect.height - height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {x, y, width, height};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsWindowMaximized(GtkWindow* window) {
|
||||||
|
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
|
||||||
|
gint state = gdk_window_get_state(gdk_window);
|
||||||
|
return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinimizeWindow(GtkWindow* window) {
|
||||||
|
// Unmaximize the window before minimizing so restore behaves correctly.
|
||||||
|
if (IsWindowMaximized(window)) {
|
||||||
|
gtk_window_unmaximize(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_window_iconify(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaximizeWindow(GtkWindow* window) {
|
||||||
|
gtk_window_maximize(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreWindow(GtkWindow* window) {
|
||||||
|
if (IsWindowMaximized(window)) {
|
||||||
|
gtk_window_unmaximize(window);
|
||||||
|
} else {
|
||||||
|
gtk_window_present(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
@ -6,8 +6,11 @@
|
|||||||
#define CEF_TESTS_CEFCLIENT_BROWSER_UTIL_GTK_H_
|
#define CEF_TESTS_CEFCLIENT_BROWSER_UTIL_GTK_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
#include "include/base/cef_macros.h"
|
#include "include/base/cef_macros.h"
|
||||||
#include "include/base/cef_platform_thread.h"
|
#include "include/base/cef_platform_thread.h"
|
||||||
|
#include "include/internal/cef_types_wrappers.h"
|
||||||
|
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
@ -36,6 +39,16 @@ class ScopedGdkThreadsEnter {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(ScopedGdkThreadsEnter);
|
DISALLOW_COPY_AND_ASSIGN(ScopedGdkThreadsEnter);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Returns the window bounds in root window (pixel) coordinates.
|
||||||
|
CefRect GetWindowBounds(GtkWindow* window, bool include_frame);
|
||||||
|
|
||||||
|
bool IsWindowMaximized(GtkWindow* window);
|
||||||
|
void MinimizeWindow(GtkWindow* window);
|
||||||
|
void MaximizeWindow(GtkWindow* window);
|
||||||
|
|
||||||
|
// Make sure the window isn't minimized or maximized.
|
||||||
|
void RestoreWindow(GtkWindow* window);
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
||||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_UTIL_GTK_H_
|
#endif // CEF_TESTS_CEFCLIENT_BROWSER_UTIL_GTK_H_
|
||||||
|
23
tests/cefclient/browser/util_mac.h
Normal file
23
tests/cefclient/browser/util_mac.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (c) 2025 The Chromium Embedded Framework Authors. All rights
|
||||||
|
// reserved. Use of this source code is governed by a BSD-style license that
|
||||||
|
// can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_UTIL_MAC_H_
|
||||||
|
#define CEF_TESTS_CEFCLIENT_BROWSER_UTIL_MAC_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
#include "include/internal/cef_types_wrappers.h"
|
||||||
|
|
||||||
|
namespace client {
|
||||||
|
|
||||||
|
// Returns the current DIP screen bounds for a visible window in the restored
|
||||||
|
// position, or nullopt if the window is currently minimized or fullscreen.
|
||||||
|
std::optional<CefRect> GetWindowBoundsInScreen(NSWindow* window);
|
||||||
|
|
||||||
|
} // namespace client
|
||||||
|
|
||||||
|
#endif // CEF_TESTS_CEFCLIENT_BROWSER_UTIL_MAC_H_
|
40
tests/cefclient/browser/util_mac.mm
Normal file
40
tests/cefclient/browser/util_mac.mm
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) 2025 The Chromium Embedded Framework Authors. All rights
|
||||||
|
// reserved. Use of this source code is governed by a BSD-style license that
|
||||||
|
// can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "tests/cefclient/browser/util_mac.h"
|
||||||
|
|
||||||
|
namespace client {
|
||||||
|
|
||||||
|
std::optional<CefRect> GetWindowBoundsInScreen(NSWindow* window) {
|
||||||
|
if ([window isMiniaturized] or [window isZoomed]) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto screen = [window screen];
|
||||||
|
if (screen == nil) {
|
||||||
|
screen = [NSScreen mainScreen];
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto bounds = [window frame];
|
||||||
|
const auto screen_bounds = [screen frame];
|
||||||
|
|
||||||
|
if (NSEqualRects(bounds, screen_bounds)) {
|
||||||
|
// Don't include windows that are transitioning to fullscreen.
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRect dip_bounds{static_cast<int>(bounds.origin.x),
|
||||||
|
static_cast<int>(bounds.origin.y),
|
||||||
|
static_cast<int>(bounds.size.width),
|
||||||
|
static_cast<int>(bounds.size.height)};
|
||||||
|
|
||||||
|
// Convert from macOS coordinates (bottom-left origin) to DIP coordinates
|
||||||
|
// (top-left origin).
|
||||||
|
dip_bounds.y = static_cast<int>(screen_bounds.size.height) -
|
||||||
|
dip_bounds.height - dip_bounds.y;
|
||||||
|
|
||||||
|
return dip_bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace client
|
@ -17,6 +17,7 @@
|
|||||||
#include "tests/cefclient/browser/main_context.h"
|
#include "tests/cefclient/browser/main_context.h"
|
||||||
#include "tests/cefclient/browser/resource.h"
|
#include "tests/cefclient/browser/resource.h"
|
||||||
#include "tests/cefclient/browser/views_style.h"
|
#include "tests/cefclient/browser/views_style.h"
|
||||||
|
#include "tests/shared/browser/geometry_util.h"
|
||||||
#include "tests/shared/common/client_switches.h"
|
#include "tests/shared/common/client_switches.h"
|
||||||
|
|
||||||
#if !defined(OS_WIN)
|
#if !defined(OS_WIN)
|
||||||
@ -229,7 +230,9 @@ void ViewsWindow::Maximize() {
|
|||||||
void ViewsWindow::SetBounds(const CefRect& bounds) {
|
void ViewsWindow::SetBounds(const CefRect& bounds) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
if (window_) {
|
if (window_) {
|
||||||
window_->SetBounds(bounds);
|
auto window_bounds = bounds;
|
||||||
|
ConstrainWindowBounds(window_->GetDisplay()->GetWorkArea(), window_bounds);
|
||||||
|
window_->SetBounds(window_bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "include/views/cef_browser_view.h"
|
#include "include/views/cef_browser_view.h"
|
||||||
#include "include/wrapper/cef_stream_resource_handler.h"
|
#include "include/wrapper/cef_stream_resource_handler.h"
|
||||||
#include "tests/cefclient/browser/main_context.h"
|
#include "tests/cefclient/browser/main_context.h"
|
||||||
|
#include "tests/cefclient/browser/root_window.h"
|
||||||
#include "tests/cefclient/browser/test_runner.h"
|
#include "tests/cefclient/browser/test_runner.h"
|
||||||
#include "tests/cefclient/browser/window_test_runner.h"
|
#include "tests/cefclient/browser/window_test_runner.h"
|
||||||
#include "tests/cefclient/browser/window_test_runner_views.h"
|
#include "tests/cefclient/browser/window_test_runner_views.h"
|
||||||
@ -40,7 +41,8 @@ const char kMessageTitlebarHeightName[] = "WindowTest.TitlebarHeight";
|
|||||||
// Create the appropriate platform test runner object.
|
// Create the appropriate platform test runner object.
|
||||||
std::unique_ptr<WindowTestRunner> CreateWindowTestRunner(
|
std::unique_ptr<WindowTestRunner> CreateWindowTestRunner(
|
||||||
CefRefPtr<CefBrowser> browser) {
|
CefRefPtr<CefBrowser> browser) {
|
||||||
if (CefBrowserView::GetForBrowser(browser)) {
|
auto root_window = RootWindow::GetForBrowser(browser->GetIdentifier());
|
||||||
|
if (root_window->IsViewsHosted()) {
|
||||||
// Browser is Views-hosted.
|
// Browser is Views-hosted.
|
||||||
return std::make_unique<WindowTestRunnerViews>();
|
return std::make_unique<WindowTestRunnerViews>();
|
||||||
}
|
}
|
||||||
@ -99,6 +101,20 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunOnMainThread(browser, request, callback);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void RunOnMainThread(CefRefPtr<CefBrowser> browser,
|
||||||
|
const CefString& request,
|
||||||
|
CefRefPtr<Callback> callback) {
|
||||||
|
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||||
|
MAIN_POST_CLOSURE(base::BindOnce(&Handler::RunOnMainThread, browser,
|
||||||
|
request, callback));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto runner = CreateWindowTestRunner(browser);
|
auto runner = CreateWindowTestRunner(browser);
|
||||||
|
|
||||||
const std::string& message_name = request;
|
const std::string& message_name = request;
|
||||||
@ -123,7 +139,6 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
callback->Success("");
|
callback->Success("");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,35 +4,21 @@
|
|||||||
|
|
||||||
#include "tests/cefclient/browser/window_test_runner.h"
|
#include "tests/cefclient/browser/window_test_runner.h"
|
||||||
|
|
||||||
|
#include "tests/cefclient/browser/root_window.h"
|
||||||
|
|
||||||
namespace client::window_test {
|
namespace client::window_test {
|
||||||
|
|
||||||
// static
|
void WindowTestRunner::SetPos(CefRefPtr<CefBrowser> browser,
|
||||||
void WindowTestRunner::ModifyBounds(const CefRect& display, CefRect& window) {
|
int x,
|
||||||
window.x += display.x;
|
int y,
|
||||||
window.y += display.y;
|
int width,
|
||||||
|
int height) {
|
||||||
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
if (window.x < display.x) {
|
auto root_window = RootWindow::GetForBrowser(browser->GetIdentifier());
|
||||||
window.x = display.x;
|
root_window->SetBounds(
|
||||||
}
|
x, y, width, height,
|
||||||
if (window.y < display.y) {
|
/*content_bounds=*/root_window->DefaultToContentBounds());
|
||||||
window.y = display.y;
|
|
||||||
}
|
|
||||||
if (window.width < 100) {
|
|
||||||
window.width = 100;
|
|
||||||
} else if (window.width >= display.width) {
|
|
||||||
window.width = display.width;
|
|
||||||
}
|
|
||||||
if (window.height < 100) {
|
|
||||||
window.height = 100;
|
|
||||||
} else if (window.height >= display.height) {
|
|
||||||
window.height = display.height;
|
|
||||||
}
|
|
||||||
if (window.x + window.width >= display.x + display.width) {
|
|
||||||
window.x = display.x + display.width - window.width;
|
|
||||||
}
|
|
||||||
if (window.y + window.height >= display.y + display.height) {
|
|
||||||
window.y = display.y + display.height - window.height;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowTestRunner::Fullscreen(CefRefPtr<CefBrowser> browser) {
|
void WindowTestRunner::Fullscreen(CefRefPtr<CefBrowser> browser) {
|
||||||
|
@ -13,25 +13,21 @@
|
|||||||
namespace client::window_test {
|
namespace client::window_test {
|
||||||
|
|
||||||
// Implement this interface for different platforms. Methods will be called on
|
// Implement this interface for different platforms. Methods will be called on
|
||||||
// the browser process UI thread unless otherwise indicated.
|
// the browser process main thread unless otherwise indicated.
|
||||||
class WindowTestRunner {
|
class WindowTestRunner {
|
||||||
public:
|
public:
|
||||||
virtual ~WindowTestRunner() = default;
|
virtual ~WindowTestRunner() = default;
|
||||||
|
|
||||||
virtual void SetPos(CefRefPtr<CefBrowser> browser,
|
void SetPos(CefRefPtr<CefBrowser> browser,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int width,
|
int width,
|
||||||
int height) = 0;
|
int height);
|
||||||
virtual void Minimize(CefRefPtr<CefBrowser> browser) = 0;
|
virtual void Minimize(CefRefPtr<CefBrowser> browser) = 0;
|
||||||
virtual void Maximize(CefRefPtr<CefBrowser> browser) = 0;
|
virtual void Maximize(CefRefPtr<CefBrowser> browser) = 0;
|
||||||
virtual void Restore(CefRefPtr<CefBrowser> browser) = 0;
|
virtual void Restore(CefRefPtr<CefBrowser> browser) = 0;
|
||||||
virtual void Fullscreen(CefRefPtr<CefBrowser> browser);
|
virtual void Fullscreen(CefRefPtr<CefBrowser> browser);
|
||||||
|
|
||||||
// Fit |window| inside |display|. Coordinates are relative to the upper-left
|
|
||||||
// corner of the display.
|
|
||||||
static void ModifyBounds(const CefRect& display, CefRect& window);
|
|
||||||
|
|
||||||
virtual void SetTitleBarHeight(CefRefPtr<CefBrowser> browser,
|
virtual void SetTitleBarHeight(CefRefPtr<CefBrowser> browser,
|
||||||
const std::optional<float>& height);
|
const std::optional<float>& height);
|
||||||
};
|
};
|
||||||
|
@ -29,113 +29,32 @@ GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsMaximized(GtkWindow* window) {
|
|
||||||
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
|
|
||||||
gint state = gdk_window_get_state(gdk_window);
|
|
||||||
return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPosImpl(CefRefPtr<CefBrowser> browser,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height) {
|
|
||||||
REQUIRE_MAIN_THREAD();
|
|
||||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
|
||||||
|
|
||||||
GtkWindow* window = GetWindow(browser);
|
|
||||||
if (!window) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
|
|
||||||
|
|
||||||
// Make sure the window isn't minimized or maximized.
|
|
||||||
if (IsMaximized(window)) {
|
|
||||||
gtk_window_unmaximize(window);
|
|
||||||
} else {
|
|
||||||
gtk_window_present(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve information about the display that contains the window.
|
|
||||||
GdkScreen* screen = gdk_screen_get_default();
|
|
||||||
gint monitor = gdk_screen_get_monitor_at_window(screen, gdk_window);
|
|
||||||
GdkRectangle rect;
|
|
||||||
gdk_screen_get_monitor_geometry(screen, monitor, &rect);
|
|
||||||
|
|
||||||
// Make sure the window is inside the display.
|
|
||||||
CefRect display_rect(rect.x, rect.y, rect.width, rect.height);
|
|
||||||
CefRect window_rect(x, y, width, height);
|
|
||||||
WindowTestRunner::ModifyBounds(display_rect, window_rect);
|
|
||||||
|
|
||||||
gdk_window_move_resize(gdk_window, window_rect.x, window_rect.y,
|
|
||||||
window_rect.width, window_rect.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MinimizeImpl(CefRefPtr<CefBrowser> browser) {
|
|
||||||
REQUIRE_MAIN_THREAD();
|
|
||||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
|
||||||
|
|
||||||
GtkWindow* window = GetWindow(browser);
|
|
||||||
if (!window) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmaximize the window before minimizing so restore behaves correctly.
|
|
||||||
if (IsMaximized(window)) {
|
|
||||||
gtk_window_unmaximize(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_window_iconify(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaximizeImpl(CefRefPtr<CefBrowser> browser) {
|
|
||||||
REQUIRE_MAIN_THREAD();
|
|
||||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
|
||||||
|
|
||||||
GtkWindow* window = GetWindow(browser);
|
|
||||||
if (!window) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gtk_window_maximize(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RestoreImpl(CefRefPtr<CefBrowser> browser) {
|
|
||||||
REQUIRE_MAIN_THREAD();
|
|
||||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
|
||||||
|
|
||||||
GtkWindow* window = GetWindow(browser);
|
|
||||||
if (!window) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (IsMaximized(window)) {
|
|
||||||
gtk_window_unmaximize(window);
|
|
||||||
} else {
|
|
||||||
gtk_window_present(window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
WindowTestRunnerGtk::WindowTestRunnerGtk() {}
|
WindowTestRunnerGtk::WindowTestRunnerGtk() = default;
|
||||||
|
|
||||||
void WindowTestRunnerGtk::SetPos(CefRefPtr<CefBrowser> browser,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height) {
|
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(SetPosImpl, browser, x, y, width, height));
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowTestRunnerGtk::Minimize(CefRefPtr<CefBrowser> browser) {
|
void WindowTestRunnerGtk::Minimize(CefRefPtr<CefBrowser> browser) {
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(MinimizeImpl, browser));
|
REQUIRE_MAIN_THREAD();
|
||||||
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
|
if (auto* window = GetWindow(browser)) {
|
||||||
|
MinimizeWindow(window);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowTestRunnerGtk::Maximize(CefRefPtr<CefBrowser> browser) {
|
void WindowTestRunnerGtk::Maximize(CefRefPtr<CefBrowser> browser) {
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(MaximizeImpl, browser));
|
REQUIRE_MAIN_THREAD();
|
||||||
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
|
if (auto* window = GetWindow(browser)) {
|
||||||
|
MaximizeWindow(window);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowTestRunnerGtk::Restore(CefRefPtr<CefBrowser> browser) {
|
void WindowTestRunnerGtk::Restore(CefRefPtr<CefBrowser> browser) {
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(RestoreImpl, browser));
|
REQUIRE_MAIN_THREAD();
|
||||||
|
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||||
|
if (auto* window = GetWindow(browser)) {
|
||||||
|
RestoreWindow(window);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace window_test
|
} // namespace window_test
|
||||||
|
@ -16,11 +16,6 @@ class WindowTestRunnerGtk : public WindowTestRunner {
|
|||||||
public:
|
public:
|
||||||
WindowTestRunnerGtk();
|
WindowTestRunnerGtk();
|
||||||
|
|
||||||
void SetPos(CefRefPtr<CefBrowser> browser,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height) override;
|
|
||||||
void Minimize(CefRefPtr<CefBrowser> browser) override;
|
void Minimize(CefRefPtr<CefBrowser> browser) override;
|
||||||
void Maximize(CefRefPtr<CefBrowser> browser) override;
|
void Maximize(CefRefPtr<CefBrowser> browser) override;
|
||||||
void Restore(CefRefPtr<CefBrowser> browser) override;
|
void Restore(CefRefPtr<CefBrowser> browser) override;
|
||||||
|
@ -16,11 +16,6 @@ class WindowTestRunnerMac : public WindowTestRunner {
|
|||||||
public:
|
public:
|
||||||
WindowTestRunnerMac();
|
WindowTestRunnerMac();
|
||||||
|
|
||||||
void SetPos(CefRefPtr<CefBrowser> browser,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height) override;
|
|
||||||
void Minimize(CefRefPtr<CefBrowser> browser) override;
|
void Minimize(CefRefPtr<CefBrowser> browser) override;
|
||||||
void Maximize(CefRefPtr<CefBrowser> browser) override;
|
void Maximize(CefRefPtr<CefBrowser> browser) override;
|
||||||
void Restore(CefRefPtr<CefBrowser> browser) override;
|
void Restore(CefRefPtr<CefBrowser> browser) override;
|
||||||
|
@ -22,48 +22,7 @@ NSWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
WindowTestRunnerMac::WindowTestRunnerMac() {}
|
WindowTestRunnerMac::WindowTestRunnerMac() = default;
|
||||||
|
|
||||||
void WindowTestRunnerMac::SetPos(CefRefPtr<CefBrowser> browser,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height) {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
REQUIRE_MAIN_THREAD();
|
|
||||||
|
|
||||||
NSWindow* window = GetWindow(browser);
|
|
||||||
|
|
||||||
// Make sure the window isn't minimized or maximized.
|
|
||||||
if ([window isMiniaturized]) {
|
|
||||||
[window deminiaturize:nil];
|
|
||||||
} else if ([window isZoomed]) {
|
|
||||||
[window performZoom:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve information for the display that contains the window.
|
|
||||||
NSScreen* screen = [window screen];
|
|
||||||
if (screen == nil) {
|
|
||||||
screen = [NSScreen mainScreen];
|
|
||||||
}
|
|
||||||
NSRect frame = [screen frame];
|
|
||||||
NSRect visibleFrame = [screen visibleFrame];
|
|
||||||
|
|
||||||
// Make sure the window is inside the display.
|
|
||||||
CefRect display_rect(
|
|
||||||
visibleFrame.origin.x,
|
|
||||||
frame.size.height - visibleFrame.size.height - visibleFrame.origin.y,
|
|
||||||
visibleFrame.size.width, visibleFrame.size.height);
|
|
||||||
CefRect window_rect(x, y, width, height);
|
|
||||||
ModifyBounds(display_rect, window_rect);
|
|
||||||
|
|
||||||
NSRect newRect;
|
|
||||||
newRect.origin.x = window_rect.x;
|
|
||||||
newRect.origin.y = frame.size.height - window_rect.height - window_rect.y;
|
|
||||||
newRect.size.width = window_rect.width;
|
|
||||||
newRect.size.height = window_rect.height;
|
|
||||||
[window setFrame:newRect display:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowTestRunnerMac::Minimize(CefRefPtr<CefBrowser> browser) {
|
void WindowTestRunnerMac::Minimize(CefRefPtr<CefBrowser> browser) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "include/wrapper/cef_helpers.h"
|
#include "include/wrapper/cef_helpers.h"
|
||||||
#include "tests/cefclient/browser/root_window_views.h"
|
#include "tests/cefclient/browser/root_window_views.h"
|
||||||
#include "tests/cefclient/browser/views_window.h"
|
#include "tests/cefclient/browser/views_window.h"
|
||||||
|
#include "tests/shared/browser/geometry_util.h"
|
||||||
|
|
||||||
namespace client::window_test {
|
namespace client::window_test {
|
||||||
|
|
||||||
@ -28,46 +29,39 @@ CefRefPtr<CefWindow> GetWindow(const CefRefPtr<CefBrowser>& browser) {
|
|||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTitlebarHeight(const CefRefPtr<CefBrowser>& browser,
|
void MinimizeImpl(CefRefPtr<CefBrowser> browser) {
|
||||||
const std::optional<float>& height) {
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CefPostTask(TID_UI, base::BindOnce(&MinimizeImpl, browser));
|
||||||
auto root_window = RootWindow::GetForBrowser(browser->GetIdentifier());
|
return;
|
||||||
DCHECK(root_window.get());
|
}
|
||||||
|
|
||||||
auto root_window_views = static_cast<RootWindowViews*>(root_window.get());
|
|
||||||
root_window_views->SetTitlebarHeight(height);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
WindowTestRunnerViews::WindowTestRunnerViews() = default;
|
|
||||||
|
|
||||||
void WindowTestRunnerViews::SetPos(CefRefPtr<CefBrowser> browser,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height) {
|
|
||||||
CefRefPtr<CefWindow> window = GetWindow(browser);
|
|
||||||
|
|
||||||
CefRect window_bounds(x, y, width, height);
|
|
||||||
ModifyBounds(window->GetDisplay()->GetWorkArea(), window_bounds);
|
|
||||||
|
|
||||||
window->SetBounds(window_bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowTestRunnerViews::Minimize(CefRefPtr<CefBrowser> browser) {
|
|
||||||
GetWindow(browser)->Minimize();
|
GetWindow(browser)->Minimize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowTestRunnerViews::Maximize(CefRefPtr<CefBrowser> browser) {
|
void MaximizeImpl(CefRefPtr<CefBrowser> browser) {
|
||||||
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
|
CefPostTask(TID_UI, base::BindOnce(&MaximizeImpl, browser));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GetWindow(browser)->Maximize();
|
GetWindow(browser)->Maximize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowTestRunnerViews::Restore(CefRefPtr<CefBrowser> browser) {
|
void RestoreImpl(CefRefPtr<CefBrowser> browser) {
|
||||||
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
|
CefPostTask(TID_UI, base::BindOnce(&RestoreImpl, browser));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GetWindow(browser)->Restore();
|
GetWindow(browser)->Restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowTestRunnerViews::Fullscreen(CefRefPtr<CefBrowser> browser) {
|
void FullscreenImpl(CefRefPtr<CefBrowser> browser) {
|
||||||
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
|
CefPostTask(TID_UI, base::BindOnce(&FullscreenImpl, browser));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto window = GetWindow(browser);
|
auto window = GetWindow(browser);
|
||||||
|
|
||||||
// Results in a call to ViewsWindow::OnWindowFullscreenTransition().
|
// Results in a call to ViewsWindow::OnWindowFullscreenTransition().
|
||||||
@ -78,10 +72,34 @@ void WindowTestRunnerViews::Fullscreen(CefRefPtr<CefBrowser> browser) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
WindowTestRunnerViews::WindowTestRunnerViews() = default;
|
||||||
|
|
||||||
|
void WindowTestRunnerViews::Minimize(CefRefPtr<CefBrowser> browser) {
|
||||||
|
MinimizeImpl(browser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowTestRunnerViews::Maximize(CefRefPtr<CefBrowser> browser) {
|
||||||
|
MaximizeImpl(browser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowTestRunnerViews::Restore(CefRefPtr<CefBrowser> browser) {
|
||||||
|
RestoreImpl(browser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowTestRunnerViews::Fullscreen(CefRefPtr<CefBrowser> browser) {
|
||||||
|
FullscreenImpl(browser);
|
||||||
|
}
|
||||||
|
|
||||||
void WindowTestRunnerViews::SetTitleBarHeight(
|
void WindowTestRunnerViews::SetTitleBarHeight(
|
||||||
CefRefPtr<CefBrowser> browser,
|
CefRefPtr<CefBrowser> browser,
|
||||||
const std::optional<float>& height) {
|
const std::optional<float>& height) {
|
||||||
SetTitlebarHeight(browser, height);
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
|
auto root_window = RootWindow::GetForBrowser(browser->GetIdentifier());
|
||||||
|
auto root_window_views = static_cast<RootWindowViews*>(root_window.get());
|
||||||
|
root_window_views->SetTitlebarHeight(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace client::window_test
|
} // namespace client::window_test
|
||||||
|
@ -15,11 +15,6 @@ class WindowTestRunnerViews : public WindowTestRunner {
|
|||||||
public:
|
public:
|
||||||
WindowTestRunnerViews();
|
WindowTestRunnerViews();
|
||||||
|
|
||||||
void SetPos(CefRefPtr<CefBrowser> browser,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height) override;
|
|
||||||
void Minimize(CefRefPtr<CefBrowser> browser) override;
|
void Minimize(CefRefPtr<CefBrowser> browser) override;
|
||||||
void Maximize(CefRefPtr<CefBrowser> browser) override;
|
void Maximize(CefRefPtr<CefBrowser> browser) override;
|
||||||
void Restore(CefRefPtr<CefBrowser> browser) override;
|
void Restore(CefRefPtr<CefBrowser> browser) override;
|
||||||
|
@ -27,52 +27,13 @@ void Toggle(HWND root_hwnd, UINT nCmdShow) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPosImpl(CefRefPtr<CefBrowser> browser,
|
} // namespace
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height) {
|
|
||||||
HWND root_hwnd = GetRootHwnd(browser);
|
|
||||||
if (!root_hwnd) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve current window placement information.
|
WindowTestRunnerWin::WindowTestRunnerWin() = default;
|
||||||
WINDOWPLACEMENT placement;
|
|
||||||
::GetWindowPlacement(root_hwnd, &placement);
|
|
||||||
|
|
||||||
// Retrieve information about the display that contains the window.
|
void WindowTestRunnerWin::Minimize(CefRefPtr<CefBrowser> browser) {
|
||||||
HMONITOR monitor =
|
REQUIRE_MAIN_THREAD();
|
||||||
MonitorFromRect(&placement.rcNormalPosition, MONITOR_DEFAULTTONEAREST);
|
|
||||||
MONITORINFO info;
|
|
||||||
info.cbSize = sizeof(info);
|
|
||||||
GetMonitorInfo(monitor, &info);
|
|
||||||
|
|
||||||
// Make sure the window is inside the display.
|
|
||||||
CefRect display_rect(info.rcWork.left, info.rcWork.top,
|
|
||||||
info.rcWork.right - info.rcWork.left,
|
|
||||||
info.rcWork.bottom - info.rcWork.top);
|
|
||||||
CefRect window_rect(x, y, width, height);
|
|
||||||
WindowTestRunner::ModifyBounds(display_rect, window_rect);
|
|
||||||
|
|
||||||
if (placement.showCmd == SW_SHOWMINIMIZED ||
|
|
||||||
placement.showCmd == SW_SHOWMAXIMIZED) {
|
|
||||||
// The window is currently minimized or maximized. Restore it to the desired
|
|
||||||
// position.
|
|
||||||
placement.rcNormalPosition.left = window_rect.x;
|
|
||||||
placement.rcNormalPosition.right = window_rect.x + window_rect.width;
|
|
||||||
placement.rcNormalPosition.top = window_rect.y;
|
|
||||||
placement.rcNormalPosition.bottom = window_rect.y + window_rect.height;
|
|
||||||
::SetWindowPlacement(root_hwnd, &placement);
|
|
||||||
::ShowWindow(root_hwnd, SW_RESTORE);
|
|
||||||
} else {
|
|
||||||
// Set the window position.
|
|
||||||
::SetWindowPos(root_hwnd, nullptr, window_rect.x, window_rect.y,
|
|
||||||
window_rect.width, window_rect.height, SWP_NOZORDER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MinimizeImpl(CefRefPtr<CefBrowser> browser) {
|
|
||||||
HWND root_hwnd = GetRootHwnd(browser);
|
HWND root_hwnd = GetRootHwnd(browser);
|
||||||
if (!root_hwnd) {
|
if (!root_hwnd) {
|
||||||
return;
|
return;
|
||||||
@ -80,7 +41,9 @@ void MinimizeImpl(CefRefPtr<CefBrowser> browser) {
|
|||||||
Toggle(root_hwnd, SW_MINIMIZE);
|
Toggle(root_hwnd, SW_MINIMIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaximizeImpl(CefRefPtr<CefBrowser> browser) {
|
void WindowTestRunnerWin::Maximize(CefRefPtr<CefBrowser> browser) {
|
||||||
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
HWND root_hwnd = GetRootHwnd(browser);
|
HWND root_hwnd = GetRootHwnd(browser);
|
||||||
if (!root_hwnd) {
|
if (!root_hwnd) {
|
||||||
return;
|
return;
|
||||||
@ -88,7 +51,9 @@ void MaximizeImpl(CefRefPtr<CefBrowser> browser) {
|
|||||||
Toggle(root_hwnd, SW_MAXIMIZE);
|
Toggle(root_hwnd, SW_MAXIMIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestoreImpl(CefRefPtr<CefBrowser> browser) {
|
void WindowTestRunnerWin::Restore(CefRefPtr<CefBrowser> browser) {
|
||||||
|
REQUIRE_MAIN_THREAD();
|
||||||
|
|
||||||
HWND root_hwnd = GetRootHwnd(browser);
|
HWND root_hwnd = GetRootHwnd(browser);
|
||||||
if (!root_hwnd) {
|
if (!root_hwnd) {
|
||||||
return;
|
return;
|
||||||
@ -96,48 +61,4 @@ void RestoreImpl(CefRefPtr<CefBrowser> browser) {
|
|||||||
::ShowWindow(root_hwnd, SW_RESTORE);
|
::ShowWindow(root_hwnd, SW_RESTORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
WindowTestRunnerWin::WindowTestRunnerWin() = default;
|
|
||||||
|
|
||||||
void WindowTestRunnerWin::SetPos(CefRefPtr<CefBrowser> browser,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height) {
|
|
||||||
if (CURRENTLY_ON_MAIN_THREAD()) {
|
|
||||||
SetPosImpl(browser, x, y, width, height);
|
|
||||||
} else {
|
|
||||||
// Execute on the main application thread.
|
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(SetPosImpl, browser, x, y, width, height));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowTestRunnerWin::Minimize(CefRefPtr<CefBrowser> browser) {
|
|
||||||
if (CURRENTLY_ON_MAIN_THREAD()) {
|
|
||||||
MinimizeImpl(browser);
|
|
||||||
} else {
|
|
||||||
// Execute on the main application thread.
|
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(MinimizeImpl, browser));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowTestRunnerWin::Maximize(CefRefPtr<CefBrowser> browser) {
|
|
||||||
if (CURRENTLY_ON_MAIN_THREAD()) {
|
|
||||||
MaximizeImpl(browser);
|
|
||||||
} else {
|
|
||||||
// Execute on the main application thread.
|
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(MaximizeImpl, browser));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowTestRunnerWin::Restore(CefRefPtr<CefBrowser> browser) {
|
|
||||||
if (CURRENTLY_ON_MAIN_THREAD()) {
|
|
||||||
RestoreImpl(browser);
|
|
||||||
} else {
|
|
||||||
// Execute on the main application thread.
|
|
||||||
MAIN_POST_CLOSURE(base::BindOnce(RestoreImpl, browser));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace client::window_test
|
} // namespace client::window_test
|
||||||
|
@ -16,11 +16,6 @@ class WindowTestRunnerWin : public WindowTestRunner {
|
|||||||
public:
|
public:
|
||||||
WindowTestRunnerWin();
|
WindowTestRunnerWin();
|
||||||
|
|
||||||
void SetPos(CefRefPtr<CefBrowser> browser,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height) override;
|
|
||||||
void Minimize(CefRefPtr<CefBrowser> browser) override;
|
void Minimize(CefRefPtr<CefBrowser> browser) override;
|
||||||
void Maximize(CefRefPtr<CefBrowser> browser) override;
|
void Maximize(CefRefPtr<CefBrowser> browser) override;
|
||||||
void Restore(CefRefPtr<CefBrowser> browser) override;
|
void Restore(CefRefPtr<CefBrowser> browser) override;
|
||||||
|
@ -7,6 +7,12 @@
|
|||||||
:fullscreen {
|
:fullscreen {
|
||||||
background: pink;
|
background: pink;
|
||||||
}
|
}
|
||||||
|
.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.mono {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
function setup() {
|
function setup() {
|
||||||
@ -74,11 +80,66 @@ function setTitlebarHeight() {
|
|||||||
else
|
else
|
||||||
send_message('TitlebarHeight', height);
|
send_message('TitlebarHeight', height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function execWindowAction() {
|
||||||
|
const dx = parseInt(document.getElementById('window_dx').value);
|
||||||
|
const dy = parseInt(document.getElementById('window_dy').value);
|
||||||
|
if (isNaN(dx) || isNaN(dy)) {
|
||||||
|
alert('Please specify a valid numeric value.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const e = document.getElementById("window_action");
|
||||||
|
const option = e.options[e.selectedIndex].text;
|
||||||
|
switch (option) {
|
||||||
|
case "moveTo":
|
||||||
|
return window.moveTo(dx, dy);
|
||||||
|
case "moveBy":
|
||||||
|
return window.moveBy(dx, dy);
|
||||||
|
case "resizeTo":
|
||||||
|
return window.resizeTo(dx, dy);
|
||||||
|
case "resizeBy":
|
||||||
|
return window.resizeBy(dx, dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="white" onload="setup()">
|
<body bgcolor="white" onload="setup()">
|
||||||
<form id="form">
|
<form id="form">
|
||||||
Click a button to perform the associated window action.
|
<p class="bold">Click a button to perform the associated window action.</p>
|
||||||
|
<p>Input values are in DIP coordinates. See <a href="https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage#markdown-header-coordinate-systems" target="_new">here</a> for important details about coordinate systems and window behavior.</p>
|
||||||
|
<details>
|
||||||
|
<summary>Implementation details for cefclient (click to expand).</summary>
|
||||||
|
<ul>
|
||||||
|
<li>The below actions will configure window size (<span class="mono">window.outerWidth/Height</span>) and position (<span class="mono">window.screenX/Y</span>) as reported by browser content (see "Current window settings" below).</li>
|
||||||
|
<li>Whether this calculation includes the window frame will depend on what information is known/provided to CEF.</li>
|
||||||
|
<ul>
|
||||||
|
<li>Views-hosted windows are sized/positioned relative to the CefWindow frame.</li>
|
||||||
|
<li>Native windows (<span class="mono">--use-native</span>) are sized/positioned relative to the cefclient window frame.</li>
|
||||||
|
<ul>
|
||||||
|
<li>MacOS windows are sized/positioned relative to the parent NSWindow frame (default behavior).</li>
|
||||||
|
<li>Windows windows are sized/positioned relative to the root HWND frame (default behavior).</li>
|
||||||
|
<li>Linux windows are sized/positioned relative to CefDisplayHandler::GetRootWindowScreenRect.</li>
|
||||||
|
</ul>
|
||||||
|
<li>Windowless (off-screen) windows (<span class="mono">--off-screen-rendering-enabled</span>) are sized/positioned relative to CefRenderHandler::GetRootScreenRect.</li>
|
||||||
|
<ul>
|
||||||
|
<li>Pass <span class="mono">--fake-screen-bounds</span> to instead size/position relative to the browser content area.
|
||||||
|
This will also report (0,0) for position.</li>
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
<li>Exiting and relaunching cefclient will save/restore window bounds as DIP coordinates in all modes.</li>
|
||||||
|
<li>The <span class="mono">window.devicePixelRatio</span> value is a combination of device scale factor and browser zoom (if not 100%).</li>
|
||||||
|
<ul>
|
||||||
|
<li>Default device scale factor will match the associated display (e.g. user/system-level display settings).</li>
|
||||||
|
<li>Device scale factor can be configured via command-line (<span class="mono">--force-device-scale-factor=[float]</span>) or the "Tests > Set Scale Factor" menu option with windowless rendering.</li>
|
||||||
|
<ul>
|
||||||
|
<li>MacOS custom device scale factor will impact rendering quality only. DIP coordinates are not impacted.</li>
|
||||||
|
<li>Windows/Linux custom device scale factor will impact rendering quality and DIP coordinates.</li>
|
||||||
|
</ul>
|
||||||
|
<li>Browser zoom can be configured via the Chrome menu or "Tests > Zoom In/Out/Reset" menu options.
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
<br/><input type="button" onclick="minimize();" value="Minimize">
|
<br/><input type="button" onclick="minimize();" value="Minimize">
|
||||||
<br/><input type="button" onclick="maximize();" value="Maximize">
|
<br/><input type="button" onclick="maximize();" value="Maximize">
|
||||||
<br/><input type="button" onclick="restore();" value="Restore"> (minimizes and then restores the window as topmost)
|
<br/><input type="button" onclick="restore();" value="Restore"> (minimizes and then restores the window as topmost)
|
||||||
@ -86,11 +147,55 @@ Click a button to perform the associated window action.
|
|||||||
<br/><input type="button" onclick="fullscreenBrowser();" value="Toggle Browser Fullscreen"> (uses <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API" target="_new">Fullscreen API</a>; background turns pink)
|
<br/><input type="button" onclick="fullscreenBrowser();" value="Toggle Browser Fullscreen"> (uses <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API" target="_new">Fullscreen API</a>; background turns pink)
|
||||||
<br/><input type="button" onclick="position();" value="Set Position">
|
<br/><input type="button" onclick="position();" value="Set Position">
|
||||||
X: <input type="text" size="4" id="x" value="200">
|
X: <input type="text" size="4" id="x" value="200">
|
||||||
Y: <input type="text" size="4" id="y" value="100">
|
Y: <input type="text" size="4" id="y" value="200">
|
||||||
Width: <input type="text" size="4" id="width" value="800">
|
Width: <input type="text" size="4" id="width" value="800">
|
||||||
Height: <input type="text" size="4" id="height" value="600">
|
Height: <input type="text" size="4" id="height" value="600">
|
||||||
<br/><input type="button" onclick="setTitlebarHeight();" value="Set Titlebar Height">
|
<br/><input type="button" onclick="setTitlebarHeight();" value="Set Titlebar Height">
|
||||||
<input type="number" min="0" max="100" id="title_bar_height" value="50"> (works on macOS with Views)
|
<input type="number" min="0" max="100" id="title_bar_height" value="50"> (works on macOS with Views)
|
||||||
|
<br/><input type="button" onclick="execWindowAction();" value="Execute JavaScript"> window.<select id="window_action">
|
||||||
|
<option>moveTo</option>
|
||||||
|
<option>moveBy</option>
|
||||||
|
<option>resizeTo</option>
|
||||||
|
<option>resizeBy</option>
|
||||||
|
</select>(<input type="text" size="4" id="window_dx" value="200">,<input type="text" size="4" id="window_dy" value="200">) (calls CefDisplayHandler::OnContentsBoundsChange)
|
||||||
</form>
|
</form>
|
||||||
|
<p class="bold">Current window settings:</p>
|
||||||
|
<div id="size"></div>
|
||||||
|
<script>
|
||||||
|
function reportDimensions() {
|
||||||
|
document.getElementById('size').innerHTML =
|
||||||
|
`DIP coordinates:` +
|
||||||
|
`<br/>window.screen.width/height: ${window.screen.width} x ${window.screen.height}` +
|
||||||
|
`<br/>window.outerWidth/Height: ${window.outerWidth} x ${window.outerHeight}` +
|
||||||
|
`<br/>window.screenX/Y: x=${window.screenX}, y=${window.screenY}` +
|
||||||
|
`<br/><br/>CSS pixels:` +
|
||||||
|
`<br/>window.innerWidth/Height: ${window.innerWidth} x ${window.innerHeight}` +
|
||||||
|
`<br/>window.devicePixelRatio: ${window.devicePixelRatio.toFixed(2)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observe window resize events.
|
||||||
|
window.addEventListener('resize', function() { console.log('resize'); reportDimensions(); });
|
||||||
|
|
||||||
|
if (window.onmove) {
|
||||||
|
// Observe window move events.
|
||||||
|
// Only available with --enable-experimental-web-platform-features.
|
||||||
|
window.addEventListener('move', reportDimensions);
|
||||||
|
} else {
|
||||||
|
// Poll for window movement.
|
||||||
|
var last_x = window.screenX;
|
||||||
|
var last_y = window.screenY;
|
||||||
|
setInterval(function() {
|
||||||
|
const x = window.screenX;
|
||||||
|
const y = window.screenY;
|
||||||
|
if (x != last_x || y != last_y) {
|
||||||
|
last_x = x;
|
||||||
|
last_y = y;
|
||||||
|
reportDimensions();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
reportDimensions();
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -42,4 +42,21 @@ void DeviceToLogical(CefTouchEvent& value, float device_scale_factor) {
|
|||||||
value.y = DeviceToLogical(value.y, device_scale_factor);
|
value.y = DeviceToLogical(value.y, device_scale_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConstrainWindowBounds(const CefRect& display, CefRect& window) {
|
||||||
|
if (window.x < display.x) {
|
||||||
|
window.x = display.x;
|
||||||
|
}
|
||||||
|
if (window.y < display.y) {
|
||||||
|
window.y = display.y;
|
||||||
|
}
|
||||||
|
window.width = std::clamp(window.width, 100, display.width);
|
||||||
|
window.height = std::clamp(window.height, 100, display.height);
|
||||||
|
if (window.x + window.width >= display.x + display.width) {
|
||||||
|
window.x = display.x + display.width - window.width;
|
||||||
|
}
|
||||||
|
if (window.y + window.height >= display.y + display.height) {
|
||||||
|
window.y = display.y + display.height - window.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
@ -20,6 +20,10 @@ CefRect DeviceToLogical(const CefRect& value, float device_scale_factor);
|
|||||||
void DeviceToLogical(CefMouseEvent& value, float device_scale_factor);
|
void DeviceToLogical(CefMouseEvent& value, float device_scale_factor);
|
||||||
void DeviceToLogical(CefTouchEvent& value, float device_scale_factor);
|
void DeviceToLogical(CefTouchEvent& value, float device_scale_factor);
|
||||||
|
|
||||||
|
// Fit |window| inside |display|. Coordinates are relative to the upper-left
|
||||||
|
// corner of the display.
|
||||||
|
void ConstrainWindowBounds(const CefRect& display, CefRect& window);
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
||||||
#endif // CEF_TESTS_SHARED_BROWSER_GEOMETRY_UTIL_H_
|
#endif // CEF_TESTS_SHARED_BROWSER_GEOMETRY_UTIL_H_
|
||||||
|
@ -24,6 +24,7 @@ const char kOffScreenRenderingEnabled[] = "off-screen-rendering-enabled";
|
|||||||
const char kOffScreenFrameRate[] = "off-screen-frame-rate";
|
const char kOffScreenFrameRate[] = "off-screen-frame-rate";
|
||||||
const char kTransparentPaintingEnabled[] = "transparent-painting-enabled";
|
const char kTransparentPaintingEnabled[] = "transparent-painting-enabled";
|
||||||
const char kShowUpdateRect[] = "show-update-rect";
|
const char kShowUpdateRect[] = "show-update-rect";
|
||||||
|
const char kFakeScreenBounds[] = "fake-screen-bounds";
|
||||||
const char kSharedTextureEnabled[] = "shared-texture-enabled";
|
const char kSharedTextureEnabled[] = "shared-texture-enabled";
|
||||||
const char kExternalBeginFrameEnabled[] = "external-begin-frame-enabled";
|
const char kExternalBeginFrameEnabled[] = "external-begin-frame-enabled";
|
||||||
const char kMouseCursorChangeDisabled[] = "mouse-cursor-change-disabled";
|
const char kMouseCursorChangeDisabled[] = "mouse-cursor-change-disabled";
|
||||||
|
@ -18,6 +18,7 @@ extern const char kOffScreenRenderingEnabled[];
|
|||||||
extern const char kOffScreenFrameRate[];
|
extern const char kOffScreenFrameRate[];
|
||||||
extern const char kTransparentPaintingEnabled[];
|
extern const char kTransparentPaintingEnabled[];
|
||||||
extern const char kShowUpdateRect[];
|
extern const char kShowUpdateRect[];
|
||||||
|
extern const char kFakeScreenBounds[];
|
||||||
extern const char kSharedTextureEnabled[];
|
extern const char kSharedTextureEnabled[];
|
||||||
extern const char kExternalBeginFrameEnabled[];
|
extern const char kExternalBeginFrameEnabled[];
|
||||||
extern const char kMouseCursorChangeDisabled[];
|
extern const char kMouseCursorChangeDisabled[];
|
||||||
|
Reference in New Issue
Block a user