root_window_host_x11.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/root_window_host_x11.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <strings.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/cursorfont.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/Xfixes.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/XInput2.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/Xrandr.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xatom.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xcursor/Xcursor.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <limits>
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/debug/trace_event.h"
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_loop.h"
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_pump_aurax11.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
255e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
265e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
275e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkPostConfig.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/capture_client.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/cursor_client.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/screen_position_client.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/user_action_client.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/env.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/cursor/cursor.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/events/event.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/events/event_utils.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/keycodes/keyboard_codes.h"
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/touch/touch_factory_x11.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/ui_base_switches.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/view_prop.h"
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/x/device_list_cache_x.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/x11_util.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/dip_util.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/chromeos/chromeos_version.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::max;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::min;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace aura {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Standard Linux mouse buttons for going back and forward.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kBackMouseButton = 8;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kForwardMouseButton = 9;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* kAtomsToCache[] = {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "WM_DELETE_WINDOW",
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "_NET_WM_PING",
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "_NET_WM_PID",
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "WM_S0",
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "Tap Paused",  // Defined in the gestures library.
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NULL
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::Window FindEventTarget(const base::NativeEvent& xev) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::Window target = xev->xany.window;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (xev->type == GenericEvent)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target = static_cast<XIDeviceEvent*>(xev->xcookie.data)->event;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return target;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectEventsForRootWindow() {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Display* display = ui::GetXDisplay();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::Window root_window = ui::GetX11RootWindow();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Receive resize events for the root-window so |x_root_bounds_| can be
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // updated.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XWindowAttributes attr;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XGetWindowAttributes(display, root_window, &attr);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(attr.your_event_mask & StructureNotifyMask)) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XSelectInput(display, root_window,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 StructureNotifyMask | attr.your_event_mask);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!base::MessagePumpForUI::HasXInput2())
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {};
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(mask, 0, sizeof(mask));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XISetMask(mask, XI_HierarchyChanged);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XISetMask(mask, XI_KeyPress);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XISetMask(mask, XI_KeyRelease);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  XIEventMask evmask;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  evmask.deviceid = XIAllDevices;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  evmask.mask_len = sizeof(mask);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  evmask.mask = mask;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  XISelectEvents(display, root_window, &evmask, 1);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Selecting for touch events seems to fail on some cases (e.g. when logging
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // in incognito). So select for non-touch events first, and then select for
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // touch-events (but keep the other events in the mask, i.e. do not memset
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |mask| back to 0).
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(sad): Figure out why this happens. http://crbug.com/153976
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_XI2_MT)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  XISetMask(mask, XI_TouchBegin);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  XISetMask(mask, XI_TouchUpdate);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  XISetMask(mask, XI_TouchEnd);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XISelectEvents(display, root_window, &evmask, 1);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We emulate Windows' WM_KEYDOWN and WM_CHAR messages.  WM_CHAR events are only
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// generated for certain keys; see
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646268.aspx.  Per
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// discussion on http://crbug.com/108480, char events should furthermore not be
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// generated for Tab, Escape, and Backspace.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((keycode >= ui::VKEY_0 && keycode <= ui::VKEY_9) ||
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (keycode >= ui::VKEY_A && keycode <= ui::VKEY_Z) ||
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (keycode >= ui::VKEY_NUMPAD0 && keycode <= ui::VKEY_NUMPAD9)) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (keycode) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_RETURN:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_SPACE:
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In addition to the keys listed at MSDN, we include other
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // graphic-character and numpad keys.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_MULTIPLY:
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_ADD:
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_SUBTRACT:
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_DECIMAL:
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_DIVIDE:
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_1:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_2:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_3:
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_4:
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_5:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_6:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_7:
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_102:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_PLUS:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_COMMA:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_MINUS:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_OEM_PERIOD:
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool default_override_redirect = false;
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Accomplishes 2 tasks concerning touch event calibration:
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 1. Being a message-pump observer,
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//    routes all the touch events to the X root window,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//    where they can be calibrated later.
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 2. Has the Calibrate method that does the actual bezel calibration,
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//    when invoked from X root window's event dispatcher.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TouchEventCalibrate : public base::MessagePumpObserver {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TouchEventCalibrate()
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : left_(0),
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      right_(0),
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      top_(0),
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bottom_(0) {
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoopForUI::current()->AddObserver(this);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_XI2_MT)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<std::string> parts;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (Tokenize(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        switches::kTouchCalibration), ",", &parts) >= 4) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!base::StringToInt(parts[0], &left_))
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DLOG(ERROR) << "Incorrect left border calibration value passed.";
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!base::StringToInt(parts[1], &right_))
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DLOG(ERROR) << "Incorrect right border calibration value passed.";
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!base::StringToInt(parts[2], &top_))
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DLOG(ERROR) << "Incorrect top border calibration value passed.";
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!base::StringToInt(parts[3], &bottom_))
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DLOG(ERROR) << "Incorrect bottom border calibration value passed.";
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(USE_XI2_MT)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TouchEventCalibrate() {
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoopForUI::current()->RemoveObserver(this);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Modify the location of the |event|,
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expanding it from |bounds| to (|bounds| + bezels).
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Required when touchscreen is bigger than screen (i.e. has bezels),
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // because we receive events in touchscreen coordinates,
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // which need to be expanded when converting to screen coordinates,
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // so that location on bezels will be outside of screen area.
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_XI2_MT)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int x = event->x();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int y = event->y();
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!left_ && !right_ && !top_ && !bottom_)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int resolution_x = bounds.width();
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int resolution_y = bounds.height();
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The "grace area" (10% in this case) is to make it easier for the user to
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // navigate to the corner.
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const double kGraceAreaFraction = 0.1;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (left_ || right_) {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Offset the x position to the real
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      x -= left_;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Check if we are in the grace area of the left side.
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Note: We might not want to do this when the gesture is locked?
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (x < 0 && x > -left_ * kGraceAreaFraction)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        x = 0;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Check if we are in the grace area of the right side.
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Note: We might not want to do this when the gesture is locked?
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (x > resolution_x - left_ &&
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          x < resolution_x - left_ + right_ * kGraceAreaFraction)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        x = resolution_x - left_;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Scale the screen area back to the full resolution of the screen.
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      x = (x * resolution_x) / (resolution_x - (right_ + left_));
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (top_ || bottom_) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // When there is a top bezel we add our border,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      y -= top_;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Check if we are in the grace area of the top side.
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Note: We might not want to do this when the gesture is locked?
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (y < 0 && y > -top_ * kGraceAreaFraction)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        y = 0;
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Check if we are in the grace area of the bottom side.
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Note: We might not want to do this when the gesture is locked?
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (y > resolution_y - top_ &&
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          y < resolution_y - top_ + bottom_ * kGraceAreaFraction)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        y = resolution_y - top_;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Scale the screen area back to the full resolution of the screen.
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      y = (y * resolution_y) / (resolution_y - (bottom_ + top_));
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Set the modified coordinate back to the event.
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (event->root_location() == event->location()) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Usually those will be equal,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // if not, I am not sure what the correct value should be.
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      event->set_root_location(gfx::Point(x, y));
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->set_location(gfx::Point(x, y));
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(USE_XI2_MT)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from base::MessagePumpObserver:
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual base::EventStatus WillProcessEvent(
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::NativeEvent& event) OVERRIDE {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_XI2_MT)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event->type == GenericEvent &&
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (event->xgeneric.evtype == XI_TouchBegin ||
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         event->xgeneric.evtype == XI_TouchUpdate ||
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         event->xgeneric.evtype == XI_TouchEnd)) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xievent->event = xievent->root;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xievent->event_x = xievent->root_x;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xievent->event_y = xievent->root_y;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(USE_XI2_MT)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::EVENT_CONTINUE;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The difference in screen's native resolution pixels between
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the border of the touchscreen and the border of the screen,
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // aka bezel sizes.
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int left_;
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int right_;
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int top_;
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int bottom_;
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// RootWindowHostX11::MouseMoveFilter filters out the move events that
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// jump back and forth between two points. This happens when sub pixel mouse
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// move is enabled and mouse move events could be jumping between two neighbor
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// pixels, e.g. move(0,0), move(1,0), move(0,0), move(1,0) and on and on.
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The filtering is done by keeping track of the last two event locations and
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// provides a Filter method to find out whether a mouse event is in a different
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// location and should be processed.
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class RootWindowHostX11::MouseMoveFilter {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MouseMoveFilter() : insert_index_(0) {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < kMaxEvents; ++i) {
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const int int_max = std::numeric_limits<int>::max();
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      recent_locations_[i] = gfx::Point(int_max, int_max);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~MouseMoveFilter() {}
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if |event| is known and should be ignored.
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool Filter(const base::NativeEvent& event) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Point& location = ui::EventLocationFromNative(event);
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < kMaxEvents; ++i) {
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (location == recent_locations_[i])
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return true;
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    recent_locations_[insert_index_] = location;
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    insert_index_ = (insert_index_ + 1) % kMaxEvents;
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const size_t kMaxEvents = 2;
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Point recent_locations_[kMaxEvents];
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t insert_index_;
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MouseMoveFilter);
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// RootWindowHostX11
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)RootWindowHostX11::RootWindowHostX11(const gfx::Rect& bounds)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : delegate_(NULL),
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()),
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xwindow_(0),
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      x_root_window_(DefaultRootWindow(xdisplay_)),
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_cursor_(ui::kCursorNull),
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window_mapped_(false),
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bounds_(bounds),
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_internal_display_(false),
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      focus_when_shown_(false),
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      touch_calibrate_(new internal::TouchEventCalibrate),
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      mouse_move_filter_(new MouseMoveFilter),
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      atom_cache_(xdisplay_, kAtomsToCache) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSetWindowAttributes swa;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&swa, 0, sizeof(swa));
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  swa.background_pixmap = None;
36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  swa.override_redirect = default_override_redirect;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xwindow_ = XCreateWindow(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xdisplay_, x_root_window_,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bounds.x(), bounds.y(), bounds.width(), bounds.height(),
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,               // border width
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CopyFromParent,  // depth
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      InputOutput,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CopyFromParent,  // visual
37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CWBackPixmap | CWOverrideRedirect,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &swa);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    KeyPressMask | KeyReleaseMask |
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    EnterWindowMask | LeaveWindowMask |
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ExposureMask | VisibilityChangeMask |
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    StructureNotifyMask | PropertyChangeMask |
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    PointerMotionMask;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSelectInput(xdisplay_, xwindow_, event_mask);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XFlush(xdisplay_);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::MessagePumpForUI::HasXInput2())
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectEventsForRootWindow();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the initial size of the X root window.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XWindowAttributes attrs;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XGetWindowAttributes(xdisplay_, x_root_window_, &attrs);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  x_root_bounds_.SetRect(attrs.x, attrs.y, attrs.width, attrs.height);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(erg): We currently only request window deletion events. We also
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should listen for activation events and anything else that GTK+ listens
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for, and do something useful.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::Atom protocols[2];
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the desktop environment.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Likewise, the X server needs to know this window's pid so it knows which
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // program to kill if the window hangs.
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pid_t pid = getpid();
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XChangeProperty(xdisplay_,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  xwindow_,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  atom_cache_.GetAtom("_NET_WM_PID"),
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  XA_CARDINAL,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  32,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PropModeReplace,
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  reinterpret_cast<unsigned char*>(&pid), 1);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // crbug.com/120229 - set the window title so gtalk can find the primary root
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // window to broadcast.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jhorwich) Remove this once Chrome supports window-based broadcasting.
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int root_window_number = 0;
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string name = base::StringPrintf("aura_root_%d", root_window_number++);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XStoreName(xdisplay_, xwindow_, name.c_str());
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XRRSelectInput(xdisplay_, x_root_window_,
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 RRScreenChangeNotifyMask | RROutputChangeNotifyMask);
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Env::GetInstance()->AddObserver(this);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)RootWindowHostX11::~RootWindowHostX11() {
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Env::GetInstance()->RemoveObserver(this);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnConfineCursor();
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XDestroyWindow(xdisplay_, xwindow_);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool RootWindowHostX11::Dispatch(const base::NativeEvent& event) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XEvent* xev = event;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FindEventTarget(event) == x_root_window_)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DispatchEventForRootWindow(event);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (xev->type) {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EnterNotify: {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::MouseEvent mouseenter_event(xev);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TranslateAndDispatchMouseEvent(&mouseenter_event);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case Expose: {
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y,
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            xev->xexpose.width, xev->xexpose.height);
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      delegate_->AsRootWindow()->ScheduleRedrawRect(damage_rect);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case KeyPress: {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::KeyEvent keydown_event(xev, false);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->OnHostKeyEvent(&keydown_event);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case KeyRelease: {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::KeyEvent keyup_event(xev, false);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->OnHostKeyEvent(&keyup_event);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ButtonPress: {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (static_cast<int>(xev->xbutton.button) == kBackMouseButton ||
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<int>(xev->xbutton.button) == kForwardMouseButton) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        client::UserActionClient* gesture_client =
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            client::GetUserActionClient(delegate_->AsRootWindow());
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (gesture_client) {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          gesture_client->OnUserAction(
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              static_cast<int>(xev->xbutton.button) == kBackMouseButton ?
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              client::UserActionClient::BACK :
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              client::UserActionClient::FORWARD);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }  // fallthrough
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ButtonRelease: {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::MouseEvent mouseev(xev);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TranslateAndDispatchMouseEvent(&mouseev);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FocusOut:
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (xev->xfocus.mode != NotifyGrab)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnHostLostWindowCapture();
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ConfigureNotify: {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_EQ(xwindow_, xev->xconfigure.event);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_EQ(xwindow_, xev->xconfigure.window);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // It's possible that the X window may be resized by some other means
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // than from within aura (e.g. the X window manager can change the
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // size). Make sure the root window size is maintained properly.
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          xev->xconfigure.width, xev->xconfigure.height);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool size_changed = bounds_.size() != bounds.size();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool origin_changed = bounds_.origin() != bounds.origin();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bounds_ = bounds;
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdateIsInternalDisplay();
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Always update barrier and mouse location because |bounds_| might
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // have already been updated in |SetBounds|.
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (pointer_barriers_) {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UnConfineCursor();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ConfineCursorToRootWindow();
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (size_changed)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnHostResized(bounds.size());
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (origin_changed)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->OnHostMoved(bounds_.origin());
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GenericEvent:
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DispatchXI2Event(event);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MapNotify: {
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If there's no window manager running, we need to assign the X input
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // focus to our host window.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!IsWindowManagerPresent() && focus_when_shown_)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        XSetInputFocus(xdisplay_, xwindow_, RevertToNone, CurrentTime);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ClientMessage: {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Atom message_type = static_cast<Atom>(xev->xclient.data.l[0]);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (message_type == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We have received a close message from the window manager.
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->AsRootWindow()->OnRootWindowHostCloseRequested();
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (message_type == atom_cache_.GetAtom("_NET_WM_PING")) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        XEvent reply_event = *xev;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reply_event.xclient.window = x_root_window_;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        XSendEvent(xdisplay_,
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   reply_event.xclient.window,
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   False,
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   SubstructureRedirectMask | SubstructureNotifyMask,
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   &reply_event);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MappingNotify: {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (xev->xmapping.request) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case MappingModifier:
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case MappingKeyboard:
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          XRefreshKeyboardMapping(&xev->xmapping);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          delegate_->AsRootWindow()->OnKeyboardMappingChanged();
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case MappingPointer:
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ui::UpdateButtonMap();
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MotionNotify: {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Discard all but the most recent motion event that targets the same
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // window with unchanged state.
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XEvent last_event;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (XPending(xev->xany.display)) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        XEvent next_event;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        XPeekEvent(xev->xany.display, &next_event);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (next_event.type == MotionNotify &&
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            next_event.xmotion.window == xev->xmotion.window &&
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            next_event.xmotion.subwindow == xev->xmotion.subwindow &&
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            next_event.xmotion.state == xev->xmotion.state) {
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          XNextEvent(xev->xany.display, &last_event);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          xev = &last_event;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::MouseEvent mouseev(xev);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TranslateAndDispatchMouseEvent(&mouseev);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::SetDelegate(RootWindowHostDelegate* delegate) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_ = delegate;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)RootWindow* RootWindowHostX11::GetRootWindow() {
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return delegate_->AsRootWindow();
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::AcceleratedWidget RootWindowHostX11::GetAcceleratedWidget() {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return xwindow_;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::Show() {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!window_mapped_) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Before we map the window, set size hints. Otherwise, some window managers
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // will ignore toplevel XMoveWindow commands.
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XSizeHints size_hints;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_hints.flags = PPosition | PWinGravity;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_hints.x = bounds_.x();
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_hints.y = bounds_.y();
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set StaticGravity so that the window position is not affected by the
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // frame width when running with window manager.
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_hints.win_gravity = StaticGravity;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XMapWindow(xdisplay_, xwindow_);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We now block until our window is mapped. Some X11 APIs will crash and
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // asynchronous.
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::MessagePumpAuraX11::Current()->BlockUntilWindowMapped(xwindow_);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_mapped_ = true;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::Hide() {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_mapped_) {
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XWithdrawWindow(xdisplay_, xwindow_, 0);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_mapped_ = false;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::ToggleFullScreen() {
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Rect RootWindowHostX11::GetBounds() const {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bounds_;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::SetBounds(const gfx::Rect& bounds) {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Even if the host window's size doesn't change, aura's root window
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // size, which is in DIP, changes when the scale changes.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float current_scale = delegate_->GetDeviceScaleFactor();
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float new_scale = gfx::Screen::GetScreenFor(delegate_->AsRootWindow())->
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetDisplayNearestWindow(delegate_->AsRootWindow()).device_scale_factor();
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool origin_changed = bounds_.origin() != bounds.origin();
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool size_changed = bounds_.size() != bounds.size();
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XWindowChanges changes = {0};
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned value_mask = 0;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size_changed) {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    changes.width = bounds.width();
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    changes.height = bounds.height();
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value_mask = CWHeight | CWWidth;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (origin_changed) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    changes.x = bounds.x();
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    changes.y = bounds.y();
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value_mask |= CWX | CWY;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value_mask)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assume that the resize will go through as requested, which should be the
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // case if we're running without a window manager.  If there's a window
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (possibly synthetic) ConfigureNotify about the actual size and correct
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |bounds_| later.
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds_ = bounds;
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateIsInternalDisplay();
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (origin_changed)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->OnHostMoved(bounds.origin());
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size_changed || current_scale != new_scale) {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->OnHostResized(bounds.size());
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->AsRootWindow()->SchedulePaintInRect(
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_->AsRootWindow()->bounds());
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Insets RootWindowHostX11::GetInsets() const {
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return insets_;
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::SetInsets(const gfx::Insets& insets) {
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  insets_ = insets;
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (pointer_barriers_) {
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UnConfineCursor();
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ConfineCursorToRootWindow();
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Point RootWindowHostX11::GetLocationOnNativeScreen() const {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bounds_.origin();
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::SetCapture() {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(oshima): Grab x input.
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::ReleaseCapture() {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(oshima): Release x input.
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::SetCursor(gfx::NativeCursor cursor) {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cursor == current_cursor_)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_cursor_ = cursor;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetCursorInternal(cursor);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool RootWindowHostX11::QueryMouseLocation(gfx::Point* location_return) {
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client::CursorClient* cursor_client =
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client::GetCursorClient(GetRootWindow());
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cursor_client && !cursor_client->IsMouseEventsEnabled()) {
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *location_return = gfx::Point(0, 0);
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::Window root_return, child_return;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int root_x_return, root_y_return, win_x_return, win_y_return;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int mask_return;
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XQueryPointer(xdisplay_,
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                xwindow_,
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &root_return,
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &child_return,
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &root_x_return, &root_y_return,
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &win_x_return, &win_y_return,
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &mask_return);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *location_return = gfx::Point(max(0, min(bounds_.width(), win_x_return)),
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                max(0, min(bounds_.height(), win_y_return)));
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (win_x_return >= 0 && win_x_return < bounds_.width() &&
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          win_y_return >= 0 && win_y_return < bounds_.height());
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool RootWindowHostX11::ConfineCursorToRootWindow() {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if XFIXES_MAJOR >= 5
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!pointer_barriers_.get());
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (pointer_barriers_)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pointer_barriers_.reset(new XID[4]);
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect bounds(bounds_);
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bounds.Inset(insets_);
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Horizontal, top barriers.
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pointer_barriers_[0] = XFixesCreatePointerBarrier(
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xdisplay_, x_root_window_,
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bounds.x(), bounds.y(), bounds.right(), bounds.y(),
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BarrierPositiveY,
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, XIAllDevices);
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Horizontal, bottom barriers.
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pointer_barriers_[1] = XFixesCreatePointerBarrier(
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xdisplay_, x_root_window_,
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bounds.x(), bounds.bottom(), bounds.right(),  bounds.bottom(),
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BarrierNegativeY,
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, XIAllDevices);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Vertical, left  barriers.
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pointer_barriers_[2] = XFixesCreatePointerBarrier(
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xdisplay_, x_root_window_,
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bounds.x(), bounds.y(), bounds.x(), bounds.bottom(),
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BarrierPositiveX,
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, XIAllDevices);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Vertical, right barriers.
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pointer_barriers_[3] = XFixesCreatePointerBarrier(
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xdisplay_, x_root_window_,
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bounds.right(), bounds.y(), bounds.right(), bounds.bottom(),
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BarrierNegativeX,
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0, XIAllDevices);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::UnConfineCursor() {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if XFIXES_MAJOR >= 5
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (pointer_barriers_) {
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[0]);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[1]);
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[2]);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[3]);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pointer_barriers_.reset();
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::OnCursorVisibilityChanged(bool show) {
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Temporarily pause tap-to-click when the cursor is hidden.
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Atom prop = atom_cache_.GetAtom("Tap Paused");
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned char value = !show;
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  XIDeviceList dev_list =
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(xdisplay_);
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only slave pointer devices could possibly have tap-paused property.
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < dev_list.count; i++) {
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (dev_list[i].use == XISlavePointer) {
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Atom old_type;
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int old_format;
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned long old_nvalues, bytes;
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned char* data;
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int result = XIGetProperty(xdisplay_, dev_list[i].deviceid, prop, 0, 0,
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 False, AnyPropertyType, &old_type, &old_format,
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &old_nvalues, &bytes, &data);
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (result != Success)
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      XFree(data);
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      XIChangeProperty(xdisplay_, dev_list[i].deviceid, prop, XA_INTEGER, 8,
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       PropModeReplace, &value, 1);
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::MoveCursorTo(const gfx::Point& location) {
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0,
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               bounds_.x() + location.x(),
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               bounds_.y() + location.y());
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
811c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::SetFocusWhenShown(bool focus_when_shown) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME";
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  focus_when_shown_ = focus_when_shown;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsWindowManagerPresent() && !focus_when_shown_) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::SetIntProperty(xwindow_,
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       k_NET_WM_USER_TIME,
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       k_NET_WM_USER_TIME,
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       0);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool RootWindowHostX11::CopyAreaToSkCanvas(const gfx::Rect& source_bounds,
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const gfx::Point& dest_offset,
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             SkCanvas* canvas) {
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::XScopedImage> scoped_image(GetXImage(source_bounds));
826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!scoped_image)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XImage* image = scoped_image->get();
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(image);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (image->bits_per_pixel == 32) {
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((0xff << SK_R32_SHIFT) != image->red_mask ||
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (0xff << SK_G32_SHIFT) != image->green_mask ||
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (0xff << SK_B32_SHIFT) != image->blue_mask) {
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(WARNING) << "XImage and Skia byte orders differ";
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set the alpha channel before copying to the canvas.  Otherwise, areas of
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the framebuffer that were cleared by ply-image rather than being obscured
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // by an image during boot may end up transparent.
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(derat|marcheu): Remove this if/when ply-image has been updated to
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // set the framebuffer's alpha channel regardless of whether the device
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // claims to support alpha or not.
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < image->width * image->height * 4; i += 4)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image->data[i + 3] = 0xff;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkBitmap bitmap;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitmap.setConfig(SkBitmap::kARGB_8888_Config,
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     image->width, image->height,
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     image->bytes_per_line);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitmap.setPixels(image->data);
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), NULL);
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel;
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
863c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::PostNativeEvent(
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::NativeEvent& native_event) {
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(xwindow_);
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(xdisplay_);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XEvent xevent = *native_event;
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xevent.xany.display = xdisplay_;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xevent.xany.window = xwindow_;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (xevent.type) {
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EnterNotify:
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case LeaveNotify:
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MotionNotify:
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case KeyPress:
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case KeyRelease:
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ButtonPress:
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ButtonRelease: {
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The fields used below are in the same place for all of events
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // above. Using xmotion from XEvent's unions to avoid repeating
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the code.
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xevent.xmotion.root = x_root_window_;
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xevent.xmotion.time = CurrentTime;
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Point point(xevent.xmotion.x, xevent.xmotion.y);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->AsRootWindow()->ConvertPointToNativeScreen(&point);
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xevent.xmotion.x_root = point.x();
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xevent.xmotion.y_root = point.y();
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::OnDeviceScaleFactorChanged(
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float device_scale_factor) {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::PrepareForShutdown() {
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::OnWindowInitialized(Window* window) {
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::OnRootWindowInitialized(RootWindow* root_window) {
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // UpdateIsInternalDisplay relies on:
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 1. delegate_ pointing to RootWindow - available after SetDelegate.
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 2. RootWindow's kDisplayIdKey property set - available by the time
9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //    RootWindow::Init is called.
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //    (set in DisplayManager::CreateRootWindowForDisplay)
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ready when NotifyRootWindowInitialized is called from RootWindow::Init.
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!delegate_ || root_window != GetRootWindow())
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateIsInternalDisplay();
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
919c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool RootWindowHostX11::DispatchEventForRootWindow(
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::NativeEvent& event) {
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (event->type) {
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ConfigureNotify:
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_EQ(x_root_window_, event->xconfigure.event);
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      x_root_bounds_.SetRect(event->xconfigure.x, event->xconfigure.y,
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          event->xconfigure.width, event->xconfigure.height);
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GenericEvent:
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DispatchXI2Event(event);
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
936c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::DispatchXI2Event(const base::NativeEvent& event) {
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XEvent* xev = event;
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!factory->ShouldProcessXI2Event(xev))
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TRACE_EVENT1("input", "RootWindowHostX11::DispatchXI2Event",
943868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               "event_latency_us",
944868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               (ui::EventTimeForNow() - ui::EventTimeFromNative(event)).
945868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 InMicroseconds());
946868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::EventType type = ui::EventTypeFromNative(xev);
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XEvent last_event;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_coalesced = 0;
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_TOUCH_MOVED:
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_TOUCH_PRESSED:
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ui::ET_TOUCH_CANCELLED:
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_TOUCH_RELEASED: {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::TouchEvent touchev(xev);
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (base::chromeos::IsRunningOnChromeOS()) {
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!bounds_.Contains(touchev.location()))
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // X maps the touch-surface to the size of the X root-window.
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // In multi-monitor setup, Coordinate Transformation Matrix
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // repositions the touch-surface onto part of X root-window
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // containing aura root-window corresponding to the touchscreen.
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // However, if aura root-window has non-zero origin,
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // we need to relocate the event into aura root-window coordinates.
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        touchev.Relocate(bounds_.origin());
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_XI2_MT)
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (is_internal_display_)
9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          touch_calibrate_->Calibrate(&touchev, bounds_);
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(USE_XI2_MT)
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_CHROMEOS)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->OnHostTouchEvent(&touchev);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_MOVED:
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_DRAGGED:
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_PRESSED:
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_RELEASED:
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_ENTERED:
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSE_EXITED: {
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If this is a motion event, we want to coalesce all pending motion
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // events that are at the top of the queue.
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (num_coalesced > 0)
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          xev = &last_event;
9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mouse_move_filter_ && mouse_move_filter_->Filter(xev))
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (type == ui::ET_MOUSE_PRESSED ||
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 type == ui::ET_MOUSE_RELEASED) {
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        XIDeviceEvent* xievent =
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<XIDeviceEvent*>(xev->xcookie.data);
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int button = xievent->detail;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (button == kBackMouseButton || button == kForwardMouseButton) {
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (type == ui::ET_MOUSE_RELEASED)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          client::UserActionClient* gesture_client =
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              client::GetUserActionClient(delegate_->AsRootWindow());
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (gesture_client) {
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bool reverse_direction =
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            gesture_client->OnUserAction(
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (button == kBackMouseButton && !reverse_direction) ||
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (button == kForwardMouseButton && reverse_direction) ?
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                client::UserActionClient::BACK :
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                client::UserActionClient::FORWARD);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::MouseEvent mouseev(xev);
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TranslateAndDispatchMouseEvent(&mouseev);
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_MOUSEWHEEL: {
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::MouseWheelEvent mouseev(xev);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TranslateAndDispatchMouseEvent(&mouseev);
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_SCROLL_FLING_START:
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_SCROLL_FLING_CANCEL:
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_SCROLL: {
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::ScrollEvent scrollev(xev);
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_->OnHostScrollEvent(&scrollev);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::ET_UNKNOWN:
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we coalesced an event we need to free its cookie.
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_coalesced > 0)
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1041c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool RootWindowHostX11::IsWindowManagerPresent() {
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of WM_Sn selections (where n is a screen number).
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return XGetSelectionOwner(
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xdisplay_, atom_cache_.GetAtom("WM_S0")) != None;
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1048c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::SetCursorInternal(gfx::NativeCursor cursor) {
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  XDefineCursor(xdisplay_, xwindow_, cursor.platform());
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1052c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::TranslateAndDispatchMouseEvent(
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::MouseEvent* event) {
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RootWindow* root_window = GetRootWindow();
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client::ScreenPositionClient* screen_position_client =
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetScreenPositionClient(root_window);
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect local(bounds_.size());
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (screen_position_client && !local.Contains(event->location())) {
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Point location(event->location());
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // In order to get the correct point in screen coordinates
10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // during passive grab, we first need to find on which host window
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the mouse is on, and find out the screen coordinates on that
10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // host window, then convert it back to this host window's coordinate.
10652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    screen_position_client->ConvertHostPointToScreen(root_window, &location);
10662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    screen_position_client->ConvertPointFromScreen(root_window, &location);
10672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root_window->ConvertPointToHost(&location);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->set_location(location);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->set_root_location(location);
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->OnHostMouseEvent(event);
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1074c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<ui::XScopedImage> RootWindowHostX11::GetXImage(
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& snapshot_bounds) {
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::XScopedImage> image(new ui::XScopedImage(
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      XGetImage(xdisplay_, xwindow_,
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                snapshot_bounds.x(), snapshot_bounds.y(),
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                snapshot_bounds.width(), snapshot_bounds.height(),
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                AllPlanes, ZPixmap)));
1081c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!image) {
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "XGetImage failed";
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image.reset();
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return image.Pass();
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1088c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RootWindowHostX11::UpdateIsInternalDisplay() {
10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RootWindow* root_window = GetRootWindow();
10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Screen* screen = gfx::Screen::GetScreenFor(root_window);
10912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Display display = screen->GetDisplayNearestWindow(root_window);
10922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  is_internal_display_ = display.IsInternal();
10932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) {
1097c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return new RootWindowHostX11(bounds);
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size RootWindowHost::GetNativeScreenSize() {
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay();
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace test {
110790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
110890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SetUseOverrideRedirectWindowByDefault(bool override_redirect) {
110990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  default_override_redirect = override_redirect;
111090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
111190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
111290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace test
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace aura
1114