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