Home | History | Annotate | Download | only in core
      1 // Copyright 2014 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.
      4 
      5 #include "ui/wm/core/nested_accelerator_controller.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/event_types.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "ui/aura/test/aura_test_base.h"
     11 #include "ui/aura/test/test_windows.h"
     12 #include "ui/aura/window.h"
     13 #include "ui/aura/window_event_dispatcher.h"
     14 #include "ui/base/accelerators/accelerator.h"
     15 #include "ui/base/accelerators/accelerator.h"
     16 #include "ui/base/accelerators/accelerator_manager.h"
     17 #include "ui/events/event_constants.h"
     18 #include "ui/events/event_utils.h"
     19 #include "ui/events/platform/platform_event_dispatcher.h"
     20 #include "ui/events/platform/platform_event_source.h"
     21 #include "ui/events/platform/scoped_event_dispatcher.h"
     22 #include "ui/wm/core/nested_accelerator_delegate.h"
     23 #include "ui/wm/public/dispatcher_client.h"
     24 
     25 #if defined(USE_X11)
     26 #include <X11/Xlib.h>
     27 #include "ui/events/test/events_test_utils_x11.h"
     28 #endif  // USE_X11
     29 
     30 namespace wm {
     31 namespace test {
     32 
     33 namespace {
     34 
     35 class MockDispatcher : public ui::PlatformEventDispatcher {
     36  public:
     37   MockDispatcher() : num_key_events_dispatched_(0) {}
     38 
     39   int num_key_events_dispatched() { return num_key_events_dispatched_; }
     40 
     41  private:
     42   // ui::PlatformEventDispatcher:
     43   virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE {
     44     return true;
     45   }
     46   virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE {
     47     if (ui::EventTypeFromNative(event) == ui::ET_KEY_RELEASED)
     48       num_key_events_dispatched_++;
     49     return ui::POST_DISPATCH_NONE;
     50   }
     51 
     52   int num_key_events_dispatched_;
     53 
     54   DISALLOW_COPY_AND_ASSIGN(MockDispatcher);
     55 };
     56 
     57 class TestTarget : public ui::AcceleratorTarget {
     58  public:
     59   TestTarget() : accelerator_pressed_count_(0) {}
     60   virtual ~TestTarget() {}
     61 
     62   int accelerator_pressed_count() const { return accelerator_pressed_count_; }
     63 
     64   // Overridden from ui::AcceleratorTarget:
     65   virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE {
     66     accelerator_pressed_count_++;
     67     return true;
     68   }
     69   virtual bool CanHandleAccelerators() const OVERRIDE { return true; }
     70 
     71  private:
     72   int accelerator_pressed_count_;
     73 
     74   DISALLOW_COPY_AND_ASSIGN(TestTarget);
     75 };
     76 
     77 void DispatchKeyReleaseA(aura::Window* root_window) {
     78 // Sending both keydown and keyup is necessary here because the accelerator
     79 // manager only checks a keyup event following a keydown event. See
     80 // ShouldHandle() in ui/base/accelerators/accelerator_manager.cc for details.
     81 #if defined(OS_WIN)
     82   MSG native_event_down = {NULL, WM_KEYDOWN, ui::VKEY_A, 0};
     83   aura::WindowTreeHost* host = root_window->GetHost();
     84   host->PostNativeEvent(native_event_down);
     85   MSG native_event_up = {NULL, WM_KEYUP, ui::VKEY_A, 0};
     86   host->PostNativeEvent(native_event_up);
     87 #elif defined(USE_X11)
     88   ui::ScopedXI2Event native_event;
     89   native_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, 0);
     90   aura::WindowTreeHost* host = root_window->GetHost();
     91   host->PostNativeEvent(native_event);
     92   native_event.InitKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, 0);
     93   host->PostNativeEvent(native_event);
     94 #endif
     95   // Make sure the inner message-loop terminates after dispatching the events.
     96   base::MessageLoop::current()->PostTask(
     97       FROM_HERE, base::MessageLoop::current()->QuitClosure());
     98 }
     99 
    100 class MockNestedAcceleratorDelegate : public NestedAcceleratorDelegate {
    101  public:
    102   MockNestedAcceleratorDelegate()
    103       : accelerator_manager_(new ui::AcceleratorManager) {}
    104   virtual ~MockNestedAcceleratorDelegate() {}
    105 
    106   // NestedAcceleratorDelegate:
    107   virtual Result ProcessAccelerator(
    108       const ui::Accelerator& accelerator) OVERRIDE {
    109     return accelerator_manager_->Process(accelerator) ?
    110         RESULT_PROCESSED : RESULT_NOT_PROCESSED;
    111   }
    112 
    113   void Register(const ui::Accelerator& accelerator,
    114                 ui::AcceleratorTarget* target) {
    115     accelerator_manager_->Register(
    116         accelerator, ui::AcceleratorManager::kNormalPriority, target);
    117   }
    118 
    119  private:
    120   scoped_ptr<ui::AcceleratorManager> accelerator_manager_;
    121 
    122   DISALLOW_COPY_AND_ASSIGN(MockNestedAcceleratorDelegate);
    123 };
    124 
    125 class NestedAcceleratorTest : public aura::test::AuraTestBase {
    126  public:
    127   NestedAcceleratorTest() {}
    128   virtual ~NestedAcceleratorTest() {}
    129 
    130   virtual void SetUp() OVERRIDE {
    131     AuraTestBase::SetUp();
    132     delegate_ = new MockNestedAcceleratorDelegate();
    133     nested_accelerator_controller_.reset(
    134         new NestedAcceleratorController(delegate_));
    135     aura::client::SetDispatcherClient(root_window(),
    136                                       nested_accelerator_controller_.get());
    137   }
    138 
    139   virtual void TearDown() OVERRIDE {
    140     aura::client::SetDispatcherClient(root_window(), NULL);
    141     AuraTestBase::TearDown();
    142     delegate_ = NULL;
    143     nested_accelerator_controller_.reset();
    144   }
    145 
    146   MockNestedAcceleratorDelegate* delegate() { return delegate_; }
    147 
    148  private:
    149   scoped_ptr<NestedAcceleratorController> nested_accelerator_controller_;
    150   MockNestedAcceleratorDelegate* delegate_;
    151 
    152   DISALLOW_COPY_AND_ASSIGN(NestedAcceleratorTest);
    153 };
    154 
    155 }  // namespace
    156 
    157 // Aura window above lock screen in z order.
    158 // http://crbug.com/396494
    159 TEST_F(NestedAcceleratorTest, DISABLED_AssociatedWindowAboveLockScreen) {
    160   // TODO(oshima|sadrul): remove when Win implements PES.
    161   if (!ui::PlatformEventSource::GetInstance())
    162     return;
    163   MockDispatcher inner_dispatcher;
    164   scoped_ptr<aura::Window> mock_lock_container(
    165       CreateNormalWindow(0, root_window(), NULL));
    166   aura::test::CreateTestWindowWithId(1, mock_lock_container.get());
    167 
    168   scoped_ptr<aura::Window> associated_window(
    169       CreateNormalWindow(2, root_window(), NULL));
    170   EXPECT_TRUE(aura::test::WindowIsAbove(associated_window.get(),
    171                                         mock_lock_container.get()));
    172 
    173   DispatchKeyReleaseA(root_window());
    174   scoped_ptr<ui::ScopedEventDispatcher> override_dispatcher =
    175       ui::PlatformEventSource::GetInstance()->OverrideDispatcher(
    176           &inner_dispatcher);
    177   aura::client::DispatcherRunLoop run_loop(
    178       aura::client::GetDispatcherClient(root_window()), NULL);
    179   run_loop.Run();
    180   EXPECT_EQ(1, inner_dispatcher.num_key_events_dispatched());
    181 }
    182 
    183 // Test that the nested dispatcher handles accelerators.
    184 // http://crbug.com/396494
    185 TEST_F(NestedAcceleratorTest, DISABLED_AcceleratorsHandled) {
    186   // TODO(oshima|sadrul): remove when Win implements PES.
    187   if (!ui::PlatformEventSource::GetInstance())
    188     return;
    189   MockDispatcher inner_dispatcher;
    190   ui::Accelerator accelerator(ui::VKEY_A, ui::EF_NONE);
    191   accelerator.set_type(ui::ET_KEY_RELEASED);
    192   TestTarget target;
    193   delegate()->Register(accelerator, &target);
    194 
    195   DispatchKeyReleaseA(root_window());
    196   scoped_ptr<ui::ScopedEventDispatcher> override_dispatcher =
    197       ui::PlatformEventSource::GetInstance()->OverrideDispatcher(
    198           &inner_dispatcher);
    199   aura::client::DispatcherRunLoop run_loop(
    200       aura::client::GetDispatcherClient(root_window()), NULL);
    201   run_loop.Run();
    202   EXPECT_EQ(0, inner_dispatcher.num_key_events_dispatched());
    203   EXPECT_EQ(1, target.accelerator_pressed_count());
    204 }
    205 
    206 }  //  namespace test
    207 }  //  namespace wm
    208