190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <X11/Xlib.h>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#undef RootWindow
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/debug/stack_trace.h"
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_loop.h"
1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/message_loop/message_pump_x11.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/run_loop.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/env.h"
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/root_window.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/aura/window.h"
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/aura/window_tree_host.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/x/x11_util.h"
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/gfx/point_conversions.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/screen.h"
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/views/controls/image_view.h"
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/views/widget/widget.h"
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace views {
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace {
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class ScopedCapturer {
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  explicit ScopedCapturer(aura::RootWindowHost* host)
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : host_(host) {
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    host_->SetCapture();
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ~ScopedCapturer() {
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    host_->ReleaseCapture();
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::RootWindowHost* host_;
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScopedCapturer);
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)X11WholeScreenMoveLoop::X11WholeScreenMoveLoop(
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    X11WholeScreenMoveLoopDelegate* delegate)
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : delegate_(delegate),
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      in_move_loop_(false),
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      grab_input_window_(None) {
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {}
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// DesktopRootWindowHostLinux, MessageLoop::Dispatcher implementation:
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool X11WholeScreenMoveLoop::Dispatch(const base::NativeEvent& event) {
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  XEvent* xev = event;
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note: the escape key is handled in the tab drag controller, which has
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // keyboard focus even though we took pointer grab.
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (xev->type) {
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case MotionNotify: {
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (drag_widget_.get()) {
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        gfx::Screen* screen = gfx::Screen::GetNativeScreen();
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        gfx::Point location = gfx::ToFlooredPoint(
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            screen->GetCursorScreenPoint() - drag_offset_);
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        drag_widget_->SetBounds(gfx::Rect(location, drag_image_.size()));
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      delegate_->OnMouseMovement(&xev->xmotion);
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case ButtonRelease: {
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (xev->xbutton.button == Button1) {
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Assume that drags are being done with the left mouse button. Only
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // break the drag if the left mouse button was released.
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        delegate_->OnMouseReleased();
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// DesktopRootWindowHostLinux, aura::client::WindowMoveClient implementation:
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source,
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                         gfx::NativeCursor cursor) {
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Start a capture on the host, so that it continues to receive events during
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // the drag.
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ScopedCapturer capturer(source->GetDispatcher()->host());
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!in_move_loop_);  // Can only handle one nested loop at a time.
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  in_move_loop_ = true;
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  XDisplay* display = gfx::GetXDisplay();
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  grab_input_window_ = CreateDragInputWindow(display);
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!drag_image_.isNull())
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CreateDragImageWindow();
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::MessagePumpX11::Current()->AddDispatcherForWindow(
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      this, grab_input_window_);
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!GrabPointerWithCursor(cursor))
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // We are handling a mouse drag outside of the aura::RootWindow system. We
1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // must manually make aura think that the mouse button is pressed so that we
1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // don't draw extraneous tooltips.
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Env::GetInstance()->set_mouse_button_flags(ui::EF_LEFT_MOUSE_BUTTON);
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::RunLoop run_loop(aura::Env::GetInstance()->GetDispatcher());
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  quit_closure_ = run_loop.QuitClosure();
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  run_loop.Run();
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid X11WholeScreenMoveLoop::UpdateCursor(gfx::NativeCursor cursor) {
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(in_move_loop_);
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  GrabPointerWithCursor(cursor);
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void X11WholeScreenMoveLoop::EndMoveLoop() {
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!in_move_loop_)
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // We undo our emulated mouse click from RunMoveLoop();
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  aura::Env::GetInstance()->set_mouse_button_flags(0);
1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(erg): Is this ungrab the cause of having to click to give input focus
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on drawn out windows? Not ungrabbing here screws the X server until I kill
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // the chrome process.
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Ungrab before we let go of the window.
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  XDisplay* display = gfx::GetXDisplay();
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  XUngrabPointer(display, CurrentTime);
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::MessagePumpX11::Current()->RemoveDispatcherForWindow(
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      grab_input_window_);
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  drag_widget_.reset();
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  delegate_->OnMoveLoopEnded();
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  XDestroyWindow(display, grab_input_window_);
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  in_move_loop_ = false;
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  quit_closure_.Run();
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void X11WholeScreenMoveLoop::SetDragImage(const gfx::ImageSkia& image,
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          gfx::Vector2dF offset) {
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  drag_image_ = image;
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  drag_offset_ = offset;
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Reset the Y offset, so that the drag-image is always just below the cursor,
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // so that it is possible to see where the cursor is going.
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  drag_offset_.set_y(0.f);
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool X11WholeScreenMoveLoop::GrabPointerWithCursor(gfx::NativeCursor cursor) {
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  XDisplay* display = gfx::GetXDisplay();
1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  XGrabServer(display);
1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  XUngrabPointer(display, CurrentTime);
1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int ret = XGrabPointer(
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      display,
1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      grab_input_window_,
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      False,
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      GrabModeAsync,
1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      GrabModeAsync,
1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      None,
1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      cursor.platform(),
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CurrentTime);
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  XUngrabServer(display);
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (ret != GrabSuccess) {
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DLOG(ERROR) << "Grabbing new tab for dragging failed: "
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                << ui::GetX11ErrorString(display, ret);
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return true;
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)Window X11WholeScreenMoveLoop::CreateDragInputWindow(XDisplay* display) {
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Creates an invisible, InputOnly toplevel window. This window will receive
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // all mouse movement for drags. It turns out that normal windows doing a
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // grab doesn't redirect pointer motion events if the pointer isn't over the
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // grabbing window. But InputOnly windows are able to grab everything. This
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // is what GTK+ does, and I found a patch to KDE that did something similar.
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned long attribute_mask = CWEventMask | CWOverrideRedirect;
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  XSetWindowAttributes swa;
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  memset(&swa, 0, sizeof(swa));
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  swa.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   StructureNotifyMask;
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  swa.override_redirect = True;
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Window window = XCreateWindow(display,
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                DefaultRootWindow(display),
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                -100, -100, 10, 10,
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                0, CopyFromParent, InputOnly, CopyFromParent,
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                attribute_mask, &swa);
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  XMapRaised(display, window);
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::MessagePumpX11::Current()->BlockUntilWindowMapped(window);
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return window;
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void X11WholeScreenMoveLoop::CreateDragImageWindow() {
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Widget* widget = new Widget;
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Widget::InitParams params(Widget::InitParams::TYPE_DRAG);
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  params.opacity = Widget::InitParams::OPAQUE_WINDOW;
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  params.accept_events = false;
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point location = gfx::ToFlooredPoint(
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      gfx::Screen::GetNativeScreen()->GetCursorScreenPoint() - drag_offset_);
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  params.bounds = gfx::Rect(location, drag_image_.size());
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  widget->set_focus_on_creation(false);
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE);
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  widget->Init(params);
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  widget->GetNativeWindow()->SetName("DragWindow");
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ImageView* image = new ImageView();
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  image->SetImage(drag_image_);
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  image->SetBounds(0, 0, drag_image_.width(), drag_image_.height());
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  widget->SetContentsView(image);
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  widget->Show();
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false);
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  drag_widget_.reset(widget);
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace views
238