diff --git content/browser/renderer_host/render_widget_host_view_aura.cc content/browser/renderer_host/render_widget_host_view_aura.cc index 852e71f..b765a5b 100644 --- content/browser/renderer_host/render_widget_host_view_aura.cc +++ content/browser/renderer_host/render_widget_host_view_aura.cc @@ -769,6 +769,13 @@ void RenderWidgetHostViewAura::SetKeyboardFocus() { } } #endif +#if defined(OS_LINUX) + if (has_external_parent_ && CanFocus()) { + aura::WindowTreeHost* host = window_->GetHost(); + if (host) + host->Show(); + } +#endif // TODO(wjmaclean): can host_ ever be null? if (host_ && set_focus_on_mouse_down_or_key_event_) { set_focus_on_mouse_down_or_key_event_ = false; diff --git content/browser/renderer_host/render_widget_host_view_base.cc content/browser/renderer_host/render_widget_host_view_base.cc index 292087d..8d6da47 100644 --- content/browser/renderer_host/render_widget_host_view_base.cc +++ content/browser/renderer_host/render_widget_host_view_base.cc @@ -44,6 +44,7 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase() current_display_rotation_(display::Display::ROTATE_0), pinch_zoom_enabled_(content::IsPinchToZoomEnabled()), text_input_manager_(nullptr), + has_external_parent_(false), renderer_frame_number_(0), weak_factory_(this) { } @@ -324,6 +325,10 @@ void RenderWidgetHostViewBase::FocusedNodeTouched( DVLOG(1) << "FocusedNodeTouched: " << editable; } +void RenderWidgetHostViewBase::SetHasExternalParent(bool val) { + has_external_parent_ = val; +} + uint32_t RenderWidgetHostViewBase::RendererFrameNumber() { return renderer_frame_number_; } diff --git content/browser/renderer_host/render_widget_host_view_base.h content/browser/renderer_host/render_widget_host_view_base.h index 5e25a02..b81350b 100644 --- content/browser/renderer_host/render_widget_host_view_base.h +++ content/browser/renderer_host/render_widget_host_view_base.h @@ -107,6 +107,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView, void EndFrameSubscription() override; void FocusedNodeTouched(const gfx::Point& location_dips_screen, bool editable) override; + void SetHasExternalParent(bool val) override; // This only needs to be overridden by RenderWidgetHostViewBase subclasses // that handle content embedded within other RenderWidgetHostViews. @@ -477,6 +478,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView, // destroyed before the RWHV is destroyed. TextInputManager* text_input_manager_; + // True if the widget has a external parent view/window outside of the + // Chromium-controlled view/window hierarchy. + bool has_external_parent_; + private: void FlushInput(); diff --git content/public/browser/render_widget_host_view.h content/public/browser/render_widget_host_view.h index ff3127b..e666db1 100644 --- content/public/browser/render_widget_host_view.h +++ content/public/browser/render_widget_host_view.h @@ -172,6 +172,10 @@ class CONTENT_EXPORT RenderWidgetHostView { // when the value has changed. Views must initially default to false. virtual void SetNeedsBeginFrames(bool needs_begin_frames) = 0; + // Set whether the widget has a external parent view/window outside of the + // Chromium-controlled view/window hierarchy. + virtual void SetHasExternalParent(bool val) = 0; + #if defined(OS_MACOSX) // Return the accelerated widget which hosts the CALayers that draw the // content of the view in GetNativeView. This may be null. diff --git ui/views/widget/desktop_aura/desktop_screen_win.cc ui/views/widget/desktop_aura/desktop_screen_win.cc index f772f64..7d13f9f 100644 --- ui/views/widget/desktop_aura/desktop_screen_win.cc +++ ui/views/widget/desktop_aura/desktop_screen_win.cc @@ -32,6 +32,8 @@ display::Display DesktopScreenWin::GetDisplayMatching( } HWND DesktopScreenWin::GetHWNDFromNativeView(gfx::NativeView window) const { + if (!window) + return NULL; aura::WindowTreeHost* host = window->GetHost(); return host ? host->GetAcceleratedWidget() : NULL; } diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc index 964fe4a..b878661 100644 --- ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc +++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc @@ -86,6 +86,7 @@ DesktopWindowTreeHostWin::DesktopWindowTreeHostWin( should_animate_window_close_(false), pending_close_(false), has_non_client_view_(false), + has_external_parent_(false), tooltip_(NULL) { } @@ -136,8 +137,12 @@ void DesktopWindowTreeHostWin::Init(aura::Window* content_window, native_widget_delegate_); HWND parent_hwnd = NULL; - if (params.parent && params.parent->GetHost()) + if (params.parent_widget) { + parent_hwnd = params.parent_widget; + has_external_parent_ = true; + } else if (params.parent && params.parent->GetHost()) { parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget(); + } remove_standard_frame_ = params.remove_standard_frame; has_non_client_view_ = Widget::RequiresNonClientView(params.type); @@ -645,6 +650,10 @@ bool DesktopWindowTreeHostWin::CanActivate() const { return native_widget_delegate_->CanActivate(); } +bool DesktopWindowTreeHostWin::RemoveCaption() const { + return GetWidget()->remove_caption(); +} + bool DesktopWindowTreeHostWin::WantsMouseEventsWhenInactive() const { return wants_mouse_events_when_inactive_; } @@ -825,11 +834,15 @@ void DesktopWindowTreeHostWin::HandleFrameChanged() { } void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) { - // TODO(beng): inform the native_widget_delegate_. + // See comments in CefBrowserHostImpl::PlatformSetFocus. + if (has_external_parent_ && CanActivate()) + HandleActivationChanged(true); } void DesktopWindowTreeHostWin::HandleNativeBlur(HWND focused_window) { - // TODO(beng): inform the native_widget_delegate_. + // See comments in CefBrowserHostImpl::PlatformSetFocus. + if (has_external_parent_ && CanActivate()) + HandleActivationChanged(false); } bool DesktopWindowTreeHostWin::HandleMouseEvent(const ui::MouseEvent& event) { diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_win.h ui/views/widget/desktop_aura/desktop_window_tree_host_win.h index 884df90..518a69c 100644 --- ui/views/widget/desktop_aura/desktop_window_tree_host_win.h +++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.h @@ -138,6 +138,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin bool CanMaximize() const override; bool CanMinimize() const override; bool CanActivate() const override; + bool RemoveCaption() const override; bool WantsMouseEventsWhenInactive() const override; bool WidgetSizeIsClientSize() const override; bool IsModal() const override; @@ -252,6 +253,10 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin // True if the window should have the frame removed. bool remove_standard_frame_; + // True if the widget has a external parent view/window outside of the + // Chromium-controlled view/window hierarchy. + bool has_external_parent_; + // Owned by TooltipController, but we need to forward events to it so we keep // a reference. corewm::TooltipWin* tooltip_; diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index 816faa3..4c2d702 100644 --- ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc @@ -195,6 +195,7 @@ DesktopWindowTreeHostX11::DesktopWindowTreeHostX11( use_native_frame_(false), should_maximize_after_map_(false), use_argb_visual_(false), + has_external_parent_(false), drag_drop_client_(NULL), native_widget_delegate_(native_widget_delegate), desktop_native_widget_aura_(desktop_native_widget_aura), @@ -208,6 +209,7 @@ DesktopWindowTreeHostX11::DesktopWindowTreeHostX11( has_window_focus_(false), has_pointer_focus_(false), modal_dialog_xid_(0), + xwindow_destroyed_(false), close_widget_factory_(this), weak_factory_(this) {} @@ -545,7 +547,8 @@ void DesktopWindowTreeHostX11::CloseNow() { // Actually free our native resources. if (ui::PlatformEventSource::GetInstance()) ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); - XDestroyWindow(xdisplay_, xwindow_); + if (!xwindow_destroyed_) + XDestroyWindow(xdisplay_, xwindow_); xwindow_ = None; desktop_native_widget_aura_->OnHostClosed(); @@ -686,6 +689,8 @@ void DesktopWindowTreeHostX11::GetWindowPlacement( } gfx::Rect DesktopWindowTreeHostX11::GetWindowBoundsInScreen() const { + if (!screen_bounds_.IsEmpty()) + return screen_bounds_; return ToDIPRect(bounds_in_pixels_); } @@ -1208,6 +1213,8 @@ void DesktopWindowTreeHostX11::HideImpl() { } gfx::Rect DesktopWindowTreeHostX11::GetBounds() const { + if (!screen_bounds_.IsEmpty()) + return screen_bounds_; return bounds_in_pixels_; } @@ -1267,6 +1274,8 @@ void DesktopWindowTreeHostX11::SetBounds( } gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const { + if (!screen_bounds_.IsEmpty()) + return screen_bounds_.origin(); return bounds_in_pixels_.origin(); } @@ -1390,9 +1399,15 @@ void DesktopWindowTreeHostX11::InitX11Window( attribute_mask |= CWBorderPixel; swa.border_pixel = 0; + gfx::AcceleratedWidget parent_widget = params.parent_widget; + if (parent_widget == gfx::kNullAcceleratedWidget) + parent_widget = x_root_window_; + else + has_external_parent_ = true; + bounds_in_pixels_ = ToPixelRect(params.bounds); bounds_in_pixels_.set_size(AdjustSize(bounds_in_pixels_.size())); - xwindow_ = XCreateWindow(xdisplay_, x_root_window_, bounds_in_pixels_.x(), + xwindow_ = XCreateWindow(xdisplay_, parent_widget, bounds_in_pixels_.x(), bounds_in_pixels_.y(), bounds_in_pixels_.width(), bounds_in_pixels_.height(), 0, // border width @@ -2022,6 +2037,10 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent( } break; } + case DestroyNotify: + xwindow_destroyed_ = true; + CloseNow(); + break; case FocusIn: case FocusOut: OnFocusEvent(xev->type == FocusIn, event->xfocus.mode, diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h index a4b68b3..bb82659 100644 --- ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h +++ ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h @@ -91,6 +91,12 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 // there is no dialog on the host window. XID GetModalDialog(); + void set_screen_bounds(const gfx::Rect& bounds) { screen_bounds_ = bounds; } + + // Returns true if the widget has a external parent view/window outside of the + // Chromium-controlled view/window hierarchy. + bool has_external_parent() const { return has_external_parent_; } + protected: // Overridden from DesktopWindowTreeHost: void Init(aura::Window* content_window, @@ -301,6 +307,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 // The bounds of |xwindow_|. gfx::Rect bounds_in_pixels_; + // Override the screen bounds when the host is a child window. + gfx::Rect screen_bounds_; + // Whenever the bounds are set, we keep the previous set of bounds around so // we can have a better chance of getting the real // |restored_bounds_in_pixels_|. Window managers tend to send a Configure @@ -340,6 +349,10 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 // Whether we used an ARGB visual for our window. bool use_argb_visual_; + // True if the widget has a external parent view/window outside of the + // Chromium-controlled view/window hierarchy. + bool has_external_parent_; + DesktopDragDropClientAuraX11* drag_drop_client_; std::unique_ptr x11_non_client_event_filter_; @@ -427,6 +440,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 XID modal_dialog_xid_; + // True if the xwindow has already been destroyed. + bool xwindow_destroyed_; + base::WeakPtrFactory close_widget_factory_; base::WeakPtrFactory weak_factory_; diff --git ui/views/widget/widget.cc ui/views/widget/widget.cc index 68e6acd..07eb1fc 100644 --- ui/views/widget/widget.cc +++ ui/views/widget/widget.cc @@ -126,9 +126,11 @@ Widget::InitParams::InitParams(Type type) mirror_origin_in_rtl(false), shadow_type(SHADOW_TYPE_DEFAULT), remove_standard_frame(false), + remove_caption(false), use_system_default_icon(false), show_state(ui::SHOW_STATE_DEFAULT), parent(nullptr), + parent_widget(gfx::kNullAcceleratedWidget), native_widget(nullptr), desktop_window_tree_host(nullptr), layer_type(ui::LAYER_TEXTURED), @@ -165,6 +167,7 @@ Widget::Widget() auto_release_capture_(true), root_layers_dirty_(false), movement_disabled_(false), + remove_caption_(false), observer_manager_(this) { } @@ -296,7 +299,8 @@ void Widget::Init(const InitParams& in_params) { params.name = params.delegate->GetContentsView()->GetClassName(); params.child |= (params.type == InitParams::TYPE_CONTROL); - is_top_level_ = !params.child; + is_top_level_ = !params.child || params.parent_widget; + remove_caption_ = params.remove_caption; if (params.opacity == views::Widget::InitParams::INFER_OPACITY && params.type != views::Widget::InitParams::TYPE_WINDOW && @@ -360,7 +364,12 @@ void Widget::Init(const InitParams& in_params) { } } else if (params.delegate) { SetContentsView(params.delegate->GetContentsView()); - SetInitialBoundsForFramelessWindow(params.bounds); + if (params.parent_widget) { + // Set the bounds directly instead of applying an inset. + SetBounds(params.bounds); + } else { + SetInitialBoundsForFramelessWindow(params.bounds); + } } // This must come after SetContentsView() or it might not be able to find // the correct NativeTheme (on Linux). See http://crbug.com/384492 diff --git ui/views/widget/widget.h ui/views/widget/widget.h index 1e62c09..551518e 100644 --- ui/views/widget/widget.h +++ ui/views/widget/widget.h @@ -234,12 +234,17 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // rendered, and that the client area should be equivalent to the window // area. Only used on some platforms (Windows and Linux). bool remove_standard_frame; + // Specifies that the system default caption and icon should not be + // rendered but the window may still have a resizable border. Only used on + // some platforms (Windows and Linux). + bool remove_caption; // Only used by ShellWindow on Windows. Specifies that the default icon of // packaged app should be the system default icon. bool use_system_default_icon; // Whether the widget should be maximized or minimized. ui::WindowShowState show_state; gfx::NativeView parent; + gfx::AcceleratedWidget parent_widget; // Used only by mus and is necessitated by mus not being a NativeView. ui::Window* parent_mus = nullptr; // Specifies the initial bounds of the Widget. Default is empty, which means @@ -753,6 +758,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, bool movement_disabled() const { return movement_disabled_; } void set_movement_disabled(bool disabled) { movement_disabled_ = disabled; } + // True if the system default caption and icon should not be rendered but the + // window may still have a resizable border. + bool remove_caption() const { return remove_caption_; } + // Returns the work area bounds of the screen the Widget belongs to. gfx::Rect GetWorkAreaBoundsInScreen() const; @@ -971,6 +980,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // disabled. bool movement_disabled_; + // True if the system default caption and icon should not be rendered but the + // window may still have a resizable border. + bool remove_caption_; + ScopedObserver observer_manager_; DISALLOW_COPY_AND_ASSIGN(Widget); diff --git ui/views/widget/widget_hwnd_utils.cc ui/views/widget/widget_hwnd_utils.cc index b843416..8b81a51 100644 --- ui/views/widget/widget_hwnd_utils.cc +++ ui/views/widget/widget_hwnd_utils.cc @@ -114,6 +114,11 @@ void CalculateWindowStylesFromInitParams( // See layered window comment above. if (*ex_style & WS_EX_COMPOSITED) *style &= ~(WS_THICKFRAME | WS_CAPTION); + + if (params.remove_caption) { + *style &= ~(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | + WS_THICKFRAME); + } break; } case Widget::InitParams::TYPE_CONTROL: diff --git ui/views/win/hwnd_message_handler.cc ui/views/win/hwnd_message_handler.cc index 020d0a1..4a613f7 100644 --- ui/views/win/hwnd_message_handler.cc +++ ui/views/win/hwnd_message_handler.cc @@ -850,6 +850,8 @@ void HWNDMessageHandler::SizeConstraintsChanged() { } else { style &= ~WS_MINIMIZEBOX; } + if (delegate_->RemoveCaption()) + style &= ~(WS_CAPTION | WS_SYSMENU | WS_THICKFRAME); SetWindowLong(hwnd(), GWL_STYLE, style); } @@ -2472,8 +2474,12 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message, active_mouse_tracking_flags_ = 0; } else if (event.type() == ui::ET_MOUSEWHEEL) { // Reroute the mouse wheel to the window under the pointer if applicable. - return (ui::RerouteMouseWheel(hwnd(), w_param, l_param) || - delegate_->HandleMouseEvent(ui::MouseWheelEvent(msg))) ? 0 : 1; + if (ui::RerouteMouseWheel(hwnd(), w_param, l_param) || + delegate_->HandleMouseEvent(ui::MouseWheelEvent(msg))) { + SetMsgHandled(TRUE); + return 0; + } + return 1; } // There are cases where the code handling the message destroys the window, diff --git ui/views/win/hwnd_message_handler_delegate.h ui/views/win/hwnd_message_handler_delegate.h index 14021805..c4843c8 100644 --- ui/views/win/hwnd_message_handler_delegate.h +++ ui/views/win/hwnd_message_handler_delegate.h @@ -59,6 +59,10 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate { virtual bool CanMinimize() const = 0; virtual bool CanActivate() const = 0; + // Returns true if the system default caption and icon should not be rendered + // but the window may still have a resizable border. + virtual bool RemoveCaption() const = 0; + // Returns true if the delegate wants mouse events when inactive and the // window is clicked and should not become activated. A return value of false // indicates the mouse events will be dropped.