15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/workspace/workspace_event_handler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/metrics/user_metrics_recorder.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/touch/touch_uma.h"
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_state.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/wm/wm_event.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window_delegate.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/hit_test.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
180529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochWorkspaceEventHandler::WorkspaceEventHandler()
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    : click_component_(HTNOWHERE) {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WorkspaceEventHandler::~WorkspaceEventHandler() {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WorkspaceEventHandler::OnMouseEvent(ui::MouseEvent* event) {
260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  aura::Window* target = static_cast<aura::Window*>(event->target());
270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (event->type() == ui::ET_MOUSE_PRESSED &&
280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      event->IsOnlyLeftMouseButton() &&
290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ((event->flags() &
300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          (ui::EF_IS_DOUBLE_CLICK | ui::EF_IS_TRIPLE_CLICK)) == 0)) {
310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    click_component_ = target->delegate()->
320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        GetNonClientComponent(event->location());
330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (event->handled())
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (event->type()) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_MOVED: {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int component =
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          target->delegate()->GetNonClientComponent(event->location());
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      multi_window_resize_controller_.Show(target, component,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           event->location());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_ENTERED:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_CAPTURE_CHANGED:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_EXITED:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_PRESSED: {
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      wm::WindowState* target_state = wm::GetWindowState(target);
530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (event->IsOnlyLeftMouseButton()) {
550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        if (event->flags() & ui::EF_IS_DOUBLE_CLICK) {
560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          int component = target->delegate()->
570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              GetNonClientComponent(event->location());
580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          if (component == HTCAPTION &&
590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              component == click_component_) {
600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction(
610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                ash::UMA_TOGGLE_MAXIMIZE_CAPTION_CLICK);
620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            const wm::WMEvent wm_event(wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION);
630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            target_state->OnWMEvent(&wm_event);
640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            event->StopPropagation();
650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          }
660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          // WindowEventHandler can receive each event up to two times. Once a
670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          // double-click has been received clear the target. Otherwise a
680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          // duplicate of the event will be checking target history against
690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          // itself.
700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          click_component_ = HTNOWHERE;
710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        }
720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      } else {
730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        click_component_ = HTNOWHERE;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      multi_window_resize_controller_.Hide();
7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      HandleVerticalResizeDoubleClick(target_state, event);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WorkspaceEventHandler::OnGestureEvent(ui::GestureEvent* event) {
860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (event->handled() || event->type() != ui::ET_GESTURE_TAP)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aura::Window* target = static_cast<aura::Window*>(event->target());
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int previous_target_component = click_component_;
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  click_component_ = target->delegate()->
920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetNonClientComponent(event->location());
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (click_component_ != HTCAPTION)
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (event->details().tap_count() != 2) {
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Note: TouchUMA::GESTURE_FRAMEVIEW_TAP is counted twice for each tap.
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    TouchUMA::GetInstance()->
1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        RecordGestureAction(TouchUMA::GESTURE_FRAMEVIEW_TAP);
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (click_component_ == previous_target_component) {
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction(
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        ash::UMA_TOGGLE_MAXIMIZE_CAPTION_GESTURE);
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Note: TouchUMA::GESTURE_FRAMEVIEW_TAP is counted twice each time
1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // TouchUMA::GESTURE_MAXIMIZE_DOUBLETAP is counted once.
1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    TouchUMA::GetInstance()->RecordGestureAction(
1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        TouchUMA::GESTURE_MAXIMIZE_DOUBLETAP);
1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const wm::WMEvent wm_event(wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION);
1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    wm::GetWindowState(target)->OnWMEvent(&wm_event);
1130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    event->StopPropagation();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  click_component_ = HTNOWHERE;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WorkspaceEventHandler::HandleVerticalResizeDoubleClick(
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    wm::WindowState* target_state,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::MouseEvent* event) {
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  aura::Window* target = target_state->window();
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (event->flags() & ui::EF_IS_DOUBLE_CLICK) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int component =
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        target->delegate()->GetNonClientComponent(event->location());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (component == HTBOTTOM || component == HTTOP) {
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Shell::GetInstance()->metrics()->RecordUserMetricsAction(
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          UMA_TOGGLE_SINGLE_AXIS_MAXIMIZE_BORDER_CLICK);
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const wm::WMEvent wm_event(wm::WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE);
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      target_state->OnWMEvent(&wm_event);
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event->StopPropagation();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (component == HTLEFT || component == HTRIGHT) {
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Shell::GetInstance()->metrics()->RecordUserMetricsAction(
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          UMA_TOGGLE_SINGLE_AXIS_MAXIMIZE_BORDER_CLICK);
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const wm::WMEvent wm_event(wm::WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE);
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      target_state->OnWMEvent(&wm_event);
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      event->StopPropagation();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
142