Commit 1c4a77b3 authored by sky@chromium.org's avatar sky@chromium.org

Attempt 2: Allows tab dragging when maximized on aura. To fix it I made it so

that you can drag a maximized window when tab dragging and no
constraints are imposed on the window. Only when the mouse is released
do we do anything. This only handles the multiple tab case, if you've
selected all the tabs in a maximized window we won't detach.

BUG=116074
TEST=none
R=ben@chromium.org
TBR=ben@chromium.org

Review URL: https://chromiumcodereview.appspot.com/9566014

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@124440 0039d316-1c4b-4281-b951-d872f2087c98
parent 16dd6e25
......@@ -7,11 +7,20 @@
#include "ash/wm/window_util.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_property.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/rect.h"
DECLARE_WINDOW_PROPERTY_TYPE(bool)
namespace ash {
namespace {
const aura::WindowProperty<bool> kWindowTrackedByWorkspaceSplitProp = {true};
} // namespace
void SetRestoreBounds(aura::Window* window, const gfx::Rect& bounds) {
scoped_ptr<const gfx::Rect> old_bounds(GetRestoreBounds(window));
window->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds));
......@@ -37,4 +46,15 @@ void ToggleMaximizedState(aura::Window* window) {
: ui::SHOW_STATE_MAXIMIZED);
}
const aura::WindowProperty<bool>* const
kWindowTrackedByWorkspaceSplitPropKey = &kWindowTrackedByWorkspaceSplitProp;
void SetTrackedByWorkspace(aura::Window* window, bool value) {
window->SetProperty(kWindowTrackedByWorkspaceSplitPropKey, value);
}
bool GetTrackedByWorkspace(aura::Window* window) {
return window->GetProperty(kWindowTrackedByWorkspaceSplitPropKey);
}
}
......@@ -10,6 +10,8 @@
namespace aura {
class Window;
template<typename T>
struct WindowProperty;
}
namespace gfx {
......@@ -37,6 +39,16 @@ ASH_EXPORT void ClearRestoreBounds(aura::Window* window);
// Toggles the maximized state of the specified window.
ASH_EXPORT void ToggleMaximizedState(aura::Window* window);
ASH_EXPORT extern const aura::WindowProperty<bool>* const
kWindowTrackedByWorkspaceSplitPropKey;
// Sets whether the specified window is tracked by workspace code. Default is
// true. If set to false the workspace does not switch the current workspace,
// nor does it attempt to impose constraints on the bounds of the window. This
// is intended for tab dragging.
ASH_EXPORT void SetTrackedByWorkspace(aura::Window* window, bool value);
ASH_EXPORT bool GetTrackedByWorkspace(aura::Window* window);
}
#endif // ASH_WM_PROPERTY_UTIL_H_
......@@ -53,7 +53,7 @@ bool ToplevelWindowEventFilter::PreHandleMouseEvent(aura::Window* target,
if (WindowResizer::GetBoundsChangeForWindowComponent(component)) {
window_resizer_.reset(
CreateWindowResizer(target, event->location(), component));
if (!window_resizer_->is_resizable())
if (window_resizer_.get() && !window_resizer_->is_resizable())
window_resizer_.reset();
} else {
window_resizer_.reset();
......@@ -107,7 +107,7 @@ ui::GestureStatus ToplevelWindowEventFilter::PreHandleGestureEvent(
in_gesture_resize_ = true;
window_resizer_.reset(
CreateWindowResizer(target, event->location(), component));
if (!window_resizer_->is_resizable())
if (window_resizer_.get() && !window_resizer_->is_resizable())
window_resizer_.reset();
break;
}
......@@ -163,6 +163,8 @@ WindowResizer* ToplevelWindowEventFilter::CreateWindowResizer(
aura::Window* window,
const gfx::Point& point,
int window_component) {
if (!wm::IsWindowNormal(window))
return NULL; // Don't allow resizing/dragging maximized/fullscreen windows.
return new WindowResizer(window, point, window_component, grid_size_);
}
......
......@@ -106,13 +106,6 @@ gfx::Point ConvertPointToParent(aura::Window* window,
return result;
}
bool IsNormalWindow(aura::Window* window) {
return window->GetProperty(aura::client::kShowStateKey) ==
ui::SHOW_STATE_NORMAL ||
window->GetProperty(aura::client::kShowStateKey) ==
ui::SHOW_STATE_DEFAULT;
}
} // namespace
// static
......@@ -142,8 +135,7 @@ WindowResizer::WindowResizer(aura::Window* window,
GetPositionChangeDirectionForWindowComponent(window_component_)),
size_change_direction_(
GetSizeChangeDirectionForWindowComponent(window_component_)),
is_resizable_(bounds_change_ != kBoundsChangeDirection_None &&
IsNormalWindow(window)),
is_resizable_(bounds_change_ != kBoundsChangeDirection_None),
grid_size_(grid_size),
did_move_or_resize_(false),
root_filter_(NULL) {
......
......@@ -51,6 +51,13 @@ aura::Window* GetActivatableWindow(aura::Window* window) {
return internal::ActivationController::GetActivatableWindow(window);
}
bool IsWindowNormal(aura::Window* window) {
return window->GetProperty(aura::client::kShowStateKey) ==
ui::SHOW_STATE_NORMAL ||
window->GetProperty(aura::client::kShowStateKey) ==
ui::SHOW_STATE_DEFAULT;
}
bool IsWindowMaximized(aura::Window* window) {
return window->GetProperty(aura::client::kShowStateKey) ==
ui::SHOW_STATE_MAXIMIZED;
......
......@@ -30,6 +30,9 @@ ASH_EXPORT aura::Window* GetActiveWindow();
// this is probably what you're looking for.
ASH_EXPORT aura::Window* GetActivatableWindow(aura::Window* window);
// Returns true if |window| is normal or default.
ASH_EXPORT bool IsWindowNormal(aura::Window* window);
// Returns true if |window| is in the maximized state.
ASH_EXPORT bool IsWindowMaximized(aura::Window* window);
......
......@@ -4,6 +4,7 @@
#include "ash/wm/workspace/workspace_event_filter.h"
#include "ash/wm/property_util.h"
#include "ash/wm/window_frame.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/workspace_layout_manager.h"
......@@ -66,6 +67,12 @@ WindowResizer* WorkspaceEventFilter::CreateWindowResizer(
aura::Window* window,
const gfx::Point& point,
int window_component) {
// Allow dragging maximized windows if it's not tracked by workspace. This is
// set by tab dragging code.
if (!wm::IsWindowNormal(window) &&
(window_component != HTCAPTION || GetTrackedByWorkspace(window))) {
return NULL;
}
return
new WorkspaceWindowResizer(window, point, window_component, grid_size());
}
......
......@@ -8,6 +8,7 @@
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/workspace.h"
#include "ash/wm/workspace/workspace_manager.h"
#include "ash/wm/workspace/workspace_window_resizer.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/event.h"
#include "ui/aura/root_window.h"
......@@ -29,13 +30,19 @@ WorkspaceLayoutManager::WorkspaceLayoutManager(
: workspace_manager_(workspace_manager) {
}
WorkspaceLayoutManager::~WorkspaceLayoutManager() {}
WorkspaceLayoutManager::~WorkspaceLayoutManager() {
const aura::Window::Windows& windows(
workspace_manager_->contents_view()->children());
for (size_t i = 0; i < windows.size(); ++i)
windows[i]->RemoveObserver(this);
}
void WorkspaceLayoutManager::OnWindowResized() {
// Workspace is updated via RootWindowObserver::OnRootWindowResized.
}
void WorkspaceLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
child->AddObserver(this);
if (!workspace_manager_->IsManagedWindow(child))
return;
......@@ -56,6 +63,7 @@ void WorkspaceLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
void WorkspaceLayoutManager::OnWillRemoveWindowFromLayout(
aura::Window* child) {
child->RemoveObserver(this);
ClearRestoreBounds(child);
workspace_manager_->RemoveWindow(child);
}
......@@ -75,16 +83,29 @@ void WorkspaceLayoutManager::SetChildBounds(
aura::Window* child,
const gfx::Rect& requested_bounds) {
gfx::Rect child_bounds(requested_bounds);
if (wm::IsWindowMaximized(child)) {
child_bounds = gfx::Screen::GetMonitorWorkAreaNearestWindow(child);
} else if (wm::IsWindowFullscreen(child)) {
child_bounds = gfx::Screen::GetMonitorAreaNearestWindow(child);
} else {
child_bounds = gfx::Screen::GetMonitorWorkAreaNearestWindow(child).
AdjustToFit(requested_bounds);
if (GetTrackedByWorkspace(child)) {
if (wm::IsWindowMaximized(child)) {
child_bounds = gfx::Screen::GetMonitorWorkAreaNearestWindow(child);
} else if (wm::IsWindowFullscreen(child)) {
child_bounds = gfx::Screen::GetMonitorAreaNearestWindow(child);
} else {
child_bounds = gfx::Screen::GetMonitorWorkAreaNearestWindow(child).
AdjustToFit(requested_bounds);
}
}
SetChildBoundsDirect(child, child_bounds);
}
void WorkspaceLayoutManager::OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) {
if (key == ash::kWindowTrackedByWorkspaceSplitPropKey &&
ash::GetTrackedByWorkspace(window)) {
// We currently don't need to support transitioning from true to false, so
// we ignore it.
workspace_manager_->AddWindow(window);
}
}
} // namespace internal
} // namespace ash
......@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/window_observer.h"
namespace aura {
class MouseEvent;
......@@ -26,7 +27,8 @@ namespace internal {
class WorkspaceManager;
// LayoutManager for top level windows when WorkspaceManager is enabled.
class ASH_EXPORT WorkspaceLayoutManager : public aura::LayoutManager {
class ASH_EXPORT WorkspaceLayoutManager : public aura::LayoutManager,
public aura::WindowObserver {
public:
explicit WorkspaceLayoutManager(WorkspaceManager* workspace_manager);
virtual ~WorkspaceLayoutManager();
......@@ -45,6 +47,11 @@ class ASH_EXPORT WorkspaceLayoutManager : public aura::LayoutManager {
virtual void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) OVERRIDE;
// Overriden from aura::WindowObserver:
virtual void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) OVERRIDE;
private:
// Owned by WorkspaceController.
WorkspaceManager* workspace_manager_;
......
......@@ -88,7 +88,7 @@ WorkspaceManager::~WorkspaceManager() {
bool WorkspaceManager::IsManagedWindow(aura::Window* window) const {
return window->type() == aura::client::WINDOW_TYPE_NORMAL &&
!window->transient_parent();
!window->transient_parent() && ash::GetTrackedByWorkspace(window);
}
void WorkspaceManager::AddWindow(aura::Window* window) {
......@@ -186,10 +186,7 @@ gfx::Rect WorkspaceManager::AlignBoundsToGrid(const gfx::Rect& bounds) {
void WorkspaceManager::OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) {
if (!IsManagedWindow(window))
return;
if (key != aura::client::kShowStateKey)
if (key != aura::client::kShowStateKey || !IsManagedWindow(window))
return;
DCHECK(FindBy(window));
......
......@@ -31,7 +31,7 @@ class ShelfLayoutManager;
class WorkspaceManagerTest;
// WorkspaceManager manages multiple workspaces in the desktop.
class ASH_EXPORT WorkspaceManager : public aura::WindowObserver{
class ASH_EXPORT WorkspaceManager : public aura::WindowObserver {
public:
explicit WorkspaceManager(aura::Window* viewport);
virtual ~WorkspaceManager();
......
......@@ -4,6 +4,7 @@
#include "ash/wm/workspace/workspace_window_resizer.h"
#include "ash/wm/window_util.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_property.h"
......@@ -30,8 +31,10 @@ WorkspaceWindowResizer::WorkspaceWindowResizer(aura::Window* window,
const gfx::Point& location,
int window_component,
int grid_size)
: WindowResizer(window, location, window_component, grid_size) {
: WindowResizer(window, location, window_component, grid_size),
constrain_size_(wm::IsWindowNormal(window)) {
if (is_resizable() && GetHeightBeforeObscured(window) &&
constrain_size_ &&
(!WindowTouchesBottomOfScreen() ||
bounds_change() != kBoundsChange_Repositions)) {
ClearHeightBeforeObscured(window);
......@@ -84,6 +87,9 @@ int WorkspaceWindowResizer::GetHeightBeforeObscured(aura::Window* window) {
}
void WorkspaceWindowResizer::AdjustBounds(gfx::Rect* bounds) const {
if (!constrain_size_)
return;
gfx::Rect work_area(gfx::Screen::GetMonitorWorkAreaNearestWindow(window()));
if (bounds->bottom() < work_area.bottom()) {
int height = GetHeightBeforeObscured(window());
......
......@@ -43,6 +43,9 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
// Returns true if the window touches the bottom of the work area.
bool WindowTouchesBottomOfScreen() const;
// True if the window size (height) should be constrained.
const bool constrain_size_;
DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizer);
};
......
......@@ -45,6 +45,9 @@ WorkspaceController::WorkspaceController(aura::Window* viewport)
WorkspaceController::~WorkspaceController() {
Shell::GetRootWindow()->RemoveObserver(this);
Shell::GetRootWindow()->RemoveRootWindowObserver(this);
// WorkspaceLayoutManager may attempt to access state from us. Destroy it now.
if (viewport_->layout_manager() == layout_manager_)
viewport_->SetLayoutManager(NULL);
}
void WorkspaceController::ToggleOverview() {
......
......@@ -40,6 +40,10 @@
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
#if defined(USE_AURA)
#include "ash/wm/property_util.h"
#endif
using content::UserMetricsAction;
using content::WebContents;
......@@ -322,8 +326,11 @@ TabDragController2::~TabDragController2() {
if (destroyed_)
*destroyed_ = true;
if (move_loop_browser_view_)
if (move_loop_browser_view_) {
move_loop_browser_view_->set_move_observer(NULL);
SetTrackedByWorkspace(
move_loop_browser_view_->GetWidget()->GetNativeView(), true);
}
if (source_tabstrip_)
GetModel(source_tabstrip_)->RemoveObserver(this);
......@@ -1096,6 +1103,11 @@ void TabDragController2::EndDragImpl(EndDragType type) {
bring_to_front_timer_.Stop();
if (is_dragging_window_) {
if (type == NORMAL || (type == TAB_DESTROYED && drag_data_.size() > 1)) {
SetTrackedByWorkspace(
GetAttachedBrowserView()->GetWidget()->GetNativeView(), true);
}
// End the nested drag loop.
GetAttachedBrowserView()->GetWidget()->EndMoveLoop();
waiting_for_run_loop_to_exit_ = true;
......@@ -1391,6 +1403,14 @@ Browser* TabDragController2::CreateBrowserForDrag(
break; // Nothing to do for DETACH_ABOVE_OR_BELOW.
}
SetTrackedByWorkspace(browser->window()->GetNativeHandle(), false);
browser->window()->SetBounds(new_bounds);
return browser;
}
void TabDragController2::SetTrackedByWorkspace(gfx::NativeWindow window,
bool value) {
#if defined(USE_AURA)
ash::SetTrackedByWorkspace(window, value);
#endif
}
......@@ -279,6 +279,10 @@ class TabDragController2 : public TabDragController,
const gfx::Point& screen_point,
std::vector<gfx::Rect>* drag_bounds);
// Marks whether |window| is constrained. While dragging we set this to false
// to allow maximized windows to move any where.
void SetTrackedByWorkspace(gfx::NativeWindow window, bool value);
// Handles registering for notifications.
content::NotificationRegistrar registrar_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment