Home | History | Annotate | Download | only in views
      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 "chrome/browser/ui/views/javascript_app_modal_event_blocker_x11.h"
      6 
      7 #include "chrome/browser/ui/views/frame/browser_view.h"
      8 #include "ui/aura/env.h"
      9 #include "ui/aura/window.h"
     10 #include "ui/events/event.h"
     11 #include "ui/wm/core/window_animations.h"
     12 #include "ui/wm/core/window_util.h"
     13 
     14 namespace {
     15 
     16 // Returns the toplevel window for the deepest transient ancestor of |window|.
     17 aura::Window* GetTopmostTransientParent(aura::Window* window) {
     18   aura::Window* topmost = wm::GetToplevelWindow(window);
     19   while (topmost && wm::GetTransientParent(topmost))
     20     topmost = wm::GetToplevelWindow(wm::GetTransientParent(topmost));
     21   return topmost;
     22 }
     23 
     24 }  // namespace
     25 
     26 JavascriptAppModalEventBlockerX11::JavascriptAppModalEventBlockerX11(
     27     aura::Window* modal_window)
     28     : modal_window_(modal_window),
     29       browser_view_with_modal_dialog_(NULL) {
     30   aura::Window* topmost_transient_parent =
     31       GetTopmostTransientParent(modal_window);
     32   browser_view_with_modal_dialog_ =
     33       BrowserView::GetBrowserViewForNativeWindow(topmost_transient_parent);
     34   // |browser_view_with_modal_dialog_| is NULL if the dialog was opened by an
     35   // extension background page.
     36 
     37   aura::Env::GetInstance()->PrependPreTargetHandler(this);
     38 
     39   // WindowModalityController will cancel touches as appropriate.
     40 }
     41 
     42 JavascriptAppModalEventBlockerX11::~JavascriptAppModalEventBlockerX11() {
     43   aura::Env::GetInstance()->RemovePreTargetHandler(this);
     44 }
     45 
     46 bool JavascriptAppModalEventBlockerX11::ShouldStopPropagationTo(
     47     ui::EventTarget* target) {
     48   // Stop propagation if:
     49   // -|target| is a browser window or a transient child of a browser window.
     50   // -|target| is not the browser window which hosts |modal_window_| and not
     51   //  a transient child of that browser window.
     52   // WindowModalityController will stop the transient parent from handling the
     53   // event if the user clicks the modal window's transient parent (as opposed to
     54   // clicking the modal window itself).
     55   aura::Window* window =
     56       GetTopmostTransientParent(static_cast<aura::Window*>(target));
     57   if (!window)
     58     return false;
     59   BrowserView* browser_view =
     60       BrowserView::GetBrowserViewForNativeWindow(window);
     61   return browser_view && browser_view != browser_view_with_modal_dialog_;
     62 }
     63 
     64 void JavascriptAppModalEventBlockerX11::OnKeyEvent(ui::KeyEvent* event) {
     65   if (ShouldStopPropagationTo(event->target()))
     66     event->StopPropagation();
     67 }
     68 
     69 void JavascriptAppModalEventBlockerX11::OnMouseEvent(ui::MouseEvent* event) {
     70   if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED &&
     71       ShouldStopPropagationTo(event->target())) {
     72     if (event->type() == ui::ET_MOUSE_PRESSED)
     73       wm::AnimateWindow(modal_window_, wm::WINDOW_ANIMATION_TYPE_BOUNCE);
     74     event->StopPropagation();
     75   }
     76 }
     77 
     78 void JavascriptAppModalEventBlockerX11::OnScrollEvent(ui::ScrollEvent* event) {
     79   if (ShouldStopPropagationTo(event->target()))
     80     event->StopPropagation();
     81 }
     82 
     83 void JavascriptAppModalEventBlockerX11::OnTouchEvent(ui::TouchEvent* event) {
     84   if (event->type() != ui::ET_TOUCH_CANCELLED &&
     85       ShouldStopPropagationTo(event->target())) {
     86     if (event->type() == ui::ET_TOUCH_PRESSED)
     87       wm::AnimateWindow(modal_window_, wm::WINDOW_ANIMATION_TYPE_BOUNCE);
     88     event->StopPropagation();
     89   }
     90 }
     91