1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file.
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/views/controls/menu/menu_event_dispatcher_linux.h"
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/aura/window.h"
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/event_utils.h"
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/keycodes/keyboard_code_conversion.h"
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/keycodes/keyboard_codes.h"
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/views/controls/menu/menu_controller.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/widget/widget.h"
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace views {
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace internal {
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochMenuEventDispatcher::MenuEventDispatcher(MenuController* controller)
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : menu_controller_(controller) {}
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochMenuEventDispatcher::~MenuEventDispatcher() {}
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool MenuEventDispatcher::CanDispatchEvent(const ui::PlatformEvent& event) {
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochuint32_t MenuEventDispatcher::DispatchEvent(const ui::PlatformEvent& event) {
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool should_quit = false;
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool should_perform_default = true;
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool should_process_event = true;
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check if the event should be handled.
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<ui::Event> ui_event(ui::EventFromNative(event));
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (ui_event && menu_controller_->owner()) {
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    aura::Window* menu_window = menu_controller_->owner()->GetNativeWindow();
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    aura::Window* target_window = static_cast<aura::Window*>(
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        static_cast<ui::EventTarget*>(menu_window->GetRootWindow())->
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            GetEventTargeter()->FindTargetForEvent(menu_window,
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                   ui_event.get()));
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(flackr): The event shouldn't be handled if target_window is not
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // menu_window, however the event targeter does not properly target the
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // open menu. For now, we allow targeters to prevent handling by the menu.
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!target_window)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      should_process_event = false;
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (menu_controller_->exit_type() == MenuController::EXIT_ALL ||
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      menu_controller_->exit_type() == MenuController::EXIT_DESTROYED) {
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    should_quit = true;
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (should_process_event) {
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    switch (ui::EventTypeFromNative(event)) {
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case ui::ET_KEY_PRESSED: {
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (!menu_controller_->OnKeyDown(ui::KeyboardCodeFromNative(event))) {
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          should_quit = true;
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          should_perform_default = false;
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          break;
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // Do not check mnemonics if the Alt or Ctrl modifiers are pressed.
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        int flags = ui::EventFlagsFromNative(event);
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if ((flags & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) == 0) {
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          char c = ui::GetCharacterFromKeyCode(
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              ui::KeyboardCodeFromNative(event), flags);
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          if (menu_controller_->SelectByChar(c)) {
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            should_quit = true;
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            should_perform_default = false;
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            break;
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          }
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        should_quit = false;
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        should_perform_default = false;
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      }
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case ui::ET_KEY_RELEASED:
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        should_quit = false;
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        should_perform_default = false;
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      default:
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (should_quit || menu_controller_->exit_type() != MenuController::EXIT_NONE)
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    menu_controller_->TerminateNestedMessageLoop();
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return should_perform_default ? ui::POST_DISPATCH_PERFORM_DEFAULT
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                : ui::POST_DISPATCH_NONE;
88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
90c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace internal
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace views
92