diff --git content/browser/renderer_host/render_widget_host_view_aura.cc content/browser/renderer_host/render_widget_host_view_aura.cc index bbb79c9..bf9a924 100644 --- content/browser/renderer_host/render_widget_host_view_aura.cc +++ content/browser/renderer_host/render_widget_host_view_aura.cc @@ -758,6 +758,13 @@ void RenderWidgetHostViewAura::SetKeyboardFocus() { ::SetFocus(host->GetAcceleratedWidget()); } #endif +#if defined(OS_LINUX) + if (has_external_parent_ && CanFocus()) { + aura::WindowTreeHost* host = window_->GetHost(); + if (host) + host->Show(); + } +#endif if (host_ && set_focus_on_mouse_down_) { set_focus_on_mouse_down_ = false; host_->Focus(); diff --git content/browser/renderer_host/render_widget_host_view_base.cc content/browser/renderer_host/render_widget_host_view_base.cc index 1b40705..52599e5 100644 --- content/browser/renderer_host/render_widget_host_view_base.cc +++ content/browser/renderer_host/render_widget_host_view_base.cc @@ -374,6 +374,7 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase() current_device_scale_factor_(0), current_display_rotation_(gfx::Display::ROTATE_0), pinch_zoom_enabled_(content::IsPinchToZoomEnabled()), + has_external_parent_(false), renderer_frame_number_(0), weak_factory_(this) { } @@ -568,6 +569,10 @@ void RenderWidgetHostViewBase::EndFrameSubscription() { NOTREACHED(); } +void RenderWidgetHostViewBase::SetHasExternalParent(bool val) { + has_external_parent_ = val; +} + uint32 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 bf3b8e1..351c601 100644 --- content/browser/renderer_host/render_widget_host_view_base.h +++ content/browser/renderer_host/render_widget_host_view_base.h @@ -78,6 +78,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView, void BeginFrameSubscription( scoped_ptr subscriber) override; void EndFrameSubscription() override; + void SetHasExternalParent(bool val) override; // IPC::Listener implementation: bool OnMessageReceived(const IPC::Message& msg) override; @@ -414,6 +415,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView, // renderer. bool pinch_zoom_enabled_; + // 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 d503fa9..5a7ea6c 100644 --- content/public/browser/render_widget_host_view.h +++ content/public/browser/render_widget_host_view.h @@ -146,6 +146,10 @@ class CONTENT_EXPORT RenderWidgetHostView { // deleted after this call. virtual void EndFrameSubscription() = 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) // Set the view's active state (i.e., tint state of controls). virtual void SetActive(bool active) = 0; diff --git ui/views/widget/desktop_aura/desktop_screen_win.cc ui/views/widget/desktop_aura/desktop_screen_win.cc index a8e088c..838b6a0 100644 --- ui/views/widget/desktop_aura/desktop_screen_win.cc +++ ui/views/widget/desktop_aura/desktop_screen_win.cc @@ -32,6 +32,8 @@ gfx::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 48368f9..6a566ba 100644 --- ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc +++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc @@ -85,6 +85,7 @@ DesktopWindowTreeHostWin::DesktopWindowTreeHostWin( should_animate_window_close_(false), pending_close_(false), has_non_client_view_(false), + has_external_parent_(false), tooltip_(NULL) { } @@ -131,8 +132,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(); + } message_handler_->set_remove_standard_frame(params.remove_standard_frame); @@ -793,11 +798,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 363c019..97ada1d 100644 --- ui/views/widget/desktop_aura/desktop_window_tree_host_win.h +++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.h @@ -242,6 +242,10 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin // Init time, before the Widget has created the NonClientView. bool has_non_client_view_; + // 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 298c92b..393a5dc 100644 --- ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc @@ -165,6 +165,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), @@ -173,7 +174,8 @@ DesktopWindowTreeHostX11::DesktopWindowTreeHostX11( custom_window_shape_(false), urgency_hint_set_(false), activatable_(true), - close_widget_factory_(this) { + close_widget_factory_(this), + xwindow_destroyed_(false) { } DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() { @@ -384,7 +386,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(); @@ -533,6 +536,8 @@ void DesktopWindowTreeHostX11::GetWindowPlacement( } gfx::Rect DesktopWindowTreeHostX11::GetWindowBoundsInScreen() const { + if (!screen_bounds_.IsEmpty()) + return screen_bounds_; return ToDIPRect(bounds_in_pixels_); } @@ -970,6 +975,8 @@ void DesktopWindowTreeHostX11::HideImpl() { } gfx::Rect DesktopWindowTreeHostX11::GetBounds() const { + if (!screen_bounds_.IsEmpty()) + return screen_bounds_; return bounds_in_pixels_; } @@ -1027,6 +1034,8 @@ void DesktopWindowTreeHostX11::SetBounds( } gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const { + if (!screen_bounds_.IsEmpty()) + return screen_bounds_.origin(); return bounds_in_pixels_.origin(); } @@ -1140,9 +1149,15 @@ void DesktopWindowTreeHostX11::InitX11Window( } } + 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 @@ -1797,6 +1812,10 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent( } break; } + case DestroyNotify: + xwindow_destroyed_ = true; + CloseNow(); + break; case FocusOut: if (xev->xfocus.mode != NotifyGrab) { ReleaseCapture(); 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 09b5993..db1b2bc 100644 --- ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h +++ ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h @@ -85,6 +85,12 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 // internal list of open windows. static void CleanUpWindowList(void (*func)(aura::Window* window)); + 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, @@ -265,6 +271,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 @@ -301,6 +310,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_; scoped_ptr x11_non_client_event_filter_; @@ -353,6 +366,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 base::WeakPtrFactory close_widget_factory_; + // True if the xwindow has already been destroyed. + bool xwindow_destroyed_; + DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostX11); }; diff --git ui/views/widget/desktop_aura/x11_desktop_handler.cc ui/views/widget/desktop_aura/x11_desktop_handler.cc index 5ab84f9..c4095fa 100644 --- ui/views/widget/desktop_aura/x11_desktop_handler.cc +++ ui/views/widget/desktop_aura/x11_desktop_handler.cc @@ -31,6 +31,30 @@ views::X11DesktopHandler* g_handler = NULL; namespace views { +namespace { + +bool IsParentOfWindow(XDisplay* xdisplay, + ::Window potential_parent, + ::Window window) { + ::Window parent_win, root_win; + Window* child_windows; + unsigned int num_child_windows; + while (window) { + if (!XQueryTree(xdisplay, window, &root_win, &parent_win, + &child_windows, &num_child_windows)) { + break; + } + if(child_windows) + XFree(child_windows); + if (parent_win == potential_parent) + return true; + window = parent_win; + } + return false; +} + +} // namespace + // static X11DesktopHandler* X11DesktopHandler::get() { if (!g_handler) @@ -86,7 +110,11 @@ void X11DesktopHandler::ActivateWindow(::Window window) { // in an active X window. } - if (wm_supports_active_window_) { + DesktopWindowTreeHostX11* host = + DesktopWindowTreeHostX11::GetHostForXID(window); + const bool has_external_parent = host && host->has_external_parent(); + + if (wm_supports_active_window_ && !has_external_parent) { DCHECK_EQ(gfx::GetXDisplay(), xdisplay_); // If the window is not already active, send a hint to activate it @@ -175,8 +203,10 @@ uint32_t X11DesktopHandler::DispatchEvent(const ui::PlatformEvent& event) { ::Window window; if (ui::GetXIDProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &window) && window) { - x_active_window_ = window; - OnActiveWindowChanged(window, ACTIVE); + if (!IsParentOfWindow(xdisplay_, window, current_window_)) { + x_active_window_ = window; + OnActiveWindowChanged(window, ACTIVE); + } } else { x_active_window_ = None; } diff --git ui/views/widget/widget.cc ui/views/widget/widget.cc index 6c0168d..fbcfbfc 100644 --- ui/views/widget/widget.cc +++ ui/views/widget/widget.cc @@ -124,6 +124,7 @@ Widget::InitParams::InitParams() use_system_default_icon(false), show_state(ui::SHOW_STATE_DEFAULT), parent(NULL), + parent_widget(gfx::kNullAcceleratedWidget), native_widget(NULL), desktop_window_tree_host(NULL), layer_type(ui::LAYER_TEXTURED), @@ -148,6 +149,7 @@ Widget::InitParams::InitParams(Type type) use_system_default_icon(false), show_state(ui::SHOW_STATE_DEFAULT), parent(NULL), + parent_widget(gfx::kNullAcceleratedWidget), native_widget(NULL), desktop_window_tree_host(NULL), layer_type(ui::LAYER_TEXTURED), @@ -323,7 +325,7 @@ void Widget::Init(const InitParams& in_params) { InitParams params = in_params; params.child |= (params.type == InitParams::TYPE_CONTROL); - is_top_level_ = !params.child; + is_top_level_ = !params.child || params.parent_widget; if (params.opacity == views::Widget::InitParams::INFER_OPACITY && params.type != views::Widget::InitParams::TYPE_WINDOW && @@ -386,7 +388,12 @@ void Widget::Init(const InitParams& in_params) { Minimize(); } 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 301c0af..de63108 100644 --- ui/views/widget/widget.h +++ ui/views/widget/widget.h @@ -232,6 +232,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // Whether the widget should be maximized or minimized. ui::WindowShowState show_state; gfx::NativeView parent; + gfx::AcceleratedWidget parent_widget; // Specifies the initial bounds of the Widget. Default is empty, which means // the NativeWidget may specify a default size. If the parent is specified, // |bounds| is in the parent's coordinate system. If the parent is not