text:
namespace {

const float kMaxMagnifiedScale = 4.0f;
const float kMaxMagnifiedScaleThreshold = 4.0f;
const float kMinMagnifiedScaleThreshold = 1.1f;
const float kNonMagnifiedScale = 1.0f;

const float kInitialMagnifiedScale = 2.0f;
const float kScrollScaleChangeFactor = 0.0125f;

// Default animation parameters for redrawing the magnification window.
const gfx::Tween::Type kDefaultAnimationTweenType = gfx::Tween::EASE_OUT;
const int kDefaultAnimationDurationInMs = 100;

// Use linear transformation to make the magnifier window move smoothly
// to center the focus when user types in a text input field.
const gfx::Tween::Type kCenterCaretAnimationTweenType = gfx::Tween::LINEAR;

// The delay of the timer for moving magnifier window for centering the text
// input focus.
const int kMoveMagnifierDelayInMs = 10;

// Threadshold of panning. If the cursor moves to within pixels (in DIP) of
// |kCursorPanningMargin| from the edge, the view-port moves.
const int kCursorPanningMargin = 100;

// Threadshold of panning. If the caret moves to within pixels (in DIP) of
// |kCaretPanningMargin| from the edge, the view-port moves.
const int kCaretPanningMargin = 50;

void MoveCursorTo(aura::WindowTreeHost* host, const gfx::Point& root_location) {
  gfx::Point3F host_location_3f(root_location);
  host->GetRootTransform().TransformPoint(&host_location_3f);
  host->MoveCursorToHostLocation(
      gfx::ToCeiledPoint(host_location_3f.AsPointF()));
}

ui::InputMethod* GetInputMethod(aura::Window* root_window) {
  if (root_window->GetHost())
    return root_window->GetHost()->GetInputMethod();
  return nullptr;
}

}  // namespace

