Index: ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc |
diff --git a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc |
index e465174db814c72bdaa0f88dbd3bebd67aff6418..6cddd6146624bc45e6a966c0f78392224ae57bb1 100644 |
--- a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc |
+++ b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc |
@@ -4,6 +4,7 @@ |
#include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h" |
+#include <X11/extensions/XInput2.h> |
#include <X11/Xlib.h> |
// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. |
#undef RootWindow |
@@ -18,11 +19,13 @@ |
#include "ui/aura/window_tree_host.h" |
#include "ui/base/x/x11_util.h" |
#include "ui/events/event.h" |
+#include "ui/events/event_utils.h" |
#include "ui/events/keycodes/keyboard_code_conversion_x.h" |
#include "ui/events/platform/x11/x11_event_source.h" |
#include "ui/gfx/point_conversions.h" |
#include "ui/gfx/screen.h" |
#include "ui/views/controls/image_view.h" |
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" |
#include "ui/views/widget/widget.h" |
namespace views { |
@@ -79,16 +82,19 @@ void X11WholeScreenMoveLoop::DispatchMouseMovement() { |
// DesktopWindowTreeHostLinux, ui::PlatformEventDispatcher implementation: |
bool X11WholeScreenMoveLoop::CanDispatchEvent(const ui::PlatformEvent& event) { |
- return event->xany.window == grab_input_window_; |
+ return in_move_loop_; |
} |
uint32_t X11WholeScreenMoveLoop::DispatchEvent(const ui::PlatformEvent& event) { |
+ if (!in_move_loop_) |
+ return ui::POST_DISPATCH_PERFORM_DEFAULT; |
XEvent* xev = event; |
// Note: the escape key is handled in the tab drag controller, which has |
// keyboard focus even though we took pointer grab. |
switch (xev->type) { |
case MotionNotify: { |
+ LOG(INFO) << "MotionNotify in " << grab_input_window_; |
if (drag_widget_.get()) { |
gfx::Screen* screen = gfx::Screen::GetNativeScreen(); |
gfx::Point location = gfx::ToFlooredPoint( |
@@ -106,27 +112,61 @@ uint32_t X11WholeScreenMoveLoop::DispatchEvent(const ui::PlatformEvent& event) { |
base::Bind(&X11WholeScreenMoveLoop::DispatchMouseMovement, |
weak_factory_.GetWeakPtr())); |
} |
- break; |
+ return ui::POST_DISPATCH_NONE; |
} |
case ButtonRelease: { |
if (xev->xbutton.button == Button1) { |
+ LOG(INFO) << "Release in " << grab_input_window_; |
// Assume that drags are being done with the left mouse button. Only |
// break the drag if the left mouse button was released. |
DispatchMouseMovement(); |
delegate_->OnMouseReleased(); |
} |
- break; |
+ return ui::POST_DISPATCH_NONE; |
} |
case KeyPress: { |
if (ui::KeyboardCodeFromXKeyEvent(xev) == ui::VKEY_ESCAPE) { |
canceled_ = true; |
EndMoveLoop(); |
+ return ui::POST_DISPATCH_NONE; |
} |
break; |
} |
+ case GenericEvent: { |
+ ui::EventType type = ui::EventTypeFromNative(xev); |
+ switch (type) { |
+ case ui::ET_MOUSE_MOVED: |
+ case ui::ET_MOUSE_DRAGGED: |
+ case ui::ET_MOUSE_RELEASED: { |
+ LOG(INFO) << "XI event " << type << " in " << grab_input_window_; |
+ XEvent xevent = {0}; |
+ if (type == ui::ET_MOUSE_RELEASED) { |
+ xevent.type = ButtonRelease; |
+ xevent.xbutton.button = ui::EventButtonFromNative(xev); |
+ } else { |
+ xevent.type = MotionNotify; |
+ } |
+ xevent.xany.display = xev->xgeneric.display; |
+ xevent.xany.window = grab_input_window_; |
+ // The fields used below are in the same place for all of events |
+ // above. Using xmotion from XEvent's unions to avoid repeating |
+ // the code. |
+ xevent.xmotion.root = DefaultRootWindow(xev->xgeneric.display); |
+ xevent.xmotion.time = ui::EventTimeFromNative(xev).InMilliseconds(); |
+ gfx::Point point(ui::EventSystemLocationFromNative(xev)); |
+ xevent.xmotion.x_root = point.x(); |
+ xevent.xmotion.y_root = point.y(); |
+ DispatchEvent(&xevent); |
sadrul
2014/04/25 17:19:50
It would be really great if we didn't have to recr
varkha
2014/04/25 18:00:35
We talked about this offline. I think it would be
|
+ return ui::POST_DISPATCH_NONE; |
+ } |
+ default: |
+ break; |
+ } |
+ } |
} |
- return ui::POST_DISPATCH_STOP_PROPAGATION; |
+ return (event->xany.window == grab_input_window_) ? |
+ ui::POST_DISPATCH_NONE : ui::POST_DISPATCH_PERFORM_DEFAULT; |
} |
bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, |
@@ -154,7 +194,10 @@ bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, |
return false; |
} |
- ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); |
+ scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher = |
+ nested_dispatcher_.Pass(); |
+ nested_dispatcher_ = |
+ ui::PlatformEventSource::GetInstance()->OverrideDispatcher(this); |
if (!drag_image_.isNull() && CheckIfIconValid()) |
CreateDragImageWindow(); |
@@ -174,6 +217,7 @@ bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source, |
base::RunLoop run_loop; |
quit_closure_ = run_loop.QuitClosure(); |
run_loop.Run(); |
+ nested_dispatcher_ = old_dispatcher.Pass(); |
return !canceled_; |
} |
@@ -209,10 +253,13 @@ void X11WholeScreenMoveLoop::EndMoveLoop() { |
XUngrabPointer(display, CurrentTime); |
XUngrabKeyboard(display, CurrentTime); |
- ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); |
+ LOG(INFO) << "Ungrab"; |
drag_widget_.reset(); |
delegate_->OnMoveLoopEnded(); |
XDestroyWindow(display, grab_input_window_); |
+ grab_input_window_ = None; |
+ // Restore the previous dispatcher. |
+ nested_dispatcher_.reset(); |
in_move_loop_ = false; |
quit_closure_.Run(); |
@@ -232,6 +279,8 @@ bool X11WholeScreenMoveLoop::GrabPointerAndKeyboard(gfx::NativeCursor cursor) { |
XGrabServer(display); |
XUngrabPointer(display, CurrentTime); |
+ LOG(INFO) << "Ungrab"; |
+ |
int ret = XGrabPointer( |
display, |
grab_input_window_, |
@@ -259,6 +308,7 @@ bool X11WholeScreenMoveLoop::GrabPointerAndKeyboard(gfx::NativeCursor cursor) { |
<< ui::GetX11ErrorString(display, ret); |
} |
} |
+ LOG(INFO) << "Grab " << grab_input_window_; |
XUngrabServer(display); |
return ret == GrabSuccess; |