tray_event_filter.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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.
4
5#include "ash/system/tray/tray_event_filter.h"
6
7#include "ash/root_window_controller.h"
8#include "ash/shell.h"
9#include "ash/shell_window_ids.h"
10#include "ash/system/tray/tray_background_view.h"
11#include "ash/system/tray/tray_bubble_wrapper.h"
12#include "ash/system/tray/tray_constants.h"
13#include "ash/system/tray/tray_event_filter.h"
14#include "ash/wm/property_util.h"
15#include "ash/wm/shelf_layout_manager.h"
16#include "ui/aura/event_filter.h"
17#include "ui/aura/window.h"
18#include "ui/views/widget/widget.h"
19
20namespace ash {
21namespace internal {
22
23TrayEventFilter::TrayEventFilter(TrayBubbleWrapper* wrapper)
24    : wrapper_(wrapper) {
25  ash::Shell::GetInstance()->AddEnvEventFilter(this);
26}
27
28TrayEventFilter::~TrayEventFilter() {
29  ash::Shell::GetInstance()->RemoveEnvEventFilter(this);
30}
31
32bool TrayEventFilter::PreHandleKeyEvent(aura::Window* target,
33                                        ui::KeyEvent* event) {
34  return false;
35}
36
37bool TrayEventFilter::PreHandleMouseEvent(aura::Window* target,
38                                          ui::MouseEvent* event) {
39  if (event->type() == ui::ET_MOUSE_PRESSED)
40    return ProcessLocatedEvent(target, *event);
41  return false;
42}
43
44ui::EventResult TrayEventFilter::PreHandleTouchEvent(aura::Window* target,
45                                                     ui::TouchEvent* event) {
46  if (event->type() == ui::ET_TOUCH_PRESSED) {
47    if (ProcessLocatedEvent(target, *event))
48      return ui::ER_CONSUMED;
49  }
50  return ui::ER_UNHANDLED;
51}
52
53ui::EventResult TrayEventFilter::PreHandleGestureEvent(
54    aura::Window* target,
55    ui::GestureEvent* event) {
56  return ui::ER_UNHANDLED;
57}
58
59bool TrayEventFilter::ProcessLocatedEvent(aura::Window* target,
60                                          const ui::LocatedEvent& event) {
61  if (target) {
62    // Don't process events that occurred inside an embedded menu.
63    ash::internal::RootWindowController* root_controller =
64        ash::GetRootWindowController(target->GetRootWindow());
65    if (root_controller && root_controller->GetContainer(
66            ash::internal::kShellWindowId_MenuContainer)->Contains(target)) {
67      return false;
68    }
69  }
70  if (!wrapper_->bubble_widget())
71    return false;
72
73  gfx::Rect bounds = wrapper_->bubble_widget()->GetWindowBoundsInScreen();
74  gfx::Insets insets;
75  wrapper_->bubble_view()->GetBorderInsets(&insets);
76  bounds.Inset(insets);
77  if (bounds.Contains(event.root_location()))
78    return false;
79  if (wrapper_->tray()) {
80    // If the user clicks on the parent tray, don't process the event here,
81    // let the tray logic handle the event and determine show/hide behavior.
82    bounds = wrapper_->tray()->GetWidget()->GetClientAreaBoundsInScreen();
83    if (bounds.Contains(event.root_location()))
84      return false;
85  }
86  // Handle clicking outside the bubble and tray and return true if the
87  // event was handled.
88  return wrapper_->tray()->ClickedOutsideBubble();
89}
90
91}  // namespace internal
92}  // namespace ash
93