diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-03 18:23:18 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-03 18:23:18 +0000 |
commit | 2a3197bb6a8a4c6f3a7affadce28cda638906131 (patch) | |
tree | 3269ee97d0c0e180d7529169178571f0c56060eb | |
parent | 820de97b4820ef0da82d9ee74f3009dc88d3c93e (diff) | |
download | chromium_src-2a3197bb6a8a4c6f3a7affadce28cda638906131.zip chromium_src-2a3197bb6a8a4c6f3a7affadce28cda638906131.tar.gz chromium_src-2a3197bb6a8a4c6f3a7affadce28cda638906131.tar.bz2 |
Adds some widget methods I'm going to need for dragging real browsers:
. RunMoveLoop/EndMoveLoop. The new TabDragController will invoke this
to start dragging a window.
. SetMouseCapture/ReleaseMouseCapture - I have to futz with mouse
capture during tab dragging.
. SetVisibilityChangedAnimationsEnabled - so that I can disable the
aero show/hide effect when showing a new browser.
BUG=98345
TEST=none
R=ben@chromium.org
Review URL: http://codereview.chromium.org/9022039
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@116149 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ash/wm/toplevel_window_event_filter.cc | 43 | ||||
-rw-r--r-- | ash/wm/toplevel_window_event_filter.h | 21 | ||||
-rw-r--r-- | ui/aura/aura.gyp | 4 | ||||
-rw-r--r-- | ui/aura/client/window_move_client.cc | 24 | ||||
-rw-r--r-- | ui/aura/client/window_move_client.h | 41 | ||||
-rw-r--r-- | ui/views/widget/native_widget_aura.cc | 22 | ||||
-rw-r--r-- | ui/views/widget/native_widget_aura.h | 5 | ||||
-rw-r--r-- | ui/views/widget/native_widget_gtk.cc | 15 | ||||
-rw-r--r-- | ui/views/widget/native_widget_gtk.h | 5 | ||||
-rw-r--r-- | ui/views/widget/native_widget_private.h | 5 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win.cc | 136 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win.h | 5 | ||||
-rw-r--r-- | ui/views/widget/widget.cc | 26 | ||||
-rw-r--r-- | ui/views/widget/widget.h | 29 |
14 files changed, 360 insertions, 21 deletions
diff --git a/ash/wm/toplevel_window_event_filter.cc b/ash/wm/toplevel_window_event_filter.cc index c4d0695..c173ce7 100644 --- a/ash/wm/toplevel_window_event_filter.cc +++ b/ash/wm/toplevel_window_event_filter.cc @@ -1,10 +1,11 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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 "ash/wm/toplevel_window_event_filter.h" #include "ash/wm/window_util.h" +#include "base/message_loop.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/cursor.h" #include "ui/aura/event.h" @@ -13,6 +14,7 @@ #include "ui/aura/window_delegate.h" #include "ui/base/hit_test.h" #include "ui/base/ui_base_types.h" +#include "ui/gfx/screen.h" namespace ash { @@ -135,7 +137,9 @@ void ToggleMaximizedState(aura::Window* window) { ToplevelWindowEventFilter::ToplevelWindowEventFilter(aura::Window* owner) : EventFilter(owner), + in_move_loop_(false), window_component_(HTNOWHERE) { + aura::client::SetWindowMoveClient(owner, this); } ToplevelWindowEventFilter::~ToplevelWindowEventFilter() { @@ -163,13 +167,17 @@ bool ToplevelWindowEventFilter::PreHandleMouseEvent(aura::Window* target, event->flags() & ui::EF_IS_DOUBLE_CLICK) { ToggleMaximizedState(target); } - UpdateLocationFromEvent(target, event); + UpdateMouseDownLocation(target, event->location()); return GetBoundsChangeForWindowComponent(window_component_) != kBoundsChange_None; case ui::ET_MOUSE_DRAGGED: return HandleDrag(target, event); case ui::ET_MOUSE_RELEASED: window_component_ = HTNOWHERE; + if (in_move_loop_) { + MessageLoop::current()->Quit(); + in_move_loop_ = false; + } break; default: break; @@ -191,7 +199,7 @@ ui::TouchStatus ToplevelWindowEventFilter::PreHandleTouchEvent( // Handle touch move by simulate mouse drag with single touch. switch (event->type()) { case ui::ET_TOUCH_PRESSED: - UpdateLocationFromEvent(target, event); + UpdateMouseDownLocation(target, event->location()); pressed_touch_ids_.insert(event->touch_id()); if (pressed_touch_ids_.size() == 1) return ui::TOUCH_STATUS_START; @@ -215,6 +223,29 @@ ui::TouchStatus ToplevelWindowEventFilter::PreHandleTouchEvent( return ui::TOUCH_STATUS_UNKNOWN; } +void ToplevelWindowEventFilter::RunMoveLoop(aura::Window* source) { + DCHECK(!in_move_loop_); // Can only handle one nested loop at a time. + in_move_loop_ = true; + window_component_ = HTCAPTION; + gfx::Point source_mouse_location(gfx::Screen::GetCursorScreenPoint()); + aura::Window::ConvertPointToWindow( + aura::RootWindow::GetInstance(), source, &source_mouse_location); + UpdateMouseDownLocation(source, source_mouse_location); + MessageLoopForUI::current()->RunWithDispatcher( + aura::RootWindow::GetInstance()->GetDispatcher()); + in_move_loop_ = false; +} + +void ToplevelWindowEventFilter::EndMoveLoop() { + if (!in_move_loop_) + return; + + in_move_loop_ = false; + window_component_ = HTNOWHERE; + MessageLoopForUI::current()->Quit(); + aura::RootWindow::GetInstance()->PostNativeEvent(ui::CreateNoopEvent()); +} + void ToplevelWindowEventFilter::MoveWindowToFront(aura::Window* target) { aura::Window* parent = target->parent(); aura::Window* child = target; @@ -263,11 +294,11 @@ bool ToplevelWindowEventFilter::HandleDrag(aura::Window* target, return true; } -void ToplevelWindowEventFilter::UpdateLocationFromEvent( +void ToplevelWindowEventFilter::UpdateMouseDownLocation( aura::Window* target, - aura::LocatedEvent* event) { + const gfx::Point& location) { mouse_down_bounds_ = target->bounds(); - mouse_down_offset_in_parent_ = event->location(); + mouse_down_offset_in_parent_ = location; aura::Window::ConvertPointToWindow(target, target->parent(), &mouse_down_offset_in_parent_); } diff --git a/ash/wm/toplevel_window_event_filter.h b/ash/wm/toplevel_window_event_filter.h index b548289..ea3661d 100644 --- a/ash/wm/toplevel_window_event_filter.h +++ b/ash/wm/toplevel_window_event_filter.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -9,6 +9,7 @@ #include <set> #include "base/compiler_specific.h" +#include "ui/aura/client/window_move_client.h" #include "ui/aura/event_filter.h" #include "ash/ash_export.h" #include "ui/gfx/point.h" @@ -22,7 +23,9 @@ class Window; namespace ash { -class ASH_EXPORT ToplevelWindowEventFilter : public aura::EventFilter { +class ASH_EXPORT ToplevelWindowEventFilter : + public aura::EventFilter, + public aura::client::WindowMoveClient { public: explicit ToplevelWindowEventFilter(aura::Window* owner); virtual ~ToplevelWindowEventFilter(); @@ -35,6 +38,10 @@ class ASH_EXPORT ToplevelWindowEventFilter : public aura::EventFilter { virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target, aura::TouchEvent* event) OVERRIDE; + // Overridden form aura::client::WindowMoveClient: + virtual void RunMoveLoop(aura::Window* source) OVERRIDE; + virtual void EndMoveLoop() OVERRIDE; + protected: // Returns the |window_component_|. See the variable definition below for // more details. @@ -50,9 +57,10 @@ class ASH_EXPORT ToplevelWindowEventFilter : public aura::EventFilter { // The return value is returned by OnMouseEvent() above. bool HandleDrag(aura::Window* target, aura::LocatedEvent* event); - // Updates the event location to window. - void UpdateLocationFromEvent(aura::Window* target, - aura::LocatedEvent* event); + // Updates |mouse_down_offset_in_parent_| and |mouse_down_bounds_| from + // |location|. + void UpdateMouseDownLocation(aura::Window* target, + const gfx::Point& location); // Updates the |window_component_| using the |event|'s location. void UpdateWindowComponentForEvent(aura::Window* window, @@ -91,6 +99,9 @@ class ASH_EXPORT ToplevelWindowEventFilter : public aura::EventFilter { // The bounds of the target window when the mouse was pressed. gfx::Rect mouse_down_bounds_; + // Are we running a nested message loop from RunMoveLoop(). + bool in_move_loop_; + // The window component (hit-test code) the mouse is currently over. int window_component_; diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp index 5c70bb5..2348f02 100644 --- a/ui/aura/aura.gyp +++ b/ui/aura/aura.gyp @@ -1,4 +1,4 @@ -# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# 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. @@ -39,6 +39,8 @@ 'client/stacking_client.h', 'client/tooltip_client.cc', 'client/tooltip_client.h', + 'client/window_move_client.cc', + 'client/window_move_client.h', 'client/window_types.h', 'cursor.h', 'root_window_host.h', diff --git a/ui/aura/client/window_move_client.cc b/ui/aura/client/window_move_client.cc new file mode 100644 index 0000000..8257713 --- /dev/null +++ b/ui/aura/client/window_move_client.cc @@ -0,0 +1,24 @@ +// 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/aura/client/window_move_client.h" + +#include "ui/aura/window.h" + +namespace aura { +namespace client { + +const char kWindowMoveClientKey[] = "WindowMoveClient"; + +void SetWindowMoveClient(Window* window, WindowMoveClient* client) { + window->SetProperty(kWindowMoveClientKey, client); +} + +WindowMoveClient* GetWindowMoveClient(Window* window) { + return reinterpret_cast<WindowMoveClient*>( + window->GetProperty(kWindowMoveClientKey)); +} + +} // namespace client +} // namespace aura diff --git a/ui/aura/client/window_move_client.h b/ui/aura/client/window_move_client.h new file mode 100644 index 0000000..5392e47 --- /dev/null +++ b/ui/aura/client/window_move_client.h @@ -0,0 +1,41 @@ +// 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_AURA_CLIENT_WINDOW_MOVE_CLIENT_H_ +#define UI_AURA_CLIENT_WINDOW_MOVE_CLIENT_H_ +#pragma once + +#include "ui/aura/aura_export.h" + +namespace aura { +class Window; +namespace client { + +// A property key to store a client that handles window moves. The type of +// the value is |aura::client::WindowMoveClient*|. +AURA_EXPORT extern const char kWindowMoveClientKey[]; + +// An interface implemented by an object that manages programatically keyed +// window moving. +class AURA_EXPORT WindowMoveClient { + public: + // Starts a nested message loop for moving the window. + virtual void RunMoveLoop(Window* window) = 0; + + // Ends a previously started move loop. + virtual void EndMoveLoop() = 0; + + protected: + virtual ~WindowMoveClient() {} +}; + +// Sets/Gets the activation client for the specified window. +AURA_EXPORT void SetWindowMoveClient(Window* window, + WindowMoveClient* client); +AURA_EXPORT WindowMoveClient* GetWindowMoveClient(Window* window); + +} // namespace client +} // namespace aura + +#endif // UI_AURA_CLIENT_WINDOW_MOVE_CLIENT_H_ diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index da2a1da..687d7ca 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc @@ -9,6 +9,7 @@ #include "ui/aura/client/activation_client.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/drag_drop_client.h" +#include "ui/aura/client/window_move_client.h" #include "ui/aura/client/window_types.h" #include "ui/aura/event.h" #include "ui/aura/root_window.h" @@ -554,6 +555,27 @@ void NativeWidgetAura::SetInactiveRenderingDisabled(bool value) { active_window_observer_.reset(new ActiveWindowObserver(this)); } +Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop() { + if (window_->parent() && + aura::client::GetWindowMoveClient(window_->parent())) { + SetMouseCapture(); + aura::client::GetWindowMoveClient(window_->parent())->RunMoveLoop(window_); + return Widget::MOVE_LOOP_SUCCESSFUL; + } + return Widget::MOVE_LOOP_CANCELED; +} + +void NativeWidgetAura::EndMoveLoop() { + if (window_->parent() && + aura::client::GetWindowMoveClient(window_->parent())) { + aura::client::GetWindowMoveClient(window_->parent())->EndMoveLoop(); + } +} + +void NativeWidgetAura::SetVisibilityChangedAnimationsEnabled(bool value) { + // Nothing needed on aura. +} + //////////////////////////////////////////////////////////////////////////////// // NativeWidgetAura, views::InputMethodDelegate implementation: diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h index 121b89b..874615c 100644 --- a/ui/views/widget/native_widget_aura.h +++ b/ui/views/widget/native_widget_aura.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -118,6 +118,9 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate, virtual void FocusNativeView(gfx::NativeView native_view) OVERRIDE; virtual gfx::Rect GetWorkAreaBoundsInScreen() const OVERRIDE; virtual void SetInactiveRenderingDisabled(bool value) OVERRIDE; + virtual Widget::MoveLoopResult RunMoveLoop() OVERRIDE; + virtual void EndMoveLoop() OVERRIDE; + virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE; // Overridden from views::InputMethodDelegate: virtual void DispatchKeyEventPostIME(const KeyEvent& key) OVERRIDE; diff --git a/ui/views/widget/native_widget_gtk.cc b/ui/views/widget/native_widget_gtk.cc index 2bf0ef3..3cf2188 100644 --- a/ui/views/widget/native_widget_gtk.cc +++ b/ui/views/widget/native_widget_gtk.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -1284,6 +1284,19 @@ gfx::Rect NativeWidgetGtk::GetWorkAreaBoundsInScreen() const { void NativeWidgetGtk::SetInactiveRenderingDisabled(bool value) { } +Widget::MoveLoopResult NativeWidgetGtk::RunMoveLoop() { + NOTIMPLEMENTED(); + return Widget::MOVE_LOOP_CANCELED; +} + +void NativeWidgetGtk::EndMoveLoop() { + NOTIMPLEMENTED(); +} + +void NativeWidgetGtk::SetVisibilityChangedAnimationsEnabled(bool value) { + // Nothing needed on gtk. +} + //////////////////////////////////////////////////////////////////////////////// // NativeWidgetGtk, protected: diff --git a/ui/views/widget/native_widget_gtk.h b/ui/views/widget/native_widget_gtk.h index 7c9e0e3..d3437d4 100644 --- a/ui/views/widget/native_widget_gtk.h +++ b/ui/views/widget/native_widget_gtk.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -222,6 +222,9 @@ class VIEWS_EXPORT NativeWidgetGtk : public internal::NativeWidgetPrivate, virtual void FocusNativeView(gfx::NativeView native_view) OVERRIDE; virtual gfx::Rect GetWorkAreaBoundsInScreen() const OVERRIDE; virtual void SetInactiveRenderingDisabled(bool value) OVERRIDE; + virtual Widget::MoveLoopResult RunMoveLoop() OVERRIDE; + virtual void EndMoveLoop() OVERRIDE; + virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE; protected: // Modifies event coordinates to the targeted widget contained by this widget. diff --git a/ui/views/widget/native_widget_private.h b/ui/views/widget/native_widget_private.h index a5702c3..46441fd 100644 --- a/ui/views/widget/native_widget_private.h +++ b/ui/views/widget/native_widget_private.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -202,6 +202,9 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget, virtual void FocusNativeView(gfx::NativeView native_view) = 0; virtual gfx::Rect GetWorkAreaBoundsInScreen() const = 0; virtual void SetInactiveRenderingDisabled(bool value) = 0; + virtual Widget::MoveLoopResult RunMoveLoop() = 0; + virtual void EndMoveLoop() = 0; + virtual void SetVisibilityChangedAnimationsEnabled(bool value) = 0; // Overridden from NativeWidget: virtual internal::NativeWidgetPrivate* AsNativeWidgetPrivate() OVERRIDE; diff --git a/ui/views/widget/native_widget_win.cc b/ui/views/widget/native_widget_win.cc index 9af3a4d..d0e57c7 100644 --- a/ui/views/widget/native_widget_win.cc +++ b/ui/views/widget/native_widget_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -56,6 +56,116 @@ namespace views { namespace { +// MoveLoopMouseWatcher is used to determine if the user canceled or completed a +// move. win32 doesn't appear to offer a way to determine the result of a move, +// so we install hooks to determine if we got a mouse up and assume the move +// completed. +class MoveLoopMouseWatcher { + public: + explicit MoveLoopMouseWatcher(NativeWidgetWin* host); + ~MoveLoopMouseWatcher(); + + // Returns true if the mouse is up, or if we couldn't install the hook. + bool got_mouse_up() const { return got_mouse_up_; } + + private: + // Instance that owns the hook. We only allow one instance to hook the mouse + // at a time. + static MoveLoopMouseWatcher* instance_; + + // Key and mouse callbacks from the hook. + static LRESULT CALLBACK MouseHook(int n_code, WPARAM w_param, LPARAM l_param); + static LRESULT CALLBACK KeyHook(int n_code, WPARAM w_param, LPARAM l_param); + + void Unhook(); + + // NativeWidgetWin that created us. + NativeWidgetWin* host_; + + // Did we get a mouse up? + bool got_mouse_up_; + + // Hook identifiers. + HHOOK mouse_hook_; + HHOOK key_hook_; + + DISALLOW_COPY_AND_ASSIGN(MoveLoopMouseWatcher); +}; + +// static +MoveLoopMouseWatcher* MoveLoopMouseWatcher::instance_ = NULL; + +MoveLoopMouseWatcher::MoveLoopMouseWatcher(NativeWidgetWin* host) + : host_(host), + got_mouse_up_(false), + mouse_hook_(NULL), + key_hook_(NULL) { + // Only one instance can be active at a time. + if (instance_) + instance_->Unhook(); + + mouse_hook_ = SetWindowsHookEx( + WH_MOUSE, &MouseHook, NULL, GetCurrentThreadId()); + if (mouse_hook_) { + instance_ = this; + // We don't care if setting the key hook succeeded. + key_hook_ = SetWindowsHookEx( + WH_KEYBOARD, &KeyHook, NULL, GetCurrentThreadId()); + } + if (instance_ != this) { + // Failed installation. Assume we got a mouse up in this case, otherwise + // we'll think all drags were canceled. + got_mouse_up_ = true; + } +} + +MoveLoopMouseWatcher::~MoveLoopMouseWatcher() { + Unhook(); +} + +void MoveLoopMouseWatcher::Unhook() { + if (instance_ != this) + return; + + DCHECK(mouse_hook_); + UnhookWindowsHookEx(mouse_hook_); + if (key_hook_) + UnhookWindowsHookEx(key_hook_); + key_hook_ = NULL; + mouse_hook_ = NULL; + instance_ = NULL; +} + +// static +LRESULT CALLBACK MoveLoopMouseWatcher::MouseHook(int n_code, + WPARAM w_param, + LPARAM l_param) { + DCHECK(instance_); + if (n_code == HC_ACTION && w_param == WM_LBUTTONUP) + instance_->got_mouse_up_ = true; + return CallNextHookEx(instance_->mouse_hook_, n_code, w_param, l_param); +} + +// static +LRESULT CALLBACK MoveLoopMouseWatcher::KeyHook(int n_code, + WPARAM w_param, + LPARAM l_param) { + if (n_code == HC_ACTION && w_param == VK_ESCAPE) { + int value = TRUE; + HRESULT result = DwmSetWindowAttribute( + instance_->host_->GetNativeView(), + DWMWA_TRANSITIONS_FORCEDISABLED, + &value, + sizeof(value)); + // Hide the window on escape, otherwise the window is visibly going to snap + // back to the original location before we close it. + // This behavior is specific to tab dragging, in that we generally wouldn't + // want this functionality if we have other consumers using this API. + instance_->host_->Hide(); + } + return CallNextHookEx(instance_->key_hook_, n_code, w_param, l_param); +} + // Get the source HWND of the specified message. Depending on the message, the // source HWND is encoded in either the WPARAM or the LPARAM value. HWND GetControlHWNDForMessage(UINT message, WPARAM w_param, LPARAM l_param) { @@ -717,7 +827,8 @@ void NativeWidgetWin::StackAbove(gfx::NativeView native_view) { } void NativeWidgetWin::StackAtTop() { - NOTIMPLEMENTED(); + SetWindowPos(HWND_TOP, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); } void NativeWidgetWin::SetShape(gfx::NativeRegion region) { @@ -998,6 +1109,27 @@ gfx::Rect NativeWidgetWin::GetWorkAreaBoundsInScreen() const { void NativeWidgetWin::SetInactiveRenderingDisabled(bool value) { } +Widget::MoveLoopResult NativeWidgetWin::RunMoveLoop() { + ReleaseMouseCapture(); + MoveLoopMouseWatcher watcher(this); + SendMessage(hwnd(), WM_SYSCOMMAND, SC_MOVE | 0x0002, GetMessagePos()); + // Windows doesn't appear to offer a way to determine whether the user + // canceled the move or not. We assume if the user released the mouse it was + // successful. + return watcher.got_mouse_up() ? Widget::MOVE_LOOP_SUCCESSFUL : + Widget::MOVE_LOOP_CANCELED; +} + +void NativeWidgetWin::EndMoveLoop() { + SendMessage(hwnd(), WM_CANCELMODE, 0, 0); +} + +void NativeWidgetWin::SetVisibilityChangedAnimationsEnabled(bool value) { + int dwm_value = value ? FALSE : TRUE; + DwmSetWindowAttribute( + hwnd(), DWMWA_TRANSITIONS_FORCEDISABLED, &dwm_value, sizeof(dwm_value)); +} + //////////////////////////////////////////////////////////////////////////////// // NativeWidgetWin, MessageLoop::Observer implementation: diff --git a/ui/views/widget/native_widget_win.h b/ui/views/widget/native_widget_win.h index 1daf32e..c6cd9c8 100644 --- a/ui/views/widget/native_widget_win.h +++ b/ui/views/widget/native_widget_win.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -254,6 +254,9 @@ class VIEWS_EXPORT NativeWidgetWin : public ui::WindowImpl, virtual void FocusNativeView(gfx::NativeView native_view) OVERRIDE; virtual gfx::Rect GetWorkAreaBoundsInScreen() const OVERRIDE; virtual void SetInactiveRenderingDisabled(bool value) OVERRIDE; + virtual Widget::MoveLoopResult RunMoveLoop() OVERRIDE; + virtual void EndMoveLoop() OVERRIDE; + virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE; protected: // Information saved before going into fullscreen mode, used to restore the diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index 3b3d086..51fed47 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -444,6 +444,18 @@ void Widget::SetBoundsConstrained(const gfx::Rect& bounds) { } } +void Widget::SetVisibilityChangedAnimationsEnabled(bool value) { + native_widget_->SetVisibilityChangedAnimationsEnabled(value); +} + +Widget::MoveLoopResult Widget::RunMoveLoop() { + return native_widget_->RunMoveLoop(); +} + +void Widget::EndMoveLoop() { + native_widget_->EndMoveLoop(); +} + void Widget::StackAboveWidget(Widget* widget) { native_widget_->StackAbove(widget->GetNativeView()); } @@ -799,6 +811,18 @@ NativeWidget* Widget::native_widget() { return native_widget_; } +void Widget::SetMouseCapture(views::View* view) { + is_mouse_button_pressed_ = true; + root_view_->SetMouseHandler(view); + if (!native_widget_->HasMouseCapture()) + native_widget_->SetMouseCapture(); +} + +void Widget::ReleaseMouseCapture() { + if (native_widget_->HasMouseCapture()) + native_widget_->ReleaseMouseCapture(); +} + const Event* Widget::GetCurrentEvent() { return event_stack_.empty() ? NULL : event_stack_.top()->event(); } diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index 2af755c..f00d6b7 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -107,6 +107,15 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, FRAME_TYPE_FORCE_NATIVE // Force the native frame. }; + // Result from RunMoveLoop(). + enum MoveLoopResult { + // The move loop completed successfully. + MOVE_LOOP_SUCCESSFUL, + + // The user canceled the move loop. + MOVE_LOOP_CANCELED + }; + struct VIEWS_EXPORT InitParams { enum Type { TYPE_WINDOW, // A decorated Window, like a frame window. @@ -306,6 +315,18 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // non-child widgets. void SetBoundsConstrained(const gfx::Rect& bounds); + // Sets whether animations that occur when visibility is changed are enabled. + // Default is true. + void SetVisibilityChangedAnimationsEnabled(bool value); + + // Starts a nested message loop that moves the window. This can be used to + // start a window move operation from a mouse moved event. This returns when + // the move completes. + MoveLoopResult RunMoveLoop(); + + // Stops a previously started move loop. This is not immediate. + void EndMoveLoop(); + // Places the widget in front of the specified widget in z-order. void StackAboveWidget(Widget* widget); void StackAbove(gfx::NativeView native_view); @@ -533,6 +554,12 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, return native_widget_; } + // Sets mouse capture on the specified view. + void SetMouseCapture(views::View* view); + + // Releases mouse capture. + void ReleaseMouseCapture(); + // Returns the current event being processed. If there are multiple events // being processed at the same time (e.g. one event triggers another event), // then the most recent event is returned. Returns NULL if no event is being |