Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ash / wm / partial_screenshot_view.cc
blobb18c9fb530f0cd5076ef1440297c9b3e10333d6a
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/wm/partial_screenshot_view.h"
7 #include <algorithm>
9 #include "ash/display/mouse_cursor_event_filter.h"
10 #include "ash/screenshot_delegate.h"
11 #include "ash/shell.h"
12 #include "ash/shell_window_ids.h"
13 #include "ash/wm/overlay_event_filter.h"
14 #include "ui/aura/client/capture_client.h"
15 #include "ui/aura/window_event_dispatcher.h"
16 #include "ui/base/cursor/cursor.h"
17 #include "ui/events/event.h"
18 #include "ui/gfx/canvas.h"
19 #include "ui/gfx/rect.h"
20 #include "ui/views/view.h"
21 #include "ui/views/widget/widget.h"
22 #include "ui/views/widget/widget_observer.h"
24 namespace ash {
26 // A self-owned object to handle the cancel and the finish of current partial
27 // screenshot session.
28 class PartialScreenshotView::OverlayDelegate
29 : public OverlayEventFilter::Delegate,
30 public views::WidgetObserver {
31 public:
32 OverlayDelegate() {
33 Shell::GetInstance()->overlay_filter()->Activate(this);
36 void RegisterWidget(views::Widget* widget) {
37 widgets_.push_back(widget);
38 widget->AddObserver(this);
41 // Overridden from OverlayEventFilter::Delegate:
42 virtual void Cancel() OVERRIDE {
43 // Make sure the mouse_warp_mode allows warping. It can be stopped by a
44 // partial screenshot view.
45 MouseCursorEventFilter* mouse_cursor_filter =
46 Shell::GetInstance()->mouse_cursor_filter();
47 mouse_cursor_filter->set_mouse_warp_mode(
48 MouseCursorEventFilter::WARP_ALWAYS);
49 for (size_t i = 0; i < widgets_.size(); ++i)
50 widgets_[i]->Close();
53 virtual bool IsCancelingKeyEvent(ui::KeyEvent* event) OVERRIDE {
54 return event->key_code() == ui::VKEY_ESCAPE;
57 virtual aura::Window* GetWindow() OVERRIDE {
58 // Just returns NULL because this class does not handle key events in
59 // OverlayEventFilter, except for cancel keys.
60 return NULL;
63 // Overridden from views::WidgetObserver:
64 virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
65 widget->RemoveObserver(this);
66 widgets_.erase(std::remove(widgets_.begin(), widgets_.end(), widget));
67 if (widgets_.empty())
68 delete this;
71 private:
72 virtual ~OverlayDelegate() {
73 Shell::GetInstance()->overlay_filter()->Deactivate(this);
76 std::vector<views::Widget*> widgets_;
78 DISALLOW_COPY_AND_ASSIGN(OverlayDelegate);
81 // static
82 std::vector<PartialScreenshotView*>
83 PartialScreenshotView::StartPartialScreenshot(
84 ScreenshotDelegate* screenshot_delegate) {
85 std::vector<PartialScreenshotView*> views;
87 if (Shell::GetInstance()->overlay_filter()->IsActive())
88 return views;
90 OverlayDelegate* overlay_delegate = new OverlayDelegate();
91 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
92 for (aura::Window::Windows::iterator it = root_windows.begin();
93 it != root_windows.end(); ++it) {
94 PartialScreenshotView* new_view = new PartialScreenshotView(
95 overlay_delegate, screenshot_delegate);
96 new_view->Init(*it);
97 views.push_back(new_view);
99 return views;
102 PartialScreenshotView::PartialScreenshotView(
103 PartialScreenshotView::OverlayDelegate* overlay_delegate,
104 ScreenshotDelegate* screenshot_delegate)
105 : is_dragging_(false),
106 overlay_delegate_(overlay_delegate),
107 screenshot_delegate_(screenshot_delegate) {
110 PartialScreenshotView::~PartialScreenshotView() {
111 overlay_delegate_ = NULL;
112 screenshot_delegate_ = NULL;
115 void PartialScreenshotView::Init(aura::Window* root_window) {
116 views::Widget* widget = new views::Widget;
117 views::Widget::InitParams params(
118 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
119 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
120 params.delegate = this;
121 // The partial screenshot rectangle has to be at the real top of
122 // the screen.
123 params.parent =
124 Shell::GetContainer(root_window, kShellWindowId_OverlayContainer);
126 widget->Init(params);
127 widget->SetContentsView(this);
128 widget->SetBounds(root_window->GetBoundsInScreen());
129 widget->GetNativeView()->SetName("PartialScreenshotView");
130 widget->StackAtTop();
131 widget->Show();
132 // Releases the mouse capture to let mouse events come to the view. This
133 // will close the context menu.
134 aura::client::CaptureClient* capture_client =
135 aura::client::GetCaptureClient(root_window);
136 if (capture_client->GetCaptureWindow())
137 capture_client->ReleaseCapture(capture_client->GetCaptureWindow());
139 overlay_delegate_->RegisterWidget(widget);
142 gfx::Rect PartialScreenshotView::GetScreenshotRect() const {
143 int left = std::min(start_position_.x(), current_position_.x());
144 int top = std::min(start_position_.y(), current_position_.y());
145 int width = ::abs(start_position_.x() - current_position_.x());
146 int height = ::abs(start_position_.y() - current_position_.y());
147 return gfx::Rect(left, top, width, height);
150 void PartialScreenshotView::OnSelectionStarted(const gfx::Point& position) {
151 start_position_ = position;
154 void PartialScreenshotView::OnSelectionChanged(const gfx::Point& position) {
155 if (is_dragging_ && current_position_ == position)
156 return;
157 current_position_ = position;
158 SchedulePaint();
159 is_dragging_ = true;
162 void PartialScreenshotView::OnSelectionFinished() {
163 overlay_delegate_->Cancel();
164 if (!is_dragging_)
165 return;
167 is_dragging_ = false;
168 if (screenshot_delegate_) {
169 aura::Window*root_window =
170 GetWidget()->GetNativeWindow()->GetRootWindow();
171 screenshot_delegate_->HandleTakePartialScreenshot(
172 root_window,
173 gfx::IntersectRects(root_window->bounds(), GetScreenshotRect()));
177 gfx::NativeCursor PartialScreenshotView::GetCursor(
178 const ui::MouseEvent& event) {
179 // Always use "crosshair" cursor.
180 return ui::kCursorCross;
183 void PartialScreenshotView::OnPaint(gfx::Canvas* canvas) {
184 if (is_dragging_) {
185 // Screenshot area representation: black rectangle with white
186 // rectangle inside. To avoid capturing these rectangles when mouse
187 // release, they should be outside of the actual capturing area.
188 gfx::Rect screenshot_rect = GetScreenshotRect();
189 screenshot_rect.Inset(-1, -1, -1, -1);
190 canvas->DrawRect(screenshot_rect, SK_ColorWHITE);
191 screenshot_rect.Inset(-1, -1, -1, -1);
192 canvas->DrawRect(screenshot_rect, SK_ColorBLACK);
196 bool PartialScreenshotView::OnMousePressed(const ui::MouseEvent& event) {
197 // Prevent moving across displays during drag. Capturing a screenshot across
198 // the displays is not supported yet.
199 // TODO(mukai): remove this restriction.
200 MouseCursorEventFilter* mouse_cursor_filter =
201 Shell::GetInstance()->mouse_cursor_filter();
202 mouse_cursor_filter->set_mouse_warp_mode(MouseCursorEventFilter::WARP_NONE);
203 OnSelectionStarted(event.location());
204 return true;
207 bool PartialScreenshotView::OnMouseDragged(const ui::MouseEvent& event) {
208 OnSelectionChanged(event.location());
209 return true;
212 bool PartialScreenshotView::OnMouseWheel(const ui::MouseWheelEvent& event) {
213 // Do nothing but do not propagate events futhermore.
214 return true;
217 void PartialScreenshotView::OnMouseReleased(const ui::MouseEvent& event) {
218 OnSelectionFinished();
221 void PartialScreenshotView::OnMouseCaptureLost() {
222 is_dragging_ = false;
223 OnSelectionFinished();
226 void PartialScreenshotView::OnGestureEvent(ui::GestureEvent* event) {
227 switch(event->type()) {
228 case ui::ET_GESTURE_TAP_DOWN:
229 OnSelectionStarted(event->location());
230 break;
231 case ui::ET_GESTURE_SCROLL_UPDATE:
232 OnSelectionChanged(event->location());
233 break;
234 case ui::ET_GESTURE_SCROLL_END:
235 case ui::ET_SCROLL_FLING_START:
236 OnSelectionFinished();
237 break;
238 default:
239 break;
242 event->SetHandled();
245 } // namespace ash