1diff --git content/browser/renderer_host/render_widget_host_view_base.cc content/browser/renderer_host/render_widget_host_view_base.cc 2index 1eb2b692c59d3..e48e4618bbc7b 100644 3--- content/browser/renderer_host/render_widget_host_view_base.cc 4+++ content/browser/renderer_host/render_widget_host_view_base.cc 5@@ -606,6 +606,14 @@ float RenderWidgetHostViewBase::GetDeviceScaleFactor() const { 6 return screen_infos_.current().device_scale_factor; 7 } 8 9+void RenderWidgetHostViewBase::SetHasExternalParent(bool val) { 10+ has_external_parent_ = val; 11+} 12+ 13+bool RenderWidgetHostViewBase::HasExternalParent() const { 14+ return has_external_parent_; 15+} 16+ 17 void RenderWidgetHostViewBase::OnAutoscrollStart() { 18 if (!GetMouseWheelPhaseHandler()) 19 return; 20diff --git content/browser/renderer_host/render_widget_host_view_base.h content/browser/renderer_host/render_widget_host_view_base.h 21index 0c21c3b6e2a4b..bf50bce147881 100644 22--- content/browser/renderer_host/render_widget_host_view_base.h 23+++ content/browser/renderer_host/render_widget_host_view_base.h 24@@ -67,6 +67,7 @@ class CursorManager; 25 class MouseWheelPhaseHandler; 26 class RenderWidgetHostImpl; 27 class RenderWidgetHostViewBaseObserver; 28+class RenderWidgetHostViewGuest; 29 class SyntheticGestureTarget; 30 class TextInputManager; 31 class TouchSelectionControllerClientManager; 32@@ -132,6 +133,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView { 33 const gfx::Size& max_size) override; 34 void DisableAutoResize(const gfx::Size& new_size) override; 35 float GetDeviceScaleFactor() const final; 36+ void SetHasExternalParent(bool val) override; 37+ bool HasExternalParent() const override; 38 TouchSelectionControllerClientManager* 39 GetTouchSelectionControllerClientManager() override; 40 bool ShouldVirtualKeyboardOverlayContent() override; 41@@ -168,6 +171,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView { 42 // Called when screen information or native widget bounds change. 43 virtual void UpdateScreenInfo(); 44 45+ // Generates the most current set of ScreenInfos from the current set of 46+ // displays in the system for use in UpdateScreenInfo. 47+ virtual display::ScreenInfos GetNewScreenInfosForUpdate(); 48+ 49 // Called by the TextInputManager to notify the view about being removed from 50 // the list of registered views, i.e., TextInputManager is no longer tracking 51 // TextInputState from this view. The RWHV should reset |text_input_manager_| 52@@ -407,6 +414,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView { 53 const gfx::Rect& bounds, 54 const gfx::Rect& anchor_rect) = 0; 55 56+ // Perform all the initialization steps necessary for this object to represent 57+ // the platform widget owned by |guest_view| and embedded in 58+ // |parent_host_view|. 59+ virtual void InitAsGuest(RenderWidgetHostView* parent_host_view, 60+ RenderWidgetHostViewGuest* guest_view) {} 61+ 62 // Sets the cursor for this view to the one associated with the specified 63 // cursor_type. 64 virtual void UpdateCursor(const WebCursor& cursor) = 0; 65@@ -638,6 +651,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView { 66 67 raw_ptr<TooltipObserver> tooltip_observer_for_testing_ = nullptr; 68 69+ // True if the widget has a external parent view/window outside of the 70+ // Chromium-controlled view/window hierarchy. 71+ bool has_external_parent_ = false; 72+ 73 private: 74 FRIEND_TEST_ALL_PREFIXES( 75 BrowserSideFlingBrowserTest, 76@@ -659,10 +676,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView { 77 78 void SynchronizeVisualProperties(); 79 80- // Generates the most current set of ScreenInfos from the current set of 81- // displays in the system for use in UpdateScreenInfo. 82- display::ScreenInfos GetNewScreenInfosForUpdate(); 83- 84 // Called when display properties that need to be synchronized with the 85 // renderer process changes. This method is called before notifying 86 // RenderWidgetHostImpl in order to allow the view to allocate a new 87diff --git content/browser/renderer_host/render_widget_host_view_event_handler.cc content/browser/renderer_host/render_widget_host_view_event_handler.cc 88index 855e5ff668236..2bf32cabf159b 100644 89--- content/browser/renderer_host/render_widget_host_view_event_handler.cc 90+++ content/browser/renderer_host/render_widget_host_view_event_handler.cc 91@@ -52,6 +52,10 @@ namespace { 92 // of the border area, in percentage of the corresponding dimension. 93 const int kMouseLockBorderPercentage = 15; 94 95+#if BUILDFLAG(IS_LINUX) 96+#include "ui/aura/window_tree_host.h" 97+#endif 98+ 99 #if BUILDFLAG(IS_WIN) 100 // A callback function for EnumThreadWindows to enumerate and dismiss 101 // any owned popup windows. 102@@ -834,6 +838,14 @@ void RenderWidgetHostViewEventHandler::MoveCursorToCenter( 103 } 104 return; 105 } 106+#endif 107+#if BUILDFLAG(IS_LINUX) 108+ if (host_view_->HasExternalParent() && 109+ window_ && window_->delegate()->CanFocus()) { 110+ aura::WindowTreeHost* host = window_->GetHost(); 111+ if (host) 112+ host->Show(); 113+ } 114 #endif 115 synthetic_move_position_ = center_in_screen; 116 } 117@@ -863,6 +875,17 @@ bool RenderWidgetHostViewEventHandler::MatchesSynthesizedMovePosition( 118 } 119 120 void RenderWidgetHostViewEventHandler::SetKeyboardFocus() { 121+#if BUILDFLAG(IS_WIN) 122+ if (host_view_->HasExternalParent() && 123+ window_ && window_->delegate()->CanFocus()) { 124+ aura::WindowTreeHost* host = window_->GetHost(); 125+ if (host) { 126+ gfx::AcceleratedWidget hwnd = host->GetAcceleratedWidget(); 127+ if (!(::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE)) 128+ ::SetFocus(hwnd); 129+ } 130+ } 131+#endif 132 // TODO(wjmaclean): can host_ ever be null? 133 if (host_ && set_focus_on_mouse_down_or_key_event_) { 134 set_focus_on_mouse_down_or_key_event_ = false; 135diff --git content/public/browser/render_widget_host_view.h content/public/browser/render_widget_host_view.h 136index d213587450f06..3fde9a9ce47d5 100644 137--- content/public/browser/render_widget_host_view.h 138+++ content/public/browser/render_widget_host_view.h 139@@ -253,6 +253,14 @@ class CONTENT_EXPORT RenderWidgetHostView { 140 // This must always return the same device scale factor as GetScreenInfo. 141 virtual float GetDeviceScaleFactor() const = 0; 142 143+ // Set whether the widget has a external parent view/window outside of the 144+ // Chromium-controlled view/window hierarchy. 145+ virtual void SetHasExternalParent(bool val) = 0; 146+ 147+ // Returns true if the widget has a external parent view/window outside of the 148+ // Chromium-controlled view/window hierarchy. 149+ virtual bool HasExternalParent() const = 0; 150+ 151 #if BUILDFLAG(IS_MAC) 152 // Set the view's active state (i.e., tint state of controls). 153 virtual void SetActive(bool active) = 0; 154diff --git ui/platform_window/x11/x11_window.cc ui/platform_window/x11/x11_window.cc 155index 549190ed1823a..8532cf8511570 100644 156--- ui/platform_window/x11/x11_window.cc 157+++ ui/platform_window/x11/x11_window.cc 158@@ -1710,7 +1710,8 @@ void X11Window::CreateXWindow(const PlatformWindowInitProperties& properties) { 159 req.border_pixel = 0; 160 161 bounds_in_pixels_ = SanitizeBounds(bounds); 162- req.parent = x_root_window_; 163+ req.parent = properties.parent_widget == gfx::kNullAcceleratedWidget ? 164+ x_root_window_ : static_cast<x11::Window>(properties.parent_widget); 165 req.x = bounds_in_pixels_.x(); 166 req.y = bounds_in_pixels_.y(); 167 req.width = bounds_in_pixels_.width(); 168diff --git ui/views/widget/desktop_aura/desktop_screen_win.cc ui/views/widget/desktop_aura/desktop_screen_win.cc 169index 7c352dd0d992d..516623a91b0e1 100644 170--- ui/views/widget/desktop_aura/desktop_screen_win.cc 171+++ ui/views/widget/desktop_aura/desktop_screen_win.cc 172@@ -20,6 +20,8 @@ DesktopScreenWin::~DesktopScreenWin() { 173 } 174 175 HWND DesktopScreenWin::GetHWNDFromNativeWindow(gfx::NativeWindow window) const { 176+ if (!window) 177+ return nullptr; 178 aura::WindowTreeHost* host = window->GetHost(); 179 return host ? host->GetAcceleratedWidget() : nullptr; 180 } 181diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc 182index a41611a5d66a2..e39a12c85686d 100644 183--- ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc 184+++ ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc 185@@ -231,6 +231,18 @@ Widget::MoveLoopResult DesktopWindowTreeHostLinux::RunMoveLoop( 186 escape_behavior); 187 } 188 189+gfx::Rect DesktopWindowTreeHostLinux::GetWindowBoundsInScreen() const { 190+ if (!screen_bounds_.IsEmpty()) 191+ return screen_bounds_; 192+ return DesktopWindowTreeHostPlatform::GetWindowBoundsInScreen(); 193+} 194+ 195+gfx::Point DesktopWindowTreeHostLinux::GetLocationOnScreenInPixels() const { 196+ if (!screen_bounds_.IsEmpty()) 197+ return screen_bounds_.origin(); 198+ return DesktopWindowTreeHostPlatform::GetLocationOnScreenInPixels(); 199+} 200+ 201 void DesktopWindowTreeHostLinux::DispatchEvent(ui::Event* event) { 202 // In Windows, the native events sent to chrome are separated into client 203 // and non-client versions of events, which we record on our LocatedEvent 204@@ -372,6 +384,8 @@ void DesktopWindowTreeHostLinux::AddAdditionalInitProperties( 205 206 properties->wayland_app_id = params.wayland_app_id; 207 208+ properties->parent_widget = params.parent_widget; 209+ 210 DCHECK(!properties->x11_extension_delegate); 211 properties->x11_extension_delegate = this; 212 } 213diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h 214index e9a126e30da2a..e2d068ba5f592 100644 215--- ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h 216+++ ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h 217@@ -86,6 +86,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux 218 ui::PinnedModeExtension* GetPinnedModeExtension(); 219 const ui::PinnedModeExtension* GetPinnedModeExtension() const; 220 221+ void set_screen_bounds(const gfx::Rect& bounds) { screen_bounds_ = bounds; } 222+ 223 protected: 224 // Overridden from DesktopWindowTreeHost: 225 void Init(const Widget::InitParams& params) override; 226@@ -95,6 +97,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux 227 const gfx::Vector2d& drag_offset, 228 Widget::MoveLoopSource source, 229 Widget::MoveLoopEscapeBehavior escape_behavior) override; 230+ gfx::Rect GetWindowBoundsInScreen() const override; 231+ gfx::Point GetLocationOnScreenInPixels() const override; 232 233 // PlatformWindowDelegate: 234 void DispatchEvent(ui::Event* event) override; 235@@ -152,6 +156,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux 236 // destroyed. 237 static std::list<gfx::AcceleratedWidget>* open_windows_; 238 239+ // Override the screen bounds when the host is a child window. 240+ gfx::Rect screen_bounds_; 241+ 242 // The display and the native X window hosting the root window. 243 base::WeakPtrFactory<DesktopWindowTreeHostLinux> weak_factory_{this}; 244 }; 245diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc 246index 1c9525d4d4302..f6e54a3362848 100644 247--- ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc 248+++ ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc 249@@ -217,8 +217,8 @@ void DesktopWindowTreeHostPlatform::Init(const Widget::InitParams& params) { 250 if (properties.parent_widget) { 251 window_parent_ = DesktopWindowTreeHostPlatform::GetHostForWidget( 252 properties.parent_widget); 253- DCHECK(window_parent_); 254- window_parent_->window_children_.insert(this); 255+ if (window_parent_) 256+ window_parent_->window_children_.insert(this); 257 } 258 259 // Calculate initial bounds. 260diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc 261index 7323cb11296e9..7876f7d208bd1 100644 262--- ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc 263+++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc 264@@ -180,8 +180,12 @@ void DesktopWindowTreeHostWin::Init(const Widget::InitParams& params) { 265 native_widget_delegate_); 266 267 HWND parent_hwnd = nullptr; 268- if (params.parent && params.parent->GetHost()) 269+ if (params.parent_widget) { 270+ parent_hwnd = params.parent_widget; 271+ has_external_parent_ = true; 272+ } else if (params.parent && params.parent->GetHost()) { 273 parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget(); 274+ } 275 276 remove_standard_frame_ = params.remove_standard_frame; 277 has_non_client_view_ = Widget::RequiresNonClientView(params.type); 278@@ -988,11 +992,15 @@ void DesktopWindowTreeHostWin::HandleFrameChanged() { 279 } 280 281 void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) { 282- // TODO(beng): inform the native_widget_delegate_. 283+ // See comments in CefBrowserHostImpl::PlatformSetFocus. 284+ if (has_external_parent_ && CanActivate()) 285+ HandleActivationChanged(true); 286 } 287 288 void DesktopWindowTreeHostWin::HandleNativeBlur(HWND focused_window) { 289- // TODO(beng): inform the native_widget_delegate_. 290+ // See comments in CefBrowserHostImpl::PlatformSetFocus. 291+ if (has_external_parent_ && CanActivate()) 292+ HandleActivationChanged(false); 293 } 294 295 bool DesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) { 296diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_win.h ui/views/widget/desktop_aura/desktop_window_tree_host_win.h 297index 7511694b58e56..eb7d82b4d520e 100644 298--- ui/views/widget/desktop_aura/desktop_window_tree_host_win.h 299+++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.h 300@@ -322,6 +322,10 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin 301 // True if the window should have the frame removed. 302 bool remove_standard_frame_; 303 304+ // True if the widget has a external parent view/window outside of the 305+ // Chromium-controlled view/window hierarchy. 306+ bool has_external_parent_ = false; 307+ 308 // Owned by TooltipController, but we need to forward events to it so we keep 309 // a reference. 310 raw_ptr<corewm::TooltipWin> tooltip_; 311diff --git ui/views/widget/widget.cc ui/views/widget/widget.cc 312index 0e20d424e46c5..8d394e3e2f10a 100644 313--- ui/views/widget/widget.cc 314+++ ui/views/widget/widget.cc 315@@ -341,7 +341,8 @@ void Widget::Init(InitParams params) { 316 } 317 318 params.child |= (params.type == InitParams::TYPE_CONTROL); 319- is_top_level_ = !params.child; 320+ is_top_level_ = !params.child || 321+ params.parent_widget != gfx::kNullAcceleratedWidget; 322 323 if (params.opacity == views::Widget::InitParams::WindowOpacity::kInferred && 324 params.type != views::Widget::InitParams::TYPE_WINDOW) { 325@@ -417,13 +418,21 @@ void Widget::Init(InitParams params) { 326 327 if (show_state == ui::SHOW_STATE_MAXIMIZED) { 328 Maximize(); 329+ saved_show_state_ = ui::SHOW_STATE_MAXIMIZED; 330 } else if (show_state == ui::SHOW_STATE_MINIMIZED) { 331 Minimize(); 332 saved_show_state_ = ui::SHOW_STATE_MINIMIZED; 333+ } else if (show_state == ui::SHOW_STATE_FULLSCREEN) { 334+ SetFullscreen(true); 335 } 336 } else if (delegate) { 337 SetContentsView(delegate->TransferOwnershipOfContentsView()); 338- SetInitialBoundsForFramelessWindow(bounds); 339+ if (params.parent_widget != gfx::kNullAcceleratedWidget) { 340+ // Set the bounds directly instead of applying an inset. 341+ SetBounds(bounds); 342+ } else { 343+ SetInitialBoundsForFramelessWindow(bounds); 344+ } 345 } 346 347 native_theme_observation_.Observe(GetNativeTheme()); 348@@ -1407,10 +1416,16 @@ void Widget::OnNativeWidgetParentChanged(gfx::NativeView parent) { 349 } 350 351 gfx::Size Widget::GetMinimumSize() const { 352+ gfx::Size size; 353+ if (widget_delegate_->MaybeGetMinimumSize(&size)) 354+ return size; 355 return non_client_view_ ? non_client_view_->GetMinimumSize() : gfx::Size(); 356 } 357 358 gfx::Size Widget::GetMaximumSize() const { 359+ gfx::Size size; 360+ if (widget_delegate_->MaybeGetMaximumSize(&size)) 361+ return size; 362 return non_client_view_ ? non_client_view_->GetMaximumSize() : gfx::Size(); 363 } 364 365diff --git ui/views/widget/widget.h ui/views/widget/widget.h 366index 0bcdee12f8539..200e0a1b0770b 100644 367--- ui/views/widget/widget.h 368+++ ui/views/widget/widget.h 369@@ -329,6 +329,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, 370 // the concept with bubble anchoring a la BubbleDialogDelegateView. 371 gfx::NativeView parent = nullptr; 372 373+ gfx::AcceleratedWidget parent_widget = gfx::kNullAcceleratedWidget; 374+ 375 // Specifies the initial bounds of the Widget. Default is empty, which means 376 // the NativeWidget may specify a default size. If the parent is specified, 377 // |bounds| is in the parent's coordinate system. If the parent is not 378diff --git ui/views/widget/widget_delegate.h ui/views/widget/widget_delegate.h 379index 3375d6c362923..24f36f6e5587a 100644 380--- ui/views/widget/widget_delegate.h 381+++ ui/views/widget/widget_delegate.h 382@@ -381,6 +381,10 @@ class VIEWS_EXPORT WidgetDelegate { 383 // Returns true if the title text should be centered. 384 bool ShouldCenterWindowTitleText() const; 385 386+ // CEF supports override of min/max size values. 387+ virtual bool MaybeGetMinimumSize(gfx::Size* size) const { return false; } 388+ virtual bool MaybeGetMaximumSize(gfx::Size* size) const { return false; } 389+ 390 bool focus_traverses_out() const { return params_.focus_traverses_out; } 391 bool enable_arrow_key_traversal() const { 392 return params_.enable_arrow_key_traversal; 393diff --git ui/views/widget/widget_hwnd_utils.cc ui/views/widget/widget_hwnd_utils.cc 394index b10784dce1f69..4a6acf542dece 100644 395--- ui/views/widget/widget_hwnd_utils.cc 396+++ ui/views/widget/widget_hwnd_utils.cc 397@@ -67,7 +67,7 @@ void CalculateWindowStylesFromInitParams( 398 if (!widget_delegate->CanResize()) 399 *style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX); 400 if (params.remove_standard_frame) 401- *style &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX); 402+ *style &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU); 403 404 if (native_widget_delegate->IsDialogBox()) { 405 *style |= DS_MODALFRAME; 406diff --git ui/views/win/hwnd_message_handler.cc ui/views/win/hwnd_message_handler.cc 407index 302915bac66a4..0bbed4079bfaf 100644 408--- ui/views/win/hwnd_message_handler.cc 409+++ ui/views/win/hwnd_message_handler.cc 410@@ -3126,10 +3126,13 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message, 411 } else if (event.type() == ui::ET_MOUSEWHEEL) { 412 ui::MouseWheelEvent mouse_wheel_event(msg); 413 // Reroute the mouse wheel to the window under the pointer if applicable. 414- return (ui::RerouteMouseWheel(hwnd(), w_param, l_param) || 415- delegate_->HandleMouseEvent(&mouse_wheel_event)) 416- ? 0 417- : 1; 418+ if (ui::RerouteMouseWheel(hwnd(), w_param, l_param) || 419+ delegate_->HandleMouseEvent(&mouse_wheel_event)) { 420+ SetMsgHandled(TRUE); 421+ return 0; 422+ } else { 423+ return 1; 424+ } 425 } 426 427 // Suppress |ET_MOUSE_MOVED| and |ET_MOUSE_DRAGGED| events from WM_MOUSE* 428