2022-06-02 11:49:50 +02:00
|
|
|
diff --git chrome/browser/ui/views/chrome_javascript_app_modal_view_factory_views.cc chrome/browser/ui/views/chrome_javascript_app_modal_view_factory_views.cc
|
2023-04-26 21:55:59 +02:00
|
|
|
index b169371e4d42f..509e4bda85b47 100644
|
2022-06-02 11:49:50 +02:00
|
|
|
--- chrome/browser/ui/views/chrome_javascript_app_modal_view_factory_views.cc
|
|
|
|
+++ chrome/browser/ui/views/chrome_javascript_app_modal_view_factory_views.cc
|
2023-04-26 21:55:59 +02:00
|
|
|
@@ -100,7 +100,7 @@ javascript_dialogs::AppModalDialogView* CreateViewsJavaScriptDialog(
|
2022-06-02 11:49:50 +02:00
|
|
|
gfx::NativeWindow parent_window =
|
|
|
|
controller->web_contents()->GetTopLevelNativeWindow();
|
|
|
|
#if defined(USE_AURA)
|
|
|
|
- if (!parent_window->GetRootWindow()) {
|
|
|
|
+ if (parent_window && !parent_window->GetRootWindow()) {
|
|
|
|
// When we are part of a WebContents that isn't actually being displayed
|
|
|
|
// on the screen, we can't actually attach to it.
|
|
|
|
parent_window = nullptr;
|
|
|
|
diff --git components/constrained_window/constrained_window_views.cc components/constrained_window/constrained_window_views.cc
|
2024-01-17 20:33:52 +01:00
|
|
|
index 9e07412327ce9..3ac78725eba18 100644
|
2022-06-02 11:49:50 +02:00
|
|
|
--- components/constrained_window/constrained_window_views.cc
|
|
|
|
+++ components/constrained_window/constrained_window_views.cc
|
2023-09-15 21:51:43 +02:00
|
|
|
@@ -105,15 +105,24 @@ void UpdateModalDialogPosition(views::Widget* widget,
|
2022-06-02 11:49:50 +02:00
|
|
|
if (widget->HasCapture())
|
|
|
|
return;
|
|
|
|
|
|
|
|
+ // |host_view| will be nullptr with CEF windowless rendering.
|
|
|
|
+ auto host_view = dialog_host->GetHostView();
|
|
|
|
views::Widget* host_widget =
|
|
|
|
- views::Widget::GetWidgetForNativeView(dialog_host->GetHostView());
|
|
|
|
+ host_view ? views::Widget::GetWidgetForNativeView(host_view) : nullptr;
|
|
|
|
|
|
|
|
// If the host view is not backed by a Views::Widget, just update the widget
|
|
|
|
// size. This can happen on MacViews under the Cocoa browser where the window
|
|
|
|
// modal dialogs are displayed as sheets, and their position is managed by a
|
|
|
|
// ConstrainedWindowSheetController instance.
|
|
|
|
if (!host_widget) {
|
|
|
|
+#if BUILDFLAG(IS_MAC)
|
|
|
|
widget->SetSize(size);
|
|
|
|
+#elif BUILDFLAG(IS_POSIX)
|
|
|
|
+ // Set the bounds here instead of relying on the default behavior of
|
|
|
|
+ // DesktopWindowTreeHostPlatform::CenterWindow which incorrectly centers
|
|
|
|
+ // the window on the screen.
|
|
|
|
+ widget->SetBounds(gfx::Rect(dialog_host->GetDialogPosition(size), size));
|
|
|
|
+#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-01-17 20:33:52 +01:00
|
|
|
@@ -123,36 +132,22 @@ void UpdateModalDialogPosition(views::Widget* widget,
|
|
|
|
position.set_y(position.y() -
|
|
|
|
widget->non_client_view()->frame_view()->GetInsets().top());
|
|
|
|
|
|
|
|
- gfx::Rect dialog_bounds(position, size);
|
|
|
|
-
|
|
|
|
if (widget->is_top_level() && SupportsGlobalScreenCoordinates()) {
|
|
|
|
- const gfx::Rect initial_dialog_bounds =
|
|
|
|
- dialog_bounds +
|
|
|
|
- host_widget->GetClientAreaBoundsInScreen().OffsetFromOrigin();
|
|
|
|
- const gfx::Rect initial_host_bounds =
|
|
|
|
- host_widget->GetWindowBoundsInScreen();
|
|
|
|
-
|
|
|
|
- // TODO(crbug.com/1341530): The requested dialog bounds should never fall
|
|
|
|
- // outside the bounds of the transient parent.
|
|
|
|
- DCHECK(initial_dialog_bounds.Intersects(initial_host_bounds));
|
|
|
|
-
|
|
|
|
- // We should not show a window-modal dialog for a window that exists outside
|
|
|
|
- // the bounds of the screen. This risks the modal window becoming
|
|
|
|
- // effectively deadlocked as controls to dismiss the dialog may become
|
|
|
|
- // inaccessible.
|
|
|
|
- // It is also insufficient to reposition only the dialog but not the host
|
|
|
|
- // window as many systems will clip child dialogs to their transient
|
|
|
|
- // parents. Further, if the window-constrained dialog is visually
|
|
|
|
- // disassociated with its parent window it may be difficult to discern which
|
|
|
|
- // window the dialog is modal to.
|
|
|
|
- host_widget->SetBoundsConstrained(initial_host_bounds);
|
|
|
|
- const gfx::Rect adjusted_host_bounds =
|
|
|
|
- host_widget->GetClientAreaBoundsInScreen();
|
|
|
|
- dialog_bounds += adjusted_host_bounds.OffsetFromOrigin();
|
|
|
|
- dialog_bounds.AdjustToFit(adjusted_host_bounds);
|
|
|
|
+ position += host_widget->GetClientAreaBoundsInScreen().OffsetFromOrigin();
|
|
|
|
+ // If the dialog extends partially off any display, clamp its position to
|
|
|
|
+ // be fully visible within that display. If the dialog doesn't intersect
|
|
|
|
+ // with any display clamp its position to be fully on the nearest display.
|
|
|
|
+ gfx::Rect display_rect = gfx::Rect(position, size);
|
|
|
|
+ const display::Display display =
|
|
|
|
+ display::Screen::GetScreen()->GetDisplayNearestView(
|
|
|
|
+ dialog_host->GetHostView());
|
|
|
|
+ const gfx::Rect work_area = display.work_area();
|
|
|
|
+ if (!work_area.Contains(display_rect))
|
|
|
|
+ display_rect.AdjustToFit(work_area);
|
|
|
|
+ position = display_rect.origin();
|
|
|
|
}
|
|
|
|
|
|
|
|
- widget->SetBounds(dialog_bounds);
|
|
|
|
+ widget->SetBounds(gfx::Rect(position, size));
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
@@ -224,7 +219,8 @@ views::Widget* CreateWebModalDialogViews(views::WidgetDelegate* dialog,
|
2022-06-02 11:49:50 +02:00
|
|
|
|
2023-09-15 21:51:43 +02:00
|
|
|
views::Widget* widget = views::DialogDelegate::CreateDialogWidget(
|
2022-06-02 11:49:50 +02:00
|
|
|
dialog, nullptr,
|
|
|
|
- manager->delegate()->GetWebContentsModalDialogHost()->GetHostView());
|
|
|
|
+ manager->delegate()->GetWebContentsModalDialogHost()->GetHostView(),
|
2023-09-15 21:51:43 +02:00
|
|
|
+ manager->delegate()->GetWebContentsModalDialogHost()->GetAcceleratedWidget());
|
|
|
|
widget->SetNativeWindowProperty(
|
|
|
|
views::kWidgetIdentifierKey,
|
|
|
|
const_cast<void*>(kConstrainedWindowWidgetIdentifier));
|
2024-01-17 20:33:52 +01:00
|
|
|
@@ -246,8 +242,13 @@ views::Widget* CreateBrowserModalDialogViews(views::DialogDelegate* dialog,
|
2022-06-02 11:49:50 +02:00
|
|
|
|
|
|
|
gfx::NativeView parent_view =
|
|
|
|
parent ? CurrentClient()->GetDialogHostView(parent) : nullptr;
|
|
|
|
+ // Use with CEF windowless rendering.
|
|
|
|
+ gfx::AcceleratedWidget parent_widget =
|
|
|
|
+ parent ? gfx::kNullAcceleratedWidget :
|
2023-09-15 21:51:43 +02:00
|
|
|
+ CurrentClient()->GetModalDialogHost(parent)->GetAcceleratedWidget();
|
2022-06-02 11:49:50 +02:00
|
|
|
views::Widget* widget =
|
|
|
|
- views::DialogDelegate::CreateDialogWidget(dialog, nullptr, parent_view);
|
|
|
|
+ views::DialogDelegate::CreateDialogWidget(dialog, nullptr, parent_view,
|
|
|
|
+ parent_widget);
|
2023-09-15 21:51:43 +02:00
|
|
|
widget->SetNativeWindowProperty(
|
|
|
|
views::kWidgetIdentifierKey,
|
|
|
|
const_cast<void*>(kConstrainedWindowWidgetIdentifier));
|
2024-01-17 20:33:52 +01:00
|
|
|
@@ -263,8 +264,7 @@ views::Widget* CreateBrowserModalDialogViews(views::DialogDelegate* dialog,
|
2022-06-02 11:49:50 +02:00
|
|
|
if (!requires_positioning)
|
|
|
|
return widget;
|
|
|
|
|
|
|
|
- ModalDialogHost* host =
|
|
|
|
- parent ? CurrentClient()->GetModalDialogHost(parent) : nullptr;
|
|
|
|
+ ModalDialogHost* host = CurrentClient()->GetModalDialogHost(parent);
|
|
|
|
if (host) {
|
|
|
|
DCHECK_EQ(parent_view, host->GetHostView());
|
|
|
|
ModalDialogHostObserver* dialog_host_observer =
|
|
|
|
diff --git components/constrained_window/native_web_contents_modal_dialog_manager_views.cc components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
|
2023-10-19 20:08:48 +02:00
|
|
|
index b986b7fa98c73..1000f529acc82 100644
|
2022-06-02 11:49:50 +02:00
|
|
|
--- components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
|
|
|
|
+++ components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
|
2023-10-19 20:08:48 +02:00
|
|
|
@@ -188,9 +188,20 @@ void NativeWebContentsModalDialogManagerViews::HostChanged(
|
2022-06-02 11:49:50 +02:00
|
|
|
if (host_) {
|
|
|
|
host_->AddObserver(this);
|
|
|
|
|
|
|
|
- for (auto* widget : observed_widgets_) {
|
|
|
|
- views::Widget::ReparentNativeView(widget->GetNativeView(),
|
|
|
|
- host_->GetHostView());
|
|
|
|
+ // |host_view| will be nullptr with CEF windowless rendering.
|
|
|
|
+ if (auto host_view = host_->GetHostView()) {
|
|
|
|
+ for (auto* widget : observed_widgets_) {
|
2023-06-14 10:20:02 +02:00
|
|
|
+#if defined(USE_AURA)
|
|
|
|
+ auto widget_view = widget->GetNativeView();
|
|
|
|
+ // Don't reparent between different root windows. Doing so causes
|
|
|
|
+ // issues with layout of dialogs containing Chrome browsers.
|
|
|
|
+ if (host_view->GetRootWindow() == widget_view->GetRootWindow()) {
|
|
|
|
+ views::Widget::ReparentNativeView(widget_view, host_view);
|
|
|
|
+ }
|
|
|
|
+#else
|
|
|
|
+ views::Widget::ReparentNativeView(widget->GetNativeView(), host_view);
|
|
|
|
+#endif
|
2022-06-02 11:49:50 +02:00
|
|
|
+ }
|
|
|
|
}
|
|
|
|
|
|
|
|
OnPositionRequiresUpdate();
|
|
|
|
diff --git components/web_modal/modal_dialog_host.h components/web_modal/modal_dialog_host.h
|
2023-10-19 20:08:48 +02:00
|
|
|
index 51ed6bcf6b540..c6e1161140655 100644
|
2022-06-02 11:49:50 +02:00
|
|
|
--- components/web_modal/modal_dialog_host.h
|
|
|
|
+++ components/web_modal/modal_dialog_host.h
|
|
|
|
@@ -34,6 +34,10 @@ class WEB_MODAL_EXPORT ModalDialogHost {
|
|
|
|
|
|
|
|
// Returns the view against which the dialog is positioned and parented.
|
|
|
|
virtual gfx::NativeView GetHostView() const = 0;
|
|
|
|
+ // Returns the widget against which the dialog is positioned and parented.
|
|
|
|
+ // Used with CEF windowless rendering.
|
2023-09-15 21:51:43 +02:00
|
|
|
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() const {
|
2022-06-02 11:49:50 +02:00
|
|
|
+ return gfx::kNullAcceleratedWidget; }
|
|
|
|
// Gets the position for the dialog in coordinates relative to the host view.
|
|
|
|
virtual gfx::Point GetDialogPosition(const gfx::Size& size) = 0;
|
|
|
|
// Returns whether a dialog currently about to be shown should be activated.
|
|
|
|
diff --git ui/views/window/dialog_delegate.cc ui/views/window/dialog_delegate.cc
|
2023-11-21 20:17:55 +01:00
|
|
|
index 89942cb82dee4..ce30f3bb93fc0 100644
|
2022-06-02 11:49:50 +02:00
|
|
|
--- ui/views/window/dialog_delegate.cc
|
|
|
|
+++ ui/views/window/dialog_delegate.cc
|
2023-11-21 20:17:55 +01:00
|
|
|
@@ -60,10 +60,12 @@ DialogDelegate::DialogDelegate() {
|
2022-06-02 11:49:50 +02:00
|
|
|
// static
|
|
|
|
Widget* DialogDelegate::CreateDialogWidget(WidgetDelegate* delegate,
|
|
|
|
gfx::NativeWindow context,
|
|
|
|
- gfx::NativeView parent) {
|
|
|
|
+ gfx::NativeView parent,
|
|
|
|
+ gfx::AcceleratedWidget parent_widget) {
|
|
|
|
views::Widget* widget = new views::Widget;
|
|
|
|
views::Widget::InitParams params =
|
|
|
|
- GetDialogWidgetInitParams(delegate, context, parent, gfx::Rect());
|
|
|
|
+ GetDialogWidgetInitParams(delegate, context, parent, gfx::Rect(),
|
|
|
|
+ parent_widget);
|
|
|
|
widget->Init(std::move(params));
|
|
|
|
return widget;
|
|
|
|
}
|
2023-11-21 20:17:55 +01:00
|
|
|
@@ -72,17 +74,19 @@ Widget* DialogDelegate::CreateDialogWidget(WidgetDelegate* delegate,
|
2022-06-02 11:49:50 +02:00
|
|
|
Widget* DialogDelegate::CreateDialogWidget(
|
|
|
|
std::unique_ptr<WidgetDelegate> delegate,
|
|
|
|
gfx::NativeWindow context,
|
|
|
|
- gfx::NativeView parent) {
|
|
|
|
+ gfx::NativeView parent,
|
|
|
|
+ gfx::AcceleratedWidget parent_widget) {
|
|
|
|
DCHECK(delegate->owned_by_widget());
|
|
|
|
- return CreateDialogWidget(delegate.release(), context, parent);
|
|
|
|
+ return CreateDialogWidget(delegate.release(), context, parent, parent_widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
-bool DialogDelegate::CanSupportCustomFrame(gfx::NativeView parent) {
|
|
|
|
+bool DialogDelegate::CanSupportCustomFrame(gfx::NativeView parent,
|
|
|
|
+ gfx::AcceleratedWidget parent_widget) {
|
|
|
|
#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \
|
|
|
|
BUILDFLAG(ENABLE_DESKTOP_AURA)
|
|
|
|
// The new style doesn't support unparented dialogs on Linux desktop.
|
|
|
|
- return parent != nullptr;
|
|
|
|
+ return parent != nullptr || parent_widget != gfx::kNullAcceleratedWidget;
|
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif
|
2023-11-21 20:17:55 +01:00
|
|
|
@@ -93,14 +97,15 @@ Widget::InitParams DialogDelegate::GetDialogWidgetInitParams(
|
2022-06-02 11:49:50 +02:00
|
|
|
WidgetDelegate* delegate,
|
|
|
|
gfx::NativeWindow context,
|
|
|
|
gfx::NativeView parent,
|
|
|
|
- const gfx::Rect& bounds) {
|
|
|
|
+ const gfx::Rect& bounds,
|
|
|
|
+ gfx::AcceleratedWidget parent_widget) {
|
|
|
|
views::Widget::InitParams params;
|
|
|
|
params.delegate = delegate;
|
|
|
|
params.bounds = bounds;
|
|
|
|
DialogDelegate* dialog = delegate->AsDialogDelegate();
|
|
|
|
|
|
|
|
if (dialog)
|
|
|
|
- dialog->params_.custom_frame &= CanSupportCustomFrame(parent);
|
|
|
|
+ dialog->params_.custom_frame &= CanSupportCustomFrame(parent, parent_widget);
|
|
|
|
|
|
|
|
if (!dialog || dialog->use_custom_frame()) {
|
|
|
|
params.opacity = Widget::InitParams::WindowOpacity::kTranslucent;
|
2023-11-21 20:17:55 +01:00
|
|
|
@@ -113,6 +118,7 @@ Widget::InitParams DialogDelegate::GetDialogWidgetInitParams(
|
2022-06-02 11:49:50 +02:00
|
|
|
}
|
|
|
|
params.context = context;
|
|
|
|
params.parent = parent;
|
|
|
|
+ params.parent_widget = parent_widget;
|
|
|
|
#if !BUILDFLAG(IS_APPLE)
|
|
|
|
// Web-modal (ui::MODAL_TYPE_CHILD) dialogs with parents are marked as child
|
|
|
|
// widgets to prevent top-level window behavior (independent movement, etc).
|
|
|
|
diff --git ui/views/window/dialog_delegate.h ui/views/window/dialog_delegate.h
|
2023-09-15 21:51:43 +02:00
|
|
|
index 083874eb3f0bc..2ccacfca7d413 100644
|
2022-06-02 11:49:50 +02:00
|
|
|
--- ui/views/window/dialog_delegate.h
|
|
|
|
+++ ui/views/window/dialog_delegate.h
|
2023-09-15 21:51:43 +02:00
|
|
|
@@ -96,13 +96,18 @@ class VIEWS_EXPORT DialogDelegate : public WidgetDelegate {
|
2022-06-02 11:49:50 +02:00
|
|
|
// your use case.
|
|
|
|
static Widget* CreateDialogWidget(std::unique_ptr<WidgetDelegate> delegate,
|
|
|
|
gfx::NativeWindow context,
|
|
|
|
- gfx::NativeView parent);
|
|
|
|
+ gfx::NativeView parent,
|
|
|
|
+ gfx::AcceleratedWidget parent_widget =
|
|
|
|
+ gfx::kNullAcceleratedWidget);
|
|
|
|
static Widget* CreateDialogWidget(WidgetDelegate* delegate,
|
|
|
|
gfx::NativeWindow context,
|
|
|
|
- gfx::NativeView parent);
|
|
|
|
+ gfx::NativeView parent,
|
|
|
|
+ gfx::AcceleratedWidget parent_widget =
|
|
|
|
+ gfx::kNullAcceleratedWidget);
|
|
|
|
|
|
|
|
// Whether using custom dialog frame is supported for this dialog.
|
|
|
|
- static bool CanSupportCustomFrame(gfx::NativeView parent);
|
|
|
|
+ static bool CanSupportCustomFrame(gfx::NativeView parent,
|
|
|
|
+ gfx::AcceleratedWidget parent_widget);
|
|
|
|
|
|
|
|
// Returns the dialog widget InitParams for a given |context| or |parent|.
|
|
|
|
// If |bounds| is not empty, used to initially place the dialog, otherwise
|
2023-09-15 21:51:43 +02:00
|
|
|
@@ -110,7 +115,9 @@ class VIEWS_EXPORT DialogDelegate : public WidgetDelegate {
|
2022-06-02 11:49:50 +02:00
|
|
|
static Widget::InitParams GetDialogWidgetInitParams(WidgetDelegate* delegate,
|
|
|
|
gfx::NativeWindow context,
|
|
|
|
gfx::NativeView parent,
|
|
|
|
- const gfx::Rect& bounds);
|
|
|
|
+ const gfx::Rect& bounds,
|
|
|
|
+ gfx::AcceleratedWidget parent_widget =
|
|
|
|
+ gfx::kNullAcceleratedWidget);
|
|
|
|
|
|
|
|
// Returns a mask specifying which of the available DialogButtons are visible
|
|
|
|
// for the dialog.
|