Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2325)

Unified Diff: ash/wm/drag_window_controller.cc

Issue 1838003002: Create drag windows on all displays (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix silly typo Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ash/wm/drag_window_controller.h ('k') | ash/wm/drag_window_resizer.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ash/wm/drag_window_controller.cc
diff --git a/ash/wm/drag_window_controller.cc b/ash/wm/drag_window_controller.cc
index 405b86932bc3bafa8a02ac6f27e7de799ac8a17d..ee62ab4412730aa1927438c92874c4b1d36bb116 100644
--- a/ash/wm/drag_window_controller.cc
+++ b/ash/wm/drag_window_controller.cc
@@ -4,11 +4,19 @@
#include "ash/wm/drag_window_controller.h"
+#include <algorithm>
+
+#include "ash/display/window_tree_host_manager.h"
+#include "ash/screen_util.h"
+#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/window_util.h"
+#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_delegate.h"
#include "ui/aura/window_event_dispatcher.h"
+#include "ui/base/hit_test.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_tree_owner.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
@@ -19,102 +27,210 @@
namespace ash {
-DragWindowController::DragWindowController(aura::Window* window)
- : window_(window),
- drag_widget_(NULL) {
-}
+// This keeps tack of the drag window's state. It creates/destory/updates bounds
+// and opacity based on the current bounds.
+class DragWindowController::DragWindowDetails : public aura::WindowDelegate {
+ public:
+ DragWindowDetails(const gfx::Display& display, aura::Window* original_window)
+ : root_window_(Shell::GetInstance()
+ ->window_tree_host_manager()
+ ->GetRootWindowForDisplayId(display.id())) {}
+
+ ~DragWindowDetails() override {
+ delete drag_window_;
+ DCHECK(!drag_window_);
+ }
-DragWindowController::~DragWindowController() {
- Hide();
-}
+ void Update(aura::Window* original_window,
+ const gfx::Rect& bounds_in_screen,
+ const gfx::Point& drag_location_in_screen) {
+ gfx::Rect root_bounds_in_screen = root_window_->GetBoundsInScreen();
+ if (!root_bounds_in_screen.Intersects(bounds_in_screen)) {
+ delete drag_window_;
+ // Make sure drag_window_ is reset so that new drag window will be created
+ // when it becomes necessary again.
+ DCHECK(!drag_window_);
+ layer_owner_.reset();
+ return;
+ }
+ if (!drag_window_)
+ CreateDragWindow(original_window, bounds_in_screen);
+
+ gfx::Rect bounds_in_root = ScreenUtil::ConvertRectFromScreen(
+ drag_window_->parent(), bounds_in_screen);
+ drag_window_->SetBounds(bounds_in_root);
+ if (root_bounds_in_screen.Contains(drag_location_in_screen)) {
+ SetOpacity(original_window, 1.f);
+ } else {
+ drag_window_->SetBounds(bounds_in_root);
+ gfx::Rect visible_bounds = root_bounds_in_screen;
+ visible_bounds.Intersect(bounds_in_screen);
+ SetOpacity(original_window,
+ GetDragWindowOpacity(bounds_in_screen, visible_bounds));
+ }
+ }
-void DragWindowController::SetDestinationDisplay(
- const gfx::Display& dst_display) {
- dst_display_ = dst_display;
-}
+ private:
+ friend class DragWindowController;
+
+ void CreateDragWindow(aura::Window* original_window,
+ const gfx::Rect& bounds_in_screen) {
+ DCHECK(!drag_window_);
+ drag_window_ = new aura::Window(this);
+ int parent_id = original_window->parent()->id();
+ aura::Window* container = root_window_->GetChildById(parent_id);
+
+ drag_window_->SetType(ui::wm::WINDOW_TYPE_POPUP);
+ drag_window_->SetTransparent(true);
+ drag_window_->Init(ui::LAYER_TEXTURED);
+ drag_window_->SetName("DragWindow");
+ drag_window_->set_id(kShellWindowId_PhantomWindow);
+ drag_window_->SetProperty(aura::client::kAnimationsDisabledKey, true);
+ container->AddChild(drag_window_);
+ drag_window_->SetBounds(bounds_in_screen);
+ SetShadowType(drag_window_, ::wm::SHADOW_TYPE_RECTANGULAR);
+
+ RecreateWindowLayers(original_window);
+ layer_owner_->root()->SetVisible(true);
+ drag_window_->layer()->Add(layer_owner_->root());
+ drag_window_->layer()->StackAtTop(layer_owner_->root());
+
+ // Show the widget after all the setups.
+ drag_window_->Show();
+
+ // Fade the window in.
+ ui::Layer* drag_layer = drag_window_->layer();
+ drag_layer->SetOpacity(0);
+ ui::ScopedLayerAnimationSettings scoped_setter(drag_layer->GetAnimator());
+ drag_layer->SetOpacity(1);
+ }
-void DragWindowController::Show() {
- if (!drag_widget_)
- CreateDragWidget(window_->GetBoundsInScreen());
- drag_widget_->Show();
-}
+ void RecreateWindowLayers(aura::Window* original_window) {
+ DCHECK(!layer_owner_.get());
+ layer_owner_ = ::wm::RecreateLayers(original_window);
+ // TODO(oshima): Recreated child layers may not have been painted
+ // yet, and may not be able to paint to because it does not have
+ // its original delegate.
+ layer_owner_->root()->set_delegate(original_window->layer()->delegate());
+ // Place the layer at (0, 0) of the DragWindowController's window.
+ gfx::Rect layer_bounds = layer_owner_->root()->bounds();
+ layer_bounds.set_origin(gfx::Point(0, 0));
+ layer_owner_->root()->SetBounds(layer_bounds);
+ layer_owner_->root()->SetVisible(false);
+ // Detach it from the current container.
+ layer_owner_->root()->parent()->Remove(layer_owner_->root());
+ }
-void DragWindowController::SetBounds(const gfx::Rect& bounds) {
- DCHECK(drag_widget_);
- bounds_ = bounds;
- SetBoundsInternal(bounds);
+ void SetOpacity(const aura::Window* original_window, float opacity) {
+ ui::Layer* layer = drag_window_->layer();
+ ui::ScopedLayerAnimationSettings scoped_setter(layer->GetAnimator());
+ layer->SetOpacity(opacity);
+ layer_owner_->root()->SetOpacity(1.0f);
+ }
+
+ // aura::WindowDelegate:
+ gfx::Size GetMinimumSize() const override { return gfx::Size(); }
+ gfx::Size GetMaximumSize() const override { return gfx::Size(); }
+ void OnBoundsChanged(const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override {}
+ gfx::NativeCursor GetCursor(const gfx::Point& point) override {
+ return gfx::kNullCursor;
+ }
+ int GetNonClientComponent(const gfx::Point& point) const override {
+ return HTNOWHERE;
+ }
+ bool ShouldDescendIntoChildForEventHandling(
+ aura::Window* child,
+ const gfx::Point& location) override {
+ return false;
+ }
+ bool CanFocus() override { return false; }
+ void OnCaptureLost() override {}
+ void OnPaint(const ui::PaintContext& context) override {}
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
+ void OnWindowDestroyed(aura::Window* window) override {}
+ void OnWindowTargetVisibilityChanged(bool visible) override {}
+ bool HasHitTestMask() const override { return false; }
+ void GetHitTestMask(gfx::Path* mask) const override {}
+ void OnWindowDestroying(aura::Window* window) override {
+ DCHECK_EQ(drag_window_, window);
+ drag_window_ = nullptr;
+ }
+
+ aura::Window* root_window_;
+
+ aura::Window* drag_window_ = nullptr; // Owned by the container.
+
+ // The copy of window_->layer() and its descendants.
+ scoped_ptr<ui::LayerTreeOwner> layer_owner_;
+
+ DISALLOW_COPY_AND_ASSIGN(DragWindowDetails);
+};
+
+// static
+float DragWindowController::GetDragWindowOpacity(
+ const gfx::Rect& window_bounds,
+ const gfx::Rect& visible_bounds) {
+ // The maximum opacity of the drag phantom window.
+ static const float kMaxOpacity = 0.8f;
+
+ return kMaxOpacity * visible_bounds.size().GetArea() /
+ window_bounds.size().GetArea();
}
-void DragWindowController::Hide() {
- if (drag_widget_) {
- drag_widget_->Close();
- drag_widget_ = NULL;
+DragWindowController::DragWindowController(aura::Window* window)
+ : window_(window) {
+ DCHECK(drag_windows_.empty());
+ gfx::Screen* screen = gfx::Screen::GetScreen();
+ gfx::Display current = screen->GetDisplayNearestWindow(window_);
+
+ for (const gfx::Display& display : screen->GetAllDisplays()) {
+ if (current.id() == display.id())
+ continue;
+ drag_windows_.push_back(
+ make_scoped_ptr(new DragWindowDetails(display, window_)));
}
- layer_owner_.reset();
}
-void DragWindowController::SetOpacity(float opacity) {
- DCHECK(drag_widget_);
- ui::Layer* layer = drag_widget_->GetNativeWindow()->layer();
- ui::ScopedLayerAnimationSettings scoped_setter(layer->GetAnimator());
- layer->SetOpacity(opacity);
+DragWindowController::~DragWindowController() {}
+
+void DragWindowController::Update(const gfx::Rect& bounds_in_screen,
+ const gfx::Point& drag_location_in_screen) {
+ for (scoped_ptr<DragWindowDetails>& details : drag_windows_)
+ details->Update(window_, bounds_in_screen, drag_location_in_screen);
}
-void DragWindowController::CreateDragWidget(const gfx::Rect& bounds) {
- DCHECK(!drag_widget_);
- drag_widget_ = new views::Widget;
- views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
- params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
- params.parent = window_->parent();
- params.keep_on_top = true;
- drag_widget_->set_focus_on_creation(false);
- drag_widget_->Init(params);
- drag_widget_->SetVisibilityChangedAnimationsEnabled(false);
- drag_widget_->GetNativeWindow()->SetName("DragWindow");
- drag_widget_->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow);
- // Show shadow for the dragging window.
- SetShadowType(drag_widget_->GetNativeWindow(),
- ::wm::SHADOW_TYPE_RECTANGULAR);
- SetBoundsInternal(bounds);
- drag_widget_->StackAbove(window_);
-
- RecreateWindowLayers();
- aura::Window* window = drag_widget_->GetNativeWindow();
- layer_owner_->root()->SetVisible(true);
- window->layer()->Add(layer_owner_->root());
- window->layer()->StackAtTop(layer_owner_->root());
-
- // Show the widget after all the setups.
- drag_widget_->Show();
-
- // Fade the window in.
- ui::Layer* widget_layer = drag_widget_->GetNativeWindow()->layer();
- widget_layer->SetOpacity(0);
- ui::ScopedLayerAnimationSettings scoped_setter(widget_layer->GetAnimator());
- widget_layer->SetOpacity(1);
+int DragWindowController::GetDragWindowsCountForTest() const {
+ int count = 0;
+ for (const scoped_ptr<DragWindowDetails>& details : drag_windows_) {
+ if (details->drag_window_)
+ count++;
+ }
+ return count;
}
-void DragWindowController::SetBoundsInternal(const gfx::Rect& bounds) {
- aura::Window* window = drag_widget_->GetNativeWindow();
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(window->GetRootWindow());
- if (screen_position_client && dst_display_.is_valid())
- screen_position_client->SetBounds(window, bounds, dst_display_);
- else
- drag_widget_->SetBounds(bounds);
+const aura::Window* DragWindowController::GetDragWindowForTest(
+ size_t index) const {
+ for (const scoped_ptr<DragWindowDetails>& details : drag_windows_) {
+ if (details->drag_window_) {
+ if (index == 0)
+ return details->drag_window_;
+ index--;
+ }
+ }
+ return nullptr;
}
-void DragWindowController::RecreateWindowLayers() {
- DCHECK(!layer_owner_.get());
- layer_owner_ = ::wm::RecreateLayers(window_);
- layer_owner_->root()->set_delegate(window_->layer()->delegate());
- // Place the layer at (0, 0) of the DragWindowController's window.
- gfx::Rect layer_bounds = layer_owner_->root()->bounds();
- layer_bounds.set_origin(gfx::Point(0, 0));
- layer_owner_->root()->SetBounds(layer_bounds);
- layer_owner_->root()->SetVisible(false);
- // Detach it from the current container.
- layer_owner_->root()->parent()->Remove(layer_owner_->root());
+const ui::LayerTreeOwner* DragWindowController::GetDragLayerOwnerForTest(
+ size_t index) const {
+ for (const scoped_ptr<DragWindowDetails>& details : drag_windows_) {
+ if (details->layer_owner_) {
+ if (index == 0)
+ return details->layer_owner_.get();
+ index--;
+ }
+ }
+ return nullptr;
}
} // namespace ash
« no previous file with comments | « ash/wm/drag_window_controller.h ('k') | ash/wm/drag_window_resizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698