namespace ash {

////////////////////////////////////////////////////////////////////////////////
// MagnificationControllerImpl:

class MagnificationControllerImpl : public MagnificationController,
                                    public ui::EventHandler,
                                    public ui::ImplicitAnimationObserver,
                                    public aura::WindowObserver,
                                    public ui::InputMethodObserver {
 public:
  MagnificationControllerImpl();
  ~MagnificationControllerImpl() override;

  // MagnificationController overrides:
  void SetEnabled(bool enabled) override;
  bool IsEnabled() const override;
  void SetKeepFocusCentered(bool keep_focus_centered) override;
  bool KeepFocusCentered() const override;
  void SetScale(float scale, bool animate) override;
  float GetScale() const override { return scale_; }
  void MoveWindow(int x, int y, bool animate) override;
  void MoveWindow(const gfx::Point& point, bool animate) override;
  gfx::Point GetWindowPosition() const override {
    return gfx::ToFlooredPoint(origin_);
  }
  void SetScrollDirection(ScrollDirection direction) override;
  gfx::Rect GetViewportRect() const override;
  void HandleFocusedNodeChanged(
      bool is_editable_node,
      const gfx::Rect& node_bounds_in_screen) override;
  void SwitchTargetRootWindow(aura::Window* new_root_window,
                              bool redraw_original_root_window) override;

  // For test
  gfx::Point GetPointOfInterestForTesting() override {
    return point_of_interest_;
  }

  bool IsOnAnimationForTesting() const override { return is_on_animation_; }

  void DisableMoveMagnifierDelayForTesting() override {
    disable_move_magnifier_delay_ = true;
  }

 private:
  // ui::ImplicitAnimationObserver overrides:
  void OnImplicitAnimationsCompleted() override;

  // aura::WindowObserver overrides:
  void OnWindowDestroying(aura::Window* root_window) override;
  void OnWindowBoundsChanged(aura::Window* window,
                             const gfx::Rect& old_bounds,
                             const gfx::Rect& new_bounds) override;

  // Redraws the magnification window with the given origin position and the
  // given scale. Returns true if the window is changed; otherwise, false.
  // These methods should be called internally just after the scale and/or
  // the position are changed to redraw the window.
  bool Redraw(const gfx::PointF& position, float scale, bool animate);

  // Redraws the magnification window with the given origin position in dip and
  // the given scale. Returns true if the window is changed; otherwise, false.
  // The last two parameters specify the animation duration and tween type.
  // If |animation_in_ms| is zero, there will be no animation, and |tween_type|
  // will be ignored.
  bool RedrawDIP(const gfx::PointF& position_in_dip,
                 float scale,
                 int animation_in_ms,
                 gfx::Tween::Type tween_type);

  // 1) If the screen is scrolling (i.e. animating) and should scroll further,
  // it does nothing.
  // 2) If the screen is scrolling (i.e. animating) and the direction is NONE,
  // it stops the scrolling animation.
  // 3) If the direction is set to value other than NONE, it starts the
  // scrolling/ animation towards that direction.
  void StartOrStopScrollIfNecessary();

  // Redraw with the given zoom scale keeping the mouse cursor location. In
  // other words, zoom (or unzoom) centering around the cursor.
  void RedrawKeepingMousePosition(float scale, bool animate);

  void OnMouseMove(const gfx::Point& location);

  // Move the mouse cursot to the given point. Actual move will be done when
  // the animation is completed. This should be called after animation is
  // started.
  void AfterAnimationMoveCursorTo(const gfx::Point& location);

  // Returns if the magnification scale is 1.0 or not (larger then 1.0).
  bool IsMagnified() const;

  // Returns the rect of the magnification window.
  gfx::RectF GetWindowRectDIP(float scale) const;
  // Returns the size of the root window.
  gfx::Size GetHostSizeDIP() const;

  // Correct the given scale value if necessary.
  void ValidateScale(float* scale);

  // ui::EventHandler overrides:
  void OnMouseEvent(ui::MouseEvent* event) override;
  void OnScrollEvent(ui::ScrollEvent* event) override;
  void OnTouchEvent(ui::TouchEvent* event) override;

  // Moves the view port when |point| is located within
  // |x_panning_margin| and |y_pannin_margin| to the edge of the visible
  // window region. The view port will be moved so that the |point| will be
  // moved to the point where it has |x_target_margin| and |y_target_margin|
  // to the edge of the visible region.
  void MoveMagnifierWindowFollowPoint(const gfx::Point& point,
                                      int x_panning_margin,
                                      int y_panning_margin,
                                      int x_target_margin,
                                      int y_target_margin);

  // Moves the view port to center |point| in magnifier screen.
  void MoveMagnifierWindowCenterPoint(const gfx::Point& point);

  // Moves the viewport so that |rect| is fully visible. If |rect| is larger
  // than the viewport horizontally or vertically, the viewport will be moved
  // to center the |rect| in that dimension.
  void MoveMagnifierWindowFollowRect(const gfx::Rect& rect);

  // Invoked when |move_magnifier_timer_| fires to move the magnifier window to
  // follow the caret.
  void OnMoveMagnifierTimer();

  // ui::InputMethodObserver:
  void OnTextInputTypeChanged(const ui::TextInputClient* client) override {}
  void OnFocus() override {}
  void OnBlur() override {}
  void OnTextInputStateChanged(const ui::TextInputClient* client) override {}
  void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {}
  void OnShowImeIfNeeded() override {}
  void OnCaretBoundsChanged(const ui::TextInputClient* client) override;

  // Target root window. This must not be NULL.
  aura::Window* root_window_;

  // True if the magnified window is currently animating a change. Otherwise,
  // false.
  bool is_on_animation_;

  bool is_enabled_;

  bool keep_focus_centered_;

  // True if the cursor needs to move the given position after the animation
  // will be finished. When using this, set |position_after_animation_| as well.
  bool move_cursor_after_animation_;
  // Stores the position of cursor to be moved after animation.
  gfx::Point position_after_animation_;

  // Stores the last mouse cursor (or last touched) location. This value is
  // used on zooming to keep this location visible.
  gfx::Point point_of_interest_;

  // Current scale, origin (left-top) position of the magnification window.
  float scale_;
  gfx::PointF origin_;

  ScrollDirection scroll_direction_;

  // Timer for moving magnifier window when it fires.
  base::OneShotTimer<MagnificationControllerImpl> move_magnifier_timer_;

  // Most recent caret position in |root_window_| coordinates.
  gfx::Point caret_point_;

  // Flag for disabling moving magnifier delay. It can only be true in testing
  // mode.
  bool disable_move_magnifier_delay_;

  DISALLOW_COPY_AND_ASSIGN(MagnificationControllerImpl);
};

////////////////////////////////////////////////////////////////////////////////
// MagnificationControllerImpl:

MagnificationControllerImpl::MagnificationControllerImpl()
    : root_window_(Shell::GetPrimaryRootWindow()),
      is_on_animation_(false),
      is_enabled_(false),
      keep_focus_centered_(false),
      move_cursor_after_animation_(false),
      scale_(kNonMagnifiedScale),
      scroll_direction_(SCROLL_NONE),
      disable_move_magnifier_delay_(false) {
  Shell::GetInstance()->AddPreTargetHandler(this);
  root_window_->AddObserver(this);
  point_of_interest_ = root_window_->bounds().CenterPoint();
}

MagnificationControllerImpl::~MagnificationControllerImpl() {
  ui::InputMethod* input_method = GetInputMethod(root_window_);
  if (input_method)
    input_method->RemoveObserver(this);

  root_window_->RemoveObserver(this);

  Shell::GetInstance()->RemovePreTargetHandler(this);
}

void MagnificationControllerImpl::RedrawKeepingMousePosition(
    float scale, bool animate) {
  gfx::Point mouse_in_root = point_of_interest_;

  // mouse_in_root is invalid value when the cursor is hidden.
  if (!root_window_->bounds().Contains(mouse_in_root))
    mouse_in_root = root_window_->bounds().CenterPoint();

  const gfx::PointF origin =
      gfx::PointF(mouse_in_root.x() -
                      (scale_ / scale) * (mouse_in_root.x() - origin_.x()),
                  mouse_in_root.y() -
                      (scale_ / scale) * (mouse_in_root.y() - origin_.y()));
  bool changed = RedrawDIP(origin, scale,
                           animate ? kDefaultAnimationDurationInMs : 0,
                           kDefaultAnimationTweenType);
  if (changed)
    AfterAnimationMoveCursorTo(mouse_in_root);
}

bool MagnificationControllerImpl::Redraw(const gfx::PointF& position,
                                         float scale,
                                         bool animate) {
  const gfx::PointF position_in_dip =
      ui::ConvertPointToDIP(root_window_->layer(), position);
  return RedrawDIP(position_in_dip, scale,
                   animate ? kDefaultAnimationDurationInMs : 0,
                   kDefaultAnimationTweenType);
}

bool MagnificationControllerImpl::RedrawDIP(const gfx::PointF& position_in_dip,
                                            float scale,
                                            int duration_in_ms,
                                            gfx::Tween::Type tween_type) {
  DCHECK(root_window_);

  float x = position_in_dip.x();
  float y = position_in_dip.y();

  ValidateScale(&scale);

  if (x < 0)
    x = 0;
  if (y < 0)
    y = 0;

  const gfx::Size host_size_in_dip = GetHostSizeDIP();
  const gfx::SizeF window_size_in_dip = GetWindowRectDIP(scale).size();
  float max_x = host_size_in_dip.width() - window_size_in_dip.width();
  float max_y = host_size_in_dip.height() - window_size_in_dip.height();
  if (x > max_x)
    x = max_x;
  if (y > max_y)
    y = max_y;

  // Does nothing if both the origin and the scale are not changed.
  if (origin_.x() == x  &&
      origin_.y() == y &&
      scale == scale_) {
    return false;
  }

  origin_.set_x(x);
  origin_.set_y(y);
  scale_ = scale;

  // Creates transform matrix.
  gfx::Transform transform;
  // Flips the signs intentionally to convert them from the position of the
  // magnification window.
  transform.Scale(scale_, scale_);
  transform.Translate(-origin_.x(), -origin_.y());

  ui::ScopedLayerAnimationSettings settings(
      root_window_->layer()->GetAnimator());
  settings.AddObserver(this);
  settings.SetPreemptionStrategy(
      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
  settings.SetTweenType(tween_type);
  settings.SetTransitionDuration(
      base::TimeDelta::FromMilliseconds(duration_in_ms));

  gfx::Display display =
      Shell::GetScreen()->GetDisplayNearestWindow(root_window_);
  scoped_ptr<RootWindowTransformer> transformer(
      CreateRootWindowTransformerForDisplay(root_window_, display));
  GetRootWindowController(root_window_)->ash_host()->SetRootWindowTransformer(
      transformer.Pass());

  if (duration_in_ms > 0)
    is_on_animation_ = true;

  return true;
}

void MagnificationControllerImpl::StartOrStopScrollIfNecessary() {
  // This value controls the scrolling speed.
  const int kMoveOffset = 40;
  if (is_on_animation_) {
    if (scroll_direction_ == SCROLL_NONE)
      root_window_->layer()->GetAnimator()->StopAnimating();
    return;
  }

  gfx::PointF new_origin = origin_;
  switch (scroll_direction_) {
    case SCROLL_NONE:
      // No need to take action.
      return;
    case SCROLL_LEFT:
      new_origin.Offset(-kMoveOffset, 0);
      break;
    case SCROLL_RIGHT:
      new_origin.Offset(kMoveOffset, 0);
      break;
    case SCROLL_UP:
      new_origin.Offset(0, -kMoveOffset);
      break;
    case SCROLL_DOWN:
      new_origin.Offset(0, kMoveOffset);
      break;
  }
  RedrawDIP(new_origin, scale_, kDefaultAnimationDurationInMs,
            kDefaultAnimationTweenType);
}

void MagnificationControllerImpl::OnMouseMove(const gfx::Point& location) {
  DCHECK(root_window_);

  gfx::Point mouse(location);
  int margin = kCursorPanningMargin / scale_;  // No need to consider DPI.
  MoveMagnifierWindowFollowPoint(mouse, margin, margin, margin, margin);
}

gfx::Rect MagnificationControllerImpl::GetViewportRect() const {
  return gfx::ToEnclosingRect(GetWindowRectDIP(scale_));
}

void MagnificationControllerImpl::HandleFocusedNodeChanged(
    bool is_editable_node,
    const gfx::Rect& node_bounds_in_screen) {
  // The editable node is handled by OnCaretBoundsChanged.
  if (is_editable_node)
    return;

  gfx::Rect node_bounds_in_root =
      ScreenUtil::ConvertRectFromScreen(root_window_, node_bounds_in_screen);
  if (GetViewportRect().Contains(node_bounds_in_root))
    return;

  MoveMagnifierWindowFollowRect(node_bounds_in_root);
}

void MagnificationControllerImpl::SwitchTargetRootWindow(
    aura::Window* new_root_window,
    bool redraw_original_root_window) {
  DCHECK(new_root_window);

  if (new_root_window == root_window_)
    return;

  // Stores the previous scale.
  float scale = GetScale();

  // Unmagnify the previous root window.
  root_window_->RemoveObserver(this);
  if (redraw_original_root_window)
    RedrawKeepingMousePosition(1.0f, true);
  root_window_ = new_root_window;
  RedrawKeepingMousePosition(scale, true);
  root_window_->AddObserver(this);
}

void MagnificationControllerImpl::AfterAnimationMoveCursorTo(
    const gfx::Point& location) {
  DCHECK(root_window_);

  aura::client::CursorClient* cursor_client =
      aura::client::GetCursorClient(root_window_);
  if (cursor_client) {
    // When cursor is invisible, do not move or show the cursor after the
    // animation.
    if (!cursor_client->IsCursorVisible())
      return;
    cursor_client->DisableMouseEvents();
  }
  move_cursor_after_animation_ = true;
  position_after_animation_ = location;
}

gfx::Size MagnificationControllerImpl::GetHostSizeDIP() const {
  return root_window_->bounds().size();
}

gfx::RectF MagnificationControllerImpl::GetWindowRectDIP(float scale) const {
  const gfx::Size size_in_dip = root_window_->bounds().size();
  const float width = size_in_dip.width() / scale;
  const float height = size_in_dip.height() / scale;

  return gfx::RectF(origin_.x(), origin_.y(), width, height);
}

bool MagnificationControllerImpl::IsMagnified() const {
  return scale_ >= kMinMagnifiedScaleThreshold;
}

void MagnificationControllerImpl::ValidateScale(float* scale) {
  // Adjust the scale to just |kNonMagnifiedScale| if scale is smaller than
  // |kMinMagnifiedScaleThreshold|;
  if (*scale < kMinMagnifiedScaleThreshold)
    *scale = kNonMagnifiedScale;

  // Adjust the scale to just |kMinMagnifiedScale| if scale is bigger than
  // |kMinMagnifiedScaleThreshold|;
  if (*scale > kMaxMagnifiedScaleThreshold)
    *scale = kMaxMagnifiedScale;

  DCHECK(kNonMagnifiedScale <= *scale && *scale <= kMaxMagnifiedScale);
}

void MagnificationControllerImpl::OnImplicitAnimationsCompleted() {
  if (!is_on_animation_)
    return;

  if (move_cursor_after_animation_) {
    MoveCursorTo(root_window_->GetHost(), position_after_animation_);
    move_cursor_after_animation_ = false;

    aura::client::CursorClient* cursor_client =
        aura::client::GetCursorClient(root_window_);
    if (cursor_client)
      cursor_client->EnableMouseEvents();
  }

  is_on_animation_ = false;

  StartOrStopScrollIfNecessary();
}

void MagnificationControllerImpl::OnWindowDestroying(
    aura::Window* root_window) {
  if (root_window == root_window_) {
    // There must be at least one root window because this controller is
    // destroyed before the root windows get destroyed.
    DCHECK(root_window);

    aura::Window* target_root_window = Shell::GetTargetRootWindow();
    CHECK(target_root_window);

    // The destroyed root window must not be target.
    CHECK_NE(target_root_window, root_window);
    // Don't redraw the old root window as it's being destroyed.
    SwitchTargetRootWindow(target_root_window, false);
    point_of_interest_ = target_root_window->bounds().CenterPoint();
  }
}

void MagnificationControllerImpl::OnWindowBoundsChanged(
    aura::Window* window,
    const gfx::Rect& old_bounds,
    const gfx::Rect& new_bounds) {
  // TODO(yoshiki): implement here. crbug.com/230979
}

////////////////////////////////////////////////////////////////////////////////
// MagnificationControllerImpl: MagnificationController implementation

void MagnificationControllerImpl::SetScale(float scale, bool animate) {
  if (!is_enabled_)
    return;

  ValidateScale(&scale);
  Shell::GetInstance()->accessibility_delegate()->
      SaveScreenMagnifierScale(scale);
  RedrawKeepingMousePosition(scale, animate);
}

void MagnificationControllerImpl::MoveWindow(int x, int y, bool animate) {
  if (!is_enabled_)
    return;

  Redraw(gfx::Point(x, y), scale_, animate);
}

void MagnificationControllerImpl::MoveWindow(const gfx::Point& point,
                                             bool animate) {
  if (!is_enabled_)
    return;

  Redraw(point, scale_, animate);
}

void MagnificationControllerImpl::SetScrollDirection(
    ScrollDirection direction) {
  scroll_direction_ = direction;
  StartOrStopScrollIfNecessary();
}

void MagnificationControllerImpl::SetEnabled(bool enabled) {
  Shell* shell = Shell::GetInstance();
  ui::InputMethod* input_method = GetInputMethod(root_window_);
  if (enabled) {
    if (!is_enabled_ && input_method)
      input_method->AddObserver(this);

    float scale =
        Shell::GetInstance()->accessibility_delegate()->
        GetSavedScreenMagnifierScale();
    if (scale <= 0.0f)
      scale = kInitialMagnifiedScale;
    ValidateScale(&scale);

    // Do nothing, if already enabled with same scale.
    if (is_enabled_ && scale == scale_)
      return;

    is_enabled_ = enabled;
    RedrawKeepingMousePosition(scale, true);
    shell->accessibility_delegate()->SaveScreenMagnifierScale(scale);
  } else {
    // Do nothing, if already disabled.
    if (!is_enabled_)
      return;

    if (input_method)
      input_method->RemoveObserver(this);

    RedrawKeepingMousePosition(kNonMagnifiedScale, true);
    is_enabled_ = enabled;
  }
}

bool MagnificationControllerImpl::IsEnabled() const {
  return is_enabled_;
}

void MagnificationControllerImpl::SetKeepFocusCentered(
    bool keep_focus_centered) {
  keep_focus_centered_ = keep_focus_centered;
}

bool MagnificationControllerImpl::KeepFocusCentered() const {
  return keep_focus_centered_;
}

////////////////////////////////////////////////////////////////////////////////
// MagnificationControllerImpl: aura::EventFilter implementation

void MagnificationControllerImpl::OnMouseEvent(ui::MouseEvent* event) {
  aura::Window* target = static_cast<aura::Window*>(event->target());
  aura::Window* current_root = target->GetRootWindow();
  gfx::Rect root_bounds = current_root->bounds();

  if (root_bounds.Contains(event->root_location())) {
    // This must be before |SwitchTargetRootWindow()|.
    if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)
      point_of_interest_ = event->root_location();

    if (current_root != root_window_) {
      DCHECK(current_root);
      SwitchTargetRootWindow(current_root, true);
    }

    if (IsMagnified() && event->type() == ui::ET_MOUSE_MOVED)
      OnMouseMove(event->root_location());
  }
}

void MagnificationControllerImpl::OnScrollEvent(ui::ScrollEvent* event) {
  if (event->IsAltDown() && event->IsControlDown()) {
    if (event->type() == ui::ET_SCROLL_FLING_START ||
        event->type() == ui::ET_SCROLL_FLING_CANCEL) {
      event->StopPropagation();
      return;
    }

    if (event->type() == ui::ET_SCROLL) {
      ui::ScrollEvent* scroll_event = static_cast<ui::ScrollEvent*>(event);
      float scale = GetScale();
      scale += scroll_event->y_offset() * kScrollScaleChangeFactor;
      SetScale(scale, true);
      event->StopPropagation();
      return;
    }
  }
}

void MagnificationControllerImpl::OnTouchEvent(ui::TouchEvent* event) {
  aura::Window* target = static_cast<aura::Window*>(event->target());
  aura::Window* current_root = target->GetRootWindow();
  if (current_root == root_window_) {
    gfx::Rect root_bounds = current_root->bounds();
    if (root_bounds.Contains(event->root_location()))
      point_of_interest_ = event->root_location();
  }
}

void MagnificationControllerImpl::MoveMagnifierWindowFollowPoint(
    const gfx::Point& point,
    int x_panning_margin,
    int y_panning_margin,
    int x_target_margin,
    int y_target_margin) {
  DCHECK(root_window_);
  bool start_zoom = false;

  const gfx::Rect window_rect = GetViewportRect();
  const int left = window_rect.x();
  const int right = window_rect.right();

  int x_diff = 0;
  if (point.x() < left + x_panning_margin) {
    // Panning left.
    x_diff = point.x() - (left + x_target_margin);
    start_zoom = true;
  } else if (right - x_panning_margin < point.x()) {
    // Panning right.
    x_diff = point.x() - (right - x_target_margin);
    start_zoom = true;
  }
  int x = left + x_diff;

  const int top = window_rect.y();
  const int bottom = window_rect.bottom();

  int y_diff = 0;
  if (point.y() < top + y_panning_margin) {
    // Panning up.
    y_diff = point.y() - (top + y_target_margin);
    start_zoom = true;
  } else if (bottom - y_panning_margin < point.y()) {
    // Panning down.
    y_diff = point.y() - (bottom - y_target_margin);
    start_zoom = true;
  }
  int y = top + y_diff;
  if (start_zoom && !is_on_animation_) {
    bool ret = RedrawDIP(gfx::Point(x, y), scale_,
                         0,  // No animation on panning.
                         kDefaultAnimationTweenType);

    if (ret) {
      // If the magnified region is moved, hides the mouse cursor and moves it.
      if (x_diff != 0 || y_diff != 0)
        MoveCursorTo(root_window_->GetHost(), point);
    }
  }
}

void MagnificationControllerImpl::MoveMagnifierWindowCenterPoint(
    const gfx::Point& point) {
  DCHECK(root_window_);

  const gfx::Rect window_rect = GetViewportRect();
  if (point == window_rect.CenterPoint())
    return;

  if (!is_on_animation_) {
    // With animation on panning.
    RedrawDIP(window_rect.origin() + (point - window_rect.CenterPoint()),
              scale_, kDefaultAnimationDurationInMs,
              kCenterCaretAnimationTweenType);
  }
}

void MagnificationControllerImpl::MoveMagnifierWindowFollowRect(
    const gfx::Rect& rect) {
  DCHECK(root_window_);
  bool should_pan = false;

  const gfx::Rect viewport_rect = GetViewportRect();
  const int left = viewport_rect.x();
  const int right = viewport_rect.right();
  const gfx::Point rect_center = rect.CenterPoint();
  const gfx::Point window_center = viewport_rect.CenterPoint();

  int x = left;
  if (rect.x() < left || right < rect.right()) {
    // Panning horizontally.
    x = rect_center.x() - viewport_rect.width() / 2;
    should_pan = true;
  }

  const int top = viewport_rect.y();
  const int bottom = viewport_rect.bottom();

  int y = top;
  if (rect.y() < top || bottom < rect.bottom()) {
    // Panning vertically.
    y = rect_center.y() - viewport_rect.height() / 2;
    should_pan = true;
  }

  if (should_pan) {
    if (is_on_animation_) {
      root_window_->layer()->GetAnimator()->StopAnimating();
      is_on_animation_ = false;
    }
    RedrawDIP(gfx::Point(x, y), scale_,
              0,  // No animation on panning.
              kDefaultAnimationTweenType);
  }
}

void MagnificationControllerImpl::OnMoveMagnifierTimer() {
  MoveMagnifierWindowCenterPoint(caret_point_);
}

void MagnificationControllerImpl::OnCaretBoundsChanged(
    const ui::TextInputClient* client) {
  // caret bounds in screen coordinates.
  const gfx::Rect caret_bounds = client->GetCaretBounds();
  // Note: OnCaretBoundsChanged could be fired OnTextInputTypeChanged during
  // which the caret position is not set a meaning position, and we do not
  // need to adjust the view port position based on the bogus caret position.
  // This is only a transition period, the caret position will be fixed upon
  // focusing right after.
  if (caret_bounds.width() == 0 && caret_bounds.height() == 0)
    return;

  caret_point_ = caret_bounds.CenterPoint();
  // |caret_point_| in |root_window_| coordinates.
  wm::ConvertPointFromScreen(root_window_, &caret_point_);

  // If the feature for centering the text input focus is disabled, the
  // magnifier window will be moved to follow the focus with a panning margin.
  if (!KeepFocusCentered()) {
    // Visible window_rect in |root_window_| coordinates.
    const gfx::Rect visible_window_rect = GetViewportRect();
    const int panning_margin = kCaretPanningMargin / scale_;
    MoveMagnifierWindowFollowPoint(caret_point_,
                                   panning_margin,
                                   panning_margin,
                                   visible_window_rect.width() / 2,
                                   visible_window_rect.height() / 2);
    return;
  }

  // Move the magnifier window to center the focus with a little delay.
  // In Gmail compose window, when user types a blank space, it will insert
  // a non-breaking space(NBSP). NBSP will be replaced with a blank space
  // character when user types a non-blank space character later, which causes
  // OnCaretBoundsChanged be called twice. The first call moves the caret back
  // to the character position just before NBSP, replaces the NBSP with blank
  // space plus the new character, then the second call will move caret to the
  // position after the new character. In order to avoid the magnifier window
  // being moved back and forth with these two OnCaretBoundsChanged events, we
  // defer moving magnifier window until the |move_magnifier_timer_| fires,
  // when the caret settles eventually.
  move_magnifier_timer_.Stop();
  move_magnifier_timer_.Start(
      FROM_HERE,
      base::TimeDelta::FromMilliseconds(
          disable_move_magnifier_delay_ ? 0 : kMoveMagnifierDelayInMs),
      this, &MagnificationControllerImpl::OnMoveMagnifierTimer);
}

////////////////////////////////////////////////////////////////////////////////
// MagnificationController:

// static
MagnificationController* MagnificationController::CreateInstance() {
  return new MagnificationControllerImpl();
}

}  // namespace ash


