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 "content/browser/renderer_host/render_widget_host_view_mac.h" | 5 #include "content/browser/renderer_host/render_widget_host_view_mac.h" |
6 | 6 |
7 #include <Cocoa/Cocoa.h> | 7 #include <Cocoa/Cocoa.h> |
8 | 8 |
9 #include "base/mac/mac_util.h" | 9 #include "base/mac/mac_util.h" |
10 #include "base/mac/scoped_nsautorelease_pool.h" | 10 #include "base/mac/scoped_nsautorelease_pool.h" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 - (BOOL)canRubberbandRight:(NSView*)view { | 85 - (BOOL)canRubberbandRight:(NSView*)view { |
86 return true; | 86 return true; |
87 } | 87 } |
88 | 88 |
89 @end | 89 @end |
90 | 90 |
91 namespace content { | 91 namespace content { |
92 | 92 |
93 namespace { | 93 namespace { |
94 | 94 |
95 id MockGestureEvent( | 95 id MockGestureEvent(NSEventType type, double magnification) { |
96 NSEventType type, NSTimeInterval timestamp, double magnification) { | |
97 id event = [OCMockObject mockForClass:[NSEvent class]]; | 96 id event = [OCMockObject mockForClass:[NSEvent class]]; |
98 NSPoint locationInWindow = NSMakePoint(0, 0); | 97 NSPoint locationInWindow = NSMakePoint(0, 0); |
99 CGFloat deltaX = 0; | 98 CGFloat deltaX = 0; |
100 CGFloat deltaY = 0; | 99 CGFloat deltaY = 0; |
| 100 NSTimeInterval timestamp = 1; |
101 NSUInteger modifierFlags = 0; | 101 NSUInteger modifierFlags = 0; |
| 102 |
102 [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(type)] type]; | 103 [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(type)] type]; |
103 [(NSEvent*)[[event stub] | 104 [(NSEvent*)[[event stub] |
104 andReturnValue:OCMOCK_VALUE(locationInWindow)] locationInWindow]; | 105 andReturnValue:OCMOCK_VALUE(locationInWindow)] locationInWindow]; |
105 [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(deltaX)] deltaX]; | 106 [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(deltaX)] deltaX]; |
106 [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(deltaY)] deltaY]; | 107 [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(deltaY)] deltaY]; |
107 [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(timestamp)] timestamp]; | 108 [(NSEvent*)[[event stub] andReturnValue:OCMOCK_VALUE(timestamp)] timestamp]; |
108 [(NSEvent*)[[event stub] | 109 [(NSEvent*)[[event stub] |
109 andReturnValue:OCMOCK_VALUE(modifierFlags)] modifierFlags]; | 110 andReturnValue:OCMOCK_VALUE(modifierFlags)] modifierFlags]; |
110 [(NSEvent*)[[event stub] | 111 [(NSEvent*)[[event stub] |
111 andReturnValue:OCMOCK_VALUE(magnification)] magnification]; | 112 andReturnValue:OCMOCK_VALUE(magnification)] magnification]; |
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 EXPECT_TRUE([view->cocoa_view() isOpaque]); | 860 EXPECT_TRUE([view->cocoa_view() isOpaque]); |
860 set_background = process_host->sink().GetUniqueMessageMatching( | 861 set_background = process_host->sink().GetUniqueMessageMatching( |
861 ViewMsg_SetBackgroundOpaque::ID); | 862 ViewMsg_SetBackgroundOpaque::ID); |
862 ASSERT_TRUE(set_background); | 863 ASSERT_TRUE(set_background); |
863 ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background); | 864 ViewMsg_SetBackgroundOpaque::Read(set_background, &sent_background); |
864 EXPECT_TRUE(get<0>(sent_background)); | 865 EXPECT_TRUE(get<0>(sent_background)); |
865 | 866 |
866 host->Shutdown(); | 867 host->Shutdown(); |
867 } | 868 } |
868 | 869 |
869 TEST_F(RenderWidgetHostViewMacTest, PinchThresholding) { | 870 class RenderWidgetHostViewMacPinchTest : public RenderWidgetHostViewMacTest { |
| 871 public: |
| 872 RenderWidgetHostViewMacPinchTest() : process_host_(NULL) {} |
| 873 |
| 874 bool ZoomDisabledForPinchUpdateMessage() { |
| 875 const IPC::Message* message = NULL; |
| 876 // The first message may be a PinchBegin. Go for the second message if |
| 877 // there are two. |
| 878 switch (process_host_->sink().message_count()) { |
| 879 case 1: |
| 880 message = process_host_->sink().GetMessageAt(0); |
| 881 break; |
| 882 case 2: |
| 883 message = process_host_->sink().GetMessageAt(1); |
| 884 break; |
| 885 default: |
| 886 NOTREACHED(); |
| 887 break; |
| 888 } |
| 889 DCHECK(message); |
| 890 Tuple<IPC::WebInputEventPointer, ui::LatencyInfo, bool> data; |
| 891 InputMsg_HandleInputEvent::Read(message, &data); |
| 892 IPC::WebInputEventPointer ipc_event = get<0>(data); |
| 893 const blink::WebGestureEvent* gesture_event = |
| 894 static_cast<const blink::WebGestureEvent*>(ipc_event); |
| 895 return gesture_event->data.pinchUpdate.zoomDisabled; |
| 896 } |
| 897 |
| 898 MockRenderProcessHost* process_host_; |
| 899 }; |
| 900 |
| 901 TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) { |
870 // This tests Lion+ functionality, so don't run the test pre-Lion. | 902 // This tests Lion+ functionality, so don't run the test pre-Lion. |
871 if (!base::mac::IsOSLionOrLater()) | 903 if (!base::mac::IsOSLionOrLater()) |
872 return; | 904 return; |
873 | 905 |
874 // Initialize the view associated with a MockRenderWidgetHostImpl, rather than | 906 // Initialize the view associated with a MockRenderWidgetHostImpl, rather than |
875 // the MockRenderProcessHost that is set up by the test harness which mocks | 907 // the MockRenderProcessHost that is set up by the test harness which mocks |
876 // out |OnMessageReceived()|. | 908 // out |OnMessageReceived()|. |
877 TestBrowserContext browser_context; | 909 TestBrowserContext browser_context; |
878 MockRenderProcessHost* process_host = | 910 process_host_ = new MockRenderProcessHost(&browser_context); |
879 new MockRenderProcessHost(&browser_context); | |
880 MockRenderWidgetHostDelegate delegate; | 911 MockRenderWidgetHostDelegate delegate; |
881 MockRenderWidgetHostImpl* host = new MockRenderWidgetHostImpl( | 912 MockRenderWidgetHostImpl* host = new MockRenderWidgetHostImpl( |
882 &delegate, process_host, MSG_ROUTING_NONE); | 913 &delegate, process_host_, MSG_ROUTING_NONE); |
883 RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false); | 914 RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false); |
884 | 915 |
885 // We'll use this IPC message to ack events. | 916 // We'll use this IPC message to ack events. |
886 InputHostMsg_HandleInputEvent_ACK_Params ack; | 917 InputHostMsg_HandleInputEvent_ACK_Params ack; |
887 ack.type = blink::WebInputEvent::GesturePinchUpdate; | 918 ack.type = blink::WebInputEvent::GesturePinchUpdate; |
888 ack.state = INPUT_EVENT_ACK_STATE_CONSUMED; | 919 ack.state = INPUT_EVENT_ACK_STATE_CONSUMED; |
889 scoped_ptr<IPC::Message> response( | 920 scoped_ptr<IPC::Message> response( |
890 new InputHostMsg_HandleInputEvent_ACK(0, ack)); | 921 new InputHostMsg_HandleInputEvent_ACK(0, ack)); |
891 | 922 |
892 // Do a gesture that crosses the threshold. | 923 // Do a gesture that crosses the threshold. |
893 { | 924 { |
894 NSEvent* pinchBeginEvent = | 925 NSEvent* pinchBeginEvent = |
895 MockGestureEvent(NSEventTypeBeginGesture, 100.1, 0); | 926 MockGestureEvent(NSEventTypeBeginGesture, 0); |
896 NSEvent* pinchUpdateEvents[3] = { | 927 NSEvent* pinchUpdateEvents[3] = { |
897 MockGestureEvent(NSEventTypeMagnify, 100.2, 0.25), | 928 MockGestureEvent(NSEventTypeMagnify, 0.25), |
898 MockGestureEvent(NSEventTypeMagnify, 100.3, 0.25), | 929 MockGestureEvent(NSEventTypeMagnify, 0.25), |
899 MockGestureEvent(NSEventTypeMagnify, 100.4, 0.25), | 930 MockGestureEvent(NSEventTypeMagnify, 0.25), |
900 }; | 931 }; |
901 NSEvent* pinchEndEvent = | 932 NSEvent* pinchEndEvent = |
902 MockGestureEvent(NSEventTypeEndGesture, 100.5, 0); | 933 MockGestureEvent(NSEventTypeEndGesture, 0); |
903 | 934 |
904 // No messages are sent for the pinch begin and the first update event. | |
905 [view->cocoa_view() beginGestureWithEvent:pinchBeginEvent]; | 935 [view->cocoa_view() beginGestureWithEvent:pinchBeginEvent]; |
| 936 EXPECT_EQ(0U, process_host_->sink().message_count()); |
| 937 |
| 938 // No zoom is sent for the first update event. |
906 [view->cocoa_view() magnifyWithEvent:pinchUpdateEvents[0]]; | 939 [view->cocoa_view() magnifyWithEvent:pinchUpdateEvents[0]]; |
907 ASSERT_EQ(0U, process_host->sink().message_count()); | 940 host->OnMessageReceived(*response); |
| 941 EXPECT_EQ(2U, process_host_->sink().message_count()); |
| 942 EXPECT_TRUE(ZoomDisabledForPinchUpdateMessage()); |
| 943 process_host_->sink().ClearMessages(); |
908 | 944 |
909 // The second update event crosses the threshold of 0.4, and so a begin | 945 // The second update event crosses the threshold of 0.4, and so zoom is no |
910 // and update are sent. | 946 // longer disabled. |
911 [view->cocoa_view() magnifyWithEvent:pinchUpdateEvents[1]]; | 947 [view->cocoa_view() magnifyWithEvent:pinchUpdateEvents[1]]; |
912 ASSERT_EQ(2U, process_host->sink().message_count()); | 948 EXPECT_FALSE(ZoomDisabledForPinchUpdateMessage()); |
913 host->OnMessageReceived(*response); | 949 host->OnMessageReceived(*response); |
| 950 EXPECT_EQ(1U, process_host_->sink().message_count()); |
| 951 process_host_->sink().ClearMessages(); |
914 | 952 |
915 // The third update only causes one event to be sent. | 953 // The third update still has zoom enabled. |
916 [view->cocoa_view() magnifyWithEvent:pinchUpdateEvents[2]]; | 954 [view->cocoa_view() magnifyWithEvent:pinchUpdateEvents[2]]; |
917 ASSERT_EQ(3U, process_host->sink().message_count()); | 955 EXPECT_FALSE(ZoomDisabledForPinchUpdateMessage()); |
918 host->OnMessageReceived(*response); | 956 host->OnMessageReceived(*response); |
| 957 EXPECT_EQ(1U, process_host_->sink().message_count()); |
| 958 process_host_->sink().ClearMessages(); |
919 | 959 |
920 // As does the end. | |
921 [view->cocoa_view() endGestureWithEvent:pinchEndEvent]; | 960 [view->cocoa_view() endGestureWithEvent:pinchEndEvent]; |
922 ASSERT_EQ(4U, process_host->sink().message_count()); | 961 EXPECT_EQ(1U, process_host_->sink().message_count()); |
923 | 962 process_host_->sink().ClearMessages(); |
924 process_host->sink().ClearMessages(); | |
925 } | 963 } |
926 | 964 |
927 // Do a gesture that doesn't cross the threshold, but happens within 1 second, | 965 // Do a gesture that doesn't cross the threshold, but happens when we're not |
928 // so it should be sent to the renderer. | 966 // at page scale factor one, so it should be sent to the renderer. |
929 { | 967 { |
930 NSEvent* pinchBeginEvent = | 968 NSEvent* pinchBeginEvent = MockGestureEvent(NSEventTypeBeginGesture, 0); |
931 MockGestureEvent(NSEventTypeBeginGesture, 101.0, 0); | 969 NSEvent* pinchUpdateEvent = MockGestureEvent(NSEventTypeMagnify, 0.25); |
932 NSEvent* pinchUpdateEvent = | 970 NSEvent* pinchEndEvent = MockGestureEvent(NSEventTypeEndGesture, 0); |
933 MockGestureEvent(NSEventTypeMagnify, 101.1, 0.25); | |
934 NSEvent* pinchEndEvent = | |
935 MockGestureEvent(NSEventTypeEndGesture, 101.2, 0); | |
936 | 971 |
937 // No message comes for the begin event. | 972 view->page_is_at_scale_one_ = false; |
| 973 |
938 [view->cocoa_view() beginGestureWithEvent:pinchBeginEvent]; | 974 [view->cocoa_view() beginGestureWithEvent:pinchBeginEvent]; |
939 ASSERT_EQ(0U, process_host->sink().message_count()); | 975 EXPECT_EQ(0U, process_host_->sink().message_count()); |
940 | 976 |
941 // Two messages come for the first update event. | 977 // Expect that a zoom happen because the time threshold has not passed. |
942 [view->cocoa_view() magnifyWithEvent:pinchUpdateEvent]; | 978 [view->cocoa_view() magnifyWithEvent:pinchUpdateEvent]; |
943 ASSERT_EQ(2U, process_host->sink().message_count()); | 979 EXPECT_FALSE(ZoomDisabledForPinchUpdateMessage()); |
944 host->OnMessageReceived(*response); | 980 host->OnMessageReceived(*response); |
| 981 EXPECT_EQ(2U, process_host_->sink().message_count()); |
| 982 process_host_->sink().ClearMessages(); |
945 | 983 |
946 // The end event sends one message. | |
947 [view->cocoa_view() endGestureWithEvent:pinchEndEvent]; | 984 [view->cocoa_view() endGestureWithEvent:pinchEndEvent]; |
948 ASSERT_EQ(3U, process_host->sink().message_count()); | 985 EXPECT_EQ(1U, process_host_->sink().message_count()); |
949 | 986 process_host_->sink().ClearMessages(); |
950 process_host->sink().ClearMessages(); | |
951 } | 987 } |
952 | 988 |
953 // Do a gesture that doesn't cross the threshold and happens more than one | 989 // Do a gesture again, after the page scale is no longer at one, and ensure |
954 // second later. | 990 // that it is thresholded again. |
955 { | 991 { |
956 NSEvent* pinchBeginEvent = | 992 NSEvent* pinchBeginEvent = MockGestureEvent(NSEventTypeBeginGesture, 0); |
957 MockGestureEvent(NSEventTypeBeginGesture, 103.0, 0); | 993 NSEvent* pinchUpdateEvent = MockGestureEvent(NSEventTypeMagnify, 0.25); |
958 NSEvent* pinchUpdateEvent = | 994 NSEvent* pinchEndEvent = MockGestureEvent(NSEventTypeEndGesture, 0); |
959 MockGestureEvent(NSEventTypeMagnify, 103.1, 0.25); | |
960 NSEvent* pinchEndEvent = | |
961 MockGestureEvent(NSEventTypeEndGesture, 103.2, 0); | |
962 | 995 |
963 // No message comes for the begin event. | 996 view->page_is_at_scale_one_ = true; |
| 997 |
964 [view->cocoa_view() beginGestureWithEvent:pinchBeginEvent]; | 998 [view->cocoa_view() beginGestureWithEvent:pinchBeginEvent]; |
965 ASSERT_EQ(0U, process_host->sink().message_count()); | 999 EXPECT_EQ(0U, process_host_->sink().message_count()); |
966 | 1000 |
967 // Two messages come for the first update event. | 1001 // Get back to zoom one right after the begin event. This should still keep |
| 1002 // the thresholding in place (it is latched at the begin event). |
| 1003 view->page_is_at_scale_one_ = false; |
| 1004 |
| 1005 // Expect that zoom be disabled because the time threshold has passed. |
968 [view->cocoa_view() magnifyWithEvent:pinchUpdateEvent]; | 1006 [view->cocoa_view() magnifyWithEvent:pinchUpdateEvent]; |
969 ASSERT_EQ(0U, process_host->sink().message_count()); | 1007 EXPECT_EQ(2U, process_host_->sink().message_count()); |
| 1008 EXPECT_TRUE(ZoomDisabledForPinchUpdateMessage()); |
| 1009 host->OnMessageReceived(*response); |
| 1010 process_host_->sink().ClearMessages(); |
970 | 1011 |
971 // As does the end. | |
972 [view->cocoa_view() endGestureWithEvent:pinchEndEvent]; | 1012 [view->cocoa_view() endGestureWithEvent:pinchEndEvent]; |
973 ASSERT_EQ(0U, process_host->sink().message_count()); | 1013 EXPECT_EQ(1U, process_host_->sink().message_count()); |
974 | 1014 process_host_->sink().ClearMessages(); |
975 process_host->sink().ClearMessages(); | |
976 } | 1015 } |
977 | 1016 |
978 // Clean up. | 1017 // Clean up. |
979 host->Shutdown(); | 1018 host->Shutdown(); |
980 } | 1019 } |
981 | 1020 |
982 | 1021 |
983 } // namespace content | 1022 } // namespace content |
OLD | NEW |