// 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/partial_screenshot_view.h" #include "ash/screenshot_delegate.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/wm/overlay_event_filter.h" #include "ui/aura/root_window.h" #include "ui/base/cursor/cursor.h" #include "ui/gfx/canvas.h" #include "ui/gfx/rect.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" namespace ash { PartialScreenshotView::PartialScreenshotView( ScreenshotDelegate* screenshot_delegate) : is_dragging_(false), screenshot_delegate_(screenshot_delegate) { } PartialScreenshotView::~PartialScreenshotView() { screenshot_delegate_ = NULL; } // static void PartialScreenshotView::StartPartialScreenshot( ScreenshotDelegate* screenshot_delegate) { views::Widget* widget = new views::Widget; PartialScreenshotView* view = new PartialScreenshotView( screenshot_delegate); aura::RootWindow* root_window = Shell::GetActiveRootWindow(); views::Widget::InitParams params( views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.transparent = true; params.delegate = view; // The partial screenshot rectangle has to be at the real top of // the screen. params.parent = Shell::GetContainer( root_window, internal::kShellWindowId_OverlayContainer); widget->Init(params); widget->SetContentsView(view); widget->SetBounds(root_window->bounds()); widget->GetNativeView()->SetName("PartialScreenshotView"); widget->StackAtTop(); widget->Show(); // Captures mouse events in case that context menu already captures the // events. This will close the context menu. widget->GetNativeView()->SetCapture(); Shell::GetInstance()->overlay_filter()->Activate(view); } gfx::NativeCursor PartialScreenshotView::GetCursor( const views::MouseEvent& event) { // Always use "crosshair" cursor. return ui::kCursorCross; } void PartialScreenshotView::Cancel() { Shell::GetInstance()->overlay_filter()->Deactivate(); views::Widget* widget = GetWidget(); if (widget) widget->Close(); } bool PartialScreenshotView::IsCancelingKeyEvent(aura::KeyEvent* event) { return event->key_code() == ui::VKEY_ESCAPE; } aura::Window* PartialScreenshotView::GetWindow() { return GetWidget()->GetNativeWindow(); } void PartialScreenshotView::OnPaint(gfx::Canvas* canvas) { if (is_dragging_) { // Screenshot area representation: black rectangle with white // rectangle inside. To avoid capturing these rectangles when mouse // release, they should be outside of the actual capturing area. gfx::Rect screenshot_rect = GetScreenshotRect(); screenshot_rect.Inset(-1, -1, -1, -1); canvas->DrawRect(screenshot_rect, SK_ColorWHITE); screenshot_rect.Inset(-1, -1, -1, -1); canvas->DrawRect(screenshot_rect, SK_ColorBLACK); } } void PartialScreenshotView::OnMouseCaptureLost() { Cancel(); } bool PartialScreenshotView::OnMousePressed(const views::MouseEvent& event) { start_position_ = event.location(); return true; } bool PartialScreenshotView::OnMouseDragged(const views::MouseEvent& event) { current_position_ = event.location(); SchedulePaint(); is_dragging_ = true; return true; } bool PartialScreenshotView::OnMouseWheel(const views::MouseWheelEvent& event) { // Do nothing but do not propagate events futhermore. return true; } void PartialScreenshotView::OnMouseReleased(const views::MouseEvent& event) { Cancel(); if (!is_dragging_) return; is_dragging_ = false; if (screenshot_delegate_) { aura::RootWindow *root_window = Shell::GetPrimaryRootWindow(); screenshot_delegate_->HandleTakePartialScreenshot( root_window, root_window->bounds().Intersect(GetScreenshotRect())); } } gfx::Rect PartialScreenshotView::GetScreenshotRect() const { int left = std::min(start_position_.x(), current_position_.x()); int top = std::min(start_position_.y(), current_position_.y()); int width = ::abs(start_position_.x() - current_position_.x()); int height = ::abs(start_position_.y() - current_position_.y()); return gfx::Rect(left, top, width, height); } } // namespace ash