text:
/*
# GracefulExpress

Working with the `Graceful` class, provides full graceful shutdown for an
`express`-based server:

1. Each request is wrapped a domain to ensure that even if an exception is thrown in a
callback, the client receives a response. If found, your `Graceful` instance is notified
of the error, and starts the shutdown process.
2. It keeps track of all active requests so we know when it is safe to shut down.
3. On shutdown, it calls `server.close()` to stop accepting new connections, destroys
all inactive sockets (idle keepalive connections), and sets 'Connection: close' on all
in-process requests.
5. A backstop for all requests that leak through when the server is in shutdown mode:
calling your Express error handler with an `Error` with `statusCode = 503`

*/
'use strict';

var domain = require('domain');
var util = require('./util');
var http = require('http');

var Graceful = require('./graceful');

/*
The `constructor` has some optional parameters:

+ `graceful` - required to enable full server shutdown scenarios. Can be set either on
construction or later with `listen()` or `setGraceful()`. Default is `Graceful.instance`,
so if you've created an instance in this process already, it will be found automatically.
+ `server` - the http server, though unlikely to be available on construction of this
class. More likely you'll use `listen()` or `setServer()` later - see below.
+ `inProcessTest` - if set to true, will prevent domains from being set up for every
request, enabling in-process testing of your endpoints, as is often done with `supertest`.
Defaults to true if we can detect that this is a `mocha` run.

*/
function GracefulExpress(options) {
  options = options || {};

  this.server = null;
  this.graceful = null;

  var startFile = process.mainModule.filename;
  this._setOption('inProcessTest', options, /mocha$/.test(startFile));

  this.reaperPollInterval = options.reaperPollInterval || 500;
  util.verifyType('number', this, 'reaperPollInterval');

  this.shuttingDown = false;
  this._serverClosed = false;

  this._responses = [];
  this._sockets = [];
  this._activeSockets = [];

  //both here for symmetry; unlikely that both of these are available on construction
  this.setGraceful(options.graceful || Graceful.instance);
  this.setServer(options.server);

  this.middleware = this.middleware.bind(this);
}

