OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #import "chrome/browser/cocoa/tabpose_window.h" | 5 #import "chrome/browser/cocoa/tabpose_window.h" |
6 | 6 |
7 #import <QuartzCore/QuartzCore.h> | 7 #import <QuartzCore/QuartzCore.h> |
8 | 8 |
9 #include "app/resource_bundle.h" | 9 #include "app/resource_bundle.h" |
10 #include "base/mac_util.h" | 10 #include "base/mac_util.h" |
11 #include "base/scoped_callback_factory.h" | 11 #include "base/scoped_callback_factory.h" |
12 #include "base/sys_string_conversions.h" | 12 #include "base/sys_string_conversions.h" |
13 #include "chrome/app/chrome_dll_resource.h" | |
13 #include "chrome/browser/browser_process.h" | 14 #include "chrome/browser/browser_process.h" |
14 #import "chrome/browser/cocoa/bookmark_bar_constants.h" | 15 #import "chrome/browser/cocoa/bookmark_bar_constants.h" |
15 #import "chrome/browser/cocoa/browser_window_controller.h" | 16 #import "chrome/browser/cocoa/browser_window_controller.h" |
16 #import "chrome/browser/cocoa/tab_strip_controller.h" | 17 #import "chrome/browser/cocoa/tab_strip_controller.h" |
17 #import "chrome/browser/cocoa/tab_strip_model_observer_bridge.h" | 18 #import "chrome/browser/cocoa/tab_strip_model_observer_bridge.h" |
18 #import "chrome/browser/debugger/devtools_window.h" | 19 #import "chrome/browser/debugger/devtools_window.h" |
19 #include "chrome/browser/prefs/pref_service.h" | 20 #include "chrome/browser/prefs/pref_service.h" |
20 #include "chrome/browser/renderer_host/backing_store_mac.h" | 21 #include "chrome/browser/renderer_host/backing_store_mac.h" |
21 #include "chrome/browser/renderer_host/render_view_host.h" | 22 #include "chrome/browser/renderer_host/render_view_host.h" |
22 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" | 23 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
455 // Computes coordinates for |tiles_|. | 456 // Computes coordinates for |tiles_|. |
456 void Layout(NSRect containing_rect); | 457 void Layout(NSRect containing_rect); |
457 | 458 |
458 int selected_index() const { return selected_index_; } | 459 int selected_index() const { return selected_index_; } |
459 void set_selected_index(int index); | 460 void set_selected_index(int index); |
460 | 461 |
461 const Tile& selected_tile() const { return *tiles_[selected_index()]; } | 462 const Tile& selected_tile() const { return *tiles_[selected_index()]; } |
462 Tile& tile_at(int index) { return *tiles_[index]; } | 463 Tile& tile_at(int index) { return *tiles_[index]; } |
463 const Tile& tile_at(int index) const { return *tiles_[index]; } | 464 const Tile& tile_at(int index) const { return *tiles_[index]; } |
464 | 465 |
466 // These return which index needs to be selected when the user presses | |
467 // up, down, left, or right respectively. | |
468 int up_index() const; | |
469 int down_index() const; | |
470 int left_index() const; | |
471 int right_index() const; | |
472 | |
473 // These return which index needs to be selected on tab / shift-tab. | |
474 int next_index() const; | |
475 int previous_index() const; | |
476 | |
465 // Inserts a new Tile object containing |contents| at |index|. Does no | 477 // Inserts a new Tile object containing |contents| at |index|. Does no |
466 // relayout. | 478 // relayout. |
467 void InsertTileAt(int index, TabContents* contents); | 479 void InsertTileAt(int index, TabContents* contents); |
468 | 480 |
469 // Removes the Tile object at |index|. Does no relayout. | 481 // Removes the Tile object at |index|. Does no relayout. |
470 void RemoveTileAt(int index); | 482 void RemoveTileAt(int index); |
471 | 483 |
472 // Moves the Tile object at |from_index| to |to_index|. Since this doesn't | 484 // Moves the Tile object at |from_index| to |to_index|. Since this doesn't |
473 // change the number of tiles, relayout can be done just by swapping the | 485 // change the number of tiles, relayout can be done just by swapping the |
474 // tile rectangles in the index interval [from_index, to_index], so this does | 486 // tile rectangles in the index interval [from_index, to_index], so this does |
475 // layout. | 487 // layout. |
476 void MoveTileFromTo(int from_index, int to_index); | 488 void MoveTileFromTo(int from_index, int to_index); |
477 | 489 |
478 private: | 490 private: |
491 int count_x() const { | |
492 return ceilf(tiles_.size() / static_cast<float>(count_y_)); | |
493 } | |
494 int count_y() const { | |
495 return count_y_; | |
496 } | |
497 int last_row_count_x() const { | |
498 return tiles_.size() - count_x() * (count_y() - 1); | |
499 } | |
500 int tiles_in_row(int row) const { | |
501 return row != count_y() - 1 ? count_x() : last_row_count_x(); | |
502 } | |
503 void index_to_tile_xy(int index, int* tile_x, int* tile_y) const { | |
504 *tile_x = index % count_x(); | |
505 *tile_y = index / count_x(); | |
506 } | |
507 int tile_xy_to_index(int tile_x, int tile_y) const { | |
508 return tile_y * count_x() + tile_x; | |
509 } | |
510 | |
479 ScopedVector<Tile> tiles_; | 511 ScopedVector<Tile> tiles_; |
480 int selected_index_; | 512 int selected_index_; |
513 int count_y_; | |
481 | 514 |
482 DISALLOW_COPY_AND_ASSIGN(TileSet); | 515 DISALLOW_COPY_AND_ASSIGN(TileSet); |
483 }; | 516 }; |
484 | 517 |
485 void TileSet::Build(TabStripModel* source_model) { | 518 void TileSet::Build(TabStripModel* source_model) { |
486 selected_index_ = source_model->selected_index(); | 519 selected_index_ = source_model->selected_index(); |
487 tiles_.resize(source_model->count()); | 520 tiles_.resize(source_model->count()); |
488 for (size_t i = 0; i < tiles_.size(); ++i) { | 521 for (size_t i = 0; i < tiles_.size(); ++i) { |
489 tiles_[i] = new Tile; | 522 tiles_[i] = new Tile; |
490 tiles_[i]->contents_ = source_model->GetTabContentsAt(i); | 523 tiles_[i]->contents_ = source_model->GetTabContentsAt(i); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
535 // |count_x * count_y >= tile_count|, and such that wasted space is minimized. | 568 // |count_x * count_y >= tile_count|, and such that wasted space is minimized. |
536 // See the comments in | 569 // See the comments in |
537 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding()| for a more | 570 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding()| for a more |
538 // detailed discussion. | 571 // detailed discussion. |
539 // TODO(thakis): It might be good enough to choose |count_x| and |count_y| | 572 // TODO(thakis): It might be good enough to choose |count_x| and |count_y| |
540 // such that count_x / count_y is roughly equal to |aspect|? | 573 // such that count_x / count_y is roughly equal to |aspect|? |
541 double fny = FitNRectsWithAspectIntoBoundingSizeWithConstantPadding( | 574 double fny = FitNRectsWithAspectIntoBoundingSizeWithConstantPadding( |
542 tile_count, aspect, | 575 tile_count, aspect, |
543 container_width, container_height - kFooterExtraHeight, | 576 container_width, container_height - kFooterExtraHeight, |
544 kSmallPaddingX, kSmallPaddingY + kFooterExtraHeight); | 577 kSmallPaddingX, kSmallPaddingY + kFooterExtraHeight); |
545 int count_y(roundf(fny)); | 578 count_y_ = roundf(fny); |
546 int count_x(ceilf(tile_count / float(count_y))); | |
547 int last_row_count_x = tile_count - count_x * (count_y - 1); | |
548 | 579 |
549 // Now that |count_x| and |count_y| are known, it's straightforward to compute | 580 // Now that |count_x()| and |count_y_| are known, it's straightforward to |
550 // thumbnail width/height. See comment in | 581 // compute thumbnail width/height. See comment in |
551 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding| for the derivation | 582 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding| for the derivation |
552 // of these two formulas. | 583 // of these two formulas. |
553 int small_width = | 584 int small_width = |
554 floor((container_width + kSmallPaddingX) / float(count_x) - | 585 floor((container_width + kSmallPaddingX) / static_cast<float>(count_x()) - |
555 kSmallPaddingX); | 586 kSmallPaddingX); |
556 int small_height = | 587 int small_height = |
557 floor((container_height + kSmallPaddingY) / float(count_y) - | 588 floor((container_height + kSmallPaddingY) / static_cast<float>(count_y_) - |
558 (kSmallPaddingY + kFooterExtraHeight)); | 589 (kSmallPaddingY + kFooterExtraHeight)); |
559 | 590 |
560 // |small_width / small_height| has only roughly an aspect ratio of |aspect|. | 591 // |small_width / small_height| has only roughly an aspect ratio of |aspect|. |
561 // Shrink the thumbnail rect to make the aspect ratio fit exactly, and add | 592 // Shrink the thumbnail rect to make the aspect ratio fit exactly, and add |
562 // the extra space won by shrinking to the outer padding. | 593 // the extra space won by shrinking to the outer padding. |
563 int smallExtraPaddingLeft = 0; | 594 int smallExtraPaddingLeft = 0; |
564 int smallExtraPaddingTop = 0; | 595 int smallExtraPaddingTop = 0; |
565 if (aspect > small_width/float(small_height)) { | 596 if (aspect > small_width/static_cast<float>(small_height)) { |
566 small_height = small_width / aspect; | 597 small_height = small_width / aspect; |
567 CGFloat all_tiles_height = | 598 CGFloat all_tiles_height = |
568 (small_height + kSmallPaddingY + kFooterExtraHeight) * count_y - | 599 (small_height + kSmallPaddingY + kFooterExtraHeight) * count_y() - |
569 (kSmallPaddingY + kFooterExtraHeight); | 600 (kSmallPaddingY + kFooterExtraHeight); |
570 smallExtraPaddingTop = (container_height - all_tiles_height)/2; | 601 smallExtraPaddingTop = (container_height - all_tiles_height)/2; |
571 } else { | 602 } else { |
572 small_width = small_height * aspect; | 603 small_width = small_height * aspect; |
573 CGFloat all_tiles_width = | 604 CGFloat all_tiles_width = |
574 (small_width + kSmallPaddingX) * count_x - kSmallPaddingX; | 605 (small_width + kSmallPaddingX) * count_x() - kSmallPaddingX; |
575 smallExtraPaddingLeft = (container_width - all_tiles_width)/2; | 606 smallExtraPaddingLeft = (container_width - all_tiles_width)/2; |
576 } | 607 } |
577 | 608 |
578 // Compute inter-tile padding in the zoomed-out view. | 609 // Compute inter-tile padding in the zoomed-out view. |
579 CGFloat scale_small_to_big = NSWidth(containing_rect) / float(small_width); | 610 CGFloat scale_small_to_big = |
611 NSWidth(containing_rect) / static_cast<float>(small_width); | |
580 CGFloat big_padding_x = kSmallPaddingX * scale_small_to_big; | 612 CGFloat big_padding_x = kSmallPaddingX * scale_small_to_big; |
581 CGFloat big_padding_y = | 613 CGFloat big_padding_y = |
582 (kSmallPaddingY + kFooterExtraHeight) * scale_small_to_big; | 614 (kSmallPaddingY + kFooterExtraHeight) * scale_small_to_big; |
583 | 615 |
584 // Now all dimensions are known. Lay out all tiles on a regular grid: | 616 // Now all dimensions are known. Lay out all tiles on a regular grid: |
585 // X X X X | 617 // X X X X |
586 // X X X X | 618 // X X X X |
587 // X X | 619 // X X |
588 for (int row = 0, i = 0; i < tile_count; ++row) { | 620 for (int row = 0, i = 0; i < tile_count; ++row) { |
589 for (int col = 0; col < count_x && i < tile_count; ++col, ++i) { | 621 for (int col = 0; col < count_x() && i < tile_count; ++col, ++i) { |
590 // Compute the smalled, zoomed-out thumbnail rect. | 622 // Compute the smalled, zoomed-out thumbnail rect. |
591 tiles_[i]->thumb_rect_.size = NSMakeSize(small_width, small_height); | 623 tiles_[i]->thumb_rect_.size = NSMakeSize(small_width, small_height); |
592 | 624 |
593 int small_x = col * (small_width + kSmallPaddingX) + | 625 int small_x = col * (small_width + kSmallPaddingX) + |
594 kSmallPaddingLeft + smallExtraPaddingLeft; | 626 kSmallPaddingLeft + smallExtraPaddingLeft; |
595 int small_y = row * (small_height + kSmallPaddingY + kFooterExtraHeight) + | 627 int small_y = row * (small_height + kSmallPaddingY + kFooterExtraHeight) + |
596 kSmallPaddingTop + smallExtraPaddingTop; | 628 kSmallPaddingTop + smallExtraPaddingTop; |
597 | 629 |
598 tiles_[i]->thumb_rect_.origin = NSMakePoint( | 630 tiles_[i]->thumb_rect_.origin = NSMakePoint( |
599 small_x, NSHeight(containing_rect) - small_y - small_height); | 631 small_x, NSHeight(containing_rect) - small_y - small_height); |
(...skipping 22 matching lines...) Expand all Loading... | |
622 int big_x = col * (NSWidth(containing_rect) + big_padding_x); | 654 int big_x = col * (NSWidth(containing_rect) + big_padding_x); |
623 int big_y = row * (NSHeight(containing_rect) + big_padding_y); | 655 int big_y = row * (NSHeight(containing_rect) + big_padding_y); |
624 tiles_[i]->start_thumb_rect_.origin = NSMakePoint(big_x, -big_y); | 656 tiles_[i]->start_thumb_rect_.origin = NSMakePoint(big_x, -big_y); |
625 } | 657 } |
626 } | 658 } |
627 | 659 |
628 // Go through last row and center it: | 660 // Go through last row and center it: |
629 // X X X X | 661 // X X X X |
630 // X X X X | 662 // X X X X |
631 // X X | 663 // X X |
632 int last_row_empty_tiles_x = count_x - last_row_count_x; | 664 int last_row_empty_tiles_x = count_x() - last_row_count_x(); |
633 CGFloat small_last_row_shift_x = | 665 CGFloat small_last_row_shift_x = |
634 last_row_empty_tiles_x * (small_width + kSmallPaddingX) / 2; | 666 last_row_empty_tiles_x * (small_width + kSmallPaddingX) / 2; |
635 CGFloat big_last_row_shift_x = | 667 CGFloat big_last_row_shift_x = |
636 last_row_empty_tiles_x * (NSWidth(containing_rect) + big_padding_x) / 2; | 668 last_row_empty_tiles_x * (NSWidth(containing_rect) + big_padding_x) / 2; |
637 for (int i = tile_count - last_row_count_x; i < tile_count; ++i) { | 669 for (int i = tile_count - last_row_count_x(); i < tile_count; ++i) { |
638 tiles_[i]->thumb_rect_.origin.x += small_last_row_shift_x; | 670 tiles_[i]->thumb_rect_.origin.x += small_last_row_shift_x; |
639 tiles_[i]->start_thumb_rect_.origin.x += big_last_row_shift_x; | 671 tiles_[i]->start_thumb_rect_.origin.x += big_last_row_shift_x; |
640 tiles_[i]->favicon_rect_.origin.x += small_last_row_shift_x; | 672 tiles_[i]->favicon_rect_.origin.x += small_last_row_shift_x; |
641 tiles_[i]->title_rect_.origin.x += small_last_row_shift_x; | 673 tiles_[i]->title_rect_.origin.x += small_last_row_shift_x; |
642 } | 674 } |
643 } | 675 } |
644 | 676 |
645 void TileSet::set_selected_index(int index) { | 677 void TileSet::set_selected_index(int index) { |
646 CHECK_GE(index, 0); | 678 CHECK_GE(index, 0); |
647 CHECK_LT(index, static_cast<int>(tiles_.size())); | 679 CHECK_LT(index, static_cast<int>(tiles_.size())); |
648 selected_index_ = index; | 680 selected_index_ = index; |
649 } | 681 } |
650 | 682 |
683 // Given a |value| in [0, from_scale), map it into [0, to_scale) such that: | |
684 // * [0, from_scale) ends up in the middle of [0, to_scale) if the latter is | |
685 // a bigger range | |
686 // * The middle of [0, from_scale) is mapped to [0, to_scale), and the parts | |
687 // of the former that don't fit are mapped to 0 and to_scale - respectively | |
688 // if the former is a bigger range. | |
689 static int rescale(int value, int from_scale, int to_scale) { | |
690 int left = (to_scale - from_scale) / 2; | |
691 int result = value + left; | |
692 if (result < 0) | |
693 return 0; | |
694 if (result >= to_scale) | |
695 return to_scale - 1; | |
696 return result; | |
697 } | |
698 | |
699 int TileSet::up_index() const { | |
700 int tile_x, tile_y; | |
701 index_to_tile_xy(selected_index(), &tile_x, &tile_y); | |
702 tile_y -= 1; | |
703 if (tile_y == count_y() - 2) { | |
704 // Transition from last row to second-to-last row. | |
705 tile_x = rescale(tile_x, last_row_count_x(), count_x()); | |
706 } else if (tile_y < 0) { | |
707 // Transition from first row to last row. | |
708 tile_x = rescale(tile_x, count_x(), last_row_count_x()); | |
709 tile_y = count_y() - 1; | |
710 } | |
711 return tile_xy_to_index(tile_x, tile_y); | |
712 } | |
713 | |
714 int TileSet::down_index() const { | |
715 int tile_x, tile_y; | |
716 index_to_tile_xy(selected_index(), &tile_x, &tile_y); | |
717 tile_y += 1; | |
718 if (tile_y == count_y() - 1) { | |
719 // Transition from second-to-last row to last row. | |
720 tile_x = rescale(tile_x, count_x(), last_row_count_x()); | |
721 } else if (tile_y >= count_y()) { | |
722 // Transition from last row to first row. | |
723 tile_x = rescale(tile_x, last_row_count_x(), count_x()); | |
724 tile_y = 0; | |
725 } | |
726 return tile_xy_to_index(tile_x, tile_y); | |
727 } | |
728 | |
729 int TileSet::left_index() const { | |
730 int tile_x, tile_y; | |
731 index_to_tile_xy(selected_index(), &tile_x, &tile_y); | |
732 tile_x -= 1; | |
733 if (tile_x < 0) | |
734 tile_x = tiles_in_row(tile_y) - 1; | |
735 return tile_xy_to_index(tile_x, tile_y); | |
736 } | |
737 | |
738 int TileSet::right_index() const { | |
739 int tile_x, tile_y; | |
740 index_to_tile_xy(selected_index(), &tile_x, &tile_y); | |
741 tile_x += 1; | |
742 if (tile_x >= tiles_in_row(tile_y)) | |
743 tile_x = 0; | |
744 return tile_xy_to_index(tile_x, tile_y); | |
745 } | |
746 | |
747 int TileSet::next_index() const { | |
748 int new_index = selected_index() + 1; | |
749 if (new_index >= static_cast<int>(tiles_.size())) | |
viettrungluu
2010/09/16 20:07:21
I think this would be a fine place to use ?:.
Nico
2010/09/16 20:08:54
but then i need to write "+1" twice!
| |
750 new_index = 0; | |
751 return new_index; | |
752 } | |
753 | |
754 int TileSet::previous_index() const { | |
755 int new_index = selected_index() - 1; | |
756 if (new_index < 0) | |
viettrungluu
2010/09/16 20:07:21
Ditto.
| |
757 new_index = tiles_.size() - 1; | |
758 return new_index; | |
759 } | |
760 | |
651 void TileSet::InsertTileAt(int index, TabContents* contents) { | 761 void TileSet::InsertTileAt(int index, TabContents* contents) { |
652 tiles_.insert(tiles_.begin() + index, new Tile); | 762 tiles_.insert(tiles_.begin() + index, new Tile); |
653 tiles_[index]->contents_ = contents; | 763 tiles_[index]->contents_ = contents; |
654 } | 764 } |
655 | 765 |
656 void TileSet::RemoveTileAt(int index) { | 766 void TileSet::RemoveTileAt(int index) { |
657 tiles_.erase(tiles_.begin() + index); | 767 tiles_.erase(tiles_.begin() + index); |
658 } | 768 } |
659 | 769 |
660 // Moves the Tile object at |from_index| to |to_index|. Also updates rectangles | 770 // Moves the Tile object at |from_index| to |to_index|. Also updates rectangles |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
928 // there's a one frame flash of grey at the beginning of the animation | 1038 // there's a one frame flash of grey at the beginning of the animation |
929 // (|bgLayer_| showing through with none of its children visible yet). | 1039 // (|bgLayer_| showing through with none of its children visible yet). |
930 [[self contentView] setLayer:rootLayer_]; | 1040 [[self contentView] setLayer:rootLayer_]; |
931 [[self contentView] setWantsLayer:YES]; | 1041 [[self contentView] setWantsLayer:YES]; |
932 } | 1042 } |
933 | 1043 |
934 - (BOOL)canBecomeKeyWindow { | 1044 - (BOOL)canBecomeKeyWindow { |
935 return YES; | 1045 return YES; |
936 } | 1046 } |
937 | 1047 |
1048 // Handle key events that should be executed repeatedly while the key is down. | |
938 - (void)keyDown:(NSEvent*)event { | 1049 - (void)keyDown:(NSEvent*)event { |
939 // Overridden to prevent beeps. | 1050 if (state_ == tabpose::kFadingOut) |
1051 return; | |
1052 NSString* characters = [event characters]; | |
1053 if ([characters length] < 1) | |
1054 return; | |
1055 | |
1056 unichar character = [characters characterAtIndex:0]; | |
1057 int newIndex = -1; | |
1058 switch (character) { | |
1059 case NSUpArrowFunctionKey: | |
1060 newIndex = tileSet_->up_index(); | |
1061 break; | |
1062 case NSDownArrowFunctionKey: | |
1063 newIndex = tileSet_->down_index(); | |
1064 break; | |
1065 case NSLeftArrowFunctionKey: | |
1066 newIndex = tileSet_->left_index(); | |
1067 break; | |
1068 case NSRightArrowFunctionKey: | |
1069 newIndex = tileSet_->right_index(); | |
1070 break; | |
1071 case NSTabCharacter: | |
1072 newIndex = tileSet_->next_index(); | |
1073 break; | |
1074 case NSBackTabCharacter: | |
1075 newIndex = tileSet_->previous_index(); | |
1076 break; | |
1077 } | |
1078 if (newIndex != -1) | |
1079 [self selectTileAtIndexWithoutAnimation:newIndex]; | |
940 } | 1080 } |
941 | 1081 |
1082 // Handle keyboard events that should be executed once when the key is released. | |
942 - (void)keyUp:(NSEvent*)event { | 1083 - (void)keyUp:(NSEvent*)event { |
943 if (state_ == tabpose::kFadingOut) | 1084 if (state_ == tabpose::kFadingOut) |
944 return; | 1085 return; |
945 | |
946 NSString* characters = [event characters]; | 1086 NSString* characters = [event characters]; |
947 if ([characters length] < 1) | 1087 if ([characters length] < 1) |
948 return; | 1088 return; |
949 | 1089 |
950 unichar character = [characters characterAtIndex:0]; | 1090 unichar character = [characters characterAtIndex:0]; |
951 switch (character) { | 1091 switch (character) { |
952 case NSEnterCharacter: | 1092 case NSEnterCharacter: |
953 case NSNewlineCharacter: | 1093 case NSNewlineCharacter: |
954 case NSCarriageReturnCharacter: | 1094 case NSCarriageReturnCharacter: |
955 case ' ': | 1095 case ' ': |
956 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | 1096 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; |
957 break; | 1097 break; |
958 case '\e': // Escape | 1098 case '\e': // Escape |
959 tileSet_->set_selected_index(tabStripModel_->selected_index()); | 1099 tileSet_->set_selected_index(tabStripModel_->selected_index()); |
960 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | 1100 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; |
961 break; | 1101 break; |
962 // TODO(thakis): Support moving the selection via arrow keys. | |
963 } | 1102 } |
964 } | 1103 } |
965 | 1104 |
1105 // Handle keyboard events that contain cmd or ctrl. | |
1106 - (BOOL)performKeyEquivalent:(NSEvent*)event { | |
1107 if (state_ == tabpose::kFadingOut) | |
1108 return NO; | |
1109 NSString* characters = [event characters]; | |
1110 if ([characters length] < 1) | |
1111 return NO; | |
1112 unichar character = [characters characterAtIndex:0]; | |
1113 if ([event modifierFlags] & NSCommandKeyMask) { | |
1114 if (character >= '1' && character <= '9') { | |
1115 int index = | |
1116 character == '9' ? tabStripModel_->count() - 1 : character - '1'; | |
1117 if (index < tabStripModel_->count()) { | |
1118 tileSet_->set_selected_index(index); | |
1119 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | |
1120 return YES; | |
1121 } | |
1122 } | |
1123 } | |
1124 return NO; | |
1125 } | |
1126 | |
966 - (void)mouseMoved:(NSEvent*)event { | 1127 - (void)mouseMoved:(NSEvent*)event { |
967 int newIndex = -1; | 1128 int newIndex = -1; |
968 CGPoint p = NSPointToCGPoint([event locationInWindow]); | 1129 CGPoint p = NSPointToCGPoint([event locationInWindow]); |
969 for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) { | 1130 for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) { |
970 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i]; | 1131 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i]; |
971 CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_]; | 1132 CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_]; |
972 if ([static_cast<CALayer*>([layer presentationLayer]) containsPoint:lp]) | 1133 if ([static_cast<CALayer*>([layer presentationLayer]) containsPoint:lp]) |
973 newIndex = i; | 1134 newIndex = i; |
974 } | 1135 } |
975 if (newIndex >= 0) | 1136 if (newIndex >= 0) |
(...skipping 14 matching lines...) Expand all Loading... | |
990 [[self parentWindow] removeChildWindow:self]; | 1151 [[self parentWindow] removeChildWindow:self]; |
991 | 1152 |
992 // We're dealloc'd in an autorelease pool – by then the observer registry | 1153 // We're dealloc'd in an autorelease pool – by then the observer registry |
993 // might be dead, so explicitly reset the observer now. | 1154 // might be dead, so explicitly reset the observer now. |
994 tabStripModelObserverBridge_.reset(); | 1155 tabStripModelObserverBridge_.reset(); |
995 | 1156 |
996 [super close]; | 1157 [super close]; |
997 } | 1158 } |
998 | 1159 |
999 - (void)commandDispatch:(id)sender { | 1160 - (void)commandDispatch:(id)sender { |
1000 // Without this, -validateUserInterfaceItem: is not called. | 1161 if ([sender tag] == IDC_TABPOSE) |
1162 [self fadeAway:NO]; | |
1001 } | 1163 } |
1002 | 1164 |
1003 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { | 1165 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { |
1004 // Disable all browser-related menu items. | 1166 // Disable all browser-related menu items except the tab overview toggle. |
1005 return NO; | 1167 SEL action = [item action]; |
1168 NSInteger tag = [item tag]; | |
1169 return action == @selector(commandDispatch:) && tag == IDC_TABPOSE; | |
1006 } | 1170 } |
1007 | 1171 |
1008 - (void)fadeAway:(BOOL)slomo { | 1172 - (void)fadeAway:(BOOL)slomo { |
1009 if (state_ == tabpose::kFadingOut) | 1173 if (state_ == tabpose::kFadingOut) |
1010 return; | 1174 return; |
1011 | 1175 |
1012 state_ = tabpose::kFadingOut; | 1176 state_ = tabpose::kFadingOut; |
1013 [self setAcceptsMouseMovedEvents:NO]; | 1177 [self setAcceptsMouseMovedEvents:NO]; |
1014 | 1178 |
1015 // Select chosen tab. | 1179 // Select chosen tab. |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1253 tile.set_tab_contents(contents); | 1417 tile.set_tab_contents(contents); |
1254 ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index]; | 1418 ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index]; |
1255 [thumbLayer setTabContents:contents]; | 1419 [thumbLayer setTabContents:contents]; |
1256 } | 1420 } |
1257 | 1421 |
1258 - (void)tabStripModelDeleted { | 1422 - (void)tabStripModelDeleted { |
1259 [self close]; | 1423 [self close]; |
1260 } | 1424 } |
1261 | 1425 |
1262 @end | 1426 @end |
OLD | NEW |