OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" | 5 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" |
6 | 6 |
7 #include <X11/Xlib.h> | 7 #include <X11/Xlib.h> |
8 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. | 8 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. |
9 #undef RootWindow | 9 #undef RootWindow |
10 | 10 |
| 11 #include "base/bind.h" |
11 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
12 #include "base/message_loop/message_pump_x11.h" | 13 #include "base/message_loop/message_pump_x11.h" |
13 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
14 #include "third_party/skia/include/core/SkBitmap.h" | 15 #include "third_party/skia/include/core/SkBitmap.h" |
15 #include "ui/aura/env.h" | 16 #include "ui/aura/env.h" |
16 #include "ui/aura/window.h" | 17 #include "ui/aura/window.h" |
17 #include "ui/aura/window_event_dispatcher.h" | 18 #include "ui/aura/window_event_dispatcher.h" |
18 #include "ui/aura/window_tree_host.h" | 19 #include "ui/aura/window_tree_host.h" |
19 #include "ui/base/x/x11_util.h" | 20 #include "ui/base/x/x11_util.h" |
20 #include "ui/events/event.h" | 21 #include "ui/events/event.h" |
(...skipping 29 matching lines...) Expand all Loading... |
50 DISALLOW_COPY_AND_ASSIGN(ScopedCapturer); | 51 DISALLOW_COPY_AND_ASSIGN(ScopedCapturer); |
51 }; | 52 }; |
52 | 53 |
53 } // namespace | 54 } // namespace |
54 | 55 |
55 X11WholeScreenMoveLoop::X11WholeScreenMoveLoop( | 56 X11WholeScreenMoveLoop::X11WholeScreenMoveLoop( |
56 X11WholeScreenMoveLoopDelegate* delegate) | 57 X11WholeScreenMoveLoopDelegate* delegate) |
57 : delegate_(delegate), | 58 : delegate_(delegate), |
58 in_move_loop_(false), | 59 in_move_loop_(false), |
59 should_reset_mouse_flags_(false), | 60 should_reset_mouse_flags_(false), |
60 grab_input_window_(None) { | 61 grab_input_window_(None), |
| 62 weak_factory_(this) { |
| 63 last_xmotion_.type = LASTEvent; |
61 } | 64 } |
62 | 65 |
63 X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {} | 66 X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {} |
64 | 67 |
65 //////////////////////////////////////////////////////////////////////////////// | 68 //////////////////////////////////////////////////////////////////////////////// |
66 // DesktopWindowTreeHostLinux, MessagePumpDispatcher implementation: | 69 // DesktopWindowTreeHostLinux, MessagePumpDispatcher implementation: |
67 | 70 |
| 71 void X11WholeScreenMoveLoop::DispatchMouseMovement() { |
| 72 if (!weak_factory_.HasWeakPtrs()) |
| 73 return; |
| 74 weak_factory_.InvalidateWeakPtrs(); |
| 75 DCHECK_EQ(MotionNotify, last_xmotion_.type); |
| 76 delegate_->OnMouseMovement(&last_xmotion_); |
| 77 last_xmotion_.type = LASTEvent; |
| 78 } |
| 79 |
68 uint32_t X11WholeScreenMoveLoop::Dispatch(const base::NativeEvent& event) { | 80 uint32_t X11WholeScreenMoveLoop::Dispatch(const base::NativeEvent& event) { |
69 XEvent* xev = event; | 81 XEvent* xev = event; |
70 | 82 |
71 // Note: the escape key is handled in the tab drag controller, which has | 83 // Note: the escape key is handled in the tab drag controller, which has |
72 // keyboard focus even though we took pointer grab. | 84 // keyboard focus even though we took pointer grab. |
73 switch (xev->type) { | 85 switch (xev->type) { |
74 case MotionNotify: { | 86 case MotionNotify: { |
75 if (drag_widget_.get()) { | 87 if (drag_widget_.get()) { |
76 gfx::Screen* screen = gfx::Screen::GetNativeScreen(); | 88 gfx::Screen* screen = gfx::Screen::GetNativeScreen(); |
77 gfx::Point location = gfx::ToFlooredPoint( | 89 gfx::Point location = gfx::ToFlooredPoint( |
78 screen->GetCursorScreenPoint() - drag_offset_); | 90 screen->GetCursorScreenPoint() - drag_offset_); |
79 drag_widget_->SetBounds(gfx::Rect(location, drag_image_.size())); | 91 drag_widget_->SetBounds(gfx::Rect(location, drag_image_.size())); |
80 drag_widget_->StackAtTop(); | 92 drag_widget_->StackAtTop(); |
81 } | 93 } |
82 delegate_->OnMouseMovement(&xev->xmotion); | 94 last_xmotion_ = xev->xmotion; |
| 95 if (!weak_factory_.HasWeakPtrs()) { |
| 96 // Post a task to dispatch mouse movement event when control returns to |
| 97 // the message loop. This allows smoother dragging since the events are |
| 98 // dispatched without waiting for the drag widget updates. |
| 99 base::MessageLoopForUI::current()->PostTask( |
| 100 FROM_HERE, |
| 101 base::Bind(&X11WholeScreenMoveLoop::DispatchMouseMovement, |
| 102 weak_factory_.GetWeakPtr())); |
| 103 } |
83 break; | 104 break; |
84 } | 105 } |
85 case ButtonRelease: { | 106 case ButtonRelease: { |
86 if (xev->xbutton.button == Button1) { | 107 if (xev->xbutton.button == Button1) { |
87 // Assume that drags are being done with the left mouse button. Only | 108 // Assume that drags are being done with the left mouse button. Only |
88 // break the drag if the left mouse button was released. | 109 // break the drag if the left mouse button was released. |
| 110 DispatchMouseMovement(); |
89 delegate_->OnMouseReleased(); | 111 delegate_->OnMouseReleased(); |
90 } | 112 } |
91 break; | 113 break; |
92 } | 114 } |
93 case KeyPress: { | 115 case KeyPress: { |
94 if (ui::KeyboardCodeFromXKeyEvent(xev) == ui::VKEY_ESCAPE) | 116 if (ui::KeyboardCodeFromXKeyEvent(xev) == ui::VKEY_ESCAPE) |
95 EndMoveLoop(); | 117 EndMoveLoop(); |
96 break; | 118 break; |
97 } | 119 } |
98 } | 120 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 // cursor. Note: we can be called from handling an XdndStatus message after | 178 // cursor. Note: we can be called from handling an XdndStatus message after |
157 // EndMoveLoop() was called, but before we return from the nested RunLoop. | 179 // EndMoveLoop() was called, but before we return from the nested RunLoop. |
158 GrabPointerAndKeyboard(cursor); | 180 GrabPointerAndKeyboard(cursor); |
159 } | 181 } |
160 } | 182 } |
161 | 183 |
162 void X11WholeScreenMoveLoop::EndMoveLoop() { | 184 void X11WholeScreenMoveLoop::EndMoveLoop() { |
163 if (!in_move_loop_) | 185 if (!in_move_loop_) |
164 return; | 186 return; |
165 | 187 |
| 188 // Prevent DispatchMouseMovement from dispatching any posted motion event. |
| 189 weak_factory_.InvalidateWeakPtrs(); |
| 190 last_xmotion_.type = LASTEvent; |
| 191 |
166 // We undo our emulated mouse click from RunMoveLoop(); | 192 // We undo our emulated mouse click from RunMoveLoop(); |
167 if (should_reset_mouse_flags_) { | 193 if (should_reset_mouse_flags_) { |
168 aura::Env::GetInstance()->set_mouse_button_flags(0); | 194 aura::Env::GetInstance()->set_mouse_button_flags(0); |
169 should_reset_mouse_flags_ = false; | 195 should_reset_mouse_flags_ = false; |
170 } | 196 } |
171 | 197 |
172 // TODO(erg): Is this ungrab the cause of having to click to give input focus | 198 // TODO(erg): Is this ungrab the cause of having to click to give input focus |
173 // on drawn out windows? Not ungrabbing here screws the X server until I kill | 199 // on drawn out windows? Not ungrabbing here screws the X server until I kill |
174 // the chrome process. | 200 // the chrome process. |
175 | 201 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 for (int x = 0; x < in_bitmap->width(); ++x) { | 328 for (int x = 0; x < in_bitmap->width(); ++x) { |
303 if (SkColorGetA(in_row[x]) > kMinAlpha) | 329 if (SkColorGetA(in_row[x]) > kMinAlpha) |
304 return true; | 330 return true; |
305 } | 331 } |
306 } | 332 } |
307 | 333 |
308 return false; | 334 return false; |
309 } | 335 } |
310 | 336 |
311 } // namespace views | 337 } // namespace views |
OLD | NEW |