module.exports = GracefulExpress;

// Public Methods
// ========

// `listen` is a helper method to create an http server, wire it up properly, and start
// it listening on your desired interface. Returns the created server.
GracefulExpress.prototype.listen = function listen(app) {
  if (!app) {
    throw new Error('Need to provide express app as first parameter');
  }

  var args = Array.prototype.slice.call(arguments, 1);

  var server = http.createServer(app);
  this.setServer(server);

  server.listen.apply(server, args);

  return server;
};

// `middleware` should be added as a global middleware, before any handler that might stop
// the processing chain. It wires up a domain to capture any errors produced by the rest
// of that request's handlers, keeps track of sockets and responses, and rejects requests
// if they get here while the server is shutting down.
GracefulExpress.prototype.middleware = function middleware(req, res, next) {
  var _this = this;

  if (this.inProcessTest) {
    return next();
  }

  this.addActiveSocket(req.socket);
  this._addResponse(res);

  //bind to all three to be completely sure; handler only called once
  var finish = util.once(function() {
    _this.removeActiveSocket(req.socket);
    _this._removeResponse(res);
  });
  res.on('finish', finish);
  res.on('close', finish);
  res.on('end', finish);

  if (this.shuttingDown) {
    this._preventKeepAlive(res);

    var err = new Error('Server is shutting down; rejecting request');
    err.statusCode = 503;
    err.text = 'Please try again later; this server is shutting down';
    return next(err);
  }

  var d = domain.create();
  d.add(req);
  d.add(res);
  d.on('error', function(err) {
    _this._onError(err, req, res, next);
  });

  d.run(next);
};

