Home | History | Annotate | Download | only in aura
      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 "ui/aura/root_window_host_x11.h"
      6 
      7 #include <strings.h>
      8 #include <X11/cursorfont.h>
      9 #include <X11/extensions/Xfixes.h>
     10 #include <X11/extensions/XInput2.h>
     11 #include <X11/extensions/Xrandr.h>
     12 #include <X11/Xatom.h>
     13 #include <X11/Xcursor/Xcursor.h>
     14 #include <X11/Xlib.h>
     15 
     16 #include <algorithm>
     17 #include <limits>
     18 #include <string>
     19 
     20 #include "base/command_line.h"
     21 #include "base/debug/trace_event.h"
     22 #include "base/message_loop/message_loop.h"
     23 #include "base/message_loop/message_pump_aurax11.h"
     24 #include "base/stl_util.h"
     25 #include "base/strings/string_number_conversions.h"
     26 #include "base/strings/string_util.h"
     27 #include "base/strings/stringprintf.h"
     28 #include "third_party/skia/include/core/SkBitmap.h"
     29 #include "third_party/skia/include/core/SkCanvas.h"
     30 #include "third_party/skia/include/core/SkPostConfig.h"
     31 #include "ui/aura/client/capture_client.h"
     32 #include "ui/aura/client/cursor_client.h"
     33 #include "ui/aura/client/screen_position_client.h"
     34 #include "ui/aura/client/user_action_client.h"
     35 #include "ui/aura/env.h"
     36 #include "ui/aura/root_window.h"
     37 #include "ui/base/cursor/cursor.h"
     38 #include "ui/base/events/event.h"
     39 #include "ui/base/events/event_utils.h"
     40 #include "ui/base/keycodes/keyboard_codes.h"
     41 #include "ui/base/touch/touch_factory_x11.h"
     42 #include "ui/base/ui_base_switches.h"
     43 #include "ui/base/view_prop.h"
     44 #include "ui/base/x/device_list_cache_x.h"
     45 #include "ui/base/x/x11_util.h"
     46 #include "ui/compositor/dip_util.h"
     47 #include "ui/compositor/layer.h"
     48 #include "ui/gfx/codec/png_codec.h"
     49 #include "ui/gfx/screen.h"
     50 
     51 #if defined(OS_CHROMEOS)
     52 #include "base/chromeos/chromeos_version.h"
     53 #endif
     54 
     55 using std::max;
     56 using std::min;
     57 
     58 namespace aura {
     59 
     60 namespace {
     61 
     62 // Standard Linux mouse buttons for going back and forward.
     63 const int kBackMouseButton = 8;
     64 const int kForwardMouseButton = 9;
     65 
     66 const char* kAtomsToCache[] = {
     67   "WM_DELETE_WINDOW",
     68   "_NET_WM_PING",
     69   "_NET_WM_PID",
     70   "WM_S0",
     71 #if defined(OS_CHROMEOS)
     72   "Tap Paused",  // Defined in the gestures library.
     73 #endif
     74   NULL
     75 };
     76 
     77 ::Window FindEventTarget(const base::NativeEvent& xev) {
     78   ::Window target = xev->xany.window;
     79   if (xev->type == GenericEvent)
     80     target = static_cast<XIDeviceEvent*>(xev->xcookie.data)->event;
     81   return target;
     82 }
     83 
     84 #if defined(USE_XI2_MT)
     85 bool IsSideBezelsEnabled() {
     86   static bool side_bezels_enabled =
     87       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
     88           switches::kTouchSideBezels) == "1";
     89   return side_bezels_enabled;
     90 }
     91 #endif
     92 
     93 void SelectEventsForRootWindow() {
     94   Display* display = ui::GetXDisplay();
     95   ::Window root_window = ui::GetX11RootWindow();
     96 
     97   // Receive resize events for the root-window so |x_root_bounds_| can be
     98   // updated.
     99   XWindowAttributes attr;
    100   XGetWindowAttributes(display, root_window, &attr);
    101   if (!(attr.your_event_mask & StructureNotifyMask)) {
    102     XSelectInput(display, root_window,
    103                  StructureNotifyMask | attr.your_event_mask);
    104   }
    105 
    106   if (!base::MessagePumpForUI::HasXInput2())
    107     return;
    108 
    109   unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {};
    110   memset(mask, 0, sizeof(mask));
    111 
    112   XISetMask(mask, XI_HierarchyChanged);
    113   XISetMask(mask, XI_KeyPress);
    114   XISetMask(mask, XI_KeyRelease);
    115 
    116   XIEventMask evmask;
    117   evmask.deviceid = XIAllDevices;
    118   evmask.mask_len = sizeof(mask);
    119   evmask.mask = mask;
    120   XISelectEvents(display, root_window, &evmask, 1);
    121 
    122   // Selecting for touch events seems to fail on some cases (e.g. when logging
    123   // in incognito). So select for non-touch events first, and then select for
    124   // touch-events (but keep the other events in the mask, i.e. do not memset
    125   // |mask| back to 0).
    126   // TODO(sad): Figure out why this happens. http://crbug.com/153976
    127 #if defined(USE_XI2_MT)
    128   XISetMask(mask, XI_TouchBegin);
    129   XISetMask(mask, XI_TouchUpdate);
    130   XISetMask(mask, XI_TouchEnd);
    131   XISelectEvents(display, root_window, &evmask, 1);
    132 #endif
    133 }
    134 
    135 // We emulate Windows' WM_KEYDOWN and WM_CHAR messages.  WM_CHAR events are only
    136 // generated for certain keys; see
    137 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx.  Per
    138 // discussion on http://crbug.com/108480, char events should furthermore not be
    139 // generated for Tab, Escape, and Backspace.
    140 bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) {
    141   if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) ||
    142       (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) ||
    143       (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) {
    144     return true;
    145   }
    146 
    147   switch (keycode) {
    148     case ui::VKEY_RETURN:
    149     case ui::VKEY_SPACE:
    150     // In addition to the keys listed at MSDN, we include other
    151     // graphic-character and numpad keys.
    152     case ui::VKEY_MULTIPLY:
    153     case ui::VKEY_ADD:
    154     case ui::VKEY_SUBTRACT:
    155     case ui::VKEY_DECIMAL:
    156     case ui::VKEY_DIVIDE:
    157     case ui::VKEY_OEM_1:
    158     case ui::VKEY_OEM_2:
    159     case ui::VKEY_OEM_3:
    160     case ui::VKEY_OEM_4:
    161     case ui::VKEY_OEM_5:
    162     case ui::VKEY_OEM_6:
    163     case ui::VKEY_OEM_7:
    164     case ui::VKEY_OEM_102:
    165     case ui::VKEY_OEM_PLUS:
    166     case ui::VKEY_OEM_COMMA:
    167     case ui::VKEY_OEM_MINUS:
    168     case ui::VKEY_OEM_PERIOD:
    169       return true;
    170     default:
    171       return false;
    172   }
    173 }
    174 
    175 bool default_override_redirect = false;
    176 
    177 }  // namespace
    178 
    179 namespace internal {
    180 
    181 // Accomplishes 2 tasks concerning touch event calibration:
    182 // 1. Being a message-pump observer,
    183 //    routes all the touch events to the X root window,
    184 //    where they can be calibrated later.
    185 // 2. Has the Calibrate method that does the actual bezel calibration,
    186 //    when invoked from X root window's event dispatcher.
    187 class TouchEventCalibrate : public base::MessagePumpObserver {
    188  public:
    189   TouchEventCalibrate()
    190     : left_(0),
    191       right_(0),
    192       top_(0),
    193       bottom_(0) {
    194     base::MessageLoopForUI::current()->AddObserver(this);
    195 #if defined(USE_XI2_MT)
    196     std::vector<std::string> parts;
    197     if (Tokenize(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
    198         switches::kTouchCalibration), ",", &parts) >= 4) {
    199       if (!base::StringToInt(parts[0], &left_))
    200         DLOG(ERROR) << "Incorrect left border calibration value passed.";
    201       if (!base::StringToInt(parts[1], &right_))
    202         DLOG(ERROR) << "Incorrect right border calibration value passed.";
    203       if (!base::StringToInt(parts[2], &top_))
    204         DLOG(ERROR) << "Incorrect top border calibration value passed.";
    205       if (!base::StringToInt(parts[3], &bottom_))
    206         DLOG(ERROR) << "Incorrect bottom border calibration value passed.";
    207     }
    208 #endif  // defined(USE_XI2_MT)
    209   }
    210 
    211   virtual ~TouchEventCalibrate() {
    212     base::MessageLoopForUI::current()->RemoveObserver(this);
    213   }
    214 
    215 #if defined(USE_XI2_MT)
    216   bool IsEventOnSideBezels(
    217       const base::NativeEvent& xev,
    218       const gfx::Rect& bounds) {
    219     if (!left_ && !right_)
    220       return false;
    221 
    222     gfx::Point location = ui::EventLocationFromNative(xev);
    223     int x = location.x();
    224     return x < left_ || x > bounds.width() - right_;
    225   }
    226 #endif  // defined(USE_XI2_MT)
    227 
    228   // Modify the location of the |event|,
    229   // expanding it from |bounds| to (|bounds| + bezels).
    230   // Required when touchscreen is bigger than screen (i.e. has bezels),
    231   // because we receive events in touchscreen coordinates,
    232   // which need to be expanded when converting to screen coordinates,
    233   // so that location on bezels will be outside of screen area.
    234   void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) {
    235 #if defined(USE_XI2_MT)
    236     int x = event->x();
    237     int y = event->y();
    238 
    239     if (!left_ && !right_ && !top_ && !bottom_)
    240       return;
    241 
    242     const int resolution_x = bounds.width();
    243     const int resolution_y = bounds.height();
    244     // The "grace area" (10% in this case) is to make it easier for the user to
    245     // navigate to the corner.
    246     const double kGraceAreaFraction = 0.1;
    247     if (left_ || right_) {
    248       // Offset the x position to the real
    249       x -= left_;
    250       // Check if we are in the grace area of the left side.
    251       // Note: We might not want to do this when the gesture is locked?
    252       if (x < 0 && x > -left_ * kGraceAreaFraction)
    253         x = 0;
    254       // Check if we are in the grace area of the right side.
    255       // Note: We might not want to do this when the gesture is locked?
    256       if (x > resolution_x - left_ &&
    257           x < resolution_x - left_ + right_ * kGraceAreaFraction)
    258         x = resolution_x - left_;
    259       // Scale the screen area back to the full resolution of the screen.
    260       x = (x * resolution_x) / (resolution_x - (right_ + left_));
    261     }
    262     if (top_ || bottom_) {
    263       // When there is a top bezel we add our border,
    264       y -= top_;
    265 
    266       // Check if we are in the grace area of the top side.
    267       // Note: We might not want to do this when the gesture is locked?
    268       if (y < 0 && y > -top_ * kGraceAreaFraction)
    269         y = 0;
    270 
    271       // Check if we are in the grace area of the bottom side.
    272       // Note: We might not want to do this when the gesture is locked?
    273       if (y > resolution_y - top_ &&
    274           y < resolution_y - top_ + bottom_ * kGraceAreaFraction)
    275         y = resolution_y - top_;
    276       // Scale the screen area back to the full resolution of the screen.
    277       y = (y * resolution_y) / (resolution_y - (bottom_ + top_));
    278     }
    279 
    280     // Set the modified coordinate back to the event.
    281     if (event->root_location() == event->location()) {
    282       // Usually those will be equal,
    283       // if not, I am not sure what the correct value should be.
    284       event->set_root_location(gfx::Point(x, y));
    285     }
    286     event->set_location(gfx::Point(x, y));
    287 #endif  // defined(USE_XI2_MT)
    288   }
    289 
    290  private:
    291   // Overridden from base::MessagePumpObserver:
    292   virtual base::EventStatus WillProcessEvent(
    293       const base::NativeEvent& event) OVERRIDE {
    294 #if defined(USE_XI2_MT)
    295     if (event->type == GenericEvent &&
    296         (event->xgeneric.evtype == XI_TouchBegin ||
    297          event->xgeneric.evtype == XI_TouchUpdate ||
    298          event->xgeneric.evtype == XI_TouchEnd)) {
    299       XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data);
    300       xievent->event = xievent->root;
    301       xievent->event_x = xievent->root_x;
    302       xievent->event_y = xievent->root_y;
    303     }
    304 #endif  // defined(USE_XI2_MT)
    305     return base::EVENT_CONTINUE;
    306   }
    307 
    308   virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
    309   }
    310 
    311   // The difference in screen's native resolution pixels between
    312   // the border of the touchscreen and the border of the screen,
    313   // aka bezel sizes.
    314   int left_;
    315   int right_;
    316   int top_;
    317   int bottom_;
    318 
    319   DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate);
    320 };
    321 
    322 }  // namespace internal
    323 
    324 ////////////////////////////////////////////////////////////////////////////////
    325 // RootWindowHostX11::MouseMoveFilter filters out the move events that
    326 // jump back and forth between two points. This happens when sub pixel mouse
    327 // move is enabled and mouse move events could be jumping between two neighbor
    328 // pixels, e.g. move(0,0), move(1,0), move(0,0), move(1,0) and on and on.
    329 // The filtering is done by keeping track of the last two event locations and
    330 // provides a Filter method to find out whether a mouse event is in a different
    331 // location and should be processed.
    332 
    333 class RootWindowHostX11::MouseMoveFilter {
    334  public:
    335   MouseMoveFilter() : insert_index_(0) {
    336     for (size_t i = 0; i < kMaxEvents; ++i) {
    337       const int int_max = std::numeric_limits<int>::max();
    338       recent_locations_[i] = gfx::Point(int_max, int_max);
    339     }
    340   }
    341   ~MouseMoveFilter() {}
    342 
    343   // Returns true if |event| is known and should be ignored.
    344   bool Filter(const base::NativeEvent& event) {
    345     const gfx::Point& location = ui::EventLocationFromNative(event);
    346     for (size_t i = 0; i < kMaxEvents; ++i) {
    347       if (location == recent_locations_[i])
    348         return true;
    349     }
    350 
    351     recent_locations_[insert_index_] = location;
    352     insert_index_ = (insert_index_ + 1) % kMaxEvents;
    353     return false;
    354   }
    355 
    356  private:
    357   static const size_t kMaxEvents = 2;
    358 
    359   gfx::Point recent_locations_[kMaxEvents];
    360   size_t insert_index_;
    361 
    362   DISALLOW_COPY_AND_ASSIGN(MouseMoveFilter);
    363 };
    364 
    365 ////////////////////////////////////////////////////////////////////////////////
    366 // RootWindowHostX11
    367 
    368 RootWindowHostX11::RootWindowHostX11(const gfx::Rect& bounds)
    369     : delegate_(NULL),
    370       xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()),
    371       xwindow_(0),
    372       x_root_window_(DefaultRootWindow(xdisplay_)),
    373       current_cursor_(ui::kCursorNull),
    374       window_mapped_(false),
    375       bounds_(bounds),
    376       is_internal_display_(false),
    377       focus_when_shown_(false),
    378       touch_calibrate_(new internal::TouchEventCalibrate),
    379       mouse_move_filter_(new MouseMoveFilter),
    380       atom_cache_(xdisplay_, kAtomsToCache) {
    381   XSetWindowAttributes swa;
    382   memset(&swa, 0, sizeof(swa));
    383   swa.background_pixmap = None;
    384   swa.override_redirect = default_override_redirect;
    385   xwindow_ = XCreateWindow(
    386       xdisplay_, x_root_window_,
    387       bounds.x(), bounds.y(), bounds.width(), bounds.height(),
    388       0,               // border width
    389       CopyFromParent,  // depth
    390       InputOutput,
    391       CopyFromParent,  // visual
    392       CWBackPixmap | CWOverrideRedirect,
    393       &swa);
    394   base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_);
    395   base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this);
    396 
    397   long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
    398                     KeyPressMask | KeyReleaseMask |
    399                     EnterWindowMask | LeaveWindowMask |
    400                     ExposureMask | VisibilityChangeMask |
    401                     StructureNotifyMask | PropertyChangeMask |
    402                     PointerMotionMask;
    403   XSelectInput(xdisplay_, xwindow_, event_mask);
    404   XFlush(xdisplay_);
    405 
    406   if (base::MessagePumpForUI::HasXInput2())
    407     ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
    408 
    409   SelectEventsForRootWindow();
    410 
    411   // Get the initial size of the X root window.
    412   XWindowAttributes attrs;
    413   XGetWindowAttributes(xdisplay_, x_root_window_, &attrs);
    414   x_root_bounds_.SetRect(attrs.x, attrs.y, attrs.width, attrs.height);
    415 
    416   // TODO(erg): We currently only request window deletion events. We also
    417   // should listen for activation events and anything else that GTK+ listens
    418   // for, and do something useful.
    419   ::Atom protocols[2];
    420   protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
    421   protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
    422   XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
    423 
    424   // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
    425   // the desktop environment.
    426   XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
    427 
    428   // Likewise, the X server needs to know this window's pid so it knows which
    429   // program to kill if the window hangs.
    430   pid_t pid = getpid();
    431   XChangeProperty(xdisplay_,
    432                   xwindow_,
    433                   atom_cache_.GetAtom("_NET_WM_PID"),
    434                   XA_CARDINAL,
    435                   32,
    436                   PropModeReplace,
    437                   reinterpret_cast<unsigned char*>(&pid), 1);
    438 
    439   XRRSelectInput(xdisplay_, x_root_window_,
    440                  RRScreenChangeNotifyMask | RROutputChangeNotifyMask);
    441   Env::GetInstance()->AddObserver(this);
    442 }
    443 
    444 RootWindowHostX11::~RootWindowHostX11() {
    445   Env::GetInstance()->RemoveObserver(this);
    446   base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this);
    447   base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
    448 
    449   UnConfineCursor();
    450 
    451   XDestroyWindow(xdisplay_, xwindow_);
    452 }
    453 
    454 bool RootWindowHostX11::Dispatch(const base::NativeEvent& event) {
    455   XEvent* xev = event;
    456 
    457   if (FindEventTarget(event) == x_root_window_)
    458     return DispatchEventForRootWindow(event);
    459 
    460   switch (xev->type) {
    461     case EnterNotify: {
    462       ui::MouseEvent mouse_event(xev);
    463       // EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is not
    464       // real mouse move event.
    465       mouse_event.set_flags(mouse_event.flags() | ui::EF_IS_SYNTHESIZED);
    466       TranslateAndDispatchMouseEvent(&mouse_event);
    467       break;
    468     }
    469     case LeaveNotify: {
    470       ui::MouseEvent mouse_event(xev);
    471       TranslateAndDispatchMouseEvent(&mouse_event);
    472       break;
    473     }
    474     case Expose: {
    475       gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y,
    476                             xev->xexpose.width, xev->xexpose.height);
    477       delegate_->AsRootWindow()->ScheduleRedrawRect(damage_rect);
    478       break;
    479     }
    480     case KeyPress: {
    481       ui::KeyEvent keydown_event(xev, false);
    482       delegate_->OnHostKeyEvent(&keydown_event);
    483       break;
    484     }
    485     case KeyRelease: {
    486       ui::KeyEvent keyup_event(xev, false);
    487       delegate_->OnHostKeyEvent(&keyup_event);
    488       break;
    489     }
    490     case ButtonPress: {
    491       if (static_cast<int>(xev->xbutton.button) == kBackMouseButton ||
    492           static_cast<int>(xev->xbutton.button) == kForwardMouseButton) {
    493         client::UserActionClient* gesture_client =
    494             client::GetUserActionClient(delegate_->AsRootWindow());
    495         if (gesture_client) {
    496           gesture_client->OnUserAction(
    497               static_cast<int>(xev->xbutton.button) == kBackMouseButton ?
    498               client::UserActionClient::BACK :
    499               client::UserActionClient::FORWARD);
    500         }
    501         break;
    502       }
    503     }  // fallthrough
    504     case ButtonRelease: {
    505       ui::MouseEvent mouseev(xev);
    506       TranslateAndDispatchMouseEvent(&mouseev);
    507       break;
    508     }
    509     case FocusOut:
    510       if (xev->xfocus.mode != NotifyGrab)
    511         delegate_->OnHostLostWindowCapture();
    512       break;
    513     case ConfigureNotify: {
    514       DCHECK_EQ(xwindow_, xev->xconfigure.event);
    515       DCHECK_EQ(xwindow_, xev->xconfigure.window);
    516       // It's possible that the X window may be resized by some other means
    517       // than from within aura (e.g. the X window manager can change the
    518       // size). Make sure the root window size is maintained properly.
    519       gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
    520           xev->xconfigure.width, xev->xconfigure.height);
    521       bool size_changed = bounds_.size() != bounds.size();
    522       bool origin_changed = bounds_.origin() != bounds.origin();
    523       bounds_ = bounds;
    524       UpdateIsInternalDisplay();
    525       // Always update barrier and mouse location because |bounds_| might
    526       // have already been updated in |SetBounds|.
    527       if (pointer_barriers_) {
    528         UnConfineCursor();
    529         ConfineCursorToRootWindow();
    530       }
    531       if (size_changed)
    532         delegate_->OnHostResized(bounds.size());
    533       if (origin_changed)
    534         delegate_->OnHostMoved(bounds_.origin());
    535       break;
    536     }
    537     case GenericEvent:
    538       DispatchXI2Event(event);
    539       break;
    540     case MapNotify: {
    541       // If there's no window manager running, we need to assign the X input
    542       // focus to our host window.
    543       if (!IsWindowManagerPresent() && focus_when_shown_)
    544         XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime);
    545       break;
    546     }
    547     case ClientMessage: {
    548       Atom message_type = static_cast<Atom>(xev->xclient.data.l[0]);
    549       if (message_type == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
    550         // We have received a close message from the window manager.
    551         delegate_->AsRootWindow()->OnRootWindowHostCloseRequested();
    552       } else if (message_type == atom_cache_.GetAtom("_NET_WM_PING")) {
    553         XEvent reply_event = *xev;
    554         reply_event.xclient.window = x_root_window_;
    555 
    556         XSendEvent(xdisplay_,
    557                    reply_event.xclient.window,
    558                    False,
    559                    SubstructureRedirectMask | SubstructureNotifyMask,
    560                    &reply_event);
    561       }
    562       break;
    563     }
    564     case MappingNotify: {
    565       switch (xev->xmapping.request) {
    566         case MappingModifier:
    567         case MappingKeyboard:
    568           XRefreshKeyboardMapping(&xev->xmapping);
    569           delegate_->AsRootWindow()->OnKeyboardMappingChanged();
    570           break;
    571         case MappingPointer:
    572           ui::UpdateButtonMap();
    573           break;
    574         default:
    575           NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request;
    576           break;
    577       }
    578       break;
    579     }
    580     case MotionNotify: {
    581       // Discard all but the most recent motion event that targets the same
    582       // window with unchanged state.
    583       XEvent last_event;
    584       while (XPending(xev->xany.display)) {
    585         XEvent next_event;
    586         XPeekEvent(xev->xany.display, &next_event);
    587         if (next_event.type == MotionNotify &&
    588             next_event.xmotion.window == xev->xmotion.window &&
    589             next_event.xmotion.subwindow == xev->xmotion.subwindow &&
    590             next_event.xmotion.state == xev->xmotion.state) {
    591           XNextEvent(xev->xany.display, &last_event);
    592           xev = &last_event;
    593         } else {
    594           break;
    595         }
    596       }
    597 
    598       ui::MouseEvent mouseev(xev);
    599       TranslateAndDispatchMouseEvent(&mouseev);
    600       break;
    601     }
    602   }
    603   return true;
    604 }
    605 
    606 void RootWindowHostX11::SetDelegate(RootWindowHostDelegate* delegate) {
    607   delegate_ = delegate;
    608 }
    609 
    610 RootWindow* RootWindowHostX11::GetRootWindow() {
    611   return delegate_->AsRootWindow();
    612 }
    613 
    614 gfx::AcceleratedWidget RootWindowHostX11::GetAcceleratedWidget() {
    615   return xwindow_;
    616 }
    617 
    618 void RootWindowHostX11::Show() {
    619   if (!window_mapped_) {
    620     // Before we map the window, set size hints. Otherwise, some window managers
    621     // will ignore toplevel XMoveWindow commands.
    622     XSizeHints size_hints;
    623     size_hints.flags = PPosition | PWinGravity;
    624     size_hints.x = bounds_.x();
    625     size_hints.y = bounds_.y();
    626     // Set StaticGravity so that the window position is not affected by the
    627     // frame width when running with window manager.
    628     size_hints.win_gravity = StaticGravity;
    629     XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
    630 
    631     XMapWindow(xdisplay_, xwindow_);
    632 
    633     // We now block until our window is mapped. Some X11 APIs will crash and
    634     // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
    635     // asynchronous.
    636     base::MessagePumpAuraX11::Current()->BlockUntilWindowMapped(xwindow_);
    637     window_mapped_ = true;
    638   }
    639 }
    640 
    641 void RootWindowHostX11::Hide() {
    642   if (window_mapped_) {
    643     XWithdrawWindow(xdisplay_, xwindow_, 0);
    644     window_mapped_ = false;
    645   }
    646 }
    647 
    648 void RootWindowHostX11::ToggleFullScreen() {
    649   NOTIMPLEMENTED();
    650 }
    651 
    652 gfx::Rect RootWindowHostX11::GetBounds() const {
    653   return bounds_;
    654 }
    655 
    656 void RootWindowHostX11::SetBounds(const gfx::Rect& bounds) {
    657   // Even if the host window's size doesn't change, aura's root window
    658   // size, which is in DIP, changes when the scale changes.
    659   float current_scale = delegate_->GetDeviceScaleFactor();
    660   float new_scale = gfx::Screen::GetScreenFor(delegate_->AsRootWindow())->
    661       GetDisplayNearestWindow(delegate_->AsRootWindow()).device_scale_factor();
    662   bool origin_changed = bounds_.origin() != bounds.origin();
    663   bool size_changed = bounds_.size() != bounds.size();
    664   XWindowChanges changes = {0};
    665   unsigned value_mask = 0;
    666 
    667   if (size_changed) {
    668     changes.width = bounds.width();
    669     changes.height = bounds.height();
    670     value_mask = CWHeight | CWWidth;
    671   }
    672 
    673   if (origin_changed) {
    674     changes.x = bounds.x();
    675     changes.y = bounds.y();
    676     value_mask |= CWX | CWY;
    677   }
    678   if (value_mask)
    679     XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
    680 
    681   // Assume that the resize will go through as requested, which should be the
    682   // case if we're running without a window manager.  If there's a window
    683   // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
    684   // (possibly synthetic) ConfigureNotify about the actual size and correct
    685   // |bounds_| later.
    686   bounds_ = bounds;
    687   UpdateIsInternalDisplay();
    688   if (origin_changed)
    689     delegate_->OnHostMoved(bounds.origin());
    690   if (size_changed || current_scale != new_scale) {
    691     delegate_->OnHostResized(bounds.size());
    692   } else {
    693     delegate_->AsRootWindow()->SchedulePaintInRect(
    694         delegate_->AsRootWindow()->bounds());
    695   }
    696 }
    697 
    698 gfx::Insets RootWindowHostX11::GetInsets() const {
    699   return insets_;
    700 }
    701 
    702 void RootWindowHostX11::SetInsets(const gfx::Insets& insets) {
    703   insets_ = insets;
    704   if (pointer_barriers_) {
    705     UnConfineCursor();
    706     ConfineCursorToRootWindow();
    707   }
    708 }
    709 
    710 gfx::Point RootWindowHostX11::GetLocationOnNativeScreen() const {
    711   return bounds_.origin();
    712 }
    713 
    714 void RootWindowHostX11::SetCapture() {
    715   // TODO(oshima): Grab x input.
    716 }
    717 
    718 void RootWindowHostX11::ReleaseCapture() {
    719   // TODO(oshima): Release x input.
    720 }
    721 
    722 void RootWindowHostX11::SetCursor(gfx::NativeCursor cursor) {
    723   if (cursor == current_cursor_)
    724     return;
    725   current_cursor_ = cursor;
    726   SetCursorInternal(cursor);
    727 }
    728 
    729 bool RootWindowHostX11::QueryMouseLocation(gfx::Point* location_return) {
    730   client::CursorClient* cursor_client =
    731       client::GetCursorClient(GetRootWindow());
    732   if (cursor_client && !cursor_client->IsMouseEventsEnabled()) {
    733     *location_return = gfx::Point(0, 0);
    734     return false;
    735   }
    736 
    737   ::Window root_return, child_return;
    738   int root_x_return, root_y_return, win_x_return, win_y_return;
    739   unsigned int mask_return;
    740   XQueryPointer(xdisplay_,
    741                 xwindow_,
    742                 &root_return,
    743                 &child_return,
    744                 &root_x_return, &root_y_return,
    745                 &win_x_return, &win_y_return,
    746                 &mask_return);
    747   *location_return = gfx::Point(max(0, min(bounds_.width(), win_x_return)),
    748                                 max(0, min(bounds_.height(), win_y_return)));
    749   return (win_x_return >= 0 && win_x_return < bounds_.width() &&
    750           win_y_return >= 0 && win_y_return < bounds_.height());
    751 }
    752 
    753 bool RootWindowHostX11::ConfineCursorToRootWindow() {
    754 #if XFIXES_MAJOR >= 5
    755   DCHECK(!pointer_barriers_.get());
    756   if (pointer_barriers_)
    757     return false;
    758   pointer_barriers_.reset(new XID[4]);
    759   gfx::Rect bounds(bounds_);
    760   bounds.Inset(insets_);
    761   // Horizontal, top barriers.
    762   pointer_barriers_[0] = XFixesCreatePointerBarrier(
    763       xdisplay_, x_root_window_,
    764       bounds.x(), bounds.y(), bounds.right(), bounds.y(),
    765       BarrierPositiveY,
    766       0, XIAllDevices);
    767   // Horizontal, bottom barriers.
    768   pointer_barriers_[1] = XFixesCreatePointerBarrier(
    769       xdisplay_, x_root_window_,
    770       bounds.x(), bounds.bottom(), bounds.right(),  bounds.bottom(),
    771       BarrierNegativeY,
    772       0, XIAllDevices);
    773   // Vertical, left  barriers.
    774   pointer_barriers_[2] = XFixesCreatePointerBarrier(
    775       xdisplay_, x_root_window_,
    776       bounds.x(), bounds.y(), bounds.x(), bounds.bottom(),
    777       BarrierPositiveX,
    778       0, XIAllDevices);
    779   // Vertical, right barriers.
    780   pointer_barriers_[3] = XFixesCreatePointerBarrier(
    781       xdisplay_, x_root_window_,
    782       bounds.right(), bounds.y(), bounds.right(), bounds.bottom(),
    783       BarrierNegativeX,
    784       0, XIAllDevices);
    785 #endif
    786   return true;
    787 }
    788 
    789 void RootWindowHostX11::UnConfineCursor() {
    790 #if XFIXES_MAJOR >= 5
    791   if (pointer_barriers_) {
    792     XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[0]);
    793     XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[1]);
    794     XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[2]);
    795     XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[3]);
    796     pointer_barriers_.reset();
    797   }
    798 #endif
    799 }
    800 
    801 void RootWindowHostX11::OnCursorVisibilityChanged(bool show) {
    802   SetCrOSTapPaused(!show);
    803 }
    804 
    805 void RootWindowHostX11::MoveCursorTo(const gfx::Point& location) {
    806   XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0,
    807                bounds_.x() + location.x(),
    808                bounds_.y() + location.y());
    809 }
    810 
    811 void RootWindowHostX11::SetFocusWhenShown(bool focus_when_shown) {
    812   static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME";
    813   focus_when_shown_ = focus_when_shown;
    814   if (IsWindowManagerPresent() && !focus_when_shown_) {
    815     ui::SetIntProperty(xwindow_,
    816                        k_NET_WM_USER_TIME,
    817                        k_NET_WM_USER_TIME,
    818                        0);
    819   }
    820 }
    821 
    822 bool RootWindowHostX11::CopyAreaToSkCanvas(const gfx::Rect& source_bounds,
    823                                              const gfx::Point& dest_offset,
    824                                              SkCanvas* canvas) {
    825   ui::XScopedImage scoped_image(
    826       XGetImage(xdisplay_, xwindow_,
    827                 source_bounds.x(), source_bounds.y(),
    828                 source_bounds.width(), source_bounds.height(),
    829                 AllPlanes, ZPixmap));
    830   XImage* image = scoped_image.get();
    831   if (!image) {
    832     LOG(ERROR) << "XGetImage failed";
    833     return false;
    834   }
    835 
    836   if (image->bits_per_pixel == 32) {
    837     if ((0xff << SK_R32_SHIFT) != image->red_mask ||
    838         (0xff << SK_G32_SHIFT) != image->green_mask ||
    839         (0xff << SK_B32_SHIFT) != image->blue_mask) {
    840       LOG(WARNING) << "XImage and Skia byte orders differ";
    841       return false;
    842     }
    843 
    844     // Set the alpha channel before copying to the canvas.  Otherwise, areas of
    845     // the framebuffer that were cleared by ply-image rather than being obscured
    846     // by an image during boot may end up transparent.
    847     // TODO(derat|marcheu): Remove this if/when ply-image has been updated to
    848     // set the framebuffer's alpha channel regardless of whether the device
    849     // claims to support alpha or not.
    850     for (int i = 0; i < image->width * image->height * 4; i += 4)
    851       image->data[i + 3] = 0xff;
    852 
    853     SkBitmap bitmap;
    854     bitmap.setConfig(SkBitmap::kARGB_8888_Config,
    855                      image->width, image->height,
    856                      image->bytes_per_line);
    857     bitmap.setPixels(image->data);
    858     canvas->drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), NULL);
    859   } else {
    860     NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel;
    861     return false;
    862   }
    863 
    864   return true;
    865 }
    866 
    867 void RootWindowHostX11::PostNativeEvent(
    868     const base::NativeEvent& native_event) {
    869   DCHECK(xwindow_);
    870   DCHECK(xdisplay_);
    871   XEvent xevent = *native_event;
    872   xevent.xany.display = xdisplay_;
    873   xevent.xany.window = xwindow_;
    874 
    875   switch (xevent.type) {
    876     case EnterNotify:
    877     case LeaveNotify:
    878     case MotionNotify:
    879     case KeyPress:
    880     case KeyRelease:
    881     case ButtonPress:
    882     case ButtonRelease: {
    883       // The fields used below are in the same place for all of events
    884       // above. Using xmotion from XEvent's unions to avoid repeating
    885       // the code.
    886       xevent.xmotion.root = x_root_window_;
    887       xevent.xmotion.time = CurrentTime;
    888 
    889       gfx::Point point(xevent.xmotion.x, xevent.xmotion.y);
    890       delegate_->AsRootWindow()->ConvertPointToNativeScreen(&point);
    891       xevent.xmotion.x_root = point.x();
    892       xevent.xmotion.y_root = point.y();
    893     }
    894     default:
    895       break;
    896   }
    897   XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
    898 }
    899 
    900 void RootWindowHostX11::OnDeviceScaleFactorChanged(
    901     float device_scale_factor) {
    902 }
    903 
    904 void RootWindowHostX11::PrepareForShutdown() {
    905   base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
    906 }
    907 
    908 void RootWindowHostX11::OnWindowInitialized(Window* window) {
    909 }
    910 
    911 void RootWindowHostX11::OnRootWindowInitialized(RootWindow* root_window) {
    912   // UpdateIsInternalDisplay relies on:
    913   // 1. delegate_ pointing to RootWindow - available after SetDelegate.
    914   // 2. RootWindow's kDisplayIdKey property set - available by the time
    915   //    RootWindow::Init is called.
    916   //    (set in DisplayManager::CreateRootWindowForDisplay)
    917   // Ready when NotifyRootWindowInitialized is called from RootWindow::Init.
    918   if (!delegate_ || root_window != GetRootWindow())
    919     return;
    920   UpdateIsInternalDisplay();
    921 
    922   // We have to enable Tap-to-click by default because the cursor is set to
    923   // visible in Shell::InitRootWindowController.
    924   SetCrOSTapPaused(false);
    925 }
    926 
    927 bool RootWindowHostX11::DispatchEventForRootWindow(
    928     const base::NativeEvent& event) {
    929   switch (event->type) {
    930     case ConfigureNotify:
    931       DCHECK_EQ(x_root_window_, event->xconfigure.event);
    932       x_root_bounds_.SetRect(event->xconfigure.x, event->xconfigure.y,
    933           event->xconfigure.width, event->xconfigure.height);
    934       break;
    935 
    936     case GenericEvent:
    937       DispatchXI2Event(event);
    938       break;
    939   }
    940 
    941   return true;
    942 }
    943 
    944 void RootWindowHostX11::DispatchXI2Event(const base::NativeEvent& event) {
    945   ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
    946   XEvent* xev = event;
    947   if (!factory->ShouldProcessXI2Event(xev))
    948     return;
    949 
    950   TRACE_EVENT1("input", "RootWindowHostX11::DispatchXI2Event",
    951                "event_latency_us",
    952                (ui::EventTimeForNow() - ui::EventTimeFromNative(event)).
    953                  InMicroseconds());
    954 
    955   ui::EventType type = ui::EventTypeFromNative(xev);
    956   XEvent last_event;
    957   int num_coalesced = 0;
    958 
    959   switch (type) {
    960     case ui::ET_TOUCH_MOVED:
    961     case ui::ET_TOUCH_PRESSED:
    962     case ui::ET_TOUCH_CANCELLED:
    963     case ui::ET_TOUCH_RELEASED: {
    964 #if defined(USE_XI2_MT)
    965       // Ignore events from the bezel when the side bezel flag is not explicitly
    966       // enabled.
    967       if (!IsSideBezelsEnabled() &&
    968           touch_calibrate_->IsEventOnSideBezels(xev, bounds_)) {
    969         break;
    970       }
    971 #endif  // defined(USE_XI2_MT)
    972       ui::TouchEvent touchev(xev);
    973 #if defined(OS_CHROMEOS)
    974       if (base::chromeos::IsRunningOnChromeOS()) {
    975         if (!bounds_.Contains(touchev.location()))
    976           break;
    977         // X maps the touch-surface to the size of the X root-window.
    978         // In multi-monitor setup, Coordinate Transformation Matrix
    979         // repositions the touch-surface onto part of X root-window
    980         // containing aura root-window corresponding to the touchscreen.
    981         // However, if aura root-window has non-zero origin,
    982         // we need to relocate the event into aura root-window coordinates.
    983         touchev.Relocate(bounds_.origin());
    984 #if defined(USE_XI2_MT)
    985         if (is_internal_display_)
    986           touch_calibrate_->Calibrate(&touchev, bounds_);
    987 #endif  // defined(USE_XI2_MT)
    988       }
    989 #endif  // defined(OS_CHROMEOS)
    990       delegate_->OnHostTouchEvent(&touchev);
    991       break;
    992     }
    993     case ui::ET_MOUSE_MOVED:
    994     case ui::ET_MOUSE_DRAGGED:
    995     case ui::ET_MOUSE_PRESSED:
    996     case ui::ET_MOUSE_RELEASED:
    997     case ui::ET_MOUSE_ENTERED:
    998     case ui::ET_MOUSE_EXITED: {
    999       if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
   1000         // If this is a motion event, we want to coalesce all pending motion
   1001         // events that are at the top of the queue.
   1002         num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
   1003         if (num_coalesced > 0)
   1004           xev = &last_event;
   1005 
   1006         if (mouse_move_filter_ && mouse_move_filter_->Filter(xev))
   1007           break;
   1008       } else if (type == ui::ET_MOUSE_PRESSED ||
   1009                  type == ui::ET_MOUSE_RELEASED) {
   1010         XIDeviceEvent* xievent =
   1011             static_cast<XIDeviceEvent*>(xev->xcookie.data);
   1012         int button = xievent->detail;
   1013         if (button == kBackMouseButton || button == kForwardMouseButton) {
   1014           if (type == ui::ET_MOUSE_RELEASED)
   1015             break;
   1016           client::UserActionClient* gesture_client =
   1017               client::GetUserActionClient(delegate_->AsRootWindow());
   1018           if (gesture_client) {
   1019             bool reverse_direction =
   1020                 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
   1021             gesture_client->OnUserAction(
   1022                 (button == kBackMouseButton && !reverse_direction) ||
   1023                 (button == kForwardMouseButton && reverse_direction) ?
   1024                 client::UserActionClient::BACK :
   1025                 client::UserActionClient::FORWARD);
   1026           }
   1027           break;
   1028         }
   1029       }
   1030       ui::MouseEvent mouseev(xev);
   1031       TranslateAndDispatchMouseEvent(&mouseev);
   1032       break;
   1033     }
   1034     case ui::ET_MOUSEWHEEL: {
   1035       ui::MouseWheelEvent mouseev(xev);
   1036       TranslateAndDispatchMouseEvent(&mouseev);
   1037       break;
   1038     }
   1039     case ui::ET_SCROLL_FLING_START:
   1040     case ui::ET_SCROLL_FLING_CANCEL:
   1041     case ui::ET_SCROLL: {
   1042       ui::ScrollEvent scrollev(xev);
   1043       delegate_->OnHostScrollEvent(&scrollev);
   1044       break;
   1045     }
   1046     case ui::ET_UMA_DATA:
   1047       break;
   1048     case ui::ET_UNKNOWN:
   1049       break;
   1050     default:
   1051       NOTREACHED();
   1052   }
   1053 
   1054   // If we coalesced an event we need to free its cookie.
   1055   if (num_coalesced > 0)
   1056     XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
   1057 }
   1058 
   1059 bool RootWindowHostX11::IsWindowManagerPresent() {
   1060   // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
   1061   // of WM_Sn selections (where n is a screen number).
   1062   return XGetSelectionOwner(
   1063       xdisplay_, atom_cache_.GetAtom("WM_S0")) != None;
   1064 }
   1065 
   1066 void RootWindowHostX11::SetCursorInternal(gfx::NativeCursor cursor) {
   1067   XDefineCursor(xdisplay_, xwindow_, cursor.platform());
   1068 }
   1069 
   1070 void RootWindowHostX11::TranslateAndDispatchMouseEvent(
   1071     ui::MouseEvent* event) {
   1072   RootWindow* root_window = GetRootWindow();
   1073   client::ScreenPositionClient* screen_position_client =
   1074       GetScreenPositionClient(root_window);
   1075   gfx::Rect local(bounds_.size());
   1076 
   1077   if (screen_position_client && !local.Contains(event->location())) {
   1078     gfx::Point location(event->location());
   1079     // In order to get the correct point in screen coordinates
   1080     // during passive grab, we first need to find on which host window
   1081     // the mouse is on, and find out the screen coordinates on that
   1082     // host window, then convert it back to this host window's coordinate.
   1083     screen_position_client->ConvertHostPointToScreen(root_window, &location);
   1084     screen_position_client->ConvertPointFromScreen(root_window, &location);
   1085     root_window->ConvertPointToHost(&location);
   1086     event->set_location(location);
   1087     event->set_root_location(location);
   1088   }
   1089   delegate_->OnHostMouseEvent(event);
   1090 }
   1091 
   1092 void RootWindowHostX11::UpdateIsInternalDisplay() {
   1093   RootWindow* root_window = GetRootWindow();
   1094   gfx::Screen* screen = gfx::Screen::GetScreenFor(root_window);
   1095   gfx::Display display = screen->GetDisplayNearestWindow(root_window);
   1096   is_internal_display_ = display.IsInternal();
   1097 }
   1098 
   1099 void RootWindowHostX11::SetCrOSTapPaused(bool state) {
   1100 #if defined(OS_CHROMEOS)
   1101   // Temporarily pause tap-to-click when the cursor is hidden.
   1102   Atom prop = atom_cache_.GetAtom("Tap Paused");
   1103   unsigned char value = state;
   1104   XIDeviceList dev_list =
   1105       ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(xdisplay_);
   1106 
   1107   // Only slave pointer devices could possibly have tap-paused property.
   1108   for (int i = 0; i < dev_list.count; i++) {
   1109     if (dev_list[i].use == XISlavePointer) {
   1110       Atom old_type;
   1111       int old_format;
   1112       unsigned long old_nvalues, bytes;
   1113       unsigned char* data;
   1114       int result = XIGetProperty(xdisplay_, dev_list[i].deviceid, prop, 0, 0,
   1115                                  False, AnyPropertyType, &old_type, &old_format,
   1116                                  &old_nvalues, &bytes, &data);
   1117       if (result != Success)
   1118         continue;
   1119       XFree(data);
   1120       XIChangeProperty(xdisplay_, dev_list[i].deviceid, prop, XA_INTEGER, 8,
   1121                        PropModeReplace, &value, 1);
   1122     }
   1123   }
   1124 #endif
   1125 }
   1126 
   1127 // static
   1128 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) {
   1129   return new RootWindowHostX11(bounds);
   1130 }
   1131 
   1132 // static
   1133 gfx::Size RootWindowHost::GetNativeScreenSize() {
   1134   ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay();
   1135   return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
   1136 }
   1137 
   1138 namespace test {
   1139 
   1140 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) {
   1141   default_override_redirect = override_redirect;
   1142 }
   1143 
   1144 }  // namespace test
   1145 }  // namespace aura
   1146