| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/media/desktop_media_picker.h" | 5 #include "chrome/browser/ui/views/desktop_media_picker_views.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "chrome/browser/media/desktop_media_list.h" | 8 #include "chrome/browser/media/desktop_media_list.h" |
| 9 #include "chrome/browser/media/desktop_media_list_observer.h" | |
| 10 #include "chrome/browser/ui/ash/ash_util.h" | 9 #include "chrome/browser/ui/ash/ash_util.h" |
| 11 #include "chrome/browser/ui/views/constrained_window_views.h" | 10 #include "chrome/browser/ui/views/constrained_window_views.h" |
| 12 #include "components/web_modal/web_contents_modal_dialog_manager.h" | 11 #include "components/web_modal/web_contents_modal_dialog_manager.h" |
| 13 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
| 14 #include "grit/generated_resources.h" | 13 #include "grit/generated_resources.h" |
| 15 #include "ui/aura/window_tree_host.h" | 14 #include "ui/aura/window_tree_host.h" |
| 16 #include "ui/base/l10n/l10n_util.h" | 15 #include "ui/base/l10n/l10n_util.h" |
| 17 #include "ui/events/event_constants.h" | 16 #include "ui/events/event_constants.h" |
| 18 #include "ui/events/keycodes/keyboard_codes.h" | 17 #include "ui/events/keycodes/keyboard_codes.h" |
| 19 #include "ui/gfx/canvas.h" | 18 #include "ui/gfx/canvas.h" |
| 20 #include "ui/native_theme/native_theme.h" | 19 #include "ui/native_theme/native_theme.h" |
| 21 #include "ui/views/background.h" | 20 #include "ui/views/background.h" |
| 22 #include "ui/views/bubble/bubble_frame_view.h" | 21 #include "ui/views/bubble/bubble_frame_view.h" |
| 23 #include "ui/views/controls/image_view.h" | 22 #include "ui/views/controls/image_view.h" |
| 24 #include "ui/views/controls/label.h" | 23 #include "ui/views/controls/label.h" |
| 25 #include "ui/views/controls/scroll_view.h" | 24 #include "ui/views/controls/scroll_view.h" |
| 26 #include "ui/views/layout/box_layout.h" | |
| 27 #include "ui/views/layout/layout_constants.h" | 25 #include "ui/views/layout/layout_constants.h" |
| 28 #include "ui/views/widget/widget.h" | 26 #include "ui/views/widget/widget.h" |
| 29 #include "ui/views/window/dialog_client_view.h" | 27 #include "ui/views/window/dialog_client_view.h" |
| 30 #include "ui/views/window/dialog_delegate.h" | |
| 31 #include "ui/wm/core/shadow_types.h" | 28 #include "ui/wm/core/shadow_types.h" |
| 32 | 29 |
| 33 using content::DesktopMediaID; | 30 using content::DesktopMediaID; |
| 34 | 31 |
| 35 namespace { | 32 namespace { |
| 36 | 33 |
| 37 const int kThumbnailWidth = 160; | 34 const int kThumbnailWidth = 160; |
| 38 const int kThumbnailHeight = 100; | 35 const int kThumbnailHeight = 100; |
| 39 const int kThumbnailMargin = 10; | 36 const int kThumbnailMargin = 10; |
| 40 const int kLabelHeight = 40; | 37 const int kLabelHeight = 40; |
| 41 const int kListItemWidth = kThumbnailMargin * 2 + kThumbnailWidth; | 38 const int kListItemWidth = kThumbnailMargin * 2 + kThumbnailWidth; |
| 42 const int kListItemHeight = | 39 const int kListItemHeight = |
| 43 kThumbnailMargin * 2 + kThumbnailHeight + kLabelHeight; | 40 kThumbnailMargin * 2 + kThumbnailHeight + kLabelHeight; |
| 44 const int kListColumns = 3; | 41 const int kListColumns = 3; |
| 45 const int kTotalListWidth = kListColumns * kListItemWidth; | 42 const int kTotalListWidth = kListColumns * kListItemWidth; |
| 46 | 43 |
| 47 const int kDesktopMediaSourceViewGroupId = 1; | 44 const int kDesktopMediaSourceViewGroupId = 1; |
| 48 | 45 |
| 49 const char kDesktopMediaSourceViewClassName[] = | 46 const char kDesktopMediaSourceViewClassName[] = |
| 50 "DesktopMediaPicker_DesktopMediaSourceView"; | 47 "DesktopMediaPicker_DesktopMediaSourceView"; |
| 51 | 48 |
| 52 content::DesktopMediaID::Id AcceleratedWidgetToDesktopMediaId( | 49 DesktopMediaID::Id AcceleratedWidgetToDesktopMediaId( |
| 53 gfx::AcceleratedWidget accelerated_widget) { | 50 gfx::AcceleratedWidget accelerated_widget) { |
| 54 #if defined(OS_WIN) | 51 #if defined(OS_WIN) |
| 55 return reinterpret_cast<content::DesktopMediaID::Id>(accelerated_widget); | 52 return reinterpret_cast<DesktopMediaID::Id>(accelerated_widget); |
| 56 #else | 53 #else |
| 57 return static_cast<content::DesktopMediaID::Id>(accelerated_widget); | 54 return static_cast<DesktopMediaID::Id>(accelerated_widget); |
| 58 #endif | 55 #endif |
| 59 } | 56 } |
| 60 | 57 |
| 61 int GetMediaListViewHeightForRows(size_t rows) { | 58 int GetMediaListViewHeightForRows(size_t rows) { |
| 62 return kListItemHeight * rows; | 59 return kListItemHeight * rows; |
| 63 } | 60 } |
| 64 | 61 |
| 65 class DesktopMediaListView; | 62 } // namespace |
| 66 class DesktopMediaPickerDialogView; | |
| 67 class DesktopMediaPickerViews; | |
| 68 | |
| 69 // View used for each item in DesktopMediaListView. Shows a single desktop media | |
| 70 // source as a thumbnail with the title under it. | |
| 71 class DesktopMediaSourceView : public views::View { | |
| 72 public: | |
| 73 DesktopMediaSourceView(DesktopMediaListView* parent, | |
| 74 DesktopMediaID source_id); | |
| 75 virtual ~DesktopMediaSourceView(); | |
| 76 | |
| 77 // Updates thumbnail and title from |source|. | |
| 78 void SetName(const base::string16& name); | |
| 79 void SetThumbnail(const gfx::ImageSkia& thumbnail); | |
| 80 | |
| 81 // Id for the source shown by this View. | |
| 82 const DesktopMediaID& source_id() const { | |
| 83 return source_id_; | |
| 84 } | |
| 85 | |
| 86 // Returns true if the source is selected. | |
| 87 bool is_selected() const { return selected_; } | |
| 88 | |
| 89 // Updates selection state of the element. If |selected| is true then also | |
| 90 // calls SetSelected(false) for the source view that was selected before that | |
| 91 // (if any). | |
| 92 void SetSelected(bool selected); | |
| 93 | |
| 94 // views::View interface. | |
| 95 virtual const char* GetClassName() const OVERRIDE; | |
| 96 virtual void Layout() OVERRIDE; | |
| 97 virtual views::View* GetSelectedViewForGroup(int group) OVERRIDE; | |
| 98 virtual bool IsGroupFocusTraversable() const OVERRIDE; | |
| 99 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; | |
| 100 virtual void OnFocus() OVERRIDE; | |
| 101 virtual void OnBlur() OVERRIDE; | |
| 102 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; | |
| 103 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; | |
| 104 | |
| 105 private: | |
| 106 DesktopMediaListView* parent_; | |
| 107 DesktopMediaID source_id_; | |
| 108 | |
| 109 views::ImageView* image_view_; | |
| 110 views::Label* label_; | |
| 111 | |
| 112 bool selected_; | |
| 113 | |
| 114 DISALLOW_COPY_AND_ASSIGN(DesktopMediaSourceView); | |
| 115 }; | |
| 116 | |
| 117 // View that shows list of desktop media sources available from | |
| 118 // DesktopMediaList. | |
| 119 class DesktopMediaListView : public views::View, | |
| 120 public DesktopMediaListObserver { | |
| 121 public: | |
| 122 DesktopMediaListView(DesktopMediaPickerDialogView* parent, | |
| 123 scoped_ptr<DesktopMediaList> media_list); | |
| 124 virtual ~DesktopMediaListView(); | |
| 125 | |
| 126 void StartUpdating(content::DesktopMediaID::Id dialog_window_id); | |
| 127 | |
| 128 // Called by DesktopMediaSourceView when selection has changed. | |
| 129 void OnSelectionChanged(); | |
| 130 | |
| 131 // Called by DesktopMediaSourceView when a source has been double-clicked. | |
| 132 void OnDoubleClick(); | |
| 133 | |
| 134 // Returns currently selected source. | |
| 135 DesktopMediaSourceView* GetSelection(); | |
| 136 | |
| 137 // views::View overrides. | |
| 138 virtual gfx::Size GetPreferredSize() const OVERRIDE; | |
| 139 virtual void Layout() OVERRIDE; | |
| 140 virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE; | |
| 141 | |
| 142 private: | |
| 143 // DesktopMediaList::Observer interface | |
| 144 virtual void OnSourceAdded(int index) OVERRIDE; | |
| 145 virtual void OnSourceRemoved(int index) OVERRIDE; | |
| 146 virtual void OnSourceMoved(int old_index, int new_index) OVERRIDE; | |
| 147 virtual void OnSourceNameChanged(int index) OVERRIDE; | |
| 148 virtual void OnSourceThumbnailChanged(int index) OVERRIDE; | |
| 149 | |
| 150 DesktopMediaPickerDialogView* parent_; | |
| 151 scoped_ptr<DesktopMediaList> media_list_; | |
| 152 | |
| 153 DISALLOW_COPY_AND_ASSIGN(DesktopMediaListView); | |
| 154 }; | |
| 155 | |
| 156 // Dialog view used for DesktopMediaPickerViews. | |
| 157 class DesktopMediaPickerDialogView : public views::DialogDelegateView { | |
| 158 public: | |
| 159 DesktopMediaPickerDialogView(content::WebContents* parent_web_contents, | |
| 160 gfx::NativeWindow context, | |
| 161 gfx::NativeWindow parent_window, | |
| 162 DesktopMediaPickerViews* parent, | |
| 163 const base::string16& app_name, | |
| 164 const base::string16& target_name, | |
| 165 scoped_ptr<DesktopMediaList> media_list); | |
| 166 virtual ~DesktopMediaPickerDialogView(); | |
| 167 | |
| 168 // Called by parent (DesktopMediaPickerViews) when it's destroyed. | |
| 169 void DetachParent(); | |
| 170 | |
| 171 // Called by DesktopMediaListView. | |
| 172 void OnSelectionChanged(); | |
| 173 void OnDoubleClick(); | |
| 174 | |
| 175 // views::View overrides. | |
| 176 virtual gfx::Size GetPreferredSize() const OVERRIDE; | |
| 177 virtual void Layout() OVERRIDE; | |
| 178 | |
| 179 // views::DialogDelegateView overrides. | |
| 180 virtual ui::ModalType GetModalType() const OVERRIDE; | |
| 181 virtual base::string16 GetWindowTitle() const OVERRIDE; | |
| 182 virtual bool IsDialogButtonEnabled(ui::DialogButton button) const OVERRIDE; | |
| 183 virtual base::string16 GetDialogButtonLabel( | |
| 184 ui::DialogButton button) const OVERRIDE; | |
| 185 virtual bool Accept() OVERRIDE; | |
| 186 virtual void DeleteDelegate() OVERRIDE; | |
| 187 | |
| 188 void OnMediaListRowsChanged(); | |
| 189 | |
| 190 private: | |
| 191 DesktopMediaPickerViews* parent_; | |
| 192 base::string16 app_name_; | |
| 193 | |
| 194 views::Label* label_; | |
| 195 views::ScrollView* scroll_view_; | |
| 196 DesktopMediaListView* list_view_; | |
| 197 | |
| 198 DISALLOW_COPY_AND_ASSIGN(DesktopMediaPickerDialogView); | |
| 199 }; | |
| 200 | |
| 201 // Implementation of DesktopMediaPicker for Views. | |
| 202 class DesktopMediaPickerViews : public DesktopMediaPicker { | |
| 203 public: | |
| 204 DesktopMediaPickerViews(); | |
| 205 virtual ~DesktopMediaPickerViews(); | |
| 206 | |
| 207 void NotifyDialogResult(DesktopMediaID source); | |
| 208 | |
| 209 // DesktopMediaPicker overrides. | |
| 210 virtual void Show(content::WebContents* web_contents, | |
| 211 gfx::NativeWindow context, | |
| 212 gfx::NativeWindow parent, | |
| 213 const base::string16& app_name, | |
| 214 const base::string16& target_name, | |
| 215 scoped_ptr<DesktopMediaList> media_list, | |
| 216 const DoneCallback& done_callback) OVERRIDE; | |
| 217 | |
| 218 private: | |
| 219 DoneCallback callback_; | |
| 220 | |
| 221 // The |dialog_| is owned by the corresponding views::Widget instance. | |
| 222 // When DesktopMediaPickerViews is destroyed the |dialog_| is destroyed | |
| 223 // asynchronously by closing the widget. | |
| 224 DesktopMediaPickerDialogView* dialog_; | |
| 225 | |
| 226 DISALLOW_COPY_AND_ASSIGN(DesktopMediaPickerViews); | |
| 227 }; | |
| 228 | 63 |
| 229 DesktopMediaSourceView::DesktopMediaSourceView( | 64 DesktopMediaSourceView::DesktopMediaSourceView( |
| 230 DesktopMediaListView* parent, | 65 DesktopMediaListView* parent, |
| 231 DesktopMediaID source_id) | 66 DesktopMediaID source_id) |
| 232 : parent_(parent), | 67 : parent_(parent), |
| 233 source_id_(source_id), | 68 source_id_(source_id), |
| 234 image_view_(new views::ImageView()), | 69 image_view_(new views::ImageView()), |
| 235 label_(new views::Label()), | 70 label_(new views::Label()), |
| 236 selected_(false) { | 71 selected_(false) { |
| 237 AddChildView(image_view_); | 72 AddChildView(image_view_); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 DesktopMediaListView::DesktopMediaListView( | 198 DesktopMediaListView::DesktopMediaListView( |
| 364 DesktopMediaPickerDialogView* parent, | 199 DesktopMediaPickerDialogView* parent, |
| 365 scoped_ptr<DesktopMediaList> media_list) | 200 scoped_ptr<DesktopMediaList> media_list) |
| 366 : parent_(parent), | 201 : parent_(parent), |
| 367 media_list_(media_list.Pass()) { | 202 media_list_(media_list.Pass()) { |
| 368 media_list_->SetThumbnailSize(gfx::Size(kThumbnailWidth, kThumbnailHeight)); | 203 media_list_->SetThumbnailSize(gfx::Size(kThumbnailWidth, kThumbnailHeight)); |
| 369 } | 204 } |
| 370 | 205 |
| 371 DesktopMediaListView::~DesktopMediaListView() {} | 206 DesktopMediaListView::~DesktopMediaListView() {} |
| 372 | 207 |
| 373 void DesktopMediaListView::StartUpdating( | 208 void DesktopMediaListView::StartUpdating(DesktopMediaID::Id dialog_window_id) { |
| 374 content::DesktopMediaID::Id dialog_window_id) { | |
| 375 media_list_->SetViewDialogWindowId(dialog_window_id); | 209 media_list_->SetViewDialogWindowId(dialog_window_id); |
| 376 media_list_->StartUpdating(this); | 210 media_list_->StartUpdating(this); |
| 377 } | 211 } |
| 378 | 212 |
| 379 void DesktopMediaListView::OnSelectionChanged() { | 213 void DesktopMediaListView::OnSelectionChanged() { |
| 380 parent_->OnSelectionChanged(); | 214 parent_->OnSelectionChanged(); |
| 381 } | 215 } |
| 382 | 216 |
| 383 void DesktopMediaListView::OnDoubleClick() { | 217 void DesktopMediaListView::OnDoubleClick() { |
| 384 parent_->OnDoubleClick(); | 218 parent_->OnDoubleClick(); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 // by a root window. | 391 // by a root window. |
| 558 views::Widget* widget = NULL; | 392 views::Widget* widget = NULL; |
| 559 if (parent_web_contents) | 393 if (parent_web_contents) |
| 560 widget = CreateWebModalDialogViews(this, parent_web_contents); | 394 widget = CreateWebModalDialogViews(this, parent_web_contents); |
| 561 else | 395 else |
| 562 widget = DialogDelegate::CreateDialogWidget(this, context, parent_window); | 396 widget = DialogDelegate::CreateDialogWidget(this, context, parent_window); |
| 563 | 397 |
| 564 // DesktopMediaList needs to know the ID of the picker window which | 398 // DesktopMediaList needs to know the ID of the picker window which |
| 565 // matches the ID it gets from the OS. Depending on the OS and configuration | 399 // matches the ID it gets from the OS. Depending on the OS and configuration |
| 566 // we get this ID differently. | 400 // we get this ID differently. |
| 567 content::DesktopMediaID::Id dialog_window_id = 0; | 401 DesktopMediaID::Id dialog_window_id = 0; |
| 568 | 402 |
| 569 // If there is |parent_window| or |parent_web_contents|, the picker window | 403 // If there is |parent_window| or |parent_web_contents|, the picker window |
| 570 // is embedded in the parent and does not have its own native window id, so we | 404 // is embedded in the parent and does not have its own native window id, so we |
| 571 // do not filter in that case. | 405 // do not filter in that case. |
| 572 if (!parent_window && !parent_web_contents) { | 406 if (!parent_window && !parent_web_contents) { |
| 573 #if defined(USE_ASH) | 407 #if defined(USE_ASH) |
| 574 if (chrome::IsNativeWindowInAsh(widget->GetNativeWindow())) { | 408 if (chrome::IsNativeWindowInAsh(widget->GetNativeWindow())) { |
| 575 dialog_window_id = content::DesktopMediaID::RegisterAuraWindow( | 409 dialog_window_id = |
| 576 widget->GetNativeWindow()).id; | 410 DesktopMediaID::RegisterAuraWindow(widget->GetNativeWindow()).id; |
| 577 DCHECK_NE(dialog_window_id, 0); | 411 DCHECK_NE(dialog_window_id, 0); |
| 578 } | 412 } |
| 579 #endif | 413 #endif |
| 580 | 414 |
| 581 if (dialog_window_id == 0) { | 415 if (dialog_window_id == 0) { |
| 582 dialog_window_id = AcceleratedWidgetToDesktopMediaId( | 416 dialog_window_id = AcceleratedWidgetToDesktopMediaId( |
| 583 widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget()); | 417 widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget()); |
| 584 } | 418 } |
| 585 } | 419 } |
| 586 | 420 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 | 521 |
| 688 void DesktopMediaPickerDialogView::OnMediaListRowsChanged() { | 522 void DesktopMediaPickerDialogView::OnMediaListRowsChanged() { |
| 689 gfx::Rect widget_bound = GetWidget()->GetWindowBoundsInScreen(); | 523 gfx::Rect widget_bound = GetWidget()->GetWindowBoundsInScreen(); |
| 690 | 524 |
| 691 int new_height = widget_bound.height() - scroll_view_->height() + | 525 int new_height = widget_bound.height() - scroll_view_->height() + |
| 692 scroll_view_->GetPreferredSize().height(); | 526 scroll_view_->GetPreferredSize().height(); |
| 693 | 527 |
| 694 GetWidget()->CenterWindow(gfx::Size(widget_bound.width(), new_height)); | 528 GetWidget()->CenterWindow(gfx::Size(widget_bound.width(), new_height)); |
| 695 } | 529 } |
| 696 | 530 |
| 531 DesktopMediaSourceView* |
| 532 DesktopMediaPickerDialogView::GetMediaSourceViewForTesting(int index) const { |
| 533 if (list_view_->child_count() <= index) |
| 534 return NULL; |
| 535 |
| 536 return reinterpret_cast<DesktopMediaSourceView*>(list_view_->child_at(index)); |
| 537 } |
| 538 |
| 697 DesktopMediaPickerViews::DesktopMediaPickerViews() : dialog_(NULL) { | 539 DesktopMediaPickerViews::DesktopMediaPickerViews() : dialog_(NULL) { |
| 698 } | 540 } |
| 699 | 541 |
| 700 DesktopMediaPickerViews::~DesktopMediaPickerViews() { | 542 DesktopMediaPickerViews::~DesktopMediaPickerViews() { |
| 701 if (dialog_) { | 543 if (dialog_) { |
| 702 dialog_->DetachParent(); | 544 dialog_->DetachParent(); |
| 703 dialog_->GetWidget()->Close(); | 545 dialog_->GetWidget()->Close(); |
| 704 } | 546 } |
| 705 } | 547 } |
| 706 | 548 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 725 DCHECK(!callback_.is_null()); | 567 DCHECK(!callback_.is_null()); |
| 726 | 568 |
| 727 // Notify the |callback_| asynchronously because it may need to destroy | 569 // Notify the |callback_| asynchronously because it may need to destroy |
| 728 // DesktopMediaPicker. | 570 // DesktopMediaPicker. |
| 729 content::BrowserThread::PostTask( | 571 content::BrowserThread::PostTask( |
| 730 content::BrowserThread::UI, FROM_HERE, | 572 content::BrowserThread::UI, FROM_HERE, |
| 731 base::Bind(callback_, source)); | 573 base::Bind(callback_, source)); |
| 732 callback_.Reset(); | 574 callback_.Reset(); |
| 733 } | 575 } |
| 734 | 576 |
| 735 } // namespace | |
| 736 | |
| 737 // static | 577 // static |
| 738 scoped_ptr<DesktopMediaPicker> DesktopMediaPicker::Create() { | 578 scoped_ptr<DesktopMediaPicker> DesktopMediaPicker::Create() { |
| 739 return scoped_ptr<DesktopMediaPicker>(new DesktopMediaPickerViews()); | 579 return scoped_ptr<DesktopMediaPicker>(new DesktopMediaPickerViews()); |
| 740 } | 580 } |
| OLD | NEW |