Home | History | Annotate | Download | only in desktop_aura
      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/views/widget/desktop_aura/x11_topmost_window_finder.h"
      6 
      7 #include <X11/Xutil.h>
      8 
      9 #include "ui/aura/client/screen_position_client.h"
     10 #include "ui/aura/window.h"
     11 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
     12 
     13 namespace views {
     14 
     15 X11TopmostWindowFinder::X11TopmostWindowFinder() : toplevel_(None) {
     16 }
     17 
     18 X11TopmostWindowFinder::~X11TopmostWindowFinder() {
     19 }
     20 
     21 aura::Window* X11TopmostWindowFinder::FindLocalProcessWindowAt(
     22     const gfx::Point& screen_loc,
     23     const std::set<aura::Window*>& ignore) {
     24   screen_loc_ = screen_loc;
     25   ignore_ = ignore;
     26 
     27   std::vector<aura::Window*> local_process_windows =
     28       DesktopWindowTreeHostX11::GetAllOpenWindows();
     29   bool found_local_process_window = false;
     30   for (size_t i = 0; i < local_process_windows.size(); ++i) {
     31     if (ShouldStopIteratingAtLocalProcessWindow(local_process_windows[i])) {
     32       found_local_process_window = true;
     33       break;
     34     }
     35   }
     36   if (!found_local_process_window)
     37     return NULL;
     38 
     39   ui::EnumerateTopLevelWindows(this);
     40   return DesktopWindowTreeHostX11::GetContentWindowForXID(toplevel_);
     41 }
     42 
     43 XID X11TopmostWindowFinder::FindWindowAt(const gfx::Point& screen_loc) {
     44   screen_loc_ = screen_loc;
     45   ui::EnumerateTopLevelWindows(this);
     46   return toplevel_;
     47 }
     48 
     49 bool X11TopmostWindowFinder::ShouldStopIterating(XID xid) {
     50   if (!ui::IsWindowVisible(xid))
     51     return false;
     52 
     53   aura::Window* window =
     54       views::DesktopWindowTreeHostX11::GetContentWindowForXID(xid);
     55   if (window) {
     56     if (ShouldStopIteratingAtLocalProcessWindow(window)) {
     57       toplevel_ = xid;
     58       return true;
     59     }
     60     return false;
     61   }
     62 
     63   if (ui::WindowContainsPoint(xid, screen_loc_)) {
     64     toplevel_ = xid;
     65     return true;
     66   }
     67   return false;
     68 }
     69 
     70 bool X11TopmostWindowFinder::ShouldStopIteratingAtLocalProcessWindow(
     71     aura::Window* window) {
     72   if (ignore_.find(window) != ignore_.end())
     73     return false;
     74 
     75   // Currently |window|->IsVisible() always returns true.
     76   // TODO(pkotwicz): Fix this. crbug.com/353038
     77   if (!window->IsVisible())
     78     return false;
     79 
     80   DesktopWindowTreeHostX11* host =
     81       DesktopWindowTreeHostX11::GetHostForXID(
     82           window->GetHost()->GetAcceleratedWidget());
     83   if (!host->GetX11RootWindowOuterBounds().Contains(screen_loc_))
     84     return false;
     85 
     86   ::Region shape = host->GetWindowShape();
     87   if (!shape)
     88     return true;
     89 
     90   aura::client::ScreenPositionClient* screen_position_client =
     91       aura::client::GetScreenPositionClient(window->GetRootWindow());
     92   gfx::Point window_loc(screen_loc_);
     93   screen_position_client->ConvertPointFromScreen(window, &window_loc);
     94   return XPointInRegion(shape, window_loc.x(), window_loc.y()) == True;
     95 }
     96 
     97 }  // namespace views
     98