// `setGraceful` can be used to provide a `Graceful` instance after construction.
GracefulExpress.prototype.setGraceful = function setGraceful(graceful) {
  if (graceful) {
    this.graceful = graceful;
    util.verifyGraceful(this.graceful);

    this.graceful.on('shutdown', this._onShutdown.bind(this));
    this.graceful.addCheck(this._isReadyForShutdown.bind(this));
  }
};

// `setServer` can be used to set `this.server` if you'd like to create it yourself.
GracefulExpress.prototype.setServer = function setServer(server) {
  if (server) {
    this.server = server;
    util.verifyServer(this.server);

    this.server.on('close', this._onClose.bind(this));
    this.server.on('connection', this._onConnection.bind(this));
  }
};

/*
Public: Advanced
========
By default sockets are marked as active when they pass through `middleware` and then
marked inactive again when the request is finished. This allows us to kill any unused
keepalive connections as the server is shutting down.

If you're doing some very custom things in your app, or just using `socket.io`, you may
have need to tell `GracefulExpress` that a given socket is not actually inactive, and
therefore shouldn't be destroyed immediately on shutdown. See
`test/scenarios/socket.io.js` for a complete example.
*/

// `addActiveSocket` adds provided socket to `this._activeSockets`, with no
// duplicate-checking.
GracefulExpress.prototype.addActiveSocket = function addActiveSocket(socket) {
  if (!socket || typeof socket !== 'object') {
    throw new Error('socket must be an object');
  }

  this._activeSockets.push(socket);
};

