Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: content/browser/tab_contents/tab_contents_view_aura.cc

Issue 9963079: Adds a TabContentsViewAura. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 // This is just a placeholder - TabContentsViewAura is not yet implemented 5 #include "content/browser/tab_contents/tab_contents_view_aura.h"
6 // (instead chrome has it's own TabContentsViewViews that is used for Aura). 6
7 7 #include "base/utf_string_conversions.h"
8 // We need to make sure the compiler sees this interface declaration somewhere 8 #include "content/browser/renderer_host/render_view_host_factory.h"
9 // so that it can emit exported versions of the inline ctor/dtor functions, 9 #include "content/browser/tab_contents/interstitial_page_impl.h"
10 // otherwise chrome.dll will get a linker error on Windows Aura builds. 10 #include "content/browser/tab_contents/tab_contents.h"
11 #include "content/public/browser/render_view_host.h"
12 #include "content/public/browser/render_widget_host.h"
13 #include "content/public/browser/render_widget_host_view.h"
14 #include "content/public/browser/web_contents_delegate.h"
11 #include "content/public/browser/web_contents_view_delegate.h" 15 #include "content/public/browser/web_contents_view_delegate.h"
16 #include "content/public/browser/web_drag_dest_delegate.h"
17 #include "ui/aura/client/drag_drop_client.h"
18 #include "ui/aura/client/drag_drop_delegate.h"
19 #include "ui/aura/event.h"
20 #include "ui/aura/root_window.h"
21 #include "ui/aura/window.h"
22 #include "ui/base/clipboard/custom_data_helper.h"
23 #include "ui/base/dragdrop/drag_drop_types.h"
24 #include "ui/base/dragdrop/os_exchange_data.h"
25 #include "ui/base/dragdrop/os_exchange_data_provider_aura.h"
26 #include "ui/gfx/compositor/layer.h"
27 #include "ui/gfx/screen.h"
28 #include "webkit/glue/webdropdata.h"
29
30 namespace {
31
32 // Listens to all mouse drag events during a drag and drop and sends them to
33 // the renderer.
34 class WebDragSourceAura : public MessageLoopForUI::Observer {
35 public:
36 explicit WebDragSourceAura(TabContents* contents)
37 : contents_(contents) {
38 MessageLoopForUI::current()->AddObserver(this);
39 }
40
41 virtual ~WebDragSourceAura() {
42 MessageLoopForUI::current()->RemoveObserver(this);
43 }
44
45 // MessageLoop::Observer implementation:
46 virtual base::EventStatus WillProcessEvent(
47 const base::NativeEvent& event) OVERRIDE {
48 return base::EVENT_CONTINUE;
49 }
50 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
51 ui::EventType type = ui::EventTypeFromNative(event);
52 content::RenderViewHost* rvh = NULL;
53 switch (type) {
54 case ui::ET_MOUSE_DRAGGED:
55 rvh = contents_->GetRenderViewHost();
56 if (rvh) {
57 gfx::Point screen_loc = ui::EventLocationFromNative(event);
58 gfx::Point client_loc = screen_loc;
59 aura::Window* window = rvh->GetView()->GetNativeView();
60 aura::Window::ConvertPointToWindow(window->GetRootWindow(),
61 window, &client_loc);
62 rvh->DragSourceMovedTo(client_loc.x(), client_loc.y(),
63 screen_loc.x(), screen_loc.y());
64 }
65 break;
66 default:
67 break;
68 }
69 }
70
71
72 private:
73 TabContents* contents_;
74
75 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
76 };
77
78 // Utility to fill a ui::OSExchangeDataProviderAura object from WebDropData.
79 void PrepareDragData(const WebDropData& drop_data,
80 ui::OSExchangeDataProviderAura* provider) {
81 if (!drop_data.plain_text.empty())
82 provider->SetString(drop_data.plain_text);
83 if (drop_data.url.is_valid())
84 provider->SetURL(drop_data.url, drop_data.url_title);
85 if (!drop_data.text_html.empty())
86 provider->SetHtml(drop_data.text_html, drop_data.html_base_url);
87 if (!drop_data.filenames.empty()) {
88 std::vector<FilePath> paths;
89 for (std::vector<string16>::const_iterator it = drop_data.filenames.begin();
90 it != drop_data.filenames.end(); ++it)
91 paths.push_back(FilePath::FromUTF8Unsafe(UTF16ToUTF8(*it)));
92 provider->SetFilenames(paths);
93 }
94 if (!drop_data.custom_data.empty()) {
95 Pickle pickle;
96 ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
97 provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
98 pickle);
99 }
100 }
101
102 // Utility to fill a WebDropData object from ui::OSExchangeData.
103 void PrepareWebDropData(WebDropData* drop_data,
104 const ui::OSExchangeData& data) {
105 string16 plain_text, url_title;
106 GURL url;
107
108 data.GetString(&plain_text);
109 if (!plain_text.empty())
110 drop_data->plain_text = plain_text;
111
112 data.GetURLAndTitle(&url, &url_title);
113 if (url.is_valid()) {
114 drop_data->url = url;
115 drop_data->url_title = url_title;
116 }
117
118 data.GetHtml(&drop_data->text_html, &drop_data->html_base_url);
119
120 std::vector<FilePath> files;
121 if (data.GetFilenames(&files) && !files.empty()) {
122 for (std::vector<FilePath>::const_iterator it = files.begin();
123 it != files.end(); ++it)
124 drop_data->filenames.push_back(UTF8ToUTF16(it->AsUTF8Unsafe()));
125 }
126
127 Pickle pickle;
128 if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
129 &pickle))
130 ui::ReadCustomDataIntoMap(pickle.data(), pickle.size(),
131 &drop_data->custom_data);
132 }
133
134 // Utilities to convert between WebKit::WebDragOperationsMask and
135 // ui::DragDropTypes.
136 int ConvertFromWeb(WebKit::WebDragOperationsMask ops) {
137 int drag_op = ui::DragDropTypes::DRAG_NONE;
138 if (ops & WebKit::WebDragOperationCopy)
139 drag_op |= ui::DragDropTypes::DRAG_COPY;
140 if (ops & WebKit::WebDragOperationMove)
141 drag_op |= ui::DragDropTypes::DRAG_MOVE;
142 if (ops & WebKit::WebDragOperationLink)
143 drag_op |= ui::DragDropTypes::DRAG_LINK;
144 return drag_op;
145 }
146
147 WebKit::WebDragOperationsMask ConvertToWeb(int drag_op) {
148 int web_drag_op = WebKit::WebDragOperationNone;
149 if (drag_op & ui::DragDropTypes::DRAG_COPY)
150 web_drag_op |= WebKit::WebDragOperationCopy;
151 if (drag_op & ui::DragDropTypes::DRAG_MOVE)
152 web_drag_op |= WebKit::WebDragOperationMove;
153 if (drag_op & ui::DragDropTypes::DRAG_LINK)
154 web_drag_op |= WebKit::WebDragOperationLink;
155 return (WebKit::WebDragOperationsMask) web_drag_op;
156 }
157
158 } // namespace
159
160
161 ////////////////////////////////////////////////////////////////////////////////
162 // TabContentsViewAura, public:
163
164 TabContentsViewAura::TabContentsViewAura(
165 TabContents* tab_contents,
166 content::WebContentsViewDelegate* delegate)
167 : tab_contents_(tab_contents),
168 view_(NULL),
169 delegate_(delegate),
170 current_drag_op_(WebKit::WebDragOperationNone),
171 close_tab_after_drag_ends_(false) {
172 }
173
174 TabContentsViewAura::~TabContentsViewAura() {
175 }
176
177 ////////////////////////////////////////////////////////////////////////////////
178 // TabContentsViewAura, private:
179
180 void TabContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
181 if (tab_contents_->GetInterstitialPage())
182 tab_contents_->GetInterstitialPage()->SetSize(size);
183 content::RenderWidgetHostView* rwhv =
184 tab_contents_->GetRenderWidgetHostView();
185 if (rwhv)
186 rwhv->SetSize(size);
187 }
188
189 void TabContentsViewAura::EndDrag(WebKit::WebDragOperationsMask ops) {
190 aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
191 gfx::Point screen_loc = root_window->last_mouse_location();
192 gfx::Point client_loc = screen_loc;
193 content::RenderViewHost* rvh = tab_contents_->GetRenderViewHost();
194 aura::Window* window = rvh->GetView()->GetNativeView();
195 aura::Window::ConvertPointToWindow(root_window, window, &client_loc);
196 rvh->DragSourceEndedAt(client_loc.x(), client_loc.y(), screen_loc.x(),
197 screen_loc.y(), ops);
198 }
199
200 content::WebDragDestDelegate* TabContentsViewAura::GetDragDestDelegate() {
201 return delegate_.get() ? delegate_->GetDragDestDelegate() : NULL;
202 }
203
204 ////////////////////////////////////////////////////////////////////////////////
205 // TabContentsViewAura, WebContentsView implementation:
206
207 void TabContentsViewAura::CreateView(const gfx::Size& initial_size) {
208 initial_size_ = initial_size;
209
210 window_.reset(new aura::Window(this));
211 window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
212 window_->SetTransparent(false);
213 window_->Init(ui::LAYER_TEXTURED);
214 window_->layer()->SetMasksToBounds(true);
215 window_->SetName("TabContentsViewAura");
216
217 // TODO(beng): allow for delegate init step.
218
219 // TODO(beng): drag & drop init.
220 }
221
222 content::RenderWidgetHostView* TabContentsViewAura::CreateViewForWidget(
223 content::RenderWidgetHost* render_widget_host) {
224 if (render_widget_host->GetView()) {
225 // During testing, the view will already be set up in most cases to the
226 // test view, so we don't want to clobber it with a real one. To verify that
227 // this actually is happening (and somebody isn't accidentally creating the
228 // view twice), we check for the RVH Factory, which will be set when we're
229 // making special ones (which go along with the special views).
230 DCHECK(RenderViewHostFactory::has_factory());
231 return render_widget_host->GetView();
232 }
233
234 view_ = content::RenderWidgetHostView::CreateViewForWidget(
235 render_widget_host);
236 view_->InitAsChild(NULL);
237 GetNativeView()->AddChild(view_->GetNativeView());
238 view_->Show();
239
240 // We listen to drag drop events in the newly created view's window.
241 aura::client::SetDragDropDelegate(view_->GetNativeView(), this);
242 return view_;
243 }
244
245 gfx::NativeView TabContentsViewAura::GetNativeView() const {
246 return window_.get();
247 }
248
249 gfx::NativeView TabContentsViewAura::GetContentNativeView() const {
250 return view_->GetNativeView();
251 }
252
253 gfx::NativeWindow TabContentsViewAura::GetTopLevelNativeWindow() const {
254 return window_->GetToplevelWindow();
255 }
256
257 void TabContentsViewAura::GetContainerBounds(gfx::Rect *out) const {
258 *out = window_->GetScreenBounds();
259 }
260
261 void TabContentsViewAura::SetPageTitle(const string16& title) {
262 window_->set_title(title);
263 }
264
265 void TabContentsViewAura::OnTabCrashed(base::TerminationStatus status,
266 int error_code) {
267 view_ = NULL;
268 }
269
270 void TabContentsViewAura::SizeContents(const gfx::Size& size) {
271 gfx::Rect bounds = window_->bounds();
272 if (bounds.size() != size) {
273 bounds.set_size(size);
274 window_->SetBounds(bounds);
275 } else {
276 // Our size matches what we want but the renderers size may not match.
277 // Pretend we were resized so that the renderers size is updated too.
278 SizeChangedCommon(size);
279
280 }
281 }
282
283 void TabContentsViewAura::RenderViewCreated(content::RenderViewHost* host) {
284 }
285
286 void TabContentsViewAura::Focus() {
287 if (tab_contents_->GetInterstitialPage()) {
288 tab_contents_->GetInterstitialPage()->Focus();
289 return;
290 }
291
292 if (delegate_.get() && delegate_->Focus())
293 return;
294
295 content::RenderWidgetHostView* rwhv =
296 tab_contents_->GetRenderWidgetHostView();
297 if (rwhv)
298 rwhv->Focus();
299 }
300
301 void TabContentsViewAura::SetInitialFocus() {
302 if (tab_contents_->FocusLocationBarByDefault())
303 tab_contents_->SetFocusToLocationBar(false);
304 else
305 Focus();
306 }
307
308 void TabContentsViewAura::StoreFocus() {
309 if (delegate_.get())
310 delegate_->StoreFocus();
311 }
312
313 void TabContentsViewAura::RestoreFocus() {
314 if (delegate_.get())
315 delegate_->RestoreFocus();
316 }
317
318 bool TabContentsViewAura::IsDoingDrag() const {
319 aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
320 if (aura::client::GetDragDropClient(root_window))
321 return aura::client::GetDragDropClient(root_window)->IsDragDropInProgress();
322 return false;
323 }
324
325 void TabContentsViewAura::CancelDragAndCloseTab() {
326 DCHECK(IsDoingDrag());
327 // We can't close the tab while we're in the drag and
328 // |drag_handler_->CancelDrag()| is async. Instead, set a flag to cancel
329 // the drag and when the drag nested message loop ends, close the tab.
330 aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
331 if (aura::client::GetDragDropClient(root_window))
332 aura::client::GetDragDropClient(root_window)->DragCancel();
333
334 close_tab_after_drag_ends_ = true;
335 }
336
337 bool TabContentsViewAura::IsEventTracking() const {
338 return false;
339 }
340
341 void TabContentsViewAura::CloseTabAfterEventTracking() {
342 }
343
344 void TabContentsViewAura::GetViewBounds(gfx::Rect* out) const {
345 *out = window_->GetScreenBounds();
346 }
347
348 ////////////////////////////////////////////////////////////////////////////////
349 // TabContentsViewAura, RenderViewHostDelegate::View implementation:
350
351 void TabContentsViewAura::CreateNewWindow(
352 int route_id,
353 const ViewHostMsg_CreateWindow_Params& params) {
354 tab_contents_view_helper_.CreateNewWindow(tab_contents_, route_id, params);
355 }
356
357 void TabContentsViewAura::CreateNewWidget(int route_id,
358 WebKit::WebPopupType popup_type) {
359 tab_contents_view_helper_.CreateNewWidget(tab_contents_,
360 route_id,
361 false,
362 popup_type);
363 }
364
365 void TabContentsViewAura::CreateNewFullscreenWidget(int route_id) {
366 tab_contents_view_helper_.CreateNewWidget(tab_contents_,
367 route_id,
368 true,
369 WebKit::WebPopupTypeNone);
370 }
371
372 void TabContentsViewAura::ShowCreatedWindow(int route_id,
373 WindowOpenDisposition disposition,
374 const gfx::Rect& initial_pos,
375 bool user_gesture) {
376 tab_contents_view_helper_.ShowCreatedWindow(
377 tab_contents_, route_id, disposition, initial_pos, user_gesture);
378 }
379
380 void TabContentsViewAura::ShowCreatedWidget(int route_id,
381 const gfx::Rect& initial_pos) {
382 tab_contents_view_helper_.ShowCreatedWidget(tab_contents_,
383 route_id,
384 false,
385 initial_pos);
386 }
387
388 void TabContentsViewAura::ShowCreatedFullscreenWidget(int route_id) {
389 tab_contents_view_helper_.ShowCreatedWidget(tab_contents_,
390 route_id,
391 true,
392 gfx::Rect());
393 }
394
395 void TabContentsViewAura::ShowContextMenu(
396 const content::ContextMenuParams& params) {
397 // Allow WebContentsDelegates to handle the context menu operation first.
398 if (tab_contents_->GetDelegate() &&
399 tab_contents_->GetDelegate()->HandleContextMenu(params)) {
400 return;
401 }
402
403 if (delegate_.get())
404 delegate_->ShowContextMenu(params);
405 }
406
407 void TabContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds,
408 int item_height,
409 double item_font_size,
410 int selected_item,
411 const std::vector<WebMenuItem>& items,
412 bool right_aligned) {
413 // External popup menus are only used on Mac.
414 NOTIMPLEMENTED();
415 }
416
417 void TabContentsViewAura::StartDragging(
418 const WebDropData& drop_data,
419 WebKit::WebDragOperationsMask operations,
420 const SkBitmap& image,
421 const gfx::Point& image_offset) {
422 aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
423 if (!aura::client::GetDragDropClient(root_window))
424 return;
425
426 ui::OSExchangeDataProviderAura* provider = new ui::OSExchangeDataProviderAura;
427 PrepareDragData(drop_data, provider);
428 if (!image.isNull())
429 provider->set_drag_image(image);
430 ui::OSExchangeData data(provider); // takes ownership of |provider|.
431
432 scoped_ptr<WebDragSourceAura> drag_source(
433 new WebDragSourceAura(tab_contents_));
434
435 // We need to enable recursive tasks on the message loop so we can get
436 // updates while in the system DoDragDrop loop.
437 int result_op = 0;
438 {
439 // TODO(sad): Avoid using last_mouse_location here, since the drag may not
440 // always start from a mouse-event (e.g. a touch or gesture event could
441 // initiate the drag). The location information should be carried over from
442 // webkit. http://crbug.com/114754
443 gfx::Point location(root_window->last_mouse_location());
444 location.Offset(-image_offset.x(), -image_offset.y());
445 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
446 result_op = aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
447 data, location, ConvertFromWeb(operations));
448 }
449
450 EndDrag(ConvertToWeb(result_op));
451 tab_contents_->GetRenderViewHost()->DragSourceSystemDragEnded();}
452
453 void TabContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) {
454 current_drag_op_ = operation;
455 }
456
457 void TabContentsViewAura::GotFocus() {
458 if (tab_contents_->GetDelegate())
459 tab_contents_->GetDelegate()->WebContentsFocused(tab_contents_);
460 }
461
462 void TabContentsViewAura::TakeFocus(bool reverse) {
463 if (tab_contents_->GetDelegate() &&
464 !tab_contents_->GetDelegate()->TakeFocus(reverse) &&
465 delegate_.get()) {
466 delegate_->TakeFocus(reverse);
467 }
468 }
469
470 ////////////////////////////////////////////////////////////////////////////////
471 // TabContentsViewAura, aura::WindowDelegate implementation:
472
473 gfx::Size TabContentsViewAura::GetMinimumSize() const {
474 return gfx::Size();
475 }
476
477 void TabContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
478 const gfx::Rect& new_bounds) {
479 SizeChangedCommon(new_bounds.size());
480 if (delegate_.get())
481 delegate_->SizeChanged(new_bounds.size());
482 }
483
484 void TabContentsViewAura::OnFocus() {
485 }
486
487 void TabContentsViewAura::OnBlur() {
488 }
489
490 bool TabContentsViewAura::OnKeyEvent(aura::KeyEvent* event) {
491 return false;
492 }
493
494 gfx::NativeCursor TabContentsViewAura::GetCursor(const gfx::Point& point) {
495 return NULL;
496 }
497
498 int TabContentsViewAura::GetNonClientComponent(const gfx::Point& point) const {
499 return HTCLIENT;
500 }
501
502 bool TabContentsViewAura::OnMouseEvent(aura::MouseEvent* event) {
503 if (!tab_contents_->GetDelegate())
504 return false;
505
506 switch (event->type()) {
507 case ui::ET_MOUSE_PRESSED:
508 tab_contents_->GetDelegate()->ActivateContents(tab_contents_);
509 break;
510 case ui::ET_MOUSE_MOVED:
511 tab_contents_->GetDelegate()->ContentsMouseEvent(
512 tab_contents_, gfx::Screen::GetCursorScreenPoint(), true);
513 break;
514 default:
515 break;
516 }
517 return false;
518 }
519
520 ui::TouchStatus TabContentsViewAura::OnTouchEvent(aura::TouchEvent* event) {
521 return ui::TOUCH_STATUS_UNKNOWN;
522 }
523
524 ui::GestureStatus TabContentsViewAura::OnGestureEvent(
525 aura::GestureEvent* event) {
526 return ui::GESTURE_STATUS_UNKNOWN;
527 }
528
529 bool TabContentsViewAura::CanFocus() {
530 return false;
531 }
532
533 void TabContentsViewAura::OnCaptureLost() {
534 }
535
536 void TabContentsViewAura::OnPaint(gfx::Canvas* canvas) {
537 }
538
539 void TabContentsViewAura::OnWindowDestroying() {
540 }
541
542 void TabContentsViewAura::OnWindowDestroyed() {
543 }
544
545 void TabContentsViewAura::OnWindowVisibilityChanged(bool visible) {
546 if (visible)
547 tab_contents_->ShowContents();
548 else
549 tab_contents_->HideContents();
550 }
551 ////////////////////////////////////////////////////////////////////////////////
552 // TabContentsViewAura, aura::client::DragDropDelegate implementation:
553
554 void TabContentsViewAura::OnDragEntered(const aura::DropTargetEvent& event) {
555 if (GetDragDestDelegate())
556 GetDragDestDelegate()->DragInitialize(tab_contents_);
557
558 WebDropData drop_data;
559 PrepareWebDropData(&drop_data, event.data());
560 WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
561
562 gfx::Point screen_pt =
563 GetNativeView()->GetRootWindow()->last_mouse_location();
564 tab_contents_->GetRenderViewHost()->DragTargetDragEnter(
565 drop_data, event.location(), screen_pt, op);
566
567 if (GetDragDestDelegate()) {
568 GetDragDestDelegate()->OnReceiveDragData(event.data());
569 GetDragDestDelegate()->OnDragEnter();
570 }
571 }
572
573 int TabContentsViewAura::OnDragUpdated(const aura::DropTargetEvent& event) {
574 WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
575 gfx::Point screen_pt =
576 GetNativeView()->GetRootWindow()->last_mouse_location();
577 tab_contents_->GetRenderViewHost()->DragTargetDragOver(
578 event.location(), screen_pt, op);
579
580 if (GetDragDestDelegate())
581 GetDragDestDelegate()->OnDragOver();
582
583 return ConvertFromWeb(current_drag_op_);
584 }
585
586 void TabContentsViewAura::OnDragExited() {
587 tab_contents_->GetRenderViewHost()->DragTargetDragLeave();
588 if (GetDragDestDelegate())
589 GetDragDestDelegate()->OnDragLeave();
590 }
591
592 int TabContentsViewAura::OnPerformDrop(const aura::DropTargetEvent& event) {
593 tab_contents_->GetRenderViewHost()->DragTargetDrop(
594 event.location(),
595 GetNativeView()->GetRootWindow()->last_mouse_location());
596 if (GetDragDestDelegate())
597 GetDragDestDelegate()->OnDrop();
598 return current_drag_op_;
599 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698