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 "base/mac/scoped_nsautorelease_pool.h" | 7 #include "base/mac/scoped_nsautorelease_pool.h" |
| 8 #include "base/utf_string_conversions.h" |
8 #include "content/browser/browser_thread_impl.h" | 9 #include "content/browser/browser_thread_impl.h" |
9 #include "content/browser/renderer_host/test_render_view_host.h" | 10 #include "content/browser/renderer_host/test_render_view_host.h" |
10 #include "content/common/gpu/gpu_messages.h" | 11 #include "content/common/gpu/gpu_messages.h" |
11 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
12 #include "ui/base/test/cocoa_test_event_utils.h" | 13 #include "ui/base/test/cocoa_test_event_utils.h" |
13 #import "ui/base/test/ui_cocoa_test_helper.h" | 14 #import "ui/base/test/ui_cocoa_test_helper.h" |
14 #include "webkit/plugins/npapi/webplugin.h" | 15 #include "webkit/plugins/npapi/webplugin.h" |
15 | 16 |
16 namespace content { | 17 namespace content { |
17 | 18 |
| 19 namespace { |
| 20 |
| 21 // Generates the |length| of composition rectangle vector and save them to |
| 22 // |output|. It starts from |origin| and each rectangle contains |unit_size|. |
| 23 void GenerateCompositionRectArray(const gfx::Point& origin, |
| 24 const gfx::Size& unit_size, |
| 25 size_t length, |
| 26 const std::vector<size_t>& break_points, |
| 27 std::vector<gfx::Rect>* output) { |
| 28 DCHECK(output); |
| 29 output->clear(); |
| 30 |
| 31 std::queue<int> break_point_queue; |
| 32 for (size_t i = 0; i < break_points.size(); ++i) |
| 33 break_point_queue.push(break_points[i]); |
| 34 break_point_queue.push(length); |
| 35 size_t next_break_point = break_point_queue.front(); |
| 36 break_point_queue.pop(); |
| 37 |
| 38 gfx::Rect current_rect(origin, unit_size); |
| 39 for (size_t i = 0; i < length; ++i) { |
| 40 if (i == next_break_point) { |
| 41 current_rect.set_x(origin.x()); |
| 42 current_rect.set_y(current_rect.y() + current_rect.height()); |
| 43 next_break_point = break_point_queue.front(); |
| 44 break_point_queue.pop(); |
| 45 } |
| 46 output->push_back(current_rect); |
| 47 current_rect.set_x(current_rect.right()); |
| 48 } |
| 49 } |
| 50 |
| 51 gfx::Rect GetExpectedRect(const gfx::Point& origin, |
| 52 const gfx::Size& size, |
| 53 const ui::Range& range, |
| 54 int line_no) { |
| 55 return gfx::Rect( |
| 56 origin.x() + range.start() * size.width(), |
| 57 origin.y() + line_no * size.height(), |
| 58 range.length() * size.width(), |
| 59 size.height()); |
| 60 } |
| 61 |
| 62 } // namespace |
| 63 |
18 class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness { | 64 class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness { |
19 public: | 65 public: |
20 RenderWidgetHostViewMacTest() : old_rwhv_(NULL), rwhv_mac_(NULL) {} | 66 RenderWidgetHostViewMacTest() : old_rwhv_(NULL), rwhv_mac_(NULL) {} |
21 | 67 |
22 virtual void SetUp() { | 68 virtual void SetUp() { |
23 RenderViewHostImplTestHarness::SetUp(); | 69 RenderViewHostImplTestHarness::SetUp(); |
24 | 70 |
25 // TestRenderViewHost's destruction assumes that its view is a | 71 // TestRenderViewHost's destruction assumes that its view is a |
26 // TestRenderWidgetHostView, so store its view and reset it back to the | 72 // TestRenderWidgetHostView, so store its view and reset it back to the |
27 // stored view in |TearDown()|. | 73 // stored view in |TearDown()|. |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 | 244 |
199 // Clean up. | 245 // Clean up. |
200 rwhv_mac_->DestroyFakePluginWindowHandle(accelerated_handle); | 246 rwhv_mac_->DestroyFakePluginWindowHandle(accelerated_handle); |
201 } | 247 } |
202 | 248 |
203 TEST_F(RenderWidgetHostViewMacTest, Fullscreen) { | 249 TEST_F(RenderWidgetHostViewMacTest, Fullscreen) { |
204 rwhv_mac_->InitAsFullscreen(NULL); | 250 rwhv_mac_->InitAsFullscreen(NULL); |
205 EXPECT_TRUE(rwhv_mac_->pepper_fullscreen_window()); | 251 EXPECT_TRUE(rwhv_mac_->pepper_fullscreen_window()); |
206 } | 252 } |
207 | 253 |
| 254 TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharaacterRangeCaretCase) { |
| 255 const string16 kDummyString = UTF8ToUTF16("hogehoge"); |
| 256 const size_t kDummyOffset = 0; |
| 257 |
| 258 gfx::Rect caret_rect(10, 11, 0, 10); |
| 259 ui::Range caret_range(0, 0); |
| 260 |
| 261 NSRect rect; |
| 262 NSRange actual_range; |
| 263 rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range); |
| 264 rwhv_mac_->SelectionBoundsChanged(caret_rect, caret_rect); |
| 265 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 266 caret_range.ToNSRange(), |
| 267 &rect, |
| 268 &actual_range)); |
| 269 EXPECT_EQ(caret_rect, gfx::Rect(NSRectToCGRect(rect))); |
| 270 EXPECT_EQ(caret_range, ui::Range(actual_range)); |
| 271 |
| 272 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 273 ui::Range(0, 1).ToNSRange(), |
| 274 &rect, |
| 275 &actual_range)); |
| 276 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 277 ui::Range(1, 1).ToNSRange(), |
| 278 &rect, |
| 279 &actual_range)); |
| 280 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 281 ui::Range(2, 3).ToNSRange(), |
| 282 &rect, |
| 283 &actual_range)); |
| 284 |
| 285 // Caret moved. |
| 286 caret_rect = gfx::Rect(20, 11, 0, 10); |
| 287 caret_range = ui::Range(1, 1); |
| 288 rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range); |
| 289 rwhv_mac_->SelectionBoundsChanged(caret_rect, caret_rect); |
| 290 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 291 caret_range.ToNSRange(), |
| 292 &rect, |
| 293 &actual_range)); |
| 294 EXPECT_EQ(caret_rect, gfx::Rect(NSRectToCGRect(rect))); |
| 295 EXPECT_EQ(caret_range, ui::Range(actual_range)); |
| 296 |
| 297 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 298 ui::Range(0, 0).ToNSRange(), |
| 299 &rect, |
| 300 &actual_range)); |
| 301 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 302 ui::Range(1, 2).ToNSRange(), |
| 303 &rect, |
| 304 &actual_range)); |
| 305 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 306 ui::Range(2, 3).ToNSRange(), |
| 307 &rect, |
| 308 &actual_range)); |
| 309 |
| 310 // No caret. |
| 311 caret_range = ui::Range(1, 2); |
| 312 rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range); |
| 313 rwhv_mac_->SelectionBoundsChanged(caret_rect, gfx::Rect(30, 11, 0, 10)); |
| 314 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 315 ui::Range(0, 0).ToNSRange(), |
| 316 &rect, |
| 317 &actual_range)); |
| 318 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 319 ui::Range(0, 1).ToNSRange(), |
| 320 &rect, |
| 321 &actual_range)); |
| 322 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 323 ui::Range(1, 1).ToNSRange(), |
| 324 &rect, |
| 325 &actual_range)); |
| 326 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 327 ui::Range(1, 2).ToNSRange(), |
| 328 &rect, |
| 329 &actual_range)); |
| 330 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 331 ui::Range(2, 2).ToNSRange(), |
| 332 &rect, |
| 333 &actual_range)); |
| 334 } |
| 335 |
| 336 TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionSinglelineCase) { |
| 337 const gfx::Point kOrigin(10, 11); |
| 338 const gfx::Size kBoundsUnit(10, 20); |
| 339 |
| 340 // If there are no update from renderer, always returned caret position. |
| 341 NSRect rect; |
| 342 NSRange actual_range; |
| 343 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 344 ui::Range(0, 0).ToNSRange(), |
| 345 &rect, |
| 346 &actual_range)); |
| 347 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 348 ui::Range(0, 1).ToNSRange(), |
| 349 &rect, |
| 350 &actual_range)); |
| 351 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 352 ui::Range(1, 0).ToNSRange(), |
| 353 &rect, |
| 354 &actual_range)); |
| 355 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 356 ui::Range(1, 1).ToNSRange(), |
| 357 &rect, |
| 358 &actual_range)); |
| 359 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 360 ui::Range(1, 2).ToNSRange(), |
| 361 &rect, |
| 362 &actual_range)); |
| 363 |
| 364 const int kCompositionLength = 10; |
| 365 std::vector<gfx::Rect> composition_bounds; |
| 366 const int kCompositionStart = 3; |
| 367 const ui::Range kCompositionRange(kCompositionStart, |
| 368 kCompositionStart + kCompositionLength); |
| 369 GenerateCompositionRectArray(kOrigin, |
| 370 kBoundsUnit, |
| 371 kCompositionLength, |
| 372 std::vector<size_t>(), |
| 373 &composition_bounds); |
| 374 rwhv_mac_->ImeCompositionRangeChanged(kCompositionRange, composition_bounds); |
| 375 |
| 376 // Out of range requests will return caret position. |
| 377 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 378 ui::Range(0, 0).ToNSRange(), |
| 379 &rect, |
| 380 &actual_range)); |
| 381 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 382 ui::Range(1, 1).ToNSRange(), |
| 383 &rect, |
| 384 &actual_range)); |
| 385 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 386 ui::Range(1, 2).ToNSRange(), |
| 387 &rect, |
| 388 &actual_range)); |
| 389 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 390 ui::Range(2, 2).ToNSRange(), |
| 391 &rect, |
| 392 &actual_range)); |
| 393 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 394 ui::Range(13, 14).ToNSRange(), |
| 395 &rect, |
| 396 &actual_range)); |
| 397 EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 398 ui::Range(14, 15).ToNSRange(), |
| 399 &rect, |
| 400 &actual_range)); |
| 401 |
| 402 for (int i = 0; i <= kCompositionLength; ++i) { |
| 403 for (int j = 0; j <= kCompositionLength - i; ++j) { |
| 404 const ui::Range range(i, i + j); |
| 405 const gfx::Rect expected_rect = GetExpectedRect(kOrigin, |
| 406 kBoundsUnit, |
| 407 range, |
| 408 0); |
| 409 const NSRange request_range = ui::Range( |
| 410 kCompositionStart + range.start(), |
| 411 kCompositionStart + range.end()).ToNSRange(); |
| 412 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
| 413 request_range, |
| 414 &rect, |
| 415 &actual_range)); |
| 416 EXPECT_EQ(ui::Range(request_range), ui::Range(actual_range)); |
| 417 EXPECT_EQ(expected_rect, gfx::Rect(NSRectToCGRect(rect))); |
| 418 } |
| 419 } |
| 420 } |
| 421 |
| 422 TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionMultilineCase) { |
| 423 const gfx::Point kOrigin(10, 11); |
| 424 const gfx::Size kBoundsUnit(10, 20); |
| 425 NSRect rect; |
| 426 |
| 427 const int kCompositionLength = 30; |
| 428 std::vector<gfx::Rect> composition_bounds; |
| 429 const ui::Range kCompositionRange(0, kCompositionLength); |
| 430 // Set breaking point at 10 and 20. |
| 431 std::vector<size_t> break_points; |
| 432 break_points.push_back(10); |
| 433 break_points.push_back(20); |
| 434 GenerateCompositionRectArray(kOrigin, |
| 435 kBoundsUnit, |
| 436 kCompositionLength, |
| 437 break_points, |
| 438 &composition_bounds); |
| 439 rwhv_mac_->ImeCompositionRangeChanged(kCompositionRange, composition_bounds); |
| 440 |
| 441 // Range doesn't contain line breaking point. |
| 442 ui::Range range; |
| 443 range = ui::Range(5, 8); |
| 444 NSRange actual_range; |
| 445 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 446 &rect, |
| 447 &actual_range)); |
| 448 EXPECT_EQ(range, ui::Range(actual_range)); |
| 449 EXPECT_EQ( |
| 450 GetExpectedRect(kOrigin, kBoundsUnit, range, 0), |
| 451 gfx::Rect(NSRectToCGRect(rect))); |
| 452 range = ui::Range(15, 18); |
| 453 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 454 &rect, |
| 455 &actual_range)); |
| 456 EXPECT_EQ(range, ui::Range(actual_range)); |
| 457 EXPECT_EQ( |
| 458 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 8), 1), |
| 459 gfx::Rect(NSRectToCGRect(rect))); |
| 460 range = ui::Range(25, 28); |
| 461 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 462 &rect, |
| 463 &actual_range)); |
| 464 EXPECT_EQ(range, ui::Range(actual_range)); |
| 465 EXPECT_EQ( |
| 466 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 8), 2), |
| 467 gfx::Rect(NSRectToCGRect(rect))); |
| 468 |
| 469 // Range contains line breaking point. |
| 470 range = ui::Range(8, 12); |
| 471 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 472 &rect, |
| 473 &actual_range)); |
| 474 EXPECT_EQ(ui::Range(8, 10), ui::Range(actual_range)); |
| 475 EXPECT_EQ( |
| 476 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(8, 10), 0), |
| 477 gfx::Rect(NSRectToCGRect(rect))); |
| 478 range = ui::Range(18, 22); |
| 479 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 480 &rect, |
| 481 &actual_range)); |
| 482 EXPECT_EQ(ui::Range(18, 20), ui::Range(actual_range)); |
| 483 EXPECT_EQ( |
| 484 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(8, 10), 1), |
| 485 gfx::Rect(NSRectToCGRect(rect))); |
| 486 |
| 487 // Start point is line breaking point. |
| 488 range = ui::Range(10, 12); |
| 489 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 490 &rect, |
| 491 &actual_range)); |
| 492 EXPECT_EQ(ui::Range(10, 12), ui::Range(actual_range)); |
| 493 EXPECT_EQ( |
| 494 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 2), 1), |
| 495 gfx::Rect(NSRectToCGRect(rect))); |
| 496 range = ui::Range(20, 22); |
| 497 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 498 &rect, |
| 499 &actual_range)); |
| 500 EXPECT_EQ(ui::Range(20, 22), ui::Range(actual_range)); |
| 501 EXPECT_EQ( |
| 502 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 2), 2), |
| 503 gfx::Rect(NSRectToCGRect(rect))); |
| 504 |
| 505 // End point is line breaking point. |
| 506 range = ui::Range(5, 10); |
| 507 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 508 &rect, |
| 509 &actual_range)); |
| 510 EXPECT_EQ(ui::Range(5, 10), ui::Range(actual_range)); |
| 511 EXPECT_EQ( |
| 512 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 10), 0), |
| 513 gfx::Rect(NSRectToCGRect(rect))); |
| 514 range = ui::Range(15, 20); |
| 515 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 516 &rect, |
| 517 &actual_range)); |
| 518 EXPECT_EQ(ui::Range(15, 20), ui::Range(actual_range)); |
| 519 EXPECT_EQ( |
| 520 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 10), 1), |
| 521 gfx::Rect(NSRectToCGRect(rect))); |
| 522 |
| 523 // Start and end point are same line breaking point. |
| 524 range = ui::Range(10, 10); |
| 525 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 526 &rect, |
| 527 &actual_range)); |
| 528 EXPECT_EQ(ui::Range(10, 10), ui::Range(actual_range)); |
| 529 EXPECT_EQ( |
| 530 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 0), 1), |
| 531 gfx::Rect(NSRectToCGRect(rect))); |
| 532 range = ui::Range(20, 20); |
| 533 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 534 &rect, |
| 535 &actual_range)); |
| 536 EXPECT_EQ(ui::Range(20, 20), ui::Range(actual_range)); |
| 537 EXPECT_EQ( |
| 538 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 0), 2), |
| 539 gfx::Rect(NSRectToCGRect(rect))); |
| 540 |
| 541 // Start and end point are different line breaking point. |
| 542 range = ui::Range(10, 20); |
| 543 EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
| 544 &rect, |
| 545 &actual_range)); |
| 546 EXPECT_EQ(ui::Range(10, 20), ui::Range(actual_range)); |
| 547 EXPECT_EQ( |
| 548 GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 10), 1), |
| 549 gfx::Rect(NSRectToCGRect(rect))); |
| 550 } |
208 } // namespace content | 551 } // namespace content |
OLD | NEW |