// `removeActiveSocket` removes the first instance of provided socket from
// `this._activeSockets`.
GracefulExpress.prototype.removeActiveSocket = function removeActiveSocket(socket) {
  if (!socket || typeof socket !== 'object') {
    throw new Error('socket must be an object');
  }

  for (var i = 0, max = this._activeSockets.length; i < max; i += 1) {
    var element = this._activeSockets[i];

    if (element === socket) {
      this._activeSockets = this._activeSockets.slice(0, i)
        .concat(this._activeSockets.slice(i + 1));

      return;
    }
  }
};

// Event handlers
// ========

/*
`_onError` is the method called when a request domain catches an error. It

  1. closes the http keepalive connection
  2. starts a graceful shutdown if we have a `Graceful` instance
  3. and passes the error to the registered express error handler
*/
GracefulExpress.prototype._onError = function _onError(err, req, res, next) {
  this._preventKeepAlive(res);

  //Don't want the entire domain object to pollute the log entry for this error
  delete err.domain;
  delete err.domainEmitter;

  if (this.graceful) {
    this.graceful.shutdown(err, req);
  }

  next(err);
};

// `_onClose` runs when the http server's 'close' event fires. Stops the socket reaper
// interval and records receipt.
GracefulExpress.prototype._onClose = function _onClose() {
  if (this.interval) {
    clearInterval(this.interval);
    this.interval = null;
  }

  this._serverClosed = true;
};

/*
`_onConnection` runs when the http server's 'connection' event fires. It's how we can
be sure that we're capturing all sockets connected to the server.

_Note: A big reason for going with this approach is Google Chrome's interesting behavior:
without the dev tools open, if you just request one URL (with no assets) from a server,
you end up with a zombie socket connected to the server which never hits any middleware.
This will prevent the server's close event from firing._
*/
GracefulExpress.prototype._onConnection = function _onConnection(socket) {
  this._addSocket(socket);
};

/*
`_onShutdown` runs when `Graceful`'s 'shutdown' event fires. It first tells the `http`
server to stop accepting new connections. Unfortunately, this isn't enough, as it will
continue to service existing requests and already-existing keepalive connections.

+ `_closeConnAfterResponses` tells all current requests to close the connection after
that request is complete.
+ `_closeInactiveSockets` shuts down all inactive sockets (usually idle keepalive
connections).
+ `_startSocketReaper` starts an interval to repeatedly call `_closeInactiveSockets`,
catching sockets as they become inactive.

*/
GracefulExpress.prototype._onShutdown = function _onShutdown() {
  this.shuttingDown = true;

  if (this.server) {
    try {
      this.server.close();
    }
    catch (e) {}
  }

  this._closeConnAfterResponses();
  this._closeInactiveSockets();
  this._startSocketReaper();
};

// `_isReadyForShutdown` lets `Graceful` know when we're ready for `process.exit()`
GracefulExpress.prototype._isReadyForShutdown = function _isReadyForShutdown() {
  if (this.inProcessTest) {
    return true;
  }

  //if we never got the server, we never registered for the server 'close' event
  if (!this.server) {
    return this._responses.length === 0;
  }

  return this._serverClosed;
};

// Helper methods
// ========

// `_preventKeepAlive` tells any connection to close at the end of the current request.
// Unfortunately not enough because some keepalive connections will not make any requests
// as we're shutting down.
GracefulExpress.prototype._preventKeepAlive = function _preventKeepAlive(res) {
  res.shouldKeepAlive = false;
};

