Index: ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc |
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc |
index aec6aa2968b23f500743fe3dbd11964aa150aca3..8fc6b74ad219fd7fbb08b2b43b7ec938e09b9f9e 100644 |
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc |
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc |
@@ -8,23 +8,30 @@ |
#include <X11/Xlib.h> |
// Get rid of X11 macros which conflict with gtest. |
+// It is necessary to include this header before the rest so that Bool can be |
+// undefined. |
+#include "ui/events/test/events_test_utils_x11.h" |
#undef Bool |
#undef None |
+#include "base/command_line.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/run_loop.h" |
#include "ui/aura/window.h" |
#include "ui/aura/window_tree_host.h" |
#include "ui/base/hit_test.h" |
#include "ui/base/x/x11_util.h" |
+#include "ui/events/devices/x11/touch_factory_x11.h" |
#include "ui/events/platform/x11/x11_event_source.h" |
#include "ui/gfx/geometry/point.h" |
#include "ui/gfx/geometry/rect.h" |
#include "ui/gfx/path.h" |
+#include "ui/gfx/switches.h" |
#include "ui/gfx/x/x11_atom_cache.h" |
#include "ui/views/test/views_test_base.h" |
#include "ui/views/test/x11_property_change_waiter.h" |
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" |
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" |
#include "ui/views/widget/widget_delegate.h" |
#include "ui/views/window/non_client_view.h" |
@@ -32,6 +39,8 @@ namespace views { |
namespace { |
+const int kPointerDeviceId = 1; |
+ |
// Blocks till the window state hint, |hint|, is set or unset. |
class WMStateWaiter : public X11PropertyChangeWaiter { |
public: |
@@ -454,4 +463,137 @@ TEST_F(DesktopWindowTreeHostX11Test, ToggleMinimizePropogateToContentWindow) { |
EXPECT_TRUE(widget.GetNativeWindow()->IsVisible()); |
} |
+class MouseEventRecorder : public ui::EventHandler { |
+ public: |
+ MouseEventRecorder() {} |
+ ~MouseEventRecorder() override {} |
+ |
+ void Reset() { mouse_events_.clear(); } |
+ |
+ const std::vector<ui::MouseEvent>& mouse_events() const { |
+ return mouse_events_; |
+ } |
+ |
+ private: |
+ // ui::EventHandler: |
+ void OnMouseEvent(ui::MouseEvent* mouse) override { |
+ mouse_events_.push_back(*mouse); |
+ } |
+ |
+ std::vector<ui::MouseEvent> mouse_events_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MouseEventRecorder); |
+}; |
+ |
+// A custom event-source that can be used to directly dispatch synthetic X11 |
+// events. |
+class CustomX11EventSource : public ui::X11EventSource { |
+ public: |
+ CustomX11EventSource() : X11EventSource(gfx::GetXDisplay()) {} |
+ ~CustomX11EventSource() override {} |
+ |
+ void DispatchSingleEvent(XEvent* xevent) { |
+ PlatformEventSource::DispatchEvent(xevent); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(CustomX11EventSource); |
+}; |
+ |
+class DesktopWindowTreeHostX11HighDPITest |
+ : public DesktopWindowTreeHostX11Test { |
+ public: |
+ DesktopWindowTreeHostX11HighDPITest() {} |
+ ~DesktopWindowTreeHostX11HighDPITest() override {} |
+ |
+ void DispatchSingleEventToWidget(XEvent* event, Widget* widget) { |
+ DCHECK_EQ(GenericEvent, event->type); |
+ XIDeviceEvent* device_event = |
+ static_cast<XIDeviceEvent*>(event->xcookie.data); |
+ device_event->event = |
+ widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget(); |
+ event_source_.DispatchSingleEvent(event); |
+ } |
+ |
+ void PretendCapture(views::Widget* capture_widget) { |
+ DesktopWindowTreeHostX11* capture_host = nullptr; |
+ if (capture_widget) { |
+ capture_host = static_cast<DesktopWindowTreeHostX11*>( |
+ capture_widget->GetNativeWindow()->GetHost()); |
+ } |
+ DesktopWindowTreeHostX11::g_current_capture = capture_host; |
+ if (capture_widget) |
+ capture_widget->GetNativeWindow()->SetCapture(); |
+ } |
+ |
+ private: |
+ void SetUp() override { |
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
+ command_line->AppendSwitchASCII(switches::kForceDeviceScaleFactor, "2"); |
+ std::vector<unsigned int> pointer_devices; |
+ pointer_devices.push_back(kPointerDeviceId); |
+ ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(pointer_devices); |
+ |
+ DesktopWindowTreeHostX11Test::SetUp(); |
+ } |
+ |
+ CustomX11EventSource event_source_; |
+ DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostX11HighDPITest); |
+}; |
+ |
+TEST_F(DesktopWindowTreeHostX11HighDPITest, LocatedEventDispatchWithCapture) { |
pkotwicz
2015/02/13 20:15:35
This test must be an interactive ui test. (Because
sadrul
2015/02/13 20:27:36
That's why this test doesn't actually do native ca
|
+ Widget first; |
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); |
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
+ params.native_widget = new DesktopNativeWidgetAura(&first); |
+ params.bounds = gfx::Rect(0, 0, 50, 50); |
+ first.Init(params); |
+ first.Show(); |
+ |
+ Widget second; |
+ params = CreateParams(Widget::InitParams::TYPE_WINDOW); |
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
+ params.native_widget = new DesktopNativeWidgetAura(&second); |
+ params.bounds = gfx::Rect(50, 50, 50, 50); |
+ second.Init(params); |
+ second.Show(); |
+ |
+ ui::X11EventSource::GetInstance()->DispatchXEvents(); |
+ |
+ MouseEventRecorder first_recorder, second_recorder; |
+ first.GetNativeWindow()->AddPreTargetHandler(&first_recorder); |
+ second.GetNativeWindow()->AddPreTargetHandler(&second_recorder); |
+ |
+ // Dispatch an event on |first|. Verify it gets the event. |
+ ui::ScopedXI2Event event; |
+ event.InitGenericButtonEvent(kPointerDeviceId, ui::ET_MOUSEWHEEL, |
+ gfx::Point(50, 50), ui::EF_NONE); |
+ DispatchSingleEventToWidget(event, &first); |
+ ASSERT_EQ(1u, first_recorder.mouse_events().size()); |
+ EXPECT_EQ(ui::ET_MOUSEWHEEL, first_recorder.mouse_events()[0].type()); |
+ EXPECT_EQ(gfx::Point(25, 25).ToString(), |
+ first_recorder.mouse_events()[0].location().ToString()); |
+ ASSERT_EQ(0u, second_recorder.mouse_events().size()); |
+ |
+ first_recorder.Reset(); |
+ second_recorder.Reset(); |
+ |
+ // Set a capture on |second|, and dispatch the same event to |first|. This |
+ // event should reach |second| instead. |
+ PretendCapture(&second); |
+ event.InitGenericButtonEvent(kPointerDeviceId, ui::ET_MOUSEWHEEL, |
+ gfx::Point(50, 50), ui::EF_NONE); |
+ DispatchSingleEventToWidget(event, &first); |
+ |
+ ASSERT_EQ(0u, first_recorder.mouse_events().size()); |
+ ASSERT_EQ(1u, second_recorder.mouse_events().size()); |
+ EXPECT_EQ(ui::ET_MOUSEWHEEL, second_recorder.mouse_events()[0].type()); |
+ EXPECT_EQ(gfx::Point(-25, -25).ToString(), |
+ second_recorder.mouse_events()[0].location().ToString()); |
+ |
+ PretendCapture(nullptr); |
+ first.GetNativeWindow()->RemovePreTargetHandler(&first_recorder); |
+ second.GetNativeWindow()->RemovePreTargetHandler(&second_recorder); |
+} |
+ |
} // namespace views |