| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/ui/views/apps/shaped_app_window_targeter.h" | 5 #include "chrome/browser/ui/views/apps/shaped_app_window_targeter.h" |
| 6 | 6 |
| 7 #include "apps/ui/views/app_window_frame_view.h" | 7 #include "apps/ui/views/app_window_frame_view.h" |
| 8 #include "chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h" | 8 #include "chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h" |
| 9 #include "ui/aura/test/aura_test_base.h" | 9 #include "ui/aura/test/aura_test_base.h" |
| 10 #include "ui/aura/window.h" | 10 #include "ui/aura/window.h" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 ChromeNativeAppWindowViewsAura app_window_; | 56 ChromeNativeAppWindowViewsAura app_window_; |
| 57 | 57 |
| 58 DISALLOW_COPY_AND_ASSIGN(ShapedAppWindowTargeterTest); | 58 DISALLOW_COPY_AND_ASSIGN(ShapedAppWindowTargeterTest); |
| 59 }; | 59 }; |
| 60 | 60 |
| 61 TEST_F(ShapedAppWindowTargeterTest, HitTestBasic) { | 61 TEST_F(ShapedAppWindowTargeterTest, HitTestBasic) { |
| 62 aura::Window* window = widget()->GetNativeWindow(); | 62 aura::Window* window = widget()->GetNativeWindow(); |
| 63 { | 63 { |
| 64 // Without any custom shapes, the event should be targeted correctly to the | 64 // Without any custom shapes, the event should be targeted correctly to the |
| 65 // window. | 65 // window. |
| 66 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(40, 40), | 66 ui::MouseEvent move( |
| 67 gfx::Point(40, 40), ui::EventTimeForNow(), ui::EF_NONE, | 67 ui::ET_MOUSE_MOVED, gfx::Point(40, 40), gfx::Point(40, 40), |
| 68 ui::EF_NONE); | 68 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 69 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 69 ui::EventDispatchDetails details = | 70 ui::EventDispatchDetails details = |
| 70 event_processor()->OnEventFromSource(&move); | 71 event_processor()->OnEventFromSource(&move); |
| 71 ASSERT_FALSE(details.dispatcher_destroyed); | 72 ASSERT_FALSE(details.dispatcher_destroyed); |
| 72 EXPECT_EQ(window, move.target()); | 73 EXPECT_EQ(window, move.target()); |
| 73 } | 74 } |
| 74 | 75 |
| 75 scoped_ptr<SkRegion> region(new SkRegion); | 76 scoped_ptr<SkRegion> region(new SkRegion); |
| 76 region->op(SkIRect::MakeXYWH(0, 0, 0, 0), SkRegion::kUnion_Op); | 77 region->op(SkIRect::MakeXYWH(0, 0, 0, 0), SkRegion::kUnion_Op); |
| 77 app_window()->UpdateShape(region.Pass()); | 78 app_window()->UpdateShape(region.Pass()); |
| 78 { | 79 { |
| 79 // With an empty custom shape, all events within the window should fall | 80 // With an empty custom shape, all events within the window should fall |
| 80 // through to the root window. | 81 // through to the root window. |
| 81 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(40, 40), | 82 ui::MouseEvent move( |
| 82 gfx::Point(40, 40), ui::EventTimeForNow(), ui::EF_NONE, | 83 ui::ET_MOUSE_MOVED, gfx::Point(40, 40), gfx::Point(40, 40), |
| 83 ui::EF_NONE); | 84 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 85 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 84 ui::EventDispatchDetails details = | 86 ui::EventDispatchDetails details = |
| 85 event_processor()->OnEventFromSource(&move); | 87 event_processor()->OnEventFromSource(&move); |
| 86 ASSERT_FALSE(details.dispatcher_destroyed); | 88 ASSERT_FALSE(details.dispatcher_destroyed); |
| 87 EXPECT_EQ(root_window(), move.target()); | 89 EXPECT_EQ(root_window(), move.target()); |
| 88 } | 90 } |
| 89 | 91 |
| 90 // Window shape (global coordinates) | 92 // Window shape (global coordinates) |
| 91 // 30 70 90 130 | 93 // 30 70 90 130 |
| 92 // 30 + +-----+ | 94 // 30 + +-----+ |
| 93 // . | | <- mouse move (40,40) | 95 // . | | <- mouse move (40,40) |
| 94 // 70 +--------+ +---------+ | 96 // 70 +--------+ +---------+ |
| 95 // | . | <- mouse move (80,80) | 97 // | . | <- mouse move (80,80) |
| 96 // 90 +--------+ +---------+ | 98 // 90 +--------+ +---------+ |
| 97 // | | | 99 // | | |
| 98 // 130 +-----+ | 100 // 130 +-----+ |
| 99 region.reset(new SkRegion); | 101 region.reset(new SkRegion); |
| 100 region->op(SkIRect::MakeXYWH(40, 0, 20, 100), SkRegion::kUnion_Op); | 102 region->op(SkIRect::MakeXYWH(40, 0, 20, 100), SkRegion::kUnion_Op); |
| 101 region->op(SkIRect::MakeXYWH(0, 40, 100, 20), SkRegion::kUnion_Op); | 103 region->op(SkIRect::MakeXYWH(0, 40, 100, 20), SkRegion::kUnion_Op); |
| 102 app_window()->UpdateShape(region.Pass()); | 104 app_window()->UpdateShape(region.Pass()); |
| 103 { | 105 { |
| 104 // With the custom shape, the events that don't fall within the custom shape | 106 // With the custom shape, the events that don't fall within the custom shape |
| 105 // will go through to the root window. | 107 // will go through to the root window. |
| 106 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(40, 40), | 108 ui::MouseEvent move( |
| 107 gfx::Point(40, 40), ui::EventTimeForNow(), ui::EF_NONE, | 109 ui::ET_MOUSE_MOVED, gfx::Point(40, 40), gfx::Point(40, 40), |
| 108 ui::EF_NONE); | 110 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 111 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 109 ui::EventDispatchDetails details = | 112 ui::EventDispatchDetails details = |
| 110 event_processor()->OnEventFromSource(&move); | 113 event_processor()->OnEventFromSource(&move); |
| 111 ASSERT_FALSE(details.dispatcher_destroyed); | 114 ASSERT_FALSE(details.dispatcher_destroyed); |
| 112 EXPECT_EQ(root_window(), move.target()); | 115 EXPECT_EQ(root_window(), move.target()); |
| 113 | 116 |
| 114 // But events within the shape will still reach the window. | 117 // But events within the shape will still reach the window. |
| 115 ui::MouseEvent move2(ui::ET_MOUSE_MOVED, gfx::Point(80, 80), | 118 ui::MouseEvent move2( |
| 116 gfx::Point(80, 80), ui::EventTimeForNow(), ui::EF_NONE, | 119 ui::ET_MOUSE_MOVED, gfx::Point(80, 80), gfx::Point(80, 80), |
| 117 ui::EF_NONE); | 120 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 121 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 118 details = event_processor()->OnEventFromSource(&move2); | 122 details = event_processor()->OnEventFromSource(&move2); |
| 119 ASSERT_FALSE(details.dispatcher_destroyed); | 123 ASSERT_FALSE(details.dispatcher_destroyed); |
| 120 EXPECT_EQ(window, move2.target()); | 124 EXPECT_EQ(window, move2.target()); |
| 121 } | 125 } |
| 122 } | 126 } |
| 123 | 127 |
| 124 TEST_F(ShapedAppWindowTargeterTest, HitTestOnlyForShapedWindow) { | 128 TEST_F(ShapedAppWindowTargeterTest, HitTestOnlyForShapedWindow) { |
| 125 // Install a window-targeter on the root window that allows a window to | 129 // Install a window-targeter on the root window that allows a window to |
| 126 // receive events outside of its bounds. Verify that this window-targeter is | 130 // receive events outside of its bounds. Verify that this window-targeter is |
| 127 // active unless the window has a custom shape. | 131 // active unless the window has a custom shape. |
| 128 gfx::Insets inset(-30, -30, -30, -30); | 132 gfx::Insets inset(-30, -30, -30, -30); |
| 129 root_window()->SetEventTargeter(scoped_ptr<ui::EventTargeter>( | 133 root_window()->SetEventTargeter(scoped_ptr<ui::EventTargeter>( |
| 130 new wm::EasyResizeWindowTargeter(root_window(), inset, inset))); | 134 new wm::EasyResizeWindowTargeter(root_window(), inset, inset))); |
| 131 | 135 |
| 132 aura::Window* window = widget()->GetNativeWindow(); | 136 aura::Window* window = widget()->GetNativeWindow(); |
| 133 { | 137 { |
| 134 // Without any custom shapes, an event within the window bounds should be | 138 // Without any custom shapes, an event within the window bounds should be |
| 135 // targeted correctly to the window. | 139 // targeted correctly to the window. |
| 136 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(40, 40), | 140 ui::MouseEvent move( |
| 137 gfx::Point(40, 40), ui::EventTimeForNow(), ui::EF_NONE, | 141 ui::ET_MOUSE_MOVED, gfx::Point(40, 40), gfx::Point(40, 40), |
| 138 ui::EF_NONE); | 142 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 143 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 139 ui::EventDispatchDetails details = | 144 ui::EventDispatchDetails details = |
| 140 event_processor()->OnEventFromSource(&move); | 145 event_processor()->OnEventFromSource(&move); |
| 141 ASSERT_FALSE(details.dispatcher_destroyed); | 146 ASSERT_FALSE(details.dispatcher_destroyed); |
| 142 EXPECT_EQ(window, move.target()); | 147 EXPECT_EQ(window, move.target()); |
| 143 } | 148 } |
| 144 { | 149 { |
| 145 // Without any custom shapes, an event that falls just outside the window | 150 // Without any custom shapes, an event that falls just outside the window |
| 146 // bounds should also be targeted correctly to the window, because of the | 151 // bounds should also be targeted correctly to the window, because of the |
| 147 // targeter installed on the root-window. | 152 // targeter installed on the root-window. |
| 148 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10), | 153 ui::MouseEvent move( |
| 149 gfx::Point(10, 10), ui::EventTimeForNow(), ui::EF_NONE, | 154 ui::ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10), |
| 150 ui::EF_NONE); | 155 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 156 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 151 ui::EventDispatchDetails details = | 157 ui::EventDispatchDetails details = |
| 152 event_processor()->OnEventFromSource(&move); | 158 event_processor()->OnEventFromSource(&move); |
| 153 ASSERT_FALSE(details.dispatcher_destroyed); | 159 ASSERT_FALSE(details.dispatcher_destroyed); |
| 154 EXPECT_EQ(window, move.target()); | 160 EXPECT_EQ(window, move.target()); |
| 155 } | 161 } |
| 156 | 162 |
| 157 scoped_ptr<SkRegion> region(new SkRegion); | 163 scoped_ptr<SkRegion> region(new SkRegion); |
| 158 region->op(SkIRect::MakeXYWH(40, 0, 20, 100), SkRegion::kUnion_Op); | 164 region->op(SkIRect::MakeXYWH(40, 0, 20, 100), SkRegion::kUnion_Op); |
| 159 region->op(SkIRect::MakeXYWH(0, 40, 100, 20), SkRegion::kUnion_Op); | 165 region->op(SkIRect::MakeXYWH(0, 40, 100, 20), SkRegion::kUnion_Op); |
| 160 app_window()->UpdateShape(region.Pass()); | 166 app_window()->UpdateShape(region.Pass()); |
| 161 { | 167 { |
| 162 // With the custom shape, the events that don't fall within the custom shape | 168 // With the custom shape, the events that don't fall within the custom shape |
| 163 // will go through to the root window. | 169 // will go through to the root window. |
| 164 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10), | 170 ui::MouseEvent move( |
| 165 gfx::Point(10, 10), ui::EventTimeForNow(), ui::EF_NONE, | 171 ui::ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10), |
| 166 ui::EF_NONE); | 172 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 173 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 167 ui::EventDispatchDetails details = | 174 ui::EventDispatchDetails details = |
| 168 event_processor()->OnEventFromSource(&move); | 175 event_processor()->OnEventFromSource(&move); |
| 169 ASSERT_FALSE(details.dispatcher_destroyed); | 176 ASSERT_FALSE(details.dispatcher_destroyed); |
| 170 EXPECT_EQ(root_window(), move.target()); | 177 EXPECT_EQ(root_window(), move.target()); |
| 171 } | 178 } |
| 172 | 179 |
| 173 // Remove the custom shape. This should restore the behaviour of targeting the | 180 // Remove the custom shape. This should restore the behaviour of targeting the |
| 174 // app window for events just outside its bounds. | 181 // app window for events just outside its bounds. |
| 175 app_window()->UpdateShape(scoped_ptr<SkRegion>()); | 182 app_window()->UpdateShape(scoped_ptr<SkRegion>()); |
| 176 { | 183 { |
| 177 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10), | 184 ui::MouseEvent move( |
| 178 gfx::Point(10, 10), ui::EventTimeForNow(), ui::EF_NONE, | 185 ui::ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10), |
| 179 ui::EF_NONE); | 186 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 187 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 180 ui::EventDispatchDetails details = | 188 ui::EventDispatchDetails details = |
| 181 event_processor()->OnEventFromSource(&move); | 189 event_processor()->OnEventFromSource(&move); |
| 182 ASSERT_FALSE(details.dispatcher_destroyed); | 190 ASSERT_FALSE(details.dispatcher_destroyed); |
| 183 EXPECT_EQ(window, move.target()); | 191 EXPECT_EQ(window, move.target()); |
| 184 } | 192 } |
| 185 } | 193 } |
| 186 | 194 |
| 187 // Tests targeting of events on a window with an EasyResizeWindowTargeter | 195 // Tests targeting of events on a window with an EasyResizeWindowTargeter |
| 188 // installed on its container. | 196 // installed on its container. |
| 189 TEST_F(ShapedAppWindowTargeterTest, ResizeInsetsWithinBounds) { | 197 TEST_F(ShapedAppWindowTargeterTest, ResizeInsetsWithinBounds) { |
| 190 aura::Window* window = widget()->GetNativeWindow(); | 198 aura::Window* window = widget()->GetNativeWindow(); |
| 191 { | 199 { |
| 192 // An event in the center of the window should always have | 200 // An event in the center of the window should always have |
| 193 // |window| as its target. | 201 // |window| as its target. |
| 194 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(80, 80), | 202 ui::MouseEvent move( |
| 195 gfx::Point(80, 80), ui::EventTimeForNow(), ui::EF_NONE, | 203 ui::ET_MOUSE_MOVED, gfx::Point(80, 80), gfx::Point(80, 80), |
| 196 ui::EF_NONE); | 204 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 205 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 197 ui::EventDispatchDetails details = | 206 ui::EventDispatchDetails details = |
| 198 event_processor()->OnEventFromSource(&move); | 207 event_processor()->OnEventFromSource(&move); |
| 199 ASSERT_FALSE(details.dispatcher_destroyed); | 208 ASSERT_FALSE(details.dispatcher_destroyed); |
| 200 EXPECT_EQ(window, move.target()); | 209 EXPECT_EQ(window, move.target()); |
| 201 } | 210 } |
| 202 { | 211 { |
| 203 // Without an EasyResizeTargeter on the container, an event | 212 // Without an EasyResizeTargeter on the container, an event |
| 204 // inside the window and within 5px of an edge should have | 213 // inside the window and within 5px of an edge should have |
| 205 // |window| as its target. | 214 // |window| as its target. |
| 206 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(32, 37), | 215 ui::MouseEvent move( |
| 207 gfx::Point(32, 37), ui::EventTimeForNow(), ui::EF_NONE, | 216 ui::ET_MOUSE_MOVED, gfx::Point(32, 37), gfx::Point(32, 37), |
| 208 ui::EF_NONE); | 217 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 218 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 209 ui::EventDispatchDetails details = | 219 ui::EventDispatchDetails details = |
| 210 event_processor()->OnEventFromSource(&move); | 220 event_processor()->OnEventFromSource(&move); |
| 211 ASSERT_FALSE(details.dispatcher_destroyed); | 221 ASSERT_FALSE(details.dispatcher_destroyed); |
| 212 EXPECT_EQ(window, move.target()); | 222 EXPECT_EQ(window, move.target()); |
| 213 } | 223 } |
| 214 | 224 |
| 215 #if !defined(OS_CHROMEOS) | 225 #if !defined(OS_CHROMEOS) |
| 216 // The non standard app frame has a easy resize targetter installed. | 226 // The non standard app frame has a easy resize targetter installed. |
| 217 scoped_ptr<views::NonClientFrameView> frame( | 227 scoped_ptr<views::NonClientFrameView> frame( |
| 218 app_window_views()->CreateNonStandardAppFrame()); | 228 app_window_views()->CreateNonStandardAppFrame()); |
| 219 { | 229 { |
| 220 // Ensure that the window has an event targeter (there should be an | 230 // Ensure that the window has an event targeter (there should be an |
| 221 // EasyResizeWindowTargeter installed). | 231 // EasyResizeWindowTargeter installed). |
| 222 EXPECT_TRUE(static_cast<ui::EventTarget*>(window)->GetEventTargeter()); | 232 EXPECT_TRUE(static_cast<ui::EventTarget*>(window)->GetEventTargeter()); |
| 223 } | 233 } |
| 224 { | 234 { |
| 225 // An event in the center of the window should always have | 235 // An event in the center of the window should always have |
| 226 // |window| as its target. | 236 // |window| as its target. |
| 227 // TODO(mgiuca): This isn't really testing anything (note that it has the | 237 // TODO(mgiuca): This isn't really testing anything (note that it has the |
| 228 // same expectation as the border case below). In the real environment, the | 238 // same expectation as the border case below). In the real environment, the |
| 229 // target will actually be the RenderWidgetHostViewAura's window that is the | 239 // target will actually be the RenderWidgetHostViewAura's window that is the |
| 230 // child of the child of |window|, whereas in the border case it *will* be | 240 // child of the child of |window|, whereas in the border case it *will* be |
| 231 // |window|. However, since this test environment does not have a | 241 // |window|. However, since this test environment does not have a |
| 232 // RenderWidgetHostViewAura, we cannot differentiate the two cases. Fix | 242 // RenderWidgetHostViewAura, we cannot differentiate the two cases. Fix |
| 233 // the test environment so that the test can assert that non-border events | 243 // the test environment so that the test can assert that non-border events |
| 234 // bubble down to a child of |window|. | 244 // bubble down to a child of |window|. |
| 235 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(80, 80), | 245 ui::MouseEvent move( |
| 236 gfx::Point(80, 80), ui::EventTimeForNow(), ui::EF_NONE, | 246 ui::ET_MOUSE_MOVED, gfx::Point(80, 80), gfx::Point(80, 80), |
| 237 ui::EF_NONE); | 247 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 248 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 238 ui::EventDispatchDetails details = | 249 ui::EventDispatchDetails details = |
| 239 event_processor()->OnEventFromSource(&move); | 250 event_processor()->OnEventFromSource(&move); |
| 240 ASSERT_FALSE(details.dispatcher_destroyed); | 251 ASSERT_FALSE(details.dispatcher_destroyed); |
| 241 EXPECT_EQ(window, move.target()); | 252 EXPECT_EQ(window, move.target()); |
| 242 } | 253 } |
| 243 { | 254 { |
| 244 // With an EasyResizeTargeter on the container, an event | 255 // With an EasyResizeTargeter on the container, an event |
| 245 // inside the window and within 5px of an edge should have | 256 // inside the window and within 5px of an edge should have |
| 246 // |window| as its target. | 257 // |window| as its target. |
| 247 ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(32, 37), | 258 ui::MouseEvent move( |
| 248 gfx::Point(32, 37), ui::EventTimeForNow(), ui::EF_NONE, | 259 ui::ET_MOUSE_MOVED, gfx::Point(32, 37), gfx::Point(32, 37), |
| 249 ui::EF_NONE); | 260 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, |
| 261 ui::PointerEventDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); |
| 250 ui::EventDispatchDetails details = | 262 ui::EventDispatchDetails details = |
| 251 event_processor()->OnEventFromSource(&move); | 263 event_processor()->OnEventFromSource(&move); |
| 252 ASSERT_FALSE(details.dispatcher_destroyed); | 264 ASSERT_FALSE(details.dispatcher_destroyed); |
| 253 EXPECT_EQ(window, move.target()); | 265 EXPECT_EQ(window, move.target()); |
| 254 } | 266 } |
| 255 #endif // defined (OS_CHROMEOS) | 267 #endif // defined (OS_CHROMEOS) |
| 256 } | 268 } |
| OLD | NEW |