mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-01 11:57:04 +01:00
alloy: mac: Fix default popup window positioning (see issue #3244)
Popup windows will be created on the display that best matches the requested coordinates. The requested size will apply to the content area (as required by JS documentation) and window size will be reduced if necessary to fit within the target display. The requested origin will apply to the window (including frame) and will be modified if necessary so that the window is fully visible on the target display. This change does not implement popup positioning for cefclient which uses an application-created parent window. This change grants access to the getScreenDetails JS API without user prompt.
This commit is contained in:
parent
fb71a32356
commit
c05cb73de1
11
BUILD.gn
11
BUILD.gn
@ -373,6 +373,8 @@ source_set("libcef_static_unittested") {
|
||||
sources = [
|
||||
"libcef/browser/devtools/devtools_util.cc",
|
||||
"libcef/browser/devtools/devtools_util.h",
|
||||
"libcef/browser/screen_util.h",
|
||||
"libcef/browser/screen_util.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
@ -389,6 +391,7 @@ source_set("libcef_static_unittested") {
|
||||
test("libcef_static_unittests") {
|
||||
sources = [
|
||||
"libcef/browser/devtools/devtools_util_unittest.cc",
|
||||
"libcef/browser/screen_util_unittest.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
@ -416,6 +419,8 @@ static_library("libcef_static") {
|
||||
"libcef/browser/alloy/alloy_content_browser_client.h",
|
||||
"libcef/browser/alloy/alloy_download_util.cc",
|
||||
"libcef/browser/alloy/alloy_download_util.h",
|
||||
"libcef/browser/alloy/alloy_permission_manager.cc",
|
||||
"libcef/browser/alloy/alloy_permission_manager.h",
|
||||
"libcef/browser/alloy/alloy_web_contents_view_delegate.cc",
|
||||
"libcef/browser/alloy/alloy_web_contents_view_delegate.h",
|
||||
"libcef/browser/alloy/browser_platform_delegate_alloy.cc",
|
||||
@ -669,6 +674,8 @@ static_library("libcef_static") {
|
||||
"libcef/browser/request_context_impl.cc",
|
||||
"libcef/browser/request_context_impl.h",
|
||||
"libcef/browser/scheme_impl.cc",
|
||||
"libcef/browser/screen_util.cc",
|
||||
"libcef/browser/screen_util.h",
|
||||
"libcef/browser/server_impl.cc",
|
||||
"libcef/browser/server_impl.h",
|
||||
"libcef/browser/simple_menu_model_impl.cc",
|
||||
@ -1645,7 +1652,7 @@ if (is_mac) {
|
||||
"libcef_dll/libcef_dll.rc",
|
||||
]
|
||||
|
||||
deps += [
|
||||
deps += [
|
||||
# Bring in ui_unscaled_resources.rc which contains custom cursors.
|
||||
# TODO(cef): Remove this once custom cursors can be loaded via
|
||||
# ResourceBundle. See crbug.com/147663.
|
||||
@ -2249,7 +2256,7 @@ if (is_mac) {
|
||||
#
|
||||
# ceftests targets.
|
||||
#
|
||||
|
||||
|
||||
if (is_linux) {
|
||||
copy("copy_ceftests_files") {
|
||||
sources = gypi_paths2.shared_sources_resources
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include "libcef/browser/alloy/alloy_permission_manager.h"
|
||||
#include "libcef/browser/download_manager_delegate.h"
|
||||
#include "libcef/browser/extensions/extension_system.h"
|
||||
#include "libcef/browser/prefs/browser_prefs.h"
|
||||
@ -380,7 +381,9 @@ content::SSLHostStateDelegate* AlloyBrowserContext::GetSSLHostStateDelegate() {
|
||||
|
||||
content::PermissionControllerDelegate*
|
||||
AlloyBrowserContext::GetPermissionControllerDelegate() {
|
||||
return nullptr;
|
||||
if (!permission_manager_.get())
|
||||
permission_manager_ = std::make_unique<AlloyPermissionManager>();
|
||||
return permission_manager_.get();
|
||||
}
|
||||
|
||||
content::BackgroundFetchDelegate*
|
||||
|
@ -145,6 +145,8 @@ class AlloyBrowserContext : public ChromeProfileAlloy,
|
||||
std::unique_ptr<content::ResourceContext> resource_context_;
|
||||
|
||||
scoped_refptr<MediaDeviceIDSalt> media_device_id_salt_;
|
||||
|
||||
std::unique_ptr<content::PermissionControllerDelegate> permission_manager_;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_BROWSER_CONTEXT_H_
|
||||
|
115
libcef/browser/alloy/alloy_permission_manager.cc
Normal file
115
libcef/browser/alloy/alloy_permission_manager.cc
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright 2022 The Chromium Embedded Framework Authors. Portions copyright
|
||||
// 2015 The Chromium 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 "libcef/browser/alloy/alloy_permission_manager.h"
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "content/public/browser/permission_controller.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "third_party/blink/public/common/permissions/permission_utils.h"
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsAllowed(blink::PermissionType permission) {
|
||||
return permission == blink::PermissionType::WINDOW_PLACEMENT;
|
||||
}
|
||||
|
||||
blink::mojom::PermissionStatus GetPermissionStatusFromType(
|
||||
blink::PermissionType permission) {
|
||||
return IsAllowed(permission) ? blink::mojom::PermissionStatus::GRANTED
|
||||
: blink::mojom::PermissionStatus::DENIED;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void AlloyPermissionManager::RequestPermission(
|
||||
blink::PermissionType permission,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
bool user_gesture,
|
||||
base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) {
|
||||
if (render_frame_host->IsNestedWithinFencedFrame()) {
|
||||
std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
|
||||
return;
|
||||
}
|
||||
std::move(callback).Run(GetPermissionStatusFromType(permission));
|
||||
}
|
||||
|
||||
void AlloyPermissionManager::RequestPermissions(
|
||||
const std::vector<blink::PermissionType>& permissions,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
bool user_gesture,
|
||||
base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
|
||||
callback) {
|
||||
if (render_frame_host->IsNestedWithinFencedFrame()) {
|
||||
std::move(callback).Run(std::vector<blink::mojom::PermissionStatus>(
|
||||
permissions.size(), blink::mojom::PermissionStatus::DENIED));
|
||||
return;
|
||||
}
|
||||
std::vector<blink::mojom::PermissionStatus> result;
|
||||
for (const auto& permission : permissions) {
|
||||
result.push_back(GetPermissionStatusFromType(permission));
|
||||
}
|
||||
std::move(callback).Run(result);
|
||||
}
|
||||
|
||||
void AlloyPermissionManager::RequestPermissionsFromCurrentDocument(
|
||||
const std::vector<blink::PermissionType>& permissions,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
bool user_gesture,
|
||||
base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
|
||||
callback) {
|
||||
if (render_frame_host->IsNestedWithinFencedFrame()) {
|
||||
std::move(callback).Run(std::vector<blink::mojom::PermissionStatus>(
|
||||
permissions.size(), blink::mojom::PermissionStatus::DENIED));
|
||||
return;
|
||||
}
|
||||
std::vector<blink::mojom::PermissionStatus> result;
|
||||
for (const auto& permission : permissions) {
|
||||
result.push_back(GetPermissionStatusFromType(permission));
|
||||
}
|
||||
std::move(callback).Run(result);
|
||||
}
|
||||
|
||||
blink::mojom::PermissionStatus AlloyPermissionManager::GetPermissionStatus(
|
||||
blink::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) {
|
||||
return GetPermissionStatusFromType(permission);
|
||||
}
|
||||
|
||||
blink::mojom::PermissionStatus
|
||||
AlloyPermissionManager::GetPermissionStatusForCurrentDocument(
|
||||
blink::PermissionType permission,
|
||||
content::RenderFrameHost* render_frame_host) {
|
||||
if (render_frame_host->IsNestedWithinFencedFrame())
|
||||
return blink::mojom::PermissionStatus::DENIED;
|
||||
return GetPermissionStatusFromType(permission);
|
||||
}
|
||||
|
||||
blink::mojom::PermissionStatus
|
||||
AlloyPermissionManager::GetPermissionStatusForWorker(
|
||||
blink::PermissionType permission,
|
||||
content::RenderProcessHost* render_process_host,
|
||||
const GURL& worker_origin) {
|
||||
return GetPermissionStatusFromType(permission);
|
||||
}
|
||||
|
||||
void AlloyPermissionManager::ResetPermission(blink::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) {}
|
||||
|
||||
AlloyPermissionManager::SubscriptionId
|
||||
AlloyPermissionManager::SubscribePermissionStatusChange(
|
||||
blink::PermissionType permission,
|
||||
content::RenderProcessHost* render_process_host,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback) {
|
||||
return SubscriptionId();
|
||||
}
|
||||
|
||||
void AlloyPermissionManager::UnsubscribePermissionStatusChange(
|
||||
SubscriptionId subscription_id) {}
|
68
libcef/browser/alloy/alloy_permission_manager.h
Normal file
68
libcef/browser/alloy/alloy_permission_manager.h
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright 2022 The Chromium Embedded Framework Authors. Portions copyright
|
||||
// 2015 The Chromium 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_LIBCEF_BROWSER_ALLOY_ALLOY_PERMISSION_MANAGER_H_
|
||||
#define CEF_LIBCEF_BROWSER_ALLOY_ALLOY_PERMISSION_MANAGER_H_
|
||||
#pragma once
|
||||
|
||||
#include "base/callback_forward.h"
|
||||
#include "content/public/browser/permission_controller_delegate.h"
|
||||
|
||||
// Permision manager implementations that only allows WINDOW_PLACEMENT API
|
||||
class AlloyPermissionManager : public content::PermissionControllerDelegate {
|
||||
public:
|
||||
AlloyPermissionManager() = default;
|
||||
|
||||
AlloyPermissionManager(const AlloyPermissionManager&) = delete;
|
||||
AlloyPermissionManager& operator=(const AlloyPermissionManager&) = delete;
|
||||
|
||||
// PermissionManager implementation.
|
||||
void RequestPermission(
|
||||
blink::PermissionType permission,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
bool user_gesture,
|
||||
base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
|
||||
override;
|
||||
void RequestPermissions(
|
||||
const std::vector<blink::PermissionType>& permission,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
bool user_gesture,
|
||||
base::OnceCallback<
|
||||
void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
|
||||
override;
|
||||
void RequestPermissionsFromCurrentDocument(
|
||||
const std::vector<blink::PermissionType>& permissions,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
bool user_gesture,
|
||||
base::OnceCallback<
|
||||
void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
|
||||
override;
|
||||
blink::mojom::PermissionStatus GetPermissionStatus(
|
||||
blink::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) override;
|
||||
blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
|
||||
blink::PermissionType permission,
|
||||
content::RenderFrameHost* render_frame_host) override;
|
||||
blink::mojom::PermissionStatus GetPermissionStatusForWorker(
|
||||
blink::PermissionType permission,
|
||||
content::RenderProcessHost* render_process_host,
|
||||
const GURL& worker_origin) override;
|
||||
void ResetPermission(blink::PermissionType permission,
|
||||
const GURL& requesting_origin,
|
||||
const GURL& embedding_origin) override;
|
||||
SubscriptionId SubscribePermissionStatusChange(
|
||||
blink::PermissionType permission,
|
||||
content::RenderProcessHost* render_process_host,
|
||||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& requesting_origin,
|
||||
base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
|
||||
override;
|
||||
void UnsubscribePermissionStatusChange(
|
||||
SubscriptionId subscription_id) override;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_PERMISSION_MANAGER_H_
|
@ -154,7 +154,6 @@ bool CefBrowserInfoManager::CanCreateWindow(
|
||||
CefPopupFeatures cef_features;
|
||||
TranslatePopupFeatures(features, cef_features);
|
||||
|
||||
#if (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC))
|
||||
// Default to the size from the popup features.
|
||||
if (cef_features.xSet)
|
||||
window_info.bounds.x = cef_features.x;
|
||||
@ -164,7 +163,6 @@ bool CefBrowserInfoManager::CanCreateWindow(
|
||||
window_info.bounds.width = cef_features.width;
|
||||
if (cef_features.heightSet)
|
||||
window_info.bounds.height = cef_features.height;
|
||||
#endif
|
||||
|
||||
allow = !handler->OnBeforePopup(
|
||||
browser.get(), opener_frame, pending_popup->target_url.spec(),
|
||||
|
@ -140,6 +140,13 @@ NSUInteger NativeModifiers(int cef_modifiers) {
|
||||
return native_modifiers;
|
||||
}
|
||||
|
||||
constexpr int kDefaultHeight = 750;
|
||||
constexpr int kDefaultWidth = 750;
|
||||
constexpr NSWindowStyleMask kDefaultStyleMask =
|
||||
NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
|
||||
NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable |
|
||||
NSWindowStyleMaskUnifiedTitleAndToolbar;
|
||||
|
||||
} // namespace
|
||||
|
||||
CefBrowserPlatformDelegateNativeMac::CefBrowserPlatformDelegateNativeMac(
|
||||
@ -176,19 +183,15 @@ bool CefBrowserPlatformDelegateNativeMac::CreateHostWindow() {
|
||||
// Create a new window.
|
||||
NSRect window_rect = {{x, y}, {width, height}};
|
||||
if (window_rect.size.width == 0)
|
||||
window_rect.size.width = 750;
|
||||
window_rect.size.width = kDefaultWidth;
|
||||
if (window_rect.size.height == 0)
|
||||
window_rect.size.height = 750;
|
||||
window_rect.size.height = kDefaultHeight;
|
||||
|
||||
content_rect = {{0, 0}, {window_rect.size.width, window_rect.size.height}};
|
||||
|
||||
newWnd = [[UnderlayOpenGLHostingWindow alloc]
|
||||
initWithContentRect:window_rect
|
||||
styleMask:(NSWindowStyleMaskTitled |
|
||||
NSWindowStyleMaskClosable |
|
||||
NSWindowStyleMaskMiniaturizable |
|
||||
NSWindowStyleMaskResizable |
|
||||
NSWindowStyleMaskUnifiedTitleAndToolbar)
|
||||
styleMask:kDefaultStyleMask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
||||
#include "libcef/browser/context.h"
|
||||
#include "libcef/browser/native/window_delegate_view.h"
|
||||
#include "libcef/browser/screen_util.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "base/base_paths_win.h"
|
||||
@ -146,6 +147,61 @@ float GetWindowScaleFactor(HWND hwnd) {
|
||||
.device_scale_factor();
|
||||
}
|
||||
|
||||
struct ScreenInfo {
|
||||
float scale_factor;
|
||||
CefRect rect;
|
||||
};
|
||||
|
||||
ScreenInfo GetScreenInfo(int x, int y) {
|
||||
const auto display =
|
||||
display::Screen::GetScreen()->GetDisplayNearestPoint(gfx::Point(x, y));
|
||||
const auto rect = display.work_area();
|
||||
|
||||
return ScreenInfo{display.device_scale_factor(),
|
||||
CefRect(rect.x(), rect.y(), rect.width(), rect.height())};
|
||||
}
|
||||
|
||||
CefRect GetFrameRectFromLogicalContentRect(CefRect content,
|
||||
DWORD style,
|
||||
DWORD ex_style,
|
||||
bool has_menu,
|
||||
float scale) {
|
||||
const auto scaled_rect = gfx::ScaleToRoundedRect(
|
||||
gfx::Rect(content.x, content.y, content.width, content.height), scale);
|
||||
|
||||
RECT rect = {0, 0, scaled_rect.width(), scaled_rect.height()};
|
||||
|
||||
AdjustWindowRectEx(&rect, style, has_menu, ex_style);
|
||||
|
||||
return CefRect(scaled_rect.x(), scaled_rect.y(), rect.right - rect.left,
|
||||
rect.bottom - rect.top);
|
||||
}
|
||||
|
||||
CefRect GetAdjustedWindowRect(CefRect content,
|
||||
DWORD style,
|
||||
DWORD ex_style,
|
||||
bool has_menu) {
|
||||
// If height or width is not provided, let OS determine position and size,
|
||||
// similarly to Chromium behavior
|
||||
if (content.width == CW_USEDEFAULT || content.height == CW_USEDEFAULT) {
|
||||
return CefRect(CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT);
|
||||
}
|
||||
|
||||
if (content.x == CW_USEDEFAULT) {
|
||||
content.x = 0;
|
||||
}
|
||||
|
||||
if (content.y == CW_USEDEFAULT) {
|
||||
content.y = 0;
|
||||
}
|
||||
|
||||
const ScreenInfo screen = GetScreenInfo(content.x, content.y);
|
||||
const CefRect rect = MakeVisibleOnScreenRect(content, screen.rect);
|
||||
|
||||
return GetFrameRectFromLogicalContentRect(rect, style, ex_style, has_menu,
|
||||
screen.scale_factor);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CefBrowserPlatformDelegateNativeWin::CefBrowserPlatformDelegateNativeWin(
|
||||
@ -182,14 +238,23 @@ bool CefBrowserPlatformDelegateNativeWin::CreateHostWindow() {
|
||||
|
||||
has_frame_ = !(window_info_.style & WS_CHILD);
|
||||
|
||||
std::wstring windowName(CefString(&window_info_.window_name));
|
||||
const std::wstring windowName(CefString(&window_info_.window_name));
|
||||
|
||||
CefRect window_rect = window_info_.bounds;
|
||||
|
||||
if (!window_info_.parent_window) {
|
||||
const bool has_menu =
|
||||
!(window_info_.style & WS_CHILD) && (window_info_.menu != NULL);
|
||||
window_rect = GetAdjustedWindowRect(window_rect, window_info_.style,
|
||||
window_info_.ex_style, has_menu);
|
||||
}
|
||||
|
||||
// Create the new browser window.
|
||||
CreateWindowEx(window_info_.ex_style, GetWndClass(), windowName.c_str(),
|
||||
window_info_.style, window_info_.bounds.x,
|
||||
window_info_.bounds.y, window_info_.bounds.width,
|
||||
window_info_.bounds.height, window_info_.parent_window,
|
||||
window_info_.menu, ::GetModuleHandle(NULL), this);
|
||||
window_info_.style, window_rect.x, window_rect.y,
|
||||
window_rect.width, window_rect.height,
|
||||
window_info_.parent_window, window_info_.menu,
|
||||
::GetModuleHandle(NULL), this);
|
||||
|
||||
// It's possible for CreateWindowEx to fail if the parent window was
|
||||
// destroyed between the call to CreateBrowser and the above one.
|
||||
@ -348,18 +413,17 @@ void CefBrowserPlatformDelegateNativeWin::NotifyMoveOrResizeStarted() {
|
||||
void CefBrowserPlatformDelegateNativeWin::SizeTo(int width, int height) {
|
||||
HWND window = window_info_.window;
|
||||
|
||||
RECT rect = {0, 0, width, height};
|
||||
DWORD style = GetWindowLong(window, GWL_STYLE);
|
||||
DWORD ex_style = GetWindowLong(window, GWL_EXSTYLE);
|
||||
bool has_menu = !(style & WS_CHILD) && (GetMenu(window) != NULL);
|
||||
const DWORD style = GetWindowLong(window, GWL_STYLE);
|
||||
const DWORD ex_style = GetWindowLong(window, GWL_EXSTYLE);
|
||||
const bool has_menu = !(style & WS_CHILD) && (GetMenu(window) != NULL);
|
||||
const float scale = GetWindowScaleFactor(window);
|
||||
|
||||
// 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);
|
||||
const CefRect content_rect(0, 0, width, height);
|
||||
const CefRect frame_rect = GetFrameRectFromLogicalContentRect(
|
||||
content_rect, style, ex_style, has_menu, scale);
|
||||
|
||||
// Size the window. The left/top values may be negative.
|
||||
SetWindowPos(window, NULL, 0, 0, rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
SetWindowPos(window, NULL, 0, 0, frame_rect.width, frame_rect.height,
|
||||
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
@ -616,4 +680,4 @@ LRESULT CALLBACK CefBrowserPlatformDelegateNativeWin::WndProc(HWND hwnd,
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, message, wParam, lParam);
|
||||
}
|
||||
}
|
39
libcef/browser/screen_util.cc
Normal file
39
libcef/browser/screen_util.cc
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2022 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 "libcef/browser/screen_util.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kMinWidth = 0;
|
||||
constexpr int kMinHeight = 0;
|
||||
|
||||
// Makes sure that line segment lies entirely between min and max.
|
||||
int clamp_segment_start(int start, int len, int min, int max) {
|
||||
start = std::clamp(start, min, max);
|
||||
const int end = start + len;
|
||||
const int excess = end - max;
|
||||
|
||||
if (excess > 0)
|
||||
start = start - excess;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CefRect MakeVisibleOnScreenRect(const CefRect& rect, const CefRect& screen) {
|
||||
const int width = std::clamp(rect.width, kMinWidth, screen.width);
|
||||
const int height = std::clamp(rect.height, kMinHeight, screen.height);
|
||||
|
||||
const int right_border = screen.x + screen.width;
|
||||
const int x = clamp_segment_start(rect.x, width, screen.x, right_border);
|
||||
|
||||
const int bottom_border = screen.y + screen.height;
|
||||
const int y = clamp_segment_start(rect.y, height, screen.y, bottom_border);
|
||||
|
||||
return CefRect(x, y, width, height);
|
||||
}
|
17
libcef/browser/screen_util.h
Normal file
17
libcef/browser/screen_util.h
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2022 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_LIBCEF_BROWSER_SCREEN_UTIL_H_
|
||||
#define CEF_LIBCEF_BROWSER_SCREEN_UTIL_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/internal/cef_types_wrappers.h"
|
||||
|
||||
// Create a new rectangle from the input |rect| rectangle that is fully visible
|
||||
// on provided |screen_rect| screen. The width and height of the resulting
|
||||
// rectangle are clamped to the screen width and height respectively if they
|
||||
// would overflow.
|
||||
CefRect MakeVisibleOnScreenRect(const CefRect& rect, const CefRect& screen);
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_SCREEN_UTIL_H_
|
81
libcef/browser/screen_util_unittest.cc
Normal file
81
libcef/browser/screen_util_unittest.cc
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2022 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 "cef/libcef/browser/screen_util.h"
|
||||
#include "tests/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kScreenWidth = 1024;
|
||||
constexpr int kScreenHeight = 768;
|
||||
const CefRect kMainScreen(0, 0, kScreenWidth, kScreenHeight);
|
||||
const CefRect kLeftScreen(-1024, 0, kScreenWidth, kScreenHeight);
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(MakeVisibleOnScreenRect, RectSizeIsBiggerThanScreen) {
|
||||
const CefRect rect{400, 500, 1500, 800};
|
||||
|
||||
auto result = MakeVisibleOnScreenRect(rect, kMainScreen);
|
||||
|
||||
EXPECT_EQ(result.x, 0);
|
||||
EXPECT_EQ(result.width, kMainScreen.width);
|
||||
EXPECT_EQ(result.y, 0);
|
||||
EXPECT_EQ(result.height, kMainScreen.height);
|
||||
}
|
||||
|
||||
TEST(MakeVisibleOnScreenRect, RightBorderIsOutsideTheScreen) {
|
||||
const CefRect rect{600, 400, 500, 300};
|
||||
|
||||
auto result = MakeVisibleOnScreenRect(rect, kMainScreen);
|
||||
|
||||
EXPECT_EQ(result.x, 524);
|
||||
EXPECT_EQ(result.width, rect.width);
|
||||
EXPECT_EQ(result.y, rect.y);
|
||||
EXPECT_EQ(result.height, rect.height);
|
||||
}
|
||||
|
||||
TEST(MakeVisibleOnScreenRect, LeftBorderIsOutsideTheScreen) {
|
||||
const CefRect rect{-400, 400, 500, 300};
|
||||
|
||||
auto result = MakeVisibleOnScreenRect(rect, kMainScreen);
|
||||
|
||||
EXPECT_EQ(result.x, 0);
|
||||
EXPECT_EQ(result.width, rect.width);
|
||||
EXPECT_EQ(result.y, rect.y);
|
||||
EXPECT_EQ(result.height, rect.height);
|
||||
}
|
||||
|
||||
TEST(MakeVisibleOnScreenRect, BottomBorderIsOutsideTheScreen) {
|
||||
const CefRect rect{600, 500, 300, 300};
|
||||
|
||||
auto result = MakeVisibleOnScreenRect(rect, kMainScreen);
|
||||
|
||||
EXPECT_EQ(result.x, 600);
|
||||
EXPECT_EQ(result.width, rect.width);
|
||||
EXPECT_EQ(result.y, 468);
|
||||
EXPECT_EQ(result.height, rect.height);
|
||||
}
|
||||
|
||||
TEST(MakeVisibleOnScreenRect, RectIsVisibleOnTheLeftScreen) {
|
||||
const CefRect rect{-500, 300, 300, 300};
|
||||
|
||||
auto result = MakeVisibleOnScreenRect(rect, kLeftScreen);
|
||||
|
||||
EXPECT_EQ(result.x, rect.x);
|
||||
EXPECT_EQ(result.width, rect.width);
|
||||
EXPECT_EQ(result.y, rect.y);
|
||||
EXPECT_EQ(result.height, rect.height);
|
||||
}
|
||||
|
||||
TEST(MakeVisibleOnScreenRect, RectSizeIsBiggerThanLeftScreen) {
|
||||
const CefRect rect{-500, 300, 3000, 3000};
|
||||
|
||||
auto result = MakeVisibleOnScreenRect(rect, kLeftScreen);
|
||||
|
||||
EXPECT_EQ(result.x, kLeftScreen.x);
|
||||
EXPECT_EQ(result.width, kLeftScreen.width);
|
||||
EXPECT_EQ(result.y, kLeftScreen.y);
|
||||
EXPECT_EQ(result.height, kLeftScreen.height);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user