// `_setOption` makes dealing with undefined boolean options a bit easier.
GracefulExpress.prototype._setOption = function _setOption(name, options, defaultVal) {
  this[name] = options[name];
  if (typeof this[name] === 'undefined') {
    this[name] = defaultVal;
  }
};

// Response tracking
// ========

// `_closeConnAfterResponses` calls `_preventKeepAlive` on every active request
GracefulExpress.prototype._closeConnAfterResponses = function _closeConnAfterResponses() {
  for (var i = 0, max = this._responses.length; i < max; i += 1) {
    var res = this._responses[i];
    this._preventKeepAlive(res);
  }
};

// `_addResponse` adds `res` to the list of in-progress responses
GracefulExpress.prototype._addResponse = function _addResponse(res) {
  this._responses.push(res);
};

// `_removeResponse` removes `res` from the list of in-progress responses
GracefulExpress.prototype._removeResponse = function _removeResponse(res) {
  for (var i = 0, max = this._responses.length; i < max; i += 1) {
    var element = this._responses[i];
    if (element === res) {
      this._responses = this._responses.slice(0, i).concat(this._responses.slice(i + 1));
      return;
    }
  }
};

// Socket tracking
// =======
// The rest of socket tracking, aside from the two public methods to add and remove
// active sockets.

// `_startSocketReaper` starts an interval to call `_closeInactiveSockets()` repeatedly,
// attempting to catch anything that slipped through the cracks.
GracefulExpress.prototype._startSocketReaper = function _startSocketReaper() {
  var _this = this;

  this.interval = setInterval(function() {
    _this._closeInactiveSockets();
  }, this.reaperPollInterval);
};

// `_closeInactiveSockets` destroys all inactive sockets
GracefulExpress.prototype._closeInactiveSockets = function _closeInactiveSockets() {
  var inactive = this._getInactiveSockets();

  for (var i = 0, max = inactive.length; i < max; i += 1) {
    var socket = inactive[i];
    socket.destroySoon();
  }
};

// `_getInactiveSockets` builds a list of inactive sockets by looping through all
// `this._sockets`, ensuring that they are not present in `this._activeSockets`
GracefulExpress.prototype._getInactiveSockets = function _getInactiveSockets() {
  var inactive = [];

  for (var i = 0, iMax = this._sockets.length; i < iMax; i += 1) {
    var socket = this._sockets[i];
    var add = true;

    for (var j = 0, jMax = this._activeSockets.length; j < jMax; j += 1) {
      var active = this._activeSockets[j];

      if (socket === active) {
        add = false;
        break;
      }
    }

    if (add) {
      inactive.push(socket);
    }
  }

  return inactive;
};

// `_addSocket` adds provided socket to `this._sockets` if it isn't already in the list
GracefulExpress.prototype._addSocket = function _addSocket(socket) {
  var _this = this;

  for (var i = 0, max = this._sockets.length; i < max; i += 1) {
    var element = this._sockets[i];

    if (element === socket) {
      return;
    }
  }

  this._sockets.push(socket);

  socket.on('close', function() {
    _this._removeSocket(socket);
  });
};

// `_removeSocket` removes provided socket from `this._sockets`
GracefulExpress.prototype._removeSocket = function _removeSocket(socket) {
  for (var i = 0, max = this._sockets.length; i < max; i += 1) {
    var element = this._sockets[i];
    if (element === socket) {
      this._sockets = this._sockets.slice(0, i).concat(this._sockets.slice(i + 1));
      return;
    }
  }
};

redpajama_set_name: RedPajamaGithub


text:
<?php echo $title ?>

<?php echo validation_errors(); ?>

<?php echo form_open('projet/supprimer/'.$projet->id) ?>
    Cocher la case pour valider la suppression du projet
    <input type="checkbox" name="check" />

    <input type="submit" name="submit" value="Supprimer le projet" />

</form>

<a href="<?php echo site_url('projet/'.$projet->id) ?>">Annuler


text:
using System;
using System.Collections.Generic;
using System.Text;
using Epi.Cloud.Common.Metadata;

namespace MvcDynamicForms.Fields
{
    /// <summary>
    /// Represents a dynamically generated html input field.
    /// </summary>
    [Serializable]
    public abstract class InputField : Field
    {
        protected double _promptTop;
        protected double _promptLeft;
        protected double _promptWidth;
        protected double _controlWidth;
        protected double _controlHeight;
        protected string _key = Guid.NewGuid().ToString();
        protected string _requiredMessage = "Required";
        protected string _promptClass = "MvcDynamicFieldPrompt";
        protected string _errorClass = "MvcDynamicFieldError";
        protected Boolean _isRequired;
        protected Boolean _isReadOnly;
        protected int _MaxLength;
        protected string _InputFieldfontstyle;
        protected double _InputFieldfontSize;
        protected string _InputFieldfontfamily;
        protected string _BackgroundColor;
        protected int _FieldTypeId;
        protected string _Pattern;
        protected string _Lower;
        protected string _Upper;
        protected Dictionary<string, string> _inputHtmlAttributes = new Dictionary<string, string>();

        /// <summary>
        /// Used to identify each InputField when performing model binding.
        /// </summary>
        ///
        public int FieldTypeId { get; set; }

        public string Key
        {
            get { return _key; }
            set { _key = value.ToLower(); }
        }
        /// <summary>
        /// Used to identify InputFields when working with end users' responses.
        /// </summary>
        public string Title { get; set; }
        /// <summary>
        /// The question asked of the end user. This text appears before the html input element.
        /// </summary>
        public string Prompt { get; set; }
        /// <summary>
        /// The html class applied to the label element that appears before the input element.
        /// </summary>
        public string PromptClass
        {
            get
            {
                return _promptClass;
            }
            set
            {
                _promptClass = value;
            }
        }
        public string Value { get; set; }
        /// <summary>
        /// String representing the user's response to the field.
        /// </summary>
        public abstract string Response { get; set; }
        /// <summary>
        /// Whether the field must be completed to be valid.
        /// </summary>
        public bool Required { get; set; }

