root/ui/aura/window_targeter_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. FindTargetForLocatedEvent
  2. root_window
  3. GetEffectiveVisibleBoundsInRootWindow
  4. TEST_F
  5. TEST_F
  6. TEST_F

// Copyright (c) 2013 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/window_targeter.h"

#include "ui/aura/scoped_window_targeter.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/events/test/test_event_handler.h"

namespace aura {

// Always returns the same window.
class StaticWindowTargeter : public ui::EventTargeter {
 public:
  explicit StaticWindowTargeter(aura::Window* window)
      : window_(window) {}
  virtual ~StaticWindowTargeter() {}

 private:
  // ui::EventTargeter:
  virtual ui::EventTarget* FindTargetForLocatedEvent(
      ui::EventTarget* root,
      ui::LocatedEvent* event) OVERRIDE {
    return window_;
  }

  Window* window_;

  DISALLOW_COPY_AND_ASSIGN(StaticWindowTargeter);
};

class WindowTargeterTest : public test::AuraTestBase {
 public:
  WindowTargeterTest() {}
  virtual ~WindowTargeterTest() {}

  Window* root_window() { return AuraTestBase::root_window(); }
};

gfx::RectF GetEffectiveVisibleBoundsInRootWindow(Window* window) {
  gfx::RectF bounds = gfx::Rect(window->bounds().size());
  Window* root = window->GetRootWindow();
  CHECK(window->layer());
  CHECK(root->layer());
  gfx::Transform transform;
  if (!window->layer()->GetTargetTransformRelativeTo(root->layer(), &transform))
    return gfx::RectF();
  transform.TransformRect(&bounds);
  return bounds;
}

TEST_F(WindowTargeterTest, Basic) {
  test::TestWindowDelegate delegate;
  scoped_ptr<Window> window(CreateNormalWindow(1, root_window(), &delegate));
  Window* one = CreateNormalWindow(2, window.get(), &delegate);
  Window* two = CreateNormalWindow(3, window.get(), &delegate);

  window->SetBounds(gfx::Rect(0, 0, 100, 100));
  one->SetBounds(gfx::Rect(0, 0, 500, 100));
  two->SetBounds(gfx::Rect(501, 0, 500, 1000));

  root_window()->Show();

  ui::test::TestEventHandler handler;
  one->AddPreTargetHandler(&handler);

  ui::MouseEvent press(ui::ET_MOUSE_PRESSED,
                       gfx::Point(20, 20),
                       gfx::Point(20, 20),
                       ui::EF_NONE,
                       ui::EF_NONE);
  DispatchEventUsingWindowDispatcher(&press);
  EXPECT_EQ(1, handler.num_mouse_events());

  handler.Reset();
  DispatchEventUsingWindowDispatcher(&press);
  EXPECT_EQ(1, handler.num_mouse_events());

  one->RemovePreTargetHandler(&handler);
}

TEST_F(WindowTargeterTest, ScopedWindowTargeter) {
  test::TestWindowDelegate delegate;
  scoped_ptr<Window> window(CreateNormalWindow(1, root_window(), &delegate));
  Window* child = CreateNormalWindow(2, window.get(), &delegate);

  window->SetBounds(gfx::Rect(30, 30, 100, 100));
  child->SetBounds(gfx::Rect(20, 20, 50, 50));
  root_window()->Show();

  ui::EventTarget* root = root_window();
  ui::EventTargeter* targeter = root->GetEventTargeter();

  gfx::Point event_location(60, 60);
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(child, targeter->FindTargetForEvent(root, &mouse));
  }

  // Install a targeter on |window| so that the events never reach the child.
  scoped_ptr<ScopedWindowTargeter> scoped_targeter(
      new ScopedWindowTargeter(window.get(), scoped_ptr<ui::EventTargeter>(
          new StaticWindowTargeter(window.get()))));
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root, &mouse));
  }
  scoped_targeter.reset();
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(child, targeter->FindTargetForEvent(root, &mouse));
  }
}

TEST_F(WindowTargeterTest, TargetTransformedWindow) {
  root_window()->Show();

  test::TestWindowDelegate delegate;
  scoped_ptr<Window> window(CreateNormalWindow(2, root_window(), &delegate));

  const gfx::Rect window_bounds(100, 20, 400, 80);
  window->SetBounds(window_bounds);

  ui::EventTarget* root_target = root_window();
  ui::EventTargeter* targeter = root_target->GetEventTargeter();
  gfx::Point event_location(490, 50);
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root_target, &mouse));
  }

  // Scale |window| by 50%. This should move it away from underneath
  // |event_location|, so an event in that location will not be targeted to it.
  gfx::Transform transform;
  transform.Scale(0.5, 0.5);
  window->SetTransform(transform);
  EXPECT_EQ(gfx::RectF(100, 20, 200, 40).ToString(),
            GetEffectiveVisibleBoundsInRootWindow(window.get()).ToString());
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(root_window(), targeter->FindTargetForEvent(root_target, &mouse));
  }

  transform = gfx::Transform();
  transform.Translate(200, 10);
  transform.Scale(0.5, 0.5);
  window->SetTransform(transform);
  EXPECT_EQ(gfx::RectF(300, 30, 200, 40).ToString(),
            GetEffectiveVisibleBoundsInRootWindow(window.get()).ToString());
  {
    ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
                         ui::EF_NONE, ui::EF_NONE);
    EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root_target, &mouse));
  }
}

}  // namespace aura

/* [<][>][^][v][top][bottom][index][help] */