diff options
Diffstat (limited to 'chromium/ui/views/widget')
43 files changed, 1171 insertions, 1678 deletions
diff --git a/chromium/ui/views/widget/android/android_focus_rules.cc b/chromium/ui/views/widget/android/android_focus_rules.cc deleted file mode 100644 index c01ace9ca58..00000000000 --- a/chromium/ui/views/widget/android/android_focus_rules.cc +++ /dev/null @@ -1,19 +0,0 @@ -// 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 "ui/views/widget/android/android_focus_rules.h" - -#include "ui/aura/window.h" - -namespace views { - -AndroidFocusRules::AndroidFocusRules() {} - -AndroidFocusRules::~AndroidFocusRules() {} - -bool AndroidFocusRules::SupportsChildActivation(aura::Window* window) const { - return window->IsRootWindow(); -} - -} // namespace views diff --git a/chromium/ui/views/widget/android/android_focus_rules.h b/chromium/ui/views/widget/android/android_focus_rules.h deleted file mode 100644 index 867d53d4812..00000000000 --- a/chromium/ui/views/widget/android/android_focus_rules.h +++ /dev/null @@ -1,28 +0,0 @@ -// 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 UI_VIEWS_WIDGET_ANDROID_ANDROID_FOCUS_RULES_H_ -#define UI_VIEWS_WIDGET_ANDROID_ANDROID_FOCUS_RULES_H_ - -#include "base/macros.h" -#include "ui/wm/core/base_focus_rules.h" - -namespace views { - -// A set of focus rules for Android using aura. -class AndroidFocusRules : public wm::BaseFocusRules { - public: - AndroidFocusRules(); - ~AndroidFocusRules() override; - - private: - // wm::BaseFocusRules: - bool SupportsChildActivation(aura::Window* window) const override; - - DISALLOW_COPY_AND_ASSIGN(AndroidFocusRules); -}; - -} // namespace views - -#endif // UI_VIEWS_WIDGET_ANDROID_ANDROID_FOCUS_RULES_H_ diff --git a/chromium/ui/views/widget/android/native_widget_android.cc b/chromium/ui/views/widget/android/native_widget_android.cc deleted file mode 100644 index 2aed158559a..00000000000 --- a/chromium/ui/views/widget/android/native_widget_android.cc +++ /dev/null @@ -1,841 +0,0 @@ -// 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 "ui/views/widget/android/native_widget_android.h" - -#include "base/bind.h" -#include "base/macros.h" -#include "base/run_loop.h" -#include "base/strings/string_util.h" -#include "third_party/skia/include/core/SkRegion.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/cursor_client.h" -#include "ui/aura/client/default_capture_client.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/client/window_tree_client.h" -#include "ui/aura/env.h" -#include "ui/aura/window.h" -#include "ui/aura/window_event_dispatcher.h" -#include "ui/aura/window_observer.h" -#include "ui/aura/window_tree_host.h" -#include "ui/base/dragdrop/os_exchange_data.h" -#include "ui/base/ui_base_types.h" -#include "ui/compositor/layer.h" -#include "ui/events/event.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font_list.h" -#include "ui/gfx/screen.h" -#include "ui/native_theme/native_theme_aura.h" -#include "ui/views/drag_utils.h" -#include "ui/views/views_delegate.h" -#include "ui/views/widget/android/android_focus_rules.h" -#include "ui/views/widget/native_widget_aura.h" -#include "ui/views/widget/native_widget_delegate.h" -#include "ui/views/widget/root_view.h" -#include "ui/views/widget/tooltip_manager_aura.h" -#include "ui/views/widget/widget_aura_utils.h" -#include "ui/views/widget/widget_delegate.h" -#include "ui/views/widget/window_reorderer.h" -#include "ui/wm/core/default_activation_client.h" -#include "ui/wm/core/default_screen_position_client.h" -#include "ui/wm/core/focus_controller.h" -#include "ui/wm/core/shadow_types.h" -#include "ui/wm/core/window_animations.h" -#include "ui/wm/core/window_util.h" -#include "ui/wm/public/activation_client.h" -#include "ui/wm/public/dispatcher_client.h" -#include "ui/wm/public/drag_drop_client.h" -#include "ui/wm/public/window_move_client.h" -#include "ui/wm/public/window_types.h" - -// TODO(bshe): Most of the code is copied from NativeWidgetAura or -// DesktopNativeWidgetAura. Share more code instead of duplicate code when -// possible. crbug.com/554961. -namespace { - -class WindowTreeClientImpl : public aura::client::WindowTreeClient { - public: - explicit WindowTreeClientImpl(aura::Window* root_window) - : root_window_(root_window) { - aura::client::SetWindowTreeClient(root_window_, this); - } - ~WindowTreeClientImpl() override { - aura::client::SetWindowTreeClient(root_window_, nullptr); - } - - // Overridden from client::WindowTreeClient: - aura::Window* GetDefaultParent(aura::Window* context, - aura::Window* window, - const gfx::Rect& bounds) override { - return root_window_; - } - - private: - aura::Window* root_window_; - - DISALLOW_COPY_AND_ASSIGN(WindowTreeClientImpl); -}; - -// TODO(bshe|jonross): Get rid of nested message loop once crbug.com/523680 is -// fixed. -class AndroidDispatcherClient : public aura::client::DispatcherClient { - public: - AndroidDispatcherClient() {} - ~AndroidDispatcherClient() override {} - - // aura::client::DispatcherClient: - void PrepareNestedLoopClosures(base::MessagePumpDispatcher* dispatcher, - base::Closure* run_closure, - base::Closure* quit_closure) override { - scoped_ptr<base::RunLoop> run_loop(new base::RunLoop()); - *quit_closure = run_loop->QuitClosure(); - *run_closure = - base::Bind(&AndroidDispatcherClient::RunNestedDispatcher, - base::Unretained(this), base::Passed(&run_loop), dispatcher); - } - - private: - void RunNestedDispatcher(scoped_ptr<base::RunLoop> run_loop, - base::MessagePumpDispatcher* dispatcher) { - base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); - base::MessageLoop::ScopedNestableTaskAllower allow(loop); - run_loop->Run(); - } - - DISALLOW_COPY_AND_ASSIGN(AndroidDispatcherClient); -}; - -} // namespace - -namespace views { - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, public - -NativeWidgetAndroid::NativeWidgetAndroid( - internal::NativeWidgetDelegate* delegate) - : delegate_(delegate), - window_(new aura::Window(this)), - ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET), - destroying_(false), - cursor_(gfx::kNullCursor), - saved_window_state_(ui::SHOW_STATE_DEFAULT), - close_widget_factory_(this) { - aura::client::SetFocusChangeObserver(window_, this); - aura::client::SetActivationChangeObserver(window_, this); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, internal::NativeWidgetPrivate implementation: - -void NativeWidgetAndroid::InitNativeWidget(const Widget::InitParams& params) { - ownership_ = params.ownership; - NativeWidgetAura::RegisterNativeWidgetForWindow(this, window_); - - window_->SetType(GetAuraWindowTypeForWidgetType(params.type)); - window_->Init(params.layer_type); - wm::SetShadowType(window_, wm::SHADOW_TYPE_NONE); - window_->Show(); - - // TODO(bshe): Get rid of the hard coded size. Tracked in crbug.com/551923. - host_.reset(aura::WindowTreeHost::Create(gfx::Rect(0, 0, 800, 600))); - host_->InitHost(); - host_->AddObserver(this); - - window_tree_client_.reset(new WindowTreeClientImpl(host_->window())); - - focus_client_.reset(new wm::FocusController(new AndroidFocusRules)); - aura::client::SetFocusClient(host_->window(), focus_client_.get()); - host_->window()->AddPreTargetHandler(focus_client_.get()); - - new wm::DefaultActivationClient(host_->window()); - - capture_client_.reset( - new aura::client::DefaultCaptureClient(host_->window())); - - screen_position_client_.reset(new wm::DefaultScreenPositionClient); - aura::client::SetScreenPositionClient(host_->window(), - screen_position_client_.get()); - dispatcher_client_.reset(new AndroidDispatcherClient); - aura::client::SetDispatcherClient(host_->window(), dispatcher_client_.get()); - - delegate_->OnNativeWidgetCreated(false); - - DCHECK(GetWidget()->GetRootView()); - if (params.type != Widget::InitParams::TYPE_TOOLTIP) - tooltip_manager_.reset(new views::TooltipManagerAura(GetWidget())); - - if (params.type != Widget::InitParams::TYPE_TOOLTIP && - params.type != Widget::InitParams::TYPE_POPUP) { - aura::client::SetDragDropDelegate(window_, this); - } - - aura::client::SetActivationDelegate(window_, this); - - host_->window()->AddChild(window_); - window_reorderer_.reset( - new WindowReorderer(window_, GetWidget()->GetRootView())); - - // TODO(bshe): figure out how to add cursor manager, drag drop client and all - // the necessary parts that exists in desktop_native_widget_aura. -} - -void NativeWidgetAndroid::OnWidgetInitDone() {} - -NonClientFrameView* NativeWidgetAndroid::CreateNonClientFrameView() { - NOTIMPLEMENTED(); - return nullptr; -} - -bool NativeWidgetAndroid::ShouldUseNativeFrame() const { - // There is only one frame type for aura. - return false; -} - -bool NativeWidgetAndroid::ShouldWindowContentsBeTransparent() const { - NOTIMPLEMENTED(); - return false; -} - -void NativeWidgetAndroid::FrameTypeChanged() { - NOTIMPLEMENTED(); -} - -Widget* NativeWidgetAndroid::GetWidget() { - return delegate_->AsWidget(); -} - -const Widget* NativeWidgetAndroid::GetWidget() const { - return delegate_->AsWidget(); -} - -gfx::NativeView NativeWidgetAndroid::GetNativeView() const { - return window_; -} - -gfx::NativeWindow NativeWidgetAndroid::GetNativeWindow() const { - return window_; -} - -Widget* NativeWidgetAndroid::GetTopLevelWidget() { - return GetWidget(); -} - -const ui::Compositor* NativeWidgetAndroid::GetCompositor() const { - return host_->compositor(); -} - -const ui::Layer* NativeWidgetAndroid::GetLayer() const { - return GetNativeWindow()->layer(); -} - -void NativeWidgetAndroid::ReorderNativeViews() { - window_reorderer_->ReorderChildWindows(); -} - -void NativeWidgetAndroid::ViewRemoved(View* view) { - // TODO(bshe): Implement drag and drop. crbug.com/554029. - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::SetNativeWindowProperty(const char* name, - void* value) { - GetNativeWindow()->SetNativeWindowProperty(name, value); -} - -void* NativeWidgetAndroid::GetNativeWindowProperty(const char* name) const { - return GetNativeWindow()->GetNativeWindowProperty(name); -} - -TooltipManager* NativeWidgetAndroid::GetTooltipManager() const { - return tooltip_manager_.get(); -} - -void NativeWidgetAndroid::SetCapture() { - GetNativeWindow()->SetCapture(); -} - -void NativeWidgetAndroid::ReleaseCapture() { - GetNativeWindow()->ReleaseCapture(); -} - -bool NativeWidgetAndroid::HasCapture() const { - return GetNativeWindow()->HasCapture(); -} - -ui::InputMethod* NativeWidgetAndroid::GetInputMethod() { - return host_->GetInputMethod(); -} - -void NativeWidgetAndroid::CenterWindow(const gfx::Size& size) { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::GetWindowPlacement( - gfx::Rect* bounds, - ui::WindowShowState* show_state) const { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); -} - -bool NativeWidgetAndroid::SetWindowTitle(const base::string16& title) { - if (GetNativeWindow()->title() == title) - return false; - GetNativeWindow()->SetTitle(title); - return true; -} - -void NativeWidgetAndroid::SetWindowIcons(const gfx::ImageSkia& window_icon, - const gfx::ImageSkia& app_icon) { - // TODO(bshe): Implement this. See crbug.com/554953. - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::InitModalType(ui::ModalType modal_type) { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); -} - -gfx::Rect NativeWidgetAndroid::GetWindowBoundsInScreen() const { - return GetNativeWindow()->GetBoundsInScreen(); -} - -gfx::Rect NativeWidgetAndroid::GetClientAreaBoundsInScreen() const { - // View-to-screen coordinate system transformations depend on this returning - // the full window bounds, for example View::ConvertPointToScreen(). - return GetNativeWindow()->GetBoundsInScreen(); -} - -gfx::Rect NativeWidgetAndroid::GetRestoredBounds() const { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); - return gfx::Rect(); -} - -void NativeWidgetAndroid::SetBounds(const gfx::Rect& bounds) { - // TODO(bshe): This may not work. We may need to resize SurfaceView too. See - // crbug.com/554952. - host_->SetBounds(bounds); -} - -void NativeWidgetAndroid::SetSize(const gfx::Size& size) { - gfx::Rect bounds = host_->GetBounds(); - SetBounds(gfx::Rect(bounds.origin(), size)); -} - -void NativeWidgetAndroid::StackAbove(gfx::NativeView native_view) { - // TODO(bshe): Implements window stacking logic. See crbug.com/554047 - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::StackAtTop() { - // TODO(bshe): Implements window stacking logic. See crbug.com/554047 - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::StackBelow(gfx::NativeView native_view) { - // TODO(bshe): Implements window stacking logic. See crbug.com/554047 - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::SetShape(SkRegion* region) { - GetNativeWindow()->layer()->SetAlphaShape(make_scoped_ptr(region)); -} - -void NativeWidgetAndroid::Close() { - // TODO(bshe): This might not be right. See crbug.com/554259. - DCHECK(ownership_ == Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET); - GetNativeWindow()->SuppressPaint(); - Hide(); - GetNativeWindow()->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_NONE); - - if (!close_widget_factory_.HasWeakPtrs()) { - base::MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(&NativeWidgetAndroid::CloseNow, - close_widget_factory_.GetWeakPtr())); - } -} - -void NativeWidgetAndroid::CloseNow() { - // TODO(bshe): This might not be right. See crbug.com/554259. - host_->RemoveObserver(this); - host_.reset(); - delete window_; -} - -void NativeWidgetAndroid::Show() { - host_->Show(); - GetNativeWindow()->Show(); -} - -void NativeWidgetAndroid::Hide() { - host_->Hide(); - GetNativeWindow()->Hide(); -} - -void NativeWidgetAndroid::ShowMaximizedWithBounds( - const gfx::Rect& restored_bounds) { - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::ShowWithWindowState(ui::WindowShowState state) { - NOTIMPLEMENTED(); -} - -bool NativeWidgetAndroid::IsVisible() const { - return GetNativeWindow()->IsVisible(); -} - -void NativeWidgetAndroid::Activate() { - aura::client::GetActivationClient(host_->window()) - ->ActivateWindow(GetNativeWindow()); -} - -void NativeWidgetAndroid::Deactivate() { - aura::client::GetActivationClient(host_->window()) - ->DeactivateWindow(GetNativeWindow()); -} - -bool NativeWidgetAndroid::IsActive() const { - return wm::IsActiveWindow(GetNativeWindow()); -} - -void NativeWidgetAndroid::SetAlwaysOnTop(bool on_top) { - GetNativeWindow()->SetProperty(aura::client::kAlwaysOnTopKey, on_top); -} - -bool NativeWidgetAndroid::IsAlwaysOnTop() const { - return GetNativeWindow()->GetProperty(aura::client::kAlwaysOnTopKey); -} - -void NativeWidgetAndroid::SetVisibleOnAllWorkspaces(bool always_visible) { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::Maximize() { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::Minimize() { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); -} - -bool NativeWidgetAndroid::IsMaximized() const { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); - return false; -} - -bool NativeWidgetAndroid::IsMinimized() const { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); - return false; -} - -void NativeWidgetAndroid::Restore() { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::SetFullscreen(bool fullscreen) { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); -} - -bool NativeWidgetAndroid::IsFullscreen() const { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); - return false; -} - -void NativeWidgetAndroid::SetOpacity(unsigned char opacity) { - GetNativeWindow()->layer()->SetOpacity(opacity / 255.0); -} - -void NativeWidgetAndroid::SetUseDragFrame(bool use_drag_frame) { - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::FlashFrame(bool flash) { - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::RunShellDrag( - View* view, - const ui::OSExchangeData& data, - const gfx::Point& location, - int operation, - ui::DragDropTypes::DragEventSource source) { - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::SchedulePaintInRect(const gfx::Rect& rect) { - GetNativeWindow()->SchedulePaintInRect(rect); -} - -void NativeWidgetAndroid::SetCursor(gfx::NativeCursor cursor) { - cursor_ = cursor; - aura::client::CursorClient* cursor_client = - aura::client::GetCursorClient(host_->window()); - if (cursor_client) - cursor_client->SetCursor(cursor); -} - -bool NativeWidgetAndroid::IsMouseEventsEnabled() const { - aura::client::CursorClient* cursor_client = - aura::client::GetCursorClient(host_->window()); - return cursor_client ? cursor_client->IsMouseEventsEnabled() : true; -} - -void NativeWidgetAndroid::ClearNativeFocus() { - aura::client::FocusClient* client = aura::client::GetFocusClient(window_); - if (client && window_->Contains(client->GetFocusedWindow())) - client->ResetFocusWithinActiveWindow(window_); -} - -gfx::Rect NativeWidgetAndroid::GetWorkAreaBoundsInScreen() const { - return gfx::Screen::GetScreenFor(window_) - ->GetDisplayNearestWindow(window_) - .work_area(); -} - -Widget::MoveLoopResult NativeWidgetAndroid::RunMoveLoop( - const gfx::Vector2d& drag_offset, - Widget::MoveLoopSource source, - Widget::MoveLoopEscapeBehavior escape_behavior) { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); - return Widget::MOVE_LOOP_SUCCESSFUL; -} - -void NativeWidgetAndroid::EndMoveLoop() { - // TODO(bshe): Implement this. See crbug.com/554208. - NOTIMPLEMENTED(); -} - -void NativeWidgetAndroid::SetVisibilityChangedAnimationsEnabled(bool value) { - GetNativeWindow()->SetProperty(aura::client::kAnimationsDisabledKey, !value); -} - -void NativeWidgetAndroid::SetVisibilityAnimationDuration( - const base::TimeDelta& duration) { - wm::SetWindowVisibilityAnimationDuration(GetNativeWindow(), duration); -} - -void NativeWidgetAndroid::SetVisibilityAnimationTransition( - Widget::VisibilityTransition transition) { - wm::WindowVisibilityAnimationTransition wm_transition = wm::ANIMATE_NONE; - switch (transition) { - case Widget::ANIMATE_SHOW: - wm_transition = wm::ANIMATE_SHOW; - break; - case Widget::ANIMATE_HIDE: - wm_transition = wm::ANIMATE_HIDE; - break; - case Widget::ANIMATE_BOTH: - wm_transition = wm::ANIMATE_BOTH; - break; - case Widget::ANIMATE_NONE: - wm_transition = wm::ANIMATE_NONE; - break; - } - wm::SetWindowVisibilityAnimationTransition(GetNativeWindow(), wm_transition); -} - -ui::NativeTheme* NativeWidgetAndroid::GetNativeTheme() const { - return ui::NativeThemeAura::instance(); -} - -void NativeWidgetAndroid::OnRootViewLayout() { - NOTIMPLEMENTED(); -} - -bool NativeWidgetAndroid::IsTranslucentWindowOpacitySupported() const { - return true; -} - -void NativeWidgetAndroid::OnSizeConstraintsChanged() { - window_->SetProperty(aura::client::kCanMaximizeKey, - GetWidget()->widget_delegate()->CanMaximize()); - window_->SetProperty(aura::client::kCanMinimizeKey, - GetWidget()->widget_delegate()->CanMinimize()); - window_->SetProperty(aura::client::kCanResizeKey, - GetWidget()->widget_delegate()->CanResize()); -} - -void NativeWidgetAndroid::RepostNativeEvent(gfx::NativeEvent native_event) { - OnEvent(native_event); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, aura::WindowDelegate implementation: - -gfx::Size NativeWidgetAndroid::GetMinimumSize() const { - return delegate_->GetMinimumSize(); -} - -gfx::Size NativeWidgetAndroid::GetMaximumSize() const { - // If a window have a maximum size, the window should not be - // maximizable. - DCHECK(delegate_->GetMaximumSize().IsEmpty() || - !window_->GetProperty(aura::client::kCanMaximizeKey)); - return delegate_->GetMaximumSize(); -} - -void NativeWidgetAndroid::OnBoundsChanged(const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - // Assume that if the old bounds was completely empty a move happened. This - // handles the case of a maximize animation acquiring the layer (acquiring a - // layer results in clearing the bounds). - if (old_bounds.origin() != new_bounds.origin() || - (old_bounds == gfx::Rect(0, 0, 0, 0) && !new_bounds.IsEmpty())) { - delegate_->OnNativeWidgetMove(); - } - if (old_bounds.size() != new_bounds.size()) - delegate_->OnNativeWidgetSizeChanged(new_bounds.size()); -} - -gfx::NativeCursor NativeWidgetAndroid::GetCursor(const gfx::Point& point) { - return cursor_; -} - -int NativeWidgetAndroid::GetNonClientComponent(const gfx::Point& point) const { - return delegate_->GetNonClientComponent(point); -} - -bool NativeWidgetAndroid::ShouldDescendIntoChildForEventHandling( - aura::Window* child, - const gfx::Point& location) { - views::WidgetDelegate* widget_delegate = GetWidget()->widget_delegate(); - if (widget_delegate && - !widget_delegate->ShouldDescendIntoChildForEventHandling(child, location)) - return false; - - // Don't descend into |child| if there is a view with a Layer that contains - // the point and is stacked above |child|s layer. - typedef std::vector<ui::Layer*> Layers; - const Layers& root_layers(delegate_->GetRootLayers()); - if (root_layers.empty()) - return true; - - Layers::const_iterator child_layer_iter( - std::find(window_->layer()->children().begin(), - window_->layer()->children().end(), child->layer())); - if (child_layer_iter == window_->layer()->children().end()) - return true; - - for (std::vector<ui::Layer*>::const_reverse_iterator i = root_layers.rbegin(); - i != root_layers.rend(); ++i) { - ui::Layer* layer = *i; - if (layer->visible() && layer->bounds().Contains(location)) { - Layers::const_iterator root_layer_iter( - std::find(window_->layer()->children().begin(), - window_->layer()->children().end(), layer)); - if (root_layer_iter > child_layer_iter) - return false; - } - } - return true; -} - -bool NativeWidgetAndroid::CanFocus() { - return ShouldActivate(); -} - -void NativeWidgetAndroid::OnCaptureLost() { - delegate_->OnMouseCaptureLost(); -} - -void NativeWidgetAndroid::OnPaint(const ui::PaintContext& context) { - delegate_->OnNativeWidgetPaint(context); -} - -void NativeWidgetAndroid::OnDeviceScaleFactorChanged( - float device_scale_factor) { - GetWidget()->DeviceScaleFactorChanged(device_scale_factor); -} - -void NativeWidgetAndroid::OnWindowDestroying(aura::Window* window) { - delegate_->OnNativeWidgetDestroying(); - - // If the aura::Window is destroyed, we can no longer show tooltips. - tooltip_manager_.reset(); -} - -void NativeWidgetAndroid::OnWindowDestroyed(aura::Window* window) { - window_ = nullptr; - delegate_->OnNativeWidgetDestroyed(); - if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) - delete this; -} - -void NativeWidgetAndroid::OnWindowTargetVisibilityChanged(bool visible) { - delegate_->OnNativeWidgetVisibilityChanged(visible); -} - -bool NativeWidgetAndroid::HasHitTestMask() const { - return delegate_->HasHitTestMask(); -} - -void NativeWidgetAndroid::GetHitTestMask(gfx::Path* mask) const { - DCHECK(mask); - delegate_->GetHitTestMask(mask); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, ui::EventHandler implementation: - -void NativeWidgetAndroid::OnKeyEvent(ui::KeyEvent* event) { - DCHECK(window_); - // Renderer may send a key event back to us if the key event wasn't handled, - // and the window may be invisible by that time. - if (!window_->IsVisible()) - return; - - FocusManager* focus_manager = GetWidget()->GetFocusManager(); - delegate_->OnKeyEvent(event); - if (!event->handled() && focus_manager) - focus_manager->OnKeyEvent(*event); - event->SetHandled(); -} - -void NativeWidgetAndroid::OnMouseEvent(ui::MouseEvent* event) { - DCHECK(window_); - DCHECK(window_->IsVisible()); - if (event->type() == ui::ET_MOUSEWHEEL) { - delegate_->OnMouseEvent(event); - if (event->handled()) - return; - } - - if (tooltip_manager_.get()) - tooltip_manager_->UpdateTooltip(); - TooltipManagerAura::UpdateTooltipManagerForCapture(GetWidget()); - delegate_->OnMouseEvent(event); -} - -void NativeWidgetAndroid::OnScrollEvent(ui::ScrollEvent* event) { - delegate_->OnScrollEvent(event); -} - -void NativeWidgetAndroid::OnGestureEvent(ui::GestureEvent* event) { - DCHECK(window_); - DCHECK(window_->IsVisible() || event->IsEndingEvent()); - delegate_->OnGestureEvent(event); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, aura::client::ActivationDelegate implementation: - -bool NativeWidgetAndroid::ShouldActivate() const { - return delegate_->CanActivate(); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, aura::client::ActivationChangeObserver -// implementation: - -void NativeWidgetAndroid::OnWindowActivated( - aura::client::ActivationChangeObserver::ActivationReason, - aura::Window* gained_active, - aura::Window* lost_active) { - DCHECK(window_ == gained_active || window_ == lost_active); - if (GetWidget()->GetFocusManager()) { - if (window_ == gained_active) - GetWidget()->GetFocusManager()->RestoreFocusedView(); - else if (window_ == lost_active) - GetWidget()->GetFocusManager()->StoreFocusedView(true); - } - delegate_->OnNativeWidgetActivationChanged(window_ == gained_active); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, aura::client::FocusChangeObserver: - -void NativeWidgetAndroid::OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) { - if (window_ == gained_focus) - delegate_->OnNativeFocus(); - else if (window_ == lost_focus) - delegate_->OnNativeBlur(); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, aura::WindowDragDropDelegate implementation: - -void NativeWidgetAndroid::OnDragEntered(const ui::DropTargetEvent& event) { - // TODO: Implement drag and drop. crbug.com/554029. - NOTIMPLEMENTED(); -} - -int NativeWidgetAndroid::OnDragUpdated(const ui::DropTargetEvent& event) { - // TODO: Implement drag and drop. crbug.com/554029. - NOTIMPLEMENTED(); - return 0; -} - -void NativeWidgetAndroid::OnDragExited() { - // TODO: Implement drag and drop. crbug.com/554029. - NOTIMPLEMENTED(); -} - -int NativeWidgetAndroid::OnPerformDrop(const ui::DropTargetEvent& event) { - // TODO: Implement drag and drop. crbug.com/554029. - NOTIMPLEMENTED(); - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, aura::WindowTreeHostObserver implementation: - -void NativeWidgetAndroid::OnHostCloseRequested( - const aura::WindowTreeHost* host) { - GetWidget()->Close(); -} - -void NativeWidgetAndroid::OnHostResized(const aura::WindowTreeHost* host) { - gfx::Rect new_bounds = gfx::Rect(host_->window()->bounds().size()); - GetNativeWindow()->SetBounds(new_bounds); - delegate_->OnNativeWidgetSizeChanged(new_bounds.size()); -} - -void NativeWidgetAndroid::OnHostMoved(const aura::WindowTreeHost* host, - const gfx::Point& new_origin) { - TRACE_EVENT1("views", "NativeWidgetAndroid::OnHostMoved", "new_origin", - new_origin.ToString()); - - delegate_->OnNativeWidgetMove(); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, protected: - -NativeWidgetAndroid::~NativeWidgetAndroid() { - destroying_ = true; - if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) - delete delegate_; - else - CloseNow(); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidgetAndroid, private: - -bool NativeWidgetAndroid::IsDocked() const { - NOTIMPLEMENTED(); - return false; -} - -void NativeWidgetAndroid::SetInitialFocus(ui::WindowShowState show_state) { - // The window does not get keyboard messages unless we focus it. - if (!GetWidget()->SetInitialFocus(show_state)) - window_->Focus(); -} - -} // namespace views diff --git a/chromium/ui/views/widget/android/native_widget_android.h b/chromium/ui/views/widget/android/native_widget_android.h deleted file mode 100644 index 8aaa3c470bd..00000000000 --- a/chromium/ui/views/widget/android/native_widget_android.h +++ /dev/null @@ -1,249 +0,0 @@ -// 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 UI_VIEWS_WIDGET_ANDROID_NATIVE_WIDGET_ANDROID_H_ -#define UI_VIEWS_WIDGET_ANDROID_NATIVE_WIDGET_ANDROID_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "ui/aura/client/focus_change_observer.h" -#include "ui/aura/window_delegate.h" -#include "ui/aura/window_observer.h" -#include "ui/aura/window_tree_host_observer.h" -#include "ui/base/cursor/cursor.h" -#include "ui/events/event_constants.h" -#include "ui/views/views_export.h" -#include "ui/views/widget/native_widget_private.h" -#include "ui/wm/public/activation_change_observer.h" -#include "ui/wm/public/activation_delegate.h" -#include "ui/wm/public/drag_drop_delegate.h" - -namespace aura { -class Window; -class WindowTreeHost; -namespace client { -class DefaultCaptureClient; -class DispatcherClient; -class ScreenPositionClient; -class WindowTreeClient; -} -} -namespace gfx { -class FontList; -} -namespace wm { -class FocusController; -} - -namespace views { - -class TooltipManagerAura; -class WindowReorderer; - -// NativeWidgetAndroid creates and hosts the Widget in an Android native window. -// It is used to create a top level window on Android platform. -class VIEWS_EXPORT NativeWidgetAndroid - : public internal::NativeWidgetPrivate, - public aura::WindowDelegate, - public aura::client::ActivationDelegate, - public aura::client::ActivationChangeObserver, - public aura::client::FocusChangeObserver, - public aura::client::DragDropDelegate, - public aura::WindowTreeHostObserver { - public: - explicit NativeWidgetAndroid(internal::NativeWidgetDelegate* delegate); - - aura::WindowTreeHost* host() { return host_.get(); } - - // Overridden from internal::NativeWidgetPrivate: - void InitNativeWidget(const Widget::InitParams& params) override; - void OnWidgetInitDone() override; - NonClientFrameView* CreateNonClientFrameView() override; - bool ShouldUseNativeFrame() const override; - bool ShouldWindowContentsBeTransparent() const override; - void FrameTypeChanged() override; - Widget* GetWidget() override; - const Widget* GetWidget() const override; - gfx::NativeView GetNativeView() const override; - gfx::NativeWindow GetNativeWindow() const override; - Widget* GetTopLevelWidget() override; - const ui::Compositor* GetCompositor() const override; - const ui::Layer* GetLayer() const override; - void ReorderNativeViews() override; - void ViewRemoved(View* view) override; - void SetNativeWindowProperty(const char* name, void* value) override; - void* GetNativeWindowProperty(const char* name) const override; - TooltipManager* GetTooltipManager() const override; - void SetCapture() override; - void ReleaseCapture() override; - bool HasCapture() const override; - ui::InputMethod* GetInputMethod() override; - void CenterWindow(const gfx::Size& size) override; - void GetWindowPlacement(gfx::Rect* bounds, - ui::WindowShowState* maximized) const override; - bool SetWindowTitle(const base::string16& title) override; - void SetWindowIcons(const gfx::ImageSkia& window_icon, - const gfx::ImageSkia& app_icon) override; - void InitModalType(ui::ModalType modal_type) override; - gfx::Rect GetWindowBoundsInScreen() const override; - gfx::Rect GetClientAreaBoundsInScreen() const override; - gfx::Rect GetRestoredBounds() const override; - void SetBounds(const gfx::Rect& bounds) override; - void SetSize(const gfx::Size& size) override; - void StackAbove(gfx::NativeView native_view) override; - void StackAtTop() override; - void StackBelow(gfx::NativeView native_view) override; - void SetShape(SkRegion* shape) override; - void Close() override; - void CloseNow() override; - void Show() override; - void Hide() override; - void ShowMaximizedWithBounds(const gfx::Rect& restored_bounds) override; - void ShowWithWindowState(ui::WindowShowState state) override; - bool IsVisible() const override; - void Activate() override; - void Deactivate() override; - bool IsActive() const override; - void SetAlwaysOnTop(bool always_on_top) override; - bool IsAlwaysOnTop() const override; - void SetVisibleOnAllWorkspaces(bool always_visible) override; - void Maximize() override; - void Minimize() override; - bool IsMaximized() const override; - bool IsMinimized() const override; - void Restore() override; - void SetFullscreen(bool fullscreen) override; - bool IsFullscreen() const override; - void SetOpacity(unsigned char opacity) override; - void SetUseDragFrame(bool use_drag_frame) override; - void FlashFrame(bool flash_frame) override; - void RunShellDrag(View* view, - const ui::OSExchangeData& data, - const gfx::Point& location, - int operation, - ui::DragDropTypes::DragEventSource source) override; - void SchedulePaintInRect(const gfx::Rect& rect) override; - void SetCursor(gfx::NativeCursor cursor) override; - bool IsMouseEventsEnabled() const override; - void ClearNativeFocus() override; - gfx::Rect GetWorkAreaBoundsInScreen() const override; - Widget::MoveLoopResult RunMoveLoop( - const gfx::Vector2d& drag_offset, - Widget::MoveLoopSource source, - Widget::MoveLoopEscapeBehavior escape_behavior) override; - void EndMoveLoop() override; - void SetVisibilityChangedAnimationsEnabled(bool value) override; - void SetVisibilityAnimationDuration(const base::TimeDelta& duration) override; - void SetVisibilityAnimationTransition( - Widget::VisibilityTransition transition) override; - ui::NativeTheme* GetNativeTheme() const override; - void OnRootViewLayout() override; - bool IsTranslucentWindowOpacitySupported() const override; - void OnSizeConstraintsChanged() override; - void RepostNativeEvent(gfx::NativeEvent native_event) override; - - // Overridden from aura::WindowDelegate: - gfx::Size GetMinimumSize() const override; - gfx::Size GetMaximumSize() const override; - void OnBoundsChanged(const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) override; - gfx::NativeCursor GetCursor(const gfx::Point& point) override; - int GetNonClientComponent(const gfx::Point& point) const override; - bool ShouldDescendIntoChildForEventHandling( - aura::Window* child, - const gfx::Point& location) override; - bool CanFocus() override; - void OnCaptureLost() override; - void OnPaint(const ui::PaintContext& context) override; - void OnDeviceScaleFactorChanged(float device_scale_factor) override; - void OnWindowDestroying(aura::Window* window) override; - void OnWindowDestroyed(aura::Window* window) override; - void OnWindowTargetVisibilityChanged(bool visible) override; - bool HasHitTestMask() const override; - void GetHitTestMask(gfx::Path* mask) const override; - - // Overridden from ui::EventHandler: - void OnKeyEvent(ui::KeyEvent* event) override; - void OnMouseEvent(ui::MouseEvent* event) override; - void OnScrollEvent(ui::ScrollEvent* event) override; - void OnGestureEvent(ui::GestureEvent* event) override; - - // Overridden from aura::client::ActivationDelegate: - bool ShouldActivate() const override; - - // Overridden from aura::client::ActivationChangeObserver: - void OnWindowActivated( - aura::client::ActivationChangeObserver::ActivationReason reason, - aura::Window* gained_active, - aura::Window* lost_active) override; - - // Overridden from aura::client::FocusChangeObserver: - void OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) override; - - // Overridden from aura::client::DragDropDelegate: - void OnDragEntered(const ui::DropTargetEvent& event) override; - int OnDragUpdated(const ui::DropTargetEvent& event) override; - void OnDragExited() override; - int OnPerformDrop(const ui::DropTargetEvent& event) override; - - // Overridden from aura::WindowTreeHostObserver: - void OnHostCloseRequested(const aura::WindowTreeHost* host) override; - void OnHostResized(const aura::WindowTreeHost* host) override; - void OnHostMoved(const aura::WindowTreeHost* host, - const gfx::Point& new_origin) override; - - protected: - ~NativeWidgetAndroid() override; - - internal::NativeWidgetDelegate* delegate() { return delegate_; } - - private: - class ActiveWindowObserver; - - bool IsDocked() const; - void SetInitialFocus(ui::WindowShowState show_state); - - internal::NativeWidgetDelegate* delegate_; - - // WARNING: set to NULL when destroyed. As the Widget is not necessarily - // destroyed along with |window_| all usage of |window_| should first verify - // non-NULL. - aura::Window* window_; - - // See class documentation for Widget in widget.h for a note about ownership. - Widget::InitParams::Ownership ownership_; - - // Are we in the destructor? - bool destroying_; - - gfx::NativeCursor cursor_; - - // The saved window state for exiting full screen state. - ui::WindowShowState saved_window_state_; - - scoped_ptr<TooltipManagerAura> tooltip_manager_; - - // Reorders child windows of |window_| associated with a view based on the - // order of the associated views in the widget's view hierarchy. - scoped_ptr<WindowReorderer> window_reorderer_; - - scoped_ptr<aura::WindowTreeHost> host_; - scoped_ptr<wm::FocusController> focus_client_; - scoped_ptr<aura::client::DefaultCaptureClient> capture_client_; - scoped_ptr<aura::client::WindowTreeClient> window_tree_client_; - scoped_ptr<aura::client::ScreenPositionClient> screen_position_client_; - scoped_ptr<aura::client::DispatcherClient> dispatcher_client_; - - // The following factory is used for calls to close the - // NativeWidgetAndroid instance. - base::WeakPtrFactory<NativeWidgetAndroid> close_widget_factory_; - - DISALLOW_COPY_AND_ASSIGN(NativeWidgetAndroid); -}; - -} // namespace views - -#endif // UI_VIEWS_WIDGET_ANDROID_NATIVE_WIDGET_ANDROID_H_ diff --git a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc b/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc deleted file mode 100644 index 409057da5f0..00000000000 --- a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2012 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 "ui/views/widget/desktop_aura/desktop_dispatcher_client.h" - -#include "base/auto_reset.h" -#include "base/bind.h" -#include "base/run_loop.h" -#include "build/build_config.h" - -namespace views { - -DesktopDispatcherClient::DesktopDispatcherClient() { -} - -DesktopDispatcherClient::~DesktopDispatcherClient() { -} - -void DesktopDispatcherClient::PrepareNestedLoopClosures( - base::MessagePumpDispatcher* dispatcher, - base::Closure* run_closure, - base::Closure* quit_closure) { -#if defined(OS_WIN) - scoped_ptr<base::RunLoop> run_loop(new base::RunLoop(dispatcher)); -#else - scoped_ptr<base::RunLoop> run_loop(new base::RunLoop()); -#endif - *quit_closure = run_loop->QuitClosure(); - *run_closure = - base::Bind(&base::RunLoop::Run, base::Owned(run_loop.release())); -} - -} // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.h b/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.h deleted file mode 100644 index 3d7f6f42caa..00000000000 --- a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2012 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 UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DISPATCHER_CLIENT_H_ -#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DISPATCHER_CLIENT_H_ - -#include "base/callback.h" -#include "base/macros.h" -#include "ui/views/views_export.h" -#include "ui/wm/public/dispatcher_client.h" - -namespace views { - -// TODO(erg): I won't lie to you; I have no idea what this is or what it does. -class VIEWS_EXPORT DesktopDispatcherClient - : public aura::client::DispatcherClient { - public: - DesktopDispatcherClient(); - ~DesktopDispatcherClient() override; - - void PrepareNestedLoopClosures(base::MessagePumpDispatcher* dispatcher, - base::Closure* run_closure, - base::Closure* quit_closure) override; - - private: - DISALLOW_COPY_AND_ASSIGN(DesktopDispatcherClient); -}; - -} // namespace views - -#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DISPATCHER_CLIENT_H_ diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc index 3ef11e83603..e9907e2a275 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc @@ -1186,8 +1186,8 @@ void DesktopDragDropClientAuraX11::CreateDragWidget( params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.accept_events = false; - gfx::Point location = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint() - - drag_widget_offset_; + gfx::Point location = + gfx::Screen::GetScreen()->GetCursorScreenPoint() - drag_widget_offset_; params.bounds = gfx::Rect(location, image.size()); widget->set_focus_on_creation(false); widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE); diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc index 01c1d875c29..f69b839d73a 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc @@ -32,7 +32,6 @@ #include "ui/views/view_constants_aura.h" #include "ui/views/widget/desktop_aura/desktop_capture_client.h" #include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h" -#include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h" #include "ui/views/widget/desktop_aura/desktop_event_client.h" #include "ui/views/widget/desktop_aura/desktop_focus_rules.h" #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h" @@ -61,7 +60,6 @@ #if defined(OS_WIN) #include "ui/base/win/shell.h" -#include "ui/gfx/win/dpi.h" #endif DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(VIEWS_EXPORT, @@ -341,11 +339,6 @@ void DesktopNativeWidgetAura::OnHostClosed() { void DesktopNativeWidgetAura::OnDesktopWindowTreeHostDestroyed( aura::WindowTreeHost* host) { - // |dispatcher_| is still valid, but DesktopWindowTreeHost is nearly - // destroyed. Do cleanup here of members DesktopWindowTreeHost may also use. - aura::client::SetDispatcherClient(host->window(), NULL); - dispatcher_client_.reset(); - // We explicitly do NOT clear the cursor client property. Since the cursor // manager is a singleton, it can outlive any window hierarchy, and it's // important that objects attached to this destroying window hierarchy have @@ -483,10 +476,6 @@ void DesktopNativeWidgetAura::InitNativeWidget( aura::client::SetActivationClient(host_->window(), focus_controller); host_->window()->AddPreTargetHandler(focus_controller); - dispatcher_client_.reset(new DesktopDispatcherClient); - aura::client::SetDispatcherClient(host_->window(), - dispatcher_client_.get()); - position_client_.reset(new DesktopScreenPositionClient(host_->window())); drag_drop_client_ = desktop_window_tree_host_->CreateDragDropClient( @@ -689,18 +678,9 @@ gfx::Rect DesktopNativeWidgetAura::GetRestoredBounds() const { void DesktopNativeWidgetAura::SetBounds(const gfx::Rect& bounds) { if (!content_window_) return; - // TODO(ananta) - // This code by default scales the bounds rectangle by 1. - // We could probably get rid of this and similar logic from - // the DesktopNativeWidgetAura::OnWindowTreeHostResized function. - float scale = 1; aura::Window* root = host_->window(); - if (root) { - scale = gfx::Screen::GetScreenFor(root)-> - GetDisplayNearestWindow(root).device_scale_factor(); - } - gfx::Rect bounds_in_pixels = - gfx::ScaleToEnclosingRect(bounds, scale, scale); + gfx::Screen* screen = gfx::Screen::GetScreen(); + gfx::Rect bounds_in_pixels = screen->DIPToScreenRectInWindow(root, bounds); desktop_window_tree_host_->AsWindowTreeHost()->SetBounds(bounds_in_pixels); } @@ -840,9 +820,6 @@ void DesktopNativeWidgetAura::SetOpacity(unsigned char opacity) { desktop_window_tree_host_->SetOpacity(opacity); } -void DesktopNativeWidgetAura::SetUseDragFrame(bool use_drag_frame) { -} - void DesktopNativeWidgetAura::FlashFrame(bool flash_frame) { if (content_window_) desktop_window_tree_host_->FlashFrame(flash_frame); @@ -1069,7 +1046,7 @@ void DesktopNativeWidgetAura::OnScrollEvent(ui::ScrollEvent* event) { return; // Convert unprocessed scroll events into wheel events. - ui::MouseWheelEvent mwe(*static_cast<ui::ScrollEvent*>(event)); + ui::MouseWheelEvent mwe(*event->AsScrollEvent()); native_widget_delegate_->OnMouseEvent(&mwe); if (mwe.handled()) event->SetHandled(); diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h index 2a756d9fd72..47f514924bf 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h @@ -42,7 +42,6 @@ namespace corewm { class TooltipController; } class DesktopCaptureClient; -class DesktopDispatcherClient; class DesktopEventClient; class DesktopNativeCursorManager; class DesktopWindowTreeHost; @@ -149,7 +148,6 @@ class VIEWS_EXPORT DesktopNativeWidgetAura void SetFullscreen(bool fullscreen) override; bool IsFullscreen() const override; void SetOpacity(unsigned char opacity) override; - void SetUseDragFrame(bool use_drag_frame) override; void FlashFrame(bool flash_frame) override; void RunShellDrag(View* view, const ui::OSExchangeData& data, @@ -256,7 +254,6 @@ class VIEWS_EXPORT DesktopNativeWidgetAura internal::NativeWidgetDelegate* native_widget_delegate_; scoped_ptr<wm::FocusController> focus_client_; - scoped_ptr<DesktopDispatcherClient> dispatcher_client_; scoped_ptr<aura::client::ScreenPositionClient> position_client_; scoped_ptr<aura::client::DragDropClient> drag_drop_client_; scoped_ptr<aura::client::WindowTreeClient> window_tree_client_; diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc index 9578951b137..86e60d31fc8 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/macros.h" +#include "base/run_loop.h" #include "build/build_config.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/cursor_client.h" @@ -17,15 +18,17 @@ #include "ui/events/event_utils.h" #include "ui/events/test/event_generator.h" #include "ui/gfx/screen.h" +#include "ui/views/test/native_widget_factory.h" #include "ui/views/test/test_views.h" #include "ui/views/test/test_views_delegate.h" #include "ui/views/test/views_test_base.h" #include "ui/views/test/widget_test.h" #include "ui/views/widget/widget.h" #include "ui/views/window/dialog_delegate.h" -#include "ui/wm/public/dispatcher_client.h" #if defined(OS_WIN) +#include "ui/base/view_prop.h" +#include "ui/base/win/window_event_target.h" #include "ui/views/win/hwnd_util.h" #endif @@ -231,15 +234,10 @@ TEST_F(DesktopNativeWidgetAuraTest, WidgetCanBeDestroyedFromNestedLoop) { widget->Init(params); widget->Show(); - aura::Window* window = widget->GetNativeView(); - aura::Window* root = window->GetRootWindow(); - aura::client::DispatcherClient* client = - aura::client::GetDispatcherClient(root); - // Post a task that terminates the nested loop and destroyes the widget. This // task will be executed from the nested loop initiated with the call to // |RunWithDispatcher()| below. - aura::client::DispatcherRunLoop run_loop(client, NULL); + base::RunLoop run_loop; base::Closure quit_runloop = run_loop.QuitClosure(); message_loop()->PostTask(FROM_HERE, base::Bind(&QuitNestedLoopAndCloseWidget, @@ -434,9 +432,7 @@ TEST_F(DesktopAuraWidgetTest, TopLevelOwnedPopupRepositionTest) { gfx::Rect new_pos(10, 10, 400, 400); popup_window.owned_window()->SetBoundsInScreen( - new_pos, - gfx::Screen::GetScreenFor( - popup_window.owned_window())->GetDisplayNearestPoint(gfx::Point())); + new_pos, gfx::Screen::GetScreen()->GetDisplayNearestPoint(gfx::Point())); EXPECT_EQ(new_pos, popup_window.top_level_widget()->GetWindowBoundsInScreen()); @@ -493,7 +489,8 @@ void RunCloseWidgetDuringDispatchTest(WidgetTest* test, Widget* widget = new Widget; Widget::InitParams params = test->CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = new PlatformDesktopNativeWidget(widget); + params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(params, widget, nullptr); params.bounds = gfx::Rect(0, 0, 50, 100); widget->Init(params); widget->SetContentsView(new CloseWidgetView(last_event_type)); @@ -535,8 +532,8 @@ TEST_F(WidgetTest, WindowMouseModalityTest) { gfx::Rect initial_bounds(0, 0, 500, 500); init_params.bounds = initial_bounds; init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - init_params.native_widget = - new PlatformDesktopNativeWidget(&top_level_widget); + init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl( + init_params, &top_level_widget, nullptr); top_level_widget.Init(init_params); top_level_widget.Show(); EXPECT_TRUE(top_level_widget.IsVisible()); @@ -632,6 +629,32 @@ TEST_F(WidgetTest, WindowModalityActivationTest) { modal_dialog_widget->CloseNow(); } + +// This test validates that sending WM_CHAR/WM_SYSCHAR/WM_SYSDEADCHAR +// messages via the WindowEventTarget interface implemented by the +// HWNDMessageHandler class does not cause a crash due to an unprocessed +// event +TEST_F(WidgetTest, CharMessagesAsKeyboardMessagesDoesNotCrash) { + Widget widget; + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); + params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(params, &widget, nullptr); + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget.Init(params); + widget.Show(); + + ui::WindowEventTarget* target = + reinterpret_cast<ui::WindowEventTarget*>(ui::ViewProp::GetValue( + widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(), + ui::WindowEventTarget::kWin32InputEventTarget)); + ASSERT_NE(nullptr, target); + bool handled = false; + target->HandleKeyboardMessage(WM_CHAR, 0, 0, &handled); + target->HandleKeyboardMessage(WM_SYSCHAR, 0, 0, &handled); + target->HandleKeyboardMessage(WM_SYSDEADCHAR, 0, 0, &handled); + widget.CloseNow(); +} + #endif // defined(OS_WIN) } // namespace test diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc index a8e088c92c6..4df7b7ffae5 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc @@ -24,7 +24,7 @@ DesktopScreenWin::~DesktopScreenWin() { } //////////////////////////////////////////////////////////////////////////////// -// DesktopScreenWin, gfx::ScreenWin implementation: +// DesktopScreenWin, display::win::ScreenWin implementation: gfx::Display DesktopScreenWin::GetDisplayMatching( const gfx::Rect& match_rect) const { diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.h b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.h index 8add5bdb3f2..085ba321da1 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.h @@ -6,18 +6,18 @@ #define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_SCREEN_WIN_H_ #include "base/macros.h" -#include "ui/gfx/screen_win.h" +#include "ui/display/win/screen_win.h" #include "ui/views/views_export.h" namespace views { -class VIEWS_EXPORT DesktopScreenWin : public gfx::ScreenWin { +class VIEWS_EXPORT DesktopScreenWin : public display::win::ScreenWin { public: DesktopScreenWin(); ~DesktopScreenWin() override; private: - // Overridden from gfx::ScreenWin: + // Overridden from display::win::ScreenWin: gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override; HWND GetHWNDFromNativeView(gfx::NativeView window) const override; gfx::NativeWindow GetNativeWindowFromHWND(HWND hwnd) const override; diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc index 07bcfca6189..6ffd94a3c89 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc @@ -20,6 +20,7 @@ #include "ui/display/util/x11/edid_parser_x11.h" #include "ui/events/platform/platform_event_source.h" #include "ui/gfx/display.h" +#include "ui/gfx/font_render_params.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/native_widget_types.h" @@ -38,9 +39,12 @@ const int64_t kConfigureDelayMs = 500; double GetDeviceScaleFactor() { float device_scale_factor = 1.0f; - if (views::LinuxUI::instance()) + if (views::LinuxUI::instance()) { device_scale_factor = views::LinuxUI::instance()->GetDeviceScaleFactor(); + } else if (gfx::Display::HasForceDeviceScaleFactor()) { + device_scale_factor = gfx::Display::GetForcedDeviceScaleFactor(); + } return device_scale_factor; } @@ -104,9 +108,9 @@ DesktopScreenX11::DesktopScreenX11() RROutputChangeNotifyMask | RRCrtcChangeNotifyMask); - displays_ = BuildDisplaysFromXRandRInfo(); + SetDisplaysInternal(BuildDisplaysFromXRandRInfo()); } else { - displays_ = GetFallbackDisplayList(); + SetDisplaysInternal(GetFallbackDisplayList()); } } @@ -255,7 +259,7 @@ uint32_t DesktopScreenX11::DispatchEvent(const ui::PlatformEvent& event) { // static void DesktopScreenX11::UpdateDeviceScaleFactorForTest() { DesktopScreenX11* screen = - static_cast<DesktopScreenX11*>(gfx::Screen::GetNativeScreen()); + static_cast<DesktopScreenX11*>(gfx::Screen::GetScreen()); screen->ConfigureTimerFired(); } @@ -310,7 +314,8 @@ std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() { crtc(XRRGetCrtcInfo(xdisplay_, resources.get(), output_info->crtc)); int64_t display_id = -1; - if (!ui::GetDisplayId(output_id, static_cast<uint8_t>(i), &display_id)) { + if (!ui::EDIDParserX11(output_id).GetDisplayId(static_cast<uint8_t>(i), + &display_id)) { // It isn't ideal, but if we can't parse the EDID data, fallback on the // display number. display_id = i; @@ -362,11 +367,17 @@ std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() { void DesktopScreenX11::ConfigureTimerFired() { std::vector<gfx::Display> old_displays = displays_; - displays_ = BuildDisplaysFromXRandRInfo(); - + SetDisplaysInternal(BuildDisplaysFromXRandRInfo()); change_notifier_.NotifyDisplaysChanged(old_displays, displays_); } +void DesktopScreenX11::SetDisplaysInternal( + const std::vector<gfx::Display>& displays) { + displays_ = displays; + gfx::SetFontRenderParamsDeviceScaleFactor( + GetPrimaryDisplay().device_scale_factor()); +} + //////////////////////////////////////////////////////////////////////////////// gfx::Screen* CreateDesktopScreen() { diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h index c49d4daf28b..e96d983ccb2 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h @@ -8,6 +8,7 @@ #include <stdint.h> #include "base/macros.h" +#include "base/memory/scoped_ptr.h" #include "base/timer/timer.h" #include "ui/events/platform/platform_event_dispatcher.h" #include "ui/gfx/display_change_notifier.h" @@ -70,6 +71,9 @@ class VIEWS_EXPORT DesktopScreenX11 : public gfx::Screen, // We delay updating the display so we can coalesce events. void ConfigureTimerFired(); + // Updates |displays_| and sets FontRenderParams's scale factor. + void SetDisplaysInternal(const std::vector<gfx::Display>& displays); + Display* xdisplay_; ::Window x_root_window_; diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc index c527545c4b0..a2e2d2aed7e 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc @@ -16,6 +16,7 @@ #include "ui/base/x/x11_util.h" #include "ui/events/test/event_generator.h" #include "ui/gfx/display_observer.h" +#include "ui/gfx/font_render_params.h" #include "ui/gfx/x/x11_types.h" #include "ui/views/test/views_test_base.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" @@ -83,9 +84,10 @@ class DesktopScreenX11Test : public views::ViewsTestBase, DesktopScreenX11* screen() { return screen_.get(); } void NotifyDisplaysChanged(const std::vector<gfx::Display>& displays) { - DesktopScreenX11* screen = screen_.get(); - screen->change_notifier_.NotifyDisplaysChanged(screen->displays_, displays); - screen->displays_ = displays; + std::vector<gfx::Display> old_displays = screen_->displays_; + screen_->SetDisplaysInternal(displays); + screen_->change_notifier_.NotifyDisplaysChanged(old_displays, + screen_->displays_); } void ResetDisplayChanges() { @@ -439,6 +441,7 @@ TEST_F(DesktopScreenX11Test, DeviceScaleFactorChange) { displays[0].set_device_scale_factor(2.5f); NotifyDisplaysChanged(displays); EXPECT_EQ(1u, changed_display_.size()); + EXPECT_EQ(2.5f, gfx::GetFontRenderParamsDeviceScaleFactor()); displays[1].set_device_scale_factor(2.5f); NotifyDisplaysChanged(displays); @@ -456,6 +459,7 @@ TEST_F(DesktopScreenX11Test, DeviceScaleFactorChange) { displays[1].set_device_scale_factor(1.f); NotifyDisplaysChanged(displays); EXPECT_EQ(4u, changed_display_.size()); + EXPECT_EQ(1.f, gfx::GetFontRenderParamsDeviceScaleFactor()); } } // namespace views diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc index c354154a542..fa9ea48b500 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc @@ -125,6 +125,7 @@ void DesktopWindowTreeHostWin::Init(aura::Window* content_window, const Widget::InitParams& params) { // TODO(beng): SetInitParams(). content_window_ = content_window; + wants_mouse_events_when_inactive_ = params.wants_mouse_events_when_inactive; aura::client::SetAnimationHost(content_window_, this); @@ -136,8 +137,7 @@ void DesktopWindowTreeHostWin::Init(aura::Window* content_window, if (params.parent && params.parent->GetHost()) parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget(); - message_handler_->set_remove_standard_frame(params.remove_standard_frame); - + remove_standard_frame_ = params.remove_standard_frame; has_non_client_view_ = Widget::RequiresNonClientView(params.type); gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(params.bounds); @@ -587,24 +587,30 @@ void DesktopWindowTreeHostWin::OnWindowHidingAnimationCompleted() { //////////////////////////////////////////////////////////////////////////////// // DesktopWindowTreeHostWin, HWNDMessageHandlerDelegate implementation: -bool DesktopWindowTreeHostWin::IsWidgetWindow() const { +bool DesktopWindowTreeHostWin::HasNonClientView() const { return has_non_client_view_; } -bool DesktopWindowTreeHostWin::IsUsingCustomFrame() const { - return !GetWidget()->ShouldUseNativeFrame(); +FrameMode DesktopWindowTreeHostWin::GetFrameMode() const { + return GetWidget()->ShouldUseNativeFrame() ? FrameMode::SYSTEM_DRAWN + : FrameMode::CUSTOM_DRAWN; +} + +bool DesktopWindowTreeHostWin::HasFrame() const { + return !remove_standard_frame_; } void DesktopWindowTreeHostWin::SchedulePaint() { GetWidget()->GetRootView()->SchedulePaint(); } -void DesktopWindowTreeHostWin::EnableInactiveRendering() { - native_widget_delegate_->EnableInactiveRendering(); +void DesktopWindowTreeHostWin::SetAlwaysRenderAsActive( + bool always_render_as_active) { + native_widget_delegate_->SetAlwaysRenderAsActive(always_render_as_active); } -bool DesktopWindowTreeHostWin::IsInactiveRenderingDisabled() { - return native_widget_delegate_->IsInactiveRenderingDisabled(); +bool DesktopWindowTreeHostWin::IsAlwaysRenderAsActive() { + return native_widget_delegate_->IsAlwaysRenderAsActive(); } bool DesktopWindowTreeHostWin::CanResize() const { @@ -626,7 +632,7 @@ bool DesktopWindowTreeHostWin::CanActivate() const { } bool DesktopWindowTreeHostWin::WantsMouseEventsWhenInactive() const { - return false; + return wants_mouse_events_when_inactive_; } bool DesktopWindowTreeHostWin::WidgetSizeIsClientSize() const { @@ -692,7 +698,7 @@ bool DesktopWindowTreeHostWin::ShouldHandleSystemCommands() const { } void DesktopWindowTreeHostWin::HandleAppDeactivated() { - native_widget_delegate_->EnableInactiveRendering(); + native_widget_delegate_->SetAlwaysRenderAsActive(false); } void DesktopWindowTreeHostWin::HandleActivationChanged(bool active) { @@ -911,9 +917,11 @@ void DesktopWindowTreeHostWin::HandleWindowSizeChanged() { // changed (can occur on Windows 10 when snapping a window to the side of // the screen). In that case do a resize to the current size to reenable // swaps. - if (compositor()) - compositor()->SetScaleAndSize(compositor()->device_scale_factor(), - compositor()->size()); + if (compositor()) { + compositor()->SetScaleAndSize( + compositor()->device_scale_factor(), + message_handler_->GetClientAreaBounds().size()); + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h index ad82485eb0c..3465112eac0 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h @@ -126,11 +126,12 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin void OnWindowHidingAnimationCompleted() override; // Overridden from HWNDMessageHandlerDelegate: - bool IsWidgetWindow() const override; - bool IsUsingCustomFrame() const override; + bool HasNonClientView() const override; + FrameMode GetFrameMode() const override; + bool HasFrame() const override; void SchedulePaint() override; - void EnableInactiveRendering() override; - bool IsInactiveRenderingDisabled() override; + void SetAlwaysRenderAsActive(bool always_render_as_active) override; + bool IsAlwaysRenderAsActive() override; bool CanResize() const override; bool CanMaximize() const override; bool CanMinimize() const override; @@ -244,6 +245,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin // Init time, before the Widget has created the NonClientView. bool has_non_client_view_; + // True if the window should have the frame removed. + bool remove_standard_frame_; + // Owned by TooltipController, but we need to forward events to it so we keep // a reference. corewm::TooltipWin* tooltip_; @@ -256,6 +260,10 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin scoped_ptr<aura::client::ScopedTooltipDisabler> tooltip_disabler_; + // Indicates if current window will receive mouse events when should not + // become activated. + bool wants_mouse_events_when_inactive_ = false; + DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostWin); }; diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index e2fb724b914..cecae1ee81d 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc @@ -109,7 +109,7 @@ const char* kAtomsToCache[] = { "_NET_WM_WINDOW_TYPE_NOTIFICATION", "_NET_WM_WINDOW_TYPE_TOOLTIP", "XdndActionAsk", - "XdndActionCopy" + "XdndActionCopy", "XdndActionLink", "XdndActionList", "XdndActionMove", @@ -820,7 +820,7 @@ void DesktopWindowTreeHostX11::SetFullscreen(bool fullscreen) { if (fullscreen) { restored_bounds_in_pixels_ = bounds_in_pixels_; const gfx::Display display = - gfx::Screen::GetScreenFor(NULL)->GetDisplayNearestWindow(window()); + gfx::Screen::GetScreen()->GetDisplayNearestWindow(window()); bounds_in_pixels_ = ToPixelRect(display.bounds()); } else { bounds_in_pixels_ = restored_bounds_in_pixels_; @@ -938,10 +938,10 @@ void DesktopWindowTreeHostX11::SizeConstraintsChanged() { // DesktopWindowTreeHostX11, aura::WindowTreeHost implementation: gfx::Transform DesktopWindowTreeHostX11::GetRootTransform() const { - gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); + gfx::Display display = gfx::Screen::GetScreen()->GetPrimaryDisplay(); if (window_mapped_) { aura::Window* win = const_cast<aura::Window*>(window()); - display = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(win); + display = gfx::Screen::GetScreen()->GetDisplayNearestWindow(win); } float scale = display.device_scale_factor(); @@ -1287,7 +1287,7 @@ void DesktopWindowTreeHostX11::InitX11Window( gfx::Size DesktopWindowTreeHostX11::AdjustSize( const gfx::Size& requested_size_in_pixels) { std::vector<gfx::Display> displays = - gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE)->GetAllDisplays(); + gfx::Screen::GetScreen()->GetAllDisplays(); // Compare against all monitor sizes. The window manager can move the window // to whichever monitor it wants. for (size_t i = 0; i < displays.size(); ++i) { @@ -1533,9 +1533,9 @@ void DesktopWindowTreeHostX11::ConvertEventToDifferentHost( DesktopWindowTreeHostX11* host) { DCHECK_NE(this, host); const gfx::Display display_src = - gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(window()); + gfx::Screen::GetScreen()->GetDisplayNearestWindow(window()); const gfx::Display display_dest = - gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(host->window()); + gfx::Screen::GetScreen()->GetDisplayNearestWindow(host->window()); DCHECK_EQ(display_src.device_scale_factor(), display_dest.device_scale_factor()); gfx::Vector2d offset = GetLocationOnNativeScreen() - diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h index 759194f6b52..7e842fed086 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h +++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h @@ -36,7 +36,6 @@ class EventHandler; namespace views { class DesktopDragDropClientAuraX11; -class DesktopDispatcherClient; class DesktopWindowTreeHostObserverX11; class X11DesktopWindowMoveClient; class X11WindowEventFilter; diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc index 162cf3c49a3..7c2253493ac 100644 --- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc +++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc @@ -24,7 +24,7 @@ #include "ui/base/hit_test.h" #include "ui/base/x/x11_util.h" #include "ui/events/devices/x11/touch_factory_x11.h" -#include "ui/events/platform/x11/x11_event_source.h" +#include "ui/events/platform/x11/x11_event_source_glib.h" #include "ui/events/test/platform_event_source_test_api.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" @@ -68,11 +68,9 @@ class WMStateWaiter : public X11PropertyChangeWaiter { bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override { std::vector<Atom> hints; if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &hints)) { - std::vector<Atom>::iterator it = std::find( - hints.begin(), - hints.end(), - atom_cache_->GetAtom(hint_)); - bool hint_set = (it != hints.end()); + auto it = std::find(hints.cbegin(), hints.cend(), + atom_cache_->GetAtom(hint_)); + bool hint_set = (it != hints.cend()); return hint_set != wait_till_set_; } return true; diff --git a/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc index f5343ad5a2b..46357f60f00 100644 --- a/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc +++ b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc @@ -55,11 +55,9 @@ class MinimizeWaiter : public X11PropertyChangeWaiter { bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override { std::vector<Atom> wm_states; if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &wm_states)) { - std::vector<Atom>::iterator it = std::find( - wm_states.begin(), - wm_states.end(), - atom_cache_->GetAtom("_NET_WM_STATE_HIDDEN")); - return it == wm_states.end(); + auto it = std::find(wm_states.cbegin(), wm_states.cend(), + atom_cache_->GetAtom("_NET_WM_STATE_HIDDEN")); + return it == wm_states.cend(); } return true; } @@ -97,9 +95,8 @@ class StackingClientListWaiter : public X11PropertyChangeWaiter { std::vector<XID> stack; ui::GetXWindowStack(ui::GetX11RootWindow(), &stack); for (size_t i = 0; i < expected_windows_.size(); ++i) { - std::vector<XID>::iterator it = std::find( - stack.begin(), stack.end(), expected_windows_[i]); - if (it == stack.end()) + auto it = std::find(stack.cbegin(), stack.cend(), expected_windows_[i]); + if (it == stack.cend()) return true; } return false; diff --git a/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc b/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc index a33f12ff76e..eca9951d2da 100644 --- a/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc +++ b/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc @@ -22,6 +22,7 @@ #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/keycodes/keyboard_code_conversion_x.h" +#include "ui/events/platform/platform_event_source.h" #include "ui/events/platform/scoped_event_dispatcher.h" #include "ui/events/platform/x11/x11_event_source.h" #include "ui/views/widget/desktop_aura/x11_pointer_grab.h" @@ -81,7 +82,7 @@ uint32_t X11WholeScreenMoveLoop::DispatchEvent(const ui::PlatformEvent& event) { case ui::ET_MOUSE_DRAGGED: { bool dispatch_mouse_event = !last_motion_in_screen_.get(); last_motion_in_screen_.reset( - static_cast<ui::MouseEvent*>(ui::EventFromNative(xev).release())); + ui::EventFromNative(xev).release()->AsMouseEvent()); last_motion_in_screen_->set_location( ui::EventSystemLocationFromNative(xev)); if (dispatch_mouse_event) { diff --git a/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc b/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc index c8f1065d31e..c0ead5563fd 100644 --- a/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc +++ b/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc @@ -151,9 +151,8 @@ void X11WindowEventFilter::OnClickedMaximizeButton(ui::MouseEvent* event) { if (!widget) return; - gfx::Screen* screen = gfx::Screen::GetNativeScreen(); gfx::Rect display_work_area = - screen->GetDisplayNearestWindow(target).work_area(); + gfx::Screen::GetScreen()->GetDisplayNearestWindow(target).work_area(); gfx::Rect bounds = widget->GetWindowBoundsInScreen(); if (event->IsMiddleMouseButton()) { bounds.set_y(display_work_area.y()); diff --git a/chromium/ui/views/widget/desktop_widget_unittest.cc b/chromium/ui/views/widget/desktop_widget_unittest.cc index 6bd67c6ee4a..0004ccab265 100644 --- a/chromium/ui/views/widget/desktop_widget_unittest.cc +++ b/chromium/ui/views/widget/desktop_widget_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ui/views/test/native_widget_factory.h" #include "ui/views/test/views_test_base.h" #include "ui/views/test/widget_test.h" #include "ui/views/widget/widget.h" @@ -18,7 +19,8 @@ TEST_F(DesktopScreenPositionClientTest, PositionDialog) { Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); params.bounds = gfx::Rect(10, 11, 200, 200); params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.native_widget = new PlatformDesktopNativeWidget(&parent_widget); + params.native_widget = test::CreatePlatformDesktopNativeWidgetImpl( + params, &parent_widget, nullptr); parent_widget.Init(params); // Owned by |dialog|. @@ -52,7 +54,8 @@ TEST_F(DesktopScreenPositionClientTest, PositionControlWithNonRootParent) { CreateParams(Widget::InitParams::TYPE_WINDOW); params1.bounds = gfx::Rect(origin, gfx::Size(700, 600)); params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params1.native_widget = new PlatformDesktopNativeWidget(&widget1); + params1.native_widget = + test::CreatePlatformDesktopNativeWidgetImpl(params1, &widget1, nullptr); widget1.Init(params1); Widget::InitParams params2 = diff --git a/chromium/ui/views/widget/native_widget_aura.cc b/chromium/ui/views/widget/native_widget_aura.cc index fb2396c8399..4f24e5caced 100644 --- a/chromium/ui/views/widget/native_widget_aura.cc +++ b/chromium/ui/views/widget/native_widget_aura.cc @@ -137,8 +137,8 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) { // If a parent is specified but no bounds are given, // use the origin of the parent's display so that the widget // will be added to the same display as the parent. - gfx::Rect bounds = gfx::Screen::GetScreenFor(parent)-> - GetDisplayNearestWindow(parent).bounds(); + gfx::Rect bounds = + gfx::Screen::GetScreen()->GetDisplayNearestWindow(parent).bounds(); window_bounds.set_origin(bounds.origin()); } } @@ -283,8 +283,8 @@ void NativeWidgetAura::CenterWindow(const gfx::Size& size) { // When centering window, we take the intersection of the host and // the parent. We assume the root window represents the visible // rect of a single screen. - gfx::Rect work_area = gfx::Screen::GetScreenFor(window_)-> - GetDisplayNearestWindow(window_).work_area(); + gfx::Rect work_area = + gfx::Screen::GetScreen()->GetDisplayNearestWindow(window_).work_area(); aura::client::ScreenPositionClient* screen_position_client = aura::client::GetScreenPositionClient(window_->GetRootWindow()); @@ -404,7 +404,7 @@ void NativeWidgetAura::SetBounds(const gfx::Rect& bounds) { aura::client::GetScreenPositionClient(root); if (screen_position_client) { gfx::Display dst_display = - gfx::Screen::GetScreenFor(window_)->GetDisplayMatching(bounds); + gfx::Screen::GetScreen()->GetDisplayMatching(bounds); screen_position_client->SetBounds(window_, bounds, dst_display); return; } @@ -495,7 +495,10 @@ void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) { // SetInitialFocus() should be always be called, even for // SHOW_STATE_INACTIVE. If the window has to stay inactive, the method will // do the right thing. - SetInitialFocus(state); + // Activate() might fail if the window is non-activatable. In this case, we + // should pass SHOW_STATE_INACTIVE to SetInitialFocus() to stop the initial + // focused view from getting focused. See crbug.com/515594 for example. + SetInitialFocus(IsActive() ? state : ui::SHOW_STATE_INACTIVE); } // On desktop aura, a window is activated first even when it is shown as @@ -595,10 +598,6 @@ void NativeWidgetAura::SetOpacity(unsigned char opacity) { window_->layer()->SetOpacity(opacity / 255.0); } -void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) { - NOTIMPLEMENTED(); -} - void NativeWidgetAura::FlashFrame(bool flash) { if (window_) window_->SetProperty(aura::client::kDrawAttentionKey, flash); @@ -643,8 +642,7 @@ void NativeWidgetAura::ClearNativeFocus() { gfx::Rect NativeWidgetAura::GetWorkAreaBoundsInScreen() const { if (!window_) return gfx::Rect(); - return gfx::Screen::GetScreenFor(window_)-> - GetDisplayNearestWindow(window_).work_area(); + return gfx::Screen::GetScreen()->GetDisplayNearestWindow(window_).work_area(); } Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop( @@ -875,7 +873,6 @@ void NativeWidgetAura::OnKeyEvent(ui::KeyEvent* event) { return; delegate_->OnKeyEvent(event); - event->SetHandled(); } void NativeWidgetAura::OnMouseEvent(ui::MouseEvent* event) { diff --git a/chromium/ui/views/widget/native_widget_aura.h b/chromium/ui/views/widget/native_widget_aura.h index 30bf169c784..9e27cca806b 100644 --- a/chromium/ui/views/widget/native_widget_aura.h +++ b/chromium/ui/views/widget/native_widget_aura.h @@ -42,8 +42,8 @@ class VIEWS_EXPORT NativeWidgetAura public: explicit NativeWidgetAura(internal::NativeWidgetDelegate* delegate); - // Called internally by NativeWidget implementations to associate - // |native_widget| with |window|. + // Called internally by NativeWidgetAura and DesktopNativeWidgetAura to + // associate |native_widget| with |window|. static void RegisterNativeWidgetForWindow( internal::NativeWidgetPrivate* native_widget, aura::Window* window); @@ -108,7 +108,6 @@ class VIEWS_EXPORT NativeWidgetAura void SetFullscreen(bool fullscreen) override; bool IsFullscreen() const override; void SetOpacity(unsigned char opacity) override; - void SetUseDragFrame(bool use_drag_frame) override; void FlashFrame(bool flash_frame) override; void RunShellDrag(View* view, const ui::OSExchangeData& data, diff --git a/chromium/ui/views/widget/native_widget_aura_unittest.cc b/chromium/ui/views/widget/native_widget_aura_unittest.cc index f10981f2327..0a626ae45a1 100644 --- a/chromium/ui/views/widget/native_widget_aura_unittest.cc +++ b/chromium/ui/views/widget/native_widget_aura_unittest.cc @@ -19,9 +19,12 @@ #include "ui/events/event_utils.h" #include "ui/gfx/screen.h" #include "ui/views/layout/fill_layout.h" +#include "ui/views/test/widget_test.h" #include "ui/views/widget/root_view.h" #include "ui/views/widget/widget_delegate.h" +#include "ui/wm/core/base_focus_rules.h" #include "ui/wm/core/default_activation_client.h" +#include "ui/wm/core/focus_controller.h" namespace views { namespace { @@ -34,19 +37,50 @@ NativeWidgetAura* Init(aura::Window* parent, Widget* widget) { return static_cast<NativeWidgetAura*>(widget->native_widget()); } +// TestFocusRules is intended to provide a way to manually set a window's +// activatability so that the focus rules can be tested. +class TestFocusRules : public wm::BaseFocusRules { + public: + TestFocusRules() {} + ~TestFocusRules() override {} + + void set_can_activate(bool can_activate) { can_activate_ = can_activate; } + + // wm::BaseFocusRules overrides: + bool SupportsChildActivation(aura::Window* window) const override { + return true; + } + + bool CanActivateWindow(aura::Window* window) const override { + return can_activate_; + } + + private: + bool can_activate_ = true; + + DISALLOW_COPY_AND_ASSIGN(TestFocusRules); +}; + class NativeWidgetAuraTest : public aura::test::AuraTestBase { public: NativeWidgetAuraTest() {} ~NativeWidgetAuraTest() override {} + TestFocusRules* test_focus_rules() { return test_focus_rules_; } + // testing::Test overrides: void SetUp() override { AuraTestBase::SetUp(); - new wm::DefaultActivationClient(root_window()); + test_focus_rules_ = new TestFocusRules; + focus_controller_.reset(new wm::FocusController(test_focus_rules_)); + aura::client::SetActivationClient(root_window(), focus_controller_.get()); host()->SetBounds(gfx::Rect(640, 480)); } private: + scoped_ptr<wm::FocusController> focus_controller_; + TestFocusRules* test_focus_rules_; + DISALLOW_COPY_AND_ASSIGN(NativeWidgetAuraTest); }; @@ -485,5 +519,20 @@ TEST_F(NativeWidgetAuraTest, OnWidgetMovedInvokedAfterAcquireLayer) { widget->CloseNow(); } +// Tests that if a widget has a view which should be initially focused when the +// widget is shown, this view should not get focused if the associated window +// can not be activated. +TEST_F(NativeWidgetAuraTest, PreventFocusOnNonActivableWindow) { + test_focus_rules()->set_can_activate(false); + views::test::TestInitialFocusWidgetDelegate delegate(root_window()); + delegate.GetWidget()->Show(); + EXPECT_FALSE(delegate.view()->HasFocus()); + + test_focus_rules()->set_can_activate(true); + views::test::TestInitialFocusWidgetDelegate delegate2(root_window()); + delegate2.GetWidget()->Show(); + EXPECT_TRUE(delegate2.view()->HasFocus()); +} + } // namespace } // namespace views diff --git a/chromium/ui/views/widget/native_widget_delegate.h b/chromium/ui/views/widget/native_widget_delegate.h index 224972c2d12..033db2bf107 100644 --- a/chromium/ui/views/widget/native_widget_delegate.h +++ b/chromium/ui/views/widget/native_widget_delegate.h @@ -51,8 +51,12 @@ class VIEWS_EXPORT NativeWidgetDelegate { // Returns true if the window can be activated. virtual bool CanActivate() const = 0; - virtual bool IsInactiveRenderingDisabled() const = 0; - virtual void EnableInactiveRendering() = 0; + // Prevents the window from being rendered as deactivated. This state is + // reset automatically as soon as the window becomes activated again. There is + // no ability to control the state through this API as this leads to sync + // problems. + virtual void SetAlwaysRenderAsActive(bool always_render_as_active) = 0; + virtual bool IsAlwaysRenderAsActive() const = 0; // Called when the activation state of a window has changed. virtual void OnNativeWidgetActivationChanged(bool active) = 0; @@ -113,11 +117,10 @@ class VIEWS_EXPORT NativeWidgetDelegate { // |point|, in client coordinates. virtual int GetNonClientComponent(const gfx::Point& point) = 0; - // Mouse and key event handlers. + // Event handlers. virtual void OnKeyEvent(ui::KeyEvent* event) = 0; virtual void OnMouseEvent(ui::MouseEvent* event) = 0; virtual void OnMouseCaptureLost() = 0; - virtual void OnScrollEvent(ui::ScrollEvent* event) = 0; virtual void OnGestureEvent(ui::GestureEvent* event) = 0; @@ -133,7 +136,6 @@ class VIEWS_EXPORT NativeWidgetDelegate { // Provides the hit-test mask if HasHitTestMask above returns true. virtual void GetHitTestMask(gfx::Path* mask) const = 0; - // virtual Widget* AsWidget() = 0; virtual const Widget* AsWidget() const = 0; diff --git a/chromium/ui/views/widget/native_widget_mac.h b/chromium/ui/views/widget/native_widget_mac.h index f2f79181a05..1b7deb2c801 100644 --- a/chromium/ui/views/widget/native_widget_mac.h +++ b/chromium/ui/views/widget/native_widget_mac.h @@ -107,7 +107,6 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate { void SetFullscreen(bool fullscreen) override; bool IsFullscreen() const override; void SetOpacity(unsigned char opacity) override; - void SetUseDragFrame(bool use_drag_frame) override; void FlashFrame(bool flash_frame) override; void RunShellDrag(View* view, const ui::OSExchangeData& data, diff --git a/chromium/ui/views/widget/native_widget_mac.mm b/chromium/ui/views/widget/native_widget_mac.mm index f61ff8171a5..126623ff0e7 100644 --- a/chromium/ui/views/widget/native_widget_mac.mm +++ b/chromium/ui/views/widget/native_widget_mac.mm @@ -193,8 +193,10 @@ const ui::Layer* NativeWidgetMac::GetLayer() const { } void NativeWidgetMac::ReorderNativeViews() { - if (bridge_) + if (bridge_) { bridge_->SetRootView(GetWidget()->GetRootView()); + bridge_->ReorderChildViews(); + } } void NativeWidgetMac::ViewRemoved(View* view) { @@ -410,6 +412,10 @@ void NativeWidgetMac::ShowWithWindowState(ui::WindowShowState state) { bridge_->SetVisibilityState(state == ui::SHOW_STATE_INACTIVE ? BridgedNativeWidget::SHOW_INACTIVE : BridgedNativeWidget::SHOW_AND_ACTIVATE_WINDOW); + + // Ignore the SetInitialFocus() result. BridgedContentView should get + // firstResponder status regardless. + delegate_->SetInitialFocus(state); } bool NativeWidgetMac::IsVisible() const { @@ -484,11 +490,7 @@ bool NativeWidgetMac::IsFullscreen() const { } void NativeWidgetMac::SetOpacity(unsigned char opacity) { - NOTIMPLEMENTED(); -} - -void NativeWidgetMac::SetUseDragFrame(bool use_drag_frame) { - NOTIMPLEMENTED(); + [GetNativeWindow() setAlphaValue:opacity / 255.0]; } void NativeWidgetMac::FlashFrame(bool flash_frame) { @@ -504,9 +506,15 @@ void NativeWidgetMac::RunShellDrag(View* view, } void NativeWidgetMac::SchedulePaintInRect(const gfx::Rect& rect) { - // TODO(tapted): This should use setNeedsDisplayInRect:, once the coordinate - // system of |rect| has been converted. - [GetNativeView() setNeedsDisplay:YES]; + // |rect| is relative to client area of the window. + NSWindow* window = GetNativeWindow(); + NSRect client_rect = [window contentRectForFrameRect:[window frame]]; + NSRect target_rect = rect.ToCGRect(); + + // Convert to Appkit coordinate system (origin at bottom left). + target_rect.origin.y = + NSHeight(client_rect) - target_rect.origin.y - NSHeight(target_rect); + [GetNativeView() setNeedsDisplayInRect:target_rect]; if (bridge_ && bridge_->layer()) bridge_->layer()->SchedulePaint(rect); } diff --git a/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm b/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm index 8f192662b24..528f67d42a7 100644 --- a/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm +++ b/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm @@ -6,8 +6,10 @@ #import <Cocoa/Cocoa.h> +#import "base/mac/mac_util.h" #import "base/mac/scoped_nsobject.h" #include "base/macros.h" +#include "ui/base/test/ui_controls.h" #import "ui/base/test/windowed_nsnotification_observer.h" #include "ui/views/test/test_widget_observer.h" #include "ui/views/test/widget_test.h" @@ -24,7 +26,11 @@ class NativeWidgetMacInteractiveUITest class Observer; NativeWidgetMacInteractiveUITest() - : activationCount_(0), deactivationCount_(0) {} + : activationCount_(0), deactivationCount_(0) { + // TODO(tapted): Remove this when these are absorbed into Chrome's + // interactive_ui_tests target. See http://crbug.com/403679. + ui_controls::EnableUIControls(); + } Widget* MakeWidget() { return GetParam() ? CreateTopLevelFramelessPlatformWidget() @@ -133,6 +139,79 @@ TEST_P(NativeWidgetMacInteractiveUITest, ShowInactiveIgnoresKeyStatus) { widget->CloseNow(); } +namespace { + +// Show |widget| and wait for it to become the key window. +void ShowKeyWindow(Widget* widget) { + base::scoped_nsobject<WindowedNSNotificationObserver> waiter( + [[WindowedNSNotificationObserver alloc] + initForNotification:NSWindowDidBecomeKeyNotification + object:widget->GetNativeWindow()]); + widget->Show(); + EXPECT_TRUE([waiter wait]); + EXPECT_TRUE([widget->GetNativeWindow() isKeyWindow]); +} + +NSData* ViewAsTIFF(NSView* view) { + NSBitmapImageRep* bitmap = + [view bitmapImageRepForCachingDisplayInRect:[view bounds]]; + [view cacheDisplayInRect:[view bounds] toBitmapImageRep:bitmap]; + return [bitmap TIFFRepresentation]; +} + +} // namespace + +// Test that parent windows keep their traffic lights enabled when showing +// dialogs. +TEST_F(NativeWidgetMacInteractiveUITest, ParentWindowTrafficLights) { + Widget* parent_widget = CreateTopLevelPlatformWidget(); + parent_widget->SetBounds(gfx::Rect(100, 100, 100, 100)); + ShowKeyWindow(parent_widget); + + NSWindow* parent = parent_widget->GetNativeWindow(); + EXPECT_TRUE([parent isMainWindow]); + + NSButton* button = [parent standardWindowButton:NSWindowCloseButton]; + EXPECT_TRUE(button); + NSData* active_button_image = ViewAsTIFF(button); + EXPECT_TRUE(active_button_image); + + // Create an activatable frameless child. Frameless so that it doesn't have + // traffic lights of its own, and activatable so that it can take key status. + Widget* child_widget = new Widget; + Widget::InitParams params(Widget::InitParams::TYPE_WINDOW_FRAMELESS); + params.native_widget = new NativeWidgetMac(child_widget); + params.bounds = gfx::Rect(130, 130, 100, 100); + params.parent = parent_widget->GetNativeView(); + child_widget->Init(params); + ShowKeyWindow(child_widget); + + // Ensure the button instance is still valid. + EXPECT_EQ(button, [parent standardWindowButton:NSWindowCloseButton]); + + // Parent window should still be main, and have its traffic lights active. + EXPECT_TRUE([parent isMainWindow]); + EXPECT_FALSE([parent isKeyWindow]); + + // Enabled status doesn't actually change, but check anyway. + EXPECT_TRUE([button isEnabled]); + NSData* button_image_with_child = ViewAsTIFF(button); + EXPECT_TRUE([active_button_image isEqualToData:button_image_with_child]); + + // Verify that activating some other random window does change the button. + Widget* other_widget = CreateTopLevelPlatformWidget(); + other_widget->SetBounds(gfx::Rect(200, 200, 100, 100)); + ShowKeyWindow(other_widget); + EXPECT_FALSE([parent isMainWindow]); + EXPECT_FALSE([parent isKeyWindow]); + EXPECT_TRUE([button isEnabled]); + NSData* inactive_button_image = ViewAsTIFF(button); + EXPECT_FALSE([active_button_image isEqualToData:inactive_button_image]); + + other_widget->CloseNow(); + parent_widget->CloseNow(); +} + INSTANTIATE_TEST_CASE_P(NativeWidgetMacInteractiveUITestInstance, NativeWidgetMacInteractiveUITest, ::testing::Bool()); diff --git a/chromium/ui/views/widget/native_widget_mac_unittest.mm b/chromium/ui/views/widget/native_widget_mac_unittest.mm index 5a48f025722..ba095dfbeeb 100644 --- a/chromium/ui/views/widget/native_widget_mac_unittest.mm +++ b/chromium/ui/views/widget/native_widget_mac_unittest.mm @@ -22,13 +22,17 @@ #import "ui/events/test/cocoa_test_event_utils.h" #include "ui/events/test/event_generator.h" #import "ui/gfx/mac/coordinate_conversion.h" +#include "ui/views/bubble/bubble_delegate.h" #import "ui/views/cocoa/bridged_native_widget.h" #import "ui/views/cocoa/native_widget_mac_nswindow.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/label.h" +#include "ui/views/controls/native/native_view_host.h" #include "ui/views/native_cursor.h" +#include "ui/views/test/native_widget_factory.h" #include "ui/views/test/test_widget_observer.h" #include "ui/views/test/widget_test.h" +#include "ui/views/widget/native_widget_mac.h" #include "ui/views/widget/native_widget_private.h" #include "ui/views/window/dialog_delegate.h" @@ -53,6 +57,24 @@ @property(readonly, nonatomic) int invalidateShadowCount; @end +// Used to mock BridgedContentView so that calls to drawRect: can be +// intercepted. +@interface MockBridgedView : NSView { + @private + // Number of times -[NSView drawRect:] has been called. + NSUInteger drawRectCount_; + + // The dirtyRect parameter passed to last invocation of drawRect:. + NSRect lastDirtyRect_; +} + +@property(assign, nonatomic) NSUInteger drawRectCount; +@property(assign, nonatomic) NSRect lastDirtyRect; +@end + +@interface FocusableTestNSView : NSView +@end + namespace views { namespace test { @@ -190,6 +212,30 @@ class WidgetChangeObserver : public TestWidgetObserver { DISALLOW_COPY_AND_ASSIGN(WidgetChangeObserver); }; +class NativeHostHolder { + public: + NativeHostHolder() + : view_([[NSView alloc] init]), host_(new NativeViewHost()) { + host_->set_owned_by_client(); + } + + void AttachNativeView() { + DCHECK(!host_->native_view()); + host_->Attach(view_.get()); + } + + void Detach() { host_->Detach(); } + + gfx::NativeView view() const { return view_.get(); } + NativeViewHost* host() const { return host_.get(); } + + private: + base::scoped_nsobject<NSView> view_; + scoped_ptr<NativeViewHost> host_; + + DISALLOW_COPY_AND_ASSIGN(NativeHostHolder); +}; + // Test visibility states triggered externally. TEST_F(NativeWidgetMacTest, HideAndShowExternally) { Widget* widget = CreateTopLevelPlatformWidget(); @@ -468,8 +514,9 @@ TEST_F(NativeWidgetMacTest, SetCursor) { EXPECT_NE(arrow, hand); EXPECT_NE(arrow, ibeam); - // At the start of the test, the cursor stack should be empty. - EXPECT_FALSE([NSCursor currentCursor]); + // Make arrow the current cursor. + [arrow set]; + EXPECT_EQ(arrow, [NSCursor currentCursor]); // Use an event generator to ask views code to set the cursor. However, note // that this does not cause Cocoa to generate tracking rectangle updates. @@ -477,7 +524,7 @@ TEST_F(NativeWidgetMacTest, SetCursor) { widget->GetNativeWindow()); // Move the mouse over the first view, then simulate a tracking rectangle - // update. + // update. Verify that the cursor changed from arrow to hand type. event_generator.MoveMouseTo(gfx::Point(50, 50)); [widget->GetNativeWindow() cursorUpdate:event_in_content]; EXPECT_EQ(hand, [NSCursor currentCursor]); @@ -534,12 +581,12 @@ TEST_F(NativeWidgetMacTest, NonWidgetParent) { [[native_parent contentView] addSubview:anchor_view]; // Note: Don't use WidgetTest::CreateChildPlatformWidget because that makes - // windows of TYPE_CONTROL which are automatically made visible. But still - // mark it as a child to test window positioning. + // windows of TYPE_CONTROL which need a parent Widget to obtain the focus + // manager. Widget* child = new Widget; Widget::InitParams init_params; init_params.parent = anchor_view; - init_params.child = true; + init_params.type = Widget::InitParams::TYPE_POPUP; child->Init(init_params); TestWidgetObserver child_observer(child); @@ -556,7 +603,8 @@ TEST_F(NativeWidgetMacTest, NonWidgetParent) { NativeWidgetMac::GetBridgeForNativeWindow(child->GetNativeWindow()); EXPECT_EQ(native_parent, bridged_native_widget->parent()->GetNSWindow()); - child->SetBounds(gfx::Rect(50, 50, 200, 100)); + const gfx::Rect child_bounds(50, 50, 200, 100); + child->SetBounds(child_bounds); EXPECT_FALSE(child->IsVisible()); EXPECT_EQ(0u, [[native_parent childWindows] count]); @@ -567,11 +615,9 @@ TEST_F(NativeWidgetMacTest, NonWidgetParent) { [[native_parent childWindows] objectAtIndex:0]); EXPECT_EQ(native_parent, [child->GetNativeWindow() parentWindow]); - // Child should be positioned on screen relative to the parent, but note we - // positioned the parent in Cocoa coordinates, so we need to convert. - gfx::Point parent_origin = gfx::ScreenRectFromNSRect(ParentRect()).origin(); - EXPECT_EQ(gfx::Rect(150, parent_origin.y() + 50, 200, 100), - child->GetWindowBoundsInScreen()); + // Only non-toplevel Widgets are positioned relative to the parent, so the + // bounds set above should be in screen coordinates. + EXPECT_EQ(child_bounds, child->GetWindowBoundsInScreen()); // Removing the anchor_view from its view hierarchy is permitted. This should // not break the relationship between the two windows. @@ -918,6 +964,96 @@ TEST_F(NativeWidgetMacTest, NoopReparentNativeView) { parent_widget->CloseNow(); } +// Attaches a child window to |parent| that checks its parent's delegate is +// cleared when the child is destroyed. This assumes the child is destroyed via +// destruction of its parent. +class ParentCloseMonitor : public WidgetObserver { + public: + explicit ParentCloseMonitor(Widget* parent) { + Widget* child = new Widget(); + child->AddObserver(this); + Widget::InitParams init_params(Widget::InitParams::TYPE_WINDOW_FRAMELESS); + init_params.parent = parent->GetNativeView(); + init_params.bounds = gfx::Rect(100, 100, 100, 100); + init_params.native_widget = + CreatePlatformNativeWidgetImpl(init_params, child, kStubCapture, + nullptr); + child->Init(init_params); + child->Show(); + + // NSWindow parent/child relationship should be established on Show() and + // the parent should have a delegate. Retain the parent since it can't be + // retrieved from the child while it is being destroyed. + parent_nswindow_.reset([[child->GetNativeWindow() parentWindow] retain]); + EXPECT_TRUE(parent_nswindow_); + EXPECT_TRUE([parent_nswindow_ delegate]); + } + + ~ParentCloseMonitor() override { + EXPECT_TRUE(child_closed_); // Otherwise the observer wasn't removed. + } + + void OnWidgetDestroying(Widget* child) override { + // Upon a parent-triggered close, the NSWindow relationship will already be + // removed. The parent should still be open (children are always closed + // first), but not have a delegate (since it is being torn down). + EXPECT_FALSE([child->GetNativeWindow() parentWindow]); + EXPECT_TRUE([parent_nswindow_ isVisible]); + EXPECT_FALSE([parent_nswindow_ delegate]); + + EXPECT_FALSE(child_closed_); + child->RemoveObserver(this); + child_closed_ = true; + } + + bool child_closed() const { return child_closed_; } + + private: + base::scoped_nsobject<NSWindow> parent_nswindow_; + bool child_closed_ = false; + + DISALLOW_COPY_AND_ASSIGN(ParentCloseMonitor); +}; + +// Ensures when a parent window is destroyed, and triggers its child windows to +// be closed, that the child windows (via AppKit) do not attempt to call back +// into the parent, whilst it's in the process of being destroyed. +TEST_F(NativeWidgetMacTest, NoParentDelegateDuringTeardown) { + // First test "normal" windows and AppKit close. + { + Widget* parent = CreateTopLevelPlatformWidget(); + parent->SetBounds(gfx::Rect(100, 100, 300, 200)); + parent->Show(); + ParentCloseMonitor monitor(parent); + [parent->GetNativeWindow() close]; + EXPECT_TRUE(monitor.child_closed()); + } + + // Test the Widget::CloseNow() flow. + { + Widget* parent = CreateTopLevelPlatformWidget(); + parent->SetBounds(gfx::Rect(100, 100, 300, 200)); + parent->Show(); + ParentCloseMonitor monitor(parent); + parent->CloseNow(); + EXPECT_TRUE(monitor.child_closed()); + } + + // Test the WIDGET_OWNS_NATIVE_WIDGET flow. + { + scoped_ptr<Widget> parent(new Widget); + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.bounds = gfx::Rect(100, 100, 300, 200); + parent->Init(params); + parent->Show(); + + ParentCloseMonitor monitor(parent.get()); + parent.reset(); + EXPECT_TRUE(monitor.child_closed()); + } +} + // Tests Cocoa properties that should be given to particular widget types. TEST_F(NativeWidgetMacTest, NativeProperties) { // Create a regular widget (TYPE_WINDOW). @@ -938,6 +1074,20 @@ TEST_F(NativeWidgetMacTest, NativeProperties) { // Dialogs shouldn't take main status away from their parent. EXPECT_FALSE([dialog_widget->GetNativeWindow() canBecomeMainWindow]); + // Create a bubble widget with a parent: also shouldn't get main. + BubbleDelegateView* bubble_view = new BubbleDelegateView(); + bubble_view->set_parent_window(regular_widget->GetNativeView()); + Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_view); + EXPECT_TRUE([bubble_widget->GetNativeWindow() canBecomeKeyWindow]); + EXPECT_FALSE([bubble_widget->GetNativeWindow() canBecomeMainWindow]); + + // But a bubble without a parent should still be able to become main. + Widget* toplevel_bubble_widget = + BubbleDelegateView::CreateBubble(new BubbleDelegateView()); + EXPECT_TRUE([toplevel_bubble_widget->GetNativeWindow() canBecomeKeyWindow]); + EXPECT_TRUE([toplevel_bubble_widget->GetNativeWindow() canBecomeMainWindow]); + + toplevel_bubble_widget->CloseNow(); regular_widget->CloseNow(); } @@ -991,7 +1141,8 @@ TEST_F(NativeWidgetMacTest, DoesHideTitle) { // Same as CreateTopLevelPlatformWidget but with a custom delegate. Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); Widget* widget = new Widget; - params.native_widget = new NativeWidgetCapture(widget); + params.native_widget = + CreatePlatformNativeWidgetImpl(params, widget, kStubCapture, nullptr); CustomTitleWidgetDelegate delegate(widget); params.delegate = &delegate; params.bounds = gfx::Rect(0, 0, 800, 600); @@ -1089,6 +1240,235 @@ TEST_F(NativeWidgetMacTest, GetWorkAreaBoundsInScreen) { EXPECT_TRUE(NSIsEmptyRect(actual)); } +// Test that Widget opacity can be changed. +TEST_F(NativeWidgetMacTest, ChangeOpacity) { + Widget* widget = CreateTopLevelPlatformWidget(); + NSWindow* ns_window = widget->GetNativeWindow(); + + CGFloat old_opacity = [ns_window alphaValue]; + widget->SetOpacity(0xAA); + EXPECT_NE(old_opacity, [ns_window alphaValue]); + EXPECT_DOUBLE_EQ(0xAA / 255.0, [ns_window alphaValue]); + + widget->CloseNow(); +} + +// Test that NativeWidgetMac::SchedulePaintInRect correctly passes the dirtyRect +// parameter to BridgedContentView::drawRect, for a titled window (window with a +// toolbar). +TEST_F(NativeWidgetMacTest, SchedulePaintInRect_Titled) { + Widget* widget = CreateTopLevelPlatformWidget(); + + gfx::Rect screen_rect(50, 50, 100, 100); + widget->SetBounds(screen_rect); + + // Setup the mock content view for the NSWindow, so that we can intercept + // drawRect. + NSWindow* window = widget->GetNativeWindow(); + base::scoped_nsobject<MockBridgedView> mock_bridged_view( + [[MockBridgedView alloc] init]); + [window setContentView:mock_bridged_view]; + + // Ensure the initial draw of the window is done. + base::RunLoop().RunUntilIdle(); + + // Add a dummy view to the widget. This will cause SchedulePaint to be called + // on the dummy view. + View* dummy_view = new View(); + gfx::Rect dummy_bounds(25, 30, 10, 15); + dummy_view->SetBoundsRect(dummy_bounds); + // Reset drawRect count. + [mock_bridged_view setDrawRectCount:0]; + widget->GetContentsView()->AddChildView(dummy_view); + + // SchedulePaint is asyncronous. Wait for drawRect: to be called. + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(1u, [mock_bridged_view drawRectCount]); + int client_area_height = widget->GetClientAreaBoundsInScreen().height(); + // These are expected dummy_view bounds in AppKit coordinate system. The y + // coordinate of rect origin is calculated as: + // client_area_height - 30 (dummy_view's y coordinate) - 15 (dummy view's + // height). + gfx::Rect expected_appkit_bounds(25, client_area_height - 45, 10, 15); + EXPECT_NSEQ(expected_appkit_bounds.ToCGRect(), + [mock_bridged_view lastDirtyRect]); + widget->CloseNow(); +} + +// Test that NativeWidgetMac::SchedulePaintInRect correctly passes the dirtyRect +// parameter to BridgedContentView::drawRect, for a borderless window. +TEST_F(NativeWidgetMacTest, SchedulePaintInRect_Borderless) { + Widget* widget = CreateTopLevelFramelessPlatformWidget(); + + gfx::Rect screen_rect(50, 50, 100, 100); + widget->SetBounds(screen_rect); + + // Setup the mock content view for the NSWindow, so that we can intercept + // drawRect. + NSWindow* window = widget->GetNativeWindow(); + base::scoped_nsobject<MockBridgedView> mock_bridged_view( + [[MockBridgedView alloc] init]); + [window setContentView:mock_bridged_view]; + + // Ensure the initial draw of the window is done. + base::RunLoop().RunUntilIdle(); + + // Add a dummy view to the widget. This will cause SchedulePaint to be called + // on the dummy view. + View* dummy_view = new View(); + gfx::Rect dummy_bounds(25, 30, 10, 15); + dummy_view->SetBoundsRect(dummy_bounds); + // Reset drawRect count. + [mock_bridged_view setDrawRectCount:0]; + widget->GetRootView()->AddChildView(dummy_view); + + // SchedulePaint is asyncronous. Wait for drawRect: to be called. + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(1u, [mock_bridged_view drawRectCount]); + // These are expected dummy_view bounds in AppKit coordinate system. The y + // coordinate of rect origin is calculated as: + // 100(client area height) - 30 (dummy_view's y coordinate) - 15 (dummy view's + // height). + gfx::Rect expected_appkit_bounds(25, 55, 10, 15); + EXPECT_NSEQ(expected_appkit_bounds.ToCGRect(), + [mock_bridged_view lastDirtyRect]); + widget->CloseNow(); +} + +// Ensure traversing NSView focus correctly updates the views::FocusManager. +TEST_F(NativeWidgetMacTest, ChangeFocusOnChangeFirstResponder) { + Widget* widget = CreateTopLevelPlatformWidget(); + widget->GetRootView()->SetFocusable(true); + widget->Show(); + + base::scoped_nsobject<NSView> child_view([[FocusableTestNSView alloc] + initWithFrame:[widget->GetNativeView() bounds]]); + [widget->GetNativeView() addSubview:child_view]; + EXPECT_TRUE([child_view acceptsFirstResponder]); + EXPECT_TRUE(widget->GetRootView()->IsFocusable()); + + FocusManager* manager = widget->GetFocusManager(); + manager->SetFocusedView(widget->GetRootView()); + EXPECT_EQ(manager->GetFocusedView(), widget->GetRootView()); + + [widget->GetNativeWindow() makeFirstResponder:child_view]; + EXPECT_FALSE(manager->GetFocusedView()); + + [widget->GetNativeWindow() makeFirstResponder:widget->GetNativeView()]; + EXPECT_EQ(manager->GetFocusedView(), widget->GetRootView()); + + widget->CloseNow(); +} + +class NativeWidgetMacViewsOrderTest : public WidgetTest { + public: + NativeWidgetMacViewsOrderTest() {} + + protected: + // testing::Test: + void SetUp() override { + WidgetTest::SetUp(); + + widget_ = CreateTopLevelPlatformWidget(); + + ASSERT_EQ(1u, [[widget_->GetNativeView() subviews] count]); + compositor_view_ = [[widget_->GetNativeView() subviews] firstObject]; + + native_host_parent_ = new View(); + widget_->GetContentsView()->AddChildView(native_host_parent_); + + const int kNativeViewCount = 3; + for (int i = 0; i < kNativeViewCount; ++i) { + scoped_ptr<NativeHostHolder> holder(new NativeHostHolder()); + native_host_parent_->AddChildView(holder->host()); + holder->AttachNativeView(); + hosts_.push_back(std::move(holder)); + } + EXPECT_EQ(kNativeViewCount, native_host_parent_->child_count()); + EXPECT_TRUE(([[widget_->GetNativeView() subviews] isEqualToArray:@[ + compositor_view_, hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view() + ]])); + } + + void TearDown() override { + widget_->CloseNow(); + WidgetTest::TearDown(); + } + + NSView* GetContentNativeView() { return widget_->GetNativeView(); } + + Widget* widget_ = nullptr; + View* native_host_parent_ = nullptr; + NSView* compositor_view_ = nil; + std::vector<scoped_ptr<NativeHostHolder>> hosts_; + + private: + DISALLOW_COPY_AND_ASSIGN(NativeWidgetMacViewsOrderTest); +}; + +// Test that NativeViewHost::Attach()/Detach() method saves the NativeView +// z-order. +TEST_F(NativeWidgetMacViewsOrderTest, NativeViewAttached) { + hosts_[1]->Detach(); + EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[ + compositor_view_, hosts_[0]->view(), hosts_[2]->view() + ]])); + + hosts_[1]->AttachNativeView(); + EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[ + compositor_view_, hosts_[0]->view(), hosts_[1]->view(), + hosts_[2]->view() + ]])); +} + +// Tests that NativeViews order changes according to views::View hierarchy. +TEST_F(NativeWidgetMacViewsOrderTest, ReorderViews) { + native_host_parent_->ReorderChildView(hosts_[2]->host(), 1); + EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[ + compositor_view_, hosts_[0]->view(), hosts_[2]->view(), + hosts_[1]->view() + ]])); + + native_host_parent_->RemoveChildView(hosts_[2]->host()); + EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[ + compositor_view_, hosts_[0]->view(), hosts_[1]->view() + ]])); + + View* new_parent = new View(); + native_host_parent_->RemoveChildView(hosts_[1]->host()); + native_host_parent_->AddChildView(new_parent); + new_parent->AddChildView(hosts_[1]->host()); + new_parent->AddChildView(hosts_[2]->host()); + EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[ + compositor_view_, hosts_[0]->view(), hosts_[1]->view(), + hosts_[2]->view() + ]])); + + native_host_parent_->ReorderChildView(new_parent, 0); + EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[ + compositor_view_, hosts_[1]->view(), hosts_[2]->view(), + hosts_[0]->view() + ]])); +} + +// Test that unassociated native views stay on top after reordering. +TEST_F(NativeWidgetMacViewsOrderTest, UnassociatedViewsIsAbove) { + base::scoped_nsobject<NSView> child_view([[NSView alloc] init]); + [GetContentNativeView() addSubview:child_view]; + EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[ + compositor_view_, hosts_[0]->view(), hosts_[1]->view(), + hosts_[2]->view(), child_view + ]])); + + native_host_parent_->ReorderChildView(hosts_[2]->host(), 1); + EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[ + compositor_view_, hosts_[0]->view(), hosts_[2]->view(), + hosts_[1]->view(), child_view + ]])); +} + } // namespace test } // namespace views @@ -1108,3 +1488,21 @@ TEST_F(NativeWidgetMacTest, GetWorkAreaBoundsInScreen) { } @end + +@implementation MockBridgedView + +@synthesize drawRectCount = drawRectCount_; +@synthesize lastDirtyRect = lastDirtyRect_; + +- (void)drawRect:(NSRect)dirtyRect { + ++drawRectCount_; + lastDirtyRect_ = dirtyRect; +} + +@end + +@implementation FocusableTestNSView +- (BOOL)acceptsFirstResponder { + return YES; +} +@end diff --git a/chromium/ui/views/widget/native_widget_private.h b/chromium/ui/views/widget/native_widget_private.h index 6e52bf66749..777eaa226a4 100644 --- a/chromium/ui/views/widget/native_widget_private.h +++ b/chromium/ui/views/widget/native_widget_private.h @@ -194,7 +194,6 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget { virtual void SetFullscreen(bool fullscreen) = 0; virtual bool IsFullscreen() const = 0; virtual void SetOpacity(unsigned char opacity) = 0; - virtual void SetUseDragFrame(bool use_drag_frame) = 0; virtual void FlashFrame(bool flash) = 0; virtual void RunShellDrag(View* view, const ui::OSExchangeData& data, diff --git a/chromium/ui/views/widget/tooltip_manager.h b/chromium/ui/views/widget/tooltip_manager.h index 4287fc53d6a..e8074047340 100644 --- a/chromium/ui/views/widget/tooltip_manager.h +++ b/chromium/ui/views/widget/tooltip_manager.h @@ -8,7 +8,6 @@ #include <string> #include "base/strings/string16.h" -#include "ui/gfx/native_widget_types.h" #include "ui/views/views_export.h" namespace gfx { @@ -39,10 +38,8 @@ class VIEWS_EXPORT TooltipManager { virtual ~TooltipManager() {} // Returns the maximum width of the tooltip. |point| gives the location - // the tooltip is to be displayed on in screen coordinates. |context| is - // used to determine which gfx::Screen should be used. - virtual int GetMaxWidth(const gfx::Point& location, - gfx::NativeView context) const = 0; + // the tooltip is to be displayed on in screen coordinates. + virtual int GetMaxWidth(const gfx::Point& location) const = 0; // Returns the font list used for tooltips. virtual const gfx::FontList& GetFontList() const = 0; diff --git a/chromium/ui/views/widget/tooltip_manager_aura.cc b/chromium/ui/views/widget/tooltip_manager_aura.cc index 1c5bd26c32e..c4bf40ea856 100644 --- a/chromium/ui/views/widget/tooltip_manager_aura.cc +++ b/chromium/ui/views/widget/tooltip_manager_aura.cc @@ -49,7 +49,7 @@ void TooltipManagerAura::UpdateTooltipManagerForCapture(Widget* source) { if (!screen_position_client) return; screen_position_client->ConvertPointToScreen(root_window, &screen_loc); - gfx::Screen* screen = gfx::Screen::GetScreenFor(root_window); + gfx::Screen* screen = gfx::Screen::GetScreen(); aura::Window* target = screen->GetWindowAtScreenPoint(screen_loc); if (!target) return; @@ -81,10 +81,10 @@ const gfx::FontList& TooltipManagerAura::GetFontList() const { return GetDefaultFontList(); } -int TooltipManagerAura::GetMaxWidth(const gfx::Point& point, - aura::Window* context) const { - return aura::client::GetTooltipClient(context->GetRootWindow())-> - GetMaxWidth(point, context); +int TooltipManagerAura::GetMaxWidth(const gfx::Point& point) const { + return aura::client::GetTooltipClient( + widget_->GetNativeView()->GetRootWindow()) + ->GetMaxWidth(point); } void TooltipManagerAura::UpdateTooltip() { diff --git a/chromium/ui/views/widget/tooltip_manager_aura.h b/chromium/ui/views/widget/tooltip_manager_aura.h index 8d6bd9aff84..f429385525a 100644 --- a/chromium/ui/views/widget/tooltip_manager_aura.h +++ b/chromium/ui/views/widget/tooltip_manager_aura.h @@ -39,8 +39,7 @@ class TooltipManagerAura : public TooltipManager { static const gfx::FontList& GetDefaultFontList(); // TooltipManager: - int GetMaxWidth(const gfx::Point& location, - aura::Window* context) const override; + int GetMaxWidth(const gfx::Point& location) const override; const gfx::FontList& GetFontList() const override; void UpdateTooltip() override; void TooltipTextChanged(View* view) override; diff --git a/chromium/ui/views/widget/widget.cc b/chromium/ui/views/widget/widget.cc index 02a570db6da..ffafd0d2bbb 100644 --- a/chromium/ui/views/widget/widget.cc +++ b/chromium/ui/views/widget/widget.cc @@ -10,6 +10,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" #include "ui/base/cursor/cursor.h" +#include "ui/base/default_style.h" #include "ui/base/default_theme_provider.h" #include "ui/base/hit_test.h" #include "ui/base/ime/input_method.h" @@ -110,30 +111,7 @@ class DefaultWidgetDelegate : public WidgetDelegate { //////////////////////////////////////////////////////////////////////////////// // Widget, InitParams: -Widget::InitParams::InitParams() - : type(TYPE_WINDOW), - delegate(nullptr), - child(false), - opacity(INFER_OPACITY), - accept_events(true), - activatable(ACTIVATABLE_DEFAULT), - keep_on_top(false), - visible_on_all_workspaces(false), - ownership(NATIVE_WIDGET_OWNS_WIDGET), - mirror_origin_in_rtl(false), - shadow_type(SHADOW_TYPE_DEFAULT), - remove_standard_frame(false), - use_system_default_icon(false), - show_state(ui::SHOW_STATE_DEFAULT), - parent(nullptr), - native_widget(nullptr), - native_theme(nullptr), - desktop_window_tree_host(nullptr), - layer_type(ui::LAYER_TEXTURED), - context(nullptr), - force_show_in_taskbar(false), - force_software_compositing(false) { -} +Widget::InitParams::InitParams() : InitParams(TYPE_WINDOW) {} Widget::InitParams::InitParams(Type type) : type(type), @@ -152,7 +130,6 @@ Widget::InitParams::InitParams(Type type) show_state(ui::SHOW_STATE_DEFAULT), parent(nullptr), native_widget(nullptr), - native_theme(nullptr), desktop_window_tree_host(nullptr), layer_type(ui::LAYER_TEXTURED), context(nullptr), @@ -160,6 +137,8 @@ Widget::InitParams::InitParams(Type type) force_software_compositing(false) { } +Widget::InitParams::InitParams(const InitParams& other) = default; + Widget::InitParams::~InitParams() { } @@ -168,14 +147,13 @@ Widget::InitParams::~InitParams() { Widget::Widget() : native_widget_(nullptr), - native_theme_(nullptr), widget_delegate_(nullptr), non_client_view_(nullptr), dragged_view_(nullptr), ownership_(InitParams::NATIVE_WIDGET_OWNS_WIDGET), is_secondary_widget_(true), frame_type_(FRAME_TYPE_DEFAULT), - disable_inactive_rendering_(false), + always_render_as_active_(false), widget_closed_(false), saved_show_state_(ui::SHOW_STATE_DEFAULT), focus_on_creation_(true), @@ -203,22 +181,6 @@ Widget::~Widget() { } // static -Widget* Widget::CreateWindow(WidgetDelegate* delegate) { - return CreateWindowWithBounds(delegate, gfx::Rect()); -} - -// static -Widget* Widget::CreateWindowWithBounds(WidgetDelegate* delegate, - const gfx::Rect& bounds) { - Widget* widget = new Widget; - Widget::InitParams params; - params.bounds = bounds; - params.delegate = delegate; - widget->Init(params); - return widget; -} - -// static Widget* Widget::CreateWindowWithParent(WidgetDelegate* delegate, gfx::NativeView parent) { return CreateWindowWithParentAndBounds(delegate, parent, gfx::Rect()); @@ -278,7 +240,6 @@ Widget* Widget::GetTopLevelWidgetForNativeView(gfx::NativeView native_view) { return native_widget ? native_widget->GetWidget() : NULL; } - // static void Widget::GetAllChildWidgets(gfx::NativeView native_view, Widgets* children) { @@ -299,14 +260,16 @@ void Widget::ReparentNativeView(gfx::NativeView native_view, // static int Widget::GetLocalizedContentsWidth(int col_resource_id) { - return ui::GetLocalizedContentsWidthForFont(col_resource_id, - ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); + return ui::GetLocalizedContentsWidthForFont( + col_resource_id, ResourceBundle::GetSharedInstance().GetFontWithDelta( + ui::kMessageFontSizeDelta)); } // static int Widget::GetLocalizedContentsHeight(int row_resource_id) { - return ui::GetLocalizedContentsHeightForFont(row_resource_id, - ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); + return ui::GetLocalizedContentsHeightForFont( + row_resource_id, ResourceBundle::GetSharedInstance().GetFontWithDelta( + ui::kMessageFontSizeDelta)); } // static @@ -369,7 +332,6 @@ void Widget::Init(const InitParams& in_params) { internal::NativeWidgetPrivate::IsMouseButtonDown(); } native_widget_->InitNativeWidget(params); - native_theme_ = params.native_theme; if (RequiresNonClientView(params.type)) { non_client_view_ = new NonClientView; non_client_view_->SetFrameView(CreateNonClientFrameView()); @@ -532,9 +494,9 @@ void Widget::CenterWindow(const gfx::Size& size) { } void Widget::SetBoundsConstrained(const gfx::Rect& bounds) { - gfx::Rect work_area = - gfx::Screen::GetScreenFor(GetNativeView())->GetDisplayNearestPoint( - bounds.origin()).work_area(); + gfx::Rect work_area = gfx::Screen::GetScreen() + ->GetDisplayNearestPoint(bounds.origin()) + .work_area(); if (work_area.IsEmpty()) { SetBounds(bounds); } else { @@ -683,10 +645,6 @@ bool Widget::IsActive() const { return native_widget_->IsActive(); } -void Widget::DisableInactiveRendering() { - SetInactiveRenderingDisabled(true); -} - void Widget::SetAlwaysOnTop(bool on_top) { native_widget_->SetAlwaysOnTop(on_top); } @@ -737,10 +695,6 @@ void Widget::SetOpacity(unsigned char opacity) { native_widget_->SetOpacity(opacity); } -void Widget::SetUseDragFrame(bool use_drag_frame) { - native_widget_->SetUseDragFrame(use_drag_frame); -} - void Widget::FlashFrame(bool flash) { native_widget_->FlashFrame(flash); } @@ -774,7 +728,7 @@ const ui::ThemeProvider* Widget::GetThemeProvider() const { } const ui::NativeTheme* Widget::GetNativeTheme() const { - return native_theme_? native_theme_ : native_widget_->GetNativeTheme(); + return native_widget_->GetNativeTheme(); } FocusManager* Widget::GetFocusManager() { @@ -1007,7 +961,7 @@ void Widget::SynthesizeMouseMoveEvent() { // In screen coordinate. gfx::Point mouse_location = EventMonitor::GetLastMouseLocation(); if (!GetWindowBoundsInScreen().Contains(mouse_location)) - return; + return; // Convert: screen coordinate -> widget coordinate. View::ConvertPointFromScreen(root_view_.get(), &mouse_location); @@ -1031,8 +985,7 @@ void Widget::OnSizeConstraintsChanged() { non_client_view_->SizeConstraintsChanged(); } -void Widget::OnOwnerClosing() { -} +void Widget::OnOwnerClosing() {} //////////////////////////////////////////////////////////////////////////////// // Widget, NativeWidgetDelegate implementation: @@ -1049,12 +1002,8 @@ bool Widget::CanActivate() const { return widget_delegate_->CanActivate(); } -bool Widget::IsInactiveRenderingDisabled() const { - return disable_inactive_rendering_; -} - -void Widget::EnableInactiveRendering() { - SetInactiveRenderingDisabled(false); +bool Widget::IsAlwaysRenderAsActive() const { + return always_render_as_active_; } void Widget::OnNativeWidgetActivationChanged(bool active) { @@ -1067,8 +1016,8 @@ void Widget::OnNativeWidgetActivationChanged(bool active) { FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetActivationChanged(this, active)); - if (IsVisible() && non_client_view()) - non_client_view()->frame_view()->SchedulePaint(); + if (non_client_view()) + non_client_view()->frame_view()->ActivationChanged(active); } void Widget::OnNativeFocus() { @@ -1338,7 +1287,7 @@ bool Widget::SetInitialFocus(ui::WindowShowState show_state) { show_state == ui::SHOW_STATE_MINIMIZED) { // If not focusing the window now, tell the focus manager which view to // focus when the window is restored. - if (v) + if (v && focus_manager_.get()) focus_manager_->SetStoredFocusView(v); return true; } @@ -1401,22 +1350,24 @@ void Widget::DestroyRootView() { root_view_.reset(); } -void Widget::OnDragWillStart() { -} +void Widget::OnDragWillStart() {} -void Widget::OnDragComplete() { -} +void Widget::OnDragComplete() {} //////////////////////////////////////////////////////////////////////////////// // Widget, private: -void Widget::SetInactiveRenderingDisabled(bool value) { - if (value == disable_inactive_rendering_) +void Widget::SetAlwaysRenderAsActive(bool always_render_as_active) { + if (always_render_as_active_ == always_render_as_active) return; - disable_inactive_rendering_ = value; - if (non_client_view_) - non_client_view_->SetInactiveRenderingDisabled(value); + always_render_as_active_ = always_render_as_active; + + // If active, the frame should already be painted. Otherwise, + // |always_render_as_active_| just changed, and the widget is inactive, so + // schedule a repaint. + if (non_client_view_ && !IsActive()) + non_client_view_->frame_view()->SchedulePaint(); } void Widget::SaveWindowPlacement() { diff --git a/chromium/ui/views/widget/widget.h b/chromium/ui/views/widget/widget.h index 80aaddee1a6..0ceaf825ffb 100644 --- a/chromium/ui/views/widget/widget.h +++ b/chromium/ui/views/widget/widget.h @@ -97,8 +97,8 @@ class RootView; // The Widget instance owns its NativeWidget. This state implies someone // else wants to control the lifetime of this object. When they destroy // the Widget it is responsible for destroying the NativeWidget (from its -// destructor). -// +// destructor). This is often used to place a Widget in a scoped_ptr<> or +// on the stack in a test. class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, public ui::EventSource, public FocusTraversable, @@ -202,25 +202,27 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, InitParams(); explicit InitParams(Type type); + InitParams(const InitParams& other); ~InitParams(); Type type; - // If NULL, a default implementation will be constructed. + // If null, a default implementation will be constructed. The default + // implementation deletes itself when the Widget closes. WidgetDelegate* delegate; bool child; // If TRANSLUCENT_WINDOW, the widget may be fully or partially transparent. - // Translucent windows may not always be supported. Use - // IsTranslucentWindowOpacitySupported to determine if translucent windows - // are supported. // If OPAQUE_WINDOW, we can perform optimizations based on the widget being - // fully opaque. Defaults to TRANSLUCENT_WINDOW if - // ViewsDelegate::UseTransparentWindows(). Defaults to OPAQUE_WINDOW for - // non-window widgets. + // fully opaque. + // Default is based on ViewsDelegate::GetOpacityForInitParams(). Defaults + // to OPAQUE_WINDOW for non-window widgets. + // Translucent windows may not always be supported. Use + // IsTranslucentWindowOpacitySupported to determine whether they are. WindowOpacity opacity; bool accept_events; Activatable activatable; bool keep_on_top; bool visible_on_all_workspaces; + // See Widget class comment above. Ownership ownership; bool mirror_origin_in_rtl; ShadowType shadow_type; @@ -242,8 +244,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // When set, this value is used as the Widget's NativeWidget implementation. // The Widget will not construct a default one. Default is NULL. NativeWidget* native_widget; - // If provided, sets the native theme for this widget. - ui::NativeTheme* native_theme; // Aura-only. Provides a DesktopWindowTreeHost implementation to use instead // of the default one. // TODO(beng): Figure out if there's a better way to expose this, e.g. get @@ -273,23 +273,18 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // If true then the widget uses software compositing. Defaults to false. // Only used on Windows. bool force_software_compositing; + + // Used if widget is not activatable to do determine if mouse events should + // be sent to the widget. + bool wants_mouse_events_when_inactive = false; }; Widget(); ~Widget() override; - // Creates a toplevel window with no context. These methods should only be - // used in cases where there is no contextual information because we're - // creating a toplevel window connected to no other event. - // - // If you have any parenting or context information, or can pass that - // information, prefer the WithParent or WithContext versions of these - // methods. - static Widget* CreateWindow(WidgetDelegate* delegate); - static Widget* CreateWindowWithBounds(WidgetDelegate* delegate, - const gfx::Rect& bounds); - - // Creates a decorated window Widget with the specified properties. + // Creates a decorated window Widget with the specified properties. The + // returned Widget is owned by its NativeWidget; see Widget class comment for + // details. static Widget* CreateWindowWithParent(WidgetDelegate* delegate, gfx::NativeView parent); static Widget* CreateWindowWithParentAndBounds(WidgetDelegate* delegate, @@ -297,6 +292,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, const gfx::Rect& bounds); // Creates a decorated window Widget in the same desktop context as |context|. + // The returned Widget is owned by its NativeWidget; see Widget class comment + // for details. static Widget* CreateWindowWithContext(WidgetDelegate* delegate, gfx::NativeWindow context); static Widget* CreateWindowWithContextAndBounds(WidgetDelegate* delegate, @@ -498,12 +495,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // Returns whether the Widget is the currently active window. virtual bool IsActive() const; - // Prevents the window from being rendered as deactivated. This state is - // reset automatically as soon as the window becomes activated again. There is - // no ability to control the state through this API as this leads to sync - // problems. - void DisableInactiveRendering(); - // Sets the widget to be on top of all other widgets in the windowing system. void SetAlwaysOnTop(bool on_top); @@ -532,10 +523,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // underlying windowing system. void SetOpacity(unsigned char opacity); - // Sets whether or not the window should show its frame as a "transient drag - // frame" - slightly transparent and without the standard window controls. - void SetUseDragFrame(bool use_drag_frame); - // Flashes the frame of the window to draw attention to it. Currently only // implemented on Windows for non-Aura. void FlashFrame(bool flash); @@ -565,7 +552,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, return const_cast<ui::NativeTheme*>( const_cast<const Widget*>(this)->GetNativeTheme()); } - const ui::NativeTheme* GetNativeTheme() const; + virtual const ui::NativeTheme* GetNativeTheme() const; // Returns the FocusManager for this widget. // Note that all widgets in a widget hierarchy share the same focus manager. @@ -775,8 +762,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, bool IsModal() const override; bool IsDialogBox() const override; bool CanActivate() const override; - bool IsInactiveRenderingDisabled() const override; - void EnableInactiveRendering() override; + bool IsAlwaysRenderAsActive() const override; + void SetAlwaysRenderAsActive(bool always_render_as_active) override; void OnNativeWidgetActivationChanged(bool active) override; void OnNativeFocus() override; void OnNativeBlur() override; @@ -838,12 +825,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, private: friend class ComboboxTest; + friend class CustomButtonTest; friend class TextfieldTest; - // Sets the value of |disable_inactive_rendering_|. If the value changes, - // both the NonClientView and WidgetDelegate are notified. - void SetInactiveRenderingDisabled(bool value); - // Persists the window's restored position and "show" state using the // window delegate. void SaveWindowPlacement(); @@ -866,10 +850,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, internal::NativeWidgetPrivate* native_widget_; - // If non-null, the native theme for this widget. Otherwise the native theme - // comes from |native_widget_|. - ui::NativeTheme* native_theme_; - base::ObserverList<WidgetObserver> observers_; base::ObserverList<WidgetRemovalsObserver> removals_observers_; @@ -914,7 +894,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // True when the window should be rendered as active, regardless of whether // or not it actually is. - bool disable_inactive_rendering_; + bool always_render_as_active_; // Set to true if the widget is in the process of closing. bool widget_closed_; diff --git a/chromium/ui/views/widget/widget_delegate.cc b/chromium/ui/views/widget/widget_delegate.cc index e62aa92847e..ced90b6f392 100644 --- a/chromium/ui/views/widget/widget_delegate.cc +++ b/chromium/ui/views/widget/widget_delegate.cc @@ -32,15 +32,19 @@ void WidgetDelegate::OnWorkAreaChanged() { } View* WidgetDelegate::GetInitiallyFocusedView() { - return NULL; + return nullptr; } BubbleDelegateView* WidgetDelegate::AsBubbleDelegate() { - return NULL; + return nullptr; +} + +BubbleDialogDelegateView* WidgetDelegate::AsBubbleDialogDelegate() { + return nullptr; } DialogDelegate* WidgetDelegate::AsDialogDelegate() { - return NULL; + return nullptr; } bool WidgetDelegate::CanResize() const { @@ -80,7 +84,11 @@ bool WidgetDelegate::ShouldShowWindowTitle() const { } bool WidgetDelegate::ShouldShowCloseButton() const { +#if defined(OS_MACOSX) + return false; +#else return true; +#endif } bool WidgetDelegate::ShouldHandleSystemCommands() const { diff --git a/chromium/ui/views/widget/widget_delegate.h b/chromium/ui/views/widget/widget_delegate.h index 660313d1648..0ec021505b6 100644 --- a/chromium/ui/views/widget/widget_delegate.h +++ b/chromium/ui/views/widget/widget_delegate.h @@ -19,6 +19,7 @@ class Rect; } namespace views { +class BubbleDialogDelegateView; class BubbleDelegateView; class ClientView; class DialogDelegate; @@ -51,6 +52,7 @@ class VIEWS_EXPORT WidgetDelegate { virtual View* GetInitiallyFocusedView(); virtual BubbleDelegateView* AsBubbleDelegate(); + virtual BubbleDialogDelegateView* AsBubbleDialogDelegate(); virtual DialogDelegate* AsDialogDelegate(); // Returns true if the window can be resized. diff --git a/chromium/ui/views/widget/widget_interactive_uitest.cc b/chromium/ui/views/widget/widget_interactive_uitest.cc index fa5fb3954fc..e9f9397c01b 100644 --- a/chromium/ui/views/widget/widget_interactive_uitest.cc +++ b/chromium/ui/views/widget/widget_interactive_uitest.cc @@ -26,6 +26,7 @@ #include "ui/views/controls/textfield/textfield_test_api.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/test/focus_manager_test.h" +#include "ui/views/test/native_widget_factory.h" #include "ui/views/test/widget_test.h" #include "ui/views/touchui/touch_selection_controller_impl.h" #include "ui/views/widget/widget.h" @@ -52,7 +53,7 @@ class ExitLoopOnRelease : public View { ~ExitLoopOnRelease() override {} private: - // Overridden from View: + // View: void OnMouseReleased(const ui::MouseEvent& event) override { GetWidget()->Close(); base::MessageLoop::current()->QuitNow(); @@ -68,7 +69,7 @@ class GestureCaptureView : public View { ~GestureCaptureView() override {} private: - // Overridden from View: + // View: void OnGestureEvent(ui::GestureEvent* event) override { if (event->type() == ui::ET_GESTURE_TAP_DOWN) { GetWidget()->SetCapture(this); @@ -132,7 +133,7 @@ class NestedLoopCaptureView : public View { ~NestedLoopCaptureView() override {} private: - // Overridden from View: + // View: bool OnMousePressed(const ui::MouseEvent& event) override { // Start a nested loop. widget_->Show(); @@ -654,6 +655,7 @@ TEST_F(WidgetTestInteractive, ViewFocusOnHWNDEnabledChanges) { } widget->Show(); + widget->GetNativeWindow()->GetHost()->Show(); const HWND hwnd = HWNDForWidget(widget); EXPECT_TRUE(::IsWindow(hwnd)); EXPECT_TRUE(::IsWindowEnabled(hwnd)); @@ -740,6 +742,69 @@ TEST_F(WidgetTestInteractive, WidgetNotActivatedOnFakeActivationMessages) { EXPECT_EQ(true, widget1.active()); EXPECT_EQ(false, widget2.active()); } + +// On Windows if we create a fullscreen window on a thread, then it affects the +// way other windows on the thread interact with the taskbar. To workaround +// this we reduce the bounds of a fullscreen window by 1px when it loses +// activation. This test verifies the same. +TEST_F(WidgetTestInteractive, FullscreenBoundsReducedOnActivationLoss) { + Widget widget1; + Widget::InitParams params = + CreateParams(Widget::InitParams::TYPE_WINDOW); + params.native_widget = new DesktopNativeWidgetAura(&widget1); + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget1.Init(params); + widget1.SetBounds(gfx::Rect(0, 0, 200, 200)); + widget1.Show(); + + widget1.Activate(); + RunPendingMessages(); + EXPECT_EQ(::GetActiveWindow(), + widget1.GetNativeWindow()->GetHost()->GetAcceleratedWidget()); + + widget1.SetFullscreen(true); + EXPECT_TRUE(widget1.IsFullscreen()); + // Ensure that the StopIgnoringPosChanges task in HWNDMessageHandler runs. + // This task is queued when a widget becomes fullscreen. + RunPendingMessages(); + EXPECT_EQ(::GetActiveWindow(), + widget1.GetNativeWindow()->GetHost()->GetAcceleratedWidget()); + gfx::Rect fullscreen_bounds = widget1.GetWindowBoundsInScreen(); + + Widget widget2; + params.native_widget = new DesktopNativeWidgetAura(&widget2); + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget2.Init(params); + widget2.SetBounds(gfx::Rect(0, 0, 200, 200)); + widget2.Show(); + + widget2.Activate(); + RunPendingMessages(); + EXPECT_EQ(::GetActiveWindow(), + widget2.GetNativeWindow()->GetHost()->GetAcceleratedWidget()); + + gfx::Rect fullscreen_bounds_after_activation_loss = + widget1.GetWindowBoundsInScreen(); + + // After deactivation loss the bounds of the fullscreen widget should be + // reduced by 1px. + EXPECT_EQ(fullscreen_bounds.height() - + fullscreen_bounds_after_activation_loss.height(), 1); + + widget1.Activate(); + RunPendingMessages(); + EXPECT_EQ(::GetActiveWindow(), + widget1.GetNativeWindow()->GetHost()->GetAcceleratedWidget()); + + gfx::Rect fullscreen_bounds_after_activate = + widget1.GetWindowBoundsInScreen(); + + // After activation the bounds of the fullscreen widget should be restored. + EXPECT_EQ(fullscreen_bounds, fullscreen_bounds_after_activate); + + widget1.CloseNow(); + widget2.CloseNow(); +} #endif // defined(OS_WIN) #if !defined(OS_CHROMEOS) @@ -774,8 +839,8 @@ TEST_F(WidgetTestInteractive, WindowModalWindowDestroyedActivationTest) { gfx::Rect initial_bounds(0, 0, 500, 500); init_params.bounds = initial_bounds; init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - init_params.native_widget = - new PlatformDesktopNativeWidget(&top_level_widget); + init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl( + init_params, &top_level_widget, nullptr); top_level_widget.Init(init_params); ShowSync(&top_level_widget); @@ -843,8 +908,8 @@ TEST_F(WidgetTestInteractive, MAYBE_SystemModalWindowReleasesCapture) { gfx::Rect initial_bounds(0, 0, 500, 500); init_params.bounds = initial_bounds; init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - init_params.native_widget = - new PlatformDesktopNativeWidget(&top_level_widget); + init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl( + init_params, &top_level_widget, nullptr); top_level_widget.Init(init_params); ShowSync(&top_level_widget); @@ -881,9 +946,8 @@ TEST_F(WidgetTestInteractive, CanActivateFlagIsHonored) { init_params.bounds = gfx::Rect(0, 0, 200, 200); init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; init_params.activatable = Widget::InitParams::ACTIVATABLE_NO; -#if !defined(OS_CHROMEOS) - init_params.native_widget = new PlatformDesktopNativeWidget(&widget); -#endif // !defined(OS_CHROMEOS) + init_params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(init_params, &widget, nullptr); widget.Init(init_params); widget.Show(); @@ -1048,7 +1112,8 @@ TEST_F(WidgetTestInteractive, InactiveWidgetDoesNotGrabActivation) { Widget widget2; Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = new PlatformDesktopNativeWidget(&widget2); + params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(params, &widget2, nullptr); params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; widget2.Init(params); widget2.Show(); @@ -1107,9 +1172,35 @@ TEST_F(WidgetTestInteractive, MAYBE_ExitFullscreenRestoreState) { RunPendingMessages(); } +// Testing initial focus is assigned properly for normal top-level widgets, +// and subclasses that specify a initially focused child view. +TEST_F(WidgetTestInteractive, InitialFocus) { + // By default, there is no initially focused view (even if there is a + // focusable subview). + Widget* toplevel(CreateTopLevelPlatformWidget()); + View* view = new View; + view->SetFocusable(true); + toplevel->GetContentsView()->AddChildView(view); + + ShowSync(toplevel); + toplevel->Show(); + EXPECT_FALSE(view->HasFocus()); + EXPECT_FALSE(toplevel->GetFocusManager()->GetStoredFocusView()); + toplevel->CloseNow(); + + // Testing a widget which specifies a initially focused view. + TestInitialFocusWidgetDelegate delegate(GetContext()); + + Widget* widget = delegate.GetWidget(); + ShowSync(widget); + widget->Show(); + EXPECT_TRUE(delegate.view()->HasFocus()); + EXPECT_EQ(delegate.view(), widget->GetFocusManager()->GetStoredFocusView()); +} + namespace { -// Used to veirfy OnMouseCaptureLost() has been invoked. +// Used to verify OnMouseCaptureLost() has been invoked. class CaptureLostTrackingWidget : public Widget { public: CaptureLostTrackingWidget() : got_capture_lost_(false) {} @@ -1157,8 +1248,8 @@ class WidgetCaptureTest : public ViewsTestBase { CaptureLostTrackingWidget widget1; Widget::InitParams params1 = CreateParams(views::Widget::InitParams::TYPE_WINDOW); - params1.native_widget = CreateNativeWidget(use_desktop_native_widget, - &widget1); + params1.native_widget = + CreateNativeWidget(params1, use_desktop_native_widget, &widget1); params1.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; widget1.Init(params1); widget1.Show(); @@ -1167,8 +1258,8 @@ class WidgetCaptureTest : public ViewsTestBase { Widget::InitParams params2 = CreateParams(views::Widget::InitParams::TYPE_WINDOW); params2.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params2.native_widget = CreateNativeWidget(use_desktop_native_widget, - &widget2); + params2.native_widget = + CreateNativeWidget(params2, use_desktop_native_widget, &widget2); widget2.Init(params2); widget2.Show(); @@ -1194,13 +1285,12 @@ class WidgetCaptureTest : public ViewsTestBase { EXPECT_FALSE(widget2.GetAndClearGotCaptureLost()); } - NativeWidget* CreateNativeWidget(bool create_desktop_native_widget, + NativeWidget* CreateNativeWidget(const Widget::InitParams& params, + bool create_desktop_native_widget, Widget* widget) { -#if !defined(OS_CHROMEOS) if (create_desktop_native_widget) - return new PlatformDesktopNativeWidget(widget); -#endif - return NULL; + return CreatePlatformDesktopNativeWidgetImpl(params, widget, nullptr); + return CreatePlatformNativeWidgetImpl(params, widget, kDefault, nullptr); } private: @@ -1266,7 +1356,7 @@ TEST_F(WidgetCaptureTest, MAYBE_MouseExitOnCaptureGrab) { Widget widget1; Widget::InitParams params1 = CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params1.native_widget = CreateNativeWidget(true, &widget1); + params1.native_widget = CreateNativeWidget(params1, true, &widget1); params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; widget1.Init(params1); MouseView* mouse_view1 = new MouseView; @@ -1277,7 +1367,7 @@ TEST_F(WidgetCaptureTest, MAYBE_MouseExitOnCaptureGrab) { Widget widget2; Widget::InitParams params2 = CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params2.native_widget = CreateNativeWidget(true, &widget2); + params2.native_widget = CreateNativeWidget(params2, true, &widget2); params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; widget2.Init(params2); widget2.Show(); @@ -1329,7 +1419,8 @@ TEST_F(WidgetCaptureTest, SetCaptureToNonToplevel) { Widget toplevel; Widget::InitParams toplevel_params = CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); - toplevel_params.native_widget = CreateNativeWidget(true, &toplevel); + toplevel_params.native_widget = CreateNativeWidget(toplevel_params, true, + &toplevel); toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; toplevel.Init(toplevel_params); toplevel.Show(); diff --git a/chromium/ui/views/widget/widget_removals_observer.h b/chromium/ui/views/widget/widget_removals_observer.h index e62acab36a4..d7046073c4d 100644 --- a/chromium/ui/views/widget/widget_removals_observer.h +++ b/chromium/ui/views/widget/widget_removals_observer.h @@ -18,7 +18,11 @@ class View; // from |View|. class VIEWS_EXPORT WidgetRemovalsObserver { public: - // Called immediately before a descendant view of |widget| is removed. + // Called immediately before a descendant view of |widget| is removed + // from this widget. Won't be called if the view is moved within the + // same widget, but will be called if it's moved to a different widget. + // Only called on the root of a view tree; it implies that all of the + // descendants of |view| will be removed. virtual void OnWillRemoveView(Widget* widget, View* view) {} protected: diff --git a/chromium/ui/views/widget/widget_unittest.cc b/chromium/ui/views/widget/widget_unittest.cc index 41bbe8198d7..0b8c645a5ea 100644 --- a/chromium/ui/views/widget/widget_unittest.cc +++ b/chromium/ui/views/widget/widget_unittest.cc @@ -23,12 +23,15 @@ #include "ui/gfx/native_widget_types.h" #include "ui/views/bubble/bubble_delegate.h" #include "ui/views/controls/textfield/textfield.h" +#include "ui/views/test/native_widget_factory.h" #include "ui/views/test/test_views.h" #include "ui/views/test/test_widget_observer.h" #include "ui/views/test/widget_test.h" #include "ui/views/widget/native_widget_delegate.h" +#include "ui/views/widget/native_widget_private.h" #include "ui/views/widget/root_view.h" #include "ui/views/widget/widget_deletion_observer.h" +#include "ui/views/widget/widget_removals_observer.h" #include "ui/views/window/dialog_delegate.h" #include "ui/views/window/native_frame_view.h" @@ -42,7 +45,6 @@ #if defined(OS_MACOSX) #include "base/mac/mac_util.h" -#include "ui/base/test/scoped_fake_nswindow_fullscreen.h" #endif namespace views { @@ -59,15 +61,6 @@ gfx::Point ConvertPointFromWidgetToView(View* view, const gfx::Point& p) { return tmp; } -// Helper function for Snow Leopard special cases to avoid #ifdef litter. -bool IsTestingSnowLeopard() { -#if defined(OS_MACOSX) - return base::mac::IsOSSnowLeopard(); -#else - return false; -#endif -} - // This class can be used as a deleter for scoped_ptr<Widget> // to call function Widget::CloseNow automatically. struct WidgetCloser { @@ -367,44 +360,6 @@ struct OwnershipTestState { bool native_widget_deleted; }; -// A platform NativeWidget subclass that updates a bag of state when it is -// destroyed. -class OwnershipTestNativeWidget : public PlatformNativeWidget { - public: - OwnershipTestNativeWidget(internal::NativeWidgetDelegate* delegate, - OwnershipTestState* state) - : PlatformNativeWidget(delegate), - state_(state) { - } - ~OwnershipTestNativeWidget() override { - state_->native_widget_deleted = true; - } - - private: - OwnershipTestState* state_; - - DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidget); -}; - -// A views NativeWidget subclass that updates a bag of state when it is -// destroyed. -class OwnershipTestNativeWidgetAura : public NativeWidgetCapture { - public: - OwnershipTestNativeWidgetAura(internal::NativeWidgetDelegate* delegate, - OwnershipTestState* state) - : NativeWidgetCapture(delegate), - state_(state) { - } - ~OwnershipTestNativeWidgetAura() override { - state_->native_widget_deleted = true; - } - - private: - OwnershipTestState* state_; - - DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidgetAura); -}; - // A Widget subclass that updates a bag of state when it is destroyed. class OwnershipTestWidget : public Widget { public: @@ -417,6 +372,8 @@ class OwnershipTestWidget : public Widget { DISALLOW_COPY_AND_ASSIGN(OwnershipTestWidget); }; +// TODO(sky): add coverage of ownership for the desktop variants. + // Widget owns its NativeWidget, part 1: NativeWidget is a platform-native // widget. TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) { @@ -424,8 +381,8 @@ TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) { scoped_ptr<Widget> widget(new OwnershipTestWidget(&state)); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = - new OwnershipTestNativeWidgetAura(widget.get(), &state); + params.native_widget = CreatePlatformNativeWidgetImpl( + params, widget.get(), kStubCapture, &state.native_widget_deleted); params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; widget->Init(params); @@ -445,8 +402,8 @@ TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsViewsNativeWidget) { scoped_ptr<Widget> widget(new OwnershipTestWidget(&state)); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = - new OwnershipTestNativeWidgetAura(widget.get(), &state); + params.native_widget = CreatePlatformNativeWidgetImpl( + params, widget.get(), kStubCapture, &state.native_widget_deleted); params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; widget->Init(params); @@ -470,9 +427,9 @@ TEST_F(WidgetOwnershipTest, scoped_ptr<Widget> widget(new OwnershipTestWidget(&state)); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = - new OwnershipTestNativeWidgetAura(widget.get(), &state); params.parent = toplevel->GetNativeView(); + params.native_widget = CreatePlatformNativeWidgetImpl( + params, widget.get(), kStubCapture, &state.native_widget_deleted); params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; widget->Init(params); @@ -500,8 +457,8 @@ TEST_F(WidgetOwnershipTest, Ownership_PlatformNativeWidgetOwnsWidget) { Widget* widget = new OwnershipTestWidget(&state); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = - new OwnershipTestNativeWidgetAura(widget, &state); + params.native_widget = CreatePlatformNativeWidgetImpl( + params, widget, kStubCapture, &state.native_widget_deleted); widget->Init(params); // Now destroy the native widget. @@ -519,9 +476,9 @@ TEST_F(WidgetOwnershipTest, Ownership_ViewsNativeWidgetOwnsWidget) { Widget* widget = new OwnershipTestWidget(&state); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = - new OwnershipTestNativeWidgetAura(widget, &state); params.parent = toplevel->GetNativeView(); + params.native_widget = CreatePlatformNativeWidgetImpl( + params, widget, kStubCapture, &state.native_widget_deleted); widget->Init(params); // Now destroy the native widget. This is achieved by closing the toplevel. @@ -543,8 +500,8 @@ TEST_F(WidgetOwnershipTest, Widget* widget = new OwnershipTestWidget(&state); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = - new OwnershipTestNativeWidgetAura(widget, &state); + params.native_widget = CreatePlatformNativeWidgetImpl( + params, widget, kStubCapture, &state.native_widget_deleted); widget->Init(params); // Now simulate a destroy of the platform native widget from the OS: @@ -564,9 +521,9 @@ TEST_F(WidgetOwnershipTest, Widget* widget = new OwnershipTestWidget(&state); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = - new OwnershipTestNativeWidgetAura(widget, &state); params.parent = toplevel->GetNativeView(); + params.native_widget = CreatePlatformNativeWidgetImpl( + params, widget, kStubCapture, &state.native_widget_deleted); widget->Init(params); // Destroy the widget (achieved by closing the toplevel). @@ -590,9 +547,9 @@ TEST_F(WidgetOwnershipTest, Widget* widget = new OwnershipTestWidget(&state); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = - new OwnershipTestNativeWidgetAura(widget, &state); params.parent = toplevel->GetNativeView(); + params.native_widget = CreatePlatformNativeWidgetImpl( + params, widget, kStubCapture, &state.native_widget_deleted); widget->Init(params); // Destroy the widget. @@ -616,8 +573,8 @@ TEST_F(WidgetOwnershipTest, scoped_ptr<Widget> widget(new OwnershipTestWidget(&state)); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = - new OwnershipTestNativeWidgetAura(widget.get(), &state); + params.native_widget = CreatePlatformNativeWidgetImpl( + params, widget.get(), kStubCapture, &state.native_widget_deleted); params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.delegate = delegate_view; widget->Init(params); @@ -658,7 +615,6 @@ class WidgetWithDestroyedNativeViewTest : public ViewsTestBase { widget->Activate(); widget->Deactivate(); widget->IsActive(); - widget->DisableInactiveRendering(); widget->SetAlwaysOnTop(true); widget->IsAlwaysOnTop(); widget->Maximize(); @@ -667,7 +623,6 @@ class WidgetWithDestroyedNativeViewTest : public ViewsTestBase { widget->IsMaximized(); widget->IsFullscreen(); widget->SetOpacity(0); - widget->SetUseDragFrame(true); widget->FlashFrame(true); widget->IsVisible(); widget->GetThemeProvider(); @@ -706,7 +661,8 @@ TEST_F(WidgetWithDestroyedNativeViewTest, Test) { { Widget widget; Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - params.native_widget = new PlatformDesktopNativeWidget(&widget); + params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(params, &widget, nullptr); params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; widget.Init(params); widget.Show(); @@ -971,6 +927,11 @@ TEST_F(WidgetObserverTest, ClosingOnHiddenParent) { // Test behavior of NativeWidget*::GetWindowPlacement on the native desktop. TEST_F(WidgetTest, GetWindowPlacement) { + if (IsMus()) { + NOTIMPLEMENTED(); + return; + } + WidgetAutoclosePtr widget; #if defined(OS_LINUX) && !defined(OS_CHROMEOS) // On desktop-Linux cheat and use non-desktop widgets. On X11, minimize is @@ -1081,10 +1042,12 @@ TEST_F(WidgetTest, MinimumSizeConstraints) { widget->SetSize(smaller_size); #if defined(OS_LINUX) && !defined(OS_CHROMEOS) // TODO(tapted): Desktop Linux ignores size constraints for SetSize. Fix it. - EXPECT_EQ(smaller_size, widget->GetClientAreaBoundsInScreen().size()); + const bool use_small_size = IsMus() ? false : true; #else - EXPECT_EQ(minimum_size, widget->GetClientAreaBoundsInScreen().size()); + const bool use_small_size = false; #endif + EXPECT_EQ(use_small_size ? smaller_size : minimum_size, + widget->GetClientAreaBoundsInScreen().size()); } // Tests that SetBounds() and GetWindowBoundsInScreen() is symmetric when the @@ -1155,10 +1118,10 @@ TEST_F(WidgetTest, GetWindowBoundsInScreen) { // Test that GetRestoredBounds() returns the original bounds of the window. TEST_F(WidgetTest, MAYBE_GetRestoredBounds) { -#if defined(OS_MACOSX) - // Fullscreen on Mac requires an interactive UI test, fake them here. - ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen; -#endif + if (IsMus()) { + NOTIMPLEMENTED(); + return; + } WidgetAutoclosePtr toplevel(CreateNativeDesktopWidget()); toplevel->Show(); @@ -1188,14 +1151,8 @@ TEST_F(WidgetTest, MAYBE_GetRestoredBounds) { toplevel->SetFullscreen(true); RunPendingMessages(); - if (IsTestingSnowLeopard()) { - // Fullscreen not implemented for Snow Leopard. - EXPECT_EQ(toplevel->GetWindowBoundsInScreen(), - toplevel->GetRestoredBounds()); - } else { - EXPECT_NE(toplevel->GetWindowBoundsInScreen(), - toplevel->GetRestoredBounds()); - } + EXPECT_NE(toplevel->GetWindowBoundsInScreen(), + toplevel->GetRestoredBounds()); EXPECT_EQ(bounds, toplevel->GetRestoredBounds()); toplevel->SetFullscreen(false); @@ -1239,7 +1196,8 @@ TEST_F(WidgetTest, DISABLED_FocusChangesOnBubble) { init_params.bounds = gfx::Rect(0, 0, 200, 200); init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; #if !defined(OS_CHROMEOS) - init_params.native_widget = new PlatformDesktopNativeWidget(&widget); + init_params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(init_params, &widget, nullptr); #endif widget.Init(init_params); widget.SetContentsView(contents_view); @@ -1301,6 +1259,10 @@ TEST_F(WidgetTest, BubbleControlsResetOnInit) { // the case for desktop widgets on Windows. Other platforms retain the window // size while minimized. TEST_F(WidgetTest, TestViewWidthAfterMinimizingWidget) { + if (IsMus()) { + // This test is testing behavior specific to DesktopWindowTreeHostWin. + return; + } // Create a widget. Widget widget; Widget::InitParams init_params = @@ -1309,7 +1271,8 @@ TEST_F(WidgetTest, TestViewWidthAfterMinimizingWidget) { gfx::Rect initial_bounds(0, 0, 300, 400); init_params.bounds = initial_bounds; init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - init_params.native_widget = new PlatformDesktopNativeWidget(&widget); + init_params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(init_params, &widget, nullptr); widget.Init(init_params); NonClientView* non_client_view = widget.non_client_view(); NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget); @@ -1383,7 +1346,8 @@ class DesktopAuraTestValidPaintWidget : public views::Widget { void DesktopAuraTestValidPaintWidget::InitForTest(InitParams init_params) { init_params.bounds = gfx::Rect(0, 0, 200, 200); init_params.ownership = InitParams::WIDGET_OWNS_NATIVE_WIDGET; - init_params.native_widget = new PlatformDesktopNativeWidget(this); + init_params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(init_params, this, nullptr); Init(init_params); View* contents_view = new View; @@ -1394,7 +1358,14 @@ void DesktopAuraTestValidPaintWidget::InitForTest(InitParams init_params) { Activate(); } -TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterCloseTest) { +#if defined(OS_LINUX) +// Flaky on Linux rel ng: https://crbug.com/596039. +#define MAYBE_DesktopNativeWidgetNoPaintAfterCloseTest DISABLED_DesktopNativeWidgetNoPaintAfterCloseTest +#else +#define MAYBE_DesktopNativeWidgetNoPaintAfterCloseTest DesktopNativeWidgetNoPaintAfterCloseTest +#endif + +TEST_F(WidgetTest, MAYBE_DesktopNativeWidgetNoPaintAfterCloseTest) { DesktopAuraTestValidPaintWidget widget; widget.InitForTest(CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS)); RunPendingMessages(); @@ -1406,7 +1377,12 @@ TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterCloseTest) { EXPECT_FALSE(widget.received_paint_while_hidden()); } -TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterHideTest) { +#if defined(OS_LINUX) +#define MAYBE_DesktopNativeWidgetNoPaintAfterHideTest DISABLED_DesktopNativeWidgetNoPaintAfterHideTest +#else +#define MAYBE_DesktopNativeWidgetNoPaintAfterHideTest DesktopNativeWidgetNoPaintAfterHideTest +#endif +TEST_F(WidgetTest, MAYBE_DesktopNativeWidgetNoPaintAfterHideTest) { DesktopAuraTestValidPaintWidget widget; widget.InitForTest(CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS)); RunPendingMessages(); @@ -1430,7 +1406,8 @@ TEST_F(WidgetTest, TestWindowVisibilityAfterHide) { gfx::Rect initial_bounds(0, 0, 300, 400); init_params.bounds = initial_bounds; init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - init_params.native_widget = new PlatformDesktopNativeWidget(&widget); + init_params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(init_params, &widget, nullptr); widget.Init(init_params); NonClientView* non_client_view = widget.non_client_view(); NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget); @@ -1690,7 +1667,9 @@ TEST_F(WidgetTest, SynthesizeMouseMoveEvent) { EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_MOVED)); gfx::Point cursor_location(5, 5); - ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow()); + ui::test::EventGenerator generator( + IsMus() ? widget->GetNativeWindow() : GetContext(), + widget->GetNativeWindow()); generator.MoveMouseTo(cursor_location); EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_MOVED)); @@ -1734,7 +1713,7 @@ class MousePressEventConsumer : public ui::EventHandler { // Test that mouse presses and mouse releases are dispatched normally when a // touch is down. TEST_F(WidgetTest, MouseEventDispatchWhileTouchIsDown) { - WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); + Widget* widget = CreateTopLevelNativeWidget(); widget->Show(); widget->SetSize(gfx::Size(300, 300)); @@ -1745,12 +1724,17 @@ TEST_F(WidgetTest, MouseEventDispatchWhileTouchIsDown) { MousePressEventConsumer consumer; event_count_view->AddPostTargetHandler(&consumer); - ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow()); - generator.PressTouch(); - generator.ClickLeftButton(); + scoped_ptr<ui::test::EventGenerator> generator(new ui::test::EventGenerator( + IsMus() ? widget->GetNativeWindow() : GetContext(), + widget->GetNativeWindow())); + generator->PressTouch(); + generator->ClickLeftButton(); EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED)); EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_RELEASED)); + + // For mus it's important we destroy the widget before the EventGenerator. + widget->CloseNow(); } #endif // !defined(OS_MACOSX) || defined(USE_AURA) @@ -1771,15 +1755,16 @@ class WidgetWindowTitleTest : public WidgetTest { WidgetAutoclosePtr widget(new Widget()); // Destroyed by CloseNow(). Widget::InitParams init_params = CreateParams(Widget::InitParams::TYPE_WINDOW); - widget->Init(init_params); #if !defined(OS_CHROMEOS) if (desktop_native_widget) - init_params.native_widget = new PlatformDesktopNativeWidget(widget.get()); + init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl( + init_params, widget.get(), nullptr); #else DCHECK(!desktop_native_widget) << "DesktopNativeWidget does not exist on non-Aura or on ChromeOS."; #endif + widget->Init(init_params); internal::NativeWidgetPrivate* native_widget = widget->native_widget_private(); @@ -1821,6 +1806,14 @@ TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_DesktopNativeWidget) { #endif // !OS_CHROMEOS TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) { + // This test doesn't work in mus as it assumes widget and GetContext() + // share an aura hierarchy. Test coverage of deletion from mouse pressed is + // important though and should be added, hence the NOTIMPLEMENTED(). + // http://crbug.com/594260. + if (IsMus()) { + NOTIMPLEMENTED(); + return; + } Widget* widget = new Widget; Widget::InitParams params = CreateParams(views::Widget::InitParams::TYPE_POPUP); @@ -1844,6 +1837,9 @@ TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) { #if !defined(OS_MACOSX) || defined(USE_AURA) TEST_F(WidgetTest, WidgetDeleted_InDispatchGestureEvent) { + // This test doesn't make sense for mus. Force NativeWidgetAura to be used. + DisableNativeWidgetMus(); + Widget* widget = new Widget; Widget::InitParams params = CreateParams(views::Widget::InitParams::TYPE_POPUP); @@ -1895,7 +1891,8 @@ bool RunGetNativeThemeFromDestructor(const Widget::InitParams& in_params, params.delegate = new GetNativeThemeFromDestructorView; #if !defined(OS_CHROMEOS) if (is_first_run) { - params.native_widget = new PlatformDesktopNativeWidget(widget.get()); + params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(params, widget.get(), nullptr); needs_second_run = true; } #endif @@ -1979,7 +1976,8 @@ TEST_F(WidgetTest, CloseDestroys) { CreateParams(views::Widget::InitParams::TYPE_MENU); params.opacity = Widget::InitParams::OPAQUE_WINDOW; #if !defined(OS_CHROMEOS) - params.native_widget = new PlatformDesktopNativeWidget(widget); + params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(params, widget, nullptr); #endif widget->Init(params); widget->Show(); @@ -2906,8 +2904,10 @@ class WidgetChildDestructionTest : public WidgetTest { Widget::InitParams params = CreateParams(views::Widget::InitParams::TYPE_WINDOW); #if !defined(OS_CHROMEOS) - if (top_level_has_desktop_native_widget_aura) - params.native_widget = new PlatformDesktopNativeWidget(top_level); + if (top_level_has_desktop_native_widget_aura) { + params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(params, top_level, nullptr); + } #endif top_level->Init(params); top_level->GetRootView()->AddChildView( @@ -2919,8 +2919,10 @@ class WidgetChildDestructionTest : public WidgetTest { CreateParams(views::Widget::InitParams::TYPE_POPUP); child_params.parent = top_level->GetNativeView(); #if !defined(OS_CHROMEOS) - if (child_has_desktop_native_widget_aura) - child_params.native_widget = new PlatformDesktopNativeWidget(child); + if (child_has_desktop_native_widget_aura) { + child_params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(child_params, child, nullptr); + } #endif child->Init(child_params); child->GetRootView()->AddChildView( @@ -2970,27 +2972,34 @@ TEST_F(WidgetTest, FullscreenStatePropagated) { init_params.bounds = gfx::Rect(0, 0, 500, 500); init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - { - Widget top_level_widget; - top_level_widget.Init(init_params); - top_level_widget.SetFullscreen(true); - EXPECT_EQ(top_level_widget.IsVisible(), - IsNativeWindowVisible(top_level_widget.GetNativeWindow())); - top_level_widget.CloseNow(); - } + Widget top_level_widget; + top_level_widget.Init(init_params); + top_level_widget.SetFullscreen(true); + EXPECT_EQ(top_level_widget.IsVisible(), + IsNativeWindowVisible(top_level_widget.GetNativeWindow())); + top_level_widget.CloseNow(); +} + +// Verifies nativeview visbility matches that of Widget visibility when +// SetFullscreen is invoked, for a widget provided with a desktop widget. #if !defined(OS_CHROMEOS) - { - Widget top_level_widget; - init_params.native_widget = - new PlatformDesktopNativeWidget(&top_level_widget); - top_level_widget.Init(init_params); - top_level_widget.SetFullscreen(true); - EXPECT_EQ(top_level_widget.IsVisible(), - IsNativeWindowVisible(top_level_widget.GetNativeWindow())); - top_level_widget.CloseNow(); - } -#endif +TEST_F(WidgetTest, FullscreenStatePropagated_DesktopWidget) { + Widget::InitParams init_params = + CreateParams(Widget::InitParams::TYPE_WINDOW); + init_params.show_state = ui::SHOW_STATE_NORMAL; + init_params.bounds = gfx::Rect(0, 0, 500, 500); + init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + Widget top_level_widget; + init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl( + init_params, &top_level_widget, nullptr); + + top_level_widget.Init(init_params); + top_level_widget.SetFullscreen(true); + EXPECT_EQ(top_level_widget.IsVisible(), + IsNativeWindowVisible(top_level_widget.GetNativeWindow())); + top_level_widget.CloseNow(); } +#endif namespace { @@ -3045,12 +3054,7 @@ TEST_F(WidgetTest, FullscreenFrameLayout) { widget->Show(); RunPendingMessages(); - if (IsTestingSnowLeopard()) { - // Fullscreen is currently ignored on Snow Leopard. - EXPECT_FALSE(frame->fullscreen_layout_called()); - } else { - EXPECT_TRUE(frame->fullscreen_layout_called()); - } + EXPECT_TRUE(frame->fullscreen_layout_called()); } #if !defined(OS_CHROMEOS) @@ -3078,7 +3082,8 @@ TEST_F(WidgetTest, IsActiveFromDestroy) { Widget parent_widget; Widget::InitParams parent_params = CreateParams(Widget::InitParams::TYPE_POPUP); - parent_params.native_widget = new PlatformDesktopNativeWidget(&parent_widget); + parent_params.native_widget = CreatePlatformDesktopNativeWidgetImpl( + parent_params, &parent_widget, nullptr); parent_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; parent_widget.Init(parent_params); parent_widget.Show(); @@ -3183,37 +3188,13 @@ TEST_F(WidgetTest, NonClientWindowValidAfterInit) { } #if defined(OS_WIN) -// This test validates that sending WM_CHAR/WM_SYSCHAR/WM_SYSDEADCHAR -// messages via the WindowEventTarget interface implemented by the -// HWNDMessageHandler class does not cause a crash due to an unprocessed -// event -TEST_F(WidgetTest, CharMessagesAsKeyboardMessagesDoesNotCrash) { - Widget widget; - Widget::InitParams params = - CreateParams(Widget::InitParams::TYPE_WINDOW); - params.native_widget = new PlatformDesktopNativeWidget(&widget); - params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - widget.Init(params); - widget.Show(); - - ui::WindowEventTarget* target = - reinterpret_cast<ui::WindowEventTarget*>(ui::ViewProp::GetValue( - widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(), - ui::WindowEventTarget::kWin32InputEventTarget)); - EXPECT_NE(nullptr, target); - bool handled = false; - target->HandleKeyboardMessage(WM_CHAR, 0, 0, &handled); - target->HandleKeyboardMessage(WM_SYSCHAR, 0, 0, &handled); - target->HandleKeyboardMessage(WM_SYSDEADCHAR, 0, 0, &handled); - widget.CloseNow(); -} - // Provides functionality to subclass a window and keep track of messages // received. class SubclassWindowHelper { public: explicit SubclassWindowHelper(HWND window) - : window_(window) { + : window_(window), + message_to_destroy_on_(0) { EXPECT_EQ(instance_, nullptr); instance_ = this; EXPECT_TRUE(Subclass()); @@ -3233,6 +3214,10 @@ class SubclassWindowHelper { messages_.clear(); } + void set_message_to_destroy_on(unsigned int message) { + message_to_destroy_on_ = message; + } + private: bool Subclass() { old_proc_ = reinterpret_cast<WNDPROC>( @@ -3258,14 +3243,20 @@ class SubclassWindowHelper { // Keep track of messags received for this window. instance_->messages_.insert(message); - return ::CallWindowProc(instance_->old_proc_, window, message, w_param, - l_param); + LRESULT ret = ::CallWindowProc(instance_->old_proc_, window, message, + w_param, l_param); + if (message == instance_->message_to_destroy_on_) { + instance_->Unsubclass(); + ::DestroyWindow(window); + } + return ret; } WNDPROC old_proc_; HWND window_; static SubclassWindowHelper* instance_; std::set<unsigned int> messages_; + unsigned int message_to_destroy_on_; DISALLOW_COPY_AND_ASSIGN(SubclassWindowHelper); }; @@ -3278,11 +3269,13 @@ SubclassWindowHelper* SubclassWindowHelper::instance_ = nullptr; // 1. Posting a WM_NCMOUSEMOVE message for a different location. // 2. Posting a WM_NCMOUSEMOVE message with a different hittest code. // 3. Posting a WM_MOUSEMOVE message. -TEST_F(WidgetTest, SysCommandMoveOnNCLButtonDownOnCaptionAndMoveTest) { +// Disabled because of flaky timeouts: http://crbug.com/592742 +TEST_F(WidgetTest, DISABLED_SysCommandMoveOnNCLButtonDownOnCaptionAndMoveTest) { Widget widget; Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); - params.native_widget = new PlatformDesktopNativeWidget(&widget); + params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(params, &widget, nullptr); params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; widget.Init(params); widget.SetBounds(gfx::Rect(0, 0, 200, 200)); @@ -3347,10 +3340,49 @@ TEST_F(WidgetTest, SysCommandMoveOnNCLButtonDownOnCaptionAndMoveTest) { widget.CloseNow(); } + +// This test validates that destroying the window in the context of the +// WM_SYSCOMMAND message with SC_MOVE does not crash. +// Disabled because of flaky timeouts: http://crbug.com/592742 +TEST_F(WidgetTest, DISABLED_DestroyInSysCommandNCLButtonDownOnCaption) { + Widget widget; + Widget::InitParams params = + CreateParams(Widget::InitParams::TYPE_WINDOW); + params.native_widget = + CreatePlatformDesktopNativeWidgetImpl(params, &widget, nullptr); + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + widget.Init(params); + widget.SetBounds(gfx::Rect(0, 0, 200, 200)); + widget.Show(); + ::SetCursorPos(500, 500); + + HWND window = widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(); + + SubclassWindowHelper subclass_helper(window); + + // Destroying the window in the context of the WM_SYSCOMMAND message + // should not crash. + subclass_helper.set_message_to_destroy_on(WM_SYSCOMMAND); + + ::PostMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(100, 100)); + ::PostMessage(window, WM_NCMOUSEMOVE, HTCAPTION, MAKELPARAM(110, 110)); + RunPendingMessages(); + + EXPECT_TRUE(subclass_helper.received_message(WM_NCLBUTTONDOWN)); + EXPECT_TRUE(subclass_helper.received_message(WM_SYSCOMMAND)); + + widget.CloseNow(); +} + #endif // Test that SetAlwaysOnTop and IsAlwaysOnTop are consistent. TEST_F(WidgetTest, AlwaysOnTop) { + if (IsMus()) { + NOTIMPLEMENTED(); + return; + } + WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); EXPECT_FALSE(widget->IsAlwaysOnTop()); widget->SetAlwaysOnTop(true); @@ -3401,5 +3433,78 @@ TEST_F(WidgetTest, OnDeviceScaleFactorChanged) { EXPECT_EQ(scale_factor, view->last_scale_factor()); } +namespace { + +class TestWidgetRemovalsObserver : public WidgetRemovalsObserver { + public: + TestWidgetRemovalsObserver() {} + ~TestWidgetRemovalsObserver() override {} + + void OnWillRemoveView(Widget* widget, View* view) override { + removed_views_.insert(view); + } + + bool DidRemoveView(View* view) { + return removed_views_.find(view) != removed_views_.end(); + } + + private: + std::set<View*> removed_views_; + + DISALLOW_COPY_AND_ASSIGN(TestWidgetRemovalsObserver); +}; + +} + +// Test that WidgetRemovalsObserver::OnWillRemoveView is called when deleting +// a view. +TEST_F(WidgetTest, WidgetRemovalsObserverCalled) { + WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget()); + TestWidgetRemovalsObserver removals_observer; + widget->AddRemovalsObserver(&removals_observer); + + View* parent = new View(); + widget->client_view()->AddChildView(parent); + + View* child = new View(); + parent->AddChildView(child); + + widget->client_view()->RemoveChildView(parent); + EXPECT_TRUE(removals_observer.DidRemoveView(parent)); + EXPECT_FALSE(removals_observer.DidRemoveView(child)); + + // Calling RemoveChildView() doesn't delete the view, but deleting + // |parent| will automatically delete |child|. + delete parent; + + widget->RemoveRemovalsObserver(&removals_observer); +} + +// Test that WidgetRemovalsObserver::OnWillRemoveView is called when moving +// a view from one widget to another, but not when moving a view within +// the same widget. +TEST_F(WidgetTest, WidgetRemovalsObserverCalledWhenMovingBetweenWidgets) { + WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget()); + TestWidgetRemovalsObserver removals_observer; + widget->AddRemovalsObserver(&removals_observer); + + View* parent = new View(); + widget->client_view()->AddChildView(parent); + + View* child = new View(); + widget->client_view()->AddChildView(child); + + // Reparenting the child shouldn't call the removals observer. + parent->AddChildView(child); + EXPECT_FALSE(removals_observer.DidRemoveView(child)); + + // Moving the child to a different widget should call the removals observer. + WidgetAutoclosePtr widget2(CreateTopLevelPlatformWidget()); + widget2->client_view()->AddChildView(child); + EXPECT_TRUE(removals_observer.DidRemoveView(child)); + + widget->RemoveRemovalsObserver(&removals_observer); +} + } // namespace test } // namespace views |