        /// <summary>
        /// Whether the field is readonly. If the field is readonly then the required = false
        /// </summary>
        public bool ReadOnly { get; set; }
        /// <summary>
        /// The error message that the end user sees if they do not complete the field.
        /// </summary>
        public string RequiredMessage
        {
            get
            {
                return _requiredMessage;
            }
            set
            {
                _requiredMessage = value;
            }
        }
        /// <summary>
        /// The error message that the end user sees.
        /// </summary>
        public string Error { get; set; }
        /// <summary>
        /// The class attribute of the label element that is used to display an error message to the user.
        /// </summary>
        public string ErrorClass
        {
            get
            {
                return _errorClass;
            }
            set
            {
                _errorClass = value;
            }
        }
        /// <summary>
        /// True if the field is valid; false otherwise.
        /// </summary>
        public bool IsValid
        {
            get
            {
                return string.IsNullOrEmpty(Error);
            }
        }
        /// <summary>
        /// Collection of html attribute names and values that will be applied to the rendered input elements.
        /// </summary>
        public Dictionary<string, string> InputHtmlAttributes
        {
            get
            {
                return _inputHtmlAttributes;
            }
            set
            {
                _inputHtmlAttributes = value;
            }
        }

        protected override void InitializeFromMetadata(FieldAttributes fieldAttributes, double formWidth, double formHeight)
        {
            base.InitializeFromMetadata(fieldAttributes, formWidth, formHeight);

            Title = fieldAttributes.FieldName;
            Prompt = fieldAttributes.PromptText;
            Key = fieldAttributes.FieldName;
            PromptTop = formHeight * fieldAttributes.PromptTopPositionPercentage;
            PromptLeft = formWidth * fieldAttributes.PromptLeftPositionPercentage;
            PromptWidth = formWidth * fieldAttributes.ControlWidthPercentage;
            ControlWidth = formWidth * fieldAttributes.ControlWidthPercentage;
            ControlHeight = formHeight * fieldAttributes.ControlHeightPercentage;

            InputFieldfontstyle = fieldAttributes.ControlFontStyle;
            InputFieldfontfamily = fieldAttributes.ControlFontFamily;
            InputFieldfontSize = fieldAttributes.ControlFontSize;

            IsRequired = fieldAttributes.IsRequired;
            Required = fieldAttributes.Required;
            RequiredMessage = fieldAttributes.RequiredMessage;
            ReadOnly = fieldAttributes.IsReadOnly;
            Pattern = fieldAttributes.Pattern;
            Upper = fieldAttributes.Upper;
            Lower = fieldAttributes.Lower;
            IsHighlighted=fieldAttributes.IsHighlighted;
        }

        /// <summary>
        /// Validates the user's response.
        /// </summary>
        /// <returns></returns>
        public abstract bool Validate();
        /// <summary>
        /// Removes the message stored in the Error property.
        /// </summary>
        public void ClearError()
        {
            Error = null;
        }

        public double PromptTop { get { return this._promptTop; } set { this._promptTop = value; } }
        public double PromptLeft { get { return this._promptLeft; } set { this._promptLeft = value; } }

        public double PromptWidth { get { return this._promptWidth; } set { this._promptWidth = value; } }
        public double ControlWidth { get { return System.Math.Truncate(this._controlWidth); } set { this._controlWidth = System.Math.Truncate(value); } }

        public double ControlHeight { get { return System.Math.Truncate(this._controlHeight); } set { this._controlHeight = System.Math.Truncate(value); } }
        public Boolean IsRequired { get { return this._isRequired; } set { this._isRequired = value; } }
        public Boolean IsReadOnly { get { return this._isReadOnly; } set { this._isReadOnly = value; } }
        public int MaxLength { get { return this._MaxLength; } set { this._MaxLength = value; } }

        //  protected string InputFieldfontstyle;
        //  protected string InputFieldfontSize;
        // protected string InputFieldfontfamily;
        public string InputFieldfontstyle { get { return this._InputFieldfontstyle; } set { this._InputFieldfontstyle = value; } }
        public double InputFieldfontSize { get { return this._InputFieldfontSize; } set { this._InputFieldfontSize = value; } }
        public string InputFieldfontfamily { get { return this._InputFieldfontfamily; } set { this._InputFieldfontfamily = value; } }
        public string BackgroundColor { get { return this._BackgroundColor; } set { this._BackgroundColor = value; } }

        public string Pattern { get { return this._Pattern; } set { this._Pattern = value; } }

        public string Upper { get { return this._Upper; } set { this._Upper = value; } }

        public string Lower { get { return this._Lower; } set { this._Lower= value; } }

        public string GetInputFieldStyle(string ControlFontStyle, double ControlFontSize, string ControlFontFamily)
        {

            StringBuilder FontStyle = new StringBuilder();
            StringBuilder FontWeight = new StringBuilder();
            StringBuilder TextDecoration = new StringBuilder();
            StringBuilder CssStyles = new StringBuilder();

            char[] delimiterChars = { ' ', ',' };
            string[] Styles = ControlFontStyle.Split(delimiterChars);

            foreach (string Style in Styles)
            {
                switch (Style.ToString())
                {
                    case "Italic":
                        FontStyle.Append(Style.ToString());
                        break;
                    case "Oblique":
                        FontStyle.Append(Style.ToString());

                        break;

                }

            }
            foreach (string Style in Styles)
            {
                switch (Style.ToString())
                {
                    case "Bold":
                        FontWeight.Append(Style.ToString());
                        break;
                    case "Normal":
                        FontWeight.Append(Style.ToString());
                        break;

                }

            }
            CssStyles.Append(";font:");//1
            if (!string.IsNullOrEmpty(FontStyle.ToString()))
            {

                CssStyles.Append(FontStyle);//2
                CssStyles.Append(" ");//3
            }
            CssStyles.Append(FontWeight);
            CssStyles.Append(" ");
            CssStyles.Append(this._InputFieldfontSize.ToString() + "pt ");
            CssStyles.Append(" ");
            CssStyles.Append(this._InputFieldfontfamily.ToString());

            foreach (string Style in Styles)
            {
                switch (Style.ToString())
                {
                    case "Strikeout":
                        TextDecoration.Append("line-through");
                        break;
                    case "Underline":
                        TextDecoration.Append(Style.ToString());

                        break;

                }

            }

            if (!string.IsNullOrEmpty(TextDecoration.ToString()))
            {
                CssStyles.Append(";text-decoration:");
            }

            CssStyles.Append(TextDecoration);

            return CssStyles.ToString();

        }
    }
}