Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1349)

Unified Diff: ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc

Issue 380943003: Do not release capture when transferring capture between Chrome windows on Linux (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc
index 1c14861b13c96ea5fdf14ca8b17d28515cd95956..8a986d7bc9a98fbb032f4eb63e04ce7315235e1a 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <vector>
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
#include <X11/Xlib.h>
@@ -12,11 +12,13 @@
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
+#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/x/x11_util.h"
+#include "ui/events/event_handler.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/x/x11_atom_cache.h"
@@ -53,18 +55,68 @@ class ActivationWaiter : public X11PropertyChangeWaiter {
DISALLOW_COPY_AND_ASSIGN(ActivationWaiter);
};
-// Creates a widget of size 100x100.
-scoped_ptr<Widget> CreateWidget() {
+// An event handler which counts the number of mouse moves it has seen.
+class MouseMoveCounterHandler : public ui::EventHandler {
+ public:
+ MouseMoveCounterHandler() : count_(0) {
+ }
+ virtual ~MouseMoveCounterHandler() {
+ }
+
+ // ui::EventHandler:
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ if (event->type() == ui::ET_MOUSE_MOVED)
+ ++count_;
+ }
+
+ int num_mouse_moves() const {
+ return count_;
+ }
+
+ private:
+ int count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MouseMoveCounterHandler);
+};
+
+// Creates a widget with the given bounds.
+scoped_ptr<Widget> CreateWidget(const gfx::Rect& bounds) {
scoped_ptr<Widget> widget(new Widget);
Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.remove_standard_frame = true;
params.native_widget = new DesktopNativeWidgetAura(widget.get());
- params.bounds = gfx::Rect(100, 100, 100, 100);
+ params.bounds = bounds;
widget->Init(params);
return widget.Pass();
}
+// Dispatches an XMotionEvent targeted at |host|'s X window with location
+// |point_in_screen|.
+void DispatchMouseMotionEvent(DesktopWindowTreeHostX11* desktop_host,
+ const gfx::Point& point_in_screen) {
+ aura::WindowTreeHost* host = static_cast<aura::WindowTreeHost*>(desktop_host);
+ gfx::Rect bounds_in_screen = desktop_host->window()->GetBoundsInScreen();
+
+ Display* display = gfx::GetXDisplay();
+ XEvent xev;
+ xev.xmotion.type = MotionNotify;
+ xev.xmotion.display = display;
+ xev.xmotion.window = host->GetAcceleratedWidget();
+ xev.xmotion.root = DefaultRootWindow(display);
+ xev.xmotion.subwindow = 0;
+ xev.xmotion.time = CurrentTime;
+ xev.xmotion.x = point_in_screen.x() - bounds_in_screen.x();
+ xev.xmotion.y = point_in_screen.y() - bounds_in_screen.y();
+ xev.xmotion.x_root = point_in_screen.x();
+ xev.xmotion.y_root = point_in_screen.y();
+ xev.xmotion.state = 0;
+ xev.xmotion.is_hint = NotifyNormal;
+ xev.xmotion.same_screen = True;
+
+ static_cast<ui::PlatformEventDispatcher*>(desktop_host)->DispatchEvent(&xev);
+}
+
} // namespace
class DesktopWindowTreeHostX11Test : public ViewsTestBase {
@@ -82,6 +134,7 @@ class DesktopWindowTreeHostX11Test : public ViewsTestBase {
ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
}
+ // testing::Test
virtual void SetUp() OVERRIDE {
ViewsTestBase::SetUp();
@@ -103,7 +156,7 @@ class DesktopWindowTreeHostX11Test : public ViewsTestBase {
// Chrome even if it not possible to deactivate the window wrt to the x server.
// This behavior is required by several interactive_ui_tests.
TEST_F(DesktopWindowTreeHostX11Test, Deactivate) {
- scoped_ptr<Widget> widget(CreateWidget());
+ scoped_ptr<Widget> widget(CreateWidget(gfx::Rect(100, 100, 100, 100)));
ActivationWaiter waiter(
widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
@@ -124,4 +177,81 @@ TEST_F(DesktopWindowTreeHostX11Test, Deactivate) {
EXPECT_TRUE(widget->IsActive());
}
+// Chrome attempts to make mouse capture look synchronous on Linux. Test that
+// Chrome synchronously switches the window that mouse events are forwarded to
+// when capture is changed.
+TEST_F(DesktopWindowTreeHostX11Test, CaptureEventForwarding) {
+ scoped_ptr<Widget> widget1(CreateWidget(gfx::Rect(100, 100, 100, 100)));
+ aura::Window* window1 = widget1->GetNativeWindow();
+ DesktopWindowTreeHostX11* host1 =
+ static_cast<DesktopWindowTreeHostX11*>(window1->GetHost());
+ widget1->Show();
+
+ scoped_ptr<Widget> widget2(CreateWidget(gfx::Rect(200, 100, 100, 100)));
+ aura::Window* window2 = widget2->GetNativeWindow();
+ DesktopWindowTreeHostX11* host2 =
+ static_cast<DesktopWindowTreeHostX11*>(window2->GetHost());
+ widget2->Show();
+
+ MouseMoveCounterHandler recorder1;
+ window1->AddPreTargetHandler(&recorder1);
+ MouseMoveCounterHandler recorder2;
+ window2->AddPreTargetHandler(&recorder2);
+
+ // Move the mouse to the center of |widget2|.
+ gfx::Point point_in_screen = widget2->GetWindowBoundsInScreen().CenterPoint();
+ DispatchMouseMotionEvent(host2, point_in_screen);
+ EXPECT_EQ(0, recorder1.num_mouse_moves());
+ EXPECT_EQ(1, recorder2.num_mouse_moves());
+ EXPECT_EQ(point_in_screen.ToString(),
+ aura::Env::GetInstance()->last_mouse_location().ToString());
+
+ // Set capture to |widget1|. Because DesktopWindowTreeHostX11 calls
+ // XGrabPointer() with owner == False, the X server sends events to |widget2|
+ // as long as the mouse is hovered over |widget2|. Verify that Chrome
+ // redirects mouse events to |widget1|.
+ widget1->SetCapture(NULL);
+ point_in_screen += gfx::Vector2d(1, 0);
+ DispatchMouseMotionEvent(host2, point_in_screen);
+ EXPECT_EQ(1, recorder1.num_mouse_moves());
+ EXPECT_EQ(1, recorder2.num_mouse_moves());
+ // If the event's location was correctly changed to be relative to |widget1|,
+ // Env's last mouse position will be correct.
+ EXPECT_EQ(point_in_screen.ToString(),
+ aura::Env::GetInstance()->last_mouse_location().ToString());
+
+ // Set capture to |widget2|. Subsequent events sent to |widget2| should not be
+ // forwarded.
+ widget2->SetCapture(NULL);
+ point_in_screen += gfx::Vector2d(1, 0);
+ DispatchMouseMotionEvent(host2, point_in_screen);
+ EXPECT_EQ(1, recorder1.num_mouse_moves());
+ EXPECT_EQ(2, recorder2.num_mouse_moves());
+ EXPECT_EQ(point_in_screen.ToString(),
+ aura::Env::GetInstance()->last_mouse_location().ToString());
+
+ // If the mouse is not hovered over |widget1| or |widget2|, the X server will
+ // send events to the window which has capture. Test the mouse events sent to
+ // |widget2| are not forwarded.
+ DispatchMouseMotionEvent(host2, point_in_screen);
+ EXPECT_EQ(1, recorder1.num_mouse_moves());
+ EXPECT_EQ(3, recorder2.num_mouse_moves());
+ EXPECT_EQ(point_in_screen.ToString(),
+ aura::Env::GetInstance()->last_mouse_location().ToString());
+
+ // Release capture. Test that when capture is released, mouse events are no
+ // longer forwarded to other widgets.
+ widget2->ReleaseCapture();
+ point_in_screen = widget1->GetWindowBoundsInScreen().CenterPoint();
+ DispatchMouseMotionEvent(host1, point_in_screen);
+ EXPECT_EQ(2, recorder1.num_mouse_moves());
+ EXPECT_EQ(3, recorder2.num_mouse_moves());
+ EXPECT_EQ(point_in_screen.ToString(),
+ aura::Env::GetInstance()->last_mouse_location().ToString());
+
+ // Cleanup
+ window1->RemovePreTargetHandler(&recorder1);
+ window2->RemovePreTargetHandler(&recorder2);
+}
+
} // namespace views
« no previous file with comments | « ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc ('k') | ui/views/widget/desktop_aura/x11_scoped_capture.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698